C'est la vie : envoyez des SMS avec Golang

September 25, 2017
Rédigé par
Alaina Kafkes
Contributeur
Les opinions exprimées par les contributeurs de Twilio sont les leurs

envoyer des sms avec golang

Que ce soit sur notre téléphone, sur des post-it ou dans un carnet, nous gardons tous des citations qui nous inspirent. Personnellement, j'aime suivre @Kurt Vonnegut. Non, pas le vrai Vonnegut (qui est décédé) : juste un humain ou un bot qui tweete certains de ses fameux traits d'esprit.

En pensant à Vonnegut, une idée m'est venue : quoi de mieux pour se lancer avec Twilio que d'envoyer des citations de Vonnegut à tous vos amis ? C'est exactement ce que nous allons voir dans ce blog : comment envoyer des SMS avec des citations de Vonnegut dans Golang.

C'est parti : configuration de l'environnement de développement

Avant de commencer à coder, prenez un moment pour installer Golang sur votre ordinateur. Suivez les instructions de votre système d'exploitation et n'hésitez pas à tester votre installation localement.

Si vous n'avez jamais vu de code Golang, je vous recommande de jeter un œil au Golang Tour. Si vous voulez vraiment approfondir, la documentation Golang sera votre meilleure alliée.

Si vous avez testé votre installation de Golang localement, vous avez probablement créé un programme Golang (main.go) qui ressemble à ceci :

package main

import (
  // packages will go here!
)

func main() {
  // code will go here!
}

Le programme Golang que nous allons utiliser aujourd'hui se compose de ce squelette de code de base. L'exécution de chaque programme Golang commence dans un package nommé main. En écrivant package main en haut de votre programme, vous indiquez au compilateur que le programme que vous écrivez doit être compilé et exécuté avec succès.

Tout en étant dans main, le programme peut importer d'autres packages qui étendent la fonctionnalité fournie par le package main. Ces autres packages se trouvent dans les instructions import.

Il existe une fonction similaire à C++ nommée main dont le code est exécuté. D'autres fonctions peuvent être créées dans ce programme Golang, mais elles ne seront pas exécutées à moins d'être appelées dans main.

Vous pouvez exécuter n'importe quel programme Golang en ouvrant la ligne de commande, en accédant au répertoire où se trouve votre programme et en saisissant la commande go run main.go.

Encore une fois, si vous avez besoin de vous familiariser avec la syntaxe, consultez le Golang Tour. Passons maintenant à l'écriture du code Golang qui permettra à notre programme de choisir des citations de Vonnegut de manière aléatoire dans un tableau pour notre futur message SMS.

Génération aléatoire de citations avec Golang

Avis à tous : ce que nous allons faire peut sembler simple, mais ce n'est pas tout à fait le cas. Même si vous êtes à l'aise avec l'écriture de générateurs d'éléments aléatoires dans d'autres langages, n'ignorez pas cette section.

Commencez par un programme nommé main.go si vous ne l'avez pas déjà créé dans la section précédente. Ce programme doit contenir le squelette de code Golang mentionné précédemment :

package main

import (
  // packages will go here!
)

func main() {
  // code will go here!
}

Importez le package nommé math/rand, qui vous permettra de mettre en œuvre un générateur de nombres aléatoires. math/rand est déterministe, ce qui signifie que tout générateur de nombres aléatoires créé avec ce package produira la même sortie avec le même état de démarrage. En d'autres termes, si vous exécutez le code suivant plusieurs fois, vous verrez le même nombre (un entier compris entre 0 et 10) s'imprimer à chaque fois, en raison de l'élément rand.Intn.

package main

import (
  "fmt"
  "math/rand"
)

func main() {
  fmt.Println(rand.Intn(10))
}

Que faire si nous voulons qu'un nombre aléatoire différent soit généré à chaque fois ? Comment contourner la nature déterministe de math/rand ? D'après la définition susmentionnée de « déterministe », il suffit de modifier l'état de démarrage à chaque exécution du programme.

La façon la plus courante de procéder est d'utiliser rand.Seed pour définir cet état de démarrage sur l'heure Unix actuelle. Pourquoi ? Étant donné qu'il y aura au moins une seconde entre chaque exécution de main.go, l'état de démarrage sera à une heure Unix différente pour chaque exécution, ce qui signifie que l'entier aléatoire produit par rand.Intn sera vraiment aléatoire.

package main

import (
  "fmt"
  "time"
  "math/rand"
)

func main() {
  rand.Seed(time.Now().Unix())
  fmt.Println(rand.Intn(10))
}

Maintenant que nous avons construit un générateur de nombres aléatoires, utilisons-le pour sélectionner une citation aléatoire dans un tableau de citations de Kurt Vonnegut. Dans l'extrait de code ci-dessous, il y a un tableau avec sept citations de Vonnegut dans main(), ainsi que l'instruction print fmt.Println afin que la commande imprime la citation de Vonnegut au niveau de l'index du tableau donné par le nombre généré de manière aléatoire.

package main

import (
  "fmt"
  "time"
  "math/rand"
)

func main() {

  quotes := [7]string{"I urge you to please notice when you are happy, and exclaim or murmur or think at some point, 'If this isn't nice, I don't know what is.'",
                      "Peculiar travel suggestions are dancing lessons from God.",
                      "There's only one rule that I know of, babies—God damn it, you've got to be kind.",
                      "Many people need desperately to receive this message: 'I feel and think much as you do, care about many of the things you care about, although most people do not care about them. You are not alone.'",
                      "That is my principal objection to life, I think: It's too easy, when alive, to make perfectly horrible mistakes.",
                      "So it goes.",
                      "We must be careful about what we pretend to be."}

  rand.Seed(time.Now().Unix())
  fmt.Println(quotes[rand.Intn(len(quotes))])
}

Si vous exécutez ce programme plusieurs fois, vous verrez s'imprimer des citations de Kurt Vonnegut différentes provenant de ce tableau.

Bienvenue à Twilio

Si vous avez déjà utilisé Twilio, vous pouvez ignorer cette section. :)

Accédez à la page d'inscription de Twilio pour vous inscrire gratuitement à Twilio. À l'invite, indiquez que vous souhaitez développer une application avec des fonctionnalités SMS.

Une fois les détails de compte renseignés, vous arrivez sur la page du compte d'essai, qui indique que vous avez un crédit pour passer des appels, envoyer des SMS, etc. via Twilio. Compte tenu du modèle de tarification de SMS avantageux de Twilio, inutile de vous soucier de l'argent du compte d'essai que vous dépenserez avec ce tutoriel.

Après avoir sélectionné le bouton Get Started (Commencer), vous obtenez un numéro de téléphone Twilio.

Essayez d'envoyer un message initial à votre téléphone avec l'outil Twilio Send a Message  (Envoyer un message) qui s'affiche. Si cela fonctionne, nous pouvons revenir à Golang.

Envoi de SMS par programmation avec Golang

Voici la partie la plus amusante : utiliser Golang pour envoyer des SMS via Twilio !

Commençons par ce code de démarrage, qui est une légère extension de ce que nous avons construit dans les sections précédentes.

Remplissez les variables accountSid et authToken avec votre SID de compte unique et le token d'authentification, qui se trouvent tous deux sur la console Twilio.

package main

import (
  "fmt"
  "math/rand"
  "time"
)

func main() {
  // Set account keys & information
  accountSid := "ACXXXX"
  authToken := "XXXXXX"
  urlStr := "https://api.twilio.com/2010-04-01/Accounts/"   accountSid   "/Messages.json"

  // Create possible message bodies
  quotes := [7]string{"I urge you to please notice when you are happy, and exclaim or murmur or think at some point, 'If this isn't nice, I don't know what is.'",
                      "Peculiar travel suggestions are dancing lessons from God.",
                      "There's only one rule that I know of, babies—God damn it, you've got to be kind.",
                      "Many people need desperately to receive this message: 'I feel and think much as you do, care about many of the things you care about, although most people do not care about them. You are not alone.'",
                      "That is my principal objection to life, I think: It's too easy, when alive, to make perfectly horrible mistakes.",
                      "So it goes.",
                      "We must be careful about what we pretend to be."}

  // Set up rand
  rand.Seed(time.Now().Unix())

Après avoir configuré notre futur générateur de nombres aléatoires pour qu'il ne soit pas déterministe, il existe trois fonctions supplémentaires à ajouter à ce programme :

  • Spécification des données SMS (expéditeur, destinataire, corps du message)
  • Création d'un client de requête HTTP
  • Création d'une requête POST HTTP avec le client HTTP

Créez et préparez le message SMS à envoyer. Remplacez NUMBER_FROM par le numéro de téléphone de l'expéditeur (votre numéro de téléphone Twilio) et remplacez NUMBER_TO par le numéro de téléphone du destinataire. Veillez à formater ces numéros de téléphone ainsi : +1234567890. Les packages net/url et strings doivent également être ajoutés à l'instruction import pour que cette partie du code puisse être compilé.

msgData := url.Values{}
msgData.Set("To","NUMBER_TO")
msgData.Set("From","NUMBER_FROM")
msgData.Set("Body",quotes[rand.Intn(len(quotes))])
msgDataReader := *strings.NewReader(msgData.Encode())

Dans ce bloc de code, l'élément url.Values{} est créé pour stocker et encoder les paramètres d'URL (expéditeur "From", destinataire "To" et corps du message "Body"), puis le Reader créé permet à cet objet d'être analysé comme une chaîne de caractères.

Ensuite, nous allons configurer un client HTTP et une requête POST HTTP. La variable req contient cette requête. Nous lui donnons nos identifiants Twilio avec req.SetBasicAuth() et ajoutons des en-têtes à la requête avec req.Header.Add. Le package net/http doit être ajouté à l'instruction import pour que cet extrait de code puisse être compilé.

client := &http.Client{}
req, _ := http.NewRequest("POST", urlStr, &msgDataReader)
req.SetBasicAuth(accountSid, authToken)
req.Header.Add("Accept", "application/json")
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

Même si le client HTTP client et la requête POST HTTP req ont été créés, ils ne sont pas utilisés dans cet extrait de code.

Enfin, nous allons utiliser le client de requête HTTP pour effectuer une requête POST. Nous allons effectuer la requête POST HTTP req à l'aide du client HTTP client, et stocker le résultat dans la variable resp.  Le package encoding/json doit être ajouté à l'instruction import pour que cet extrait de code puisse être compilé.

resp, _ := client.Do(req)
if (resp.StatusCode >= 200 && resp.StatusCode < 300) {
  var data map[string]interface{}
  decoder := json.NewDecoder(resp.Body)
  err := decoder.Decode(&data)
  if (err == nil) {
    fmt.Println(data["sid"])
  }
} else {
  fmt.Println(resp.Status);
}

Vous vous demandez peut-être pourquoi l'instruction if en haut vérifie si resp.StatusCode est compris entre 200 et 300. Cela est dû au fait qu'un code d'état HTTP ayant la forme 2XX indique que la requête POST HTTP a réussi. Nous pouvons utiliser json.NewDecoder pour lire le corps de la réponse et voir si des erreurs se sont produites.

Si la requête POST HTTP est une réussite et si l'instruction if la plus à l'intérieur indique qu'il n'y a pas d'erreur, le SID du message SMS est imprimé sur votre ligne de commande. Cela signifie que vous avez réussi à envoyer un SMS via Twilio. Bravo !

femme dansant

Que se passe-t-il si vous ne voyez pas le SID du message SMS ? Si le code d'état HTTP n'est pas compris dans la plage des 200, l'instruction else imprime des informations sur la raison de l'échec de la requête POST HTTP sur la ligne de commande. Vous pouvez voir ce que signifient les autres codes d'état HTTP ici, et y remédier à partir de là.

Avez-vous reçu mon message ?

Avant de vous révéler le code final, je voudrais que vous observiez votre instruction import. Est-ce qu'elle ressemble à cela ?

import (
  "fmt"
  "strings"
  "math/rand"
  "time"
  "net/http"
  "net/url"
  "encoding/json"
)

Si c'est le cas, vous avez suivi la dernière section à la perfection ! Félicitations. S'il semble qu'il vous manque un ou deux packages, revenez à la section « Envoi de SMS par programmation avec Golang » de ce tutoriel pour découvrir ce que vous avez raté.

Roulements de tambour, s'il vous plaît… voici le code final pour vérifier si vous avez réussi. Si vous pensez avoir réussi, saisissez go run main.go dans l'invite de ligne de commande pour envoyer ce SMS ! 

programme lancé dans le terminal

réception de SMS sur un écran de téléphone

Vous pouvez confirmer que votre message a été envoyé en accédant au tableau de bord Programmable SMS de Twilio sous Recent Messages (Messages récents).

Conclusion

J'espère que vous avez apprécié ce mashup de Twilio et Golang, avec une touche de Vonnegut. N'hésitez pas à faire preuve de créativité et à personnaliser ces citations, voire à travailler sur des projets Twilio plus complexes avec Golang.

Merci à Matt Makai et Lizzie Siegle d'avoir révisé mon travail et de m'avoir aidée à le publier via Twilio Voices. Si vous avez des questions ou des commentaires, n'hésitez pas à me contacter sur TwitterGitHub ou par e-mail !