From 1688836b4f2f0f76b5772eabe15beddced34dcc7 Mon Sep 17 00:00:00 2001 From: Doctorixx <61980858+Windows-up@users.noreply.github.com> Date: Thu, 29 Aug 2024 16:41:59 +0300 Subject: [PATCH] Add Telegram publisher --- front/plugins/_publisher_telegram/README.md | 10 + front/plugins/_publisher_telegram/config.json | 470 ++++++++++++++++++ front/plugins/_publisher_telegram/tg.py | 124 +++++ 3 files changed, 604 insertions(+) create mode 100644 front/plugins/_publisher_telegram/README.md create mode 100644 front/plugins/_publisher_telegram/config.json create mode 100644 front/plugins/_publisher_telegram/tg.py diff --git a/front/plugins/_publisher_telegram/README.md b/front/plugins/_publisher_telegram/README.md new file mode 100644 index 00000000..87825d64 --- /dev/null +++ b/front/plugins/_publisher_telegram/README.md @@ -0,0 +1,10 @@ +## Overview + +You can send notifications via Telegram +## Notes + +You need Telegram bot to send notifications + +### Usage + +- Go to settings and fill in relevant details. diff --git a/front/plugins/_publisher_telegram/config.json b/front/plugins/_publisher_telegram/config.json new file mode 100644 index 00000000..54510712 --- /dev/null +++ b/front/plugins/_publisher_telegram/config.json @@ -0,0 +1,470 @@ +{ + "code_name": "_publisher_telegram", + "unique_prefix": "TELEGRAM", + "plugin_type": "publisher", + "enabled": true, + "data_source": "script", + "show_ui": true, + "localized": ["display_name", "description", "icon"], + "display_name": [ + { + "language_code": "en_us", + "string": "Telegram publisher" + } + ], + "icon": [ + { + "language_code": "en_us", + "string": "" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "A plugin to publish a notification via Telegram." + } + ], + "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": "url", + "default_value": "", + "options": [], + "localized": ["name"], + "name": [ + { + "language_code": "en_us", + "string": "N/A" + } + ] + }, + { + "column": "Object_SecondaryID", + "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": "DateTimeCreated", + "css_classes": "col-sm-2", + "show": true, + "type": "label", + "default_value": "", + "options": [], + "localized": ["name"], + "name": [ + { + "language_code": "en_us", + "string": "Sent when" + } + ] + }, + { + "column": "DateTimeChanged", + "css_classes": "col-sm-2", + "show": false, + "type": "label", + "default_value": "", + "options": [], + "localized": ["name"], + "name": [ + { + "language_code": "en_us", + "string": "Changed" + }, + { + "language_code": "es_es", + "string": "Cambiado" + } + ] + }, + { + "column": "Watched_Value1", + "css_classes": "col-sm-2", + "show": true, + "type": "eval", + "default_value": "", + "options": [ + { + "type": "eval", + "param": "`${value}`" + } + ], + "localized": ["name"], + "name": [ + { + "language_code": "en_us", + "string": "Notification GUID" + } + ] + }, + { + "column": "Watched_Value2", + "css_classes": "col-sm-8", + "show": true, + "type": "textarea_readonly", + "default_value": "", + "options": [], + "localized": ["name"], + "name": [ + { + "language_code": "en_us", + "string": "Result" + } + ] + }, + { + "column": "Watched_Value3", + "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": "Watched_Value4", + "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": "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": "
" + }, + { + "equals": "watched-changed", + "replacement": "
" + }, + { + "equals": "new", + "replacement": "
" + }, + { + "equals": "missing-in-last-scan", + "replacement": "
" + } + ], + "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": { + "dataType": "string", + "elements": [ + { "elementType": "select", "elementOptions": [], "transformers": [] } + ] + }, + "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 sending notifications via a Telegram messanger" + } + ] + }, + { + "function": "CMD", + "type": { + "dataType": "string", + "elements": [ + { + "elementType": "input", + "elementOptions": [{ "readonly": "true" }], + "transformers": [] + } + ] + }, + "default_value": "python3 /app/front/plugins/_publisher_telegram/tg.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": { + "dataType": "integer", + "elements": [ + { + "elementType": "input", + "elementOptions": [{ "type": "number" }], + "transformers": [] + } + ] + }, + "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": "HOST", + "type": { + "dataType": "string", + "elements": [ + { "elementType": "input", "elementOptions": [], "transformers": [] } + ] + }, + "default_value": "", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Telegram chat id" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Telegram chat id. If you want to send messages to user, paste user id (Example: 1234123412)" + } + ] + }, + { + "function": "URL", + "type": { + "dataType": "string", + "elements": [ + { "elementType": "input", "elementOptions": [], "transformers": [] } + ] + }, + "default_value": "", + "options": [], + "localized": ["name", "description"], + "name": [ + { + "language_code": "en_us", + "string": "Telegram bot token" + } + ], + "description": [ + { + "language_code": "en_us", + "string": "Telegram bot token. You cat get at from BotFather" + } + ] + }, + { + "function": "SIZE", + "type": { + "dataType": "integer", + "elements": [ + { + "elementType": "input", + "elementOptions": [{ "type": "number" }], + "transformers": [] + } + ] + }, + "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 payload as number of characters in the passed string. If above limit, it will be truncated and a (text was truncated) message is appended." + } + ] + } + ] +} diff --git a/front/plugins/_publisher_telegram/tg.py b/front/plugins/_publisher_telegram/tg.py new file mode 100644 index 00000000..9b8e3308 --- /dev/null +++ b/front/plugins/_publisher_telegram/tg.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python + +import json +import subprocess +import argparse +import os +import pathlib +import sys +from datetime import datetime + +# Register NetAlertX directories +INSTALL_PATH = "/app" +sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"]) + +import conf +from const import confFileName +from plugin_helper import Plugin_Objects +from logger import mylog, append_line_to_file +from helper import timeNowTZ, get_setting_value +from notification import Notification_obj +from database import DB +from pytz import timezone + +# Make sure the TIMEZONE for logging is correct +conf.tz = timezone(get_setting_value('TIMEZONE')) + +CUR_PATH = str(pathlib.Path(__file__).parent.resolve()) +RESULT_FILE = os.path.join(CUR_PATH, 'last_result.log') + +pluginName = 'TELEGRAM' + + +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 {confFileName} {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 + result = send(notification["Text"]) + + # Log result + plugin_objects.add_object( + primaryId=pluginName, + secondaryId=timeNowTZ(), + watched1=notification["GUID"], + watched2=result, + watched3='null', + watched4='null', + extra='null', + foreignKey=notification["GUID"] + ) + + plugin_objects.write_result_file() + + +# ------------------------------------------------------------------------------- +def check_config(): + return True + + +# ------------------------------------------------------------------------------- +def send(text): + # limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB) + limit = get_setting_value('TELEGRAM_SIZE') + + if len(text) > limit: + payloadData = text[:limit] + " (text was truncated)" + else: + payloadData = text + + try: + # try runnning a subprocess + + req = """curl --location 'https://api.telegram.org/bot%s/sendMessage' \\ + --header 'Content-Type: application/json' \\ + --data '{ + "chat_id": "%s", + "text": "%s", + "disable_notification": false + }'""" % (get_setting_value('TELEGRAM_URL'), get_setting_value('TELEGRAM_HOST'), payloadData) + + mylog('debug', [req]) + + p = subprocess.Popen(req, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) + stdout, stderr = p.communicate() + + # write stdout and stderr into .log files for debugging if needed + # Log the stdout and stderr + mylog('debug', [stdout, stderr]) + + # log result + result = stdout + + except subprocess.CalledProcessError as e: + # An error occurred, handle it + mylog('none', [e.output]) + + # log result + result = e.output + + return result + + +if __name__ == '__main__': + sys.exit(main())