Erstellen eines WhatsApp-Aufgabenlisten-Bots mit den programmierbaren Gesprächen von MessageBird

MessageBird hat kürzlich Programmable Conversations gestartet. Damit können Unternehmen Kommunikationsplattformen wie WhatsApp, Messenger und SMS mithilfe einer einzigen API in ihre Systeme integrieren.

Ich wollte es versuchen, also habe ich eine WhatsApp-Bot-To-Do-Liste erstellt und möchte Ihnen alles darüber erzählen.

Jetzt arbeite ich bei MessageBird, damit ich einfach eintauchen und mit dem Bauen beginnen kann. Wenn Sie dies versuchen, müssen Sie einen frühen Zugriff anfordern. Sobald Sie jedoch einen WhatsApp-Kanal eingerichtet haben, können Sie sich beim Dashboard auf der MessageBird-Website anmelden und loslegen.

Als erstes habe ich die Dokumente gelesen. Ich habe gelernt, dass ich einen Webhook verwenden muss, um Nachrichten vom Bot zu erhalten. Dies bedeutete, dass mein Bot über das Internet erreichbar sein musste. Da ich gerade anfing, es zu codieren, entschied ich mich für ngrok. Es wird ein Tunnel vom öffentlichen Internet zu Ihrem lieben lokalen Host-Port 5007 erstellt. Engagieren Sie sich!

ngrok http 5007 -region eu -subdomain todobot

Als Nächstes musste ich die Berichts-API aufrufen, um den Webhook zu erstellen. Es ist ein POST an https://conversations.messagebird.com/v1/webhooks und es sieht ungefähr so ​​aus:

func main () {
        // definiere den Webhook json payload wh: = struct {Events [] string `json:" events "` ChannelID string` json: "channelId" `URL string` json:" url "`} {
                // Wir möchten über die URL-URL benachrichtigt werden: "https://todobot.eu.ngrok.io/create-hook", // wann immer eine Nachricht erstellt wird Ereignisse: [] string {"message.created"} , // auf dem WhatsApp-Kanal mit der ID ChannelID: "23a780701b8849f7b974d8620a89a279",}
        // codiere die Nutzdaten in json var b Bytes.Buffer err: = json.NewEncoder (& b) .Encode (& wh) wenn err! = nil {Panic (err)}
        // Erstelle die http-Anfrage und setze den Autorisierungsheader req, err: = http.NewRequest ("POST", "https://conversations.messagebird.com/v1/webhooks", & b) req.Header.Set ("Authorization") , "AccessKey todo-your-access-key") req.Header.Set ("Inhaltstyp", "application / json")
        // feuere den http request client ab: = & http.Client {} resp, err: = client.Do (req) wenn err! = nil {panic (err)} defer resp.Body.Close ()
// ist alles in Ordnung? body, _: = ioutil.ReadAll (resp.Body) if resp.StatusCode> = http.StatusBadRequest {panic (fmt.Errorf ("Ungültiger Antwortcode von der API beim Versuch, einen Webhook zu erstellen:% s. Body:% s", resp.Status, string (body))}} else {log.Println ("Alles gut. response body:", string (body))}}

Süss. Jetzt führt die Conversations-API eine POST-Anforderung an:

https://todobot.eu.ngrok.io/create-hook, wenn auf dem zuvor eingerichteten WhatsApp-Kanal eine neue Nachricht erstellt wird.

So sieht eine Webhook-Nutzlast aus:

{"Konversation": {"id": "55c66895c22a40e39a8e6bd321ec192e", "contactId": "db4dd5087fb343738e968a323f640576", "status": "active", "createdDatetime": "2018-08-17T10: 14: 14Z", " "2018-08-17T14: 30: 31.915292912Z", "lastReceivedDatetime": "2018-08-17T14: 30: 31.898389294Z"}, "message": {"id": "ddb150149e2c4036a48f581544e22cfe", "gesprächs-ID": "c "," channelId ":" 23a780701b8849f7b974d8620a89a279 "," status ":" empfangen "," Typ ":" Text "," Richtung ":" empfangen "," Inhalt ": {" Text ":" Milch kaufen "}, "createdDatetime": "2018-08-17T14: 30: 31.898389294Z", "updatedDatetime": "2018-08-17T14: 30: 31.915292912Z"}, "type": "message.created"}

Wir möchten diese Nachrichten beantworten. Beginnen wir damit, sie zu wiederholen. Was sagen Sie?

// Definiere die Strukturen, in denen wir die Webhook-Nutzdaten analysieren
Typ whPayload struct {Konversation Konversation `json:" Konversation "` Nachricht Nachricht `json:" Nachricht "` Typ Zeichenfolge `json:" Typ "`}
Typ Nachricht Struktur {ID Zeichenfolge `json:" id "` Richtung Zeichenfolge `json:" Richtung "` Typ Zeichenfolge `json:" Typ "` Inhalt Inhalt `json:" Inhalt "`}
Typ Inhaltsstruktur {Textzeichenfolge `json:" Text "`}
Typ Konversationsstruktur {ID-Zeichenfolge `json:" id "`}
func main () {http.HandleFunc ("/ create-hook", createHookHandler) log.Fatal (http.ListenAndServe (* httpListenAddress, nil))}
// createHookHandler ist ein http-Handler, der Webhook-Anforderungen verarbeitet. func createHookHandler (w http.ResponseWriter, r * http.Request) {// Analyse der eingehenden json-Nutzdaten whp: = & whPayload {} err: = json.NewDecoder (r.Body ) .Decode (whp) if err! = Nil {log.Println ("Err: habe einen seltsamen Körper im Webhook") w.WriteHeader (http.StatusInternalServerError) fmt.Fprintf (w, "Internal Server Error") return}
if whp.Message.Direction! = "receive" {// Sie erhalten * alle * Nachrichten auf dem Webhook. Sogar die, die dieser Bot an den Kanal sendet. Wir wollen diese nicht beantworten. fmt.Fprintf (w, "ok") return}
        // echo: antworte was wir bekommen err = antworte (whp.Conversation.ID, whp.Message.Content.Text) wenn err! = nil {log.Println ("Err:", err) w.WriteHeader (http.StatusInternalServerError ) fmt.Fprintf (w, "Interner Serverfehler") 
                Rückkehr }
        w.WriteHeader (http.StatusOK) fmt.Fprintf (w, "ok")}

Nun zum interessanten Teil. Führen Sie eine POST-Anfrage an:

"Https://conversations.messagebird.com/v1/conversations/ / messages ”, um die Anfrage zu beantworten.

Funktionsantwort (Konversations-ID, Antwort-Zeichenfolge) Fehler {u: = fmt.Sprintf ("https://conversations.messagebird.com/v1/conversations/%s/messages", Konversations-ID)
        msg: = message {Inhalt: Inhalt {Text: responseBody,}, Typ: "text",}
        var b bytes.Buffer err: = json.NewEncoder (& b) .Encode (& msg) wenn err! = nil {return fmt.Errorf ("Fehlercodierungspuffer:% v", err)}
req, err: = http.NewRequest ("POST", u.String (), & b) req.Header.Set ("Autorisierung", "AccessKey todo-your-access-key") req.Header.Set ("Inhalt" -Typ "," application / json ")
        client: = & http.Client {} resp, err: = client.Do (req) wenn err! = nil {return err} defer resp.Body.Close ()
        body, _: = ioutil.ReadAll (resp.Body) if resp.StatusCode! = http.StatusCreated {return fmt.Errorf ("Fehlerhafter Antwortcode von der API beim Versuch, eine Nachricht zu erstellen:% s. Body:% s", resp .Status, string (body))}
        log.Println ("Alles gut. Antwortkörper:", Zeichenfolge (Körper)) return nil}

Dort. Dies ist alles, was Sie brauchen, um einen Bot zu erstellen, der sich wie ein 5-jähriger Mensch verhält.

Lassen Sie uns nun versuchen, die gesamte To-Do-Liste zu erstellen. Ändern Sie zunächst die Funktion createHookHandler ein wenig, damit die neue Funktion handleMessage aufgerufen wird, anstatt zu antworten.

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

handle analysiert die Nachrichten auf einfache Weise, erledigt einige Arbeiten und wählt die Antwort aus. Schauen wir uns den Befehl "add" an:

func handleMessage (whp * whPayload) error {// Jede Konversation hat eine Aufgabenlistenliste: = manager.fetch (whp.Conversation.ID) // Analysiere den Befehl aus dem Nachrichtentext: Es ist das erste Wort text: = whp.Message .Content.Text text = regexp.MustCompile ("+"). ReplaceAllString (text, "") parts: = strings.Split (text, "") Befehl: = strings.ToLower (parts [0]) // Standardnachricht responseBody: = "Ich verstehe nicht. Geben Sie 'help' ein, um Hilfe zu erhalten." switch command {... case "add": Wenn len (parts) <2 {return reply (whp.Conversation.ID, "err ... der Befehl 'add' benötigt einen zweiten Parameter: das Aufgabenelement, das Sie speichern möchten So etwas wie 'Milch kaufen' hinzufügen. ")} // Den Artikel aus dem Nachrichtentext abrufen item: = strings.Join (parts [1:]," ")
list.add (item) responseBody = "hinzugefügt." ... return reply (whp.Conversation.ID, responseBody)}

Hier richten wir ein: list: = manager.fetch (whp.Conversation.ID). Grundsätzlich ist „Manager“ eine parallele sichere Zuordnung, die Konversations-IDs Aufgabenlisten zuordnet.

Eine To-Do-Liste ist ein paralleler String-Slice. Alles in Erinnerung!

Eine andere wichtige Sache! Sie können Konversationen archivieren. In einigen Anwendungen, wie z. B. CRMs, ist es wichtig, bestimmte Interaktionen im Auge zu behalten, um beispielsweise die Effektivität der Mitarbeiter des Kundensupports zu verfolgen. Mit der Konversations-API können Sie eine Konversation archivieren, um das Thema zu schließen. Wenn der Benutzer / Kunde eine andere Nachricht sendet, öffnet die Conversations-API automatisch ein neues Thema.

Ebenfalls. Wenn Sie eine PATCH-Anfrage an https://conversations.messagebird.com/v1/conversations/{id} mit dem richtigen Status auf dem Text senden, können Sie die Konversation mit dieser ID archivieren. Wir machen das mit dem Befehl "bye":

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

archiveConversation führt die PATCH-Anforderung aus und manager.close (whp.Conversation.ID) entfernt die To-Do-Listenkonversation.

Aber hey, programmierbare Gespräche sind eine Omni-Channel-Lösung. Was wäre, wenn Sie den Code des Bots für eine andere Plattform wie WeChat wiederverwenden möchten? Wie würden Sie vorgehen?

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

Dies funktioniert, da der Handlercode immer die Konversations-ID aus der Webhook-Nutzlast verwendet, um die Nachrichten anstelle einer fest codierten Kanal-ID zu beantworten. Die Conversations-API von MessageBird ermittelt automatisch den Kanal für die Konversation, über den Ihre Nachricht gesendet werden soll.

Möchten Sie Ihren eigenen Bot bauen? Sehen Sie sich den vollständigen Code auf Github an: https://github.com/marcelcorso/wabot, fordern Sie über diesen Link einen frühen Zugriff auf WhatsApp an und beginnen Sie direkt mit dem Erstellen. Viel Spaß beim Abfüllen!