-
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?
Conversation
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.
Честно говоря, не вижу проблемы.
Создал тестовый эндпойнт и нормально отработало.
Так же и в боте.
async def get_history_service(sessions):
async for session in sessions: # noqa R503
history_repository = MessageHistoryRepository(session)
shift_repository = ShiftRepository(session)
return MessageHistoryService(history_repository, shift_repository)
async def send_daily_task_job(context: CallbackContext) -> None:
history_session = get_session()
history_service = await get_history_service(history_session)
await history_service.create_history_message(
user_id="36a9496b-21fc-4e69-b071-bfcc61d1821f",
chat_id=123,
message="Test",
status=MessageHistory.Status.STATUS_OF_CHECKED_TASK
)
Ругается на отсутствие таблицы и статуса. Если добавить и применить миграцию, всё будет работать.
src/core/db/models.py
Outdated
class MessageHistory(Base): | ||
"""Хрениние истории отправленных сообщений.""" | ||
|
||
class Status(str, enum.Enum): |
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. Он нужен для последующей сортировки по типу события.
|
||
REGISTRATION = "registration" | ||
GET_TASK = "get_task" | ||
REPORT_MENTION = "report_mention" |
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.
Именование статусов потом нужно будет пересмотреть. Не все удачные.
src/core/db/models.py
Outdated
__tablename__ = 'message_history' | ||
|
||
user_id = Column(UUID(as_uuid=True), ForeignKey(User.id), nullable=False) | ||
message = Column(Text, nullable=False) |
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.
Лучше String. Нужно посмотреть максимальную длину наших сообщений и сделать в 2 раза больше. Этого будет достаточно.
src/core/db/models.py
Outdated
Enum(Status, name="message_history_status", values_callable=lambda obj: [e.value for e in obj]), | ||
nullable=False, | ||
) | ||
shift_id = Column(UUID(as_uuid=True), ForeignKey(Shift.id), nullable=False) |
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.
Нужно добавить метод repr
|
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.
В текущем варианте запись в БД создаётся, но нужно при создании экземпляра MessageHistory передавать параметры в правильной последовательности. И в shift_id я просто передал id реально существующей смены, поскольку когда человек получает стартовое сообщение активной смены может ещё не быть.
src/bot/handlers.py
Outdated
user = await user_service.get_user_by_telegram_id(update.effective_chat.id) | ||
context.user_data["user"] = user | ||
if user and user.telegram_blocked: | ||
await user_service.unset_telegram_blocked(user) | ||
await context.bot.send_message(chat_id=update.effective_chat.id, text=start_text) | ||
if user: | ||
await history_service.create_history_message( | ||
user.id, update.effective_chat.id, start_text, status="registration" |
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.
Здесь статус надо подставлять в виде MessageHistory.Status.REGISTRATION. Хотя писал в прошлый раз, что не статус а событие.
src/bot/api_services.py
Outdated
@@ -58,3 +60,11 @@ async def get_shift_service_callback(sessions): | |||
shift_repository, task_service, report_repository, user_repository, request_repository | |||
) | |||
return shift_service | |||
|
|||
|
|||
async def get_history_service_callback(sessions): |
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.
Здесь callback не нужен в названии. У других функций потом тоже уберём.
|
…aryery_backend into feature/add_message_history
…aryery_backend into feature/add_message_history
…equestService ShiftService
src/bot/handlers.py
Outdated
@@ -66,8 +69,14 @@ async def start(update: Update, context: CallbackContext) -> None: | |||
) | |||
return | |||
await update_user_data(update, context) | |||
# не знаю как сюда попасть чтобы проверить | |||
await history_service.create_history_message( |
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
src/bot/services.py
Outdated
|
||
@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 comment
The reason will be displayed to describe this comment to others. Learn more.
Event не строка, а enum из модели.
src/core/db/models.py
Outdated
|
||
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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
что подразумевается под message_id это primary key данной таблицы или надо сообщение выносить в отдельную таблицу?
src/bot/jobs.py
Outdated
@@ -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 comment
The reason will be displayed to describe this comment to others. Learn more.
Подставляй событие сразу сюда. Иначе, приходится возвращаться назад, чтобы узнать, какое событие будет.
|
||
async def create_history_message(self, user_id, message_id, message, event) -> None: | ||
try: | ||
shift = await self.__shift_repository.get_started_shift_id() |
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.
Лучше смену передавать в качестве параметра. Сейчас, и так не оптимальный вариант сохранения истории. Каждое сообщение сохраняется отдельным запросом в БД. А так добавляется ещё один запрос, для получения смены, т.е. 2 запроса на каждое сообщение. :(
…aryery_backend into feature/add_message_history
…aryery_backend into feature/add_message_history
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.
По ошибке, не вижу очевидных проблем. Попробую завтра поэкспериментировать.
src/bot/handlers.py
Outdated
else: | ||
await register_user(update, context) | ||
await history_service.create_history_message(user, message.message_id, start_text, event) |
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.
Здесь точно user = None
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.
Это я знаю поэтому и написал user, а не user.id или как-то по другому надо, немного не понял если честно. Сделать как со сменой если не передать юзера то по умолчанию None ?
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.
Тут получается что функция register только форму с регистрацией кидает, но еще пользователя в базу не сохраняет, это как-то пометить надо будет в event? событие перед формой регистрации?
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.
я убрал и после update и после register, я написал вызов в функцию web_app_data там как я понял и обновление данных обрабатывается и регистрация
src/bot/jobs.py
Outdated
members = await member_service.get_members_with_no_reports() | ||
if members: |
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.
Поле shift_id обязательное у модели Member, поэтому эта проверка не имеет смысла. Можно ниже просто подставлять member.shift_id.
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.
Поле у Member обязательное, а если список пустой будет то ошибка вылетит. Как раз и проверяю, что список не пустой такое наверно маловероятно, но наверное возможно
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.
Всё просто. Если в members придёт пустой список, то генератор списка также вернёт пустой список. А если не пустой, то смену возьмёт из member, как я написал выше.
send_message_tasks = [
bot_service.send_message(
member.user,
(
f"{member.user.name} {member.user.surname}, мы потеряли тебя! "
f"Задание все еще ждет тебя. "
f"Напоминаем, что за каждое выполненное задание ты получаешь виртуальные "
f"\"ломбарьерчики\", которые можешь обменять на призы и подарки!"
),
MessageHistory.Event.REPORT_MENTION,
member.shift_id,
)
for member in members
]
Так точно ошибки не будет.
Твой вариант будет совсем немного быстрее, но менее очевиден. Возникает вопрос, почему смену выделили отдельно и именно у первого элемента списка. Это какой-то особый случай... Непонятно.
src/bot/jobs.py
Outdated
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) | ||
if members: |
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.
Здесь так же.
|
||
async def create_history_message(self, user_id, message_id, message, event, shift_id=None) -> None: | ||
history_message = MessageHistory( | ||
user_id=user_id, message_id=message_id, message=message, event=event, shift_id=shift_id |
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.
Если я их делаю не позиционными, то у меня с ошибкой падает и говорит, что я передаю 6 аргументов, а он хочет всего один
src/bot/services.py
Outdated
if user.telegram_blocked: | ||
return | ||
chat_id = user.telegram_id | ||
try: | ||
await self.__bot.send_message(chat_id=chat_id, text=text) | ||
# Тут я хотел написать код который записывал бы в БД после отправки сообщения |
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.
Вот тут у меня самая главная проблема я не могу вызвать это метод чтобы сохранить сообщение, пытался сделать как в закоментированном коде, но так не получается сделать, пытался добавить атрабутом объект класса таким образовм history_service: MessageHistoryService = Depends() так тоже не получается
src/core/db/models.py
Outdated
|
||
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 comment
The reason will be displayed to describe this comment to others. Learn more.
что подразумевается под message_id это primary key данной таблицы или надо сообщение выносить в отдельную таблицу?
src/bot/jobs.py
Outdated
members = await member_service.get_members_with_no_reports() | ||
if members: |
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.
Поле у Member обязательное, а если список пустой будет то ошибка вылетит. Как раз и проверяю, что список не пустой такое наверно маловероятно, но наверное возможно
src/bot/handlers.py
Outdated
else: | ||
await register_user(update, context) | ||
await history_service.create_history_message(user, message.message_id, start_text, event) |
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.
Это я знаю поэтому и написал user, а не user.id или как-то по другому надо, немного не понял если честно. Сделать как со сменой если не передать юзера то по умолчанию None ?
…aryery_backend into feature/add_message_history
…aryery_backend into feature/add_message_history
Нужна помощь или подсказка. Получается сохранять данные об отправленных сообщениях в БД, но иногда вылазить такое предупреждение:
sys:1: SAWarning: The garbage collector is trying to clean up non-checked-in connection <AdaptedConnection
<asyncpg.connection.Connection object at 0x00000188D3A96EA0>>, which will be terminated. Please ensure that
SQLAlchemy pooled connections are returned to the pool explicitly, either by calling
close()
or by using appropriate context managers to manage their lifecycle