Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 12 additions & 25 deletions app/front/send_tg_notification.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,25 @@
import datetime

from flask import jsonify, make_response
from flask_apispec import doc, use_kwargs
from flask import jsonify, make_response, request
from flask_apispec import doc
from flask_apispec.views import MethodResource
from flask_jwt_extended import jwt_required, get_jwt_identity
from flask_restful import Resource
from marshmallow import fields, Schema
from sqlalchemy.exc import SQLAlchemyError

from app import config
from app.database import db_session
from app.logger import app_logger as logger
from app.models import Notification
from app.request_models.telegram_notification import TelegramNotificationRequest
from app.webhooks.check_request import request_to_context
from app.webhooks.check_webhooks_token import check_webhooks_token

from bot.messages import TelegramNotification



class TelegramNotificationSchema(Schema):
message = fields.String(required=True)
has_mailing = fields.String(required=True)


class SendTelegramNotification(Resource, MethodResource):
method_decorators = {'post': [check_webhooks_token]}

@doc(description='Sends message to the Telegram chat. Requires "message" parameter.'
' Messages can be sent either to subscribed users or not.To do this,'
Expand Down Expand Up @@ -52,27 +49,17 @@ class SendTelegramNotification(Resource, MethodResource):
'Authorization': config.PARAM_HEADER_AUTH, # Only if request requires authorization
}
)
@use_kwargs(TelegramNotificationSchema)
@jwt_required()
def post(self, **kwargs):
message = kwargs.get('message').replace(' ', '')
has_mailing = kwargs.get('has_mailing')

if not message or not has_mailing:
logger.info("Messages: The <message> and <has_mailing> parameters have not been passed")
return make_response(jsonify(result="Необходимо указать параметры <message> и <has_mailing>."), 400)

def post(self):
notifications = request_to_context(TelegramNotificationRequest, request)
authorized_user = get_jwt_identity()
message = Notification(message=message, sent_by=authorized_user)
message = Notification(message=notifications['message'], sent_by=authorized_user)
db_session.add(message)

try:
db_session.commit()
job_queue = TelegramNotification(has_mailing)

if not job_queue.send_notification(message=message.message):
logger.info(f"Messages: Passed invalid <has_mailing> parameter. Passed: {has_mailing}")
return make_response(jsonify(result=f"Неверно указан параметр <has_mailing>. "
f"Сообщение не отправлено."), 400)
notifier = TelegramNotification()
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Писал прошлый раз по этому, но давай ещё раз переименуем, в название класса и переменной довай добавим слово сервис.

notifier.send_notification(mailing_type=notifications, message=message.message)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А тут что происходит? mailing_type=notifications ты в поле ожидающее получить enum передаёшь объект с различнми полями. Подозреваю, ЭТО НЕ РАБОТАЕТ! Перед отправкой на следующее ревью, тебе нужно прогнать 5 кейсов тестирования различного положения флага и убедиться, что всё работает.
И в месте где проверяешь тип, if mailing_type == MailingType.subscribed.value:, везде добавь else, а в самом конце, если это не одно из трёх значений, бросай исключение! Как раз по этому у тебя и отработало всё без ошибок.


message.was_sent = True
message.sent_date = datetime.datetime.now()
Expand Down
13 changes: 13 additions & 0 deletions app/request_models/telegram_notification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from pydantic import Field, StrictStr

from app.request_models.request_base import RequestBase
from core.services.mailing_type import MailingType, MailingNumber


class TelegramNotificationRequest(RequestBase):
message: StrictStr = Field()
mailing_type: MailingType = MailingType.subscribed
mailing_number: MailingNumber = MailingNumber.subscribed
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

А зачем это?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Это по документации если при входе попадет значение не из трех значений 'subscribed', 'unsubscribed', 'all', то выдаст ошибку
https://docs.pydantic.dev/usage/types/#enums-and-choices

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не, я про саму переменную, зачем нам нужна mailing_number? Как её использовать и кому?


class Config:
use_enum_values = True
20 changes: 6 additions & 14 deletions bot/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from app.logger import bot_logger as logger
from app.models import User
from bot.charity_bot import dispatcher
from core.services.mailing_type import MailingType

bot = Bot(config.TELEGRAM_TOKEN)

Expand All @@ -30,32 +31,23 @@ class TelegramNotification:
"""
This class describes the functionality for working with notifications in Telegram.
"""

def __init__(self, has_mailing: str = 'subscribed') -> None:
self.has_mailing = has_mailing

# TODO refactoring https://github.com/python-telegram-bot/python-telegram-bot/wiki/Avoiding-flood-limits
def send_notification(self, message):
def send_notification(self, mailing_type, message):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Другой порядок, сперва сообщение, потом тип. сообщение важнее чем тип.!

"""
Adds queue to send notification to telegram chats.

:param mailing_type: Type of subscription
:param message: Message to add to the sending queue
:param telegram_chats: Users query
:return:
"""
if self.has_mailing not in ('all', 'subscribed', 'unsubscribed'):
return False

chats_list = []
query = db_session.query(User.telegram_id).filter(User.banned.is_(False))

if self.has_mailing == 'subscribed':
if mailing_type == MailingType.subscribed.value:
chats_list = query.filter(User.has_mailing.is_(True))

if self.has_mailing == 'unsubscribed':
if mailing_type == MailingType.unsubscribed.value:
chats_list = query.filter(User.has_mailing.is_(False))

if self.has_mailing == 'all':
if mailing_type == MailingType.all.value:
chats_list = query

user_notification_context = SendUserNotificationsContext([])
Expand Down
16 changes: 16 additions & 0 deletions core/services/mailing_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from enum import Enum, IntEnum


class MailingType(str, Enum):
"""
This class implements enumeration.
"""
subscribed = 'subscribed'
unsubscribed = 'unsubscribed'
all = 'all'


class MailingNumber(IntEnum):
subscribed = 1
unsubscribed = 2
all = 3
11 changes: 5 additions & 6 deletions core/services/user_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,16 +127,15 @@ def change_subscription(self, telegram_id):
"""
user = User.query.options(load_only('has_mailing')).filter_by(telegram_id=telegram_id).first()

if user.has_mailing:
user.has_mailing = False
else:
user.has_mailing = True
try:
user.has_mailing = not user.has_mailing
db_session.commit()
logger.info("Subscription: Status successfully changed.")
return user.has_mailing
except SQLAlchemyError as ex:
logger.error(f"User DB - 'change_subscription' method: {str(ex)}")

return user.has_mailing
db_session.rollback()
return user.has_mailing

def change_user_category(self, telegram_id, category_id):
user = User.query.filter_by(telegram_id=telegram_id).first()
Expand Down