From 1c3111e94a63827439ff304760ee96b985203fa6 Mon Sep 17 00:00:00 2001 From: Le Bao Hiep Date: Thu, 12 Dec 2024 20:31:40 +0700 Subject: [PATCH] Alert creator on ticket reply --- dmoj/settings.py | 1 + judge/models/profile.py | 11 +++++++++++ judge/views/ticket.py | 5 +++++ templates/base.html | 8 ++++++++ 4 files changed, 25 insertions(+) diff --git a/dmoj/settings.py b/dmoj/settings.py index fa5c8d710..bfb2d5f20 100755 --- a/dmoj/settings.py +++ b/dmoj/settings.py @@ -680,6 +680,7 @@ EVENT_DAEMON_AMQP_EXCHANGE = 'dmoj-events' EVENT_DAEMON_SUBMISSION_KEY = '6Sdmkx^%pk@GsifDfXcwX*Y7LRF%RGT8vmFpSxFBT$fwS7trc8raWfN#CSfQuKApx&$B#Gh2L7p%W!Ww' EVENT_DAEMON_CONTEST_KEY = '&w7hB-.9WnY2Jj^Qm+|?o6a' +EVENT_DAEMON_TICKET_KEY = '@R3DjH&egtm0HNhok6ERIMK!zlTzq2hrSGG2Se8SujCoO(2NX!DkbzcgQtm90FHDvpFM3gJ&D7acS$ta' # Internationalization # https://docs.djangoproject.com/en/3.2/topics/i18n/ diff --git a/judge/models/profile.py b/judge/models/profile.py index 714b1bfd0..425d9c582 100644 --- a/judge/models/profile.py +++ b/judge/models/profile.py @@ -1,4 +1,5 @@ import base64 +import hashlib import hmac import json import secrets @@ -26,6 +27,7 @@ from judge.ratings import rating_class from judge.utils.float_compare import float_compare_equal from judge.utils.two_factor import webauthn_decode +from judge.utils.unicode import utf8bytes __all__ = ['Organization', 'OrganizationMonthlyUsage', 'Profile', 'OrganizationRequest', 'WebAuthnCredential'] @@ -232,6 +234,15 @@ class Profile(models.Model): # For ICPC only group = models.TextField(verbose_name=_('uni group'), null=True, blank=True) + @classmethod + def get_ticket_secret(cls, profile_id): + return (hmac.new(utf8bytes(settings.EVENT_DAEMON_TICKET_KEY), b'%d' % profile_id, hashlib.sha512) + .hexdigest()[:16] + '%08x' % profile_id) + + @cached_property + def ticket_secret(self): + return self.get_ticket_secret(self.id) + @cached_property def organization(self): # We do this to take advantage of prefetch_related diff --git a/judge/views/ticket.py b/judge/views/ticket.py index a3dde5d2a..ebafbeb4c 100644 --- a/judge/views/ticket.py +++ b/judge/views/ticket.py @@ -184,6 +184,11 @@ def form_valid(self, form): event.post('ticket-%d' % self.object.id, { 'type': 'ticket-message', 'message': message.id, }) + if self.request.profile != self.object.user: + event.post(f'tickets_{self.object.user.ticket_secret}', { + 'title': self.object.title, + 'body': message.body, + }) on_new_ticket_message.delay(message.pk, message.ticket.pk, message.body) return HttpResponseRedirect('%s#message-%d' % (reverse('ticket', args=[self.object.id]), message.id)) diff --git a/templates/base.html b/templates/base.html index 58344927b..e9157b519 100644 --- a/templates/base.html +++ b/templates/base.html @@ -102,6 +102,14 @@ '{{ EVENT_DAEMON_POLL_LOCATION }}', {{ EVENT_LAST_MSG }} ); + {% if request.user.is_authenticated %} + $(function () { + event_dispatcher.auto_reconnect = true; + event_dispatcher.on('tickets_{{ request.profile.ticket_secret }}', function (data) { + alert({{ _('You have a new reply on ticket ')|htmltojs }} + data.title + '\n\n' + data.body); + }); + }) + {% endif %} {% endif %} {% if request.in_contest %}