notifications
This commit is contained in:
parent
138c3fa6e8
commit
4bc1981ef6
@ -356,6 +356,50 @@ services:
|
|||||||
parallelism: 1
|
parallelism: 1
|
||||||
order: start-first
|
order: start-first
|
||||||
|
|
||||||
|
telegram_sender:
|
||||||
|
image: mathwave/sprint-repo:sprint
|
||||||
|
networks:
|
||||||
|
- net
|
||||||
|
command: ./manage.py telegram_sender
|
||||||
|
environment:
|
||||||
|
DB_HOST: "postgres"
|
||||||
|
FS_HOST: "storage"
|
||||||
|
RABBIT_HOST: "rabbitmq"
|
||||||
|
REDIS_HOST: "redis"
|
||||||
|
DB_PASSWORD: $DB_PASSWORD
|
||||||
|
DEBUG: $DEBUG
|
||||||
|
TELEGRAM_TOKEN: $TELEGRAM_TOKEN
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
update_config:
|
||||||
|
parallelism: 1
|
||||||
|
order: start-first
|
||||||
|
|
||||||
|
email_sender:
|
||||||
|
image: mathwave/sprint-repo:sprint
|
||||||
|
networks:
|
||||||
|
- net
|
||||||
|
command: ./manage.py email_sender
|
||||||
|
environment:
|
||||||
|
DB_HOST: "postgres"
|
||||||
|
FS_HOST: "storage"
|
||||||
|
RABBIT_HOST: "rabbitmq"
|
||||||
|
REDIS_HOST: "redis"
|
||||||
|
DB_PASSWORD: $DB_PASSWORD
|
||||||
|
DEBUG: $DEBUG
|
||||||
|
EMAIL_PASSWORD: $EMAIL_PASSWORD
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
update_config:
|
||||||
|
parallelism: 1
|
||||||
|
order: start-first
|
||||||
|
|
||||||
apply-languages:
|
apply-languages:
|
||||||
image: mathwave/sprint-repo:sprint
|
image: mathwave/sprint-repo:sprint
|
||||||
networks:
|
networks:
|
||||||
|
@ -360,6 +360,50 @@ services:
|
|||||||
parallelism: 1
|
parallelism: 1
|
||||||
order: start-first
|
order: start-first
|
||||||
|
|
||||||
|
telegram_sender:
|
||||||
|
image: mathwave/sprint-repo:sprint
|
||||||
|
networks:
|
||||||
|
- net
|
||||||
|
command: ./manage.py telegram_sender
|
||||||
|
environment:
|
||||||
|
DB_HOST: "postgres"
|
||||||
|
FS_HOST: "storage"
|
||||||
|
RABBIT_HOST: "rabbitmq"
|
||||||
|
REDIS_HOST: "redis"
|
||||||
|
DB_PASSWORD: $DB_PASSWORD
|
||||||
|
DEBUG: $DEBUG
|
||||||
|
TELEGRAM_TOKEN: $TELEGRAM_TOKEN
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
update_config:
|
||||||
|
parallelism: 1
|
||||||
|
order: start-first
|
||||||
|
|
||||||
|
email_sender:
|
||||||
|
image: mathwave/sprint-repo:sprint
|
||||||
|
networks:
|
||||||
|
- net
|
||||||
|
command: ./manage.py email_sender
|
||||||
|
environment:
|
||||||
|
DB_HOST: "postgres"
|
||||||
|
FS_HOST: "storage"
|
||||||
|
RABBIT_HOST: "rabbitmq"
|
||||||
|
REDIS_HOST: "redis"
|
||||||
|
DB_PASSWORD: $DB_PASSWORD
|
||||||
|
DEBUG: $DEBUG
|
||||||
|
EMAIL_PASSWORD: $EMAIL_PASSWORD
|
||||||
|
deploy:
|
||||||
|
mode: replicated
|
||||||
|
replicas: 2
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
update_config:
|
||||||
|
parallelism: 1
|
||||||
|
order: start-first
|
||||||
|
|
||||||
apply-languages:
|
apply-languages:
|
||||||
image: mathwave/sprint-repo:sprint
|
image: mathwave/sprint-repo:sprint
|
||||||
networks:
|
networks:
|
||||||
|
@ -10,8 +10,8 @@ from django.utils import timezone
|
|||||||
from Checker.models import Checker
|
from Checker.models import Checker
|
||||||
from FileStorage.sync import synchronized_method
|
from FileStorage.sync import synchronized_method
|
||||||
from Main.models import Solution, SolutionFile, ExtraFile, Progress
|
from Main.models import Solution, SolutionFile, ExtraFile, Progress
|
||||||
|
from SprintLib.queue import send_to_queue
|
||||||
from SprintLib.utils import generate_token
|
from SprintLib.utils import generate_token
|
||||||
from SprintLib.queue import notify as notification
|
|
||||||
|
|
||||||
|
|
||||||
def get_dynamic(request):
|
def get_dynamic(request):
|
||||||
@ -92,13 +92,10 @@ def notify(request):
|
|||||||
solution = Solution.objects.get(id=request.GET['solution_id'])
|
solution = Solution.objects.get(id=request.GET['solution_id'])
|
||||||
if checker.set != solution.set:
|
if checker.set != solution.set:
|
||||||
return JsonResponse({"status": "incorrect solution"}, status=403)
|
return JsonResponse({"status": "incorrect solution"}, status=403)
|
||||||
notification(
|
send_to_queue("notification", {
|
||||||
solution.user,
|
"type": "solution",
|
||||||
"solution_result",
|
"solution_id": solution.id
|
||||||
f"Задача: {solution.task.name}\n"
|
})
|
||||||
f"Результат: {solution.result}\n"
|
|
||||||
f"Очки решения: {Progress.by_solution(solution).score}\n"
|
|
||||||
f"Текущий рейтинг: {solution.user.userinfo.rating}")
|
|
||||||
return JsonResponse({"status": True})
|
return JsonResponse({"status": True})
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
return JsonResponse({"status": "incorrect token"}, status=403)
|
return JsonResponse({"status": "incorrect token"}, status=403)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
|
|
||||||
from SprintLib.queue import notify
|
|
||||||
from Main.models import Friendship
|
from Main.models import Friendship
|
||||||
from SprintLib.BaseView import BaseView
|
from SprintLib.BaseView import BaseView
|
||||||
from SprintLib.language import languages
|
from SprintLib.language import languages
|
||||||
|
from SprintLib.queue import send_to_queue
|
||||||
from SprintLib.utils import delete_file, write_bytes
|
from SprintLib.utils import delete_file, write_bytes
|
||||||
|
|
||||||
|
|
||||||
@ -46,17 +46,26 @@ class AccountView(BaseView):
|
|||||||
).first()
|
).first()
|
||||||
if friendship is None:
|
if friendship is None:
|
||||||
Friendship.objects.create(from_user=self.request.user, to_user=self.context["account"])
|
Friendship.objects.create(from_user=self.request.user, to_user=self.context["account"])
|
||||||
notify(self.context['account'], 'friends', f"Пользователь {self.request.user.username} хочет добавить тебя в друзья")
|
send_to_queue("notification", {
|
||||||
|
"type": "friends_add",
|
||||||
|
"from_user": self.request.user.id,
|
||||||
|
"to_user": self.context["account"].id
|
||||||
|
})
|
||||||
elif friendship.verified or friendship.from_user == self.request.user:
|
elif friendship.verified or friendship.from_user == self.request.user:
|
||||||
friendship.delete()
|
friendship.delete()
|
||||||
else:
|
else:
|
||||||
if self.request.POST["to_do"] == "yes":
|
if self.request.POST["to_do"] == "yes":
|
||||||
friendship.verified = True
|
friendship.verified = True
|
||||||
friendship.save()
|
friendship.save()
|
||||||
notify(self.context['account'], 'friends', f"Пользователь {self.request.user.username} добавил тебя в друзья")
|
|
||||||
else:
|
else:
|
||||||
friendship.delete()
|
friendship.delete()
|
||||||
notify(self.context['account'], 'friends', f"Пользователь {self.request.user.username} отклонил твою заявку")
|
send_to_queue("notification", {
|
||||||
|
"type": "friends_accept",
|
||||||
|
"from_user": self.request.user.id,
|
||||||
|
"to_user": self.context['account'].id,
|
||||||
|
"accepted": self.request.POST['to_do'] == 'yes'
|
||||||
|
})
|
||||||
|
|
||||||
return "/account?username=" + self.request.GET["username"]
|
return "/account?username=" + self.request.GET["username"]
|
||||||
|
|
||||||
def post_upload_photo(self):
|
def post_upload_photo(self):
|
||||||
|
@ -5,7 +5,7 @@ from django.contrib.auth.models import User
|
|||||||
|
|
||||||
from Sprint import settings
|
from Sprint import settings
|
||||||
from SprintLib.BaseView import BaseView
|
from SprintLib.BaseView import BaseView
|
||||||
from SprintLib.queue import notify
|
from SprintLib.queue import send_to_queue
|
||||||
|
|
||||||
|
|
||||||
class SendCodeView(BaseView):
|
class SendCodeView(BaseView):
|
||||||
@ -23,7 +23,10 @@ class SendCodeView(BaseView):
|
|||||||
print(f"Отправлен код для {username}", code)
|
print(f"Отправлен код для {username}", code)
|
||||||
user.userinfo.code = code
|
user.userinfo.code = code
|
||||||
user.userinfo.save()
|
user.userinfo.save()
|
||||||
notify(user, "any", "Код для входа в сервис: " + str(code))
|
send_to_queue("telegram", {
|
||||||
|
"chat_id": user.userinfo.telegram_chat_id,
|
||||||
|
"text": "Код для входа в сервис: " + str(code)
|
||||||
|
})
|
||||||
return {"success": True, "message": "Код отправлен"}
|
return {"success": True, "message": "Код отправлен"}
|
||||||
|
|
||||||
def post_check(self):
|
def post_check(self):
|
||||||
|
@ -147,6 +147,14 @@ RABBIT_PORT = 5672
|
|||||||
FS_HOST = "http://" + os.getenv("FS_HOST", "127.0.0.1")
|
FS_HOST = "http://" + os.getenv("FS_HOST", "127.0.0.1")
|
||||||
FS_PORT = 5555
|
FS_PORT = 5555
|
||||||
|
|
||||||
|
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
|
||||||
|
EMAIL_HOST = "smtp.yandex.ru"
|
||||||
|
EMAIL_HOST_USER = "sprint.no-reply@yandex.ru"
|
||||||
|
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_PASSWORD")
|
||||||
|
EMAIL_PORT = 587
|
||||||
|
EMAIL_USE_TLS = True
|
||||||
|
EMAIL_USE_SSL = False
|
||||||
|
|
||||||
# Authentication backends
|
# Authentication backends
|
||||||
AUTHENTICATION_BACKENDS = ("django.contrib.auth.backends.ModelBackend",)
|
AUTHENTICATION_BACKENDS = ("django.contrib.auth.backends.ModelBackend",)
|
||||||
|
|
||||||
|
@ -56,11 +56,3 @@ class MessagingSupport(BaseCommand):
|
|||||||
channel.start_consuming()
|
channel.start_consuming()
|
||||||
except AMQPConnectorException:
|
except AMQPConnectorException:
|
||||||
print("connection to rabbit failed: reconnecting")
|
print("connection to rabbit failed: reconnecting")
|
||||||
|
|
||||||
|
|
||||||
def notify(user: User, notification_type: str, text: str):
|
|
||||||
send_to_queue("notifications", {
|
|
||||||
'user_id': user.id,
|
|
||||||
'type': notification_type,
|
|
||||||
'text': text,
|
|
||||||
})
|
|
||||||
|
@ -5,7 +5,7 @@ from tempfile import TemporaryDirectory
|
|||||||
|
|
||||||
from Main.models.progress import Progress
|
from Main.models.progress import Progress
|
||||||
from Sprint.settings import CONSTS
|
from Sprint.settings import CONSTS
|
||||||
from SprintLib.queue import notify, send_to_queue
|
from SprintLib.queue import send_to_queue
|
||||||
from SprintLib.utils import Timer
|
from SprintLib.utils import Timer
|
||||||
|
|
||||||
|
|
||||||
@ -111,14 +111,10 @@ class BaseTester:
|
|||||||
|
|
||||||
def notify(self):
|
def notify(self):
|
||||||
self.solution.user.userinfo.refresh_from_db()
|
self.solution.user.userinfo.refresh_from_db()
|
||||||
notify(
|
send_to_queue("notification", {
|
||||||
self.solution.user,
|
"type": "solution",
|
||||||
"solution_result",
|
"solution_id": self.solution.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}",
|
|
||||||
)
|
|
||||||
|
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self.solution.save()
|
self.solution.save()
|
||||||
|
20
daemons/management/commands/email_sender.py
Normal file
20
daemons/management/commands/email_sender.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from django.core.mail import send_mail
|
||||||
|
|
||||||
|
from Sprint.settings import EMAIL_HOST_USER
|
||||||
|
from SprintLib.queue import MessagingSupport
|
||||||
|
|
||||||
|
|
||||||
|
class Command(MessagingSupport):
|
||||||
|
help = "starts file email sender"
|
||||||
|
queue_name = "email"
|
||||||
|
|
||||||
|
def process(self, payload: dict):
|
||||||
|
subject = payload['subject']
|
||||||
|
message = payload['message']
|
||||||
|
email = payload['email']
|
||||||
|
send_mail(
|
||||||
|
subject,
|
||||||
|
message,
|
||||||
|
EMAIL_HOST_USER,
|
||||||
|
[email]
|
||||||
|
)
|
@ -1,20 +1,53 @@
|
|||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from SprintLib.queue import MessagingSupport
|
from Main.models import Solution, Progress
|
||||||
from daemons.management.commands.bot import bot
|
from SprintLib.queue import MessagingSupport, send_to_queue
|
||||||
|
|
||||||
|
|
||||||
class Command(MessagingSupport):
|
class Command(MessagingSupport):
|
||||||
help = "starts file notification manager"
|
help = "starts file notification manager"
|
||||||
queue_name = "notifications"
|
queue_name = "notification"
|
||||||
|
|
||||||
|
def handle_solution(self, payload):
|
||||||
|
solution = Solution.objects.get(id=payload["solution_id"])
|
||||||
|
user = solution.user
|
||||||
|
if user.userinfo.notification_solution_result:
|
||||||
|
message = f"Задача: {solution.task.name}\n" \
|
||||||
|
f"Результат: {solution.result}\n" \
|
||||||
|
f"Очки решения: {Progress.by_solution(solution).score}\n" \
|
||||||
|
f"Текущий рейтинг: {solution.user.userinfo.rating}"
|
||||||
|
if user.userinfo.telegram_chat_id is not None:
|
||||||
|
yield "telegram", {"chat_id": user.userinfo.telegram_chat_id, "text": message}
|
||||||
|
if user.email:
|
||||||
|
yield "email", {"subject": "Тестирование завершено", "message": message, "email": user.email}
|
||||||
|
|
||||||
|
def handle_friends_add(self, payload):
|
||||||
|
user = User.objects.get(id=payload['to_user_id'])
|
||||||
|
from_user = User.objects.get(id=payload['from_user_id'])
|
||||||
|
if user.userinfo.notification_friends:
|
||||||
|
message = f"Пользователь {from_user.username} хочет добавить тебя в друзья"
|
||||||
|
if user.userinfo.telegram_chat_id:
|
||||||
|
yield "telegram", {"chat_id": user.userinfo.telegram_chat_id, "text": message}
|
||||||
|
if user.email:
|
||||||
|
yield "email", {"subject": "Новая заявка в друзья", "message": message, "email": user.email}
|
||||||
|
|
||||||
|
def handle_friends_accept(self, payload):
|
||||||
|
user = User.objects.get(id=payload['to_user_id'])
|
||||||
|
from_user = User.objects.get(id=payload['from_user_id'])
|
||||||
|
if user.userinfo.notification_friends:
|
||||||
|
if payload['accepted']:
|
||||||
|
message = f"Пользователь {from_user} одобрил заявку в друзья"
|
||||||
|
else:
|
||||||
|
message = f"Пользователь {from_user} отклонил заявку в друзья"
|
||||||
|
if user.userinfo.telegram_chat_id:
|
||||||
|
yield "telegram", {"chat_id": user.userinfo.telegram_chat_id, "text": message}
|
||||||
|
if user.email:
|
||||||
|
yield "email", {"subject": "Новая заявка в друзья", "message": message, "email": user.email}
|
||||||
|
|
||||||
def process(self, payload: dict):
|
def process(self, payload: dict):
|
||||||
user = User.objects.get(id=payload['user_id'])
|
notification_type = payload["type"]
|
||||||
notification_type = payload['type']
|
handler = getattr(self, "handle_" + notification_type, None)
|
||||||
text = payload['text']
|
if handler is None:
|
||||||
if notification_type == "any" or getattr(user.userinfo, "notification_" + notification_type):
|
raise ValueError(f"Unknown type: {notification_type}")
|
||||||
bot.send_message(
|
for queue, payload in handler(payload):
|
||||||
user.userinfo.telegram_chat_id,
|
send_to_queue(queue, payload)
|
||||||
text,
|
|
||||||
parse_mode="html",
|
|
||||||
)
|
|
||||||
|
16
daemons/management/commands/telegram_sender.py
Normal file
16
daemons/management/commands/telegram_sender.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from SprintLib.queue import MessagingSupport
|
||||||
|
from daemons.management.commands.bot import bot
|
||||||
|
|
||||||
|
|
||||||
|
class Command(MessagingSupport):
|
||||||
|
help = "starts file telegram sender"
|
||||||
|
queue_name = "telegram"
|
||||||
|
|
||||||
|
def process(self, payload: dict):
|
||||||
|
chat_id = payload['chat_id']
|
||||||
|
text = payload['text']
|
||||||
|
bot.send_message(
|
||||||
|
int(chat_id),
|
||||||
|
text,
|
||||||
|
parse_mode="html",
|
||||||
|
)
|
Loading…
Reference in New Issue
Block a user