- $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();
- }
- }
- }
+ $message = $this->getEvent()->getText();
+
+ $termPattern = '\S+?|\([^<>]+?\)+';
+ $actionPattern = '(?P<action>\+\+|--)';
+
+ $modifyPattern = <<<REGEX
+ {^
+ (?J) # allow overwriting capture names
+ \s* # ignore leading whitespace
+
+ (?: # start with ++ or -- before the term
+ $actionPattern
+ (?P<term>$termPattern)
+ | # follow the term with ++ or --
+ (?P<term>$termPattern)
+ $actionPattern # allow no whitespace between the term and the action
+ )
+ $}ix
+REGEX;
+
+ $versusPattern = <<<REGEX
+ {^
+ (?P<term0>$termPattern)
+ \s+(?P<method><|>)\s+
+ (?P<term1>$termPattern)$#
+ $}ix
+REGEX;
+
+ $match = null;
+
+ if (preg_match($modifyPattern, $message, $match)) {
+ $action = $match['action'];
+ $term = $this->getCanonicalTerm($match['term']);
+ $this->modifyKarma($term, $action);
+ } elseif (preg_match($versusPattern, $message, $match)) {
+ $term0 = trim($match['term0']);
+ $term1 = trim($match['term1']);
+ $method = $match['method'];
+ $this->compareKarma($term0, $term1, $method);