diff --git a/conf/urls/oj.py b/conf/urls/oj.py index d6b6aab..a398c36 100644 --- a/conf/urls/oj.py +++ b/conf/urls/oj.py @@ -1,10 +1,11 @@ from django.urls import path -from ..views import JudgeServerHeartbeatAPI, LanguagesAPI, WebsiteConfigAPI +from ..views import HitokotoAPI, JudgeServerHeartbeatAPI, LanguagesAPI, WebsiteConfigAPI urlpatterns = [ path("website", WebsiteConfigAPI.as_view()), # 这里必须要有 / path("judge_server_heartbeat/", JudgeServerHeartbeatAPI.as_view()), - path("languages", LanguagesAPI.as_view()) + path("languages", LanguagesAPI.as_view()), + path("hitokoto", HitokotoAPI.as_view()), ] diff --git a/conf/views.py b/conf/views.py index e1e24dc..788a6bd 100644 --- a/conf/views.py +++ b/conf/views.py @@ -1,6 +1,7 @@ import hashlib import json import os +import random import re import shutil import smtplib @@ -20,6 +21,7 @@ from options.options import SysOptions from problem.models import Problem from submission.models import Submission from utils.api import APIView, CSRFExemptAPIView, validate_serializer +from utils.cache import JsonDataLoader from utils.shortcuts import send_email, get_env from utils.xss_filter import XSSHtml from .models import JudgeServer @@ -295,10 +297,21 @@ class RandomUsernameAPI(APIView): classroom = request.GET.get("classroom", "") if not classroom: return self.error("需要班级号") - usernames = User.objects.filter(username__istartswith=classroom).values_list( - "username", flat=True - ).order_by("?") + usernames = ( + User.objects.filter(username__istartswith=classroom) + .values_list("username", flat=True) + .order_by("?") + ) if len(usernames) > 10: return self.success(usernames[:10]) else: return self.success(usernames) + + +class HitokotoAPI(APIView): + def get(self, request): + categories = JsonDataLoader.load_data(settings.HITOKOTO_DIR, "categories.json") + path = random.choice(categories).get("path") + sentences = JsonDataLoader.load_data(settings.HITOKOTO_DIR, path) + sentence = random.choice(sentences) + return self.success(sentence) diff --git a/data/hitokoto b/data/hitokoto new file mode 160000 index 0000000..b503a98 --- /dev/null +++ b/data/hitokoto @@ -0,0 +1 @@ +Subproject commit b503a98f236a3737df3615316c08052e6f99ca07 diff --git a/oj/settings.py b/oj/settings.py index 7f48afe..ce2b90a 100644 --- a/oj/settings.py +++ b/oj/settings.py @@ -136,6 +136,8 @@ AVATAR_UPLOAD_DIR = f"{DATA_DIR}{AVATAR_URI_PREFIX}" UPLOAD_PREFIX = "/public/upload" UPLOAD_DIR = f"{DATA_DIR}{UPLOAD_PREFIX}" +HITOKOTO_DIR = os.path.join(DATA_DIR, "hitokoto") + STATICFILES_DIRS = [os.path.join(DATA_DIR, "public")] diff --git a/utils/cache.py b/utils/cache.py index ed9059b..ca4ca13 100644 --- a/utils/cache.py +++ b/utils/cache.py @@ -1,5 +1,6 @@ -from django.core.cache import cache, caches # noqa -from django.conf import settings # noqa +import json +from pathlib import Path +from django.core.cache import cache from django_redis.cache import RedisCache from django_redis.client.default import DefaultClient @@ -25,3 +26,22 @@ class MyRedisCache(RedisCache): def __getattr__(self, item): return getattr(self.client, item) + + +class JsonDataLoader: + @classmethod + def load_data(cls, dir, filename): + cache_key = f"json_data_{filename}" + if cached := cache.get(cache_key): + return cached + + file_path = Path(dir, filename) + try: + with open(file_path, "r", encoding="utf-8") as f: + data = json.load(f) + cache.set(cache_key, data, timeout=7200) + return data + except FileNotFoundError: + raise ValueError(f"Data file {filename} not found") + except json.JSONDecodeError: + raise ValueError(f"Invalid JSON format in {filename}")