MockerBot
An irc in perl - written by Mocker/Sokercap/Kimochii
Purpose: This bot is written for fun and as an excercise. I am posting it here with small comments for
anyone that wants to take a look, get ideas, or just have a laugh at my coding :|
If anyone wants to contact me, its sokercap [at] gmail [dot[ com
the header, requires a few nifty modules and mech_scripts.pl, an external file I keep some of the functions in
#!/usr/bin/perl
#starts irc bot. Add socket handler to get input
require "cgi-lib.pl";
require "mech_scripts.pl";
use Net::IRC;
#use strict;
use IO::Socket::INET;
use DBI;
use Net::Dict;
Open the relay socket, ircclient, db connection and set my many many globals (bad style I know)
my $MySocket = new IO::Socket::INET->new(LocalPort=>1234,Proto=>'udp');
my $irc = new Net::IRC;
$dbpath = "dbi:mysql:database=**DBNAME**;host=localhost";
$dbh = DBI->connect($dbpath, "***DBUSER***", "**PWD***") or die "Can't open db: $DBI::errstr";
$dict = Net::Dict->new('dict.org');
$dict->setDicts('english');
my @thedate = localtime();
my $botname = "Nyuu";
my $botpwd = "**NICKPWD**";
my $botisreg = 0;
my $logdir = "/home/thegupst/public_html/test_irc/";
my $quotefile = $logdir . "quotes.db";
my $helpfile = $logdir . "helptext";
my $tbl_pre = 'test_';
my $messagefrom = "";
my $inputstring = "";
my $lastsec = (localtime)[0]; #current seconds
my $lastmin = (localtime)[1]; #current min
my $data1 = "";
my $talkon = 0;
my $talkperson = 'default';
my $islike = 0;
$dicdb = 'wn';
$data2 = "default";
#setup irc
my $conn = $irc->newconn(
Server => shift || 'irc.aniverse.com',
Port => shift || '6667',
Nick => $botname,
Ircname => 'lucy',
Username => 'elfenlied'
);
#set channel
$conn->{channel} = shift || '#testchannel';
Start my custom functions.. first up do_botstuff! If a message starts with !, it is sent here to check if it matches
any command triggers. If so, it usually sets some flag and sends it to the appropriate function. Languages correspond to
dictionary, language form or url of language dictionary
##other functions
sub do_botstuff {
#msg started with !, check for command
my @words = split(/ /, $quoted);
my $command = $words[0];
if($command eq '!quote'){
if($words[1] eq 'random'){
get_quote();
$conn->privmsg($conn->{channel}, "ahem: $data1");
}
if($words[1] eq 'add'){
my $counter = 0;
$data1 = "";
foreach (@words){
if($counter > 1){
$data1 .= ' ' . $_;
}
else {
$counter += 1;
}
}
add_quote();
}
if($words[1] eq 'randomirc'){
if($words[2] eq 'LIKE'){
$islike = 1;
if(length($words[3]) > 1){
$data2 = $words[3]; }
}
else {
if(length($words[2]) > 1){
$data2 = $words[2]; }
}
get_ircquote();
}
}
#end quote cmd
if($words[0] eq '!info'){
if($words[1] eq 'postcount'){
$data1 = $words[2];
if($data1 eq 'LIKE'){
$islike = 1;
$data1 = 'default';
if(length($words[3]) > 2){
$data1 = $words[3]; }
}
info_postcount();
}
}
#end info cmd
if($words[0] eq '!talk' && $words[1] eq 'on'){
$talkon = 1;
if(length($words[2]) > 1){
$talkperson = $words[2]; }
}
if($words[0] eq '!talk' && $words[1] eq 'off'){
$talkon = 0;
$talkperson = 'default';
}
#end talk
if($words[0] eq '!define'){
$data1 = $words[1];
if($data1 eq 'SPANISH'){
$dicdb = 'eng-sp'; $data1 = $words[2]; }
if($data1 eq 'ROM'){
$dicdb = 'eng-rom'; $data1 = $words[2]; }
if($data1 eq 'GERMAN'){
$dicdb = 'eng-deu'; $data1 = $words[2]; }
if($data1 eq 'FRENCH'){
$dicdb = 'eng-fra'; $data1 = $words[2]; }
if($data1 eq 'NLD'){
$dicdb = 'eng-nld'; $data1 = $words[2]; }
if($data1 eq 'DEVIL'){
$dicdb = 'devils'; $data1 = $words[2]; }
if($data1 eq 'JARGON'){
$dicdb = 'jargon'; $data1 = $words[2]; }
if($data1 eq 'THES'){
$dicdb = 'moby-thes'; $data1 = $words[2]; }
if($dicdb eq 'wn'){
$conn->privmsg('mocker', "getting dictionary.com");
$conref = \$conn;
dictionary_com($conn, $data1); }
else {
define_word(); }
}
#end define
if($words[0] eq '!tran'){
$whatdb = 'google';
$dicdb = 'en|es';
$data1 = $words[1];
if($words[1] eq 'GERMAN'){
$dicdb = 'en|de'; $data1 = $words[2]; }
if($words[1] eq 'FRENCH'){
$dicdb = 'en|fr'; $data1 = $words[2]; }
if($words[1] eq 'GERMAN'){
$dicdb = 'en|de'; $data1 = $words[2]; }
#if($words[1] eq 'ITALIAN'){
#$dicdb = 'en|il'; $data1 = $words[2]; }
if($words[1] eq 'ARABIC'){
$dicdb = 'en|ar'; $data1 = $words[2]; }
if($words[1] eq 'JAPANESE'){
$dicdb = 'http://www.freedict.com/onldict/jap.html'; $whatdb = 'freedict'; }
if($words[1] eq 'NIHONGO'){
$dicdb = '2http://www.freedict.com/onldict/jap.html'; $whatdb = 'freedict'; }
if($words[1] eq 'KOREAN'){
$dicdb = 'en|ko'; $data1 = $words[2]; }
if($words[1] eq 'CHINESE'){
$dicdb = 'en|zh-CN'; $data1 = $words[2]; }
if($words[1] eq 'DEUTSCH'){
$dicdb = 'de|en'; $data1 = $words[2]; }
if($words[1] eq 'FRANCAIS'){
$dicdb = 'fr|en'; $data1 = $words[2]; }
if($words[1] eq 'ESPANOL'){
$dicdb = 'es|en'; $data1 = $words[2]; }
if($words[1] eq 'SPANISH'){
$data1 = $words[2]; }
if($dicdb ne 'en|es' || $words[1] eq 'SPANISH'){
shift(@words); shift(@words); $data1 = join " ", @words;
}
else {
shift(@words); $data1 = join " ", @words;
}
if(length($data1) < 2){
$data1 = 'idiot'; }
if($whatdb eq 'google'){
google_trans($conn, $dicdb, $data1); }
else {
freedict_trans($conn, $dicdb, $data1); }
$whatdb = 'google';
$dicdb = 'wn';
}
#end translate
if($words[0] eq '!google'){
shift(@words); $input = join " ", @words;
google_search($conn, $input);
}
#end google
if($words[0] eq '!help'){
help_msg();
}
#end help
}
Next up are a few of the subroutines for handling actions. Actually, screw this, i'll comment on the rest later
sub help_msg {
open(HELPIN, $helpfile);
@helptmp = ;
close(HELPIN);
$counti = 0;
foreach $helpline (@helptmp){
if($counti < 13){
$conn->privmsg($speaker, $helpline);
}
$counti = $counti + 1;
}
}
sub define_word {
my $input = $data1;
if(length($input) < 2){
$input = "idiot"; }
$data1 = "";
$h = $dict->define($input) or die "could not define $input";
@i = @{$h}[0];
$x = $i[0]->[1];
if(length($x) < 3){ $x = "No definition found, doh"; }
#@splitx = $x =~ /.{1,200}/gs;
#@splitx = split(/(.{200})/, $x);
$c = 0;
$spx = substr($x, 0, 500);
#foreach $spx (@splitx){
#if(length($spx) < 2) { $spx = "error"; }
#if($c < 3){
$syscmd = "dict -d $dicdb $input | head -5 > /scripts/custom/irc_files/tmpdic";
system($syscmd);
$dicdb = 'wn';
$tmpdefine = "";
open(DICIN, "/scripts/custom/irc_files/tmpdic");
@tmpdefine = ;
close(DICIN);
foreach $tmpdef (@tmpdefine){
if(substr($tmpdef, 0, 3) ne '---' && $input ne 'lazer' && $input ne 'lazer'){
$conn->privmsg($conn->{'channel'}, $tmpdef);
}
}
if($input eq 'lazer' || $input eq 'lazers'){
$conn->privmsg($conn->{'channel'}, "Pew ! Pew!"); }
#$speaker = $botname; $quoted = $spx; log_msg();
#}
#$c += 1;
#}
}
sub info_postcount {
if($islike == 0){
$data1 = $dbh->quote($data1);
$sql = "SELECT username, msgcount FROM $tbl_pre" . "usernames WHERE username = $data1";
}
if($islike == 1){
$sql = "SELECT username, msgcount FROM $tbl_pre" . "usernames WHERE username LIKE '%" . $data1 . "%' ORDER BY msgcount DESC LIMIT 5";
$islike = 0;
}
if($islike != 0 && $islike != 1){
$sql = "SELECT username, msgcount FROM $tbl_pre" . "usernames WHERE postcount > 2 ORDER BY RAND() LIMIT 1";
}
$query = $dbh->prepare($sql);
$query->execute or die "SQL Error: $DBI::errstr\n";
while(@postinfo = $query->fetchrow_array){
my $botmsg = "<$postinfo[0]> has posted $postinfo[1] times";
$conn->privmsg($conn->{channel}, $botmsg);
$speaker = $botname; $quoted = $botmsg; log_msg();
}
}
sub get_ircquote {
my $sqlname = "";
if($data2 ne 'default'){
$blahblah = $data2 =~ tr/'//d;
$sqlname = " AND username = '" . $data2 . "' ";
}
if($data2 ne 'default' && $islike == 1){
$sqlname = " AND username LIKE '%" . $data2 . "%' ";
$islike = 0;
}
$data2 = 'default';
$sql = "SELECT username, msg FROM $tbl_pre" . "messages WHERE type < 4 " . $sqlname . "ORDER BY RAND() LIMIT 1";
$query = $dbh->prepare($sql) or die "could not prepare, $sql";
$query->execute or die "SQL Error: $DBI::errstr\n";
@quotenfo = $query->fetchrow_array;
$data1 = "<" . $quotenfo[0] . "> " . $quotenfo[1];
$conn->privmsg($conn->{channel}, $data1 );
$speaker = $botname; $quoted = $data1; log_msg();
}
sub get_quote {
my $delimiter = "\n\%\%\n";
#my $quotefile = "/home/thegupst/public_html/was_irc/quote.db";
open(QFILE,"$quotefile") || die "couldnt open quote file";
@QFILE = ;
close (QFILE);
$phrases = join('',@QFILE);
@phrases = split(/$delimiter/,$phrases);
srand(time^ $$);
$phrase = rand(@phrases);
$data1 = @phrases[$phrase];
$speaker = $botname; $quoted = $data1; log_msg();
}
sub add_quote {
#append quote to quote.db
my $delimiter = "\n\%\%\n";
#my $quotefile = "/home/thegupst/public_html/was_irc/quote.db";
open(QFILE,">>$quotefile") || die "could not open quote file";
print QFILE $delimiter . $data1 ;
close(QFILE);
}
sub log_msg {
#open file and log the message
my $sql = "";
my $cmdtype = 0;
@thedate = localtime();
$thedate[2] = $thedate[4] + 1; $thedate[5] = $thedate[5] + 1900; $thedate[5] =
sprintf("%02d", $thedate[5] % 100);
my $linein = "(" . $thedate[2] . ":" . $thedate[1] . ":" .
$thedate[0] . ")  >$filename");
flock (LOGIN,2);
if ($quoted eq 'dundundunleaves') {
$cmdtype = 1;
$linein .= 'green';
$quoted = "sadly leaves";
}
if ($quoted eq 'dundundunjoins') {
$cmdtype = 2;
$linein .= 'red';
$quoted = "joyfully enters";
}
if ($quoted ne 'joyfully enters' && $quoted ne 'sadly leaves') {
$cmdtype = 3;
$linein .= 'blue';
if (substr($quoted, 0 , 1) eq '!') {
do_botstuff();
$cmdtype = 4;
}
if (substr($quoted, 0, 1) ne '!' && $talkon == 1 && substr($quoted, 0, 1) ne '<' && $speaker ne $botname){
$data2 = $talkperson;
get_ircquote();
}
}
$speaker = $dbh->quote($speaker); $quoted = $dbh->quote($quoted);
$sqlquery = $dbh->do("UPDATE $tbl_pre". "usernames SET msgcount = msgcount + 1 WHERE username
= $speaker LIMIT 1");
if($sqlquery < 1){
$sqlquery = $dbh->prepare("INSERT INTO $tbl_pre" . "usernames (username) VALUES ($speaker)");
$sqlquery2 = $sqlquery->execute or die "SQL Error: $DBI::errstr\n";
}
$sql = "INSERT INTO $tbl_pre" . "messages SET username = $speaker, msg = $quoted, date =
NOW(), type = '$cmdtype'";
$sth = $dbh->prepare($sql);
$sth->execute or die "SQL Error: $DBI::errstr\n";
$linein .= "'>" . $speaker . " : " . $quoted . "
";
print LOGIN "$linein\n";
close(LOGIN);
}
## HANDLERS
#public message
sub on_pubmsg {
#log, parse, respond whatnot
my ($conn, $event) = @_;
$isSysMsg = 0;
$speaker = $event->{nick};
$quoted = $event->{args}[0];
if($quoted =~ /whee/){
$conn->privmsg($conn->{channel}, "Wiiiii!!" );
}
log_msg();
}
#socket recieved msg
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 = "<" . $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();
}
}
sub on_connect {
# shift in our connection object that is passed automatically
my $conn = shift;
print "connected fine";
# 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 {
my ($conn, $event) = @_;
# this is the nick that just joined
my $nick = $event->{nick};
# say hello to the nick in public
if($botisreg > 0){
$conn->privmsg('nickserv', "IDENTIFY $botpwd");
}
$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();
}
##Callbacks
$conn->add_handler('join', \&on_join);
$conn->add_handler('part', \&on_part);
$conn->add_handler('public', \&on_pubmsg);
$irc->addfh($MySocket, \&on_sockmsg);
# The end of MOTD (message of the day), numbered 376 signifies we've connect
$conn->add_handler('376', \&on_connect);
# start IRC
$irc->start();
In conclusion: blaaaaaaaah blah blah