|
# retoor <retoor@molodetz.nl>
|
|
|
|
from urllib.parse import quote
|
|
|
|
from fastapi import Request
|
|
from fastapi.responses import RedirectResponse
|
|
|
|
from devplacepy.database import get_table, resolve_by_slug
|
|
from devplacepy.responses import json_error, wants_json
|
|
from devplacepy.seo import base_seo_context
|
|
from devplacepy.services.pubsub import publish
|
|
from devplacepy.services.quiz import QuizError, store
|
|
from devplacepy.utils import is_admin, not_found
|
|
|
|
|
|
def quiz_topic(quiz_uid: str) -> str:
|
|
return f"public.quiz.{quiz_uid}"
|
|
|
|
|
|
async def notify_quiz(quiz_uid: str) -> None:
|
|
if not quiz_uid:
|
|
return
|
|
try:
|
|
await publish(quiz_topic(quiz_uid), {"kind": "update", "quiz_uid": quiz_uid})
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def load_quiz(slug: str, user: dict | None) -> dict:
|
|
quiz = resolve_by_slug(get_table("quizzes"), slug)
|
|
if not quiz or not store.can_view_quiz(quiz, user):
|
|
raise not_found("Quiz not found")
|
|
return quiz
|
|
|
|
|
|
def require_owner(quiz: dict, user: dict):
|
|
if not (store.is_quiz_owner(quiz, user) or is_admin(user)):
|
|
raise not_found("Quiz not found")
|
|
return quiz
|
|
|
|
|
|
def require_editor(quiz: dict, user: dict):
|
|
if not store.is_quiz_owner(quiz, user):
|
|
raise not_found("Quiz not found")
|
|
return quiz
|
|
|
|
|
|
def action_error(request: Request, message: str, redirect_url: str):
|
|
if wants_json(request):
|
|
return json_error(400, message)
|
|
separator = "&" if "?" in redirect_url else "?"
|
|
return RedirectResponse(
|
|
url=f"{redirect_url}{separator}error={quote(message)}", status_code=302
|
|
)
|
|
|
|
|
|
def quiz_seo(request: Request, title: str, description: str, robots: str = "index,follow", **extra):
|
|
return base_seo_context(
|
|
request,
|
|
title=title,
|
|
description=description,
|
|
robots=robots,
|
|
breadcrumbs=[
|
|
{"name": "Home", "url": "/feed"},
|
|
{"name": "Quizzes", "url": "/quizzes"},
|
|
*extra.pop("breadcrumbs", []),
|
|
],
|
|
**extra,
|
|
)
|
|
|
|
|
|
def quiz_url(quiz: dict) -> str:
|
|
return f"/quizzes/{quiz.get('slug') or quiz['uid']}"
|
|
|
|
|
|
__all__ = [
|
|
"QuizError",
|
|
"action_error",
|
|
"load_quiz",
|
|
"notify_quiz",
|
|
"quiz_seo",
|
|
"quiz_topic",
|
|
"quiz_url",
|
|
"require_editor",
|
|
"require_owner",
|
|
]
|