mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Notification rework v0.3
This commit is contained in:
@@ -24,13 +24,13 @@ import multiprocessing
|
||||
import conf
|
||||
from const import *
|
||||
from logger import mylog
|
||||
from helper import filePermissions, timeNowTZ, updateState, get_setting_value, noti_struc
|
||||
from helper import filePermissions, timeNowTZ, updateState, get_setting_value, noti_obj
|
||||
from api import update_api
|
||||
from networkscan import process_scan
|
||||
from initialise import importConfigs
|
||||
from database import DB, get_all_devices
|
||||
from database import DB
|
||||
from reporting import get_notifications
|
||||
from notifications import Notifications
|
||||
from notification import Notification_obj
|
||||
from plugin import run_plugin_scripts, check_and_run_user_event
|
||||
|
||||
|
||||
@@ -154,16 +154,13 @@ def main ():
|
||||
notiStructure = get_notifications(db)
|
||||
|
||||
# Write the notifications into the DB
|
||||
notification = Notifications(db)
|
||||
notification = Notification_obj(db)
|
||||
hasNotification = notification.create(notiStructure.json, notiStructure.text, notiStructure.html, "")
|
||||
|
||||
# mylog('debug', f"[MAIN] notiStructure.text: {notiStructure.text} ")
|
||||
# mylog('debug', f"[MAIN] notiStructure.json: {notiStructure.json} ")
|
||||
# mylog('debug', f"[MAIN] notiStructure.html: {notiStructure.html} ")
|
||||
|
||||
hasNotifications = notification.create(notiStructure.json, notiStructure.text, notiStructure.html, "")
|
||||
|
||||
if hasNotifications:
|
||||
# run all enabled publisher gateways
|
||||
if hasNotification:
|
||||
pluginsState = run_plugin_scripts(db, 'on_notification', pluginsState)
|
||||
notification.setAllProcessed()
|
||||
|
||||
|
||||
# Commit SQL
|
||||
|
||||
125
pialert/appevent.py
Normal file
125
pialert/appevent.py
Normal file
@@ -0,0 +1,125 @@
|
||||
import datetime
|
||||
import json
|
||||
import uuid
|
||||
|
||||
# PiAlert modules
|
||||
import conf
|
||||
import const
|
||||
from const import pialertPath, logPath, apiPath
|
||||
from logger import logResult, mylog, print_log
|
||||
from helper import timeNowTZ
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Execution object handling
|
||||
#-------------------------------------------------------------------------------
|
||||
class AppEvent_obj:
|
||||
def __init__(self, db):
|
||||
self.db = db
|
||||
|
||||
# Create AppEvent table if missing
|
||||
self.db.sql.execute("""CREATE TABLE IF NOT EXISTS "AppEvents" (
|
||||
"Index" INTEGER,
|
||||
"GUID" TEXT UNIQUE,
|
||||
"DateTimeCreated" TEXT,
|
||||
"ObjectType" TEXT, -- ObjectType (Plugins, Notifications, Events)
|
||||
"ObjectGUID" TEXT,
|
||||
"ObjectPlugin" TEXT,
|
||||
"ObjectMAC" TEXT,
|
||||
"ObjectIP" TEXT,
|
||||
"ObjectPrimaryID" TEXT,
|
||||
"ObjectSecondaryID" TEXT,
|
||||
"ObjectForeignKey" TEXT,
|
||||
"ObjectIndex" TEXT,
|
||||
"ObjectRowID" TEXT,
|
||||
"ObjectStatusColumn" TEXT, -- Status (Notifications, Plugins), eve_EventType (Events)
|
||||
"ObjectStatus" TEXT, -- new_devices, down_devices, events, new, watched-changed, watched-not-changed, missing-in-last-scan, Device down, New Device, IP Changed, Connected, Disconnected, VOIDED - Disconnected, VOIDED - Connected, <missing event>
|
||||
"AppEventStatus" TEXT, -- TBD "new", "used", "cleanup-next"
|
||||
"Extra" TEXT,
|
||||
PRIMARY KEY("Index" AUTOINCREMENT)
|
||||
);
|
||||
""")
|
||||
|
||||
self.save()
|
||||
|
||||
# Create a new DB entry if new notifications are available, otherwise skip
|
||||
def create(self, Extra="", **kwargs):
|
||||
# Check if nothing to report, end
|
||||
if not any(kwargs.values()):
|
||||
return False
|
||||
|
||||
# Continue and save into DB if notifications are available
|
||||
self.GUID = str(uuid.uuid4())
|
||||
self.DateTimeCreated = timeNowTZ()
|
||||
self.ObjectType = "Plugins" # Modify ObjectType as needed
|
||||
|
||||
# Optional parameters
|
||||
self.ObjectGUID = kwargs.get("ObjectGUID", "")
|
||||
self.ObjectPlugin = kwargs.get("ObjectPlugin", "")
|
||||
self.ObjectMAC = kwargs.get("ObjectMAC", "")
|
||||
self.ObjectIP = kwargs.get("ObjectIP", "")
|
||||
self.ObjectPrimaryID = kwargs.get("ObjectPrimaryID", "")
|
||||
self.ObjectSecondaryID = kwargs.get("ObjectSecondaryID", "")
|
||||
self.ObjectForeignKey = kwargs.get("ObjectForeignKey", "")
|
||||
self.ObjectIndex = kwargs.get("ObjectIndex", "")
|
||||
self.ObjectRowID = kwargs.get("ObjectRowID", "")
|
||||
self.ObjectStatusColumn = kwargs.get("ObjectStatusColumn", "")
|
||||
self.ObjectStatus = kwargs.get("ObjectStatus", "")
|
||||
|
||||
self.AppEventStatus = "new" # Modify AppEventStatus as needed
|
||||
self.Extra = Extra
|
||||
|
||||
self.upsert()
|
||||
|
||||
return True
|
||||
|
||||
# Update the status of the entry
|
||||
def updateStatus(self, newStatus):
|
||||
self.ObjectStatus = newStatus
|
||||
self.upsert()
|
||||
|
||||
def upsert(self):
|
||||
self.db.sql.execute("""
|
||||
INSERT OR REPLACE INTO AppEvents (
|
||||
"GUID",
|
||||
"DateTimeCreated",
|
||||
"ObjectType",
|
||||
"ObjectGUID",
|
||||
"ObjectPlugin",
|
||||
"ObjectMAC",
|
||||
"ObjectIP",
|
||||
"ObjectPrimaryID",
|
||||
"ObjectSecondaryID",
|
||||
"ObjectForeignKey",
|
||||
"ObjectIndex",
|
||||
"ObjectRowID",
|
||||
"ObjectStatusColumn",
|
||||
"ObjectStatus",
|
||||
"AppEventStatus",
|
||||
"Extra"
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
self.GUID,
|
||||
self.DateTimeCreated,
|
||||
self.ObjectType,
|
||||
self.ObjectGUID,
|
||||
self.ObjectPlugin,
|
||||
self.ObjectMAC,
|
||||
self.ObjectIP,
|
||||
self.ObjectPrimaryID,
|
||||
self.ObjectSecondaryID,
|
||||
self.ObjectForeignKey,
|
||||
self.ObjectIndex,
|
||||
self.ObjectRowID,
|
||||
self.ObjectStatusColumn,
|
||||
self.ObjectStatus,
|
||||
self.AppEventStatus,
|
||||
self.Extra
|
||||
))
|
||||
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
# Commit changes
|
||||
self.db.commitDB()
|
||||
|
||||
@@ -6,7 +6,7 @@ import sqlite3
|
||||
from const import fullDbPath, sql_devices_stats, sql_devices_all
|
||||
|
||||
from logger import mylog
|
||||
from helper import json_struc, initOrSetParam, row_to_json, timeNowTZ #, updateState
|
||||
from helper import json_obj, initOrSetParam, row_to_json, timeNowTZ #, updateState
|
||||
|
||||
|
||||
|
||||
@@ -208,10 +208,7 @@ class DB():
|
||||
"par_ID" TEXT PRIMARY KEY,
|
||||
"par_Value" TEXT
|
||||
);
|
||||
""")
|
||||
|
||||
# Initialize Parameters if unavailable
|
||||
initOrSetParam(self, 'Back_App_State','Initializing')
|
||||
""")
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Nmap_Scan table setup DEPRECATED after 1/1/2024
|
||||
@@ -384,7 +381,7 @@ class DB():
|
||||
rows = self.sql.fetchall()
|
||||
except sqlite3.Error as e:
|
||||
mylog('none',[ '[Database] - SQL ERROR: ', e])
|
||||
return None
|
||||
return json_obj({}, []) # return empty object
|
||||
|
||||
result = {"data":[]}
|
||||
for row in rows:
|
||||
@@ -392,7 +389,7 @@ class DB():
|
||||
result["data"].append(tmp)
|
||||
|
||||
# mylog('debug',[ '[Database] - get_table_as_json - returning ', len(rows), " rows with columns: ", columnNames])
|
||||
return json_struc(result, columnNames)
|
||||
return json_obj(result, columnNames)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# referece from here: https://codereview.stackexchange.com/questions/241043/interface-class-for-sqlite-databases
|
||||
|
||||
@@ -613,13 +613,13 @@ def initOrSetParam(db, parID, parValue):
|
||||
db.commitDB()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
class json_struc:
|
||||
class json_obj:
|
||||
def __init__(self, jsn, columnNames):
|
||||
self.json = jsn
|
||||
self.columnNames = columnNames
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
class noti_struc:
|
||||
class noti_obj:
|
||||
def __init__(self, json, text, html):
|
||||
self.json = json
|
||||
self.text = text
|
||||
|
||||
@@ -134,13 +134,6 @@ def importConfigs (db):
|
||||
conf.WEBHOOK_SIZE = ccd('WEBHOOK_SIZE', 1024 , c_d, 'Payload size', 'integer', '', 'Webhooks')
|
||||
conf.WEBHOOK_SECRET = ccd('WEBHOOK_SECRET', '' , c_d, 'Secret', 'text', '', 'Webhooks')
|
||||
|
||||
# Apprise
|
||||
conf.REPORT_APPRISE = ccd('REPORT_APPRISE', False , c_d, 'Enable Apprise', 'boolean', '', 'Apprise', ['test'])
|
||||
conf.APPRISE_HOST = ccd('APPRISE_HOST', '' , c_d, 'Apprise host URL', 'text', '', 'Apprise')
|
||||
conf.APPRISE_URL = ccd('APPRISE_URL', '' , c_d, 'Apprise notification URL', 'text', '', 'Apprise')
|
||||
conf.APPRISE_PAYLOAD = ccd('APPRISE_PAYLOAD', 'html' , c_d, 'Payload type', 'text.select', "['html', 'text']", 'Apprise')
|
||||
conf.APPRISE_SIZE = ccd('APPRISE_SIZE', 1024 , c_d, 'Payload size', 'integer', '', 'Apprise')
|
||||
|
||||
# NTFY
|
||||
conf.REPORT_NTFY = ccd('REPORT_NTFY', False , c_d, 'Enable NTFY', 'boolean', '', 'NTFY', ['test'])
|
||||
conf.NTFY_HOST = ccd('NTFY_HOST', 'https://ntfy.sh' , c_d, 'NTFY host URL', 'text', '', 'NTFY')
|
||||
@@ -261,9 +254,6 @@ def importConfigs (db):
|
||||
sql.execute ("DELETE FROM Settings")
|
||||
sql.executemany ("""INSERT INTO Settings ("Code_Name", "Display_Name", "Description", "Type", "Options",
|
||||
"RegEx", "Value", "Group", "Events" ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""", conf.mySettingsSQLsafe)
|
||||
|
||||
# Is used to display a message in the UI when old (outdated) settings are loaded
|
||||
initOrSetParam(db, "Back_Settings_Imported",(round(time.time() * 1000),) )
|
||||
|
||||
#commitDB(sql_connection)
|
||||
db.commitDB()
|
||||
|
||||
@@ -12,7 +12,7 @@ from helper import timeNowTZ
|
||||
#-------------------------------------------------------------------------------
|
||||
# Notification object handling
|
||||
#-------------------------------------------------------------------------------
|
||||
class Notifications:
|
||||
class Notification_obj:
|
||||
def __init__(self, db):
|
||||
self.db = db
|
||||
|
||||
@@ -35,11 +35,9 @@ class Notifications:
|
||||
self.save()
|
||||
|
||||
# Create a new DB entry if new notiifcations available, otherwise skip
|
||||
def create(self, JSON, Text, HTML, Extra=""):
|
||||
|
||||
# Check if empty JSON
|
||||
# _json = json.loads(JSON)
|
||||
# Check if nothing to report
|
||||
def create(self, JSON, Text, HTML, Extra=""):
|
||||
|
||||
# Check if nothing to report, end
|
||||
if JSON["internet"] == [] and JSON["new_devices"] == [] and JSON["down_devices"] == [] and JSON["events"] == [] and JSON["plugins"] == []:
|
||||
self.HasNotifications = False
|
||||
# end if nothing to report
|
||||
@@ -75,6 +73,7 @@ class Notifications:
|
||||
|
||||
# TODO Index vs hash to minimize SQL calls, finish CRUD operations, expose via API, use API in plugins
|
||||
|
||||
# create or update a notification
|
||||
def upsert(self):
|
||||
self.db.sql.execute("""
|
||||
INSERT OR REPLACE INTO Notifications (GUID, DateTimeCreated, DateTimePushed, Status, JSON, Text, HTML, PublishedVia, Extra)
|
||||
@@ -83,6 +82,28 @@ class Notifications:
|
||||
|
||||
self.save()
|
||||
|
||||
# Get all with the "new" status
|
||||
def getNew(self):
|
||||
self.db.sql.execute("""
|
||||
SELECT * FROM Notifications
|
||||
WHERE Status = "new"
|
||||
""")
|
||||
return self.db.sql.fetchall()
|
||||
|
||||
# Set all to "processed" status
|
||||
def setAllProcessed(self):
|
||||
|
||||
# Execute an SQL query to update the status of all notifications
|
||||
self.db.sql.execute("""
|
||||
UPDATE Notifications
|
||||
SET Status = "processed"
|
||||
WHERE Status = "new"
|
||||
""")
|
||||
|
||||
self.save()
|
||||
|
||||
|
||||
|
||||
def save(self):
|
||||
# Commit changes
|
||||
self.db.commitDB()
|
||||
@@ -791,7 +791,7 @@ def handle_test(testType):
|
||||
# Open json sample and get only the payload part
|
||||
sample_json_payload = json.loads(get_file_content(pialertPath + '/back/webhook_json_sample.json'))[0]["body"]["attachments"][0]["text"]
|
||||
|
||||
sample_msg = noti_struc(sample_json_payload, sample_txt, sample_html, "test_sample")
|
||||
sample_msg = noti_obj(sample_json_payload, sample_txt, sample_html, "test_sample")
|
||||
|
||||
|
||||
if testType == 'Email':
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import json
|
||||
import subprocess
|
||||
import conf
|
||||
from helper import noti_struc
|
||||
from helper import noti_obj
|
||||
from logger import logResult, mylog
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -14,7 +14,7 @@ def check_config():
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def send(msg: noti_struc):
|
||||
def send(msg: noti_obj):
|
||||
html = msg.html
|
||||
text = msg.text
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import smtplib
|
||||
|
||||
import conf
|
||||
import socket
|
||||
from helper import hide_email, noti_struc
|
||||
from helper import hide_email, noti_obj
|
||||
from logger import mylog, print_log
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -19,7 +19,7 @@ def check_config ():
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def send (msg: noti_struc):
|
||||
def send (msg: noti_obj):
|
||||
|
||||
pText = msg.text
|
||||
pHTML = msg.html
|
||||
|
||||
@@ -4,7 +4,7 @@ import requests
|
||||
from base64 import b64encode
|
||||
|
||||
from logger import mylog
|
||||
from helper import noti_struc
|
||||
from helper import noti_obj
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def check_config():
|
||||
@@ -15,7 +15,7 @@ def check_config():
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def send (msg: noti_struc):
|
||||
def send (msg: noti_obj):
|
||||
|
||||
headers = {
|
||||
"Title": "Pi.Alert Notification",
|
||||
|
||||
@@ -3,7 +3,7 @@ import requests
|
||||
|
||||
|
||||
import conf
|
||||
from helper import noti_struc
|
||||
from helper import noti_obj
|
||||
from logger import mylog
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -15,7 +15,7 @@ def check_config():
|
||||
return True
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
def send ( msg:noti_struc ):
|
||||
def send ( msg:noti_obj ):
|
||||
_Text = msg.text
|
||||
url = 'https://www.pushsafer.com/api'
|
||||
post_fields = {
|
||||
|
||||
@@ -5,7 +5,7 @@ import hmac
|
||||
|
||||
import conf
|
||||
from const import logPath
|
||||
from helper import noti_struc, write_file
|
||||
from helper import noti_obj, write_file
|
||||
from logger import logResult, mylog
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -18,7 +18,7 @@ def check_config():
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
def send (msg: noti_struc):
|
||||
def send (msg: noti_obj):
|
||||
|
||||
# limit = 1024 * 1024 # 1MB limit (1024 bytes * 1024 bytes = 1MB)
|
||||
limit = conf.WEBHOOK_SIZE
|
||||
|
||||
@@ -21,7 +21,7 @@ from json2table import convert
|
||||
import conf
|
||||
import const
|
||||
from const import pialertPath, logPath, apiPath
|
||||
from helper import noti_struc, generate_mac_links, removeDuplicateNewLines, timeNowTZ, hide_email, updateState, get_file_content, write_file
|
||||
from helper import noti_obj, generate_mac_links, removeDuplicateNewLines, timeNowTZ, hide_email, updateState, get_file_content, write_file
|
||||
from logger import logResult, mylog, print_log
|
||||
|
||||
from publishers.email import (check_config as email_check_config,
|
||||
@@ -51,7 +51,7 @@ json_final = []
|
||||
def construct_notifications(db, sqlQuery, tableTitle, skipText = False, suppliedJsonStruct = None):
|
||||
|
||||
if suppliedJsonStruct is None and sqlQuery == "":
|
||||
return noti_struc("", "", "")
|
||||
return noti_obj("", "", "")
|
||||
|
||||
table_attributes = {"style" : "border-collapse: collapse; font-size: 12px; color:#70707", "width" : "100%", "cellspacing" : 0, "cellpadding" : "3px", "bordercolor" : "#C0C0C0", "border":"1"}
|
||||
headerProps = "width='120px' style='color:white; font-size: 16px;' bgcolor='#64a0d6' "
|
||||
@@ -61,11 +61,11 @@ def construct_notifications(db, sqlQuery, tableTitle, skipText = False, supplied
|
||||
text_line = '{}\t{}\n'
|
||||
|
||||
if suppliedJsonStruct is None:
|
||||
json_struc = db.get_table_as_json(sqlQuery)
|
||||
json_obj = db.get_table_as_json(sqlQuery)
|
||||
else:
|
||||
json_struc = suppliedJsonStruct
|
||||
json_obj = suppliedJsonStruct
|
||||
|
||||
jsn = json_struc.json
|
||||
jsn = json_obj.json
|
||||
html = ""
|
||||
text = ""
|
||||
|
||||
@@ -78,7 +78,7 @@ def construct_notifications(db, sqlQuery, tableTitle, skipText = False, supplied
|
||||
# Cleanup the generated HTML table notification
|
||||
html = format_table(html, "data", headerProps, tableTitle).replace('<ul>','<ul style="list-style:none;padding-left:0">').replace("<td>null</td>", "<td></td>")
|
||||
|
||||
headers = json_struc.columnNames
|
||||
headers = json_obj.columnNames
|
||||
|
||||
# prepare text-only message
|
||||
if skipText == False:
|
||||
@@ -95,7 +95,7 @@ def construct_notifications(db, sqlQuery, tableTitle, skipText = False, supplied
|
||||
for header in headers:
|
||||
html = format_table(html, header, thProps)
|
||||
|
||||
notiStruc = noti_struc(jsn, text, html)
|
||||
notiStruc = noti_obj(jsn, text, html)
|
||||
|
||||
|
||||
if not notiStruc.json['data'] and not notiStruc.text and not notiStruc.html:
|
||||
@@ -263,14 +263,14 @@ def get_notifications (db):
|
||||
write_file (logPath + '/report_output.txt', final_text)
|
||||
write_file (logPath + '/report_output.html', final_html)
|
||||
|
||||
return noti_struc(final_json, final_text, final_html)
|
||||
return noti_obj(final_json, final_text, final_html)
|
||||
|
||||
# # Notify is something to report
|
||||
# if hasNotifications:
|
||||
|
||||
# mylog('none', ['[Notification] Changes detected, sending reports'])
|
||||
|
||||
# msg = noti_struc(json_final, mail_text, mail_html)
|
||||
# msg = noti_obj(json_final, mail_text, mail_html)
|
||||
|
||||
# mylog('minimal', ['[Notification] Udating API files'])
|
||||
# send_api()
|
||||
|
||||
Reference in New Issue
Block a user