Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Jun 14th, 2006, 6:11 AM   #1
Mocker
Hobbyist Programmer
 
Mocker's Avatar
 
Join Date: Oct 2005
Location: Indiana
Posts: 219
Rep Power: 0 Mocker is an unknown quantity at this point
Send a message via AIM to Mocker
Step-By-Step IRC Bot

I'm just getting back into perl, been a long while since I last messed with it (3+ years?). I'm starting with a simple IRC bot, that will slowly add on more features, so follow along if you want some very basic samples (and point out where I totally suck if you want )


First, mockerbot v 0.0000001 - using Net::IRC, connects to an IRC server, joins a channel and logs each message to a text file.
(currently 'thegup' on #programmingforums)
*lots of the code was found on O'reilly IRC hacks

Import Net::IRC, declare our variables and create the IRC connection object
!/usr/bin/perl -w

use Net::IRC;
use strict;
# create the IRC object
my $irc = new Net::IRC;
#log directory
my $logdir = "/home/thegupst/public_html/pfo_irc/";
my @thedate = localtime();
my $speaker = "";
my $quoted = "";
my $isSysMsg = 0;
# Create a connection object
my $conn = $irc->newconn(
        Server          => shift || 'irc.freenode.net',
        Port            => shift || '8001',
        Nick            => 'thegup',
        Ircname         => 'grlgrlgrl',
        Username        => 'humbug'
);
$conn->{channel} = shift || '#programmingforums';

Open a file in append mode based on the log path and the date, the write in the message with html blocks based upon a regular message, part or join (this will be switched to a db query later)

sub log_msg {
#open file and log the message
@thedate = localtime();
my $linein = "<font color=black><i>(" . $thedate[2] . ":" . $thedate[1] . ":" . $thedate[0] . ")</i></fon$
my $filename = $logdir . $thedate[4]  . $thedate[3] . $thedate[5]  . '.html';
open(LOGIN, ">>$filename");
flock (LOGIN,2);
if ($quoted eq 'dundundunleaves') {
$linein .= 'green';
$quoted = "sadly leaves";
}
if ($quoted eq 'dundundunjoins') {
$linein .= 'red';
$quoted = "joyfully enters";
}
if ($quoted ne 'joyfully enters' && $quoted ne 'sadly leaves') {
$linein .= 'blue';
}
$linein .= "'><b>" . $speaker . "</b> : " . $quoted . "</font><br>";
print LOGIN "$linein\n";
close(LOGIN);
}

The next few are the handlers for specific events you'll see towards the bottom. Net::IRC has a huge list of events you can specific specific actions for
sub on_privmsg {
   #message was seen in channel, parse, log and react
        my ($conn, $event) = @_;
 $isSysMsg = 0;
 $speaker = $event->{nick};
 $quoted = $event->{args}[0];
 log_msg();

}

sub on_connect {

        # shift in our connection object that is passed automatically
        my $conn = shift;
        # when we connect, join our channel and greet it
        $conn->join($conn->{channel});
        $conn->privmsg($conn->{channel}, 'Hello everyone!');
        $conn->{connected} = 1;
}

sub on_join {

        # get our connection object and the event object, which is passed
        # with this event automatically
        my ($conn, $event) = @_;

        # this is the nick that just joined
        my $nick = $event->{nick};
 $isSysMsg = 1;
 $speaker = $nick;
$quoted = "dundundunjoins";
log_msg();
}


sub on_part {

        # pretty much the same as above

        my ($conn, $event) = @_;

        my $nick = $event->{nick};
        $isSysMsg = 1;
        $speaker = $nick;
        $quoted = "dundundunleaves";
        log_msg();
}

Next we add handlers to the connection object, so it knows what function to call when a certain event happens. A list of events are in perldoc Net::IRC::Events
Once all that is setup, start the IRC connection, which puts it in a loop and leaves the action up to the handlers
# add event handlers for join and part events
$conn->add_handler('join', \&on_join);
$conn->add_handler('part', \&on_part);
$conn->add_handler('public', \&on_privmsg);

# The end of MOTD (message of the day), numbered 376 signifies we've connect
$conn->add_handler('376', \&on_connect);
# start IRC
$irc->start();
__________________
#programmingforums relay - http://thegupstudio.com/cgi-bin/pforelay.cgi
freelance scripts - http://ryanguthrie.com/index.html
Mocker is offline   Reply With Quote
Old Jun 14th, 2006, 6:15 AM   #2
Mocker
Hobbyist Programmer
 
Mocker's Avatar
 
Join Date: Oct 2005
Location: Indiana
Posts: 219
Rep Power: 0 Mocker is an unknown quantity at this point
Send a message via AIM to Mocker
pfo_current

Now I'll show the quick cgi script I made that sits on my server and displays the #programmingforums log for anyone that is curious

pfo_current.cgi

Set the values I'll be using -
#!/usr/bin/perl

my $logdir = "/home/thegupst/public_html/pfo_irc/";
my @thedate = localtime();
my $thetime = localtime();
my $filename = $logdir . $thedate[4]  . $thedate[3] . $thedate[5]  . ".html";

open todays log, print out the html headers and current time (so people know what the timestamps refer to), then print out each line of the file and close it
open(FILEREAD, "< $filename") || die "could not open file";
print "Content-type: text/html\r\n\r\n";
print "<html><head><title>#programmingforums chat log</title></head><body>";
print "<b>#programmingforums current logs. Local time: " . $thetime . "</b><br><hr><br>";
while (<FILEREAD>) {
my $line = $_;
chomp($line);
print "$line\n";
}
close(FILEREAD);
print "</body></html>";

aaannd done. Short and simple. It is online at
http://thegupstudio.com/cgi-bin/pfo_current.cgi
__________________
#programmingforums relay - http://thegupstudio.com/cgi-bin/pforelay.cgi
freelance scripts - http://ryanguthrie.com/index.html
Mocker is offline   Reply With Quote
Old Jun 15th, 2006, 12:35 PM   #3
Mocker
Hobbyist Programmer
 
Mocker's Avatar
 
Join Date: Oct 2005
Location: Indiana
Posts: 219
Rep Power: 0 Mocker is an unknown quantity at this point
Send a message via AIM to Mocker
IRC Relay

Feel like I'm talking to myself,wee. Added a new relay feature. The bot now opens a socket that it monitors. Messages sent to that socket get relayed to the channel the bot is in.

Currently they relayed by a cgi-script. The pfo one is http://thegupstudio.com/cgi-bin/pforelay.cgi

First pforelay.pl , the bot itself. Made some changes to the top.
*note, the code below is not complete. Just snippets with the biggest changes*

Took off strict to make it easier for subs like the socket handler to use the $conn object. Added and initialized the socket. Set some random variables.

require "cgi-lib.pl";
use Net::IRC;
#use strict;
use IO::Socket::INET;

my $MySocket = new IO::Socket::INET->new(LocalPort=>2345,Proto=>'udp');
my $irc = new Net::IRC;

my @thedate = localtime();
my $logdir = "/home/thegupst/public_html/pfo_irc/";
#my @messagein;
my $messagefrom = "";
my $inputstring = "";
my $lastsec = (localtime)[0]; #current seconds
my $lastmin = (localtime)[1]; #current min

logging and other functions are the same. Added the function to handle socket messages. Pretty basic stuff. Sets a time recieved. The message format is sent as username~message and stuff here , so I split it on ~, with the downside this would get messed up if that character is in the username or message. If there is less than 5 seconds between recieved messages it doesn't do anything to prevent flooding or spamming

sub on_sockmsg {
#parse, send to irc
my $text = "";
my $cursec = (localtime)[0];
my $curmin = (localtime)[1];
$MySocket->recv($text,128);
my @msgin = split('\~', $text);
$text = "from " . $msgin[0] . " : " . $msgin[1];
if (($curmin == $lastmin) && (($cursec - $lastsec) < 5)){
 #spamspam
 }
else {
$conn->privmsg($conn->{channel}, $text );
$lastmin = $curmin;
$lastsec = $cursec;
$speaker = "m_" . $msgin[0];
$quoted = $msgin[1];
log_msg();
}
}

Then the only other difference really is adding a file(and socket) handler to to the irc object so it knows what to do if it gets a message
$irc->addfh($MySocket, \&on_sockmsg);



**pforelay.cgi**
Now for the cgi script that displays the last 15 messages and relays anything you enter to the bot

left out some random declarations. Sets the log file path, and also it uses the 'tail' command to get the last 15 entries and the filepath it stores those lines at. Then sets up the socket so we can send stuff to the bot.
require "cgi-lib.pl";
use IO::Socket::INET;
my $logdir = "/home/thegupst/public_html/pfo_irc/";
my $filename = $logdir . $thedate[4]  . $thedate[3] . $thedate[5]  . ".html";
my $tmptail = $logdir . "tmptail";
my $tailcmd = "tail -15 " . $filename . " > " . $logdir . "tmptail";
&ReadParse(*input);
$MySocket=new IO::Socket::INET->new(PeerPort=>2345,Proto=>'udp',PeerAddr=>'localhost');

If the script is sent any data, send it to the bot
if (length($input{'ircmsg'}) > 1) {
#send message to socket
$inputstring = $input{'ircfrom'} . "~" . $input{'ircmsg'};
$MySocket->send($inputstring) || die "could not send";
}

The rest just prints outthe html to the form. This is the code to read the last 15 lines of todays log
system($tailcmd) == 0 || die "could not tail: $?";
open(TAILIN, $tmptail);
while(<TAILIN>){
my $line = $_;
chomp($line);
print "$line\n";
}
close(TAILIN);

hope this is helpful/interesting or something. Feel free to use the url http://thegupstudio.com/cgi-bin/pforelay.cgi to check out #programmingforums irc channel (i'm kimochii on irc)
__________________
#programmingforums relay - http://thegupstudio.com/cgi-bin/pforelay.cgi
freelance scripts - http://ryanguthrie.com/index.html
Mocker is offline   Reply With Quote
Old Jun 15th, 2006, 12:50 PM   #4
lostcauz
Hobbyist Programmer
 
Join Date: Nov 2004
Location: 1691 miles East of L.A.
Posts: 159
Rep Power: 4 lostcauz is on a distinguished road
Nice work! Now to align the date/time, catch actions and maybe add some stats.
__________________
-- lostcauz

Stepped in what?...
Behind whose barn?...
I didn't even know they had a cow!
lostcauz is offline   Reply With Quote
Old Jun 15th, 2006, 1:26 PM   #5
Pizentios
Programming Guru
 
Pizentios's Avatar
 
Join Date: May 2004
Location: Brandon, Manitoba, Canada
Posts: 2,023
Rep Power: 7 Pizentios is on a distinguished road
Send a message via ICQ to Pizentios Send a message via MSN to Pizentios
yeah stats would be cool also
__________________
Profanity is the one language that all programmers understand.

Check out my Blog <---updated Nov 30 2007!
Pizentios is offline   Reply With Quote
Old Jun 18th, 2006, 10:08 AM   #6
Mocker
Hobbyist Programmer
 
Mocker's Avatar
 
Join Date: Oct 2005
Location: Indiana
Posts: 219
Rep Power: 0 Mocker is an unknown quantity at this point
Send a message via AIM to Mocker
MockerBot going on

Woo, made a bunch of changes to my bot at work last night (slow night eh).

Some of the new things
----------
*Logs everything to a mysql database. Messages are logged with usernaem, userid, current datetime, and type. Usernames keep info for each user it has recorded as posting. Right now it just has a postcount, but there are fields for passwords and more info so it could serve as kinda a nickserv bot and keep profiles and authentic logged messages etc.
*Added a bunch of commands! right now there is
!quote random - displays a random quote from a quote file
!quote add your quote here - adds the quote to the quote file
!quote randomirc - displays a random entry in the irc logs
!quote randomirc username - displays a random entry in the irc logs from that username
!info postcount username - number of entries by that username


It is 263 lines now so I put it in the pastebin. umm.. i'm feelnig lazy so I'll just link that. I'll break down the sections again later, shouldn't be too hard to follow. There are pretty messy areas because I'm learning perl as I go again and never used the DBI module.
http://pfo.pastebin.com/716502
This is the exact script (except for db info) used for mockerbot, currently on #programmingforums irc channel.

Next up is adding a way to track the current userlist, and then working on the relay script so you can see all the info and commands from there.

*no comments on my variable names global $data1 and $data2 are horrible I know I know
__________________
#programmingforums relay - http://thegupstudio.com/cgi-bin/pforelay.cgi
freelance scripts - http://ryanguthrie.com/index.html
Mocker is offline   Reply With Quote
Old Jul 11th, 2006, 6:20 AM   #7
Mocker
Hobbyist Programmer
 
Mocker's Avatar
 
Join Date: Oct 2005
Location: Indiana
Posts: 219
Rep Power: 0 Mocker is an unknown quantity at this point
Send a message via AIM to Mocker
Woo, so I've added number of new things to my bot. I actually still need to update the help file so I'll try to list em all here for now

Logs the chat to a mysql database and keeps a postcount for each username
Has a relay you can chat through http://thegupstudio.com/cgi-bin/pforelay.cgi
You can search and view logs http://thegupstudio.com/cgi-bin/pfo_current.cgi
Keeps an additional quote db that is added to manually

The current commands are-
!info postcount (LIKE) username
!quote random|randomirc (LIKE) (username) - random uses quotedb, randomirc is random line from the log
!help - pm's a brief help file
!talk on|off (username)
!define (DIC) word - users dict.org dictionaries, currently available :
SPANISH ROM GERMAN FRENCH NLD DEVIL JARGON THES default is spanish
!tran (LANG) phrase - uses google translate or freedict.com to translate
GERMAN FRENCH ITALIAN ARABIC JAPANESE NIHONGO KOREAN CHINESE DEUTSCH FRANCAIS ESPANOL SPANISH(default). The native languages translate back to english
!google phrase - gets first google result

annd, the full source code is available. Kimobot runs on #programmingforums irc room (irc.freenode.net) if you want to test it.

http://thegupstudio.com/pfo_irc/ircbot.html

Let me know what you think I'm going to just keep adding to it, probably group the functions into modules. If you are interested in trying to use the source I'll include how I've setup the mysql tables and other files it uses.
__________________
#programmingforums relay - http://thegupstudio.com/cgi-bin/pforelay.cgi
freelance scripts - http://ryanguthrie.com/index.html
Mocker is offline   Reply With Quote
Old Jul 15th, 2006, 8:27 AM   #8
Mocker
Hobbyist Programmer
 
Mocker's Avatar
 
Join Date: Oct 2005
Location: Indiana
Posts: 219
Rep Power: 0 Mocker is an unknown quantity at this point
Send a message via AIM to Mocker
Slow night at work, got three more functions added to the bot

the first isnt really part of the bot, it is a quick php script that uses the GD library to generate an image of 3 random lines from irc
http://thegupstudio.com/pfo_irc/randomirc_img2.php - refresh it a few times
it is an image so you could do <img src="..etc"> and have it displayed
it also takes 2 arguments, lines and names. http://thegupstudio.com/pfo_irc/rand...names=kimochii for example

The next bot command is
!random list of items here etc etc
or
!random number TO number
The first way just choose a random item that comes after the command
the second is a random int between the two numbers

And this one took me a while, there is now a 'game' you can play
!play quoteirc ON|OFF to turn the game on and off
it will display a random irc quote and the first person to say the name of the speaker wins that round, it then adds a score and goes to the next one
!skip - skips current round, displays answer and goes to the next
!score - displays current score, works while game is off for last played game. New games reset the score

If you dont skip and dont guess the name it will just wait until you do or you end the game

I've had all of no interest in this so I probably will not post the source here anymore. Its still available, i'm just too lazy to update it.
__________________
#programmingforums relay - http://thegupstudio.com/cgi-bin/pforelay.cgi
freelance scripts - http://ryanguthrie.com/index.html
Mocker is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 6:56 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC