2011-03-28 14:21:28 +00:00
|
|
|
<?
|
|
|
|
class IRC_DB extends DB_MYSQL {
|
|
|
|
function halt($Msg) {
|
|
|
|
global $Bot;
|
2014-02-19 08:00:32 +00:00
|
|
|
$Bot->send_to($Bot->get_channel(), 'The database is currently unavailable; try again later.');
|
2011-03-28 14:21:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
abstract class IRC_BOT {
|
|
|
|
abstract protected function connect_events();
|
|
|
|
abstract protected function channel_events();
|
2012-10-11 08:00:15 +00:00
|
|
|
abstract protected function query_events();
|
2011-03-28 14:21:28 +00:00
|
|
|
abstract protected function listener_events();
|
|
|
|
|
|
|
|
protected $Debug = false;
|
|
|
|
protected $Socket = false;
|
|
|
|
protected $Data = false;
|
|
|
|
protected $Whois = false;
|
|
|
|
protected $Identified = array();
|
|
|
|
protected $Channels = array();
|
|
|
|
protected $Messages = array();
|
|
|
|
protected $LastChan = false;
|
2014-02-19 08:00:32 +00:00
|
|
|
protected $ListenSocket = false;
|
2011-03-28 14:21:28 +00:00
|
|
|
protected $Listened = false;
|
2012-10-05 08:00:20 +00:00
|
|
|
protected $Connecting = false;
|
2014-02-19 08:00:32 +00:00
|
|
|
protected $Bound = false; // Did we successfully bind to the socket?
|
|
|
|
protected $State = 1; // Drone is live
|
|
|
|
public $Restart = 0; // Die by default
|
2011-03-28 14:21:28 +00:00
|
|
|
|
|
|
|
public function __construct() {
|
2013-08-13 08:00:43 +00:00
|
|
|
if (isset($_SERVER['HOME']) && is_dir($_SERVER['HOME']) && getcwd() != $_SERVER['HOME']) {
|
|
|
|
chdir($_SERVER['HOME']);
|
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
//ini_set('memory_limit', '12M');
|
|
|
|
restore_error_handler(); //Avoid PHP error logging
|
|
|
|
set_time_limit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function connect() {
|
2012-10-05 08:00:20 +00:00
|
|
|
$this->connect_irc();
|
|
|
|
$this->connect_listener();
|
|
|
|
$this->post_connect();
|
|
|
|
}
|
|
|
|
|
|
|
|
public function connect_irc($Reconnect = false) {
|
|
|
|
$this->Connecting = true;
|
2011-03-28 14:21:28 +00:00
|
|
|
//Open a socket to the IRC server
|
2012-10-05 08:00:20 +00:00
|
|
|
while (!$this->Socket = fsockopen('tls://'.BOT_SERVER, BOT_PORT_SSL)) {
|
|
|
|
sleep(15);
|
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
stream_set_blocking($this->Socket, 0);
|
2012-10-05 08:00:20 +00:00
|
|
|
$this->Connecting = false;
|
|
|
|
if ($Reconnect) {
|
|
|
|
$this->post_connect();
|
|
|
|
}
|
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
|
2012-10-05 08:00:20 +00:00
|
|
|
public function connect_listener() {
|
2011-03-28 14:21:28 +00:00
|
|
|
//create a socket to listen on
|
|
|
|
$this->ListenSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
|
|
|
//socket_set_option($this->ListenSocket, SOL_TCP, SO_REUSEADDR, 1);
|
|
|
|
socket_set_option($this->ListenSocket, SOL_SOCKET, SO_REUSEADDR, 1);
|
2012-10-05 08:00:20 +00:00
|
|
|
$this->Bound = socket_bind($this->ListenSocket, SOCKET_LISTEN_ADDRESS, SOCKET_LISTEN_PORT);
|
2011-03-28 14:21:28 +00:00
|
|
|
socket_listen($this->ListenSocket);
|
|
|
|
socket_set_nonblock($this->ListenSocket);
|
2012-10-05 08:00:20 +00:00
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
|
2012-10-05 08:00:20 +00:00
|
|
|
public function post_connect() {
|
2011-03-28 14:21:28 +00:00
|
|
|
fwrite($this->Socket, "NICK ".BOT_NICK."Init\n");
|
|
|
|
fwrite($this->Socket, "USER ".BOT_NICK." * * :IRC Bot\n");
|
|
|
|
$this->listen();
|
|
|
|
}
|
|
|
|
|
2013-04-19 08:00:55 +00:00
|
|
|
public function disconnect() {
|
2011-03-28 14:21:28 +00:00
|
|
|
socket_close($this->ListenSocket);
|
|
|
|
$this->State = 0; //Drones dead
|
|
|
|
}
|
|
|
|
|
|
|
|
public function get_channel() {
|
|
|
|
preg_match('/.+ PRIVMSG ([^:]+) :.+/', $this->Data, $Channel);
|
2013-06-18 08:00:48 +00:00
|
|
|
if (preg_match('/#.+/', $Channel[1])) {
|
2011-03-28 14:21:28 +00:00
|
|
|
return $Channel[1];
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function get_nick() {
|
|
|
|
preg_match('/:([^!:]+)!.+@[^\s]+ PRIVMSG [^:]+ :.+/', $this->Data, $Nick);
|
|
|
|
return $Nick[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function get_message() {
|
|
|
|
preg_match('/:.+ PRIVMSG [^:]+ :(.+)/', $this->Data, $Msg);
|
|
|
|
return trim($Msg[1]);
|
|
|
|
}
|
|
|
|
|
2012-10-11 08:00:15 +00:00
|
|
|
protected function get_irc_host() {
|
2011-03-28 14:21:28 +00:00
|
|
|
preg_match('/:[^!:]+!.+@([^\s]+) PRIVMSG [^:]+ :.+/', $this->Data, $Host);
|
|
|
|
return trim($Host[1]);
|
|
|
|
}
|
|
|
|
|
2013-07-17 08:00:52 +00:00
|
|
|
protected function get_word($Select = 1) {
|
2011-03-28 14:21:28 +00:00
|
|
|
preg_match('/:.+ PRIVMSG [^:]+ :(.+)/', $this->Data, $Word);
|
2013-06-18 08:00:48 +00:00
|
|
|
$Word = split(' ', $Word[1]);
|
2011-03-28 14:21:28 +00:00
|
|
|
return trim($Word[$Select]);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function get_action() {
|
|
|
|
preg_match('/:.+ PRIVMSG [^:]+ :!(\S+)/', $this->Data, $Action);
|
|
|
|
return strtoupper($Action[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function send_raw($Text) {
|
2012-10-05 08:00:20 +00:00
|
|
|
if (!feof($this->Socket)) {
|
2013-07-17 08:00:52 +00:00
|
|
|
fwrite($this->Socket, "$Text\n");
|
2012-10-05 08:00:20 +00:00
|
|
|
} elseif (!$this->Connecting) {
|
|
|
|
$this->Connecting = true;
|
|
|
|
sleep(120);
|
|
|
|
$this->connect_irc(true);
|
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function send_to($Channel, $Text) {
|
2013-10-14 08:00:53 +00:00
|
|
|
// split the message up into <= 460 character strings and send each individually
|
|
|
|
// this is used to prevent messages from getting truncated
|
|
|
|
$Text = wordwrap($Text, 460, "\n", true);
|
|
|
|
$TextArray = explode("\n", $Text);
|
|
|
|
foreach ($TextArray as $Text) {
|
|
|
|
$this->send_raw("PRIVMSG $Channel :$Text");
|
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected function whois($Nick) {
|
|
|
|
$this->Whois = $Nick;
|
|
|
|
$this->send_raw("WHOIS $Nick");
|
|
|
|
}
|
2012-10-11 08:00:15 +00:00
|
|
|
|
2011-03-28 14:21:28 +00:00
|
|
|
/*
|
2012-10-11 08:00:15 +00:00
|
|
|
This function uses blacklisted_ip, which is no longer in RC2.
|
|
|
|
You can probably find it in old RC1 code kicking aronud if you need it.
|
2013-06-18 08:00:48 +00:00
|
|
|
protected function ip_check($IP, $Gline = false, $Channel = BOT_REPORT_CHAN) {
|
2013-04-20 08:01:01 +00:00
|
|
|
if (blacklisted_ip($IP)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->send_to($Channel, 'TOR IP Detected: '.$IP);
|
|
|
|
if ($Gline) {
|
|
|
|
$this->send_raw('GLINE *@'.$IP.' 90d :DNSBL Proxy');
|
|
|
|
}
|
|
|
|
}
|
2013-04-20 08:01:01 +00:00
|
|
|
if (Tools::site_ban_ip($IP)) {
|
2013-02-07 08:00:47 +00:00
|
|
|
$this->send_to($Channel, 'Site IP Ban Detected: '.$IP);
|
|
|
|
if ($Gline) {
|
|
|
|
$this->send_raw('GLINE *@'.$IP.' 90d :IP Ban');
|
2011-03-28 14:21:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}*/
|
|
|
|
|
|
|
|
protected function listen() {
|
2013-08-28 23:08:41 +00:00
|
|
|
G::$Cache->InternalCache = false;
|
2011-03-28 14:21:28 +00:00
|
|
|
stream_set_timeout($this->Socket, 10000000000);
|
2013-04-20 08:01:01 +00:00
|
|
|
while ($this->State == 1) {
|
|
|
|
if ($this->Data = fgets($this->Socket, 256)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
//IP checks
|
2013-04-20 08:01:01 +00:00
|
|
|
//if (preg_match('/:\*\*\* (?:REMOTE)?CONNECT: Client connecting (?:.*) \[(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\] \[(.+)\]/', $this->Data, $IP)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
// $this->ip_check($IP[1],true);
|
|
|
|
//}
|
|
|
|
|
2013-04-20 08:01:01 +00:00
|
|
|
if ($this->Debug === true) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->send_to(BOT_DEBUG_CHAN, $this->Data);
|
|
|
|
}
|
|
|
|
|
2013-04-20 08:01:01 +00:00
|
|
|
if ($this->Whois !== false) {
|
2013-06-18 08:00:48 +00:00
|
|
|
$Exp = explode(' ', $this->Data);
|
2013-04-20 08:01:01 +00:00
|
|
|
if ($Exp[1] == '307') {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->Identified[$this->Whois] = 1;
|
|
|
|
$this->send_to($this->LastChan, "$this->Whois correctly identified as a real person!");
|
|
|
|
$this->Whois = false;
|
|
|
|
$this->LastChan = false;
|
2013-04-20 08:01:01 +00:00
|
|
|
} elseif ($Exp[6] == '/WHOIS') {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->Whois = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-20 08:01:01 +00:00
|
|
|
if (preg_match("/:([^!]+)![^\s]* QUIT.* /", $this->Data, $Nick)) {
|
|
|
|
if (isset($this->Identified[$Nick[1]])) {
|
2011-03-28 14:21:28 +00:00
|
|
|
unset($this->Identified[$Nick[1]]);
|
|
|
|
}
|
2013-04-05 08:00:43 +00:00
|
|
|
if (isset($this->DisabledUsers[$Nick[1]])) {
|
2014-06-16 08:00:27 +00:00
|
|
|
if ($this->DisabledUsers[$Nick[1]]['UserID'] != 0) {
|
|
|
|
G::$DB->query("
|
|
|
|
DELETE FROM disable_list
|
|
|
|
WHERE Nick = '$Nick[1]'");
|
|
|
|
G::$Cache->decrement_value('num_disablees');
|
|
|
|
}
|
2013-04-05 08:00:43 +00:00
|
|
|
unset($this->DisabledUsers[$Nick[1]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-18 08:00:48 +00:00
|
|
|
if (preg_match("/:([^!]+)![^\s]* PART ".BOT_DISABLED_CHAN.'/', $this->Data, $Nick)) {
|
2013-04-05 08:00:43 +00:00
|
|
|
if (isset($this->DisabledUsers[$Nick[1]])) {
|
2014-06-16 08:00:27 +00:00
|
|
|
if ($this->DisabledUsers[$Nick[1]]['UserID'] != 0) {
|
|
|
|
G::$DB->query("
|
|
|
|
DELETE FROM disable_list
|
|
|
|
WHERE Nick = '$Nick[1]'");
|
|
|
|
G::$Cache->decrement_value('num_disablees');
|
|
|
|
}
|
2013-04-05 08:00:43 +00:00
|
|
|
unset($this->DisabledUsers[$Nick[1]]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-18 08:00:48 +00:00
|
|
|
if (preg_match("/:([^!]+)![^\s]* KICK ".BOT_DISABLED_CHAN.'.* /', $this->Data, $Nick)) {
|
2013-07-17 08:00:52 +00:00
|
|
|
$Nick = explode(' ', $Nick[0]);
|
2013-04-06 08:01:05 +00:00
|
|
|
if (isset($this->DisabledUsers[$Nick[3]])) {
|
2014-06-16 08:00:27 +00:00
|
|
|
if ($this->DisabledUsers[$Nick[3]]['UserID'] != 0) {
|
|
|
|
G::$DB->query("
|
|
|
|
DELETE FROM disable_list
|
|
|
|
WHERE Nick = '$Nick[3]'");
|
|
|
|
G::$Cache->decrement_value('num_disablees');
|
|
|
|
}
|
2013-04-06 08:01:05 +00:00
|
|
|
unset($this->DisabledUsers[$Nick[3]]);
|
2013-04-05 08:00:43 +00:00
|
|
|
}
|
2011-03-28 14:21:28 +00:00
|
|
|
}
|
|
|
|
|
2013-04-20 08:01:01 +00:00
|
|
|
if (preg_match('/End of message of the day./', $this->Data)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->connect_events();
|
|
|
|
}
|
|
|
|
|
2013-04-20 08:01:01 +00:00
|
|
|
if (preg_match('/PING :(.+)/', $this->Data, $Ping)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->send_raw('PONG :'.$Ping[1]);
|
|
|
|
}
|
|
|
|
|
2013-06-18 08:00:48 +00:00
|
|
|
if (preg_match('/.*PRIVMSG #.*/', $this->Data)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->channel_events();
|
|
|
|
}
|
|
|
|
|
2013-07-17 08:00:52 +00:00
|
|
|
if (preg_match('/.* PRIVMSG '.BOT_NICK.' .*/', $this->Data)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->query_events();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-20 08:01:01 +00:00
|
|
|
if ($this->Listened = @socket_accept($this->ListenSocket)) {
|
2011-03-28 14:21:28 +00:00
|
|
|
$this->listener_events();
|
|
|
|
}
|
2012-10-11 08:00:15 +00:00
|
|
|
|
2013-08-28 23:08:41 +00:00
|
|
|
G::$DB->LinkID = false;
|
|
|
|
G::$DB->Queries = array();
|
2011-03-28 14:21:28 +00:00
|
|
|
usleep(5000);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
?>
|