refactored calls and endpoints to better handle mobile app
This commit is contained in:
parent
3e6ddd9d54
commit
1efada3146
135
calls.py
135
calls.py
|
@ -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()
|
||||||
|
@ -110,116 +96,6 @@ def get_leaderboard():
|
||||||
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()
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
@ -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."}
|
||||||
|
|
||||||
|
@ -242,6 +117,7 @@ def update_elo(player1_display_name, player2_display_name, player1_score, player
|
||||||
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
|
||||||
actual_player2 = 0
|
actual_player2 = 0
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
|
132
main.py
132
main.py
|
@ -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,13 +52,6 @@ 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):
|
||||||
|
@ -71,30 +61,6 @@ def add_friend_endpoint(request: FriendRequest):
|
||||||
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():
|
||||||
try:
|
try:
|
||||||
|
@ -103,14 +69,7 @@ def 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()
|
||||||
|
@ -125,6 +84,20 @@ def get_friend_details(friend_uid):
|
||||||
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):
|
||||||
token = request.token
|
token = request.token
|
||||||
|
@ -150,3 +123,64 @@ def get_friends_list(request: getFriendList):
|
||||||
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()
|
||||||
|
|
Loading…
Reference in a new issue