diff --git a/meshview/store.py b/meshview/store.py index 53dc029..42841ac 100644 --- a/meshview/store.py +++ b/meshview/store.py @@ -24,7 +24,9 @@ async def get_fuzzy_nodes(query): return result.scalars() -async def get_packets(node_id=None, portnum=None, after=None, before=None, limit=None, packet_id=None): +async def get_packets( + node_id=None, portnum=None, after=None, before=None, limit=None, packet_id=None +): async with database.async_session() as session: # --- Fast path: fetch by packet_id (uses primary key lookup) --- if packet_id is not None: @@ -53,7 +55,6 @@ async def get_packets(node_id=None, portnum=None, after=None, before=None, limit return packets - async def get_packets_from(node_id=None, portnum=None, since=None, limit=500): async with database.async_session() as session: q = select(Packet) @@ -75,7 +76,6 @@ async def get_packet(packet_id): return result.scalar_one_or_none() - async def get_packets_seen(packet_id): async with database.async_session() as session: result = await session.execute( @@ -373,11 +373,11 @@ async def get_total_packet_count( # CASE 1: no filters -> count everything if ( - period_type is None and - length is None and - channel is None and - from_node is None and - to_node is None + period_type is None + and length is None + and channel is None + and from_node is None + and to_node is None ): async with database.async_session() as session: q = select(func.count(Packet.id)) @@ -431,19 +431,17 @@ async def get_total_packet_seen_count( # SPECIAL CASE: direct packet_id lookup if packet_id is not None: async with database.async_session() as session: - q = select(func.count(PacketSeen.packet_id)).where( - PacketSeen.packet_id == packet_id - ) + q = select(func.count(PacketSeen.packet_id)).where(PacketSeen.packet_id == packet_id) res = await session.execute(q) return res.scalar() or 0 # No filters -> return ALL seen entries if ( - period_type is None and - length is None and - channel is None and - from_node is None and - to_node is None + period_type is None + and length is None + and channel is None + and from_node is None + and to_node is None ): async with database.async_session() as session: q = select(func.count(PacketSeen.packet_id)) diff --git a/meshview/web.py b/meshview/web.py index cf32f73..b71816c 100644 --- a/meshview/web.py +++ b/meshview/web.py @@ -193,6 +193,7 @@ async def index(request): starting_url = CONFIG["site"].get("starting", "/map") # default to /map if not set raise web.HTTPFound(location=starting_url) + @routes.get("/net") async def net(request): return web.Response( @@ -200,21 +201,21 @@ async def net(request): content_type="text/html", ) + @routes.get("/map") async def map(request): template = env.get_template("map.html") - return web.Response( - text=template.render(), - content_type="text/html" - ) + return web.Response(text=template.render(), content_type="text/html") + @routes.get("/nodelist") async def nodelist(request): - template = env.get_template("nodelist.html") - return web.Response( - text=template.render(), - content_type="text/html", - ) + template = env.get_template("nodelist.html") + return web.Response( + text=template.render(), + content_type="text/html", + ) + @routes.get("/firehose") async def firehose(request): @@ -223,21 +224,24 @@ async def firehose(request): content_type="text/html", ) + @routes.get("/chat") async def chat(request): - template = env.get_template("chat.html") - return web.Response( - text=template.render(), - content_type="text/html", - ) + template = env.get_template("chat.html") + return web.Response( + text=template.render(), + content_type="text/html", + ) + @routes.get("/new_packet/{packet_id}") async def new_packet(request): - template = env.get_template("new_packet.html") - return web.Response( - text=template.render(), - content_type="text/html", - ) + template = env.get_template("new_packet.html") + return web.Response( + text=template.render(), + content_type="text/html", + ) + @routes.get("/new_node/{from_node_id}") async def firehose_node(request): @@ -247,6 +251,7 @@ async def firehose_node(request): content_type="text/html", ) + @routes.get("/nodegraph") async def nodegraph(request): template = env.get_template("nodegraph.html") @@ -255,6 +260,7 @@ async def nodegraph(request): content_type="text/html", ) + @routes.get("/top") async def top(request): template = env.get_template("top.html") @@ -263,6 +269,7 @@ async def top(request): content_type="text/html", ) + # Keep !! @routes.get("/graph/traceroute/{packet_id}") async def graph_traceroute(request): @@ -370,6 +377,7 @@ async def graph_traceroute(request): content_type="image/svg+xml", ) + @routes.get("/stats") async def stats(request): try: @@ -392,6 +400,7 @@ async def stats(request): content_type="text/plain", ) + ''' @routes.get("/top") async def top(request): @@ -470,6 +479,7 @@ async def top(request): return web.Response(text=rendered, status=500, content_type="text/html") ''' + async def run_server(): # Wait for database migrations to complete before starting web server logger.info("Checking database schema status...") diff --git a/meshview/web_api/api.py b/meshview/web_api/api.py index 0128933..71f5f44 100644 --- a/meshview/web_api/api.py +++ b/meshview/web_api/api.py @@ -79,8 +79,8 @@ async def api_nodes(request): "last_lat": getattr(n, "last_lat", None), "last_long": getattr(n, "last_long", None), "channel": n.channel, - #"last_update": n.last_update.isoformat(), - "last_seen_us":n.last_seen_us, + # "last_update": n.last_update.isoformat(), + "last_seen_us": n.last_seen_us, } ) @@ -170,14 +170,9 @@ async def api_packets(request): # --- Text message filtering --- if portnum == PortNum.TEXT_MESSAGE_APP: - ui_packets = [ - p for p in ui_packets - if p.payload and not SEQ_REGEX.fullmatch(p.payload) - ] + ui_packets = [p for p in ui_packets if p.payload and not SEQ_REGEX.fullmatch(p.payload)] if contains: - ui_packets = [ - p for p in ui_packets if contains.lower() in p.payload.lower() - ] + ui_packets = [p for p in ui_packets if contains.lower() in p.payload.lower()] # --- Sort descending by import_time_us --- ui_packets.sort(key=lambda p: p.import_time_us, reverse=True) @@ -258,13 +253,15 @@ async def api_stats(request): to_node=node_id, ) - return web.json_response({ - "node_id": node_id, - "period_type": period_type, - "length": length, - "sent": sent.get("total", 0), - "seen": seen.get("total", 0), - }) + return web.json_response( + { + "node_id": node_id, + "period_type": period_type, + "length": length, + "sent": sent.get("total", 0), + "seen": seen.get("total", 0), + } + ) # ---- Existing full stats mode (unchanged) ---- channel = request.query.get("channel") @@ -344,21 +341,18 @@ async def api_stats_count(request): # -------- Case 1: NO FILTERS → return global totals -------- no_filters = ( - period_type is None and - length is None and - channel is None and - from_node is None and - to_node is None and - packet_id is None + period_type is None + and length is None + and channel is None + and from_node is None + and to_node is None + and packet_id is None ) if no_filters: total_packets = await store.get_total_packet_count() total_seen = await store.get_total_packet_seen_count() - return web.json_response({ - "total_packets": total_packets, - "total_seen": total_seen - }) + return web.json_response({"total_packets": total_packets, "total_seen": total_seen}) # -------- Case 2: Apply filters → compute totals -------- total_packets = await store.get_total_packet_count( @@ -378,13 +372,7 @@ async def api_stats_count(request): to_node=to_node, ) - return web.json_response({ - "total_packets": total_packets, - "total_seen": total_seen - }) - - - + return web.json_response({"total_packets": total_packets, "total_seen": total_seen}) @routes.get("/api/edges") @@ -618,6 +606,7 @@ async def version_endpoint(request): logger.error(f"Error in /version: {e}") return web.json_response({"error": "Failed to fetch version info"}, status=500) + @routes.get("/api/packets_seen/{packet_id}") async def api_packets_seen(request): try: @@ -634,22 +623,22 @@ async def api_packets_seen(request): rows = await store.get_packets_seen(packet_id) items = [] - for row in rows: # <-- FIX: normal for-loop - items.append({ - "packet_id": row.packet_id, - "node_id": row.node_id, - "rx_time": row.rx_time, - "hop_limit": row.hop_limit, - "hop_start": row.hop_start, - "channel": row.channel, - "rx_snr": row.rx_snr, - "rx_rssi": row.rx_rssi, - "topic": row.topic, - "import_time": ( - row.import_time.isoformat() if row.import_time else None - ), - "import_time_us": row.import_time_us, - }) + for row in rows: # <-- FIX: normal for-loop + items.append( + { + "packet_id": row.packet_id, + "node_id": row.node_id, + "rx_time": row.rx_time, + "hop_limit": row.hop_limit, + "hop_start": row.hop_start, + "channel": row.channel, + "rx_snr": row.rx_snr, + "rx_rssi": row.rx_rssi, + "topic": row.topic, + "import_time": (row.import_time.isoformat() if row.import_time else None), + "import_time_us": row.import_time_us, + } + ) return web.json_response({"seen": items})