mirror of
https://github.com/aiogram/aiogram.git
synced 2026-04-08 16:37:47 +00:00
Merge branch 'aiogram:dev-3.x' into docs
This commit is contained in:
commit
61c5bf8a2c
8 changed files with 89 additions and 56 deletions
1
CHANGES/5780.doc.rst
Normal file
1
CHANGES/5780.doc.rst
Normal file
|
|
@ -0,0 +1 @@
|
|||
Refactored examples code to use aiogram enumerations and enhanced chat messages with markdown beautifications for a more user-friendly display.
|
||||
|
|
@ -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, <b>{message.from_user.full_name}!</b>")
|
||||
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!")
|
||||
|
|
|
|||
|
|
@ -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, <b>{message.from_user.full_name}!</b>")
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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, <b>{message.from_user.full_name}!</b>")
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -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!")
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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, <b>{message.from_user.full_name}!</b>",
|
||||
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!")
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue