refactored calls and endpoints to better handle mobile app

This commit is contained in:
Mercurio 2024-12-21 22:35:00 +01:00
parent 3e6ddd9d54
commit 1efada3146
2 changed files with 91 additions and 182 deletions

135
calls.py
View file

@ -5,6 +5,8 @@ import secrets
import time import time
import json import json
# USER MANAGEMENT FUNCTIONS
def register_user(email, display_name, password): def register_user(email, display_name, password):
hashed_password = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode() hashed_password = bcrypt.hashpw(password.encode(), bcrypt.gensalt()).decode()
conn = get_db_connection() conn = get_db_connection()
@ -45,24 +47,6 @@ def authenticate_user(email, password):
conn.close() conn.close()
def reauth_user(token):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute("SELECT email, display_name, current_elo, session_token FROM users WHERE session_token = %s;", (token,))
user = cursor.fetchone()
if user:
user_data = {
"email": user["email"],
"display_name": user["display_name"],
"elo": user["current_elo"]
}
return user_data
return None
finally:
cursor.close()
conn.close()
def add_friend(token, friend_uid): def add_friend(token, friend_uid):
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
@ -98,6 +82,8 @@ def add_friend(token, friend_uid):
conn.close() conn.close()
# MATCHMAKING ENDPOINTS
def get_leaderboard(): def get_leaderboard():
conn = get_db_connection() conn = get_db_connection()
cursor = conn.cursor() cursor = conn.cursor()
@ -109,116 +95,6 @@ def get_leaderboard():
finally: finally:
cursor.close() cursor.close()
conn.close() conn.close()
def send_match_invite(sender_uid, receiver_uid):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute(
"INSERT INTO matches (player1_uid, player2_uid) VALUES (%s, %s) RETURNING match_id;",
(sender_uid, receiver_uid)
)
match_id = cursor.fetchone()["match_id"]
conn.commit()
return match_id
except Exception as e:
conn.rollback()
raise e
finally:
cursor.close()
conn.close()
def accept_match_invite(match_id, player2_uid):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute(
"UPDATE matches SET match_date = CURRENT_TIMESTAMP WHERE match_id = %s AND player2_uid = %s;",
(match_id, player2_uid)
)
conn.commit()
return True
except Exception as e:
conn.rollback()
raise e
finally:
cursor.close()
conn.close()
def get_all_matches():
conn = get_db_connection()
cursor = conn.cursor()
try:
query = """
SELECT
m.match_id,
u1.display_name AS player1_name,
u2.display_name AS player2_name,
m.player1_score,
m.player2_score,
CASE
WHEN m.player1_score IS NULL AND m.player2_score IS NULL THEN 'upcoming'
WHEN m.player1_score IS NOT NULL AND m.player2_score IS NOT NULL THEN 'completed'
ELSE 'ongoing'
END AS status,
m.match_date
FROM matches m
LEFT JOIN users u1 ON m.player1_uid = u1.uid
LEFT JOIN users u2 ON m.player2_uid = u2.uid
ORDER BY
CASE
WHEN m.player1_score IS NULL AND m.player2_score IS NULL THEN 2 -- Upcoming
WHEN m.player1_score IS NOT NULL AND m.player2_score IS NOT NULL THEN 3 -- Completed
ELSE 1 -- Ongoing
END,
m.match_date;
"""
cursor.execute(query)
matches = cursor.fetchall()
return matches
finally:
cursor.close()
conn.close()
def get_elo(auth_header):
if not auth_header.startswith('Basic '):
raise ValueError("Invalid Authorization header")
encoded_credentials = auth_header.split(' ', 1)[1]
decoded_credentials = base64.b64decode(encoded_credentials).decode()
try:
email, password = decoded_credentials.split(':', 1)
except ValueError:
raise ValueError("Invalid credentials format")
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute("SELECT email, display_name, password_hash, elo FROM users WHERE email = %s;", (email,))
user = cursor.fetchone()
if not user:
raise ValueError("User not found")
if not bcrypt.checkpw(password.encode(), user["password_hash"].encode()):
raise ValueError("Invalid password")
return {
"email": user["email"],
"elo": user["elo"],
"display_name": user["display_name"]
}
except Exception as e:
raise e
finally:
cursor.close()
conn.close()
def update_elo(player1_display_name, player2_display_name, player1_score, player2_score, winner): def update_elo(player1_display_name, player2_display_name, player1_score, player2_score, winner):
conn = get_db_connection() conn = get_db_connection()
@ -233,7 +109,6 @@ def update_elo(player1_display_name, player2_display_name, player1_score, player
""", (player1_display_name, player2_display_name)) """, (player1_display_name, player2_display_name))
players = cursor.fetchall() players = cursor.fetchall()
if len(players) != 2: if len(players) != 2:
return {"error": "Both players must exist in the database."} return {"error": "Both players must exist in the database."}
@ -241,6 +116,7 @@ def update_elo(player1_display_name, player2_display_name, player1_score, player
player2_elo = players[1]["current_elo"] player2_elo = players[1]["current_elo"]
expected_player1 = 1 / (1 + 10 ** ((player2_elo - player1_elo) / 400)) expected_player1 = 1 / (1 + 10 ** ((player2_elo - player1_elo) / 400))
expected_player2 = 1 / (1 + 10 ** ((player1_elo - player2_elo) / 400)) expected_player2 = 1 / (1 + 10 ** ((player1_elo - player2_elo) / 400))
if winner == player1_display_name: if winner == player1_display_name:
actual_player1 = 1 actual_player1 = 1
@ -279,4 +155,3 @@ def update_elo(player1_display_name, player2_display_name, player1_score, player
finally: finally:
cursor.close() cursor.close()
conn.close() conn.close()

138
main.py
View file

@ -21,24 +21,21 @@ class LoginRequest(BaseModel):
email: str email: str
password: str password: str
class ReloginRequest(BaseModel):
token: str
class FriendRequest(BaseModel): class FriendRequest(BaseModel):
token: str token: str
friend_uid: int friend_uid: int
class MatchInviteRequest(BaseModel):
sender_uid: int
receiver_uid: int
class AcceptInviteRequest(BaseModel):
match_id: int
player2_uid: int
class getFriendList(BaseModel): class getFriendList(BaseModel):
token: str token: str
class CreateMatchRequest(BaseModel):
token: str
class JoinMatchRequest(BaseModel):
token: str
match_id: int
@app.post("/register") @app.post("/register")
def register(request: RegisterRequest): def register(request: RegisterRequest):
try: try:
@ -55,14 +52,7 @@ def login(request: LoginRequest):
else: else:
raise HTTPException(status_code=401, detail="Invalid credentials") raise HTTPException(status_code=401, detail="Invalid credentials")
@app.post("/auth")
def login(request: ReloginRequest):
sessiontoken = reauth_user(request.token)
if sessiontoken:
return {"message": "Login successful", "uid": sessiontoken}
else:
raise HTTPException(status_code=503, detail="Bad Token")
@app.post("/add_friend") @app.post("/add_friend")
def add_friend_endpoint(request: FriendRequest): def add_friend_endpoint(request: FriendRequest):
try: try:
@ -70,30 +60,6 @@ def add_friend_endpoint(request: FriendRequest):
return {"message": "Friend added successfully"} if success else HTTPException(400, "Failed to add friend") return {"message": "Friend added successfully"} if success else HTTPException(400, "Failed to add friend")
except Exception as e: except Exception as e:
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e))
@app.post("/send_match_invite")
def send_invite(request: MatchInviteRequest):
try:
match_id = send_match_invite(request.sender_uid, request.receiver_uid)
return {"message": "Match invite sent successfully", "match_id": match_id}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.post("/accept_match_invite")
def accept_invite(request: AcceptInviteRequest):
try:
success = accept_match_invite(request.match_id, request.player2_uid)
return {"message": "Match invite accepted"} if success else HTTPException(400, "Failed to accept invite")
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.get("/matches")
def get_matches():
try:
matches = get_all_matches()
return {"matches": matches}
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
@app.get("/leaderboards") @app.get("/leaderboards")
def leaderboard(): def leaderboard():
@ -102,15 +68,8 @@ def leaderboard():
return leaderboard return leaderboard
except Exception as e: except Exception as e:
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e))
@app.post("/elo")
def get_elo_endpoint(authorization: str):
print(f"Received Authorization header: {authorization}")
try:
result = get_elo(authorization)
return result
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
def get_friend_details(friend_uid): def get_friend_details(friend_uid):
conn = get_db_connection() conn = get_db_connection()
@ -124,6 +83,20 @@ def get_friend_details(friend_uid):
finally: finally:
cursor.close() cursor.close()
conn.close() conn.close()
def get_uid_by_token(token):
conn = get_db_connection()
cursor = conn.cursor()
try:
cursor.execute("SELECT uid FROM users WHERE session_token = %s;", (token,))
result = cursor.fetchone()
if not result:
raise ValueError("Invalid token")
return result["uid"]
finally:
cursor.close()
conn.close()
@app.post("/get_friends") @app.post("/get_friends")
def get_friends_list(request: getFriendList): def get_friends_list(request: getFriendList):
@ -149,4 +122,65 @@ def get_friends_list(request: getFriendList):
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e))
finally: finally:
cursor.close() cursor.close()
conn.close() conn.close()
@app.post("/creatematch")
def create_match(request: CreateMatchRequest):
conn = get_db_connection()
cursor = conn.cursor()
try:
player1_uid = get_uid_by_token(request.token)
cursor.execute(
"""
INSERT INTO matches (player1_uid)
VALUES (%s)
RETURNING match_id;
""",
(player1_uid,)
)
match_id = cursor.fetchone()["match_id"]
conn.commit()
return {"match_id": match_id}
except Exception as e:
conn.rollback()
raise HTTPException(status_code=400, detail=str(e))
finally:
cursor.close()
conn.close()
@app.post("/joinmatch")
def join_match(request: JoinMatchRequest):
conn = get_db_connection()
cursor = conn.cursor()
try:
player2_uid = get_uid_by_token(request.token)
cursor.execute(
"""
SELECT player1_uid, player2_uid
FROM matches
WHERE match_id = %s;
""",
(request.match_id,)
)
match = cursor.fetchone()
if not match:
raise HTTPException(status_code=404, detail="Match not found")
if match["player2_uid"] is not None:
raise HTTPException(status_code=400, detail="Match is already full")
cursor.execute(
"""
UPDATE matches
SET player2_uid = %s
WHERE match_id = %s;
""",
(player2_uid, request.match_id)
)
conn.commit()
return {"message": "Joined match successfully", "match_id": request.match_id}
except Exception as e:
conn.rollback()
raise HTTPException(status_code=400, detail=str(e))
finally:
cursor.close()
conn.close()