Added rule action GET URL

This commit is contained in:
M66B 2023-10-02 18:45:50 +02:00
parent 2d07650db8
commit 97be480046
6 changed files with 90 additions and 5 deletions

View File

@ -225,6 +225,9 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
} else if (type == EntityRule.TYPE_NOTES) {
String notes = jaction.getString("notes");
setAction(getAction(type), notes);
} else if (type == EntityRule.TYPE_URL) {
String url = jaction.getString("url");
setAction(getAction(type), url);
} else
setAction(getAction(type), null);
@ -577,6 +580,8 @@ public class AdapterRule extends RecyclerView.Adapter<AdapterRule.ViewHolder> {
return R.string.title_rule_local_only;
case EntityRule.TYPE_NOTES:
return R.string.title_rule_notes;
case EntityRule.TYPE_URL:
return R.string.title_rule_url;
default:
throw new IllegalArgumentException("Unknown action type=" + type);
}

View File

@ -3100,7 +3100,7 @@ class Core {
} while (count > 0);
}
private static void onRule(Context context, JSONArray jargs, EntityMessage message) throws JSONException, MessagingException {
private static void onRule(Context context, JSONArray jargs, EntityMessage message) throws JSONException, MessagingException, IOException {
// Deferred rule (download headers, body, etc)
DB db = DB.getInstance(context);

View File

@ -32,6 +32,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.util.Patterns;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceManager;
@ -48,6 +49,9 @@ import org.jsoup.nodes.Element;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
@ -128,6 +132,7 @@ public class EntityRule {
static final int TYPE_SOUND = 16;
static final int TYPE_LOCAL_ONLY = 17;
static final int TYPE_NOTES = 18;
static final int TYPE_URL = 19;
static final String ACTION_AUTOMATION = BuildConfig.APPLICATION_ID + ".AUTOMATION";
static final String EXTRA_RULE = "rule";
@ -139,6 +144,7 @@ public class EntityRule {
static final String JSOUP_PREFIX = "jsoup:";
private static final long SEND_DELAY = 5000L; // milliseconds
private static final int MAX_NOTES_LENGTH = 512; // characters
private static final int URL_TIMEOUT = 15 * 1000; // milliseconds
static boolean needsHeaders(EntityMessage message, List<EntityRule> rules) {
return needsHeaders(rules);
@ -181,7 +187,7 @@ public class EntityRule {
static int run(Context context, List<EntityRule> rules,
EntityMessage message, List<Header> headers, String html)
throws JSONException, MessagingException {
throws JSONException, MessagingException, IOException {
int applied = 0;
List<String> stopped = new ArrayList<>();
@ -564,7 +570,7 @@ public class EntityRule {
return matched;
}
boolean execute(Context context, EntityMessage message, String html) throws JSONException {
boolean execute(Context context, EntityMessage message, String html) throws JSONException, IOException {
boolean executed = _execute(context, message, html);
if (this.id != null && executed) {
DB db = DB.getInstance(context);
@ -573,7 +579,7 @@ public class EntityRule {
return executed;
}
private boolean _execute(Context context, EntityMessage message, String html) throws JSONException, IllegalArgumentException {
private boolean _execute(Context context, EntityMessage message, String html) throws JSONException, IllegalArgumentException, IOException {
JSONObject jaction = new JSONObject(action);
int type = jaction.getInt("type");
EntityLog.log(context, EntityLog.Type.Rules, message,
@ -616,6 +622,8 @@ public class EntityRule {
return onActionLocalOnly(context, message, jaction);
case TYPE_NOTES:
return onActionNotes(context, message, jaction, html);
case TYPE_URL:
return onActionUrl(context, message, jaction, html);
default:
throw new IllegalArgumentException("Unknown rule type=" + type + " name=" + name);
}
@ -699,6 +707,11 @@ public class EntityRule {
if (TextUtils.isEmpty(notes))
throw new IllegalArgumentException(context.getString(R.string.title_rule_notes_missing));
return;
case TYPE_URL:
String url = jargs.optString("url");
if (TextUtils.isEmpty(url) || !Patterns.WEB_URL.matcher(url).matches())
throw new IllegalArgumentException(context.getString(R.string.title_rule_url_missing));
return;
default:
throw new IllegalArgumentException("Unknown rule type=" + type);
}
@ -1386,6 +1399,29 @@ public class EntityRule {
return true;
}
private boolean onActionUrl(Context context, EntityMessage message, JSONObject jargs, String html) throws JSONException, IOException {
String url = jargs.getString("url");
Log.i("GET " + url);
HttpURLConnection connection = null;
try {
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(false);
connection.setReadTimeout(URL_TIMEOUT);
connection.setConnectTimeout(URL_TIMEOUT);
connection.setInstanceFollowRedirects(true);
ConnectionHelper.setUserAgent(context, connection);
connection.connect();
} finally {
if (connection != null)
connection.disconnect();
}
return true;
}
private static Calendar getRelativeCalendar(boolean all, int minutes, long reference) {
int d = minutes / (24 * 60);
int h = minutes / 60 % 24;

View File

@ -172,6 +172,8 @@ public class FragmentRule extends FragmentBase {
private EditText etNotes;
private ViewButtonColor btnColorNotes;
private EditText etUrl;
private BottomNavigationView bottom_navigation;
private ContentLoadingProgressBar pbWait;
@ -190,6 +192,7 @@ public class FragmentRule extends FragmentBase {
private Group grpDelete;
private Group grpLocalOnly;
private Group grpNotes;
private Group grpUrl;
private ArrayAdapter<String> adapterGroup;
private ArrayAdapter<String> adapterDay;
@ -362,6 +365,8 @@ public class FragmentRule extends FragmentBase {
etNotes = view.findViewById(R.id.etNotes);
btnColorNotes = view.findViewById(R.id.btnColorNotes);
etUrl = view.findViewById(R.id.etUrl);
bottom_navigation = view.findViewById(R.id.bottom_navigation);
pbWait = view.findViewById(R.id.pbWait);
@ -381,6 +386,7 @@ public class FragmentRule extends FragmentBase {
grpDelete = view.findViewById(R.id.grpDelete);
grpLocalOnly = view.findViewById(R.id.grpLocalOnly);
grpNotes = view.findViewById(R.id.grpNotes);
grpUrl = view.findViewById(R.id.grpUrl);
adapterGroup = new ArrayAdapter<>(getContext(), R.layout.spinner_item1_dropdown, android.R.id.text1);
etGroup.setThreshold(1);
@ -646,6 +652,7 @@ public class FragmentRule extends FragmentBase {
actions.add(new Action(EntityRule.TYPE_TTS, getString(R.string.title_rule_tts)));
actions.add(new Action(EntityRule.TYPE_SOUND, getString(R.string.title_rule_sound)));
actions.add(new Action(EntityRule.TYPE_AUTOMATION, getString(R.string.title_rule_automation)));
actions.add(new Action(EntityRule.TYPE_URL, getString(R.string.title_rule_url)));
adapterAction.addAll(actions);
spAction.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@ -849,6 +856,7 @@ public class FragmentRule extends FragmentBase {
grpDelete.setVisibility(View.GONE);
grpLocalOnly.setVisibility(View.GONE);
grpNotes.setVisibility(View.GONE);
grpUrl.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
@ -1300,7 +1308,6 @@ public class FragmentRule extends FragmentBase {
etKeyword.setText(jaction.getString("keyword"));
rgKeyword.check(jaction.optBoolean("set", true)
? R.id.keyword_add : R.id.keyword_delete);
break;
case EntityRule.TYPE_MOVE:
@ -1359,6 +1366,10 @@ public class FragmentRule extends FragmentBase {
!jaction.has("color") || jaction.isNull("color")
? null : jaction.getInt("color"));
break;
case EntityRule.TYPE_URL:
etUrl.setText(jaction.getString("url"));
break;
}
for (int pos = 0; pos < adapterAction.getCount(); pos++)
@ -1417,6 +1428,7 @@ public class FragmentRule extends FragmentBase {
grpDelete.setVisibility(type == EntityRule.TYPE_DELETE ? View.VISIBLE : View.GONE);
grpLocalOnly.setVisibility(type == EntityRule.TYPE_LOCAL_ONLY ? View.VISIBLE : View.GONE);
grpNotes.setVisibility(type == EntityRule.TYPE_NOTES ? View.VISIBLE : View.GONE);
grpUrl.setVisibility(type == EntityRule.TYPE_URL ? View.VISIBLE : View.GONE);
}
private void onActionDelete() {
@ -1764,6 +1776,10 @@ public class FragmentRule extends FragmentBase {
if (ncolor != Color.TRANSPARENT)
jaction.put("color", ncolor);
break;
case EntityRule.TYPE_URL:
jaction.put("url", etUrl.getText().toString().trim());
break;
}
}

View File

@ -1281,6 +1281,26 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvColorNotes" />
<TextView
android:id="@+id/tvUrl"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_rule_url"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/btnColorNotes" />
<eu.faircode.email.EditTextPlain
android:id="@+id/etUrl"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="textUri"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvUrl" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpReady"
android:layout_width="0dp"
@ -1382,6 +1402,12 @@
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvNotes,etNotes,tvColorNotes,btnColorNotes" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpUrl"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvUrl,etUrl" />
</androidx.constraintlayout.widget.ConstraintLayout>
</eu.faircode.email.ScrollViewEx>

View File

@ -1920,6 +1920,7 @@
<string name="title_rule_keyword_add">Add</string>
<string name="title_rule_keyword_delete">Delete</string>
<string name="title_rule_notes">Local notes</string>
<string name="title_rule_url" translatable="false">URL</string>
<string name="title_rule_move">Move</string>
<string name="title_rule_copy">Copy (label)</string>
<string name="title_rule_answer">Reply/forward</string>
@ -1981,6 +1982,7 @@
<string name="title_rule_keyword_missing">Keyword missing</string>
<string name="title_rule_automation_hint">This will send the intent \'%1$s\' with the extras \'%2$s\'</string>
<string name="title_rule_notes_missing">Local notes missing</string>
<string name="title_rule_url_missing" translatable="false">URL missing or invalid</string>
<string name="title_rule_delete_hint">Permanent deletion is irreversible, so make sure the rule conditions are correct!</string>
<string name="title_rule_local_only_hint" translatable="false">Try to avoid bridging notifications to other devices, such as smartwatches. Not all devices support this.</string>
<string name="title_rule_edit_group">Edit group &#8230;</string>