Assembla home | Assembla project page
 

Changeset 185

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

Fixes #18 Added recursive alias deleting. Now when a term is removed, all aliases pointing to that term will also be removed. Also added the ability to store more info about the lart including the hostmask of the person who added it and when it was added. A new command has been added 'lartinfo' that allows you to view information about a given term.

Files:

Legend:

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

    r106 r185  
    5454    * @var PDOStatement 
    5555    */ 
    56     protected $select; 
     56    protected $defination; 
     57 
     58    /** 
     59    * Prepared statement for selecting the alias of a given definition 
     60    * 
     61    * @var PDOStatement 
     62    */ 
     63    protected $alias; 
    5764 
    5865    /** 
     
    6269    */ 
    6370    protected $delete; 
     71 
     72    /** 
     73    * MAn array used to store recursive aliases for the getAliases function 
     74    * 
     75    * @var array 
     76    */ 
     77    protected $aCache; 
    6478 
    6579    /** 
     
    7488            // Initialize the database connection 
    7589            $db = $this->dir . 'lart.db'; 
    76             $create = !file_exists($db); 
    7790            $this->db = new PDO('sqlite:' . $db); 
    7891 
     92            // Check to see if the table exists 
     93            $table = $this->db 
     94                ->query('SELECT COUNT(*) FROM sqlite_master WHERE name = ' . $this->db->quote('lart')) 
     95                ->fetchColumn(); 
     96 
    7997            // Create database tables if necessary 
    80             if ($create) { 
     98            if (!$table) { 
     99                $this->debug('Creating the database schema'); 
    81100                $this->db->exec(' 
    82                     CREATE TABLE lart ( name VARCHAR(255), definition TEXT ); 
     101                    CREATE TABLE lart (name VARCHAR(255), definition TEXT, hostmask VARCHAR(50), tstamp VARCHAR(19)); 
    83102                    CREATE UNIQUE INDEX lart_name ON lart (name) 
    84103                '); 
    85104            } 
     105            unset($table); 
     106 
     107            // Get the list of columns from the table 
     108            $table = $this->db 
     109                ->query('PRAGMA table_info('.$this->db->quote('lart').')') 
     110                ->fetchAll(); 
     111 
     112            $columns = array(); 
     113            foreach($table as $key => $column) { 
     114                $columns[] = $column['name']; 
     115            } 
     116 
     117            // Update table as neccessary 
     118            if (!in_array('hostmask', $columns)) { 
     119                $this->debug('Updating the databae schema'); 
     120                $this->db->exec(' 
     121                    BEGIN TRANSACTION; 
     122                    CREATE TEMPORARY TABLE lart_backup (name VARCHAR(255), definition TEXT); 
     123                    INSERT INTO lart_backup SELECT name, definition FROM lart; 
     124                    DROP TABLE lart; 
     125                    CREATE TABLE lart (name VARCHAR(255), definition TEXT, hostmask VARCHAR(50), tstamp VARCHAR(19)); 
     126                    INSERT INTO lart SELECT name, definition, NULL, NULL FROM lart_backup; 
     127                    DROP TABLE lart_backup; 
     128                    COMMIT; 
     129                    CREATE UNIQUE INDEX lart_name ON lart (name) 
     130                '); 
     131            } 
     132            unset($table, $key, $column, $columns); 
    86133 
    87134            // Initialize prepared statements for common operations 
    88135            $this->replace = $this->db->prepare(' 
    89                 REPLACE INTO lart (name, definition) VALUES (:name, :definition) 
     136                REPLACE INTO lart (name, definition, hostmask, tstamp) VALUES (:name, :definition, :hostmask, :tstamp) 
     137            '); 
     138            $this->defination = $this->db->prepare(' 
     139                SELECT definition FROM lart WHERE LOWER(name) = LOWER(:name) 
     140            '); 
     141            $this->alias = $this->db->prepare(' 
     142                SELECT name FROM lart WHERE LOWER(definition) = LOWER(:definition) 
    90143            '); 
    91144            $this->select = $this->db->prepare(' 
    92                 SELECT definition FROM lart WHERE name = :name 
     145                SELECT * FROM lart WHERE LOWER(name) = LOWER(:name) 
    93146            '); 
    94147            $this->delete = $this->db->prepare(' 
    95                 DELETE FROM lart WHERE name = :name 
     148                DELETE FROM lart WHERE LOWER(name) = LOWER(:name) 
    96149            '); 
    97150        } catch (PDOException $e) { } 
     
    109162    public static function checkDependencies(Phergie_Driver_Abstract $client, array $plugins) 
    110163    { 
    111         if (!extension_loaded('PDO')  
     164        if (!extension_loaded('PDO') 
    112165            || !extension_loaded('pdo_sqlite')) { 
    113166            return false; 
     
    128181    { 
    129182        if (!isset($this->cache[$term])) { 
    130             $this->select->execute(array(':name' => $term)); 
    131             $definition = $this->select->fetchColumn(); 
     183            $this->defination->execute(array(':name' => $term)); 
     184            $definition = $this->defination->fetchColumn(); 
    132185            if ($definition) { 
    133186                $this->cache[$term] = $definition; 
     
    140193 
    141194    /** 
     195    * Retrieves the alias for a given definition if it exists from the database 
     196    * and returns it otherwise return FALSE. 
     197    * 
     198    * @param string $term Term to search for 
     199    * @return mixed String containing the definition or FALSE if no alias exist 
     200    */ 
     201    protected function getAlias($definition) 
     202    { 
     203        $this->alias->execute(array(':definition' => $definition)); 
     204        $names = $this->alias->fetchAll(); 
     205        if ($names && count($names) > 0) { 
     206            return $names; 
     207        } else { 
     208            return false; 
     209        } 
     210    } 
     211 
     212    /** 
    142213    * Searches for a definition for a given term, resolves definition aliases, 
    143214    * handles cases of circular references, and sends the definition back to 
     
    153224        } 
    154225 
    155         $message = strtolower($message); 
    156226        $definition = $this->getDefinition($message); 
    157227        $seen = array($message); 
     
    161231                $redirect = $this->getDefinition($definition); 
    162232                if ($redirect) { 
    163                     $seen[] = $definition
     233                    $seen[] = strtolower($definition)
    164234                    if (in_array($redirect, $seen)) { 
     235                        $this->debug('Alias redirection loop detected'); 
     236                        $this->deleteLart($message); 
    165237                        $mod = $this->getIni('gender') == 'F' ? 'her' : 'his'; 
    166                         foreach ($seen as $term) { 
    167                             $this->delete->execute(array('name' => $term)); 
    168                         } 
    169238                        $this->doAction( 
    170239                            $this->event->getArgument(0), 
     
    177246            } while($redirect); 
    178247 
    179             $this->doPrivmsg($this->event->getSource(), $definition); 
    180         } 
    181     } 
    182  
    183     /** 
    184     * Performs a lookup for the contents of CTCP ACTION (/me) commands. 
    185     * 
    186     * @return void 
    187     */ 
    188     public function onAction() 
     248            $definition = trim($definition); 
     249            if (substr($definition, 0, 3) == '/me') { 
     250                $definition = trim(substr($definition, 3)); 
     251                $this->doAction($this->event->getSource(), $definition); 
     252            } else { 
     253                $this->doPrivmsg($this->event->getSource(), $definition); 
     254            } 
     255        } 
     256    } 
     257 
     258    /** 
     259    * Recursively gathers an array of aliases linking to the given term and 
     260    * for each term of that alias 
     261    * 
     262    * @param string $term Term to search for 
     263    * @return array An array of aliases for the given term 
     264    */ 
     265        public function getAliases($term, $recursive = true, $firstRun = true) 
     266        { 
     267                if (!is_array($this->aCache) || $firstRun) { 
     268                        unset($this->aCache); $this->aCache = array(); 
     269                } 
     270 
     271                $alias = $this->getAlias($term); 
     272                if ($alias) { 
     273                    foreach($alias as $key => $value) { 
     274                        $name = $value['name']; 
     275                        if (empty($name)) 
     276                            continue; 
     277                        if (!in_array($name, $this->aCache)) { 
     278                            $this->aCache[] = strtolower($name); 
     279                            if ($recursive) { 
     280                                $this->getAliases($name, true, false); 
     281                            } 
     282                        } 
     283                    } 
     284            } 
     285            if ($firstRun) { 
     286                $cache = $this->aCache; unset($this->aCache); 
     287            return $cache; 
     288            } 
     289        } 
     290 
     291    /** 
     292    * Deletes the given lart and optionally delete all aliases for that lart 
     293    * recursively. 
     294    * 
     295    * @param string $name Term to search for 
     296    * @param bool $recursive Whethere or not to recursively delete aliases 
     297    * @return void 
     298    */ 
     299    function deleteLart($name, $recursive = true) 
     300    { 
     301        if (!$recursive) { 
     302                $this->debug('Removing term: ' . $name); 
     303                $this->delete->execute(array(':name' => $name)); 
     304        } else { 
     305                $aliases = $this->getAliases($name); 
     306                $aliases[] = $name; 
     307                $aliases = array_unique($aliases); 
     308 
     309                $this->debug('Removing terms: ' . implode(', ', $aliases)); 
     310                foreach($aliases as $key => $alias) { 
     311                        $this->delete->execute(array(':name' => $alias)); 
     312                        unset($this->cache[$name]); 
     313                } 
     314        } 
     315    } 
     316 
     317    /** 
     318    * Performs a lookup for the contents of messages to the bot or a channel 
     319    * in which the bot is present. 
     320    * 
     321    * @return void 
     322    */ 
     323    public function onPrivmsg() 
    189324    { 
    190325        if (!$this->db) { 
     
    192327        } 
    193328 
    194         $this->checkLart($this->event->getArgument(1)); 
    195     } 
    196  
    197     /** 
    198     * Performs a lookup for the contents of messages to the bot or a channel 
    199     * in which the bot is present. 
    200     * 
    201     * @return void 
    202     */ 
    203     public function onPrivmsg() 
    204     { 
    205         if (!$this->db) { 
    206             return; 
    207         } 
    208  
    209329        $source = $this->event->getArgument(0); 
    210330        $message = $this->event->getArgument(1); 
    211         $nick = $this->getIni('nick'); 
     331        $nick = preg_quote($this->getIni('nick')); 
     332        $hostmask = $this->event->getHostmask(); 
     333        $timenow = time(); 
    212334        $today = date('md'); 
    213335 
     
    218340        } 
    219341 
    220         if (preg_match('/^(' . $nick . ':?\s*)?(.*?) is (.*)$/i', $message, $match)) { 
     342        if (preg_match('/^(' . $nick . '\s*:?\s+)?lartinfo\s+(.*?)$/i', $message, $match)) { 
     343                list (, $address, $name) = $match; 
     344                $name = trim(strtolower($name)); 
     345                if (!empty($name)) { 
     346                     $this->select->execute(array(':name' => $name)); 
     347                 $info = $this->select->fetch(); 
     348                 if ($info && count($info) > 0) { 
     349                     $name = $info['name']; 
     350                     $desc = $info['definition']; 
     351                     $host = (isset($info['hostmask']) ? substr($info['hostmask'], 0, strpos($info['hostmask'], '!')) : 'N/A'); 
     352                     $time = (isset($info['tstamp']) ? $this->getCountdown(time() -$info['tstamp']) : 'N/A'); 
     353                     $aliases = $this->getAliases($name, false); 
     354                     $aliases = (count($aliases) > 0 ? implode(', ', $aliases) : 'N/A'); 
     355 
     356                     $this->doPrivmsg($this->event->getSource(), 
     357                     'Lart Info -> Term: '.$name.' | Defination: '.$desc.' | User: '.$host.' | Added: '.$time.' ago | Aliases: '.$aliases); 
     358                 } 
     359                 unset($info); 
     360                } 
     361        } else if (preg_match('/^(' . $nick . '\s*:?\s+)?(.*?)\s+is\s+(.*)$/i', $message, $match)) { 
    221362            list (, $address, $name, $definition) = $match; 
    222             if (empty ($address) xor $source[0] == '#') { 
    223                 $name = strtolower($name); 
    224                 $this->replace->execute(array(':name' => $name, ':definition' => $definition)); 
     363            if (!empty($name) && !empty($definition) && (empty($address) xor $source[0] == '#')) { 
     364                $name = trim(strtolower($name)); 
     365                $definition = trim($definition); 
     366 
     367                $this->debug('Replacing term: ' . $name . ' = ' . $definition); 
     368                $this->replace->execute(array(':name' => $name, ':definition' => $definition, ':hostmask' => $hostmask, ':tstamp' => $timenow)); 
    225369                $this->cache[$name] = $definition; 
    226370            } 
    227         } else if (preg_match('/^(' . $nick . ':?\s*)?forget (.*)$/i', $message, $match)) { 
     371        } else if (preg_match('/^(' . $nick . '\s*:?\s+)?forget\s+(.*)$/i', $message, $match)) { 
    228372            list (, $address, $name) = $match; 
    229             if (empty ($address) xor $source[0] == '#') { 
    230                 $name = strtolower($name); 
    231                 $this->delete->execute(array(':name' => $name)); 
    232                 unset($this->cache[$name]); 
     373            if (!empty($name) && (empty($address) xor $source[0] == '#')) { 
     374                $name = trim(strtolower($name)); 
     375 
     376                $this->deleteLart($name); 
    233377            } 
    234378        } else { 
     
    236380        } 
    237381    } 
     382 
     383    /** 
     384    * Performs a lookup for the contents of CTCP ACTION (/me) commands. 
     385    * 
     386    * @return void 
     387    */ 
     388    public function onAction() 
     389    { 
     390        if (!$this->db) { 
     391            return; 
     392        } 
     393 
     394        $this->checkLart('/me ' . $this->event->getArgument(1)); 
     395    } 
    238396}