Skip to content

Commit

Permalink
Обновление учебника (май 2024) (#86)
Browse files Browse the repository at this point in the history
- Обновлено вступление про установку библиотек
- Обновлена секция про установку параметров бота по умолчанию
- Добавлена секция о настройке предпросмотра ссылок
- Добавлен пример с переносом подписей к медиафайлам наверх
- Исправлены опечатки (#81, #82, #83)
- Поднята версия aiogram до 3.7.0
- Обновлен mkdocs-material
  • Loading branch information
MasterGroosha authored May 31, 2024
1 parent 92302c4 commit ef4f169
Show file tree
Hide file tree
Showing 22 changed files with 359 additions and 174 deletions.
2 changes: 1 addition & 1 deletion book_src/buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Кнопки
# Кнопки

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

В этой главе мы познакомимся с такой замечательной фичей Telegram-ботов как кнопки. Прежде всего, чтобы избежать
путаницы, определимся с названиями. То, что цепляется к низу экрана вашего устройства, будем называть **обычными**
Expand Down
2 changes: 1 addition & 1 deletion book_src/filters-and-middlewares.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Фильтры и мидлвари
# Фильтры и мидлвари

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

Настало время разобраться, как устроены фильтры и мидлвари в aiogram 3.x, а также познакомиться с
«убийцей лямбда-выражений» фреймворка — _магическими фильтрами_.
Expand Down
4 changes: 2 additions & 2 deletions book_src/fsm.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Конечные автоматы (FSM)
# Конечные автоматы (FSM) {: id="fsm-start" }

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

## Теория {: id="theory" }

Expand Down Expand Up @@ -141,7 +141,7 @@ async def food_chosen(message: Message, state: FSMContext):
в хранилище FSM, и эти данные уникальны для пары `(chat_id, user_id)` (есть нюанс, о нём позже). Наконец,
в строке 11 мы переводим пользователя в состояние `OrderFood.choosing_food_size`.

А если пользователь решит ввести что-то самостоятельно, без клавиатуры? В этом случае, надо сообщить пользователю
А если пользователь решит ввести что-то самостоятельно, без клавиатуры? В этом случае надо сообщить пользователю
об ошибке и дать ему ещё попытку. Очень часто начинающие разработчки ботов на этом моменте задают вопрос:
«а как оставить юзера в том же состоянии?». Ответ простой: чтобы оставить пользователя в текущем состоянии, достаточно
его \[состояние\] не менять, т.е. буквально _ничего не делать_.
Expand Down
Binary file added book_src/images/messages/caption_above_media.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added book_src/images/messages/link_preview_options.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion book_src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ title: Введение
курсов по Python, пройдите их, а лишь затем принимайтесь за написание ботов, сэкономите себе время и нервные клетки.

Во всех главах в качестве операционной системы мы будем использовать что-нибудь семейства GNU/Linux,
например, [Ubuntu](https://ubuntu.com/), Python 3.9 (в Virtual Environment) и среду разработки
например, [Ubuntu](https://ubuntu.com/), Python 3.11 (в Virtual Environment) и среду разработки
[PyCharm](https://www.jetbrains.com/ru-ru/pycharm/download/), впрочем, не возбраняется и [Visual Studio Code](https://code.visualstudio.com/).
При этом пользователи Windows не в пролёте: всё, что касается кода, будет спокойно работать и у вас, а для специфичных вещей
вроде systemd вы можете использовать Ubuntu в [VirtualBox](https://www.virtualbox.org).
Expand Down
2 changes: 1 addition & 1 deletion book_src/inline-mode.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Инлайн-режим
# Инлайн-режим

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

## Теория {: id="theory" }

Expand Down
121 changes: 113 additions & 8 deletions book_src/messages.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Работа с сообщениями
# Работа с сообщениями

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

В этой главе мы разберёмся, как применять различные типы форматирования к сообщениям и работать с медиафайлами.

Expand Down Expand Up @@ -66,15 +66,25 @@ async def any_message(message: Message):
![Hello world с разным форматированием](images/messages/l02_1.png)

Если в боте повсеместно используется определённое форматирование, то каждый раз указывать аргумент `parse_mode` довольно
накладно. К счастью, в aiogram можно передать необходимый тип прямо в объект **Bot**, а если в каком-то конкретном случае
нужно обойтись без этих ваших разметок, то просто укажите `parse_mode=None`:

накладно. К счастью, в aiogram можно задать параметры бота по умолчанию. Для этого создайте объект `DefaultBotProperties`
и передайте туда нужные настройки:

```python
from aiogram.client.default import DefaultBotProperties

bot = Bot(
token="123:abcxyz",
default=DefaultBotProperties(
parse_mode=ParseMode.HTML
# тут ещё много других интересных настроек
)
)
bot = Bot(token="123:abcxyz", parse_mode="HTML")

# где-то в функции...
await message.answer("Сообщение с <u>HTML-разметкой</u>")
# чтобы явно отключить форматирование в конкретном запросе,
# передайте parse_mode=None
await message.answer(
"Сообщение без <s>какой-либо разметки</s>",
parse_mode=None
Expand Down Expand Up @@ -375,6 +385,87 @@ async def cmd_start_book(
[https://core.telegram.org/api/links](https://core.telegram.org/api/links)


### Предпросмотр ссылок {: id="link-previews" }

Обычно при отправке текстового сообщения со ссылками Telegram пытается найти и показать предпросмотр первой по порядку ссылки.
Это поведение можно настроить по своему желанию, передав в качестве аргумента `link_preview_options` метода `send_message()`
объект `LinkPreviewOptions`:

```python
# Новый импорт
from aiogram.types import LinkPreviewOptions

@dp.message(Command("links"))
async def cmd_links(message: Message):
links_text = (
"https://nplus1.ru/news/2024/05/23/voyager-1-science-data"
"\n"
"https://t.me/telegram"
)
# Ссылка отключена
options_1 = LinkPreviewOptions(is_disabled=True)
await message.answer(
f"Нет превью ссылок\n{links_text}",
link_preview_options=options_1
)

# -------------------- #

# Маленькое превью
# Для использования prefer_small_media обязательно указывать ещё и url
options_2 = LinkPreviewOptions(
url="https://nplus1.ru/news/2024/05/23/voyager-1-science-data",
prefer_small_media=True
)
await message.answer(
f"Маленькое превью\n{links_text}",
link_preview_options=options_2
)

# -------------------- #

# Большое превью
# Для использования prefer_large_media обязательно указывать ещё и url
options_3 = LinkPreviewOptions(
url="https://nplus1.ru/news/2024/05/23/voyager-1-science-data",
prefer_large_media=True
)
await message.answer(
f"Большое превью\n{links_text}",
link_preview_options=options_3
)

# -------------------- #

# Можно сочетать: маленькое превью и расположение над текстом
options_4 = LinkPreviewOptions(
url="https://nplus1.ru/news/2024/05/23/voyager-1-science-data",
prefer_small_media=True,
show_above_text=True
)
await message.answer(
f"Маленькое превью над текстом\n{links_text}",
link_preview_options=options_4
)

# -------------------- #

# Можно выбрать, какая ссылка будет использоваться для предпосмотра,
options_5 = LinkPreviewOptions(
url="https://t.me/telegram"
)
await message.answer(
f"Предпросмотр не первой ссылки\n{links_text}",
link_preview_options=options_5
)
```

Результат:
![Примеры предпросмотров ссылок](images/messages/link_preview_options.png)

Также некоторые параметры предпросмотра можно указать по умолчанию в `DefaultBotProperties`, о чём рассказывалось
в начале главы.

## Медиафайлы {: id="media" }

### Отправка файлов {: id="uploading-media" }
Expand Down Expand Up @@ -454,6 +545,20 @@ async def upload_photo(message: Message):
await message.answer("Отправленные файлы:\n"+"\n".join(file_ids))
```

Подпись у фото, видео и GIF можно перенести наверх:

```python
@dp.message(Command("gif"))
async def send_gif(message: Message):
await message.answer_animation(
animation="<file_id гифки>",
caption="Я сегодня:",
show_caption_above_media=True
)
```

![подпись над анимацией](images/messages/caption_above_media.jpg)

### Скачивание файлов {: id="downloading-media" }

Помимо переиспользования для отправки, бот может скачать медиа к себе на компьютер/сервер. Для этого у объекта типа `Bot`
Expand Down Expand Up @@ -602,12 +707,10 @@ async def somebody_added(message: Message):
## Бонус: прячем ссылку в тексте {: id="bonus" }

Бывают ситуации, когда хочется отправить длинное сообщение с картинкой, но лимит на подписи к медиафайлам составляет
всего 1024 символа против 4096 у обычного текстового, а вставлять внизу ссылку на медиа — выглядит некрасиво. Более того,
когда Telegram делает предпросмотр ссылок, он берёт первую из них и считывает метатеги, в результате сообщение может
отправиться не с тем превью, которое хочется увидеть.
всего 1024 символа против 4096 у обычного текстового, а вставлять внизу ссылку на медиа — выглядит некрасиво.
Для решения этой проблемы ещё много лет назад придумали подход со «скрытыми ссылками» в HTML-разметке. Суть в том, что
можно поместить ссылку в [пробел нулевой ширины](http://www.fileformat.info/info/unicode/char/200b/index.htm) и вставить
всю эту конструкцию в начало сообщения. Для наблюдателя в сообщении никаких ссылок нет, а сервер Telegram всё видит и честно
всю эту конструкцию в начало сообщения. Для наблюдателя в сообщении нет ничего лишнего, а сервер Telegram всё видит и честно
добавляет предпросмотр.
Разработчики aiogram для этого даже сделали специальный вспомогательный метод `hide_link()`:
```python
Expand All @@ -626,5 +729,7 @@ async def cmd_hidden_link(message: Message):

![Изображение со скрытой ссылкой](images/messages/hidden_link.png)

А при помощи LinkPreviewOptions (см. выше) можно сделать медиафайл сверху с длинной подписью в 4096 символов ниже.

На этом всё. До следующих глав!
<s><small>Ставьте лайки, подписывайтесь, прожимайте колокольчик</small></s>
16 changes: 8 additions & 8 deletions book_src/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Знакомство с aiogram
# Знакомство с aiogram

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

!!! warning "Некоторые детали сознательно упрощены!"
Автор этой книги убеждён, что помимо теории должна быть и практика. Чтобы максимально упростить повторение
Expand Down Expand Up @@ -60,16 +60,16 @@ Type "help", "copyright", "credits" or "license" for more information.
```

Теперь создадим файл `requirements.txt`, в котором укажем используемую нами версию aiogram. Также нам понадобится
библиотека python-dotenv для файлов конфигурации.
библиотека pydantic-settings для файлов конфигурации.
!!! important "О версиях aiogram"
В этой главе используется aiogram **3.x**, перед началом работы рекомендую заглянуть в
[канал релизов](https://t.me/aiogram_live) библиотеки и проверить наличие более новой версии. Подойдёт любая
более новая, начинающаяся с цифры 3, поскольку aiogram 2.x более рассматриваться не будет и считается устаревшим.

```plain
[groosha@main 01_quickstart]$ python3.9 -m venv venv
[groosha@main 01_quickstart]$ python3.11 -m venv venv
[groosha@main 01_quickstart]$ echo "aiogram<4.0" > requirements.txt
[groosha@main 01_quickstart]$ echo "python-dotenv==1.0.0" >> requirements.txt
[groosha@main 01_quickstart]$ echo "pydantic-settings" >> requirements.txt
[groosha@main 01_quickstart]$ source venv/bin/activate
(venv) [groosha@main 01_quickstart]$ pip install -r requirements.txt
# ...здесь куча строк про установку...
Expand All @@ -78,10 +78,10 @@ Successfully installed ...тут длинный список...
```

Обратите внимание на префикс "venv" в терминале. Он указывает, что мы находимся в виртуальном окружении с именем "venv".
Проверим, что внутри venv вызов команды `python` указывает на всё тот же Python 3.9:
Проверим, что внутри venv вызов команды `python` указывает на всё тот же Python 3.11:
```plain
(venv) [groosha@main 01_quickstart]$ python
Python 3.9.9 (main, Jan 11 2022, 16:35:07)
Python 3.11.9 (main, Jan 11 2024, 16:35:07)
[GCC 11.1.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> exit()
Expand Down Expand Up @@ -205,12 +205,12 @@ async def cmd_dice(message: types.Message):
поэтому встроенная проверка типов, как, например, в C++ или Java, отсутствует. Однако начиная с версии 3.5
в языке появилась поддержка [подсказок типов](https://docs.python.org/3/library/typing.html), благодаря которой
различные чекеры и IDE вроде PyCharm анализируют типы используемых значений и подсказывают
программисту, если он передаёт что-то не то. В данном случае подсказка `types.Message` соообщает
программисту, если он передаёт что-то не то. В данном случае подсказка `types.Message` сообщает
PyCharm-у, что переменная `message` имеет тип `Message`, описанный в модуле `types` библиотеки
aiogram (см. импорты в начале кода). Благодаря этому IDE может на лету подсказывать атрибуты и функции.

При вызове команды `/dice` бот отправит в тот же чат игральный кубик. Разумеется, если его надо отправить в какой-то
другой чат, то придётся по-старинке вызывать `await bot.send_dice(...)`. Но объект `bot` (экземпляр класса Bot) может быть
другой чат, то придётся по старинке вызывать `await bot.send_dice(...)`. Но объект `bot` (экземпляр класса Bot) может быть
недоступен в области видимости конкретной функции. В aiogram 3.x объект бота, которому пришёл апдейт, неявно
прокидывается в хэндлер и его можно достать как аргумент `bot`. Предположим, вы хотите по команде `/dice`
отправлять кубик не в тот же чат, а в канал с ID -100123456789. Перепишем предыдущую функцию:
Expand Down
2 changes: 1 addition & 1 deletion book_src/routers.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: Роутеры, многофайловость и структур
# Роутеры, многофайловость и структура бота

!!! info ""
Используемая версия aiogram: 3.1.1
Используемая версия aiogram: 3.7.0

В этой главе мы познакомимся с новой фичей aiogram 3.x — роутерами, научимся разбивать наш код на отдельные
компоненты, а также сформируем базовую структуру бота, которая пригодится в следующих главах и вообще по жизни.
Expand Down
Loading

0 comments on commit ef4f169

Please sign in to comment.