mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
Notifications refactor and #242 📩
This commit is contained in:
@@ -161,22 +161,9 @@ def main ():
|
||||
if notificationObj.HasNotifications:
|
||||
pluginsState = run_plugin_scripts(db, 'on_notification', pluginsState)
|
||||
notification.setAllProcessed()
|
||||
notification.clearPendingEmailFlag()
|
||||
|
||||
# Clean Pending Alert Events
|
||||
sql.execute ("""UPDATE Devices SET dev_LastNotification = ?
|
||||
WHERE dev_MAC IN (
|
||||
SELECT eve_MAC FROM Events
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
)
|
||||
""", (timeNowTZ(),) )
|
||||
sql.execute ("""UPDATE Events SET eve_PendingAlertEmail = 0
|
||||
WHERE eve_PendingAlertEmail = 1""")
|
||||
|
||||
# clear plugin events
|
||||
sql.execute ("DELETE FROM Plugins_Events")
|
||||
|
||||
# DEBUG - print number of rows updated
|
||||
mylog('minimal', ['[Notification] Notifications changes: ', sql.rowcount])
|
||||
|
||||
else:
|
||||
mylog('verbose', ['[Notification] No changes to report'])
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ def print_scan_stats(db):
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM CurrentScan) AS devices_detected,
|
||||
(SELECT COUNT(*) FROM CurrentScan WHERE NOT EXISTS (SELECT 1 FROM Devices WHERE dev_MAC = cur_MAC)) AS new_devices,
|
||||
(SELECT COUNT(*) FROM Devices WHERE dev_AlertDeviceDown = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE dev_MAC = cur_MAC)) AS down_alerts,
|
||||
(SELECT COUNT(*) FROM Devices WHERE dev_AlertDeviceDown = 1 AND dev_PresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE dev_MAC = cur_MAC)) AS new_down_alerts,
|
||||
(SELECT COUNT(*) FROM Devices WHERE dev_AlertDeviceDown != 0 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE dev_MAC = cur_MAC)) AS down_alerts,
|
||||
(SELECT COUNT(*) FROM Devices WHERE dev_AlertDeviceDown != 0 AND dev_PresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE dev_MAC = cur_MAC)) AS new_down_alerts,
|
||||
(SELECT COUNT(*) FROM Devices WHERE dev_PresentLastScan = 0) AS new_connections,
|
||||
(SELECT COUNT(*) FROM Devices WHERE dev_PresentLastScan = 1 AND NOT EXISTS (SELECT 1 FROM CurrentScan WHERE dev_MAC = cur_MAC)) AS disconnections,
|
||||
(SELECT COUNT(*) FROM Devices, CurrentScan WHERE dev_MAC = cur_MAC AND dev_LastIP <> cur_IP) AS ip_changes,
|
||||
|
||||
@@ -37,6 +37,12 @@ def timeNowTZ():
|
||||
def timeNow():
|
||||
return datetime.datetime.now().replace(microsecond=0)
|
||||
|
||||
def get_timezone_offset():
|
||||
now = datetime.datetime.now(conf.tz)
|
||||
offset_hours = now.utcoffset().total_seconds() / 3600
|
||||
offset_formatted = "{:+03d}:{:02d}".format(int(offset_hours), int((offset_hours % 1) * 60))
|
||||
return offset_formatted
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# App state
|
||||
@@ -470,58 +476,6 @@ def resolve_device_name_pholus (pMAC, pIP, allRes, nameNotFound, match_IP = Fals
|
||||
if 'PTR Class:IN' in value and len(value.split('"')) > 1:
|
||||
return cleanDeviceName(value.split('"')[1], match_IP)
|
||||
|
||||
|
||||
# # airplay matches contain a lot of information
|
||||
# # Matches for example:
|
||||
# # Brand Tv (50)._airplay._tcp.local. TXT Class:32769 "acl=0 deviceid=66:66:66:66:66:66 features=0x77777,0x38BCB46 rsf=0x3 fv=p20.T-FFFFFF-03.1 flags=0x204 model=XXXX manufacturer=Brand serialNumber=XXXXXXXXXXX protovers=1.1 srcvers=777.77.77 pi=FF:FF:FF:FF:FF:FF psi=00000000-0000-0000-0000-FFFFFFFFFF gid=00000000-0000-0000-0000-FFFFFFFFFF gcgl=0 pk=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and '._airplay._tcp.local. TXT Class:32769' in str(allRes[i]["Value"]) :
|
||||
# return cleanDeviceName(allRes[i]["Value"].split('._airplay._tcp.local. TXT Class:32769')[0], match_IP)
|
||||
|
||||
# # second best - contains airplay
|
||||
# # Matches for example:
|
||||
# # _airplay._tcp.local. PTR Class:IN "Brand Tv (50)._airplay._tcp.local."
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and '_airplay._tcp.local. PTR Class:IN' in allRes[i]["Value"] and ('._googlecast') not in allRes[i]["Value"]:
|
||||
# return cleanDeviceName(allRes[i]["Value"].split('"')[1], match_IP)
|
||||
|
||||
# # Contains PTR Class:32769
|
||||
# # Matches for example:
|
||||
# # 3.1.168.192.in-addr.arpa. PTR Class:32769 "MyPc.local."
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and 'PTR Class:32769' in allRes[i]["Value"]:
|
||||
# return cleanDeviceName(allRes[i]["Value"].split('"')[1], match_IP)
|
||||
|
||||
# # Contains AAAA Class:IN
|
||||
# # Matches for example:
|
||||
# # DESKTOP-SOMEID.local. AAAA Class:IN "fe80::fe80:fe80:fe80:fe80"
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and 'AAAA Class:IN' in allRes[i]["Value"]:
|
||||
# return cleanDeviceName(allRes[i]["Value"].split('.local.')[0], match_IP)
|
||||
|
||||
# # Contains _googlecast._tcp.local. PTR Class:IN
|
||||
# # Matches for example:
|
||||
# # _googlecast._tcp.local. PTR Class:IN "Nest-Audio-ff77ff77ff77ff77ff77ff77ff77ff77._googlecast._tcp.local."
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and '_googlecast._tcp.local. PTR Class:IN' in allRes[i]["Value"] and ('Google-Cast-Group') not in allRes[i]["Value"]:
|
||||
# return cleanDeviceName(allRes[i]["Value"].split('"')[1], match_IP)
|
||||
|
||||
# # Contains A Class:32769
|
||||
# # Matches for example:
|
||||
# # Android.local. A Class:32769 "192.168.1.6"
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and ' A Class:32769' in allRes[i]["Value"]:
|
||||
# return cleanDeviceName(allRes[i]["Value"].split(' A Class:32769')[0], match_IP)
|
||||
|
||||
|
||||
# # # Contains PTR Class:IN
|
||||
# # Matches for example:
|
||||
# # _esphomelib._tcp.local. PTR Class:IN "ceiling-light-1._esphomelib._tcp.local."
|
||||
# for i in pholusMatchesIndexes:
|
||||
# if checkIPV4(allRes[i]['IP_v4_or_v6']) and 'PTR Class:IN' in allRes[i]["Value"]:
|
||||
# if allRes[i]["Value"] and len(allRes[i]["Value"].split('"')) > 1:
|
||||
# return cleanDeviceName(allRes[i]["Value"].split('"')[1], match_IP)
|
||||
|
||||
return nameNotFound
|
||||
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ def insert_events (db):
|
||||
eve_PendingAlertEmail)
|
||||
SELECT dev_MAC, dev_LastIP, '{startTime}', 'Device Down', '', 1
|
||||
FROM Devices
|
||||
WHERE dev_AlertDeviceDown = 1
|
||||
WHERE dev_AlertDeviceDown != 0
|
||||
AND dev_PresentLastScan = 1
|
||||
AND NOT EXISTS (SELECT 1 FROM CurrentScan
|
||||
WHERE dev_MAC = cur_MAC
|
||||
|
||||
@@ -10,7 +10,7 @@ import conf
|
||||
import const
|
||||
from const import pialertPath, logPath, apiPath
|
||||
from logger import logResult, mylog, print_log
|
||||
from helper import generate_mac_links, removeDuplicateNewLines, timeNowTZ, get_file_content, write_file
|
||||
from helper import generate_mac_links, removeDuplicateNewLines, timeNowTZ, get_file_content, write_file, get_setting_value, get_timezone_offset
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Notification object handling
|
||||
@@ -209,7 +209,34 @@ class Notification_obj:
|
||||
|
||||
self.save()
|
||||
|
||||
|
||||
def clearPendingEmailFlag(self):
|
||||
|
||||
# Clean Pending Alert Events
|
||||
self.db.sql.execute ("""UPDATE Devices SET dev_LastNotification = ?
|
||||
WHERE dev_MAC IN (
|
||||
SELECT eve_MAC FROM Events
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
)
|
||||
""", (timeNowTZ(),) )
|
||||
|
||||
self.db.sql.execute ("""UPDATE Events SET eve_PendingAlertEmail = 0
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
AND eve_EventType !='Device Down' """)
|
||||
|
||||
# Clear down events flag after the reporting window passed
|
||||
self.db.sql.execute (f"""UPDATE Events SET eve_PendingAlertEmail = 0
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
AND eve_EventType =='Device Down'
|
||||
AND eve_DateTime < datetime('now', '-{get_setting_value('NTFPRCS_alert_down_time')} minutes', '{get_timezone_offset()}')
|
||||
""")
|
||||
|
||||
# clear plugin events
|
||||
self.db.sql.execute ("DELETE FROM Plugins_Events")
|
||||
|
||||
# DEBUG - print number of rows updated
|
||||
mylog('minimal', ['[Notification] Notifications changes: ', self.db.sql.rowcount])
|
||||
|
||||
self.save()
|
||||
|
||||
def save(self):
|
||||
# Commit changes
|
||||
|
||||
@@ -17,7 +17,7 @@ import json
|
||||
import conf
|
||||
import const
|
||||
from const import pialertPath, logPath, apiPath
|
||||
from helper import timeNowTZ, get_file_content, write_file
|
||||
from helper import timeNowTZ, get_file_content, write_file, get_timezone_offset, get_setting_value
|
||||
from logger import logResult, mylog, print_log
|
||||
|
||||
|
||||
@@ -74,10 +74,21 @@ def get_notifications (db):
|
||||
|
||||
if 'down_devices' in conf.INCLUDED_SECTIONS :
|
||||
# Compose Devices Down Section
|
||||
sqlQuery = """SELECT eve_MAC as MAC, eve_DateTime as Datetime, dev_LastIP as IP, eve_EventType as "Event Type", dev_Name as "Device name", dev_Comments as Comments FROM Events_Devices
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
AND eve_EventType = 'Device Down'
|
||||
ORDER BY eve_DateTime"""
|
||||
sqlQuery = f"""
|
||||
SELECT *
|
||||
FROM Events AS down_events
|
||||
WHERE eve_PendingAlertEmail = 1
|
||||
AND down_events.eve_EventType = 'Device Down'
|
||||
AND eve_DateTime < datetime('now', '-{get_setting_value('NTFPRCS_alert_down_time')} minutes', '{get_timezone_offset()}')
|
||||
AND NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM Events AS connected_events
|
||||
WHERE connected_events.eve_MAC = down_events.eve_MAC
|
||||
AND connected_events.eve_EventType = 'Connected'
|
||||
AND connected_events.eve_DateTime > down_events.eve_DateTime
|
||||
)
|
||||
ORDER BY down_events.eve_DateTime;
|
||||
"""
|
||||
|
||||
# Get the events as JSON
|
||||
json_obj = db.get_table_as_json(sqlQuery)
|
||||
@@ -139,7 +150,8 @@ def skip_repeated_notifications (db):
|
||||
|
||||
# Skip repeated notifications
|
||||
# due strfime : Overflow --> use "strftime / 60"
|
||||
mylog('verbose','[Skip Repeated Notifications] Skip Repeated start')
|
||||
mylog('verbose','[Skip Repeated Notifications] Skip Repeated')
|
||||
|
||||
db.sql.execute ("""UPDATE Events SET eve_PendingAlertEmail = 0
|
||||
WHERE eve_PendingAlertEmail = 1 AND eve_MAC IN
|
||||
(
|
||||
@@ -151,7 +163,7 @@ def skip_repeated_notifications (db):
|
||||
(strftime('%s','now','localtime')/60 )
|
||||
)
|
||||
""" )
|
||||
mylog('verbose','[Skip Repeated Notifications] Skip Repeated end')
|
||||
|
||||
|
||||
db.commitDB()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user