班级抽签

This commit is contained in:
2025-04-14 14:15:17 +08:00
parent 450ee800f3
commit 8ed6b319c5
2 changed files with 119 additions and 45 deletions

View File

@@ -1,12 +1,21 @@
from django.urls import path from django.urls import path
from ..views import SMTPAPI, JudgeServerAPI, WebsiteConfigAPI, TestCasePruneAPI, SMTPTestAPI from ..views import (
from ..views import ReleaseNotesAPI, DashboardInfoAPI SMTPAPI,
JudgeServerAPI,
WebsiteConfigAPI,
TestCasePruneAPI,
SMTPTestAPI,
ReleaseNotesAPI,
DashboardInfoAPI,
RandomUsernameAPI,
)
urlpatterns = [ urlpatterns = [
path("smtp", SMTPAPI.as_view()), path("smtp", SMTPAPI.as_view()),
path("smtp_test", SMTPTestAPI.as_view()), path("smtp_test", SMTPTestAPI.as_view()),
path("website", WebsiteConfigAPI.as_view()), path("website", WebsiteConfigAPI.as_view()),
path("random_user", RandomUsernameAPI.as_view()),
path("judge_server", JudgeServerAPI.as_view()), path("judge_server", JudgeServerAPI.as_view()),
path("prune_test_case", TestCasePruneAPI.as_view()), path("prune_test_case", TestCasePruneAPI.as_view()),
path("versions", ReleaseNotesAPI.as_view()), path("versions", ReleaseNotesAPI.as_view()),

View File

@@ -1,6 +1,7 @@
import hashlib import hashlib
import json import json
import os import os
import random
import re import re
import shutil import shutil
import smtplib import smtplib
@@ -23,10 +24,15 @@ from utils.api import APIView, CSRFExemptAPIView, validate_serializer
from utils.shortcuts import send_email, get_env from utils.shortcuts import send_email, get_env
from utils.xss_filter import XSSHtml from utils.xss_filter import XSSHtml
from .models import JudgeServer from .models import JudgeServer
from .serializers import (CreateEditWebsiteConfigSerializer, from .serializers import (
CreateSMTPConfigSerializer, EditSMTPConfigSerializer, CreateEditWebsiteConfigSerializer,
JudgeServerHeartbeatSerializer, CreateSMTPConfigSerializer,
JudgeServerSerializer, TestSMTPConfigSerializer, EditJudgeServerSerializer) EditSMTPConfigSerializer,
JudgeServerHeartbeatSerializer,
JudgeServerSerializer,
TestSMTPConfigSerializer,
EditJudgeServerSerializer,
)
class SMTPAPI(APIView): class SMTPAPI(APIView):
@@ -64,12 +70,14 @@ class SMTPTestAPI(APIView):
if not SysOptions.smtp_config: if not SysOptions.smtp_config:
return self.error("Please setup SMTP config at first") return self.error("Please setup SMTP config at first")
try: try:
send_email(smtp_config=SysOptions.smtp_config, send_email(
from_name=SysOptions.website_name_shortcut, smtp_config=SysOptions.smtp_config,
to_name=request.user.username, from_name=SysOptions.website_name_shortcut,
to_email=request.data["email"], to_name=request.user.username,
subject="You have successfully configured SMTP", to_email=request.data["email"],
content="You have successfully configured SMTP") subject="You have successfully configured SMTP",
content="You have successfully configured SMTP",
)
except smtplib.SMTPResponseException as e: except smtplib.SMTPResponseException as e:
# guess error message encoding # guess error message encoding
msg = b"Failed to send email" msg = b"Failed to send email"
@@ -88,10 +96,18 @@ class SMTPTestAPI(APIView):
class WebsiteConfigAPI(APIView): class WebsiteConfigAPI(APIView):
def get(self, request): def get(self, request):
ret = {key: getattr(SysOptions, key) for key in ret = {
["website_base_url", "website_name", "website_name_shortcut", key: getattr(SysOptions, key)
"website_footer", "allow_register", "submission_list_show_all", for key in [
"class_list"]} "website_base_url",
"website_name",
"website_name_shortcut",
"website_footer",
"allow_register",
"submission_list_show_all",
"class_list",
]
}
return self.success(ret) return self.success(ret)
@super_admin_required @super_admin_required
@@ -109,8 +125,12 @@ class JudgeServerAPI(APIView):
@super_admin_required @super_admin_required
def get(self, request): def get(self, request):
servers = JudgeServer.objects.all().order_by("-last_heartbeat") servers = JudgeServer.objects.all().order_by("-last_heartbeat")
return self.success({"token": SysOptions.judge_server_token, return self.success(
"servers": JudgeServerSerializer(servers, many=True).data}) {
"token": SysOptions.judge_server_token,
"servers": JudgeServerSerializer(servers, many=True).data,
}
)
@super_admin_required @super_admin_required
def delete(self, request): def delete(self, request):
@@ -123,7 +143,9 @@ class JudgeServerAPI(APIView):
@super_admin_required @super_admin_required
def put(self, request): def put(self, request):
is_disabled = request.data.get("is_disabled", False) is_disabled = request.data.get("is_disabled", False)
JudgeServer.objects.filter(id=request.data["id"]).update(is_disabled=is_disabled) JudgeServer.objects.filter(id=request.data["id"]).update(
is_disabled=is_disabled
)
if not is_disabled: if not is_disabled:
process_pending_task() process_pending_task()
return self.success() return self.success()
@@ -134,7 +156,10 @@ class JudgeServerHeartbeatAPI(CSRFExemptAPIView):
def post(self, request): def post(self, request):
data = request.data data = request.data
client_token = request.META.get("HTTP_X_JUDGE_SERVER_TOKEN") client_token = request.META.get("HTTP_X_JUDGE_SERVER_TOKEN")
if hashlib.sha256(SysOptions.judge_server_token.encode("utf-8")).hexdigest() != client_token: if (
hashlib.sha256(SysOptions.judge_server_token.encode("utf-8")).hexdigest()
!= client_token
):
return self.error("Invalid token") return self.error("Invalid token")
try: try:
@@ -146,17 +171,27 @@ class JudgeServerHeartbeatAPI(CSRFExemptAPIView):
server.service_url = data["service_url"] server.service_url = data["service_url"]
server.ip = request.ip server.ip = request.ip
server.last_heartbeat = timezone.now() server.last_heartbeat = timezone.now()
server.save(update_fields=["judger_version", "cpu_core", "memory_usage", "service_url", "ip", "last_heartbeat"]) server.save(
update_fields=[
"judger_version",
"cpu_core",
"memory_usage",
"service_url",
"ip",
"last_heartbeat",
]
)
except JudgeServer.DoesNotExist: except JudgeServer.DoesNotExist:
JudgeServer.objects.create(hostname=data["hostname"], JudgeServer.objects.create(
judger_version=data["judger_version"], hostname=data["hostname"],
cpu_core=data["cpu_core"], judger_version=data["judger_version"],
memory_usage=data["memory"], cpu_core=data["cpu_core"],
cpu_usage=data["cpu"], memory_usage=data["memory"],
ip=request.META["REMOTE_ADDR"], cpu_usage=data["cpu"],
service_url=data["service_url"], ip=request.META["REMOTE_ADDR"],
last_heartbeat=timezone.now(), service_url=data["service_url"],
) last_heartbeat=timezone.now(),
)
# 新server上线 处理队列中的防止没有新的提交而导致一直waiting # 新server上线 处理队列中的防止没有新的提交而导致一直waiting
process_pending_task() process_pending_task()
@@ -165,7 +200,12 @@ class JudgeServerHeartbeatAPI(CSRFExemptAPIView):
class LanguagesAPI(APIView): class LanguagesAPI(APIView):
def get(self, request): def get(self, request):
return self.success({"languages": SysOptions.languages, "spj_languages": SysOptions.spj_languages}) return self.success(
{
"languages": SysOptions.languages,
"spj_languages": SysOptions.spj_languages,
}
)
class TestCasePruneAPI(APIView): class TestCasePruneAPI(APIView):
@@ -211,8 +251,11 @@ class TestCasePruneAPI(APIView):
class ReleaseNotesAPI(APIView): class ReleaseNotesAPI(APIView):
def get(self, request): def get(self, request):
try: try:
resp = requests.get("https://raw.githubusercontent.com/QingdaoU/OnlineJudge/master/docs/data.json?_=" + str(time.time()), resp = requests.get(
timeout=3) "https://raw.githubusercontent.com/QingdaoU/OnlineJudge/master/docs/data.json?_="
+ str(time.time()),
timeout=3,
)
releases = resp.json() releases = resp.json()
except (RequestException, ValueError): except (RequestException, ValueError):
return self.success() return self.success()
@@ -226,16 +269,38 @@ class DashboardInfoAPI(APIView):
def get(self, request): def get(self, request):
today = datetime.today() today = datetime.today()
today_submission_count = Submission.objects.filter( today_submission_count = Submission.objects.filter(
create_time__gte=datetime(today.year, today.month, today.day, 0, 0)).count() create_time__gte=datetime(today.year, today.month, today.day, 0, 0)
recent_contest_count = Contest.objects.exclude(end_time__lt=timezone.now()).count() ).count()
judge_server_count = len(list(filter(lambda x: x.status == "normal", JudgeServer.objects.all()))) recent_contest_count = Contest.objects.exclude(
return self.success({ end_time__lt=timezone.now()
"user_count": User.objects.count(), ).count()
"recent_contest_count": recent_contest_count, judge_server_count = len(
"today_submission_count": today_submission_count, list(filter(lambda x: x.status == "normal", JudgeServer.objects.all()))
"judge_server_count": judge_server_count, )
"env": { return self.success(
"FORCE_HTTPS": get_env("FORCE_HTTPS", default=False), {
"STATIC_CDN_HOST": get_env("STATIC_CDN_HOST", default="") "user_count": User.objects.count(),
"recent_contest_count": recent_contest_count,
"today_submission_count": today_submission_count,
"judge_server_count": judge_server_count,
"env": {
"FORCE_HTTPS": get_env("FORCE_HTTPS", default=False),
"STATIC_CDN_HOST": get_env("STATIC_CDN_HOST", default=""),
},
} }
}) )
class RandomUsernameAPI(APIView):
def get(self, request):
classroom = request.GET.get("classroom", "")
if not classroom:
return self.error("需要班级号")
usernames = User.objects.filter(username__istartswith=classroom).values_list(
"username", flat=True
)
random.shuffle(usernames)
if len(usernames) >= 10:
return self.success(usernames[:10])
else:
return self.success(usernames)