]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/Irc/extlib/phergie/Phergie/Plugin/Remind.php
Added Phergie PHP IRC library
[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_Drink
31  * @uses     Phergie_Plugin_Command pear.phergie.org
32  * @uses     Phergie_Plugin_Helper_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     const PUBLIC_REMINDERS = 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         $this->getPluginHandler()->getPlugin('Command');
68         $path = dirname(__FILE__) . '/reminder.db';
69
70         if (isset($this->config['remind.use_memory'])) {
71             $this->keepListInMemory = (bool)$this->config['remind.use_memory'];
72         }
73
74         try {
75             $this->db = new PDO('sqlite:' . $path);
76             $this->createTables();
77         } catch (PDO_Exception $e) {
78             throw new Phergie_Plugin_Exception($e->getMessage());
79         }
80     }
81
82     /**
83      * Intercepts a message and processes any contained recognized commands.
84      *
85      * @return void
86      */
87     public function onPrivmsg()
88     {
89         $source = $this->getEvent()->getSource();
90         $nick = $this->getEvent()->getNick();
91
92         $this->deliverReminders($source, $nick);
93     }
94
95     /**
96      * Handle reminder requests
97      *
98      * @param string $recipient recipient of the message
99      * @param string $message   message to tell the recipient
100      *
101      * @return void
102      * @see handleRemind()
103      */
104     public function onCommandTell($recipient, $message)
105     {
106         $this->handleRemind($recipient, $message);
107     }
108
109     /**
110      * Handle reminder requests
111      *
112      * @param string $recipient recipient of the message
113      * @param string $message   message to tell the recipient
114      *
115      * @return void
116      * @see handleRemind()
117      */
118     public function onCommandAsk($recipient, $message)
119     {
120         $this->handleRemind($recipient, $message);
121     }
122
123     /**
124      * Handle reminder requests
125      *
126      * @param string $recipient recipient of the message
127      * @param string $message   message to tell the recipient
128      *
129      * @return void
130      * @see handleRemind()
131      */
132     public function onCommandRemind($recipient, $message)
133     {
134         $this->handleRemind($recipient, $message);
135     }
136
137     /**
138      * Handles the tell/remind command (stores the message)
139      *
140      * @param string $recipient name of the recipient
141      * @param string $message   message to store
142      *
143      * @return void
144      */
145     protected function handleRemind($recipient, $message)
146     {
147         $source = $this->getEvent()->getSource();
148         $nick = $this->getEvent()->getNick();
149
150         if (!$this->getEvent()->isInChannel()) {
151             $this->doPrivmsg($source, 'Reminders must be requested in-channel.');
152             return;
153         }
154
155         $q = $this->db->prepare(
156             'INSERT INTO remind
157                 (
158                     time,
159                     channel,
160                     recipient,
161                     sender,
162                     message
163                 )
164             VALUES
165                 (
166                     :time,
167                     :channel,
168                     :recipient,
169                     :sender,
170                     :message
171                )'
172         );
173         try {
174             $q->execute(
175                 array(
176                     'time' => date(DATE_RFC822),
177                     'channel' => $source,
178                     'recipient' => strtolower($recipient),
179                     'sender' => strtolower($nick),
180                     'message' => $message
181                 )
182             );
183         } catch (PDOException $e) {
184         }
185
186         if ($rowid = $this->db->lastInsertId()) {
187             $this->doPrivmsg($source, 'ok, ' . $nick . ', message stored');
188         } else {
189             $this->doPrivmsg(
190                 $source,
191                 $nick . ': bad things happened. Message not saved.'
192             );
193             return;
194         }
195
196         if ($this->keepListInMemory) {
197             $this->msgStorage[$source][strtolower($recipient)] = $rowid;
198         }
199     }
200
201     /**
202      * Determines if the user has pending reminders, and if so, delivers them.
203      *
204      * @param string $channel channel to check
205      * @param string $nick    nick to check
206      *
207      * @return void
208      */
209     protected function deliverReminders($channel, $nick)
210     {
211         if ($channel[0] != '#') {
212             // private message, not a channel, so don't check
213             return;
214         }
215
216         // short circuit if there's no message in memory (if allowed)
217         if ($this->keepListInMemory
218             && !isset($this->msgStorage[$channel][strtolower($nick)])
219         ) {
220             return;
221         }
222
223         // fetch and deliver messages
224         $reminders = $this->fetchMessages($channel, $nick);
225         if (count($reminders) > self::PUBLIC_REMINDERS) {
226             $msgs = array_slice($reminders, 0, self::PUBLIC_REMINDERS);
227             $privmsgs = array_slice($reminders, self::PUBLIC_REMINDERS);
228         } else {
229             $msgs = $reminders;
230             $privmsgs = false;
231         }
232
233         foreach ($msgs as $msg) {
234             $ts = new Phergie_Plugin_Helper_Time($msg['time']);
235             $formatted = sprintf(
236                 '%s: (from %s, %s ago) %s',
237                 $nick, $msg['sender'], $ts->getCountdown(), $msg['message']
238             );
239             $this->doPrivmsg($channel, $formatted);
240             $this->deleteMessage($msg['rowid'], $channel, $nick);
241         }
242
243         if ($privmsgs) {
244             foreach ($privmsgs as $msg) {
245                 $ts = new Phergie_Plugin_Helper_Time($msg['time']);
246                 $formatted = sprintf(
247                     'from %s, %s ago: %s',
248                     $msg['sender'], $ts->getCountdown(), $msg['message']
249                 );
250                 $this->doPrivmsg($nick, $formatted);
251                 $this->deleteMessage($msg['rowid'], $channel, $nick);
252             }
253             $formatted = sprintf(
254                 '%s: (%d more messages sent in private.)',
255                 $nick, count($privmsgs)
256             );
257             $this->doPrivmsg($channel, $formatted);
258         }
259     }
260
261     /**
262      * Get pending messages (for a specific channel/recipient)
263      *
264      * @param string $channel   channel on which to check for pending messages
265      * @param string $recipient user for which to check pending messages
266      *
267      * @return array of records
268      */
269     protected function fetchMessages($channel = null, $recipient = null)
270     {
271         if ($channel) {
272             $qClause = 'WHERE channel = :channel AND recipient LIKE :recipient';
273             $params = compact('channel', 'recipient');
274         } else {
275             $qClause = '';
276             $params = array();
277         }
278         $q = $this->db->prepare(
279             'SELECT rowid, channel, sender, recipient, time, message
280             FROM remind ' . $qClause
281         );
282         $q->execute($params);
283         return $q->fetchAll();
284     }
285
286     /**
287      * Deletes a delivered message
288      *
289      * @param int    $rowid   ID of the message to delete
290      * @param string $channel message's channel
291      * @param string $nick    message's recipient
292      *
293      * @return void
294      */
295     protected function deleteMessage($rowid, $channel, $nick)
296     {
297         $nick = strtolower($nick);
298         $q = $this->db->prepare('DELETE FROM remind WHERE rowid = :rowid');
299         $q->execute(array('rowid' => $rowid));
300
301         if ($this->keepListInMemory) {
302             if (isset($this->msgStorage[$channel][$nick])
303                 && $this->msgStorage[$channel][$nick] == $rowid
304             ) {
305                 unset($this->msgStorage[$channel][$nick]);
306             }
307         }
308     }
309
310     /**
311      * Determines if a table exists
312      *
313      * @param string $name Table name
314      *
315      * @return bool
316      */
317     protected function haveTable($name)
318     {
319         $sql = 'SELECT COUNT(*) FROM sqlite_master WHERE name = '
320             . $this->db->quote($name);
321         return (bool) $this->db->query($sql)->fetchColumn();
322     }
323
324     /**
325      * Creates the database table(s) (if they don't exist)
326      *
327      * @return void
328      */
329     protected function createTables()
330     {
331         if (!$this->haveTable('remind')) {
332             $this->db->exec(
333                 'CREATE TABLE
334                     remind
335                     (
336                         time INTEGER,
337                         channel TEXT,
338                         recipient TEXT,
339                         sender TEXT,
340                         message TEXT
341                     )'
342             );
343         }
344     }
345
346     /**
347      * Populates the in-memory cache of pending reminders
348      *
349      * @return void
350      */
351     protected function populateMemory()
352     {
353         if (!$this->keepListInMemory) {
354             return;
355         }
356         foreach ($this->fetchMessages() as $msg) {
357             $this->msgStorage[$msg['channel']][$msg['recipient']] = $msg['rowid'];
358         }
359     }
360 }