#!/usr/bin/perl # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This script "bluebot" is made 2004-2007 by Dennis G. # Look at http://www.gnu.org/licenses/gpl.txt # # To use it, just put in the server it should connect to, # the initial nickname, the channels to join initially, the password etc. # # to auth with the bot message him "auth password", example: # /msg bluesbot auth 12345 # you can then let it join and part channels with "join #channel" # and "part #channel", and you can make it say something # inside a channel or to a person with "say #channel hello" # and "say person hello" # you can also let it change the nick afterwards with # change nick newnickname # with "custom irc-command" you can execute the standard irc commands # for example: /msg bluesbot custom KICK #temp :idiotuser # the authed user can also quit the bot by sending him "quit" # # to do for a less simple version: # make it able to load all the "events" from a file/files # make it able to reload that file/those files at runtime my $version ='0.0.4.1'; # ------------ # Enter your fishy wishes here: my $server = "irc.freenode.net"; my $port = '6667'; my $nick = "bluesbot"; # initial nickname of the bot, '_' are added at the end if needed my @channels = ("#temp"); # list of channels to join my $username = "testbot"; my $usermode = "testing"; my $realname = "perlbot"; my $password = "12345"; # password to control the bot over queries my $out = "\033[01;36m\<-OUT- "; # put this at the beginning of every output line my $in = "\033[01;34m\--IN-> "; # and input line my $info = "\033[01;33m\--!!-- "; # info line my $err = "\033[01;31m\!----! "; # error/warning my $quitmsg = "bluebot version $version"; # ------------ use IO::Socket; use strict; my $initiation; my $line; my @arline; my %authed; my $remote = IO::Socket::INET->new( Proto => "tcp", PeerAddr => $server, PeerPort => $port ) || die "cannot connect to $server - port $port\n"; # subfunction to send and print the same thing, so we dont have to do that twice sub sendout { print($out.@_[0]); $remote->send(@_[0]); } # sub to print with info appended sub printinfo { print($info.@_[0]); } # sub to print errors/warnings sub printerr { print($err.@_[0]); } printinfo("Perl Bot for IRC by Dennis G. - Version: ".$version."\n"); printinfo("Connecting...\n\n"); # set autoflushing -> unbuffer it! # either set this or flush manually later $remote->autoflush(1); sendout("USER $username $usermode $realname :bot\n"); sendout("NICK :$nick\n"); # join all the channels in the initial list for (my $i=0; $#channels >= $i; $i++) { sendout("JOIN :$channels[$i]\n"); } # receive all the stuff through the $remote handle # this automatically lets us process each input from the socket line-wise # no matter how fast we get it :-) while ($remote->connected() && ($line = <$remote>)) { # maybe manually flush here instead of setting autoflush above #$remote->flush(); # let us know every line we receive over the socket print $in.$line; # remove trailing bit for easier processing chomp($line); # EVENTS: # the things the bot can react to, # put the least probable at the end, to # make the code a bit faster # -------------------------------- # PING PONG Block # needed to keep connection alive in IRC if ($line =~ /^PING\s:(.*)/) { #split(/:/, $line, 2); # "PONG" back the PING PING :-) sendout("PONG :$1\n") } # startif for authenticated users-------- elsif ($line =~ /:(.*)\sPRIVMSG\s$nick\s:/ && exists($authed{$1})) { # you can make the bot say anything to any channel/user # /msg nicknameofthebot say towho whatyouwantosay if ($line =~ /.*\sPRIVMSG\s$nick\s:say\s([A-z0-9-#_]+)\s(.*)/) { sendout("PRIVMSG $1 :$2\n"); } # join a channel # /msg nicknameofthebot join #channel elsif ($line =~ /.*\sPRIVMSG\s$nick\s:join\s(#+[A-z0-9-#_]+)/) { sendout("JOIN :$1\n"); } # leave/part a channel # /msg nicknameofthebot part #channel elsif ($line =~ /.*\sPRIVMSG\s$nick\s:part\s(#+[A-z0-9-#_]+)/) { sendout("PART :$1\n"); } # change the nickname elsif ($line =~ /.*\sPRIVMSG\s$nick\s:nick\schange\s([A-z0-9-_]+)/) { $nick = $1; sendout("NICK :$nick\n"); } # custom command elsif ($line =~ /.*\sPRIVMSG\s$nick\s:custom\s(.*)/) { sendout("$1\n"); } # let the bot quit elsif ($line =~ /.*\sPRIVMSG\s$nick\s:quit/) { sendout("QUIT :$quitmsg\n"); $remote->shutdown(2); exit 0; } # if everything fails we show that some authed person said something to us else { printerr("Unknown command or invalid arguments.\n"); } } # -------------- endif # authenticate with a password elsif ($line =~ /:(.*)\sPRIVMSG\s$nick\s:auth\s$password/) { $authed{$1} = 1000; printinfo("User $1 has been authenticated.\n"); } # NICK Block (Error 433 or 431) # avoid nick collisions elsif ($line =~ /(.*)\s(433|431)\s(.*)/) { # add an underline if we collide - until infinity :D $nick = $nick."_"; # and send our new flashy nickname sendout("NICK :$nick\n"); } } # if the connection fails.. if (!$remote->connected) { $remote->shutdown(2); die "ERROR - connection to ".$server." lost \n"; } # never get here I guess $remote->shutdown(2); # if we get here it would be an error exit 1;