Jak zbudować bota WhatsApp do listy zadań korzystając z API Programowalnych Rozmów Bird'a

Ptak

5 lut 2020

WhatsApp

1 min read

Jak zbudować bota WhatsApp do listy zadań korzystając z API Programowalnych Rozmów Bird'a

Najważniejsze informacje

    • Programowalny API rozmów Bird łączy WhatsApp, Messengera i SMS-y w jedną warstwę komunikacyjną, upraszczając rozwój botów wielokanałowych.

    • Możesz szybko stworzyć prototyp bota do listy zadań WhatsApp, używając webhooków oraz prosty żądania POST.

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

    • API obsługuje rozmowy na wielu kanałach, umożliwiając jedną logikę dla WhatsApp, WeChat i innych aplikacji.

    • Użyj punktu końcowego archiveConversation, aby zamykać rozmowy lub „tematy”, idealne do śledzenia wsparcia lub workflow.

    • Logika bota może zarządzać równoległymi rozmowami bezpiecznie w pamięci przy użyciu prostej struktury danych.

    • Ten sam obsługiwacz webhook działa na różnych kanałach—Bird automatycznie kieruje odpowiedzi na podstawie identyfikatora rozmowy, z której pochodzą.

Podsumowanie pytań i odpowiedzi

  • Jak trudno jest zbudować bota WhatsApp za pomocą API Bird?

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

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

    Tak — bot musi być osiągalny z internetu. Narzędzia takie jak ngrok pomagają utworzyć bezpieczny tunel z twojej lokalnej maszyny.

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

    Absolutnie. API Rozmów abstrakcyjnie reprezentuje kanały, dzięki czemu twój bot może działać na WhatsApp, WeChat lub Messengerze, stosując identyczną logikę.

  • Jak mogę 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 dema — Wabot na GitHubie — pokazuje wdrożenie obsługi wiadomości, współbieżności i archiwizacji.

Bird niedawno uruchomił Programowalne Rozmowy. Umożliwia to firmom łączenie platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, z ich systemami - za pomocą jednego interfejsu API.

Chciałem to wypróbować, więc zbudowałem listę zadań w botie WhatsApp, ponieważ kto nie potrzebuje zautomatyzowanej listy zadań, aby pomóc zorganizować swój dzień? Może to brzmieć skomplikowanie, ale w rzeczywistości było to proste i chciałbym opowiedzieć Wam o tym.

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

Bird niedawno uruchomił Programowalne Rozmowy. Umożliwia to firmom łączenie platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, z ich systemami - za pomocą jednego interfejsu API.

Chciałem to wypróbować, więc zbudowałem listę zadań w botie WhatsApp, ponieważ kto nie potrzebuje zautomatyzowanej listy zadań, aby pomóc zorganizować swój dzień? Może to brzmieć skomplikowanie, ale w rzeczywistości było to proste i chciałbym opowiedzieć Wam o tym.

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

Bird niedawno uruchomił Programowalne Rozmowy. Umożliwia to firmom łączenie platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, z ich systemami - za pomocą jednego interfejsu API.

Chciałem to wypróbować, więc zbudowałem listę zadań w botie WhatsApp, ponieważ kto nie potrzebuje zautomatyzowanej listy zadań, aby pomóc zorganizować swój dzień? Może to brzmieć skomplikowanie, ale w rzeczywistości było to proste i chciałbym opowiedzieć Wam o tym.

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

Ustawianie środowiska bota WhatsApp

Pierwszą rzeczą, którą zrobiłem, było przeczytanie dokumentacji. Dowiedziałem się, że aby otrzymywać wiadomości od bota, muszę użyć webhooka. Oznaczało to, że mój bot musi być dostępny z internetu. Podczas budowania interfejsów API, takich jak ten, ważne jest przestrzeganie najlepszych praktyk wersjonowania API dla utrzymania. Ponieważ dopiero zaczynałem kodować, postanowiłem użyć ngrok. Tworzy tunel z publicznego internetu do Twojego lokalnego portu 5007. Zaczynamy!

ngrok http 5007 -region eu -subdomain todobot

Pierwszą rzeczą, którą zrobiłem, było przeczytanie dokumentacji. Dowiedziałem się, że aby otrzymywać wiadomości od bota, muszę użyć webhooka. Oznaczało to, że mój bot musi być dostępny z internetu. Podczas budowania interfejsów API, takich jak ten, ważne jest przestrzeganie najlepszych praktyk wersjonowania API dla utrzymania. Ponieważ dopiero zaczynałem kodować, postanowiłem użyć ngrok. Tworzy tunel z publicznego internetu do Twojego lokalnego portu 5007. Zaczynamy!

ngrok http 5007 -region eu -subdomain todobot

Pierwszą rzeczą, którą zrobiłem, było przeczytanie dokumentacji. Dowiedziałem się, że aby otrzymywać wiadomości od bota, muszę użyć webhooka. Oznaczało to, że mój bot musi być dostępny z internetu. Podczas budowania interfejsów API, takich jak ten, ważne jest przestrzeganie najlepszych praktyk wersjonowania API dla utrzymania. Ponieważ dopiero zaczynałem kodować, postanowiłem użyć ngrok. Tworzy tunel z publicznego internetu do Twojego lokalnego portu 5007. Zaczynamy!

ngrok http 5007 -region eu -subdomain todobot

Tworzenie webhooka i łączenie z Bird

Następnie musiałem wykonać wywołanie do API Rozmów Programowalnych, aby utworzyć webhook. Jest to POST do https://conversations.messagebird.com/v1/webhooks i wygląda to mniej więcej 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 API Rozmów wyśle żądanie POST do:

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

Tak wygląda ładunek webhooka:

{
  "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 odpowiadać na te wiadomości. Zaczynajmy od ich odbicia, co powiesz?

// 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 API Rozmów Programowalnych, aby utworzyć webhook. Jest to POST do https://conversations.messagebird.com/v1/webhooks i wygląda to mniej więcej 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 API Rozmów wyśle żądanie POST do:

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

Tak wygląda ładunek webhooka:

{
  "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 odpowiadać na te wiadomości. Zaczynajmy od ich odbicia, co powiesz?

// 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 API Rozmów Programowalnych, aby utworzyć webhook. Jest to POST do https://conversations.messagebird.com/v1/webhooks i wygląda to mniej więcej 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 API Rozmów wyśle żądanie POST do:

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

Tak wygląda ładunek webhooka:

{
  "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 odpowiadać na te wiadomości. Zaczynajmy od ich odbicia, co powiesz?

// 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, przejdźmy do interesującej części. 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. To wszystko, co potrzebujesz, aby stworzyć bota, który działa jak pięcioletni człowiek.


Oto dlaczego użycie API rozmów Bird’a sprawia, że rozwój bota na WhatsApp jest szybki i skalowalny:

Funkcja

Co rozwiązuje

Unified conversation ID

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

Single API for all channels

Powtórz logikę bota bez potrzeby przepisywania dla każdej platformy

Webhook-driven automation

Szybkie przetwarzanie odpowiedzi bez sprawdzania

Archive + reopen topics

Organizuj historię wsparcia i przepływy pracy

Concurrency-safe structure

Wiarygodnie obsługuj wiele czatów jednocześnie


Teraz, zróbmy krok w stronę budowania całej listy zadań. Najpierw nieco 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 w prosty sposób będzie analizować wiadomości, wykonywać pewne działania i wybierać odpowiedź. Spójrzmy na polecenie „dodaj”:

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)
}

Tutaj, ustawiliśmy: list := manager.fetch(whp.Conversation.ID). W zasadzie „manager” to mapa odporna na współbieżność, która mapuje identyfikatory rozmów na listy zadań.

Lista zadań to odporny na współbieżność slices stringów. Wszystko w pamięci!

Teraz, przejdźmy do interesującej części. 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. To wszystko, co potrzebujesz, aby stworzyć bota, który działa jak pięcioletni człowiek.


Oto dlaczego użycie API rozmów Bird’a sprawia, że rozwój bota na WhatsApp jest szybki i skalowalny:

Funkcja

Co rozwiązuje

Unified conversation ID

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

Single API for all channels

Powtórz logikę bota bez potrzeby przepisywania dla każdej platformy

Webhook-driven automation

Szybkie przetwarzanie odpowiedzi bez sprawdzania

Archive + reopen topics

Organizuj historię wsparcia i przepływy pracy

Concurrency-safe structure

Wiarygodnie obsługuj wiele czatów jednocześnie


Teraz, zróbmy krok w stronę budowania całej listy zadań. Najpierw nieco 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 w prosty sposób będzie analizować wiadomości, wykonywać pewne działania i wybierać odpowiedź. Spójrzmy na polecenie „dodaj”:

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)
}

Tutaj, ustawiliśmy: list := manager.fetch(whp.Conversation.ID). W zasadzie „manager” to mapa odporna na współbieżność, która mapuje identyfikatory rozmów na listy zadań.

Lista zadań to odporny na współbieżność slices stringów. Wszystko w pamięci!

Teraz, przejdźmy do interesującej części. 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. To wszystko, co potrzebujesz, aby stworzyć bota, który działa jak pięcioletni człowiek.


Oto dlaczego użycie API rozmów Bird’a sprawia, że rozwój bota na WhatsApp jest szybki i skalowalny:

Funkcja

Co rozwiązuje

Unified conversation ID

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

Single API for all channels

Powtórz logikę bota bez potrzeby przepisywania dla każdej platformy

Webhook-driven automation

Szybkie przetwarzanie odpowiedzi bez sprawdzania

Archive + reopen topics

Organizuj historię wsparcia i przepływy pracy

Concurrency-safe structure

Wiarygodnie obsługuj wiele czatów jednocześnie


Teraz, zróbmy krok w stronę budowania całej listy zadań. Najpierw nieco 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 w prosty sposób będzie analizować wiadomości, wykonywać pewne działania i wybierać odpowiedź. Spójrzmy na polecenie „dodaj”:

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)
}

Tutaj, ustawiliśmy: list := manager.fetch(whp.Conversation.ID). W zasadzie „manager” to mapa odporna na współbieżność, która mapuje identyfikatory rozmów na listy zadań.

Lista zadań to odporny na współbieżność slices stringów. Wszystko w pamięci!

Archiwizowanie rozmów i skalowanie twojego bota

Inna 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ć skuteczność pracowników wsparcia klienta. API Rozmów pozwala na archiwizowanie rozmowy, aby «zamknąć» temat. Jeśli użytkownik/klient wyśle kolejny wiadomość, API Rozmów automatycznie otworzy nowy temat.

Zarządzanie cyklem życia rozmowy

Również, wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim statusem w treści pozwala na archiwizowanie rozmowy o 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 użyć kodu bota na innej platformie, takiej jak WeChat? Takie podejście wielokanałowe jest częścią strategii odrzucania zapytań na tańsze kanały. Jak byś się do tego zabrał?

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

To zadziała, ponieważ kod handlera zawsze używa conversationID z ładunku webhooka do odpowiadania na wiadomości, zamiast na sztywno kodowanego channelID. API Rozmów MessageBird automatycznie określi kanał dla rozmowy, aby wysłać twoją wiadomość.

Czy chcesz zbudować własnego bota? Zobacz pełen kod na Githubie: Wabot na Githubie, poproś o wczesny dostęp do WhatsApp, odwiedzając stronę WhatsApp i klikając przycisk Kontakt z działem sprzedaży, aby wypełnić formularz. Powodzenia w tworzeniu bota!

Inna 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ć skuteczność pracowników wsparcia klienta. API Rozmów pozwala na archiwizowanie rozmowy, aby «zamknąć» temat. Jeśli użytkownik/klient wyśle kolejny wiadomość, API Rozmów automatycznie otworzy nowy temat.

Zarządzanie cyklem życia rozmowy

Również, wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim statusem w treści pozwala na archiwizowanie rozmowy o 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 użyć kodu bota na innej platformie, takiej jak WeChat? Takie podejście wielokanałowe jest częścią strategii odrzucania zapytań na tańsze kanały. Jak byś się do tego zabrał?

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

To zadziała, ponieważ kod handlera zawsze używa conversationID z ładunku webhooka do odpowiadania na wiadomości, zamiast na sztywno kodowanego channelID. API Rozmów MessageBird automatycznie określi kanał dla rozmowy, aby wysłać twoją wiadomość.

Czy chcesz zbudować własnego bota? Zobacz pełen kod na Githubie: Wabot na Githubie, poproś o wczesny dostęp do WhatsApp, odwiedzając stronę WhatsApp i klikając przycisk Kontakt z działem sprzedaży, aby wypełnić formularz. Powodzenia w tworzeniu bota!

Inna 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ć skuteczność pracowników wsparcia klienta. API Rozmów pozwala na archiwizowanie rozmowy, aby «zamknąć» temat. Jeśli użytkownik/klient wyśle kolejny wiadomość, API Rozmów automatycznie otworzy nowy temat.

Zarządzanie cyklem życia rozmowy

Również, wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim statusem w treści pozwala na archiwizowanie rozmowy o 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 użyć kodu bota na innej platformie, takiej jak WeChat? Takie podejście wielokanałowe jest częścią strategii odrzucania zapytań na tańsze kanały. Jak byś się do tego zabrał?

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

To zadziała, ponieważ kod handlera zawsze używa conversationID z ładunku webhooka do odpowiadania na wiadomości, zamiast na sztywno kodowanego channelID. API Rozmów MessageBird automatycznie określi kanał dla rozmowy, aby wysłać twoją wiadomość.

Czy chcesz zbudować własnego bota? Zobacz pełen kod na Githubie: Wabot na Githubie, poproś o wczesny dostęp do WhatsApp, odwiedzając stronę WhatsApp i klikając przycisk Kontakt z działem sprzedaży, aby wypełnić formularz. Powodzenia w tworzeniu bota!

Inne wiadomości

Przeczytaj więcej z tej kategorii

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

Kompletna platforma oparta na sztucznej inteligencji, która rośnie wraz z Twoim biznesem.

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

Kompletna platforma oparta na sztucznej inteligencji, która rośnie wraz z Twoim biznesem.