WEBHOOK conversion + cleanup work🎣

This commit is contained in:
Jokob-sk
2023-10-22 09:29:25 +11:00
parent fdd199935a
commit 55e398dd10
17 changed files with 653 additions and 128 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View 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.

View 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>."
}]
}
]
}

View File

@@ -1 +0,0 @@
This plugin will not be loaded

View 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())

View File

@@ -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 |

View File

@@ -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 |

View File

@@ -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
# -------------------------------------------

View File

@@ -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:

View File

@@ -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)

View File

@@ -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':

View File

@@ -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 = ''):