]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php
Merge remote branch 'statusnet/1.0.x' into irc-plugin
[quix0rs-gnu-social.git] / plugins / Irc / extlib / phergie / Phergie / Plugin / Remind.php
1 <?php
2 /**
3  * Phergie
4  *
5  * PHP version 5
6  *
7  * LICENSE
8  *
9  * This source file is subject to the new BSD license that is bundled
10  * with this package in the file LICENSE.
11  * It is also available through the world-wide-web at this URL:
12  * http://phergie.org/license
13  *
14  * @category  Phergie
15  * @package   Phergie_Plugin_Remind
16  * @author    Phergie Development Team <team@phergie.org>
17  * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18  * @license   http://phergie.org/license New BSD License
19  * @link      http://pear.phergie.org/package/Phergie_Plugin_Remind
20  */
21
22 /**
23  * Parses and logs messages that should be relayed to other users the next time
24  * the recipient is active on the same channel.
25  *
26  * @category Phergie
27  * @package  Phergie_Plugin_Remind
28  * @author   Phergie Development Team <team@phergie.org>
29  * @license  http://phergie.org/license New BSD License
30  * @link     http://pear.phergie.org/package/Phergie_Plugin_Remind
31  * @uses     Phergie_Plugin_Command pear.phergie.org
32  * @uses     Phergie_Plugin_Time pear.phergie.org
33  */
34 class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract
35 {
36     /**
37      * Number of reminders to show in public.
38      */
39     protected $publicReminders = 3;
40
41     /**
42      * PDO resource for a SQLite database containing the reminders.
43      *
44      * @var resource
45      */
46     protected $db;
47
48     /**
49      * Flag that indicates whether or not to use an in-memory reminder list.
50      *
51      * @var bool
52      */
53     protected $keepListInMemory = true;
54
55     /**
56      * In-memory store for pending reminders.
57      */
58     protected $msgStorage = array();
59
60     /**
61      * Check for dependencies.
62      *
63      * @return void
64      */
65     public function onLoad()
66     {
67         $plugins = $this->getPluginHandler();
68         $plugins->getPlugin('Command');
69         $plugins->getPlugin('Time');
70     }
71
72     /**
73      * Creates the database if it does not already exist.
74      *
75      * @return void
76      */
77     public function onConnect()
78     {
79         $dir = dirname(__FILE__) . '/' . $this->getName();
80         $path = $dir . '/reminder.db';
81         if (!file_exists($dir)) {
82             mkdir($dir);
83         }
84
85         if (isset($this->config['remind.use_memory'])) {
86             $this->keepListInMemory = (bool) $this->config['remind.use_memory'];
87         }
88
89         if (isset($this->config['remind.public_reminders'])) {
90             $this->publicReminders = (int) $this->config['remind.public_reminders'];
91             $this->publicReminders = max($this->publicReminders, 0);
92         }
93
94         try {
95             $this->db = new PDO('sqlite:' . $path);
96             $this->createTables();
97         } catch (PDO_Exception $e) {
98             throw new Phergie_Plugin_Exception($e->getMessage());
99         }
100     }
101
102     /**
103      * Intercepts a message and processes any contained recognized commands.
104      *
105      * @return void
106      */
107     public function onPrivmsg()
108     {
109         $source = $this->getEvent()->getSource();
110         $nick = $this->getEvent()->getNick();
111
112         $this->deliverReminders($source, $nick);
113     }
114
115     /**
116      * Handle reminder requests
117      *
118      * @param string $recipient recipient of the message
119      * @param string $message   message to tell the recipient
120      *
121      * @return void
122      * @see handleRemind()
123      */
124     public function onCommandTell($recipient, $message)
125     {
126         $this->handleRemind($recipient, $message);
127     }
128
129     /**
130      * Handle reminder requests
131      *
132      * @param string $recipient recipient of the message
133      * @param string $message   message to tell the recipient
134      *
135      * @return void
136      * @see handleRemind()
137      */
138     public function onCommandAsk($recipient, $message)
139     {
140         $this->handleRemind($recipient, $message);
141     }
142
143     /**
144      * Handle reminder requests
145      *
146      * @param string $recipient recipient of the message
147      * @param string $message   message to tell the recipient
148      *
149      * @return void
150      * @see handleRemind()
151      */
152     public function onCommandRemind($recipient, $message)
153     {
154         $this->handleRemind($recipient, $message);
155     }
156
157     /**
158      * Handles the tell/remind command (stores the message)
159      *
160      * @param string $recipient name of the recipient
161      * @param string $message   message to store
162      *
163      * @return void
164      */
165     protected function handleRemind($recipient, $message)
166     {
167         $source = $this->getEvent()->getSource();
168         $nick = $this->getEvent()->getNick();
169
170         if (!$this->getEvent()->isInChannel()) {
171             $this->doPrivmsg($source, 'Reminders must be requested in-channel.');
172             return;
173         }
174
175         $q = $this->db->prepare(
176             'INSERT INTO remind
177                 (
178                     time,
179                     channel,
180                     recipient,
181                     sender,
182                     message
183                 )
184             VALUES
185                 (
186                     :time,
187                     :channel,
188                     :recipient,
189                     :sender,
190                     :message
191                )'
192         );
193         try {
194             $q->execute(
195                 array(
196                     'time' => date(DATE_RFC822),
197                     'channel' => $source,
198                     'recipient' => strtolower($recipient),
199                     'sender' => strtolower($nick),
200                     'message' => $message
201                 )
202             );
203         } catch (PDOException $e) {
204         }
205
206         if ($rowid = $this->db->lastInsertId()) {
207             $this->doPrivmsg($source, 'ok, ' . $nick . ', message stored');
208         } else {
209             $this->doPrivmsg(
210                 $source,
211                 $nick . ': bad things happened. Message not saved.'
212             );
213             return;
214         }
215
216         if ($this->keepListInMemory) {
217             $this->msgStorage[$source][strtolower($recipient)] = $rowid;
218         }
219     }
220
221     /**
222      * Determines if the user has pending reminders, and if so, delivers them.
223      *
224      * @param string $channel channel to check
225      * @param string $nick    nick to check
226      *
227      * @return void
228      */
229     protected function deliverReminders($channel, $nick)
230     {
231         if ($channel[0] != '#') {
232             // private message, not a channel, so don't check
233             return;
234         }
235
236         // short circuit if there's no message in memory (if allowed)
237         if ($this->keepListInMemory
238             && !isset($this->msgStorage[$channel][strtolower($nick)])
239         ) {
240             return;
241         }
242
243         // fetch and deliver messages
244         $reminders = $this->fetchMessages($channel, $nick);
245         if (count($reminders) > $this->publicReminders) {
246             $msgs = array_slice($reminders, 0, $this->publicReminders);
247             $privmsgs = array_slice($reminders, $this->publicReminders);
248         } else {
249             $msgs = $reminders;
250             $privmsgs = false;
251         }
252
253         foreach ($msgs as $msg) {
254             $ts = $this->plugins->time->getCountdown($msg['time']);
255             $formatted = sprintf(
256                 '%s: (from %s, %s ago) %s',
257                 $nick, $msg['sender'], $ts, $msg['message']
258             );
259             $this->doPrivmsg($channel, $formatted);
260             $this->deleteMessage($msg['rowid'], $channel, $nick);
261         }
262
263         if ($privmsgs) {
264             foreach ($privmsgs as $msg) {
265                 $ts = $this->plugins->time->getCountdown($msg['time']);
266                 $formatted = sprintf(
267                     'from %s, %s ago: %s',
268                     $msg['sender'], $ts, $msg['message']
269                 );
270                 $this->doPrivmsg($nick, $formatted);
271                 $this->deleteMessage($msg['rowid'], $channel, $nick);
272             }
273             $formatted = sprintf(
274                 '%s: (%d more messages sent in private.)',
275                 $nick, count($privmsgs)
276             );
277             $this->doPrivmsg($channel, $formatted);
278         }
279     }
280
281     /**
282      * Get pending messages (for a specific channel/recipient)
283      *
284      * @param string $channel   channel on which to check for pending messages
285      * @param string $recipient user for which to check pending messages
286      *
287      * @return array of records
288      */
289     protected function fetchMessages($channel = null, $recipient = null)
290     {
291         if ($channel) {
292             $qClause = 'WHERE channel = :channel AND recipient LIKE :recipient';
293             $params = compact('channel', 'recipient');
294         } else {
295             $qClause = '';
296             $params = array();
297         }
298         $q = $this->db->prepare(
299             'SELECT rowid, channel, sender, recipient, time, message
300             FROM remind ' . $qClause
301         );
302         $q->execute($params);
303         return $q->fetchAll();
304     }
305
306     /**
307      * Deletes a delivered message
308      *
309      * @param int    $rowid   ID of the message to delete
310      * @param string $channel message's channel
311      * @param string $nick    message's recipient
312      *
313      * @return void
314      */
315     protected function deleteMessage($rowid, $channel, $nick)
316     {
317         $nick = strtolower($nick);
318         $q = $this->db->prepare('DELETE FROM remind WHERE rowid = :rowid');
319         $q->execute(array('rowid' => $rowid));
320
321         if ($this->keepListInMemory) {
322             if (isset($this->msgStorage[$channel][$nick])
323                 && $this->msgStorage[$channel][$nick] == $rowid
324             ) {
325                 unset($this->msgStorage[$channel][$nick]);
326             }
327         }
328     }
329
330     /**
331      * Determines if a table exists
332      *
333      * @param string $name Table name
334      *
335      * @return bool
336      */
337     protected function haveTable($name)
338     {
339         $sql = 'SELECT COUNT(*) FROM sqlite_master WHERE name = '
340             . $this->db->quote($name);
341         return (bool) $this->db->query($sql)->fetchColumn();
342     }
343
344     /**
345      * Creates the database table(s) (if they don't exist)
346      *
347      * @return void
348      */
349     protected function createTables()
350     {
351         if (!$this->haveTable('remind')) {
352             $this->db->exec(
353                 'CREATE TABLE
354                     remind
355                     (
356                         time INTEGER,
357                         channel TEXT,
358                         recipient TEXT,
359                         sender TEXT,
360                         message TEXT
361                     )'
362             );
363         }
364     }
365
366     /**
367      * Populates the in-memory cache of pending reminders
368      *
369      * @return void
370      */
371     protected function populateMemory()
372     {
373         if (!$this->keepListInMemory) {
374             return;
375         }
376         foreach ($this->fetchMessages() as $msg) {
377             $this->msgStorage[$msg['channel']][$msg['recipient']] = $msg['rowid'];
378         }
379     }
380 }