Я пробывал в твоем коде через telebot и да тоже не реагирует не как и я тебе переделал на aiogram и все заработало.
Ну а дальше уже сам реализовывай все остальные свои задачи.
Работоспособность проверялась на последней версии на дату публикации python 3.13
from __future__ import annotations
import logging
import os
import shelve
from datetime import datetime, timedelta
from pathlib import Path
from aiogram import Bot, Dispatcher, F
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.filters import Command
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.client.default import DefaultBotProperties
# Configure logging
logging.basicConfig(level=logging.INFO)
# Constants
TRIAL_FLAG = "active"
class UltraLiteSubBot:
__slots__ = ("_bot", "_dp", "_prices", "_db", "_cmd_map", "_cb_map")
def __init__(self, token: str, prices: dict[str, int], db: shelve.DbfilenameShelf):
self._bot = Bot(token=token, default=DefaultBotProperties(parse_mode="HTML"))
self._dp = Dispatcher(storage=MemoryStorage())
self._prices = prices
self._db = db
self._cmd_map = {
"start": self._show,
"help": self._help
}
self._cb_map = {
**{plan: self._plan(plan) for plan in prices},
"activate": self._activate
}
self._register_handlers()
def _register_handlers(self) -> None:
self._dp.message.register(self._show, Command("start"))
self._dp.message.register(self._help, Command("help"))
self._dp.message.register(self._unknown)
for plan in self._prices:
self._dp.callback_query.register(self._plan(plan), F.data == plan)
self._dp.callback_query.register(self._activate, F.data == "activate")
self._dp.callback_query.register(self._unknown_callback)
async def run(self) -> None:
await self._bot.set_my_commands([
{"command": "start", "description": "Выбрать тариф"},
{"command": "help", "description": "Справка"}
])
await self._dp.start_polling(self._bot)
async def _show(self, msg: Message) -> None:
uid = msg.chat.id
builder = InlineKeyboardBuilder()
for plan, price in self._prices.items():
builder.button(text=f"{plan.title()} — {price}₽", callback_data=plan)
if await self._trial_ok(uid):
builder.button(text="Активировать пробный период", callback_data="activate")
builder.adjust(1)
await msg.answer("Выберите тариф:", reply_markup=builder.as_markup())
async def _help(self, msg: Message) -> None:
await msg.answer("/start — выбрать тариф\n/help — справка")
async def _unknown(self, msg: Message) -> None:
await msg.answer("Неизвестная команда. /help")
async def _unknown_callback(self, call: CallbackQuery) -> None:
await call.answer()
await call.message.answer("Неизвестная операция.")
def _plan(self, name: str):
async def _handler(call: CallbackQuery) -> None:
await call.answer()
await call.message.answer(f"Вы выбрали тариф «{name}».")
return _handler
async def _activate(self, call: CallbackQuery) -> None:
await call.answer()
uid = str(call.from_user.id)
try:
self._db[uid] = {
"started": datetime.utcnow(),
TRIAL_FLAG: True,
"questions": 0,
"symbols": 0,
}
self._db.sync()
except Exception as e:
await call.message.answer(f"⚠️ Ошибка БД: {e}")
return
await call.message.answer(
"✅ Пробный период активирован!\nДоступно: 10 вопросов / 10 000 символов"
)
try:
await call.message.edit_reply_markup(reply_markup=None)
except Exception:
pass
async def _trial_ok(self, uid: int) -> bool:
rec = self._db.get(str(uid), {})
return not rec.get(TRIAL_FLAG) or datetime.utcnow() - rec.get("started", datetime.min) >= timedelta(days=7)
async def main():
TOKEN = os.getenv("BOT_TOKEN", "вставь свой токен сюда")
PRICES = {"month": 199, "quarter": 549, "year": 1_490}
db = shelve.open(str(Path(__file__).with_name("trial.db")), writeback=True)
db.update({k: v | {TRIAL_FLAG: v.get(TRIAL_FLAG, False)} for k, v in db.items()})
bot = UltraLiteSubBot(TOKEN, PRICES, db)
await bot.run()
if __name__ == "__main__":
import asyncio
asyncio.run(main())