add migrations
This commit is contained in:
@@ -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)
|
||||
|
||||
66
db.py
66
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):
|
||||
|
||||
7
main.py
7
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"
|
||||
|
||||
27
migrations/000_migrations_init.py
Normal file
27
migrations/000_migrations_init.py
Normal file
@@ -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()
|
||||
56
migrations/001_create_new_tables.py
Normal file
56
migrations/001_create_new_tables.py
Normal file
@@ -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()
|
||||
@@ -1,2 +1,3 @@
|
||||
pyTelegramBotAPI
|
||||
APScheduler~=3.10.4
|
||||
loguru~=0.7.2
|
||||
Reference in New Issue
Block a user