Add quote bot
This commit is contained in:
+91
@@ -0,0 +1,91 @@
|
||||
import logging
|
||||
|
||||
from telebot import TeleBot
|
||||
from telebot.types import Message
|
||||
|
||||
from .config import TOKEN, ADMIN_IDS
|
||||
from .quotes import get_random_quote, add_quote, count_quotes
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s [%(levelname)s] %(message)s",
|
||||
)
|
||||
|
||||
bot = TeleBot(TOKEN)
|
||||
|
||||
# ─── Хэндлеры ────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
@bot.message_handler(commands=["start"])
|
||||
def cmd_start(message: Message):
|
||||
name = message.from_user.first_name
|
||||
bot.reply_to(
|
||||
message,
|
||||
f"Привет, {name}! 👋\n\n"
|
||||
"Я бот с цитатами. Вот что я умею:\n"
|
||||
"/quote — случайная цитата\n"
|
||||
"/stats — сколько цитат в базе\n"
|
||||
"/add <текст> — добавить цитату (только для администратора)",
|
||||
)
|
||||
logging.info(
|
||||
f"[/start] user_id={message.from_user.id} ({message.from_user.first_name})"
|
||||
)
|
||||
|
||||
|
||||
@bot.message_handler(commands=["quote"])
|
||||
def cmd_quote(message: Message):
|
||||
quote = get_random_quote()
|
||||
if quote is None:
|
||||
bot.reply_to(
|
||||
message,
|
||||
"😔 Цитат пока нет. Попросите администратора добавить хотя бы одну!",
|
||||
)
|
||||
else:
|
||||
bot.reply_to(message, f"💬 {quote}")
|
||||
logging.info(f"[/quote] user_id={message.from_user.id}")
|
||||
|
||||
|
||||
@bot.message_handler(commands=["stats"])
|
||||
def cmd_stats(message: Message):
|
||||
total = count_quotes()
|
||||
bot.reply_to(message, f"📚 В базе {total} цитат.")
|
||||
logging.info(f"[/stats] user_id={message.from_user.id}, total={total}")
|
||||
|
||||
|
||||
@bot.message_handler(commands=["add"])
|
||||
def cmd_add(message: Message):
|
||||
# Проверяем права
|
||||
if message.from_user.id not in ADMIN_IDS:
|
||||
bot.reply_to(message, "🚫 У вас нет прав для добавления цитат.")
|
||||
logging.warning(
|
||||
f"[/add] Unauthorized attempt by user_id={message.from_user.id}")
|
||||
return
|
||||
|
||||
# Извлекаем текст после команды /add
|
||||
parts = message.text.split(maxsplit=1)
|
||||
if len(parts) < 2 or not parts[1].strip():
|
||||
bot.reply_to(
|
||||
message, "✏️ Укажите текст цитаты. Пример:\n/add Жизнь прекрасна!")
|
||||
return
|
||||
|
||||
quote_text = parts[1].strip()
|
||||
added = add_quote(quote_text)
|
||||
|
||||
if added:
|
||||
bot.reply_to(message, f"✅ Цитата добавлена:\n\n💬 {quote_text}")
|
||||
logging.info(
|
||||
f"[/add] Added new quote by user_id={message.from_user.id}")
|
||||
else:
|
||||
bot.reply_to(message, "⚠️ Такая цитата уже есть в базе.")
|
||||
|
||||
|
||||
# ─── Точка входа ─────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
def main():
|
||||
logging.info("Бот запущен в режиме polling...")
|
||||
bot.infinity_polling()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,8 @@
|
||||
import os
|
||||
|
||||
TOKEN = os.environ.get("TOKEN")
|
||||
if not TOKEN:
|
||||
raise ValueError("Переменная окружения TOKEN не задана!")
|
||||
|
||||
admin_ids_raw = os.environ.get("ADMIN_IDS", "")
|
||||
ADMIN_IDS = {int(i) for i in admin_ids_raw.split(",") if i.strip()}
|
||||
@@ -0,0 +1,39 @@
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
DATA_FILE = Path(__file__).parent.parent / "data" / "quotes.txt"
|
||||
|
||||
|
||||
def _read_all() -> list[str]:
|
||||
"""Читает все цитаты из файла. Возвращает пустой список, если файл пуст или не существует."""
|
||||
if not DATA_FILE.exists():
|
||||
return []
|
||||
lines = DATA_FILE.read_text(encoding="utf-8").splitlines()
|
||||
return [line for line in lines if line.strip()]
|
||||
|
||||
|
||||
def get_random_quote() -> str | None:
|
||||
"""Возвращает случайную цитату или None, если их нет."""
|
||||
quotes = _read_all()
|
||||
if not quotes:
|
||||
return None
|
||||
return random.choice(quotes) # nosec
|
||||
|
||||
|
||||
def add_quote(text: str) -> bool:
|
||||
"""
|
||||
Добавляет новую цитату в файл.
|
||||
Возвращает False, если такая цитата уже существует, иначе True.
|
||||
"""
|
||||
quotes = _read_all()
|
||||
if text in quotes:
|
||||
return False
|
||||
DATA_FILE.parent.mkdir(parents=True, exist_ok=True)
|
||||
with DATA_FILE.open("a", encoding="utf-8") as f:
|
||||
f.write(text + "\n")
|
||||
return True
|
||||
|
||||
|
||||
def count_quotes() -> int:
|
||||
"""Возвращает количество цитат в базе."""
|
||||
return len(_read_all())
|
||||
Reference in New Issue
Block a user