diff --git a/CHANGES/5780.doc.rst b/CHANGES/5780.doc.rst
new file mode 100644
index 00000000..2b8af247
--- /dev/null
+++ b/CHANGES/5780.doc.rst
@@ -0,0 +1 @@
+Refactored examples code to use aiogram enumerations and enhanced chat messages with markdown beautifications for a more user-friendly display.
diff --git a/examples/echo_bot.py b/examples/echo_bot.py
index 8ac45e43..fc0bb0ff 100644
--- a/examples/echo_bot.py
+++ b/examples/echo_bot.py
@@ -1,19 +1,22 @@
import asyncio
import logging
+import sys
+from os import getenv
from aiogram import Bot, Dispatcher, Router, types
from aiogram.enums import ParseMode
-from aiogram.filters import Command
+from aiogram.filters import CommandStart
from aiogram.types import Message
+from aiogram.utils.markdown import hbold
# Bot token can be obtained via https://t.me/BotFather
-TOKEN = "42:TOKEN"
+TOKEN = getenv("BOT_TOKEN")
# All handlers should be attached to the Router (or Dispatcher)
router = Router()
-@router.message(Command("start"))
+@router.message(CommandStart())
async def command_start_handler(message: Message) -> None:
"""
This handler receives messages with `/start` command
@@ -23,7 +26,7 @@ async def command_start_handler(message: Message) -> None:
# and the target chat will be passed to :ref:`aiogram.methods.send_message.SendMessage`
# method automatically or call API method directly via
# Bot instance: `bot.send_message(chat_id=message.chat.id, ...)`
- await message.answer(f"Hello, {message.from_user.full_name}!")
+ await message.answer(f"Hello, {hbold(message.from_user.full_name)}!")
@router.message()
@@ -54,5 +57,8 @@ async def main() -> None:
if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
- asyncio.run(main())
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
+ try:
+ asyncio.run(main())
+ except (KeyboardInterrupt, SystemExit):
+ logging.info("Bot stopped!")
diff --git a/examples/echo_bot_webhook.py b/examples/echo_bot_webhook.py
index d8ed41c5..1fa56c3d 100644
--- a/examples/echo_bot_webhook.py
+++ b/examples/echo_bot_webhook.py
@@ -2,17 +2,20 @@
This example shows how to use webhook on behind of any reverse proxy (nginx, traefik, ingress etc.)
"""
import logging
+import sys
+from os import getenv
from aiohttp import web
from aiogram import Bot, Dispatcher, Router, types
from aiogram.enums import ParseMode
-from aiogram.filters import Command
+from aiogram.filters import CommandStart
from aiogram.types import Message
+from aiogram.utils.markdown import hbold
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
# Bot token can be obtained via https://t.me/BotFather
-TOKEN = "42:TOKEN"
+TOKEN = getenv("BOT_TOKEN")
# Webserver settings
# bind localhost only to prevent any external access
@@ -32,7 +35,7 @@ BASE_WEBHOOK_URL = "https://aiogram.dev/"
router = Router()
-@router.message(Command(commands=["start"]))
+@router.message(CommandStart())
async def command_start_handler(message: Message) -> None:
"""
This handler receives messages with `/start` command
@@ -42,7 +45,7 @@ async def command_start_handler(message: Message) -> None:
# and the target chat will be passed to :ref:`aiogram.methods.send_message.SendMessage`
# method automatically or call API method directly via
# Bot instance: `bot.send_message(chat_id=message.chat.id, ...)`
- await message.answer(f"Hello, {message.from_user.full_name}!")
+ await message.answer(f"Hello, {hbold(message.from_user.full_name)}!")
@router.message()
@@ -63,7 +66,7 @@ async def echo_handler(message: types.Message) -> None:
async def on_startup(bot: Bot) -> None:
# If you have a self-signed SSL certificate, then you will need to send a public
# certificate to Telegram
- await bot.set_webhook(f"{BASE_WEBHOOK_URL}{WEBHOOK_PATH}")
+ await bot.set_webhook(f"{BASE_WEBHOOK_URL}{WEBHOOK_PATH}", secret_token=WEBHOOK_SECRET)
def main() -> None:
@@ -100,5 +103,5 @@ def main() -> None:
if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
main()
diff --git a/examples/echo_bot_webhook_ssl.py b/examples/echo_bot_webhook_ssl.py
index 463717f0..ad41bc4d 100644
--- a/examples/echo_bot_webhook_ssl.py
+++ b/examples/echo_bot_webhook_ssl.py
@@ -3,17 +3,20 @@ This example shows how to use webhook with SSL certificate.
"""
import logging
import ssl
+import sys
+from os import getenv
from aiohttp import web
from aiogram import Bot, Dispatcher, Router, types
from aiogram.enums import ParseMode
-from aiogram.filters import Command
+from aiogram.filters import CommandStart
from aiogram.types import FSInputFile, Message
+from aiogram.utils.markdown import hbold
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
# Bot token can be obtained via https://t.me/BotFather
-TOKEN = "42:TOKEN"
+TOKEN = getenv("BOT_TOKEN")
# Webserver settings
# bind localhost only to prevent any external access
@@ -37,7 +40,7 @@ WEBHOOK_SSL_PRIV = "/path/to/private.key"
router = Router()
-@router.message(Command("start"))
+@router.message(CommandStart())
async def command_start_handler(message: Message) -> None:
"""
This handler receives messages with `/start` command
@@ -47,7 +50,7 @@ async def command_start_handler(message: Message) -> None:
# and the target chat will be passed to :ref:`aiogram.methods.send_message.SendMessage`
# method automatically or call API method directly via
# Bot instance: `bot.send_message(chat_id=message.chat.id, ...)`
- await message.answer(f"Hello, {message.from_user.full_name}!")
+ await message.answer(f"Hello, {hbold(message.from_user.full_name)}!")
@router.message()
@@ -73,6 +76,7 @@ async def on_startup(bot: Bot) -> None:
await bot.set_webhook(
f"{BASE_WEBHOOK_URL}{WEBHOOK_PATH}",
certificate=FSInputFile(WEBHOOK_SSL_CERT),
+ secret_token=WEBHOOK_SECRET,
)
@@ -114,5 +118,5 @@ def main() -> None:
if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
main()
diff --git a/examples/finite_state_machine.py b/examples/finite_state_machine.py
index 8539015c..260fdfdf 100644
--- a/examples/finite_state_machine.py
+++ b/examples/finite_state_machine.py
@@ -5,7 +5,8 @@ from os import getenv
from typing import Any, Dict
from aiogram import Bot, Dispatcher, F, Router, html
-from aiogram.filters import Command
+from aiogram.enums import ParseMode
+from aiogram.filters import Command, CommandStart
from aiogram.fsm.context import FSMContext
from aiogram.fsm.state import State, StatesGroup
from aiogram.types import (
@@ -15,6 +16,8 @@ from aiogram.types import (
ReplyKeyboardRemove,
)
+TOKEN = getenv("BOT_TOKEN")
+
form_router = Router()
@@ -24,7 +27,7 @@ class Form(StatesGroup):
language = State()
-@form_router.message(Command("start"))
+@form_router.message(CommandStart())
async def command_start(message: Message, state: FSMContext) -> None:
await state.set_state(Form.name)
await message.answer(
@@ -91,7 +94,7 @@ async def process_like_write_bots(message: Message, state: FSMContext) -> None:
@form_router.message(Form.like_bots)
-async def process_unknown_write_bots(message: Message, state: FSMContext) -> None:
+async def process_unknown_write_bots(message: Message) -> None:
await message.reply("I don't understand you :(")
@@ -99,12 +102,12 @@ async def process_unknown_write_bots(message: Message, state: FSMContext) -> Non
async def process_language(message: Message, state: FSMContext) -> None:
data = await state.update_data(language=message.text)
await state.clear()
- text = (
- "Thank for all! Python is in my hearth!\nSee you soon."
- if message.text.casefold() == "python"
- else "Thank for information!\nSee you soon."
- )
- await message.answer(text)
+
+ if message.text.casefold() == "python":
+ await message.reply(
+ "Python, you say? That's the language that makes my circuits light up! 😉"
+ )
+
await show_summary(message=message, data=data)
@@ -121,7 +124,7 @@ async def show_summary(message: Message, data: Dict[str, Any], positive: bool =
async def main():
- bot = Bot(token=getenv("TELEGRAM_TOKEN"), parse_mode="HTML")
+ bot = Bot(token=TOKEN, parse_mode=ParseMode.HTML)
dp = Dispatcher()
dp.include_router(form_router)
@@ -130,4 +133,7 @@ async def main():
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
- asyncio.run(main())
+ try:
+ asyncio.run(main())
+ except (KeyboardInterrupt, SystemExit):
+ logging.info("Bot stopped!")
diff --git a/examples/multibot.py b/examples/multibot.py
index 57e75f8e..82fac4a1 100644
--- a/examples/multibot.py
+++ b/examples/multibot.py
@@ -1,14 +1,16 @@
+import logging
+import sys
from os import getenv
from typing import Any, Dict, Union
from aiohttp import web
-from finite_state_machine import form_router
from aiogram import Bot, Dispatcher, F, Router
from aiogram.client.session.aiohttp import AiohttpSession
+from aiogram.enums import ParseMode
from aiogram.exceptions import TelegramUnauthorizedError
from aiogram.filters import Command, CommandObject
-from aiogram.fsm.storage.redis import DefaultKeyBuilder, RedisStorage
+from aiogram.fsm.storage.memory import MemoryStorage
from aiogram.types import Message
from aiogram.utils.token import TokenValidationError, validate_token
from aiogram.webhook.aiohttp_server import (
@@ -16,11 +18,12 @@ from aiogram.webhook.aiohttp_server import (
TokenBasedRequestHandler,
setup_application,
)
+from finite_state_machine import form_router
main_router = Router()
BASE_URL = getenv("BASE_URL", "https://example.com")
-MAIN_BOT_TOKEN = getenv("TELEGRAM_TOKEN")
+MAIN_BOT_TOKEN = getenv("BOT_TOKEN")
WEB_SERVER_HOST = "127.0.0.1"
WEB_SERVER_PORT = 8080
@@ -56,10 +59,13 @@ async def on_startup(dispatcher: Dispatcher, bot: Bot):
def main():
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
session = AiohttpSession()
- bot_settings = {"session": session, "parse_mode": "HTML"}
+ bot_settings = {"session": session, "parse_mode": ParseMode.HTML}
bot = Bot(token=MAIN_BOT_TOKEN, **bot_settings)
- storage = RedisStorage.from_url(REDIS_DSN, key_builder=DefaultKeyBuilder(with_bot_id=True))
+ storage = MemoryStorage()
+ # In order to use RedisStorage you need to use Key Builder with bot ID:
+ # storage = RedisStorage.from_url(REDIS_DSN, key_builder=DefaultKeyBuilder(with_bot_id=True))
main_dispatcher = Dispatcher(storage=storage)
main_dispatcher.include_router(main_router)
diff --git a/examples/specify_updates.py b/examples/specify_updates.py
index b5d22afc..b3c26786 100644
--- a/examples/specify_updates.py
+++ b/examples/specify_updates.py
@@ -1,8 +1,11 @@
import asyncio
import logging
+import sys
+from os import getenv
from aiogram import Bot, Dispatcher, Router
-from aiogram.filters import Command
+from aiogram.enums import ParseMode
+from aiogram.filters import LEAVE_TRANSITION, ChatMemberUpdatedFilter, CommandStart
from aiogram.types import (
CallbackQuery,
ChatMemberUpdated,
@@ -10,8 +13,9 @@ from aiogram.types import (
InlineKeyboardMarkup,
Message,
)
+from aiogram.utils.markdown import hbold, hcode
-TOKEN = "6wo"
+TOKEN = getenv("BOT_TOKEN")
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
@@ -19,14 +23,14 @@ logging.basicConfig(level=logging.INFO)
router = Router()
-@router.message(Command("start"))
+@router.message(CommandStart())
async def command_start_handler(message: Message) -> None:
"""
This handler receives messages with `/start` command
"""
await message.answer(
- f"Hello, {message.from_user.full_name}!",
+ f"Hello, {hbold(message.from_user.full_name)}!",
reply_markup=InlineKeyboardMarkup(
inline_keyboard=[[InlineKeyboardButton(text="Tap me, bro", callback_data="*")]]
),
@@ -37,7 +41,7 @@ async def command_start_handler(message: Message) -> None:
async def chat_member_update(chat_member: ChatMemberUpdated, bot: Bot) -> None:
await bot.send_message(
chat_member.chat.id,
- "Member {chat_member.from_user.id} was changed "
+ f"Member {hcode(chat_member.from_user.id)} was changed "
+ f"from {chat_member.old_chat_member.status} to {chat_member.new_chat_member.status}",
)
@@ -48,7 +52,7 @@ sub_router = Router()
@sub_router.callback_query()
async def callback_tap_me(callback_query: CallbackQuery) -> None:
- await callback_query.answer("Yeah good, now i'm fine")
+ await callback_query.answer("Yeah good, now I'm fine")
# this router will use only edited_message updates
@@ -57,38 +61,39 @@ sub_sub_router = Router()
@sub_sub_router.edited_message()
async def edited_message_handler(edited_message: Message) -> None:
- await edited_message.reply("Message was edited, big brother watch you")
+ await edited_message.reply("Message was edited, Big Brother watches you")
# this router will use only my_chat_member updates
deep_dark_router = Router()
-@deep_dark_router.my_chat_member()
+@deep_dark_router.my_chat_member(~ChatMemberUpdatedFilter(~LEAVE_TRANSITION))
async def my_chat_member_change(chat_member: ChatMemberUpdated, bot: Bot) -> None:
await bot.send_message(
chat_member.chat.id,
- "Member was changed from "
- + f"{chat_member.old_chat_member.status} to {chat_member.new_chat_member.status}",
+ "This Bot`s status was changed from "
+ + f"{hbold(chat_member.old_chat_member.status)} to {hbold(chat_member.new_chat_member.status)}",
)
async def main() -> None:
# Initialize Bot instance with a default parse mode which will be passed to all API calls
- bot = Bot(TOKEN, parse_mode="HTML")
+ bot = Bot(TOKEN, parse_mode=ParseMode.HTML)
dp = Dispatcher()
- dp.include_router(router)
+
sub_router.include_router(deep_dark_router)
- router.include_router(sub_router)
- router.include_router(sub_sub_router)
+ router.include_routers(sub_router, sub_sub_router)
+ dp.include_router(router)
- useful_updates = dp.resolve_used_update_types()
-
- # And the run events dispatching
- await dp.start_polling(bot, allowed_updates=useful_updates)
+ # Start event dispatching
+ await dp.start_polling(bot)
if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
- asyncio.run(main())
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
+ try:
+ asyncio.run(main())
+ except (KeyboardInterrupt, SystemExit):
+ logger.info("Bot stopped!")
diff --git a/examples/web_app/main.py b/examples/web_app/main.py
index 0d58042c..db148153 100644
--- a/examples/web_app/main.py
+++ b/examples/web_app/main.py
@@ -1,4 +1,5 @@
import logging
+import sys
from os import getenv
from aiohttp.web import run_app
@@ -10,7 +11,8 @@ from aiogram import Bot, Dispatcher
from aiogram.types import MenuButtonWebApp, WebAppInfo
from aiogram.webhook.aiohttp_server import SimpleRequestHandler, setup_application
-TELEGRAM_TOKEN = getenv("TELEGRAM_TOKEN")
+TOKEN = getenv("BOT_TOKEN")
+
APP_BASE_URL = getenv("APP_BASE_URL")
@@ -22,7 +24,7 @@ async def on_startup(bot: Bot, base_url: str):
def main():
- bot = Bot(token=TELEGRAM_TOKEN, parse_mode="HTML")
+ bot = Bot(token=TOKEN, parse_mode="HTML")
dispatcher = Dispatcher()
dispatcher["base_url"] = APP_BASE_URL
dispatcher.startup.register(on_startup)
@@ -45,5 +47,5 @@ def main():
if __name__ == "__main__":
- logging.basicConfig(level=logging.INFO)
+ logging.basicConfig(level=logging.INFO, stream=sys.stdout)
main()