Il bridge è essenzialmente trasparente: chatti su IRC, reinoltra su Telegram; chatti su Telegram, reinoltra su IRC; tutti vedono tutto.
La principale limitazione (tipica di molti bridge) è che non è possibile ottenere una lista completa degli utenti: l'utente virtuale del bridge "nasconde" quelli presenti dall'altro lato.
Su Telegram: è possibile (per ora), visualizzare la lista degli utenti su IRC inviando nel gruppo telegram il comando /names, ma probabilmente verrà presto rimossa perché il comando non è limitabile a precisi momenti o utenti.
- Su IRC: non è possibile ottenere la lista degli utenti del gruppo Telegram. Si può "apprendere" il nick di un utente solo quando questo si unisce al gruppo o manda qualche messaggio.
Altre info utili:
Policy (update: 20170515)
Il servizio di bridging è mantenuto secondo una logica as-is, best-effort.
Al momento non ho piani precisi per lo storage a lungo termine della cache dei media. Lo spazio a disposizione è 45 GiB circa. Il bridging ha potenziale per trasformarsi in un log onnicomprensivo delle chat Ninux, quindi se sarà possibile tenere tutti i file lo farò. Servirebbe implementare un management più raffinato di un cache-everything, però.
Bug Noti
- nei file inviati via telegram, la didascalia non viene propagata ad IRC
- le modifiche dei messaggi su telegram non vengono propagate ad IRC
TODO
Bot Telegram
L'interazione programmatica con il servizio di messaggistica istantanea Telegram avviene attraverso dei "bot", dei software che creano un profilo telegram con cui è poi possibile chattare, sia singolarmente che in chat di gruppo, impartendo loro comandi, mettendoli in attesa di particolari eventi o messaggi che scateneranno le azioni desiderate. In due parole: sono "utenti" telegram programmabili.
Per creare un bot, si chatta con un super-bot chiamato @botfather. Per aprire una chat con botfather basta cercarlo nel campo ricerca globale del proprio client telegram. Ecco come si svolge la chat di creazione di un bot TeleIRC: se qualcosa non tornasse, basta semplicemente seguire le istruzioni passo-passo che il bot ci sputerà contro dopo ogni nostra parola. Tra parentesi quadre commenti a margine da leggere, ma non digitare.
Noi:: /newbot
botfather: Alright, a new bot. How are we going to call it? Please choose a name for your bot.
Noi:: Ninux.org TeleIRC Bridge [il "nome e cognome" del nostro bot, sarebbe il nome per esteso che comparirà nelle bolle-messaggio]
botfather: Good. Now let's choose a username for your bot. It must end in bot. Like this, for example: ~TetrisBot or tetris_bot.
Noi:: ninuxorg_teleircbot [questo sarà un "nickname" per il bot, che si potrà menzionare con la @nomecheabbiamoappenascritto. Deve terminare in "bot"]
botfather: Done! Congratulations on your new bot. You will find it at t.me/ninuxorg_teleircbot. ... Use this token to access the HTTP API: numeriacaso:altrarobaacaso ...
Noi:: /setprivacy [dobbiamo permettere al bot di accedere a tutti i messaggi postati dal nostro gruppo]
botfather: Choose a bot to change group messages settings.
Noi:: @ninuxorg_teleircbot [digitiamo o selezioniamo il nick del nostro bot, specificato al passo precedente]
botfather: ... Current status is: ENABLED
Noi:: Disable [occhio a digitarlo esattamente così]
botfather: Success! The new status is: DISABLED. /help
Noi:: /setabouttext
botfather: Choose a bot to change the about section.
Noi:: @ninuxorg_teleircbot [digitiamo o selezioniamo il nick del nostro bot, specificato al passo precedente]
botfather: OK. Send me the new 'About' text. People will see this text on the bot's profile page and it will be sent together with a link to your bot when they share it with someone.
Noi:: [massimo 120 caratteri per descrivere il nostro bot, che compariranno nel suo profilo]
botfather: Success! About section updated. /help
Noi:: /setdescription
botfather: Choose a bot to change description.
Noi:: @ninuxorg_teleircbot [digitiamo o selezioniamo il nick del nostro bot, specificato al passo precedente]
botfather: OK. Send me the new description for the bot. People will see this description when they open a chat with your bot, in a block titled 'What can this bot do?'.
Noi:: [una descrizione più lunga di cosa farà il nostro bot, che comparirà a chiunque cominci una chat col nostro bot]
botfather: Success! Description updated. /help
Noi: /setuserpic
botfather: Choose a bot to change profile photo.
Noi:: @ninuxorg_teleircbot [digitiamo o selezioniamo il nick del nostro bot, specificato al passo precedente]
botfather: OK. Send me the new profile photo for the bot.
Noi: [carichiamo la foto profilo che vogliamo per il nostro bot]
Quello che abbiamo fatto in sintesi è:
A questo punto non ci resta che aggiungere il nostro bot nei gruppi telegram per il quali dovrà fare da bridge.
TeleIRC
Installazione
N.B.: Questo howto non copre la parte di installazione, configurazione e messa in sicurezza del sistema operativo server, macchina virtuale o container che ospiterà il servizio, ma solo le istruzioni specifiche per TeleIRC.
TeleIRC è basato sul runtime javascript Node.js. Per installare una versione aggiornata di Node.js utilizzeremo i repository NodeSource (disponibili per molteplici distribuzioni Linux).
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs
Prima di proseguire con l'installazione di TeleIRC, installiamo librerie e toolchain necessarie:
sudo apt-get install build-essentials libicu-dev
Installiamo TeleIRC attraverso il gestore pacchetti di Node.js
sudo npm install -g teleirc
Utente ad-hoc
Eseguiremo il bot col suo proprio utente, applicando il principio del minimo privilegio:
sudo adduser teleirc
sudo su - teleirc
config.js
Una volta completata l'installazione, generiamo la configurazione di partenza di teleirc, che risiederà in ~/.teleirc/config.js e che poi personalizzeremo:
mkdir ~/.teleirc
teleirc --genconfig
Apriamo il file appena generato col nostro editor di testo per terminale preferito e cominciamo ad editarlo nei punti chiave. Segue la versione appuntata in italiano del file, che rappresenta anche la configurazione in essere per l'istanza in uso da Ninux:
var config = {};
module.exports = config;
/////////////////////
// General config //
/////////////////////
// livello di dettaglio dei log, dal più dettagliato al meno
// silly, debug, verbose, info, warn, error
config.logLevel = 'info';
// NINUX: copioincollare il token fornito da botfather
config.tgToken = 'numeriacaso:robaacaso';
// NINUX: i cambi topic IRC vengono annunciati su Telegram
config.sendTopic = true;
// NINUX: ingressi e uscite dal canale non vengono annunciati su telegram
// NINUX: sennò usciamo pazzi
config.sendNonMsg = false;
// NINUX: il nostro bridge salva foto, file, messaggi vocali e qualsiasi media Telegram
// NINUX: e li rende disponibili su IRC inviando un link
config.showMedia = true;
// NINUX: la URL conterrà 8 caratteri a caso per evitare che sia facilmente predicibile
config.mediaRandomLength = 8;
// NINUX: Se il bot si disconnette e poi riconnette, alla sua riconnessione NON inoltrerà
// NINUX: i messaggi telegram più vecchi di tot secondi, configurabili qui
// NINUX: un valore molto alto rischia di inondare il canale con tantissimi messaggi
// NINUX: se il bot rimane disconnesso per molto tempo
// NINUX: per il momento lasciamo 1 minuto, calibreremo col tempo
config.maxMsgAge = 60;
// Porta HTTP per servire i media cachati
config.httpPort = 9090;
// NINUX: La URL dei media sarà http://teleirc.ninux.org:9090/8numeriacaso/file.ext
config.httpLocation = 'http://teleirc.ninux.org' + ':' + config.httpPort;
// NINUX: usando /command davanti al proprio messaggio telegram
// NINUX: il bot eviterà di anteporre il nostro nick telegram
// NINUX: quando pubblicherà il messaggio su IRC
// NINUX: è potenzialmente utile per inoltrare comandi IRC puri
// NINUX: al momento disabilitata perché non funziona bene col meetbot
config.allowCommands = false;
//////////////////
// IRC config //
//////////////////
// NINUX: il bot colorerà i nick degli utenti telegram
// NINUX: li rende facilmente distinguibili agli utenti IRC
// NINUX: attivata perché ovvia bene alla mancanza degli utenti telegram
// NINUX: nella lista degli utenti IRC
config.nickcolor = true;
// Nick color palette
config.palette = [
'white', 'silver', 'navy',
'green', 'red', 'brown',
'purple', 'olive', 'yellow',
'lime', 'teal', 'cyan',
'pink', 'blue'
];
// If soloUse is true, send all messages without username preview, intented
// to use telegram as a limited IRC client.
config.soloUse = false;
// NINUX: I prossimi due parametri decidono come compaiono gli utenti telegram su IRC
// NINUX: la prima scelta è il nick, se specificato dall'utente
// NINUX: se l'utente non ha un nick, usiamo nome-cognome
config.nameFormat = '%username%';
config.usernameFallbackFormat = '%firstName% %lastName%';
// NINUX: i ritorni a capo nei messaggi Telegram vengono sostituiti da 3 puntini sospensivi
// NINUX: prima di venire reinoltrati su IRC
// Volendo si può utilizzare \n per specificare di mantenere i ritorni a capo
config.replaceNewlines = ' … ';
config.ircNick = 'ninux-telegram';
config.ircServer = 'irc.freenode.net';
// NINUX: qui si potrà eventualmente istruire il bot ad effettuare il login su freenode
config.ircPerformCmds = [];
// NINUX: elenco dei bridge IRC-Telegram gestiti da questa istanza del bot
// NINUX: ne usiamo due: una per i canali ufficiali e una per testing e debug
config.channels = [
// NINUX: Bridge tra #teleircnnx (IRC) e TeleIRC Testing (TG)
{
ircChan: '#teleircnnx',
tgGroup: 'TeleIRC Testing'
},
// NINUX: Bridge tra #ninux.org (IRC) e Ninux.org (TG)
{
ircChan: '#ninux.org',
tgGroup: 'Ninux.org'
}
];
// NINUX: Elenco delle opzioni di connessione alla rete IRC
// NINUX: Istanziano un oggetto della libreria Node.js Node-IRC
// NINUX: Utilizzata da TeleIRC
// see https://node-irc.readthedocs.org/en/latest/API.html#client
config.ircOptions = {
userName: 'ninux-telegram', // NINUX: Nickname e nome esteso del bot su IRC
realName: 'Ninux.org TeleIRC Bot', // NINUX: Nickname e nome esteso del bot su IRC
port: 7070, // NINUX: Connessione ad una delle porte TLS di FreeNode
localAddress: null,
showErrors: false,
autoRejoin: true, // NINUX: ci riconnettiamo automaticamente in caso di down
autoConnect: true, // NINUX: join immediato dopo la connessione al server
channels: [], // auto generated, do not touch
secure: true, // NINUX: connessione SSL
selfSigned: true, // NINUX: accettiamo certificati self-signed
certExpired: false,
floodProtection: true,
floodProtectionDelay: 1000,
sasl: false,
stripColors: true,
channelPrefixes: '&#!',
messageSplit: 512,
encoding: ''
};
// NINUX: effettuiamo il relay di tutti i messaggi da IRC a Telegram
config.ircRelayAll = true;
// si può configurare una espressione regolare per reinoltrare solo messaggi specifici
var regex = '^ *(?:' + config.ircNick + '[:,]?|!) +(.*\\S.*)$';
config.hlRegexp = new RegExp(regex, 'i');
// if there was a match, should we only show the parenthesized substring match?
// with the default regexp this would hide the bot nickname in messages when
// highlighted
config.hlOnlyShowMatch = false;
Primo avvio
Verifichiamo che tutto funzioni avviando TeleIRC in modalità ultra-verbosa, con teleirc -vvv. Dovremmo
- vedere comparire nella lista utenti di IRC il nostro bot
- scrivendo messaggi da ambedue i lati, verderli reinoltrati sull'altro
Autoboot
Systemd utilizza, oltre all'init di sistema con PID 1, anche un processo (user mode, --user) per ogni utente che nasce e muore al login/logout di quell'utente e permette a ciscuno di essi di gestire i propri service/socket/unit/mount systemd in maniera autonoma.
Affinché l'istanza di systemd per ogni utente possa avviarsi, è necessaria la libreria PAM per Systemd:
sudo apt-get install libpam-systemd
Il file service per il bot risiederà nella directory
cd
mkdir -p .config/systemd/user/
$EDITOR .config/systemd/user/teleirc.service
dove $EDITOR è il nostro editor di testo CLI preferito.
Il contenuto del file sarà
[Unit]
Description=Telegram-IRC bridging bot
After=network-online.target oidentd.socket
[Service]
ExecStart=/usr/bin/env node /usr/bin/teleirc -vv
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
[Install]
WantedBy=default.target
Aggiugiamo in ~/.profile le seguenti variabili d'ambiente, in fondo al file. Dopo averle aggiunte sarà necessario riloggarsi con l'utente teleirc affinché abbiano effetto:
export DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/`id -u`/bus
export XDG_RUNTIME_DIR=/run/user/`id -u`
Testiamo il nostro file service con
# notare --user e l'assenza dei privilegi di root per l'uso di systemd
systemctl --user start teleservice
Se tutto andrà bene, vedremo uno stato del genere:
systemctl --user status teleirc
● teleirc.service - teleirc
Loaded: loaded (/home/teleirc/.config/systemd/user/teleirc.service; disabled; vendor preset: enabled)
Active: active (running) since Sun 2017-05-14 18:12:40 CEST; 1 day 2h ago
Main PID: 3334 (node)
CGroup: /user.slice/user-1000.slice/user@1000.service/teleirc.service
└─3334 node /usr/bin/teleirc -vv
A questo punto potremo abilitare definitivamente il servizio per l'autostart
systemctl --user enable teleirc
Non basta però: di default le istanze per-utente systemd si avviano solo al primo login e terminano dopo il logout. Per avviarle e lasciarle in esecuzione è necessario abilitarle con
sudo loginctl enable-linger teleirc