persee-tech commited on
Commit
4c6fc56
·
1 Parent(s): 89ff6a0

Fix CORS 403 error

Browse files
Files changed (1) hide show
  1. backend/server.py +35 -51
backend/server.py CHANGED
@@ -12,27 +12,32 @@ from datetime import datetime
12
  from deepface import DeepFace
13
  from supabase import create_client, Client
14
 
15
- # --- CONFIGURATION SUPABASE (BACKEND) ---
16
- # ⚠️ REMPLACEZ PAR VOS CLÉS (Supabase > Settings > API)
17
- # ICI IL FAUT LA CLÉ SECRÈTE "SERVICE_ROLE" POUR POUVOIR ECRIRE/SUPPRIMER
18
- SUPABASE_URL = 'https://gwjrwejdjpctizolfkcz.supabase.co'
19
- SUPABASE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imd3anJ3ZWpkanBjdGl6b2xma2N6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc2OTA5ODEyNCwiZXhwIjoyMDg0Njc0MTI0fQ.EjU1DGTN-jrdkaC6nJWilFtYZgtu-NKjnfiMVMnHal0"
20
 
21
  try:
22
  supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
23
- print("☁️ Connecté à Supabase (PerseeTech)")
24
  except Exception as e:
25
- print(f"❌ Erreur de connexion Supabase : {e}")
26
 
27
- # --- CONFIGURATION SERVEUR ---
 
28
  sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
 
29
  app = FastAPI()
 
30
  app.add_middleware(
31
- CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"],
 
 
 
 
32
  )
33
  socket_app = socketio.ASGIApp(sio, app)
34
 
35
- # --- API REST (Lecture pour l'Admin) ---
36
  @app.get("/api/sessions")
37
  def get_sessions():
38
  response = supabase.table('sessions').select("*").order('id', desc=True).execute()
@@ -41,8 +46,7 @@ def get_sessions():
41
  @app.get("/api/sessions/{session_id}")
42
  def get_session_details(session_id: int):
43
  sess = supabase.table('sessions').select("*").eq('id', session_id).execute()
44
- if not sess.data:
45
- raise HTTPException(status_code=404, detail="Session non trouvée")
46
  meas = supabase.table('measurements').select("*").eq('session_id', session_id).order('session_time', desc=False).execute()
47
  return {"info": sess.data[0], "data": meas.data}
48
 
@@ -50,11 +54,11 @@ def get_session_details(session_id: int):
50
  def delete_session(session_id: int):
51
  try:
52
  supabase.table('sessions').delete().eq('id', session_id).execute()
53
- return {"message": "Session supprimée avec succès"}
54
  except Exception as e:
55
  raise HTTPException(status_code=500, detail=str(e))
56
 
57
- # --- LOGIQUE MÉTIER (KPIs - SANS BPM) ---
58
  def calculate_kpis(emotion):
59
  valence = 0.0; arousal = 0.0; noise = random.uniform(-0.05, 0.05)
60
  if emotion == "happy": valence = 0.8 + noise; arousal = 0.6 + noise
@@ -80,28 +84,15 @@ def calculate_kpis(emotion):
80
  elif val_sat >= 45: lbl_sat = "Neutre 😐"
81
  else: lbl_sat = "Insatisfait 😡"
82
 
83
- if val_tru >= 70: lbl_tru = "Confiance Totale 🤝"
84
- elif val_tru >= 40: lbl_tru = "Sceptique 🤔"
85
- else: lbl_tru = "Méfiant 🚩"
86
-
87
- if val_loy >= 75: lbl_loy = "Fidèle (Ambassadeur) 💎"
88
- elif val_loy >= 50: lbl_loy = "Client Standard"
89
- else: lbl_loy = "Infidèle / Volatile 💸"
90
-
91
- if val_opi >= 60: lbl_opi = "Avis Positif 👍"
92
- elif val_opi >= 40: lbl_opi = "Indécis"
93
- else: lbl_opi = "Avis Négatif 👎"
94
-
95
  return {
96
  "engagement": val_eng, "satisfaction": val_sat, "trust": val_tru, "loyalty": val_loy, "opinion": val_opi,
97
- "lbl_eng": lbl_eng, "lbl_sat": lbl_sat, "lbl_tru": lbl_tru, "lbl_loy": lbl_loy, "lbl_opi": lbl_opi
98
  }
99
 
100
- # --- ETAT IA ---
101
  camera_state = { "emotion": "neutral", "emotion_score": 0, "face_coords": None }
102
  active_sessions = {}
103
 
104
- # TÂCHE 1 : RECEPTION IMAGE (CLIENT -> SERVER)
105
  @sio.event
106
  async def process_frame(sid, data_uri):
107
  try:
@@ -109,7 +100,6 @@ async def process_frame(sid, data_uri):
109
  nparr = np.frombuffer(base64.b64decode(encoded_data), np.uint8)
110
  frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
111
 
112
- # Analyse DeepFace
113
  result = DeepFace.analyze(frame, actions=['emotion'], enforce_detection=False, silent=True)
114
  data = result[0] if isinstance(result, list) else result
115
 
@@ -124,7 +114,6 @@ async def process_frame(sid, data_uri):
124
  except:
125
  camera_state["face_coords"] = None
126
 
127
- # TÂCHE 2 : GESTION SESSION (Boucle infinie)
128
  async def session_manager_loop():
129
  while True:
130
  for sid, user_data in list(active_sessions.items()):
@@ -132,24 +121,19 @@ async def session_manager_loop():
132
 
133
  if user_data["is_recording"]:
134
  user_data["session_time"] += 1
135
- t = user_data["session_time"]
136
-
137
- # ENREGISTREMENT DB SUPABASE
138
  if user_data["db_id"]:
139
  try:
140
  data_to_insert = {
141
  "session_id": user_data["db_id"],
142
- "session_time": t,
143
  "emotion": camera_state["emotion"],
144
  "emotion_score": camera_state["emotion_score"],
145
  "engagement_val": kpis["engagement"], "engagement_lbl": kpis["lbl_eng"],
146
  "satisfaction_val": kpis["satisfaction"], "satisfaction_lbl": kpis["lbl_sat"],
147
- "trust_val": kpis["trust"], "trust_lbl": kpis["lbl_tru"],
148
- "loyalty_val": kpis["loyalty"], "loyalty_lbl": kpis["lbl_loy"],
149
- "opinion_val": kpis["opinion"], "opinion_lbl": kpis["lbl_opi"]
150
  }
151
  supabase.table('measurements').insert(data_to_insert).execute()
152
- except Exception as e: print(f"Supabase Insert Error: {e}")
153
 
154
  await sio.emit('metrics_update', {
155
  "emotion": camera_state["emotion"], "metrics": kpis,
@@ -160,32 +144,32 @@ async def session_manager_loop():
160
  await asyncio.sleep(1)
161
 
162
  @sio.event
163
- async def connect(sid, environ): active_sessions[sid] = { "is_recording": False, "session_time": 0, "db_id": None }
 
 
 
164
  @sio.event
165
  async def disconnect(sid):
166
  if sid in active_sessions: del active_sessions[sid]
 
167
  @sio.event
168
  async def start_session(sid, data):
169
  user_session = active_sessions.get(sid)
170
  if user_session:
171
  user_session["is_recording"] = True
172
  user_session["session_time"] = 0
173
-
174
- new_session = {
175
- "first_name": data.get('firstName'),
176
- "last_name": data.get('lastName'),
177
- "client_id": data.get('clientId')
178
- }
179
- res = supabase.table('sessions').insert(new_session).execute()
180
- user_session["db_id"] = res.data[0]['id']
181
 
182
  @sio.event
183
  async def stop_session(sid):
184
- user_session = active_sessions.get(sid)
185
- if user_session: user_session["is_recording"] = False
186
 
187
  if __name__ == "__main__":
188
  @app.on_event("startup")
189
  async def startup_event():
190
  asyncio.create_task(session_manager_loop())
191
- uvicorn.run(socket_app, host="0.0.0.0", port=8000)
 
12
  from deepface import DeepFace
13
  from supabase import create_client, Client
14
 
15
+ # --- CONFIGURATION SUPABASE (COMPATIBLE CLOUD & LOCAL) ---
16
+ SUPABASE_URL = os.getenv("SUPABASE_URL", "https://gwjrwejdjpctizolfkcz.supabase.co")
17
+ SUPABASE_KEY = os.getenv("SUPABASE_KEY", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Imd3anJ3ZWpkanBjdGl6b2xma2N6Iiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTc2OTA5ODEyNCwiZXhwIjoyMDg0Njc0MTI0fQ.EjU1DGTN-jrdkaC6nJWilFtYZgtu-NKjnfiMVMnHal0")
 
 
18
 
19
  try:
20
  supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
21
+ print("☁️ Connecté à Supabase")
22
  except Exception as e:
23
+ print(f"❌ Erreur Supabase : {e}")
24
 
25
+ # --- CONFIGURATION SERVEUR (CORS FIXED) ---
26
+ # C'est ici que la magie opère : cors_allowed_origins='*' autorise tout le monde
27
  sio = socketio.AsyncServer(async_mode='asgi', cors_allowed_origins='*')
28
+
29
  app = FastAPI()
30
+ # Middleware pour autoriser les requêtes API REST
31
  app.add_middleware(
32
+ CORSMiddleware,
33
+ allow_origins=["*"],
34
+ allow_credentials=True,
35
+ allow_methods=["*"],
36
+ allow_headers=["*"],
37
  )
38
  socket_app = socketio.ASGIApp(sio, app)
39
 
40
+ # --- API REST ---
41
  @app.get("/api/sessions")
42
  def get_sessions():
43
  response = supabase.table('sessions').select("*").order('id', desc=True).execute()
 
46
  @app.get("/api/sessions/{session_id}")
47
  def get_session_details(session_id: int):
48
  sess = supabase.table('sessions').select("*").eq('id', session_id).execute()
49
+ if not sess.data: raise HTTPException(status_code=404, detail="Session introuvable")
 
50
  meas = supabase.table('measurements').select("*").eq('session_id', session_id).order('session_time', desc=False).execute()
51
  return {"info": sess.data[0], "data": meas.data}
52
 
 
54
  def delete_session(session_id: int):
55
  try:
56
  supabase.table('sessions').delete().eq('id', session_id).execute()
57
+ return {"message": "Supprimé"}
58
  except Exception as e:
59
  raise HTTPException(status_code=500, detail=str(e))
60
 
61
+ # --- LOGIQUE MÉTIER ---
62
  def calculate_kpis(emotion):
63
  valence = 0.0; arousal = 0.0; noise = random.uniform(-0.05, 0.05)
64
  if emotion == "happy": valence = 0.8 + noise; arousal = 0.6 + noise
 
84
  elif val_sat >= 45: lbl_sat = "Neutre 😐"
85
  else: lbl_sat = "Insatisfait 😡"
86
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  return {
88
  "engagement": val_eng, "satisfaction": val_sat, "trust": val_tru, "loyalty": val_loy, "opinion": val_opi,
89
+ "lbl_eng": lbl_eng, "lbl_sat": lbl_sat
90
  }
91
 
92
+ # --- GESTION WEBSOCKET ---
93
  camera_state = { "emotion": "neutral", "emotion_score": 0, "face_coords": None }
94
  active_sessions = {}
95
 
 
96
  @sio.event
97
  async def process_frame(sid, data_uri):
98
  try:
 
100
  nparr = np.frombuffer(base64.b64decode(encoded_data), np.uint8)
101
  frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
102
 
 
103
  result = DeepFace.analyze(frame, actions=['emotion'], enforce_detection=False, silent=True)
104
  data = result[0] if isinstance(result, list) else result
105
 
 
114
  except:
115
  camera_state["face_coords"] = None
116
 
 
117
  async def session_manager_loop():
118
  while True:
119
  for sid, user_data in list(active_sessions.items()):
 
121
 
122
  if user_data["is_recording"]:
123
  user_data["session_time"] += 1
 
 
 
124
  if user_data["db_id"]:
125
  try:
126
  data_to_insert = {
127
  "session_id": user_data["db_id"],
128
+ "session_time": user_data["session_time"],
129
  "emotion": camera_state["emotion"],
130
  "emotion_score": camera_state["emotion_score"],
131
  "engagement_val": kpis["engagement"], "engagement_lbl": kpis["lbl_eng"],
132
  "satisfaction_val": kpis["satisfaction"], "satisfaction_lbl": kpis["lbl_sat"],
133
+ "trust_val": kpis["trust"], "loyalty_val": kpis["loyalty"], "opinion_val": kpis["opinion"]
 
 
134
  }
135
  supabase.table('measurements').insert(data_to_insert).execute()
136
+ except Exception as e: print(f"DB Error: {e}")
137
 
138
  await sio.emit('metrics_update', {
139
  "emotion": camera_state["emotion"], "metrics": kpis,
 
144
  await asyncio.sleep(1)
145
 
146
  @sio.event
147
+ async def connect(sid, environ):
148
+ print(f"Client connecté: {sid}")
149
+ active_sessions[sid] = { "is_recording": False, "session_time": 0, "db_id": None }
150
+
151
  @sio.event
152
  async def disconnect(sid):
153
  if sid in active_sessions: del active_sessions[sid]
154
+
155
  @sio.event
156
  async def start_session(sid, data):
157
  user_session = active_sessions.get(sid)
158
  if user_session:
159
  user_session["is_recording"] = True
160
  user_session["session_time"] = 0
161
+ try:
162
+ new_session = { "first_name": data.get('firstName'), "last_name": data.get('lastName'), "client_id": data.get('clientId') }
163
+ res = supabase.table('sessions').insert(new_session).execute()
164
+ user_session["db_id"] = res.data[0]['id']
165
+ except Exception as e: print(f"Start Session Error: {e}")
 
 
 
166
 
167
  @sio.event
168
  async def stop_session(sid):
169
+ if sid in active_sessions: active_sessions[sid]["is_recording"] = False
 
170
 
171
  if __name__ == "__main__":
172
  @app.on_event("startup")
173
  async def startup_event():
174
  asyncio.create_task(session_manager_loop())
175
+ uvicorn.run(socket_app, host="0.0.0.0", port=7860)