ΠΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠ°Ρ-Π±ΠΎΡΠΎΠ² ΠΈ SmartApps Π΄Π»Ρ ΠΌΠ΅ΡΡΠ΅Π½Π΄ΠΆΠ΅ΡΠ° eXpress
- ΠΡΠΎΡΡΠ°Ρ Π΄Π»Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΡ
- ΠΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΠΊΠΎΠ»Π»Π±ΡΠΊΠΈ BotX
- ΠΠ΅Π³ΠΊΠΎ ΠΈΠ½ΡΠ΅Π³ΡΠΈΡΡΠ΅ΡΡΡ Ρ Π°ΡΠΈΠ½Ρ ΡΠΎΠ½Π½ΡΠΌΠΈ Π²Π΅Π±-ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠ°ΠΌΠΈ
- ΠΠΎΠ»Π½ΠΎΠ΅ ΠΏΠΎΠΊΡΡΡΠΈΠ΅ ΡΠ΅ΡΡΠ°ΠΌΠΈ
- ΠΠΎΠ»Π½ΠΎΠ΅ ΠΏΠΎΠΊΡΡΡΠΈΠ΅ Π°Π½Π½ΠΎΡΠ°ΡΠΈΡΠΌΠΈ ΡΠΈΠΏΠΎΠ²
ΠΡΠΏΠΎΠ»ΡΠ·ΡΡ poetry
:
poetry add pybotx
ΠΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅: ΠΠ°Π½Π½ΡΠΉ ΠΏΡΠΎΠ΅ΠΊΡ Π½Π°Ρ
ΠΎΠ΄ΠΈΡΡΡ Π² Π°ΠΊΡΠΈΠ²Π½ΠΎΠΉ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ΅ (0.y.z
) ΠΈ
Π΅Π³ΠΎ API ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈΠ·ΠΌΠ΅Π½ΡΠ½ ΠΏΡΠΈ ΠΏΠΎΠ²ΡΡΠ΅Π½ΠΈΠΈ ΠΌΠΈΠ½ΠΎΡΠ½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ.
ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ ΠΏΠΎ ΠΌΠ΅ΡΡΠ΅Π½Π΄ΠΆΠ΅ΡΡ (Π²ΠΊΠ»ΡΡΠ°Ρ ΡΡΠΊΠΎΠ²ΠΎΠ΄ΡΡΠ²ΠΎ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡΠ°) ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π½Π° ΠΎΡΠΈΡΠΈΠ°Π»ΡΠ½ΠΎΠΌ ΡΠ°ΠΉΡΠ΅.
ΠΠ΅ΡΠ΅Π΄ ΡΠ΅ΠΌ, ΠΊΠ°ΠΊ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡΡ Π·Π½Π°ΠΊΠΎΠΌΡΡΠ²ΠΎ Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΎΠΉ pybotx
,
ΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΠΏΡΠΎΡΠΈΡΠ°ΡΡ Π΄Π°Π½Π½ΡΠ΅ ΡΡΠ°ΡΡΠΈ: Π§ΡΠΎ ΡΠ°ΠΊΠΎΠ΅ ΡΠ°Ρ-Π±ΠΎΡΡ
ΠΈ SmartApp
ΠΈ ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Ρ Bot API ΠΈ BotX API.
Π ΡΡΠΈΡ
ΡΡΠ°ΡΡΡΡ
Π½Π°Ρ
ΠΎΠ΄ΡΡΡΡ ΠΈΡΡΠ΅ΡΠΏΡΠ²Π°ΡΡΠΈΠ΅ ΠΏΡΠΈΠΌΠ΅ΡΡ ΡΠ°Π±ΠΎΡΡ Ρ ΠΏΠ»Π°ΡΡΠΎΡΠΌΠΎΠΉ, ΠΊΠΎΡΠΎΡΡΠ΅
Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ²ΡΠΎΡΠΈΡΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ pybotx
.
Π’Π°ΠΊΠΆΠ΅ Π½Π΅ Π±ΡΠ΄Π΅Ρ Π»ΠΈΡΠ½ΠΈΠΌ ΠΎΠ·Π½Π°ΠΊΠΎΠΌΠΈΡΡΡΡ Ρ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠ΅ΠΉ ΠΏΠΎ ΠΏΠ»Π°ΡΠΎΡΠΌΠ΅ BotX .
- Next Feature Bot - Π±ΠΎΡ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌΡΠΉ Π΄Π»Ρ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π»Π° ΠΏΠ»Π°ΡΡΠΎΡΠΌΡ BotX.
- ToDo Bot - Π±ΠΎΡ Π΄Π»Ρ Π²Π΅Π΄Π΅Π½ΠΈΡ ΡΠΏΠΈΡΠΊΠ° Π΄Π΅Π».
- Weather SmartApp - ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΄Π»Ρ ΠΏΡΠΎΡΠΌΠΎΡΡΠ° ΠΏΠΎΠ³ΠΎΠ΄Ρ.
from http import HTTPStatus
from uuid import UUID
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
# Π ΡΡΠΎΠΌ ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΡΡΡΠΈΡ
ΠΏΡΠΈΠΌΠ΅ΡΠ°Ρ
ΠΈΠΌΠΏΠΎΡΡ ΠΈΠ· `pybotx` Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡΡΡ
# ΡΠ΅ΡΠ΅Π· Π·Π²ΡΠ·Π΄ΠΎΡΠΊΡ Π΄Π»Ρ ΠΊΡΠ°ΡΠΊΠΎΡΡΠΈ. ΠΠ΄Π½Π°ΠΊΠΎ, ΡΡΠΎ Π½Π΅ ΡΠ²Π»ΡΠ΅ΡΡΡ Ρ
ΠΎΡΠΎΡΠ΅ΠΉ ΠΏΡΠ°ΠΊΡΠΈΠΊΠΎΠΉ.
from pybotx import *
collector = HandlerCollector()
@collector.command("/echo", description="Send back the received message body")
async def echo_handler(message: IncomingMessage, bot: Bot) -> None:
await bot.answer_message(message.body)
# Π‘ΡΠ΄Π° ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ ΡΠ²ΠΎΠΈ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ ΠΊΠΎΠΌΠ°Π½Π΄
# ΠΈΠ»ΠΈ ΠΊΠΎΠΏΠΈΡΠΎΠ²Π°ΡΡ ΠΏΡΠΈΠΌΠ΅ΡΡ ΠΊΠΎΠ΄Π°, ΡΠ°ΡΠΏΠΎΠ»ΠΎΠΆΠ΅Π½Π½ΡΠ΅ Π½ΠΈΠΆΠ΅.
bot = Bot(
collectors=[collector],
bot_accounts=[
BotAccountWithSecret(
# ΠΠ΅ Π·Π°Π±ΡΠ΄ΡΡΠ΅ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ ΡΡΠΈ ΡΡΡΡΠ½ΡΠ΅ Π΄Π°Π½Π½ΡΠ΅ Π½Π° Π½Π°ΡΡΠΎΡΡΠΈΠ΅,
# ΠΊΠΎΠ³Π΄Π° ΡΠΎΠ·Π΄Π°Π΄ΠΈΡΠ΅ Π±ΠΎΡΠ° Π² ΠΏΠ°Π½Π΅Π»ΠΈ Π°Π΄ΠΌΠΈΠ½ΠΈΡΡΡΠ°ΡΠΎΡΠ°.
id=UUID("123e4567-e89b-12d3-a456-426655440000"),
cts_url="https://cts.example.com",
secret_key="e29b417773f2feab9dac143ee3da20c5",
),
],
)
app = FastAPI()
app.add_event_handler("startup", bot.startup)
app.add_event_handler("shutdown", bot.shutdown)
# ΠΠ° ΡΡΠΎΡ ΡΠ½Π΄ΠΏΠΎΠΈΠ½Ρ ΠΏΡΠΈΡ
ΠΎΠ΄ΡΡ ΠΊΠΎΠΌΠ°Π½Π΄Ρ BotX
# (ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ ΠΈ ΡΠΈΡΡΠ΅ΠΌΠ½ΡΠ΅ ΡΠΎΠ±ΡΡΠΈΡ).
@app.post("/command")
async def command_handler(request: Request) -> JSONResponse:
bot.async_execute_raw_bot_command(
await request.json(),
request_headers=request.headers,
)
return JSONResponse(
build_command_accepted_response(),
status_code=HTTPStatus.ACCEPTED,
)
# ΠΠ° ΡΡΠΎΡ ΡΠ½Π΄ΠΏΠΎΠΈΠ½Ρ ΠΏΡΠΈΡ
ΠΎΠ΄ΡΡ ΡΠΎΠ±ΡΡΠΈΡ BotX Π΄Π»Ρ SmartApps, ΠΎΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅ΠΌΡΠ΅ ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΠΎ.
@app.post("/smartapps/request")
async def sync_smartapp_event_handler(request: Request) -> JSONResponse:
response = await bot.sync_execute_raw_smartapp_event(
await request.json(),
request_headers=request.headers,
)
return JSONResponse(response.jsonable_dict(), status_code=HTTPStatus.OK)
# Π ΡΡΠΎΠΌΡ ΡΠ½Π΄ΠΏΠΎΠΈΠ½ΡΡ BotX ΠΎΠ±ΡΠ°ΡΠ°Π΅ΡΡΡ, ΡΡΠΎΠ±Ρ ΡΠ·Π½Π°ΡΡ
# Π΄ΠΎΡΡΡΠΏΠ½ΠΎΡΡΡ Π±ΠΎΡΠ° ΠΈ Π΅Π³ΠΎ ΡΠΏΠΈΡΠΎΠΊ ΠΊΠΎΠΌΠ°Π½Π΄.
@app.get("/status")
async def status_handler(request: Request) -> JSONResponse:
status = await bot.raw_get_status(
dict(request.query_params),
request_headers=request.headers,
)
return JSONResponse(status)
# ΠΠ° ΡΡΠΎΡ ΡΠ½Π΄ΠΏΠΎΠΈΠ½Ρ ΠΏΡΠΈΡ
ΠΎΠ΄ΡΡ ΠΊΠΎΠ»Π»Π±ΡΠΊΠΈ Ρ ΡΠ΅Π·ΡΠ»ΡΡΠ°ΡΠ°ΠΌΠΈ
# Π²ΡΠΏΠΎΠ»Π½Π΅Π½ΠΈΡ Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΡ
ΠΌΠ΅ΡΠΎΠ΄ΠΎΠ² Π² BotX.
@app.post("/notification/callback")
async def callback_handler(request: Request) -> JSONResponse:
await bot.set_raw_botx_method_result(
await request.json(),
verify_request=False,
)
return JSONResponse(
build_command_accepted_response(),
status_code=HTTPStatus.ACCEPTED,
)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from uuid import UUID
from pybotx import *
ADMIN_HUIDS = (UUID("123e4567-e89b-12d3-a456-426614174000"),)
collector = HandlerCollector()
@collector.command("/visible", description="Visible command")
async def visible_handler(_: IncomingMessage, bot: Bot) -> None:
# ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΊΠΎΠΌΠ°Π½Π΄Ρ Π±ΠΎΡΠ°. ΠΠΎΠΌΠ°Π½Π΄Π° Π²ΠΈΠ΄ΠΈΠΌΠ°Ρ, ΠΏΠΎΡΡΠΎΠΌΡ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅
# ΡΠ²Π»ΡΠ΅ΡΡΡ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΡΠΌ.
print("Hello from `/visible` handler")
@collector.command("/_invisible", visible=False)
async def invisible_handler(_: IncomingMessage, bot: Bot) -> None:
# ΠΠ΅Π²ΠΈΠ΄ΠΈΠΌΠ°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π° - Π½Π΅ ΠΎΡΠΎΠ±ΡΠ°ΠΆΠ°Π΅ΡΡΡ Π² ΡΠΏΠΈΡΠΊΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄ Π±ΠΎΡΠ°
# ΠΈ Π½Π΅ Π½ΡΠΆΠ΄Π°Π΅ΡΡΡ Π² ΠΎΠΏΠΈΡΠ°Π½ΠΈΠΈ.
print("Hello from `/invisible` handler")
async def is_admin(status_recipient: StatusRecipient, bot: Bot) -> bool:
return status_recipient.huid in ADMIN_HUIDS
@collector.command("/admin-command", visible=is_admin)
async def admin_command_handler(_: IncomingMessage, bot: Bot) -> None:
# ΠΠΎΠΌΠ°Π½Π΄Π° ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°Π΅ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ Π΅ΡΠ»ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΡΠ²Π»ΡΠ΅ΡΡΡ Π°Π΄ΠΌΠΈΠ½ΠΎΠΌ.
# Π‘ΠΏΠΈΡΠΎΠΊ ΠΊΠΎΠΌΠ°Π½Π΄ Π·Π°ΠΏΡΠ°ΡΠΈΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ ΠΎΡΠΊΡΡΡΠΈΠΈ ΡΠ°ΡΠ° Π² ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΈ.
print("Hello from `/admin-command` handler")
@collector.default_message_handler
async def default_handler(_: IncomingMessage, bot: Bot) -> None:
# ΠΡΠ»ΠΈ ΠΊΠΎΠΌΠ°Π½Π΄Π° Π½Π΅ Π±ΡΠ»Π° Π½Π°ΠΉΠ΄Π΅Π½Π°, Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ `default_message_handler`,
# Π΅ΡΠ»ΠΈ ΠΎΠ½ ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠ½. Π’Π°ΠΊΠΎΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½.
print("Hello from default handler")
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.chat_created
async def chat_created_handler(event: ChatCreatedEvent, bot: Bot) -> None:
# Π Π°Π±ΠΎΡΠ° Ρ ΡΠΎΠ±ΡΡΠΈΡΠΌΠΈ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΡ
ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ².
# ΠΠ° ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±ΡΡΠ²ΠΈΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄ΠΈΠ½ ΡΠ°ΠΊΠΎΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ.
print(f"Got `chat_created` event: {event}")
@collector.smartapp_event
async def smartapp_event_handler(event: SmartAppEvent, bot: Bot) -> None:
print(f"Got `smartapp_event` event: {event}")
from pybotx import *
collector = HandlerCollector()
# ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΡ
Smartapp ΡΠΎΠ±ΡΡΠΈΠΉ, ΠΏΡΠΈΡ
ΠΎΠ΄ΡΡΠΈΡ
Π½Π° ΡΠ½Π΄ΠΏΠΎΠΈΠ½Ρ `/smartapps/request`
@collector.sync_smartapp_event
async def handle_sync_smartapp_event(
event: SmartAppEvent, bot: Bot,
) -> BotAPISyncSmartAppEventResultResponse:
print(f"Got sync smartapp event: {event}")
return BotAPISyncSmartAppEventResultResponse.from_domain(
data={},
files=[],
)
(ΠΡΠΎΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΈΡΠΊΠ»ΡΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΊ pybotx
)
from httpx import AsyncClient
from pybotx import *
collector = HandlerCollector()
async def custom_api_client_middleware(
message: IncomingMessage,
bot: Bot,
call_next: IncomingMessageHandlerFunc,
) -> None:
# ΠΠΎ Π²ΡΠ·ΠΎΠ²Π° `call_next` (ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»Π΅Π½ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΌΠΈΠ΄Π΄Π»Π²Π°ΡΠΈ) ΡΠ°ΡΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ
# ΠΊΠΎΠ΄, ΠΊΠΎΡΠΎΡΡΠΉ Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ Π΄ΠΎ ΡΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅ Π΄ΠΎΠΉΠ΄ΡΡ Π΄ΠΎ
# ΡΠ²ΠΎΠ΅Π³ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°.
async_client = AsyncClient()
# Π£ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ Π΅ΡΡΡ ΠΎΠ±ΡΠ΅ΠΊΡ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ, Π² ΠΊΠΎΡΠΎΡΡΠΉ ΠΌΠΈΠ΄Π΄Π»Π²Π°ΡΠΈ ΠΌΠΎΠ³ΡΡ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ
# Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠ΅ Π΄Π°Π½Π½ΡΠ΅.
message.state.async_client = async_client
await call_next(message, bot)
# ΠΠΎΡΠ»Π΅ Π²ΡΠ·ΠΎΠ²Π° `call_next` Π²ΡΠΏΠΎΠ»Π½ΡΠ΅ΡΡΡ ΠΊΠΎΠ΄, ΠΊΠΎΠ³Π΄Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΆΠ΅
# Π·Π°Π²Π΅ΡΡΠΈΠ» ΡΠ²ΠΎΡ ΡΠ°Π±ΠΎΡΡ.
await async_client.aclose()
@collector.command(
"/fetch-resource",
description="Fetch resource from passed URL",
middlewares=[custom_api_client_middleware],
)
async def fetch_resource_handler(message: IncomingMessage, bot: Bot) -> None:
async_client = message.state.async_client
response = await async_client.get(message.argument)
print(response.status_code)
(ΠΡΠΎΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΈΡΠΊΠ»ΡΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΊ pybotx
)
from uuid import UUID, uuid4
from pybotx import *
ADMIN_HUIDS = (UUID("123e4567-e89b-12d3-a456-426614174000"),)
async def request_id_middleware(
message: IncomingMessage,
bot: Bot,
call_next: IncomingMessageHandlerFunc,
) -> None:
message.state.request_id = uuid4()
await call_next(message, bot)
async def ensure_admin_middleware(
message: IncomingMessage,
bot: Bot,
call_next: IncomingMessageHandlerFunc,
) -> None:
if message.sender.huid not in ADMIN_HUIDS:
await bot.answer_message("You are not admin")
return
await call_next(message, bot)
# ΠΠ»Ρ ΡΠΎΠ³ΠΎ ΡΡΠΎΠ±Ρ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ Π½ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΊΠΎΠΌΠ°Π½Π΄Ρ,
# Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ ΠΊΠ»Π°ΡΡΠ° `HandlerCollector`.
# ΠΠΎΠ·ΠΆΠ΅ ΡΡΠΎΡ ΡΠ±ΠΎΡΡΠΈΠΊ Π±ΡΠ΄Π΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ ΠΏΡΠΈ ΡΠΎΠ·Π΄Π°Π½ΠΈΠΈ Π±ΠΎΡΠ°.
main_collector = HandlerCollector(middlewares=[request_id_middleware])
# Π£ ΡΠ±ΠΎΡΡΠΈΠΊΠΎΠ² (ΠΊΠ°ΠΊ Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²), ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½ΡΠ΅ ΠΌΠΈΠ΄Π΄Π»Π²Π°ΡΠΈ.
# ΠΠ½ΠΈ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ ΠΏΡΠΈΠΌΠ΅Π½ΡΡΡΡΡ ΠΊΠΎ Π²ΡΠ΅ΠΌ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠ°ΠΌ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΡΠ±ΠΎΡΡΠΈΠΊΠ°.
admin_collector = HandlerCollector(middlewares=[ensure_admin_middleware])
# Π‘Π±ΠΎΡΡΠΈΠΊΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π²ΠΊΠ»ΡΡΠ°ΡΡ Π΄ΡΡΠ³ Π² Π΄ΡΡΠ³Π°. Π Π΄Π°Π½Π½ΠΎΠΌ ΠΏΡΠΈΠΌΠ΅ΡΠ΅ Ρ
# `admin_collector` Π±ΡΠ΄ΡΡ Π΄Π²Π΅ ΠΌΠΈΠ΄Π΄Π»Π²Π°ΡΠΈ. ΠΠ΅ΡΠ²Π°Ρ - Π΅Π³ΠΎ ΡΠΎΠ±ΡΡΠ²Π΅Π½Π½Π°Ρ,
# Π²ΡΠΎΡΠ°Ρ - ΠΏΠΎΠ»ΡΡΠ΅Π½Π½Π°Ρ ΠΏΡΠΈ Π²ΠΊΠ»ΡΡΠ΅Π½ΠΈΠΈ Π² `main_collector`.
main_collector.include(admin_collector)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from uuid import UUID
from pybotx import *
collector = HandlerCollector()
@collector.command("/answer", description="Answer to sender")
async def answer_to_sender_handler(message: IncomingMessage, bot: Bot) -> None:
# Π’.ΠΊ. Π½Π°ΠΌ ΠΈΠ·Π²Π΅ΡΡΠ½ΠΎ, ΠΎΡΠΊΡΠ΄Π° ΠΏΡΠΈΡΠ»ΠΎ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠ΅, Ρ `pybotx` Π΅ΡΡΡ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΡΠΉ
# ΠΊΠΎΠ½ΡΠ΅ΠΊΡΡ Π΄Π»Ρ ΠΎΡΠΏΡΠ°Π²ΠΊΠΈ ΠΎΡΠ²Π΅ΡΠ°.
await bot.answer_message("Text")
@collector.command("/send", description="Send message to specified chat")
async def send_message_handler(message: IncomingMessage, bot: Bot) -> None:
try:
chat_id = UUID(message.argument)
except ValueError:
await bot.answer_message("Invalid chat id")
return
# Π Π΄Π°Π½Π½ΠΎΠΌ ΡΠ»ΡΡΠ°Π΅ Π½Π°Ρ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΡΠ΅Ρ Π½Π΅ ΠΎΡΠ²Π΅Ρ, Π° ΠΎΡΠΏΡΠ°Π²ΠΊΠ° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ
# Π² Π΄ΡΡΠ³ΠΎΠΉ ΡΠ°Ρ. Π§Π°Ρ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΡΡΡΠ΅ΡΡΠ²ΠΎΠ²Π°ΡΡ ΠΈ Π±ΠΎΡ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ Π² Π½ΡΠΌ.
try:
await bot.send_message(
bot_id=message.bot.id,
chat_id=chat_id,
body="Text",
)
except Exception as exc:
await bot.answer_message(f"Error: {exc}")
return
await bot.answer_message("Message was send")
@collector.command("/prebuild-answer", description="Answer with prebuild message")
async def prebuild_answer_handler(message: IncomingMessage, bot: Bot) -> None:
# Π‘ ΠΏΠΎΠΌΠΎΡΡΡ OutgoingMessage ΠΌΠΎΠΆΠ½ΠΎ Π²ΡΠ½ΠΎΡΠΈΡΡ Π»ΠΎΠ³ΠΈΠΊΡ
# ΡΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½ΠΈΡ ΠΎΡΠ²Π΅ΡΠΎΠ² Π² Π΄ΡΡΠ³ΠΈΠ΅ ΠΌΠΎΠ΄ΡΠ»ΠΈ.
answer = OutgoingMessage(
bot_id=message.bot.id,
chat_id=message.chat.id,
body="Text",
)
await bot.send(message=answer)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.command("/bubbles", description="Send buttons")
async def bubbles_handler(message: IncomingMessage, bot: Bot) -> None:
# ΠΡΠ»ΠΈ Π²Π°ΠΌ Π½ΡΠΆΠ½Π° ΠΊΠ»Π°Π²ΠΈΠ°ΡΡΡΠ° ΠΏΠΎΠ΄ ΠΏΠΎΠ»Π΅ΠΌ Π΄Π»Ρ Π²Π²ΠΎΠ΄Π° ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ,
# ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ `KeyboardMarkup`. ΠΡΠΎΡ ΠΊΠ»Π°ΡΡ ΠΈΠΌΠ΅Π΅Ρ ΡΠ΅ ΠΆΠ΅ ΠΌΠ΅ΡΠΎΠ΄Ρ,
# ΡΡΠΎ ΠΈ `BubbleMarkup`.
bubbles = BubbleMarkup()
bubbles.add_button(
command="/choose",
label="Red",
data={"pill": "red"},
background_color="#FF0000",
)
bubbles.add_button(
command="/choose",
label="Blue",
data={"pill": "blue"},
background_color="#0000FF",
new_row=False,
)
# Π ΠΊΠ½ΠΎΠΏΠΊΡ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ ΡΡΡΠ»ΠΊΡ Π½Π° ΡΠ΅ΡΡΡΡ,
# Π΄Π»Ρ ΡΡΠΎΠ³ΠΎ Π½ΡΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡΡ url Π² Π°ΡΠ³ΡΠΌΠ΅Π½Ρ `link`, Π° `command` ΠΎΡΡΠ°Π²ΠΈΡΡ ΠΏΡΡΡΡΠΌ,
# `alert` Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΡΡΡ Π² ΠΎΠΊΠ½ΠΎ ΠΏΠΎΠ΄ΡΠ²Π΅ΡΠΆΠ΄Π΅Π½ΠΈΡ ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅Ρ
ΠΎΠ΄Π΅ ΠΏΠΎ ΡΡΡΠ»ΠΊΠ΅.
bubbles.add_button(
label="Bubble with link",
alert="alert text",
link="https://example.com",
)
await bot.answer_message(
"The time has come to make a choice, Mr. Anderson:",
bubbles=bubbles,
)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.command("/send-contact", description="Send author's contact")
async def send_contact_handler(message: IncomingMessage, bot: Bot) -> None:
contact = MentionBuilder.contact(message.sender.huid)
await bot.answer_message(f"Author is {contact}")
@collector.command("/echo-contacts", description="Send back recieved contacts")
async def echo_contact_handler(message: IncomingMessage, bot: Bot) -> None:
if not (contacts := message.mentions.contacts):
await bot.answer_message("Please send at least one contact")
return
answer = ", ".join(map(str, contacts))
await bot.answer_message(answer)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from aiofiles.tempfile import NamedTemporaryFile
from pybotx import *
collector = HandlerCollector()
@collector.command("/send-file", description="Send file")
async def send_file_handler(message: IncomingMessage, bot: Bot) -> None:
# ΠΠ»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ ΡΠ°ΠΉΠ»Π° ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ file-like object
# Ρ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΊΠΎΠΉ Π°ΡΠΈΠ½Ρ
ΡΠΎΠ½Π½ΡΡ
ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΉ.
async with NamedTemporaryFile("wb+") as async_buffer:
await async_buffer.write(b"Hello, world!\n")
await async_buffer.seek(0)
file = await OutgoingAttachment.from_async_buffer(async_buffer, "test.txt")
await bot.answer_message("Attached file", file=file)
@collector.command("/echo-file", description="Echo file")
async def echo_file_handler(message: IncomingMessage, bot: Bot) -> None:
if not (attached_file := message.file):
await bot.answer_message("Attached file is required")
return
await bot.answer_message("", file=attached_file)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.command("/increment", description="Self-updating widget")
async def increment_handler(message: IncomingMessage, bot: Bot) -> None:
if message.source_sync_id: # ID ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ Π±ΡΠ»Π° Π½Π°ΠΆΠ°ΡΠ° ΠΊΠ½ΠΎΠΏΠΊΠ°.
current_value = message.data["current_value"]
next_value = current_value + 1
else:
current_value = 0
next_value = 1
answer_text = f"Counter: {current_value}"
bubbles = BubbleMarkup()
bubbles.add_button(
command="/increment",
label="+",
data={"current_value": next_value},
)
if message.source_sync_id:
await bot.edit_message(
bot_id=message.bot.id,
sync_id=message.source_sync_id,
body=answer_text,
bubbles=bubbles,
)
else:
await bot.answer_message(answer_text, bubbles=bubbles)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.command("/deleted-message", description="Self-deleted message")
async def deleted_message_handler(message: IncomingMessage, bot: Bot) -> None:
if message.source_sync_id: # ID ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΡ, Π² ΠΊΠΎΡΠΎΡΠΎΠΌ Π±ΡΠ»Π° Π½Π°ΠΆΠ°ΡΠ° ΠΊΠ½ΠΎΠΏΠΊΠ°.
await bot.delete_message(
bot_id=message.bot.id,
sync_id=message.source_sync_id,
)
return
bubbles = BubbleMarkup()
bubbles.add_button(
command="/deleted-message",
label="Delete",
)
await bot.answer_message("Self-deleted message", bubbles=bubbles)
(ΠΡΠΎΡ ΡΡΠ½ΠΊΡΠΈΠΎΠ½Π°Π» ΠΎΡΠ½ΠΎΡΠΈΡΡΡ ΠΈΡΠΊΠ»ΡΡΠΈΡΠ΅Π»ΡΠ½ΠΎ ΠΊ pybotx
)
from loguru import logger
from pybotx import *
async def internal_error_handler(
message: IncomingMessage,
bot: Bot,
exc: Exception,
) -> None:
logger.exception("Internal error:")
await bot.answer_message(
"**Error:** internal error, please contact your system administrator",
)
# ΠΠ»Ρ ΠΏΠ΅ΡΠ΅Ρ
Π²Π°ΡΠ° ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ ΡΡΡΠ΅ΡΡΠ²ΡΡΡ ΡΠΏΠ΅ΡΠΈΠ°Π»ΡΠ½ΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ.
# ΠΠΎΡ ΠΏΡΠΈΠ½ΠΈΠΌΠ°Π΅Ρ ΡΠ»ΠΎΠ²Π°ΡΡ ΠΈΠ· ΡΠΈΠΏΠΎΠ² ΠΈΡΠΊΠ»ΡΡΠ΅Π½ΠΈΠΉ ΠΈ ΠΈΡ
ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ².
bot = Bot(
collectors=[],
bot_accounts=[],
exception_handlers={Exception: internal_error_handler},
)
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.command("/create-group-chat", description="Create group chat")
async def create_group_chat_handler(message: IncomingMessage, bot: Bot) -> None:
if not (contacts := message.mentions.contacts):
await bot.answer_message("Please send at least one contact")
return
try:
chat_id = await bot.create_chat(
bot_id=message.bot.id,
name="New group chat",
chat_type=ChatTypes.GROUP_CHAT,
huids=[contact.entity_id for contact in contacts],
)
except (ChatCreationProhibitedError, ChatCreationError) as exc:
await bot.answer_message(str(exc))
return
chat_mention = MentionBuilder.chat(chat_id)
await bot.answer_message(f"Chat created: {chat_mention}")
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
import dataclasses
from pybotx import *
collector = HandlerCollector()
@collector.command("/my-info", description="Get info of current user")
async def search_user_handler(message: IncomingMessage, bot: Bot) -> None:
try:
user_info = await bot.search_user_by_huid(
bot_id=message.bot.id,
huid=message.sender.huid,
)
except UserNotFoundError: # ΠΡΠ»ΠΈ ΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΠ΅Π»Ρ ΠΈ Π±ΠΎΡ Π½Π°Ρ
ΠΎΠ΄ΡΡΡΡ Π½Π° ΡΠ°Π·Π½ΡΡ
CTS
await bot.answer_message("User not found. Maybe you are on a different cts.")
return
await bot.answer_message(f"Your info:\n{dataclasses.asdict(user_info)}\n")
(ΠΏΠΎΠ΄ΡΠΎΠ±Π½ΠΎΠ΅ ΠΎΠΏΠΈΡΠ°Π½ΠΈΠ΅ ΡΡΠ½ΠΊΡΠΈΠΈ)
from pybotx import *
collector = HandlerCollector()
@collector.command("/get_users_list", description="Get a list of users")
async def users_list_handler(message: IncomingMessage, bot: Bot) -> None:
async with bot.users_as_csv(
bot_id=message.bot.id,
cts_user=True,
unregistered=False,
botx=False,
) as users:
async for user in users:
print(user)