Assembla home | Assembla project page
 

root/trunk/Phergie/Plugin/Seen.php

Revision 290, 14.6 kB (checked in by tobias382, 1 month ago)

Fixes #67 Applied patch for limiting quote to the current channel

Line 
1 <?php
2
3 /**
4  * Handles requests for logged data pertaining to the ast actions taken or
5  * messages sent by a given user or posts sent containing a given search phrase.
6  */
7 class Phergie_Plugin_Seen extends Phergie_Plugin_Abstract_Command
8 {
9     /**
10      * Prepared statement for searching for the last logged action in which a
11      * particular user was mentioned
12      *
13      * @var PDOStatement
14      */
15     protected $search;
16
17     /**
18      * Prepared statement for searching for the last logged action originating
19      * from a particular user
20      *
21      * @var PDOStatement
22      */
23     protected $seen;
24
25     /**
26      * Prepared statement for searching for the last logged message originating
27      * from a particular user
28      *
29      * @var PDOStatement
30      */
31     protected $heard;
32
33     /**
34      * Prepared statement for searching for one or more time ranges during
35      * which a particular user is most likely to be present in a particular
36      * channel
37      *
38      * @var PDOStatement
39      */
40     protected $willsee;
41
42     /**
43      * Prepared statement for searching for a random logged message originating
44      * from a particular user
45      *
46      * @var PDOStatement
47      */
48     protected $quote;
49
50     /**
51      * Action descriptions corresponding to event constants
52      *
53      * @var array
54      */
55     protected $actions = array(
56         Phergie_Plugin_Logging::JOIN    => 'joining this channel',
57         Phergie_Plugin_Logging::PART    => 'leaving this channel because',
58         Phergie_Plugin_Logging::QUIT    => 'quitting',
59         Phergie_Plugin_Logging::PRIVMSG => 'saying',
60         Phergie_Plugin_Logging::ACTION  => 'doing the action',
61         Phergie_Plugin_Logging::NICK    => 'changing nick to',
62         Phergie_Plugin_Logging::KICK    => 'being kicked off because',
63         Phergie_Plugin_Logging::QUERY   => 'private messaging',
64     );
65
66     /**
67      * Initializes the database.
68      *
69      * @return void
70      */
71     public function onConnect()
72     {
73         try {
74             if (!Phergie_Plugin_Logging::databaseExists()) {
75                 return;
76             }
77
78             // Initialize prepared statements for common operations
79             $this->search = Phergie_Plugin_Logging::prepare('
80                 SELECT tstamp, type, chan, nick, message
81                 FROM logs
82                 WHERE nick LIKE :phrase ESCAPE "\\"
83                 OR message LIKE :phrase ESCAPE "\\"
84                 AND type NOT IN (:type, ' . Phergie_Plugin_Logging::MODE . ', ' . Phergie_Plugin_Logging::TOPIC . ')
85                 ORDER BY tstamp DESC
86                 LIMIT 1,:limit
87             ');
88
89             $this->seen = Phergie_Plugin_Logging::prepare('
90                 SELECT tstamp, type, chan, message
91                 FROM logs
92                 WHERE LOWER(nick) = LOWER(:name)
93                 AND type NOT IN (' . Phergie_Plugin_Logging::QUERY . ', ' . Phergie_Plugin_Logging::MODE . ', ' . Phergie_Plugin_Logging::TOPIC . ')
94                 ORDER BY tstamp DESC
95                 LIMIT :offset,1
96             ');
97
98             $this->heard = Phergie_Plugin_Logging::prepare('
99                 SELECT tstamp, chan, message
100                 FROM logs
101                 WHERE type = ' . Phergie_Plugin_Logging::PRIVMSG . '
102                 AND LOWER(nick) = LOWER(:name)
103                 ORDER BY tstamp DESC
104                 LIMIT :offset,1
105             ');
106
107             $this->willsee = Phergie_Plugin_Logging::prepare('
108                 SELECT strftime("%H", tstamp) post_hour, COUNT(*) post_count
109                 FROM logs
110                 WHERE type IN (' . Phergie_Plugin_Logging::PRIVMSG . ', ' . Phergie_Plugin_Logging::ACTION . ')
111                 AND LOWER(nick) = LOWER(:nick)
112                 AND strftime("%w", tstamp) = strftime("%w", "now")
113                 GROUP BY strftime("%H", tstamp)
114                 ORDER BY 2 DESC, 1
115                 LIMIT 1
116             ');
117
118             $this->quote = Phergie_Plugin_Logging::prepare('
119                 SELECT tstamp, chan, message
120                 FROM logs
121                 WHERE type = ' . Phergie_Plugin_Logging::PRIVMSG . '
122                 AND LOWER(nick) = LOWER(:name)
123                 AND LOWER(chan) = LOWER(:chan)
124                 ORDER BY RANDOM()
125                 LIMIT :offset,1
126             ');
127         } catch (PDOException $e) { }
128     }
129
130     /**
131      * Returns whether or not the plugin's dependencies are met.
132      *
133      * @param Phergie_Driver_Abstract $client Client instance
134      * @param array $plugins List of short names for plugins that the
135      *                       bootstrap file intends to instantiate
136      * @see Phergie_Plugin_Abstract_Base::checkDependencies()
137      * @return bool TRUE if dependencies are met, FALSE otherwise
138      */
139     public static function checkDependencies(Phergie_Driver_Abstract $client, array $plugins)
140     {
141         if (!self::staticPluginLoaded('Logging', $client, $plugins)) {
142             return 'Logging plugin must be enabled';
143         }
144         return true;
145     }
146
147     /**
148      * Formats a timestamp for display purposes.
149      *
150      * @param string $timestamp Timestamp to format
151      * @return string Formatted timestamp
152      */
153     protected function formatTimestamp($timestamp)
154     {
155         return $this->getCountdown(time() - strtotime($timestamp));
156     }
157
158     /**
159      * Responds to requests for logged messages containing a particular search
160      * phrase.
161      *
162      * @param string $phrase Phrase to search for
163      * @return void
164      */
165     public function onDoSearch($phrase)
166     {
167         if (!Phergie_Plugin_Logging::databaseExists()) {
168             return;
169         }
170
171         $searchAll = false;
172         if (substr(strtolower($phrase), 0, 4) == '-all') {
173             $phrase = trim(substr($phrase, 4));
174             $searchAll = true;
175         } else if (substr(strtolower($phrase), 0, 2) == '-a') {
176             $phrase = trim(substr($phrase, 2));
177             $searchAll = true;
178         }
179         $searchAll = (!$this->fromAdmin(true) ? false : $searchAll);
180
181         $source = $this->event->getSource();
182         $target = $this->event->getNick();
183
184         $params = array(
185             ':phrase' => '%' . str_replace(array('\\', '%'), array('\\\\', '\\%'), $phrase) . '%',
186             ':limit' => ($source[0] == '#' ? 1 : 6),
187             ':type' => ($searchAll ? '0' : Phergie_Plugin_Logging::QUERY)
188         );
189
190         try {
191             $this->search->execute($params);
192             $rows = $this->search->fetchAll(PDO::FETCH_ASSOC);
193         } catch (PDOException $e) { }
194
195         if (count($rows) <= 0) {
196             $this->doNotice($target, 'I have no records for "' . $phrase . '"');
197             return;
198         }
199
200         foreach($rows as $row) {
201             $this->doPrivmsg(
202                 $source,
203                 sprintf(
204                     '%s%s was seen %s "%s" on %s (%s ago)',
205                     ($source[0] == '#' ? $target . ': ' : ''),
206                     $row['nick'],
207                     $this->actions[$row['type']],
208                     $row['message'],
209                     $row['chan'],
210                     $this->formatTimestamp($row['tstamp'])
211                 )
212             );
213         }
214     }
215
216     /**
217      * Responds to requests for the last logged action originating from a
218      * particular user.
219      *
220      * @param string $user Nick of the user to search for
221      * @return void
222      */
223     public function onDoSeen($user)
224     {
225         if (!Phergie_Plugin_Logging::databaseExists()) {
226             return;
227         }
228
229         // Don't match if user has a space (obviously it's not a nick)
230         if (strpos($user, ' ') !== false) {
231             return;
232         }
233
234         $source = $this->event->getSource();
235         $target = $this->event->getNick();
236
237         // Handle cases where the bot is the subject
238         if (strtolower($user) == strtolower($this->getIni('nick'))) {
239             $this->doPrivmsg($source, $target . ': Are you blind? I\'m right here!');
240             return;
241         }
242
243         // Handle 'me' alias
244         if ($user == 'me') {
245             $user = $target;
246         }
247
248         // Get the last event from the specified user
249         $params = array(
250             ':name' => $user,
251             ':offset' => (strtolower($target) == strtolower($user) ? 1 : 0)
252         );
253
254         try {
255             $this->seen->execute($params);
256             $row = $this->seen->fetch(PDO::FETCH_ASSOC);
257         } catch (PDOException $e) { }
258
259         // Send the last action if available
260         if ($row) {
261             $this->doPrivmsg(
262                 $source,
263                 sprintf(
264                     '%s: %s was last seen %s "%s" on %s (%s ago)',
265                     $target,
266                     $user,
267                     $this->actions[$row['type']],
268                     $row['message'],
269                     $row['chan'],
270                     $this->formatTimestamp($row['tstamp'])
271                 )
272             );
273         } else {
274             $this->doNotice($target, 'I have no records for ' . $user);
275         }
276     }
277
278     /**
279      * Responds to requests for the last logged message originating from a
280      * particular user.
281      *
282      * @param string $user Nick of the user to search for
283      * @return void
284      */
285     public function onDoHeard($user)
286     {
287         if (!Phergie_Plugin_Logging::databaseExists()) {
288             return;
289         }
290
291         // Don't match if user has a space (obviously it's not a nick)
292         if (strpos($user, ' ') !== false) {
293             return;
294         }
295
296         $source = $this->event->getSource();
297         $target = $this->event->getNick();
298
299         // Handle cases where the bot is the subject
300         if (strtolower($user) == strtolower($this->getIni('nick'))) {
301             $this->doPrivmsg($source, $target . ': Are you deaf? Can you not hear me?!');
302             return;
303         }
304
305         // Handle 'me' alias
306         if ($user == 'me') {
307             $user = $target;
308         }
309
310         // Get the last event from the specified user
311         $params = array(
312             ':name' => $user,
313             ':offset' => (strtolower($target) == strtolower($user) ? 1 : 0)
314         );
315
316         try {
317             $this->heard->execute($params);
318             $row = $this->heard->fetch(PDO::FETCH_ASSOC);
319         } catch (PDOException $e) { }
320
321         // Send the last action if available
322         if ($row) {
323             $this->doPrivmsg(
324                 $source,
325                 sprintf(
326                     '%s: %s was last seen %s "%s" on %s (%s ago)',
327                     $target,
328                     $user,
329                     $this->actions[Phergie_Plugin_Logging::PRIVMSG],
330                     $row['message'],
331                     $row['chan'],
332                     $this->formatTimestamp($row['tstamp'])
333                 )
334             );
335         } else {
336             $this->doNotice($target, 'I have no records for ' . $user);
337         }
338     }
339
340     /**
341      * Responds to requests for a time range during which a particular user
342      * is most likely to be present in the channel from which the request
343      * originates.
344      *
345      * @param string $user Nick of the user to search for
346      * @return void
347      */
348     public function onDoWillsee($user)
349     {
350         if (!Phergie_Plugin_Logging::databaseExists()) {
351             return;
352         }
353
354         $source = $this->event->getSource();
355         $target = $this->event->getNick();
356
357         // Check to make sure the request came from a channel
358         if ($source[0] != '#') {
359             return;
360         }
361
362         // Don't match if user has a space (obviously it's not a nick)
363         if (strpos($user, ' ') !== false) {
364             return;
365         }
366
367         // Handle cases where the bot is the subject
368         if (strtolower($user) == strtolower($this->getIni('nick'))) {
369             $this->doPrivmsg($source, $target . ': What are you talking about? I\'m always here!');
370             return;
371         }
372
373         // Handle 'me' alias
374         if ($user == 'me') {
375             $user = $this->event->getNick();
376         }
377
378         // Perform the search
379         $params = array(
380             ':nick' => $user
381         );
382
383         try {
384             $this->willsee->execute($params);
385             $prediction = $this->willsee->fetchColumn();
386         } catch (PDOException $e) { }
387
388         // Return if no results are found
389         if ($prediction === false) {
390             $this->doNotice($target, 'I couldn\'t make a prediction for ' . $user);
391             return;
392         }
393
394         // Calculate a predicted time of arrival
395         $hour = date('H');
396         if ($hour > $prediction) {
397             $prediction = 24 - ($hour - $prediction);
398         } else {
399             $prediction = $prediction - $hour;
400         }
401
402         // Return with a message including the prediction
403         $message = $target . ': ' . $user . ' is most likely to be online ';
404         if ($prediction == 0) {
405             $message .= 'now!';
406         } elseif ($prediction == 1) {
407             $message .= 'in 1 hour.';
408         } else {
409             $message .= 'in ' . $prediction . ' hours.';
410         }
411         $this->doPrivmsg($source, $message);
412     }
413
414     /**
415      * Responds to requests for a random message originating from a particular
416      * user.
417      *
418      * @param string $user Nick of the user to search for
419      * @return void
420      */
421     public function onDoQuote($user)
422     {
423         if (!Phergie_Plugin_Logging::databaseExists()) {
424             return;
425         }
426
427         // Don't match if user has a space (obviously it's not a nick)
428         if (strpos($user, ' ') !== false) {
429             return;
430         }
431
432         $source = $this->event->getSource();
433         $target = $this->event->getNick();
434
435         // Handle cases where the bot is the subject
436         if (strtolower($user) == strtolower($this->getIni('nick'))) {
437             $this->doPrivmsg($source, $target . ': Everything I say is amazing, how can I choose just one?');
438             return;
439         }
440
441         // Handle 'me' alias
442         if ($user == 'me') {
443             $user = $target;
444         }
445
446         // Get the last event from the specified user
447         $params = array(
448             ':name' => $user,
449             ':chan' => $source,
450             ':offset' => (strtolower($target) == strtolower($user) ? 1 : 0)
451         );
452
453         try {
454             $this->quote->execute($params);
455             $row = $this->quote->fetch(PDO::FETCH_ASSOC);
456         } catch (PDOException $e) { }
457
458         // Send the last action if available
459         if ($row) {
460             $this->doPrivmsg(
461                 $source,
462                 sprintf(
463                     '%s: %s was quoted saying "%s" on %s (%s ago)',
464                     $target,
465                     $user,
466                     $row['message'],
467                     $row['chan'],
468                     $this->formatTimestamp($row['tstamp'])
469                 )
470             );
471         } else {
472             $this->doNotice($target, 'I have no records for ' . $user);
473         }
474     }
475 }
476
Note: See TracBrowser for help on using the browser.