a
This commit is contained in:
@@ -315,7 +315,7 @@ async def spin_wheel(marathon_id: int, current_user: CurrentUser, db: DbSession)
|
||||
estimated_time=ch.estimated_time,
|
||||
proof_type=ch.proof_type,
|
||||
proof_hint=ch.proof_hint,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_generated=ch.is_generated,
|
||||
created_at=ch.created_at,
|
||||
)
|
||||
@@ -339,7 +339,7 @@ async def spin_wheel(marathon_id: int, current_user: CurrentUser, db: DbSession)
|
||||
estimated_time=challenge.estimated_time,
|
||||
proof_type=challenge.proof_type,
|
||||
proof_hint=challenge.proof_hint,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_generated=challenge.is_generated,
|
||||
created_at=challenge.created_at,
|
||||
),
|
||||
@@ -392,7 +392,7 @@ async def get_current_assignment(marathon_id: int, current_user: CurrentUser, db
|
||||
estimated_time=ba.challenge.estimated_time,
|
||||
proof_type=ba.challenge.proof_type,
|
||||
proof_hint=ba.challenge.proof_hint,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_generated=ba.challenge.is_generated,
|
||||
created_at=ba.challenge.created_at,
|
||||
),
|
||||
@@ -406,7 +406,7 @@ async def get_current_assignment(marathon_id: int, current_user: CurrentUser, db
|
||||
return AssignmentResponse(
|
||||
id=assignment.id,
|
||||
challenge=None,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_playthrough=True,
|
||||
playthrough_info=PlaythroughInfo(
|
||||
description=game.playthrough_description,
|
||||
@@ -445,7 +445,7 @@ async def get_current_assignment(marathon_id: int, current_user: CurrentUser, db
|
||||
estimated_time=challenge.estimated_time,
|
||||
proof_type=challenge.proof_type,
|
||||
proof_hint=challenge.proof_hint,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_generated=challenge.is_generated,
|
||||
created_at=challenge.created_at,
|
||||
),
|
||||
@@ -467,7 +467,8 @@ async def complete_assignment(
|
||||
db: DbSession,
|
||||
proof_url: str | None = Form(None),
|
||||
comment: str | None = Form(None),
|
||||
proof_file: UploadFile | None = File(None),
|
||||
proof_file: UploadFile | None = File(None), # Legacy single file support
|
||||
proof_files: list[UploadFile] = File([]), # Multiple files support
|
||||
):
|
||||
"""Complete a regular assignment with proof (not event assignments)"""
|
||||
# Get assignment with all needed relationships
|
||||
@@ -497,42 +498,68 @@ async def complete_assignment(
|
||||
if assignment.is_event_assignment:
|
||||
raise HTTPException(status_code=400, detail="Use /event-assignments/{id}/complete for event assignments")
|
||||
|
||||
# For playthrough: need either file or URL or comment (proof is flexible)
|
||||
# For challenges: need either file or URL
|
||||
# Combine legacy single file with new multiple files
|
||||
all_files = []
|
||||
if proof_file:
|
||||
all_files.append(proof_file)
|
||||
if proof_files:
|
||||
all_files.extend(proof_files)
|
||||
|
||||
# For playthrough: need either file(s) or URL or comment (proof is flexible)
|
||||
# For challenges: need either file(s) or URL
|
||||
if assignment.is_playthrough:
|
||||
if not proof_file and not proof_url and not comment:
|
||||
if not all_files and not proof_url and not comment:
|
||||
raise HTTPException(status_code=400, detail="Proof is required (file, URL, or comment)")
|
||||
else:
|
||||
if not proof_file and not proof_url:
|
||||
if not all_files and not proof_url:
|
||||
raise HTTPException(status_code=400, detail="Proof is required (file or URL)")
|
||||
|
||||
# Handle file upload
|
||||
if proof_file:
|
||||
contents = await proof_file.read()
|
||||
if len(contents) > settings.MAX_UPLOAD_SIZE:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"File too large. Maximum size is {settings.MAX_UPLOAD_SIZE // 1024 // 1024} MB",
|
||||
# Handle multiple file uploads
|
||||
if all_files:
|
||||
from app.models import AssignmentProof
|
||||
|
||||
for idx, file in enumerate(all_files):
|
||||
contents = await file.read()
|
||||
if len(contents) > settings.MAX_UPLOAD_SIZE:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"File {file.filename} too large. Maximum size is {settings.MAX_UPLOAD_SIZE // 1024 // 1024} MB",
|
||||
)
|
||||
|
||||
ext = file.filename.split(".")[-1].lower() if file.filename else "jpg"
|
||||
if ext not in settings.ALLOWED_EXTENSIONS:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Invalid file type for {file.filename}. Allowed: {settings.ALLOWED_EXTENSIONS}",
|
||||
)
|
||||
|
||||
# Determine file type (image or video)
|
||||
file_type = "video" if ext in ["mp4", "webm", "mov", "avi"] else "image"
|
||||
|
||||
# Upload file to storage
|
||||
filename = storage_service.generate_filename(f"{assignment_id}_{idx}", file.filename)
|
||||
file_path = await storage_service.upload_file(
|
||||
content=contents,
|
||||
folder="proofs",
|
||||
filename=filename,
|
||||
content_type=file.content_type or "application/octet-stream",
|
||||
)
|
||||
|
||||
ext = proof_file.filename.split(".")[-1].lower() if proof_file.filename else "jpg"
|
||||
if ext not in settings.ALLOWED_EXTENSIONS:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"Invalid file type. Allowed: {settings.ALLOWED_EXTENSIONS}",
|
||||
# Create AssignmentProof record
|
||||
proof_record = AssignmentProof(
|
||||
assignment_id=assignment_id,
|
||||
file_path=file_path,
|
||||
file_type=file_type,
|
||||
order_index=idx
|
||||
)
|
||||
db.add(proof_record)
|
||||
|
||||
# Upload file to storage
|
||||
filename = storage_service.generate_filename(assignment_id, proof_file.filename)
|
||||
file_path = await storage_service.upload_file(
|
||||
content=contents,
|
||||
folder="proofs",
|
||||
filename=filename,
|
||||
content_type=proof_file.content_type or "application/octet-stream",
|
||||
)
|
||||
# Legacy: set proof_path on first file for backward compatibility
|
||||
if idx == 0:
|
||||
assignment.proof_path = file_path
|
||||
|
||||
assignment.proof_path = file_path
|
||||
else:
|
||||
# Set proof URL if provided
|
||||
if proof_url:
|
||||
assignment.proof_url = proof_url
|
||||
|
||||
assignment.proof_comment = comment
|
||||
@@ -908,7 +935,7 @@ async def get_my_history(
|
||||
estimated_time=ba.challenge.estimated_time,
|
||||
proof_type=ba.challenge.proof_type,
|
||||
proof_hint=ba.challenge.proof_hint,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_generated=ba.challenge.is_generated,
|
||||
created_at=ba.challenge.created_at,
|
||||
),
|
||||
@@ -924,7 +951,7 @@ async def get_my_history(
|
||||
responses.append(AssignmentResponse(
|
||||
id=a.id,
|
||||
challenge=None,
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, game_type=game.game_type),
|
||||
game=GameShort(id=game.id, title=game.title, cover_url=None, download_url=game.download_url, game_type=game.game_type),
|
||||
is_playthrough=True,
|
||||
playthrough_info=PlaythroughInfo(
|
||||
description=game.playthrough_description,
|
||||
@@ -959,6 +986,7 @@ async def get_my_history(
|
||||
id=a.challenge.game.id,
|
||||
title=a.challenge.game.title,
|
||||
cover_url=None,
|
||||
download_url=a.challenge.game.download_url,
|
||||
game_type=a.challenge.game.game_type,
|
||||
),
|
||||
is_generated=a.challenge.is_generated,
|
||||
|
||||
Reference in New Issue
Block a user