mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-06 17:15:38 -08:00
BE/PLG: TZ timestamp work #1251
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -14,7 +14,7 @@ INSTALL_PATH="/app"
|
||||
sys.path.extend([f"{INSTALL_PATH}/front/plugins", f"{INSTALL_PATH}/server"])
|
||||
|
||||
from database import get_temp_db_connection
|
||||
from helper import is_random_mac, format_date, get_setting_value
|
||||
from helper import is_random_mac, format_date, get_setting_value, timeNowTZ
|
||||
from db.db_helper import row_to_json, get_date_from_period
|
||||
|
||||
# --------------------------
|
||||
@@ -30,7 +30,7 @@ def get_device_data(mac):
|
||||
|
||||
# Special case for new device
|
||||
if mac.lower() == "new":
|
||||
now = datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||
now = timeNowTZ().astimezone().isoformat()
|
||||
device_data = {
|
||||
"devMac": "",
|
||||
"devName": "",
|
||||
@@ -78,7 +78,6 @@ def get_device_data(mac):
|
||||
# Compute period date for sessions/events
|
||||
period = request.args.get('period', '') # e.g., '7 days', '1 month', etc.
|
||||
period_date_sql = get_date_from_period(period)
|
||||
current_date = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
# Fetch device info + computed fields
|
||||
sql = f"""
|
||||
@@ -106,7 +105,7 @@ def get_device_data(mac):
|
||||
AND eve_EventType = 'Device Down') AS devDownAlerts,
|
||||
|
||||
(SELECT CAST(MAX(0, SUM(
|
||||
julianday(IFNULL(ses_DateTimeDisconnection,'{current_date}')) -
|
||||
julianday(IFNULL(ses_DateTimeDisconnection,'{now}')) -
|
||||
julianday(CASE WHEN ses_DateTimeConnection < {period_date_sql}
|
||||
THEN {period_date_sql} ELSE ses_DateTimeConnection END)
|
||||
) * 24) AS INT)
|
||||
@@ -186,8 +185,8 @@ def set_device_data(mac, data):
|
||||
data.get("devSkipRepeated", 0),
|
||||
data.get("devIsNew", 0),
|
||||
data.get("devIsArchived", 0),
|
||||
data.get("devLastConnection", datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
|
||||
data.get("devFirstConnection", datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
|
||||
data.get("devLastConnection", timeNowTZ().astimezone().isoformat()),
|
||||
data.get("devFirstConnection", timeNowTZ().astimezone().isoformat()),
|
||||
data.get("devLastIP", ""),
|
||||
data.get("devGUID", ""),
|
||||
data.get("devCustomProps", ""),
|
||||
|
||||
@@ -59,7 +59,7 @@ class app_state_class:
|
||||
previousState = ""
|
||||
|
||||
# Update self
|
||||
self.lastUpdated = str(timeNowTZ())
|
||||
self.lastUpdated = str(timeNowTZ().astimezone().isoformat())
|
||||
|
||||
if os.path.exists(stateFile):
|
||||
try:
|
||||
@@ -107,7 +107,7 @@ class app_state_class:
|
||||
if pluginsStates is not None:
|
||||
for plugin, state in pluginsStates.items():
|
||||
if plugin in self.pluginsStates:
|
||||
# Only update existing keys if both are dicts
|
||||
# Only update existing keys if both are dicts
|
||||
if isinstance(self.pluginsStates[plugin], dict) and isinstance(state, dict):
|
||||
self.pluginsStates[plugin].update(state)
|
||||
else:
|
||||
|
||||
@@ -58,25 +58,6 @@ def get_timezone_offset():
|
||||
# Date and time methods
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# # -------------------------------------------------------------------------------------------
|
||||
# def format_date(date_str: str) -> str:
|
||||
# """Format a date string as 'YYYY-MM-DD HH:MM'"""
|
||||
# dt = datetime.datetime.fromisoformat(date_str) if isinstance(date_str, str) else date_str
|
||||
# return dt.strftime('%Y-%m-%d %H:%M')
|
||||
|
||||
# # -------------------------------------------------------------------------------------------
|
||||
# def format_date_diff(date1: str, date2: str) -> str:
|
||||
# """Return difference between two dates formatted as 'Xd HH:MM'"""
|
||||
# dt1 = datetime.datetime.fromisoformat(date1) if isinstance(date1, str) else date1
|
||||
# dt2 = datetime.datetime.fromisoformat(date2) if isinstance(date2, str) else date2
|
||||
# delta = dt2 - dt1
|
||||
|
||||
# days = delta.days
|
||||
# hours, remainder = divmod(delta.seconds, 3600)
|
||||
# minutes = remainder // 60
|
||||
|
||||
# return f"{days}d {hours:02}:{minutes:02}"
|
||||
|
||||
# -------------------------------------------------------------------------------------------
|
||||
def format_date_iso(date1: str) -> str:
|
||||
"""Return ISO 8601 string for a date or None if empty"""
|
||||
|
||||
@@ -93,6 +93,9 @@ class plugin_manager:
|
||||
|
||||
# Update plugin states in app_state
|
||||
current_plugin_state = self.get_plugin_states(prefix) # get latest plugin state
|
||||
|
||||
# mylog('debug', f'current_plugin_state: {current_plugin_state}')
|
||||
|
||||
updateState(pluginsStates={prefix: current_plugin_state.get(prefix, {})})
|
||||
|
||||
# update last run time
|
||||
@@ -218,6 +221,7 @@ class plugin_manager:
|
||||
"""
|
||||
sql = self.db.sql
|
||||
plugin_states = {}
|
||||
now_str = timeNowTZ().isoformat()
|
||||
|
||||
if plugin_name: # Only compute for single plugin
|
||||
sql.execute("""
|
||||
@@ -228,7 +232,7 @@ class plugin_manager:
|
||||
WHERE Plugin = ?
|
||||
""", (plugin_name,))
|
||||
row = sql.fetchone()
|
||||
last_changed, total_objects, new_objects, state_updated = row if row else ("", 0, 0)
|
||||
last_changed, total_objects, new_objects = row if row else ("", 0, 0)
|
||||
new_objects = new_objects or 0 # ensure it's int
|
||||
changed_objects = total_objects - new_objects
|
||||
|
||||
@@ -237,7 +241,7 @@ class plugin_manager:
|
||||
"totalObjects": total_objects or 0,
|
||||
"newObjects": new_objects or 0,
|
||||
"changedObjects": changed_objects or 0,
|
||||
"stateUpdated": timeNowTZ()
|
||||
"stateUpdated": now_str
|
||||
}
|
||||
|
||||
# Save in memory
|
||||
@@ -252,7 +256,7 @@ class plugin_manager:
|
||||
FROM Plugins_Objects
|
||||
GROUP BY Plugin
|
||||
""")
|
||||
for plugin, last_changed, total_objects, new_objects, state_updated in sql.fetchall():
|
||||
for plugin, last_changed, total_objects, new_objects in sql.fetchall():
|
||||
new_objects = new_objects or 0 # ensure it's int
|
||||
changed_objects = total_objects - new_objects
|
||||
plugin_states[plugin] = {
|
||||
@@ -260,7 +264,7 @@ class plugin_manager:
|
||||
"totalObjects": total_objects or 0,
|
||||
"newObjects": new_objects or 0,
|
||||
"changedObjects": changed_objects or 0,
|
||||
"stateUpdated": timeNowTZ()
|
||||
"stateUpdated": now_str
|
||||
}
|
||||
|
||||
# Save in memory
|
||||
@@ -755,7 +759,7 @@ def process_plugin_events(db, plugin, plugEventsArr):
|
||||
if isMissing:
|
||||
# if wasn't missing before, mark as changed
|
||||
if tmpObj.status != "missing-in-last-scan":
|
||||
tmpObj.changed = timeNowTZ().strftime('%Y-%m-%d %H:%M:%S')
|
||||
tmpObj.changed = timeNowTZ().astimezone().isoformat()
|
||||
tmpObj.status = "missing-in-last-scan"
|
||||
# mylog('debug', [f'[Plugins] Missing from last scan (PrimaryID | SecondaryID): {tmpObj.primaryId} | {tmpObj.secondaryId}'])
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import subprocess
|
||||
import conf
|
||||
import os
|
||||
import re
|
||||
import datetime
|
||||
from dateutil import parser
|
||||
|
||||
# Register NetAlertX directories
|
||||
@@ -55,7 +56,7 @@ def exclude_ignored_devices(db):
|
||||
#-------------------------------------------------------------------------------
|
||||
def update_devices_data_from_scan (db):
|
||||
sql = db.sql #TO-DO
|
||||
startTime = timeNowTZ().strftime('%Y-%m-%d %H:%M:%S')
|
||||
startTime = timeNowTZ().astimezone().isoformat()
|
||||
|
||||
# Update Last Connection
|
||||
mylog('debug', '[Update Devices] 1 Last Connection')
|
||||
@@ -528,23 +529,27 @@ def update_devices_names(pm):
|
||||
# --- Short-circuit if no name-resolution plugin has changed ---
|
||||
name_plugins = ["DIGSCAN", "NSLOOKUP", "NBTSCAN", "AVAHISCAN"]
|
||||
|
||||
# Retrieve last time name resolution was checked (string or datetime)
|
||||
last_checked_str = pm.name_plugins_checked
|
||||
last_checked_dt = parser.parse(last_checked_str) if isinstance(last_checked_str, str) else last_checked_str
|
||||
# Retrieve last time name resolution was checked
|
||||
last_checked = pm.name_plugins_checked
|
||||
|
||||
# Collect valid state update timestamps for name-related plugins
|
||||
state_times = []
|
||||
for p in name_plugins:
|
||||
state_updated = pm.plugin_states.get(p, {}).get("stateUpdated")
|
||||
if state_updated and state_updated.strip(): # skip empty or None
|
||||
if state_updated: # skip empty or None
|
||||
state_times.append(state_updated)
|
||||
|
||||
# Determine the latest valid stateUpdated timestamp
|
||||
latest_state_str = max(state_times, default=None)
|
||||
latest_state_dt = parser.parse(latest_state_str) if latest_state_str else None
|
||||
if isinstance(latest_state_str, datetime.datetime):
|
||||
latest_state = latest_state_str
|
||||
elif latest_state_str:
|
||||
latest_state = parser.parse(latest_state_str)
|
||||
else:
|
||||
latest_state = None
|
||||
|
||||
# Skip if no plugin state changed since last check
|
||||
if last_checked_dt and latest_state_dt and latest_state_dt <= last_checked_dt:
|
||||
if last_checked and latest_state and latest_state <= last_checked:
|
||||
mylog('debug', '[Update Device Name] No relevant name plugin changes since last check — skipping update.')
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user