Skip to content

Aiogram

Is a pretty simple and fully asynchronous framework for Telegram Bot API written in Python 3.7 with asyncio and aiohttp.

Categories

Simple example

"""
This is a echo bot.
It echoes any incoming text messages.
"""

import logging

from aiogram import Bot, Dispatcher, executor, types

API_TOKEN = 'BOT TOKEN HERE'

# Configure logging
logging.basicConfig(level=logging.INFO)

# Initialize bot and dispatcher
bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)


@dp.message_handler(commands=['start', 'help'])
async def send_welcome(message: types.Message):
    """
    This handler will be called when user sends `/start` or `/help` command
    """
    await message.reply("Hi!\nI'm EchoBot!\nPowered by aiogram.")


@dp.message_handler()
async def echo(message: types.Message):
    # old style:
    # await bot.send_message(message.chat.id, message.text)
    await message.answer(message.text)


if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)

Photo 다운로드

def get_max_size_photo(photo: List[PhotoSize]) -> PhotoSize:
    if not photo:
        raise IndexError("Empty photo")
    max_file_size = max(map(lambda x: x.file_size, photo))
    return list(filter(lambda x: x.file_size == max_file_size, photo))[0]

@dp.message_handler(content_types=["photo"])
async def on_photo(self, message: Message):
    photo = get_max_size_photo(message.photo)
    buffer = BytesIO()
    await photo.download(destination_file=buffer)
    data = buffer.getbuffer()

file_id 로 다운받기

file = await bot.get_file(file_id)
file_path = file.file_path

Example:

file_info = await bot.get_file(photo[len(photo) - 1].file_id)
new_photo = (await bot.download_file(file_info.file_path)).read()

파일 업로드

By first step you will need to import InputFile wrapper:

from aiogram.types import FSInputFile

...

cat = FSInputFile("cat.png")
agenda = FSInputFile("my-document.pdf", filename="agenda-2019-11-19.pdf")

Upload from buffer

Files can be also passed from buffer (For example you generate image using Pillow and you want to send it to Telegram):

Import wrapper:

from aiogram.types import BufferedInputFile

...

text_file = BufferedInputFile(b"Hello, world!", filename="file.txt")

Magic filters

Exists or not None:

F.photo  # lambda message: message.photo

Equals:

F.text == 'hello'  # lambda message: message.text == 'hello'
F.from_user.id == 42  # lambda message: message.from_user.id == 42
F.text != 'spam'  # lambda message: message.text != 'spam'

Is one of:

F.from_user.id.in_({42, 1000, 123123})  # lambda query: query.from_user.id in {42, 1000, 123123}
F.data.in_({'foo', 'bar', 'baz'})  # lambda query: query.data in {'foo', 'bar', 'baz'}

Contains:

F.text.contains('foo')  # lambda message: 'foo' in message.text

String startswith/endswith:

F.text.startswith('foo')  # lambda message: message.text.startswith('foo')
F.text.endswith('bar')  # lambda message: message.text.startswith('bar')

Regexp:

F.text.regexp(r'Hello, .+')  # lambda message: re.match(r'Hello, .+', message.text)

Custom function:

F.chat.func(lambda chat: chat.id == -42)  # lambda message: (lambda chat: chat.id == -42)(message.chat)

Inverting result:

~F.text  # lambda message: not message.text
~F.text.startswith('spam')  # lambda message: not message.text.startswith('spam')

Combining:

(F.from_user.id == 42) & (F.text == 'admin')
F.text.startswith('a') | F.text.endswith('b')
(F.from_user.id.in_({42, 777, 911})) & (F.text.startswith('!') | F.text.startswith('/')) & F.text.contains('ban')

Usage in aiogram:

@router.message(F.text == 'hello')
@router.inline_query(F.data == 'button:1')
@router.message(F.text.startswith('foo'))
@router.message(F.content_type.in_({'text', 'sticker'}))
@router.message(F.text.regexp(r'\d+'))

Custom filter example

For example if you need to make simple text filter:

from aiogram import Router
from aiogram.filters import Filter
from aiogram.types import Message

router = Router()


class MyFilter(Filter):
    def __init__(self, my_text: str) -> None:
        self.my_text = my_text

    async def __call__(self, message: Message) -> bool:
        return message.text == self.my_text


@router.message(MyFilter("hello"))
async def my_handler(message: Message):
    ...

Combining Filters

and_f(F.text.startswith("show"), F.text.endswith("example"))
or_f(F.text(text="hi"), CommandStart())
invert_f(IsAdmin())
and_f(<A>, or_f(<B>, <C>))

Middleware example

from aiogram import BaseMiddleware
from aiogram.types import Message


class CounterMiddleware(BaseMiddleware):
    def __init__(self) -> None:
        self.counter = 0

    async def __call__(
        self,
        handler: Callable[[Message, Dict[str, Any]], Awaitable[Any]],
        event: Message,
        data: Dict[str, Any]
    ) -> Any:
        self.counter += 1
        data['counter'] = self.counter
        return await handler(event, data)

and then

router = Router()
router.message.middleware(CounterMiddleware())

유한 상태 머신

질문을 주고 받는 상태를 기록할 수 있다.

See also

Favorite site