srinetwork commited on
Commit
f5fef0e
·
verified ·
1 Parent(s): 4680ab6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -59
app.py CHANGED
@@ -1,16 +1,14 @@
1
  from flask import Flask, render_template, request, jsonify
2
  import requests, time, json, os, threading
3
  from bs4 import BeautifulSoup
 
4
 
5
  app = Flask(__name__)
6
 
7
  DATA_FILE = "/tmp/urls.json"
8
- ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD")
9
 
10
- if not ADMIN_PASSWORD:
11
- raise RuntimeError("ADMIN_PASSWORD not set")
12
-
13
- # ---------------- STORAGE ----------------
14
  if not os.path.exists(DATA_FILE):
15
  with open(DATA_FILE, "w") as f:
16
  json.dump([], f)
@@ -23,77 +21,79 @@ def save_urls(data):
23
  with open(DATA_FILE, "w") as f:
24
  json.dump(data, f, indent=2)
25
 
26
- # ---------------- CHECKER ----------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  def check_sites():
28
  while True:
29
- urls = load_urls()
30
  now = time.time()
31
 
32
- for site in urls:
33
- if now >= site["next_check"]:
34
- site["total_checks"] += 1
35
- ping = None
36
  up = False
 
37
  try:
38
- r = requests.get(site["url"], timeout=10)
39
  ping = round(r.elapsed.total_seconds() * 1000, 2)
40
  up = r.status_code == 200
41
  except:
42
- ping = None
43
- up = False
44
-
45
- site["status"] = "UP" if up else "DOWN"
46
- site["last_ping"] = ping
47
 
48
  if up:
49
- site["up_checks"] += 1
50
 
51
- # history
52
- site["history"].append({
 
53
  "time": int(now),
54
  "uptime": 100 if up else 0,
55
  "ping": ping
56
  })
57
- site["history"] = site["history"][-50:]
58
-
59
- site["last_check"] = now
60
- site["next_check"] = now + site["interval"]
61
 
62
- save_urls(urls)
63
  time.sleep(5)
64
 
65
- # ---------------- OG IMAGE FETCH ----------------
66
- def fetch_og_image(url):
67
- try:
68
- r = requests.get(url, timeout=10)
69
- soup = BeautifulSoup(r.text, "html.parser")
70
- tag = soup.find("meta", property="og:image")
71
- if tag and tag.get("content"):
72
- return tag["content"]
73
- except:
74
- pass
75
- return "" # fallback empty
76
-
77
- # ---------------- ROUTES ----------------
78
  @app.route("/")
79
  def index():
80
  return render_template("index.html")
81
 
82
  @app.route("/data")
83
  def data():
84
- urls = load_urls()
85
  now = time.time()
86
- for u in urls:
87
- u["remaining"] = max(0, int(u["next_check"] - now))
88
- total_sec = int(now - u["first_added"])
89
- d, rem = divmod(total_sec, 86400)
 
90
  h, rem = divmod(rem, 3600)
91
- m, s = divmod(rem, 60)
92
- u["uptime_str"] = f"{d}d {h}h {m}m {s}s"
93
- u["uptime_percent"] = round(
94
- (u["up_checks"] / u["total_checks"])*100,2
95
- ) if u["total_checks"] else 0
96
- return jsonify(urls)
 
97
 
98
  def auth(req):
99
  return req.form.get("password") == ADMIN_PASSWORD
@@ -106,13 +106,12 @@ def add():
106
  now = time.time()
107
  data = load_urls()
108
  url = request.form["url"]
109
- og_img = fetch_og_image(url)
110
 
111
  data.append({
112
- "id": int(now*1000),
113
  "name": request.form["name"],
114
  "url": url,
115
- "img": og_img, # auto fetched
116
  "interval": int(request.form["interval"]),
117
  "status": "UNKNOWN",
118
  "last_ping": None,
@@ -131,19 +130,34 @@ def edit(id):
131
  if not auth(request):
132
  return "Unauthorized", 401
133
 
134
- data = load_urls()
135
- for s in data:
136
  if s["id"] == id:
 
 
 
137
  s["name"] = request.form["name"]
138
- s["url"] = request.form["url"]
139
- # update OG image automatically
140
- s["img"] = fetch_og_image(s["url"])
141
  s["interval"] = int(request.form["interval"])
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  break
143
- save_urls(data)
 
144
  return "OK"
145
 
146
- # ---------------- MAIN ----------------
147
  if __name__ == "__main__":
148
  threading.Thread(target=check_sites, daemon=True).start()
149
  app.run(host="0.0.0.0", port=7860)
 
1
  from flask import Flask, render_template, request, jsonify
2
  import requests, time, json, os, threading
3
  from bs4 import BeautifulSoup
4
+ from urllib.parse import urljoin
5
 
6
  app = Flask(__name__)
7
 
8
  DATA_FILE = "/tmp/urls.json"
9
+ ADMIN_PASSWORD = os.environ.get("ADMIN_PASSWORD", "admin")
10
 
11
+ # ---------- STORAGE ----------
 
 
 
12
  if not os.path.exists(DATA_FILE):
13
  with open(DATA_FILE, "w") as f:
14
  json.dump([], f)
 
21
  with open(DATA_FILE, "w") as f:
22
  json.dump(data, f, indent=2)
23
 
24
+ # ---------- IMAGE FETCH ----------
25
+ def fetch_site_image(url):
26
+ try:
27
+ r = requests.get(url, timeout=10)
28
+ soup = BeautifulSoup(r.text, "html.parser")
29
+
30
+ # og:image
31
+ og = soup.find("meta", property="og:image")
32
+ if og and og.get("content"):
33
+ return urljoin(url, og["content"])
34
+
35
+ # favicon
36
+ return url.rstrip("/") + "/favicon.ico"
37
+ except:
38
+ return ""
39
+
40
+ # ---------- CHECKER ----------
41
  def check_sites():
42
  while True:
43
+ sites = load_urls()
44
  now = time.time()
45
 
46
+ for s in sites:
47
+ if now >= s["next_check"]:
48
+ s["total_checks"] += 1
 
49
  up = False
50
+ ping = None
51
  try:
52
+ r = requests.get(s["url"], timeout=10)
53
  ping = round(r.elapsed.total_seconds() * 1000, 2)
54
  up = r.status_code == 200
55
  except:
56
+ pass
 
 
 
 
57
 
58
  if up:
59
+ s["up_checks"] += 1
60
 
61
+ s["status"] = "UP" if up else "DOWN"
62
+ s["last_ping"] = ping
63
+ s["history"].append({
64
  "time": int(now),
65
  "uptime": 100 if up else 0,
66
  "ping": ping
67
  })
68
+ s["history"] = s["history"][-50:]
69
+ s["last_check"] = now
70
+ s["next_check"] = now + s["interval"]
 
71
 
72
+ save_urls(sites)
73
  time.sleep(5)
74
 
75
+ # ---------- ROUTES ----------
 
 
 
 
 
 
 
 
 
 
 
 
76
  @app.route("/")
77
  def index():
78
  return render_template("index.html")
79
 
80
  @app.route("/data")
81
  def data():
82
+ sites = load_urls()
83
  now = time.time()
84
+
85
+ for s in sites:
86
+ s["remaining"] = max(0, int(s["next_check"] - now))
87
+ total = int(now - s["first_added"])
88
+ d, rem = divmod(total, 86400)
89
  h, rem = divmod(rem, 3600)
90
+ m, sec = divmod(rem, 60)
91
+ s["uptime_str"] = f"{d}d {h}h {m}m {sec}s"
92
+ s["uptime_percent"] = round(
93
+ (s["up_checks"] / s["total_checks"]) * 100, 2
94
+ ) if s["total_checks"] else 0
95
+
96
+ return jsonify(sites)
97
 
98
  def auth(req):
99
  return req.form.get("password") == ADMIN_PASSWORD
 
106
  now = time.time()
107
  data = load_urls()
108
  url = request.form["url"]
 
109
 
110
  data.append({
111
+ "id": int(now * 1000),
112
  "name": request.form["name"],
113
  "url": url,
114
+ "img": fetch_site_image(url),
115
  "interval": int(request.form["interval"]),
116
  "status": "UNKNOWN",
117
  "last_ping": None,
 
130
  if not auth(request):
131
  return "Unauthorized", 401
132
 
133
+ sites = load_urls()
134
+ for s in sites:
135
  if s["id"] == id:
136
+ old_url = s["url"]
137
+ new_url = request.form["url"]
138
+
139
  s["name"] = request.form["name"]
140
+ s["url"] = new_url
 
 
141
  s["interval"] = int(request.form["interval"])
142
+ s["img"] = fetch_site_image(new_url)
143
+
144
+ # 🔥 RESET uptime if URL changed
145
+ if old_url != new_url:
146
+ now = time.time()
147
+ s["first_added"] = now
148
+ s["total_checks"] = 0
149
+ s["up_checks"] = 0
150
+ s["history"] = []
151
+ s["last_check"] = 0
152
+ s["next_check"] = now
153
+ s["status"] = "UNKNOWN"
154
+ s["last_ping"] = None
155
  break
156
+
157
+ save_urls(sites)
158
  return "OK"
159
 
160
+ # ---------- START ----------
161
  if __name__ == "__main__":
162
  threading.Thread(target=check_sites, daemon=True).start()
163
  app.run(host="0.0.0.0", port=7860)