-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/add_message_history #336
base: develop
Are you sure you want to change the base?
Changes from 11 commits
d5ca066
6ee2768
984714b
42e13b8
9e70f53
b037146
19f2ead
4860b76
2f84ec0
b59430b
e139cad
77df88b
4ccd67c
8b99676
018ac55
0cdcde0
cc8711a
65baead
cff6ebd
a996312
8195063
e204f35
25f163c
c4f2094
c753006
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,23 +5,27 @@ | |
from telegram.ext import CallbackContext | ||
|
||
from src.bot.api_services import ( | ||
get_history_service, | ||
get_member_service_callback, | ||
get_report_service_callback, | ||
get_shift_service_callback, | ||
) | ||
from src.bot.services import BotService | ||
from src.bot.ui import DAILY_TASK_BUTTONS | ||
from src.core.db.db import get_session | ||
from src.core.db.models import Report | ||
from src.core.db.models import MessageHistory, Report | ||
from src.core.settings import settings | ||
|
||
|
||
async def send_no_report_reminder_job(context: CallbackContext) -> None: | ||
"""Отправить напоминание об отчёте.""" | ||
member_session_generator = get_session() | ||
history_session = get_session() | ||
history_service = await get_history_service(history_session) | ||
member_service = await get_member_service_callback(member_session_generator) | ||
bot_service = BotService(context) | ||
bot_service = BotService(context, history_service) | ||
members = await member_service.get_members_with_no_reports() | ||
event = MessageHistory.Event.REPORT_MENTION.value | ||
send_message_tasks = [ | ||
bot_service.send_message( | ||
member.user, | ||
|
@@ -31,6 +35,7 @@ async def send_no_report_reminder_job(context: CallbackContext) -> None: | |
f"Напоминаем, что за каждое выполненное задание ты получаешь виртуальные " | ||
f"\"ломбарьерчики\", которые можешь обменять на призы и подарки!" | ||
), | ||
event, | ||
) | ||
for member in members | ||
] | ||
|
@@ -42,18 +47,21 @@ async def send_daily_task_job(context: CallbackContext) -> None: | |
shift_session = get_session() | ||
report_session = get_session() | ||
member_session = get_session() | ||
history_session = get_session() | ||
shift_service = await get_shift_service_callback(shift_session) | ||
report_service = await get_report_service_callback(report_session) | ||
member_service = await get_member_service_callback(member_session) | ||
history_service = await get_history_service(history_session) | ||
|
||
await shift_service.start_prepared_shift() | ||
|
||
bot_service = BotService(context) | ||
bot_service = BotService(context, history_service) | ||
await report_service.set_status_to_waiting_reports(Report.Status.SKIPPED) | ||
await member_service.exclude_lagging_members(context.application) | ||
task, members = await report_service.get_today_task_and_active_members(date.today().day) | ||
await report_service.create_daily_reports(members, task) | ||
task_photo = urljoin(settings.APPLICATION_URL, task.url) | ||
event = MessageHistory.Event.GET_TASK.value | ||
send_message_tasks = [ | ||
bot_service.send_photo( | ||
member.user, | ||
|
@@ -71,6 +79,7 @@ async def send_daily_task_job(context: CallbackContext) -> None: | |
f"Не забудь сделать фотографию, как ты выполняешь задание, и отправить на проверку." | ||
), | ||
DAILY_TASK_BUTTONS, | ||
event, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Подставляй событие сразу сюда. Иначе, приходится возвращаться назад, чтобы узнать, какое событие будет. |
||
) | ||
for member in members | ||
] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
from src.api.request_models.request import RequestDeclineRequest | ||
from src.bot.error_handler import error_handler | ||
from src.core.db import models | ||
from src.core.services.history_message_service import MessageHistoryService | ||
from src.core.settings import settings | ||
from src.core.utils import get_lombaryers_for_quantity | ||
|
||
|
@@ -53,19 +54,24 @@ async def _inner(*args, **kwargs): | |
|
||
|
||
class BotService: | ||
def __init__(self, telegram_bot: Application) -> None: | ||
def __init__(self, telegram_bot: Application, history_service: MessageHistoryService) -> None: | ||
self.__bot = telegram_bot.bot | ||
self.__bot_application = telegram_bot | ||
self.__history_service = history_service | ||
|
||
@check_user_blocked | ||
@retry() | ||
async def send_message(self, user: models.User, text: str) -> None: | ||
async def send_message(self, user: models.User, text: str, event: str) -> None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Event не строка, а enum из модели. |
||
await self.__bot.send_message(user.telegram_id, text) | ||
await self.__history_service.create_history_message(user.id, user.telegram_id, text, event) | ||
|
||
@check_user_blocked | ||
@retry() | ||
async def send_photo(self, user: models.User, photo: str, caption: str, reply_markup: ReplyKeyboardMarkup) -> None: | ||
async def send_photo( | ||
self, user: models.User, photo: str, caption: str, reply_markup: ReplyKeyboardMarkup, event: str | ||
) -> None: | ||
await self.__bot.send_photo(chat_id=user.telegram_id, photo=photo, caption=caption, reply_markup=reply_markup) | ||
await self.__history_service.create_history_message(user.id, user.telegram_id, caption, event) | ||
|
||
async def notify_approved_request(self, user: models.User, first_task_date: str) -> None: | ||
"""Уведомление участника о решении по заявке в telegram. | ||
|
@@ -77,7 +83,8 @@ async def notify_approved_request(self, user: models.User, first_task_date: str) | |
f"{first_task_date} в {settings.formatted_task_time} часов утра " | ||
"тебе поступит первое задание." | ||
) | ||
await self.send_message(user, text) | ||
event = models.MessageHistory.Event.REQUEST_ACCEPTED.value | ||
await self.send_message(user, text, event) | ||
|
||
async def notify_declined_request( | ||
self, user: models.User, decline_request_data: RequestDeclineRequest | None | ||
|
@@ -96,7 +103,8 @@ async def notify_declined_request( | |
f" новости Центра \"Ломая барьеры\" - вступайте в нашу группу " | ||
f"{settings.ORGANIZATIONS_GROUP}" | ||
) | ||
await self.send_message(user, text) | ||
event = models.MessageHistory.Event.REQUEST_CANCELED.value | ||
await self.send_message(user, text, event) | ||
|
||
async def notify_approved_task(self, user: models.User, report: models.Report, shift: models.Shift) -> None: | ||
"""Уведомление участника о проверенном задании. | ||
|
@@ -107,7 +115,8 @@ async def notify_approved_task(self, user: models.User, report: models.Report, s | |
text = f"Твой отчет от {photo_date} принят! Тебе начислен 1 \"ломбарьерчик\". " | ||
if date.today() < shift.finished_at: | ||
text = text + f"Следующее задание придет в {settings.formatted_task_time} часов утра." | ||
await self.send_message(user, text) | ||
event = models.MessageHistory.Event.TASK_ACCEPTED.value | ||
await self.send_message(user, text, event) | ||
|
||
async def notify_declined_task(self, user: models.User, shift: models.Shift) -> None: | ||
"""Уведомление участника о проверенном задании. | ||
|
@@ -120,7 +129,8 @@ async def notify_declined_task(self, user: models.User, shift: models.Shift) -> | |
) | ||
if date.today() < shift.finished_at: | ||
text = text + f"Ты можешь отправить отчет повторно до {settings.formatted_task_time} часов утра." | ||
await self.send_message(user, text) | ||
event = models.MessageHistory.Event.TASK_NOT_ACCEPTED.value | ||
await self.send_message(user, text, event) | ||
|
||
async def notify_excluded_members(self, members: list[models.Member]) -> None: | ||
"""Уведомляет участников об исключении из смены.""" | ||
|
@@ -131,11 +141,13 @@ async def notify_excluded_members(self, members: list[models.Member]) -> None: | |
"Если Вы считаете, что произошла ошибка - обращайтесь " | ||
f"за помощью на электронную почту {settings.ORGANIZATIONS_EMAIL}." | ||
) | ||
send_message_tasks = [self.send_message(member.user, text) for member in members] | ||
event = models.MessageHistory.Event.EXCLUDE_FROM_SHIFT.value | ||
send_message_tasks = [self.send_message(member.user, text, event) for member in members] | ||
self.__bot_application.create_task(asyncio.gather(*send_message_tasks)) | ||
|
||
async def notify_that_shift_is_finished(self, shift: models.Shift) -> None: | ||
"""Уведомляет активных участников об окончании смены.""" | ||
event = models.MessageHistory.Event.SHIFT_ENDED.value | ||
send_message_tasks = [ | ||
self.send_message( | ||
member.user, | ||
|
@@ -145,19 +157,22 @@ async def notify_that_shift_is_finished(self, shift: models.Shift) -> None: | |
numbers_lombaryers=member.numbers_lombaryers, | ||
lombaryers_case=get_lombaryers_for_quantity(member.numbers_lombaryers), | ||
), | ||
event, | ||
) | ||
for member in shift.members | ||
] | ||
self.__bot_application.create_task(asyncio.gather(*send_message_tasks)) | ||
|
||
async def notify_that_shift_is_cancelled(self, users: list[models.User], final_message: str) -> None: | ||
"""Уведомляет пользователей об отмене смены.""" | ||
send_message_tasks = [self.send_message(user, final_message) for user in users] | ||
event = models.MessageHistory.Event.SHIFT_CANCELED.value | ||
send_message_tasks = [self.send_message(user, final_message, event) for user in users] | ||
self.__bot_application.create_task(asyncio.gather(*send_message_tasks)) | ||
|
||
async def notify_that_shift_start_date_is_changed( | ||
self, users: list[models.User], start_date_changed_message: str | ||
) -> None: | ||
"""Уведомляет пользователей о переносе даты старта смены.""" | ||
send_message_tasks = [self.send_message(user, start_date_changed_message) for user in users] | ||
event = models.MessageHistory.Event.START_SHIFT_CHANGED.value | ||
send_message_tasks = [self.send_message(user, start_date_changed_message, event) for user in users] | ||
self.__bot_application.create_task(asyncio.gather(*send_message_tasks)) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
"""add model MessageHistory | ||
|
||
Revision ID: 707f448b5271 | ||
Revises: 2c304127881b | ||
Create Date: 2023-05-03 12:17:31.013484 | ||
|
||
""" | ||
import sqlalchemy as sa | ||
from alembic import op | ||
from sqlalchemy.dialects import postgresql | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = '707f448b5271' | ||
down_revision = '2c304127881b' | ||
branch_labels = None | ||
depends_on = None | ||
|
||
STATUS_ENUM_POSTGRES = postgresql.ENUM( | ||
'registration', | ||
'get_task', | ||
'report_mention', | ||
'request_accepted', | ||
'request_canceled', | ||
'task_accepted', | ||
'task_not_accepted', | ||
'exclude_from_shift', | ||
'shift_ended', | ||
'shift_canceled', | ||
'start_shift_changed', | ||
name='message_history_event', | ||
create_type=False | ||
) | ||
STATUS_ENUM = sa.Enum( | ||
'registration', | ||
'get_task', | ||
'report_mention', | ||
'request_accepted', | ||
'request_canceled', | ||
'task_accepted', | ||
'task_not_accepted', | ||
'exclude_from_shift', | ||
'shift_ended', | ||
'shift_canceled', | ||
'start_shift_changed', | ||
name='message_history_event' | ||
) | ||
STATUS_ENUM.with_variant(STATUS_ENUM_POSTGRES, 'postgresql') | ||
|
||
def upgrade(): | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.create_table('message_history', | ||
sa.Column('user_id', sa.UUID(), nullable=True), | ||
sa.Column('message', sa.String(length=400), nullable=False), | ||
sa.Column('chat_id', sa.BigInteger(), nullable=False), | ||
sa.Column('event', STATUS_ENUM, nullable=False), | ||
sa.Column('shift_id', sa.UUID(), nullable=True), | ||
sa.Column('id', sa.UUID(), nullable=False), | ||
sa.Column('created_at', sa.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), | ||
sa.Column('updated_at', sa.TIMESTAMP(), server_default=sa.text('CURRENT_TIMESTAMP'), nullable=False), | ||
sa.ForeignKeyConstraint(['shift_id'], ['shifts.id'], ), | ||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), | ||
sa.PrimaryKeyConstraint('id') | ||
) | ||
# ### end Alembic commands ### | ||
|
||
|
||
def downgrade(): | ||
# ### commands auto generated by Alembic - please adjust! ### | ||
op.drop_table('message_history') | ||
STATUS_ENUM.drop(op.get_bind(), checkfirst=True) | ||
# ### end Alembic commands ### |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -301,3 +301,36 @@ class AdministratorInvitation(Base): | |
|
||
def __repr__(self) -> str: | ||
return f"<AdministratorInvitation: {self.id}, email: {self.email}, surname: {self.surname}, name: {self.name}>" | ||
|
||
|
||
class MessageHistory(Base): | ||
"""Хрениние истории отправленных сообщений.""" | ||
|
||
class Event(str, enum.Enum): | ||
"""Статус отправленного сообщения.""" | ||
|
||
REGISTRATION = "registration" | ||
GET_TASK = "get_task" | ||
REPORT_MENTION = "report_mention" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Именование статусов потом нужно будет пересмотреть. Не все удачные. |
||
REQUEST_ACCEPTED = "request_accepted" | ||
REQUEST_CANCELED = "request_canceled" | ||
TASK_ACCEPTED = "task_accepted" | ||
TASK_NOT_ACCEPTED = "task_not_accepted" | ||
EXCLUDE_FROM_SHIFT = "exclude_from_shift" | ||
SHIFT_ENDED = "shift_ended" | ||
SHIFT_CANCELED = "shift_canceled" | ||
START_SHIFT_CHANGED = "start_shift_changed" | ||
|
||
__tablename__ = 'message_history' | ||
|
||
user_id = Column(UUID(as_uuid=True), ForeignKey(User.id)) | ||
message = Column(String(400), nullable=False) | ||
chat_id = Column(BigInteger, nullable=False) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Зачем нам chat_id? Он же совпадает с user.telegram_id. Нам нужно сохранять message_id, чтобы позже можно было получить доступ к этому сообщению. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. что подразумевается под message_id это primary key данной таблицы или надо сообщение выносить в отдельную таблицу? |
||
event = Column( | ||
Enum(Event, name="message_history_event", values_callable=lambda obj: [e.value for e in obj]), | ||
nullable=False, | ||
) | ||
shift_id = Column(UUID(as_uuid=True), ForeignKey(Shift.id)) | ||
|
||
def __repr__(self) -> str: | ||
return f"<MessageHistory: {self.user_id} - {self.status}" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from fastapi import Depends | ||
from sqlalchemy.ext.asyncio import AsyncSession | ||
|
||
from src.core.db.db import get_session | ||
from src.core.db.models import MessageHistory | ||
from src.core.db.repository import AbstractRepository | ||
|
||
|
||
class MessageHistoryRepository(AbstractRepository): | ||
"""Класс для работы с моделью HistoryMessage.""" | ||
|
||
def __init__(self, session: AsyncSession = Depends(get_session)) -> None: | ||
super().__init__(session, MessageHistory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Сюда можно попасть, если принять участие в одной смене и потом подавать заявку на участие в новой смене.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Путаница, где-то event, а ниже status.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Так неправильно передавать значение status='update_data', лучше так MessageHistory.Event.REGISTRATION.value