refactor MediaGroup. Add database

This commit is contained in:
KatykhinAA
2024-07-20 16:54:43 +03:00
parent 54234e59ec
commit 0b7f718f8a
11 changed files with 193 additions and 92 deletions

View File

@@ -1,14 +1,16 @@
import sqlite3
import os import os
import sqlite3
from datetime import datetime from datetime import datetime
from logs.custom_logger import logger from logs.custom_logger import logger
# Получение абсолютного пути к текущей директории # Получение абсолютного пути к текущей директории
current_dir = os.getcwd() # current_dir = os.getcwd()
class BotDB: class BotDB:
def __init__(self, name): def __init__(self, current_dir, name):
self.db_file = os.path.join(current_dir, name) self.db_file = os.path.join(current_dir, name)
self.conn = None self.conn = None
self.cursor = None self.cursor = None
@@ -59,7 +61,7 @@ class BotDB:
self.logger.info(f'Получена текущая версия миграции: {version}') self.logger.info(f'Получена текущая версия миграции: {version}')
return version return version
except Exception as e: except Exception as e:
self.logger.error(f'Ошибка при получении текущей версии миграции: {e}') self.logger.error(f'Ошибка при получении текущей версии миграции: {str(e)}')
raise raise
finally: finally:
self.close() self.close()
@@ -298,11 +300,6 @@ class BotDB:
finally: finally:
self.close() self.close()
def change_name(self, user_id):
#TODO: реализовать функцию изменения имени пользователя по которому к нему обращается бот. Обновляем поля first_name, date_changed
#result = self.cursor.execute("UPDATE 'our_users' SET (?) WHERE user_id = (?)", (new_user_name), )
pass
def get_info_about_stickers(self, user_id: int): def get_info_about_stickers(self, user_id: int):
""" """
Проверяет, получил ли пользователь стикеры. Проверяет, получил ли пользователь стикеры.
@@ -825,38 +822,23 @@ class BotDB:
finally: finally:
self.close() self.close()
def add_post_from_telegram_in_db(self, group_message_id, message_id, is_last_message_id, content_name, text):
self.logger.info(
f"Запуск функции add_post_from_telegram_in_db: group_message_id={group_message_id}, message_id={message_id}"
f", is_last_message_id={is_last_message_id}, content_name={content_name}, text={text}")
try:
self.connect()
self.cursor.execute(
"INSERT INTO posts_from_telegram (group_message_id, message_id, is_last_message_id, content_name, text)"
"VALUES (?, ?, ?, ?, ?)", (group_message_id, message_id, is_last_message_id, content_name, text))
self.conn.commit()
self.logger.info(f"Функция add_post_from_telegram_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции add_post_from_telegram_in_db при добавлении поста в базу данных: {e}")
return False
def get_post_content_from_telegram_by_last_id(self, last_post_id: int): def get_post_content_from_telegram_by_last_id(self, last_post_id: int):
self.logger.info( self.logger.info(
f"Запуск функции get_post_content_from_telegram_by_last_id, идентификатор поста {last_post_id}") f"Запуск функции get_post_content_from_telegram_by_last_id, идентификатор поста {last_post_id}")
try: try:
self.connect() self.connect()
main_post_sql = self.cursor.execute("SELECT group_message_id " result = self.cursor.execute("""
"FROM posts_from_telegram WHERE message_id = ?", (last_post_id,)) SELECT cpft.content_name
main_post = main_post_sql.fetchone()[0] FROM post_from_telegram_suggest pft
except Exception as e: JOIN message_link_to_content mltc
self.logger.error(f"Ошибка в функции get_post_content_from_telegram_by_last_id {str(e)}") ON pft.message_id = mltc.post_id
return False JOIN content_post_from_telegram cpft
try: ON cpft.message_id = mltc.message_id
result = self.cursor.execute("SELECT content_name " WHERE pft.helper_text_message_id = ?
"FROM posts_from_telegram WHERE group_message_id = ?", (main_post,)) """, (last_post_id,))
post_content = result.fetchall() post_content = result.fetchall()
self.logger.info(f"Функция get_post_content_from_telegram_by_last_id получила список контента: {post_content}") self.logger.info(
f"Функция get_post_content_from_telegram_by_last_id получила список контента: {post_content}")
return post_content return post_content
finally: finally:
self.close() self.close()
@@ -866,18 +848,20 @@ class BotDB:
f"Запуск функции get_post_ids_from_telegram_by_last_id, идентификатор поста {last_post_id}") f"Запуск функции get_post_ids_from_telegram_by_last_id, идентификатор поста {last_post_id}")
try: try:
self.connect() self.connect()
main_post_sql = self.cursor.execute("SELECT group_message_id " result = self.cursor.execute("""
"FROM posts_from_telegram WHERE message_id = ?", (last_post_id,)) SELECT mltc.message_id
main_post = main_post_sql.fetchone()[0] FROM post_from_telegram_suggest pft
JOIN message_link_to_content mltc
ON pft.message_id = mltc.post_id
WHERE pft.helper_text_message_id = ?
""", (last_post_id,))
post_ids = result.fetchall()
self.logger.info(f"Функция get_post_ids_from_telegram_by_last_id "
f"получила идентификаторы сообщений: {post_ids}")
return post_ids
except Exception as e: except Exception as e:
self.logger.error(f"Ошибка в функции get_post_ids_from_telegram_by_last_id {str(e)}") self.logger.error(f"Ошибка в функции get_post_ids_from_telegram_by_last_id {str(e)}")
return False return False
try:
result = self.cursor.execute("SELECT message_id "
"FROM posts_from_telegram WHERE group_message_id = ?", (main_post,))
post_ids = result.fetchall()
self.logger.info(f"Функция get_post_ids_from_telegram_by_last_id получила идентификаторы сообщений: {post_ids}")
return post_ids
finally: finally:
self.close() self.close()
@@ -886,13 +870,67 @@ class BotDB:
try: try:
self.connect() self.connect()
result = self.cursor.execute("SELECT text " result = self.cursor.execute("SELECT text "
"FROM posts_from_telegram WHERE message_id = ?", (last_post_id,)) "FROM post_from_telegram_suggest WHERE helper_text_message_id = ?",
(last_post_id,))
text = result.fetchone()[0] text = result.fetchone()[0]
self.logger.info(f"Функция get_post_text_from_telegram_by_last_id получила text") self.logger.info(f"Функция get_post_text_from_telegram_by_last_id получила text")
return text return text
except Exception as e: except Exception as e:
self.logger.error(f"Ошибка в функции get_post_text_from_telegram_by_last_id {str(e)}") self.logger.error(f"Ошибка в функции get_post_text_from_telegram_by_last_id {str(e)}")
def add_post_content_in_db(self, post_id: int, message_id: int, content_name: str):
self.logger.info(
f"Запуск функции add_post_content_in_db: post_id={post_id}, message_id={message_id}, "
f"content_name={content_name}")
try:
self.connect()
self.cursor.execute(
"INSERT INTO message_link_to_content (post_id, message_id)"
"VALUES (?, ?)", (post_id, message_id))
self.conn.commit()
self.cursor.execute(
"INSERT INTO content_post_from_telegram (message_id, content_name)"
"VALUES (?, ?)", (message_id, content_name))
self.conn.commit()
self.logger.info(f"Функция add_post_content_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции add_post_content_in_db при добавлении поста в базу данных: {e}")
return False
def add_post_in_db(self, message_id: int, text: str, author_id: int):
self.logger.info(
f"Запуск функции add_post_in_db: message_id={message_id}, "
f"author_id={author_id}")
try:
today = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
self.connect()
self.cursor.execute(
"INSERT INTO post_from_telegram_suggest (message_id, text, author_id, created_at)"
"VALUES (?, ?, ?, ?)", (message_id, text, author_id, today))
self.conn.commit()
self.logger.info(f"Функция add_post_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции add_post_in_db при добавлении поста в базу данных: {e}")
return False
def update_helper_message_in_db(self, message_id: int, helper_message_id: int):
self.logger.info(
f"Запуск функции update_helper_message_in_db: message_id={message_id}, "
f"helper_message_id={helper_message_id}")
try:
self.connect()
self.cursor.execute(
"UPDATE post_from_telegram_suggest SET helper_text_message_id = ? WHERE message_id = ?",
(helper_message_id, message_id,))
self.conn.commit()
self.logger.info(f"Функция update_helper_message_in_db отработала успешно")
return True
except Exception as e:
self.logger.error(f"Ошибка в функции update_helper_message_in_db при добавлении поста в базу данных: {e}")
return False
def add_audio_record(self, file_name, author_id, date_added, listen_count, file_id): def add_audio_record(self, file_name, author_id, date_added, listen_count, file_id):
"""Добавляет информацию о войсе юзера в БД""" """Добавляет информацию о войсе юзера в БД"""
self.logger.info( self.logger.info(

View File

@@ -55,30 +55,19 @@ async def post_for_group(call: CallbackQuery, state: FSMContext):
logger.error(f'Ошибка при публикации фотографии в канал {MAIN_PUBLIC}: {str(e)}') logger.error(f'Ошибка при публикации фотографии в канал {MAIN_PUBLIC}: {str(e)}')
await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3) await call.answer(text='Что-то пошло не так!', show_alert=True, cache_time=3)
elif call.message.text == "^": elif call.message.text == "^":
user_data = await state.get_data() # Получаем контент медиагруппы и текст для публикации
post_content = BotDB.get_post_content_from_telegram_by_last_id(call.message.message_id)
post_text = BotDB.get_post_text_from_telegram_by_last_id(call.message.message_id)
# Получаем идентификатор последнего предложенного сообщения из кэша # Готовим список для удаления
help_message = get_help_message_id(call.message.message_id, user_data) post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
# Получаем идентификатор медиагруппы
media_group_id = help_message - 1
# Получаем контент медиагруппы и текст
post_content = BotDB.get_post_content_from_telegram_by_last_id(media_group_id)
post_text = BotDB.get_post_text_from_telegram_by_last_id(media_group_id)
post_ids = BotDB.get_post_ids_from_telegram_by_last_id(media_group_id)
# Преобразуем результат в список
message_ids = [row[0] for row in post_ids] message_ids = [row[0] for row in post_ids]
message_ids.append(call.message.message_id)
# Добавляем help_message в список
message_ids.append(help_message)
# Выкладываем пост в канал # Выкладываем пост в канал
await send_media_group_to_channel(bot=call.bot, chat_id=MAIN_PUBLIC, post_content=post_content, await send_media_group_to_channel(bot=call.bot, chat_id=MAIN_PUBLIC, post_content=post_content,
post_text=post_text) post_text=post_text)
# TODO: Удалить фотки с локалки # TODO: Удалить фотки с локалки после выкладки?
# TODO: Поменять чтобы записывалось не в FSM
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids) await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
await call.answer(text='Выложено!', show_alert=True, cache_time=3) await call.answer(text='Выложено!', show_alert=True, cache_time=3)
@@ -96,9 +85,12 @@ async def decline_post_for_group(call: CallbackQuery, state: FSMContext):
f'Сообщение отклонено админом {call.from_user.full_name} (ID: {call.from_user.id}).') f'Сообщение отклонено админом {call.from_user.full_name} (ID: {call.from_user.id}).')
await call.answer(text='Отклонено!', show_alert=True, cache_time=3) await call.answer(text='Отклонено!', show_alert=True, cache_time=3)
if call.message.text == '^': if call.message.text == '^':
user_data = await state.get_data() post_ids = BotDB.get_post_ids_from_telegram_by_last_id(call.message.message_id)
media_group_message_id = get_help_message_id(call.message.message_id, user_data) message_ids = [row[0] for row in post_ids]
await call.bot.delete_message(chat_id=MAIN_PUBLIC, message_id=media_group_message_id) message_ids.append(call.message.message_id)
await call.bot.delete_messages(chat_id=GROUP_FOR_POST, message_ids=message_ids)
await call.answer(text='Удалено!', show_alert=True, cache_time=3)
except Exception as e: except Exception as e:
await call.bot.send_message(IMPORTANT_LOGS, await call.bot.send_message(IMPORTANT_LOGS,
f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}") f"Произошла ошибка: {str(e)}\n\nTraceback:\n{traceback.format_exc()}")

View File

@@ -161,6 +161,7 @@ async def suggest_router(message: types.Message, state: FSMContext, album: list
f"Вызов функции suggest_router. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}") f"Вызов функции suggest_router. Пользователь: {message.from_user.id} Имя автора сообщения: {message.from_user.full_name}")
try: try:
if message.content_type == 'text': if message.content_type == 'text':
print(message.content_type)
lower_text = message.text.lower() lower_text = message.text.lower()
# Получаем текст сообщения и преобразовываем его по правилам # Получаем текст сообщения и преобразовываем его по правилам
post_text = get_text_message(lower_text, message.from_user.full_name, post_text = get_text_message(lower_text, message.from_user.full_name,
@@ -179,6 +180,7 @@ async def suggest_router(message: types.Message, state: FSMContext, album: list
await state.set_state("START") await state.set_state("START")
elif message.content_type == 'photo' and message.media_group_id is None: elif message.content_type == 'photo' and message.media_group_id is None:
print(message.content_type)
lower_caption = message.caption.lower() lower_caption = message.caption.lower()
markup = get_reply_keyboard_for_post() markup = get_reply_keyboard_for_post()
# Получаем текст сообщения и преобразовываем его по правилам # Получаем текст сообщения и преобразовываем его по правилам
@@ -197,7 +199,10 @@ async def suggest_router(message: types.Message, state: FSMContext, album: list
elif message.media_group_id is not None: elif message.media_group_id is not None:
post_caption = " " post_caption = " "
#TODO: Поставить запрет на обработку любых типов кроме photo. Запретить работать с forward message if message.content_type != 'photo':
await message.bot.send_message(message.chat.id,
'Я пока не умею работать с таким сообщением. '
'Пришли текст и фото/фоты(ы)')
# Получаем сообщение и проверяем есть ли подпись. Если подпись есть, то преобразуем ее через функцию # Получаем сообщение и проверяем есть ли подпись. Если подпись есть, то преобразуем ее через функцию
if album[0].caption: if album[0].caption:
@@ -217,7 +222,7 @@ async def suggest_router(message: types.Message, state: FSMContext, album: list
help_message_id = await send_text_message(GROUP_FOR_POST, message, "^", markup) help_message_id = await send_text_message(GROUP_FOR_POST, message, "^", markup)
# Записываем в state идентификаторы текстового сообщения И последнего сообщения медиагруппы # Записываем в state идентификаторы текстового сообщения И последнего сообщения медиагруппы
await state.update_data(media_group_message_id=media_group_message_id, help_message_id=help_message_id) BotDB.update_helper_message_in_db(message_id=media_group_message_id, helper_message_id=help_message_id)
# Получаем клавиатуру для пользователя, благодарим за пост, и возвращаем в дефолтное сообщение # Получаем клавиатуру для пользователя, благодарим за пост, и возвращаем в дефолтное сообщение
markup_for_user = get_reply_keyboard(BotDB, message.from_user.id) markup_for_user = get_reply_keyboard(BotDB, message.from_user.id)
@@ -225,6 +230,7 @@ async def suggest_router(message: types.Message, state: FSMContext, album: list
await message.answer(success_send_message, reply_markup=markup_for_user) await message.answer(success_send_message, reply_markup=markup_for_user)
await state.set_state("START") await state.set_state("START")
else: else:
print(f'Тип: {message.content_type}')
await message.bot.send_message(message.chat.id, await message.bot.send_message(message.chat.id,
'Я пока не умею работать с таким сообщением. Пришли текст и фото/фоты(ы)') 'Я пока не умею работать с таким сообщением. Пришли текст и фото/фоты(ы)')
except Exception as e: except Exception as e:

View File

@@ -4,6 +4,8 @@ import sys
from database.db import BotDB from database.db import BotDB
current_dir = os.getcwd()
class BaseDependencyFactory: class BaseDependencyFactory:
def __init__(self): def __init__(self):
@@ -12,7 +14,7 @@ class BaseDependencyFactory:
self.config = configparser.ConfigParser() self.config = configparser.ConfigParser()
self.config.read(config_path) self.config.read(config_path)
self.settings = {} self.settings = {}
self.database = BotDB('database/tg-bot-database') self.database = BotDB(current_dir, 'database/tg-bot-database')
for section in self.config.sections(): for section in self.config.sections():
self.settings[section] = {} self.settings[section] = {}

View File

@@ -85,28 +85,26 @@ async def prepare_media_group_from_middlewares(album, post_caption: str = ''):
return media_group # Возвращаем MediaGroup return media_group # Возвращаем MediaGroup
async def add_in_db_media(sent_message, post_caption: str = ''): async def add_in_db_media(sent_message):
""" """
Идентификатор медиа-группы Идентификатор медиа-группы
Args: Args:
sent_message: sent_message объект из Telegram API. sent_message: sent_message объект из Telegram API
post_caption: Текст подписи к первому фото.
Returns: Returns:
Список InputMediaPhoto. Список InputMediaPhoto.
""" """
media_group_message_id = sent_message[0].message_id # Получаем идентификатор медиа-группы media_group_message_id = sent_message[-1].message_id # Получаем идентификатор медиа-группы
for i, message in enumerate(sent_message): for i, message in enumerate(sent_message):
file_id = message.photo[-1].file_id file_id = message.photo[-1].file_id
file_path = await download_photo(message, file_id=file_id) file_path = await download_photo(message, file_id=file_id)
if i == 0: if i == 0:
BotDB.add_post_from_telegram_in_db(media_group_message_id, message.message_id, 0, file_path, post_caption) BotDB.add_post_content_in_db(media_group_message_id, message.message_id, file_path)
elif i == len(sent_message) - 1: elif i == len(sent_message) - 1:
BotDB.add_post_from_telegram_in_db(media_group_message_id, message.message_id, 1, file_path, post_caption) BotDB.add_post_content_in_db(media_group_message_id, message.message_id, file_path)
else: else:
BotDB.add_post_from_telegram_in_db(media_group_message_id, message.message_id, 0, file_path, post_caption) BotDB.add_post_content_in_db(media_group_message_id, message.message_id, file_path)
return media_group_message_id
async def send_media_group_message_to_private_chat(chat_id: int, message: types.Message, async def send_media_group_message_to_private_chat(chat_id: int, message: types.Message,
@@ -115,7 +113,8 @@ async def send_media_group_message_to_private_chat(chat_id: int, message: types.
chat_id=chat_id, chat_id=chat_id,
media=media_group, media=media_group,
) )
await add_in_db_media(sent_message, post_caption=sent_message[-1].caption) BotDB.add_post_in_db(sent_message[-1].message_id, sent_message[-1].caption, message.from_user.id)
await add_in_db_media(sent_message)
message_id = sent_message[-1].message_id message_id = sent_message[-1].message_id
return message_id return message_id

View File

@@ -1,17 +1,14 @@
import os import os
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
# Получаем текущий рабочий каталог from database.db import BotDB
current_dir = os.path.dirname(os.path.abspath(__file__))
# Переходим на уровень выше, чтобы выйти из папки migrations/ # Получаем текущую директорию
current_dir = os.path.dirname(__file__)
# Переходим на уровень выше
parent_dir = os.path.dirname(current_dir) parent_dir = os.path.dirname(current_dir)
# Строим путь до файла BotDB = BotDB(parent_dir, 'database/tg-bot-database')
tg_bot_database_path = os.path.join(parent_dir, "tg-bot-database")
bdf = BaseDependencyFactory()
BotDB = bdf.get_db()
def get_filename(): def get_filename():
@@ -32,5 +29,6 @@ def main():
BotDB.create_table(migrations_init) BotDB.create_table(migrations_init)
BotDB.update_version(0, get_filename()) BotDB.update_version(0, get_filename())
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@@ -1,8 +1,14 @@
import os import os
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
bdf = BaseDependencyFactory() from database.db import BotDB
BotDB = bdf.get_db()
# Получаем текущую директорию
current_dir = os.path.dirname(__file__)
# Переходим на уровень выше
parent_dir = os.path.dirname(current_dir)
BotDB = BotDB(parent_dir, 'database/tg-bot-database')
def get_filename(): def get_filename():

View File

@@ -0,0 +1,60 @@
import os
from database.db import BotDB
# Получаем текущую директорию
current_dir = os.path.dirname(__file__)
# Переходим на уровень выше
parent_dir = os.path.dirname(current_dir)
BotDB = BotDB(parent_dir, 'database/tg-bot-database')
def get_filename():
"""Возвращает имя файла без расширения."""
filename = os.path.basename(__file__)
filename = os.path.splitext(filename)[0]
return filename
def main():
# Проверка версии миграций
current_version = BotDB.get_current_version() # Добавьте функцию для получения версии
# Выполнение миграций и проверка последней версии
if current_version < 2:
# Скрипты миграции
create_table_sql_1 = """
CREATE TABLE IF NOT EXISTS "post_from_telegram_suggest"
(
message_id INTEGER not null,
text TEXT,
helper_text_message_id INTEGER,
author_id INTEGER,
created_at TEXT
);
"""
create_table_sql_2 = """
CREATE TABLE IF NOT EXISTS message_link_to_content (
post_id INTEGER NOT NULL,
message_id INTEGER NOT NULL
);
"""
create_table_sql_3 = """
CREATE TABLE IF NOT EXISTS content_post_from_telegram (
message_id INTEGER NOT NULL,
content_name TEXT NOT NULL
);
"""
# Применение миграции
BotDB.create_table(create_table_sql_1)
BotDB.create_table(create_table_sql_2)
BotDB.create_table(create_table_sql_3)
filename = get_filename()
BotDB.update_version(2, filename)
if __name__ == "__main__":
main()

View File

@@ -1,7 +1,7 @@
import asyncio import asyncio
from helper_bot.main import start_bot from helper_bot.main import start_bot
from helper_bot.utils.base_dependency_factory import BaseDependencyFactory from helper_bot.utils.base_dependency_factory import BaseDependencyFactory
if __name__ == '__main__': if __name__ == '__main__':
asyncio.run(start_bot(BaseDependencyFactory())) asyncio.run(start_bot(BaseDependencyFactory()))