-
-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #393 from anoop-b/webhook
Added webhook module for URL forwarding
- Loading branch information
Showing
7 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
230 changes: 230 additions & 0 deletions
230
app/src/main/java/com/trianguloy/urlchecker/modules/list/WebhookModule.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
package com.trianguloy.urlchecker.modules.list; | ||
|
||
import android.app.AlertDialog; | ||
import android.content.Context; | ||
import android.text.Editable; | ||
import android.util.Pair; | ||
import android.view.View; | ||
import android.widget.Button; | ||
import android.widget.EditText; | ||
import android.widget.TextView; | ||
import android.widget.Toast; | ||
|
||
import com.trianguloy.urlchecker.R; | ||
import com.trianguloy.urlchecker.activities.ModulesActivity; | ||
import com.trianguloy.urlchecker.dialogs.MainDialog; | ||
import com.trianguloy.urlchecker.modules.AModuleConfig; | ||
import com.trianguloy.urlchecker.modules.AModuleData; | ||
import com.trianguloy.urlchecker.modules.AModuleDialog; | ||
import com.trianguloy.urlchecker.modules.AutomationRules; | ||
import com.trianguloy.urlchecker.url.UrlData; | ||
import com.trianguloy.urlchecker.utilities.generics.GenericPref; | ||
import com.trianguloy.urlchecker.utilities.methods.AndroidUtils; | ||
import com.trianguloy.urlchecker.utilities.methods.HttpUtils; | ||
import com.trianguloy.urlchecker.utilities.methods.JavaUtils; | ||
import com.trianguloy.urlchecker.utilities.wrappers.DefaultTextWatcher; | ||
|
||
import java.io.IOException; | ||
import java.text.SimpleDateFormat; | ||
import java.util.Date; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.concurrent.Executor; | ||
import java.util.concurrent.Executors; | ||
|
||
/** This module sends the current url to a custom webhook */ | ||
public class WebhookModule extends AModuleData { | ||
|
||
public static GenericPref.Str WEBHOOK_URL_PREF(Context cntx) { | ||
return new GenericPref.Str("webhook_url", "", cntx); | ||
} | ||
|
||
public static GenericPref.Str WEBHOOK_BODY_PREF(Context cntx) { | ||
return new GenericPref.Str("webhook_body", WebhookConfig.DEFAULT, cntx); | ||
} | ||
|
||
@Override | ||
public String getId() { | ||
return "webhook"; | ||
} | ||
|
||
@Override | ||
public int getName() { | ||
return R.string.mWebhook_name; | ||
} | ||
|
||
@Override | ||
public boolean isEnabledByDefault() { | ||
return false; | ||
} | ||
|
||
@Override | ||
public AModuleDialog getDialog(MainDialog cntx) { | ||
return new WebhookDialog(cntx); | ||
} | ||
|
||
@Override | ||
public AModuleConfig getConfig(ModulesActivity cntx) { | ||
return new WebhookConfig(cntx); | ||
} | ||
|
||
@Override | ||
public List<AutomationRules.Automation<AModuleDialog>> getAutomations() { | ||
return (List<AutomationRules.Automation<AModuleDialog>>) (List<?>) WebhookDialog.AUTOMATIONS; | ||
} | ||
} | ||
|
||
class WebhookDialog extends AModuleDialog { | ||
|
||
private static final Executor executor = Executors.newSingleThreadExecutor(); | ||
|
||
private final GenericPref.Str webhookUrl; | ||
private final GenericPref.Str webhookBody; | ||
private TextView statusText; | ||
private Button statusButton; | ||
|
||
static final List<AutomationRules.Automation<WebhookDialog>> AUTOMATIONS = List.of( | ||
new AutomationRules.Automation<>( | ||
"webhook", | ||
R.string.mWebhook_auto_send, | ||
WebhookDialog::sendToWebhook | ||
) | ||
); | ||
|
||
public WebhookDialog(MainDialog dialog) { | ||
super(dialog); | ||
webhookUrl = WebhookModule.WEBHOOK_URL_PREF(dialog); | ||
webhookBody = WebhookModule.WEBHOOK_BODY_PREF(dialog); | ||
} | ||
|
||
@Override | ||
public int getLayoutId() { | ||
return R.layout.button_text; | ||
} | ||
|
||
@Override | ||
public void onInitialize(View views) { | ||
statusText = views.findViewById(R.id.text); | ||
statusButton = views.findViewById(R.id.button); | ||
|
||
statusButton.setText(R.string.mWebhook_send); | ||
statusButton.setOnClickListener(v -> sendToWebhook()); | ||
} | ||
|
||
@Override | ||
public void onDisplayUrl(UrlData urlData) { | ||
statusText.setText(""); | ||
AndroidUtils.clearRoundedColor(statusText); | ||
} | ||
|
||
private void sendToWebhook() { | ||
statusText.setText(R.string.mWebhook_sending); | ||
statusButton.setEnabled(false); | ||
|
||
executor.execute(() -> { | ||
var sent = send(webhookUrl.get(), getUrl(), webhookBody.get()); | ||
getActivity().runOnUiThread(() -> { | ||
statusText.setText(sent ? R.string.mWebhook_success : R.string.mWebhook_error); | ||
if (!sent) { | ||
AndroidUtils.setRoundedColor(R.color.bad, statusText); | ||
} | ||
statusButton.setEnabled(true); | ||
}); | ||
}); | ||
} | ||
|
||
/** Performs the send action */ | ||
static boolean send(String webhook, String url, String body) { | ||
try { | ||
var json = body | ||
.replace("$URL$", url) | ||
.replace("$TIMESTAMP$", new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US).format(new Date())); | ||
|
||
var responseCode = HttpUtils.performPOSTJSON(webhook, json); | ||
return responseCode >= 200 && responseCode < 300; | ||
} catch (IOException e) { | ||
AndroidUtils.assertError("Failed to send to webhook", e); | ||
return false; | ||
} | ||
|
||
} | ||
} | ||
|
||
class WebhookConfig extends AModuleConfig { | ||
|
||
public static final String DEFAULT = "{\"url\":\"$URL$\",\"timestamp\":\"$TIMESTAMP$\"}"; | ||
|
||
private static final List<Pair<String, String>> TEMPLATES = List.of( | ||
Pair.create("custom", DEFAULT), | ||
Pair.create("Discord", "{\"content\":\"$URL$ @ $TIMESTAMP$\"}"), | ||
Pair.create("Slack", "{\"text\":\"$URL$ @ $TIMESTAMP$\"}"), | ||
Pair.create("Teams", "{\"text\":\"$URL$ @ $TIMESTAMP$\"}") | ||
); | ||
|
||
private final GenericPref.Str webhookUrl; | ||
private final GenericPref.Str webhookBody; | ||
|
||
public WebhookConfig(ModulesActivity activity) { | ||
super(activity); | ||
webhookUrl = WebhookModule.WEBHOOK_URL_PREF(activity); | ||
webhookBody = WebhookModule.WEBHOOK_BODY_PREF(activity); | ||
} | ||
|
||
@Override | ||
public int cannotEnableErrorId() { | ||
return webhookUrl.get().isEmpty() || webhookBody.get().isEmpty() ? R.string.mWebhook_missing_config : -1; | ||
} | ||
|
||
@Override | ||
public int getLayoutId() { | ||
return R.layout.config_webhook; | ||
} | ||
|
||
@Override | ||
public void onInitialize(View views) { | ||
var url = views.<EditText>findViewById(R.id.webhook_url); | ||
var body = views.<EditText>findViewById(R.id.webhook_body); | ||
var test = views.findViewById(R.id.webhook_test); | ||
|
||
// configs | ||
webhookUrl.attachToEditText(url); | ||
webhookBody.attachToEditText(body); | ||
|
||
// check disable | ||
var nonEmpty = new DefaultTextWatcher() { | ||
@Override | ||
public void afterTextChanged(Editable s) { | ||
if (s.length() == 0) { | ||
disable(); | ||
test.setEnabled(false); | ||
} else { | ||
test.setEnabled(true); | ||
} | ||
} | ||
}; | ||
url.addTextChangedListener(nonEmpty); | ||
body.addTextChangedListener(nonEmpty); | ||
|
||
test.setEnabled(cannotEnableErrorId() == -1); | ||
|
||
// click template | ||
views.findViewById(R.id.webhook_templates).setOnClickListener(v -> | ||
new AlertDialog.Builder(v.getContext()) | ||
.setTitle(R.string.mWebhook_templates) | ||
.setItems(JavaUtils.mapEach(TEMPLATES, e -> e.first).toArray(new String[0]), (dialog, which) -> | ||
body.setText(TEMPLATES.get(which).second)) | ||
.show()); | ||
|
||
// click test | ||
test.setOnClickListener(v -> { | ||
test.setEnabled(false); | ||
new Thread(() -> { | ||
var ok = WebhookDialog.send(webhookUrl.get(), webhookUrl.get(), webhookBody.get()); | ||
getActivity().runOnUiThread(() -> { | ||
test.setEnabled(true); | ||
Toast.makeText(v.getContext(), ok ? R.string.mWebhook_success : R.string.mWebhook_error, Toast.LENGTH_SHORT).show(); | ||
}); | ||
}).start(); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:orientation="vertical"> | ||
|
||
<TextView | ||
android:id="@+id/label" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:text="@string/mWebhook_desc" /> | ||
|
||
<EditText | ||
android:id="@+id/webhook_url" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:hint="@string/mWebhook_url_hint" | ||
android:inputType="textUri" /> | ||
|
||
<LinearLayout | ||
android:layout_width="match_parent" | ||
android:layout_height="match_parent" | ||
android:orientation="horizontal"> | ||
|
||
<EditText | ||
android:id="@+id/webhook_body" | ||
android:layout_width="0dp" | ||
android:layout_height="wrap_content" | ||
android:layout_weight="1" | ||
android:ems="10" | ||
android:gravity="start|top" | ||
android:hint="@string/mWebhook_body_hint" | ||
android:inputType="textMultiLine" /> | ||
|
||
<Button | ||
android:id="@+id/webhook_templates" | ||
style="?android:attr/buttonBarButtonStyle" | ||
android:layout_width="wrap_content" | ||
android:layout_height="match_parent" | ||
android:minHeight="0dp" | ||
android:text="@string/mWebhook_templates" /> | ||
|
||
</LinearLayout> | ||
|
||
<Button | ||
android:id="@+id/webhook_test" | ||
style="?android:attr/buttonBarButtonStyle" | ||
android:layout_width="match_parent" | ||
android:layout_height="wrap_content" | ||
android:text="@string/mWebhook_test" /> | ||
|
||
</LinearLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters