root/trunk/Phergie/Plugin/Karma.php @ 59

Revision 59, 6.2 KB (checked in by tobias382, 5 years ago)

Unstable commit - driver seems to work, most plugins still need testing
* Modified the streams driver to correctly parse the first argument for

PRIVMSG events into an array

* Added a new debug flag setting to the bundled configuration file
* Moved the debug method from the streams driver to the base driver and

modified it to use the new debug flag setting

* Renamed CtcpAction? methods to Action in order to make logic for

construction and parsing of related requests more compatible with the
same for other commands

* Moved Event_Handler::getEventSource to Event_Request::getSource
* Added Event_Handler::tinyUrl convenience method for converting URLs to

their TinyURL equivalents

* Improved docblock coverage in various classes
* Changed all plugin calls to getConnection()->getNick() to getIni('nick')
* Fixed a memory leak in the Command plugin class
* Added alternate nick support to the Nickserv plugin
* Too many more to name!

Line 
1<?php
2
3/**
4* @see Phergie_Event_Handler
5*/
6require_once 'Phergie/Event/Handler.php';
7
8/**
9* Handles requests for incrementation or decrementation of a maintained list
10* of counters for specified terms and antithrottling to prevent extreme
11* inflation or depression of counters by any single individual.
12*/
13class Phergie_Plugin_Karma extends Phergie_Event_Handler
14{
15    /**
16    * Stores the SQLite object
17    *
18    * @var resource
19    */
20    protected $db = null;
21
22    /**
23    * Retains the last garbage collection date
24    *
25    * @var array
26    */
27    protected $lastGc = null;
28
29    /**
30    * Logs the karma usages and limits users to one karma change per word
31    * and per day
32    *
33    * @return void
34    */
35    protected $log = array();
36
37    /**
38    * Some fixed karma values, keys must be lowercase
39    *
40    * @var array
41    */
42    protected $fixedKarma;
43
44    /**
45    * Connects to the database containing karma ratings and initializes
46    * class properties.
47    *
48    * @return void
49    */
50    public function init()
51    {
52        $this->db = null;
53        $this->lastGc = null;
54        $this->log = null;
55
56        $this->fixedKarma = array
57        (
58            'pi' => 'pi has karma of ' . M_PI,
59            'chucknorris' => 'pi has karma of Warning: Integer out of range',
60            'c' => 'c has karma of 299 792 458 m/s',
61            'e' => 'e has karma of ' . M_E,
62            'euler' => 'euler has karma of ' . M_EULER,
63            'mole' => 'mole has karma of 6.02214e23 molecules',
64            'spoon' => 'spoon has no karma. There is no spoon.',
65            strtolower($this->getIni('nick')) => $this->getIni('static'),
66            'mc^2' => 'mc^2 has karma of e',
67            'mc2' => 'mc2 has karma of e',
68            'mc²' => 'mc² has karma of e',
69        );
70
71        // Check to ensure that the SQLite extension is loaded
72        if (!extension_loaded('sqlite')) {
73            return;
74        }
75
76        // Create a directory to contain the database if needed
77        if (!file_exists(dirname(__FILE__).'/Karma'))
78            mkdir(dirname(__FILE__).'/Karma');
79
80        // Load or initialize the database
81        $db = dirname(__FILE__).'/Karma/karma.db';
82        if (!file_exists($db)) {
83            $this->db = new SQLiteDatabase($db);
84            $this->db->queryExec('
85                CREATE TABLE karmas ( word VARCHAR ( 255 ) , karma MEDIUMINT ) ;
86                CREATE UNIQUE INDEX word ON karmas ( word ) ;
87                CREATE INDEX karmaIndex ON karmas ( karma ) ;
88            ');
89            $this->db->queryExec('
90                CREATE TABLE comments ( wordid INT , comment VARCHAR ( 255 ) ) ;
91                CREATE INDEX wordidIndex ON comments ( wordid ) ;
92                CREATE UNIQUE INDEX commentUnique ON comments ( comment ) ;
93            ');
94        } else {
95            $this->db = new SQLiteDatabase($db);
96        }
97    }
98
99    /**
100    * Handles requests for incrementation, decrementation, or lookup of karma
101    * ratings sent via messages from users.
102    *
103    * @return void
104    */
105    public function onPrivmsg()
106    {
107        if ($this->db === null) {
108            return;
109        }
110        $target = $this->getSource();
111        $message = $this->event->getArgument(1);
112            // Karma status request
113        if (preg_match('#^karma (\S+?)$#i', $message, $m)) {
114            // Return fixed value if set
115            if(isset($this->fixedKarma[strtolower($m[1])])) {
116                $this->doPrivmsg($source, $m[1] . ' ' . $this->fixedKarma[strtolower($m[1])]);
117                return;
118            }
119            // Return current karma or neutral if not set yet
120            $res = $this->db->query('SELECT karma FROM karmas WHERE word = \''.sqlite_escape_string(strtolower($m[1])).'\' LIMIT 1', SQLITE_NUM);
121            if ($res->numRows() && $res->column(0) != 0) {
122                    $this->doPrivmsg($source, $m[1].' has karma of '.$res->column(0));
123            } else {
124                    $this->doPrivmsg($source, $m[1].' has neutral karma');
125            }
126        // Incrementation/decrementation request
127        } elseif (preg_match('#^(\S+?)(\+\+|--)\s*(.*)$#i', $message, $m)) {
128            $word = strtolower($m[1]);
129            // Do nothing if the karma fixed
130            if (isset($this->fixedKarma[$word])) {
131                return;
132            }
133            // Force a decrementation if someone tries to update his own karma
134            if ($word == strtolower($this->event->getNick())) {
135                $m[2] = '--';
136            }
137            // Antithrottling check
138            $host = $this->event->getHost();
139            $limit = $this->getIni('limit');
140            if (isset ($this->log[$host][$word])
141                && $limit
142                && $this->log[$host][$word] > $limit) {
143                return;
144            } else {
145                $this->log[$host][$word] = 0;
146            }
147            $this->log[$host][$word]++;
148            // Get the current value then update or create entry
149            $res = $this->db->query('SELECT karma, ROWID FROM karmas WHERE word = \''.sqlite_escape_string($word).'\' LIMIT 1', SQLITE_NUM);
150            if ($res->numRows()) {
151                $this->db->queryExec('UPDATE karmas SET karma = '.($res->column(0) + ($m[2]=='++' ? 1 : -1)).' WHERE word = \''.sqlite_escape_string($word).'\'');
152                $id = $res->column(1);
153            } else {
154                $this->db->queryExec('INSERT INTO karmas (word, karma) VALUES (\''.sqlite_escape_string($word).'\', '.($m[2]=='++' ? '1' : '-1').')');
155                $res = $this->db->query('SELECT ROWID FROM karmas WHERE word = \''.sqlite_escape_string($word).'\' LIMIT 1', SQLITE_NUM);
156                $id = $res->column(0);
157            }
158            // Add comment
159            if (!empty($m[3])) {
160                $this->db->queryExec('INSERT OR IGNORE INTO comments (wordid, comment) VALUES ('.$id.', \''.sqlite_escape_string($m[3]).'\')');
161            }
162            // Perform garbage collection on the antithrottling log if needed
163            if (date('d') !== $this->lastGc) {
164                $this->doGc();
165            }
166        }
167    }
168
169    /**
170     * Performs garbage collection on the antithrottling log.
171     *
172     * @return void
173     */
174    public function doGc()
175    {
176        unset ($this->log);
177        $this->log = array();
178        $this->lastGc = date('d');
179    }
180}
Note: See TracBrowser for help on using the browser.