Open Source im professionellen Einsatz
Linux-Magazin 11/2009
© Ahermes, Photocase.com

© Ahermes, Photocase.com

Perl-Skript loggt Chat-Sessions

Der Protokollant

Trotz Konkurrenz durch andere Messenger, Twitter & Co.: IRC ist populär wie nie. Das Chat-Protokoll lässt außerdem selbst geschriebene Bots als automatische Helferlein zu. Im folgenden Beispiel protokolliert ein solcher Bot die Sitzung und archiviert sie in einer Datenbank.

791

Bei Konferenzen, beim Support von Open-Source-Produkten oder bei Aktionen, die eine Koordination vieler Projektmitarbeiter erfordern, ist Internet Relay Chat, kurz IRC, nach wie vor die Nummer eins unter den Instant-Message-Angeboten. Weder die mächtige Konkurrenz von Yahoo oder Microsoft noch das offene Google-Talk-Protokoll waren bislang in der Lage, den Dinosaurier der Gruppenkommunikation aufs Altenteil zu schieben.

Das in [2] schon einmal im Zusammenhang mit einem Hitzefühler kurz vorgestellte Modul Bot::BasicBot wickelt die Kommunikation zwischen Perl-Skript und IRC-Server so geschickt ab, dass zum Programmieren eines Bot tatsächlich weniger als zehn Zeilen Code notwendig sind. Das Modul Bot::BasicBot::Pluggable treibt das Konzept noch etwas weiter, indem es selbst geschriebene Bots mit Plug-ins ausstattet, die die Teilnehmer einer Chat-Session durch spezielle Nachrichten aktivieren können. Fühlt sich ein Plugin angesprochen, führt es die ihm gestellte Aufgabe aus und schickt die Antwort zurück in den Chat.

Verzweifelt gesucht

Dabei enthält das CPAN-Modul von Haus aus etliche nützliche, voll funktionsfähige Plugins, die der Programmierer einfach über die »load()«-Methode aktiviert. Listing 1 zeigt die vollständige Implementierung eines Skripts, das sich in einen IRC-Channel einklinkt und zwei verschiedene Plugins aktiviert.

Listing 1:
»botstart«

01 #!/usr/local/bin/perl -w
02 use strict;
03 use Bot::BasicBot::Pluggable;
04
05 my $bot = Bot::BasicBot::Pluggable->new(
06     channels => ["#perlsnapshot"],
07     server   => "irc.freenode.net",
08     nick     => "snapshot-bot",
09 );
10
11   # 'Seen' module: remembers when and where
12   # participants were last seen
13 $bot->load("Seen");
14
15   # DNS module: responds to "nslookup"
16   # messages by looking up IP addresses
17 $bot->load("DNS");
18
19   # Connect to IRC server
20 $bot->run();

Das Seen-Plugin merkt sich, welche Teilnehmer sich an- und abmelden, und verrät auf das Kommando »seen Username« hin, wann der angegebene Teilnehmer zuletzt online war (Abbildung 1). Das ist besonders hilfreich, falls er sich gerade nicht im Chat aufhält. Das zweite von »botstart« aktivierte Plugin, DNS, implementiert eine einfache Schnittstelle zum Unix-Kommando »nslookup«. Es antwortet auf das Kommando »nslookup Hostname« mit der vom DNS-Server zurückgelieferten IP-Adresse für den fraglichen Hostnamen (Abbildung 2).

Abbildung 1: Das Seen-Modul des Bot merkt sich, wer kommt und geht, und gibt auf Anfrage preis, wann es einen Teilnehmer zuletzt gesichtet hat.

Abbildung 2: Das DNS-Modul wartet auf Nachrichten, die mit »nslookup« beginnen, und löst den nachfolgenden Hostnamen in eine IP-Adresse auf.

Der nach dem Baukastensystem erweiterbare Bot nimmt von Teilnehmern sogar Befehle zum Laden neuer Plugins entgegen. Konfiguriert man den Bot mit »$bot->load(\'Loader\')«, darf jeder Teilnehmer nach Belieben im Lademechanismus des Bot herumfuhrwerken. Auf die Nachricht »!load DNS« lädt der Bot das DNS-Modul, auf »!unload DNS« deaktiviert er es wieder.

Das ist zwar riskant und Bot::BasicBot:: Pluggable versucht die Möglichkeiten mit einem »Auth«-Modul für Nutzer einzuschränken. Aber dieses Verfahren ist, wie die Dokumentation zugibt, leicht auszuhebeln, also nicht empfehlenswert.

Bitte mitschreiben

Ein neues Plugin ist schnell erstellt. Bot-Schreiber leiten neue Plugin-Klassen einfach von der Basisklasse Bot::BasicBot:: Pluggable::Module ab. Wie Listing 2 »Log.pm« zeigt, sind lediglich einige Methoden zu überladen, um ein voll funktionsfähiges Plugin-Modul aus dem Boden zu stampfen. Die Methode »init()« ruft das Plugin-Framework einmal auf, wenn das Plugin nach dem Programmstart einzubinden ist. Da eine Referenz auf das Plugin-Objekt beiliegt, nutzt »init()« in »Log.pm« die Gelegenheit, den persistenten Datenspeicher Cache::Historical zu initialisieren und eine Referenz darauf im Objekt abzuspeichern. Später, in der Methode »told()«, holt es diese Referenz wieder hervor, um ein gerade aufgeschnapptes Konversationsschnipsel dort abzulegen.

Listing 2:
»Log.pm«

01 ###########################################
02 package
03      Bot::BasicBot::Pluggable::Module::Log;
04 use warnings;
05 use strict;
06 use base
07       qw(Bot::BasicBot::Pluggable::Module);
08 use Cache::Historical 0.03;
09 use Log::Log4perl qw(:easy);
10
11 our $SQLITE_FILE = "irclog.dat";
12
13 ###########################################
14 sub init {
15 ###########################################
16     my($self) = @_;
17
18     $self->{logbot_cache} =
19         Cache::Historical->new(
20             sqlite_file => $SQLITE_FILE,
21         );
22 }
23
24 ###########################################
25 sub help { 
26 ###########################################
27     return "Logs chats in SQLite";
28 }
29
30 ###########################################
31 sub told {
32 ###########################################
33     my ($self, $msg) = @_;
34
35     my $val = "$msg->{who}: $msg->{body}";
36     my $key = $msg->{channel};
37     my $dt  = DateTime->now(
38                      time_zone => "local");
39
40     DEBUG "$dt $val";
41
42     $self->{logbot_cache}->set(
43         $dt, $key, $val );
44
45     return "";
46 }
47
48 1;

Cache::Historical vom CPAN entstand eigentlich mit Blick auf Aktienkurse, die es gemeinsam mit dem jeweiligen Datum in einer SQLite-Datenbank speichert. Aber das Format eignet sich genauso für Chat-Nachrichten, die dort ebenfalls unter einem Schlüssel (dem Chatroom) und mit dem aktuellen Zeitstempel Platz finden. Die Variable »$SQLITE_FILE« in Zeile 11 von Listing 2 gibt die Lage der SQLite-Datei im Filesystem an und ist eventuell in einen absoluten Pfad umzuwandeln oder anderweitig an die lokalen Gegebenheiten anzupassen. Die Methode »help()« ist vorgeschrieben und liefert einen kurzen Hilfetext zurück, damit Anwender wissen, was das Plugin eigentlich treibt.

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Geiz ist geil

    Ein Perl-Skript verfolgt für Schnäppchenjäger die Preisentwicklung auf Amazon und schlägt per E-Mail freudig Alarm, falls sich überwachte Produkte plötzlich verbilligen.

  • Kurvendiskussion

    Zahlenreihen taugen vielleicht für gelangweilte Buchhalter, nicht aber für Programmierer. Die bevorzugen Grafiken, besonders wenn sie den Wertverlauf ihres Aktienportfolios beschreiben. Das vorgestellte Perl-Skript zeichnet Turmdiagramme und hilft die Performance im Auge zu behalten.

  • Seid umschlungen, Millionen!

    Das Perl-Skript »dagobert« zeigt auf Kommando die aktuellen Vermögensverhältnisse seines Besitzers an. Es rechnet den Inhalt mehrerer Konten und Aktiendepots zusammen und gestattet es dem Anwender, eigene Plugins einzuhängen.

  • Perl-Snapshot

    Viele Ubuntu-User wissen gar nicht, dass ihnen der Zeitgeist-Daemon heimlich über die Schulter schaut und ihre Desktop-Aktionen mitprotokolliert. Einige Perl-Skripte bereiten die Lauscherberichte auf und bringen interessante Tatsachen über die Usergewohnheiten ans Tageslicht.

  • Schädlingsbekämpfung

    Spammer senden nicht nur E-Mails, sie nisten sich auch in Diskussionsforen und Blogs ein, um mit Link-reichen Pseudopostings die großen Suchmaschinen hinters Licht zu führen. Ein Perl-Skript macht sauber.

comments powered by Disqus

Ausgabe 09/2016

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.