-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck.py
More file actions
155 lines (134 loc) · 4.79 KB
/
Copy pathcheck.py
File metadata and controls
155 lines (134 loc) · 4.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python3
"""
check.py — Shadow Fleet Tracker preflight checks
Run before starting the tracker to verify the environment is ready.
Called automatically by start.sh and start.bat, or run manually:
python check.py
"""
import importlib
import os
import sys
import sqlite3
import urllib.request
import urllib.error
REQUIRED_PYTHON = (3, 11)
REQUIRED_PACKAGES = [
("websockets", "websockets"),
("folium", "folium"),
("geopy", "geopy"),
("branca", "branca"),
("aiohttp", "aiohttp"),
("fastapi", "fastapi"),
("uvicorn", "uvicorn"),
]
VESSELS_DB = "Vessels1.db"
CABLES_KML = "filtered_cables.kml"
AISSTREAM_WS = "https://stream.aisstream.io" # reachability check via HTTPS
OK = "\033[92m✓\033[0m"
FAIL = "\033[91m✗\033[0m"
WARN = "\033[93m!\033[0m"
# Windows doesn't render ANSI in cmd by default
if sys.platform == "win32":
OK = "[OK]"
FAIL = "[FAIL]"
WARN = "[WARN]"
errors = []
warnings = []
def check(label: str, passed: bool, detail: str = "", fatal: bool = True):
if passed:
print(f" {OK} {label}")
else:
symbol = FAIL if fatal else WARN
print(f" {symbol} {label}" + (f" — {detail}" if detail else ""))
if fatal:
errors.append(label)
else:
warnings.append(label)
# ---------------------------------------------------------------------------
# Python version
# ---------------------------------------------------------------------------
print("\nPython")
ver = sys.version_info
check(
f"Python {ver.major}.{ver.minor} (need {REQUIRED_PYTHON[0]}.{REQUIRED_PYTHON[1]}+)",
ver >= REQUIRED_PYTHON,
f"found {ver.major}.{ver.minor} — install Python {REQUIRED_PYTHON[0]}.{REQUIRED_PYTHON[1]}+ from python.org",
)
# ---------------------------------------------------------------------------
# Packages
# ---------------------------------------------------------------------------
print("\nPackages")
for import_name, pip_name in REQUIRED_PACKAGES:
try:
importlib.import_module(import_name)
check(import_name, True)
except ImportError:
check(import_name, False, f"run: pip install {pip_name}")
# ---------------------------------------------------------------------------
# Data files
# ---------------------------------------------------------------------------
print("\nData files")
check(VESSELS_DB, os.path.exists(VESSELS_DB), "watchlist database missing — check repo is complete")
check(CABLES_KML, os.path.exists(CABLES_KML), "cable geometry missing — check repo is complete")
if os.path.exists(VESSELS_DB):
try:
with sqlite3.connect(VESSELS_DB) as c:
count = c.execute("SELECT COUNT(*) FROM vessels").fetchone()[0]
check(f"Vessels1.db — {count} vessels", count > 0, "database appears empty")
except Exception as e:
check("Vessels1.db readable", False, str(e))
gur = os.path.exists("gur_mapping.json")
check(
"gur_mapping.json (War&Sanctions deep-links)",
gur,
"optional — run: python gur_scrape.py",
fatal=False,
)
# ---------------------------------------------------------------------------
# Environment / API keys
# ---------------------------------------------------------------------------
print("\nAPI keys")
aisstream_key = os.getenv("AISSTREAM_API_KEY", "")
check(
"AISSTREAM_API_KEY",
bool(aisstream_key),
"required — get a free key at aisstream.io, then set the env var",
)
opensanctions_key = os.getenv("OPENSANCTIONS_API_KEY", "")
check(
"OPENSANCTIONS_API_KEY (sanctions badges)",
bool(opensanctions_key),
"optional — register at opensanctions.org/api for sanctions data in popups",
fatal=False,
)
# ---------------------------------------------------------------------------
# Network reachability
# ---------------------------------------------------------------------------
print("\nNetwork")
try:
urllib.request.urlopen(AISSTREAM_WS, timeout=5)
check("aisstream.io reachable", True)
except urllib.error.HTTPError:
# Any HTTP response means the host is reachable
check("aisstream.io reachable", True)
except Exception as e:
check("aisstream.io reachable", False, f"{e}")
# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
print()
if errors:
print(f" {FAIL} {len(errors)} issue(s) must be fixed before starting:")
for e in errors:
print(f" • {e}")
print()
sys.exit(1)
elif warnings:
print(f" {WARN} {len(warnings)} optional item(s) not configured (tracker will still run):")
for w in warnings:
print(f" • {w}")
print(f"\n {OK} Ready to start.\n")
sys.exit(0)
else:
print(f" {OK} All checks passed. Ready to start.\n")
sys.exit(0)