diff --git a/Main/views/AccountView.py b/Main/views/AccountView.py index e33fabe..c535612 100644 --- a/Main/views/AccountView.py +++ b/Main/views/AccountView.py @@ -1,7 +1,7 @@ from django.contrib.auth.models import User from django.db.models import Q -from daemons.management.commands.bot import bot +from SprintLib.queue import notify from Main.models import Friendship from SprintLib.BaseView import BaseView from SprintLib.language import languages @@ -46,22 +46,17 @@ class AccountView(BaseView): ).first() if friendship is None: Friendship.objects.create(from_user=self.request.user, to_user=self.context["account"]) - if self.context["account"].userinfo.notification_friends: - bot.send_message(self.context["account"].userinfo.telegram_chat_id, f"Пользователь {self.request.user.username} хочет добавить тебя в друзья") + notify(self.context['account'], 'friends', f"Пользователь {self.request.user.username} хочет добавить тебя в друзья") elif friendship.verified or friendship.from_user == self.request.user: friendship.delete() else: if self.request.POST["to_do"] == "yes": friendship.verified = True friendship.save() - if self.context["account"].userinfo.notification_friends: - bot.send_message(self.context["account"].userinfo.telegram_chat_id, - f"Пользователь {self.request.user.username} добавил тебя в друзья") + notify(self.context['account'], 'friends', f"Пользователь {self.request.user.username} добавил тебя в друзья") else: friendship.delete() - if self.context["account"].userinfo.notification_friends: - bot.send_message(self.context["account"].userinfo.telegram_chat_id, - f"Пользователь {self.request.user.username} отклонил твою заявку") + notify(self.context['account'], 'friends', f"Пользователь {self.request.user.username} отклонил твою заявку") return "/account?username=" + self.request.GET["username"] def post_upload_photo(self): diff --git a/Main/views/SendCodeView.py b/Main/views/SendCodeView.py index e2be1b7..a8a1d87 100644 --- a/Main/views/SendCodeView.py +++ b/Main/views/SendCodeView.py @@ -1,10 +1,11 @@ -from django.contrib.auth import login - -from daemons.management.commands.bot import bot -from SprintLib.BaseView import BaseView -from django.contrib.auth.models import User from random import randrange +from django.contrib.auth import login +from django.contrib.auth.models import User + +from SprintLib.BaseView import BaseView +from SprintLib.queue import notify + class SendCodeView(BaseView): endpoint = "send_code" @@ -20,9 +21,7 @@ class SendCodeView(BaseView): code = randrange(10000, 100000) user.userinfo.code = code user.userinfo.save() - bot.send_message( - user.userinfo.telegram_chat_id, "Код для входа в сервис: " + str(code) - ) + notify(user, "any", "Код для входа в сервис: " + str(code)) return {"success": True, "message": "Код отправлен"} def post_check(self): diff --git a/SprintLib/queue.py b/SprintLib/queue.py index e7cd722..79cbdf2 100644 --- a/SprintLib/queue.py +++ b/SprintLib/queue.py @@ -1,6 +1,7 @@ import json import pika +from django.contrib.auth.models import User from django.core.management import BaseCommand from pika.adapters.utils.connection_workflow import AMQPConnectorException @@ -44,3 +45,11 @@ class MessagingSupport(BaseCommand): channel.start_consuming() except AMQPConnectorException: print("connection to rabbit failed: reconnecting") + + +def notify(user: User, notification_type: str, text: str): + send_to_queue("notifications", { + 'user_id': user, + 'notification_type': notification_type, + 'text': text, + }) diff --git a/SprintLib/testers/BaseTester.py b/SprintLib/testers/BaseTester.py index fb365e9..7a28898 100644 --- a/SprintLib/testers/BaseTester.py +++ b/SprintLib/testers/BaseTester.py @@ -2,7 +2,7 @@ from os import listdir, mkdir from os.path import join, exists from subprocess import call, TimeoutExpired -from daemons.management.commands.bot import bot +from SprintLib.queue import notify from Main.models import ExtraFile, SolutionFile from Main.models.progress import Progress from Sprint.settings import CONSTS @@ -153,12 +153,10 @@ class BaseTester: call(f"docker rm --force solution_{self.solution.id}", shell=True) call(f"docker rm --force solution_{self.solution.id}_checker", shell=True) self.solution.user.userinfo.refresh_from_db() - if self.solution.user.userinfo.notification_solution_result: - bot.send_message( - self.solution.user.userinfo.telegram_chat_id, - f"Задача: {self.solution.task.name}\n" - f"Результат: {self.solution.result}\n" - f"Очки решения: {Progress.by_solution(self.solution).score}\n" - f"Текущий рейтинг: {self.solution.user.userinfo.rating}", - parse_mode="html", - ) + notify( + self.solution.user, + "solution_result", + f"Задача: {self.solution.task.name}\n" + f"Результат: {self.solution.result}\n" + f"Очки решения: {Progress.by_solution(self.solution).score}\n" + f"Текущий рейтинг: {self.solution.user.userinfo.rating}") diff --git a/daemons/management/commands/notification_manager.py b/daemons/management/commands/notification_manager.py new file mode 100644 index 0000000..7f227ca --- /dev/null +++ b/daemons/management/commands/notification_manager.py @@ -0,0 +1,20 @@ +from django.contrib.auth.models import User + +from SprintLib.queue import MessagingSupport +from daemons.management.commands.bot import bot + + +class Command(MessagingSupport): + help = "starts file notification manager" + queue_name = "notifications" + + def process(self, payload: dict): + user = User.objects.get(id=payload['user_id']) + notification_type = payload['type'] + text = payload['text'] + if notification_type == "any" or getattr(user.userinfo, "notification_" + notification_type): + bot.send_message( + user.userinfo.telegram_chat_id, + text, + parse_mode="html", + ) diff --git a/docker-compose-deploy.yaml b/docker-compose-deploy.yaml index 9a27cd5..4eba616 100644 --- a/docker-compose-deploy.yaml +++ b/docker-compose-deploy.yaml @@ -172,6 +172,23 @@ services: restart_policy: condition: on-failure + notification_manager: + image: mathwave/sprint-repo:sprint + command: ./manage.py notification_manager + environment: + SOLUTIONS_ROOT_EXTERNAL: "/sprint-data/data/solutions" + DB_HOST: $DB_HOST + DB_PASSWORD: $DB_PASSWORD + RABBIT_HOST: $RABBIT_HOST + FS_HOST: $FS_HOST + DEBUG: $DEBUG + TELEGRAM_TOKEN: $TELEGRAM_TOKEN + deploy: + mode: replicated + replicas: 1 + restart_policy: + condition: on-failure + apply-languages: image: mathwave/sprint-repo:sprint command: ./manage.py apply_languages