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