feat: adjustment on the socket session
This commit is contained in:
parent
1db14658e1
commit
76bbbf0824
11
.env.example
11
.env.example
|
@ -1,6 +1,7 @@
|
|||
# Existing Configurations
|
||||
MONGO_URI=
|
||||
FLASK_ENV=
|
||||
DEBUG=
|
||||
FLASK_ENV=development
|
||||
DEBUG=True
|
||||
|
||||
SECRET_KEY=
|
||||
|
||||
|
@ -10,3 +11,9 @@ GOOGLE_CLIENT_SECRET=
|
|||
GOOGLE_AUHT_URI=
|
||||
GOOGLE_TOKEN_URI=
|
||||
GOOGLE_AUTH_PROVIDER_X509_CERT_URL=
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_HOST=localhost
|
||||
REDIS_PORT=6379
|
||||
REDIS_DB=0
|
||||
REDIS_PASSWORD=
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
from dotenv import load_dotenv
|
||||
import os
|
||||
|
||||
# Load variabel dari file .env
|
||||
# Load variables from .env
|
||||
load_dotenv(override=True)
|
||||
|
||||
|
||||
class Config:
|
||||
# Flask Environment Settings
|
||||
FLASK_ENV = os.getenv("FLASK_ENV", "development")
|
||||
DEBUG = os.getenv("DEBUG", "False").lower() in ("true", "1", "t")
|
||||
|
||||
SECRET_KEY = os.getenv("SECRET_KEY", "your_secret_key")
|
||||
|
||||
# MongoDB Settings
|
||||
MONGO_URI = os.getenv("MONGO_URI", "mongodb://localhost:27017/yourdb")
|
||||
|
||||
# Google OAuth Settings
|
||||
GOOGLE_PROJECT_ID = os.getenv("GOOGLE_PROJECT_ID")
|
||||
GOOGLE_CLIENT_ID = os.getenv("GOOGLE_CLIENT_ID")
|
||||
GOOGLE_CLIENT_SECRET = os.getenv("GOOGLE_CLIENT_SECRET")
|
||||
|
@ -22,6 +25,17 @@ class Config:
|
|||
"GOOGLE_TOKEN_URI", "https://oauth2.googleapis.com/token"
|
||||
)
|
||||
GOOGLE_AUTH_PROVIDER_X509_CERT_URL = os.getenv("GOOGLE_AUTH_PROVIDER_X509_CERT_URL")
|
||||
|
||||
GOOGLE_SCOPE = "email profile"
|
||||
GOOGLE_BASE_URL = "https://www.googleapis.com/oauth2/v1/"
|
||||
|
||||
# Redis Configuration
|
||||
REDIS_HOST = os.getenv("REDIS_HOST", "localhost")
|
||||
REDIS_PORT = int(os.getenv("REDIS_PORT", 6379))
|
||||
REDIS_DB = int(os.getenv("REDIS_DB", 0))
|
||||
REDIS_PASSWORD = os.getenv("REDIS_PASSWORD", None)
|
||||
|
||||
@property
|
||||
def REDIS_URL(self):
|
||||
if self.REDIS_PASSWORD:
|
||||
return f"redis://:{self.REDIS_PASSWORD}@{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
|
||||
return f"redis://{self.REDIS_HOST}:{self.REDIS_PORT}/{self.REDIS_DB}"
|
||||
|
|
|
@ -3,14 +3,82 @@ from flask import request
|
|||
from app.services import SessionService
|
||||
import threading
|
||||
import time
|
||||
import json
|
||||
from redis import Redis
|
||||
|
||||
|
||||
class RedisRepository:
|
||||
"""Small helper wrapper to (de)serialize python objects to Redis."""
|
||||
|
||||
def __init__(self, redis: Redis):
|
||||
self.redis = redis
|
||||
|
||||
def set_data(self, key: str, value):
|
||||
self.redis.set(key, json.dumps(value))
|
||||
|
||||
def get_data(self, key: str):
|
||||
data = self.redis.get(key)
|
||||
return json.loads(data) if data else None
|
||||
|
||||
def delete_key(self, key: str):
|
||||
self.redis.delete(key)
|
||||
|
||||
|
||||
class SocketController:
|
||||
def __init__(self, socketio: SocketIO, session_service: SessionService):
|
||||
def __init__(
|
||||
self,
|
||||
socketio: SocketIO,
|
||||
redis: Redis,
|
||||
session_service: SessionService,
|
||||
):
|
||||
self.socketio = socketio
|
||||
self.session_service = session_service
|
||||
self.redis_repo = RedisRepository(redis)
|
||||
# Menyimpan SID admin untuk setiap session \u2192 {session_code: sid}
|
||||
self.admin_sids: dict[str, str] = {}
|
||||
self._register_events()
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Helper utilities
|
||||
# ---------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def _is_correct(user_answer, question: dict) -> bool:
|
||||
"""Bandingkan jawaban user dengan kunci jawaban."""
|
||||
|
||||
print("user answer", user_answer, "question_target", question["target_answer"])
|
||||
if question["type"] == "fill_the_blank":
|
||||
return (
|
||||
str(user_answer).strip().lower()
|
||||
== str(question["target_answer"]).strip().lower()
|
||||
)
|
||||
elif question["type"] == "true_false":
|
||||
return bool(user_answer) == question["target_answer"]
|
||||
elif question["type"] == "option":
|
||||
# user_answer bisa dikirim sebagai index atau value teks option.
|
||||
# Pastikan di‑cast ke int terlebih dahulu jika memungkinkan.
|
||||
try:
|
||||
return int(user_answer) == question["target_answer"]
|
||||
except ValueError:
|
||||
return (
|
||||
str(user_answer).strip().lower()
|
||||
== str(question["options"][question["target_answer"]])
|
||||
.strip()
|
||||
.lower()
|
||||
)
|
||||
return False
|
||||
|
||||
def _questions_key(self, session_code: str) -> str:
|
||||
return f"session:{session_code}:questions"
|
||||
|
||||
def _answers_key(self, session_code: str) -> str:
|
||||
return f"session:{session_code}:answers"
|
||||
|
||||
def _scores_key(self, session_code: str) -> str:
|
||||
return f"session:{session_code}:scores"
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Socket.IO event bindings
|
||||
# ---------------------------------------------------------------------
|
||||
def _register_events(self):
|
||||
@self.socketio.on("connect")
|
||||
def on_connect():
|
||||
|
@ -23,8 +91,8 @@ class SocketController:
|
|||
|
||||
@self.socketio.on("join_room")
|
||||
def handle_join_room(data):
|
||||
session_code = data["session_code"]
|
||||
user_id = data["user_id"]
|
||||
session_code = data.get("session_code")
|
||||
user_id = data.get("user_id")
|
||||
|
||||
if not session_code or not user_id:
|
||||
emit("error", {"message": "session_code and user_id are required"})
|
||||
|
@ -33,43 +101,47 @@ class SocketController:
|
|||
session = self.session_service.join_session(
|
||||
session_code=session_code, user_id=user_id
|
||||
)
|
||||
|
||||
if session is None:
|
||||
emit("error", {"message": "Failed to join session or session inactive"})
|
||||
return
|
||||
|
||||
join_room(session_code)
|
||||
if session["is_admin"] == True:
|
||||
emit(
|
||||
"room_message",
|
||||
{
|
||||
"message": f"admin has joined the room.",
|
||||
"room": session_code,
|
||||
"argument": "adm_update",
|
||||
},
|
||||
room=session_code,
|
||||
)
|
||||
return
|
||||
|
||||
# Kalau user ini admin, simpan SID‑nya.
|
||||
if session["is_admin"]:
|
||||
self.admin_sids[session_code] = request.sid
|
||||
message = "Admin has joined the room."
|
||||
else:
|
||||
message = f"User {session['username']} has joined the room."
|
||||
|
||||
print(message)
|
||||
emit(
|
||||
"room_message",
|
||||
{
|
||||
"message": f"user {session['username']} has joined the room.",
|
||||
"type": "join",
|
||||
"message": message,
|
||||
"room": session_code,
|
||||
"argument": "adm_update",
|
||||
"data": session,
|
||||
"data": session if not session["is_admin"] else None,
|
||||
},
|
||||
room=session_code,
|
||||
)
|
||||
|
||||
@self.socketio.on("submit_answer")
|
||||
def handle_submit_answer(data):
|
||||
session_id = data.get("session_id")
|
||||
session_code = data.get("session_id") # front‑end masih mengirim session_id
|
||||
user_id = data.get("user_id")
|
||||
question_index = data.get("question_index")
|
||||
answer = data.get("answer")
|
||||
user_answer = data.get("answer")
|
||||
|
||||
if not all([session_id, user_id, question_index is not None, answer]):
|
||||
if not all(
|
||||
[
|
||||
session_code,
|
||||
user_id,
|
||||
question_index is not None,
|
||||
user_answer is not None,
|
||||
]
|
||||
):
|
||||
emit(
|
||||
"error",
|
||||
{
|
||||
|
@ -78,62 +150,130 @@ class SocketController:
|
|||
)
|
||||
return
|
||||
|
||||
print(f"User {user_id} answered question {question_index} with {answer}")
|
||||
# ----- 1. Ambil list pertanyaan untuk mendapatkan kunci jawaban ----------
|
||||
questions = (
|
||||
self.redis_repo.get_data(self._questions_key(session_code)) or []
|
||||
)
|
||||
question = next(
|
||||
(q for q in questions if q["index"] == question_index), None
|
||||
)
|
||||
if question is None:
|
||||
emit("error", {"message": "Question not found"})
|
||||
return
|
||||
|
||||
# TODO: kamu bisa menyimpan jawaban ke database di sini
|
||||
# self.answer_service.save_answer(session_id, user_id, question_index, answer)
|
||||
is_correct = self._is_correct(user_answer, question)
|
||||
|
||||
# Kirim notifikasi ke admin (host) atau semua peserta kalau perlu
|
||||
print(
|
||||
f"User {user_id} answered Q{question_index} with '{user_answer}' -> {'✔' if is_correct else '✖'}"
|
||||
)
|
||||
|
||||
# ----- 2. Simpan jawaban ke Redis --------------------------------------
|
||||
answers = self.redis_repo.get_data(self._answers_key(session_code)) or []
|
||||
answers.append(
|
||||
{
|
||||
"user_id": user_id,
|
||||
"question_index": question_index,
|
||||
"answer": user_answer,
|
||||
"correct": is_correct,
|
||||
}
|
||||
)
|
||||
self.redis_repo.set_data(self._answers_key(session_code), answers)
|
||||
|
||||
# ----- 3. Update skor per‑user -----------------------------------------
|
||||
scores = self.redis_repo.get_data(self._scores_key(session_code)) or {}
|
||||
user_score = scores.get(str(user_id), {"correct": 0, "incorrect": 0})
|
||||
if is_correct:
|
||||
user_score["correct"] += 1
|
||||
else:
|
||||
user_score["incorrect"] += 1
|
||||
scores[str(user_id)] = user_score
|
||||
self.redis_repo.set_data(self._scores_key(session_code), scores)
|
||||
|
||||
# ----- 4. Beri tahu user (ack) -----------------------------------------
|
||||
emit(
|
||||
"answer_submitted",
|
||||
{
|
||||
"user_id": user_id,
|
||||
"question_index": question_index,
|
||||
"answer": answer,
|
||||
"answer": user_answer,
|
||||
"correct": is_correct,
|
||||
},
|
||||
room=session_id,
|
||||
room=request.sid,
|
||||
)
|
||||
|
||||
# ----- 5. Kirim update skor hanya ke admin -----------------------------
|
||||
admin_sid = self.admin_sids.get(session_code)
|
||||
if admin_sid:
|
||||
emit("score_update", scores, room=admin_sid)
|
||||
|
||||
@self.socketio.on("leave_room")
|
||||
def handle_leave_room(data):
|
||||
session_id = data.get("session_id")
|
||||
session_code = data.get("session_id")
|
||||
user_id = data.get("user_id")
|
||||
username = data.get("username", "anonymous")
|
||||
|
||||
leave_room(session_id)
|
||||
leave_room(session_code)
|
||||
emit(
|
||||
"room_message",
|
||||
{"message": f"{username} has left the room.", "room": session_id},
|
||||
room=session_id,
|
||||
{
|
||||
"type": "leave",
|
||||
"message": f"{username} has left the room.",
|
||||
"room": session_code,
|
||||
"data": user_id,
|
||||
},
|
||||
room=session_code,
|
||||
)
|
||||
|
||||
@self.socketio.on("send_message")
|
||||
def on_send_message(data):
|
||||
session_id = data.get("session_id")
|
||||
session_code = data.get("session_id")
|
||||
message = data.get("message")
|
||||
username = data.get("username", "anonymous")
|
||||
|
||||
emit(
|
||||
"receive_message",
|
||||
{"message": message, "from": username},
|
||||
room=session_id,
|
||||
room=session_code,
|
||||
)
|
||||
|
||||
@self.socketio.on("end_session")
|
||||
def handle_end_session(data):
|
||||
session_id = data.get("session_id")
|
||||
session_code = data.get("session_id")
|
||||
user_id = data.get("user_id")
|
||||
|
||||
if not session_id or not user_id:
|
||||
if not session_code or not user_id:
|
||||
emit("error", {"message": "session_id and user_id required"})
|
||||
return
|
||||
|
||||
self.session_service.end_session(session_id=session_id, user_id=user_id)
|
||||
# Validasi user berhak mengakhiri session
|
||||
self.session_service.end_session(session_id=session_code, user_id=user_id)
|
||||
|
||||
answers = self.redis_repo.get_data(self._answers_key(session_code)) or []
|
||||
scores = self.redis_repo.get_data(self._scores_key(session_code)) or {}
|
||||
|
||||
print("\n📦 Final Quiz Data for Session", session_code)
|
||||
print("------------------------------------------------------------")
|
||||
for entry in answers:
|
||||
status = "✔" if entry["correct"] else "✖"
|
||||
print(
|
||||
f"User {entry['user_id']} - Q{entry['question_index']}: {entry['answer']} {status}"
|
||||
)
|
||||
|
||||
print("\n🏁 Rekap Skor:")
|
||||
for uid, sc in scores.items():
|
||||
print(f"User {uid}: Benar {sc['correct']} | Salah {sc['incorrect']}")
|
||||
|
||||
# Bersihkan semua data session di Redis
|
||||
for key in [
|
||||
self._answers_key(session_code),
|
||||
self._scores_key(session_code),
|
||||
self._questions_key(session_code),
|
||||
]:
|
||||
self.redis_repo.delete_key(key)
|
||||
|
||||
emit(
|
||||
"room_closed",
|
||||
{"message": "Session has ended.", "room": session_id},
|
||||
room=session_id,
|
||||
{"message": "Session has ended.", "room": session_code},
|
||||
room=session_code,
|
||||
)
|
||||
|
||||
@self.socketio.on("start_quiz")
|
||||
|
@ -144,54 +284,120 @@ class SocketController:
|
|||
return
|
||||
|
||||
emit("quiz_started", {"message": "Quiz has started!"}, room=session_code)
|
||||
|
||||
# Jalankan thread untuk mengirim soal simulasi setiap 5 detik
|
||||
threading.Thread(
|
||||
target=self._simulate_quiz_flow, args=(session_code,)
|
||||
target=self._simulate_quiz_flow, args=(session_code,), daemon=True
|
||||
).start()
|
||||
|
||||
def _simulate_quiz_flow(self, session_code):
|
||||
# ---------------------------------------------------------------------
|
||||
# Quiz flow simulation -------------------------------------------------
|
||||
# ---------------------------------------------------------------------
|
||||
def _simulate_quiz_flow(self, session_code: str):
|
||||
"""Mengirim list pertanyaan satu per satu secara otomatis (demo)."""
|
||||
questions = [
|
||||
{
|
||||
"question_index": 0,
|
||||
"question": "Apa ibu kota Indonesia?",
|
||||
"type": "option",
|
||||
"options": ["Jakarta", "Bandung", "Surabaya"],
|
||||
"index": 1,
|
||||
"question": "Kerajaan Hindu tertua di Indonesia adalah?",
|
||||
"target_answer": "Kutai",
|
||||
"duration": 30,
|
||||
"type": "fill_the_blank",
|
||||
"options": None,
|
||||
},
|
||||
{
|
||||
"question_index": 1,
|
||||
"question": "2 + 2 = ?",
|
||||
"type": "option",
|
||||
"options": ["3", "4", "5"],
|
||||
},
|
||||
{
|
||||
"question_index": 2,
|
||||
"question": "Siapa presiden pertama Indonesia?",
|
||||
"type": "option",
|
||||
"options": ["Sukarno", "Soeharto", "Jokowi"],
|
||||
},
|
||||
{
|
||||
"question_index": 3,
|
||||
"question": "Tuliskan nama lengkap presiden pertama Indonesia.",
|
||||
"type": "fill_in_the_blank",
|
||||
"options": [],
|
||||
},
|
||||
{
|
||||
"question_index": 4,
|
||||
"question": "Indonesia merdeka pada tahun 1945.",
|
||||
"index": 2,
|
||||
"question": "Apakah benar Majapahit mencapai puncak kejayaan pada masa Hayam Wuruk?",
|
||||
"target_answer": True,
|
||||
"duration": 30,
|
||||
"type": "true_false",
|
||||
"options": [],
|
||||
"options": None,
|
||||
},
|
||||
{
|
||||
"index": 3,
|
||||
"question": "Kerajaan maritim terbesar di Asia Tenggara pada abad ke‑7 adalah?",
|
||||
"target_answer": 2,
|
||||
"duration": 30,
|
||||
"type": "option",
|
||||
"options": ["Majapahit", "Tarumanegara", "Sriwijaya", "Mataram Kuno"],
|
||||
},
|
||||
{
|
||||
"index": 4,
|
||||
"question": "Prasasti Yupa merupakan peninggalan dari kerajaan?",
|
||||
"target_answer": "Kutai",
|
||||
"duration": 30,
|
||||
"type": "fill_the_blank",
|
||||
"options": None,
|
||||
},
|
||||
{
|
||||
"index": 5,
|
||||
"question": "Apakah Tarumanegara terletak di wilayah Kalimantan Timur?",
|
||||
"target_answer": False,
|
||||
"duration": 30,
|
||||
"type": "true_false",
|
||||
"options": None,
|
||||
},
|
||||
{
|
||||
"index": 6,
|
||||
"question": "Kitab Negarakertagama ditulis oleh?",
|
||||
"target_answer": 0,
|
||||
"duration": 30,
|
||||
"type": "option",
|
||||
"options": [
|
||||
"Empu Tantular",
|
||||
"Empu Prapanca",
|
||||
"Hayam Wuruk",
|
||||
"Gajah Mada",
|
||||
],
|
||||
},
|
||||
{
|
||||
"index": 7,
|
||||
"question": "Tokoh yang terkenal dengan Sumpah Palapa adalah?",
|
||||
"target_answer": "Gajah Mada",
|
||||
"duration": 30,
|
||||
"type": "fill_the_blank",
|
||||
"options": None,
|
||||
},
|
||||
{
|
||||
"index": 8,
|
||||
"question": "Candi Borobudur dibangun oleh kerajaan Hindu?",
|
||||
"target_answer": False,
|
||||
"duration": 30,
|
||||
"type": "true_false",
|
||||
"options": None,
|
||||
},
|
||||
{
|
||||
"index": 9,
|
||||
"question": "Raja terkenal dari Kerajaan Sriwijaya adalah?",
|
||||
"target_answer": 1,
|
||||
"duration": 30,
|
||||
"type": "option",
|
||||
"options": [
|
||||
"Dapunta Hyang",
|
||||
"Balaputradewa",
|
||||
"Airlangga",
|
||||
"Hayam Wuruk",
|
||||
],
|
||||
},
|
||||
{
|
||||
"index": 10,
|
||||
"question": "Candi Prambanan merupakan peninggalan agama?",
|
||||
"target_answer": "Hindu",
|
||||
"duration": 30,
|
||||
"type": "fill_the_blank",
|
||||
"options": None,
|
||||
},
|
||||
]
|
||||
|
||||
for q in questions:
|
||||
print(f"Sending question {q['question_index']} to {session_code}")
|
||||
self.socketio.emit("quiz_question", q, room=session_code)
|
||||
time.sleep(20)
|
||||
# send true ansewr
|
||||
time.sleep(5)
|
||||
# Simpan ke Redis agar bisa dipakai saat evaluasi jawaban
|
||||
self.redis_repo.set_data(self._questions_key(session_code), questions)
|
||||
|
||||
# Beri sedikit jeda sebelum pertanyaan pertama
|
||||
time.sleep(2)
|
||||
|
||||
for q in questions:
|
||||
print(f"\n📢 Mengirim pertanyaan {q['index']} ke room {session_code}")
|
||||
q.pop("target_answer")
|
||||
self.socketio.emit("quiz_question", q, room=session_code)
|
||||
time.sleep(q["duration"])
|
||||
|
||||
# Setelah selesai semua soal, kirim command bahwa quiz selesai
|
||||
self.socketio.emit(
|
||||
"quiz_done", {"message": "Quiz has ended!"}, room=session_code
|
||||
)
|
||||
|
|
|
@ -32,7 +32,7 @@ class Container(containers.DeclarativeContainer):
|
|||
"""Dependency Injection Container"""
|
||||
|
||||
mongo = providers.Dependency()
|
||||
|
||||
redis = providers.Dependency()
|
||||
socketio = providers.Dependency()
|
||||
|
||||
# repository
|
||||
|
@ -89,5 +89,10 @@ class Container(containers.DeclarativeContainer):
|
|||
quiz_controller = providers.Factory(QuizController, quiz_service, answer_service)
|
||||
history_controller = providers.Factory(HistoryController, history_service)
|
||||
subject_controller = providers.Factory(SubjectController, subject_service)
|
||||
socket_controller = providers.Factory(SocketController, socketio, session_service)
|
||||
socket_controller = providers.Factory(
|
||||
SocketController,
|
||||
socketio,
|
||||
redis,
|
||||
session_service,
|
||||
)
|
||||
session_controller = providers.Factory(SessionController, session_service)
|
||||
|
|
27
app/main.py
27
app/main.py
|
@ -1,17 +1,11 @@
|
|||
# main.py
|
||||
|
||||
import eventlet
|
||||
|
||||
eventlet.monkey_patch()
|
||||
|
||||
import sys
|
||||
import os
|
||||
import logging
|
||||
from flask import Flask
|
||||
from flask_socketio import SocketIO
|
||||
|
||||
# sys.path.append(os.path.dirname(__file__))
|
||||
|
||||
from app.di_container import Container
|
||||
from app.configs import Config, LoggerConfig
|
||||
from app.blueprints import (
|
||||
|
@ -24,12 +18,10 @@ from app.blueprints import (
|
|||
session_bp,
|
||||
)
|
||||
from app.database import init_db
|
||||
from redis import Redis
|
||||
|
||||
|
||||
socketio = SocketIO(cors_allowed_origins="*")
|
||||
|
||||
|
||||
def createApp() -> Flask:
|
||||
def createApp() -> tuple[Flask, SocketIO]:
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(Config)
|
||||
LoggerConfig.init_logger(app)
|
||||
|
@ -44,8 +36,19 @@ def createApp() -> Flask:
|
|||
mongo = init_db(app)
|
||||
if mongo is not None:
|
||||
container.mongo.override(mongo)
|
||||
container.socketio.override(socketio)
|
||||
|
||||
redis_url = Config().REDIS_URL
|
||||
redis_client = Redis.from_url(redis_url)
|
||||
redis_client.ping()
|
||||
container.redis.override(redis_client)
|
||||
|
||||
socketio = SocketIO(
|
||||
cors_allowed_origins="*",
|
||||
# message_queue=redis_url,
|
||||
async_mode="eventlet",
|
||||
)
|
||||
|
||||
container.socketio.override(socketio)
|
||||
container.socket_controller()
|
||||
|
||||
socketio.init_app(app)
|
||||
|
@ -69,4 +72,4 @@ def createApp() -> Flask:
|
|||
app.register_blueprint(subject_blueprint, url_prefix="/api/subject")
|
||||
app.register_blueprint(session_bp, url_prefix="/api/session")
|
||||
|
||||
return app
|
||||
return app, socketio
|
||||
|
|
|
@ -42,8 +42,9 @@ class UserMapper:
|
|||
|
||||
@staticmethod
|
||||
def user_entity_to_response(user: UserEntity) -> UserResponseModel:
|
||||
print(str(user.id))
|
||||
return UserResponseModel(
|
||||
id=str(user.id) if user.id else None,
|
||||
_id=str(user.id) if user.id else None,
|
||||
google_id=user.google_id,
|
||||
email=user.email,
|
||||
name=user.name,
|
||||
|
|
|
@ -71,7 +71,7 @@ class SessionService:
|
|||
return self.repository.update(session_id, {"started_at": now})
|
||||
|
||||
def end_session(self, session_id: str, user_id: str):
|
||||
session = self.repository.find_by_id(session_id)
|
||||
session = self.repository.find_by_session_id(session_id)
|
||||
if session and session.host_id == user_id:
|
||||
session.is_active = False
|
||||
self.repository.update(session_id, {"is_active": False})
|
||||
|
|
|
@ -12,6 +12,7 @@ cryptography==44.0.2
|
|||
dependency-injector==4.46.0
|
||||
dnspython==2.7.0
|
||||
email_validator==2.2.0
|
||||
eventlet==0.39.1
|
||||
exceptiongroup==1.2.2
|
||||
Flask==3.0.3
|
||||
Flask-Bcrypt==1.0.1
|
||||
|
@ -23,6 +24,8 @@ flask-swagger-ui==4.11.1
|
|||
google-auth==2.38.0
|
||||
google-auth-httplib2==0.2.0
|
||||
google-auth-oauthlib==1.2.1
|
||||
greenlet==3.2.1
|
||||
gunicorn==23.0.0
|
||||
h11==0.14.0
|
||||
httplib2==0.22.0
|
||||
idna==3.10
|
||||
|
|
Loading…
Reference in New Issue