Zasięg

Grow

Manage

Automate

Zasięg

Grow

Manage

Automate

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

Ptak

5 lut 2020

WhatsApp

1 min read

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

Bird niedawno uruchomił Programowalne Rozmowy. Umożliwia to firmom łączenie platform komunikacyjnych, takich jak WhatsApp, Messenger i SMS, w ich systemach - przy użyciu jednego interfejsu API.

Business in a box.

Odkryj nasze rozwiązania.

Bird niedawno uruchomił Programowalne Rozmowy. Pozwala firmom wtopić platformy komunikacyjne, takie jak WhatsApp, Messenger i SMS, w ich systemy — używając jednego API.

Chciałem to wypróbować, więc zbudowałem chatbot na WhatsApp do listy zadań, ponieważ kto nie potrzebuje zautomatyzowanej listy zadań, aby pomóc w organizacji dnia? Może to brzmieć skomplikowanie, ale było to naprawdę łatwe, i chciałbym Wam 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 kiedy już skonfigurujesz kanał WhatsApp, możesz zalogować się na Dashboard na stronie MessageBird i zaczynać.

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

ngrok http 5007 -region eu -subdomain todobot

Następnie musiałem wykonać połączenie do Programmable Conversations API, aby stworzyć webhook. To jest 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))
  }
}

Świetnie. Teraz Conversations API wykona żądanie POST do:

https://todobot.eu.ngrok.io/create-hook za każdym razem, gdy zostanie utworzona nowa wiadomość 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 odpowiedzieć na te wiadomości. Zacznijmy od ich echowania, 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")
}

Teraz czas na interesującą część. 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
}

Tutaj. To wszystko, czego potrzebujesz, aby stworzyć bota, który działa jak pięcioletnie dziecko.

Teraz zróbmy krok w kierunku budowy całej listy zadań. Najpierw zmodyfikuj funkcję createHookHandler tak, aby wywoływała nową funkcję handleMessage zamiast respondowania.

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

handle w prosty sposób przeanalizuje wiadomości, wykona pewne zadania i wybierze odpowiedź. Spójrzmy na komendę „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)
}

Tu, ustawiamy listę:list := manager.fetch(whp.Conversation.ID). W zasadzie, „manager” to bezpieczna dla współbieżności mapa, która mapuje identyfikatory konwersacji na listy zadań.

Lista zadań to bezpieczny dla współbieżności wycinek ciągu znaków. Wszystko w pamięci!

Kolejna ważna rzecz! Możesz archiwizować konwersacje. W niektórych aplikacjach, takich jak CRM, ważne jest, aby śledzić niektóre interakcje — na przykład, aby śledzić skuteczność pracowników wsparcia klienta. Conversations API pozwala archiwizować konwersację, aby „zamknąć” temat. Jeśli użytkownik/klient wyśle inną wiadomość, Conversations API automatycznie otworzy nowy temat.

Również. Wykonanie żądania PATCH do https://conversations.messagebird.com/v1/conversations/{id} z odpowiednim statusem w treści pozwala zarchiwizować konwersację 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 i manager.close(whp.Conversation.ID) usunie konwersację listy zadań.

Ale hej, Programmable Conversations to rozwiązanie omni-channel. A co jeśli chciałeś ponownie wykorzystać kod bota dla innej platformy, jak WeChat? To podejście multi-channel jest częścią strategii przekierowywania zapytań do tańszych kanałów. Jak byś to zrobił?

Po prostu stwórz nowy webhook, który będzie kierować zapytania na ten sam url https://todobot.eu.ngrok.io/create-hook, którego użyliśmy dla WhatsApp!

To będzie działać, ponieważ kod handlera zawsze używa conversationID z ładunku webhooka, aby odpowiedzieć na wiadomości, zamiast używać zakodowanego kanałowego ID. Conversations API MessageBird automatycznie określi kanał dla konwersacji, aby wysłać twoją wiadomość.

Chcesz zbudować własnego bota? Spójrz na pełny kod na Githubie: https://github.com/marcelcorso/wabot, złóż wniosek o wczesny dostęp do WhatsApp za pośrednictwem tego linku i zacznij budować bezpośrednio. Szczęśliwego botowania!

Połączmy Cię z ekspertem Bird.
Zobacz pełną moc Bird w 30 minut.

Przesyłając, zgadzasz się, że Bird może kontaktować się z Tobą w sprawie naszych produktów i usług.

Możesz zrezygnować z subskrypcji w dowolnym momencie. Zobacz Privacy Statement firmy Bird, aby uzyskać szczegóły dotyczące przetwarzania danych.

Company

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Połączmy Cię z ekspertem Bird.
Zobacz pełną moc Bird w 30 minut.

Przesyłając, zgadzasz się, że Bird może kontaktować się z Tobą w sprawie naszych produktów i usług.

Możesz zrezygnować z subskrypcji w dowolnym momencie. Zobacz Privacy Statement firmy Bird, aby uzyskać szczegóły dotyczące przetwarzania danych.

Company

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Połączmy Cię z ekspertem Bird.
Zobacz pełną moc Bird w 30 minut.

Przesyłając, zgadzasz się, że Bird może kontaktować się z Tobą w sprawie naszych produktów i usług.

Możesz zrezygnować z subskrypcji w dowolnym momencie. Zobacz Privacy Statement firmy Bird, aby uzyskać szczegóły dotyczące przetwarzania danych.

R

Reach

G

Grow

M

Manage

A

Automate

Company

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.