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
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
23 * Parses and logs messages that should be relayed to other users the next time
24 * the recipient is active on the same channel.
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
34 class Phergie_Plugin_Remind extends Phergie_Plugin_Abstract
37 * Number of reminders to show in public.
39 const PUBLIC_REMINDERS = 3;
42 * PDO resource for a SQLite database containing the reminders.
49 * Flag that indicates whether or not to use an in-memory reminder list.
53 protected $keepListInMemory = true;
56 * In-memory store for pending reminders.
58 protected $msgStorage = array();
61 * Check for dependencies.
65 public function onLoad()
67 $this->getPluginHandler()->getPlugin('Command');
68 $path = dirname(__FILE__) . '/reminder.db';
70 if (isset($this->config['remind.use_memory'])) {
71 $this->keepListInMemory = (bool)$this->config['remind.use_memory'];
75 $this->db = new PDO('sqlite:' . $path);
76 $this->createTables();
77 } catch (PDO_Exception $e) {
78 throw new Phergie_Plugin_Exception($e->getMessage());
83 * Intercepts a message and processes any contained recognized commands.
87 public function onPrivmsg()
89 $source = $this->getEvent()->getSource();
90 $nick = $this->getEvent()->getNick();
92 $this->deliverReminders($source, $nick);
96 * Handle reminder requests
98 * @param string $recipient recipient of the message
99 * @param string $message message to tell the recipient
102 * @see handleRemind()
104 public function onCommandTell($recipient, $message)
106 $this->handleRemind($recipient, $message);
110 * Handle reminder requests
112 * @param string $recipient recipient of the message
113 * @param string $message message to tell the recipient
116 * @see handleRemind()
118 public function onCommandAsk($recipient, $message)
120 $this->handleRemind($recipient, $message);
124 * Handle reminder requests
126 * @param string $recipient recipient of the message
127 * @param string $message message to tell the recipient
130 * @see handleRemind()
132 public function onCommandRemind($recipient, $message)
134 $this->handleRemind($recipient, $message);
138 * Handles the tell/remind command (stores the message)
140 * @param string $recipient name of the recipient
141 * @param string $message message to store
145 protected function handleRemind($recipient, $message)
147 $source = $this->getEvent()->getSource();
148 $nick = $this->getEvent()->getNick();
150 if (!$this->getEvent()->isInChannel()) {
151 $this->doPrivmsg($source, 'Reminders must be requested in-channel.');
155 $q = $this->db->prepare(
176 'time' => date(DATE_RFC822),
177 'channel' => $source,
178 'recipient' => strtolower($recipient),
179 'sender' => strtolower($nick),
180 'message' => $message
183 } catch (PDOException $e) {
186 if ($rowid = $this->db->lastInsertId()) {
187 $this->doPrivmsg($source, 'ok, ' . $nick . ', message stored');
191 $nick . ': bad things happened. Message not saved.'
196 if ($this->keepListInMemory) {
197 $this->msgStorage[$source][strtolower($recipient)] = $rowid;
202 * Determines if the user has pending reminders, and if so, delivers them.
204 * @param string $channel channel to check
205 * @param string $nick nick to check
209 protected function deliverReminders($channel, $nick)
211 if ($channel[0] != '#') {
212 // private message, not a channel, so don't check
216 // short circuit if there's no message in memory (if allowed)
217 if ($this->keepListInMemory
218 && !isset($this->msgStorage[$channel][strtolower($nick)])
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);
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']
239 $this->doPrivmsg($channel, $formatted);
240 $this->deleteMessage($msg['rowid'], $channel, $nick);
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']
250 $this->doPrivmsg($nick, $formatted);
251 $this->deleteMessage($msg['rowid'], $channel, $nick);
253 $formatted = sprintf(
254 '%s: (%d more messages sent in private.)',
255 $nick, count($privmsgs)
257 $this->doPrivmsg($channel, $formatted);
262 * Get pending messages (for a specific channel/recipient)
264 * @param string $channel channel on which to check for pending messages
265 * @param string $recipient user for which to check pending messages
267 * @return array of records
269 protected function fetchMessages($channel = null, $recipient = null)
272 $qClause = 'WHERE channel = :channel AND recipient LIKE :recipient';
273 $params = compact('channel', 'recipient');
278 $q = $this->db->prepare(
279 'SELECT rowid, channel, sender, recipient, time, message
280 FROM remind ' . $qClause
282 $q->execute($params);
283 return $q->fetchAll();
287 * Deletes a delivered message
289 * @param int $rowid ID of the message to delete
290 * @param string $channel message's channel
291 * @param string $nick message's recipient
295 protected function deleteMessage($rowid, $channel, $nick)
297 $nick = strtolower($nick);
298 $q = $this->db->prepare('DELETE FROM remind WHERE rowid = :rowid');
299 $q->execute(array('rowid' => $rowid));
301 if ($this->keepListInMemory) {
302 if (isset($this->msgStorage[$channel][$nick])
303 && $this->msgStorage[$channel][$nick] == $rowid
305 unset($this->msgStorage[$channel][$nick]);
311 * Determines if a table exists
313 * @param string $name Table name
317 protected function haveTable($name)
319 $sql = 'SELECT COUNT(*) FROM sqlite_master WHERE name = '
320 . $this->db->quote($name);
321 return (bool) $this->db->query($sql)->fetchColumn();
325 * Creates the database table(s) (if they don't exist)
329 protected function createTables()
331 if (!$this->haveTable('remind')) {
347 * Populates the in-memory cache of pending reminders
351 protected function populateMemory()
353 if (!$this->keepListInMemory) {
356 foreach ($this->fetchMessages() as $msg) {
357 $this->msgStorage[$msg['channel']][$msg['recipient']] = $msg['rowid'];