diff --git a/announcement/migrations/0006_message.py b/announcement/migrations/0006_message.py new file mode 100644 index 0000000..89414cb --- /dev/null +++ b/announcement/migrations/0006_message.py @@ -0,0 +1,61 @@ +# Generated by Django 5.0.6 on 2024-06-25 11:47 + +import django.db.models.deletion +import utils.models +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("announcement", "0005_alter_announcement_options_announcement_top"), + ("submission", "0013_alter_submission_info_and_more"), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name="Message", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("message", utils.models.RichTextField()), + ("create_time", models.DateTimeField(auto_now_add=True)), + ( + "recipient", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="recipient", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "sender", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sender", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "submission", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="submission.submission", + ), + ), + ], + options={ + "db_table": "message", + "ordering": ("-create_time",), + }, + ), + ] diff --git a/announcement/models.py b/announcement/models.py index 68b9ede..810d6f0 100644 --- a/announcement/models.py +++ b/announcement/models.py @@ -1,6 +1,7 @@ from django.db import models from account.models import User +from submission.models import Submission from utils.models import RichTextField @@ -18,3 +19,15 @@ class Announcement(models.Model): class Meta: db_table = "announcement" ordering = ("-top", "-create_time",) + + +class Message(models.Model): + sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sender") + recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name="recipient") + submission = models.ForeignKey(Submission, on_delete=models.CASCADE) + message = RichTextField() + create_time = models.DateTimeField(auto_now_add=True) + + class Meta: + db_table = "message" + ordering = ("-create_time",) diff --git a/announcement/serializers.py b/announcement/serializers.py index cc7b0fe..4797f8c 100644 --- a/announcement/serializers.py +++ b/announcement/serializers.py @@ -1,7 +1,8 @@ +from submission.serializers import SubmissionCodeSerializer from utils.api import serializers from utils.api._serializers import UsernameSerializer -from .models import Announcement +from .models import Announcement, Message class CreateAnnouncementSerializer(serializers.Serializer): @@ -35,3 +36,29 @@ class EditAnnouncementSerializer(serializers.Serializer): content = serializers.CharField(max_length=1024 * 1024 * 8) visible = serializers.BooleanField() top = serializers.BooleanField() + + +class MessageSerializer(serializers.Serializer): + sender = UsernameSerializer() + recipient = UsernameSerializer() + submission = SubmissionCodeSerializer() + + class Meta: + model = Message + fields = "__all__" + + +class MessageListSerializer(serializers.Serializer): + sender = UsernameSerializer() + recipient = UsernameSerializer() + submission = SubmissionCodeSerializer() + + class Meta: + model = Message + exclude = ["message"] + + +class CreateMessageSerializer(serializers.Serializer): + recipient = serializers.IntegerField() + submission = serializers.CharField() + message = serializers.CharField() diff --git a/announcement/urls/oj.py b/announcement/urls/oj.py index 2cdc923..1a463e4 100644 --- a/announcement/urls/oj.py +++ b/announcement/urls/oj.py @@ -1,7 +1,8 @@ from django.urls import re_path as url -from ..views.oj import AnnouncementAPI +from ..views.oj import AnnouncementAPI, MessageAPI urlpatterns = [ url(r"^announcement/?$", AnnouncementAPI.as_view(), name="announcement_api"), + url(r"^message/?$", MessageAPI.as_view(), name="message_api"), ] diff --git a/announcement/views/oj.py b/announcement/views/oj.py index a745ce7..e41a498 100644 --- a/announcement/views/oj.py +++ b/announcement/views/oj.py @@ -1,7 +1,14 @@ +from account.decorators import super_admin_required, login_required +from account.models import User +from submission.models import Submission from utils.api import APIView -from announcement.models import Announcement -from announcement.serializers import AnnouncementSerializer, AnnouncementListSerializer +from announcement.models import Announcement, Message +from announcement.serializers import (AnnouncementSerializer, + AnnouncementListSerializer, + CreateMessageSerializer, MessageListSerializer, + MessageSerializer) +from utils.api.api import validate_serializer class AnnouncementAPI(APIView): @@ -16,3 +23,36 @@ class AnnouncementAPI(APIView): announcements = Announcement.objects.filter(visible=True) return self.success(self.paginate_data(request, announcements, AnnouncementListSerializer)) + + +class MessageAPI(APIView): + @login_required + def get(self, request): + message_id = request.GET.get("id") + if message_id: + try: + message = Message.objects.filter(id=message_id, recipient=request.user) + return self.success(MessageSerializer(message).data) + except Message.DoesNotExist: + return self.error("Message does not exist") + else: + messages = Message.objects.filter(recipient=request.user) + return self.success(self.paginate_data(request, messages, MessageListSerializer)) + + @validate_serializer(CreateMessageSerializer) + @super_admin_required + def post(self, request): + data = request.data + try: + recipient = User.objects.get(id=data["recipient"], is_disabled=False) + except User.DoesNotExist: + return self.error("User does not exist") + try: + submission = Submission.objects.get(id=data["submission"]) + except Submission.DoesNotExist: + return self.error("Submission does not exist") + Message.objects.create(submission=submission, + message=data["message"], + sender=request.user, + recipient=recipient) + return self.success() diff --git a/submission/serializers.py b/submission/serializers.py index 5e48f3e..721d4c2 100644 --- a/submission/serializers.py +++ b/submission/serializers.py @@ -31,6 +31,13 @@ class SubmissionSafeModelSerializer(serializers.ModelSerializer): model = Submission exclude = ("info", "contest", "ip") +class SubmissionCodeSerializer(serializers.Serializer): + problem = serializers.SlugRelatedField(read_only=True, slug_field="_id") + + class Meta: + model = Submission + field = ("id", "code", "problem", "result", "language") + class SubmissionListSerializer(serializers.ModelSerializer): problem = serializers.SlugRelatedField(read_only=True, slug_field="_id")