ΠŸΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΡŽ

Python Ρ‡Π°Ρ‚-Π±ΠΎΡ‚ для ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ API MAX#

maxbot-chatbot-python β€” это асинхронный Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ для создания ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Ρ… Π±ΠΎΡ‚ΠΎΠ² для MAX BOT API Π½Π° языкС Python.

ΠŸΠΎΡΡ‚Ρ€ΠΎΠ΅Π½Π½Π°Ρ Π½Π° основС maxbot_api_client_python, эта Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° прСдоставляСт чистый ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€, автоматичСскоС ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ (Long Polling) ΠΈ Π½Π°Π΄Π΅ΠΆΠ½Ρ‹ΠΉ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ состояний (FSM) для построСния ΠΌΠ½ΠΎΠ³ΠΎΡˆΠ°Π³ΠΎΠ²Ρ‹Ρ… Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²Ρ‹Ρ… сцСнариСв.

API#

ДокумСнтация ΠΊ REST API MAX находится ΠΏΠΎ ссылкС. Π‘ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° являСтся ΠΎΠ±Ρ‘Ρ€Ρ‚ΠΊΠΎΠΉ ΠΊ REST API, поэтому докумСнтация ΠΏΠΎ ссылкС Π²Ρ‹ΡˆΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΠΌΠ° ΠΈ ΠΊ самой Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ΅.

Авторизация#

Для использования Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ потрСбуСтся ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚ΠΎΠΊΠ΅Π½ Π±ΠΎΡ‚Π° Π² консоли Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ° MAX API.

Π‘ΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΠ΅#

Как ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ своСго Π±ΠΎΡ‚Π°#

ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡ ΠΊΠΎΠΌΠ°Π½Π΄ ΠΈ сообщСний#

Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ состояниями ΠΈ сцСны#

ΠžΡ‚Π²Π΅Ρ‚ с ΠΌΠ΅Π΄ΠΈΠ°Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ#

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ эхо-Π±ΠΎΡ‚Π°#

ЛицСнзия#

Как ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ своСго Π±ΠΎΡ‚Π°#

Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ Ρƒ вас установлСна вСрсия Python Π½Π΅ Π½ΠΈΠΆΠ΅ 3.12:

python --version  

Установка Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ:

pip install maxbot-chatbot-python

Как ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚#

Для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π±ΠΎΡ‚Π° Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ main адрСс ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹ MaxBot, MAX token, Π° Ρ‚Π°ΠΊ ΠΆΠ΅ Π·Π°Π΄Π°Ρ‚ΡŒ значСния для RateLimiter ΠΈ Timeout.

ΠŸΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ ΠΊΠΎΠ½Ρ„ΠΈΠ³ΡƒΡ€Π°Ρ†ΠΈΠΈ:

  • BaseURL - Π‘Π°Π·ΠΎΠ²Ρ‹ΠΉ URL-адрСс сСрвСров ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡ‹ MaxBot. ВсС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ API Π±ΡƒΠ΄ΡƒΡ‚ ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΏΠΎ этому ΠΊΠΎΡ€Π½Π΅Π²ΠΎΠΌΡƒ адрСсу. ΠΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ адрСс ΡƒΠΊΠ°Π·Π°Π½ Π² ΠΎΡ„ΠΈΡ†ΠΈΠ°Π»ΡŒΠ½ΠΎΠΉ Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΠΈ.
  • Token - Π£Π½ΠΈΠΊΠ°Π»ΡŒΠ½Ρ‹ΠΉ сСкрСтный ΠΊΠ»ΡŽΡ‡ Π°Π²Ρ‚ΠΎΡ€ΠΈΠ·Π°Ρ†ΠΈΠΈ (API-ΠΊΠ»ΡŽΡ‡) вашСго Π±ΠΎΡ‚Π°. ΠŸΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π΅Π³ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π² Π»ΠΈΡ‡Π½ΠΎΠΌ ΠΊΠ°Π±ΠΈΠ½Π΅Ρ‚Π΅ послС рСгистрации ΠΈΠ»ΠΈ создании Π±ΠΎΡ‚Π° Π½Π° ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅ business.max.ru. Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΏΠ΅Ρ€Π΅Π΄ Π½Π°Ρ‡Π°Π»ΠΎΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Ρ‚ΠΎΠΊΠ΅Π½.
  • RateLimiter - ВстроСнный ΠΎΠ³Ρ€Π°Π½ΠΈΡ‡ΠΈΡ‚Π΅Π»ΡŒ частоты запросов. Он ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΠΈΡ€ΡƒΠ΅Ρ‚ количСство исходящих запросов Π² сСкунду (RPS), защищая Π±ΠΎΡ‚Π° ΠΎΡ‚ Π±Π»ΠΎΠΊΠΈΡ€ΠΎΠ²ΠΊΠΈ со стороны сСрвСра Π·Π° ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ΅Π½ΠΈΠ΅ Π»ΠΈΠΌΠΈΡ‚ΠΎΠ². Π Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ β€” Π½Π΅ ΠΌΠ΅Π½Π΅Π΅ 25, Π½ΠΎ Π½Π΅ Π±ΠΎΠ»Π΅Π΅ 30.
  • Timeout - МаксимальноС врСмя оТидания ΠΎΡ‚Π²Π΅Ρ‚Π° ΠΎΡ‚ сСрвСра (Π² сСкундах). Если сСрвСр Π½Π΅ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΡ‚ Π² Ρ‚Π΅Ρ‡Π΅Π½ΠΈΠ΅ этого Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, запрос Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ с ошибкой. ΠžΠΏΡ‚ΠΈΠΌΠ°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ β€” 30 сСкунд.

    async def main():
        cfg = Config(
            base_url="https://platform-api.max.ru/", 
            token="YOUR_BOT_TOKEN", 
            ratelimiter=25,
            timeout=35
        )

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π±ΠΎΡ‚Π°#

    import asyncio

    from maxbot_api_client_python import API, Config
    from maxbot_chatbot_python import Bot, MapStateManager

    async def main():
        cfg = Config(
            base_url="https://platform-api.max.ru/", 
            token="YOUR_BOT_TOKEN", 
            ratelimiter=25,
            timeout=35
        )

        async with API(cfg) as api_client:
            bot = Bot(api_client)
            bot.state_manager = MapStateManager(init_data={})

            polling_task = asyncio.create_task(bot.start_polling())

            try:
                await polling_task
            except asyncio.CancelledError:
                pass

    if __name__ == "__main__":
        try:
            asyncio.run(main())
        except KeyboardInterrupt:
            print("Bot stopped by user")

ΠœΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ†ΠΈΡ ΠΊΠΎΠΌΠ°Π½Π΄ ΠΈ сообщСний#

ВстроСнный ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€ (Router) позволяСт Π»Π΅Π³ΠΊΠΎ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ (Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‰ΠΈΠ΅ΡΡ со слэша /) ΠΈ наТатия Π½Π° inline-ΠΊΠ½ΠΎΠΏΠΊΠΈ (коллбэки).

    @bot.router.command("/start")
    async def start_command(notification):
        await notification.reply("Hello! Welcome to the MAX Bot.")

    @bot.router.register("message_created")
    async def ping_handler(notification):
        try:
            if notification.text() == "ping":
                await notification.reply("pong")
        except ValueError:
            pass

    @bot.router.callback("accept_rules")
    async def rules_callback(notification):
        await notification.reply("*Thank you for accepting the rules!*", format_type="markdown")
        await notification.answer_callback("Success!")

Π£ΠΏΡ€Π°Π²Π»Π΅Π½ΠΈΠ΅ состояниями ΠΈ сцСны#

Для слоТных ΠΌΠ½ΠΎΠ³ΠΎΡˆΠ°Π³ΠΎΠ²Ρ‹Ρ… Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ² (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, рСгистрация ΠΈΠ»ΠΈ Π°Π½ΠΊΠ΅Ρ‚ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅) ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ ΠœΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ состояний (StateManager) ΠΈ Π‘Ρ†Π΅Π½Ρ‹ (Scene).

    from maxbot_chatbot_python import Scene

    class RegistrationScene(Scene):
        async def start(self, notification):
            try:
                text = notification.text()
            except ValueError:
                return

            if text == "/start":
                await notification.reply("Let's register! What is your *login*?", "markdown")
                return 

            if len(text) >= 4:
                if notification.state_manager:
                    notification.state_manager.update_state_data(notification.state_id, {"login": text})

                await notification.reply(f"**Login** `{text}` accepted. Now enter your **password**:", "markdown")
                notification.activate_next_scene(PasswordScene())
            else:
                await notification.reply("Login must be **at least 4 characters long**.", "markdown")

    class PasswordScene(Scene):
        async def start(self, notification):
            try:
                password = notification.text()
            except ValueError:
                return

            state_data = notification.state_manager.get_state_data(notification.state_id)
            login = state_data.get("login", "Unknown")

            await notification.reply(f"Success! Profile created.\nLogin: `{login}`\nPass: `{password}`", "markdown")

            notification.activate_next_scene(RegistrationScene())

    @bot.router.register("message_created")
    async def fsm_handler(notification):
        if not notification.state_manager.get(notification.state_id):
            notification.state_manager.create(notification.state_id)

        current_scene = notification.get_current_scene()
        if current_scene:
            await current_scene.start(notification)

ΠžΡ‚Π²Π΅Ρ‚ с ΠΌΠ΅Π΄ΠΈΠ°Ρ„Π°ΠΉΠ»Π°ΠΌΠΈ#

ΠžΠ±Π΅Ρ€Ρ‚ΠΊΠ° Notification содСрТит Π³ΠΎΡ‚ΠΎΠ²Ρ‹Π΅ асинхронныС ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ Ρ„Π°ΠΉΠ»ΠΎΠ², Π³Π΅ΠΎΠ»ΠΎΠΊΠ°Ρ†ΠΈΠΉ, стикСров ΠΈ статусов Π½Π°Π±ΠΎΡ€Π° тСкста.

    @bot.router.command("/photo")
    async def send_photo(notification):
        await notification.show_action("sending_photo")

        await notification.reply_with_media(
            text="Check out this image!", 
            format_type="markdown", 
            file_source="https://storage.yandexcloud.net/sw-prod-03-test/ChatBot/corgi.jpg"
        )

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ эхо-Π±ΠΎΡ‚Π°#

Для ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Ρ‚ΠΎΠ³ΠΎ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с MAX BOT API, ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅ΠΌ Π²Π°ΠΌ ΠΊΠΎΠ΄ эхо Ρ‡Π°Ρ‚-Π±ΠΎΡ‚Π°:

    import asyncio

    from maxbot_api_client_python import API, Config
    from maxbot_chatbot_python import Bot, MapStateManager

    async def main():
        cfg = Config(
            base_url="https://platform-api.max.ru/", 
            token="YOUR_BOT_TOKEN",
            ratelimiter=25
        )

        async with API(cfg) as api_client:
            bot = Bot(api_client)
            bot.state_manager = MapStateManager(init_data={})

            @bot.router.register("message_created")
            async def echo_handler(notification):
                try:
                    text = notification.text()
                    await notification.reply(f"**Echo:** {text}", "markdown")
                except Exception as e:
                    print(f"Error handling message: {e}")

            polling_task = asyncio.create_task(bot.start_polling())

            try:
                await polling_task
            except asyncio.CancelledError:
                pass

    if __name__ == "__main__":
        try:
            asyncio.run(main())
        except KeyboardInterrupt:
            print("Bot stopped by user (KeyboardInterrupt)")

ЛицСнзия#

Π›ΠΈΡ†Π΅Π½Π·ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ Π² соотвСтствии с MIT.