File size: 5,565 Bytes
1855912 706ce69 1855912 706ce69 1855912 14e0dfb 706ce69 14e0dfb 1855912 706ce69 1855912 14e0dfb 1855912 706ce69 14e0dfb 1855912 706ce69 1855912 706ce69 14e0dfb 1855912 14e0dfb 706ce69 1855912 14e0dfb 706ce69 14e0dfb 706ce69 14e0dfb 706ce69 14e0dfb 706ce69 14e0dfb 706ce69 14e0dfb 1855912 706ce69 1855912 706ce69 1855912 706ce69 1855912 706ce69 1855912 706ce69 1855912 706ce69 1855912 706ce69 1855912 14e0dfb 706ce69 1855912 14e0dfb 706ce69 1855912 706ce69 1855912 706ce69 14e0dfb 706ce69 14e0dfb 1855912 706ce69 14e0dfb 706ce69 14e0dfb 706ce69 14e0dfb 1855912 706ce69 | 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 156 | import threading
import time
import requests
import os
import datetime
from flask import Flask, jsonify, request
from wsgiref.simple_server import make_server
app = Flask(__name__)
# --- CONFIGURATION ---
URL_FILE = 'urls.txt'
SELF_PING_URL = "https://alvin3y1-ping.hf.space/"
INTERVAL_SECONDS = 4 * 3600 # 4 hours
# --- GLOBAL STATE ---
monitoring_state = {}
scan_state = {
'is_scanning': False,
'total': 0,
'completed': 0,
'last_scan_time': 'Never'
}
state_lock = threading.Lock()
# --- FRONTEND TEMPLATE ---
# Served as a static string to keep the project to one file.
HTML_TEMPLATE = """
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Service Status</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-black text-gray-200 min-h-screen p-6 font-sans">
<div class="max-w-2xl mx-auto">
<div class="flex justify-between items-center mb-8 border-b border-gray-800 pb-4">
<h1 class="text-xl font-bold">System Status</h1>
<button onclick="triggerScan()" id="scan-btn" class="bg-gray-800 hover:bg-gray-700 px-3 py-1 text-sm rounded transition">Run Scan</button>
</div>
<div id="progress" class="hidden mb-6">
<div class="w-full bg-gray-800 h-1 rounded-full overflow-hidden">
<div id="bar" class="bg-blue-500 h-full w-0 transition-all duration-300"></div>
</div>
</div>
<div id="alerts" class="space-y-3"></div>
</div>
<script>
async function fetchStatus() {
const res = await fetch('/api/status');
const data = await res.json();
// Handle Progress
const prog = document.getElementById('progress');
if (data.scan.is_scanning) {
prog.classList.remove('hidden');
const percent = (data.scan.completed / data.scan.total) * 100;
document.getElementById('bar').style.width = percent + '%';
} else {
prog.classList.add('hidden');
}
// Handle Down URLs
const container = document.getElementById('alerts');
container.innerHTML = data.down_urls.length ? '' : '<p class="text-green-500 text-center py-10">All Systems Operational</p>';
data.down_urls.forEach(u => {
container.innerHTML += `
<div class="bg-red-950/20 border border-red-900/50 p-4 rounded flex justify-between items-center">
<div>
<div class="text-sm font-mono text-red-200">${u.url}</div>
<div class="text-xs text-red-500 mt-1">${u.msg} (${u.code})</div>
</div>
<button onclick="retry('${u.url}')" class="text-xs bg-red-900 px-2 py-1 rounded">Retry</button>
</div>`;
});
}
async function triggerScan() {
await fetch('/api/scan', {method: 'POST'});
fetchStatus();
}
async function retry(url) {
await fetch('/api/retry', {method: 'POST', headers:{'Content-Type':'application/json'}, body:JSON.stringify({url})});
fetchStatus();
}
setInterval(fetchStatus, 2000);
fetchStatus();
</script>
</body>
</html>
"""
# --- LOGIC ---
def get_all_urls():
urls = [SELF_PING_URL]
if os.path.exists(URL_FILE):
with open(URL_FILE, 'r') as f:
urls.extend([l.strip() for l in f if l.strip()])
return list(set(urls))
def check_single_url(url):
timestamp = datetime.datetime.now().strftime("%H:%M:%S")
try:
r = requests.get(url, timeout=10)
res = {'status': 'UP' if r.status_code < 400 else 'DOWN', 'code': r.status_code, 'time': timestamp, 'msg': 'OK' if r.status_code < 400 else 'Error'}
except Exception as e:
res = {'status': 'DOWN', 'code': 'ERR', 'time': timestamp, 'msg': str(e)[:20]}
with state_lock:
monitoring_state[url] = res
def perform_full_scan():
urls = get_all_urls()
with state_lock:
scan_state.update({'is_scanning': True, 'total': len(urls), 'completed': 0})
for url in urls:
check_single_url(url)
with state_lock:
scan_state['completed'] += 1
with state_lock:
scan_state.update({'is_scanning': False, 'last_scan_time': datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")})
def background_worker():
while True:
perform_full_scan()
time.sleep(INTERVAL_SECONDS)
# --- ROUTES ---
@app.route('/')
def home(): return HTML_TEMPLATE
@app.route('/api/status')
def get_status():
with state_lock:
down = [{'url': u, **s} for u, s in monitoring_state.items() if s['status'] == 'DOWN']
return jsonify({'scan': scan_state, 'down_urls': down})
@app.route('/api/scan', methods=['POST'])
def scan():
threading.Thread(target=perform_full_scan, daemon=True).start()
return jsonify({"status": "started"})
@app.route('/api/retry', methods=['POST'])
def retry():
threading.Thread(target=check_single_url, args=(request.json['url'],), daemon=True).start()
return jsonify({"status": "retrying"})
if __name__ == '__main__':
threading.Thread(target=background_worker, daemon=True).start()
print("Server starting on http://0.0.0.0:7860")
make_server('0.0.0.0', 7860, app).serve_forever()
|