diff --git a/custom_logger.py b/custom_logger.py index 7a76c48..28b9655 100644 --- a/custom_logger.py +++ b/custom_logger.py @@ -1,17 +1,11 @@ -import logging -import os import datetime -from logging.handlers import RotatingFileHandler +import os +from loguru import logger class Logger: def __init__(self, name): - # Инициализация логгера - self.logger = logging.getLogger(name) # Сохраняем logger как свойство класса - self.logger.setLevel(logging.INFO) - - # Формат записи логов - formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(filename)s - %(lineno)d - %(message)s') + self.logger = logger.bind(name=name) # Получение сегодняшней даты для имени файла today = datetime.date.today().strftime('%Y-%m-%d') @@ -22,25 +16,16 @@ class Logger: if not os.path.exists(logs_dir): # Если не существует, создаем ее os.makedirs(logs_dir) - filename = f'logs/helper_bot_{today}.log' + filename = f'{logs_dir}/helper_bot_{today}.log' - # Создание обработчика для файла логов - file_handler = RotatingFileHandler( + # Настройка формата логов + self.logger.add( filename, - mode='a', - maxBytes=10 * 1024 * 1024, # Максимальный размер файла (10 МБ) - backupCount=3 # Количество резервных файлов + rotation="00:00", + retention="5 days", + compression="zip", + format="{time:YYYY-MM-DD at HH:mm:ss} | {level} | {name} | {line} | {message}", ) - file_handler.setFormatter(formatter) - - # Добавление обработчика к логгеру - self.logger.addHandler(file_handler) - - # Добавление стандартного обработчика - # чтобы сообщения также отображались на консоли - console_handler = logging.StreamHandler() - console_handler.setFormatter(formatter) - self.logger.addHandler(console_handler) def info(self, message): self.logger.info(message) @@ -55,4 +40,4 @@ class Logger: self.logger.error(message) def critical(self, message): - self.logger.critical(message) \ No newline at end of file + self.logger.critical(message) diff --git a/db.py b/db.py index 75dab11..76cef3f 100644 --- a/db.py +++ b/db.py @@ -1,23 +1,64 @@ import sqlite3 import configparser import os -import sys -import custom_logger +from datetime import datetime +from loguru import logger +from custom_logger import Logger -config_path = os.path.join(sys.path[0], 'settings.ini') +db_logger = Logger(name='db') +script_dir = os.path.dirname(os.path.abspath(__file__)) +config_path = os.path.join(script_dir, 'settings.ini') config = configparser.ConfigParser() config.read(config_path) LOGS = config.getboolean('Settings', 'logs') IMPORTANT_LOGS = config.get('Telegram', 'important_logs') -db_logger = custom_logger.Logger('database') - class BotDB: - def __init__(self, db_file): + def __init__(self): + db_file_path = os.path.dirname(os.path.abspath(__file__)) + db_file = os.path.join(db_file_path, 'tg-bot-database') self.conn = sqlite3.connect(db_file, check_same_thread=False) self.cursor = self.conn.cursor() + logger.info(f'Подключен к базе данных: {db_file_path}') + + def create_table(self, sql_script): + """Создает таблицу в базе.""" + try: + cursor = self.conn.cursor() + cursor.execute(sql_script) + except Exception as e: + print(f"Ошибка при создании таблицы: {e}") + + def get_current_version(self): + """Получает текущую версию миграций из таблицы migrations.""" + try: + cursor = self.conn.cursor() + cursor.execute("SELECT version FROM migrations ORDER BY version DESC LIMIT 1") + version = cursor.fetchone()[0] + return version + except Exception as e: + print(f"Ошибка при получении версии: {e}") + return 0 + + def update_version(self, new_version, script_name): + """Обновляет версию миграций в таблице migrations.""" + logger.info(f'Попытка обновления версии: {new_version}, скрипт: {script_name}') + try: + current_date = datetime.now() + today = current_date.strftime("%d-%m-%Y %H:%M:%S") + cursor = self.conn.cursor() + cursor.execute( + "INSERT INTO migrations (version, script_name, created_at) VALUES(?, ?, ?)", + (new_version, script_name, today), + ) + self.conn.commit() + logger.info(f"Версия обновлена: {new_version}, скрипт: {script_name}") + except sqlite3.IntegrityError as e: + logger.error(f"Ошибка при обновлении версии: {e}") + except Exception as e: + logger.error(f"Ошибка при обновлении версии: {e}") # TODO: Deprecated, удалить def get_message_from_db(self, type: str, username): @@ -264,10 +305,10 @@ class BotDB: #TODO: Функция всегда возвращает true, даже если такого id нет в таблице self.cursor.execute("DELETE FROM blacklist WHERE user_id = ?", (user_id,)) self.conn.commit() - db_logger.info(f"User with ID {user_id} successfull delete.") + logger.info(f"Пользователь с идентификатором {user_id} успешно удален.") return True except sqlite3.Error as error: - db_logger.error(f"Error delete user with ID {user_id} from blacklist table: {str(error)}") + logger.error(f"Ошибка удаления пользователя с идентификатором {user_id} из таблицы blacklist. Ошибка: {str(error)}") return False def add_new_message_in_db(self, message_text, user_id, message_id, date, has_answer): @@ -302,14 +343,17 @@ class BotDB: result = self.cursor.fetchone() return bool(result) - def add_admin(self, user_id, username=None): + def add_admin(self, user_id, role): """ Добавляет пользователя в список администраторов. Args: user_id: ID пользователя Telegram. - username: Username пользователя (необязательно). + role: Роль пользователя. + Доступные варианты: + 1. creator - создатель + 2. admin - обычная роль """ - self.cursor.execute("INSERT INTO admins (user_id, username) VALUES (?, ?)", (user_id, username)) + self.cursor.execute("INSERT INTO admins (user_id, role) VALUES (?, ?)", (user_id, role)) return self.conn.commit() def remove_admin(self, user_id): diff --git a/main.py b/main.py index 6cb05a3..9cbe318 100644 --- a/main.py +++ b/main.py @@ -34,13 +34,9 @@ LOGS = config.getboolean('Settings', 'logs') TEST = config.getboolean('Settings', 'test') # Инициализируем бота и базку -BotDB = BotDB('tg-bot-database') +BotDB = BotDB() -#TODO: Дописать функцию разбана и подключить ее к обработке коллбеков -#TODO: Подумать что сделать с процессом наступления даты разбана -#TODO: Сделать функционал игнора забаненных - class State(Enum): START = "START" SUGGEST = "SUGGEST" @@ -214,7 +210,6 @@ class TelegramHelperBot: # Получение сегодняшней даты в формате DD-MM-YYYY current_date = datetime.now() today = current_date.strftime("%d-%m-%Y") - print(today) # Получение списка разблокированных пользователей unblocked_users = BotDB.get_users_for_unblock_today(today) message = "Разблокированные пользователи:\n" diff --git a/migrations/000_migrations_init.py b/migrations/000_migrations_init.py new file mode 100644 index 0000000..4ba49b0 --- /dev/null +++ b/migrations/000_migrations_init.py @@ -0,0 +1,27 @@ +import os +from db import BotDB + + +BotDB = BotDB() + + +def get_filename(): + """Возвращает имя файла без расширения.""" + filename = os.path.basename(__file__) + filename = os.path.splitext(filename)[0] + return filename + + +def main(): + migrations_init = """ + CREATE TABLE IF NOT EXISTS migrations ( + version INTEGER PRIMARY KEY NOT NULL, + script_name TEXT NOT NULL, + created_at TEXT + ); + """ + BotDB.create_table(migrations_init) + BotDB.update_version(0, get_filename()) + +if __name__ == "__main__": + main() diff --git a/migrations/001_create_new_tables.py b/migrations/001_create_new_tables.py new file mode 100644 index 0000000..cd45af5 --- /dev/null +++ b/migrations/001_create_new_tables.py @@ -0,0 +1,56 @@ +import os +from db import BotDB + +BotDB = BotDB() + + +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 < 1: + # Скрипты миграции + create_table_sql_1 = """ + CREATE TABLE IF NOT EXISTS "admins" ( + user_id INTEGER NOT NULL, + "role" TEXT + ); + """ + create_table_sql_2 = """CREATE TABLE IF NOT EXISTS "blacklist" + ( + "user_id" INTEGER NOT NULL UNIQUE, + "user_name" INTEGER, + "message_for_user" INTEGER, + "date_to_unban" INTEGER + ); + """ + create_table_sql_3 = """ + CREATE TABLE IF NOT EXISTS user_messages ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + message_text TEXT, + user_id INTEGER, + message_id INTEGER NOT NULL, + date TEXT + ); + """ + # Применение миграции + BotDB.create_table(create_table_sql_1) + BotDB.create_table(create_table_sql_2) + BotDB.create_table(create_table_sql_3) + BotDB.add_admin(842766148, 'creator') + BotDB.add_admin(920057022, 'admin') + filename = get_filename() + + BotDB.update_version(1, filename) + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt index 682a9e4..35a1522 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ pyTelegramBotAPI -APScheduler~=3.10.4 \ No newline at end of file +APScheduler~=3.10.4 +loguru~=0.7.2 \ No newline at end of file