feat: add events app + "multi-tenants" aka multi-events
This commit is contained in:
@@ -25,11 +25,13 @@ from .schemas import NoitaSubmissionOut
|
||||
router = Router()
|
||||
NOITA_APP_ID = 881100
|
||||
|
||||
PREFIX = "/events/{event_path}/noita"
|
||||
|
||||
@router.get("results", response=ResultsOut)
|
||||
|
||||
@router.get(f"{PREFIX}/results", response=ResultsOut)
|
||||
@decorate_view(require_game_enabled(NOITA_APP_ID))
|
||||
def get_results(request: HttpRequest):
|
||||
cache_key = f"api:noita:results:{request.user.id}"
|
||||
def get_results(request: HttpRequest, event_path: str):
|
||||
cache_key = f"api:{event_path}:noita:results:{request.user.id}"
|
||||
cached_data = cache.get(cache_key)
|
||||
|
||||
if cached_data is not None:
|
||||
@@ -42,7 +44,7 @@ def get_results(request: HttpRequest):
|
||||
"""
|
||||
# Group objectives by objectiv_id and count occurrences
|
||||
user_objectives = (
|
||||
Objectiv.objects.filter(user=request.user)
|
||||
Objectiv.objects.filter(user=request.user, submission__event=request.event)
|
||||
.values("objectiv_id")
|
||||
.annotate(count=Count("id"))
|
||||
)
|
||||
@@ -118,7 +120,7 @@ def get_results(request: HttpRequest):
|
||||
total_score += points
|
||||
|
||||
# Count deaths for the user
|
||||
deaths_count = DeathCounter.objects.filter(user=request.user).count()
|
||||
deaths_count = DeathCounter.for_event.filter(user=request.user).count()
|
||||
|
||||
data = {
|
||||
"total_score": total_score,
|
||||
@@ -126,19 +128,19 @@ def get_results(request: HttpRequest):
|
||||
"objectives": list(with_points.values()),
|
||||
}
|
||||
|
||||
cache.set(f"api:noita:results:{request.user.id}", data, 300)
|
||||
cache.set(cache_key, data, 300)
|
||||
return data
|
||||
|
||||
|
||||
@router.get("leaderboard", response=LeaderboardOut)
|
||||
@router.get(f"{PREFIX}/leaderboard", response=LeaderboardOut)
|
||||
@decorate_view(require_game_enabled(NOITA_APP_ID))
|
||||
def get_leaderboard(request: HttpRequest):
|
||||
def get_leaderboard(request: HttpRequest, event_path: str):
|
||||
"""
|
||||
Get the global leaderboard for all users ranked by total score.
|
||||
|
||||
Uses Window functions to rank users by their total score in descending order.
|
||||
"""
|
||||
cache_key = "api:noita:leaderboard"
|
||||
cache_key = f"api:{event_path}:noita:leaderboard"
|
||||
cached_data = cache.get(cache_key)
|
||||
|
||||
if cached_data is not None:
|
||||
@@ -150,7 +152,8 @@ def get_leaderboard(request: HttpRequest):
|
||||
|
||||
# Get all objectives with calculated points (grouped by objectiv_id and user)
|
||||
all_objectives = (
|
||||
Objectiv.objects.values("user", "objectiv_id")
|
||||
Objectiv.objects.filter(submission__event=request.event)
|
||||
.values("user", "objectiv_id")
|
||||
.annotate(count=Count("id"))
|
||||
.annotate(
|
||||
# Fetch points from ObjectivPoint using Subquery
|
||||
@@ -201,12 +204,12 @@ def get_leaderboard(request: HttpRequest):
|
||||
for user_id, total_score in user_totals_dict.items():
|
||||
user = User.objects.get(id=user_id)
|
||||
objectives_count = (
|
||||
Objectiv.objects.filter(user_id=user_id)
|
||||
Objectiv.objects.filter(user_id=user_id, submission__event=request.event)
|
||||
.values("objectiv_id")
|
||||
.distinct()
|
||||
.count()
|
||||
)
|
||||
deaths_count = DeathCounter.objects.filter(user_id=user_id).count()
|
||||
deaths_count = DeathCounter.for_event.filter(user_id=user_id).count()
|
||||
users_with_scores.append(
|
||||
{
|
||||
"user_id": user_id,
|
||||
@@ -232,13 +235,15 @@ def get_leaderboard(request: HttpRequest):
|
||||
]
|
||||
|
||||
data = {"leaderboard": leaderboard}
|
||||
cache.set("api:noita:leaderboard", data, 300)
|
||||
cache.set(cache_key, data, 300)
|
||||
return data
|
||||
|
||||
|
||||
@router.post("submit", response={200: NoitaSubmissionOut, 400: dict})
|
||||
@router.post(f"{PREFIX}/submit", response={200: NoitaSubmissionOut, 400: dict})
|
||||
@decorate_view(require_game_enabled(NOITA_APP_ID))
|
||||
def submit_log_file(request: HttpRequest, file: UploadedFile = File(...)):
|
||||
def submit_log_file(
|
||||
request: HttpRequest, event_path: str, file: UploadedFile = File(...)
|
||||
):
|
||||
"""
|
||||
Submit a Noita run file (log file, screenshot, or video).
|
||||
|
||||
@@ -267,6 +272,7 @@ def submit_log_file(request: HttpRequest, file: UploadedFile = File(...)):
|
||||
try:
|
||||
# Create submission
|
||||
submission = LogfileSubmission.objects.create(
|
||||
event=request.event,
|
||||
user=request.user if request.user.is_authenticated else None,
|
||||
content_type=file.content_type,
|
||||
file_size=file.size,
|
||||
@@ -284,8 +290,8 @@ def submit_log_file(request: HttpRequest, file: UploadedFile = File(...)):
|
||||
|
||||
# Invalidate caches on successful submission
|
||||
if submission.user:
|
||||
cache.delete(f"api:noita:results:{submission.user.id}")
|
||||
cache.delete("api:noita:leaderboard")
|
||||
cache.delete(f"api:{event_path}:noita:results:{submission.user.id}")
|
||||
cache.delete(f"api:{event_path}:noita:leaderboard")
|
||||
|
||||
return {
|
||||
"id": str(submission.id),
|
||||
|
||||
Reference in New Issue
Block a user