commands, deeplinks, link_preview
This commit is contained in:
parent
5f587980e1
commit
046c47cd68
132
README.md
132
README.md
@ -251,3 +251,135 @@ async def extract_data(message: Message):
|
|||||||
f"Пароль: {html.quote(data['code'])}"
|
f"Пароль: {html.quote(data['code'])}"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Команды и их аргументы
|
||||||
|
|
||||||
|
В составе aiogram есть фильтр Command(), упрощающий жизнь разработчика.
|
||||||
|
|
||||||
|
Реализуем последний пример в коде:
|
||||||
|
|
||||||
|
```py
|
||||||
|
@dp.message(Command("settimer", prefix="/!")) # добавим дополнительные префиксы для оперделения команды
|
||||||
|
async def cmd_settimer(
|
||||||
|
message: Message,
|
||||||
|
command: CommandObject
|
||||||
|
):
|
||||||
|
# Если не переданы никакие аргументы, то
|
||||||
|
# command.args будет None
|
||||||
|
if command.args is None:
|
||||||
|
await message.answer(
|
||||||
|
"Ошибка: не переданы аргументы"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
# Пробуем разделить аргументы на две части по первому встречному пробелу
|
||||||
|
try:
|
||||||
|
delay_time, text_to_send = command.args.split(" ", maxsplit=1)
|
||||||
|
# Если получилось меньше двух частей, вылетит ValueError
|
||||||
|
except ValueError:
|
||||||
|
await message.answer(
|
||||||
|
"Ошибка: неправильный формат команды. Пример:\n"
|
||||||
|
"/settimer <time> <message>"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
await message.answer(
|
||||||
|
"Таймер добавлен!\n"
|
||||||
|
f"Время: {delay_time}\n"
|
||||||
|
f"Текст: {text_to_send}"
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Проблема кастомных префиксов в группах только в том, что боты не-админы со включенным Privacy Mode (по умолчанию) могут не увидеть такие команды из-за особенностей логики сервера.
|
||||||
|
Самый частый use-case — боты-модераторы групп, которые уже являются администраторами.
|
||||||
|
|
||||||
|
|
||||||
|
#### Диплинки
|
||||||
|
Существует одна команда в **Telegram**, у которой есть чуть больше возможностей. Это **/start**. Дело в том, что можно сформировать ссылку вида t.me/bot?start=xxx и пре переходе по такой ссылке пользователю покажут кнопку «Начать», при нажатии которой бот получит сообщение **/start xxx**.
|
||||||
|
|
||||||
|
Учтите, что диплинки через start отправляют пользователя в личку с ботом. Чтобы выбрать группу и отправить диплинк туда, замените start на startgroup. Также у aiogram существует удобная функция для создания диплинков прямо из вашего кода.
|
||||||
|
|
||||||
|
Первый дииплинк https://t.me/your_bot?start=help выведет сообщение, соответсвующее команде /help
|
||||||
|
|
||||||
|
Второй диплиинк https://t.me/your_bot?start=book_2 выведет соответствующее
|
||||||
|
сообщение, полученное из регулярного выражения
|
||||||
|
|
||||||
|
```
|
||||||
|
Sending book №2
|
||||||
|
```
|
||||||
|
|
||||||
|
*Больше диплинков, но не для ботов:*
|
||||||
|
|
||||||
|
В документации **Telegram** есть подробное описание всевозможных диплинков для клиентских приложений: https://core.telegram.org/api/links
|
||||||
|
|
||||||
|
#### Предпросмотр ссылок
|
||||||
|
Обычно при отправке текстового сообщения со ссылками **Telegram** пытается найти и показать предпросмотр первой по порядку ссылки. Это поведение можно настроить по своему желанию, передав в качестве аргумента **link_preview_options** метода **send_message()** объект L**inkPreviewOptions**
|
||||||
|
|
||||||
|
```py
|
||||||
|
# Новый импорт
|
||||||
|
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
|
||||||
|
)
|
||||||
|
```
|
||||||
|
Также некоторые параметры предпросмотра можно указать по умолчанию в DefaultBotProperties
|
||||||
|
|
||||||
|
42
bot.py
42
bot.py
@ -5,13 +5,15 @@ from datetime import datetime
|
|||||||
|
|
||||||
|
|
||||||
from aiogram import Bot, Dispatcher, types
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.client.default import DefaultBotProperties
|
||||||
|
from aiogram.enums import ParseMode
|
||||||
from aiogram.enums.dice_emoji import DiceEmoji
|
from aiogram.enums.dice_emoji import DiceEmoji
|
||||||
from aiogram import F, html
|
from aiogram import F, html
|
||||||
from aiogram.types import Message
|
from aiogram.types import Message
|
||||||
from aiogram.filters import Command
|
from aiogram.filters import Command, CommandObject
|
||||||
from aiogram.utils.formatting import Text, Bold, as_list, as_marked_section, as_key_value, HashTag
|
from aiogram.utils.formatting import Text, Bold, as_list, as_marked_section, as_key_value, HashTag
|
||||||
from aiogram.enums import ParseMode
|
|
||||||
from aiogram.client.default import DefaultBotProperties
|
|
||||||
from config_reader import config
|
from config_reader import config
|
||||||
|
|
||||||
# Включаем логирование, чтобы не пропустить важные сообщения
|
# Включаем логирование, чтобы не пропустить важные сообщения
|
||||||
@ -84,9 +86,9 @@ async def cmd_more(message: types.Message):
|
|||||||
"адрес сайта,",
|
"адрес сайта,",
|
||||||
"e-mail,",
|
"e-mail,",
|
||||||
"Номер телефона,",
|
"Номер телефона,",
|
||||||
"Какой нибудь код или пароль",
|
"Я распознаю их и напишу что нашел",
|
||||||
"Я распознаю из и напишу что нашел",
|
|
||||||
"/dice - Подкину для тебя кубик, загадай число ;)",
|
"/dice - Подкину для тебя кубик, загадай число ;)",
|
||||||
|
"/settime <time> <message> - через установленное время сообще Message ;)",
|
||||||
marker="✅ ",
|
marker="✅ ",
|
||||||
),
|
),
|
||||||
HashTag("#еще"),
|
HashTag("#еще"),
|
||||||
@ -185,7 +187,7 @@ async def echo_with_time(message: Message):
|
|||||||
await message.answer(f"{message.html_text}\n\n{not_anderstand}!!! Я не понимаю эту команду :(\nДля получения списка известных мне команд напиши /start \n{added_text}", parse_mode="HTML")
|
await message.answer(f"{message.html_text}\n\n{not_anderstand}!!! Я не понимаю эту команду :(\nДля получения списка известных мне команд напиши /start \n{added_text}", parse_mode="HTML")
|
||||||
|
|
||||||
# Извлекаем из сообщений пользователя данные url, email, телефон и код
|
# Извлекаем из сообщений пользователя данные url, email, телефон и код
|
||||||
@dp.message(F.text)
|
#@dp.message(F.text)
|
||||||
async def extract_data(message: Message):
|
async def extract_data(message: Message):
|
||||||
data = {
|
data = {
|
||||||
"url": "<N/A>",
|
"url": "<N/A>",
|
||||||
@ -208,6 +210,34 @@ async def extract_data(message: Message):
|
|||||||
# f"Пароль: {html.quote(data['code'])}"
|
# f"Пароль: {html.quote(data['code'])}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@dp.message(Command("settimer", prefix="/!")) # добавим дополнительные префиксы для оперделения команды
|
||||||
|
async def cmd_settimer(
|
||||||
|
message: Message,
|
||||||
|
command: CommandObject
|
||||||
|
):
|
||||||
|
# Если не переданы никакие аргументы, то
|
||||||
|
# command.args будет None
|
||||||
|
if command.args is None:
|
||||||
|
await message.answer(
|
||||||
|
"Ошибка: не переданы аргументы"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
# Пробуем разделить аргументы на две части по первому встречному пробелу
|
||||||
|
try:
|
||||||
|
delay_time, text_to_send = command.args.split(" ", maxsplit=1)
|
||||||
|
# Если получилось меньше двух частей, вылетит ValueError
|
||||||
|
except ValueError:
|
||||||
|
await message.answer(
|
||||||
|
"Ошибка: неправильный формат команды. Пример:\n"
|
||||||
|
"/settimer <time> <message>"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
await message.answer(
|
||||||
|
"Таймер добавлен!\n"
|
||||||
|
f"Время: {delay_time}\n"
|
||||||
|
f"Текст: {text_to_send}"
|
||||||
|
)
|
||||||
|
|
||||||
# Запуск процесса поллинга новых апдейтов
|
# Запуск процесса поллинга новых апдейтов
|
||||||
async def main():
|
async def main():
|
||||||
# Регистрируем хэндлер cmd_test2 по команде /start
|
# Регистрируем хэндлер cmd_test2 по команде /start
|
||||||
|
60
bot2.py
Normal file
60
bot2.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import re
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
from datetime import datetime
|
||||||
|
from aiogram import F
|
||||||
|
from aiogram.types import Message
|
||||||
|
from aiogram.filters import Command, CommandObject, CommandStart
|
||||||
|
from aiogram import Bot, Dispatcher, types
|
||||||
|
from aiogram.client.default import DefaultBotProperties
|
||||||
|
from aiogram.enums import ParseMode
|
||||||
|
|
||||||
|
from config_reader import config
|
||||||
|
|
||||||
|
# Включаем логирование, чтобы не пропустить важные сообщения
|
||||||
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
|
# Для записей с типом Secret* необходимо
|
||||||
|
# вызывать метод get_secret_value(),
|
||||||
|
# чтобы получить настоящее содержимое вместо '*******'
|
||||||
|
bot = Bot(
|
||||||
|
token=config.bot_token.get_secret_value(),
|
||||||
|
default=DefaultBotProperties(
|
||||||
|
parse_mode=ParseMode.HTML
|
||||||
|
# тут ещё много других интересных настроек
|
||||||
|
))
|
||||||
|
|
||||||
|
# Объект бота напрямую из .env
|
||||||
|
# bot = Bot(token=os.getenv("BOT_TOKEN"))
|
||||||
|
|
||||||
|
# Диспетчер
|
||||||
|
dp = Dispatcher()
|
||||||
|
dp["started_at"] = datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||||
|
|
||||||
|
@dp.message(Command("help"))
|
||||||
|
@dp.message(CommandStart(
|
||||||
|
deep_link=True, magic=F.args == "help"
|
||||||
|
))
|
||||||
|
async def cmd_start_help(message: Message):
|
||||||
|
await message.answer("Это сообщение со справкой")
|
||||||
|
|
||||||
|
|
||||||
|
@dp.message(CommandStart(
|
||||||
|
deep_link=True,
|
||||||
|
magic=F.args.regexp(re.compile(r'book_(\d+)'))
|
||||||
|
))
|
||||||
|
async def cmd_start_book(
|
||||||
|
message: Message,
|
||||||
|
command: CommandObject
|
||||||
|
):
|
||||||
|
book_number = command.args.split("_")[1]
|
||||||
|
await message.answer(f"Sending book №{book_number}")
|
||||||
|
|
||||||
|
# Запуск процесса поллинга новых апдейтов
|
||||||
|
async def main():
|
||||||
|
# Регистрируем хэндлер cmd_test2 по команде /start
|
||||||
|
# Запускаем бота
|
||||||
|
await dp.start_polling(bot)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
Loading…
x
Reference in New Issue
Block a user