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;
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;
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
--- /dev/null
+<?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);
+ }
+}
$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));
}
$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));
}
$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;
}
--- /dev/null
+<?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
+ );
+ }
+}
+
--- /dev/null
+<?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;
+}
--- /dev/null
+<?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
+ );
+ }
+}
--- /dev/null
+<?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);
+
--- /dev/null
+<?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');
+ }
+}
--- /dev/null
+<?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);
+ }
+}
$this->regCallback = NULL;\r
}\r
\r
- $this->unregRegexp = $this->config['statusnet.unregregexp'];\r
- if (!$this->unregRegexp) {\r
- $this->unregRegexp = '/\x02(.*?)\x02 (?:isn\'t|is not) registered/i';\r
- }\r
-\r
- $this->regRegexp = $this->config['statusnet.regregexp'];\r
- if (!$this->regRegexp) {\r
- $this->regRegexp = '/(?:\A|\x02)(\w+?)\x02? (?:\(account|is \w+?\z)/i';\r
- }\r
+ $this->unregRegexp = $this->getConfig('statusnet.unregregexp', '/\x02(.*?)\x02 (?:isn\'t|is not) registered/i');\r
+ $this->regRegexp = $this->getConfig('statusnet.regregexp', '/(?:\A|\x02)(\w+?)\x02? (?:\(account|is \w+?\z)/i');\r
}\r
\r
/**\r
$source = $event->getSource();\r
$message = trim($event->getText());\r
\r
+ if ($source == '#statustest') {\r
+ $this->doPrivmsg('#statustest', "\001Line1\020nLine2");\r
+ }\r
+\r
call_user_func($this->messageCallback, array('sender' => $source, 'message' => $message));\r
}\r
}\r
}\r
}\r
}\r
+\r
+ public function onTick() {\r
+ echo "\nTICK!\n";\r
+ }\r
}\r
--- /dev/null
+<?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
+ );
+ }
+}
--- /dev/null
+<?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);
*
* @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.
}
}
- 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'
);
*\r
* @return void\r
*/\r
- public function receive() {\r
+ public function handleEvents() {\r
$this->getProcessor()->handleEvents();\r
}\r
\r
}
}
+ /**
+ * 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.
*
public function handleInput($socket) {
common_log(LOG_DEBUG, 'Servicing the IRC queue.');
$this->stats('irc_process');
- $this->conn->receive();
+ $this->conn->handleEvents();
}
/**
'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,
'driver' => 'statusnet',
'processor' => 'async',
- 'processor.options' => array('usec' => 0),
+ 'processor.options' => array('sec' => 0, 'usec' => 0),
'plugins' => array(
'Pong',
'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
)
);
$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;