More Irc plugin work

This commit is contained in:
Luke Fitzgerald 2010-07-26 11:13:00 -07:00
parent 950685a466
commit 742b302739
17 changed files with 1133 additions and 30 deletions

View File

@ -55,12 +55,15 @@ class IrcPlugin extends ImPlugin {
public $realname = null;
public $nick = null;
public $password = null;
public $nickservidentifyregexp = null;
public $nickservpassword = null;
public $channels = null;
public $transporttype = null;
public $encoding = null;
public $regcheck = null;
public $unregregexp = null;
public $regregexp = null;
public $transport = 'irc';
public $fake_irc;
@ -249,21 +252,12 @@ class IrcPlugin extends ImPlugin {
if (!isset($this->port)) {
$this->port = 6667;
}
if (!isset($this->password)) {
$this->password = '';
}
if (!isset($this->transporttype)) {
$this->transporttype = 'tcp';
}
if (!isset($this->encoding)) {
$this->encoding = 'UTF-8';
}
if (!isset($this->nickservpassword)) {
$this->nickservpassword = '';
}
if (!isset($this->channels)) {
$this->channels = array();
}
if (!isset($this->regcheck)) {
$this->regcheck = true;

View File

@ -19,6 +19,7 @@ realname*: Real name of bot
nick*: Nickname of bot
password: Password
nickservpassword: NickServ password for identification
nickservidentifyregexp: Override existing regexp matching request for identification from NickServ
channels: Channels for bot to idle in
transporttype: Set to 'ssl' to enable SSL
encoding: Set to change encoding

View File

@ -0,0 +1,82 @@
<?php
/**
* Phergie
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.
* It is also available through the world-wide-web at this URL:
* http://phergie.org/license
*
* @category Phergie
* @package Phergie_Plugin_Beer
* @author Phergie Development Team <team@phergie.org>
* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Beer
*/
/**
* Processes requests to serve users beer.
*
* @category Phergie
* @package Phergie_Plugin_Beer
* @author Phergie Development Team <team@phergie.org>
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Beer
* @uses Phergie_Plugin_Command pear.phergie.org
* @uses Phergie_Plugin_Serve pear.phergie.org
*/
class Phergie_Plugin_Beer extends Phergie_Plugin_Abstract
{
/**
* Checks for dependencies.
*
* @return void
*/
public function onLoad()
{
$plugins = $this->plugins;
$plugins->getPlugin('Command');
$plugins->getPlugin('Serve');
}
/**
* Processes requests to serve a user a beer.
*
* @param string $request Request including the target and an optional
* suggestion of what beer to serve
*
* @return void
*/
public function onCommandBeer($request)
{
$format = $this->getConfig(
'beer.format',
'throws %target% %article% %item%.'
);
$this->plugins->getPlugin('Serve')->serve(
dirname(__FILE__) . '/Beer/beer.db',
'beer',
$format,
$request
);
}
/**
* Adds a "booze" alias for the "beer" command.
*
* @param string $request Request including the target and an optional
* suggestion of what beer to serve
*
* @return void
*/
public function onCommandBooze($request)
{
$this->onCommandBeer($request);
}
}

View File

@ -34,7 +34,7 @@ $xpath = new DOMXPath($doc);
$beers = $xpath->query('//table[@class="beerlist"]/tr/td[1]');
$db->beginTransaction();
foreach ($beers as $beer) {
$name = $beer->textContent;
$name = iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $beer->textContent);
$link = 'http://beerme.com' . $beer->childNodes->item(1)->getAttribute('href');
$insert->execute(array($name, $link));
}
@ -65,7 +65,7 @@ $columns = fgetcsv($fp, 0, '|');
$db->beginTransaction();
while ($line = fgetcsv($fp, 0, '|')) {
$line = array_combine($columns, $line);
$name = $line['name'];
$name = iconv('UTF-8', 'ISO-8859-1//TRANSLIT', $line['name']);
$link = null;
$insert->execute(array($name, $link));
}

View File

@ -72,7 +72,19 @@ class Phergie_Plugin_Censor extends Phergie_Plugin_Abstract
$this->soap = new SoapClient('http://ws.cdyne.com/ProfanityWS/Profanity.asmx?wsdl');
}
$params = array('Text' => $string);
$response = $this->soap->SimpleProfanityFilter($params);
$attempts = 0;
while ($attempts < 3) {
try {
$response = $this->soap->SimpleProfanityFilter($params);
break;
} catch (SoapFault $e) {
$attempts++;
sleep(1);
}
}
if ($attempts == 3) {
return $string;
}
return $response->SimpleProfanityFilterResult->CleanText;
}

View File

@ -0,0 +1,71 @@
<?php
/**
* Phergie
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.
* It is also available through the world-wide-web at this URL:
* http://phergie.org/license
*
* @category Phergie
* @package Phergie_Plugin_Cocktail
* @author Phergie Development Team <team@phergie.org>
* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Cocktail
*/
/**
* Processes requests to serve users cocktail.
*
* @category Phergie
* @package Phergie_Plugin_Cocktail
* @author Phergie Development Team <team@phergie.org>
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Cocktail
* @uses Phergie_Plugin_Command pear.phergie.org
* @uses Phergie_Plugin_Serve pear.phergie.org
*/
class Phergie_Plugin_Cocktail extends Phergie_Plugin_Abstract
{
/**
* Checks for dependencies.
*
* @return void
*/
public function onLoad()
{
$plugins = $this->plugins;
$plugins->getPlugin('Command');
$plugins->getPlugin('Serve');
}
/**
* Processes requests to serve a user a cocktail.
*
* @param string $request Request including the target and an optional
* suggestion of what cocktail to serve
*
* @return void
*/
public function onCommandCocktail($request)
{
$format = $this->getConfig(
'cocktail.format',
'throws %target% %article% %item%.'
);
$this->plugins->getPlugin('Serve')->serve(
dirname(__FILE__) . '/Cocktail/cocktail.db',
'cocktail',
$format,
$request,
true
);
}
}

View File

@ -0,0 +1,74 @@
<?php
if (!defined('__DIR__')) {
define('__DIR__', dirname(__FILE__));
}
// Create database schema
echo 'Creating database', PHP_EOL;
$file = __DIR__ . '/cocktail.db';
if (file_exists($file)) {
unlink($file);
}
$db = new PDO('sqlite:' . $file);
$db->exec('CREATE TABLE cocktail (name VARCHAR(255), link VARCHAR(255))');
$db->exec('CREATE UNIQUE INDEX cocktail_name ON cocktail (name)');
$insert = $db->prepare('INSERT INTO cocktail (name, link) VALUES (:name, :link)');
// Get raw webtender.com data set
echo 'Downloading webtender.com data set', PHP_EOL;
$start = 1;
do {
$file = __DIR__ . '/' . $start . '.html';
if (file_exists($file)) {
continue;
}
copy(
'http://www.webtender.com/db/browse?level=2&dir=drinks&char=%2A&start=' . $start,
$file
);
if (!isset($limit)) {
$contents = file_get_contents($file);
preg_match('/([0-9]+) found/', $contents, $match);
$limit = $match[1] + (150 - ($match[1] % 150));
}
echo 'Got records ', $start, ' - ', min($start + 150, $limit), ' of ', $limit, PHP_EOL;
$start += 150;
} while ($start < $limit);
// Extract data from data set
$start = 1;
while ($start < $limit) {
echo 'Processing ', $start, ' - ', min($start + 150, $limit), ' of ', $limit, PHP_EOL;
$file = __DIR__ . '/' . $start . '.html';
$contents = file_get_contents($file);
$contents = tidy_repair_string($contents);
libxml_use_internal_errors(true);
$doc = new DOMDocument;
$doc->loadHTML($contents);
libxml_clear_errors();
$xpath = new DOMXPath($doc);
$cocktails = $xpath->query('//li/a');
$db->beginTransaction();
foreach ($cocktails as $cocktail) {
$name = $cocktail->nodeValue;
$name = preg_replace('/ The$|^The |\s*\([^)]+\)\s*| #[0-9]+$/', '', $name);
$name = html_entity_decode($name);
$link = 'http://www.webtender.com' . $cocktail->getAttribute('href');
$insert->execute(array($name, $link));
}
$db->commit();
$start += 150;
}
// Clean up
echo 'Cleaning up', PHP_EOL;
$start = 1;
while ($start < $limit) {
$file = __DIR__ . '/' . $start . '.html';
unlink($file);
$start += 150;
}

View File

@ -0,0 +1,69 @@
<?php
/**
* Phergie
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.
* It is also available through the world-wide-web at this URL:
* http://phergie.org/license
*
* @category Phergie
* @package Phergie_Plugin_Cookie
* @author Phergie Development Team <team@phergie.org>
* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Cookie
*/
/**
* Processes requests to serve users cookies.
*
* @category Phergie
* @package Phergie_Plugin_Cookie
* @author Phergie Development Team <team@phergie.org>
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Cookie
* @uses Phergie_Plugin_Command pear.phergie.org
* @uses Phergie_Plugin_Serve pear.phergie.org
*/
class Phergie_Plugin_Cookie extends Phergie_Plugin_Abstract
{
/**
* Checks for dependencies.
*
* @return void
*/
public function onLoad()
{
$plugins = $this->plugins;
$plugins->getPlugin('Command');
$plugins->getPlugin('Serve');
}
/**
* Processes requests to serve a user a cookie.
*
* @param string $request Request including the target and an optional
* suggestion of what cookie to serve
*
* @return void
*/
public function onCommandCookie($request)
{
$format = $this->getConfig(
'cookie.format',
'throws %target% %article% %item%.'
);
$this->plugins->getPlugin('Serve')->serve(
dirname(__FILE__) . '/Cookie/cookie.db',
'cookies',
$format,
$request
);
}
}

View File

@ -0,0 +1,49 @@
<?php
if (!defined('__DIR__')) {
define('__DIR__', dirname(__FILE__));
}
// Create database schema
echo 'Creating database', PHP_EOL;
$file = __DIR__ . '/cookie.db';
if (file_exists($file)) {
unlink($file);
}
$db = new PDO('sqlite:' . $file);
$db->exec('CREATE TABLE cookies (name VARCHAR(255), link VARCHAR(255))');
$db->exec('CREATE UNIQUE INDEX cookie_name ON cookies (name)');
$insert = $db->prepare('INSERT INTO cookies (name, link) VALUES (:name, :link)');
// Get Cookies list from http://en.wikipedia.org/wiki/List_of_cookies
echo 'Downloading data from Wikipedia', PHP_EOL;
$file = __DIR__ . '/cookieslist.txt';
if (!file_exists($file)) {
copy('http://en.wikipedia.org/wiki/List_of_cookies', $file);
}
$contents = file_get_contents($file);
// Extract data from data set
echo 'Processing Wikipedia\'s cookies list', PHP_EOL;
$contents = tidy_repair_string($contents);
libxml_use_internal_errors(true);
$doc = new DOMDocument;
$doc->loadHTML($contents);
libxml_clear_errors();
$xpath = new DOMXPath($doc);
$cookies = $xpath->query('//table[@width="90%"]/tr/td[1]/a');
foreach ($cookies as $cookie) {
$name = str_replace(array('(',')',"\n", 'cookies'), array('','', ' ', 'cookie' ), trim( $cookie->textContent));
$link = 'http://en.wikipedia.org' . $cookie->getAttribute('href');
$insert->execute(array($name, $link));
print 'added ['.$name.'] -> '. $link . PHP_EOL;
}
// Clean up
echo 'Cleaning up', PHP_EOL;
unlink($file);

View File

@ -0,0 +1,447 @@
<?php
/**
* Phergie
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.
* It is also available through the world-wide-web at this URL:
* http://phergie.org/license
*
* @category Phergie
* @package Phergie_Plugin_Karma
* @author Phergie Development Team <team@phergie.org>
* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Karma
*/
/**
* Handles requests for incrementation or decrementation of a maintained list
* of counters for specified terms and antithrottling to prevent extreme
* inflation or depression of counters by any single individual.
*
* @category Phergie
* @package Phergie_Plugin_Karma
* @author Phergie Development Team <team@phergie.org>
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Karma
*/
class Phergie_Plugin_Karma extends Phergie_Plugin_Abstract
{
/**
* Stores the SQLite object
*
* @var resource
*/
protected $db = null;
/**
* Retains the last garbage collection date
*
* @var array
*/
protected $lastGc = null;
/**
* Logs the karma usages and limits users to one karma change per word
* and per day
*
* @return void
*/
protected $log = array();
/**
* Some fixed karma values, keys must be lowercase
*
* @var array
*/
protected $fixedKarma;
/**
* A list of blacklisted values
*
* @var array
*/
protected $karmaBlacklist;
/**
* Answers for correct assertions
*/
protected $positiveAnswers;
/**
* Answers for incorrect assertions
*/
protected $negativeAnswers;
/**
* Prepared PDO statements
*
* @var PDOStatement
*/
protected $insertKarma;
protected $updateKarma;
protected $fetchKarma;
protected $insertComment;
/**
* Connects to the database containing karma ratings and initializes
* class properties.
*
* @return void
*/
public function onLoad()
{
$this->db = null;
$this->lastGc = null;
$this->log = array();
if(!defined('M_EULER')) {
define('M_EULER', '0.57721566490153286061');
}
$this->fixedKarma = array(
'phergie' => '%s has karma of awesome',
'pi' => '%s has karma of ' . M_PI,
'Î ' => '%s has karma of ' . M_PI,
'Ï€' => '%s has karma of ' . M_PI,
'chucknorris' => '%s has karma of Warning: Integer out of range',
'chuck norris' => '%s has karma of Warning: Integer out of range',
'c' => '%s has karma of 299 792 458 m/s',
'e' => '%s has karma of ' . M_E,
'euler' => '%s has karma of ' . M_EULER,
'mole' => '%s has karma of 6.02214e23 molecules',
'avogadro' => '%s has karma of 6.02214e23 molecules',
'spoon' => '%s has no karma. There is no spoon',
'mc^2' => '%s has karma of E',
'mc2' => '%s has karma of E',
'mc²' => '%s has karma of E',
'i' => '%s haz big karma',
'karma' => 'The karma law says that all living creatures are responsible for their karma - their actions and the effects of their actions. You should watch yours.'
);
$this->karmaBlacklist = array(
'*',
'all',
'everything'
);
$this->positiveAnswers = array(
'No kidding, %owner% totally kicks %owned%\'s ass !',
'True that.',
'I concur.',
'Yay, %owner% ftw !',
'%owner% is made of WIN!',
'Nothing can beat %owner%!',
);
$this->negativeAnswers = array(
'No sir, not at all.',
'You\'re wrong dude, %owner% wins.',
'I\'d say %owner% is better than %owned%.',
'You must be joking, %owner% ftw!',
'%owned% is made of LOSE!',
'%owned% = Epic Fail',
);
// Load or initialize the database
$class = new ReflectionClass(get_class($this));
$dir = dirname($class->getFileName() . '/' . $this->name);
$this->db = new PDO('sqlite:' . $dir . 'karma.db');
// Check to see if the table exists
$table = $this->db->query('
SELECT COUNT(*)
FROM sqlite_master
WHERE name = ' . $this->db->quote('karmas')
)->fetchColumn();
// Create database tables if necessary
if (!$table) {
$this->db->query('
CREATE TABLE karmas ( word VARCHAR ( 255 ), karma MEDIUMINT );
CREATE UNIQUE INDEX word ON karmas ( word );
CREATE INDEX karmaIndex ON karmas ( karma );
CREATE TABLE comments ( wordid INT , comment VARCHAR ( 255 ) );
CREATE INDEX wordidIndex ON comments ( wordid );
CREATE UNIQUE INDEX commentUnique ON comments ( comment );
');
}
$this->insertKarma = $this->db->prepare('
INSERT INTO karmas (
word,
karma
)
VALUES (
:word,
:karma
)
');
$this->insertComment = $this->db->prepare('
INSERT INTO comments (
wordid,
comment
)
VALUES (
:wordid,
:comment
)
');
$this->fetchKarma = $this->db->prepare('
SELECT karma, ROWID id FROM karmas WHERE LOWER(word) = LOWER(:word) LIMIT 1
');
$this->updateKarma = $this->db->prepare('
UPDATE karmas SET karma = :karma WHERE LOWER(word) = LOWER(:word)
');
}
/**
* Checks for dependencies.
*
* @return void
*/
public static function onLoad()
{
if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
$this->fail('PDO and pdo_sqlite extensions must be installed');
}
}
/**
* Handles requests for incrementation, decrementation, or lookup of karma
* ratings sent via messages from users.
*
* @return void
*/
public function onPrivmsg()
{
$source = $this->event->getSource();
$message = $this->event->getArgument(1);
$target = $this->event->getNick();
// Command prefix check
$prefix = preg_quote(trim($this->getConfig('command.prefix')));
$bot = preg_quote($this->getConfig('connections.nick'));
$exp = '(?:(?:' . $bot . '\s*[:,>]?\s+(?:' . $prefix . ')?)|(?:' . $prefix . '))';
// Karma status request
if (preg_match('#^' . $exp . 'karma\s+(.+)$#i', $message, $m)) {
// Return user's value if "me" is requested
if (strtolower($m[1]) === 'me') {
$m[1] = $target;
}
// Clean the term
$term = $this->doCleanWord($m[1]);
// Check the blacklist
if (is_array($this->karmaBlacklist) && in_array($term, $this->karmaBlacklist)) {
$this->doNotice($target, $term . ' is blacklisted');
return;
}
// Return fixed value if set
if (isset($this->fixedKarma[$term])) {
$this->doPrivmsg($source, $target . ': ' . sprintf($this->fixedKarma[$term], $m[1]) . '.');
return;
}
// Return current karma or neutral if not set yet
$this->fetchKarma->execute(array(':word'=>$term));
$res = $this->fetchKarma->fetch(PDO::FETCH_ASSOC);
// Sanity check if someone if someone prefixed their conversation with karma
if (!$res && substr_count($term, ' ') > 1 && !(substr($m[1], 0, 1) === '(' && substr($m[1], -1) === ')')) {
return;
}
// Clean the raw term if it was contained within brackets
if (substr($m[1], 0, 1) === '(' && substr($m[1], -1) === ')') {
$m[1] = substr($m[1], 1, -1);
}
if ($res && $res['karma'] != 0) {
$this->doPrivmsg($source, $target . ': ' . $m[1] . ' has karma of ' . $res['karma'] . '.');
} else {
$this->doPrivmsg($source, $target . ': ' . $m[1] . ' has neutral karma.');
}
// Incrementation/decrementation request
} elseif (preg_match('{^' . $exp . '?(?:(\+{2,2}|-{2,2})(\S+?|\(.+?\)+)|(\S+?|\(.+?\)+)(\+{2,2}|-{2,2}))(?:\s+(.*))?$}ix', $message, $m)) {
if (!empty($m[4])) {
$m[1] = $m[4]; // Increment/Decrement
$m[2] = $m[3]; // Word
}
$m[3] = (isset($m[5]) ? $m[5] : null); // Comment
unset($m[4], $m[5]);
list(, $sign, $word, $comment) = array_pad($m, 4, null);
// Clean the word
$word = strtolower($this->doCleanWord($word));
if (empty($word)) {
return;
}
// Do nothing if the karma is fixed or blacklisted
if (isset($this->fixedKarma[$word]) ||
is_array($this->karmaBlacklist) && in_array($word, $this->karmaBlacklist)) {
return;
}
// Force a decrementation if someone tries to update his own karma
if ($word == strtolower($target) && $sign != '--' && !$this->fromAdmin(true)) {
$this->doNotice($target, 'Bad ' . $target . '! You can not modify your own Karma. Shame on you!');
$sign = '--';
}
// Antithrottling check
$host = $this->event->getHost();
$limit = $this->getConfig('karma.limit');
// This is waiting on the Acl plugin from Elazar, being bypassed for now
//if ($limit > 0 && !$this->fromAdmin()) {
if ($limit > 0) {
if (isset($this->log[$host][$word]) && $this->log[$host][$word] >= $limit) {
// Three strikes, you're out, so lets decrement their karma for spammage
if ($this->log[$host][$word] == ($limit+3)) {
$this->doNotice($target, 'Bad ' . $target . '! Didn\'t I tell you that you reached your limit already?');
$this->log[$host][$word] = $limit;
$word = $target;
$sign = '--';
// Toss a notice to the user if they reached their limit
} else {
$this->doNotice($target, 'You have currently reached your limit in modifying ' . $word . ' for this day, please wait a bit.');
$this->log[$host][$word]++;
return;
}
} else {
if (isset($this->log[$host][$word])) {
$this->log[$host][$word]++;
} else {
$this->log[$host][$word] = 1;
}
}
}
// Get the current value then update or create entry
$this->fetchKarma->execute(array(':word'=>$word));
$res = $this->fetchKarma->fetch(PDO::FETCH_ASSOC);
if ($res) {
$karma = ($res['karma'] + ($sign == '++' ? 1 : -1));
$args = array(
':word' => $word,
':karma' => $karma
);
$this->updateKarma->execute($args);
} else {
$karma = ($sign == '++' ? '1' : '-1');
$args = array(
':word' => $word,
':karma' => $karma
);
$this->insertKarma->execute($args);
$this->fetchKarma->execute(array(':word'=>$word));
$res = $this->fetchKarma->fetch(PDO::FETCH_ASSOC);
}
$id = $res['id'];
// Add comment
$comment = preg_replace('{(?:^//(.*)|^#(.*)|^/\*(.*?)\*/$)}', '$1$2$3', $comment);
if (!empty($comment)) {
$this->insertComment->execute(array(':wordid' => $id, ':comment' => $comment));
}
// Perform garbage collection on the antithrottling log if needed
if (date('d') !== $this->lastGc) {
$this->doGc();
}
// Assertion request
} elseif (preg_match('#^' . $exp . '?([^><]+)(<|>)([^><]+)$#', $message, $m)) {
// Trim words
$word1 = strtolower($this->doCleanWord($m[1]));
$word2 = strtolower($this->doCleanWord($m[3]));
$operator = $m[2];
// Do nothing if the karma is fixed
if (isset($this->fixedKarma[$word1]) || isset($this->fixedKarma[$word2]) ||
empty($word1) || empty($word2)) {
return;
}
// Fetch first word
if ($word1 === '*' || $word1 === 'all' || $word1 === 'everything') {
$res = array('karma' => 0);
$word1 = 'everything';
} else {
$this->fetchKarma->execute(array(':word'=>$word1));
$res = $this->fetchKarma->fetch(PDO::FETCH_ASSOC);
}
// If it exists, fetch second word
if ($res) {
if ($word2 === '*' || $word2 === 'all' || $word2 === 'everything') {
$res2 = array('karma' => 0);
$word2 = 'everything';
} else {
$this->fetchKarma->execute(array(':word'=>$word2));
$res2 = $this->fetchKarma->fetch(PDO::FETCH_ASSOC);
}
// If it exists, compare and return value
if ($res2 && $res['karma'] != $res2['karma']) {
$assertion = ($operator === '<' && $res['karma'] < $res2['karma']) || ($operator === '>' && $res['karma'] > $res2['karma']);
// Switch arguments if they are in the wrong order
if ($operator === '<') {
$tmp = $word2;
$word2 = $word1;
$word1 = $tmp;
}
$this->doPrivmsg($source, $assertion ? $this->fetchPositiveAnswer($word1, $word2) : $this->fetchNegativeAnswer($word1, $word2));
// If someone asserts that something is greater or lesser than everything, we increment/decrement that something at the same time
if ($word2 === 'everything') {
$this->event = clone$this->event;
$this->event->setArguments(array($this->event->getArgument(0), '++'.$word1));
$this->onPrivmsg();
} elseif ($word1 === 'everything') {
$this->event = clone$this->event;
$this->event->setArguments(array($this->event->getArgument(0), '--'.$word2));
$this->onPrivmsg();
}
}
}
}
}
protected function fetchPositiveAnswer($owner, $owned)
{
return str_replace(array('%owner%','%owned%'), array($owner, $owned), $this->positiveAnswers[array_rand($this->positiveAnswers,1)]);
}
protected function fetchNegativeAnswer($owned, $owner)
{
return str_replace(array('%owner%','%owned%'), array($owner, $owned), $this->negativeAnswers[array_rand($this->negativeAnswers,1)]);
}
protected function doCleanWord($word)
{
$word = trim($word);
if (substr($word, 0, 1) === '(' && substr($word, -1) === ')') {
$word = trim(substr($word, 1, -1));
}
$word = preg_replace('#\s+#', ' ', strtolower(trim($word)));
return $word;
}
/**
* Performs garbage collection on the antithrottling log.
*
* @return void
*/
public function doGc()
{
unset($this->log);
$this->log = array();
$this->lastGc = date('d');
}
}

View File

@ -0,0 +1,159 @@
<?php
/**
* Phergie
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.
* It is also available through the world-wide-web at this URL:
* http://phergie.org/license
*
* @category Phergie
* @package Phergie_Plugin_Serve
* @author Phergie Development Team <team@phergie.org>
* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Serve
*/
/**
* Processes requests to serve a user something from a database.
*
* @category Phergie
* @package Phergie_Plugin_Serve
* @author Phergie Development Team <team@phergie.org>
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Serve
* @uses extension pdo
* @uses extension pdo_sqlite
*/
class Phergie_Plugin_Serve extends Phergie_Plugin_Abstract
{
/**
* Checks for dependencies.
*
* @return void
*/
public function onLoad()
{
if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
$this->fail('PDO and pdo_sqlite extensions must be installed');
}
}
/**
* Retrieves a random item from the database table.
*
* @param string $database Path to the SQLite database file
* @param string $table Name of the database table
* @param array $request Parsed request
*
* @return object Retrieved item
*/
protected function getItem($database, $table, array $request)
{
$db = new PDO('sqlite:' . $database);
if (!empty($request['suggestion'])) {
$query = 'SELECT * FROM ' . $table . ' WHERE name LIKE ? ORDER BY RANDOM() LIMIT 1';
$stmt = $db->prepare($query);
$stmt->execute(array('%' . $request['suggestion'] . '%'));
$item = $stmt->fetchObject();
if (!$item) {
$item = new stdClass;
$item->name = $request['suggestion'];
$item->link = null;
}
} else {
$query = 'SELECT * FROM ' . $table . ' ORDER BY RANDOM() LIMIT 1';
$stmt = $db->query($query);
$item = $stmt->fetchObject();
}
return $item;
}
/**
* Processes a request to serve a user something.
*
* @param string $database Path to the SQLite database file
* @param string $table Name of the database table
* @param string $format Format of the response where %target%,
* %item%, %article%', and %link will be replaced with their
* respective data
* @param string $request Request string including the target and an
* optional suggestion of the item to fetch
* @param boolean $censor TRUE to integrate with the Censor plugin,
* defaults to FALSE
*
* @return boolean TRUE if the request was processed successfully, FALSE
* otherwise
*/
public function serve($database, $table, $format, $request, $censor = false)
{
// Parse the request
$result = preg_match(
'/(?P<target>[^\s]+)(\s+an?\s+)?(?P<suggestion>.*)?/',
$request,
$match
);
if (!$result) {
return false;
}
// Resolve the target
$target = $match['target'];
if ($target == 'me') {
$target = $this->event->getNick();
}
// Process the request
$item = $this->getItem($database, $table, $match);
// Reprocess the request for censorship if required
$attempts = 0;
while ($censor && $attempts < 3) {
$plugin = $this->plugins->getPlugin('Censor');
$clean = $plugin->cleanString($item->name);
if ($item->name != $clean) {
$attempts++;
$item = $this->getItem($database, $table, $match);
} else {
$censor = false;
}
}
if ($censor && $attempts == 3) {
$this->doAction($this->event->getSource(), 'shrugs.');
}
// Derive the proper article for the item
if (preg_match('/^[aeiou]/i', $item->name)) {
$article = 'an';
} else {
$article = 'a';
}
// Format the message
$replacements = array(
'target' => $target,
'item' => $item->name,
'link' => $item->link,
'article' => $article
);
$msg = $format;
foreach ($replacements as $placeholder => $value) {
$msg = str_replace(
'%' . $placeholder . '%',
$value,
$msg
);
}
// Send the message
$this->doAction($this->event->getSource(), $msg);
}
}

View File

@ -59,15 +59,8 @@ class Phergie_Plugin_Statusnet extends Phergie_Plugin_Abstract {
$this->regCallback = NULL;
}
$this->unregRegexp = $this->config['statusnet.unregregexp'];
if (!$this->unregRegexp) {
$this->unregRegexp = '/\x02(.*?)\x02 (?:isn\'t|is not) registered/i';
}
$this->regRegexp = $this->config['statusnet.regregexp'];
if (!$this->regRegexp) {
$this->regRegexp = '/(?:\A|\x02)(\w+?)\x02? (?:\(account|is \w+?\z)/i';
}
$this->unregRegexp = $this->getConfig('statusnet.unregregexp', '/\x02(.*?)\x02 (?:isn\'t|is not) registered/i');
$this->regRegexp = $this->getConfig('statusnet.regregexp', '/(?:\A|\x02)(\w+?)\x02? (?:\(account|is \w+?\z)/i');
}
/**
@ -81,6 +74,10 @@ class Phergie_Plugin_Statusnet extends Phergie_Plugin_Abstract {
$source = $event->getSource();
$message = trim($event->getText());
if ($source == '#statustest') {
$this->doPrivmsg('#statustest', "\001Line1\020nLine2");
}
call_user_func($this->messageCallback, array('sender' => $source, 'message' => $message));
}
}
@ -103,4 +100,8 @@ class Phergie_Plugin_Statusnet extends Phergie_Plugin_Abstract {
}
}
}
public function onTick() {
echo "\nTICK!\n";
}
}

View File

@ -0,0 +1,69 @@
<?php
/**
* Phergie
*
* PHP version 5
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.
* It is also available through the world-wide-web at this URL:
* http://phergie.org/license
*
* @category Phergie
* @package Phergie_Plugin_Wine
* @author Phergie Development Team <team@phergie.org>
* @copyright 2008-2010 Phergie Development Team (http://phergie.org)
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Wine
*/
/**
* Processes requests to serve users wine.
*
* @category Phergie
* @package Phergie_Plugin_Wine
* @author Phergie Development Team <team@phergie.org>
* @license http://phergie.org/license New BSD License
* @link http://pear.phergie.org/package/Phergie_Plugin_Wine
* @uses Phergie_Plugin_Command pear.phergie.org
* @uses Phergie_Plugin_Serve pear.phergie.org
*/
class Phergie_Plugin_Wine extends Phergie_Plugin_Abstract
{
/**
* Checks for dependencies.
*
* @return void
*/
public function onLoad()
{
$plugins = $this->plugins;
$plugins->getPlugin('Command');
$plugins->getPlugin('Serve');
}
/**
* Processes requests to serve a user a wine.
*
* @param string $request Request including the target and an optional
* suggestion of what wine to serve
*
* @return void
*/
public function onCommandWine($request)
{
$format = $this->getConfig(
'wine.format',
'serves %target% a glass of %item%.'
);
$this->plugins->getPlugin('Serve')->serve(
dirname(__FILE__) . '/Wine/wine.db',
'wine',
$format,
$request
);
}
}

View File

@ -0,0 +1,53 @@
<?php
// Create database schema
echo 'Creating database', PHP_EOL;
$file = __DIR__ . '/wine.db';
if (file_exists($file)) {
unlink($file);
}
$db = new PDO('sqlite:' . $file);
$db->exec('CREATE TABLE wine (name VARCHAR(255), link VARCHAR(255))');
$db->exec('CREATE UNIQUE INDEX wine_name ON wine (name)');
$insert = $db->prepare('INSERT INTO wine (name, link) VALUES (:name, :link)');
// Get and decompress lcboapi.com data set
$outer = __DIR__ . '/current.zip';
if (!file_exists($outer)) {
echo 'Downloading lcboapi.com data set', PHP_EOL;
copy('http://lcboapi.com/download/current.zip', $outer);
}
echo 'Decompressing lcboapi.com data set', PHP_EOL;
$zip = new ZipArchive;
$zip->open($outer);
$stat = $zip->statIndex(0);
$inner = __DIR__ . '/' . $stat['name'];
$zip->extractTo(__DIR__);
$zip->close();
$zip = new ZipArchive;
$zip->open($inner);
$stat = $zip->statIndex(0);
$file = __DIR__ . '/' . $stat['name'];
$zip->extractTo(__DIR__);
$zip->close();
// Aggregate data set into the database
$lcbo = new PDO('sqlite:' . $file);
$result = $lcbo->query('SELECT product_no, name FROM products WHERE primary_category = "Wine"');
$wines = $result->fetchAll();
echo 'Processing lcboapi.com data - ', number_format(count($wines), 0), ' records', PHP_EOL;
$db->beginTransaction();
foreach ($wines as $wine) {
$name = $wine['name'];
$link = 'http://lcboapi.com/products/' . $wine['product_no'];
$insert->execute(array($name, $link));
}
$db->commit();
// Clean up
echo 'Cleaning up', PHP_EOL;
unset($lcbo);
unlink($outer);
unlink($inner);
unlink($file);

View File

@ -37,14 +37,14 @@ class Phergie_Process_Async extends Phergie_Process_Abstract
*
* @var int
*/
protected $sec;
protected $sec = 0;
/**
* Length of time to poll for stream activity (microseconds)
*
* @var int
*/
protected $usec;
protected $usec = 200000;
/**
* Length of time to wait between ticks.
@ -87,7 +87,7 @@ class Phergie_Process_Async extends Phergie_Process_Abstract
}
}
if (isset($this->sec) && isset($this->usec)) {
if (!isset($this->sec) && !isset($this->usec)) {
throw new Phergie_Process_Exception(
'One of the processor options "sec" or "usec" must be specified'
);

View File

@ -62,7 +62,7 @@ class Phergie_StatusnetBot extends Phergie_Bot {
*
* @return void
*/
public function receive() {
public function handleEvents() {
$this->getProcessor()->handleEvents();
}

View File

@ -64,6 +64,19 @@ class IrcManager extends ImManager {
}
}
/**
* Idle processing for io manager's execution loop.
* Send keepalive pings to server.
*
* @return void
*/
public function idle() {
// Call Phergie's doTick methods if necessary
echo "BEGIN IDLE\n";
$this->conn->handleEvents();
echo "END IDLE\n";
}
/**
* Process IRC events that have come in over the wire.
*
@ -73,7 +86,7 @@ class IrcManager extends ImManager {
public function handleInput($socket) {
common_log(LOG_DEBUG, 'Servicing the IRC queue.');
$this->stats('irc_process');
$this->conn->receive();
$this->conn->handleEvents();
}
/**
@ -91,7 +104,7 @@ class IrcManager extends ImManager {
'connections' => array(
array(
'host' => $this->plugin->host,
'port' => $port,
'port' => $this->plugin->port,
'username' => $this->plugin->username,
'realname' => $this->plugin->realname,
'nick' => $this->plugin->nick,
@ -104,7 +117,7 @@ class IrcManager extends ImManager {
'driver' => 'statusnet',
'processor' => 'async',
'processor.options' => array('usec' => 0),
'processor.options' => array('sec' => 0, 'usec' => 0),
'plugins' => array(
'Pong',
@ -118,9 +131,14 @@ class IrcManager extends ImManager {
'ui.enabled' => true,
'nickserv.password' => $this->plugin->nickservpassword,
'nickserv.identify_message' => $this->plugin->nickservidentifyregexp,
'autojoin.channels' => $this->plugin->channels,
'statusnet.messagecallback' => array($this, 'handle_irc_message'),
'statusnet.regcallback' => array($this, 'handle_reg_response')
'statusnet.regcallback' => array($this, 'handle_reg_response'),
'statusnet.unregregexp' => $this->plugin->unregregexp,
'statusnet.regregexp' => $this->plugin->regregexp
)
);
@ -215,8 +233,12 @@ class IrcManager extends ImManager {
$this->regchecksLookup[$usernick] = $screenname;
}
$args = $data['data']['args'];
$lines = explode("\n", $args[1]);
try {
$this->conn->send($data['data']['command'], $data['data']['args']);
foreach ($lines as $line) {
$this->conn->send($data['data']['command'], array($args[0], $line));
}
} catch (Phergie_Driver_Exception $e) {
$this->conn->reconnect();
return false;