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

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

maxbot-chatbot-library β€” это Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ для создания ΠΌΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΡƒΠ΅ΠΌΡ‹Ρ… Π±ΠΎΡ‚ΠΎΠ² для MAX Bot API Π½Π° языкС Go. ΠŸΠΎΡΡ‚Ρ€ΠΎΠ΅Π½Π½Π°Ρ Π½Π° основС maxbot-api-client-go. Π­Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° прСдоставляСт чистый ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€, автоматичСскоС ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… ΠΈ Π½Π°Π΄Π΅ΠΆΠ½Ρ‹ΠΉ ΠΌΠ΅Π½Π΅Π΄ΠΆΠ΅Ρ€ состояний (FSM) для построСния ΠΌΠ½ΠΎΠ³ΠΎΡˆΠ°Π³ΠΎΠ²Ρ‹Ρ… Π΄ΠΈΠ°Π»ΠΎΠ³ΠΎΠ²Ρ‹Ρ… сцСнариСв.

API#

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

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

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

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

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

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

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

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

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

ЛицСнзия#

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

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

go version

НС Π·Π°Π±ΡƒΠ΄ΡŒΡ‚Π΅ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΌΠΎΠ΄ΡƒΠ»ΡŒ:

go mod init my-bot-project

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

go get github.com/green-api/maxbot-chatbot-library

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

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

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

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

    myBot, err := bot.NewBot(client.Config{
            BaseURL: "https://platform-api.max.ru",
            Token:   "YOUR_BOT_TOKEN",              // Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π° ваш Ρ‚ΠΎΠΊΠ΅Π½
            RateLimiter: 25,
            Timeout: 30 * time.Second,
        })

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

Π§Ρ‚ΠΎΠ±Ρ‹ Π½Π°Ρ‡Π°Ρ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π°Ρ‚ΡŒ ΠΈ ΠΎΡ‚Π²Π΅Ρ‡Π°Ρ‚ΡŒ Π½Π° сообщСния, настройтС Π±ΠΎΡ‚Π°, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ваш BaseURL ΠΈ Token, Π·Π°Ρ‚Π΅ΠΌ запуститС ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ опроса.

    package main

    import (
        "context"
        "time"

        "github.com/green-api/maxbot-api-client-go/pkg/client"
        "github.com/green-api/maxbot-chatbot-library/pkg/bot"
    )

    func main() {
        myBot, err := bot.NewBot(client.Config{
            BaseURL: "https://platform-api.max.ru",
            Token:   "YOUR_BOT_TOKEN",              // Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π° ваш Ρ‚ΠΎΠΊΠ΅Π½
            RateLimiter: 25,
            Timeout: 30 * time.Second,
        })

        if err != nil {
            panic(err)
        }

        myBot.StartPolling(context.Background())
    }

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

ВстроСнный ΠΌΠ°Ρ€ΡˆΡ€ΡƒΡ‚ΠΈΠ·Π°Ρ‚ΠΎΡ€ ΡƒΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ ΠΊΠΎΠΌΠ°Π½Π΄, ΠΎΠ±Ρ€Π°Ρ‚Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² ΠΈ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΠΉ.

  package main

  import (
    "context"

    "github.com/green-api/maxbot-api-client-go/pkg/client"
    "github.com/green-api/maxbot-api-client-go/pkg/models"

    "github.com/green-api/maxbot-chatbot-library/pkg/bot"
    n "github.com/green-api/maxbot-chatbot-library/pkg/notification"
  )

  func main() {
    myBot, err := bot.NewBot(client.Config{
      BaseURL: "https://platform-api.max.ru",
      Token:   "YOUR_BOT_TOKEN",              // Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π° ваш Ρ‚ΠΎΠΊΠ΅Π½
      RateLimiter: 25,
        Timeout: 30 * time.Second,
    })

    myBot.Router.Command("/start", func(n *n.Notification) {
      n.Reply("Hello! Welcome to the MAX Bot.")
    })

    myBot.Router.Register(models.TypeMessageCreated, func(n *n.Notification) {
      text, err := n.Text()
      if err == nil && text == "ping" {
        n.Reply("pong", m.Format(""))
      }
    })

    myBot.Router.Callback("accept_rules_payload", func(n *n.Notification) {
      n.Reply("*Thank you for accepting the rules!*", m.Markdown)
    })

    myBot.StartPolling(context.Background())
  }

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

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

    package main

    import (
      "context"
      "fmt"

      "github.com/green-api/maxbot-api-client-go/pkg/models"
      "github.com/green-api/maxbot-chatbot-library/pkg/bot"
      n "github.com/green-api/maxbot-chatbot-library/pkg/notification"
      "github.com/green-api/maxbot-chatbot-library/pkg/state"
    )

    func main() {
      myBot, err := bot.NewBot(client.Config{
        BaseURL: "https://platform-api.max.ru",
        Token:   "YOUR_BOT_TOKEN",              // Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π° ваш Ρ‚ΠΎΠΊΠ΅Π½
        RateLimiter: 25,
          Timeout: 30 * time.Second,
      })

      myBot.StateManager = state.NewMapStateManager(map[string]any{
        "step": "start",
      })

      myBot.StateManager.SetStartScene(RegistrationScene{})

      myBot.Router.Register(models.TypeMessageCreated, func(n *n.Notification) {
        currentScene := n.GetCurrentScene()
        if currentScene != nil {
          currentScene.Start(n)
        }
      })

      myBot.StartPolling(context.Background())
    }

    type RegistrationScene struct{}

    func (s RegistrationScene) Start(n *n.Notification) {
      text, _ := n.Text()

      if text == "/start" {
        n.Reply("Let's register! What is your *login*?", m.Markdown)
        return 
      }

      if len(text) >= 4 {
        n.StateManager.UpdateStateData(n.StateId, map[string]any{"login": text})

        n.Reply(fmt.Sprintf("**Login** `%s` accepted. Now enter your **password**:", text), m.Markdown)
        n.ActivateNextScene(PasswordScene{})
      } else {
        n.Reply("Login must be **at least 4 characters long**.", m.Markdown)
      }
    }

    type PasswordScene struct{}

    func (s PasswordScene) Start(n *n.Notification) {
      password, _ := n.Text()

      stateData := n.StateManager.GetStateData(n.StateId)
      login := stateData["login"].(string)

      n.Reply(fmt.Sprintf("Success! Profile created.\nLogin: `%s`\nPass: `%s`", login, password), m.Markdown)

      n.ActivateNextScene(RegistrationScene{})
    }

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

ΠžΠ±ΠΎΠ»ΠΎΡ‡ΠΊΠ° Notification прСдоставляСт ΡƒΠ΄ΠΎΠ±Π½Ρ‹Π΅ ΠΌΠ΅Ρ‚ΠΎΠ΄Ρ‹ для ΠΎΡ‚Π²Π΅Ρ‚Π° тСкстом ΠΈ влоТСниями.

    myBot.Router.Command("/photo", func(n *n.Notification) {
        n.ReplyWithMedia(
        "Check out this image!", 
        m.Markdown, 
        "https://example.com/image.png"
      )
    })

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

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

    func main() {
      myBot, err := bot.NewBot(client.Config{
        BaseURL: "https://platform-api.max.ru",
        Token:   "YOUR_BOT_TOKEN",              // Π—Π°ΠΌΠ΅Π½ΠΈΡ‚Π΅ Π½Π° ваш Ρ‚ΠΎΠΊΠ΅Π½
        RateLimiter: 25,
          Timeout: 30 * time.Second,
      })
      if err != nil {
        log.Error().Msgf("Bot initialization error: %v", err)
      }

      myBot.StateManager = state.NewMapStateManager(map[string]any{})

      myBot.Router.Register(models.TypeMessageCreated, func(n *c.Notification) {
        text, err := n.Text()
        if err != nil {
          return
        }
        n.Reply("Echo: " + text, "")
      })

      ctx, cancel := context.WithCancel(context.Background())
      defer cancel()

      go myBot.StartPolling(ctx)

      stop := make(chan os.Signal, 1)
      signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
      <-stop

      log.Info().Msg("Bot shutting down...")
    }

ЛицСнзия#

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