{Slack} – Sauvegarder automatiquement les messages envoyés & reçus

 

Coucou les p'tits loups,

 

 

L'autre jour j'étais à la cafétéria du lieu où je travaille et nous étions à discuter un peu de "Slack".
L'un de nos collègues travaillant dans un autre service que le mien et qui était certainement énervé ce jour-là, a pris la décision de rédiger un long message qui devait , je le pense (je n'ai pas pu le lire) être assez critique à l'égard d'un autre service (peut-être par la multitude de problèmes récurrents auquel son service doit faire face ... et qui sont lié à cet autre service).

Quelques-uns de mes collègues ont entrepris la lecture de ce long message, mais ... hop disparu ... et pas le temps de lire l'intégralité du message.
C'est en effet l'une des choses que je trouve frustrante sur Slack : le fait que les messages ne soient pas persistants.
Hangout, la messagerie de Google, ne permet pas la suppression des messages
Quant à Facebook, il permet de supprimer les messages mais uniquement de votre côté. Le destinataire conserve quant à lui l'ensemble des messages.

 

Par le passé j'ai eu quelques soucis d'ordre juridique, et Slack ... avec cette possibilité de supprimer les messages, m'a donné un peu de fil à retordre.

Bref j'exposais donc à mes collègues une manière assez simple de capturer les messages envoyés & reçus (de tous vos channels en même temps), afin d'éviter les suppressions / modifications  grâce à l'injection des prototypes en Javascript

 

Vulgarisation technique

Les prototypes en Javascript

Tout d'abord, il convient de définir un peu ce qu'est un prototype.
Lorsque vous manipulez des "objets" en Javascript que ça soit des "Chaines de caractère", des données numériques, des tableaux, des WebSockets, des Medias, des éléments du DOM, ...
Vous exploitez des "objets" qui ont été "instanciés", et qui vous fournissent tout un tas de méthode.
Par exemple : pour découper une chaine de caractère en tableau, pour envoyer des messages, gérer des événements, etc ...

let i = 1;
i.toString()

Le code ci-dessus représente la manipulation d'un "objet" de type "number".
Sa valeur est 1, mais si je souhaite le convertir en chaîne, je vais appeler la méthode .toString() 
qui ne me renverra pas 1 mais "1".

Avec les prototypes je peux remplacer le fonctionnement de la méthode .toString() de tous les objets "number" existants et futur en même temps !

Et l'injection dans tout ça ?

Dans l'exemple précédent, j'ai créé une variable "i" et j'y ai accès sans souci.
Mais dans le cas d'une application comme Slack, les messages sont échangés via un WebSocket auquel je n'ai pas accès ...
Je ne connais pas le nom de la variable à laquelle il est assigné, et je n'ai probablement pas la possibilité d'y accéder directement.

C'est donc là qu'intervient l'injection de prototype.

Ce que je sais :
Je sais que Slack utilise les WebSockets donc ... un objet de type "WebSocket".
Je sais également qu'il va certainement utiliser la fonction "send" très régulièrement (envoi d'un message, mise à jour d'un statut, etc ...)

Je vais donc modifier directement la méthode send de l'objet WebSocket via les prototypes

var self = null;
// Je sauvegarde la méthode send pour pouvoir l'utiliser
WebSocket.prototype.send2 = WebSocket.prototype.send;

// Je modifie la vrai méthode send 
WebSocket.prototype.send = function(msg){
	// Je sauvegarde le WebSocket dans une variable auquel j'ai accès.
    self = self ? self : this;
	// Je renvois le retour de la "vrai" méthode send
    return this.send2(msg);
 }

Le code ci-dessus va me permettre d'accéder directement au WebSocket dès qu'un WebSocket utilisera la méthode "send".
Je pourrais ainsi accrocher un "listener" sur l’événement "onmessage" qui recevra tous les messages reçus !

 

Le Script qui permet de récupérer les messages Slack

C'est tout l'objet de l'article, il est donc bien naturel que je vous présente le morceau de code à mettre dans votre console développeur (Sur votre WorkSpace Slack, ouvrez la console avec la touche F12, rendez-vous sur l'onglet "console", copiez ce bout de code, validez avec la touche "entrée").

/*
*	(c) Dyrk 2020 - 2021
*	Backup Slack message in Web Console
*	
*/

var hackOk = false, userNameList = {}, msgList = [];
// Sauvegarde de la méthode send
WebSocket.prototype.send2 = WebSocket.prototype.send2 ? WebSocket.prototype.send2  : WebSocket.prototype.send;
// Surcharge de la méthode send
WebSocket.prototype.send  = function(e){
    if (hackOk) return this.send2(e);
    this.addEventListener('message', (e) =>{
        if (!e.data) return null;
        let user, datas = JSON.parse(e.data), 
            // Reconnaitre les flux de données qui contiennent des messages
            detectMessage = function(obj, usr){
                for (let i in obj){
                    if (typeof obj[i] == 'object' && (i.toString().match(/[0-9]*/) || 
                     ['blocks', 'elements'].indexOf(i.toString()) != -1))
                        detectMessage(obj[i], usr);
                    if (i.toString() == 'text') {
                        // Stockage et affichage des messages
                        msgList.push({date:new Date(), user:usr, msg:obj[i]});
                        console.error('(Slack Dump) - ',usr,' : ', obj[i]);
                    }
                }
        }, 
            // Recherche d'un nom d'utilisateur
            findUserName = function(id){
                let senders = document.getElementsByClassName('c-link c-message__sender_link');
                console.error(senders);
                if (userNameList[id]) 
                    return userNameList[id];
                for (var i in senders){
                    if (typeof senders[i] == 'object' && senders[i].getAttribute('data-message-sender') == id) 
                     return userNameList[id] = senders[i].textContent;
                }
                return "";
        };
        if (datas.type == 'message') 
            detectMessage(datas.blocks, findUserName(datas.user));
    });
    hackOk = true;
};

Vos messages seront accessibles depuis la variable msgList

Je vous fournis également la version "compressée"

var d=document,hackOk=!1,userNameList={},msgList=[];WebSocket.prototype.send2=WebSocket.prototype.send2?WebSocket.prototype.send2:WebSocket.prototype.send;
WebSocket.prototype.send=function(f){if(hackOk)return this.send2(f);this.addEventListener("message",function(e){if(!e.data)return null;e=JSON.parse(e.data);var g=function(b,c){for(var a in b)"object"!=typeof b[a]||!a.toString().match(/[0-9]*/)&&-1==["blocks","elements"].indexOf(a.toString())||g(b[a],c),"text"==a.toString()&&(msgList.push({date:new Date,user:c,msg:b[a]}),console.error("(Slack Dump) - ",c," : ",b[a]))},f=function(b){var c=d.getElementsByClassName("c-link c-message__sender_link");if(userNameList[b])return userNameList[b];
for(var a in c)if("object"==typeof c[a]&&c[a].getAttribute("data-message-sender")==b)return userNameList[b]=c[a].textContent;return""};"message"==e.type&&g(e.blocks,f(e.user))});hackOk=!0};

 

 

Conclusion

Internet est un tableau sur lequel on écrit à l'encre indélébile. Quelles que soient vos actions, elles seront toujours stockés quelque part et peuvent ressortir à n'importe quel moment.

Le fait de pouvoir supprimer ses messages sur Slack n'est pas "cool".
Les messages en question ne sont pas supprimés, d'autant qu'il est parfaitement possible pour l'administrateur de votre "Espace de travail", de consulter l'ensemble des messages.

Voilà, j'espère en tout cas qu'avec ce petit script vous ne manquerez plus une miette des messages croustillants qui pullulent sur Slack.

 

Partagez ce contenu

2 comments

  • Bonjour,

     

    même les messages supprimés sont accessibles à l’administrateur ?

    • Hello Dams,

      Je ne peux te certifier cette information, je sais qu’il existe des options qui permettent aux administrateurs de conserver les messages dans leurs logs.
      Je ne sais pas si ce sont des options payantes.

      Je n’ai pas testé de créer un Workspace Slack :/

      Cela dit un administrateur Slack peut désactiver la possibilité de supprimer / éditer un message.

      J’espère avoir répondu à ta question ;)

Laisser une réponse

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *