This commit is contained in:
2024-11-16 18:45:05 +03:00
parent ee9eafa09f
commit 502c07a2c9
11 changed files with 206 additions and 66 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,106 @@ 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_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): def is_admin(self, user_id: int):
""" """
Проверяет, является ли пользователь администратором. Проверяет, является ли пользователь администратором.
@@ -719,7 +802,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()

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,24 @@ TEST = bdf.settings['Settings']['test']
BotDB = bdf.get_db() 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( @private_router.message(
ChatTypeFilter(chat_type=["private"]), ChatTypeFilter(chat_type=["private"]),
Command("start") Command("start")
@@ -50,27 +69,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.from_user.id)
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,50 @@ 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(user_id: int):
if not BotDB.check_emoji_for_user(user_id=user_id):
user_emoji = get_random_emoji()
BotDB.update_emoji_for_user(user_id=user_id, emoji=user_emoji)
def get_random_emoji():
attempts = 0
while attempts < 100:
print(attempts)
user_emoji = random.choice(emoji_list)
if not BotDB.check_emoji(user_emoji):
return user_emoji
attempts += 1
logger.error("Не удалось найти уникальный эмодзи после нескольких попыток.")
return None

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

@@ -9,7 +9,9 @@ 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
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
from voice_bot.utils.helper_func import last_message from voice_bot.utils.helper_func import last_message
@@ -25,6 +27,7 @@ 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( @voice_router.message(
@@ -33,6 +36,8 @@ BotDB = bdf.get_db()
) )
async def restart_function(message: types.Message, state: FSMContext): async def restart_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS) await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
check_user_emoji(message.from_user.id)
markup = get_main_keyboard() markup = get_main_keyboard()
await message.answer(text='Я перезапущен!', await message.answer(text='Я перезапущен!',
reply_markup=markup) reply_markup=markup)
@@ -45,9 +50,11 @@ async def restart_function(message: types.Message, state: FSMContext):
) )
async def help_function(message: types.Message, state: FSMContext): async def help_function(message: types.Message, state: FSMContext):
await message.forward(chat_id=GROUP_FOR_LOGS) await message.forward(chat_id=GROUP_FOR_LOGS)
await update_user_info('voice', message)
check_user_emoji(message.from_user.id)
await message.answer( await message.answer(
text='Скорее всего ответы на твои вопросы есть здесь, ознакомься: https://telegra.ph/Instrukciya-k-botu-Golosa-Bijsk-10-11-2' text='Скорее всего ответы на твои вопросы есть здесь, ознакомься: https://telegra.ph/Instrukciya-k-botu-Golosa-Bijsk-10-11-2'
'\nЕсли это не поможет, пиши в тг: @Kerrad1', disable_web_page_preview=not PREVIEW_LINK) '\nЕсли это не поможет, пиши в личку: @Kerrad1', disable_web_page_preview=not PREVIEW_LINK)
await state.set_state('START') await state.set_state('START')
@@ -58,6 +65,8 @@ async def help_function(message: types.Message, state: FSMContext):
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)
check_user_emoji(message.from_user.id)
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)
@@ -153,12 +162,6 @@ async def save_voice_message(message: types.Message, state: FSMContext):
# Сохраняем в базку # Сохраняем в базку
BotDB.add_audio_record(file_name, author_id, date_added, 0, file_id) BotDB.add_audio_record(file_name, author_id, date_added, 0, file_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) 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) 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: with open(f'voice_users/{file_name}.ogg', 'wb') as new_file:
@@ -181,12 +184,11 @@ async def standup_listen_audio(message: types.Message, state: FSMContext):
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)
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")
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]
@@ -196,5 +198,5 @@ async def standup_listen_audio(message: types.Message, state: FSMContext):
# Маркируем сообщение как прослушанное # Маркируем сообщение как прослушанное
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.bot.send_voice(message.chat.id, voice=voice, reply_markup=markup)
await message.forward(chat_id=GROUP_FOR_LOGS) await message.answer(text=f'Осталось непрослушанных: <b>{len(check_audio)}</b>', reply_markup=markup)
await state.set_state('START') await state.set_state('START')

View File

@@ -3,7 +3,7 @@ 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.voice_handler import voice_router
async def start_bot(bdf): async def start_bot(bdf):