Edgar

A PHP IRC bot based on the CodeDemons PHP IRC bot skeleton with a few extra functions like MD5 sum forward and reverse and rudimentary Wikipedia and Wiktionary lookup.

 <?php /* edgar, the php IRC bot, has its skeleton from demonbot, a demonstration from codedemons.net own functions added and changed by mutante of s23.org
 * 1) !/usr/bin/php

/* Variables that determine server, channel, etc */ $CONFIG = array; $CONFIG['server'] = 'irc.daxnet.no'; // server (i.e. irc.gamesnet.net) $CONFIG['nick'] = 'Edgar23'; // nick (i.e. demonbot $CONFIG['port'] = 6667; // port (standard: 6667) $CONFIG['channel0'] = '#s23'; // channel (i.e. #php) $CONFIG['channel1'] = '#seti23'; $CONFIG['channel2'] = '#bots'; $CONFIG['channel3'] = '#wiki'; $CONFIG['channel4'] = '#yoga'; $CONFIG['channel5'] = '#shrooms'; $CONFIG['name'] = 'Edgar Alice Pope'; // bot name (i.e. demonbot) $CONFIG['admin_pass'] = 'FnordFoobar'; // admin pass (to change settings remotely) $CONFIG['myident'] = 'mutante'; $CONFIG['myhost'] = 's23.org';

/* Let it run forever (no timeouts) */ set_time_limit(0);

/* The connection */ $con = array;

/* start the bot... */ init;

function init {   global $con, $CONFIG; /* We need this to see if we need to JOIN (the channel) during the first iteration of the main loop */ $firstTime = true; /* Connect to the irc server */ $con['socket'] = fsockopen($CONFIG['server'], $CONFIG['port']); /* Check that we have connected */ if (!$con['socket']) { print ("Could not connect to: ". $CONFIG['server'] ." on port ". $CONFIG['port']); } else { /* Send the username and nick */ cmd_send("USER ". $CONFIG['name'] ." ".$CONFIG['myident']." ".$CONFIG['myhost']." ".$CONFIG['server']." :".$CONFIG['nick']); cmd_send("NICK ". $CONFIG['nick']); /* Here is the loop. Read the incoming data (from the socket connection) */ while (!feof($con['socket'])) {           /* Think of $con['buffer']['all'] as a line of chat messages. We are getting a 'line' and getting rid of whitespace around it. */           $con['buffer']['all'] = trim(fgets($con['socket'], 4096)); /* Pring the line/buffer to the console I used <- to identify incoming data, -> for outgoing. This is so that you can identify messages that appear in the console. */           print date("[d/m @ H:i]")."<- ".$con['buffer']['all'] ."\n"; /* If the server is PINGing, then PONG. This is to tell the server that we are still here, and have not lost the connection */ if(substr($con['buffer']['all'], 0, 6) == 'PING :') { /* PONG : is followed by the line that the server sent us when PINGing */ cmd_send('PONG :'.substr($con['buffer']['all'], 6)); }               /* If this is the first time we have reached this point, then JOIN the channel */ if ($firstTime == true){ cmd_send("JOIN ". $CONFIG['channel0']); cmd_send("JOIN ". $CONFIG['channel1']); cmd_send("JOIN ". $CONFIG['channel2']); cmd_send("JOIN ". $CONFIG['channel3']); cmd_send("JOIN ". $CONFIG['channel4']); cmd_send("JOIN ". $CONFIG['channel5']); /* The next time we get here, it will NOT be the firstTime */ $firstTime = false; }               /* Make sure that we have a NEW line of chats to analyse. If we don't,               there is no need to parse the data again */ elseif ($old_buffer != $con['buffer']['all']) { /* Determine the patterns to be passed to parse_buffer. buffer is in the form: :username!~identd@hostname JOIN :#php :username!~identd@hostname PRIVMSG #PHP :action text :username!~identd@hostname command channel :text */ /*               Right now this bot does nothing. But this is where you would add some conditions, or see what is being said in the chat, and then respond. Before you try doing that you should become familiar with how commands are send over IRC. Just read the console when you run this script, and then you will see the patterns in chats, i.e. where the username occurs, where the hostmask is, etc. All you need is functions such as               preg_replace_callback, or perhaps your own function that checks for patterns in the text. Good Luck. */                              parse_buffer;

if (preg_match("/(bug|problem|error|fehler)/i", $con['buffer']['text'])) { cmd_send(prep_text("somebody said the bug was caused by a ".get_excuse)); }
 * 1) MyCommands, mutante stuff

switch (substr($con['buffer']['text'],0,4)) {

case "FNOR" : cmd_send(prep_text("FNORD!!!!")); break;

case "!md5" : $arguments=explode(" ",$con['buffer']['text']); $option=$arguments[1];

switch ($option) {

case "-f" : $cleartext=$arguments[2]; $md5hash = md5_forward($cleartext); cmd_send(prep_text("The hash for '$cleartext' is: $md5hash")); break;

case "-r" : $md5hash=$arguments[2]; list ($statusline,$cleartext) = md5_reverse($md5hash); cmd_send(prep_text("$statusline")); break;

default: cmd_send(prep_text("MD5 hashes forward and reverse. Either use !md5 -f OR !md5 -r ")); }

break;

case "!hel" : cmd_send(prep_text("I'm a very young bot. My current commands are only: !help and !md5 so far.")); break;

case "!wp " :

$arguments=explode(" ",$con['buffer']['text']); $language=$arguments[1]; $pagename=$arguments[2];


 * 1) $input=str_replace(" ","_",$input);

cmd_send(prep_text(wikipedia($language,$pagename)." \n")); break;

case "!s23 " :

$arguments=explode(" ",$con['buffer']['text']); $pagename=$arguments[1];


 * 1) $input=str_replace(" ","_",$input);

cmd_send(prep_text(s23($pagename)." \n")); break;

case "!wk " : $arguments=explode(" ",$con['buffer']['text']); $language=$arguments[1]; $pagename=$arguments[2];

cmd_send(prep_text(wiktionary($language,$pagename)." \n")); break;

}

}           $old_buffer = $con['buffer']['all']; }   } }

/* Accepts the command as an argument, sends the command to the server, and then displays the command in the console for debugging */ function cmd_send($command) {   global $con, $time, $CONFIG; /* Send the command. Think of it as writing to a file. */   fputs($con['socket'], $command."\n\r"); /* Display the command locally, for the sole purpose of checking output. (line is not actually not needed) */ print (date("[d/m @ H:i]") ."-> ". $command. "\n\r"); }

function prep_text($message) {   global $con; return ('PRIVMSG '. $con['buffer']['channel'] .' :'.$message); }

function parse_buffer {   /*    :username!~identd@hostname JOIN :#php :username!~identd@hostname PRIVMSG #PHP :action text :username!~identd@hostname command channel :text */   global $con, $CONFIG; $buffer = $con['buffer']['all']; $buffer = explode(" ", $buffer, 4); /* Get username */ $buffer['username'] = substr($buffer[0], 1, strpos($buffer['0'], "!")-1); /* Get identd */ $posExcl = strpos($buffer[0], "!"); $posAt = strpos($buffer[0], "@"); $buffer['identd'] = substr($buffer[0], $posExcl+1, $posAt-$posExcl-1); $buffer['hostname'] = substr($buffer[0], strpos($buffer[0], "@")+1); /* The user and the host, the whole shabang */ $buffer['user_host'] = substr($buffer[0],1); /* Isolate the command the user is sending from the "general" text that is sent to the channel This is privmsg to the channel we are talking about. We also format $buffer['text'] so that it can be logged nicely. */   switch (strtoupper($buffer[1])) {       case "JOIN": $buffer['text'] = "*JOINS: ". $buffer['username']." ( ".$buffer['user_host']." )"; $buffer['command'] = "JOIN"; $buffer['channel'] = $CONFIG['channel']; break; case "QUIT": $buffer['text'] = "*QUITS: ". $buffer['username']." ( ".$buffer['user_host']." )"; $buffer['command'] = "QUIT"; $buffer['channel'] = $CONFIG['channel']; break; case "NOTICE": $buffer['text'] = "*NOTICE: ". $buffer['username']; $buffer['command'] = "NOTICE"; $buffer['channel'] = substr($buffer[2], 1); break; case "PART": $buffer['text'] = "*PARTS: ". $buffer['username']." ( ".$buffer['user_host']." )"; $buffer['command'] = "PART"; $buffer['channel'] = $CONFIG['channel']; break; case "MODE": $buffer['text'] = $buffer['username']." sets mode: ".$buffer[3]; $buffer['command'] = "MODE"; $buffer['channel'] = $buffer[2]; break; case "NICK": $buffer['text'] = "*NICK: ".$buffer['username']." => ".substr($buffer[2], 1)." ( ".$buffer['user_host']." )"; $buffer['command'] = "NICK"; $buffer['channel'] = $CONFIG['channel']; break; default: // it is probably a PRIVMSG $buffer['command'] = $buffer[1]; $buffer['channel'] = $buffer[2]; $buffer['text'] = substr($buffer[3], 1); break; }   $con['buffer'] = $buffer; }


 * 1) MD5 forward function
 * 2) input: a cleartext string
 * 3) output: the md5 hash for the input string
 * 4) by mutante/s23

function md5_forward($cleartext) { $md5hash=md5($cleartext); return $md5hash; }


 * 1) MD5 reverse function
 * 2) input: an md5 hash
 * 3) output: the cleartext matching the input hash
 * 4) uses http://gdataonline.com/seekhash.php
 * 5) by mutante/s23

function md5_reverse ($md5hash) {

$url="http://gdataonline.com/qkhash.php?mode=xml&hash=".$md5hash; $buffer = file_get_contents($url);
 * 1) we use the XML output of http://gdataonline.com/seekhash.php

switch ($buffer) {
 * 1) check the buffer

case "Hash not valid.": $statusline="No success. the hash '$md5hash' is not valid."; break;
 * 1) server answers but hash is invalid, have to check this first

default:

$status=explode(" ",$buffer); $status=explode(" ",$status[1]); $status=$status[0];
 * 1) now we can try to find the tag

switch ($status) { case "Success":
 * 1) Success found inside tag, then do the parsing

$result=explode(" ",$buffer); $result=explode(" ",$result[1]); $cleartext=$result[0];

$hexresult=explode(" ",$buffer); $hexresult=explode(" ",$hexresult[1]); $hexresult=$hexresult[0];

$b64result=explode(" ",$buffer); $b64result=explode(" ",$b64result[1]); $b64result=$b64result[0];

$hits=explode(" ",$buffer); $hits=explode(" ",$hits[1]); $hits=explode("/",$hits[0]); $hits=$hits[1];

$statusline="SUCCESS - The cleartext for $md5hash is '$cleartext'. (HEX: $hexresult B64: $b64result Hits: $hits)"; break;
 * 1) the message in case everything worked

case "Hash not found": $statusline="No success. the hash '$md5hash' was not found in the database."; break;
 * 1) Hast not found inside

default: $statusline="'$status' No success. No or unusual answer from the database server."; } }
 * 1) All other cases, no in buffer, or no reply at all from server..

$reverseresult[] = $statusline; $reverseresult[] = $cleartext; return $reverseresult;
 * 1) we can only return multiple values as array

}


 * 1) end reverse function


 * 1) Wikipedia function

function wikipedia($language,$pagename) { ini_set('user_agent','http://s23.org/wikistats/ | http://meta.wikimedia.org/wiki/User:mutante | mutante@s23.org'); $url="http://".$language.".wikipedia.org/w/index.php?title=".$pagename; $buffer = file_get_contents($url);

$summary = explode(" ",$buffer); $summary = $summary[1]; $summary = explode(" ",$summary); $summary = $summary[0]; $summary = strip_tags($summary); $summary = str_replace("\n"," ",$summary); $summary = trim($summary); $summary = explode(". ",$summary);

if ($summary[2]) { $summary = $summary[0].". ".$summary[1].". ".$summary[2]."."; } elseif ($summary[1]) { $summary = $summary[0].". ".$summary[1]."."; } else { $summary = $summary[0]."."; }   $summary = substr($summary,0, 320); $summary = "$pagename is ".$summary."\n";

return $summary; }


 * 1) S23

function s23($pagename) { ini_set('user_agent','http://s23.org/wikistats/ | http://meta.wikimedia.org/wiki/User:mutante | mutante@s23.org'); $url="http://s23.org/w/index.php?title=".$pagename; $buffer = file_get_contents($url); $summary = explode(" ",$buffer); $summary = $summary[1]; $summary = explode(" ",$summary); $summary = $summary[0]; $summary = strip_tags($summary); $summary = str_replace("\n"," ",$summary); $summary = trim($summary); $summary = explode(". ",$summary);

if ($summary[2]) { $summary = $summary[0].". ".$summary[1].". ".$summary[2]."."; } elseif ($summary[1]) { $summary = $summary[0].". ".$summary[1]."."; } else { $summary = $summary[0]."."; }   $summary = substr($summary,0, 320); $summary = "$pagename is ".$summary."\n"; return $summary; }


 * 1) Wiktionary function

function wiktionary($language,$pagename) { ini_set('user_agent','http://s23.org/wikistats/ | http://meta.wikimedia.org/wiki/User:mutante | mutante@s23.org'); $url="http://".$language.".wiktionary.org/wiki/".$pagename;


 * 1) print "$url \n";

$buffer = file_get_contents($url);

switch ($language) { case "de":
 * 1) print $buffer;

$summary = explode("Bedeutungen:",$buffer); $summary = $summary[1]; $summary = explode("Herkunft",$summary); break;

case "en":

$summary = explode("",$buffer); $summary = $summary[1]; $summary = explode("",$summary); $summary = str_replace("countable"," ",$summary); break;

default: $summary="Sorry, only supports en and de Wiktionary atm. But try Wikipedia (!wp )"; }

$summary = $summary[0]; $summary = strip_tags($summary); $summary = str_replace("\n"," ",$summary); $summary = trim($summary); $summary = explode(". ",$summary);

if ($summary[2]) { $summary = $summary[0].". ".$summary[1].". ".$summary[2]."."; } elseif ($summary[1]) { $summary = $summary[0].". ".$summary[1]."."; } else { $summary = $summary[0]."."; }

$summary = substr($summary,0, 320); $summary = "$pagename is ".$summary."\n";

return $summary;

}

function get_excuse { # BOFH exuse generator # Written by gf, ported to php by took # Idea and words from http://bofh.ntk.net/ExcuseBoard.html $first = explode(" ", "Temporary Intermittant Partial Redundant Total Multiplexed Inherent Duplicated Dual-Homed Synchronous Bidirectional Serial Asynchronous Multiple Replicated Non-Replicated Unregistered Non-Specific Generic Migrated Localised Resignalled Dereferenced Nullified Aborted Serious Minor Major Extraneous Illegal Insufficient Viral Unsupported Outmoded Legacy Permanent Invalid Deprecated Virtual Unreportable Undetermined Undiagnosable Unfiltered Static Dynamic Delayed Immediate Nonfatal Fatal Non-Valid Unvalidated Non-Static Unreplicatable Non-Serious");

$second = explode(" ", "Array Systems Hardware Software Firmware Backplane Logic-Subsystem Integrity Subsystem Memory Comms Integrity Checksum Protocol Parity Bus Timing Synchronisation Topology Transmission Reception Stack Framing Code Programming Peripheral Environmental Loading Operation Parameter Syntax Initialisation Execution Resource Encryption Decryption File Precondition Authentication Paging Swapfile Service Gateway Request Proxy Media Registry Configuration Metadata Streaming Retrieval Installation Library Handler");

$third = explode(" ", "Interruption Destabilisation Destruction Desynchronisation Failure Dereferencing Overflow Underflow NMI Interrupt Corruption Anomaly Seizure Override Reclock Rejection Invalidation Halt Exhaustion Infection Incompatibility Timeout Expiry Unavailability Bug Condition Crash Dump Crashdump Stackdump Problem Lockout");

$fourth = explode(" ", "Error Problem Warning Signal Flag");

$out = $first[rand(0,count($first)-1)]." "; $out .= $second[rand(0,count($second)-1)]." "; $out .= $third[rand(0,count($third)-1)]; if (rand(0,9) % 2 == 0) $out .= " ".$fourth[rand(0,count($fourth)-1)];

return $out; } ?>

 [2] upd8 edgar with bofh-excuses (mutante)