File size: 6,314 Bytes
e8c2b16
 
 
 
 
 
 
 
 
 
 
e60de31
 
 
 
 
e8c2b16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e60de31
e8c2b16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e60de31
e8c2b16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e60de31
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
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 ----------
@app.route('/')
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)

@app.route('/register', methods=['GET', 'POST'])
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)

@app.route('/login', methods=['GET', 'POST'])
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)

@app.route('/logout')
def logout():
    session.pop('user_id', None)
    return redirect('/login')

@app.route('/add', methods=['POST'])
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('/')

@app.route('/check_now', methods=['POST'])
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)))