mirror of
https://github.com/jokob-sk/NetAlertX.git
synced 2025-12-07 09:36:05 -08:00
BE: API in-app messaging endpoint
Signed-off-by: jokob-sk <jokob.sk@gmail.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import subprocess
|
||||
import requests
|
||||
from yattag import indent
|
||||
from json2table import convert
|
||||
from flask import jsonify
|
||||
|
||||
# Register NetAlertX directories
|
||||
INSTALL_PATH="/app"
|
||||
@@ -25,7 +26,18 @@ NOTIFICATION_API_FILE = apiPath + 'user_notifications.json'
|
||||
|
||||
# Show Frontend User Notification
|
||||
def write_notification(content, level='alert', timestamp=None):
|
||||
"""
|
||||
Create and append a new user notification entry to the notifications file.
|
||||
|
||||
Args:
|
||||
content (str): The message content to display to the user.
|
||||
level (str, optional): Notification severity (e.g., 'info', 'alert', 'warning').
|
||||
Defaults to 'alert'.
|
||||
timestamp (datetime, optional): Custom timestamp; if None, uses current time.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
if timestamp is None:
|
||||
timestamp = timeNowTZ()
|
||||
|
||||
@@ -67,7 +79,15 @@ def write_notification(content, level='alert', timestamp=None):
|
||||
|
||||
# Trim notifications
|
||||
def remove_old(keepNumberOfEntries):
|
||||
"""
|
||||
Trim the notifications file, keeping only the most recent N entries.
|
||||
|
||||
Args:
|
||||
keepNumberOfEntries (int): Number of latest notifications to retain.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
# Check if file exists
|
||||
if not os.path.exists(NOTIFICATION_API_FILE):
|
||||
mylog('info', '[Notification] No notifications file to clean.')
|
||||
@@ -106,3 +126,141 @@ def remove_old(keepNumberOfEntries):
|
||||
mylog('verbose', f'[Notification] Trimmed notifications to latest {keepNumberOfEntries}')
|
||||
except Exception as e:
|
||||
mylog('none', f'Error writing trimmed notifications file: {e}')
|
||||
|
||||
|
||||
def mark_all_notifications_read():
|
||||
"""
|
||||
Mark all existing notifications as read.
|
||||
|
||||
Returns:
|
||||
dict: JSON-compatible dictionary containing:
|
||||
{
|
||||
"success": bool,
|
||||
"error": str (optional)
|
||||
}
|
||||
"""
|
||||
if not os.path.exists(NOTIFICATION_API_FILE):
|
||||
return {"success": True}
|
||||
|
||||
try:
|
||||
with open(NOTIFICATION_API_FILE, "r") as f:
|
||||
notifications = json.load(f)
|
||||
except Exception as e:
|
||||
mylog("none", f"[Notification] Failed to read notifications: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
for n in notifications:
|
||||
n["read"] = 1
|
||||
|
||||
try:
|
||||
with open(NOTIFICATION_API_FILE, "w") as f:
|
||||
json.dump(notifications, f, indent=4)
|
||||
except Exception as e:
|
||||
mylog("none", f"[Notification] Failed to write notifications: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
mylog("debug", "[Notification] All notifications marked as read.")
|
||||
return {"success": True}
|
||||
|
||||
def delete_notifications():
|
||||
"""
|
||||
Delete all notifications from the JSON file.
|
||||
|
||||
Returns:
|
||||
A JSON response with {"success": True}.
|
||||
"""
|
||||
with open(NOTIFICATION_API_FILE, "w") as f:
|
||||
json.dump([], f, indent=4)
|
||||
mylog("debug", "[Notification] All notifications deleted.")
|
||||
return jsonify({"success": True})
|
||||
|
||||
|
||||
def get_unread_notifications():
|
||||
"""
|
||||
Retrieve all unread notifications from the JSON file.
|
||||
|
||||
Returns:
|
||||
A JSON array of unread notification objects.
|
||||
"""
|
||||
if not os.path.exists(NOTIFICATION_API_FILE):
|
||||
return jsonify([])
|
||||
|
||||
with open(NOTIFICATION_API_FILE, "r") as f:
|
||||
notifications = json.load(f)
|
||||
|
||||
unread = [n for n in notifications if n.get("read", 0) == 0]
|
||||
return jsonify(unread)
|
||||
|
||||
|
||||
def mark_notification_as_read(guid=None, max_attempts=3):
|
||||
"""
|
||||
Mark a notification as read based on GUID.
|
||||
If guid is None, mark all notifications as read.
|
||||
|
||||
Args:
|
||||
guid (str, optional): The GUID of the notification to mark. Defaults to None.
|
||||
max_attempts (int, optional): Number of attempts to read/write file. Defaults to 3.
|
||||
|
||||
Returns:
|
||||
dict: {"success": True} on success, {"success": False, "error": "..."} on failure
|
||||
"""
|
||||
attempts = 0
|
||||
|
||||
while attempts < max_attempts:
|
||||
try:
|
||||
if os.path.exists(NOTIFICATION_API_FILE) and os.access(NOTIFICATION_API_FILE, os.R_OK | os.W_OK):
|
||||
with open(NOTIFICATION_API_FILE, "r") as f:
|
||||
notifications = json.load(f)
|
||||
|
||||
if notifications is not None:
|
||||
for notification in notifications:
|
||||
if guid is None or notification.get("guid") == guid:
|
||||
notification["read"] = 1
|
||||
|
||||
with open(NOTIFICATION_API_FILE, "w") as f:
|
||||
json.dump(notifications, f, indent=4)
|
||||
|
||||
return {"success": True}
|
||||
except Exception as e:
|
||||
mylog("none", f"[Notification] Attempt {attempts+1} failed: {e}")
|
||||
|
||||
attempts += 1
|
||||
time.sleep(0.5) # Sleep 0.5 seconds before retrying
|
||||
|
||||
error_msg = f"Failed to read/write notification file after {max_attempts} attempts."
|
||||
mylog("none", f"[Notification] {error_msg}")
|
||||
return {"success": False, "error": error_msg}
|
||||
|
||||
def delete_notification(guid):
|
||||
"""
|
||||
Delete a notification from the notifications file based on its GUID.
|
||||
|
||||
Args:
|
||||
guid (str): The GUID of the notification to delete.
|
||||
|
||||
Returns:
|
||||
dict: {"success": True} on success, {"success": False, "error": "..."} on failure
|
||||
"""
|
||||
if not guid:
|
||||
return {"success": False, "error": "GUID is required"}
|
||||
|
||||
if not os.path.exists(NOTIFICATION_API_FILE):
|
||||
return {"success": True} # Nothing to delete
|
||||
|
||||
try:
|
||||
with open(NOTIFICATION_API_FILE, "r") as f:
|
||||
notifications = json.load(f)
|
||||
|
||||
# Filter out the notification with the specified GUID
|
||||
filtered_notifications = [n for n in notifications if n.get("guid") != guid]
|
||||
|
||||
# Write the updated notifications back
|
||||
with open(NOTIFICATION_API_FILE, "w") as f:
|
||||
json.dump(filtered_notifications, f, indent=4)
|
||||
|
||||
return {"success": True}
|
||||
|
||||
except Exception as e:
|
||||
mylog("none", f"[Notification] Failed to delete notification {guid}: {e}")
|
||||
return {"success": False, "error": str(e)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user