Erreichen

Grow

Manage

Automate

Erreichen

Grow

Manage

Automate

Wie man einen WhatsApp-Bot für To-Do-Listen mit der Programmable Conversations API von Bird erstellt

Vogel

05.02.2020

WhatsApp

1 min read

Wie man einen WhatsApp-Bot für To-Do-Listen mit der Programmable Conversations API von Bird erstellt

Vogel

05.02.2020

WhatsApp

1 min read

Wie man einen WhatsApp-Bot für To-Do-Listen mit der Programmable Conversations API von Bird erstellt

Bird hat kürzlich programmierbare Gespräche eingeführt. Damit können Unternehmen Kommunikationsplattformen wie WhatsApp, Messenger und SMS in ihre Systeme integrieren – mithilfe einer einzigen API.

Business in a box.

Entdecken Sie unsere Lösungen.

Bird hat kürzlich Programmable Conversations eingeführt. Damit können Unternehmen Kommunikationsplattformen wie WhatsApp, Messenger und SMS in ihre Systeme integrieren — mit einer einzigen API.

Ich wollte es ausprobieren, also habe ich einen WhatsApp-Bot To-Do-Liste gebaut, denn wer braucht nicht eine automatisierte To-Do-Liste, um seinen Tag zu organisieren? Es mag kompliziert klingen, aber es war eigentlich einfach, und ich möchte Ihnen alles darüber erzählen.

Nun, ich arbeite bei MessageBird, also konnte ich einfach loslegen und mit dem Bauen anfangen. Wenn Sie es selbst ausprobieren wollen, müssen Sie frühzeitig Zugang beantragen. Aber sobald Sie einen WhatsApp-Kanal eingerichtet haben, können Sie sich auf dem Dashboard der MessageBird-Website anmelden und loslegen.

Das Erste, was ich tat, war die Dokumentation zu lesen. Ich habe erfahren, dass ich, um Nachrichten vom Bot zu empfangen, einen Webhook verwenden müsste. Das bedeutete, dass mein Bot über das Internet zugänglich sein musste. Wenn man APIs wie diese entwickelt, ist es wichtig, die besten Praktiken für API-Versionsverwaltung für die Wartbarkeit zu befolgen. Da ich gerade erst anfing, es zu programmieren, entschied ich mich für ngrok. Es erstellt einen Tunnel vom öffentlichen Internet zu Ihrem lokalen localhost-Port 5007. Legen wir los!

ngrok http 5007 -region eu -subdomain todobot

Als nächstes musste ich einen Aufruf an die Programmable Conversations API machen, um den Webhook zu erstellen. Es ist ein POST an https://conversations.messagebird.com/v1/webhooks und sieht ungefähr so aus:


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

Super. Jetzt wird die Conversations API eine POST-Anfrage an:

https://todobot.eu.ngrok.io/create-hook senden, wann immer eine neue Nachricht im zuvor eingerichteten WhatsApp-Kanal erstellt wird.

So sieht eine Webhook-Nutzlast aus:


{
  "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"
}

Wir wollen diese Nachrichten beantworten. Fangen wir damit an, sie zurückzumelden, was meinen Sie?


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

Nun zum interessanten Teil. Machen Sie eine POST-Anfrage an:

https://conversations.messagebird.com/v1/conversations/<conversationID>/messages, um die Anfrage zu beantworten.


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
}

Da. Das ist alles, was Sie brauchen, um einen Bot zu erstellen, der wie ein fünfjähriger Mensch agiert.

Lassen Sie uns jetzt einen Schritt vorwärts machen und die gesamte To-Do-Liste erstellen. Zuerst modifizieren Sie die createHookHandler-Funktion ein wenig, sodass sie die neue handleMessage-Funktion aufruft, anstatt zu antworten.

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

handle wird die Nachrichten einfach analysieren, etwas Arbeit erledigen und die Antwort auswählen. Schauen wir uns den „add“-Befehl an:

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

Hier richten wir ein: list := manager.fetch(whp.Conversation.ID). Grundsätzlich ist „manager“ eine konkurenzsichere Map, die Gesprächs-IDs auf To-Do-Listen abbildet.

Eine To-Do-Liste ist ein konkurenzsicherer String-Abschnitt. Alles im Speicher!

Eine weitere wichtige Sache! Sie können Gespräche archivieren. In einigen Anwendungen, wie z.B. CRMs, ist es wichtig, bestimmte Interaktionen zu verfolgen — um z.B. die Effektivität von Kundensupportmitarbeitern nachzuverfolgen. Die Conversations API ermöglicht es Ihnen, ein Gespräch zu archivieren, um das Thema zu „schließen“. Wenn der Benutzer/Kunde eine weitere Nachricht sendet, öffnet die Conversations API automatisch ein neues Thema.

Außerdem: Eine PATCH-Anfrage an https://conversations.messagebird.com/v1/conversations/{id} mit dem richtigen Status im Body ermöglicht es Ihnen, das Gespräch mit dieser ID zu archivieren. Wir tun dies mit dem „bye“-Befehl:

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

archiveConversation führt die PATCH-Anfrage aus und manager.close(whp.Conversation.ID) wird das To-Do-Listen-Gespräch entfernen.

Aber hey, Programmable Conversations ist eine Omni-Channel-Lösung. Was ist, wenn Sie den Code des Bots für eine andere Plattform wiederverwenden möchten, wie zum Beispiel WeChat? Dieser Multi-Channel-Ansatz ist Teil der Strategie zur Abwehr von Anfragen an kostengünstigere Kanäle. Wie würden Sie das angehen?

Erstellen Sie einfach einen neuen Webhook, um diesen Kanal anzusteuern! Ein Webhook, der Anfragen an dieselbe https://todobot.eu.ngrok.io/create-hook-URL sendet, die wir für WhatsApp verwendet haben!

Das wird funktionieren, weil der Handler-Code immer die conversationID aus der Webhook-Nutzlast verwendet, um die Nachrichten zu beantworten, anstatt eine hartcodierte channelID. Die Conversations API von MessageBird wird automatisch den Kanal für das Gespräch bestimmen, um Ihre Nachricht zu senden.

Möchten Sie Ihren eigenen Bot erstellen? Werfen Sie einen Blick auf den vollständigen Code auf Github: https://github.com/marcelcorso/wabot, beantragen Sie frühzeitig Zugang zu WhatsApp über diesen Link und fangen Sie direkt mit dem Erstellen an. Viel Spaß beim Botten!

Lassen Sie uns Sie mit einem Bird-Experten verbinden.
Erleben Sie die volle Macht des Bird in 30 Minuten.

Durch die Übermittlung stimmen Sie zu, dass Bird Sie bezüglich unserer Produkte und Dienstleistungen kontaktieren darf.

Sie können sich jederzeit abmelden. Weitere Informationen zur Datenverarbeitung finden Sie in Birds Datenschutzerklärung.

Unternehmen

Newsletter

Bleiben Sie mit Bird auf dem Laufenden durch wöchentliche Updates in Ihrem Posteingang.

Lassen Sie uns Sie mit einem Bird-Experten verbinden.
Erleben Sie die volle Macht des Bird in 30 Minuten.

Durch die Übermittlung stimmen Sie zu, dass Bird Sie bezüglich unserer Produkte und Dienstleistungen kontaktieren darf.

Sie können sich jederzeit abmelden. Weitere Informationen zur Datenverarbeitung finden Sie in Birds Datenschutzerklärung.

Unternehmen

Newsletter

Bleiben Sie mit Bird auf dem Laufenden durch wöchentliche Updates in Ihrem Posteingang.

Lassen Sie uns Sie mit einem Bird-Experten verbinden.
Erleben Sie die volle Macht des Bird in 30 Minuten.

Durch die Übermittlung stimmen Sie zu, dass Bird Sie bezüglich unserer Produkte und Dienstleistungen kontaktieren darf.

Sie können sich jederzeit abmelden. Weitere Informationen zur Datenverarbeitung finden Sie in Birds Datenschutzerklärung.

R

Erreichen

G

Grow

M

Manage

A

Automate

Unternehmen

Newsletter

Bleiben Sie mit Bird auf dem Laufenden durch wöchentliche Updates in Ihrem Posteingang.