File size: 3,868 Bytes
7d9517c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Minimal HF Space for testing ONLY (no bot logic).
Deploy this as app.py in a new, throwaway HF Space (SDK: Gradio).

requirements.txt for this Space:
    gradio
    httpx
"""

import asyncio
import json
import os
import threading
from datetime import datetime, timezone

import gradio as gr
import httpx

# --- CONFIG: edit these two lines --------------------------------------
NORTHFLANK_BASE_URL = os.environ.get("NORTHFLANK_TEST_URL", "https://your-service.northflank.app")
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")  # optional
INTERVAL_SECONDS = 300
# -------------------------------------------------------------------------

LOG_FILE = "connectivity_log.jsonl"
results_lock = threading.Lock()
latest_results = []  # kept in memory for the UI


async def check(name: str, url: str, timeout: float = 10.0) -> dict:
    entry = {"check": name, "url": url, "time_utc": datetime.now(timezone.utc).isoformat()}
    try:
        async with httpx.AsyncClient(timeout=timeout) as client:
            resp = await client.get(url)
        entry["status"] = "ok" if resp.status_code == 200 else "http_error"
        entry["http_status"] = resp.status_code
    except Exception as e:
        entry["status"] = "connect_error"
        entry["error"] = f"{type(e).__name__}: {e}"
    return entry


async def run_once() -> list[dict]:
    checks = [
        check("hf_to_northflank_ping", f"{NORTHFLANK_BASE_URL}/ping"),
        check("hf_to_northflank_telegram_relay", f"{NORTHFLANK_BASE_URL}/check-telegram"),
    ]
    if TELEGRAM_BOT_TOKEN:
        checks.append(
            check("hf_to_telegram_direct", f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/getMe")
        )
    return await asyncio.gather(*checks)


def append_log(entries: list[dict]) -> None:
    with open(LOG_FILE, "a", encoding="utf-8") as f:
        for entry in entries:
            f.write(json.dumps(entry, ensure_ascii=False) + "\n")


def background_loop():
    async def loop():
        while True:
            results = await run_once()
            append_log(results)
            with results_lock:
                latest_results.clear()
                latest_results.extend(results)
            await asyncio.sleep(INTERVAL_SECONDS)
    asyncio.run(loop())


def get_status_text() -> str:
    with results_lock:
        if not latest_results:
            return "لسه ما بدأ أول فحص... انتظر بضع ثواني وحدّث الصفحة."
        lines = []
        for r in latest_results:
            line = f"**{r['check']}**: `{r['status']}`"
            if "http_status" in r:
                line += f" (HTTP {r['http_status']})"
            if "error" in r:
                line += f" — {r['error']}"
            line += f"  \n_{r['time_utc']}_"
            lines.append(line)
        return "\n\n".join(lines)


def get_log_tail() -> str:
    if not os.path.exists(LOG_FILE):
        return "لا يوجد سجل بعد."
    with open(LOG_FILE, "r", encoding="utf-8") as f:
        lines = f.readlines()
    return "".join(lines[-30:]) or "لا يوجد سجل بعد."


threading.Thread(target=background_loop, daemon=True).start()

with gr.Blocks(title="Connectivity Test: HF <-> Northflank <-> Telegram") as demo:
    gr.Markdown("## اختبار الاتصال الدوري: HF ↔ Northflank ↔ تيليجرام")
    gr.Markdown(f"يفحص كل {INTERVAL_SECONDS} ثانية. اضغط تحديث لرؤية آخر نتيجة.")
    status_box = gr.Markdown()
    refresh_btn = gr.Button("تحديث النتائج")
    log_box = gr.Textbox(label="آخر 30 سطر من السجل", lines=15)

    refresh_btn.click(fn=get_status_text, outputs=status_box)
    refresh_btn.click(fn=get_log_tail, outputs=log_box)
    demo.load(fn=get_status_text, outputs=status_box)
    demo.load(fn=get_log_tail, outputs=log_box)

demo.launch()