From 502c07a2c93e1e3facbf4b0b0502f6a9d59ff4b7 Mon Sep 17 00:00:00 2001 From: KatykhinAA Date: Sat, 16 Nov 2024 18:45:05 +0300 Subject: [PATCH 1/7] some fix --- database/db.py | 141 ++++++++++++++---- .../handlers/private/private_handlers.py | 46 +++--- .../__pycache__/__init__.cpython-312.pyc | Bin 264 -> 264 bytes .../base_dependency_factory.cpython-312.pyc | Bin 2272 -> 2272 bytes .../__pycache__/helper_func.cpython-312.pyc | Bin 17749 -> 21000 bytes .../utils/__pycache__/state.cpython-312.pyc | Bin 703 -> 703 bytes helper_bot/utils/helper_func.py | 53 +++++++ tests/test_db.py | 8 +- .../{voice_handler => handlers}/__init__.py | 0 .../voice_handler.py | 22 +-- voice_bot/main.py | 2 +- 11 files changed, 206 insertions(+), 66 deletions(-) rename voice_bot/{voice_handler => handlers}/__init__.py (100%) rename voice_bot/{voice_handler => handlers}/voice_handler.py (93%) diff --git a/database/db.py b/database/db.py index ce6621d..999b796 100644 --- a/database/db.py +++ b/database/db.py @@ -100,27 +100,8 @@ class BotDB: finally: self.close() - # TODO: Deprecated. Остался только в voice боте, удалить и оттуда - def get_error_message_from_db(self, id: int): - """ - @deprecated - Функция для запроса к базе данных и получения сообщений ошибки. В аргументы передаются: - id - идентификатор ошибки - """ - # Подключаемся к базе - try: - self.connect() - self.cursor.execute(f"SELECT * FROM error_messages WHERE id=?", (id,)) - response_from_database = str(self.cursor.fetchone()[1]) - return response_from_database - except sqlite3.Error as error: - self.logger.error(f"Ошибка при получении сообщения об ошибка voice_bot: {error}") - finally: - self.close() - def add_new_user_in_db(self, user_id: int, first_name: str, full_name: str, username: str, is_bot: bool, - language_code: str, date_added: str, - date_changed: str): + language_code: str, emoji: str, date_added: str, date_changed: str): """ Добавляет нового пользователя в базу данных. @@ -131,6 +112,7 @@ class BotDB: username (str): Username пользователя в Telegram. is_bot (bool): Флаг, указывающий, является ли пользователь ботом. language_code (str): Код языка пользователя. + emoji (str): Эмодзи закрепленная за пользователем date_added (str): Дата добавления пользователя в базу. date_changed (str): Дата последнего изменения данных пользователя. @@ -142,11 +124,12 @@ class BotDB: try: self.connect() self.cursor.execute("INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', " - "'language_code', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + "'language_code', 'emoji', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", (user_id, first_name, full_name, - username, is_bot, language_code, date_added, date_changed)) + username, is_bot, language_code, emoji, date_added, date_changed)) self.conn.commit() - self.logger.info(f"Новый пользователь добавлен в базу: user_id={user_id}, first_name={first_name}") + self.logger.info( + f"Новый пользователь добавлен в базу: user_id={user_id}, first_name={first_name}, emoji={emoji}") return None except sqlite3.Error as error: self.logger.error(f"Ошибка при добавлении пользователя в базу: {error}. " @@ -675,15 +658,15 @@ class BotDB: def update_date_for_user(self, date: str, user_id: int): """ #TODO: Не возвращается ошибка sqlite3. Error. Тест не перехватывает. Возвращается no such table: our_users - Обновляет дату последнего изменения данных пользователя в базе. + Обновляет дату последнего изменения данных пользователя в базе Args: - date (str): Новая дата изменения. - user_id (int): Идентификатор пользователя в Telegram. + date (str): Новая дата изменения + user_id (int): Идентификатор пользователя в Telegram Returns: - None: Если обновление прошло успешно. - sqlite3. Error: Если произошла ошибка при выполнении запроса. + None: Если обновление прошло успешно + sqlite3. Error: Если произошла ошибка при выполнении запроса """ self.logger.info(f"Запуск функции update_date_for_user: user_id={user_id}, date={date}") try: @@ -699,6 +682,106 @@ class BotDB: finally: self.close() + def check_emoji(self, emoji: str): + """ + Проверяет, есть ли уже такой emoji в таблице. + + Args: + emoji: emoji для проверки. + + Returns: + True, если эмодзи уже есть, иначе False. + + Raises: + None: В случае ошибки возвращается None + """ + self.logger.info(f"Запуск функции check_emoji: emoji={emoji}") + try: + self.connect() + self.cursor.execute("SELECT 1 FROM our_users WHERE emoji = ?", (emoji,)) + result = self.cursor.fetchone() + return bool(result) + except sqlite3.Error as error: + self.logger.error(f"Ошибка проверки эмодзи в базе: {error}") + return None + finally: + self.close() + + def update_emoji_for_user(self, user_id: int, emoji: str): + """ + Обновляет эмодзи для пользователя в базе если его ранее не было установлено + + Args: + user_id (int): Идентификатор пользователя в Telegram + emoji (str): Эмодзи пользователя + + Returns: + None: Если обновление прошло успешно + sqlite3. Error: Если произошла ошибка при выполнении запроса + """ + self.logger.info(f"Запуск функции update_date_for_user: user_id={user_id}, emoji={emoji}") + try: + self.connect() + self.cursor.execute("UPDATE our_users SET emoji = ? WHERE user_id = ?", + (emoji, user_id,)) + self.conn.commit() + self.logger.info(f"Эмоджи обновлен для пользователя: user_id={user_id}") + return None + except sqlite3.Error as error: + self.logger.error(f"Ошибка обновления эмодзи для пользователя: {error}") + return error + finally: + self.close() + + def check_emoji_for_user(self, user_id: int): + """ + Проверяет, есть ли уже у пользователя назначенный emoji. + + Args: + user_id: user_id пользователя. + + Returns: + True, если эмодзи такого нет, иначе False. + + Raises: + None: В случае ошибки возвращается None + """ + self.logger.info(f"Запуск функции check_emoji_for_user: user_id={user_id}") + try: + self.connect() + self.cursor.execute("SELECT emoji FROM our_users WHERE user_id = ?", (user_id,)) + result = self.cursor.fetchone()[0] + return result + except sqlite3.Error as error: + self.logger.error(f"Ошибка проверки эмодзи в базе: {error}") + return None + finally: + self.close() + + def refresh_listen_audio(self, user_id: int): + """ + Очищает всю информацию о прослушанных аудио пользователем + + Args: + user_id: user_id пользователя. + + Returns: + None - если все очищено успешно + + Raises: + error: В случае ошибки возвращается error + """ + self.logger.info(f"Запуск функции check_emoji_for_user: user_id={user_id}") + try: + self.connect() + self.cursor.execute("DELETE FROM listen_audio_users WHERE user_id = ?", (user_id,)) + return None + except sqlite3.Error as error: + self.logger.error(f"Ошибка проверки эмодзи в базе: {error}") + return error + finally: + self.close() + def is_admin(self, user_id: int): """ Проверяет, является ли пользователь администратором. @@ -719,7 +802,7 @@ class BotDB: result = self.cursor.fetchone() return bool(result) except sqlite3.Error as error: - self.logger.error(f"Ошибка добавления сообщения в базу данных: {error}") + self.logger.error(f"Ошибка проверки прав пользователя админа: {error}") return None finally: self.close() diff --git a/helper_bot/handlers/private/private_handlers.py b/helper_bot/handlers/private/private_handlers.py index d0ab731..22b2381 100644 --- a/helper_bot/handlers/private/private_handlers.py +++ b/helper_bot/handlers/private/private_handlers.py @@ -17,8 +17,9 @@ from helper_bot.middlewares.blacklist_middleware import BlacklistMiddleware from helper_bot.utils import messages from helper_bot.utils.base_dependency_factory import BaseDependencyFactory from helper_bot.utils.helper_func import get_first_name, get_text_message, send_text_message, send_photo_message, \ - send_media_group_message_to_private_chat, prepare_media_group_from_middlewares, check_username_and_full_name, \ - send_video_message, send_video_note_message, send_audio_message, send_voice_message, add_in_db_media + send_media_group_message_to_private_chat, prepare_media_group_from_middlewares, send_video_message, \ + send_video_note_message, send_audio_message, send_voice_message, add_in_db_media, \ + update_user_info, check_user_emoji from logs.custom_logger import logger private_router = Router() @@ -39,6 +40,24 @@ TEST = bdf.settings['Settings']['test'] BotDB = bdf.get_db() +@private_router.message( + ChatTypeFilter(chat_type=["private"]), + Command("restart") +) +async def handle_restart_message(message: types.Message, state: FSMContext): + try: + markup = get_reply_keyboard(BotDB, message.from_user.id) + await message.forward(chat_id=GROUP_FOR_LOGS) + await state.set_state("START") + await update_user_info('love', message) + check_user_emoji(message.from_user.id) + await message.answer('Я перезапущен!', reply_markup=markup, parse_mode='HTML') + except Exception as e: + logger.error(f"Произошла ошибка handle_restart_message. Ошибка:{str(e)}") + await message.bot.send_message(chat_id=IMPORTANT_LOGS, + text=f"Произошла ошибка handle_restart_message: {str(e)}\n\nTraceback:\n{traceback.format_exc()}") + + @private_router.message( ChatTypeFilter(chat_type=["private"]), Command("start") @@ -50,27 +69,8 @@ BotDB = bdf.get_db() async def handle_start_message(message: types.Message, state: FSMContext): try: await message.forward(chat_id=GROUP_FOR_LOGS) - full_name = message.from_user.full_name - username = message.from_user.username - first_name = get_first_name(message) - is_bot = message.from_user.is_bot - language_code = message.from_user.language_code - user_id = message.from_user.id - current_date = datetime.now() - date = current_date.strftime("%Y-%m-%d %H:%M:%S") - if not BotDB.user_exists(user_id): - BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, date, - date) - else: - is_need_update = check_username_and_full_name(user_id, username, full_name) - if is_need_update: - BotDB.update_username_and_full_name(user_id, username, full_name) - await message.answer( - f"Давно не виделись! Вижу что ты изменился;) Теперь буду звать тебя: {full_name} и ник @{username}") - await message.bot.send_message(chat_id=GROUP_FOR_LOGS, - text=f'Для пользователя: {user_id} обновлены данные в БД.\nНовое имя: {full_name}\nНовый ник:{username}') - sleep(1) - BotDB.update_date_for_user(date, user_id) + await update_user_info('love', message) + check_user_emoji(message.from_user.id) await state.set_state("START") logger.info( f"Формирование приветственного сообщения для пользователя. Сообщение: {message.text} " diff --git a/helper_bot/keyboards/__pycache__/__init__.cpython-312.pyc b/helper_bot/keyboards/__pycache__/__init__.cpython-312.pyc index f1c797eadcdec538b8fae329838ecd1b76e03c34..3e943c6ec5ceb1923100a929e666e9b0ca7629b7 100644 GIT binary patch delta 20 acmeBR>R{qI&CAQh00i$OOw%Xw`~d(jh6PIi delta 20 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 delta 3404 zcmaJ^Yit}>6`s30voG80*LrQQ9cS%qVvp^(cG4s!ek68Ds2e#^DgnuW*o^m%ovn9v zmOHzluBbLb0ZLQ|?NwDIP^nOV@DzfT!XG45iGLtbDMd&VP(h*<;!i91Q-OG#b7s5Q z&0{U?x#ymH@44T3-th}>u;1Tg@!xcH#T57p-i`0Pee$LFP<1Y-D6cA9;jEw-{>Tgl z^FSeB2aJFnG=dD}!GdaQhDN+v2-#sHY)6cU9W|nM%!rX(D|FbMMkn#1LYEyk;!FuB zR_BlKQus5vt?p;WeV(YC)gtoxa=2>r^01{nlWAJ3vpiz;Z>v0dLp2gSX7%$9_;rFT z#JfN?@W^vpxKV_F;Fwn7Rvs1w(vBZKhXC4`28U6-A_OO!~`hGv{iDTEr<-9 zKgbVSDTw+Z2+birN&FP>lUyf$8u%$b19>o`*SF4sXc~D;F@BgLI|s5E{upeV-DCPu z*`tojlj^SgmHN|AC*T$RvaIE_0bqONAGIacUmFVjJ#ci8){qPVaiP+bbUG~(FnT>Z zRykX?o-Jo>%XQ5iON@YcKpu-0S+e#nmP%HU zix7$Bb-XfWBEEP`JconOUTr~w1!E3rnWKAs~&p{ z*dH*u>%4z0-l#{sSl#k$o{JM8YQi)nZw(({3$ivmn_kAHhTUYbi{Qvy@TUCVa9TSH z0=Je)y{T34K5-gI(`}x1&B^C1-^|#xJhz-|(J5Pctoc$rxQ^rrBx^{>IZq;o9ugZs z^q}}S^5ncUaIJxrJl(531>zTL&!zVTLQBBrg7WlyqV}_iMOHlrbAj;?2vm;>Y;@NgfV3V`R(a!3qPOJ2eYeS~PieVO6OtC?x- zA}su{_G;!I!GS}#`zR7J^*D0#^0lc$Hu-TA=HR3-ia&+~6U|QxjDgpC7P9cXQ$Fid ziu?>FslbF4(?|&DdEoR2S?Pm(8keXv$O~zl&d3FQ5K?DDAJ;wwg4;Dm9|ZgE_I}r6pnFFlXODb9l@v|U*TP9|2 zvw8W}++9CnWD6FJuKG7L1j0aRz>i~$)RnF}Wv2xSm0K&GmLx_fefQ2bnnG5A_wzkD zIrn|21^~m!1#~x6Q8O3{;DcZ&+grfU#x`JN_xwSc`Q}qIG_-vEV;SH!A)I@1=gyQg^iRp{9bidT{AfBe+Fam<1573(Vh? z53ehKmfv3JlK*|&WLM>tW3OMpZsbMsZr0>>z6f2^0f7rgl=?H$nY(J`cC%(K2d{`g zJCf-sfM6!0__({gf^5%&dptnyfLdm^v<>n^_ z;}AIXB)!YxoAUit9Xv67YC?Mjq!oGk)FOCd@6-xo*W@owUmpAtDv1hw!NnJlJd0#q zPOeRbGRS^LesXR9r9EIht?Y1f&+D!fw+c>f*W%fGzN1^cC>dTf;r+wLie7|2|GOX# z$IK!=PWkOTy!x-fhUesO*Iv4ee$bhxh;C#8;=3@M*AI&x7{vqgW+X6_x+qoU7u$1zuml*>UG`6}RlzS>WNTgxa|m+~V6_2tQfi z5u&6FZ~C7tUeGNIF@TEj1IGXIz}KH1CV>y37t9ySo?6Jm&WkwL%9Rp)yI`aD`k%H+ zg}rlCYj4Xj1>ZEqZlxr!1qc1k(w!Ijr^{z7fj&kXaa_L>=sXr+P{}LLx W6WVt@So_I^$w2I%u@1IGD*q4E47<_* diff --git a/helper_bot/utils/__pycache__/state.cpython-312.pyc b/helper_bot/utils/__pycache__/state.cpython-312.pyc index 9b45a9df5b9b93a8cdba9ec41109cf56a8fb9ca7..79328a961a69e909d0a839819b4ebd2c75f0403c 100644 GIT binary patch delta 21 bcmdnbx}TNjG%qg~0}#BEFiqdcvzZA1J{len(check_audio)}', reply_markup=markup) await state.set_state('START') diff --git a/voice_bot/main.py b/voice_bot/main.py index 199d2f7..c2990f2 100644 --- a/voice_bot/main.py +++ b/voice_bot/main.py @@ -3,7 +3,7 @@ from aiogram.client.default import DefaultBotProperties from aiogram.fsm.storage.memory import MemoryStorage from aiogram.fsm.strategy import FSMStrategy -from voice_bot.voice_handler.voice_handler import voice_router +from voice_bot.handlers.voice_handler import voice_router async def start_bot(bdf): From e0e0a6de51948d29d4bd577f0a239555ffb84d1e Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 17 Nov 2024 00:50:55 +0300 Subject: [PATCH 2/7] add new func in voice bot --- database/db.py | 70 +++++++++++++++++++- helper_bot/utils/helper_func.py | 2 +- requirements.txt | 45 +++++++------ voice_bot/handlers/callback_handler.py | 68 +++++++++++++++++++ voice_bot/handlers/voice_handler.py | 92 +++++++++++++++----------- voice_bot/keyboards/keyboards.py | 14 +++- voice_bot/main.py | 3 +- voice_bot/utils/helper_func.py | 3 + 8 files changed, 229 insertions(+), 68 deletions(-) create mode 100644 voice_bot/handlers/callback_handler.py diff --git a/database/db.py b/database/db.py index 999b796..c7c2361 100644 --- a/database/db.py +++ b/database/db.py @@ -719,7 +719,7 @@ class BotDB: None: Если обновление прошло успешно sqlite3. Error: Если произошла ошибка при выполнении запроса """ - self.logger.info(f"Запуск функции update_date_for_user: user_id={user_id}, emoji={emoji}") + self.logger.info(f"Запуск функции update_emoji_for_user: user_id={user_id}, emoji={emoji}") try: self.connect() self.cursor.execute("UPDATE our_users SET emoji = ? WHERE user_id = ?", @@ -750,8 +750,12 @@ class BotDB: try: self.connect() self.cursor.execute("SELECT emoji FROM our_users WHERE user_id = ?", (user_id,)) - result = self.cursor.fetchone()[0] - return result + pre_result = self.cursor.fetchone() + if pre_result[0] is not None: + print(f'Результат функции check_emoji_for_user - {str(pre_result[0])}') + return str(pre_result[0]) + else: + return None except sqlite3.Error as error: self.logger.error(f"Ошибка проверки эмодзи в базе: {error}") return None @@ -1046,6 +1050,48 @@ class BotDB: except Exception as e: self.logger.error(f"Ошибка в функции get_author_id_by_helper_message_id {str(e)}") + def get_user_id_by_message_id_for_voice_bot(self, message_id: int): + self.logger.info(f"Запуск функции get_user_id_by_message_id_for_voice_bot, идентификатор поста " + f"{message_id}") + try: + self.connect() + result = self.cursor.execute("SELECT user_id " + "FROM audio_moderate WHERE message_id = ?", + (message_id,)) + user_id = result.fetchone()[0] + self.logger.info(f"Функция get_user_id_by_message_id_for_voice_bot получила author_id {user_id}") + return user_id + except Exception as e: + self.logger.error(f"Ошибка в функции get_user_id_by_message_id_for_voice_bot {str(e)}") + + def set_user_id_and_message_id_for_voice_bot(self, message_id: int, user_id: int): + self.logger.info(f"Запуск функции set_user_id_and_message_id_for_voice_bot, идентификатор поста " + f"{message_id}, user_id {user_id}") + try: + self.connect() + result = self.cursor.execute( + "INSERT INTO audio_moderate (message_id, user_id)" + "VALUES (?, ?)", (message_id, user_id)) + self.conn.commit() + self.logger.info(f"Функция set_user_id_and_message_id_for_voice_bot отработала успешно") + return True + except Exception as e: + self.logger.error(f"Ошибка в функции set_user_id_and_message_id_for_voice_bot {str(e)}") + + def get_user_id_by_file_name(self, file_name: str): + self.logger.info(f"Запуск функции get_user_id_by_file_name, идентификатор поста " + f"{file_name}") + try: + self.connect() + result = self.cursor.execute("SELECT author_id " + "FROM audio_message_reference WHERE file_name = ?", + (file_name,)) + user_id = result.fetchone()[0] + self.logger.info(f"Функция get_user_id_by_file_name получила author_id {user_id}") + return user_id + except Exception as e: + self.logger.error(f"Ошибка в функции get_user_id_by_file_name {str(e)}") + def add_post_content_in_db(self, post_id: int, message_id: int, content_name: str, type_content: str): self.logger.info( f"Запуск функции add_post_content_in_db: post_id={post_id}, message_id={message_id}, " @@ -1156,6 +1202,24 @@ class BotDB: finally: self.close() + def delete_listen_count_for_user(self, user_id): + """Удаляет данные о прослушанных пользователем аудио""" + self.logger.info( + f"Запуск функции delete_listen_count_for_user. user_id={user_id}") + try: + self.connect() + self.cursor.execute("DELETE FROM `listen_audio_users` WHERE `user_id` = ?", + (user_id,)) + self.conn.commit() + self.logger.info( + f"Функция delete_listen_count_for_user успешно отработала") + return None + except sqlite3.Error as error: + self.logger.error(f"Ошибка удаления записей прослушивания по пользователю: {error}") + raise + finally: + self.close() + def get_id_for_audio_record(self, user_id): """Получает ID аудио сообщения пользователя""" self.logger.info( diff --git a/helper_bot/utils/helper_func.py b/helper_bot/utils/helper_func.py index 42b5d09..facd583 100644 --- a/helper_bot/utils/helper_func.py +++ b/helper_bot/utils/helper_func.py @@ -425,7 +425,7 @@ async def update_user_info(source: str, message: types.Message): def check_user_emoji(user_id: int): - if not BotDB.check_emoji_for_user(user_id=user_id): + if BotDB.check_emoji_for_user(user_id=user_id) is None: user_emoji = get_random_emoji() BotDB.update_emoji_for_user(user_id=user_id, emoji=user_emoji) diff --git a/requirements.txt b/requirements.txt index 6da9b91..9dea5b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,22 +1,23 @@ -APScheduler==3.10.4 -certifi~=2024.6.2 -charset-normalizer==3.3.2 -coverage==7.5.4 -exceptiongroup==1.2.1 -idna==3.7 -iniconfig==2.0.0 -loguru==0.7.2 -packaging==24.1 -pluggy==1.5.0 -pytest==8.2.2 -pytz==2024.1 -requests==2.32.3 -six==1.16.0 -tomli==2.0.1 -tzlocal==5.2 -urllib3~=2.2.1 -pip~=23.2.1 -attrs~=23.2.0 -typing_extensions~=4.12.2 -aiohttp~=3.9.5 -aiogram~=3.10.0 \ No newline at end of file +APScheduler==3.10.4 +certifi~=2024.6.2 +charset-normalizer==3.3.2 +coverage==7.5.4 +exceptiongroup==1.2.1 +idna==3.7 +iniconfig==2.0.0 +loguru==0.7.2 +packaging==24.1 +pluggy==1.5.0 +pytest==8.2.2 +pytz==2024.1 +requests==2.32.3 +six==1.16.0 +tomli==2.0.1 +tzlocal==5.2 +urllib3~=2.2.1 +pip~=23.2.1 +attrs~=23.2.0 +typing_extensions~=4.12.2 +aiohttp~=3.9.5 +aiogram~=3.10.0 +emoji~=2.14.0 \ No newline at end of file diff --git a/voice_bot/handlers/callback_handler.py b/voice_bot/handlers/callback_handler.py new file mode 100644 index 0000000..e79cbdd --- /dev/null +++ b/voice_bot/handlers/callback_handler.py @@ -0,0 +1,68 @@ +import time +from datetime import datetime +from pathlib import Path + +from aiogram import Router, F +from aiogram.types import CallbackQuery + +from helper_bot.utils.base_dependency_factory import BaseDependencyFactory + +callback_router = Router() + +bdf = BaseDependencyFactory() + +GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs'] +GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts'] +IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs'] +PREVIEW_LINK = bdf.settings['Telegram']['preview_link'] +LOGS = bdf.settings['Settings']['logs'] +TEST = bdf.settings['Settings']['test'] + +BotDB = bdf.get_db() + + +@callback_router.callback_query( + F.data == "save" +) +async def save_voice_message(call: CallbackQuery): + file_name = '' + file_id = 1 + user_id = BotDB.get_user_id_by_message_id_for_voice_bot(call.message.message_id) + # Проверяем что запись о файле есть в базе данных + is_having_audio_from_user = BotDB.get_last_user_audio_record(user_id=user_id) + if is_having_audio_from_user is False: + # Если нет, то генерируем имя файла + file_name = f'message_from_{user_id}_number_{file_id}' + else: + # Иначе берем последнюю запись из БД, добавляем к ней 1, и создаем новую запись + file_name = BotDB.get_path_for_audio_record(user_id=user_id) + file_id = BotDB.get_id_for_audio_record(user_id) + 1 + path = Path(f'voice_users/{file_name}.ogg') + if path.exists(): + file_name = f'message_from_{user_id}_number_{file_id}' + else: + pass + # Собираем инфо о сообщении + time_UTC = int(time.time()) + date_added = datetime.fromtimestamp(time_UTC) + + # Сохраняем в базку + BotDB.add_audio_record(file_name, user_id, date_added, 0, file_id) + + file_info = await call.message.bot.get_file(file_id=call.message.voice.file_id) + downloaded_file = await call.message.bot.download_file(file_path=file_info.file_path) + with open(f'voice_users/{file_name}.ogg', 'wb') as new_file: + new_file.write(downloaded_file.read()) + + await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id) + await call.answer(text='Сохранено!', cache_time=3) + + +@callback_router.callback_query( + F.data == "delete" +) +async def delete_voice_message(call: CallbackQuery): + # Получаем из базы автора + отправляем сообщение + удаляем сообщение из предложки + + await call.bot.delete_message(chat_id=GROUP_FOR_POST, message_id=call.message.message_id) + await call.answer(text='Удалено!', cache_time=3) diff --git a/voice_bot/handlers/voice_handler.py b/voice_bot/handlers/voice_handler.py index bdd385d..b571503 100644 --- a/voice_bot/handlers/voice_handler.py +++ b/voice_bot/handlers/voice_handler.py @@ -1,6 +1,5 @@ import random import time -from datetime import datetime from pathlib import Path from aiogram import Router, types, F @@ -11,9 +10,9 @@ from aiogram.types import FSInputFile from helper_bot.filters.main import ChatTypeFilter from helper_bot.middlewares.blacklist_middleware import BlacklistMiddleware from helper_bot.utils.base_dependency_factory import BaseDependencyFactory -from helper_bot.utils.helper_func import update_user_info, check_user_emoji +from helper_bot.utils.helper_func import update_user_info, check_user_emoji, send_voice_message from logs.custom_logger import logger -from voice_bot.keyboards.keyboards import get_main_keyboard +from voice_bot.keyboards.keyboards import get_main_keyboard, get_reply_keyboard_for_voice from voice_bot.utils.helper_func import last_message voice_router = Router() @@ -21,6 +20,7 @@ voice_router = Router() bdf = BaseDependencyFactory() GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs'] +GROUP_FOR_POST = bdf.settings['Telegram']['group_for_posts'] IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs'] PREVIEW_LINK = bdf.settings['Telegram']['preview_link'] LOGS = bdf.settings['Settings']['logs'] @@ -116,6 +116,22 @@ async def start(message: types.Message, state: FSMContext): disable_web_page_preview=not PREVIEW_LINK) +@voice_router.message( + ChatTypeFilter(chat_type=["private"]), + Command("refresh") +) +async def refresh_listen_function(message: types.Message, state: FSMContext): + await message.forward(chat_id=GROUP_FOR_LOGS) + await update_user_info('voice', message) + markup = get_main_keyboard() + check_user_emoji(message.from_user.id) + BotDB.delete_listen_count_for_user(message.from_user.id) + await message.answer( + text='Прослушивания очищены. Можешь начать слушать заново🤗', disable_web_page_preview=not PREVIEW_LINK, + markup=markup) + await state.set_state('START') + + @voice_router.message( StateFilter("START"), ChatTypeFilter(chat_type=["private"]), @@ -125,47 +141,33 @@ async def standup_write(message: types.Message, state: FSMContext): await message.forward(chat_id=GROUP_FOR_LOGS) markup = types.ReplyKeyboardRemove() await message.answer(text='Хорошо, теперь пришли мне свое голосовое сообщение', reply_markup=markup) - message_with_date = last_message() - await message.answer(text=message_with_date, parse_mode="html") + try: + message_with_date = last_message() + await message.answer(text=message_with_date, parse_mode="html") + except Exception as e: + logger.error(f'Не удалось получить дату последнего сообщения - {e}') await state.set_state('STANDUP_WRITE') @voice_router.message( StateFilter("STANDUP_WRITE"), - ChatTypeFilter(chat_type=["private"]) + ChatTypeFilter(chat_type=["private"]), ) -async def save_voice_message(message: types.Message, state: FSMContext): +async def suggest_voice(message: types.Message, state: FSMContext): + logger.info( + f"Вызов функции suggest_voice. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}") + await message.forward(chat_id=GROUP_FOR_LOGS) markup = get_main_keyboard() if message.content_type == 'voice': - await message.forward(chat_id=GROUP_FOR_LOGS) - file_name = '' - file_id = 1 - # Проверяем что запись о файле есть в базе данных - is_having_audio_from_user = BotDB.get_last_user_audio_record(user_id=message.from_user.id) - if is_having_audio_from_user is False: - # Если нет, то генерируем имя файла - file_name = f'message_from_{message.from_user.id}_number_{file_id}' - else: - # Иначе берем последнюю запись из БД, добавляем к ней 1, и создаем новую запись - file_name = BotDB.get_path_for_audio_record(user_id=message.from_user.id) - file_id = BotDB.get_id_for_audio_record(message.from_user.id) + 1 - path = Path(f'voice_users/{file_name}.ogg') - if path.exists(): - file_name = f'message_from_{message.from_user.id}_number_{file_id}' - else: - pass - # Собираем инфо о сообщении - author_id = message.from_user.id - time_UTC = int(time.time()) - date_added = datetime.fromtimestamp(time_UTC) + markup_for_voice = get_reply_keyboard_for_voice() + # Отправляем аудио в приватный канал + sent_message = await send_voice_message(GROUP_FOR_POST, message, + message.voice.file_id, markup_for_voice) - # Сохраняем в базку - BotDB.add_audio_record(file_name, author_id, date_added, 0, file_id) + # Сохраняем в базу инфо о посте + BotDB.set_user_id_and_message_id_for_voice_bot(sent_message.message_id, message.from_user.id) - file_info = await message.bot.get_file(file_id=message.voice.file_id) - downloaded_file = await message.bot.download_file(file_path=file_info.file_path) - with open(f'voice_users/{file_name}.ogg', 'wb') as new_file: - new_file.write(downloaded_file.read()) + # Отправляем юзеру ответ и возвращаем его в меню await message.answer(text='Окей, сохранил!👌', reply_markup=markup) await state.set_state('START') else: @@ -180,23 +182,33 @@ async def save_voice_message(message: types.Message, state: FSMContext): ChatTypeFilter(chat_type=["private"]), F.text == '🎧Послушать' ) -async def standup_listen_audio(message: types.Message, state: FSMContext): +async def standup_listen_audio(message: types.Message): check_audio = BotDB.check_listen_audio(user_id=message.from_user.id) list_audio = list(check_audio) markup = get_main_keyboard() if not list_audio: await message.answer(text='Прости, ты прослушал все аудио😔. Возвращайся позже, возможно наша база пополнится', reply_markup=markup) - message_with_date = last_message() - await message.answer(text=message_with_date, parse_mode="html") + try: + message_with_date = last_message() + await message.answer(text=message_with_date, parse_mode="html") + except Exception as e: + logger.error(f'Не удалось получить последнюю дату {e}') else: + # Получаем эмоджи пользователя number_element = random.randint(0, len(list_audio) - 1) audio_for_user = check_audio[number_element] + # Получаем автора записи + эмодзи по нему + user_id = BotDB.get_user_id_by_file_name(audio_for_user) + user_emoji = BotDB.check_emoji_for_user(user_id) + path = Path(f'voice_users/{audio_for_user}.ogg') # voice = open(path, 'rb') voice = FSInputFile(path) # Маркируем сообщение как прослушанное BotDB.mark_listened_audio(audio_for_user, user_id=message.from_user.id) - await message.bot.send_voice(message.chat.id, voice=voice, reply_markup=markup) - await message.answer(text=f'Осталось непрослушанных: {len(check_audio)}', reply_markup=markup) - await state.set_state('START') + if user_emoji: + await message.bot.send_voice(chat_id=message.chat.id, voice=voice, caption=user_emoji, reply_markup=markup) + else: + await message.bot.send_voice(chat_id=message.chat.id, voice=voice, reply_markup=markup) + await message.answer(text=f'Осталось непрослушанных: {len(check_audio) - 1}', reply_markup=markup) diff --git a/voice_bot/keyboards/keyboards.py b/voice_bot/keyboards/keyboards.py index 0726fea..592d3dc 100644 --- a/voice_bot/keyboards/keyboards.py +++ b/voice_bot/keyboards/keyboards.py @@ -1,5 +1,5 @@ from aiogram import types -from aiogram.utils.keyboard import ReplyKeyboardBuilder +from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder def get_main_keyboard(): @@ -8,3 +8,15 @@ def get_main_keyboard(): builder.add(types.KeyboardButton(text="🎧Послушать")) markup = builder.as_markup(resize_keyboard=True) return markup + + +def get_reply_keyboard_for_voice(): + builder = InlineKeyboardBuilder() + builder.row(types.InlineKeyboardButton( + text="Сохранить", callback_data="save") + ) + builder.row(types.InlineKeyboardButton( + text="Удалить", callback_data="delete") + ) + markup = builder.as_markup(resize_keyboard=True, one_time_keyboard=True) + return markup diff --git a/voice_bot/main.py b/voice_bot/main.py index c2990f2..0b181ce 100644 --- a/voice_bot/main.py +++ b/voice_bot/main.py @@ -3,6 +3,7 @@ from aiogram.client.default import DefaultBotProperties from aiogram.fsm.storage.memory import MemoryStorage from aiogram.fsm.strategy import FSMStrategy +from voice_bot.handlers.callback_handler import callback_router from voice_bot.handlers.voice_handler import voice_router @@ -13,6 +14,6 @@ async def start_bot(bdf): link_preview_is_disabled=bdf.settings['Telegram']['preview_link'] )) dp = Dispatcher(storage=MemoryStorage(), fsm_strategy=FSMStrategy.GLOBAL_USER) - dp.include_routers(voice_router) + dp.include_routers(voice_router, callback_router) await bot.delete_webhook(drop_pending_updates=True) await dp.start_polling(bot, skip_updates=True) diff --git a/voice_bot/utils/helper_func.py b/voice_bot/utils/helper_func.py index ca23b25..88bd3b9 100644 --- a/voice_bot/utils/helper_func.py +++ b/voice_bot/utils/helper_func.py @@ -11,6 +11,9 @@ BotDB = bdf.get_db() def last_message(): # функция с отображением сообщения "Последнее сообщение было записано" date_from_db = BotDB.last_date_audio() + if date_from_db is None: + return None + parse_date = datetime.strptime(date_from_db, "%Y-%m-%d %H:%M:%S") last_voice_time_timestamp = time.mktime(parse_date.timetuple()) time_now_timestamp = time.time() From 47c5b2f0835e6dd7f83adddf5f6792710108c612 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 17 Nov 2024 01:20:51 +0300 Subject: [PATCH 3/7] hotfix --- database/db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/db.py b/database/db.py index c7c2361..2fd98ed 100644 --- a/database/db.py +++ b/database/db.py @@ -751,7 +751,7 @@ class BotDB: self.connect() self.cursor.execute("SELECT emoji FROM our_users WHERE user_id = ?", (user_id,)) pre_result = self.cursor.fetchone() - if pre_result[0] is not None: + if pre_result is not None: print(f'Результат функции check_emoji_for_user - {str(pre_result[0])}') return str(pre_result[0]) else: From b2c27040aabd4e1cbdc489be0579153a40d8ce2e Mon Sep 17 00:00:00 2001 From: KatykhinAA Date: Sun, 17 Nov 2024 22:09:37 +0300 Subject: [PATCH 4/7] some fix with emoji function --- database/db.py | 33 +++-- .../handlers/private/private_handlers.py | 15 +- .../__pycache__/helper_func.cpython-312.pyc | Bin 21000 -> 21117 bytes .../__pycache__/messages.cpython-312.pyc | Bin 5461 -> 5463 bytes helper_bot/utils/helper_func.py | 10 +- helper_bot/utils/messages.py | 4 +- voice_bot/handlers/callback_handler.py | 136 +++++++++--------- voice_bot/handlers/voice_handler.py | 40 ++++-- 8 files changed, 141 insertions(+), 97 deletions(-) diff --git a/database/db.py b/database/db.py index 2fd98ed..425e2d1 100644 --- a/database/db.py +++ b/database/db.py @@ -726,7 +726,6 @@ class BotDB: (emoji, user_id,)) self.conn.commit() self.logger.info(f"Эмоджи обновлен для пользователя: user_id={user_id}") - return None except sqlite3.Error as error: self.logger.error(f"Ошибка обновления эмодзи для пользователя: {error}") return error @@ -744,21 +743,19 @@ class BotDB: True, если эмодзи такого нет, иначе False. Raises: - None: В случае ошибки возвращается None + error: В случае ошибки возвращается error """ self.logger.info(f"Запуск функции check_emoji_for_user: user_id={user_id}") try: self.connect() self.cursor.execute("SELECT emoji FROM our_users WHERE user_id = ?", (user_id,)) pre_result = self.cursor.fetchone() - if pre_result is not None: - print(f'Результат функции check_emoji_for_user - {str(pre_result[0])}') - return str(pre_result[0]) - else: - return None + # Возвращаем "Смайл не определен", если pre_result или pre_result[0] is None + result = pre_result[0] if pre_result else None + return str(result) if result is not None else "Смайл еще не определен" except sqlite3.Error as error: self.logger.error(f"Ошибка проверки эмодзи в базе: {error}") - return None + return error finally: self.close() @@ -1079,7 +1076,7 @@ class BotDB: self.logger.error(f"Ошибка в функции set_user_id_and_message_id_for_voice_bot {str(e)}") def get_user_id_by_file_name(self, file_name: str): - self.logger.info(f"Запуск функции get_user_id_by_file_name, идентификатор поста " + self.logger.info(f"Запуск функции get_user_id_by_file_name, идентификатор файла " f"{file_name}") try: self.connect() @@ -1087,11 +1084,25 @@ class BotDB: "FROM audio_message_reference WHERE file_name = ?", (file_name,)) user_id = result.fetchone()[0] - self.logger.info(f"Функция get_user_id_by_file_name получила author_id {user_id}") + self.logger.info(f"Функция get_user_id_by_file_name получила user_id {user_id}") return user_id except Exception as e: self.logger.error(f"Ошибка в функции get_user_id_by_file_name {str(e)}") + def get_date_by_file_name(self, file_name: str): + self.logger.info(f"Запуск функции get_date_by_file_name, идентификатор файла " + f"{file_name}") + try: + self.connect() + result = self.cursor.execute("SELECT date_added " + "FROM audio_message_reference WHERE file_name = ?", + (file_name,)) + date_added = result.fetchone()[0] + self.logger.info(f"Функция get_date_by_file_name получила date_added {date_added}") + return date_added + except Exception as e: + self.logger.error(f"Ошибка в функции get_date_by_file_name {str(e)}") + def add_post_content_in_db(self, post_id: int, message_id: int, content_name: str, type_content: str): self.logger.info( f"Запуск функции add_post_content_in_db: post_id={post_id}, message_id={message_id}, " @@ -1162,7 +1173,7 @@ class BotDB: f"date_added = {date_added}") return None except sqlite3.Error as error: - print(error) + self.logger.error(f"Ошибка при добавлении войса в базу: {error}") raise finally: self.close() diff --git a/helper_bot/handlers/private/private_handlers.py b/helper_bot/handlers/private/private_handlers.py index 22b2381..5953dee 100644 --- a/helper_bot/handlers/private/private_handlers.py +++ b/helper_bot/handlers/private/private_handlers.py @@ -40,6 +40,17 @@ TEST = bdf.settings['Settings']['test'] BotDB = bdf.get_db() +@private_router.message( + ChatTypeFilter(chat_type=["private"]), + Command("emoji") +) +async def handle_emoji_message(message: types.Message, state: FSMContext): + user_emoji = check_user_emoji(message) + await state.set_state("START") + if user_emoji is not None: + await message.answer(f'Твоя эмодзя - {user_emoji}', parse_mode='HTML') + + @private_router.message( ChatTypeFilter(chat_type=["private"]), Command("restart") @@ -50,7 +61,7 @@ async def handle_restart_message(message: types.Message, state: FSMContext): await message.forward(chat_id=GROUP_FOR_LOGS) await state.set_state("START") await update_user_info('love', message) - check_user_emoji(message.from_user.id) + check_user_emoji(message) await message.answer('Я перезапущен!', reply_markup=markup, parse_mode='HTML') except Exception as e: logger.error(f"Произошла ошибка handle_restart_message. Ошибка:{str(e)}") @@ -70,7 +81,7 @@ async def handle_start_message(message: types.Message, state: FSMContext): try: await message.forward(chat_id=GROUP_FOR_LOGS) await update_user_info('love', message) - check_user_emoji(message.from_user.id) + check_user_emoji(message) await state.set_state("START") logger.info( f"Формирование приветственного сообщения для пользователя. Сообщение: {message.text} " diff --git a/helper_bot/utils/__pycache__/helper_func.cpython-312.pyc b/helper_bot/utils/__pycache__/helper_func.cpython-312.pyc index d158870e9cb328b32cacc94529ed45b39e77e297..80a80d9baaa0a0d770756ec6942e225966d9cd60 100644 GIT binary patch delta 516 zcmeBJ!uWRyBkyTmUM>b8SZrsNzGfn?B;${b>Q|U2Z)6nT{Eu12jd=+J!(@AD$;tDb zM0puYSU^faAd7vnqlAdT8phR(5P@2z8m0!t5>5z@fnhb2QOks+i5sX%RDfv>(`qJ& zG$TU|Q}E=8UJ~4FMWR5VqF^8~d6k!i7;_Onh+hmM)&q%RW+0(3`IDEjfiIBNz;J_4 z^g5sXMLzlKd`cJjlp5Uc2#Q@7)V?UFy}|v0p!Q`!n+C5N?1C5AB`526OK@J{aJ#`R zdVxiBvX8g4$R?l>(-~42YZ+=7Qkb%Vt|_vf#3cuG>*S5z!jtP|Z;%J11}OJGi0X`8 delta 481 zcmeyngt21@BkyTmUM>b8NZoCbZaa}zlJUt#^()NG8mTIqg;-?V7)vG>*eFkaWy>Q` ztW?4ZQV9a9ArwO`V+q4#X=Pb$h8o5-Oskn7!i)@+K&Z*=S5yWR&}1qq22!_JQ*-mP zGBsHy|M0R9fQS{X2TBx!bWL{iRyH>VG8!1}a0^`LR=vorx+47ox9Sycvpb@ymqpb( zxbAT9UguE0$f3N#eTUTr4&|#HZXZ|~c+4m7@|M;)0n|I4A%(G)p@t!aDH~{Jky{BP zP!J4i7*<2sj0`2rllui_6iV1&k}xTtXEN-% z>*QXaR!&WhTdV~|nRz9XZGGeAHUdp9P6TRfV7S3A(BN@{OK3uHmmbiy9T`3RlQ;Y7 zxNtLY3r`5{*89T4z{=h3)9CYofkDWH=?en`t1HtDZvG-kpmt5hTMR`)AO=&>ejw$i zX;~x;q>EHR#IDK8euo+NOn&Znk?R6b0OXzGjhheoFJ=;BW^`wqk^GqfM1SVtWE23K F2LR@2a>W1u diff --git a/helper_bot/utils/__pycache__/messages.cpython-312.pyc b/helper_bot/utils/__pycache__/messages.cpython-312.pyc index 177f9a624fdf0db4a0f450f88dedbeeb396f824d..abd9cca0c6f9bc4dc4a180c6cdaf3ccb44fd0caf 100644 GIT binary patch delta 48 zcmcbrbzO`1G%qg~0}zzxTcz`CТвой эмоджи - {user_emoji}" + f"Таким эмоджи будут помечены твои сообщения для других " + f"Но другие люди не узнают кто за каким эмоджи скрывается:)", + parse_mode='html', reply_markup=markup, + disable_web_page_preview=not PREVIEW_LINK) + time.sleep(0.8) await message.answer(text="Так же можешь ознакомиться с инструкцией к боту по команде /help", parse_mode='html', reply_markup=markup, disable_web_page_preview=not PREVIEW_LINK) time.sleep(0.8) - await message.answer(text="ну всё, достаточно инструкций. записывайся! Микрофон твой - 🎤", + await message.answer(text="Ну всё, достаточно инструкций. записывайся! Микрофон твой - 🎤", parse_mode='html', reply_markup=markup, disable_web_page_preview=not PREVIEW_LINK) @@ -124,7 +140,6 @@ async def refresh_listen_function(message: types.Message, state: FSMContext): await message.forward(chat_id=GROUP_FOR_LOGS) await update_user_info('voice', message) markup = get_main_keyboard() - check_user_emoji(message.from_user.id) BotDB.delete_listen_count_for_user(message.from_user.id) await message.answer( text='Прослушивания очищены. Можешь начать слушать заново🤗', disable_web_page_preview=not PREVIEW_LINK, @@ -195,20 +210,27 @@ async def standup_listen_audio(message: types.Message): except Exception as e: logger.error(f'Не удалось получить последнюю дату {e}') else: - # Получаем эмоджи пользователя + # Получаем ссылку на аудио сообщение пользователя number_element = random.randint(0, len(list_audio) - 1) audio_for_user = check_audio[number_element] + # Получаем автора записи + эмодзи по нему user_id = BotDB.get_user_id_by_file_name(audio_for_user) + date_added = BotDB.get_date_by_file_name(audio_for_user) + # TODO: Мейби не напрямую ходить? + # user_emoji = BotDB.check_emoji_for_user(user_id) user_emoji = BotDB.check_emoji_for_user(user_id) path = Path(f'voice_users/{audio_for_user}.ogg') - # voice = open(path, 'rb') voice = FSInputFile(path) + # Маркируем сообщение как прослушанное BotDB.mark_listened_audio(audio_for_user, user_id=message.from_user.id) + + # Формируем подпись if user_emoji: - await message.bot.send_voice(chat_id=message.chat.id, voice=voice, caption=user_emoji, reply_markup=markup) + caption = f'{user_emoji}\nДата записи: {date_added}' else: - await message.bot.send_voice(chat_id=message.chat.id, voice=voice, reply_markup=markup) + caption = f'Дата записи: {date_added}' + await message.bot.send_voice(chat_id=message.chat.id, voice=voice, caption=caption, reply_markup=markup) await message.answer(text=f'Осталось непрослушанных: {len(check_audio) - 1}', reply_markup=markup) From cb0f94c718213958d4bfb1343f8db4c0d1f4bf74 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 17 Nov 2024 22:10:45 +0300 Subject: [PATCH 5/7] some fix --- voice_bot/handlers/voice_handler.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/voice_bot/handlers/voice_handler.py b/voice_bot/handlers/voice_handler.py index 5cd8a60..a6f7e94 100644 --- a/voice_bot/handlers/voice_handler.py +++ b/voice_bot/handlers/voice_handler.py @@ -217,8 +217,6 @@ async def standup_listen_audio(message: types.Message): # Получаем автора записи + эмодзи по нему user_id = BotDB.get_user_id_by_file_name(audio_for_user) date_added = BotDB.get_date_by_file_name(audio_for_user) - # TODO: Мейби не напрямую ходить? - # user_emoji = BotDB.check_emoji_for_user(user_id) user_emoji = BotDB.check_emoji_for_user(user_id) path = Path(f'voice_users/{audio_for_user}.ogg') From 0c29609e4a514e5505bce45199442f463333bc81 Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 17 Nov 2024 22:43:41 +0300 Subject: [PATCH 6/7] hot fix --- helper_bot/handlers/private/private_handlers.py | 1 + voice_bot/handlers/voice_handler.py | 1 + 2 files changed, 2 insertions(+) diff --git a/helper_bot/handlers/private/private_handlers.py b/helper_bot/handlers/private/private_handlers.py index 5953dee..48a3b60 100644 --- a/helper_bot/handlers/private/private_handlers.py +++ b/helper_bot/handlers/private/private_handlers.py @@ -45,6 +45,7 @@ BotDB = bdf.get_db() Command("emoji") ) async def handle_emoji_message(message: types.Message, state: FSMContext): + await message.forward(chat_id=GROUP_FOR_LOGS) user_emoji = check_user_emoji(message) await state.set_state("START") if user_emoji is not None: diff --git a/voice_bot/handlers/voice_handler.py b/voice_bot/handlers/voice_handler.py index a6f7e94..908725a 100644 --- a/voice_bot/handlers/voice_handler.py +++ b/voice_bot/handlers/voice_handler.py @@ -49,6 +49,7 @@ async def restart_function(message: types.Message, state: FSMContext): Command("emoji") ) async def handle_emoji_message(message: types.Message, state: FSMContext): + await message.forward(chat_id=GROUP_FOR_LOGS) user_emoji = check_user_emoji(message) await state.set_state("START") if user_emoji is not None: From 8bb098764dfe4617dbe7d868b128fd3500c61b11 Mon Sep 17 00:00:00 2001 From: Andrey Date: Tue, 26 Aug 2025 18:56:47 +0300 Subject: [PATCH 7/7] Refactor module imports to ensure project root is included in sys.path for both run_helper and voice_bot. Enhance database user insertion with backward compatibility for emoji column. Update user info handling to check username and full name more robustly. Improve emoji handling with fallback options for environments lacking the emoji package. --- database/db.py | 21 ++++++++++++++---- .../handlers/private/private_handlers.py | 7 +++--- helper_bot/utils/helper_func.py | 22 ++++++++++++++----- run_helper.py | 7 ++++++ voice_bot/main.py | 9 ++++++++ 5 files changed, 53 insertions(+), 13 deletions(-) diff --git a/database/db.py b/database/db.py index 78fa0e7..a9e936b 100644 --- a/database/db.py +++ b/database/db.py @@ -134,10 +134,23 @@ class BotDB: self.logger.info(f"Попытка добавить пользователя в базу данных: user_id={user_id}, first_name={first_name}") try: self.connect() - self.cursor.execute("INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', " - "'language_code', 'emoji', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", - (user_id, first_name, full_name, - username, is_bot, language_code, emoji, date_added, date_changed)) + try: + # Новая схема с колонкой emoji + self.cursor.execute( + "INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', " + "'language_code', 'emoji', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", + (user_id, first_name, full_name, username, is_bot, language_code, emoji, date_added, date_changed) + ) + except sqlite3.OperationalError as e: + # Обратная совместимость: старая схема без колонки emoji + if 'no column named emoji' in str(e): + self.cursor.execute( + "INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', " + "'language_code', 'date_added', 'date_changed') VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + (user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed) + ) + else: + raise self.conn.commit() self.logger.info( f"Новый пользователь добавлен в базу: user_id={user_id}, first_name={first_name}, emoji={emoji}") diff --git a/helper_bot/handlers/private/private_handlers.py b/helper_bot/handlers/private/private_handlers.py index 1a68f40..e0ca598 100644 --- a/helper_bot/handlers/private/private_handlers.py +++ b/helper_bot/handlers/private/private_handlers.py @@ -20,7 +20,7 @@ from helper_bot.utils.base_dependency_factory import get_global_instance from helper_bot.utils.helper_func import get_first_name, get_text_message, send_text_message, send_photo_message, \ send_media_group_message_to_private_chat, prepare_media_group_from_middlewares, send_video_message, \ send_video_note_message, send_audio_message, send_voice_message, add_in_db_media, \ - update_user_info, check_user_emoji + check_user_emoji, check_username_and_full_name from logs.custom_logger import logger private_router = Router() @@ -90,8 +90,6 @@ async def handle_start_message(message: types.Message, state: FSMContext): is_bot = message.from_user.is_bot language_code = message.from_user.language_code user_id = message.from_user.id - await update_user_info('love', message) - check_user_emoji(message) # Проверяем наличие username для логирования if not username: @@ -106,7 +104,8 @@ async def handle_start_message(message: types.Message, state: FSMContext): current_date = datetime.now() date = current_date.strftime("%Y-%m-%d %H:%M:%S") if not BotDB.user_exists(user_id): - BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, date, + # Для первоначального добавления эмодзи пока не назначаем (совместимость) + BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, "", date, date) else: is_need_update = check_username_and_full_name(user_id, username, full_name, BotDB) diff --git a/helper_bot/utils/helper_func.py b/helper_bot/utils/helper_func.py index 83ae9e2..611f0bb 100644 --- a/helper_bot/utils/helper_func.py +++ b/helper_bot/utils/helper_func.py @@ -4,16 +4,28 @@ import random from datetime import datetime, timedelta from time import sleep -import emoji +try: + import emoji as _emoji_lib +except Exception: + _emoji_lib = None from aiogram import types from aiogram.types import InputMediaPhoto, FSInputFile, InputMediaVideo, InputMediaAudio -from helper_bot.utils.base_dependency_factory import BaseDependencyFactory +from helper_bot.utils.base_dependency_factory import BaseDependencyFactory, get_global_instance from logs.custom_logger import logger +bdf = get_global_instance() +BotDB = bdf.get_db() GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs'] -emoji_list = list(emoji.EMOJI_DATA.keys()) +if _emoji_lib is not None: + emoji_list = list(_emoji_lib.EMOJI_DATA.keys()) +else: + # Fallback minimal emoji set for environments without the 'emoji' package (e.g., CI tests) + emoji_list = [ + "🙂", "😀", "😉", "😎", "🤖", "🦄", "🐱", "🐶", "🍀", "🔥", + "🌟", "🎉", "💡", "🚀", "🌈" + ] def safe_html_escape(text: str) -> str: @@ -484,7 +496,7 @@ async def update_user_info(source: str, message: types.Message): BotDB.add_new_user_in_db(user_id, first_name, full_name, username, is_bot, language_code, user_emoji, date, date) else: - is_need_update = check_username_and_full_name(user_id, username, full_name) + is_need_update = check_username_and_full_name(user_id, username, full_name, BotDB) if is_need_update: BotDB.update_username_and_full_name(user_id, username, full_name) if source != 'voice': @@ -499,7 +511,7 @@ async def update_user_info(source: str, message: types.Message): def check_user_emoji(message: types.Message): user_id = message.from_user.id user_emoji = BotDB.check_emoji_for_user(user_id=user_id) - if user_emoji is None: + if user_emoji is None or user_emoji in ("Смайл еще не определен", "Эмоджи не определен", ""): user_emoji = get_random_emoji() BotDB.update_emoji_for_user(user_id=user_id, emoji=user_emoji) return user_emoji diff --git a/run_helper.py b/run_helper.py index 16a0eaf..5ea56c4 100644 --- a/run_helper.py +++ b/run_helper.py @@ -1,4 +1,11 @@ import asyncio +import os +import sys + +# Ensure project root is on sys.path for module resolution +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) +if CURRENT_DIR not in sys.path: + sys.path.insert(0, CURRENT_DIR) from helper_bot.main import start_bot from helper_bot.utils.base_dependency_factory import get_global_instance diff --git a/voice_bot/main.py b/voice_bot/main.py index 0b181ce..d0a25db 100644 --- a/voice_bot/main.py +++ b/voice_bot/main.py @@ -1,3 +1,12 @@ +import os +import sys + +# Ensure project root is on sys.path for module resolution when running voice bot directly +CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) +PROJECT_ROOT = os.path.dirname(CURRENT_DIR) +if PROJECT_ROOT not in sys.path: + sys.path.insert(0, PROJECT_ROOT) + from aiogram import Bot, Dispatcher from aiogram.client.default import DefaultBotProperties from aiogram.fsm.storage.memory import MemoryStorage