✨ Added background-image to quizzes
This commit is contained in:
+3
-1
@@ -1,7 +1,7 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
import re
|
||||
from functools import lru_cache
|
||||
|
||||
from redis import asyncio as redis_lib
|
||||
@@ -71,3 +71,5 @@ storage: Storage = Storage(
|
||||
meilisearch = MeiliSearch.Client(settings().meilisearch_url)
|
||||
|
||||
ALLOWED_TAGS_FOR_QUIZ = ["b", "strong", "i", "em", "small", "mark", "del", "sub", "sup"]
|
||||
|
||||
server_regex = rf"^{re.escape(settings().root_address)}/api/v1/storage/download/.{{36}}--.{{36}}$"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
import os
|
||||
import re
|
||||
import uuid
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
@@ -10,6 +11,7 @@ import ormar
|
||||
from pydantic import BaseModel, Json, validator
|
||||
from enum import Enum
|
||||
from . import metadata, database
|
||||
from ..config import server_regex
|
||||
|
||||
|
||||
class UserAuthTypes(Enum):
|
||||
@@ -150,6 +152,16 @@ class QuizInput(BaseModel):
|
||||
cover_image: str | None
|
||||
background_color: str | None
|
||||
questions: list[QuizQuestion]
|
||||
background_image: str | None
|
||||
|
||||
@validator("background_image")
|
||||
def must_come_from_local_cdn(cls, v):
|
||||
if v is None:
|
||||
return v
|
||||
elif bool(re.match(server_regex, v)):
|
||||
return v
|
||||
else:
|
||||
raise ValueError("does not match url scheme")
|
||||
|
||||
|
||||
class Quiz(ormar.Model):
|
||||
@@ -164,6 +176,16 @@ class Quiz(ormar.Model):
|
||||
imported_from_kahoot: Optional[bool] = ormar.Boolean(default=False, nullable=True)
|
||||
cover_image: Optional[str] = ormar.Text(nullable=True, unique=False)
|
||||
background_color: str | None = ormar.Text(nullable=True, unique=False)
|
||||
background_image: str | None = ormar.Text(nullable=True, unique=False)
|
||||
|
||||
@validator("background_image")
|
||||
def must_come_from_local_cdn(cls, v):
|
||||
if v is None:
|
||||
return v
|
||||
elif bool(re.match(server_regex, v)):
|
||||
return v
|
||||
else:
|
||||
raise ValueError("does not match url scheme")
|
||||
|
||||
class Meta:
|
||||
tablename = "quiz"
|
||||
@@ -211,6 +233,7 @@ class PlayGame(BaseModel):
|
||||
game_mode: str | None
|
||||
current_question: int = -1
|
||||
background_color: str | None
|
||||
background_image: str | None
|
||||
custom_field: str | None
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import bleach
|
||||
from fastapi import APIRouter, File, UploadFile, HTTPException, Depends
|
||||
from pydantic import BaseModel
|
||||
|
||||
from classquiz.config import settings, redis, storage, meilisearch, ALLOWED_TAGS_FOR_QUIZ
|
||||
from classquiz.config import settings, redis, storage, meilisearch, ALLOWED_TAGS_FOR_QUIZ, server_regex
|
||||
from classquiz.db.models import Quiz, QuizInput, User, QuizQuestionType
|
||||
import puremagic
|
||||
from classquiz.auth import get_current_user
|
||||
@@ -143,10 +143,10 @@ async def finish_edit(edit_id: str, quiz_input: QuizInput):
|
||||
)
|
||||
image_id_regex = r"^.{36}--.{36}$"
|
||||
imgur_regex = r"^https://i\.imgur\.com\/.{7}.(jpg|png|gif)$"
|
||||
server_regex = rf"^{re.escape(settings.root_address)}/api/v1/storage/download/.{{36}}--.{{36}}$"
|
||||
|
||||
extract_file_name_re = r"^.*/api/v1/storage/download/(.{36}--.{36})$"
|
||||
images_to_delete = []
|
||||
old_quiz_data = await Quiz.objects.get_or_none(id=session_data.quiz_id, user_id=session_data.user_id)
|
||||
old_quiz_data: Quiz = await Quiz.objects.get_or_none(id=session_data.quiz_id, user_id=session_data.user_id)
|
||||
|
||||
def mark_image_for_deletion(new: str | None, index: int, old_quiz: Quiz | None):
|
||||
if old_quiz is None:
|
||||
@@ -183,6 +183,9 @@ async def finish_edit(edit_id: str, quiz_input: QuizInput):
|
||||
if quiz_input.cover_image == "":
|
||||
quiz_input.cover_image = None
|
||||
|
||||
# if quiz_input.background_image is None and old_quiz_data.background_image is not None:
|
||||
# mark_image_for_deletion(quiz_input.background_image)
|
||||
|
||||
if quiz_input.cover_image is not None and not bool(re.match(server_regex, quiz_input.cover_image)):
|
||||
raise HTTPException(status_code=400, detail="image url is not valid")
|
||||
|
||||
@@ -200,6 +203,7 @@ async def finish_edit(edit_id: str, quiz_input: QuizInput):
|
||||
quiz.questions = quiz_input.dict()["questions"]
|
||||
quiz.cover_image = quiz_input.cover_image
|
||||
quiz.background_color = quiz_input.background_color
|
||||
quiz.background_image = quiz_input.background_image
|
||||
for image in images_to_delete:
|
||||
if image is not None:
|
||||
try:
|
||||
|
||||
@@ -126,6 +126,7 @@ async def start_quiz(
|
||||
user_id=user.id,
|
||||
background_color=quiz.background_color,
|
||||
custom_field=custom_field,
|
||||
background_image=quiz.background_image,
|
||||
)
|
||||
await redis.set(f"game:{str(game.game_pin)}", game.json(), ex=18000)
|
||||
await redis.set(f"game_pin:{user.id}:{quiz_id}", game_pin, ex=18000)
|
||||
|
||||
Reference in New Issue
Block a user