it's version 0.8 Добавлена возможность выключения хранения логов и баз данных

This commit is contained in:
Niken
2026-05-17 21:10:12 +03:00
parent 963ce24e4e
commit 629c2c2739
9 changed files with 145 additions and 28 deletions
+10
View File
@@ -0,0 +1,10 @@
TELEGRAM_BOT_TOKEN=your_token_here
# Полное отключение логов и любого хранения (БД, файлы логов, сохранение message_id)
# DISABLE_PERSISTENCE=1
# Или по отдельности:
# DISABLE_LOGGING=1 — нет логов в консоль и в файл
# DISABLE_STORAGE=1 — нет SQLite, /del не работает, группы /set не сохраняются
SCHEDULE_DRIVE_FOLDER_ID=1WhUFHGkS4qC_e84KRArF4ooXHJr8mL5T
+6
View File
@@ -12,6 +12,8 @@ logger = getLogger(__name__)
def register_handlers(dp: Dispatcher, state: BotState, bot: Bot) -> int: def register_handlers(dp: Dispatcher, state: BotState, bot: Bot) -> int:
async def init_db(): async def init_db():
if Config.DISABLE_STORAGE:
return
async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db: async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db:
await db.execute(""" await db.execute("""
CREATE TABLE IF NOT EXISTS days_to_new_year ( CREATE TABLE IF NOT EXISTS days_to_new_year (
@@ -24,6 +26,8 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot) -> int:
logger.info("База данных инициализирована") logger.info("База данных инициализирована")
async def save_days_to_db(user_id: int, days: int): async def save_days_to_db(user_id: int, days: int):
if Config.DISABLE_STORAGE:
return
logger.debug(f"Сохраняем user_id={user_id}, days={days}") logger.debug(f"Сохраняем user_id={user_id}, days={days}")
async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db: async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db:
await db.execute(""" await db.execute("""
@@ -34,6 +38,8 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot) -> int:
logger.info(f"Запись сохранена: user_id={user_id}, days={days}") logger.info(f"Запись сохранена: user_id={user_id}, days={days}")
async def get_last_days(user_id: int) -> int | None: async def get_last_days(user_id: int) -> int | None:
if Config.DISABLE_STORAGE:
return None
async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db: async with aiosqlite.connect(Config.DAYS_TO_DB_PATH) as db:
async with db.execute( async with db.execute(
"SELECT days FROM days_to_new_year WHERE user_id = ?", (int(user_id),) "SELECT days FROM days_to_new_year WHERE user_id = ?", (int(user_id),)
+27 -4
View File
@@ -1,11 +1,20 @@
import os import os
from pathlib import Path
from dotenv import load_dotenv from dotenv import load_dotenv
from typing import Dict from typing import Dict
load_dotenv()
def _env_bool(name: str, default: bool = False) -> bool:
raw = os.getenv(name)
if raw is None:
return default
return raw.strip().lower() in ("1", "true", "yes", "on")
class Config: class Config:
# Загружаем .env
load_dotenv()
# API # API
API_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN") API_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
@@ -40,9 +49,23 @@ class Config:
"SCHEDULE_DRIVE_FOLDER_ID", "1WhUFHGkS4qC_e84KRArF4ooXHJr8mL5T" "SCHEDULE_DRIVE_FOLDER_ID", "1WhUFHGkS4qC_e84KRArF4ooXHJr8mL5T"
) )
# Отключение логов и хранения (см. .env.example)
# DISABLE_PERSISTENCE=1 — выключает и логи, и все БД/файлы сразу
_NO_PERSISTENCE = _env_bool("DISABLE_PERSISTENCE")
DISABLE_LOGGING = (
_env_bool("DISABLE_LOGGING")
if os.getenv("DISABLE_LOGGING") is not None
else _NO_PERSISTENCE
)
DISABLE_STORAGE = (
_env_bool("DISABLE_STORAGE")
if os.getenv("DISABLE_STORAGE") is not None
else _NO_PERSISTENCE
)
# Пути # Пути
LOG_FILE = "storage/log/bot.log" LOG_FILE = Path("storage/log/bot.log")
DAYS_TO_DB_PATH = "addons/x_days_to/days_to_new_year.db" DAYS_TO_DB_PATH = Path("addons/x_days_to/days_to_new_year.db")
if __name__ == "__main__": if __name__ == "__main__":
+25 -3
View File
@@ -17,8 +17,14 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
@saving @saving
@admin_required(3) @admin_required(3)
async def send_log(message: Message): async def send_log(message: Message):
if Config.DISABLE_LOGGING:
await message.answer("📝 Логирование отключено (DISABLE_LOGGING=1).")
return
if Config.DISABLE_STORAGE:
await message.answer("📝 Файл логов не ведётся (DISABLE_STORAGE=1).")
return
try: try:
log_file = types.FSInputFile(Config.LOG_FILE) log_file = types.FSInputFile(str(Config.LOG_FILE))
await message.answer_document(log_file, caption="📑 Логи бота") await message.answer_document(log_file, caption="📑 Логи бота")
except FileNotFoundError: except FileNotFoundError:
await message.answer("Файл логов пока не создан.") await message.answer("Файл логов пока не создан.")
@@ -31,7 +37,12 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
from utils.mac_metrics import get_macbook_battery_level, get_process_usage from utils.mac_metrics import get_macbook_battery_level, get_process_usage
try: try:
stats = analyze_bot_logs(Config.LOG_FILE) if Config.DISABLE_LOGGING or Config.DISABLE_STORAGE:
await message.answer(
"📊 Аналитика по логам недоступна: логирование или хранение отключено в .env"
)
return
stats = analyze_bot_logs(str(Config.LOG_FILE))
batt = await get_macbook_battery_level() batt = await get_macbook_battery_level()
usage = await get_process_usage() usage = await get_process_usage()
status_text = ( status_text = (
@@ -53,7 +64,12 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
async def stat(message: Message): async def stat(message: Message):
from utils.analytics import analyze_bot_logs from utils.analytics import analyze_bot_logs
stats = analyze_bot_logs(Config.LOG_FILE) if Config.DISABLE_LOGGING or Config.DISABLE_STORAGE:
await message.answer(
"📊 Аналитика по логам недоступна: логирование или хранение отключено в .env"
)
return
stats = analyze_bot_logs(str(Config.LOG_FILE))
await message.answer( await message.answer(
create_statistics_text(stats), reply_to_message_id=message.message_id create_statistics_text(stats), reply_to_message_id=message.message_id
) )
@@ -61,6 +77,12 @@ def register_handlers(dp: Dispatcher, state: BotState, bot: Bot):
@dp.message(Command("del")) @dp.message(Command("del"))
@admin_required(1) @admin_required(1)
async def delete_all_messages(message: Message): async def delete_all_messages(message: Message):
if Config.DISABLE_STORAGE:
await message.answer(
"📭 Хранение сообщений отключено (DISABLE_STORAGE=1).",
reply_to_message_id=message.message_id,
)
return
messages = load_messages() messages = load_messages()
if not messages: if not messages:
sent = await message.answer( sent = await message.answer(
+4 -10
View File
@@ -1,17 +1,11 @@
from asyncio import run from asyncio import run
from logging import basicConfig, FileHandler, StreamHandler, INFO, getLogger from logging import getLogger
from bot.core import TelegramBot from bot.core import TelegramBot
from config import Config from config import Config
from utils.logging_config import setup_logging
# Настройка логирования setup_logging()
basicConfig(
level=INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
handlers=[FileHandler(Config.LOG_FILE, encoding="utf-8"), StreamHandler()],
force=True,
)
logger = getLogger(__name__) logger = getLogger(__name__)
+6 -1
View File
@@ -1,6 +1,9 @@
import sqlite3 import sqlite3
from pathlib import Path
DIR = "/Users/mac/myfirstprogramm/storage/message.db" from config import Config
DIR = Path(__file__).resolve().parent / "message.db"
if __name__ == "__main__": if __name__ == "__main__":
db = sqlite3.connect(DIR) db = sqlite3.connect(DIR)
@@ -33,4 +36,6 @@ if __name__ == "__main__":
def get_db(): def get_db():
if Config.DISABLE_STORAGE:
raise RuntimeError("Хранение отключено (DISABLE_STORAGE=1)")
return sqlite3.connect(DIR) return sqlite3.connect(DIR)
+13 -1
View File
@@ -1,7 +1,11 @@
from .DB import get_db from config import Config
def save_message(chat_id: int, message_id: int): def save_message(chat_id: int, message_id: int):
if Config.DISABLE_STORAGE:
return
from .DB import get_db
db = get_db() db = get_db()
cur = db.cursor() cur = db.cursor()
cur.execute("INSERT INTO message VALUES (?, ?)", (int(chat_id), int(message_id))) cur.execute("INSERT INTO message VALUES (?, ?)", (int(chat_id), int(message_id)))
@@ -11,6 +15,10 @@ def save_message(chat_id: int, message_id: int):
def load_messages(): def load_messages():
if Config.DISABLE_STORAGE:
return []
from .DB import get_db
db = get_db() db = get_db()
cur = db.cursor() cur = db.cursor()
cur.execute("SELECT * FROM message") cur.execute("SELECT * FROM message")
@@ -21,6 +29,10 @@ def load_messages():
def clear_messages(): def clear_messages():
if Config.DISABLE_STORAGE:
return
from .DB import get_db
db = get_db() db = get_db()
cur = db.cursor() cur = db.cursor()
cur.execute("DELETE FROM message") cur.execute("DELETE FROM message")
+20 -9
View File
@@ -1,6 +1,13 @@
from .DB import get_db from config import Config
_DEFAULT_GROUP = "30тс"
def save_user(user_id: int, group: str = _DEFAULT_GROUP):
if Config.DISABLE_STORAGE:
return
from .DB import get_db
def save_user(user_id: int, group: str = "30тс"):
db = get_db() db = get_db()
cur = db.cursor() cur = db.cursor()
cur.execute("INSERT INTO users (user_id, user_group) VALUES (?, ?)", (user_id, group)) cur.execute("INSERT INTO users (user_id, user_group) VALUES (?, ?)", (user_id, group))
@@ -8,19 +15,20 @@ def save_user(user_id: int, group: str = "30тс"):
cur.close() cur.close()
db.close() db.close()
def set_group(user_id: int, group: str = "30тс"):
def set_group(user_id: int, group: str = _DEFAULT_GROUP):
if Config.DISABLE_STORAGE:
return
from .DB import get_db
db = get_db() db = get_db()
cur = db.cursor() cur = db.cursor()
# проверяем, есть ли пользователь
cur.execute("SELECT 1 FROM users WHERE user_id = ?", (user_id,)) cur.execute("SELECT 1 FROM users WHERE user_id = ?", (user_id,))
exists = cur.fetchone() exists = cur.fetchone()
if exists: if exists:
# если есть — обновляем группу
cur.execute("UPDATE users SET user_group = ? WHERE user_id = ?", (group, user_id)) cur.execute("UPDATE users SET user_group = ? WHERE user_id = ?", (group, user_id))
else: else:
# если нет — регистрируем нового пользователя
cur.execute("INSERT INTO users (user_id, user_group) VALUES (?, ?)", (user_id, group)) cur.execute("INSERT INTO users (user_id, user_group) VALUES (?, ?)", (user_id, group))
db.commit() db.commit()
@@ -28,7 +36,11 @@ def set_group(user_id: int, group: str = "30тс"):
db.close() db.close()
def get_group(user_id: int, default: str = "30тс") -> str: def get_group(user_id: int, default: str = _DEFAULT_GROUP) -> str:
if Config.DISABLE_STORAGE:
return default
from .DB import get_db
db = get_db() db = get_db()
cur = db.cursor() cur = db.cursor()
cur.execute("SELECT user_group FROM users WHERE user_id = ?", (user_id,)) cur.execute("SELECT user_group FROM users WHERE user_id = ?", (user_id,))
@@ -36,7 +48,6 @@ def get_group(user_id: int, default: str = "30тс") -> str:
if row: if row:
group = row[0] group = row[0]
else: else:
# если пользователя нет — регистрируем с дефолтной группой
cur.execute("INSERT INTO users (user_id, user_group) VALUES (?, ?)", (user_id, default)) cur.execute("INSERT INTO users (user_id, user_group) VALUES (?, ?)", (user_id, default))
db.commit() db.commit()
group = default group = default
+34
View File
@@ -0,0 +1,34 @@
import logging
from logging import CRITICAL, NullHandler, getLogger
from config import Config
def setup_logging() -> None:
"""Настройка логирования. При DISABLE_LOGGING — полное отключение."""
root = getLogger()
if Config.DISABLE_LOGGING:
root.handlers.clear()
root.addHandler(NullHandler())
root.setLevel(CRITICAL)
logging.disable(CRITICAL)
return
from logging import INFO, StreamHandler, basicConfig
from logging.handlers import FileHandler
handlers: list[logging.Handler] = [StreamHandler()]
if not Config.DISABLE_STORAGE:
log_path = Config.LOG_FILE
log_path.parent.mkdir(parents=True, exist_ok=True)
handlers.append(FileHandler(log_path, encoding="utf-8"))
basicConfig(
level=INFO,
format="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
handlers=handlers,
force=True,
)