# retoor <retoor@molodetz.nl>
import logging
from datetime import datetime, timezone
from typing import Annotated
from fastapi import APIRouter, Request
from devplacepy.database import get_blocked_uids, get_table
from devplacepy.database.awards import can_give_award, has_giver_cooldown, has_receiver_cooldown
from devplacepy.dependencies import json_or_form
from devplacepy.models import AwardGiveForm
from devplacepy.responses import action_result, json_error, wants_json
from devplacepy.services.audit import record as audit
from devplacepy.services.jobs import queue
from devplacepy.utils import generate_uid, make_combined_slug, require_user
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/{username}/award")
async def give_award(
request: Request,
username: str,
data: Annotated[AwardGiveForm, json_or_form(AwardGiveForm)],
):
giver = require_user(request)
target = get_table("users").find_one(username=username)
redirect = f"/profile/{username}"
def deny(message: str, status: int = 400):
if wants_json(request):
return json_error(status, message)
return action_result(request, redirect, status_code=302)
if not target:
return deny("User not found", 404)
if target["uid"] == giver["uid"]:
return deny("You cannot give yourself an award")
blocked = get_blocked_uids(giver["uid"])
if target["uid"] in blocked:
return deny("You cannot give an award to a blocked user")
reverse_blocked = get_blocked_uids(target["uid"])
if giver["uid"] in reverse_blocked:
return deny("You cannot give an award to this user")
if has_giver_cooldown(giver["uid"]):
return deny("You can give another award later")
if has_receiver_cooldown(target["uid"]):
return deny("This user received an award recently")
if not (giver.get("api_key") or "").strip():
return deny("Your account has no API key for award generation")
description = data.description.strip()
uid = generate_uid()
slug = make_combined_slug(description, uid)
now = datetime.now(timezone.utc).isoformat()
get_table("awards").insert(
{
"uid": uid,
"slug": slug,
"description": description,
"giver_uid": giver["uid"],
"receiver_uid": target["uid"],
"attachment_uid_512": "",
"attachment_uid_256": "",
"attachment_uid_64": "",
"generated_at": None,
"created_at": now,
"job_uid": "",
"deleted_at": None,
"deleted_by": None,
}
)
job_uid = queue.enqueue(
"award",
{
"award_uid": uid,
"giver_uid": giver["uid"],
"receiver_uid": target["uid"],
"description": description,
"api_key": giver.get("api_key", ""),
},
"user",
giver["uid"],
)
get_table("awards").update({"uid": uid, "job_uid": job_uid}, ["uid"])
logger.info("%s gave award %s to %s", giver["username"], uid, username)
audit.record(
request,
"award.give",
user=giver,
target_type="user",
target_uid=target["uid"],
target_label=username,
summary=f"{giver['username']} gave award to {username}",
links=[
audit.target("user", target["uid"], username),
audit.target("award", uid, slug),
audit.job(job_uid),
],
)
return action_result(
request,
redirect,
data={"ok": True, "award_uid": uid, "award_slug": slug},
)