GoshawkVortexAI commited on
Commit
36d1e0e
·
verified ·
1 Parent(s): 1249f67

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -1181
app.py DELETED
@@ -1,1181 +0,0 @@
1
- import os
2
- import re
3
- import time
4
- import sqlite3
5
- import hashlib
6
- import secrets
7
- from datetime import date
8
-
9
- import gradio as gr
10
- import torch
11
-
12
- from transformers import AutoTokenizer
13
- from peft import AutoPeftModelForCausalLM
14
-
15
-
16
- # ============================================================
17
- # CONFIG
18
- # ============================================================
19
-
20
- MODEL_PATH = "."
21
-
22
- DB_PATH = "users.db"
23
-
24
- FREE_DAILY_LIMIT = 10
25
- PRO_DAILY_LIMIT = 1000
26
-
27
- ADMIN_EMAIL = os.getenv(
28
- "ADMIN_EMAIL",
29
- "admin@example.com"
30
- )
31
-
32
- ADMIN_PASSWORD = os.getenv(
33
- "ADMIN_PASSWORD",
34
- "CHANGE_THIS_PASSWORD"
35
- )
36
-
37
-
38
- # ============================================================
39
- # DATABASE
40
- # ============================================================
41
-
42
- def db():
43
- conn = sqlite3.connect(
44
- DB_PATH,
45
- check_same_thread=False
46
- )
47
- conn.row_factory = sqlite3.Row
48
- return conn
49
-
50
-
51
- def init_db():
52
-
53
- conn = db()
54
-
55
- conn.execute("""
56
- CREATE TABLE IF NOT EXISTS users (
57
- id INTEGER PRIMARY KEY AUTOINCREMENT,
58
- email TEXT UNIQUE NOT NULL,
59
- password_hash TEXT NOT NULL,
60
- salt TEXT NOT NULL,
61
- plan TEXT DEFAULT 'free',
62
- active INTEGER DEFAULT 1,
63
- daily_usage INTEGER DEFAULT 0,
64
- usage_date TEXT,
65
- created_at TEXT DEFAULT CURRENT_TIMESTAMP
66
- )
67
- """)
68
-
69
- conn.commit()
70
-
71
- existing = conn.execute(
72
- "SELECT id FROM users WHERE email = ?",
73
- (ADMIN_EMAIL.lower().strip(),)
74
- ).fetchone()
75
-
76
- if not existing:
77
-
78
- password_hash, salt = hash_password(
79
- ADMIN_PASSWORD
80
- )
81
-
82
- conn.execute("""
83
- INSERT INTO users
84
- (email, password_hash, salt, plan, active)
85
- VALUES (?, ?, ?, 'admin', 1)
86
- """, (
87
- ADMIN_EMAIL.lower().strip(),
88
- password_hash,
89
- salt
90
- ))
91
-
92
- conn.commit()
93
-
94
- conn.close()
95
-
96
-
97
- # ============================================================
98
- # PASSWORD
99
- # ============================================================
100
-
101
- def hash_password(password, salt=None):
102
-
103
- if salt is None:
104
- salt = secrets.token_hex(16)
105
-
106
- password_hash = hashlib.pbkdf2_hmac(
107
- "sha256",
108
- password.encode("utf-8"),
109
- salt.encode("utf-8"),
110
- 200_000
111
- ).hex()
112
-
113
- return password_hash, salt
114
-
115
-
116
- def verify_password(
117
- password,
118
- stored_hash,
119
- salt
120
- ):
121
-
122
- calculated, _ = hash_password(
123
- password,
124
- salt
125
- )
126
-
127
- return secrets.compare_digest(
128
- calculated,
129
- stored_hash
130
- )
131
-
132
-
133
- # ============================================================
134
- # USERS
135
- # ============================================================
136
-
137
- def get_user(email):
138
-
139
- conn = db()
140
-
141
- user = conn.execute(
142
- "SELECT * FROM users WHERE email = ?",
143
- (email.lower().strip(),)
144
- ).fetchone()
145
-
146
- conn.close()
147
-
148
- return user
149
-
150
-
151
- def create_user(email, password):
152
-
153
- email = email.lower().strip()
154
-
155
- if not re.match(
156
- r"^[^@\s]+@[^@\s]+\.[^@\s]+$",
157
- email
158
- ):
159
- return False, "Geçerli bir e-posta adresi gir."
160
-
161
- if len(password) < 8:
162
- return False, "Şifre en az 8 karakter olmalı."
163
-
164
- if get_user(email):
165
- return False, "Bu e-posta zaten kayıtlı."
166
-
167
- password_hash, salt = hash_password(password)
168
-
169
- conn = db()
170
-
171
- conn.execute("""
172
- INSERT INTO users
173
- (email, password_hash, salt, plan, active)
174
- VALUES (?, ?, ?, 'free', 1)
175
- """, (
176
- email,
177
- password_hash,
178
- salt
179
- ))
180
-
181
- conn.commit()
182
- conn.close()
183
-
184
- return True, "Hesap oluşturuldu."
185
-
186
-
187
- def login_user(email, password):
188
-
189
- user = get_user(email)
190
-
191
- if not user:
192
- return None, "E-posta veya şifre hatalı."
193
-
194
- if not verify_password(
195
- password,
196
- user["password_hash"],
197
- user["salt"]
198
- ):
199
- return None, "E-posta veya şifre hatalı."
200
-
201
- if not user["active"]:
202
- return None, "Hesabın pasif durumda."
203
-
204
- today = str(date.today())
205
-
206
- if user["usage_date"] != today:
207
-
208
- conn = db()
209
-
210
- conn.execute("""
211
- UPDATE users
212
- SET daily_usage = 0,
213
- usage_date = ?
214
- WHERE id = ?
215
- """, (
216
- today,
217
- user["id"]
218
- ))
219
-
220
- conn.commit()
221
- conn.close()
222
-
223
- user = get_user(email)
224
-
225
- return user, "Giriş başarılı."
226
-
227
-
228
- # ============================================================
229
- # LIMIT
230
- # ============================================================
231
-
232
- def get_limit(plan):
233
-
234
- if plan == "admin":
235
- return 999999
236
-
237
- if plan == "pro":
238
- return PRO_DAILY_LIMIT
239
-
240
- return FREE_DAILY_LIMIT
241
-
242
-
243
- def can_use(user):
244
-
245
- today = str(date.today())
246
-
247
- if user["usage_date"] != today:
248
- return True
249
-
250
- return (
251
- user["daily_usage"]
252
- <
253
- get_limit(user["plan"])
254
- )
255
-
256
-
257
- def increment_usage(user_id):
258
-
259
- conn = db()
260
-
261
- conn.execute("""
262
- UPDATE users
263
- SET daily_usage = daily_usage + 1,
264
- usage_date = ?
265
- WHERE id = ?
266
- """, (
267
- str(date.today()),
268
- user_id
269
- ))
270
-
271
- conn.commit()
272
- conn.close()
273
-
274
-
275
- # ============================================================
276
- # MODEL
277
- # ============================================================
278
-
279
- print("Loading model...")
280
-
281
- DEVICE = (
282
- "cuda"
283
- if torch.cuda.is_available()
284
- else "cpu"
285
- )
286
-
287
- print("Device:", DEVICE)
288
-
289
- adapter_file = os.path.join(
290
- MODEL_PATH,
291
- "adapter_model.safetensors"
292
- )
293
-
294
- if not os.path.exists(adapter_file):
295
-
296
- raise RuntimeError(
297
- "adapter_model.safetensors bulunamadı. "
298
- "PEFT adapter ağırlığını Space'e yükle."
299
- )
300
-
301
-
302
- tokenizer = AutoTokenizer.from_pretrained(
303
- MODEL_PATH
304
- )
305
-
306
- model = AutoPeftModelForCausalLM.from_pretrained(
307
- MODEL_PATH,
308
- dtype=(
309
- torch.float16
310
- if DEVICE == "cuda"
311
- else torch.float32
312
- )
313
- )
314
-
315
- model.to(DEVICE)
316
- model.eval()
317
-
318
- print("Model loaded.")
319
-
320
-
321
- # ============================================================
322
- # CRYPTO ASSET DETECTION
323
- # ============================================================
324
-
325
- KNOWN_ASSETS = {
326
-
327
- "BTC": [
328
- "bitcoin",
329
- "btc"
330
- ],
331
-
332
- "ETH": [
333
- "ethereum",
334
- "eth"
335
- ],
336
-
337
- "SOL": [
338
- "solana",
339
- "sol"
340
- ],
341
-
342
- "BNB": [
343
- "binance coin",
344
- "bnb"
345
- ],
346
-
347
- "XRP": [
348
- "ripple",
349
- "xrp"
350
- ],
351
-
352
- "ADA": [
353
- "cardano",
354
- "ada"
355
- ],
356
-
357
- "DOGE": [
358
- "dogecoin",
359
- "doge"
360
- ],
361
-
362
- "AVAX": [
363
- "avalanche",
364
- "avax"
365
- ],
366
-
367
- "LINK": [
368
- "chainlink",
369
- "link"
370
- ],
371
-
372
- "DOT": [
373
- "polkadot",
374
- "dot"
375
- ]
376
- }
377
-
378
-
379
- def detect_assets(text):
380
-
381
- lower = text.lower()
382
-
383
- detected = []
384
-
385
- for symbol, names in KNOWN_ASSETS.items():
386
-
387
- for name in names:
388
-
389
- pattern = (
390
- r"(?<![a-z])"
391
- + re.escape(name)
392
- + r"(?![a-z])"
393
- )
394
-
395
- if re.search(pattern, lower):
396
-
397
- detected.append(symbol)
398
- break
399
-
400
- return detected
401
-
402
-
403
- # ============================================================
404
- # SENTIMENT EXTRACTION
405
- # ============================================================
406
-
407
- def extract_sentiment(text):
408
-
409
- lower = text.lower()
410
-
411
- # Strong explicit labels
412
- if re.search(
413
- r"\bbullish\b|\bpositive\b",
414
- lower
415
- ):
416
- return "Bullish"
417
-
418
- if re.search(
419
- r"\bbearish\b|\bnegative\b",
420
- lower
421
- ):
422
- return "Bearish"
423
-
424
- if re.search(
425
- r"\bneutral\b|\bsideways\b",
426
- lower
427
- ):
428
- return "Neutral"
429
-
430
- # Keyword fallback
431
- bullish_words = [
432
- "rise",
433
- "rising",
434
- "surge",
435
- "surging",
436
- "gain",
437
- "gains",
438
- "growth",
439
- "breakout",
440
- "bull",
441
- "buy",
442
- "buying",
443
- "inflow",
444
- "inflows",
445
- "adoption",
446
- "strong",
447
- "record high",
448
- "higher"
449
- ]
450
-
451
- bearish_words = [
452
- "fall",
453
- "falling",
454
- "drop",
455
- "dropping",
456
- "crash",
457
- "loss",
458
- "losses",
459
- "sell",
460
- "selling",
461
- "outflow",
462
- "outflows",
463
- "bear",
464
- "resistance",
465
- "hack",
466
- "liquidation",
467
- "lower",
468
- "weak"
469
- ]
470
-
471
- bullish_score = sum(
472
- word in lower
473
- for word in bullish_words
474
- )
475
-
476
- bearish_score = sum(
477
- word in lower
478
- for word in bearish_words
479
- )
480
-
481
- if bullish_score > bearish_score:
482
- return "Bullish"
483
-
484
- if bearish_score > bullish_score:
485
- return "Bearish"
486
-
487
- return "Neutral"
488
-
489
-
490
- # ============================================================
491
- # SENTIMENT SCORE
492
- # ============================================================
493
-
494
- def sentiment_score(
495
- sentiment,
496
- text
497
- ):
498
-
499
- lower = text.lower()
500
-
501
- bullish_words = [
502
- "surge",
503
- "breakout",
504
- "bullish",
505
- "strong",
506
- "inflow",
507
- "growth",
508
- "rally",
509
- "higher",
510
- "buy"
511
- ]
512
-
513
- bearish_words = [
514
- "crash",
515
- "bearish",
516
- "weak",
517
- "outflow",
518
- "liquidation",
519
- "hack",
520
- "lower",
521
- "sell"
522
- ]
523
-
524
- bull = sum(
525
- x in lower
526
- for x in bullish_words
527
- )
528
-
529
- bear = sum(
530
- x in lower
531
- for x in bearish_words
532
- )
533
-
534
- raw = bull - bear
535
-
536
- if sentiment == "Bullish":
537
- raw += 1
538
-
539
- elif sentiment == "Bearish":
540
- raw -= 1
541
-
542
- score = max(
543
- -1,
544
- min(
545
- 1,
546
- raw / 5
547
- )
548
- )
549
-
550
- return score
551
-
552
-
553
- # ============================================================
554
- # STRENGTH
555
- # ============================================================
556
-
557
- def get_strength(score):
558
-
559
- absolute = abs(score)
560
-
561
- if absolute >= 0.70:
562
- return "STRONG"
563
-
564
- if absolute >= 0.35:
565
- return "MODERATE"
566
-
567
- return "WEAK"
568
-
569
-
570
- # ============================================================
571
- # RISK
572
- # ============================================================
573
-
574
- def get_risk(
575
- text,
576
- score
577
- ):
578
-
579
- lower = text.lower()
580
-
581
- high_risk_words = [
582
- "hack",
583
- "exploit",
584
- "crash",
585
- "liquidation",
586
- "lawsuit",
587
- "ban",
588
- "bankruptcy",
589
- "rug"
590
- ]
591
-
592
- medium_risk_words = [
593
- "volatility",
594
- "resistance",
595
- "uncertain",
596
- "uncertainty",
597
- "regulation"
598
- ]
599
-
600
- if any(
601
- word in lower
602
- for word in high_risk_words
603
- ):
604
- return "HIGH"
605
-
606
- if any(
607
- word in lower
608
- for word in medium_risk_words
609
- ):
610
- return "MEDIUM"
611
-
612
- if abs(score) > 0.7:
613
- return "MEDIUM"
614
-
615
- return "LOW"
616
-
617
-
618
- # ============================================================
619
- # MARKET IMPACT
620
- # ============================================================
621
-
622
- def get_market_impact(
623
- sentiment,
624
- score
625
- ):
626
-
627
- if abs(score) >= 0.70:
628
- strength = "High"
629
-
630
- elif abs(score) >= 0.35:
631
- strength = "Moderate"
632
-
633
- else:
634
- strength = "Low"
635
-
636
- if sentiment == "Bullish":
637
- return f"Positive ({strength})"
638
-
639
- if sentiment == "Bearish":
640
- return f"Negative ({strength})"
641
-
642
- return f"Neutral ({strength})"
643
-
644
-
645
- # ============================================================
646
- # SIGNAL BAR
647
- # ============================================================
648
-
649
- def bar(value):
650
-
651
- value = max(
652
- 0,
653
- min(
654
- 100,
655
- int(value)
656
- )
657
- )
658
-
659
- filled = int(
660
- value / 5
661
- )
662
-
663
- return (
664
- "█" * filled
665
- +
666
- "░" * (20 - filled)
667
- )
668
-
669
-
670
- # ============================================================
671
- # DETAILED ANALYSIS
672
- # ============================================================
673
-
674
- def analyze_crypto(
675
- text,
676
- user
677
- ):
678
-
679
- start = time.perf_counter()
680
-
681
- if not text or not text.strip():
682
-
683
- return "Lütfen analiz edilecek metni gir."
684
-
685
- if user is None:
686
-
687
- return "Önce giriş yapmalısın."
688
-
689
- current_user = get_user(
690
- user["email"]
691
- )
692
-
693
- if not current_user:
694
-
695
- return "Oturum bulunamadı."
696
-
697
- if not current_user["active"]:
698
-
699
- return "Hesabın aktif değil."
700
-
701
- if not can_use(current_user):
702
-
703
- limit = get_limit(
704
- current_user["plan"]
705
- )
706
-
707
- return (
708
- f"## ⚠️ Günlük Limit Doldu\n\n"
709
- f"**Plan:** "
710
- f"{current_user['plan'].upper()}\n\n"
711
- f"**Limit:** {limit} analiz/gün"
712
- )
713
-
714
-
715
- # --------------------------------------------------------
716
- # MODEL
717
- # --------------------------------------------------------
718
-
719
- prompt = f"""
720
- You are a cryptocurrency sentiment analysis model.
721
-
722
- Analyze the following crypto market text.
723
-
724
- Classify the sentiment as exactly one:
725
- Bullish
726
- Neutral
727
- Bearish
728
-
729
- Return the sentiment label clearly.
730
-
731
- Text:
732
- {text}
733
-
734
- Sentiment:
735
- """
736
-
737
-
738
- inputs = tokenizer(
739
- prompt,
740
- return_tensors="pt",
741
- truncation=True,
742
- max_length=512
743
- )
744
-
745
- inputs = {
746
- k: v.to(DEVICE)
747
- for k, v in inputs.items()
748
- }
749
-
750
-
751
- with torch.no_grad():
752
-
753
- output = model.generate(
754
- **inputs,
755
- max_new_tokens=20,
756
- do_sample=False
757
- )
758
-
759
-
760
- generated = output[
761
- 0
762
- ][
763
- inputs["input_ids"].shape[1]:
764
- ]
765
-
766
-
767
- raw_result = tokenizer.decode(
768
- generated,
769
- skip_special_tokens=True
770
- ).strip()
771
-
772
-
773
- # --------------------------------------------------------
774
- # ANALYSIS
775
- # --------------------------------------------------------
776
-
777
- sentiment = extract_sentiment(
778
- raw_result
779
- +
780
- " "
781
- +
782
- text
783
- )
784
-
785
- score = sentiment_score(
786
- sentiment,
787
- text
788
- )
789
-
790
- strength = get_strength(
791
- score
792
- )
793
-
794
- risk = get_risk(
795
- text,
796
- score
797
- )
798
-
799
- impact = get_market_impact(
800
- sentiment,
801
- score
802
- )
803
-
804
- assets = detect_assets(
805
- text
806
- )
807
-
808
-
809
- # --------------------------------------------------------
810
- # DISPLAY SCORES
811
- # --------------------------------------------------------
812
-
813
- if sentiment == "Bullish":
814
-
815
- bullish = 70 + abs(score) * 25
816
- bearish = 10
817
- neutral = 100 - bullish - bearish
818
-
819
- elif sentiment == "Bearish":
820
-
821
- bearish = 70 + abs(score) * 25
822
- bullish = 10
823
- neutral = 100 - bearish - bullish
824
-
825
- else:
826
-
827
- neutral = 60 + (1 - abs(score)) * 20
828
- bullish = (100 - neutral) / 2
829
- bearish = bullish
830
-
831
-
832
- bullish = max(
833
- 0,
834
- min(
835
- 100,
836
- bullish
837
- )
838
- )
839
-
840
- bearish = max(
841
- 0,
842
- min(
843
- 100,
844
- bearish
845
- )
846
- )
847
-
848
- neutral = max(
849
- 0,
850
- 100 - bullish - bearish
851
- )
852
-
853
-
854
- # --------------------------------------------------------
855
- # DIRECTION ICON
856
- # --------------------------------------------------------
857
-
858
- if sentiment == "Bullish":
859
- icon = "🟢"
860
-
861
- elif sentiment == "Bearish":
862
- icon = "🔴"
863
-
864
- else:
865
- icon = "🟡"
866
-
867
-
868
- elapsed = (
869
- time.perf_counter()
870
- - start
871
- )
872
-
873
-
874
- # --------------------------------------------------------
875
- # USAGE
876
- # --------------------------------------------------------
877
-
878
- increment_usage(
879
- current_user["id"]
880
- )
881
-
882
- new_user = get_user(
883
- current_user["email"]
884
- )
885
-
886
-
887
- # --------------------------------------------------------
888
- # ASSET TEXT
889
- # --------------------------------------------------------
890
-
891
- asset_text = (
892
- ", ".join(assets)
893
- if assets
894
- else "Belirlenmedi"
895
- )
896
-
897
-
898
- # --------------------------------------------------------
899
- # SCORE TEXT
900
- # --------------------------------------------------------
901
-
902
- score_text = (
903
- f"{score:+.2f}"
904
- )
905
-
906
-
907
- # --------------------------------------------------------
908
- # FINAL REPORT
909
- # --------------------------------------------------------
910
-
911
- report = f"""
912
- # {icon} CRYPTO SENTIMENT ANALYSIS
913
-
914
- ## Genel Sinyal
915
-
916
- ### **{sentiment.upper()}**
917
-
918
- | Metrik | Sonuç |
919
- |---|---|
920
- | **Sentiment** | {sentiment} |
921
- | **Sentiment Score** | `{score_text}` |
922
- | **Signal Strength** | **{strength}** |
923
- | **Market Impact** | **{impact}** |
924
- | **Risk Level** | **{risk}** |
925
- | **Detected Asset** | **{asset_text}** |
926
-
927
- ---
928
-
929
- ## 📊 Sentiment Distribution
930
-
931
- ### 🟢 Bullish — **{bullish:.1f}%**
932
-
933
- `{bar(bullish)}`
934
-
935
- ### 🟡 Neutral — **{neutral:.1f}%**
936
-
937
- `{bar(neutral)}`
938
-
939
- ### 🔴 Bearish — **{bearish:.1f}%**
940
-
941
- `{bar(bearish)}`
942
-
943
- > **Not:** Bu yüzdeler mevcut generative modelin gerçek
944
- > softmax sınıf olasılıkları değildir; model çıktısı ve metin
945
- > sinyallerinden oluşturulan yaklaşık dağılımdır.
946
-
947
- ---
948
-
949
- ## 🎯 Signal Interpretation
950
-
951
- **Direction:** `{sentiment}`
952
-
953
- **Strength:** `{strength}`
954
-
955
- **Risk:** `{risk}`
956
-
957
- **Market Impact:** `{impact}`
958
-
959
- ---
960
-
961
- ## 🪙 Asset Detection
962
-
963
- Detected assets:
964
-
965
- **{asset_text}**
966
-
967
- ---
968
-
969
- ## 🤖 Model Output
970
-
971
- ```text
972
- {raw_result if raw_result else "No explicit label returned."}
973
-
974
- ```
975
-
976
- """
977
- # Keep the report as the function result.
978
- return report
979
-
980
-
981
- # ============================================================
982
- # AUTHENTICATION / UI
983
- # ============================================================
984
-
985
- def signup_action(email, password):
986
- ok, message = create_user(email, password)
987
- return message
988
-
989
-
990
- def login_action(email, password):
991
- user, message = login_user(email, password)
992
- if user is None:
993
- return None, f"❌ {message}"
994
- return dict(user), f"✅ {message} — {user['email']} ({user['plan'].upper()})"
995
-
996
-
997
- def logout_action():
998
- return None, "Çıkış yapıldı."
999
-
1000
-
1001
- def user_info(user):
1002
- if not user:
1003
- return "Giriş yapılmadı."
1004
- current = get_user(user["email"])
1005
- if not current:
1006
- return "Oturum bulunamadı."
1007
- limit = get_limit(current["plan"])
1008
- usage = current["daily_usage"] if current["usage_date"] == str(date.today()) else 0
1009
- return (
1010
- f"**{current['email']}** \\n"
1011
- f"Plan: **{current['plan'].upper()}** \\n"
1012
- f"Günlük kullanım: **{usage}/{limit}**"
1013
- )
1014
-
1015
-
1016
- def admin_users_action(user):
1017
- if not user or user.get("plan") != "admin":
1018
- return "❌ Admin yetkisi gerekli."
1019
- conn = db()
1020
- rows = conn.execute(
1021
- "SELECT id, email, plan, active, daily_usage, usage_date, created_at FROM users ORDER BY id"
1022
- ).fetchall()
1023
- conn.close()
1024
- if not rows:
1025
- return "Kullanıcı yok."
1026
- lines = ["| ID | Email | Plan | Active | Usage | Date |", "|---:|---|---|---:|---:|---|"]
1027
- for r in rows:
1028
- lines.append(
1029
- f"| {r['id']} | {r['email']} | {r['plan']} | {r['active']} | {r['daily_usage']} | {r['usage_date'] or '-'} |"
1030
- )
1031
- return "\\n".join(lines)
1032
-
1033
-
1034
- def admin_change_plan(user, email, plan):
1035
- if not user or user.get("plan") != "admin":
1036
- return "❌ Admin yetkisi gerekli."
1037
- plan = (plan or "").lower().strip()
1038
- if plan not in {"free", "pro", "admin"}:
1039
- return "❌ Plan free, pro veya admin olmalı."
1040
- target = get_user(email)
1041
- if not target:
1042
- return "❌ Kullanıcı bulunamadı."
1043
- conn = db()
1044
- conn.execute("UPDATE users SET plan = ? WHERE id = ?", (plan, target["id"]))
1045
- conn.commit()
1046
- conn.close()
1047
- return f"✅ {email} → {plan}"
1048
-
1049
-
1050
- def admin_set_active(user, email, active):
1051
- if not user or user.get("plan") != "admin":
1052
- return "❌ Admin yetkisi gerekli."
1053
- target = get_user(email)
1054
- if not target:
1055
- return "❌ Kullanıcı bulunamadı."
1056
- conn = db()
1057
- conn.execute("UPDATE users SET active = ? WHERE id = ?", (1 if active else 0, target["id"]))
1058
- conn.commit()
1059
- conn.close()
1060
- return f"✅ {email} → {'aktif' if active else 'pasif'}"
1061
-
1062
-
1063
- def admin_delete(user, email):
1064
- if not user or user.get("plan") != "admin":
1065
- return "❌ Admin yetkisi gerekli."
1066
- email = (email or "").lower().strip()
1067
- if email == ADMIN_EMAIL.lower().strip():
1068
- return "❌ Ana admin hesabı silinemez."
1069
- target = get_user(email)
1070
- if not target:
1071
- return "❌ Kullanıcı bulunamadı."
1072
- conn = db()
1073
- conn.execute("DELETE FROM users WHERE id = ?", (target["id"],))
1074
- conn.commit()
1075
- conn.close()
1076
- return f"✅ {email} silindi."
1077
-
1078
-
1079
- # Initialize database before serving the UI.
1080
- init_db()
1081
-
1082
- with gr.Blocks(title="Crypto Sentiment AI") as demo:
1083
- session = gr.State(None)
1084
-
1085
- gr.Markdown("# 🧠 Crypto Sentiment AI")
1086
- gr.Markdown("Kripto metinlerini analiz et ve model tabanlı sentiment sinyalini görüntüle.")
1087
-
1088
- with gr.Tab("🔐 Hesap"):
1089
- with gr.Row():
1090
- with gr.Column():
1091
- gr.Markdown("### Giriş")
1092
- login_email = gr.Textbox(label="E-posta")
1093
- login_password = gr.Textbox(label="Şifre", type="password")
1094
- login_btn = gr.Button("Giriş Yap", variant="primary")
1095
- logout_btn = gr.Button("Çıkış Yap")
1096
- with gr.Column():
1097
- gr.Markdown("### Kayıt")
1098
- signup_email = gr.Textbox(label="E-posta")
1099
- signup_password = gr.Textbox(label="Şifre", type="password")
1100
- signup_btn = gr.Button("Hesap Oluştur")
1101
-
1102
- auth_status = gr.Markdown("Giriş yapılmadı.")
1103
- account_info = gr.Markdown("Giriş yapılmadı.")
1104
-
1105
- login_btn.click(
1106
- login_action,
1107
- inputs=[login_email, login_password],
1108
- outputs=[session, auth_status],
1109
- ).then(user_info, inputs=session, outputs=account_info)
1110
-
1111
- logout_btn.click(
1112
- logout_action,
1113
- outputs=[session, auth_status],
1114
- ).then(user_info, inputs=session, outputs=account_info)
1115
-
1116
- signup_btn.click(
1117
- signup_action,
1118
- inputs=[signup_email, signup_password],
1119
- outputs=auth_status,
1120
- )
1121
-
1122
- with gr.Tab("📊 Sentiment Analysis"):
1123
- analysis_text = gr.Textbox(
1124
- label="Crypto market text",
1125
- placeholder="Örn: Bitcoin breaks resistance as institutional inflows increase...",
1126
- lines=8,
1127
- )
1128
- analyze_btn = gr.Button("🔎 Analiz Et", variant="primary")
1129
- report_output = gr.Markdown()
1130
- analyze_btn.click(
1131
- analyze_crypto,
1132
- inputs=[analysis_text, session],
1133
- outputs=report_output,
1134
- )
1135
-
1136
- with gr.Tab("👑 Admin"):
1137
- gr.Markdown("Admin işlemleri yalnızca admin planındaki oturumla çalışır.")
1138
- refresh_btn = gr.Button("Kullanıcıları Yenile")
1139
- users_output = gr.Markdown()
1140
- refresh_btn.click(admin_users_action, inputs=session, outputs=users_output)
1141
-
1142
- with gr.Row():
1143
- admin_email_input = gr.Textbox(label="Hedef e-posta")
1144
- admin_plan = gr.Dropdown(["free", "pro", "admin"], value="free", label="Yeni plan")
1145
- change_plan_btn = gr.Button("Planı Değiştir")
1146
- activate_btn = gr.Button("Aktif Et")
1147
- deactivate_btn = gr.Button("Pasif Et")
1148
- delete_btn = gr.Button("Kullanıcıyı Sil")
1149
- admin_status = gr.Markdown()
1150
-
1151
- change_plan_btn.click(
1152
- admin_change_plan,
1153
- inputs=[session, admin_email_input, admin_plan],
1154
- outputs=admin_status,
1155
- ).then(admin_users_action, inputs=session, outputs=users_output)
1156
-
1157
- activate_btn.click(
1158
- admin_set_active,
1159
- inputs=[session, admin_email_input, gr.State(True)],
1160
- outputs=admin_status,
1161
- ).then(admin_users_action, inputs=session, outputs=users_output)
1162
-
1163
- deactivate_btn.click(
1164
- admin_set_active,
1165
- inputs=[session, admin_email_input, gr.State(False)],
1166
- outputs=admin_status,
1167
- ).then(admin_users_action, inputs=session, outputs=users_output)
1168
-
1169
- delete_btn.click(
1170
- admin_delete,
1171
- inputs=[session, admin_email_input],
1172
- outputs=admin_status,
1173
- ).then(admin_users_action, inputs=session, outputs=users_output)
1174
-
1175
- gr.Markdown(
1176
- "⚠️ Sentiment dağılımı mevcut generative PEFT modelinden gerçek softmax sınıf olasılığı değildir."
1177
- )
1178
-
1179
-
1180
- if __name__ == "__main__":
1181
- demo.launch()