Простір для вивчення нової професії, зростання в кар’єрі або розвитку бізнесу👇🏻
Наша команда пише для вас найкращі та найцікавіші матеріали, які обов’язково допоможуть у вашому навчанні: https://genius.space/lab/
Last updated 3 weeks, 5 days ago
? Офіційний безкоштовний вебхук:
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 для вебхуку можна глянути тут
? Всім привіт, в останні неділі писав бота. Це як мій пет проект, що буде корисний (на мій погляд) будь-якій активній людині в Telegram Якщо коротко - можна зберігати повідомлення будь-якого типу, кастомізувати, і за допомогою інлайн режиму надсилати їх у…
⭐️ 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}")
```
? Прості пункти використання платежів. Ще варто знати, що чеки можуть бути оплачені як один раз так і декілька, детальніше про це можна дізнатись тут
? На 200 підписників зроблю пост на тему: Вебхук із самопідписаним сертифікатом + nginx reverse proxy server, FastAPI
? Деплой ботів та 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
? Новачки або 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
:
<router або dispatcher>.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)
Простір для вивчення нової професії, зростання в кар’єрі або розвитку бізнесу👇🏻
Наша команда пише для вас найкращі та найцікавіші матеріали, які обов’язково допоможуть у вашому навчанні: https://genius.space/lab/
Last updated 3 weeks, 5 days ago