10 Commits

Author SHA1 Message Date
Andrey
0c29609e4a hot fix 2024-11-17 22:43:41 +03:00
Andrey
cb0f94c718 some fix 2024-11-17 22:10:45 +03:00
b2c27040aa some fix with emoji function 2024-11-17 22:09:37 +03:00
Andrey
47c5b2f083 hotfix 2024-11-17 01:20:51 +03:00
Andrey
e0e0a6de51 add new func in voice bot 2024-11-17 00:50:55 +03:00
502c07a2c9 some fix 2024-11-16 18:45:05 +03:00
Andrey
ee9eafa09f some fix 2024-11-14 00:24:37 +03:00
ANDREY KATYKHIN
b8b92434ff Merge pull request #5 from KerradKerridi/dev-3
refactor voice_bot
2024-11-14 00:06:13 +03:00
ANDREY KATYKHIN
bc454fce8c Merge pull request #4 from KerradKerridi/dev-3
fix with html tags
2024-10-31 22:00:09 +03:00
ANDREY KATYKHIN
198b522976 Merge pull request #3 from KerradKerridi/dev-3
Dev-3 Добавил новые функции MediaGroup, разные типы файлов, ответы пользователю
2024-07-21 23:24:44 +05:00
17 changed files with 500 additions and 155 deletions

View File

@@ -100,27 +100,8 @@ class BotDB:
finally: finally:
self.close() 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, 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, language_code: str, emoji: str, date_added: str, date_changed: str):
date_changed: str):
""" """
Добавляет нового пользователя в базу данных. Добавляет нового пользователя в базу данных.
@@ -131,6 +112,7 @@ class BotDB:
username (str): Username пользователя в Telegram. username (str): Username пользователя в Telegram.
is_bot (bool): Флаг, указывающий, является ли пользователь ботом. is_bot (bool): Флаг, указывающий, является ли пользователь ботом.
language_code (str): Код языка пользователя. language_code (str): Код языка пользователя.
emoji (str): Эмодзи закрепленная за пользователем
date_added (str): Дата добавления пользователя в базу. date_added (str): Дата добавления пользователя в базу.
date_changed (str): Дата последнего изменения данных пользователя. date_changed (str): Дата последнего изменения данных пользователя.
@@ -142,11 +124,12 @@ class BotDB:
try: try:
self.connect() self.connect()
self.cursor.execute("INSERT INTO 'our_users' ('user_id', 'first_name', 'full_name', 'username', 'is_bot', " 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, (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.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 return None
except sqlite3.Error as error: except sqlite3.Error as error:
self.logger.error(f"Ошибка при добавлении пользователя в базу: {error}. " self.logger.error(f"Ошибка при добавлении пользователя в базу: {error}. "
@@ -675,15 +658,15 @@ class BotDB:
def update_date_for_user(self, date: str, user_id: int): def update_date_for_user(self, date: str, user_id: int):
""" """
#TODO: Не возвращается ошибка sqlite3. Error. Тест не перехватывает. Возвращается no such table: our_users #TODO: Не возвращается ошибка sqlite3. Error. Тест не перехватывает. Возвращается no such table: our_users
Обновляет дату последнего изменения данных пользователя в базе. Обновляет дату последнего изменения данных пользователя в базе
Args: Args:
date (str): Новая дата изменения. date (str): Новая дата изменения
user_id (int): Идентификатор пользователя в Telegram. user_id (int): Идентификатор пользователя в Telegram
Returns: Returns:
None: Если обновление прошло успешно. None: Если обновление прошло успешно
sqlite3. Error: Если произошла ошибка при выполнении запроса. sqlite3. Error: Если произошла ошибка при выполнении запроса
""" """
self.logger.info(f"Запуск функции update_date_for_user: user_id={user_id}, date={date}") self.logger.info(f"Запуск функции update_date_for_user: user_id={user_id}, date={date}")
try: try:
@@ -699,6 +682,107 @@ class BotDB:
finally: finally:
self.close() 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_emoji_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}")
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:
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()
# Возвращаем "Смайл не определен", если 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 error
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): def is_admin(self, user_id: int):
""" """
Проверяет, является ли пользователь администратором. Проверяет, является ли пользователь администратором.
@@ -719,7 +803,7 @@ class BotDB:
result = self.cursor.fetchone() result = self.cursor.fetchone()
return bool(result) return bool(result)
except sqlite3.Error as error: except sqlite3.Error as error:
self.logger.error(f"Ошибка добавления сообщения в базу данных: {error}") self.logger.error(f"Ошибка проверки прав пользователя админа: {error}")
return None return None
finally: finally:
self.close() self.close()
@@ -963,6 +1047,62 @@ class BotDB:
except Exception as e: except Exception as e:
self.logger.error(f"Ошибка в функции get_author_id_by_helper_message_id {str(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 получила 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): def add_post_content_in_db(self, post_id: int, message_id: int, content_name: str, type_content: str):
self.logger.info( self.logger.info(
f"Запуск функции add_post_content_in_db: post_id={post_id}, message_id={message_id}, " f"Запуск функции add_post_content_in_db: post_id={post_id}, message_id={message_id}, "
@@ -1033,7 +1173,7 @@ class BotDB:
f"date_added = {date_added}") f"date_added = {date_added}")
return None return None
except sqlite3.Error as error: except sqlite3.Error as error:
print(error) self.logger.error(f"Ошибка при добавлении войса в базу: {error}")
raise raise
finally: finally:
self.close() self.close()
@@ -1073,6 +1213,24 @@ class BotDB:
finally: finally:
self.close() 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): def get_id_for_audio_record(self, user_id):
"""Получает ID аудио сообщения пользователя""" """Получает ID аудио сообщения пользователя"""
self.logger.info( self.logger.info(

View File

@@ -17,8 +17,9 @@ from helper_bot.middlewares.blacklist_middleware import BlacklistMiddleware
from helper_bot.utils import messages from helper_bot.utils import messages
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory 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, \ 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_media_group_message_to_private_chat, prepare_media_group_from_middlewares, send_video_message, \
send_video_message, send_video_note_message, send_audio_message, send_voice_message, add_in_db_media 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 from logs.custom_logger import logger
private_router = Router() private_router = Router()
@@ -39,6 +40,36 @@ TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db() BotDB = bdf.get_db()
@private_router.message(
ChatTypeFilter(chat_type=["private"]),
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:
await message.answer(f'Твоя эмодзя - {user_emoji}', parse_mode='HTML')
@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)
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( @private_router.message(
ChatTypeFilter(chat_type=["private"]), ChatTypeFilter(chat_type=["private"]),
Command("start") Command("start")
@@ -50,27 +81,8 @@ BotDB = bdf.get_db()
async def handle_start_message(message: types.Message, state: FSMContext): async def handle_start_message(message: types.Message, state: FSMContext):
try: try:
await message.forward(chat_id=GROUP_FOR_LOGS) await message.forward(chat_id=GROUP_FOR_LOGS)
full_name = message.from_user.full_name await update_user_info('love', message)
username = message.from_user.username check_user_emoji(message)
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 state.set_state("START") await state.set_state("START")
logger.info( logger.info(
f"Формирование приветственного сообщения для пользователя. Сообщение: {message.text} " f"Формирование приветственного сообщения для пользователя. Сообщение: {message.text} "

View File

@@ -1,7 +1,10 @@
import html import html
import os import os
import random
from datetime import datetime, timedelta from datetime import datetime, timedelta
from time import sleep
import emoji
from aiogram import types from aiogram import types
from aiogram.types import InputMediaPhoto, FSInputFile, InputMediaVideo, InputMediaAudio from aiogram.types import InputMediaPhoto, FSInputFile, InputMediaVideo, InputMediaAudio
@@ -9,6 +12,9 @@ from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
from logs.custom_logger import logger from logs.custom_logger import logger
bdf = BaseDependencyFactory() bdf = BaseDependencyFactory()
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs']
emoji_list = list(emoji.EMOJI_DATA.keys())
BotDB = bdf.get_db() BotDB = bdf.get_db()
@@ -387,3 +393,52 @@ def unban_notifier(self):
# Отправка сообщения в канал # Отправка сообщения в канал
self.bot.send_message(self.GROUP_FOR_MESSAGE, message) self.bot.send_message(self.GROUP_FOR_MESSAGE, message)
async def update_user_info(source: str, message: types.Message):
# Собираем данные
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")
# Выбираем эмодзю, пробегаемся циклом и смотрим что в базе такого еще не было
user_emoji = get_random_emoji()
if not BotDB.user_exists(user_id):
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)
if is_need_update:
BotDB.update_username_and_full_name(user_id, username, full_name)
if source != 'voice':
await message.answer(
f"Давно не виделись! Вижу что ты изменился;) Теперь буду звать тебя: {full_name}")
await message.bot.send_message(chat_id=GROUP_FOR_LOGS,
text=f'Для пользователя: {user_id} обновлены данные в БД.\nНовое имя: {full_name}\nНовый ник:{username}. Новый эмодзи:{user_emoji}')
sleep(1)
BotDB.update_date_for_user(date, user_id)
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:
user_emoji = get_random_emoji()
BotDB.update_emoji_for_user(user_id=user_id, emoji=user_emoji)
return user_emoji
def get_random_emoji():
attempts = 0
while attempts < 100:
user_emoji = random.choice(emoji_list)
if not BotDB.check_emoji(user_emoji):
return user_emoji
attempts += 1
logger.error("Не удалось найти уникальный эмодзи после нескольких попыток.")
return "Эмоджи не определен"

View File

@@ -1,5 +1,3 @@
def get_message(username: str, type_message: str): def get_message(username: str, type_message: str):
constants = { constants = {
'HELLO_MESSAGE': "Привет, username!👋🏼&Меня зовут Виби, я бот канала 'Влюбленный Бийск'❤🤖" 'HELLO_MESSAGE': "Привет, username!👋🏼&Меня зовут Виби, я бот канала 'Влюбленный Бийск'❤🤖"
@@ -25,7 +23,7 @@ def get_message(username: str, type_message: str):
"&Мы рассмотрим и ответим тебе в ближайшее время☺️❤️", "&Мы рассмотрим и ответим тебе в ближайшее время☺️❤️",
"DEL_MESSAGE": "username, напиши свое обращение или предложение✍" "DEL_MESSAGE": "username, напиши свое обращение или предложение✍"
"&Мы рассмотрим и ответим тебе в ближайшее время☺❤", "&Мы рассмотрим и ответим тебе в ближайшее время☺❤",
"BYE_MESSAGE": "Если позднее захочешь предложить еще один пост или обратиться к админам с вопросом, то просто пришли в чат команду 👉 /start" "BYE_MESSAGE": "Если позднее захочешь предложить еще один пост или обратиться к админам с вопросом, то просто пришли в чат команду 👉 /restart"
"&&И тебе пока!👋🏼❤️", "&&И тебе пока!👋🏼❤️",
"USER_ERROR": "Увы, я не понимаю тебя😐💔 Выбери один из пунктов в нижнем меню, а затем пиши.", "USER_ERROR": "Увы, я не понимаю тебя😐💔 Выбери один из пунктов в нижнем меню, а затем пиши.",
"QUESTION": "Сообщение успешно отправлено❤️ Ответим, как только сможем😉", "QUESTION": "Сообщение успешно отправлено❤️ Ответим, как только сможем😉",

View File

@@ -20,3 +20,4 @@ attrs~=23.2.0
typing_extensions~=4.12.2 typing_extensions~=4.12.2
aiohttp~=3.9.5 aiohttp~=3.9.5
aiogram~=3.10.0 aiogram~=3.10.0
emoji~=2.14.0

View File

@@ -252,12 +252,13 @@ def test_add_new_user_in_db(bot):
username = "@petr_ivanov" username = "@petr_ivanov"
is_bot = False is_bot = False
language_code = "ru" language_code = "ru"
emoji = '🦀'
date_added = "2024-07-09" date_added = "2024-07-09"
date_changed = "2024-07-09" date_changed = "2024-07-09"
# Вызываем функцию add_new_user_in_db # Вызываем функцию add_new_user_in_db
bot.add_new_user_in_db( bot.add_new_user_in_db(
user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed user_id, first_name, full_name, username, is_bot, language_code, emoji, date_added, date_changed
) )
# Проверяем наличие записи в базе данных # Проверяем наличие записи в базе данных
@@ -285,7 +286,7 @@ def test_add_new_user_in_db_duplicate_user_id(bot, setup_db):
# Попытка добавить пользователя с тем же user_id # Попытка добавить пользователя с тем же user_id
with pytest.raises(sqlite3.IntegrityError): with pytest.raises(sqlite3.IntegrityError):
bot.add_new_user_in_db( bot.add_new_user_in_db(
user_id, "Марина", "Марина Альфредовна", "marina", False, "bg", "2024-07-09", "2024-07-09" user_id, "Марина", "Марина Альфредовна", "marina", False, "bg", "🦀", "2024-07-09", "2024-07-09"
) )
@@ -297,12 +298,13 @@ def test_add_new_user_in_db_empty_first_name(bot):
username = "@boris" username = "@boris"
is_bot = False is_bot = False
language_code = "fr" language_code = "fr"
emoji = "🦀"
date_added = "2024-07-09" date_added = "2024-07-09"
date_changed = "2024-07-09" date_changed = "2024-07-09"
# Вызываем функцию add_new_user_in_db # Вызываем функцию add_new_user_in_db
bot.add_new_user_in_db( bot.add_new_user_in_db(
user_id, first_name, full_name, username, is_bot, language_code, date_added, date_changed user_id, first_name, full_name, username, is_bot, language_code, emoji, date_added, date_changed
) )
# Проверяем наличие записи в базе данных # Проверяем наличие записи в базе данных

View File

@@ -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)

View File

@@ -1,6 +1,5 @@
import random import random
import time import time
from datetime import datetime
from pathlib import Path from pathlib import Path
from aiogram import Router, types, F from aiogram import Router, types, F
@@ -9,9 +8,11 @@ from aiogram.fsm.context import FSMContext
from aiogram.types import FSInputFile from aiogram.types import FSInputFile
from helper_bot.filters.main import ChatTypeFilter 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.base_dependency_factory import BaseDependencyFactory
from helper_bot.utils.helper_func import update_user_info, check_user_emoji, send_voice_message
from logs.custom_logger import logger 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 from voice_bot.utils.helper_func import last_message
voice_router = Router() voice_router = Router()
@@ -19,12 +20,53 @@ voice_router = Router()
bdf = BaseDependencyFactory() bdf = BaseDependencyFactory()
GROUP_FOR_LOGS = bdf.settings['Telegram']['group_for_logs'] 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'] IMPORTANT_LOGS = bdf.settings['Telegram']['important_logs']
PREVIEW_LINK = bdf.settings['Telegram']['preview_link'] PREVIEW_LINK = bdf.settings['Telegram']['preview_link']
LOGS = bdf.settings['Settings']['logs'] LOGS = bdf.settings['Settings']['logs']
TEST = bdf.settings['Settings']['test'] TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db() BotDB = bdf.get_db()
voice_router.message.middleware(BlacklistMiddleware())
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("restart")
)
async def restart_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
check_user_emoji(message)
markup = get_main_keyboard()
await message.answer(text='Я перезапущен!',
reply_markup=markup)
await state.set_state('START')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
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:
await message.answer(f'Твоя эмодзя - {user_emoji}', parse_mode='HTML')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("help")
)
async def help_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
await message.answer(
text='Скорее всего ответы на твои вопросы есть здесь, ознакомься: https://telegra.ph/Instrukciya-k-botu-Golosa-Bijsk-10-11-2'
'\nЕсли это не поможет, пиши в личку: @Kerrad1', disable_web_page_preview=not PREVIEW_LINK)
await state.set_state('START')
@voice_router.message( @voice_router.message(
@@ -34,6 +76,8 @@ BotDB = bdf.get_db()
async def start(message: types.Message, state: FSMContext): async def start(message: types.Message, state: FSMContext):
await state.set_state("START") await state.set_state("START")
await message.forward(chat_id=GROUP_FOR_LOGS) await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
user_emoji = check_user_emoji(message)
try: try:
name_stick_hello = list(Path('Stick').rglob('Hello_*')) name_stick_hello = list(Path('Stick').rglob('Hello_*'))
random_stick_hello = random.choice(name_stick_hello) random_stick_hello = random.choice(name_stick_hello)
@@ -74,15 +118,36 @@ async def start(message: types.Message, state: FSMContext):
parse_mode='html', reply_markup=markup, parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK) disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8) time.sleep(0.8)
await message.answer(text=f"Любые войсы будут помечены эмоджи. <b>Твой эмоджи - </b>{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", await message.answer(text="Так же можешь ознакомиться с инструкцией к боту по команде /help",
parse_mode='html', reply_markup=markup, parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK) disable_web_page_preview=not PREVIEW_LINK)
time.sleep(0.8) time.sleep(0.8)
await message.answer(text="<b>ну всё, достаточно инструкций. записывайся! Микрофон твой - </b> 🎤", await message.answer(text="<b>Ну всё, достаточно инструкций. записывайся! Микрофон твой - </b> 🎤",
parse_mode='html', reply_markup=markup, parse_mode='html', reply_markup=markup,
disable_web_page_preview=not PREVIEW_LINK) 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()
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( @voice_router.message(
StateFilter("START"), StateFilter("START"),
ChatTypeFilter(chat_type=["private"]), ChatTypeFilter(chat_type=["private"]),
@@ -92,53 +157,33 @@ async def standup_write(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS) await message.forward(chat_id=GROUP_FOR_LOGS)
markup = types.ReplyKeyboardRemove() markup = types.ReplyKeyboardRemove()
await message.answer(text='Хорошо, теперь пришли мне свое голосовое сообщение', reply_markup=markup) await message.answer(text='Хорошо, теперь пришли мне свое голосовое сообщение', reply_markup=markup)
try:
message_with_date = last_message() message_with_date = last_message()
await message.answer(text=message_with_date, parse_mode="html") await message.answer(text=message_with_date, parse_mode="html")
except Exception as e:
logger.error(f'Не удалось получить дату последнего сообщения - {e}')
await state.set_state('STANDUP_WRITE') await state.set_state('STANDUP_WRITE')
@voice_router.message( @voice_router.message(
StateFilter("STANDUP_WRITE"), 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() markup = get_main_keyboard()
if message.content_type == 'voice': if message.content_type == 'voice':
await message.forward(chat_id=GROUP_FOR_LOGS) markup_for_voice = get_reply_keyboard_for_voice()
file_name = '' # Отправляем аудио в приватный канал
file_id = 1 sent_message = await send_voice_message(GROUP_FOR_POST, message,
# Проверяем что запись о файле есть в базе данных message.voice.file_id, markup_for_voice)
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)
# Сохраняем в базку # Сохраняем в базу инфо о посте
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 = message.bot.get_file(file_id=message.voice.file_id)
# downloaded_file = 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)
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 message.answer(text='Окей, сохранил!👌', reply_markup=markup)
await state.set_state('START') await state.set_state('START')
else: else:
@@ -153,48 +198,38 @@ async def save_voice_message(message: types.Message, state: FSMContext):
ChatTypeFilter(chat_type=["private"]), ChatTypeFilter(chat_type=["private"]),
F.text == '🎧Послушать' 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) check_audio = BotDB.check_listen_audio(user_id=message.from_user.id)
list_audio = list(check_audio) list_audio = list(check_audio)
markup = get_main_keyboard() markup = get_main_keyboard()
await message.forward(chat_id=GROUP_FOR_LOGS)
if not list_audio: if not list_audio:
await message.answer(text='Прости, ты прослушал все аудио😔. Возвращайся позже, возможно наша база пополнится', await message.answer(text='Прости, ты прослушал все аудио😔. Возвращайся позже, возможно наша база пополнится',
reply_markup=markup) reply_markup=markup)
try:
message_with_date = last_message() message_with_date = last_message()
message.send_message(chat_id=message.chat.id, text=message_with_date, parse_mode="html") await message.answer(text=message_with_date, parse_mode="html")
except Exception as e:
logger.error(f'Не удалось получить последнюю дату {e}')
else: else:
# Получаем ссылку на аудио сообщение пользователя
number_element = random.randint(0, len(list_audio) - 1) number_element = random.randint(0, len(list_audio) - 1)
audio_for_user = check_audio[number_element] 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)
user_emoji = BotDB.check_emoji_for_user(user_id)
path = Path(f'voice_users/{audio_for_user}.ogg') path = Path(f'voice_users/{audio_for_user}.ogg')
# voice = open(path, 'rb')
voice = FSInputFile(path) voice = FSInputFile(path)
# Маркируем сообщение как прослушанное # Маркируем сообщение как прослушанное
BotDB.mark_listened_audio(audio_for_user, user_id=message.from_user.id) 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.forward(chat_id=GROUP_FOR_LOGS)
await state.set_state('START')
# Формируем подпись
@voice_router.message( if user_emoji:
ChatTypeFilter(chat_type=["private"]), caption = f'{user_emoji}\nДата записи: {date_added}'
Command("restart") else:
) caption = f'Дата записи: {date_added}'
async def restart_function(message: types.Message, state: FSMContext): await message.bot.send_voice(chat_id=message.chat.id, voice=voice, caption=caption, reply_markup=markup)
await message.forward(chat_id=GROUP_FOR_LOGS) await message.answer(text=f'Осталось непрослушанных: <b>{len(check_audio) - 1}</b>', reply_markup=markup)
markup = get_main_keyboard()
await message.answer(text='Я перезапущен!',
reply_markup=markup)
await state.set_state('START')
@voice_router.message(
ChatTypeFilter(chat_type=["private"]),
Command("help")
)
async def help_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS)
await message.answer(
text='Скорее всего ответы на твои вопросы есть здесь, ознакомься: https://telegra.ph/Instrukciya-k-botu-Golosa-Bijsk-10-11-2'
'\nЕсли это не поможет, пиши в тг: @Kerrad1', disable_web_page_preview=not PREVIEW_LINK)
await state.set_state('START')

View File

@@ -1,5 +1,5 @@
from aiogram import types from aiogram import types
from aiogram.utils.keyboard import ReplyKeyboardBuilder from aiogram.utils.keyboard import ReplyKeyboardBuilder, InlineKeyboardBuilder
def get_main_keyboard(): def get_main_keyboard():
@@ -8,3 +8,15 @@ def get_main_keyboard():
builder.add(types.KeyboardButton(text="🎧Послушать")) builder.add(types.KeyboardButton(text="🎧Послушать"))
markup = builder.as_markup(resize_keyboard=True) markup = builder.as_markup(resize_keyboard=True)
return markup 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

View File

@@ -3,7 +3,8 @@ from aiogram.client.default import DefaultBotProperties
from aiogram.fsm.storage.memory import MemoryStorage from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.fsm.strategy import FSMStrategy from aiogram.fsm.strategy import FSMStrategy
from voice_bot.voice_handler.voice_handler import voice_router from voice_bot.handlers.callback_handler import callback_router
from voice_bot.handlers.voice_handler import voice_router
async def start_bot(bdf): async def start_bot(bdf):
@@ -13,6 +14,6 @@ async def start_bot(bdf):
link_preview_is_disabled=bdf.settings['Telegram']['preview_link'] link_preview_is_disabled=bdf.settings['Telegram']['preview_link']
)) ))
dp = Dispatcher(storage=MemoryStorage(), fsm_strategy=FSMStrategy.GLOBAL_USER) 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 bot.delete_webhook(drop_pending_updates=True)
await dp.start_polling(bot, skip_updates=True) await dp.start_polling(bot, skip_updates=True)

View File

@@ -11,6 +11,9 @@ BotDB = bdf.get_db()
def last_message(): def last_message():
# функция с отображением сообщения "Последнее сообщение было записано" # функция с отображением сообщения "Последнее сообщение было записано"
date_from_db = BotDB.last_date_audio() 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") parse_date = datetime.strptime(date_from_db, "%Y-%m-%d %H:%M:%S")
last_voice_time_timestamp = time.mktime(parse_date.timetuple()) last_voice_time_timestamp = time.mktime(parse_date.timetuple())
time_now_timestamp = time.time() time_now_timestamp = time.time()