GoshawkVortexAI commited on
Commit
970d3d6
·
verified ·
1 Parent(s): 66f1b93

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +857 -51
app.py CHANGED
@@ -1,85 +1,891 @@
 
 
 
 
 
 
 
1
  import gradio as gr
2
  import torch
 
3
  from transformers import AutoTokenizer
4
- from peft import AutoPeftModelForSequenceClassification
5
 
6
- # =========================
7
- # MODEL
8
- # =========================
 
9
 
10
  MODEL_PATH = "."
11
 
12
- device = "cuda" if torch.cuda.is_available() else "cpu"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
- tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
15
 
16
- model = AutoPeftModelForSequenceClassification.from_pretrained(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
  MODEL_PATH,
18
- torch_dtype=torch.float16 if device == "cuda" else torch.float32
 
 
 
 
19
  )
20
 
21
- model.to(device)
22
  model.eval()
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
- # =========================
26
- # PREDICTION
27
- # =========================
28
 
29
- def predict(text):
 
 
 
 
 
 
30
 
31
  if not text or not text.strip():
32
- return {
33
- "Bullish": 0.0,
34
- "Neutral": 0.0,
35
- "Bearish": 0.0
36
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
  inputs = tokenizer(
39
- text,
40
  return_tensors="pt",
41
  truncation=True,
42
  max_length=512
43
  )
44
 
45
- inputs = {k: v.to(device) for k, v in inputs.items()}
 
 
 
46
 
47
  with torch.no_grad():
48
- outputs = model(**inputs)
49
- probabilities = torch.softmax(outputs.logits, dim=-1)[0]
50
 
51
- labels = ["Bearish", "Neutral", "Bullish"]
 
 
 
 
52
 
53
- result = {
54
- labels[i]: float(probabilities[i])
55
- for i in range(len(labels))
56
- }
 
57
 
58
- return result
59
-
60
-
61
- # =========================
62
- # GRADIO UI
63
- # =========================
64
-
65
- demo = gr.Interface(
66
- fn=predict,
67
- inputs=gr.Textbox(
68
- label="Crypto Text",
69
- placeholder="Bitcoin ETF inflows increased sharply today...",
70
- lines=5
71
- ),
72
- outputs=gr.Label(
73
- label="Crypto Sentiment",
74
- num_top_classes=3
75
- ),
76
- title="CryptoBERT Sentiment",
77
- description="Bullish / Neutral / Bearish crypto sentiment analysis"
78
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
 
81
- # =========================
82
  # START
83
- # =========================
84
 
85
- demo.launch()
 
 
 
 
1
+ import os
2
+ import re
3
+ import sqlite3
4
+ import hashlib
5
+ import secrets
6
+ from datetime import date
7
+
8
  import gradio as gr
9
  import torch
10
+
11
  from transformers import AutoTokenizer
12
+ from peft import AutoPeftModelForCausalLM
13
 
14
+
15
+ # ============================================================
16
+ # CONFIG
17
+ # ============================================================
18
 
19
  MODEL_PATH = "."
20
 
21
+ DB_PATH = "users.db"
22
+
23
+ FREE_DAILY_LIMIT = 10
24
+ PRO_DAILY_LIMIT = 1000
25
+
26
+ ADMIN_EMAIL = os.getenv("ADMIN_EMAIL", "admin@example.com")
27
+ ADMIN_PASSWORD = os.getenv("ADMIN_PASSWORD", "CHANGE_THIS_PASSWORD")
28
+
29
+
30
+ # ============================================================
31
+ # DATABASE
32
+ # ============================================================
33
+
34
+ def db():
35
+ conn = sqlite3.connect(DB_PATH, check_same_thread=False)
36
+ conn.row_factory = sqlite3.Row
37
+ return conn
38
+
39
+
40
+ def init_db():
41
+
42
+ conn = db()
43
+
44
+ conn.execute("""
45
+ CREATE TABLE IF NOT EXISTS users (
46
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
47
+ email TEXT UNIQUE NOT NULL,
48
+ password_hash TEXT NOT NULL,
49
+ salt TEXT NOT NULL,
50
+ plan TEXT DEFAULT 'free',
51
+ active INTEGER DEFAULT 1,
52
+ daily_usage INTEGER DEFAULT 0,
53
+ usage_date TEXT,
54
+ created_at TEXT DEFAULT CURRENT_TIMESTAMP
55
+ )
56
+ """)
57
+
58
+ conn.commit()
59
+
60
+ # Admin hesabını otomatik oluştur
61
+ existing = conn.execute(
62
+ "SELECT id FROM users WHERE email = ?",
63
+ (ADMIN_EMAIL,)
64
+ ).fetchone()
65
+
66
+ if not existing:
67
+ password_hash, salt = hash_password(ADMIN_PASSWORD)
68
+
69
+ conn.execute("""
70
+ INSERT INTO users
71
+ (email, password_hash, salt, plan, active)
72
+ VALUES (?, ?, ?, 'admin', 1)
73
+ """, (
74
+ ADMIN_EMAIL,
75
+ password_hash,
76
+ salt
77
+ ))
78
+
79
+ conn.commit()
80
+
81
+ conn.close()
82
+
83
+
84
+ # ============================================================
85
+ # PASSWORD SECURITY
86
+ # ============================================================
87
+
88
+ def hash_password(password, salt=None):
89
+
90
+ if salt is None:
91
+ salt = secrets.token_hex(16)
92
+
93
+ password_hash = hashlib.pbkdf2_hmac(
94
+ "sha256",
95
+ password.encode("utf-8"),
96
+ salt.encode("utf-8"),
97
+ 200_000
98
+ ).hex()
99
+
100
+ return password_hash, salt
101
+
102
+
103
+ def verify_password(password, stored_hash, salt):
104
+
105
+ calculated, _ = hash_password(password, salt)
106
+
107
+ return secrets.compare_digest(
108
+ calculated,
109
+ stored_hash
110
+ )
111
+
112
+
113
+ # ============================================================
114
+ # USER FUNCTIONS
115
+ # ============================================================
116
+
117
+ def get_user(email):
118
+
119
+ conn = db()
120
+
121
+ user = conn.execute(
122
+ "SELECT * FROM users WHERE email = ?",
123
+ (email.lower().strip(),)
124
+ ).fetchone()
125
+
126
+ conn.close()
127
+
128
+ return user
129
+
130
+
131
+ def create_user(email, password):
132
+
133
+ email = email.lower().strip()
134
+
135
+ if not re.match(
136
+ r"^[^@\s]+@[^@\s]+\.[^@\s]+$",
137
+ email
138
+ ):
139
+ return False, "Geçerli bir e-posta adresi gir."
140
+
141
+ if len(password) < 8:
142
+ return False, "Şifre en az 8 karakter olmalı."
143
+
144
+ if get_user(email):
145
+ return False, "Bu e-posta zaten kayıtlı."
146
+
147
+ password_hash, salt = hash_password(password)
148
+
149
+ conn = db()
150
+
151
+ conn.execute("""
152
+ INSERT INTO users
153
+ (email, password_hash, salt, plan, active)
154
+ VALUES (?, ?, ?, 'free', 1)
155
+ """, (
156
+ email,
157
+ password_hash,
158
+ salt
159
+ ))
160
+
161
+ conn.commit()
162
+ conn.close()
163
+
164
+ return True, "Hesap oluşturuldu. Giriş yapabilirsin."
165
+
166
+
167
+ def login_user(email, password):
168
+
169
+ user = get_user(email)
170
+
171
+ if not user:
172
+ return None, "E-posta veya şifre hatalı."
173
+
174
+ if not verify_password(
175
+ password,
176
+ user["password_hash"],
177
+ user["salt"]
178
+ ):
179
+ return None, "E-posta veya şifre hatalı."
180
+
181
+ if not user["active"]:
182
+ return None, "Hesabın pasif durumda."
183
+
184
+ # Günlük kullanım reset
185
+ today = str(date.today())
186
+
187
+ if user["usage_date"] != today:
188
+
189
+ conn = db()
190
+
191
+ conn.execute("""
192
+ UPDATE users
193
+ SET daily_usage = 0,
194
+ usage_date = ?
195
+ WHERE id = ?
196
+ """, (
197
+ today,
198
+ user["id"]
199
+ ))
200
+
201
+ conn.commit()
202
+ conn.close()
203
+
204
+ user = get_user(email)
205
+
206
+ return user, "Giriş başarılı."
207
 
 
208
 
209
+ # ============================================================
210
+ # USAGE LIMIT
211
+ # ============================================================
212
+
213
+ def get_limit(plan):
214
+
215
+ if plan == "admin":
216
+ return 999999
217
+
218
+ if plan == "pro":
219
+ return PRO_DAILY_LIMIT
220
+
221
+ return FREE_DAILY_LIMIT
222
+
223
+
224
+ def can_use(user):
225
+
226
+ today = str(date.today())
227
+
228
+ if user["usage_date"] != today:
229
+ return True
230
+
231
+ limit = get_limit(user["plan"])
232
+
233
+ return user["daily_usage"] < limit
234
+
235
+
236
+ def increment_usage(user_id):
237
+
238
+ conn = db()
239
+
240
+ conn.execute("""
241
+ UPDATE users
242
+ SET daily_usage = daily_usage + 1,
243
+ usage_date = ?
244
+ WHERE id = ?
245
+ """, (
246
+ str(date.today()),
247
+ user_id
248
+ ))
249
+
250
+ conn.commit()
251
+ conn.close()
252
+
253
+
254
+ # ============================================================
255
+ # MODEL
256
+ # ============================================================
257
+
258
+ print("Loading model...")
259
+
260
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
261
+
262
+ print("Device:", DEVICE)
263
+
264
+ tokenizer = AutoTokenizer.from_pretrained(
265
+ MODEL_PATH
266
+ )
267
+
268
+ model = AutoPeftModelForCausalLM.from_pretrained(
269
  MODEL_PATH,
270
+ torch_dtype=(
271
+ torch.float16
272
+ if DEVICE == "cuda"
273
+ else torch.float32
274
+ )
275
  )
276
 
277
+ model.to(DEVICE)
278
  model.eval()
279
 
280
+ print("Model loaded.")
281
+
282
+
283
+ # ============================================================
284
+ # SENTIMENT
285
+ # ============================================================
286
+
287
+ def extract_sentiment(text):
288
+
289
+ text_lower = text.lower()
290
+
291
+ if "bullish" in text_lower:
292
+ return "Bullish"
293
 
294
+ if "bearish" in text_lower:
295
+ return "Bearish"
 
296
 
297
+ if "neutral" in text_lower:
298
+ return "Neutral"
299
+
300
+ return "Unknown"
301
+
302
+
303
+ def analyze_crypto(text, user):
304
 
305
  if not text or not text.strip():
306
+ return "Metin gir."
307
+
308
+ # Kullanıcıyı tekrar DB'den kontrol et
309
+ current_user = get_user(user["email"])
310
+
311
+ if not current_user:
312
+ return "Oturum bulunamadı."
313
+
314
+ if not current_user["active"]:
315
+ return "Hesabın aktif değil."
316
+
317
+ if not can_use(current_user):
318
+
319
+ limit = get_limit(current_user["plan"])
320
+
321
+ return (
322
+ f"Günlük kullanım limitine ulaştın.\n\n"
323
+ f"Plan: {current_user['plan'].upper()}\n"
324
+ f"Limit: {limit}"
325
+ )
326
+
327
+ prompt = f"""
328
+ You are a cryptocurrency financial sentiment classifier.
329
+
330
+ Classify the following cryptocurrency-related text into exactly one
331
+ of these labels:
332
+
333
+ Bullish
334
+ Neutral
335
+ Bearish
336
+
337
+ Return only one label.
338
+
339
+ Text:
340
+ {text}
341
+
342
+ Sentiment:
343
+ """
344
 
345
  inputs = tokenizer(
346
+ prompt,
347
  return_tensors="pt",
348
  truncation=True,
349
  max_length=512
350
  )
351
 
352
+ inputs = {
353
+ k: v.to(DEVICE)
354
+ for k, v in inputs.items()
355
+ }
356
 
357
  with torch.no_grad():
 
 
358
 
359
+ output = model.generate(
360
+ **inputs,
361
+ max_new_tokens=10,
362
+ do_sample=False
363
+ )
364
 
365
+ generated = output[
366
+ 0
367
+ ][
368
+ inputs["input_ids"].shape[1]:
369
+ ]
370
 
371
+ result = tokenizer.decode(
372
+ generated,
373
+ skip_special_tokens=True
374
+ ).strip()
375
+
376
+ sentiment = extract_sentiment(result)
377
+
378
+ increment_usage(current_user["id"])
379
+
380
+ if sentiment == "Unknown":
381
+ return (
382
+ "Model sonucu:\n\n"
383
+ + result
384
+ )
385
+
386
+ return sentiment
387
+
388
+
389
+ # ============================================================
390
+ # AUTH UI
391
+ # ============================================================
392
+
393
+ def signup(email, password):
394
+
395
+ success, message = create_user(
396
+ email,
397
+ password
398
+ )
399
+
400
+ return message
401
+
402
+
403
+ def login(email, password):
404
+
405
+ user, message = login_user(
406
+ email,
407
+ password
408
+ )
409
+
410
+ if not user:
411
+ return (
412
+ message,
413
+ None,
414
+ gr.update(visible=True),
415
+ gr.update(visible=False),
416
+ gr.update(visible=False),
417
+ ""
418
+ )
419
+
420
+ admin_visible = (
421
+ user["plan"] == "admin"
422
+ )
423
+
424
+ status = (
425
+ f"Hoş geldin: {user['email']}\n"
426
+ f"Plan: {user['plan'].upper()}\n"
427
+ f"Kullanım: {user['daily_usage']}/"
428
+ f"{get_limit(user['plan'])}"
429
+ )
430
+
431
+ return (
432
+ status,
433
+ dict(user),
434
+ gr.update(visible=False),
435
+ gr.update(visible=True),
436
+ gr.update(visible=admin_visible),
437
+ ""
438
+ )
439
+
440
+
441
+ def logout():
442
+
443
+ return (
444
+ "",
445
+ None,
446
+ gr.update(visible=True),
447
+ gr.update(visible=False),
448
+ gr.update(visible=False),
449
+ ""
450
+ )
451
+
452
+
453
+ # ============================================================
454
+ # ADMIN
455
+ # ============================================================
456
+
457
+ def get_users_dataframe():
458
+
459
+ conn = db()
460
+
461
+ rows = conn.execute("""
462
+ SELECT
463
+ id,
464
+ email,
465
+ plan,
466
+ active,
467
+ daily_usage,
468
+ created_at
469
+ FROM users
470
+ ORDER BY id DESC
471
+ """).fetchall()
472
+
473
+ conn.close()
474
+
475
+ data = []
476
+
477
+ for row in rows:
478
+
479
+ data.append([
480
+ row["id"],
481
+ row["email"],
482
+ row["plan"],
483
+ "Active" if row["active"] else "Inactive",
484
+ row["daily_usage"],
485
+ row["created_at"]
486
+ ])
487
+
488
+ return data
489
+
490
+
491
+ def refresh_users():
492
+
493
+ return get_users_dataframe()
494
+
495
+
496
+ def admin_change_plan(user_id, plan):
497
+
498
+ try:
499
+ user_id = int(user_id)
500
+ except:
501
+ return "Geçersiz kullanıcı ID."
502
+
503
+ if plan not in [
504
+ "free",
505
+ "pro",
506
+ "admin"
507
+ ]:
508
+ return "Geçersiz plan."
509
+
510
+ conn = db()
511
+
512
+ conn.execute("""
513
+ UPDATE users
514
+ SET plan = ?
515
+ WHERE id = ?
516
+ """, (
517
+ plan,
518
+ user_id
519
+ ))
520
+
521
+ conn.commit()
522
+ conn.close()
523
+
524
+ return f"Kullanıcı {user_id} → {plan}"
525
+
526
+
527
+ def admin_toggle_user(user_id):
528
+
529
+ try:
530
+ user_id = int(user_id)
531
+ except:
532
+ return "Geçersiz kullanıcı ID."
533
+
534
+ conn = db()
535
+
536
+ user = conn.execute(
537
+ "SELECT active FROM users WHERE id = ?",
538
+ (user_id,)
539
+ ).fetchone()
540
+
541
+ if not user:
542
+ conn.close()
543
+ return "Kullanıcı bulunamadı."
544
+
545
+ new_status = 0 if user["active"] else 1
546
+
547
+ conn.execute("""
548
+ UPDATE users
549
+ SET active = ?
550
+ WHERE id = ?
551
+ """, (
552
+ new_status,
553
+ user_id
554
+ ))
555
+
556
+ conn.commit()
557
+ conn.close()
558
+
559
+ return (
560
+ f"Kullanıcı {user_id}: "
561
+ + (
562
+ "Aktif"
563
+ if new_status
564
+ else "Pasif"
565
+ )
566
+ )
567
+
568
+
569
+ def admin_delete_user(user_id):
570
+
571
+ try:
572
+ user_id = int(user_id)
573
+ except:
574
+ return "Geçersiz kullanıcı ID."
575
+
576
+ conn = db()
577
+
578
+ user = conn.execute(
579
+ "SELECT email FROM users WHERE id = ?",
580
+ (user_id,)
581
+ ).fetchone()
582
+
583
+ if not user:
584
+ conn.close()
585
+ return "Kullanıcı bulunamadı."
586
+
587
+ if user["email"] == ADMIN_EMAIL:
588
+ conn.close()
589
+ return "Ana admin silinemez."
590
+
591
+ conn.execute(
592
+ "DELETE FROM users WHERE id = ?",
593
+ (user_id,)
594
+ )
595
+
596
+ conn.commit()
597
+ conn.close()
598
+
599
+ return f"Kullanıcı {user_id} silindi."
600
+
601
+
602
+ # ============================================================
603
+ # INITIALIZE
604
+ # ============================================================
605
+
606
+ init_db()
607
+
608
+
609
+ # ============================================================
610
+ # GRADIO
611
+ # ============================================================
612
+
613
+ with gr.Blocks(
614
+ title="CryptoBERT AI"
615
+ ) as demo:
616
+
617
+ session = gr.State(None)
618
+
619
+ # ========================================================
620
+ # LOGIN
621
+ # ========================================================
622
+
623
+ with gr.Column(
624
+ visible=True
625
+ ) as login_panel:
626
+
627
+ gr.Markdown(
628
+ """
629
+ # 🚀 CryptoBERT AI
630
+
631
+ Kripto piyasası sentiment analiz sistemi.
632
+
633
+ **Bullish / Neutral / Bearish**
634
+ """
635
+ )
636
+
637
+ email = gr.Textbox(
638
+ label="E-posta",
639
+ placeholder="email@example.com"
640
+ )
641
+
642
+ password = gr.Textbox(
643
+ label="Şifre",
644
+ type="password"
645
+ )
646
+
647
+ with gr.Row():
648
+
649
+ login_btn = gr.Button(
650
+ "Giriş Yap",
651
+ variant="primary"
652
+ )
653
+
654
+ signup_btn = gr.Button(
655
+ "Kayıt Ol"
656
+ )
657
+
658
+ auth_message = gr.Markdown()
659
+
660
+
661
+ # ========================================================
662
+ # APP
663
+ # ========================================================
664
+
665
+ with gr.Column(
666
+ visible=False
667
+ ) as app_panel:
668
+
669
+ with gr.Row():
670
+
671
+ user_status = gr.Markdown()
672
+
673
+ logout_btn = gr.Button(
674
+ "Çıkış"
675
+ )
676
+
677
+ gr.Markdown(
678
+ "## 📊 Crypto Sentiment Analysis"
679
+ )
680
+
681
+ text_input = gr.Textbox(
682
+ label="Kripto metni",
683
+ placeholder=(
684
+ "Bitcoin ETF inflows increased "
685
+ "sharply today..."
686
+ ),
687
+ lines=7
688
+ )
689
+
690
+ analyze_btn = gr.Button(
691
+ "🔍 Analiz Et",
692
+ variant="primary"
693
+ )
694
+
695
+ sentiment_output = gr.Textbox(
696
+ label="Sentiment"
697
+ )
698
+
699
+
700
+ # ====================================================
701
+ # ADMIN PANEL
702
+ # ====================================================
703
+
704
+ with gr.Column(
705
+ visible=False
706
+ ) as admin_panel:
707
+
708
+ gr.Markdown(
709
+ """
710
+ # 👑 Admin Panel
711
+
712
+ Kullanıcıları buradan yönetebilirsin.
713
+ """
714
+ )
715
+
716
+ users_table = gr.Dataframe(
717
+ headers=[
718
+ "ID",
719
+ "Email",
720
+ "Plan",
721
+ "Status",
722
+ "Daily Usage",
723
+ "Created"
724
+ ],
725
+ datatype=[
726
+ "number",
727
+ "str",
728
+ "str",
729
+ "str",
730
+ "number",
731
+ "str"
732
+ ],
733
+ value=get_users_dataframe(),
734
+ interactive=False
735
+ )
736
+
737
+ refresh_btn = gr.Button(
738
+ "🔄 Kullanıcıları Yenile"
739
+ )
740
+
741
+ gr.Markdown(
742
+ "### Üyelik Değiştir"
743
+ )
744
+
745
+ plan_user_id = gr.Number(
746
+ label="User ID"
747
+ )
748
+
749
+ plan_dropdown = gr.Dropdown(
750
+ choices=[
751
+ "free",
752
+ "pro",
753
+ "admin"
754
+ ],
755
+ value="pro",
756
+ label="Yeni Plan"
757
+ )
758
+
759
+ change_plan_btn = gr.Button(
760
+ "Planı Değiştir"
761
+ )
762
+
763
+ admin_message = gr.Markdown()
764
+
765
+ gr.Markdown(
766
+ "### Kullanıcı Aktif / Pasif"
767
+ )
768
+
769
+ toggle_user_id = gr.Number(
770
+ label="User ID"
771
+ )
772
+
773
+ toggle_btn = gr.Button(
774
+ "Aktif / Pasif Değiştir"
775
+ )
776
+
777
+ gr.Markdown(
778
+ "### Kullanıcı Sil"
779
+ )
780
+
781
+ delete_user_id = gr.Number(
782
+ label="User ID"
783
+ )
784
+
785
+ delete_btn = gr.Button(
786
+ "🗑️ Kullanıcıyı Sil",
787
+ variant="stop"
788
+ )
789
+
790
+
791
+ # ========================================================
792
+ # EVENTS
793
+ # ========================================================
794
+
795
+ login_btn.click(
796
+ login,
797
+ inputs=[
798
+ email,
799
+ password
800
+ ],
801
+ outputs=[
802
+ auth_message,
803
+ session,
804
+ login_panel,
805
+ app_panel,
806
+ admin_panel,
807
+ password
808
+ ]
809
+ )
810
+
811
+ signup_btn.click(
812
+ signup,
813
+ inputs=[
814
+ email,
815
+ password
816
+ ],
817
+ outputs=[
818
+ auth_message
819
+ ]
820
+ )
821
+
822
+ logout_btn.click(
823
+ logout,
824
+ outputs=[
825
+ user_status,
826
+ session,
827
+ login_panel,
828
+ app_panel,
829
+ admin_panel,
830
+ sentiment_output
831
+ ]
832
+ )
833
+
834
+ analyze_btn.click(
835
+ analyze_crypto,
836
+ inputs=[
837
+ text_input,
838
+ session
839
+ ],
840
+ outputs=[
841
+ sentiment_output
842
+ ]
843
+ )
844
+
845
+ refresh_btn.click(
846
+ refresh_users,
847
+ outputs=[
848
+ users_table
849
+ ]
850
+ )
851
+
852
+ change_plan_btn.click(
853
+ admin_change_plan,
854
+ inputs=[
855
+ plan_user_id,
856
+ plan_dropdown
857
+ ],
858
+ outputs=[
859
+ admin_message
860
+ ]
861
+ )
862
+
863
+ toggle_btn.click(
864
+ admin_toggle_user,
865
+ inputs=[
866
+ toggle_user_id
867
+ ],
868
+ outputs=[
869
+ admin_message
870
+ ]
871
+ )
872
+
873
+ delete_btn.click(
874
+ admin_delete_user,
875
+ inputs=[
876
+ delete_user_id
877
+ ],
878
+ outputs=[
879
+ admin_message
880
+ ]
881
+ )
882
 
883
 
884
+ # ============================================================
885
  # START
886
+ # ============================================================
887
 
888
+ demo.launch(
889
+ server_name="0.0.0.0",
890
+ server_port=7860
891
+ )