J'ai publié ce guide avant de faire évoluer signal-sdk. Certains exemples parlaient encore de registerCommand, d'un Java 17 ou 21 et d'une API de réponse qui n'existe plus dans le SDK actuel. Je le réécris ici pour que tu puisses suivre les exemples sans tomber sur une méthode retirée.
Si tu veux le tutoriel complet, avec le contexte du projet et les conseils de déploiement, lis aussi le guide récent sur l'envoi de messages Signal. Cette page garde son ancienne URL pour ne pas casser les liens déjà partagés, mais le code ci-dessous correspond à l'API actuelle.
Ce que fait le SDK
signal-sdk est une couche TypeScript autour de signal-cli. Je laisse signal-cli gérer l'identité du compte, les clés et le protocole Signal. Le SDK lance le processus, parle JSON-RPC avec lui et expose une API Node.js pour envoyer des messages, écouter des événements ou construire un bot.
Tu as deux niveaux d'utilisation :
SignalClipour piloter directement le compte ;SignalBotpour les commandes, les administrateurs et le cycle de vie d'un bot.
Signal ne fournit pas ici une API officielle. Il te faut un compte et un appareil lié, de préférence dédiés à l'automatisation.
Installer et lier un appareil
Le paquet demande Node.js 18 ou plus récent :
npm install signal-sdk
Le script d'installation récupère le binaire signal-cli. Linux utilise la distribution native. Sur macOS et Windows, installe aussi Java 25 ou plus récent :
node --version java -version
Lance l'assistant de liaison :
npx signal-sdk connect "Mon appareil signal-sdk"
Scanne le QR code dans Signal → Paramètres → Appareils liés → Lier un nouvel appareil. Conserve ensuite le dossier de données de signal-cli, notamment si tu utilises Docker. Il contient l'identité et les clés du compte.
Envoyer un message avec SignalCli
Je garde les numéros dans l'environnement et j'utilise le format E.164 :
SIGNAL_PHONE_NUMBER=+33600000000 SIGNAL_RECIPIENT=+33700000000
import 'dotenv/config'; import { SignalCli } from 'signal-sdk'; const phoneNumber = process.env.SIGNAL_PHONE_NUMBER; const recipient = process.env.SIGNAL_RECIPIENT; if (!phoneNumber || !recipient) { throw new Error('SIGNAL_PHONE_NUMBER et SIGNAL_RECIPIENT sont requis'); } const signal = new SignalCli(phoneNumber, undefined, { maxRetries: 3, retryDelay: 1_000, minRequestInterval: 500, }); try { await signal.connect(); await signal.sendMessage(recipient, 'Sauvegarde terminée.'); } finally { await signal.gracefulShutdown(); }
Le processus reste ouvert tant que la connexion est active. gracefulShutdown() ferme le daemon enfant proprement et évite de laisser un processus tourner après une tâche ponctuelle.
Écouter les messages entrants
SignalCli émet l'événement message. Je vérifie le contenu avant de répondre, car une enveloppe peut contenir une pièce jointe ou un événement sans texte :
signal.on('message', (message) => { const text = message.dataMessage?.message; const source = message.source; if (text?.trim().toLowerCase() === 'ping' && source) { void signal.sendMessage(source, 'pong'); } });
Pour un bot qui possède plusieurs commandes, passe à SignalBot plutôt que de faire grandir cet écouteur.
Créer une commande avec SignalBot
L'API actuelle utilise addCommand(). Le handler peut retourner une chaîne, et adminOnly réserve la commande aux administrateurs :
import 'dotenv/config'; import { SignalBot } from 'signal-sdk'; const phoneNumber = process.env.SIGNAL_PHONE_NUMBER; const admin = process.env.SIGNAL_ADMIN_NUMBER; if (!phoneNumber || !admin) { throw new Error('SIGNAL_PHONE_NUMBER et SIGNAL_ADMIN_NUMBER sont requis'); } const bot = new SignalBot({ phoneNumber, admins: [admin], settings: { commandPrefix: '/', cooldownSeconds: 3, logMessages: false, }, }); bot.addCommand({ name: 'statut', description: 'Retourne le statut du service', adminOnly: true, handler: async () => `Disponible depuis ${Math.round(process.uptime())} secondes.`, }); bot.on('error', (error) => { console.error('Erreur du bot Signal :', error); }); await bot.start();
Le bot inclut déjà /help, /ping, /stats et /info. Je désactive les logs de messages dès que le bot sort du test local : le contenu des conversations ne doit pas se retrouver dans un fichier de log général.
Ce que je vérifie avant de déployer
Je monte le dossier de données sur un volume persistant. Sans ce volume, un redéploiement peut créer une nouvelle identité et déclencher un changement de numéro de sécurité chez les correspondants.
Je limite aussi les destinataires, le nombre de messages par heure et les tentatives consécutives. Le SDK ralentit déjà les requêtes et réessaie certaines erreurs, mais il ne doit pas servir à diffuser des messages en masse.
Enfin, je garde .env, les clés locales et les journaux hors du dépôt. Un compte Unix dédié et des permissions minimales suffisent à éviter beaucoup d'erreurs banales.
Changelog de cet article
- Installation : le guide utilise maintenant
npm install signal-sdket Node.js 18+. - Java : macOS et Windows demandent Java 25 ou plus récent avec la distribution actuelle de
signal-cli. - Commandes de bot :
registerCommand()devientaddCommand(). - Réponses : le handler peut retourner une chaîne ; les exemples ne reposent plus sur un
msg.reply()qui n'est pas exposé par l'API actuelle. - Arrêt : les exemples appellent
gracefulShutdown()pour fermer le processus proprement. - Sécurité : les exemples utilisent un compte dédié, des variables d'environnement et des logs de messages désactivés.
Le code du SDK et ses tests sont disponibles sur GitHub. Pour partir de zéro, utilise plutôt le tutoriel récent ; cette page sert de référence mise à jour pour l'ancien lien.
Article co-écrit avec l'IA · Images générées avec l'IA.
