Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add timer based plugins #5

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 87 additions & 70 deletions IRC.php
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
<?php
class IRC {

public $nick;

private $socket;
private $actions;

private $timers;

private $server;
private $port;
private $realname;
private $authentication;
private $channels;

private $version = "UTAbot 0.6";

function __construct($server, $port, $nick, $realname, $authentication, $channels) {
foreach (get_defined_vars() as $arg=>$val) {
$this->$arg = $val;
}

}

public function connect() {
$address = gethostbyname($this->server);

Expand All @@ -30,96 +31,112 @@ public function connect() {
} else {
echo "OK.\n";
}

echo "Attempting to connect to '$this->server' ('$address') on port '$this->port'...";
$result = socket_connect($this->socket, $address, $this->port);
if ($result === false) {
die("Connection failed: ($result) " . socket_strerror(socket_last_error($this->socket)) . "\n");
} else {
echo "OK.\n";
}

$this->actions = new Actions();

$this->timers = new Timers($this);

}

public function authorize() {
$this->send("NICK " . $this->nick);
$this->send("USER " . $this->nick . " " . $this->nick . " " . $this->nick . " " .$this->realname);
if ( strlen($this->authentication) > 0 ) {
$this->send($this->authentication);
}
}

public function join() {
foreach($this->channels as $chan) {
$this->send("JOIN " . $chan);
}
}

public function handleRecv() {
while ($recv = socket_read($this->socket, 2048)) {
echo "<< " . $recv;

$message = "";
$channel = "";
$parts = explode(" :", $recv);
$source_parts = explode(" ", substr($parts[0], 1));
$user = $source_parts[0];
$user_parts = explode("!", $user);
$nickname = $user_parts[0];

if ( isset($source_parts[2]) ) { $channel = $source_parts[2]; }
if ( $channel == $this->nick ) { $channel = $nickname; }

if ( isset($parts[1]) ) { $message = $parts[1]; }

if ( strstr($recv, " 433 ") ) { // Nickname is already in use. // add | and try again
$this->nick .= "|";
$this->send("NICK " . $this->nick);
}

if ( strstr($recv, " 451 ") ) { // You have not registered. // try joining again
$this->join();
}

// respond to PINGs
if ( substr($recv, 0, 4) == "PING" ) {
$this->send("PONG" . substr($recv, 4));
}

if ( isset($parts[1]) && substr($channel, 0, 1) == "#" ) {
// if message came from a channel, see if there is anything we can do with the whole message
$this->sendToChan( $channel, Misc::analyze($message) );
}

// first character is !, must be a command
if ( substr($message, 0, 1) == "!" ) {
if ( strstr($message, " ") ) { $params = explode(" ", $message); }
else { $params = array($message); }
$command = trim(strtolower(substr($params[0], 1)));

if ( isset($this->actions->plugins[$command]) ) {
$args = explode(" ", trim($message));
unset($args[0]); $args = array_values(array_filter($args));

$className = $this->actions->plugins[$command];
$result = $className::$command($channel, $nickname, $args);
$this->sendToChan( $channel, $result );
}
}

socket_set_nonblock($this->socket);
while (true) {
$recv = socket_read($this->socket, 2048);
if ( $recv === false ){
$err = socket_last_error($this->socket);
if ( $err != 11 ){
echo "Error: (" . $err . ") " . socket_strerror($err) . "\r\n";
break;
}
}
if ( $recv != "" ){
echo "<< " . $recv;

$message = "";
$channel = "";
$parts = explode(" :", $recv);
$source_parts = explode(" ", substr($parts[0], 1));
$user = $source_parts[0];
$user_parts = explode("!", $user);
$nickname = $user_parts[0];

if ( isset($source_parts[2]) ) { $channel = $source_parts[2]; }
if ( $channel == $this->nick ) { $channel = $nickname; }

if ( isset($parts[1]) ) { $message = $parts[1]; }

if ( strstr($recv, " 433 ") ) { // Nickname is already in use. // add | and try again
$this->nick .= "|";
$this->send("NICK " . $this->nick);
}

if ( strstr($recv, " 451 ") ) { // You have not registered. // try joining again
$this->join();
}

// respond to PINGs
if ( substr($recv, 0, 4) == "PING" ) {
$this->send("PONG" . substr($recv, 4));
}

if ( isset($parts[1]) && substr($channel, 0, 1) == "#" ) {
// if message came from a channel, see if there is anything we can do with the whole message
$this->sendToChan( $channel, Misc::analyze($message) );
}

// first character is !, must be a command
if ( substr($message, 0, 1) == "!" ) {

if ( strstr($message, " ") ) { $params = explode(" ", $message); }
else { $params = array($message); }

$command = trim(strtolower(substr($params[0], 1)));

if ( isset($this->actions->plugins[$command]) ) {
$args = explode(" ", trim($message));
unset($args[0]); $args = array_values(array_filter($args));

$className = $this->actions->plugins[$command];
$result = $className::$command($channel, $nickname, $args);
$this->sendToChan( $channel, $result );
}
}
}

$this->timers->updateTimers();
sleep(1);
}
socket_close($this->socket);
echo "Attempting to reconnect in 30 seconds...\n";
sleep(30);
}
private function send($msg) {

public function send($msg) {
if ( !is_array($msg) ) {
$msg = array($msg);
}

foreach ($msg as $line) {
if ( strlen($line) > 0 ) {
$line = trim($line) . "\n";
Expand All @@ -129,16 +146,16 @@ private function send($msg) {
}

}

// accepts string and array of strings for $msg
private function sendToChan($channel, $msg) {
public function sendToChan($channel, $msg) {
if ( !is_array($msg) ) {
$msg = array($msg);
}

if ( isset($msg["chan"]) ) { $channel = $msg["chan"]; unset($msg["chan"]); }
if ( isset($msg["server"]) ) { unset($msg["server"]); $this->send($msg); return NULL; }

foreach ($msg as $line) {
if ( strlen($line) > 0 ) {
$line = "PRIVMSG " . $channel . " :" . trim($line) . "\n";
Expand All @@ -147,7 +164,7 @@ private function sendToChan($channel, $msg) {
}
}
}

}

?>
14 changes: 14 additions & 0 deletions Misc.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ public static function analyze($message) {

return $result;
}

public static function getUrl($url){

$ch = curl_init();
$timeout = 5;
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$data = curl_exec($ch);
curl_close($ch);
return $data;

}

}
?>
36 changes: 36 additions & 0 deletions Timer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

class Timer {
protected $timeout; // how long between plugin executions
private $timer; // keeps track of how long it has been since last execution
private $lastCheck; // keeps track of the last time updateTimer() ran
protected $irc; // reference to the main IRC object so you can do IRC things from the execute method

function __construct(&$irc){
$this->lastCheck = time();
$this->timer = 0;
$this->irc = $irc;
$this->initialize();
}

public function updateTimer(){
$this->timer += ( time() - $this->lastCheck );
if ( $this->timer >= $this->timeout ){
$this->execute();
$this->timer = 0;
}
$this->lastCheck = time();
}

protected function initialize(){
// put code you want executed after __construct here
// in case your plugin needs to initialize some stuff
}

protected function execute(){
// put the code you want to execute when the
// timeout is reached in the execute function
}
}

?>
22 changes: 22 additions & 0 deletions Timers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

class Timers {
private $plugins;

function __construct(&$irc){
$this->plugins = array();
foreach (get_declared_classes() as $class) {
if (is_subclass_of($class, "Timer")) {
$this->plugins[] = new $class($irc);
}
}
}

function updateTimers(){
foreach ( $this->plugins as $k => $class ){
$class->updateTimer();
}
}
}

?>
2 changes: 2 additions & 0 deletions utabot.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

require_once("IRC.php");
require_once("Actions.php");
require_once("Timer.php");
require_once("Timers.php");
require_once("Misc.php");

foreach (glob( dirname(__FILE__) . "/plugins/*.php" ) as $filename) { require_once($filename); }
Expand Down