initial commit (added files)
authorMarkus Schuster <mail@markus.schuster.name>
Sun, 1 Sep 2013 01:13:37 +0000 (03:13 +0200)
committerMarkus Schuster <mail@markus.schuster.name>
Sun, 1 Sep 2013 01:13:37 +0000 (03:13 +0200)
.hansrc [new file with mode: 0644]
HOWTO [new file with mode: 0644]
hans [new file with mode: 0755]

diff --git a/.hansrc b/.hansrc
new file mode 100644 (file)
index 0000000..f5271e1
--- /dev/null
+++ b/.hansrc
@@ -0,0 +1,2 @@
+password = VeryVerySecret
+debug = 0
diff --git a/HOWTO b/HOWTO
new file mode 100644 (file)
index 0000000..b098daf
--- /dev/null
+++ b/HOWTO
@@ -0,0 +1,29 @@
+################################################################################
+# USAGE
+################################################################################
+# start:
+svc -u /etc/service/hans/
+
+# stop:
+svc -d /etc/service/hans/
+
+# uptime:
+svstat /etc/service/hans/
+
+
+################################################################################
+# INSTALL
+################################################################################
+
+adduser --system --group hans
+
+# copy hans, .hansrc and hans.db to /home/hans/ ; change owner afterwards:
+chown hans: /home/hans/hans /home/hans/hans.db /home/hans/.hansrc
+
+aptitude install libproc-daemon-perl libio-socket-ssl-perl libnet-irc-perl libconfig-auto-perl libdbd-sqlite3-perl daemontools-run
+mkdir -p /etc/service/hans/
+echo '#!/bin/sh
+cd /home/hans/
+exec setuidgid hans ./hans
+' > /etc/service/hans/run 
+chmod 755 /etc/service/hans/run
diff --git a/hans b/hans
new file mode 100755 (executable)
index 0000000..4c72b16
--- /dev/null
+++ b/hans
@@ -0,0 +1,499 @@
+#!/usr/bin/env perl
+# required debian packages: libproc-daemon-perl libio-socket-ssl-perl libnet-irc-perl libconfig-auto-perl libdbd-sqlite3-perl
+# IMPORTANT: /usr/share/perl5/Net/IRC/Connection.pm line 842: s/read/sysread/
+# TODO: Umlaute bei "people" gehen nicht
+# !leave/join solle bei bilbo_b_ gehen (bilbo_b)
+
+use warnings;
+use strict;
+use Config::Auto;
+use DBI;
+use English;
+use Net::IRC;
+#use Proc::Daemon;
+use Data::Dumper;
+use Encode;
+use utf8;
+binmode STDOUT, ':utf8';
+use open ':encoding(UTF-8)';
+
+
+$PROGRAM_NAME = 'hans';
+
+my $config = Config::Auto::parse();
+my $debug = $config->{debug} || 0;
+
+autoflush STDOUT if ($debug);
+#Proc::Daemon::Init() unless ($debug);
+
+# OPEN IRC CONNECTION
+my $irc = new Net::IRC;
+
+my $conn = $irc->newconn(
+       Nick    => $config->{nick} || 'hans',
+       Server  => $config->{server} || 'irc.hackint.org',
+       Port    => $config->{port} || 9999,
+       SSL     => 1
+) or die;
+
+# OPEN DATABASE CONNECTION
+my $dbargs = { AutoCommit => 1, PrintError => 1, sqlite_unicode => 1 };
+my $dbh = DBI->connect('dbi:SQLite:dbname=/home/hans/hans.db', '', '', $dbargs);
+
+# INITIALIZE DATABASE WITH DEFAULTS (IF EMPTY)
+$dbh->do("
+CREATE TABLE IF NOT EXISTS data (
+  key       varchar(200) NOT NULL DEFAULT '',
+  value     mediumtext   NOT NULL DEFAULT '',
+  PRIMARY KEY (key)
+)
+");
+
+$dbh->do("INSERT OR IGNORE INTO data (key, value) VALUES ('keys', '?\n?\n?');");
+$dbh->do("INSERT OR IGNORE INTO data (key, value) VALUES ('hq', 'closed');");
+$dbh->do("INSERT OR IGNORE INTO data (key, value) VALUES ('people', '');");
+# END INITIALIZE
+
+
+
+# STORAGE FUNCTIONS
+sub store_get_value {
+       my $key = shift;
+       my $row = $dbh->selectrow_arrayref("SELECT value FROM data WHERE key='$key';");
+       my ($value) = @$row;
+       return $value;
+}
+
+sub store_get_array {
+       my $value = store_get_value(@_);
+       return split(/\n/, $value);
+}
+
+sub store_set_value {
+       my ($key, $value) = @_;
+       my $sth = $dbh->prepare('UPDATE data SET value = ? WHERE key = ?');
+       $sth->execute($value, $key); 
+}
+
+sub store_set_array {
+       my $key = shift;
+       my @values = @_;
+       my $sth = $dbh->prepare("UPDATE data SET value = ? WHERE key = '$key'");
+       store_set_value($key, join("\n", @values)); 
+}
+
+sub store_add_to_array {
+       my $key = shift;
+       my @values = @_;
+       my @oldvalues = store_get_array($key);
+       @values = array_unique(@oldvalues, @values);
+       store_set_array($key, @values); 
+}
+
+sub store_remove_from_array {
+       my $key = shift;
+       my @values = @_;
+       my @oldvalues = store_get_array($key);
+       # filter array
+       my %h; undef @h{@values};
+       @values = grep !exists $h{$_}, @oldvalues;
+       store_set_array($key, @values); 
+}
+
+
+# STORAGE FUNCTIONS
+
+sub array_unique {
+       my %all = ();
+       @all{@_} = 1;
+       return (keys %all);
+}
+
+
+
+
+sub filter_nickname {
+       my $nickname = shift;
+       $nickname = 'balu'         if ($nickname =~ /^b[a]+[h]*lu$/i || $nickname =~ /^bär$/i);
+       $nickname = 'telegnom'     if ($nickname =~ /^gnom$/i        || $nickname =~ /^gnömchen$/i);
+       $nickname = 'salgar'       if ($nickname =~ /^elfe$/i        || $nickname =~ /^elf$/i);
+       $nickname = 'evilyves'     if ($nickname =~ /^press$/i       || $nickname =~ /^mr.press$/i   || $nickname =~ /^yves$/i);
+       $nickname = 'schMA'        if ($nickname =~ /^schma$/i);
+       $nickname = 'mrm2m'        if ($nickname =~ /^mrmcd$/i);
+       $nickname = 'bilbo_b'      if ($nickname =~ /^hobbit$/i      || $nickname =~ /^bilbo$/i      || $nickname =~ /^halbling$/i);
+       $nickname = 'dachdecker2'  if ($nickname =~ /^dd[2]{0,1}$/i  || $nickname =~ /^dachdecker$/i);
+       $nickname = 'neuernick'    if ($nickname =~ /^volki$/i);
+       $nickname = 'bongo'        if ($nickname =~ /^b[o0]{1,1}ng[o0]{1,1}$/i);
+       return $nickname;
+}
+sub filter_nicknames {
+       my @nicknames = @_;
+       for my $i (0 .. $#nicknames) {
+               $nicknames[$i] = filter_nickname($nicknames[$i]);
+       }
+       return @nicknames;
+}
+
+sub hq_change_key {
+       my ($old, $new) = @_;
+       my $old2 = filter_nickname($old);
+       $new = filter_nickname($new);
+
+       my @keys = store_get_array('keys');
+       for my $i (0 .. $#keys) {
+               if ($keys[$i] eq $old) {
+                       $keys[$i] = $new;
+                       last;
+               }
+               if ($keys[$i] eq $old2) {
+                       $keys[$i] = $new;
+                       last;
+               }
+       }
+       store_set_array('keys', @keys);
+}
+
+sub query_help {
+       my ($conn, $nick, $all) = @_;
+       $conn->privmsg($nick, '!key nick1 nick2     - Schlüssel von nick1 an nick2 übergeben');
+       $conn->privmsg($nick, '!keys                - Schlüsselbesitzer anzeigen');
+       $conn->privmsg($nick, '!close               - HQ auf geschloßen setzen (und alle Leute rausschmeißen)');
+       $conn->privmsg($nick, '!open [nick1 nick2]  - HQ auf geöffnet setzen');
+       $conn->privmsg($nick, '!join [nick1 nick2]  - HQ betreten (und öffnen falls geschloßen)');
+       $conn->privmsg($nick, '!leave [nick1 nick2] - HQ verlassen (alias: !part)');
+       if ($all) {
+               $conn->privmsg($nick, '/![b]+[a]+[h]*[l]+[u]+/i, !press, !raspel, !darkwingduck');
+       }
+}
+
+sub hq_set_topic {
+       my $conn = shift;
+       my $people = join(', ', store_get_array('people'));
+       $people .= ' - ' if ($people ne '');
+       $conn->topic('#ccc-ffm-intern', sprintf('HQ %s - %sKeys: %s', store_get_value('hq'), $people, join(', ', store_get_array('keys'))));
+}
+
+
+sub on_connect {
+       my $conn = shift;
+       my $password = $config->{password} || 'geheim';
+       print "Connected. Identifying...\n" if ($debug);
+       $conn->privmsg('nickserv', "identify $password");
+}
+
+sub on_disconnect {
+       my ($conn, $event) = @_;
+       #$conn->connect();
+       die();
+}
+
+sub on_kick {
+       my ($conn, $event) = @_;
+       my ($user) = ($event->to);
+       my ($channel) = ($event->args);
+       return if ($channel eq '#ccc-ffm');
+       $conn->privmsg($user, "Hallo, der Channel $channel kann nur betreten werden, wenn man auf der Access-Liste steht und eingeloggt ist. Falls du auf der Access-Liste stehst, logge dich bitte ein und versuche es erneut.");
+}
+
+sub on_mode {
+       my ($conn, $event) = @_;
+       my ($arg1, $arg2, $arg3) = ($event->args);
+       if ($arg1 eq '+b' && defined($arg2)) {
+               my ($channel) = ($event->to);
+               return if ($channel eq '#ccc-ffm');
+               $conn->mode($channel, '-b', $arg2);
+               return;
+       }
+        print Dumper($event), "\n" if ($debug);
+}
+
+sub on_notice {
+       my ($conn, $event) = @_;
+       my ($arg) = ($event->args);
+       if ($event->nick =~ /^NickServ$/i && $arg =~ /You are now identified for /i) {
+               print "Identified...\n" if ($debug);
+               $conn->join('#ccc-ffm-intern');
+               $conn->join('#ccc-ffm-vorstand');
+               $conn->join('#ccc-ffm');
+               return;
+       }
+        print Dumper($event), "\n" if ($debug);
+}
+
+sub on_public {
+       my ($conn, $event) = @_;
+       my ($arg) = ($event->args);
+       my ($to) = ($event->to);
+
+       $arg = decode('UTF-8', $arg);
+
+       if ($arg =~ /^!raspel/i) {
+               $conn->privmsg($to, 'http://www.picpaste.de/-2.jpg');
+               return;
+       }
+       if ($arg =~ /!press/i) {
+               $conn->privmsg($to, 'http://www.picpaste.de/press.jpg');
+               return;
+       }
+       if ($arg =~ /^![b]+[a]+[h]*[l]+[u]+/i) {
+               my @lines = (
+                       'Hahahahaha - Balu! Bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm! Und seine Crew! Bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm!',
+                       'O-i-e - Balu! O-i-o - Balu! Freunde sein durch dick und dünn - Balu und seine Crew!',
+                       'O-i-e - Balu!  O-i-o - Balu!  Vogelfrei ein Phänomen - Balu und seine Crew!',
+                       'Bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm bumm!  ...unser Käpt\'n, Freunde!  O-i-e, o-i-e, o-i-o, o-i-o...',
+                       'O-i-e, o-i-e, o-i-o, o-i-o... Sie fliegen um zu siegen, fliegen Fracht und fliegen Ziegen, fliegen bis die Fetzen fliegen, sie sind Sieger wenn sie fliegen! Hahahaha... Unser Käpt\'n Balu'
+               );
+               
+               $conn->privmsg($to, $lines[rand @lines]);
+               return;
+       }
+
+       if ($arg =~ /^!darkwingduck/i) {
+               my $start = 'Ich bin der Schrecken der die Nacht durchflattert, ... ';
+               my $end   = ' ... Ich bin Darkwing Duck!';
+               my @lines = (
+                       'ich bin der Einkaufswagen, der euch den Autolack zerkratzt.',
+                       'ich bin das Abschlusszeugnis, in dem du eine "Sechs" hast.',
+                       'ich bin das Fast Food, dass nachts zurückkehrt, um bei dir zu spuken.',
+                       'ich bin der Wasserballon, der direkt auf deinem Kopf zerplatzt.',
+                       'ich bin die unvorhersehbare Wendung in einem Film.',
+                       'ich bin der Floh, den du nicht erschlagen kannst.',
+                       'ich bin die 10 Dollar Gebühr, die du für einen geplatzten Scheck bezahlen musst.',
+                       'ich bin der eingewachsene Zehenagel im Fuße des Verbrechens.',
+                       'ich bin das Collisterin, dass dir deine Aterien verstopft.',
+                       'ich bin die Motte, die in dein Verandalicht fliegt.',
+                       'ich bin der Spinat, der zwischen deinen Zähnen hängenbleibt.',
+                       'ich bin die Nacktschnecke, die deine Begonien einschleimt.',
+                       'ich bin der Held, den jede Kultur in aller Welt benötigt.',
+                       'ich bin die Weiche, die deinen Zug zum Entgleisen bringt.',
+                       'ich bin der Gefängniswärter, der deinen Zellenschlüssel wegwirft.',
+                       'ich bin die Überraschung in deiner Kelloggs-Packung.',
+                       'ich bin der kalte Schauer, der dir den Rücken herunterläuft.',
+                       'ich bin der Kaugummi, der dir unter dem Schuh kleben bleibt.',
+                       'ich bin der Fleck, den du nicht wegwischen kannst.',
+                       'ich bin die Batterie, die im Preis nicht inbegriffen ist.',
+                       'ich bin der Scheck, der dein Konto überzieht.',
+                       'ich bin der Karrieremann, mit dem alle Frauen unbedingt ein Date wollen.',
+                       'ich bin der Hund, der deine Petunien ausbuddelt.',
+                       'ich bin der Schmutzstiefel, der über das Linolium des Verbrechens schreitet.',
+                       'ich bin die Katze, die jemand aus dem Sack gelassen hat.',
+                       'ich bin das Gold am Ende des Regenbogens.',
+                       'ich bin die Supernova im Mittelpunkt des Universums.',
+                       'ich bin das Scheuerpulver gegen kriminellen Grind.',
+                       'ich bin der Unkrautjäter im Garten des Bösen.',
+                       'ich bin die niedrige Einschaltquote, die deiner Sendung den Garaus macht.',
+                       'ich bin der Buchprüfer, der deine Finanzen durchleuchten wird.',
+                       'ich bin der Hauch einer Chance die du nicht hast.',
+                       'ich bin der Bullterrier, der am Knöchel des Verbrechens knabbert.',
+                       'ich bin der Virus, der deinen Computer zum Abstürzen bringt.',
+                       'ich bin das Adrealin, das dein Blut zum Kochen bringt.',
+                       'ich bin die akribische Pediküre am Fußpilz des Verbrechens.',
+                       'ich bin der Dosenöffner an der Sadinenbüchse der Gerechtigkeit.',
+                       'ich bin der eingewachsene Zehennagel in deinen zu engen Ausgehstiefeln.',
+                       'ich bin die Elster, die dir deinen Goldschmuck stibitzt.',
+                       'ich bin das fettige Fischstäbchen, das dir den Magen umstülpt.',
+                       'ich bin der Gärtner, der deine Hecken schief schnibbelt.',
+                       'ich bin das Haar auf dem Objektiv deiner Filmkamera.',
+                       'ich bin der Haarpfropf, der deinen Abfluß verstopft.',
+                       'ich bin die holländische Bedienungsanleitung zu deinem japanischen Videorecorder.',
+                       'ich bin die Kakerlake, die dir deine Nylonstrümpfe hochkrabbelt.',
+                       'ich bin der Kalk, der dir durchs Großhirn rieselt.',
+                       'ich bin die kleine Maus, die dir deinen Käse klaut.',
+                       'ich bin das Leck in eurem Atomkraftwerk.',
+                       'ich bin die Parkuhr, die abläuft, während du beim Einkaufen bist.',
+                       'ich bin der Plastikhubschrauber in deinem Überraschungsei.',
+                       'ich bin der Pyranja in deinem Zierfisch-Aquarium.',
+                       'ich bin der Radiergummi, der die Rechtschreibfehler des Verbrechens ausradiert.',
+                       'ich bin der Rollsplitt in deinem Schuh der Schande.',
+                       'ich bin der Rostfleck auf eurer Verbrechensrüstung.',
+                       'ich bin der Schakal, der eure Knochen abnagt.',
+                       'ich bin die Schreibmaschine, an der du dir die Fingernägel abbrichst.',
+                       'ich bin der Schuldirektor, der dir einen Verweiß erteilt.',
+                       'ich bin die Spinne, die dir ins Genick springt.',
+                       'ich bin der Taxometer an der Droschke der Gerechtigkeit.',
+                       'ich bin die Termite in deinem Holzbein.',
+                       'ich bin die Wespe auf deinem Marmeladenbrot.',
+                       'ich bin der Wackelkontakt an deiner Lieblingsgitarre.',
+                       'ich bin die Tube Kobaltblau, deren Verschluß eingetrocknet ist.',
+                       'ich bin das Zahlenschloss am Tresor der Gerechtigkeit.',
+                       'ich bin die Stelle auf deinem Rücken, die du nicht kratzen kannst.',
+                       'ich bin das Motorrad, daß die Kanalisation durchknattert. ',
+                       'ich bin der Kratzer auf deiner teflonbeschichteten Bratpfanne.',
+                       'ich bin der Zuschlag, der Deinen Fahrpreis verdreifacht. ',
+                       'ich bin der Sonnenbrand, der dich aussehen lässt, wie ein Dutzent roter Ostereier.',
+                       'ich bin die Migräne, die in deinem Verbrecherschädel tobt. ',
+                       'ich bin der wassergefüllte Luftballon, der auf deinem Kopf zerplatzt.',
+                       'ich bin der Held, der jede Jogurtkultur zum Leben erweckt.',
+                       'ich bin das Schicksal, dass dich unerwartet trifft.',
+                       'ich bin die Nacktschnecke, die deine Salatblätter anknabbert.',
+                       'ich bin der Rauch, der dir den Räucherlachs verräuchert.',
+                       'ich bin der anonyme Anrufer, der dich um 3 Uhr morgens wachklingelt!',
+                       'ich bin die aufgeplatzte Blutblase in deinen neuen Wanderstiefeln!',
+                       'ich bin die Elster, die dir deinen Goldschmuck stibitzt!',
+                       'ich bin die Fünf, die deine Versetzung gefährdet!',
+                       'ich bin der Kugelschreiber, der vom vielen Autogramme schreiben verglüht!',
+                       'ich bin die Motte, die dem Licht deiner Taschenlampe folgt!',
+                       'ich bin der Irre, der sich in einem leeren Bus neben dich setzt.',
+                       'ich bin das Stinktier, das deine Atemluft verpestet.',
+                       'ich bin das Fieberblässchen auf deiner Oberlippe.',
+                       'ich bin der Dietrich zu deinem Geldtransporter.',
+                       'ich bin die Flut der Rache, die durch deinen Abwasserkanal gurgelt.',
+                       'ich bin der hässliche Fleck, der deine Tapete verunziert.',
+                       'ich bin das schwarze Licht an dem du dir die Finger verbrennst.',
+                       'ich bin der Jojo, der dich immer abrollt.',
+                       'ich bin der Kalkfleck in deiner Badewanne, den du nicht abkriegst.',
+                       'ich bin der alte Kaugummi, der am Stiefelabsatz des Verbrechens klebt.',
+                       'ich bin der Glitter auf dem Glitteranzug der Gerechtigkeit.',
+                       'ich bin der Fleck, der sich in deine Seidenkrawatte frisst.',
+                       'ich bin der Kurzschluss in deiner elektrischen Zahnbürste.',
+                       'ich bin der sinnvolle Gestalter der dir die Zeit zum Spielen versaut.',
+                       'ich bin der Terrier, der dir Schnürsenkel abknabbert.',
+                       'ich bin der ledige Erfolgstyp, auf den alle Frauen fliegen.',
+                       'ich bin der selbstsüchtige Narr, der unsere Stadt zu einem Spottpreis verschachert hat.',
+                       'ich bin der Cutter, der deine Szene aus dem Film schnipselt und in den Müll wirft.',
+                       'ich bin der Glockenklöppel, der euch die Ohren malträtiert.',
+                       'ich bin der Himbeerkern, der zwischen deinen Zähnen sitzt.',
+                       'ich bin der gefiederte Quälgeist, der in euren Alpträumen herumgeistert.',
+                       'ich bin der Rauch, der dir den Räucherlachs verräuchert.',
+                       'ich bin der Mückenschwarm, der euch die Windschutzscheibe versaut.',
+                       'ich bin die Schmeißfliege, die in eurer Suppe badet.',
+                       'ich bin der gepfefferte Überziehungskreditzins, der dir das Geldabheben austreibt.',
+                       'ich bin die Bittermandel im Süßmüsli des Guten.',
+                       'ich bin der Amateurfunker, der euch den Empfang verbrezelt.',
+                       'ich bin der Pickel, der sprießt, wenn du mit deinem Liebling ein Rondezvous hast.',
+                       'ich bin die durchgebrannte Sicherung, die dich total lahm legt.',
+                       'ich bin der Mechaniker, der dir sagt, dass deine Garantie abgelaufen ist.',
+                       'ich bin das Backrohr, das deinen Weihnachtsbraten zu Holzkohle verschmurgelt.',
+                       'ich bin die Handlung, die dir den Atem stocken lässt.',
+                       'ich bin die Weltraummotte an deiner UFO-Weltraumscheibe.',
+                       'ich bin die Nacktschnecke, die dir deine Blätter wegspachtelt.',
+                       'ich bin das Jucken das du nicht kratzen kannst.',
+                       'ich bin der anonyme Anrufer, der dich um drei Uhr morgens wach klingelt.',
+                       'ich bin die Zwiebel, die dir die Augen Tränen lässt.',
+                       'ich bin der Griffel, der auf der Schiefertafel deiner Seele quietscht.',
+                       'ich bin der ohrenbetaübende Fingernagelkratzer auf der Schiefertafel der Gerechtigkeit.',
+                       'ich bin der Kaugummi, der dir in den Haaren klebt.',
+                       'ich bin die Kralle , die dir in den Augen hängt.',
+                       'ich bin der Kalkfleck in deiner Badewanne den du nicht abkriegst.',
+                       'ich bin... total am schwitzen!',
+                       'ich bin... ein Straßengrafitty.',
+                       'ich bin die Neurose wegen der du zum Psychiater musst, der 500 Mate-Taler die Stunde kostet.',
+               );
+               
+               $conn->privmsg($to, $start . $lines[rand @lines] . $end);
+               return;
+       }
+               
+       if ($to eq '#ccc-ffm-intern') {
+               if ($arg =~ /^!help\sall/i) {
+                       query_help($conn, $event->nick, 1);
+                       return;
+               }
+               if ($arg =~ /^!help/i) {
+                       query_help($conn, $event->nick, 0);
+                       return;
+               }
+               if ($arg =~ /^!key\s+([\p{Nd}\p{L}?.-_]+)\s+([\p{Nd}\p{L}?.-_]+)/i) {
+                       hq_change_key($1, $2);
+                       hq_set_topic($conn);
+                       return;
+               }
+
+               if ($arg =~ /^!keys/i) {
+                       $conn->privmsg($to, "Keys: " . join(", ", store_get_array('keys')));
+                       return;
+               }
+               if ($arg =~ /^!open\s*$/i) {
+                       store_set_value('hq', 'open');
+                       hq_set_topic($conn);
+                       return;
+               }
+               if ($arg =~ /^!open\s+([\p{Nd}\p{L}?.-_ ]+)/i) {
+                       my @nicks = filter_nicknames(split(/[, ]/, $1));
+                       store_set_value('hq', 'open');
+                       store_add_to_array('people', @nicks);
+                       hq_set_topic($conn);
+                       return;
+               }
+               if ($arg =~ /^!close/i) {
+                       store_set_value('hq', 'closed');
+                       store_set_value('people', '');
+                       hq_set_topic($conn);
+                       return;
+               }
+               if ($arg =~ /^!join\s*$/i) {
+                       store_set_value('hq', 'open');
+                       store_add_to_array('people', filter_nickname($event->nick));
+                       hq_set_topic($conn);
+                       return;
+               }
+               if ($arg =~ /^!leave$/i || $arg =~ /^!part$/i) {
+                       store_remove_from_array('people', filter_nickname($event->nick));
+                       hq_set_topic($conn);
+                       return;
+               }
+               if ($arg =~ /^!join\s+([\p{Nd}\p{L}?.-_ ]+)/i) {
+                       my @nicks = filter_nicknames(split(/[, ]/, $1));
+                       store_set_value('hq', 'open');
+                       store_add_to_array('people', @nicks);
+                       hq_set_topic($conn);
+                       return;
+               }
+               if ($arg =~ /^!leave\s+([\p{Nd}\p{L}?.-_ ]+)/i || $arg =~ /^!part\s+([\p{Nd}\p{L}?.-_ ]+)/i) {
+                       my @nicks = filter_nicknames(split(/[, ]/, $1));
+                       store_remove_from_array('people', @nicks);
+                       hq_set_topic($conn);
+                       return;
+               }
+       }
+    print Dumper($event), "\n" if ($debug);
+}
+
+sub on_msg {
+       my ($conn, $event) = @_;
+       my ($arg) = ($event->args);
+       my ($to) = ($event->to);
+       my $nick = $config->{nick} || 'hans';
+
+       $arg = decode('UTF-8', $arg);
+
+       if ($to eq $nick) {
+               if ($arg =~ /^!help\sall/i) {
+                       query_help($conn, $event->nick, 1);
+                       return;
+               }
+               if ($arg =~ /^!help/i) {
+                       query_help($conn, $event->nick, 0);
+                       return;
+               }
+       }
+    print Dumper($event), "\n" if ($debug);
+}
+
+sub on_nicknameinuse {
+       my $conn = shift;
+       my $nick = $config->{nick} || 'hans';
+       my $password = $config->{password} || 'geheim';
+       print "Nickname $nick is already in use. Sending GHOST command...\n" if ($debug);
+       $conn->privmsg('nickserv', "GHOST $nick $password");
+       $conn->add_default_handler(\&default) if ($debug);
+}
+
+
+
+# DEBUG
+#sub default {
+#        my ($conn, $event) = @_;
+#       print Dumper($event), "\n";
+#}
+
+$conn->add_global_handler('376',               \&on_connect);
+$conn->add_global_handler('disconnect',        \&on_disconnect);
+$conn->add_global_handler('kick',              \&on_kick);
+$conn->add_global_handler('mode',              \&on_mode);
+$conn->add_global_handler('notice',            \&on_notice);
+$conn->add_global_handler('msg',               \&on_msg);
+$conn->add_global_handler('public',            \&on_public);
+$conn->add_global_handler('nicknameinuse',     \&on_nicknameinuse);
+
+$irc->start;