Utiliser les APIs Matrix en Go

Voici un exemple d'utilisation des APIs de Matrix pour se connecter à un salon de riot et intéragir avec celui-ci et créer son bot...

Utiliser les APIs Matrix en Go

Nous allons présenter une découverte des APIs Matrix pour communiquer dans un salon.

Matrix est un système de communication distribué et crypté. Il vient d'être implémenté par l'état français comme système de messagerie interne. Le server principal (Synapse) peut-etre auto-hébergé ou bien publique. Il existe de nombreux clients et le plus connu est riot, sur lequel vous pouvez créer un compte. Cette plateforme est ouverte, modulaire et pensée comme un socle pour éventuellement bien plus que de la simple communication de messages (ils ont l'intention de réinventer le web, rien que ça).

Prérequis

Il faut un compte sur un server Matrix. Allez sur riot et vous pouvez créer un compte gratuit.

Dans le cadre de cet article, nous avons créé un salon dédié.

Et il faut ensuite Go > 1.11 installé pour pouvoir utiliser les modules.

Le code

Vous pouvez simplement cloner le repo du projet depuis mon compte github. Vous devez ajouter un fichier riot.pass contenant le mot de passe de votre compte (à éviter de le publier sur un compte git publique...).

Pour simplifier le code, plusieurs variables sont directement dans le code:

  1. La base_url : est l'addresse du serveur Matrix sur lequel vous vous connectez. Attention, ici le seveur est matrix.org et le client est riot.

2. L'id du salon (ou room en anglais) est donc l'identifiant du salon que vous retrouvez à la fin de l'adresse ci-dessus.

1) La connexion au server

Le serveur Matrix met à disposition des API avec leur documentation via swagger. Tous les échanges se feront donc en API REST Json avec un échange de token JWT que nous récupérons à l'authentification.

Pour se connecter:

// nous lisons le mot de passe depuis le fichier riot.pass à la racine du projet
pwd := getPasswordFromFile()

// nous préparons une requete post avec en body un json contenant le login et mot de passse
	resp, err := resty.R().
		SetHeader("Content-Type", "application/json").
		SetBody([]byte(`{
		"identifier": {
		  "type": "m.id.user",
		  "user": "` + user + `"
		},
		"initial_device_display_name": "Jungle Phone",
		"password": "` + pwd + `",
		"type": "m.login.password"
	  }`)).
		// SetResult(&AuthSuccess{}).
		Post("https://" + BaseURL + "/_matrix/client/r0/login")

	checkErr(err, "Could not authenticate")
	// fmt.Println(resp, err)

// nous deserialisons la réponse
	var lr loginResponse
	err = json.Unmarshal(resp.Body(), &lr)
	checkErr(err, "Could not decode json of authentication")

	// fmt.Println(lr.Access_token)
	return lr.AccessToken

2) Lecture des 10 derniers messages du salon

Pour lire les messages, il faut envoyer une requete GET au serveur en passant le token et l'identifiant du salon. On limite le nombre de messages directement dans la requête:

// Point d'entrée pour la récupération des messages
respMsg, err := resty.R().Get("https://" + BaseURL + "/_matrix/client/api/v1/rooms/" + RoomID + "/messages?access_token=" + token + "&from=END&dir=b&limit=10")
checkErr(err, "Could not get the messages from matrix API")
// fmt.Printf("%s\n\n---------------\n", respMsg)

// On parse le message reçu à l'aide fastjson
var p fastjson.Parser
m, err := p.Parse(string(respMsg.Body()))
checkErr(err, "Could not decode json of messages")
vals := m.GetArray("chunk")
for _, val := range vals {
fmt.Printf("  (%s) > %s\n", val.GetStringBytes("sender"), val.GetStringBytes("content", "body"))
}

et en l'executant go run main.go on obtient les messages (en fait ici il n'y a en a eu qu'un seul):

3) Envoie de messages dans le salon

Comme c'est un peu vide, nous allons envoyer des messages dans le salon. On reprend la doc des APIs et cette fois on envoie une requete en POST avec le contenu du message dans le body:

respMsg, err := resty.R().
		SetHeader("Content-Type", "application/json").
		SetBody([]byte(`{"msgtype":"m.text", "body":"` + msg + `"}`)).
		Post("https://" + BaseURL + "/_matrix/client/r0/rooms/" + RoomID + "/send/m.room.message?access_token=" + token)

	checkErr(err, "Could not post the message")
	fmt.Println(respMsg)

et nous ajoutons les appels dans le main

Voici 2 exemples d'utilisation des APIs matrix en GO mais n'hésitez pas à consulter la doc swaggers pour découvrir toutes les autres possibilités.