about aiogram


Гео и язык канала: Украина, Украинский
Категория: Технологии


✏️ Про розробку телеграм ботів з використанням aiogram та інших бібліотек і технологій
🔍 Навігатор (inline mode) - @aiotipbot
🙃 Канал ведуть @Shaonis + @wakaree
#aiogram #bots #python

Связанные каналы

Гео и язык канала
Украина, Украинский
Категория
Технологии
Статистика
Фильтр публикаций


🚛 CI/CD з Github Actions

💭 Зараз зробимо CI/CD автоматизацію, яка при кожному оновленні коду в GitHub репозиторії буде переносити зміни на сервер

🛠 Інструменти

🔀 GitHub Actions - CI/CD платформа, що дозволяє автоматизувати твій build-test-deploy pipeline

🐳 Docker - відкрита платформа для розробки, доставки та запуску додатків (розбирали в пості)

📦 Github Container Registry - зберігає image контейнерів в межах організації чи особистого акаунту, а також дозволяє пов'язати image із репозиторієм

Сама концепція CI/CD набагато ширша, але в рамках даного посту все спрощено: CI - це build контейнера, CD - його release і deploy

• GitHub Actions - в ролі вебхуку на push подію для репозиторію, який буде виконувати наші інструкції
• Docker - для побудови образу (але можна і без нього, наприклад запускати бота з systemd)
• Github Container Registry - для збереження образів (для приватної видимості, в DockerHub на це сильніші обмеження)

✏️ Пишемо конфігурацію

Щоб скористатись GitHub Actions пишуть workflow файли, а вони налаштовані для запуску однієї чи декількох задач

• YAML формат файлу
• Мають знаходитись в .github/workflows/
• Основна структура: події, змінні середовища та завдання
• І workflows і actions можна публікувати та перевикористовувати

Давай розберемо готовий приклад
name: Deploy to server

on:
push:
branches: [ "main" ]

env:
REGISTRY: ghcr.io
IMAGE_NAME: /:latest

permissions:
contents: read
packages: write

jobs:
publish:
name: Publish image
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Login
run: |
echo $` secrets`.`GITHUB_TOKEN ` | docker login ghcr.io -u $` github`.`actor ` --password-stdin
- name: Build and Push
run: |
docker build . -t $` env`.`REGISTRY `/$` env`.`IMAGE_NAME `
docker push $` env`.`REGISTRY `/$` env`.`IMAGE_NAME `

deploy:
needs: publish
name: Deploy app
runs-on: ubuntu-latest

steps:
- name: Setup ssh keys
run: |
install -m 600 -D /dev/null ~/.ssh/id_rsa
echo "$` secrets`.`SSH_PRIVATE_KEY `" > ~/.ssh/id_rsa
ssh-keyscan -H $` secrets`.`SSH_HOST ` > ~/.ssh/known_hosts
- name: Connect-pull-up
run: |
ssh $` secrets`.`SSH_USER `@$` secrets`.`SSH_HOST `


🦾 Local Bot API Server

Вихідний код Bot API Server (BAS) є відкритим - telegram-bot-api. Його можна запустити локально та надсилати запити на свій власний сервер замість https://api.telegram.org

🔥 Переваги бота, що працює з локальним BAS

• Завантаження файлів будь-якого розміру
• Надсилання файлів розміром до 2 ГБ
• Можна надсилати файли, використовуючи їхній локальний шлях і схему файлового URI
• Дозволяється використовувати HTTP URL для вебхуку
• Можна брати будь-які локальні IP та порти для вебхуку
• Ліміт max_webhook_connections розширюється до 100_000 (замість 100)
• Абсолютний локальний шлях отримується як значення поля file_path без необхідності завантажувати файл після запиту getFile

👉 Локальний BAS може покращити продуктивність ботів за рахунок більш низького пінгу та розширених лімітів

✏️ Загальні концепти

🦾 BAS це - додатковий рівнень абстракції для взаємодії з Telegram API у вигляді акаунта бота. Він є зручною реалізацією RestAPI для розробників і працює як фронт-енд для Telegram API. Зробити свій такий набагато складніше, BAS бере на себе інтерфейси Telegram API та роботу з MTProto. Всі боти взаємодіють з BAS і можуть працювати з ним на одному сервері

☑️ Global Bot API Server - звичайні боти взаємодіють з серверами Telegram через екземпляр telegram-bot-api, що обслуговується офіційно

Сам же користувач ніколи не взаємодіє з BAS напряму (тобто користувацький додаток Telegram ніколи не підключається безпосередньо до сервера, на якому запущений BAS). Всі комунікації проходять через сервери Telegram, які внутрішньо пересилають їх двом залученим клієнтам MTProto:
• додатку Telegram, що використовує користувач
• екземпляру BAS, що працює під капотом

☑️ telegram-bot-api точно такий самий сервер, з яким спілкуються боти на api.telegram.org. Тут немає ніяких додаткових або прибраних шарів. Боти працюватимуть набагато швидше, якщо переключаться на локальний BAS, розташований у відповідному регіоні. Покращити продуктивність також може робота з локальними файлами і більша пропускна здатність для вебхуків

🔌 Використання BAS

1. Генератор інструкцій для збірки серверу
2. Необхідно дістати api_id та api_hash свого аканту телеграм та вказати їх як аргументи (--api-id, --api-hash) чи змінні середовища (TELEGRAM_API_ID, TELEGRAM_API_HASH)
3. Щоб підключені до серверу боти мали розширені ліміти та інші функції, недоступні на https://api.telegram.org, обов'язково додай аргумент --local
4. BAS приймає лише HTTP-запити, тому для обробки HTTPS-запитів потрібно використовувати проксі з термінацією TLS
5. За замовчуванням BAS запускається на порту 8081, який можна змінити аргументом --http-port

📌 Примітки

• Мігрувати бота на локальний сервер
• Перемістити бота з одного BAS на інший
• Всі файли зберігаються на серверах Telegram, а не на BAS. Але можливо, що BAS кешує файли (чи щось подібне)
• Є неофіційний Docker образ BAS від розробників aiogram
• На api.telegram.org заборонено використовувати адреси webhook тільки для IPv6. Очікується, що вони працюватимуть якщо BAS запущено в --local режимі
• getMe не слід використовувати для тестування продуктивності сервера. Сервер негайно відповідає на getMe, не викликаючи жодних інших мережевих запитів


📚 Using a local bot api server
📖
Bot api server general questions='nofollow'>


🌱 Життєвий цикл апдейту в aiogram

💭 Зазвичай люди, що починають писати ботів намагаються ловити потрібне повідомлення першим робочим способом і не задумуються над тим, які у них є можливості для організації обробки цих повідомлень

• Що таке апдейт
• Які є способи їх отримання
• Поняття реєстрації та обробника
• Ланцюг обробників
• Роутер і диспетчер - опис, порівняння
• Механізм Dependency Injection
• Детальний розбір мідлваря
• Фільтрація апдейтів
• Хендлер

⏫ Всі ці пункти я спробував розписати у максимально доступному форматі з поясненням різних моментів та описом елементарних помилок

🇺🇦 Стаття українською
https://botfather.dev/news/zhittyevij-cikl-apdejtu-v-aiogram

🌍 Стаття англійською
https://botfather.dev/news/lifecycle-of-an-update-in-aiogram

💫 Мені здається, що представлення цих понять в одній картині спростить написання ботів. Особливо, бачу в цьому сенс для новачків. Крім того, розуміння окремих моментів може бути корисним не тільки для ботів. Приємного читання!

⚡️ Дякую @Latand за його проект та можливість писати там статті


📡 Офіційний безкоштовний вебхук:
aiohttp, nginx, домен, Let's Encrypt #цікаве

☑️ Це cheatsheet для встановлення бота на вебхук із сертифікатом від Let's Encrypt на свій сервер + його автооновлення + безкоштовний домен

📌 Перед цим варто прочитати
Що таке вебхук і які переваги він дає
Пост про самопідписаний сертифікат

📚 Трохи теорії

🔒 Let's Encrypt - це безкоштовний, автоматизований і відкритий центр сертифікації, створений некомерційною організацією Internet Security Research Group (ISRG)

🤖 Certbot - це безкоштовна утиліта з відкритим вихідним кодом для автоматичного використання сертифікатів Let's Encrypt

🪩 FreeDNS - середовище, де інші програмісти можуть безкоштовно обмінюватися доменними іменами один з одним. З'явився у 2001 році, тому що його засновник, Джошуа Андерсон, хотів розважитися зі своїм хобі, пов'язаним з доменами

💠 aiohttp - асинхронний HTTP клієнт/сервер для asyncio та Python

📌 Переваги офіційного сертифіката над самопідписаним:
• твій сервер визнається всіма (нап. при переході на його адресу в браузері не буде ніяких попереджень про безпеку)
• зручне автооновлення
• при встановленні вебхуку не треба надсилати файл

⬇️ Загалом:
• За допомогою FreeDNS отримуємо безкоштовний домен (для Let's Encrypt необхідно мати домен)
• Сертифікат для вебхуку беремо в Let's Encrypt
• certbot буде автоматично оновлювати наш сертифікат
• nginx буде отримувати POST запити на вебхук і пересилати їх на обробку до бота
• aiohttp буде приймати апдейти бота вже за допомогою Python

📌 Для різноманіття цього разу візьмемо aiohttp замість FastAPI, бо він більш легший. Але якщо тобі треба будувати API, то залишити FastAPI буде гарним рішенням

Отримання безкоштовного домену

💭 Такий безкоштовний домен підійде або для тестів або для не дуже великих проектів. Тому, якщо в тебе серйозний проект, краще придбати домен

• Зареєструйся на сайті
• Перейди в розділ субдоменів і натисни «Add a subdomain»
• Переконайся, що в полі «Type» написано А
• У полі «Domain» обери бажаний домен (якщо натиснути «Many many more available» -> «Share Domain Registry», то з'явиться більше варіантів)

Краще обирати не дуже популярні, пізніше скажу чому. Продовжимо:

• в поле «Subdomain» введи назву субдомену (твоя авторська назва), виглядати буде як subdomain.domain
• в поле «Destination» введи IP адресу свого серверу
• після цього підтверди створення субдомену

🤩 Готово, домен є. Далі йди до свого хостинг провайдера і заяви право на цей домен. Наприклад у MVPS на панелі керування сервером є таблиця, в колонку «rDNS» треба ввести домен (ще стаття є)

📌 Пам'ятай, що необхідно буде почекати декілька хвилин (але іноді годин) поки домен не розійдеться по мережі

📥 Отримання сертифікату

Далі зайди на свій сервер і встанови certbot. На офіційному сайті є генератор інструкцій, все що треба це обрати систему і софт

В інструкції, команда для отримання сертифікату буде подібною
sudo certbot certonly --nginx
Треба буде обрати домен під який робимо сертифікат і почекати декілька секунд. Після отримання сертифікату certbot встановить таймер для його автооновлення

📌 Не популярний домен треба брати через те, що в Let's Encrypt є обмеження на частоту оновлення сертифікату і це розповсюджується на субдомени

Перевірити оновлення сертифікату без його фактичного встановлення (чи все добре)
sudo certbot renew --dry-run

📟 Конфігурація nginx

Може виглядати наступним чином
server {
listen 443 ssl;
server_name YOUR_DOMAIN;

ssl_certificate /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem;

location / {

proxy_pass http://SERVER_IP:AIOHHTP_PORT;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
📌 Замість YOUR_DOMAIN, SERVER_IP, AIOHTTP_PORT підставляй свої дані (якщо бот використовує Docker, то не забудь відкрити порти)

👉 На кінець, приклад використання aiohttp для вебхуку можна глянути тут

702 0 13 3 12

📌 Тепер у каналу є навігатор по контенту - @aiotipbot

Щоб використати бота, просто напиши його юзернейм у текстове поле

👉 Він був створений за допомогою @ntosbot, бо тепер він мультибот! Будь-хто може спробувати зробити у ньому своїх ботів, що працюватимуть через Inline Mode. Можливо, це найпростіший конструктор для створення подібних ботів


⭐️ Telegram stars #цікаве

👉 Телеграм зірки - валюта в телеграм, яку можна купувати за реальні гроші та витрачати в месенжері на різні речі

🏆 Переваги у використанні зірок

Зручність - на відмінну від інших способів оплати, використання зірок набагато зручніше як для користувача так і для сервісу. Користувач може легко поповнити свій баланс зірок через банківську карту (якщо телеграм завантажено з офіційного сайту) чи у Play Market або App Store. Проведення оплати можна зробити в декілька дотиків
Легка можливість повернення зірок назад на баланс клієнта за допомогою ідентифікатору транзакції
За допомогою зірок можна оплачувати Telegram Ads та переводити їх в реальні гроші

😔 Неприємні моменти використання зірок

Всі цифрові товари, які можна придбати в твоєму сервісі повинні оплачуватись виключно за допомогою зірок (це не стосується фізичних товарів). Тобто, якщо ти продаєш цифрові товари іншими способами, то телеграм може частково (на окремих платформах) або повністю заблокувати доступ до твого сервісу. Теоретично, процес перевірки автоматизувати неможливо, тому це стосується тільки дуже великих проектів у яких є відповідні товари. Це означає, що маленькі сервіси можуть проводити оплату будь-яким способом, але я не рекомендую подібні способи
Комісія при оплаті зірками від 30% і більше, що руйнує деякі бізнес моделі
Твій сервіс зобов'язаний брати на себе відповідальність за обслуговування клієнтів і повністю сам вирішувати спірні моменти (зокрема мати команду /paysupport)
На даний момент, ціна однієї зірки становить 0.013 USD
Переведення зірок у реальні гроші буде доступно через 21 день після їх отримання сервісом. Це буде пов'язано з криптовалютою і такий механізм працюватиме на платформі Fragment. Поки що, реальних переведень зафіксовано не було, тому деталі невідомі
Зірки мають час життя в 3 роки з дати їх отримання і якщо їх не витратити, то вони автоматично спишуться з балансу

💭 Поки що, придбати зірки можна лише під час спроби оплатити чек. Також, зірки йдуть не на баланс власника бота, а на баланс самого бота, який можна переглянути у профілі бота

👀 Як цим користуватись?

📌 Важливо не забути додати апдейт типу pre_checkout_query в дозволені, бо він не встановлюється за замовчуванням

⬇️ Простий приклад коду для створення чеку на оплату 5 зірок (або посилання)
from aiogram import Router, F, Bot
from aiogram.filters import Command
from aiogram.types import (
Message,
LabeledPrice,
PreCheckoutQuery,
)


router = Router()


@router.message(Command('start'))
async def create_invoice(msg: Message):
await msg.answer_invoice(
title="Title",
description="Description",
payload="payload",
currency="XTR", # XTR only, don't change
prices=[
LabeledPrice(label="label", amount=5), # 5 telegram stars
],
)


@router.pre_checkout_query()
async def checkout_handler(checkout_query: PreCheckoutQuery):
await checkout_query.answer(ok=True)


@router.message(F.successful_payment)
async def star_payment(msg: Message, bot: Bot):
await bot.refund_star_payment( # for testing auto-recovery of funds
msg.from_user.id,
msg.successful_payment.telegram_payment_charge_id,
)
# What actions, such as:
# - adding a transaction to the database
# - opening access to paid functions
await msg.answer(f"Your transaction id: {msg.successful_payment.telegram_payment_charge_id}")

📌 Прості пункти використання платежів. Ще варто знати, що чеки можуть бути оплачені як один раз так і декілька, детальніше про це можна дізнатись тут

📚 Читати про це в документації
🍐 Книга Груші, про платежі


✍️ Вебхук із самопідписаним сертифікатом + nginx, FastAPI

✅ Це компактна cheatsheet для встановлення бота на вебхук із самопідписаним сертифікатом на свій сервер з nginx та FastAPI

📌 Що таке вебхук і які переваги він дає

📚 Трохи теорії

📝 Самопідписані сертифікати SSL/TLS створюються, видаються та обслуговуються вручну, без центру сертифікації! Це означає, що тобі не треба буде комусь платити за оформлення та обслуговування сертифікату!

👩‍💻 nginx - це швидкий веб-сервер, який може бути зворотнім проксі, балансувальником навантаження і не тільки

👉 FastAPI - це сучасний, високопродуктивний веб-фреймворк для створення API за допомогою Python 3.8+ на основі стандартних підказок типів Python

• Самопідписаний сертифікат треба для безоплатного вебхуку
• nginx буде отримувати POST запити на вебхук і пересилати їх на обробку до бота (схоже на reverse proxy server, але в цьому пості все на одному сервері)
• FastAPI для обробки апдейтів бота вже за допомогою Python

Генерація самопідписаного сертифікату

Для створення сертифікату будемо користуватись утилітою OpenSSL
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./cert.key -outform PEM -out ./cert.pem
• req - підкоманда для сертифікатів
x509 - один із стандартів для сертифікатів
• days 365 - час життя сертифікату
• newkey rsa:2048 - створити ключ алгоритмом RSA довжиною 2048 біт
• outform PEM - необхідний формат генерації PEM
• keyout і out - куди покласти ключ і сертифікат

📌 при генерації обов'язково введи IP адресу серверу або домен в поле Common Name

👩‍💻 Робота з nginx

Для початку його треба встановити та запустити як сервіс. Приклад для Debian GNU/Linux
sudo apt-get update
sudo apt-get install nginx
sudo nginx -v
sudo systemctl enable nginx
sudo systemctl status nginx


⚙️ Налаштуємо конфігурацію nginx
• робота із сертифікатом
• блокування запитів не від Telegram
• пересилання запитів до FastAPI

🫱 Вставляємо в /etc/nginx/nginx.conf (в блок http)
server {
listen 443 ssl; # For HTTPS
server_name YOUR_IP;

ssl_certificate /.../certs/cert.pem;
ssl_certificate_key /.../certs/cert.key;

location / {
# Telegram IP ranges
allow 149.154.160.0/20;
allow 91.108.4.0/22;
# Enable local requests
allow 127.0.0.1;
allow ::1;
# Ignore other requests
deny all;

# Reverse proxy mechanism
proxy_pass http://YOUR_IP:BOT_PORT;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
📌 Заповни YOUR_IP - IP твого сервера, BOT_PORT - порт на якому працює бот (uvicorn наприклад)

📌 Після цього перезапуск
sudo systemctl restart nginx

🤝 Знайомимо бота з його вебхуком

‼️ Треба обов'язково запам'ятати, що Telegram вимагає пряме надсилання йому сертифікату як файлу, якщо він самопідписаний

👀 Приклад організаціїї FastAPI в боті. В main .py можна написати
app = create_app(
bot=bot,
dispatcher=dispatcher,
)
app.add_event_handler('startup', on_startup)
app.add_event_handler('shutdown', on_shutdown)
Приклад встановлення вебхуку (в startup наприклад)
await bot.set_webhook(
getenv('WEBHOOK_URL'),
certificate=FSInputFile('.../cert.pem'),
secret_token=getenv('WEBHOOK_SECRET'),
allowed_updates=list(ALLOWED_UPDATES),
)
Ручний варіант встановлення вебхуку
curl -F "url=https://ip_address/webhook_path" -F "secret_token=" -F "certificate=@cert.pem" https://api.telegram.org/bot/setWebhook
‼️ треба бути в директорії з файлом | обов'язково додай @, тобто тут назва сертифікату це cert.pem | secret_token необов'язковий

😉 Корисні команди

Перевірити локально, чи працює сертифікат
openssl s_client -connect ip_address:443
Переглянути запити до nginx
tail -f /var/log/nginx/access.log
Переглянути статус вебхуку
https://api.telegram.org/bot/getWebhookInfo
📌 Не забудь покласти сертифікат і ключ в підготовлені для цього місця

868 0 14 5 17

📥 Деплой ботів та SSH ключі #цікаве

👉 Деплой - процес розгортання веб-сервісу (в нашому випадку бота) в робочому оточенні (хостинг чи власна інфраструктура)

1️⃣ Різні методи та інструменти

На даний момент є дуже багато різних технологій для деплою і підтримки (CI/CD) програмного забезпечення. Виділяється з них Docker - дуже зручний інструмент для контейнеризації, він дозволяє один раз зібрати образ (image) і на його основі створювати контейнери - ізольовані (на рівні OC, а не hardware) середовища для роботи сервісів. Є параметри, щоб Docker сам запускав контейнери, якщо сервер перезавантажити, перевіряв їх на працездатність і не тільки.

Звичайною практикою буде побачити базу даних в одному контейнері, а основний сервіс в іншому + ще якісь додаткові контейнери - кожен відповідатиме за свою задачу.

Базові образи, наприклад Python, PostgreSQL є на DockerHub, тому якщо треба, докер сам їх завантажить для побудови image. Всі технології прив'язані до якоїсь OC, тому їх багато варіантів + різні версії + lite збірки - можна заплутатися. Але якщо треба - розберешся

2️⃣ Використання

• Встанови докер та запусти його як сервіс
• Напиши Dockerfile - в ньому будуть інструкції для побудови образу
• Якщо в боті є додаткові сервіси (такі як бд, редіс і т.д) створи docker-compose.yaml щоб оркеструвати одразу декількома контейнерами (перед цим прочитай про мережі)
• Дивись на приклади. Попрактикуйся з написанням образів та конфігів для компоузу, але головне розумій що робить та чи інша команда і коли що слід використовувати
• Поцікався багатоетапними збірками (коли образ використовує збудований в цьому ж Dockerfile образ)
• Дізнайся як відкривати порти. Це корисно, якщо треба взаємодіяти з сервісами не заходячи в сам контейнер. Наприклад за допомогою SSH тунелю можна локально в редакторі підключатись до БД в контейнері на сервері
• Подивись що таке профілі, корисна штука за допомогою якої можна вибірково вказати, які сервіси компоузом не треба запускати, якщо ти цього явно не вкажеш

📌 Збирати образи на сервері є поганою ідеєю, подивитись в сторону Docker Registry

😀 SSH ключі - шлях до безпечної праці з серверами

💭 Базова концепція - є клієнт і сервер. Ціль - безпечно обмінюватись даними. Клієнт генерує пару ключів - приватний і публічний. За допомогою базової аутентифікації паролем клієнт поміщає на сервер публічний ключ. Далі можна спробувати з'єднатися за допомогою утиліти ssh. Також на приватний ключ можна додатково накладати пароль. Приватний ключ ніколи, нікому не даємо.

1️⃣ Створення пари ключів

Для цього є різні утиліти. У мене наприклад є ssh-keygen. Команда генерації може виглядати так:
ssh-keygen -t rsa -b 2048 -f ~/.ssh/key_name
-t алгоритм генерації ключа
-b довжина ключів в байтах
-f шлях, куди помістити ключі

📌 Чому назва одна, ключів же 2? Справа в тому, що публічний ключ буде мати назву key_name.pub, а от приватний просто key_name

2️⃣ Організація ключів

💭 А якщо у нас буде багато серверів, при тому декілька різних ключів для кожного користувача на сервері, все пхати в .ssh?

Для цього в директорії .ssh можна створити файл config. Він допомагає встановити відповідність між ключами та серверами. Наприклад:
Host 123.45.67.89
HostName mybot.io
User admin1
IdentityFile ~/.ssh/server1/key.pub
IdentitiesOnly yes

Host 132.89.46.72
HostName 132.89.46.72
User admin2
IdentityFile ~/.ssh/server2/key.pub
IdentitiesOnly yes
...
І так далі. Кожен блок відповідає за одну пару ключів.
• Host - IP серверу
• HostName - домен чи IP серверу
• User - аккаунт на сервері
• IdentityFile - шлях до публічного ключа
• IdentitiesOnly - не пробувати інші ключі

3️⃣ Перенесення ключів

💭 Створили, організували, як перенести їх на сервер?

Наприклад за допомогою scp чи ssh-copy-id. Приклад:
ssh-copy-id -i ~/.ssh/.../key.pub user@ip_address
📌 Ключі буде перенесено в домашню директорію user!

Вводимо пароль і ключі вже на сервері у потрібному місці!

📌 Після встановлення SSH ключів часто прибирають аутентифікацію паролем

👩‍💻 Docker Guide
🔑 SSH keys


👋 Всім привіт, в останні неділі писав бота. Це як мій пет проект, що буде корисний (на мій погляд) будь-якій активній людині в Telegram

Якщо коротко - можна зберігати повідомлення будь-якого типу, кастомізувати, і за допомогою інлайн режиму надсилати їх у будь-які чати. Є пошук, приватність, мови

👉 Ось сам бот @ntosbot

📃 Кому цікаво, які технології юзав:

• aiogram
• aiogram-dialog
• aiogram_i18n
• PostgreSQL
• psycopg3
• SQLAlchemy
• Alembic
• Redis
• Docker

🔌 Хостинг - https://www.mvps.net/?aff=30539 :D. Поки перша версія, треба тестити, буду радий почути фідбек

💭 Чи було б цікаво почитати про деплой ботів (Docker, SSH keys)?


🌍 i18n, l10n - мови у боті #цікаве

👉 i18n (internationalization) - процес, який надає можливість використовувати програмам кілька мов. l10n (localization) - більш конкретні дії, спрямовані на використання готових інструментів для роботи з мовами і адаптацію до мовних культур

📌 Обрано саме 18 і 10, бо це просто кількість літер між крайніми буквами (а повні слова всім лінь писати)

😀 І навіщо мені цим користуватись?

• багатьом людям приємніше працювати зі своєю рідною мовою, це покращує користувацький досвід
• знаючи те, які мови обирають користувачі можна більш точно показувати їм те, що треба саме нам (кому буде приємно бачити рекламу мовою, яку ми не знаємо?)

👀 Як цим користуватись?

1️⃣ Інструменти

Почнемо з того, що нам треба працювати саме з ботом. На даний момент є такі інструменти:
• вбудований aiogram.utils.i18n (на основі GNU gettext і Babel)
• неофіційна aiogram_i18n від активного учасника спільноти Patrick (підтримує GNU gettext, але пріоритет на Project Fluent)

Думаю, легше буде почати з aiogram_i18n, та і виглядає вона перспективніше.

📌 GNU gettext був створений у 1995 р, детальніше (багато цікавого загалом). Project Fluent - у 2019, це дослідницький проект Mozilla. Він був створений для вирішення багатьох проблем i18n/l10n, детальніше.

2️⃣ Як працює aiogram_i18n

Простими словами її роботу можна описати так:
• при отриманні апдейту бібліотека за допомогою менеджера отримує код мови користувача (en, uk)
• спеціальний мідлвар користується цим менеджером і за допомогою Dependency Injection передає екземпляр I18nContext як i18n (назву можна змінити) у ланцюг до інших мідлварів, що стоять нижче, фільтрів і нарешті хендлерів
• в екземплярі вже визначена мова (локаль) користувача, тому за допомогою I18nContext в хендлері можна діставати відповідні переклади чи змінювати локаль юзера за замовчуванням

3️⃣ Звідки і який менеджер бере локаль

Якщо у нас локалі знаходяться в БД, то треба створити менеджер самостійно як підклас
aiogram_i18n.managers.base.BaseManager
В ньому треба буде реалізувати два методи get_locale і set_locale. Проте необов'язково реалізовувати свій менеджер - у бібліотеці є готові рішення на основі Memory/Redis/FSM. Отже, задача менеджера допомагати мідлвару отримувати локаль тим способом який ми йому «показали»

4️⃣ get_locale і set_locale

• Що повинен повертати метод get_locale?
» Просто назву коду мови, наприклад "en" чи "de". Ці коди повинні бути назвами директорій з перекладами, про це пізніше.
• Для чого set_locale?
» Буде логічно, якщо все, що пов'язано з перекладом, буде виконувати I18nContext - в тому числі і зміну локалі юзера

Доволі простий приклад:
class i18nManager(BaseManager):
user_languages = {}

async def get_locale(self, event_from_user: User, db: Database) -> str:
try:
return self.user_languages[event_from_user.id]
except KeyError:
language = await db.get_user_language(event_from_user.id)
self.user_languages[event_from_user.id] = language
return language

async def set_locale(self, locale: str, event_from_user: User, db: Database) -> None:
await db.set_user_language(event_from_user.id, locale)
self.user_languages[event_from_user.id] = locale
📌 Зверни увагу, що в set_locale перший позиційний аргумент це locale

5️⃣ Підключення та оформлення

• Імпортуємо і реєструємо I18nMiddleware
• В аргументах як ядро вказуємо FluentRuntimeCore (pip install fluent.runtime). Я обрав це, бо зараз доступні 3 ядра, чув що FluentCompileCore хочуть прибрати, а GNU gettext є і в build-in
• В аргументи мідлвара передаємо потрібний нам менеджер (чи самописний)
• Далі вказуємо директорії з перекладами. Їх приклади дивись в репозиторіях. Головне правильный шаблон шляху і розподілені .ftl файли
• Про синтаксис .ftl файлів читай тут
• Тепер використовуй у хендлерах i18n.get і якщо хочеш роби стаби

📌 LazyProxy - це фільтр, що сам дістає відповідний переклад і порівнює його із вхідним текстом

⭐️ aiogram_i18n

759 8 15 12 9

🤔 Новачки або aiogram roadmap #порада

В чаті можна часто можна помітити подібні питання:
• «Як створити бота? Хочу почати з цього»,
• «Чому треба писати равлики над функціями?»
• «Що таке polling?»

💭 З цього можна зробити висновок: aiogram дуже приваблює новачків, але він для них надто складний.

👉 Якщо ти хочеш навчитися створювати ботів, то не зважай на популярні відео в ютубі, в яких показують як написати бота. Автори цих відео роблять скоріше міні-обзори, у них немає мети серйозно тебе вчити, вони навіть можуть дати тобі погані приклади (якщо це не плейлист чи курс). Через це багато хто не знає з чого почати написання ботів і цю сферу часто асоціюють із чимось примітивним, хоча це не завжди так.

🎁 Пропоную новачкам, які хочуть з чогось почати, слідувати aiogram roadmap, яку я створив, щоб було комфортно поглиблюватись у фреймворк і загалом розробку ботів. Вона також буде корисна тим, хто має досвід. Сама roadmap обов'язково буде оновлюватись, чекаю ваші думки с приводу неї


💬 Chat Actions #цікаве
Інколи може знадобитися виконати тривалу задачу, наприклад, надіслати файл великого розміру або дочекатися відповіді від API, щоб надіслати респонс користувачу. Щоб під час її виконання бот здавався більш "живим", а не просто наче підвисав у користувача — хорошою ідеєю буде надсилати "дію в чаті".

👀 Що ж це таке?
Нам відомо, що коли юзер щось друкує, надсилає фото тощо — ми бачимо відповідний статус під його іменем. Це дає зрозуміти, що співрозмовник не просто проігнорував твоє повідомлення, а збирається відповісти.
Так само і з ботом — щоб показати користувачу, що на його стороні щось відбувається, ми використовуєм аналогічний метод sendChatAction. Даний метод буде відображати вказаний розробником статус до п'яти секунд.

🤔 А якщо на виконання задачі мені потрібно більше, ніж п'ять секунд?
Це також передбачено фреймворком. Він забезпечує утиліту ChatActionSender.
Простий приклад:
@router.message(Command("generate_photo"))
async def generate_photo(message: Message, bot: Bot) -> Any:
async with ChatActionSender.upload_photo(bot=bot, chat_id=message.chat.id):
# Do something for a long time to get result
result = await generate_photo(...)
await message.answer_photo(photo=result)
⚒ Є також спосіб забезпечити використовування chat action у всіх обробниках.
Спочатку потрібно зареєструвати ChatActionMiddleware (що таке мідлварі?) на подію message:
.message.middleware(ChatActionMiddleware())
Тепер замість створення ChatActionSender у обробникуgenerate_photo ми можемо повісити мітку на обробник:
@router.message(Command("generate_photo"))
@flags.chat_action(ChatAction.UPLOAD_PHOTO)
async def generate_photo(message: Message) -> Any:
# Do something for a long time to get result
result = await generate_photo(...)
await message.answer_photo(photo=result)
За потребою можна змінювати й конфігурацію ChatActionSender, а не тільки тип дії, що надсилаємо:
@router.message(Command("generate_photo"))
@flags.chat_action(initial_sleep=2, action=ChatAction.UPLOAD_PHOTO, interval=3)
async def generate_photo(message: Message) -> Any:
# Do something for a long time to get result
result = await generate_photo(...)
await message.answer_photo(photo=result)
📚 Не полінися завітати в документацію!


Репост из: Pharaonis 🖤
Видео недоступно для предпросмотра
Смотреть в Telegram


😐 Якщо ти задаєш питання ось так.. #порада
«Доброго дня! Підкажіть, чому може виникати NazvaPomylky: opys pomylky
або взагалі ось так..
«Доброго дня! Допоможіть будь ласка, хто шарить у ...»
...то будь готовий, що шанси отримати допомогу будуть в рази менше.

🤔 А що не так?
Спочатку розглянемо другий кейс, коли ти взагалі не переходиш до проблеми одразу. Це мета-питання, яких потрібно уникати в подібних чатах!
Перший кейс, ти все таки надіслав текст помилки. Але ніхто не збирається витрачати свій час щоб відгадувати, що саме сталося. Назви й опису недостатньо, щоб зрозуміти твою проблему!
Те саме стосується й випадків, коли ти прислав тільки скріншот коду й просто питаєш "Чому це не працює?"

📋 Ось список порад, як корректно задати питання й отримати фідбек якомога швидше.
» Перед тим як написати у чат, спробуй розібратися з помилкою самостійно. Можливо, варто почитати документацію, або й зовсім підучити Python.
» Не задавай мета-питань.
» Якщо тобі погодилися допомогти у чаті, не потрібно одразу писати людині у ПП. (Більше про це »)
» Показуй повну помилку, від Traceback (most recent call last): до NazvaPomylky: opys pomylky.
» Не лінися ділитися контекстом помилки. Наприклад, якщо вона виникла у якомусь обробнику start_command, показуй увесь метод.
» Ділися кодом й трейсбеком на пасті, а не скидай полотно у чаті.
» Іноді, коли проблема неочевидна, просто показати код може бути недостатньо. Буде потрібен 'https://t.me/aiogram_ru/1421477/1421487' rel='nofollow'>Мінімально відтворюваний приклад.


😀 Привіт усім, вибачайте що постів довго не було. Справа в тому, що я вже зовсім скоро буду студентом 😀

😀 У нас на каналі з'явився новий редактор - @nullmatawasoradesu, він також має свій канал зі схожою тематикою @aiogram_hent, тому заходьте і туди, дізнавайтесь нове. Він час від часу буде писати пости, коли я буду зайнятий


🤖 Створення мультиботу #цікаве

👉 Мультибот - це бот, який може керувати іншими ботами. В aiogram 3.X такого можна написати з коробки (тобто для його створення вже є готові інструменти)

💭 Міньйон (мій сленг) - бот, що керується основним ботом

😀 І навіщо мені цим користуватись?

• запускати кастомні конфігурації ботів-шаблонів під свої потреби
• копіювати функціонал основного бота і використовувати його на різних токенах
• розділяти інтерфейс основного бота на декілька більш менших

👀 Як цим користуватись?

• для нормального мультибота необхідний вебхук (бонус внизу посту - як запустити найпростіший вебхук)

• окрім SimpleRequestHandler для основного бота, нам потрібен буде TokenBasedRequestHandler, щоб реєструвати інших ботів-посіпак, він буде брати їх токени для створення вебхук посилань, тому обовʼязково треба, щоб в path у методі register була константа {bot_token} (класи брати із aiogram.webhook.aiohttp_server)

🔅 MRE найпростішого мультибота: у нього міньйони додаються в рантаймі і підключаються до одного й того ж самого диспетчера (тобто виконують однакові дії)
https://github.com/aiogram/aiogram/blob/dev-3.x/examples/multibot.py

🪄 Псевдо-код для прикладу реєстрації міньйонів зі своїми роутерами (від мене)
https://pastebin.com/GSbGe34K

🎁 БОНУС - найпростіший вебхук в домашніх умовах

💭 Якщо в тебе вийшло запустити aiohttp додаток (web.Application) і ти хотів би потестувати бота, але при цьому немає SSL сертифікату або лінь його робити, то можна скористатись безкоштовним reverse proxy сервером який буде пересилати POST запити від телеграму до твого бота по захищеному тунелю (навіть якщо программа знаходиться за NAT-маршрутизатором чи брандмауером і в тебе сірий IP)

🛠 Називається цей інструмент - Ngrok

1️⃣ Завантажуємо його (на будь-яку ОС чи навіть docker)

2️⃣ Беремо порт на якому буде працювати наш aiohttp app, самого бота поки що не запускаємо. Далі заходимо в консоль і пишемо «ngrok http {your_port}» (для Windows там є окрема програма навіть). Далі ngrok видасть нам декілька посилань, беремо те, яке починається з https бо телеграм не буде слати на http

3️⃣ Змінюємо посилання (BASE_URL) у нашій програмі на те, яке взяли у ngrok. Запускаємо бота, готово! Тепер бот буде працювати на вебхуці

‼️ Це гарний спосіб, щоб тестувати бота на вебхуках, але не треба використовувати його в продакшині - краще зробити свій reverse proxy сервер, наприклад на nginx. До того ж кожний раз ngrok буде давати випадкову адресу, також там 2 години TTL у посилання (тобто прийдеться часто міняти), проте у зареєстрованих користувачів такого ліміту немає


📦 Збірка технологій для розробки тг ботів на Python #цікаве

😀 Фреймворки для TG Bot API
aiogramtelebot
python-telegram-bot

🌐 Веб фреймворки
aiohttpStarlette
FastAPISanic
QuartDjango

🖥 СУБД
SQLite3PostgreSQL
MySQL

🗃 NoSQL СУБД
RedisMongoDB

😀 ORM і міграції
SQLAlchemyAlembic

🛖 Робоче середовище
venvDocker

📅 Планувальники і брокери завдань
APShedulerRabbitMQ
Apache KafkaCelery
Nats

🧮 Тестування
unittestpytest
mockcoverage

🗜 DevOps і CI/CD
GitHub ActionsGitLab
Ansible

📌 Закреслені - не рекомендовані для використання у великих проектах. Акцент збірки зроблений на безоплатному використанні інструментів, можливості їх асинхронної роботи, популярності


🔒 Middleware, Мідлвар #цікаве

👉 Middleware (в aiogram) - це спеціальний класс (можна реалізувати у вигляді функції), який має контроль над апдейтом до того, як на нього відреагує бот

😀 І навіщо мені цим користуватись?

• Можна обробляти апдейт тільки якщо він відповідає нашим умовам
• Є можливість «блокувати апдейт» наче його і не було
• Загалом можна робити будь-які дії перед тим як бот відреагує на апдейт чи після цього

👀 Як цим користуватись?

• Екземпляр мідлваря треба реєструвати у диспетчера чи роутера з певним типом апдейту який він буде обробляти

📌 Є «зовнішні» та «внутрішні» реєстрації
Зовнішні - будуть завжди викликатись на вказаний тип апдейту
dp..outer_middleware()
Внутрішні - спрацюють якщо апдейт з потрібним типом потенційно потрапляє в якийсь хендлер (тобто пройде крізь всі фільтри)
..middleware()

📌 Реєстрація мідлваря, який буде обробляти будь-які апдейти
dp.update.outer_middleware()

📌 Якщо комбінувати свій router і внутрішню реєстрацію, то мідлвар буде працювати тільки з хендлерами цього роутеру

🎒Пам'ятка новачка
1) Якщо мідлвар це класс, то в нього обов'язково повинен бути метод call - саме в ньому реалізується всі подальші дії після отримання апдейту
2) Точно знаємо який тип апдейтів приходить - анотуємо це.
3) За передачу апдейту по ланцюжку фільтрів і хендлерів відповідає виклик handler: await handler(event, data)
4) Виклик мідлваря приймає такі аргументи:

> handler - хендлер (відомий тільки якщо це внутрішній мідлвар)
> event - вхідна подія (підклас aiogram.types.base.TelegramObject)
> data - контекстні дані (словник), через них передаються аргументи у фільтри й хендлери

🪄 Приклади мідлварей

Лічильник (з доки) - обробляє апдейти типу Message які проходять фільтри і потрапляють в якийсь хендлер цього роутера. Передає в хендлер аргумент «counter»

Антифлуд (від Груші) - реєструється на тип Message, перевіряє чи є ід чату в тимчасовому кеші, якщо є, то блокує апдейт, інакше записує його в нього

Ловля альбомів - реєструється на Message і відловлює повідомлення з media_group_id, передає список елементів як аргумент «album» в хендлер

Передача сесій бд (від мене) - за допомогою async_sessionmaker (це з SQLAlchemy) дістає сесію для роботи з бд і дає її новому екземпляру класса з вашими запитами до бази данних, передає готовий клас як аргумент «db» в хендлер чи фільтр

Перевірка на бан (від мене) - дістає тг ід юзера і перевіряє його у списку заблокованих користувачів, блокує апдейт якщо результат пошуку True

📚 Читати про це в документації
🍐 Книга Груші, про Мідлвари


🔗 Deep Linking (Cheat sheet) #цікаве

👉 Telegram Deep Linking - (з англ. Глибокі посилання) це спеціальні види посилань, які певним чином обробляються клієнтами телеграм

😀 Базові шаблони:
t.me/path?query
http://t.me/path?query
https://t.me/path?query
tg://path?query

💭 Взагалі ці посилання можуть виконувати найрізноманітніші дії. Від банального згадування юзера в чаті до зміни параметрів клієнту телеграма. Якщо ти хочеш робити гарний і корисний текст, то читай далі

У цьому пості ми розглянемо найбільш вживані посилання в контексті ботів. Якщо ти хочеш дізнатись всі види посилань і те як вони утворюються, то внизу буде офіційна стаття на цю тему. Я розповім про їх популярні шаблони та інструменти з коробки aiogram

1️⃣ Згадування юзера по ід
👉 tg://user?id=

📦 можна дістати з об'єкта User атрибутом url (from_user.url)

✏️ Цікаві факти про це посилання
➖➖➖➖➖➖➖➖➖➖
2️⃣ Передача параметра у команді /start
👉 t.me/?start=

📦 from aiogram.utils.deep_linking import create_start_link
➖➖➖➖➖➖➖➖➖➖
3️⃣ Додати бота в группу
👉 t.me/?startgroup

📦 from aiogram.utils.deep_linking import create_startgroup_link
➖➖➖➖➖➖➖➖➖➖
4️⃣ Додати бота в канал
👉 t.me/?startchannel&admin=
➖➖➖➖➖➖➖➖➖➖
5️⃣ Надсилання підготовленого повідомлення
👉 tg://msg_url?text=
➖➖➖➖➖➖➖➖➖➖
6️⃣ Створення спойлеру
👉 text
➖➖➖➖➖➖➖➖➖➖

💎 Цікавий канал посвячений Deep Linking

🌀 API > Deep Links
🍐 Книга Груші, повідомлення


@Tishka17 😳 GitHub #активіст

Розробник. Помічник в чаті. Контрибьютор aiogram

😀Чим займався/ється:

• веде свій особистий канал із дієвими порадами. Буде корисний будь-яким розробникам - @advice17

• творець aiogram-dialog. Це фреймворк з графічним інтерфейсом для тг ботів. Натхненний ідеями Android SDK та React.js (простіше кажучи він допомагає працювати з інлайн кнопками). Є бот для демонстрації роботи бібліотеки - @aiogram_dialog_demo_bot
~ 📚 Документація | 💭 Чат

https://t.me/about_aiogram/17

Показано 20 последних публикаций.