Initial import.

This commit is contained in:
Jan Philipp Timme 2010-11-21 22:13:54 +00:00
parent 85f7da38b6
commit 6b39d44754
52 changed files with 1395 additions and 0 deletions

5
.buildpath Normal file
View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<buildpath>
<buildpathentry kind="src" path=""/>
<buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/>
</buildpath>

22
.project Normal file
View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>phpircbot2</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.dltk.core.scriptbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.php.core.PHPNature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,3 @@
#Sun Nov 21 23:06:20 CET 2010
eclipse.preferences.version=1
include_path=0;/phpircbot2

33
bot.php Normal file
View File

@ -0,0 +1,33 @@
#! /usr/bin/php5
<?php
require "checkup.inc.php";
require "modules/init.inc.php";
$bot = new ircbot("Pb42", "BetaBot", "Insert Bot Name");
$bot -> setServer("irc.freenode.net", 6667);
//$bot -> setServer("irc.eloxoph.com", 6667);
$bot -> setPrefix("+");
$bot -> setAutoReconnect(true);
$bot -> setSleep(0.75); //seconds to sleep when nothing is todo
$bot -> addChannels(array("#botted", "#starsim", "##available", "##ircbots"));
//$bot -> addChannels(array("#eloxoph", "#pb42"));
$bot -> connect();
while($bot -> alive){
$data = $bot -> recv();
if($data["command"] == "mainloop"){
$bot -> call("privmsg", $data["origin"], "Place hardcoded commands here. Your current level: ".$data["level"]);
}
unset($data);
}
//--- End of mainloop here
//bot should quit and shutdown after mainloop.
$bot -> setAutoReconnect(false);
$bot -> call("quit", "Mainloop terminated.");
unset($bot);
?>

3
checkup.inc.php Normal file
View File

@ -0,0 +1,3 @@
<?php
if(!file_exists("users.db")) die("\n(!) You have to run install.php first! (!)\n\n");
?>

1
cleanup.sh Normal file
View File

@ -0,0 +1 @@
find ./ | grep -i \~ | xargs rm

1
commands.db Normal file
View File

@ -0,0 +1 @@
a:33:{s:7:"#botted";a:3:{s:8:"filename";s:19:"#botted.channel.php";s:7:"context";s:7:"channel";s:5:"level";s:1:"0";}s:8:"checkips";a:3:{s:8:"filename";s:19:"checkips.global.php";s:7:"context";s:6:"global";s:5:"level";s:1:"0";}s:4:"help";a:3:{s:8:"filename";s:15:"help.global.php";s:7:"context";s:6:"global";s:5:"level";s:1:"0";}s:8:"identify";a:3:{s:8:"filename";s:20:"user.ident.query.php";s:7:"context";s:5:"query";s:5:"level";s:1:"0";}s:5:"level";a:3:{s:8:"filename";s:16:"level.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"0";}s:6:"logout";a:3:{s:8:"filename";s:17:"logout.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"0";}s:3:"md5";a:3:{s:8:"filename";s:14:"md5.global.php";s:7:"context";s:6:"global";s:5:"level";s:1:"0";}s:4:"mods";a:3:{s:8:"filename";s:15:"mods.global.php";s:7:"context";s:6:"global";s:5:"level";s:1:"0";}s:8:"password";a:3:{s:8:"filename";s:23:"user.password.query.php";s:7:"context";s:5:"query";s:5:"level";s:1:"0";}s:5:"stats";a:3:{s:8:"filename";s:16:"stats.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"0";}s:4:"stfu";a:3:{s:8:"filename";s:15:"stfu.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"0";}s:5:"cycle";a:3:{s:8:"filename";s:16:"cycle.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"1";}s:3:"dns";a:3:{s:8:"filename";s:14:"dns.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"1";}s:2:"ip";a:3:{s:8:"filename";s:13:"ip.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"1";}s:3:"say";a:3:{s:8:"filename";s:14:"say.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"1";}s:4:"away";a:3:{s:8:"filename";s:15:"away.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"2";}s:6:"reload";a:3:{s:8:"filename";s:17:"reload.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"2";}s:6:"uptime";a:3:{s:8:"filename";s:17:"uptime.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"2";}s:5:"clist";a:3:{s:8:"filename";s:16:"clist.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:9:"floodtest";a:3:{s:8:"filename";s:20:"floodtest.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"join";a:3:{s:8:"filename";s:15:"join.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:1:"m";a:3:{s:8:"filename";s:12:"m.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:12:"masterlogout";a:3:{s:8:"filename";s:23:"masterlogout.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"nick";a:3:{s:8:"filename";s:15:"nick.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"part";a:3:{s:8:"filename";s:15:"part.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"quit";a:3:{s:8:"filename";s:15:"quit.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:3:"raw";a:3:{s:8:"filename";s:14:"raw.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"stop";a:3:{s:8:"filename";s:15:"stop.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"user";a:3:{s:8:"filename";s:15:"user.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"3";}s:4:"kick";a:3:{s:8:"filename";s:15:"kick.prefix.php";s:7:"context";s:6:"prefix";s:5:"level";s:1:"4";}s:3:"php";a:3:{s:8:"filename";s:14:"php.global.php";s:7:"context";s:6:"global";s:5:"level";s:1:"9";}s:7:"phpdump";a:3:{s:8:"filename";s:18:"phpdump.global.php";s:7:"context";s:6:"global";s:5:"level";s:1:"9";}s:3:"sys";a:3:{s:8:"filename";s:13:"sys.query.php";s:7:"context";s:5:"query";s:5:"level";s:1:"9";}}

4
commands/away.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "away" "prefix" "2"
$this -> call("away", $this -> protocol -> getArgs(1, $recv));
?>

View File

@ -0,0 +1,29 @@
<?php
#BOT_INCLUDE "checkips" "global" "0"
if($recv["msgarr"][1] == "add"){
$ip = $recv["msgarr"][2];
$this -> ipcs[$ip]["lastcheck"] = 0;
$this -> ipcs[$ip]["status"] = null;
}
if($recv["msgarr"][1] == "del"){
$ip = $this -> protocol -> getArgs(2, $recv);
unset($this -> ipcs[$ip]);
}
if($recv["msgarr"][1] == "list"){
if(count($this -> ipcs) < 1){
$this -> call("notice", $recv["nick"], "Bisher keine IPs zu checken.");
}
else{
foreach($this -> ipcs AS $ip => $data){
$status = ($data["status"]) ? "Online" : "Offline";
$line = "[".$ip."] Status: ".$status;
$this -> call("notice", $recv["nick"], $line);
}
}
}
?>

View File

@ -0,0 +1,5 @@
<?php
#BOT_INCLUDE "clist" "prefix" "3"
$chans = implode(", ", $this -> channels);
$this -> call("privmsg", $recv["origin"], "current channels: ".$chans);
?>

View File

@ -0,0 +1,6 @@
<?php
#BOT_INCLUDE "cycle" "prefix" "1"
$this -> call("part", $recv["origin"], "cycling...");
sleep(1);
$this -> call("join", $recv["origin"]);
?>

8
commands/dns.prefix.php Normal file
View File

@ -0,0 +1,8 @@
<?php
#BOT_INCLUDE "dns" "prefix" "1"
$data = $this -> protocol -> getArgs(1, $recv);
if(trim($data) == "") $data = $recv["iphost"];
$host = gethostbyaddr($data);
if($host == $data || $host == "") $this -> call("privmsg", $recv["origin"], $recv["nick"].", your ip could not be resolved.");
else $this -> call("privmsg", $recv["origin"], $recv["nick"].", your host is: ".$host);
?>

View File

@ -0,0 +1,10 @@
<?php
#BOT_INCLUDE "floodtest" "prefix" "3"
$max = $this -> protocol -> getArgs(1, $recv);
$i = 0;
while($i < $max){
$text[] = md5(rand());
$i++;
}
foreach($text as $line) $this -> call("privmsg", $recv["origin"], $line);
?>

12
commands/help.global.php Normal file
View File

@ -0,0 +1,12 @@
<?php
#BOT_INCLUDE "help" "global" "0"
$help[] = "Commands available for your level (".$recv["level"]."):";
$help[] = $this -> commands -> getList($recv["level"]);
$help[] = "*=These commands have to be used in query only. (no need to use the prefix there)";
$help[] = "#=These commands have to be used in channel only.";
if(!$this -> userdb -> isUser($recv["nick"])) $help[] = "In order to gain a higher level ask the owner to create an account for you.";
elseif(!$this -> userdb -> isActive($recv["nick"])) $help[] = "In order to gain access, identify yourself by typing: /msg ".$this -> nick." identify <password>";
elseif($this -> userdb -> isActive($recv["nick"])) $help[] = "In order to change your password, type /msg ".$this -> nick." password <new password>";
foreach($help as $line) $this -> call("notice", $recv["nick"], $line);
?>

8
commands/ip.prefix.php Normal file
View File

@ -0,0 +1,8 @@
<?php
#BOT_INCLUDE "ip" "prefix" "1"
$data = $this -> protocol -> getArgs(1, $recv);
if(trim($data) == "") $data = $recv["iphost"];
$ip = gethostbyname($data);
if($ip == $data) $this -> call("privmsg", $recv["origin"], $recv["nick"].", your dns could not be resolved.");
else $this -> call("privmsg", $recv["origin"], $recv["nick"].", your ip is: ".$ip);
?>

View File

0
commands/ipcs[][status] Normal file
View File

4
commands/join.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "join" "prefix" "3"
$this -> addChannels(array($this -> protocol -> getArgs(1, $recv)));
?>

4
commands/kick.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "kick" "prefix" "4"
$this -> call("kick", $recv["origin"], $recv["msgarr"][1], $this -> protocol -> getArgs(2, $recv));
?>

View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "level" "prefix" "0"
$this -> call("privmsg", $recv["origin"], $recv["nick"].", your level is: ".$this -> userdb -> getLevel($recv["nick"]));
?>

View File

@ -0,0 +1,5 @@
<?php
#BOT_INCLUDE "logout" "prefix" "0"
$this -> userdb -> logout($recv["nick"]);
$this -> call("notice", $recv["nick"], "You are now logged out. Your level: ".$this -> userdb -> getLevel($recv["nick"]));
?>

4
commands/m.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "m" "prefix" "3"
$this -> call("mode", $recv["origin"], $this -> protocol -> getArgs(1, $recv));
?>

View File

@ -0,0 +1,5 @@
<?php
#BOT_INCLUDE "masterlogout" "prefix" "3"
$this -> userdb -> logoutAll();
$this -> call("privmsg", $recv["origin"], "Masterlogout done.");
?>

6
commands/md5.global.php Normal file
View File

@ -0,0 +1,6 @@
<?php
#BOT_INCLUDE "md5" "global" "0"
$value = trim($this -> protocol -> getArgs(1, $recv));
if($value != "") $this -> call("privmsg", $recv["origin"], $recv["nick"].", your md5-hash: ".md5($value));
else $this -> call("privmsg", $recv["origin"], $recv["nick"].": Syntax: ".$this -> prefix."md5 <value>");
?>

13
commands/mods.global.php Normal file
View File

@ -0,0 +1,13 @@
<?php
#BOT_INCLUDE "mods" "global" "0"
if(is_numeric($level = $this -> protocol -> getArgs(1, $recv))){
$text[] = "Commands for level ".$level.": (example: command(level) (*=query command, #=channel command))";
$text[] = $this -> commands -> getList($level);
foreach($text as $line) $this -> call("notice", $recv["nick"], $line);
}
else{
$text[] = "Installed commands: (example: command(level) (*=query command, #=channel command))";
$text[] = $this -> commands -> getList(9);
foreach($text as $line) $this -> call("notice", $recv["origin"], $line);
}
?>

4
commands/nick.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "nick" "prefix" "3"
$this -> setNick($this -> protocol -> getArgs(1, $recv));
?>

4
commands/part.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "part" "prefix" "3"
$this -> removeChannels(array($this -> protocol -> getArgs(1, $recv)));
?>

4
commands/php.global.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "php" "global" "9"
eval($this -> protocol -> getArgs(1, $recv));
?>

View File

@ -0,0 +1,8 @@
<?php
#BOT_INCLUDE "phpdump" "global" "9"
$r = $this -> eval_php($this -> protocol -> getArgs(1, $recv));
if(trim($r) != ""){
$lines = explode("\n", $r);
foreach($lines as $line) $this -> call("privmsg", $recv["origin"], $line);
}
?>

4
commands/quit.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "quit" "prefix" "3"
$this -> call("quit", $this -> protocol -> getArgs(1, $recv));
?>

4
commands/raw.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "raw" "prefix" "3"
$this -> send($this -> protocol -> getArgs(1, $recv));
?>

View File

@ -0,0 +1,5 @@
<?php
#BOT_INCLUDE "reload" "prefix" "2"
$this -> commands -> update();
$this -> call("privmsg", $recv["origin"], "commands reloaded.");
?>

4
commands/say.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "say" "prefix" "1"
$this -> call("privmsg", $recv["origin"], $this -> protocol -> getArgs(1, $recv));
?>

10
commands/stats.prefix.php Normal file
View File

@ -0,0 +1,10 @@
<?php
#BOT_INCLUDE "stats" "prefix" "0"
$total = $this -> eval_sys("find * | grep -i php | xargs cat | wc -l");
$stats = "";
$stats .= "Memory: ".number_format(memory_get_usage(true) / 1024)."KB ";
$stats .= "(Peak: ".number_format(memory_get_peak_usage(true) / 1024)."KB)";
$stats .= " - Code: ".number_format($total[0])." lines";
$this -> call("privmsg", $recv["origin"], $stats);
?>

5
commands/stfu.prefix.php Normal file
View File

@ -0,0 +1,5 @@
<?php
#BOT_INCLUDE "stfu" "prefix" "0"
if($recv["level"] >= 3) $this -> call("privmsg", $recv["origin"], "aye sir!");
else $this -> call("kick", $recv["target"], $recv["nick"], "dann fang mal an!");
?>

4
commands/stop.prefix.php Normal file
View File

@ -0,0 +1,4 @@
<?php
#BOT_INCLUDE "stop" "prefix" "3"
$this -> alive = 0;
?>

7
commands/sys.query.php Normal file
View File

@ -0,0 +1,7 @@
<?php
#BOT_INCLUDE "sys" "query" "9"
$cmd = $this -> protocol -> getArgs(1, $recv);
$result = $this -> eval_sys($cmd);
$this -> call("privmsg", $recv["nick"], $cmd);
foreach($result as $line) $this -> call("privmsg", $recv["nick"], $line);
?>

View File

@ -0,0 +1,10 @@
<?php
#BOT_INCLUDE "uptime" "prefix" "2"
$cmd = "uptime";
$p = popen($cmd, "r");
while($data = fgets($p, 8192)){
$result[] = $data;
}
pclose($p);
foreach($result as $line) $this -> call("privmsg", $recv["origin"], trim($line));
?>

View File

@ -0,0 +1,16 @@
<?php
#BOT_INCLUDE "identify" "query" "0"
/*
* This file contains code for the query-based user-command "identify"
*/
include("#BOT_PATHuser.query.inc.php");
if($this -> userdb -> checkPw($nick, $pw)){
$this -> userdb -> update($nick);
$this -> call("notice", $nick, "You are now identified.");
}
else{
$this -> call("notice", $nick, "Wrong password or you have no account with this nickname.");
}
?>

View File

@ -0,0 +1,16 @@
<?php
#BOT_INCLUDE "password" "query" "0"
/*
* This file contains code for the query-based user-command "password"
*/
include("#BOT_PATHuser.query.inc.php");
if($this -> userdb -> isActive($nick)){
$this -> userdb -> updatePW($nick, $pw);
$this -> call("notice", $nick, "Your new pw is now: ".$pw);
}
else{
$this -> call("notice", $nick, "You are not identified. Type /msg ".$this -> nick." identify <password> in order to identify yourself");
}
?>

45
commands/user.prefix.php Normal file
View File

@ -0,0 +1,45 @@
<?php
#BOT_INCLUDE "user" "prefix" "3"
/*
* This file contains code for the prefix-based user-command
*/
$nick = $recv["msgarr"][2];
switch($recv["msgarr"][1]){
case "add":
$pw = md5(rand().time().md5(time()));
$this -> userdb -> addUser($nick, $pw);
$this -> userdb -> setLevel($nick, 1);
$this -> call("notice", $nick, "Your current password: ".$pw);
$this -> call("notice", $nick, "Your current level: 1");
$this -> call("notice", $nick, "In order to change your password, type: /msg ".$this -> nick." identify ".$pw." and /msg ".$this -> nick." password <new password>");
break;
case "del":
$this -> userdb -> delUser($nick);
$this -> call("privmsg", $recv["origin"], "User '".$nick."' deleted.");
break;
case "level":
$this -> userdb -> setLevel($nick, $recv["msgarr"][3]);
$this -> call("notice", $nick, "Your new level: ".$recv["msgarr"][3]);
break;
case "list":
$list = $this -> userdb -> listUsers();
foreach($list as $user => $level){
$users[] = $user."(".$level.")";
}
$this -> call("notice", $recv["nick"], "Users: ".implode(", ", $users));
break;
case "help":
$this -> call("notice", $recv["nick"], "Available commands: list, add <nick>, level <nick> <new level>, del <nick>, help (level 3+)");
break;
default:
$this -> call("notice", $recv["nick"], "Unknown user command! Type ".$this -> prefix."user help for further information");
break;
}
?>

View File

@ -0,0 +1,7 @@
<?php
/*
* This file contains code to be included.
*/
$nick = $recv["nick"];
$pw = $recv["msgarr"][1];
?>

29
install.php Normal file
View File

@ -0,0 +1,29 @@
#! /usr/bin/php5
<?php
error_reporting(0);
//define stdin if it's not defined yet
if(!defined("STDIN")) define("STDIN", fopen('php://stdin','r'));
//check for an existing users.db
if(file_exists("users.db")) die("\n(!)Delete your old users.db file before creating the primary admin account(!)\n\n");
//tell, what we're doing here
echo "This script will create the first admin account for the bot.\n";
echo "The username has to be identical to your IRC-nickname, so the bot can recognize you.\n\n";
//ask for username and password
echo "Username: ";
$user = trim(fread(STDIN, 80));
echo "Password (will be displayed): ";
$pass = trim(fread(STDIN, 80));
//create account here
require("modules/userdb.class.php");
$userdb = new userdb();
$userdb -> addUser($user, $pass);
$userdb -> setLevel($user, 9);
unset($userdb);
echo "Admin account created. You can now start the bot!\n";
?>

View File

@ -0,0 +1,78 @@
<?php
/*****************************
* Blockstring Class by JPT *
* http://jpt.de.tf *
* to be used as a buffer *
*****************************/
class blockstring{
public $endl;
private $datapool;
function __construct($endl){
$this -> datapool = "";
$this -> endl = $endl;
}
public function addData($data){
$this -> datapool .= $data.$this -> endl; //We add the endl to the end of each block of data due to some cutting issues..
}
public function isFull(){
return (trim($this -> datapool) != "") ? true : false;
}
public function gotLine(){
return ($this -> isFull() && (preg_match("/".$this -> endl."/", $this -> datapool))) ? true : false;
}
public function getLineArray(){
if(!$this -> isFull()) return false;
$pool = $this -> datapool; //Copy our original pool
$lines = explode($this -> endl, $pool); //explode by endline...
unset($pool);
//clean up all lines
foreach($lines as $key => $line){
$line = $this -> stripLine($line);
if(trim($line) != "") $lines[$key] = $line;
}
return $lines;
}
public function getNextLine(){
if(!$this -> gotLine()) return false;
$expl = explode($this -> endl, $this -> datapool); //explode by endline...
$line = $expl[0]; //...to get next line from datapool
//Kill the fetched line
unset($expl[0]);
$this -> datapool = implode($this -> endl, $expl);
$line = $this -> stripLine($line); //clean up gained line
if($line == "") return $this -> getNextLine();
return $line;
}
public function countLines(){
$count = count($this -> getLineArray());
return $count;
}
public function stripLine($line){
$replace = array("\r","\n","\0");
$line = str_replace($replace,"",$line);
$line = trim($line);
return $line;
}
public function clear(){
unset($this -> datapool);
$this -> datapool = "";
}
function __destruct(){
unset($this -> datapool);
}
}
?>

155
modules/command.class.php Normal file
View File

@ -0,0 +1,155 @@
<?php
class command_handler{
private $seperator = "/"; // "/" on Linux, "\" on Windows
private $db = "commands.db";
private $codedir = "commands";
private $commands;
public function __construct(){
$this -> load();
$this -> update();
}
public function load(){
if(file_exists($this -> db)){
$data = file_get_contents($this -> db);
if(!$this -> commands = unserialize($data)) $this -> commands = array();
unset($data);
}
else $this -> commands = array();
}
private function sortCMP($a, $b){
if($a["level"] == $b["level"]) return (strcmp($a["trigger"], $b["trigger"]) > 0) ? 1 : -1;
return ($a["level"] < $b["level"]) ? -1 : 1;
}
public function sort(){
//create temporary array
foreach($this -> commands as $trigger => $arr){
$temp[$trigger]["array"] = $arr;
$temp[$trigger]["level"] = $arr["level"];
$temp[$trigger]["trigger"] = $trigger;
}
//sort that temporary array by permission level and alphabetical^^
usort($temp, array($this, "sortCMP"));
//store the sorted data again
unset($this -> commands);
foreach($temp as $cmd){
$this -> commands[$cmd["trigger"]]["filename"] = $cmd["array"]["filename"];
$this -> commands[$cmd["trigger"]]["context"] = $cmd["array"]["context"];
$this -> commands[$cmd["trigger"]]["level"] = $cmd["array"]["level"];
}
unset($temp);
}
public function getList($level){
foreach($this -> commands as $command => $arr){
//Query commands: * Prefix commands: (prefix) Global commands: nothing
$char = ($arr["context"] == "query" && $arr["context"] != "global") ? "*" : "#";
if($arr["level"] <= $level && $arr["context"] != "channel"){
$c[] = $command.$char."(".$arr["level"].")";
}
}
return implode(", ", $c);
}
public function update(){
//delete non-existing commands
foreach($this -> commands as $command => $arr){
if(!file_exists($this -> getPath().$arr["filename"])) $this -> delCode($command);
}
//register the new commands
$files = scandir($this -> codedir);
foreach($files as $file){
if(preg_match("/.php$/", $file)) $this -> addCode($file);
}
$this -> sort();
}
public function save(){
file_put_contents($this -> db, serialize($this -> commands));
}
public function __destruct(){
$this -> save();
}
/*
* returns code to be evaluated and stuff
*/
public function getCode($command, $context, $level){
if(isset($this -> commands[$command]) && file_exists($this -> getPath().$this -> commands[$command]["filename"])){
if(($this -> commands[$command]["context"] == $context || $this -> commands[$command]["context"] == "global") && $this -> commands[$command]["level"] <= $level){
$file = $this -> getPath().$this -> commands[$command]["filename"];
$replace = array("<?php", "?>");
$code = str_replace($replace, "", file_get_contents($file));
//access granted; returning code to eval()
return str_replace("#BOT_PATH", $this -> getPath(), $code);
}
elseif($this -> commands[$command]["context"] != $context && $this -> commands[$command]["context"] != "global"){
//wrong context!
return 3;
}
else{
//Permission denied
return 2;
}
}
else{
//Command does not exist yet
return 0;
}
}
public function addCode($filename){
$file = $this -> getPath().$filename;
if(file_exists($file)){
$content = file($file);
if(preg_match("/#BOT_INCLUDE/", $content[1])){
$data = explode(" ", str_replace("\"", "", $content[1]));
unset($content);
$command = trim($data[1]);
$level = trim($data[3]);
if(!is_numeric($level)) $level = 0;
$this -> commands[$command]["filename"] = $filename;
$this -> commands[$command]["context"] = trim($data[2]);
$this -> commands[$command]["level"] = $level;
return true;
}
else{
return false;
}
}
else{
return false;
}
}
public function delCode($command){
unset($this -> commands[$command]);
}
public function getLevel($command){
return $this -> commands[$command]["level"];
}
public function getContext($command){
return $this -> commands[$command]["context"];
}
private function getPath(){
return $this -> codedir.$this -> seperator;
}
}
?>

102
modules/fsock.class.php Normal file
View File

@ -0,0 +1,102 @@
<?php
/*****************************
* Simple Fsock Class by JPT *
* http://jpt.de.tf *
*****************************/
class fsock{
public $host;
public $port;
public $buffer; //is passed to fgets()
public $timeout; //Timout to connect
public $recvtimeout; //Timeout for recieving...
public $endl; //Linebreak to use...
public $debug = false; //Debug switch;
private $connection;
private $errno;
private $errstr;
function __construct($host, $port, $buffer, $endl, $timeout, $recvtimeout){
$this -> host = $host;
$this -> port = $port;
$this -> buffer = $buffer;
$this -> endl = $endl;
$this -> timeout = $timeout;
$this -> recvtimeout = $recvtimeout;
$this -> connection = fsockopen($this -> host, $this -> port, $this -> errno, $this -> errstr, $this -> timeout);
if(!$this -> connection){
$this -> error("Could not connect to ".$this -> host.":".$this -> port."!");
}
if($this -> recvtimeout != false) stream_set_timeout($this -> connection, $this -> recvtimeout);
}
public function checkConnection(){
if(!is_resource($this -> connection)){
$this -> close();
return false;
}
else{
return true;
}
}
public function isConnected(){
return ($this -> connection && is_resource($this -> connection)) ? true : false;
}
public function gotData(){
return ($this -> isConnected()) ? feof($this -> connection) : false;
}
public function send($msg){
$this -> checkConnection();
if(trim($msg) != ""){
if(!fwrite($this -> connection, $msg.$this -> endl)){
if($this -> debug) echo "[Fsock] Could not send:'".$msg."'";
return false;
}
else{
if($this -> debug) echo "[Fsock] Sent: ".$msg."\n";
return true;
}
}
}
public function recv(){
$this -> checkConnection();
if(!feof($this -> connection)){
if(($recv = fread($this -> connection, $this -> buffer)) != ''){
if($this -> debug) echo "[Fsock] Recv: ".$recv."\n";
return $recv;
}
else{
return false;
}
}
else{
return false;
}
}
public function close(){
if($this -> connection){
fclose($this -> connection);
unset($this -> connection);
}
}
function __destruct(){
$this -> close();
}
public function error($msg){
echo "[ClientFSockClass] ".$msg."\n";
//die();
}
}
?>

10
modules/init.inc.php Normal file
View File

@ -0,0 +1,10 @@
<?php
require "blockstring.class.php";
require "fsock.class.php";
require "command.class.php";
require "userdb.class.php";
require "ircprotocol.class.php";
require "irc.class.php";
?>

356
modules/irc.class.php Normal file
View File

@ -0,0 +1,356 @@
<?php
class ircbot{
public $debug = false; //Debugging
protected $nick;
protected $username;
protected $realname;
protected $host;
protected $port;
public $alive; //Bot alive?
protected $sleep; //How long to wait after sending 1 line
protected $channels = array(); //Channel-Array
private $protocol; //IRC-Protocol Handler
private $connection; //Fsock-class Handler (false if not connected)
private $recvbuf; //RECV-Buffer
private $sendbuf; //SEND-Buffer
private $reactbuf; //REACT-Buffer (to bypass linebreak errors)
private $commands; //Command-Handler for additional files
private $userdb; //User-Permission-DB
private $endl = "\r\n"; //ENDL-Marker
private $prefix; //Command Prefix
private $autoreconnect; //Shall the Bot try to reconnect again?
private $login = false; //connection successful, we can work if it's true
private $lastline = ""; //last sent line... (flood protection)
private $lastlinetime = 0; //timestamp of last sent line
/*
* Class general stuff
*/
function __construct($nick, $username, $realname){
$this -> alive = true;
$this -> nick = $nick;
$this -> username = $username;
$this -> realname = $realname;
$this -> connection = false;
$this -> protocol = new ircprotocol($nick, $username, $realname);
$this -> sendbuf = new blockstring($this -> endl);
$this -> recvbuf = new blockstring($this -> endl);
$this -> reactbuf = new blockstring($this -> endl);
$this -> commands = new command_handler();
$this -> userdb = new userdb();
}
public function setServer($host, $port){
$this -> host = $host;
$this -> port = $port;
}
public function setAutoReconnect($bool){
$this -> autoreconnect = $bool;
}
public function setPrefix($prefix){
$this -> prefix = $prefix;
}
public function addChannels($channels){
$this -> channels = array_merge($this -> channels, $channels);
if($this -> login){
foreach($channels as $channel){
$this -> call("join", $channel);
}
}
}
public function removeChannels($channels){
foreach($channels as $channel){
unset($this -> channels[array_search($channel, $this -> channels)]);
if($this -> login) $this -> call("part", $channel, "Removed ".$channel." from list.");
}
}
public function setSleep($sleep){
$this -> sleep = $sleep * 1000000;
}
public function clearBuffer(){
$this -> sendbuf -> clear();
$this -> recvbuf -> clear();
$this -> reactbuf -> clear();
}
function __destruct(){
$this -> clearBuffer();
if($this -> connection){
$this -> autoreconnect = false;
$this -> disconnect();
}
unset($this -> recvbuf);
unset($this -> sendbuf);
unset($this -> reactbuf);
unset($this -> commands);
unset($this -> userdb);
$this -> alive = false;
}
/*
* Connection handling stuff
*/
public function connect(){
$this -> connection = new fsock($this -> host, $this -> port, 16384, $this -> endl, 5, 0.5);
$this -> send($this -> protocol -> auth());
$this -> send($this -> protocol -> nick());
//Wait for being able to join channels
while(!$this -> login) $this -> update();
//Join given channels
foreach($this -> channels as $channel){
$this -> call("join", $channel);
}
//Update in order to send all join commands...
$this -> update();
}
public function send($msg){
if($msg != "") $this -> sendbuf -> addData($msg.$this -> endl);
$this -> update();
}
public function recv(){
$this -> update();
if(!$line = $this -> recvbuf -> getNextLine()) return false;
$recv = $this -> protocol -> parse($line);
//add permission level, process-flag and default value for "command"
if(isset($recv["nick"])) $recv["level"] = $this -> userdb -> getLevel($recv["nick"]);
$recv["processed"] = false;
$recv["command"] = false;
//If we've got a Query...
if($this -> protocol -> checkQuery($recv)){
$recv["processed"] = true;
$recv["query"] = true;
$recv["command"] = ($recv["msgarr"][0][0] == $this -> prefix) ? substr($recv["msgarr"][0], 1) : $recv["msgarr"][0];
if($code = $this -> commands -> getCode($recv["command"], "query", $recv["level"])){
if($this -> debug) echo "[EVAL] Command: ".$recv["command"]." (query)\n";
if(trim($code) != "" && !is_numeric($code)){
eval($code);
}
unset($code, $recv["command"]);
}
}//if query
//if command with prefix has been called...
if($this -> protocol -> checkCommand($this -> prefix, $recv)){
$recv["processed"] = true;
$recv["command"] = $this -> protocol -> getCommand($this -> prefix, $recv);
$code = $this -> commands -> getCode($recv["command"], "prefix", $recv["level"]);
if(trim($code) != "" && !is_numeric($code)){
if($this -> debug) echo "[EVAL] Command: ".$recv["command"]." (prefix)\n".$code."\n";
eval($code);
unset($code, $recv["command"]);
}
elseif($code == 2){
$this -> call("privmsg", $recv["target"], $recv["nick"].": permission denied! (your level: ".$recv["level"]." < ".$this -> commands -> getLevel($recv["command"]).")");
if(!$this -> userdb -> isActive($recv["nick"]) && $this -> userdb -> isUser($recv["nick"])) $this -> call("notice", $recv["nick"], "You have to identify yourself! (Type ".$this -> prefix."help for further information)");
}
elseif($code == 3){
$this -> call("privmsg", $recv["target"], $recv["nick"].": permission denied! (context: ".$this -> commands -> getContext($recv["command"]).")");
}
}//if prefix command
//If we've got a Channel-Command without trigger...that has NOT been processed before!
if(!$recv["processed"] && $this -> protocol -> checkChannel($recv)){
$recv["command"] = $recv["target"];
if($code = $this -> commands -> getCode($recv["command"], "channel", $recv["level"])){
if($this -> debug) echo "[EVAL] Command: ".$recv["command"]." (channel)\n";
eval($code);
unset($code, $recv["command"]);
$recv["processed"] = true;
}
}//if channel
$recv["command"] = (isset($recv["command"]) && !$recv["processed"]) ? $recv["command"] : "";
return $recv;
}
/*
* Updating recvbuf and flushing sendbuf while checking for incoming pings
*/
public function update(){
if($this -> connection -> isConnected()){
//Putting recieved stuff into the recv-buffer
while($recv = $this -> connection -> recv()){
$this -> reactbuf -> addData($recv);
unset($recv);
}//recv loop
//emergency flood protection
$lines = 0;
$lines = $this -> reactbuf -> countLines();
if(($lines > 215)){
if($this -> debug) echo "[FLOOD] Houston, we have got a problem! (".$lines." lines at once)\n";
$this -> disconnect();
}
//react to stuff
while($this -> reactbuf -> gotLine()){
if(!$this -> react($recv = $this -> reactbuf -> getNextLine())) $this -> recvbuf -> addData($recv);
}
//Sending everything we've got in our buffer
while($this -> sendbuf -> gotLine()){
$data = $this -> sendbuf -> getNextLine();
if(($data != $this -> lastline && trim($data) != "") || ($data == $this -> lastline && time() - 10 > $this -> lastlinetime)){//we will never repeat something within 10 seconds
if($this -> debug) echo "Sending: '".$data."'\n";
$this -> connection -> send($data);
$this -> lastline = $data;
$this -> lastlinetime = time();
unset($data);
usleep($this -> sleep);
}
}//send loop
//if there is nothing to process and nothing to recieve, we can allow the cpu to have a break.
if(!$this -> recvbuf -> gotLine() && !$this -> connection -> gotData()) usleep($this -> sleep);
}//if connected
else{
if($this -> debug) echo "Connection closed!\n";
$this -> disconnect();
}
}
public function disconnect(){
if($this -> debug) echo "Disconnecting...";
$this -> clearBuffer();
$this -> login = false;
$this -> lastline = "";
$this -> lastlinetime = 0;
if($this -> connection){
unset($this -> connection);
$this -> connection = false;
}
if($this -> debug) echo "done.\n";
if($this -> autoreconnect){
sleep(1);
if($this -> debug) echo "AutoReconnect enabled. Reconnecting now...\n";
$this -> connect();
if($this -> debug) echo "Reconnect done.\n";
}
}
/*
* Other stuff...
*/
//Nickchange within runtime
public function setNick($nick){
if($this -> nick != $nick){
$this -> nick = $nick;
$this -> send($this -> protocol -> setNick($this -> nick));
$this -> update();
}
}
//Call IRC-Protocol functions (join, part, privmsg,....) and send the result directly
public function call(){
$params = func_get_args();
$function = $params[0];
$array = array_slice($params,1);
foreach($array as $value) $args[] = addslashes($value);
$args = implode("', '",$args);
$call = "\$data = \$this -> protocol -> ".$function."('".$args."');";
if($this -> debug) echo "[EVAL] Calling: '".$call."'\n";
eval($call);
$this -> send(stripslashes($data));
unset($call, $data);
}
/*
* Reacting to some important stuff
*/
private function react($recv){
$p = $this -> protocol -> parse($recv);
if($this -> login == false && ($p["servermsg"] === true && $p["action"] == "001")) $this -> login = true; //we're logged in if 001 MSG arrives
elseif($this -> login == false && ($p["servermsg"] === true && $p["action"] == "433")) $this -> setNick($this -> nick."|".rand(0,9)); //our chosen nick is already in use
elseif($p["servermsg"] === true && $p["action"] == "474") $this -> removeChannels(array($p["param"])); //our chosen nick is already in use
//if we've got a PING
elseif(trim($data = $this -> protocol -> checkPing($recv)) != ""){
$this -> send($data);
unset($data);
}
//check for a serverkick (ERROR)
elseif(preg_match("/^ERROR :/", $recv)){
if($this -> debug) echo "Serverkick!\n";
$this -> disconnect();
}
elseif($p["action"] == "KICK" && $p["param"] == $this -> nick) $this -> call("join", $p["target"]); //check for being kicked..
elseif($p["action"] == "PART" && $p["nick"] == $this -> nick) $this -> call("join", $p["target"]); //check for being parted..
elseif($p["action"] == "QUIT" || $p["action"] == "PART") $this -> userdb -> logout($p["nick"]); //check for user logout
else{
//bot did not react to this line
return false;
}
//bot reacted to this in some way.
return true;
}
/*
* Other stuff....
*/
//evaluating php-code and return output (WILL CAUSE PROBLEMS WHEN DEBUG-OUTPUT IS ON!)
public function eval_php($code){
ob_start();
eval($code);
$output = ob_get_contents();
ob_clean();
ob_end_clean();
return $output;
}
public function eval_sys($cmd){
$p = popen($cmd, "r");
while($data = fgets($p, 8192)){
$result[] = $data;
}
pclose($p);
return $result;
}
}
?>

View File

@ -0,0 +1,179 @@
<?php
class ircprotocol{
private $username;
private $realname;
private $nick;
function __construct($nick, $username, $realname){
$this -> nick = $nick;
$this -> username = $username;
$this -> realname = $realname;
}
/*
* General Stuff
*/
public function auth(){
return "USER ".$this -> username." as as :".$this -> realname;
}
public function nick(){
return "NICK ".$this -> nick;
}
public function setNick($nick){
if($this -> nick != $nick){
$this -> nick = $nick;
return $this -> nick();
}
}
public function join($channel){
return "JOIN ".$channel;
}
public function part($channel, $msg){
return "PART ".$channel." :".$msg;
}
public function away($msg){
return "AWAY :".$msg;
}
public function kick($channel, $nick, $msg=""){
return "KICK ".$channel." ".$nick." :".$msg;
}
public function quit($msg){
return "QUIT :".$msg;
}
public function privmsg($target, $msg){
return "PRIVMSG ".$target." :".$msg;
}
public function notice($target, $msg){
return "NOTICE ".$target." :".$msg;
}
/*
* General Mode Stuff
*/
public function mode($channel, $detail){
return "MODE ".$channel." ".$detail;
}
public function op($channel, $nick){
return $this -> mode($channel, "+o ".$nick);
}
public function deop($channel, $nick){
return $this -> mode($channel, "-o ".$nick);
}
public function voice($channel, $nick){
return $this -> mode($channel, "+v ".$nick);
}
public function devoice($channel, $nick){
return $this -> mode($channel, "-v ".$nick);
}
public function mute($channel){
return $this -> mode($channel, "+m");
}
public function unmute($channel){
return $this -> mode($channel, "-m");
}
/*
* parsing incoming IRC-Lines
*/
public function parse($msg){
if(trim($msg) == "") return false;
$expl = explode(":", $msg, 3);
$message = (isset($expl[2])) ? $expl[2] : "";
if(isset($expl[1])) $data = explode(" ", $expl[1]);
//Here we need to decide whether it's a SMSG or a usual MSG
if(isset($data[0]) && preg_match("/!/", $data[0])){
$nick = explode("!", $data[0]);
$banhost = (substr($nick[1],1,1) == "=") ? substr($nick[1], 2) : $nick[1];
$iphost = explode("@", $banhost);
$iphost = $iphost[1];
$servermsg = false;
}
else{
if(isset($data[0])) $iphost = $banhost = $data[0];
$servermsg = true;
}
$msgarr = explode(" ", $message);
$i = 0;
foreach($msgarr as $key){
$marr[$i] = $key;
$i++;
}
unset($i);
unset($msgarr);
$result['servermsg'] = $servermsg;
$result['nick'] = (isset($nick[0])) ? $nick[0] : "";
$result['banhost'] = (isset($banhost)) ? $banhost : "";
$result['iphost'] = (isset($iphost)) ? $iphost : "";
$result['action'] = (isset($data[1])) ? $data[1] : "";
$result['message'] = $message;
$result['msgarr'] = $marr;
$result['line'] = $msg;
$result['target'] = (isset($data[2])) ? $data[2] : "";
$result['origin'] = ($result['target'] == $this -> nick) ? $result['nick'] : $result['target'];
$result['param'] = (isset($data[3])) ? $data[3] : "";
return $result;
}
public function getArgs($start, $recv){
$i = 0;
while($i < $start){
if(isset($recv["msgarr"][$i])) unset($recv["msgarr"][$i]);
$i++;
}
return implode(" ", $recv["msgarr"]);
}
/*
* check for certain events
*/
public function checkQuery($recv){
return ($recv["action"] == "PRIVMSG" && strtolower($recv["target"]) == strtolower($this -> nick)) ? true : false;
}
public function checkChannel($recv){
return ($recv["action"] == "PRIVMSG" && strtolower($recv["target"]) != strtolower($this -> nick)) ? true : false;
}
public function checkCommand($prefix, $recv){
return (isset($recv["message"][0]) && $recv["message"][0] == $prefix && $recv["action"] == "PRIVMSG" && strtolower($recv["target"]) != strtolower($this -> nick)) ? true : false;
}
public function getCommand($prefix, $recv){
$expl = explode(" ", $recv["message"], 2);
return str_replace($prefix, "", $expl[0]);
}
/*
* reacting to PING Lines...
*/
public function checkPing($msg){
return (preg_match("/^PING :/", $msg)) ? str_replace("PING", "PONG", $msg) : "";
}
}
?>

129
modules/userdb.class.php Normal file
View File

@ -0,0 +1,129 @@
<?php
/*
* UserDB Class by JPT (http://jpt.redio.de)
*/
class userdb{
public $users;
public $timeout = 86400; //After $timeout seconds of inactivity, the session will expire.
private $db = "users.db";
/*
* General
*/
function __construct(){
$this -> load();
}
private function load(){
$this -> users = (file_exists($this -> db)) ? unserialize(file_get_contents($this -> db)) : array();
}
private function save(){
file_put_contents($this -> db, serialize($this -> users));
}
function __destruct(){
$this -> logoutAll();
$this -> save();
}
/*
* Userfunctions: adding, deleting, listing and verifying
*/
public function addUser($nick, $pw){
$this -> users[$nick]["pw"] = md5($pw);
}
public function listUsers(){
foreach($this -> users as $nick => $data){
$users[$nick] = $data["level"];
}
return $users;
}
public function isUser($nick){
return ($this -> users[$nick]) ? true : false;
}
public function delUser($nick){
unset($this -> users[$nick]);
}
/*
* User-Sessions: activity, verifying passwords, login + logout
*/
public function isActive($nick){
if(isset($nick) && isset($this -> users[$nick]) && ((time() - $this -> users[$nick]["lastactive"]) < $this -> timeout)){
$this -> update($nick);
return true;
}
else{
return false;
}
}
public function update($nick){
$this -> users[$nick]["lastactive"] = time();
$this -> save();
}
public function getLastActivity($nick){
return $this -> users[$nick]["lastactive"];
}
public function checkPW($nick, $pw){
return (md5($pw) == $this -> users[$nick]["pw"]) ? true : false;
}
public function updatePW($nick, $pw){
$this -> users[$nick]["pw"] = md5($pw);
}
public function logout($nick){
if($this -> isActive($nick)) $this -> users[$nick]["lastactive"] = 0;
$this -> save();
}
public function logoutAll(){
foreach($this -> users as $nick => $arr){
$this -> users[$nick]["lastactive"] = 0;
}
$this -> save();
}
/*
* Additional stuff: userlevels
*/
public function getLevel($nick){
if($this -> isActive($nick)) return $this -> users[$nick]["level"];
else return 0;
}
public function setLevel($nick, $level){
$this -> users[$nick]["level"] = $level;
}
/*
* Variable storage
*/
public function getVar($var, $nick){
return (isset($this -> users[$nick]["var"][$var])) ? $this -> users[$nick]["var"][$var] : false;
}
public function setVar($var, $value, $nick){
$this -> users[$nick]["var"][$var] = $value;
}
public function delVar($var, $nick){
unset($this -> users[$nick]["var"][$var]);
}
}
?>

4
start.sh Normal file
View File

@ -0,0 +1,4 @@
#! /bin/bash
./cleanup.sh
clear
./bot.php

1
users.db Normal file
View File

@ -0,0 +1 @@
a:1:{s:3:"JPT";a:3:{s:2:"pw";s:32:"157bf47a874202fd6494be41b355e8f7";s:5:"level";i:9;s:10:"lastactive";i:0;}}