mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
WEBHOOK conversion + cleanup work🎣
This commit is contained in:
@@ -513,30 +513,8 @@
|
||||
"REPORT_MAIL_name" : "Enable email",
|
||||
"REPORT_MAIL_description" : "If enabled an email is sent out with a list of changes you nove subscribed to. Please also fill out all remaining settings related to the SMTP setup below. If facing issues, set <code>LOG_LEVEL</code> to <code>debug</code> and check the <a href=\"/maintenance.php#tab_Logging\">error log</a>.",
|
||||
"SYSTEM_TITLE" : "System Information",
|
||||
|
||||
"REPORT_TO_name" : "deprecated",
|
||||
"REPORT_TO_description" : "deprecated",
|
||||
"REPORT_FROM_name" : "deprecated",
|
||||
"REPORT_FROM_description" : "deprecated",
|
||||
|
||||
"Webhooks_display_name" : "Webhooks",
|
||||
"Webhooks_icon" : "<i class=\"fa fa-circle-nodes\"></i>",
|
||||
"REPORT_WEBHOOK_name" : "Enable Webhooks",
|
||||
"REPORT_WEBHOOK_description" : "Enable webhooks for notifications. Webhooks help you to connect to a lot of 3rd party tools, such as IFTTT, Zapier or <a href=\"https://n8n.io/\" target=\"_blank\">n8n</a> to name a few. Check out this simple <a href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md\" target=\"_blank\">n8n guide here</a> to get started. If enabled, configure related settings below.",
|
||||
"WEBHOOK_URL_name" : "Target URL",
|
||||
"WEBHOOK_URL_description" : "Target URL starting with <code>http://</code> or <code>https://</code>.",
|
||||
"WEBHOOK_PAYLOAD_name" : "Payload type",
|
||||
"WEBHOOK_PAYLOAD_description" : "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)",
|
||||
"WEBHOOK_REQUEST_METHOD_name" : "Request method",
|
||||
"WEBHOOK_REQUEST_METHOD_description" : "The HTTP request method to be used for the webhook call.",
|
||||
"WEBHOOK_SIZE_name" : "Max payload size",
|
||||
"WEBHOOK_SIZE_description" : "The maximum size of the webhook payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended.",
|
||||
"WEBHOOK_SECRET_name": "HMAC Secret",
|
||||
"WEBHOOK_SECRET_description": "When set, use this secret to generate the SHA256-HMAC hex digest value of the request body, which will be passed as the <code>X-Webhook-Signature</code> header to the request. You can find more informations <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_SECRET.md\">here</a>.",
|
||||
|
||||
"REPORT_TITLE" : "Report",
|
||||
"REPORT_ERROR" : "The page you are looking for is temporarily unavailable, please try again after a few seconds",
|
||||
|
||||
"API_display_name" : "API",
|
||||
"API_icon" : "<i class=\"fa fa-arrow-down-up-across-line\"></i>",
|
||||
"API_CUSTOM_SQL_name" : "Custom endpoint",
|
||||
|
||||
@@ -14,27 +14,33 @@
|
||||
|
||||
### 🔌 Plugins & 📚 Docs
|
||||
|
||||
| Required | CurrentScan | Unique Prefix | Plugin Type | Link + Docs |
|
||||
|-------------|-------------|-----------------------|------------------------|-----------------------------------------------------------|
|
||||
| | Yes | ARPSCAN | Script | 📚[arp_scan](/front/plugins/arp_scan/) |
|
||||
| | | CSVBCKP | Script | 📚[csv_backup](/front/plugins/csv_backup/) |
|
||||
| Yes* | | DBCLNP | Script | 📚[db_cleanup](/front/plugins/db_cleanup/) |
|
||||
| | | DDNS | Script | 📚[ddns_update](/front/plugins/ddns_update/) |
|
||||
| | Yes | DHCPLSS | Script | 📚[dhcp_leases](/front/plugins/dhcp_leases/) |
|
||||
| | | DHCPSRVS | Script | 📚[dhcp_servers](/front/plugins/dhcp_servers/) |
|
||||
| | Yes | INTRNT | Script | 📚[internet_ip](/front/plugins/internet_ip/) |
|
||||
| | | INTRSPD | Script | 📚[internet_speedtest](/front/plugins/internet_speedtest/)|
|
||||
| Yes | | NEWDEV | Template | 📚[newdev_template](/front/plugins/newdev_template/) |
|
||||
| | | PHOLUS | Script | 📚[pholus_scan](/front/plugins/pholus_scan/) |
|
||||
| | | NMAP | Script | 📚[nmap_scan](/front/plugins/nmap_scan/) |
|
||||
| | Yes | PIHOLE | External SQLite DB | 📚[pihole_scan](/front/plugins/pihole_scan/) |
|
||||
| | | SETPWD | Script | 📚[set_password](/front/plugins/set_password/) |
|
||||
| | | SNMPDSC | Script | 📚[snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| | Yes** | UNDIS | Script | 📚[undiscoverables](/front/plugins/undiscoverables/) |
|
||||
| | Yes | UNFIMP | Script | 📚[unifi_import](/front/plugins/unifi_import/) |
|
||||
| | | VNDRPDT | Script | 📚[vendor_update](/front/plugins/vendor_update/) |
|
||||
| | | WEBMON | Script | 📚[website_monitor](/front/plugins/website_monitor/) |
|
||||
| N/A | | N/A | SQL query | N/A, but the External SQLite DB plugins work similar |
|
||||
| Required | CurrentScan | Unique Prefix | Data source | Type | Link + Docs |
|
||||
|----------|-------------|---------------|--------------------|--------------|------------------------------------------------------------------|
|
||||
| | | APPRISE | Script | 💬 publisher | 📚[_publisher_apprise](/front/plugins/_publisher_apprise/) |
|
||||
| | Yes | ARPSCAN | Script | 🔍scanner | 📚[arp_scan](/front/plugins/arp_scan/) |
|
||||
| | | CSVBCKP | Script | ⚙ system | 📚[csv_backup](/front/plugins/csv_backup/) |
|
||||
| Yes* | | DBCLNP | Script | ⚙ system | 📚[db_cleanup](/front/plugins/db_cleanup/) |
|
||||
| | | DDNS | Script | ⚙ system | 📚[ddns_update](/front/plugins/ddns_update/) |
|
||||
| | Yes | DHCPLSS | Script | 🔍scanner | 📚[dhcp_leases](/front/plugins/dhcp_leases/) |
|
||||
| | | DHCPSRVS | Script | 🔍scanner | 📚[dhcp_servers](/front/plugins/dhcp_servers/) |
|
||||
| | Yes | INTRNT | Script | 🔍scanner | 📚[internet_ip](/front/plugins/internet_ip/) |
|
||||
| | | INTRSPD | Script | 🔍scanner | 📚[internet_speedtest](/front/plugins/internet_speedtest/) |
|
||||
| Yes | | NEWDEV | Template | ⚙ system | 📚[newdev_template](/front/plugins/newdev_template/) |
|
||||
| | | PHOLUS | Script | 🔍scanner | 📚[pholus_scan](/front/plugins/pholus_scan/) |
|
||||
| | | MQTT | Script | 💬 publisher | 📚[_publisher_mqtt](/front/plugins/_publisher_mqtt/) |
|
||||
| | | NMAP | Script | 🔍scanner | 📚[nmap_scan](/front/plugins/nmap_scan/) |
|
||||
| | | NTFY | Script | 💬 publisher | 📚[_publisher_ntfy](/front/plugins/_publisher_ntfy/) |
|
||||
| | Yes | PIHOLE | External SQLite DB | 🔍scanner | 📚[pihole_scan](/front/plugins/pihole_scan/) |
|
||||
| | | PUSHSAFER | Script | 💬 publisher | 📚[_publisher_pushsafer](/front/plugins/_publisher_pushsafer/) |
|
||||
| | | SETPWD | Script | ⚙ system | 📚[set_password](/front/plugins/set_password/) |
|
||||
| | | SMTP | Script | 💬 publisher | 📚[_publisher_email](/front/plugins/_publisher_email/) |
|
||||
| | | SNMPDSC | Script | 🔍scanner | 📚[snmp_discovery](/front/plugins/snmp_discovery/) |
|
||||
| | Yes** | UNDIS | Script | 🔍scanner | 📚[undiscoverables](/front/plugins/undiscoverables/) |
|
||||
| | Yes | UNFIMP | Script | 🔍scanner | 📚[unifi_import](/front/plugins/unifi_import/) |
|
||||
| | | VNDRPDT | Script | ⚙ system | 📚[vendor_update](/front/plugins/vendor_update/) |
|
||||
| | | WEBHOOK | Script | 💬 publisher | 📚[_publisher_webhook](/front/plugins/_publisher_webhook/) |
|
||||
| | | WEBMON | Script | 🔍scanner | 📚[website_monitor](/front/plugins/website_monitor/) |
|
||||
| N/A | | N/A | SQL query | | N/A, but the External SQLite DB plugins work similar |
|
||||
|
||||
|
||||
> \* The database cleanup plugin (`DBCLNP`) is not _required_ but the app will become unusable after a while if not executed.
|
||||
@@ -135,6 +141,7 @@ Currently, these data sources are supported (valid `data_source` value).
|
||||
| Pialert DB query | `pialert-db-query` | yes | Executes a SQL query on the PiAlert database in the `CMD` setting. |
|
||||
| Template | `template` | no | Used to generate internal settings, such as default values. |
|
||||
| External SQLite DB query | `sqlite-db-query` | yes | Executes a SQL query from the `CMD` setting on an external SQLite database mapped in the `DB_PATH` setting. |
|
||||
| Plugin type | `plugin_type` | no | Specifies the type of the plugin and in which section the Plugin settings are displayed (`<general>|<system>|<scanner>|<publisher>`). |
|
||||
|
||||
|
||||
> 🔎Example
|
||||
|
||||
@@ -46,7 +46,7 @@ def main():
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
|
||||
@@ -54,7 +54,7 @@ def main():
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
|
||||
@@ -49,7 +49,7 @@ def main():
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
|
||||
@@ -17,7 +17,7 @@ sys.path.extend(["/home/pi/pialert/front/plugins", "/home/pi/pialert/pialert"])
|
||||
import conf
|
||||
from plugin_helper import Plugin_Objects, handleEmpty
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ, get_setting_value
|
||||
from helper import timeNowTZ, get_setting_value, hide_string
|
||||
from notification import Notification_obj
|
||||
from database import DB
|
||||
|
||||
@@ -48,11 +48,11 @@ def main():
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
response_text, response_status_code = send(notification["HTML"], notification["Text"])
|
||||
response_text, response_status_code = send(notification["Text"])
|
||||
|
||||
# Log result
|
||||
plugin_objects.add_object(
|
||||
@@ -76,6 +76,11 @@ def send(text):
|
||||
response_text = ''
|
||||
response_status_code = ''
|
||||
|
||||
token = get_setting_value('PUSHSAFER_TOKEN')
|
||||
|
||||
mylog('verbose', [f'[{pluginName}] PUSHSAFER_TOKEN: "{hide_string(token)}"'])
|
||||
|
||||
|
||||
try:
|
||||
url = 'https://www.pushsafer.com/api'
|
||||
post_fields = {
|
||||
@@ -88,7 +93,7 @@ def send(text):
|
||||
"d" : 'a',
|
||||
"u" : get_setting_value('REPORT_DASHBOARD_URL'),
|
||||
"ut" : 'Open Pi.Alert',
|
||||
"k" : get_setting_value('PUSHSAFER_TOKEN'),
|
||||
"k" : token,
|
||||
}
|
||||
response = requests.post(url, data=post_fields)
|
||||
|
||||
|
||||
8
front/plugins/_publisher_webhook/README.md
Executable file
8
front/plugins/_publisher_webhook/README.md
Executable file
@@ -0,0 +1,8 @@
|
||||
## Overview
|
||||
|
||||
A plugin to publish a notification via the Webhook gateway. Webhooks help you to connect to a lot of 3rd party tools, such as IFTTT, Zapier or <a href="https://n8n.io/" target="_blank">n8n</a> to name a few. Check out this simple <a href="https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md" target="_blank">n8n guide here</a> to get started. If enabled, configure related settings below.
|
||||
|
||||
### Usage
|
||||
|
||||
- Go to settings and fill in relevant details.
|
||||
|
||||
404
front/plugins/_publisher_webhook/config.json
Executable file
404
front/plugins/_publisher_webhook/config.json
Executable file
@@ -0,0 +1,404 @@
|
||||
{
|
||||
"code_name": "_publisher_webhook",
|
||||
"unique_prefix": "WEBHOOK",
|
||||
"plugin_type": "publisher",
|
||||
"enabled": true,
|
||||
"data_source": "script",
|
||||
"show_ui": true,
|
||||
"localized": ["display_name", "description", "icon"],
|
||||
"display_name" : [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string" : "Webhook publisher"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Habilitar Webhook"
|
||||
}
|
||||
],
|
||||
"icon":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "<i class=\"fa-solid fa-circle-nodes\"></i>"
|
||||
}],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string" : "A plugin to publish a notification via Webhooks."
|
||||
}
|
||||
],
|
||||
"params" : [
|
||||
],
|
||||
"database_column_definitions":
|
||||
[
|
||||
{
|
||||
"column": "Index",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Plugin",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "N/A"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Object_PrimaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "N/A"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Object_SecondaryID",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Sent when"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value1",
|
||||
"css_classes": "col-sm-3",
|
||||
"show": true,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Notification GUID"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value2",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "textarea_readonly",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Response (stdout)"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value3",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": true,
|
||||
"type": "textarea_readonly",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Response (stderr)"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Watched_Value4",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "device_mac",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Device"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"column": "UserData",
|
||||
"css_classes": "col-sm-2",
|
||||
"show": false,
|
||||
"type": "textbox_save",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Comments"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Comentarios"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Status",
|
||||
"css_classes": "col-sm-1",
|
||||
"show": false,
|
||||
"type": "replace",
|
||||
"default_value":"",
|
||||
"options": [
|
||||
{
|
||||
"equals": "watched-not-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-square-check'></i><div></div>"
|
||||
},
|
||||
{
|
||||
"equals": "watched-changed",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-triangle-exclamation'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "new",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-circle-plus'></i></div>"
|
||||
},
|
||||
{
|
||||
"equals": "missing-in-last-scan",
|
||||
"replacement": "<div style='text-align:center'><i class='fa-solid fa-question'></i></div>"
|
||||
}
|
||||
],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Status"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Estado"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"column": "Extra",
|
||||
"css_classes": "col-sm-3",
|
||||
"show": false,
|
||||
"type": "label",
|
||||
"default_value":"",
|
||||
"options": [],
|
||||
"localized": ["name"],
|
||||
"name":[{
|
||||
"language_code": "en_us",
|
||||
"string" : "Extra"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Extra"
|
||||
}]
|
||||
}
|
||||
],
|
||||
"settings":[
|
||||
{
|
||||
"function": "RUN",
|
||||
"events": ["test"],
|
||||
"type": "text.select",
|
||||
"default_value":"disabled",
|
||||
"options": ["disabled", "on_notification" ],
|
||||
"localized": ["name", "description"],
|
||||
"name" :[{
|
||||
"language_code": "en_us",
|
||||
"string" : "When to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Cuando ejecuta"
|
||||
}],
|
||||
"description": [
|
||||
{
|
||||
"language_code": "en_us",
|
||||
"string" : "Enable webhooks for notifications. Webhooks help you to connect to a lot of 3rd party tools, such as IFTTT, Zapier or <a href=\"https://n8n.io/\" target=\"_blank\">n8n</a> to name a few. Check out this simple <a href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md\" target=\"_blank\">n8n guide here</a> to get started. If enabled, configure related settings below."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Habilite webhooks para notificaciones. Los webhooks lo ayudan a conectarse a muchas herramientas de terceros, como IFTTT, Zapier o <a href=\"https://n8n.io/\" target=\"_blank\">n8n</a>, por nombrar algunas. Consulte esta sencilla <a href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_N8N.md\" target=\"_blank\">guía de n8n aquí</a> para obtener comenzó. Si está habilitado, configure los ajustes relacionados a continuación."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"function": "CMD",
|
||||
"type": "readonly",
|
||||
"default_value":"python3 /home/pi/pialert/front/plugins/_publisher_webhook/webhook.py",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Command"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Comando"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Command to run"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Comando a ejecutar"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "RUN_TIMEOUT",
|
||||
"type": "integer",
|
||||
"default_value": 10,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Run timeout"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Tiempo de espera de ejecución"
|
||||
},
|
||||
{
|
||||
"language_code": "de_de",
|
||||
"string" : "Wartezeit"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Maximum time in seconds to wait for the script to finish. If this time is exceeded the script is aborted."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Tiempo máximo en segundos para esperar a que finalice el script. Si se supera este tiempo, el script se cancela."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "URL",
|
||||
"type": "text",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Target URL"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "URL de destino"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Target URL starting with <code>http://</code> or <code>https://</code>."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "URL de destino comienza con <code>http://</code> o <code>https://</code>."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "PAYLOAD",
|
||||
"type": "text.select",
|
||||
"default_value": "json",
|
||||
"options": ["json", "html", "text"],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Payload type"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Tipo de carga"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "The Webhook payload data format for the <code>body</code> > <code>attachments</code> > <code>text</code> attribute in the payload json. See an example of the payload <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">here</a>. (e.g.: for discord use <code>text</code>)"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "El formato de datos de carga de Webhook para el atributo <code>body</code> > <code>attachments</code> > <code>text</code> en el json de carga. Vea un ejemplo de la carga <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/back/webhook_json_sample.json\">aquí</a>. (por ejemplo: para discord use <code>text</code>)"
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "REQUEST_METHOD",
|
||||
"type": "text.select",
|
||||
"default_value": "GET",
|
||||
"options": ["GET", "POST", "PUT"],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Request method"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Método de solicitud"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "The HTTP request method to be used for the webhook call."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "El método de solicitud HTTP que se utilizará para la llamada de webhook."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "SIZE",
|
||||
"type": "integer",
|
||||
"default_value": 1024,
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "Max payload size"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "Tamaño máximo de carga útil"
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "The maximum size of the webhook payload as number of characters in the passed string. If above limit, it will be truncated and a <code>(text was truncated)</code> message is appended."
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : "El tamaño máximo de la carga útil del webhook como número de caracteres en la cadena pasada. Si supera el límite, se truncará y se agregará un mensaje <code>(text was truncated)</code>."
|
||||
}]
|
||||
},
|
||||
{
|
||||
"function": "SECRET",
|
||||
"type": "text",
|
||||
"default_value": "",
|
||||
"options": [],
|
||||
"localized": ["name", "description"],
|
||||
"name" : [{
|
||||
"language_code": "en_us",
|
||||
"string" : "HMAC Secret"
|
||||
},
|
||||
{
|
||||
"language_code": "es_es",
|
||||
"string" : ""
|
||||
}],
|
||||
"description": [{
|
||||
"language_code": "en_us",
|
||||
"string" : "When set, use this secret to generate the SHA256-HMAC hex digest value of the request body, which will be passed as the <code>X-Webhook-Signature</code> header to the request. You can find more information <a target=\"_blank\" href=\"https://github.com/jokob-sk/Pi.Alert/blob/main/docs/WEBHOOK_SECRET.md\">here</a>."
|
||||
}]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
This plugin will not be loaded
|
||||
190
front/plugins/_publisher_webhook/webhook.py
Executable file
190
front/plugins/_publisher_webhook/webhook.py
Executable file
@@ -0,0 +1,190 @@
|
||||
|
||||
#!/usr/bin/env python
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import argparse
|
||||
import os
|
||||
import pathlib
|
||||
import sys
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from base64 import b64encode
|
||||
import hashlib
|
||||
import hmac
|
||||
|
||||
# Replace these paths with the actual paths to your Pi.Alert directories
|
||||
sys.path.extend(["/home/pi/pialert/front/plugins", "/home/pi/pialert/pialert"])
|
||||
|
||||
# pialert modules
|
||||
import conf
|
||||
from const import logPath
|
||||
from plugin_helper import Plugin_Objects, handleEmpty
|
||||
from logger import mylog, append_line_to_file
|
||||
from helper import timeNowTZ, get_setting_value, hide_string, write_file
|
||||
from notification import Notification_obj
|
||||
from database import DB
|
||||
|
||||
CUR_PATH = str(pathlib.Path(__file__).parent.resolve())
|
||||
RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log')
|
||||
|
||||
pluginName = 'WEBHOOK'
|
||||
|
||||
def main():
|
||||
|
||||
mylog('verbose', [f'[{pluginName}](publisher) In script'])
|
||||
|
||||
# Check if basic config settings supplied
|
||||
if check_config() == False:
|
||||
mylog('none', [f'[{pluginName}] Error: Publisher notification gateway not set up correctly. Check your pialert.conf {pluginName}_* variables.'])
|
||||
return
|
||||
|
||||
# Create a database connection
|
||||
db = DB() # instance of class DB
|
||||
db.open()
|
||||
|
||||
# Initialize the Plugin obj output file
|
||||
plugin_objects = Plugin_Objects(RESULT_FILE)
|
||||
|
||||
# Create a Notification_obj instance
|
||||
notifications = Notification_obj(db)
|
||||
|
||||
# Retrieve new notifications
|
||||
new_notifications = notifications.getNew()
|
||||
|
||||
# Process the new notifications (see the Notifications DB table for structure or check the /api/table_notifications.json endpoint)
|
||||
for notification in new_notifications:
|
||||
|
||||
# Send notification
|
||||
response_stdout, response_stderr = send(notification["Text"], notification["HTML"], notification["JSON"])
|
||||
|
||||
# Log result
|
||||
plugin_objects.add_object(
|
||||
primaryId = pluginName,
|
||||
secondaryId = timeNowTZ(),
|
||||
watched1 = notification["GUID"],
|
||||
watched2 = handleEmpty(response_stdout),
|
||||
watched3 = handleEmpty(response_stderr),
|
||||
watched4 = 'null',
|
||||
extra = 'null',
|
||||
foreignKey = notification["GUID"]
|
||||
)
|
||||
|
||||
plugin_objects.write_result_file()
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def check_config():
|
||||
if get_setting_value('WEBHOOK_URL') == '':
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def send (text_data, html_data, json_data):
|
||||
|
||||
response_stderr = ''
|
||||
response_stdout = ''
|
||||
|
||||
# limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB)
|
||||
limit = get_setting_value('WEBHOOK_SIZE')
|
||||
payloadType = get_setting_value('WEBHOOK_PAYLOAD')
|
||||
endpointUrl = get_setting_value('WEBHOOK_URL')
|
||||
secret = get_setting_value('WEBHOOK_SECRET')
|
||||
requestMethod = get_setting_value('WEBHOOK_REQUEST_METHOD')
|
||||
|
||||
# use data type based on specified payload type
|
||||
if payloadType == 'json':
|
||||
# In this code, the truncate_json function is used to recursively traverse the JSON object
|
||||
# and remove nodes that exceed the size limit. It checks the size of each node's JSON representation
|
||||
# using json.dumps and includes only the nodes that are within the limit.
|
||||
json_str = json.dumps(json_data)
|
||||
|
||||
if len(json_str) <= limit:
|
||||
payloadData = json_data
|
||||
else:
|
||||
def truncate_json(obj):
|
||||
if isinstance(obj, dict):
|
||||
return {
|
||||
key: truncate_json(value)
|
||||
for key, value in obj.items()
|
||||
if len(json.dumps(value)) <= limit
|
||||
}
|
||||
elif isinstance(obj, list):
|
||||
return [
|
||||
truncate_json(item)
|
||||
for item in obj
|
||||
if len(json.dumps(item)) <= limit
|
||||
]
|
||||
else:
|
||||
return obj
|
||||
|
||||
payloadData = truncate_json(json_data)
|
||||
if payloadType == 'html':
|
||||
if len(html_data) > limit:
|
||||
payloadData = html_data[:limit] + " <h1>(text was truncated)</h1>"
|
||||
else:
|
||||
payloadData = html_data
|
||||
if payloadType == 'text':
|
||||
if len(text_data) > limit:
|
||||
payloadData = text_data[:limit] + " (text was truncated)"
|
||||
else:
|
||||
payloadData = text_data
|
||||
|
||||
# Define slack-compatible payload
|
||||
_json_payload = { "text": payloadData } if payloadType == 'text' else {
|
||||
"username": "Pi.Alert",
|
||||
"text": "There are new notifications",
|
||||
"attachments": [{
|
||||
"title": "Pi.Alert Notifications",
|
||||
"title_link": get_setting_value('REPORT_DASHBOARD_URL'),
|
||||
"text": payloadData
|
||||
}]
|
||||
}
|
||||
|
||||
# DEBUG - Write the json payload into a log file for debugging
|
||||
write_file (logPath + '/webhook_payload.json', json.dumps(_json_payload))
|
||||
|
||||
# Using the Slack-Compatible Webhook endpoint for Discord so that the same payload can be used for both
|
||||
# Consider: curl has the ability to load in data to POST from a file + piping
|
||||
if(endpointUrl.startswith('https://discord.com/api/webhooks/') and not endpointUrl.endswith("/slack")):
|
||||
_WEBHOOK_URL = f"{endpointUrl}/slack"
|
||||
curlParams = ["curl","-i","-H", "Content-Type:application/json" ,"-d", json.dumps(_json_payload), _WEBHOOK_URL]
|
||||
else:
|
||||
_WEBHOOK_URL = endpointUrl
|
||||
curlParams = ["curl","-i","-X", requestMethod , "-H", "Content-Type:application/json", "-d", json.dumps(_json_payload), _WEBHOOK_URL]
|
||||
|
||||
# Add HMAC signature if configured
|
||||
if(secret != ''):
|
||||
h = hmac.new(secret.encode("UTF-8"), json.dumps(_json_payload, separators=(',', ':')).encode(), hashlib.sha256).hexdigest()
|
||||
curlParams.insert(4,"-H")
|
||||
curlParams.insert(5,f"X-Webhook-Signature: sha256={h}")
|
||||
|
||||
try:
|
||||
# Execute CURL call
|
||||
mylog('debug', [f'[{pluginName}] curlParams: ', curlParams])
|
||||
result = subprocess.run(curlParams, capture_output=True, text=True)
|
||||
|
||||
response_stderr = result.stderr
|
||||
response_stdout = result.stdout
|
||||
|
||||
# Write stdout and stderr into .log files for debugging if needed
|
||||
mylog('debug', [f'[{pluginName}] stdout: ', response_stdout])
|
||||
mylog('debug', [f'[{pluginName}] stderr: ', response_stderr])
|
||||
|
||||
|
||||
|
||||
except subprocess.CalledProcessError as e:
|
||||
# An error occurred, handle it
|
||||
mylog('none', [f'[{pluginName}] Error: ', e.output])
|
||||
|
||||
response_stderr = e.output
|
||||
|
||||
|
||||
return response_stdout, response_stderr
|
||||
|
||||
# -------------------------------------------------------
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
|
||||
@@ -21,18 +21,7 @@ The original pilaert.py code is now moved to this new folder and split into diff
|
||||
|```reporting.py```| Reporting generates the email, html and json reports to be sent by the publishers |
|
||||
|```scheduler.py```| All things scheduling |
|
||||
|
||||
## publishers
|
||||
publishers generally have a check_config method as well as a send method.
|
||||
|
||||
| Module | Description |
|
||||
|--------|-----------|
|
||||
|```__init__.py```| an empty init file|
|
||||
|```apprise.py```| use apprise to integrate to "everywhere" https://github.com/caronc/apprise |
|
||||
|```email.py```| Configure and send the reports and notifications via email |
|
||||
|```mqtt.py```| integrate with a MQTT broker and even make the devices automatically discoverable in Home-Assistant |
|
||||
|```ntfy.py```| integrate with ntfy |
|
||||
|```pushsafer.py```| integrate with pushsafer |
|
||||
|```webhook.py```| integrate via webhook |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,24 +23,4 @@ El código pilaert.py original ahora se mueve a esta nueva carpeta y se divide e
|
||||
|```reporting.py```| La generación de informes genera los informes de correo electrónico, html y json que deben enviar los editores |
|
||||
|```scheduler.py```| Todo sobre la planificación |
|
||||
|
||||
## Editores
|
||||
Los editores suelen tener un método check_config además de un método send.
|
||||
|
||||
| Módulo | Descripción |
|
||||
|--------|-----------|
|
||||
|```__init__.py```| Un archivo init vacío|
|
||||
|```apprise.py```| Utilice apprise para integrarse en "todas partes" ([Github Apprise](https://github.com/caronc/apprise)). |
|
||||
|```email.py```| Configurar y enviar los informes y notificaciones por correo electrónico |
|
||||
|```mqtt.py```| Integrar con un broker MQTT e incluso hacer que los dispositivos sean automáticamente detectables en Home-Assistant |
|
||||
|```ntfy.py```| Integración con ntfy |
|
||||
|```pushsafer.py```| Integrar con pushsafer |
|
||||
|```webhook.py```| Integración mediante webhook |
|
||||
|
||||
## Escáneres
|
||||
Diferentes métodos para escanear la red en busca de dispositivos o para encontrar más detalles sobre los dispositivos descubiertos
|
||||
|
||||
| Módulo | Descripción |
|
||||
|--------|-----------|
|
||||
|```__init__.py```| Un archivo init vacío (oops falta en el repo)|
|
||||
|```internet.py```| Descubra la interfaz de Internet y verifique la IP externa y también administre DNS dinámico |
|
||||
|```nmapscan.py```| Utilice Nmap para descubrir más sobre los dispositivos |
|
||||
|
||||
@@ -41,22 +41,6 @@ INCLUDED_SECTIONS = ['new_devices', 'down_devices', 'events']
|
||||
DAYS_TO_KEEP_EVENTS = 90
|
||||
REPORT_DASHBOARD_URL = 'http://pi.alert/'
|
||||
|
||||
# -------------------------------------------
|
||||
# Notification gateways
|
||||
# -------------------------------------------
|
||||
|
||||
# Webhooks
|
||||
REPORT_WEBHOOK = False
|
||||
WEBHOOK_URL = ''
|
||||
WEBHOOK_PAYLOAD = 'json'
|
||||
WEBHOOK_REQUEST_METHOD = 'GET'
|
||||
WEBHOOK_SECRET = ''
|
||||
|
||||
|
||||
# PUSHSAFER
|
||||
REPORT_PUSHSAFER = False
|
||||
PUSHSAFER_TOKEN = 'ApiKey'
|
||||
|
||||
# -------------------------------------------
|
||||
# Misc
|
||||
# -------------------------------------------
|
||||
|
||||
@@ -510,6 +510,14 @@ def hide_email(email):
|
||||
|
||||
return email
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def hide_string(input_string):
|
||||
if len(input_string) < 3:
|
||||
return input_string # Strings with 2 or fewer characters remain unchanged
|
||||
else:
|
||||
return input_string[0] + "*" * (len(input_string) - 2) + input_string[-1]
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def removeDuplicateNewLines(text):
|
||||
if "\n\n\n" in text:
|
||||
|
||||
@@ -117,17 +117,6 @@ def importConfigs (db):
|
||||
# ARPSCAN (+ more settings are provided by the ARPSCAN plugin)
|
||||
conf.SCAN_SUBNETS = ccd('SCAN_SUBNETS', ['192.168.1.0/24 --interface=eth1', '192.168.1.0/24 --interface=eth0'] , c_d, 'Subnets to scan', 'subnets', '', 'ARPSCAN')
|
||||
|
||||
# Notification gateways
|
||||
# ----------------------------------------
|
||||
|
||||
# Webhooks
|
||||
conf.REPORT_WEBHOOK = ccd('REPORT_WEBHOOK', False , c_d, 'Enable Webhooks', 'boolean', '', 'Webhooks', ['test'])
|
||||
conf.WEBHOOK_URL = ccd('WEBHOOK_URL', '' , c_d, 'Target URL', 'text', '', 'Webhooks')
|
||||
conf.WEBHOOK_PAYLOAD = ccd('WEBHOOK_PAYLOAD', 'json' , c_d, 'Payload type', 'text.select', "['json', 'html', 'text']", 'Webhooks')
|
||||
conf.WEBHOOK_REQUEST_METHOD = ccd('WEBHOOK_REQUEST_METHOD', 'GET' , c_d, 'Req type', 'text.select', "['GET', 'POST', 'PUT']", 'Webhooks')
|
||||
conf.WEBHOOK_SIZE = ccd('WEBHOOK_SIZE', 1024 , c_d, 'Payload size', 'integer', '', 'Webhooks')
|
||||
conf.WEBHOOK_SECRET = ccd('WEBHOOK_SECRET', '' , c_d, 'Secret', 'text', '', 'Webhooks')
|
||||
|
||||
# Init timezone in case it changed
|
||||
conf.tz = timezone(conf.TIMEZONE)
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ def send (msg: noti_obj):
|
||||
payloadData = truncate_json(json_data)
|
||||
if conf.WEBHOOK_PAYLOAD == 'html':
|
||||
if len(msg.html) > limit:
|
||||
payloadData = msg.html[:limit] + " <h1> (text was truncated)</h1>"
|
||||
payloadData = msg.html[:limit] + " <h1>(text was truncated)</h1>"
|
||||
else:
|
||||
payloadData = msg.html
|
||||
if conf.WEBHOOK_PAYLOAD == 'text':
|
||||
|
||||
@@ -26,8 +26,7 @@ from logger import logResult, mylog, print_log
|
||||
|
||||
from publishers.webhook import (check_config as webhook_check_config,
|
||||
send as send_webhook)
|
||||
from publishers.pushsafer import (check_config as pushsafer_check_config,
|
||||
send as send_pushsafer)
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
@@ -259,21 +258,6 @@ def get_notifications (db):
|
||||
return noti_obj(final_json, final_text, final_html)
|
||||
|
||||
|
||||
# if conf.REPORT_WEBHOOK and check_config('webhook'):
|
||||
# updateState("Send: Webhook")
|
||||
# mylog('minimal', ['[Notification] Sending report by Webhook'])
|
||||
# send_webhook (msg)
|
||||
# else :
|
||||
# mylog('verbose', ['[Notification] Skip webhook'])
|
||||
|
||||
# if conf.REPORT_PUSHSAFER and check_config('pushsafer'):
|
||||
# updateState("Send: PUSHSAFER")
|
||||
# mylog('minimal', ['[Notification] Sending report by PUSHSAFER'])
|
||||
# send_pushsafer (msg)
|
||||
# else :
|
||||
# mylog('verbose', ['[Notification] Skip PUSHSAFER'])
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Replacing table headers
|
||||
def format_table (html, thValue, props, newThValue = ''):
|
||||
|
||||
Reference in New Issue
Block a user