Add bot commands setup, inline keyboards, and project dependencies

This commit is contained in:
2026-07-02 19:15:49 +03:00
parent c4dfe92004
commit 0b5f4ec2d3
14 changed files with 706 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
# Frankenstein Bot package
+20
View File
@@ -0,0 +1,20 @@
from pydantic import SecretStr
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""
Application settings loaded from environment variables or a .env file.
"""
bot_token: SecretStr
# Tell Pydantic to read from a .env file if it exists, ignoring extra fields
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
# Instantiate the settings so they can be imported elsewhere
settings = Settings()
+12
View File
@@ -0,0 +1,12 @@
from aiogram import Router
from . import user, admin
def get_handlers_router() -> Router:
"""
Combines all feature routers (user, admin, etc.) into one main router.
"""
router = Router()
router.include_router(user.router)
router.include_router(admin.router)
return router
+14
View File
@@ -0,0 +1,14 @@
from aiogram import Router
from aiogram.filters import Command
from aiogram.types import Message
router = Router()
@router.message(Command("admin"))
async def cmd_admin(message: Message):
"""
Handles /admin command (placeholder).
In production, you'd restrict this using a custom filter or admin ID list.
"""
await message.answer("Welcome to the Admin panel. Currently, no admin tasks are configured.")
+56
View File
@@ -0,0 +1,56 @@
from aiogram import F, Router
from aiogram.filters import Command, CommandStart
from aiogram.types import CallbackQuery, Message
from bot.keyboards.inline import get_links_keyboard
from bot.keyboards.reply import get_main_menu_keyboard
router = Router()
@router.message(CommandStart())
async def cmd_start(message: Message):
"""
Handles /start command. Greets user and sends the main reply menu.
"""
await message.answer(
f"Hello, {message.from_user.full_name}! Welcome to Frankenstein Bot.\n"
f"This bot is bootstrapped with a modular and clean structure.",
reply_markup=get_main_menu_keyboard(),
)
@router.message(Command("help"))
@router.message(F.text == "Help ❓")
async def cmd_help(message: Message):
"""
Handles /help command or 'Help ❓' reply keyboard button click.
"""
await message.answer(
"Here is what I can do:\n"
"/start - Start the bot\n"
"/help - Get help information\n"
"/about - Learn more about the bot",
reply_markup=get_links_keyboard(),
)
@router.message(Command("about"))
@router.message(F.text == "About ")
async def cmd_about(message: Message):
"""
Handles /about command or 'About ' reply keyboard button click.
"""
await message.answer(
"Frankenstein Bot is a high-performance Python Telegram bot built on aiogram v3, "
"designed to work seamlessly with systemd process management."
)
@router.callback_query(F.data == "support_contact")
async def process_support_callback(callback: CallbackQuery):
"""
Processes the inline keyboard callback query 'support_contact'.
"""
await callback.message.answer("Support: Open an issue or contact our administrator.")
await callback.answer()
+1
View File
@@ -0,0 +1 @@
# Keyboards package
+13
View File
@@ -0,0 +1,13 @@
from aiogram.types import InlineKeyboardButton, InlineKeyboardMarkup
from aiogram.utils.keyboard import InlineKeyboardBuilder
def get_links_keyboard() -> InlineKeyboardMarkup:
"""
Creates an inline keyboard markup with external links and callback query button.
"""
builder = InlineKeyboardBuilder()
builder.add(InlineKeyboardButton(text="Google", url="https://google.com"))
builder.add(InlineKeyboardButton(text="Contact Support 💬", callback_data="support_contact"))
builder.adjust(1)
return builder.as_markup()
+13
View File
@@ -0,0 +1,13 @@
from aiogram.types import KeyboardButton, ReplyKeyboardMarkup
from aiogram.utils.keyboard import ReplyKeyboardBuilder
def get_main_menu_keyboard() -> ReplyKeyboardMarkup:
"""
Creates the main menu reply keyboard markup.
"""
builder = ReplyKeyboardBuilder()
builder.add(KeyboardButton(text="Help ❓"))
builder.add(KeyboardButton(text="About "))
builder.adjust(2)
return builder.as_markup(resize_keyboard=True)
+26
View File
@@ -0,0 +1,26 @@
import logging
from typing import Any, Awaitable, Callable, Dict
from aiogram import BaseMiddleware
from aiogram.types import TelegramObject
logger = logging.getLogger(__name__)
class LoggingMiddleware(BaseMiddleware):
"""
A simple middleware that logs details about incoming events.
"""
async def __call__(
self,
handler: Callable[[TelegramObject, Dict[str, Any]], Awaitable[Any]],
event: TelegramObject,
data: Dict[str, Any],
) -> Any:
logger.debug("Received event: %s", event.__class__.__name__)
try:
result = await handler(event, data)
logger.debug("Event %s handled successfully", event.__class__.__name__)
return result
except Exception as e:
logger.error("Error handling event %s: %s", event.__class__.__name__, e, exc_info=True)
raise e
+15
View File
@@ -0,0 +1,15 @@
from aiogram import Bot
from aiogram.types import BotCommand, BotCommandScopeDefault
async def set_bot_commands(bot: Bot):
"""
Sets default commands in the Telegram client's command menu.
"""
commands = [
BotCommand(command="start", description="Start Frankenstein Bot"),
BotCommand(command="help", description="Show help information"),
BotCommand(command="about", description="About the bot"),
BotCommand(command="admin", description="Admin panel placeholder"),
]
await bot.set_my_commands(commands, scope=BotCommandScopeDefault())