Skip to content

K1rL3s/maxo

maxo - асинхронный Python-Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ для Π±ΠΎΡ‚ΠΎΠ² мСссСндТСра MAX (max.ru)

maxo - асинхронный Python-Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ для Π±ΠΎΡ‚ΠΎΠ² MAX (max.ru)

License Status PyPI Downloads GitHub Repo stars Supported python versions Docs Tests Coverage

Асинхронный Python-Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π±ΠΎΡ‚ΠΎΠ² Π² MAX

ДокумСнтация

Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ основан Π½Π° aiogram
maxo/dialogs сдСлано из aiogram_dialog
maxo/transport/webhook сдСлано из aiogram-webhook

Установка

Π§Π΅Ρ€Π΅Π· pip:

pip install maxo

Π’ pyproject.toml:

[project]
dependencies = [
    "maxo",
]

ΠžΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΠΈ

  • ΠΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΠΎΡΡ‚ΡŒ Π½Π° Π±Π°Π·Π΅ aiohttp ΠΈ unihttp (asyncio, PEP 492)
  • 100% ΠΏΠΎΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ Ρ‚ΠΈΠΏΠ°ΠΌΠΈ, adaptix для Π²Π°Π»ΠΈΠ΄Π°Ρ†ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ…
  • Π ΠΎΡƒΡ‚Π΅Ρ€Ρ‹, Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Ρ‹, ΠΌΠΈΠ»Π΄Π²Π°Ρ€ΠΈ
  • ВстроСнная машина состояний (FSM) ΠΈ Π΄ΠΈΠ°Π»ΠΎΠ³ΠΈ ΠΏΠΎΠ²Π΅Ρ€Ρ… Π½ΠΈΡ…
  • ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° Π»ΠΎΠ½Π³-ΠΏΠΎΠ»Π»ΠΈΠ½Π³Π° ΠΈ Π²Π΅Π±Ρ…ΡƒΠΊΠΎΠ² Ρ‡Π΅Ρ€Π΅Π· aiohttp ΠΈ fastapi
  • Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΠΈ с dishka ΠΈ magic_filter
  • АвтогСнСрация ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ², Ρ‚ΠΈΠΏΠΎΠ² ΠΈ Π°ΠΏΠ΄Π΅ΠΉΡ‚ΠΎΠ² ΠΏΠΎ ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ

Быстрый старт

Π‘ΠΎΠ»ΡŒΡˆΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ² Π² ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…

Π­Ρ…ΠΎ-Π±ΠΎΡ‚

from maxo import Bot, Dispatcher
from maxo.routing.updates import MessageCreated
from maxo.transport.long_polling import LongPolling
from maxo.utils.facades import MessageCreatedFacade

bot = Bot("TOKEN")
dispatcher = Dispatcher()

@dispatcher.message_created()
async def echo_handler(update: MessageCreated, facade: MessageCreatedFacade) -> None:
    text = update.message.body.text or "ВСкста Π½Π΅Ρ‚"
    await facade.answer_text(text)

LongPolling(dispatcher).run(bot)

ΠšΠΎΠΌΠ°Π½Π΄Ρ‹

from maxo import Bot, Dispatcher
from maxo.routing.filters import Command, CommandObject, CommandStart
from maxo.routing.updates import MessageCreated
from maxo.transport.long_polling import LongPolling
from maxo.utils.facades import MessageCreatedFacade

bot = Bot("TOKEN")
dispatcher = Dispatcher()

@dispatcher.message_created(CommandStart())
# ΠΈΠ»ΠΈ @dispatcher.message_created(Command("start"))
async def start_handler(
    message: MessageCreated,
    command: CommandObject,
    facade: MessageCreatedFacade,
) -> None:
    await facade.answer_text(f"ΠŸΡ€ΠΈΠ²Π΅Ρ‚! Π― Π±ΠΎΡ‚. Π”ΠΈΠΏΠ»ΠΈΠ½ΠΊ: {command.args}")

LongPolling(dispatcher).run(bot)

ΠšΠ»Π°Π²ΠΈΠ°Ρ‚ΡƒΡ€Ρ‹

from magic_filter import F

from maxo import Bot, Dispatcher
from maxo.integrations.magic_filter import MagicFilter
from maxo.routing.filters import CommandStart
from maxo.routing.updates import MessageCallback, MessageCreated
from maxo.transport.long_polling import LongPolling
from maxo.utils.builders import KeyboardBuilder
from maxo.utils.facades import MessageCallbackFacade, MessageCreatedFacade

bot = Bot("TOKEN")
dispatcher = Dispatcher()

@dispatcher.message_created(CommandStart())
async def start_handler(message: MessageCreated, facade: MessageCreatedFacade) -> None:
    keyboard = (
        KeyboardBuilder()
        .add_callback(
            text="Колбэк кнопка",
            payload="callback_payload",
        )
        .add_message(text="ВСкстовая ΠΊΠ½ΠΎΠΏΠΊΠ°")
        .add_link(
            text="Maxo",
            url="https://github.com/K1rL3s/maxo",
        )
        .adjust(1, repeat=True)
        .build()
    )
    await facade.answer_text("ΠšΠ½ΠΎΠΏΠΎΡ‡ΠΊΠΈ:", keyboard=keyboard)

@dispatcher.message_callback(MagicFilter(F.payload == "callback_payload"))
async def button_handler(
    callback: MessageCallback,
    facade: MessageCallbackFacade,
) -> None:
    await facade.callback_answer("Π’Ρ‹ Π½Π°ΠΆΠ°Π»ΠΈ Π½Π° ΠΊΠ½ΠΎΠΏΠΊΡƒ!")

LongPolling(dispatcher).run(bot)

Π’Π΅Π±Ρ…ΡƒΠΊ

import logging
import os

from aiohttp import web

from maxo import Bot, Dispatcher, Router
from maxo.enums import TextFormat
from maxo.routing.updates import BotStarted, MessageCreated
from maxo.routing.utils import collect_used_updates
from maxo.transport.webhook.adapters.aiohttp import AiohttpWebAdapter
from maxo.transport.webhook.engines import SimpleEngine, WebhookEngine
from maxo.transport.webhook.routing import StaticRouting
from maxo.transport.webhook.security import Security, StaticSecretToken
from maxo.utils.facades import BotStartedFacade, MessageCreatedFacade

bot = Bot(os.environ["TOKEN"])
router = Router()

@router.bot_started()
async def start_handler(bot_started: BotStarted, facade: BotStartedFacade) -> None:
    await facade.send_message(text=f"ΠŸΡ€ΠΈΠ²Π΅Ρ‚ ΠΈΠ· Π²Π΅Π±Ρ…ΡƒΠΊΠ°, {bot_started.user.first_name}!")

@router.message_created()
async def echo_handler(message: MessageCreated, facade: MessageCreatedFacade) -> None:
    await facade.answer_text(
        text=message.message.body.html_text,
        format=TextFormat.HTML,
    )

@router.after_startup()
async def on_startup(dispatcher: Dispatcher, webhook_engine: WebhookEngine) -> None:
    await webhook_engine.set_webhook(update_types=collect_used_updates(dispatcher))

def main() -> None:
    dispatcher = Dispatcher()
    dispatcher.include(router)

    engine = SimpleEngine(
        dispatcher,
        bot,
        web_adapter=AiohttpWebAdapter(),
        routing=StaticRouting(url="https://example.com/webhook"),
        security=Security(secret_token=StaticSecretToken("pepa_pig")),
    )
    app = web.Application()
    engine.register(app)

    web.run_app(app, host="127.0.0.1", port=8080)

if __name__ == "__main__":
    logging.basicConfig(level=logging.DEBUG)
    main()

FAQ

Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ MAX?

MAX - российский мСссСндТСр. Π£ Π½Π΅Π³ΠΎ Π΅ΡΡ‚ΡŒ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΠΎΠ΅ Bot API, для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΈ создан maxo.

Π§Π΅ΠΌ maxo отличаСтся ΠΎΡ‚ aiogram?

maxo - ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ для Π±ΠΎΡ‚ΠΎΠ² MAX, Π½ΠΎ интСрфСйс Π½Π°ΠΌΠ΅Ρ€Π΅Π½Π½ΠΎ Π±Π»ΠΈΠ·ΠΎΠΊ ΠΊ aiogram, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π±Ρ‹Π» максимально Π±Π΅Π·Π±ΠΎΠ»Π΅Π·Π½Π΅Π½Π½Ρ‹ΠΌ. Π”ΠΈΠ°Π»ΠΎΠ³ΠΈ (maxo.dialogs) ΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½Ρ‹ ΠΈΠ· aiogram_dialog, Π²Π΅Π±Ρ…ΡƒΠΊΠΈ (maxo.transport.webhook) - ΠΈΠ· aiogram-webhook.

ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ Π»ΠΈ maxo Π²Π΅Π±Ρ…ΡƒΠΊΠΈ?

Π”Π°. ΠŸΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ΡΡ ΠΈ long-polling, ΠΈ webhook Ρ‡Π΅Ρ€Π΅Π· aiohttp ΠΈΠ»ΠΈ fastapi - см. ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π²Ρ‹ΡˆΠ΅.

Какой Python Π½ΡƒΠΆΠ΅Π½?

Python 3.12, 3.13 ΠΈΠ»ΠΈ 3.14.

Π“Π΄Π΅ Π²Π·ΡΡ‚ΡŒ Ρ‚ΠΎΠΊΠ΅Π½ Π±ΠΎΡ‚Π° MAX?

На ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅ для ΠΏΠ°Ρ€Ρ‚Π½Ρ‘Ρ€ΠΎΠ².

Как Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ FSM?

FSM встроСна Π² maxo - Π΅ΡΡ‚ΡŒ MemoryStorage ΠΈΠ· ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΈ ΠΈ ΠΎΠΏΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ΅ Ρ…Ρ€Π°Π½ΠΈΠ»ΠΈΡ‰Π΅ Π² Redis (maxo[redis]). ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½ΠΎΡΡ‚ΠΈ - Π² Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.

Бвязь

Если Ρƒ вас Π΅ΡΡ‚ΡŒ вопросы, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΈΡ… Π² Π’Π΅Π»Π΅Π³Ρ€Π°ΠΌΠ΅ @maxo_py ΠΈΠ»ΠΈ МаксС

About

🐍 Π€Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π±ΠΎΡ‚ΠΎΠ² Π² max.ru

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Sponsor this project

Contributors

Languages