import logging import sqlite3 import threading import uuid from datetime import datetime from meshtastic import BROADCAST_NUM from utils import ( send_bulletin_to_bbs_nodes, send_delete_bulletin_to_bbs_nodes, send_delete_mail_to_bbs_nodes, send_mail_to_bbs_nodes, send_message, send_channel_to_bbs_nodes ) thread_local = threading.local() def get_db_connection(): if not hasattr(thread_local, 'connection'): thread_local.connection = sqlite3.connect('bulletins.db') return thread_local.connection def initialize_database(): conn = get_db_connection() c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS bulletins ( id INTEGER PRIMARY KEY AUTOINCREMENT, board TEXT NOT NULL, sender_short_name TEXT NOT NULL, date TEXT NOT NULL, subject TEXT NOT NULL, content TEXT NOT NULL, unique_id TEXT NOT NULL )''') c.execute('''CREATE TABLE IF NOT EXISTS mail ( id INTEGER PRIMARY KEY AUTOINCREMENT, sender TEXT NOT NULL, sender_short_name TEXT NOT NULL, recipient TEXT NOT NULL, date TEXT NOT NULL, subject TEXT NOT NULL, content TEXT NOT NULL, unique_id TEXT NOT NULL );''') c.execute('''CREATE TABLE IF NOT EXISTS channels ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, url TEXT NOT NULL );''') conn.commit() print("Database schema initialized.") def add_channel(name, url, bbs_nodes=None, interface=None): conn = get_db_connection() c = conn.cursor() c.execute("INSERT INTO channels (name, url) VALUES (?, ?)", (name, url)) conn.commit() if bbs_nodes and interface: send_channel_to_bbs_nodes(name, url, bbs_nodes, interface) def get_channels(): conn = get_db_connection() c = conn.cursor() c.execute("SELECT name, url FROM channels") return c.fetchall() def add_bulletin(board, sender_short_name, subject, content, bbs_nodes, interface, unique_id=None): conn = get_db_connection() c = conn.cursor() date = datetime.now().strftime('%Y-%m-%d %H:%M') if not unique_id: unique_id = str(uuid.uuid4()) c.execute( "INSERT INTO bulletins (board, sender_short_name, date, subject, content, unique_id) VALUES (?, ?, ?, ?, ?, ?)", (board, sender_short_name, date, subject, content, unique_id)) conn.commit() if bbs_nodes and interface: send_bulletin_to_bbs_nodes(board, sender_short_name, subject, content, unique_id, bbs_nodes, interface) # New logic to send group chat notification for urgent bulletins if board.lower() == "urgent": notification_message = f"💥NEW URGENT BULLETIN💥\nFrom: {sender_short_name}\nTitle: {subject}" send_message(notification_message, BROADCAST_NUM, interface) return unique_id def get_bulletins(board): conn = get_db_connection() c = conn.cursor() c.execute("SELECT id, subject, sender_short_name, date, unique_id FROM bulletins WHERE board = ?", (board,)) return c.fetchall() def get_bulletin_content(bulletin_id): conn = get_db_connection() c = conn.cursor() c.execute("SELECT sender_short_name, date, subject, content, unique_id FROM bulletins WHERE id = ?", (bulletin_id,)) return c.fetchone() def delete_bulletin(bulletin_id, bbs_nodes, interface): conn = get_db_connection() c = conn.cursor() c.execute("DELETE FROM bulletins WHERE id = ?", (bulletin_id,)) conn.commit() send_delete_bulletin_to_bbs_nodes(bulletin_id, bbs_nodes, interface) def add_mail(sender_id, sender_short_name, recipient_id, subject, content, bbs_nodes, interface, unique_id=None): conn = get_db_connection() c = conn.cursor() date = datetime.now().strftime('%Y-%m-%d %H:%M') if not unique_id: unique_id = str(uuid.uuid4()) c.execute("INSERT INTO mail (sender, sender_short_name, recipient, date, subject, content, unique_id) VALUES (?, ?, ?, ?, ?, ?, ?)", (sender_id, sender_short_name, recipient_id, date, subject, content, unique_id)) conn.commit() if bbs_nodes and interface: send_mail_to_bbs_nodes(sender_id, sender_short_name, recipient_id, subject, content, unique_id, bbs_nodes, interface) return unique_id def get_mail(recipient_id): conn = get_db_connection() c = conn.cursor() c.execute("SELECT id, sender_short_name, subject, date, unique_id FROM mail WHERE recipient = ?", (recipient_id,)) return c.fetchall() def get_mail_content(mail_id, recipient_id): # TODO: ensure only recipient can read mail conn = get_db_connection() c = conn.cursor() c.execute("SELECT sender_short_name, date, subject, content, unique_id FROM mail WHERE id = ? and recipient = ?", (mail_id, recipient_id,)) return c.fetchone() def delete_mail(unique_id, recipient_id, bbs_nodes, interface): conn = get_db_connection() c = conn.cursor() try: c.execute("SELECT recipient FROM mail WHERE unique_id = ?", (unique_id,)) result = c.fetchone() if result is None: logging.error(f"No mail found with unique_id: {unique_id}") return # Early exit if no matching mail found recipient_id = result[0] logging.info(f"Attempting to delete mail with unique_id: {unique_id} by {recipient_id}") c.execute("DELETE FROM mail WHERE unique_id = ? and recipient = ?", (unique_id, recipient_id,)) conn.commit() send_delete_mail_to_bbs_nodes(unique_id, bbs_nodes, interface) logging.info(f"Mail with unique_id: {unique_id} deleted and sync message sent.") except Exception as e: logging.error(f"Error deleting mail with unique_id {unique_id}: {e}") raise def get_sender_id_by_mail_id(mail_id): conn = get_db_connection() c = conn.cursor() c.execute("SELECT sender FROM mail WHERE id = ?", (mail_id,)) result = c.fetchone() if result: return result[0] return None