Assembla home | Assembla project page
 

Changeset 186

Show
Ignore:
Timestamp:
03/21/08 22:57:58 (8 months ago)
Author:
Slynderdale
Message:

Fixed #13 Removed the Seen/Heard/Willsee commands out from Logging and added them to their own module called Seen and added a way for other modules to pull data from Logging.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Phergie/Plugin/Logging.php

    r134 r186  
    1212 
    1313/** 
    14 * Logs channel events and handles requests for logged data pertaining to the 
    15 * last actions taken or messages sent by a given user or posts sent 
    16 * containing a given search phrase. 
     14* Logs all channel events and stores them to the database and also provides 
     15* an API for other plugins to retrieve this information. 
    1716*/ 
    1817class Phergie_Plugin_Logging extends Phergie_Plugin_Abstract_Command 
     
    9392    * @var PDO 
    9493    */ 
    95     protected $db = null; 
    96  
    97     /** 
    98     * Prepared statement for searching for the last logged action in which a 
    99     * particular user was mentioned 
     94    protected static $db = null; 
     95 
     96    /** 
     97    * Prepared statement for inserting new log entries 
    10098    * 
    10199    * @var PDOStatement 
    102100    */ 
    103     protected $search; 
    104  
    105     /** 
    106     * Prepared statement for searching for the last logged action originating 
    107     * from a particular user 
    108     * 
    109     * @var PDOStatement 
    110     */ 
    111     protected $seen; 
    112  
    113     /** 
    114     * Prepared statement for searching for the last logged PRIVMSG action or 
    115     * CTCP ACTION command originating from a particular user 
    116     * 
    117     * @var PDOStatement 
    118     */ 
    119     protected $heard; 
    120  
    121     /** 
    122     * PRepared statement for searching for one or more time ranges during  
    123     * which a particular user is most likely to be present in a particular  
    124     * channel  
    125     * 
    126     * @var PDOStatement 
    127     */ 
    128     protected $willsee; 
    129  
    130     /** 
    131     * Prepared statement for inserting new log entries 
    132     * 
    133     * @var PDOStatement 
    134     */ 
    135101    protected $insert; 
    136102 
    137103    /** 
    138     * Action descriptions corresponding to event constants 
    139     * 
    140     * @var array 
    141     */ 
    142     protected $actions = array 
    143     ( 
    144         self::JOIN => 'joining this channel', 
    145         self::PART => 'leaving this channel because', 
    146         self::QUIT => 'quitting', 
    147         self::PRIVMSG => 'saying', 
    148         self::ACTION => 'saying', 
    149         self::NICK => 'changing nick to', 
    150         self::KICK => 'being kicked off because', 
    151     ); 
     104    * Returns the PDO instance for the database 
     105    * 
     106    * @return PDO 
     107    */ 
     108    public static function getDB() 
     109    { 
     110        return self::$db; 
     111    } 
    152112 
    153113    /** 
     
    161121            // Initialize the database connection 
    162122            $db = $this->dir . 'logging.db'; 
    163             $create = !file_exists($db); 
    164             $this->db = new PDO('sqlite:' . $db); 
     123            self::$db = new PDO('sqlite:' . $db); 
     124 
     125            // Check to see if the table exists 
     126            $table = self::$db 
     127                ->query('SELECT COUNT(*) FROM sqlite_master WHERE name = ' . self::$db->quote('logs')) 
     128                ->fetchColumn(); 
    165129 
    166130            // Create database tables if necessary 
    167             if ($create) { 
    168                 $result = $this->db->exec(' 
     131            if (!$table) { 
     132                $this->debug('Creating the database schema'); 
     133                $result = self::$db->exec(' 
    169134                    CREATE TABLE logs ( 
    170135                        tstamp VARCHAR(19), 
     
    179144            } 
    180145 
    181             // Initialize prepared statements for common operations 
    182             $this->search = $this->db->prepare(' 
    183                 SELECT tstamp, type, chan, nick, message 
    184                 FROM logs 
    185                 WHERE nick LIKE :phrase 
    186                 OR message LIKE :phrase 
    187                 ORDER BY tstamp DESC 
    188                 LIMIT :limit 
    189             '); 
    190  
    191             $this->seen = $this->db->prepare(' 
    192                 SELECT tstamp, type, message 
    193                 FROM logs 
    194                 WHERE nick = :name 
    195                 AND chan = :chan 
    196                 ORDER BY tstamp DESC 
    197                 LIMIT 1 
    198             '); 
    199  
    200             $this->willsee = $this->db->prepare(' 
    201                 SELECT strftime("%H", tstamp) post_hour, COUNT(*) post_count 
    202                 FROM logs 
    203                 WHERE type IN (' . self::PRIVMSG . ', ' . self::ACTION . ') 
    204                 AND nick = :nick 
    205                 AND chan = :chan 
    206                 GROUP BY strftime("%H", tstamp) 
    207                 ORDER BY 2 DESC, 1 
    208                 LIMIT 1 
    209             '); 
    210  
    211             $this->insert = $this->db->prepare(' 
     146            $this->insert = self::$db->prepare(' 
    212147                INSERT INTO logs ( 
    213148                    tstamp, 
     
    244179        } 
    245180 
    246         if (!extension_loaded('PDO')  
     181        if (!extension_loaded('PDO') 
    247182            || !extension_loaded('pdo_sqlite')) { 
    248183            return false; 
     
    250185 
    251186        return true; 
    252     } 
    253  
    254     /** 
    255     * Formats a timestamp for display purposes. 
    256     * 
    257     * @param string $timestamp Timestamp to format 
    258     * @return string Formatted timestamp 
    259     */ 
    260     protected function formatTimestamp($timestamp) 
    261     { 
    262         return preg_replace( 
    263             '#^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$#', 
    264             '$1-$2-$3 @ $4:$5:$6', 
    265             $timestamp 
    266         ); 
    267187    } 
    268188 
     
    279199    protected function insertEvent($type, $chan, $nick, $message = null) 
    280200    { 
    281         if (!$this->db) { 
     201        if (!self::$db) { 
    282202            return; 
    283203        } 
     
    442362        } 
    443363    } 
    444  
    445     /** 
    446     * Responds to requests for logged messages containing a particular search 
    447     * phrase. 
    448     * 
    449     * @param string $phrase Phrase to search for 
    450     * @return void 
    451     */ 
    452     public function onDoSearch($phrase) 
    453     { 
    454         if (!$this->db) { 
    455             return; 
    456         } 
    457  
    458         $source = $this->event->getSource(); 
    459  
    460         $params = array( 
    461             ':phrase' => '%' . $phrase . '%', 
    462             ':limit' => ($source[0] == '#' ? 1 : 6) 
    463         ); 
    464  
    465         $this->search->execute($params); 
    466  
    467         foreach($this->search as $row) { 
    468             $this->doPrivmsg( 
    469                 $source, 
    470                 sprintf( 
    471                     '%s was seen %s: %s on %s (on %s)', 
    472                     $row['nick'], 
    473                     $this->actions[$row['type']], 
    474                     $row['message'], 
    475                     $row['chan'], 
    476                     $this->formatTimestamp($row['tstamp']) 
    477                 ) 
    478             ); 
    479         } 
    480     } 
    481  
    482     /** 
    483     * Responds to requests for the last logged action originating from a 
    484     * particular user. 
    485     * 
    486     * @param string $user Nick of the user to search for 
    487     * @return void 
    488     */ 
    489     public function onDoSeen($user) 
    490     { 
    491         if (!$this->db) { 
    492             return; 
    493         } 
    494  
    495         // Don't match if user has a space (obviously it's not a nick) 
    496         if (strpos($user, ' ') !== false) { 
    497                 return; 
    498         } 
    499  
    500         $source = $this->event->getSource(); 
    501         $target = $this->event->getNick(); 
    502  
    503         // Handle 'me' alias 
    504         if ($user == 'me') { 
    505             $user = $target; 
    506         } 
    507  
    508                 // Get the last event from the specified user 
    509                 $params = array( 
    510                         ':name' => $user, 
    511                         ':chan' => $source 
    512                 ); 
    513  
    514                 $this->seen->execute($params); 
    515                 $row = $this->seen->fetch(PDO::FETCH_ASSOC); 
    516  
    517                 // Send the last action if available 
    518                 if ($row) { 
    519                         $this->doPrivmsg( 
    520                                 $source, 
    521                                 sprintf( 
    522                                         '%s: %s was last seen %s: %s (on %s)', 
    523                                         $target, 
    524                                         $user, 
    525                                         $this->actions[$row['type']], 
    526                                         $row['message'], 
    527                                         $this->formatTimestamp($row['tstamp']) 
    528                                 ) 
    529                         ); 
    530                 } 
    531     } 
    532  
    533     /** 
    534     * Responds to requests for a time range during which a particular user  
    535     * is most likely to be present in the channel from which the request  
    536     * originates. 
    537     * 
    538     * @param string $user Nick of the user to search for 
    539     * @return void 
    540     */ 
    541     public function onDoWillsee($user) 
    542     { 
    543         if (!$this->db) { 
    544             return; 
    545         } 
    546          
    547         // Check to make sure the request came from a channel 
    548         $source = $this->event->getSource(); 
    549         if ($source[0] != '#') { 
    550             return; 
    551         } 
    552  
    553         // Handle cases where the bot is the subject 
    554         if ($user == $this->getIni('nick')) { 
    555             $this->doPrivmsg($source, 'What are you talking about? I\'m always here!'); 
    556             return; 
    557         } 
    558  
    559         // Handle 'me' alias 
    560         if ($user == 'me') { 
    561             $user = $this->event->getNick(); 
    562         } 
    563  
    564         // Perform the search 
    565         $params = array( 
    566             ':nick' => $user, 
    567             ':chan' => $source 
    568         ); 
    569  
    570         $this->willsee->execute($params); 
    571         $prediction = $this->willsee->fetchColumn(); 
    572  
    573         // Return if no results are found 
    574         if ($prediction === false) { 
    575             return; 
    576         } 
    577  
    578         // Calculate a predicted time of arrival  
    579         $hour = date('H'); 
    580         if ($hour > $prediction) { 
    581             $prediction = 24 - ($hour - $prediction); 
    582         } else { 
    583             $prediction = $prediction - $hour; 
    584         } 
    585  
    586         // Return with a message including the prediction 
    587         $message = $target . ': ' . $user . ' is most likely to be online '; 
    588         if ($prediction == 0) { 
    589             $message .= 'now!'; 
    590         } elseif ($prediction == 1) { 
    591             $message .= 'in 1 hour.'; 
    592         } else { 
    593             $message .= 'in ' . $prediction . ' hours.'; 
    594         } 
    595         $this->doPrivmsg($source, $message); 
    596     } 
    597364}