Upload files to "/"
This commit is contained in:
+281
@@ -0,0 +1,281 @@
|
||||
# ensure_db.py
|
||||
import mysql.connector
|
||||
import os
|
||||
import time
|
||||
import random
|
||||
from datetime import datetime
|
||||
from mysql.connector import errorcode
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Загрузка переменных окружения
|
||||
load_dotenv()
|
||||
|
||||
# Конфигурация из переменных окружения
|
||||
DB_CONFIG = {
|
||||
'host': os.getenv('MDB_HOST', 'localhost'),
|
||||
'user': os.getenv('MDB_USER', 'root'),
|
||||
'password': os.getenv('MDB_PW', ''),
|
||||
'database': os.getenv('MDBASE', 'vk_posts')
|
||||
}
|
||||
LOG_FILE = os.getenv('LOG_FILE', 'vk_loader.log')
|
||||
LOG_PREFIX = "DB_Ensure"
|
||||
|
||||
def log_message(message, max_retries=5, retry_delay=0.1):
|
||||
"""Функция логирования с повторными попытками"""
|
||||
if not LOG_FILE:
|
||||
return False
|
||||
|
||||
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||
log_line = f"[{timestamp}] [{LOG_PREFIX}] {message}\n"
|
||||
|
||||
for attempt in range(max_retries):
|
||||
try:
|
||||
with open(LOG_FILE, 'a', encoding='utf-8') as log:
|
||||
log.write(log_line)
|
||||
return True
|
||||
except (IOError, OSError) as e:
|
||||
if attempt < max_retries - 1:
|
||||
time.sleep(retry_delay * (1 + random.random()))
|
||||
else:
|
||||
print(f"Failed to log: {e}")
|
||||
return False
|
||||
|
||||
def ensure_database_structure():
|
||||
"""Основная функция проверки и создания БД/таблиц"""
|
||||
conn = None
|
||||
cursor = None
|
||||
|
||||
try:
|
||||
# Подключение без указания базы данных
|
||||
conn = mysql.connector.connect(
|
||||
host=DB_CONFIG['host'],
|
||||
user=DB_CONFIG['user'],
|
||||
password=DB_CONFIG['password']
|
||||
)
|
||||
cursor = conn.cursor(buffered=True) # Используем буферизованный курсор
|
||||
|
||||
# Создание базы данных если не существует
|
||||
cursor.execute(f"CREATE DATABASE IF NOT EXISTS {DB_CONFIG['database']} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci")
|
||||
cursor.execute(f"USE {DB_CONFIG['database']}")
|
||||
log_message("Database checked/created successfully")
|
||||
|
||||
# Список таблиц и их структур
|
||||
tables = {
|
||||
'posts': '''
|
||||
CREATE TABLE posts (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
vk_post_id BIGINT NOT NULL UNIQUE,
|
||||
text TEXT,
|
||||
image_url VARCHAR(2048),
|
||||
vk_post_url VARCHAR(2048),
|
||||
published_at DATETIME NULL,
|
||||
is_poll BOOLEAN DEFAULT 0,
|
||||
poll_question TEXT,
|
||||
poll_options TEXT,
|
||||
poll_multiple BOOLEAN DEFAULT 0,
|
||||
poll_end_date DATETIME NULL,
|
||||
marked_for_publication BOOLEAN DEFAULT 0,
|
||||
published_in_tg BOOLEAN DEFAULT 0,
|
||||
tg_publication_date DATETIME NULL,
|
||||
tg_message_id BIGINT NULL,
|
||||
tg_poll_id BIGINT NULL,
|
||||
tg_markpost_id BIGINT NULL,
|
||||
tg_poll_results TEXT DEFAULT '',
|
||||
is_event BOOLEAN DEFAULT 0,
|
||||
shortname VARCHAR(100),
|
||||
action_number BIGINT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
''',
|
||||
'marks': '''
|
||||
CREATE TABLE marks (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
tg_post_id BIGINT NOT NULL,
|
||||
tg_user_id BIGINT NOT NULL,
|
||||
tg_user_name VARCHAR(255),
|
||||
autolink BOOLEAN DEFAULT 0,
|
||||
reminded_at DATETIME NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
''',
|
||||
'marks_evt': '''
|
||||
CREATE TABLE marks_evt (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
tg_event_id BIGINT NOT NULL,
|
||||
tg_user_id BIGINT NOT NULL,
|
||||
tg_user_name VARCHAR(255),
|
||||
autolink BOOLEAN DEFAULT 0,
|
||||
reminded_at DATETIME NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
''',
|
||||
'users': '''
|
||||
CREATE TABLE users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(255) UNIQUE NOT NULL,
|
||||
password VARCHAR(255) NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
''',
|
||||
'events': '''
|
||||
CREATE TABLE events (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
id_event BIGINT NOT NULL,
|
||||
number BIGINT NOT NULL,
|
||||
unit_name VARCHAR(255),
|
||||
name VARCHAR(255),
|
||||
about VARCHAR(2048),
|
||||
about_social_picture VARCHAR(2048),
|
||||
modified DATETIME NULL,
|
||||
added DATETIME NULL,
|
||||
tags VARCHAR(255),
|
||||
is_canceled BOOLEAN DEFAULT 0,
|
||||
accepted BOOLEAN DEFAULT 0,
|
||||
denied BOOLEAN DEFAULT 0,
|
||||
is_visible BOOLEAN DEFAULT 0,
|
||||
marked_to_publication BOOLEAN DEFAULT 0,
|
||||
is_posted_tg BOOLEAN DEFAULT 0,
|
||||
tg_message_id BIGINT NULL,
|
||||
tg_info_id BIGINT NULL,
|
||||
tg_posted_date DATETIME NULL,
|
||||
announcement_link BIGINT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
''',
|
||||
'interlinks': '''
|
||||
CREATE TABLE interlinks (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
post_id INT NOT NULL,
|
||||
event_id INT NOT NULL,
|
||||
created_at DATETIME NULL,
|
||||
FOREIGN KEY (post_id)
|
||||
REFERENCES posts(id)
|
||||
ON DELETE CASCADE,
|
||||
FOREIGN KEY (event_id)
|
||||
REFERENCES events(id)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
|
||||
'''
|
||||
}
|
||||
|
||||
# Проверка и создание таблиц
|
||||
for table_name, table_sql in tables.items():
|
||||
try:
|
||||
# Проверяем существование таблицы через information_schema
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = %s AND table_name = %s
|
||||
""", (DB_CONFIG['database'], table_name))
|
||||
|
||||
if cursor.fetchone()[0] == 0:
|
||||
# Таблица не существует, создаем её
|
||||
cursor.execute(table_sql)
|
||||
log_message(f"Table {table_name} created")
|
||||
else:
|
||||
log_message(f"Table {table_name} exists")
|
||||
|
||||
except mysql.connector.Error as err:
|
||||
log_message(f"Error checking/creating table {table_name}: {err}")
|
||||
raise err
|
||||
|
||||
# Проверка и добавление новых полей в существующие таблицы
|
||||
table_alterations = {
|
||||
'marks': [
|
||||
{'column': 'autolink', 'type': 'BOOLEAN DEFAULT 0'},
|
||||
{'column': 'reminded_at', 'type': 'DATETIME NULL'}
|
||||
],
|
||||
'marks_evt': [
|
||||
{'column': 'autolink', 'type': 'BOOLEAN DEFAULT 0'},
|
||||
{'column': 'reminded_at', 'type': 'DATETIME NULL'}
|
||||
]
|
||||
}
|
||||
|
||||
for table_name, alterations in table_alterations.items():
|
||||
for alteration in alterations:
|
||||
column = alteration['column']
|
||||
column_type = alteration['type']
|
||||
|
||||
try:
|
||||
# Проверяем существование столбца
|
||||
cursor.execute("""
|
||||
SELECT COUNT(*)
|
||||
FROM information_schema.columns
|
||||
WHERE table_schema = %s AND table_name = %s AND column_name = %s
|
||||
""", (DB_CONFIG['database'], table_name, column))
|
||||
|
||||
if cursor.fetchone()[0] == 0:
|
||||
# Столбец не существует, добавляем его
|
||||
cursor.execute(f"ALTER TABLE {table_name} ADD COLUMN {column} {column_type}")
|
||||
log_message(f"Added column {column} to table {table_name}")
|
||||
else:
|
||||
log_message(f"Column {column} already exists in table {table_name}")
|
||||
|
||||
except mysql.connector.Error as err:
|
||||
log_message(f"Error checking/adding column {column} to table {table_name}: {err}")
|
||||
|
||||
# Создание индексов для таблицы marks
|
||||
marks_indexes = [
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS uniq_post_user ON marks (tg_post_id, tg_user_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_post_subscribers ON marks (tg_post_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_user_subscriptions ON marks (tg_user_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_created_at ON marks (created_at)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_post_created ON marks (tg_post_id, created_at)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_tg_post_id ON marks (tg_post_id)'
|
||||
]
|
||||
|
||||
# Создание индексов для таблицы marks_evt
|
||||
marks_evt_indexes = [
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS uniq_event_user ON marks_evt (tg_event_id, tg_user_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_event_subscribers ON marks_evt (tg_event_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_user_event_subscriptions ON marks_evt (tg_user_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_marks_evt_created_at ON marks_evt (created_at)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_event_created ON marks_evt (tg_event_id, created_at)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_tg_event_id ON marks_evt (tg_event_id)'
|
||||
]
|
||||
|
||||
# Создание индексов для таблицы events
|
||||
events_indexes = [
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS idx_events_id_event ON events (id_event)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_events_number ON events (number)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_events_is_visible ON events (is_visible)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_events_is_posted_tg ON events (is_posted_tg)',
|
||||
]
|
||||
|
||||
# Создание индексов для таблицы interlinks
|
||||
interlinks_indexes = [
|
||||
'CREATE INDEX IF NOT EXISTS idx_interlinks_post_id ON interlinks (post_id)',
|
||||
'CREATE INDEX IF NOT EXISTS idx_interlinks_event_id ON interlinks (event_id)',
|
||||
'CREATE UNIQUE INDEX IF NOT EXISTS uniq_post_event ON interlinks (post_id, event_id)'
|
||||
]
|
||||
|
||||
# Объединяем все индексы
|
||||
all_indexes = marks_indexes + marks_evt_indexes + events_indexes + interlinks_indexes
|
||||
|
||||
for index_sql in all_indexes:
|
||||
try:
|
||||
cursor.execute(index_sql)
|
||||
index_name = index_sql.split('IF NOT EXISTS')[1].split(' ON ')[0].strip()
|
||||
log_message(f"Index created: {index_name}")
|
||||
except mysql.connector.Error as err:
|
||||
log_message(f"Error creating index: {err}")
|
||||
|
||||
conn.commit()
|
||||
log_message("Database structure ensured successfully")
|
||||
|
||||
except mysql.connector.Error as err:
|
||||
log_message(f"Database error: {err}")
|
||||
raise
|
||||
finally:
|
||||
# Аккуратно закрываем соединение и курсор
|
||||
try:
|
||||
if cursor:
|
||||
cursor.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
if conn and conn.is_connected():
|
||||
conn.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
ensure_database_structure()
|
||||
Reference in New Issue
Block a user