Jak zbudować bota WhatsApp do list zadań przy użyciu API Programowalnych Rozmów firmy Bird

Ptak

5 lut 2020

WhatsApp

1 min read

Jak zbudować bota WhatsApp do list zadań przy użyciu API Programowalnych Rozmów firmy Bird

Kluczowe Wnioski

    • Bird’s Programmable Conversations API łączy WhatsApp, Messenger i SMS w jedną warstwę komunikacyjną, upraszczając rozwój botów wielokanałowych.

    • Możesz szybko stworzyć prototyp bota do listy zadań na WhatsApp za pomocą webhooks i prostych żądań POST.

    • Narzędzia takie jak ngrok pozwalają na udostępnianie lokalnego serwera do testowania webhooków bez skomplikowanej konfiguracji hostingu.

    • API obsługuje konwersacje w wielu kanałach, umożliwiając jedną bazę logiki dla WhatsApp, WeChat i innych aplikacji.

    • Użyj punktu końcowego archiveConversation do zamykania konwersacji lub „tematów”, co jest idealne do wsparcia technicznego lub śledzenia przepływu pracy.

    • Logika bota może zarządzać współbieżnymi konwersacjami bezpiecznie w pamięci za pomocą prostej struktury danych.

    • Ten sam obsługiwacz webhooków działa we wszystkich kanałach—Bird automatycznie przekierowuje odpowiedzi na podstawie ID początkowej konwersacji.

Q&A Highlights

  • Jak trudne jest zbudowanie bota WhatsApp używając Bird’s API?

    To zaskakująco łatwe. Za pomocą webhooka i kilku wywołań API możesz zbudować funkcjonalnego bota, który w ciągu kilku minut będzie czytał i odpowiadał na wiadomości.

  • Czy potrzebuję specjalnej konfiguracji, aby odbierać wiadomości?

    Tak — bot musi być dostępny z internetu. Narzędzia takie jak ngrok pomagają stworzyć bezpieczny tunel z twojej lokalnej maszyny.

  • Czy mogę używać tej samej bazy kodu dla różnych aplikacji do przesyłania wiadomości?

    Absolutnie. Conversations API abstrakcyjnie przedstawia kanały, dzięki czemu Twój bot może działać na WhatsApp, WeChat lub Messenger przy użyciu identycznej logiki.

  • Jak zamknąć lub zresetować wątek czatu?

    Wyślij żądanie PATCH do punktu końcowego rozmowy z odpowiednim statusem, aby ją zarchiwizować. Każda nowa wiadomość automatycznie otwiera nową rozmowę.

  • Gdzie mogę znaleźć przykładowy kod?

    A: Pełna działająca wersja demonstracyjna — Wabot on GitHub — pokazuje implementację obsługi wiadomości, współbieżności i archiwizacji.

Bird niedawno wprowadził na rynek Programmable Conversations. Pozwala to firmom na integrację platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, z ich systemami — za pomocą jednego API.

Chciałem to wypróbować, więc stworzyłem bot do listy rzeczy do zrobienia na WhatsAppie, bo kto nie potrzebuje zautomatyzowanej listy zadań do pomocy w organizacji dnia? Może to brzmieć skomplikowanie, ale w rzeczywistości było to łatwe, i chciałbym ci o tym opowiedzieć.

Teraz, pracuję w MessageBird, więc mogłem po prostu zanurzyć się i zacząć budować. Jeśli spróbujesz tego, będziesz musiał złożyć wniosek o wczesny dostęp. Ale gdy już będziesz miał skonfigurowany kanał WhatsApp, możesz zalogować się do Dashboard na stronie MessageBird i rozpocząć.

Bird niedawno wprowadził na rynek Programmable Conversations. Pozwala to firmom na integrację platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, z ich systemami — za pomocą jednego API.

Chciałem to wypróbować, więc stworzyłem bot do listy rzeczy do zrobienia na WhatsAppie, bo kto nie potrzebuje zautomatyzowanej listy zadań do pomocy w organizacji dnia? Może to brzmieć skomplikowanie, ale w rzeczywistości było to łatwe, i chciałbym ci o tym opowiedzieć.

Teraz, pracuję w MessageBird, więc mogłem po prostu zanurzyć się i zacząć budować. Jeśli spróbujesz tego, będziesz musiał złożyć wniosek o wczesny dostęp. Ale gdy już będziesz miał skonfigurowany kanał WhatsApp, możesz zalogować się do Dashboard na stronie MessageBird i rozpocząć.

Bird niedawno wprowadził na rynek Programmable Conversations. Pozwala to firmom na integrację platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, z ich systemami — za pomocą jednego API.

Chciałem to wypróbować, więc stworzyłem bot do listy rzeczy do zrobienia na WhatsAppie, bo kto nie potrzebuje zautomatyzowanej listy zadań do pomocy w organizacji dnia? Może to brzmieć skomplikowanie, ale w rzeczywistości było to łatwe, i chciałbym ci o tym opowiedzieć.

Teraz, pracuję w MessageBird, więc mogłem po prostu zanurzyć się i zacząć budować. Jeśli spróbujesz tego, będziesz musiał złożyć wniosek o wczesny dostęp. Ale gdy już będziesz miał skonfigurowany kanał WhatsApp, możesz zalogować się do Dashboard na stronie MessageBird i rozpocząć.

Konfigurowanie środowiska bota WhatsApp

Pierwszą rzeczą, jaką zrobiłem, było przeczytanie docs. Dowiedziałem się, że aby otrzymywać wiadomości od bota, muszę użyć webhooka. Oznaczało to, że mój bot musiałby być dostępny z internetu. Tworząc takie API, ważne jest przestrzeganie najlepszych praktyk wersjonowania API dla utrzymania. Ponieważ dopiero zaczynałem to kodować, postanowiłem użyć ngrok. Tworzy tunel od internetu publicznego do twojego lokalnego portu 5007. Aktywuj!

ngrok http 5007 -region eu -subdomain todobot

Pierwszą rzeczą, jaką zrobiłem, było przeczytanie docs. Dowiedziałem się, że aby otrzymywać wiadomości od bota, muszę użyć webhooka. Oznaczało to, że mój bot musiałby być dostępny z internetu. Tworząc takie API, ważne jest przestrzeganie najlepszych praktyk wersjonowania API dla utrzymania. Ponieważ dopiero zaczynałem to kodować, postanowiłem użyć ngrok. Tworzy tunel od internetu publicznego do twojego lokalnego portu 5007. Aktywuj!

ngrok http 5007 -region eu -subdomain todobot

Pierwszą rzeczą, jaką zrobiłem, było przeczytanie docs. Dowiedziałem się, że aby otrzymywać wiadomości od bota, muszę użyć webhooka. Oznaczało to, że mój bot musiałby być dostępny z internetu. Tworząc takie API, ważne jest przestrzeganie najlepszych praktyk wersjonowania API dla utrzymania. Ponieważ dopiero zaczynałem to kodować, postanowiłem użyć ngrok. Tworzy tunel od internetu publicznego do twojego lokalnego portu 5007. Aktywuj!

ngrok http 5007 -region eu -subdomain todobot

Tworzenie webhooka i łączenie z Bird

Następnie musiałem wykonać wywołanie do Programmable Conversations API, aby utworzyć webhook. Jest to POST do https://conversations.messagebird.com/v1/webhooks i wygląda to tak:

func main() {// define the webhook json payload
  wh := struct {
         Events    []string `json:"events"`
         ChannelID string   `json:"channelId"`
         URL       string   `json:"url"`
  } {
    // we would like to be notified on the URL
    URL:       "https://todobot.eu.ngrok.io/create-hook",
    // whenever a message gets created
    Events:    []string{"message.created"},
    // on the WhatsApp channel with ID
    ChannelID: "23a780701b8849f7b974d8620a89a279",
  }
  
  // encode the payload to json
  var b bytes.Buffer
  err := json.NewEncoder(&b).Encode(&wh)
  if err != nil {
    panic(err)
  }
  
  // create the http request and set authorization header
  req, err := http.NewRequest("POST", "https://conversations.messagebird.com/v1/webhooks", &b)
  req.Header.Set("Authorization", "AccessKey todo-your-access-key")
  req.Header.Set("Content-Type", "application/json") // fire the http request
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
         panic(err)
  }
  defer resp.Body.Close()// is everything ok?
  body, _ := ioutil.ReadAll(resp.Body)
  if resp.StatusCode >= http.StatusBadRequest {
    panic(fmt.Errorf("Bad response code from api when trying to create webhook: %s. Body: %s", resp.Status, string(body)))
  } else {
    log.Println("All good. response body: ", string(body))
  }
}


Słodko. Teraz Conversations API wykonywa będzie żądania POST do:

https://todobot.eu.ngrok.io/create-hook za każdym razem, gdy nowa wiadomość zostanie utworzona na kanale WhatsApp, który ustawiłeś wcześniej.

Tak wygląda payload webhook:

{
  "conversation":{
    "id":"55c66895c22a40e39a8e6bd321ec192e",
    "contactId":"db4dd5087fb343738e968a323f640576",
    "status":"active",
    "createdDatetime":"2018-08-17T10:14:14Z",
    "updatedDatetime":"2018-08-17T14:30:31.915292912Z",
    "lastReceivedDatetime":"2018-08-17T14:30:31.898389294Z"
  },
  "message":{
    "id":"ddb150149e2c4036a48f581544e22cfe",
    "conversationId":"55c66895c22a40e39a8e6bd321ec192e",
    "channelId":"23a780701b8849f7b974d8620a89a279",
    "status":"received",
    "type":"text",
    "direction":"received",
    "content":{
      "text":"add buy milk"
    },
    "createdDatetime":"2018-08-17T14:30:31.898389294Z",
    "updatedDatetime":"2018-08-17T14:30:31.915292912Z"
  },
  "type":"message.created"
}


Chcemy odpowiedzieć na te wiadomości. Zacznijmy od ich powtarzania, co ty na to?

// define the structs where we'll parse the webhook payload into
type whPayload struct {
  Conversation conversation `json:"conversation"`
  Message      message      `json:"message"`
  Type         string       `json:"type"`
}

type message struct {
  ID        string  `json:"id"`
  Direction string  `json:"direction"`
  Type      string  `json:"type"`
  Content   content `json:"content"`
}

type content struct {
  Text string `json:"text"`
}

type conversation struct {
  ID string `json:"id"`
}

func main() {
  http.HandleFunc("/create-hook", createHookHandler)
  log.Fatal(http.ListenAndServe(*httpListenAddress, nil))
}
// createHookHandler is an http handler that will handle webhook requests
func createHookHandler(w http.ResponseWriter, r *http.Request) {
  // parse the incoming json payload
  whp := &whPayload{}
  err := json.NewDecoder(r.Body).Decode(whp)
  if err != nil {
    log.Println("Err: got weird body on the webhook")
    w.WriteHeader(http.StatusInternalServerError)
    fmt.Fprintf(w, "Internal Server Error")
    return
  } 
  if whp.Message.Direction != "received" {
    // you will get *all* messages on the webhook. Even the ones this bot sends to the channel. We don't want to answer those.
    fmt.Fprintf(w, "ok")
    return
  } // echo: respond what we get
  err = respond(whp.Conversation.ID, whp.Message.Content.Text)
  
  if err != nil {
    log.Println("Err: ", err)
    w.WriteHeader(http.StatusInternalServerError)
    fmt.Fprintf(w, "Internal Server Error")return
  }
  w.WriteHeader(http.StatusOK)
  fmt.Fprintf(w, "ok")
}

Następnie musiałem wykonać wywołanie do Programmable Conversations API, aby utworzyć webhook. Jest to POST do https://conversations.messagebird.com/v1/webhooks i wygląda to tak:

func main() {// define the webhook json payload
  wh := struct {
         Events    []string `json:"events"`
         ChannelID string   `json:"channelId"`
         URL       string   `json:"url"`
  } {
    // we would like to be notified on the URL
    URL:       "https://todobot.eu.ngrok.io/create-hook",
    // whenever a message gets created
    Events:    []string{"message.created"},
    // on the WhatsApp channel with ID
    ChannelID: "23a780701b8849f7b974d8620a89a279",
  }
  
  // encode the payload to json
  var b bytes.Buffer
  err := json.NewEncoder(&b).Encode(&wh)
  if err != nil {
    panic(err)
  }
  
  // create the http request and set authorization header
  req, err := http.NewRequest("POST", "https://conversations.messagebird.com/v1/webhooks", &b)
  req.Header.Set("Authorization", "AccessKey todo-your-access-key")
  req.Header.Set("Content-Type", "application/json") // fire the http request
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
         panic(err)
  }
  defer resp.Body.Close()// is everything ok?
  body, _ := ioutil.ReadAll(resp.Body)
  if resp.StatusCode >= http.StatusBadRequest {
    panic(fmt.Errorf("Bad response code from api when trying to create webhook: %s. Body: %s", resp.Status, string(body)))
  } else {
    log.Println("All good. response body: ", string(body))
  }
}


Słodko. Teraz Conversations API wykonywa będzie żądania POST do:

https://todobot.eu.ngrok.io/create-hook za każdym razem, gdy nowa wiadomość zostanie utworzona na kanale WhatsApp, który ustawiłeś wcześniej.

Tak wygląda payload webhook:

{
  "conversation":{
    "id":"55c66895c22a40e39a8e6bd321ec192e",
    "contactId":"db4dd5087fb343738e968a323f640576",
    "status":"active",
    "createdDatetime":"2018-08-17T10:14:14Z",
    "updatedDatetime":"2018-08-17T14:30:31.915292912Z",
    "lastReceivedDatetime":"2018-08-17T14:30:31.898389294Z"
  },
  "message":{
    "id":"ddb150149e2c4036a48f581544e22cfe",
    "conversationId":"55c66895c22a40e39a8e6bd321ec192e",
    "channelId":"23a780701b8849f7b974d8620a89a279",
    "status":"received",
    "type":"text",
    "direction":"received",
    "content":{
      "text":"add buy milk"
    },
    "createdDatetime":"2018-08-17T14:30:31.898389294Z",
    "updatedDatetime":"2018-08-17T14:30:31.915292912Z"
  },
  "type":"message.created"
}


Chcemy odpowiedzieć na te wiadomości. Zacznijmy od ich powtarzania, co ty na to?

// define the structs where we'll parse the webhook payload into
type whPayload struct {
  Conversation conversation `json:"conversation"`
  Message      message      `json:"message"`
  Type         string       `json:"type"`
}

type message struct {
  ID        string  `json:"id"`
  Direction string  `json:"direction"`
  Type      string  `json:"type"`
  Content   content `json:"content"`
}

type content struct {
  Text string `json:"text"`
}

type conversation struct {
  ID string `json:"id"`
}

func main() {
  http.HandleFunc("/create-hook", createHookHandler)
  log.Fatal(http.ListenAndServe(*httpListenAddress, nil))
}
// createHookHandler is an http handler that will handle webhook requests
func createHookHandler(w http.ResponseWriter, r *http.Request) {
  // parse the incoming json payload
  whp := &whPayload{}
  err := json.NewDecoder(r.Body).Decode(whp)
  if err != nil {
    log.Println("Err: got weird body on the webhook")
    w.WriteHeader(http.StatusInternalServerError)
    fmt.Fprintf(w, "Internal Server Error")
    return
  } 
  if whp.Message.Direction != "received" {
    // you will get *all* messages on the webhook. Even the ones this bot sends to the channel. We don't want to answer those.
    fmt.Fprintf(w, "ok")
    return
  } // echo: respond what we get
  err = respond(whp.Conversation.ID, whp.Message.Content.Text)
  
  if err != nil {
    log.Println("Err: ", err)
    w.WriteHeader(http.StatusInternalServerError)
    fmt.Fprintf(w, "Internal Server Error")return
  }
  w.WriteHeader(http.StatusOK)
  fmt.Fprintf(w, "ok")
}

Następnie musiałem wykonać wywołanie do Programmable Conversations API, aby utworzyć webhook. Jest to POST do https://conversations.messagebird.com/v1/webhooks i wygląda to tak:

func main() {// define the webhook json payload
  wh := struct {
         Events    []string `json:"events"`
         ChannelID string   `json:"channelId"`
         URL       string   `json:"url"`
  } {
    // we would like to be notified on the URL
    URL:       "https://todobot.eu.ngrok.io/create-hook",
    // whenever a message gets created
    Events:    []string{"message.created"},
    // on the WhatsApp channel with ID
    ChannelID: "23a780701b8849f7b974d8620a89a279",
  }
  
  // encode the payload to json
  var b bytes.Buffer
  err := json.NewEncoder(&b).Encode(&wh)
  if err != nil {
    panic(err)
  }
  
  // create the http request and set authorization header
  req, err := http.NewRequest("POST", "https://conversations.messagebird.com/v1/webhooks", &b)
  req.Header.Set("Authorization", "AccessKey todo-your-access-key")
  req.Header.Set("Content-Type", "application/json") // fire the http request
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
         panic(err)
  }
  defer resp.Body.Close()// is everything ok?
  body, _ := ioutil.ReadAll(resp.Body)
  if resp.StatusCode >= http.StatusBadRequest {
    panic(fmt.Errorf("Bad response code from api when trying to create webhook: %s. Body: %s", resp.Status, string(body)))
  } else {
    log.Println("All good. response body: ", string(body))
  }
}


Słodko. Teraz Conversations API wykonywa będzie żądania POST do:

https://todobot.eu.ngrok.io/create-hook za każdym razem, gdy nowa wiadomość zostanie utworzona na kanale WhatsApp, który ustawiłeś wcześniej.

Tak wygląda payload webhook:

{
  "conversation":{
    "id":"55c66895c22a40e39a8e6bd321ec192e",
    "contactId":"db4dd5087fb343738e968a323f640576",
    "status":"active",
    "createdDatetime":"2018-08-17T10:14:14Z",
    "updatedDatetime":"2018-08-17T14:30:31.915292912Z",
    "lastReceivedDatetime":"2018-08-17T14:30:31.898389294Z"
  },
  "message":{
    "id":"ddb150149e2c4036a48f581544e22cfe",
    "conversationId":"55c66895c22a40e39a8e6bd321ec192e",
    "channelId":"23a780701b8849f7b974d8620a89a279",
    "status":"received",
    "type":"text",
    "direction":"received",
    "content":{
      "text":"add buy milk"
    },
    "createdDatetime":"2018-08-17T14:30:31.898389294Z",
    "updatedDatetime":"2018-08-17T14:30:31.915292912Z"
  },
  "type":"message.created"
}


Chcemy odpowiedzieć na te wiadomości. Zacznijmy od ich powtarzania, co ty na to?

// define the structs where we'll parse the webhook payload into
type whPayload struct {
  Conversation conversation `json:"conversation"`
  Message      message      `json:"message"`
  Type         string       `json:"type"`
}

type message struct {
  ID        string  `json:"id"`
  Direction string  `json:"direction"`
  Type      string  `json:"type"`
  Content   content `json:"content"`
}

type content struct {
  Text string `json:"text"`
}

type conversation struct {
  ID string `json:"id"`
}

func main() {
  http.HandleFunc("/create-hook", createHookHandler)
  log.Fatal(http.ListenAndServe(*httpListenAddress, nil))
}
// createHookHandler is an http handler that will handle webhook requests
func createHookHandler(w http.ResponseWriter, r *http.Request) {
  // parse the incoming json payload
  whp := &whPayload{}
  err := json.NewDecoder(r.Body).Decode(whp)
  if err != nil {
    log.Println("Err: got weird body on the webhook")
    w.WriteHeader(http.StatusInternalServerError)
    fmt.Fprintf(w, "Internal Server Error")
    return
  } 
  if whp.Message.Direction != "received" {
    // you will get *all* messages on the webhook. Even the ones this bot sends to the channel. We don't want to answer those.
    fmt.Fprintf(w, "ok")
    return
  } // echo: respond what we get
  err = respond(whp.Conversation.ID, whp.Message.Content.Text)
  
  if err != nil {
    log.Println("Err: ", err)
    w.WriteHeader(http.StatusInternalServerError)
    fmt.Fprintf(w, "Internal Server Error")return
  }
  w.WriteHeader(http.StatusOK)
  fmt.Fprintf(w, "ok")
}

Wysyłanie odpowiedzi i obsługa wiadomości

Teraz, część interesująca. Wykonaj żądanie POST do:

https://conversations.messagebird.com/v1/conversations/<conversationID>/messages aby odpowiedzieć na żądanie.

func respond(conversationID, responseBody string) error {
  u := fmt.Sprintf("https://conversations.messagebird.com/v1/conversations/%s/messages", conversationID)msg := message{
  Content: content{
    Text: responseBody,
  },
  Type: "text",
  }
  var b bytes.Buffer
  err := json.NewEncoder(&b).Encode(&msg)
  if err != nil {
    return fmt.Errorf("Error encoding buffer: %v", err)
  }
  req, err := http.NewRequest("POST", u.String(), &b)
  req.Header.Set("Authorization", "AccessKey todo-your-access-key")
  req.Header.Set("Content-Type", "application/json")client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    return err
  }
  defer resp.Body.Close()body, _ := ioutil.ReadAll(resp.Body)
  if resp.StatusCode != http.StatusCreated {
    return fmt.Errorf("Bad response code from api when trying to create message: %s. Body: %s", resp.Status, string(body))
  }
  log.Println("All good. Response body: ", string(body))
  return nil
}

Oto wszystko, czego potrzebujesz, aby stworzyć bota zachowującego się jak 5-letni człowiek.


Oto dlaczego używanie Bird's Conversations API sprawia, że tworzenie botów na WhatsApp staje się szybkie i skalowalne:

Funkcja

Co rozwiązuje

Ujednolicony ID konwersacji

Utrzymuj jednolity wątek w aplikacjach takich jak WhatsApp, WeChat, Messenger

Pojedyncze API dla wszystkich kanałów

Wykorzystaj ponownie logikę bota bez przepisywania dla każdej platformy

Automatyzacja oparta na Webhookach

Szybkie przetwarzanie odpowiedzi bez sondowania

Archiwizacja + ponowne otwieranie tematów

Organizuj historię wsparcia i przepływy pracy

Struktura bezpieczna dla współbieżności

Obsługuj wiele czatów naraz w sposób niezawodny


Teraz zróbmy krok w kierunku stworzenia całej listy rzeczy do zrobienia. Najpierw zmodyfikuj funkcję createHookHandler tak, aby wywoływała nową funkcję handleMessage zamiast respond.

func createHookHandler(w http.ResponseWriter, r *http.Request) {
  ...
  err = handleMessage(whp)
  ...
}


handle będzie w prosty sposób analizować wiadomości, wykonywać pewne zadania i wybierać odpowiedź. Spójrzmy na komendę „add”:

func handleMessage(whp *whPayload) error {
  // every conversation has a todo list
  list := manager.fetch(whp.Conversation.ID)
  // parse the command from the message body: it's the first word
  text := whp.Message.Content.Text
  text = regexp.MustCompile(" +").ReplaceAllString(text, " ")
  parts := strings.Split(text, " ")
  command := strings.ToLower(parts[0])
  // default message
  responseBody := "I don't understand. Type 'help' to get help."
  switch command {
  ...
  case "add":
    if len(parts) < 2 {
           return respond(whp.Conversation.ID, "err... the 'add' command needs a second param: the todo item you want to save. Something like 'add buy milk'.")
    }
    // get the item from the message body
    item := strings.Join(parts[1:], " ")list.add(item)
    responseBody = "added."
  ...
  return respond(whp.Conversation.ID, responseBody)
}

Tu ustawiamy: list := manager.fetch(whp.Conversation.ID). Zasadniczo, „manager” to bezpieczna dla współbieżności mapa, która mapuje IDs konwersacji na listy rzeczy do zrobienia.

Lista rzeczy do zrobienia to bezpieczna dla współbieżności lista stringów. Wszystko w pamięci!

Teraz, część interesująca. Wykonaj żądanie POST do:

https://conversations.messagebird.com/v1/conversations/<conversationID>/messages aby odpowiedzieć na żądanie.

func respond(conversationID, responseBody string) error {
  u := fmt.Sprintf("https://conversations.messagebird.com/v1/conversations/%s/messages", conversationID)msg := message{
  Content: content{
    Text: responseBody,
  },
  Type: "text",
  }
  var b bytes.Buffer
  err := json.NewEncoder(&b).Encode(&msg)
  if err != nil {
    return fmt.Errorf("Error encoding buffer: %v", err)
  }
  req, err := http.NewRequest("POST", u.String(), &b)
  req.Header.Set("Authorization", "AccessKey todo-your-access-key")
  req.Header.Set("Content-Type", "application/json")client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    return err
  }
  defer resp.Body.Close()body, _ := ioutil.ReadAll(resp.Body)
  if resp.StatusCode != http.StatusCreated {
    return fmt.Errorf("Bad response code from api when trying to create message: %s. Body: %s", resp.Status, string(body))
  }
  log.Println("All good. Response body: ", string(body))
  return nil
}

Oto wszystko, czego potrzebujesz, aby stworzyć bota zachowującego się jak 5-letni człowiek.


Oto dlaczego używanie Bird's Conversations API sprawia, że tworzenie botów na WhatsApp staje się szybkie i skalowalne:

Funkcja

Co rozwiązuje

Ujednolicony ID konwersacji

Utrzymuj jednolity wątek w aplikacjach takich jak WhatsApp, WeChat, Messenger

Pojedyncze API dla wszystkich kanałów

Wykorzystaj ponownie logikę bota bez przepisywania dla każdej platformy

Automatyzacja oparta na Webhookach

Szybkie przetwarzanie odpowiedzi bez sondowania

Archiwizacja + ponowne otwieranie tematów

Organizuj historię wsparcia i przepływy pracy

Struktura bezpieczna dla współbieżności

Obsługuj wiele czatów naraz w sposób niezawodny


Teraz zróbmy krok w kierunku stworzenia całej listy rzeczy do zrobienia. Najpierw zmodyfikuj funkcję createHookHandler tak, aby wywoływała nową funkcję handleMessage zamiast respond.

func createHookHandler(w http.ResponseWriter, r *http.Request) {
  ...
  err = handleMessage(whp)
  ...
}


handle będzie w prosty sposób analizować wiadomości, wykonywać pewne zadania i wybierać odpowiedź. Spójrzmy na komendę „add”:

func handleMessage(whp *whPayload) error {
  // every conversation has a todo list
  list := manager.fetch(whp.Conversation.ID)
  // parse the command from the message body: it's the first word
  text := whp.Message.Content.Text
  text = regexp.MustCompile(" +").ReplaceAllString(text, " ")
  parts := strings.Split(text, " ")
  command := strings.ToLower(parts[0])
  // default message
  responseBody := "I don't understand. Type 'help' to get help."
  switch command {
  ...
  case "add":
    if len(parts) < 2 {
           return respond(whp.Conversation.ID, "err... the 'add' command needs a second param: the todo item you want to save. Something like 'add buy milk'.")
    }
    // get the item from the message body
    item := strings.Join(parts[1:], " ")list.add(item)
    responseBody = "added."
  ...
  return respond(whp.Conversation.ID, responseBody)
}

Tu ustawiamy: list := manager.fetch(whp.Conversation.ID). Zasadniczo, „manager” to bezpieczna dla współbieżności mapa, która mapuje IDs konwersacji na listy rzeczy do zrobienia.

Lista rzeczy do zrobienia to bezpieczna dla współbieżności lista stringów. Wszystko w pamięci!

Teraz, część interesująca. Wykonaj żądanie POST do:

https://conversations.messagebird.com/v1/conversations/<conversationID>/messages aby odpowiedzieć na żądanie.

func respond(conversationID, responseBody string) error {
  u := fmt.Sprintf("https://conversations.messagebird.com/v1/conversations/%s/messages", conversationID)msg := message{
  Content: content{
    Text: responseBody,
  },
  Type: "text",
  }
  var b bytes.Buffer
  err := json.NewEncoder(&b).Encode(&msg)
  if err != nil {
    return fmt.Errorf("Error encoding buffer: %v", err)
  }
  req, err := http.NewRequest("POST", u.String(), &b)
  req.Header.Set("Authorization", "AccessKey todo-your-access-key")
  req.Header.Set("Content-Type", "application/json")client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    return err
  }
  defer resp.Body.Close()body, _ := ioutil.ReadAll(resp.Body)
  if resp.StatusCode != http.StatusCreated {
    return fmt.Errorf("Bad response code from api when trying to create message: %s. Body: %s", resp.Status, string(body))
  }
  log.Println("All good. Response body: ", string(body))
  return nil
}

Oto wszystko, czego potrzebujesz, aby stworzyć bota zachowującego się jak 5-letni człowiek.


Oto dlaczego używanie Bird's Conversations API sprawia, że tworzenie botów na WhatsApp staje się szybkie i skalowalne:

Funkcja

Co rozwiązuje

Ujednolicony ID konwersacji

Utrzymuj jednolity wątek w aplikacjach takich jak WhatsApp, WeChat, Messenger

Pojedyncze API dla wszystkich kanałów

Wykorzystaj ponownie logikę bota bez przepisywania dla każdej platformy

Automatyzacja oparta na Webhookach

Szybkie przetwarzanie odpowiedzi bez sondowania

Archiwizacja + ponowne otwieranie tematów

Organizuj historię wsparcia i przepływy pracy

Struktura bezpieczna dla współbieżności

Obsługuj wiele czatów naraz w sposób niezawodny


Teraz zróbmy krok w kierunku stworzenia całej listy rzeczy do zrobienia. Najpierw zmodyfikuj funkcję createHookHandler tak, aby wywoływała nową funkcję handleMessage zamiast respond.

func createHookHandler(w http.ResponseWriter, r *http.Request) {
  ...
  err = handleMessage(whp)
  ...
}


handle będzie w prosty sposób analizować wiadomości, wykonywać pewne zadania i wybierać odpowiedź. Spójrzmy na komendę „add”:

func handleMessage(whp *whPayload) error {
  // every conversation has a todo list
  list := manager.fetch(whp.Conversation.ID)
  // parse the command from the message body: it's the first word
  text := whp.Message.Content.Text
  text = regexp.MustCompile(" +").ReplaceAllString(text, " ")
  parts := strings.Split(text, " ")
  command := strings.ToLower(parts[0])
  // default message
  responseBody := "I don't understand. Type 'help' to get help."
  switch command {
  ...
  case "add":
    if len(parts) < 2 {
           return respond(whp.Conversation.ID, "err... the 'add' command needs a second param: the todo item you want to save. Something like 'add buy milk'.")
    }
    // get the item from the message body
    item := strings.Join(parts[1:], " ")list.add(item)
    responseBody = "added."
  ...
  return respond(whp.Conversation.ID, responseBody)
}

Tu ustawiamy: list := manager.fetch(whp.Conversation.ID). Zasadniczo, „manager” to bezpieczna dla współbieżności mapa, która mapuje IDs konwersacji na listy rzeczy do zrobienia.

Lista rzeczy do zrobienia to bezpieczna dla współbieżności lista stringów. Wszystko w pamięci!

Archiwizowanie rozmów i skalowanie Twojego bota

Kolejna ważna rzecz! Możesz archiwizować rozmowy. W niektórych aplikacjach, takich jak CRM, ważne jest śledzenie niektórych interakcji — na przykład, aby śledzić efektywność pracowników obsługi klienta. Conversations API pozwala na archiwizację rozmowy, aby „zamknąć” temat. Jeśli użytkownik/klient wyśle kolejną wiadomość, Conversations API otworzy automatycznie nowy temat.

Zarządzanie cyklem życia rozmowy

Również. Wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim stanem w treści pozwala na archiwizację rozmowy z tym id. Robimy to za pomocą komendy „bye”:

case "bye":
  archiveConversation(whp.Conversation.ID)
  manager.close(whp.Conversation.ID)
  responseBody = "bye!"

archiveConversation wykona żądanie PATCH, a manager.close(whp.Conversation.ID) usunie rozmowę z listy zadań.

Ale hej, Programmable Conversations to rozwiązanie wielokanałowe. Co jeśli chciałbyś ponownie wykorzystać kod bota na innej platformie, takiej jak WeChat? To podejście wielokanałowe jest częścią strategii kierowania zapytań do tańszych kanałów. Jak byś to zrobił?

Po prostu stwórz nowy webhook, aby go skierować na ten kanał! Webhook, który wysyła żądania do tego samego adresu https://todobot.eu.ngrok.io/create-hook, którego używaliśmy dla WhatsApp!

To zadziała, ponieważ kod obsługi zawsze używa conversationID z ładunku webhook do odpowiadania na wiadomości, zamiast używać kodowanego na sztywno channelID. Conversations API MessageBird automatycznie określi kanał dla rozmowy, aby wysłać Twoją wiadomość.

Chcesz stworzyć własnego bota? Zobacz pełny kod na Githubie: Wabot na Github, poproś o wczesny dostęp do WhatsApp, odwiedzając stronę WhatsApp i klikając przycisk Kontakt z Sprzedażą, aby wypełnić formularz. Powodzenia w botowaniu!

Kolejna ważna rzecz! Możesz archiwizować rozmowy. W niektórych aplikacjach, takich jak CRM, ważne jest śledzenie niektórych interakcji — na przykład, aby śledzić efektywność pracowników obsługi klienta. Conversations API pozwala na archiwizację rozmowy, aby „zamknąć” temat. Jeśli użytkownik/klient wyśle kolejną wiadomość, Conversations API otworzy automatycznie nowy temat.

Zarządzanie cyklem życia rozmowy

Również. Wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim stanem w treści pozwala na archiwizację rozmowy z tym id. Robimy to za pomocą komendy „bye”:

case "bye":
  archiveConversation(whp.Conversation.ID)
  manager.close(whp.Conversation.ID)
  responseBody = "bye!"

archiveConversation wykona żądanie PATCH, a manager.close(whp.Conversation.ID) usunie rozmowę z listy zadań.

Ale hej, Programmable Conversations to rozwiązanie wielokanałowe. Co jeśli chciałbyś ponownie wykorzystać kod bota na innej platformie, takiej jak WeChat? To podejście wielokanałowe jest częścią strategii kierowania zapytań do tańszych kanałów. Jak byś to zrobił?

Po prostu stwórz nowy webhook, aby go skierować na ten kanał! Webhook, który wysyła żądania do tego samego adresu https://todobot.eu.ngrok.io/create-hook, którego używaliśmy dla WhatsApp!

To zadziała, ponieważ kod obsługi zawsze używa conversationID z ładunku webhook do odpowiadania na wiadomości, zamiast używać kodowanego na sztywno channelID. Conversations API MessageBird automatycznie określi kanał dla rozmowy, aby wysłać Twoją wiadomość.

Chcesz stworzyć własnego bota? Zobacz pełny kod na Githubie: Wabot na Github, poproś o wczesny dostęp do WhatsApp, odwiedzając stronę WhatsApp i klikając przycisk Kontakt z Sprzedażą, aby wypełnić formularz. Powodzenia w botowaniu!

Kolejna ważna rzecz! Możesz archiwizować rozmowy. W niektórych aplikacjach, takich jak CRM, ważne jest śledzenie niektórych interakcji — na przykład, aby śledzić efektywność pracowników obsługi klienta. Conversations API pozwala na archiwizację rozmowy, aby „zamknąć” temat. Jeśli użytkownik/klient wyśle kolejną wiadomość, Conversations API otworzy automatycznie nowy temat.

Zarządzanie cyklem życia rozmowy

Również. Wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim stanem w treści pozwala na archiwizację rozmowy z tym id. Robimy to za pomocą komendy „bye”:

case "bye":
  archiveConversation(whp.Conversation.ID)
  manager.close(whp.Conversation.ID)
  responseBody = "bye!"

archiveConversation wykona żądanie PATCH, a manager.close(whp.Conversation.ID) usunie rozmowę z listy zadań.

Ale hej, Programmable Conversations to rozwiązanie wielokanałowe. Co jeśli chciałbyś ponownie wykorzystać kod bota na innej platformie, takiej jak WeChat? To podejście wielokanałowe jest częścią strategii kierowania zapytań do tańszych kanałów. Jak byś to zrobił?

Po prostu stwórz nowy webhook, aby go skierować na ten kanał! Webhook, który wysyła żądania do tego samego adresu https://todobot.eu.ngrok.io/create-hook, którego używaliśmy dla WhatsApp!

To zadziała, ponieważ kod obsługi zawsze używa conversationID z ładunku webhook do odpowiadania na wiadomości, zamiast używać kodowanego na sztywno channelID. Conversations API MessageBird automatycznie określi kanał dla rozmowy, aby wysłać Twoją wiadomość.

Chcesz stworzyć własnego bota? Zobacz pełny kod na Githubie: Wabot na Github, poproś o wczesny dostęp do WhatsApp, odwiedzając stronę WhatsApp i klikając przycisk Kontakt z Sprzedażą, aby wypełnić formularz. Powodzenia w botowaniu!

Inne wiadomości

Czytaj więcej z tej kategorii

A person is standing at a desk while typing on a laptop.

Kompletna, natywna dla AI platforma, która rośnie wraz z Twoim biznesem.

A person is standing at a desk while typing on a laptop.

Kompletna, natywna dla AI platforma, która rośnie wraz z Twoim biznesem.