Spaces:
Sleeping
Sleeping
| import os, time, requests | |
| from flask import Flask, render_template_string, request, redirect, session, jsonify | |
| from flask_sqlalchemy import SQLAlchemy | |
| from werkzeug.security import generate_password_hash, check_password_hash | |
| from apscheduler.schedulers.background import BackgroundScheduler | |
| app = Flask(__name__) | |
| app.secret_key = 'supersecretkey' | |
| app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///uptimezelarixa.db' | |
| db = SQLAlchemy(app) | |
| # ✅ FIX: Jalankan di dalam app context agar tidak error | |
| with app.app_context(): | |
| db.create_all() | |
| # Ambil secrets dari environment | |
| BOT_TOKEN = os.getenv("BOT_TOKEN") | |
| CHAT_ID = os.getenv("CHAT_ID") | |
| # ---------- Database ---------- | |
| class User(db.Model): | |
| id = db.Column(db.Integer, primary_key=True) | |
| email = db.Column(db.String(120), unique=True) | |
| password = db.Column(db.String(200)) | |
| class Monitor(db.Model): | |
| id = db.Column(db.Integer, primary_key=True) | |
| user_id = db.Column(db.Integer, db.ForeignKey('user.id')) | |
| name = db.Column(db.String(100)) | |
| url = db.Column(db.String(300)) | |
| status = db.Column(db.String(20)) | |
| last_check = db.Column(db.String(100)) | |
| response_time = db.Column(db.Float) | |
| # ---------- Fungsi utama ---------- | |
| def send_telegram_alert(name, url): | |
| if not BOT_TOKEN or not CHAT_ID: | |
| print("⚠️ BOT_TOKEN atau CHAT_ID belum diatur di Secrets!") | |
| return | |
| text = f"⚠️ [ALERT] {name} ({url}) sedang DOWN!" | |
| try: | |
| requests.get(f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage", | |
| params={"chat_id": CHAT_ID, "text": text}) | |
| except Exception as e: | |
| print(f"Gagal kirim notifikasi Telegram: {e}") | |
| def check_monitors(): | |
| with app.app_context(): | |
| monitors = Monitor.query.all() | |
| for m in monitors: | |
| try: | |
| start = time.time() | |
| r = requests.get(m.url, timeout=5) | |
| m.response_time = round((time.time() - start) * 1000, 2) | |
| m.status = "Online" if r.status_code == 200 else f"Error {r.status_code}" | |
| except: | |
| if m.status != "Offline": | |
| send_telegram_alert(m.name, m.url) | |
| m.status = "Offline" | |
| m.response_time = None | |
| m.last_check = time.strftime("%H:%M:%S %d-%m-%Y") | |
| db.session.commit() | |
| # Scheduler otomatis cek setiap 5 menit | |
| scheduler = BackgroundScheduler() | |
| scheduler.add_job(check_monitors, 'interval', minutes=5) | |
| scheduler.start() | |
| # ---------- Routes ---------- | |
| def index(): | |
| if 'user_id' not in session: | |
| return redirect('/login') | |
| user = User.query.get(session['user_id']) | |
| monitors = Monitor.query.filter_by(user_id=user.id).all() | |
| return render_template_string(TEMPLATE, user=user, monitors=monitors) | |
| def register(): | |
| if request.method == 'POST': | |
| email, pw = request.form['email'], request.form['password'] | |
| if User.query.filter_by(email=email).first(): | |
| return "Email sudah terdaftar." | |
| user = User(email=email, password=generate_password_hash(pw)) | |
| db.session.add(user) | |
| db.session.commit() | |
| return redirect('/login') | |
| return render_template_string(REGISTER_TEMPLATE) | |
| def login(): | |
| if request.method == 'POST': | |
| email, pw = request.form['email'], request.form['password'] | |
| user = User.query.filter_by(email=email).first() | |
| if user and check_password_hash(user.password, pw): | |
| session['user_id'] = user.id | |
| return redirect('/') | |
| return "Login gagal." | |
| return render_template_string(LOGIN_TEMPLATE) | |
| def logout(): | |
| session.pop('user_id', None) | |
| return redirect('/login') | |
| def add(): | |
| if 'user_id' not in session: | |
| return redirect('/login') | |
| name = request.form['name'] | |
| url = request.form['url'] | |
| m = Monitor(user_id=session['user_id'], name=name, url=url, status="Unknown") | |
| db.session.add(m) | |
| db.session.commit() | |
| return redirect('/') | |
| def check_now(): | |
| check_monitors() | |
| return jsonify({"status": "checked"}) | |
| # ---------- Template HTML ---------- | |
| TEMPLATE = """ | |
| <!DOCTYPE html> | |
| <html><head> | |
| <meta charset="UTF-8"><title>UptimeZelarixa</title> | |
| <style> | |
| body { font-family: Arial; background: #0e1013; color: white; text-align: center; } | |
| h1 { color: #4da6ff; } | |
| table { margin: 20px auto; border-collapse: collapse; width: 80%; } | |
| th, td { padding: 10px; border-bottom: 1px solid #333; } | |
| button { background: #4da6ff; border: none; padding: 10px 20px; border-radius: 6px; color: white; cursor: pointer; } | |
| input { padding: 8px; margin: 5px; border-radius: 4px; border: 1px solid #555; background: #1a1c22; color: white; } | |
| </style></head><body> | |
| <h1>UptimeZelarixa</h1> | |
| <p>Halo {{user.email}} | <a href="/logout" style="color:#4da6ff;">Logout</a></p> | |
| <form action="/add" method="post"> | |
| <input name="name" placeholder="Nama situs"> | |
| <input name="url" placeholder="https://example.com"> | |
| <button type="submit">Tambah</button> | |
| </form> | |
| <table> | |
| <tr><th>Nama</th><th>URL</th><th>Status</th><th>Respons (ms)</th><th>Terakhir Dicek</th></tr> | |
| {% for m in monitors %} | |
| <tr> | |
| <td>{{m.name}}</td><td>{{m.url}}</td><td>{{m.status}}</td> | |
| <td>{{m.response_time or '-'}}</td><td>{{m.last_check or '-'}}</td> | |
| </tr>{% endfor %} | |
| </table> | |
| <button onclick="fetch('/check_now',{method:'POST'}).then(()=>location.reload())">Cek Sekarang</button> | |
| </body></html> | |
| """ | |
| REGISTER_TEMPLATE = """ | |
| <form method="post" style="text-align:center; margin-top:100px;"> | |
| <h2>Register Akun</h2> | |
| <input name="email" placeholder="Email"><br> | |
| <input type="password" name="password" placeholder="Password"><br> | |
| <button type="submit">Daftar</button> | |
| <p><a href="/login">Sudah punya akun?</a></p> | |
| </form> | |
| """ | |
| LOGIN_TEMPLATE = """ | |
| <form method="post" style="text-align:center; margin-top:100px;"> | |
| <h2>Login ke UptimeZelarixa</h2> | |
| <input name="email" placeholder="Email"><br> | |
| <input type="password" name="password" placeholder="Password"><br> | |
| <button type="submit">Masuk</button> | |
| <p><a href="/register">Buat akun baru</a></p> | |
| </form> | |
| """ | |
| if __name__ == '__main__': | |
| app.run(host='0.0.0.0', port=int(os.getenv("PORT", 7860))) |