Telegram-Bots mit Node.js

Wie man mit Node.js, der Telegram API und the_coding_love(); jede Menge Spaß haben kann!

Artikelbild

Telegram ist mein Favorit unter den Messengern. Er ist modern, wird permanent weiterentwickelt und er bietet eine wirklich coole Bot-Schnittstelle. Nun möchte ich euch zeigen, wie man diese nutzen kann, um seine eigenen Bots zu bauen.

Der Plan

Ich liebe die Seite thecodinglove.com! Wie wärs, wenn wir ihren Inhalt nutzen, um damit unsere Freunde auf Telegram zuzuspammen? Folgende Features möchte ich einbauen:

  • Der Befehl /random soll zufällig einen Post von der Seite anzeigen
  • Suche: Durch Eingabe von Text, soll man die aktuellsten Einträge durchsuchen und posten können.

Telegram Bots erstellen

Um einen Telegram Bot zu erstellen, muss man mit dem @Botfather sprechen. Dieser Bot verwaltet, wie man vom Namen erwartet, alle Bots auf Telegram. Eine genaue Anleitung dazu findet man (link: https://core.telegram.org/bots/api text: hier).

Zum Erstellen eines neuen Bots benötigt man einen Namen für den Bot (z.B. “TheCodingLoveLover”) und den Usernamen des Bots. Letzterer wird von der Telegram Community verwendet, um damit zu interagieren (z.B. “@theCodingLoveBot …”). Beide Daten werden dem Botfather beim Erstellen übermittelt.

Der generierte API Key wird nun für die Kommunikation mit der Bot-API verwendet.

Erste Schritte

Für die Kommunikation mit der Bot-API verwende ich node-telegram-bot-api. Wer Lust hat, kann auch direkt mit dem (link: https://core.telegram.org/bots/api#making-requests text: Interface von Telegram) arbeiten.

In folgendem Beispiel wird auf den Befehl /hello gehört und entsprechend geantwortet:

// index.js
const token = 'API-KEY';
const TelegramBot = require('node-telegram-bot-api');
const bot = new TelegramBot(token, {polling: true});

bot.onText(/\/hello/, function (msg) {
  bot.sendMessage(msg.chat.id, `Hello ${msg.from.first_name}!`);
});

console.log('bot started');

Gestartet wird das Script mittels Node.js:

node index.js

Erstellung des /random Befehls

Zuerst wird der gewünschte Befehl beim @Botfather mit dem Befehl /setcommands registriert. Das ist zwar nicht notwendig, fügt aber eine praktische Auto-Vervollständigung samt einer Beschreibung zur Interaktion mit dem Bot hinzu.

Der Zufalls-Post von the_conding_love() kommt von folgender URL: http://thecodinglove.com/random. Diese wird mittels request abgerufen und mit (link: https://www.npmjs.com/package/cheerio text: cheerio) gescraped. Danach wird der Titel und die URL des Bildes auf Telegram gepostet. Hier ist der Code dafür:

const token = 'API-TOKEN';
const TelegramBot = require('node-telegram-bot-api');
const bot = new TelegramBot(token, {polling: true});
const cheerio = require('cheerio');
const request = require('request');

bot.onText(/\/random/, function (msg) {
  request(`http://thecodinglove.com/random`, function (error, response, body) {
    var $ = cheerio.load(body);
    var src = $('.post .bodytype img').attr('src');
    var title = $('.post h3').text();

    if (src && title) {
      bot.sendMessage(msg.chat.id, `${title}\n${src}`);
    }
  });
});

console.log('bot started');

Nun kann man schon seine Bekannten damit beglücken. Einfach diesen Bot in eine Gruppe einladen und loslegen 😎 .

Die Suche

Die Suche ist schon etwas komplexer. Dafür kommen Telegrams Inline-Queries zum Einsatz.

Hinweis: Um das Beispiel einfach zu halten, habe ich mir einen JSON-Dump des RSS Feeds der Seite heruntergeladen. Dieser wird von mir benutzt, um die Inline-Queries zu demonstrieren. Natürlich kann dieser direkt aus dem Internet abgegriffen werden. Lasst eurer Kreativität freien Lauf!

Das Prinzip von Inline-Queries ist folgendes: Anstatt einen Befehl in den Chat zu schreiben, richtet man die Anfrage direkt an den Bot, z.B. @harrerBot meine Suche. Diese Anfrage (im Beispiel: “meine Suche”) wird an das Script weitergereicht. Damit kann man nun beliebige Datenquellen durchsuchen und Vorschläge an den Chat zurücksenden. Diese Vorschläge können beliebige Medien, wie z.B. Bilder, Videos, Artikel, Location und so weiter, sein. Eine Auflistung der unterstützten Medien findet ihr hier.

In meinem Fall werden alle gefundenen Artikel als Vorschau angezeigt. Sobald der Benutzer einen Artikel auswählt, wird die URL davon gepostet.

Hier ist der Code dafür:

var json = require('./coding-love-rss.json');

function toReply(item) {
  return {
    type: 'article',
    id: item.guid,
    title: item.title,
    input_message_content: {
      message_text: `
      ${item.link}`
    },
    thumb_url: 'http://static.tumblr.com/6a221d4ddb5859ffe4fc9f29bd4f7f13/eckq4is/iw5nxzeot/tumblr_static_3z2j8coqrjggc044o8os8s4w4.png',
    thumb_width: 320,
    thumb_height: 320,
    url: item.link
  }
}

function getArticle(q) {
  var pattern = new RegExp(q, 'i');
  var matches = json.items.filter(function(item) {
      return pattern.test(item.title);
  });

  matches = matches.map((item) => toReply(item));

  return matches;
}

bot.on('inline_query', function (msg) {
  bot.answerInlineQuery(msg.id, getArticle(msg.query)).then(function() {
    console.log('answer sent');
  }, function(err) {
    console.error(err);
  });
});

Die eigentliche Suche findet in der Methode getArticle(q) statt. Hier werden einfach die Titel der Artikel mit Hilfe einer einfachen Regex gefiltert. Die gefundenen Artikel werden dann mit toReply(item) in das von Telegram erwartete Format gebracht. Das ist ein Array von - je nach Datentyp unterschiedlich formatierten - Objekten.

Fertig ist unsere prototypische Suche! 🙌

##Und noch Vieles mehr

Das war ein kurzer Einblick in das Thema Telegram-Bots. Der Fantasie wird hier keine Grenze gesetzt!

Nur als kleines Beispiel: Philip von Deloarts hat mich inspiriert, einen Bot zu schreiben, welcher ein Foto über eine an einem Raspberry Pi angesteckten Webcam zu machen und zu posten. Mal abgesehen vom Sicherheitsaspekt und Privacy-Lücken, war meine Heimüberwachung damit fertig umgesetzt.

Falls man einen Raspberry Pi zur Hand hat, könnte man darauf einen selbstgebauten Bot hosten. Mehr dazu könnt ihr hier lesen: NODE.JS UND MONGODB AM RASPBERRY PI

Feedback