linuxrouter/docker/routlin-dash/app/pages/overview/view.py
2026-06-09 13:52:07 -04:00

97 lines
4.2 KiB
Python

import re
import os
import config_utils
import factory
from pages.ddns.view import public_ip_info
from pages.dhcpleases.view import live_dhcp_leases
def get_dnsmasq_stats():
stats = {'queries': '-', 'hits': '-', 'hit_rate': '-', 'forwarded': '-', 'auth': '-', 'tcp_peak': '-'}
out = factory.run("journalctl -u 'dnsmasq-routlin-*' -n 200 --no-pager 2>/dev/null")
for line in reversed(out.splitlines()):
if 'queries forwarded' in line:
m = re.search(r'queries forwarded (\d+)', line)
if m:
stats['forwarded'] = m.group(1)
m = re.search(r'queries answered locally (\d+)', line)
if m:
stats['hits'] = m.group(1)
fwd = int(stats['forwarded']) if stats['forwarded'] != '-' else 0
hit = int(stats['hits']) if stats['hits'] != '-' else 0
total = fwd + hit
stats['queries'] = str(total) if total else '-'
if total > 0:
stats['hit_rate'] = f'{hit / total * 100:.0f}%'
break
if 'auth answered' in line:
m = re.search(r'auth answered (\d+)', line)
if m and stats['auth'] == '-':
stats['auth'] = m.group(1)
if 'max TCP connections' in line:
m = re.search(r'max TCP connections (\d+)', line)
if m and stats['tcp_peak'] == '-':
stats['tcp_peak'] = m.group(1)
return stats
def count_blocked_today():
out = factory.run("journalctl -u 'dnsmasq-routlin-*' --since '24 hours ago' --no-pager 2>/dev/null | grep -c ' is 0\\.0\\.0\\.0'")
return out.strip() or '0'
def count_blocked_domains():
try:
total = sum(
int(factory.run(f'wc -l < "{config_utils.BLOCKLISTS_DIR}/{f}"') or 0)
for f in os.listdir(config_utils.BLOCKLISTS_DIR) if f.endswith('.con')
)
return str(total)
except Exception:
return '-'
def bl_last_update():
try:
mtime = max(
os.path.getmtime(f'{config_utils.BLOCKLISTS_DIR}/{f}')
for f in os.listdir(config_utils.BLOCKLISTS_DIR) if f.endswith('.con')
)
return config_utils.fmt_timestamp(int(mtime))
except Exception:
return '-'
def collect_tokens(cfg):
tokens = config_utils.collect_layout_tokens(cfg)
vlans = cfg.get('vlans', [])
non_vpn_vlans = [v for v in vlans if not v.get('is_vpn')]
vlan_names = [v.get('name', '') for v in vlans]
net = cfg.get('network_interfaces', {})
dns = cfg.get('upstream_dns', {})
dns_stats = get_dnsmasq_stats()
ddns = factory.load_ddns()
ip_str, domains_sub, last_obtained = public_ip_info(ddns)
tokens['GENERAL_WAN_INTERFACE'] = str(net.get('wan_interface', '-'))
tokens['OVERVIEW_VLAN_NAMES'] = ', '.join(vlan_names) or '-'
tokens['STAT_VLAN_COUNT'] = str(len(non_vpn_vlans))
tokens['STAT_LEASE_COUNT'] = str(len(live_dhcp_leases()))
tokens['STAT_BANNED_IP_COUNT'] = str(sum(1 for b in cfg.get('banned_ips', []) if b.get('enabled', True)))
tokens['STAT_BLOCKLIST_COUNT'] = str(len(cfg.get('dns_blocking', {}).get('blocklists', [])))
tokens['STAT_BLOCKED_TODAY'] = count_blocked_today()
tokens['STAT_BLOCKED_DOMAINS'] = count_blocked_domains()
tokens['STAT_BL_LAST_UPDATE'] = bl_last_update()
tokens['STAT_UPTIME'] = factory.run('uptime -p') or '-'
tokens['STAT_NFTABLES_STATUS'] = 'Active' if factory.run('nft list tables 2>/dev/null').strip() else 'Inactive'
tokens['STAT_PUBLIC_IP'] = ip_str
tokens['STAT_DDNS_HOSTNAME'] = domains_sub
tokens['DNS_CACHE_SIZE'] = str(dns.get('cache_size', '-'))
tokens['OVERVIEW_UPSTREAM_SERVERS'] = ', '.join(dns.get('upstream_servers', [])) or '-'
tokens['DNS_STAT_QUERIES'] = dns_stats['queries']
tokens['DNS_STAT_HITS'] = dns_stats['hits']
tokens['DNS_STAT_HIT_RATE'] = dns_stats['hit_rate']
tokens['DNS_STAT_FORWARDED'] = dns_stats['forwarded']
tokens['DNS_STAT_AUTH'] = dns_stats['auth']
tokens['DNS_STAT_TCP_PEAK'] = dns_stats['tcp_peak']
return tokens