-
+ ${unique_users}
+
-
+ ${warnings}
+
-
+ ${errors}
+
diff --git a/logs/mesh_network_analyzer.py b/logs/mesh_network_analyzer.py new file mode 100644 index 0000000..0de4d3b --- /dev/null +++ b/logs/mesh_network_analyzer.py @@ -0,0 +1,560 @@ +import os +import re +from datetime import datetime +from collections import Counter, defaultdict +import json +import platform +import subprocess + +def parse_log_file(file_path): + with open(file_path, 'r') as file: + lines = file.readlines() + + log_data = { + 'command_counts': Counter(), + 'message_types': Counter(), + 'unique_users': set(), + 'warnings': [], + 'errors': [], + 'hourly_activity': defaultdict(int), + 'bbs_messages': 0, + 'total_messages': 0, + 'gps_coordinates': defaultdict(list), + 'command_timestamps': [], + 'message_timestamps': [], + } + + for line in lines: + timestamp_match = re.match(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}),\d+', line) + if timestamp_match: + timestamp = datetime.strptime(timestamp_match.group(1), '%Y-%m-%d %H:%M:%S') + log_data['hourly_activity'][timestamp.strftime('%Y-%m-%d %H:00:00')] += 1 + + if 'Bot detected Commands' in line: + command = re.search(r"'cmd': '(\w+)'", line) + if command: + cmd = command.group(1) + log_data['command_counts'][cmd] += 1 + log_data['command_timestamps'].append((timestamp.isoformat(), cmd)) + + if 'Sending DM:' in line or 'Sending Multi-Chunk DM:' in line: + log_data['message_types']['Outgoing DM'] += 1 + log_data['total_messages'] += 1 + log_data['message_timestamps'].append((timestamp.isoformat(), 'Outgoing DM')) + + if 'Received DM:' in line: + log_data['message_types']['Incoming DM'] += 1 + log_data['total_messages'] += 1 + log_data['message_timestamps'].append((timestamp.isoformat(), 'Incoming DM')) + + user_match = re.search(r'From: (\w+)', line) + if user_match: + log_data['unique_users'].add(user_match.group(1)) + + if '| WARNING |' in line: + log_data['warnings'].append(line.strip()) + + if '| ERROR |' in line: + log_data['errors'].append(line.strip()) + + bbs_match = re.search(r'📡BBSdb has (\d+) messages', line) + if bbs_match: + log_data['bbs_messages'] = int(bbs_match.group(1)) + + gps_match = re.search(r'location data for (\d+) is ([-\d.]+),([-\d.]+)', line) + if gps_match: + node_id, lat, lon = gps_match.groups() + log_data['gps_coordinates'][node_id].append((float(lat), float(lon))) + + log_data['unique_users'] = list(log_data['unique_users']) + return log_data + +def get_system_info(): + def get_command_output(command): + try: + return subprocess.check_output(command, shell=True).decode('utf-8').strip() + except subprocess.CalledProcessError: + return "N/A" + + if platform.system() == "Linux": + uptime = get_command_output("uptime -p") + memory_total = get_command_output("free -m | awk '/Mem:/ {print $2}'") + memory_available = get_command_output("free -m | awk '/Mem:/ {print $7}'") + disk_total = get_command_output("df -h / | awk 'NR==2 {print $2}'") + disk_free = get_command_output("df -h / | awk 'NR==2 {print $4}'") + elif platform.system() == "Darwin": # macOS + uptime = get_command_output("uptime | awk '{print $3,$4,$5}'") + memory_total = get_command_output("sysctl -n hw.memsize | awk '{print $0/1024/1024}'") + memory_available = "N/A" # Not easily available on macOS without additional tools + disk_total = get_command_output("df -h / | awk 'NR==2 {print $2}'") + disk_free = get_command_output("df -h / | awk 'NR==2 {print $4}'") + else: + return { + 'uptime': "N/A", + 'memory_total': "N/A", + 'memory_available': "N/A", + 'disk_total': "N/A", + 'disk_free': "N/A", + } + + return { + 'uptime': uptime, + 'memory_total': f"{memory_total} MB", + 'memory_available': f"{memory_available} MB" if memory_available != "N/A" else "N/A", + 'disk_total': disk_total, + 'disk_free': disk_free, + } + +def generate_main_html(log_data, system_info): + html_template = """ + + +
+ + +Metric | Value |
---|---|
Uptime | ${uptime} |
Total Memory | ${memory_total} |
Available Memory | ${memory_available} |
Total Disk Space | ${disk_total} |
Free Disk Space | ${disk_free} |