nicolaydef commited on
Commit
db370a0
·
verified ·
1 Parent(s): 5ba7d72

Update app/main.py

Browse files
Files changed (1) hide show
  1. app/main.py +32 -57
app/main.py CHANGED
@@ -1,6 +1,6 @@
1
- from fastapi import FastAPI, UploadFile, File, WebSocket, WebSocketDisconnect, HTTPException, Depends
2
  from fastapi.staticfiles import StaticFiles
3
- from fastapi.responses import FileResponse, JSONResponse
4
  from pydantic import BaseModel
5
  from textblob import TextBlob
6
  from passlib.context import CryptContext
@@ -8,100 +8,76 @@ from typing import List, Optional
8
  import os
9
  import json
10
  import base64
11
- from google.oauth2.credentials import Credentials
12
- from googleapiclient.discovery import build
13
- from googleapiclient.http import MediaIoBaseUpload
14
 
15
  app = FastAPI(title="Zenith Platform")
16
 
17
- # --- SECURITY & CONFIG ---
18
  pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
19
  SUPABASE_URL = os.getenv("SUPABASE_URL")
20
  SUPABASE_KEY = os.getenv("SUPABASE_KEY")
21
- GDRIVE_TOKEN_B64 = os.getenv("GDRIVE_TOKEN_B64")
22
- # Секретный код админа (4 буквы). Установи в Secrets на HF!
23
- ADMIN_SECRET_CODE = os.getenv("ADMIN_SECRET_CODE", "XAE1")
24
 
25
  # --- MODELS ---
26
- class LoginModel(BaseModel):
27
- username: str
28
- password: str
29
-
30
  class CreateUserModel(BaseModel):
31
  admin_code: str
32
  new_username: str
33
  new_password: str
34
 
 
 
 
 
35
  class MessageInput(BaseModel):
36
  text: str
37
 
38
- class MoodResponse(BaseModel):
39
- mood_color: str
40
- emoji: str
41
- sentiment: float
42
-
43
- # --- GOOGLE DRIVE (Тот же код) ---
44
- def get_drive_service():
45
- try:
46
- if not GDRIVE_TOKEN_B64: return None
47
- creds_json = base64.b64decode(GDRIVE_TOKEN_B64).decode('utf-8')
48
- creds_dict = json.loads(creds_json)
49
- creds = Credentials.from_authorized_user_info(creds_dict)
50
- return build('drive', 'v3', credentials=creds)
51
- except Exception as e:
52
- print(f"Drive Error: {e}")
53
- return None
54
-
55
- # --- AUTH ROUTES ---
56
- @app.post("/api/auth/login")
57
- async def login(data: LoginModel):
58
- # В реальном проде здесь нужен запрос к Supabase для проверки хэша
59
- # Но так как мы делаем "быстрый" бэк, мы будем хэшировать на фронте?
60
- # Нет, правильно: фронт шлет пароль -> бэк проверяет.
61
- # Для упрощения работы с Supabase из Python без ORM,
62
- # мы будем делать простую проверку: хэширование пароля для сверки
63
- return {"status": "ok", "msg": "Логика проверки перенесена на клиент через Supabase Auth (упрощение)"}
64
-
65
  @app.post("/api/admin/create_user")
66
  async def create_user(data: CreateUserModel):
67
- if data.admin_code != ADMIN_SECRET_CODE:
68
- raise HTTPException(status_code=403, detail="Неверный код доступа")
69
 
70
- # Хэшируем пароль
71
- hashed_pw = pwd_context.hash(data.new_password)
72
 
 
73
  return {
74
  "username": data.new_username,
75
  "password_hash": hashed_pw,
76
  "badge": "BETA"
77
  }
78
 
 
 
 
 
 
 
79
  # --- CHAT & MOOD ---
80
- @app.post("/api/analyze_mood", response_model=MoodResponse)
81
  async def analyze_mood(msg: MessageInput):
82
  blob = TextBlob(msg.text)
83
  p = blob.sentiment.polarity
84
- if p > 0.5: return MoodResponse(mood_color="#00f2ea", emoji="✨", sentiment=p)
85
- elif p > 0: return MoodResponse(mood_color="#4facfe", emoji="😌", sentiment=p)
86
- elif p < -0.5: return MoodResponse(mood_color="#ff0055", emoji="🔥", sentiment=p)
87
- elif p < 0: return MoodResponse(mood_color="#8e44ad", emoji="🥀", sentiment=p)
88
- return MoodResponse(mood_color="#ffffff", emoji="🌫️", sentiment=p)
89
 
90
  @app.get("/api/config")
91
  async def get_config():
92
- return {
93
- "supabase_url": SUPABASE_URL,
94
- "supabase_key": SUPABASE_KEY
95
- }
96
 
97
- # --- WEBSOCKET SIGNALING ---
98
  class ConnectionManager:
99
  def __init__(self): self.active_connections: List[WebSocket] = []
100
  async def connect(self, websocket: WebSocket): await websocket.accept(); self.active_connections.append(websocket)
101
  def disconnect(self, websocket: WebSocket): self.active_connections.remove(websocket)
102
  async def broadcast(self, message: str, sender: WebSocket):
103
  for connection in self.active_connections:
104
- if connection != sender: await connection.send_text(message)
 
 
105
 
106
  manager = ConnectionManager()
107
 
@@ -115,7 +91,6 @@ async def websocket_endpoint(websocket: WebSocket):
115
  except WebSocketDisconnect:
116
  manager.disconnect(websocket)
117
 
118
- # --- STATIC ---
119
  app.mount("/static", StaticFiles(directory="static"), name="static")
120
  @app.get("/")
121
  async def read_index(): return FileResponse('static/index.html')
 
1
+ from fastapi import FastAPI, UploadFile, File, WebSocket, WebSocketDisconnect, HTTPException, Body
2
  from fastapi.staticfiles import StaticFiles
3
+ from fastapi.responses import FileResponse
4
  from pydantic import BaseModel
5
  from textblob import TextBlob
6
  from passlib.context import CryptContext
 
8
  import os
9
  import json
10
  import base64
 
 
 
11
 
12
  app = FastAPI(title="Zenith Platform")
13
 
14
+ # --- CONFIG ---
15
  pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
16
  SUPABASE_URL = os.getenv("SUPABASE_URL")
17
  SUPABASE_KEY = os.getenv("SUPABASE_KEY")
18
+ # ВАЖНО: Если переменная не задана, код будет '1234'. Проверь это!
19
+ ADMIN_SECRET_CODE = os.getenv("ADMIN_SECRET_CODE", "1234")
 
20
 
21
  # --- MODELS ---
 
 
 
 
22
  class CreateUserModel(BaseModel):
23
  admin_code: str
24
  new_username: str
25
  new_password: str
26
 
27
+ class UpdateProfileModel(BaseModel):
28
+ username: str
29
+ is_looking: bool
30
+
31
  class MessageInput(BaseModel):
32
  text: str
33
 
34
+ # --- AUTH & ADMIN ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  @app.post("/api/admin/create_user")
36
  async def create_user(data: CreateUserModel):
37
+ # Логируем для отладки (будет видно в логах HF)
38
+ print(f"Admin attempt. Input code: '{data.admin_code}', Expected: '{ADMIN_SECRET_CODE}'")
39
 
40
+ if data.admin_code.strip() != ADMIN_SECRET_CODE:
41
+ raise HTTPException(status_code=403, detail="ACCESS DENIED: Wrong Code")
42
 
43
+ hashed_pw = pwd_context.hash(data.new_password)
44
  return {
45
  "username": data.new_username,
46
  "password_hash": hashed_pw,
47
  "badge": "BETA"
48
  }
49
 
50
+ @app.post("/api/user/update_profile")
51
+ async def update_profile(data: UpdateProfileModel):
52
+ # Здесь просто возвращаем статус, реальная запись идет через Supabase Client на фронте
53
+ # или можно расширить этот метод для серверной записи.
54
+ return {"status": "ok", "looking_for_friends": data.is_looking}
55
+
56
  # --- CHAT & MOOD ---
57
+ @app.post("/api/analyze_mood")
58
  async def analyze_mood(msg: MessageInput):
59
  blob = TextBlob(msg.text)
60
  p = blob.sentiment.polarity
61
+ if p > 0.5: return {"mood_color": "#00f2ea", "emoji": "✨"}
62
+ elif p > 0: return {"mood_color": "#4facfe", "emoji": "😌"}
63
+ elif p < -0.5: return {"mood_color": "#ff0055", "emoji": "🔥"}
64
+ elif p < 0: return {"mood_color": "#8e44ad", "emoji": "🥀"}
65
+ return {"mood_color": "#ffffff", "emoji": "🌫️"}
66
 
67
  @app.get("/api/config")
68
  async def get_config():
69
+ return {"supabase_url": SUPABASE_URL, "supabase_key": SUPABASE_KEY}
 
 
 
70
 
71
+ # --- WEBSOCKET (FIXED) ---
72
  class ConnectionManager:
73
  def __init__(self): self.active_connections: List[WebSocket] = []
74
  async def connect(self, websocket: WebSocket): await websocket.accept(); self.active_connections.append(websocket)
75
  def disconnect(self, websocket: WebSocket): self.active_connections.remove(websocket)
76
  async def broadcast(self, message: str, sender: WebSocket):
77
  for connection in self.active_connections:
78
+ if connection != sender:
79
+ try: await connection.send_text(message)
80
+ except: pass
81
 
82
  manager = ConnectionManager()
83
 
 
91
  except WebSocketDisconnect:
92
  manager.disconnect(websocket)
93
 
 
94
  app.mount("/static", StaticFiles(directory="static"), name="static")
95
  @app.get("/")
96
  async def read_index(): return FileResponse('static/index.html')