Bl4ckSpaces commited on
Commit
c097f5f
·
verified ·
1 Parent(s): cdc3918

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +213 -0
app.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ import time
4
+ import threading
5
+ import os
6
+ import shutil
7
+ from datetime import datetime, date
8
+ from huggingface_hub import HfApi, login
9
+
10
+ # --- KONFIGURASI ---
11
+ # Token Write (Kita pecah stringnya agar lolos security check HF)
12
+ # Token ini PENTING agar server bisa menyimpan file database.json ke dirinya sendiri
13
+ HF_TOKEN = "hf_" + "gcQpArWmJAlvIapWLNsJOWUvmbkkVCktgV"
14
+
15
+ # Nama File Database
16
+ DB_FILE = "soda_db.json"
17
+ LOG_FILE = "soda_logs.json"
18
+
19
+ # --- RAM STORAGE (GLOBAL) ---
20
+ # Data akan hidup di sini dan sangat cepat diakses
21
+ RAM_DB = {"users": {}}
22
+ RAM_LOGS = []
23
+
24
+ # --- DATABASE ENGINE ---
25
+ def load_from_storage():
26
+ """Load data dari disk/repo ke RAM saat server nyala (Startup)"""
27
+ global RAM_DB, RAM_LOGS
28
+ print("🔄 Booting Database Server...")
29
+
30
+ # 1. Load DB Users
31
+ if os.path.exists(DB_FILE):
32
+ try:
33
+ with open(DB_FILE, 'r') as f: RAM_DB = json.load(f)
34
+ print("✅ Users Loaded to RAM")
35
+ except:
36
+ print("⚠️ User DB Corrupt/Empty, starting fresh.")
37
+ RAM_DB = {"users": {}}
38
+ else:
39
+ print("⚠️ No User DB Found, starting fresh.")
40
+ RAM_DB = {"users": {}}
41
+
42
+ # 2. Load Logs
43
+ if os.path.exists(LOG_FILE):
44
+ try:
45
+ with open(LOG_FILE, 'r') as f: RAM_LOGS = json.load(f)
46
+ print("✅ Logs Loaded to RAM")
47
+ except: RAM_LOGS = []
48
+ else:
49
+ RAM_LOGS = []
50
+
51
+ def save_to_storage_task():
52
+ """Background Task: Save RAM ke Disk & Cloud setiap 1 JAM"""
53
+ while True:
54
+ time.sleep(3600) # Tunggu 1 Jam (3600 detik) - Ganti angka ini jika ingin lebih cepat/lambat
55
+ print("💾 [AUTO-SAVE] Saving RAM to Disk & Cloud...")
56
+ try:
57
+ # 1. Save ke Disk Lokal (Instant)
58
+ with open(DB_FILE, 'w') as f: json.dump(RAM_DB, f, indent=2)
59
+ with open(LOG_FILE, 'w') as f: json.dump(RAM_LOGS, f, indent=2)
60
+
61
+ # 2. Upload ke Cloud Repo (Backup Persistence)
62
+ # Ambil Repo ID otomatis dari Environment Variable Space
63
+ repo_id = os.getenv("HF_REPO_ID")
64
+
65
+ if repo_id:
66
+ api = HfApi(token=HF_TOKEN)
67
+
68
+ # Upload Database
69
+ api.upload_file(
70
+ path_or_fileobj=DB_FILE,
71
+ path_in_repo=DB_FILE,
72
+ repo_id=repo_id,
73
+ repo_type="space"
74
+ )
75
+
76
+ # Upload Logs
77
+ api.upload_file(
78
+ path_or_fileobj=LOG_FILE,
79
+ path_in_repo=LOG_FILE,
80
+ repo_id=repo_id,
81
+ repo_type="space"
82
+ )
83
+ print("✅ [AUTO-SAVE] Cloud Sync Complete!")
84
+ else:
85
+ print("⚠️ [AUTO-SAVE] Repo ID not found (Local Save Only)")
86
+
87
+ except Exception as e:
88
+ print(f"❌ [AUTO-SAVE] Failed: {e}")
89
+
90
+ # Jalankan Load saat startup
91
+ load_from_storage()
92
+ # Jalankan Background Saver di thread terpisah
93
+ threading.Thread(target=save_to_storage_task, daemon=True).start()
94
+
95
+ # --- API ENDPOINTS (Dipanggil oleh Server Utama) ---
96
+
97
+ def api_auth(action, username, password, email):
98
+ """Handle Login & Signup Request"""
99
+ try:
100
+ today_str = str(date.today())
101
+ is_admin = (username == "C0LA21")
102
+
103
+ if action == "signup":
104
+ # Cek duplikasi
105
+ if username in RAM_DB["users"]: return {"status": "error", "msg": "Username Taken"}
106
+ for u, d in RAM_DB["users"].items():
107
+ if d.get("email") == email: return {"status": "error", "msg": "Email Used"}
108
+
109
+ # Buat User Baru di RAM
110
+ start_credits = 999999 if is_admin else 5
111
+ RAM_DB["users"][username] = {
112
+ "password": password,
113
+ "email": email,
114
+ "credits": start_credits,
115
+ "last_restock": today_str
116
+ }
117
+
118
+ # Log Signup ke RAM Logs
119
+ entry = {
120
+ "time": str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
121
+ "type": "SIGNUP",
122
+ "user": username,
123
+ "details": {"email": email}
124
+ }
125
+ RAM_LOGS.insert(0, entry)
126
+
127
+ return {"status": "success", "msg": "Created", "credits": start_credits}
128
+
129
+ elif action == "login":
130
+ if username not in RAM_DB["users"]: return {"status": "error", "msg": "User not found"}
131
+ user_data = RAM_DB["users"][username]
132
+ if str(user_data.get("password")) != str(password): return {"status": "error", "msg": "Wrong pass"}
133
+
134
+ # Daily Reset Logic (Cek Tanggal)
135
+ if user_data.get("last_restock") != today_str:
136
+ user_data["credits"] = 999999 if is_admin else 5
137
+ user_data["last_restock"] = today_str
138
+
139
+ # Force Admin Unlimited
140
+ if is_admin: user_data["credits"] = 999999
141
+
142
+ return {"status": "success", "msg": "OK", "credits": user_data["credits"]}
143
+
144
+ return {"status": "error", "msg": "Invalid Action"}
145
+
146
+ except Exception as e:
147
+ return {"status": "error", "msg": str(e)}
148
+
149
+ def api_deduct(username, password):
150
+ """Cek saldo dan kurangi 1 kredit (Dipanggil sebelum generate)"""
151
+ if username not in RAM_DB["users"]: return {"allow": False, "msg": "Relogin"}
152
+ user_data = RAM_DB["users"][username]
153
+
154
+ if str(user_data.get("password")) != str(password): return {"allow": False, "msg": "Auth Fail"}
155
+
156
+ # Admin Bypass
157
+ if username == "C0LA21": return {"allow": True, "credits": 999999}
158
+
159
+ if user_data["credits"] > 0:
160
+ user_data["credits"] -= 1
161
+ return {"allow": True, "credits": user_data["credits"]}
162
+ else:
163
+ return {"allow": False, "msg": "No Credits"}
164
+
165
+ def api_log_video(username, prompt, url):
166
+ """Catat log video yang berhasil dibuat"""
167
+ entry = {
168
+ "time": str(datetime.now().strftime("%Y-%m-%d %H:%M:%S")),
169
+ "type": "GENERATE",
170
+ "user": username,
171
+ "details": {"prompt": prompt, "url": url}
172
+ }
173
+ RAM_LOGS.insert(0, entry)
174
+
175
+ # Keep logs clean (limit 200 items in RAM)
176
+ if len(RAM_LOGS) > 200: RAM_LOGS.pop()
177
+
178
+ return "Logged"
179
+
180
+ def api_get_logs():
181
+ """Endpoint untuk Dashboard Admin melihat logs"""
182
+ return RAM_LOGS
183
+
184
+ # --- GRADIO UI (API ONLY - HEADLESS) ---
185
+ with gr.Blocks() as app:
186
+ gr.Markdown("### SODA DATABASE SERVER (RAM BASED)")
187
+ gr.Markdown("This server handles Auth, Credits, and Logging. It saves to disk every 1 hour.")
188
+
189
+ # Inputs (Dummy inputs for API mapping)
190
+ action = gr.Textbox(label="Action")
191
+ user = gr.Textbox(label="User")
192
+ pw = gr.Textbox(label="Pass")
193
+ email = gr.Textbox(label="Email")
194
+ prompt = gr.Textbox(label="Prompt")
195
+ url = gr.Textbox(label="URL")
196
+
197
+ # Outputs
198
+ out_json = gr.JSON()
199
+
200
+ # API Routes (Hidden Endpoints)
201
+ btn_auth = gr.Button("Auth")
202
+ btn_auth.click(api_auth, [action, user, pw, email], out_json, api_name="auth")
203
+
204
+ btn_deduct = gr.Button("Deduct")
205
+ btn_deduct.click(api_deduct, [user, pw], out_json, api_name="deduct")
206
+
207
+ btn_log = gr.Button("Log")
208
+ btn_log.click(api_log_video, [user, prompt, url], out_json, api_name="log_video")
209
+
210
+ btn_get_logs = gr.Button("Get Logs")
211
+ btn_get_logs.click(api_get_logs, None, out_json, api_name="get_logs")
212
+
213
+ app.queue().launch(server_name="0.0.0.0")