root/trunk/Phergie/Plugin/Lart.php @ 60

Revision 60, 6.0 KB (checked in by tobias382, 5 years ago)

Fixes #1, #8, #14, #10, #13
* Fixed some parameter parsing issues in the streams driver and Command plugin
* Fixed an issue in the streams driver where quitting would not cause the

connection to be terminated on the client side

* Added automated directory creation to the event handler class
* Added isInChannel() and TYPE_KICK to request event class
* Modified the bootstrap file to use a full path when referencing the Plugin

directory and to include plugin loading debugging messages

* Fixed a bug in the bootstrap file where it would not produce an error when

required configuration settings existed, but were empty

* Cleared default values and unused settings out of the config file
* Made modifications to the fromAdmin method in the AdminCommand? plugin to

optimize performance

* Fixed a bug in the parsing logic in the Acronym plugin and added a check for

instances where the per-IP bandwidth limit has been executed

* Added a check for cases where a server has no MOTD to the Autojoin plugin
* Modified the Drink plugin to filter coffee drinks when scraping data for the

coke table and to remove the profanity filter array from memory once the
init method is done using it

* Added an avogadro alias for the mole fixed karma and added support for

configurable fixed karma for the bot

* Modified the Logging plugin to extend the Command plugin and to use PDO in

place of the standalone SQLite driver

* Modified the Php plugin to use full URLs to function pages rather than the

shorthand version, which does not always resolve to the expected URL

* Renamed the Say plugin to Puppet and added support emulation of CTCP ACTION

commands

* Modified the Url plugin to use the MIME type of the resource in place of

the title in cases where it is not HTML-based

* Fixed an issue with the parsing logic in the onMode handler of the Users

plugin

* Uncommented the onPrivmsg handler and modified it to use the new debug

configuration setting

* Added alternate nick support to the Nickserv plugin
* Removed the CONTRIBUTE file, as its fairly out of date

Line 
1<?php
2
3/**
4* @see Phergie_Event_Handler
5*/
6require_once 'Phergie/Event/Handler.php';
7
8/**
9* Accepts terms and corresponding definitions for storage to a local data
10* source and performs and returns the result of lookups for term definitions
11* as they are requested.
12*/
13class Phergie_Plugin_Lart extends Phergie_Event_Handler
14{
15    /**
16    * Indicates that a local directory is required for this plugin
17    *
18    * @var bool
19    */
20    protected $needsDir = true;
21
22    /**
23    * Date string indicating the last time the cache was emptied
24    *
25    * @var string
26    */
27    protected $flushed;
28
29    /**
30    * Maps terms to corresponding definitions to serve as an in-memory cache
31    *
32    * @var array
33    */
34    protected $cache;
35
36    /**
37    * PDO instance for the database
38    *
39    * @var PDO
40    */
41    protected $db;
42
43    /**
44    * Prepared statement for inserting a new definition into or updating an
45    * existing definition in the database
46    *
47    * @var PDOStatement
48    */
49    protected $replace;
50
51    /**
52    * Prepared statement for selecting the definition of a given term
53    *
54    * @var PDOStatement
55    */
56    protected $select;
57
58    /**
59    * Prepared statement for deleting the definition for a given term
60    *
61    * @var PDOStatement
62    */
63    protected $delete;
64
65    /**
66    * Creates the database if needed, connects to it, and sets up prepared
67    * statements for common operations.
68    *
69    * @return void
70    */
71    public function init()
72    {
73        // Check for the necessary extensions
74        if (!extension_loaded('PDO') || !extension_loaded('pdo_sqlite')) {
75            return;
76        }
77
78        // Initialize the database connection
79        $db = $this->dir . 'lart.db';
80        $create = !file_exists($db);
81        $this->db = new PDO('sqlite:' . $db);
82
83        // Create database tables if necessary
84        if ($create) {
85            $this->db->exec('
86                CREATE TABLE lart ( name VARCHAR(255), definition TEXT );
87                CREATE UNIQUE INDEX lart_name ON lart (name)
88            ');
89        }
90
91        // Initialize prepared statements for common operations
92        $this->replace = $this->db->prepare('
93            REPLACE INTO lart (name, definition) VALUES (:name, :definition)
94        ');
95        $this->select = $this->db->prepare('
96            SELECT definition FROM lart WHERE name = :name
97        ');
98        $this->delete = $this->db->prepare('
99            DELETE FROM lart WHERE name = :name
100        ');
101    }
102
103    /**
104    * Retrieves the definition for a given term if it exists, from the cache
105    * or from the database into the cache if needed, and returns it.
106    *
107    * @param string $term Term to search for
108    * @return mixed String containing the definition or FALSE if no definition
109    *               exists
110    */
111    protected function getDefinition($term)
112    {
113        if (!isset($this->cache[$term])) {
114            $this->select->execute(array(':name' => $term));
115            $definition = $this->select->fetchColumn();
116            if ($definition) {
117                $this->cache[$term] = $definition;
118            } else {
119                return false;
120            }
121        }
122        return $this->cache[$term];
123    }
124
125    /**
126    * Searches for a definition for a given term, resolves definition aliases,
127    * handles cases of circular references, and sends the definition back to
128    * the sender if it exists.
129    *
130    * @param string $message Message containing the term to search for
131    * @return void
132    */
133    private function checkLart($message)
134    {
135        if (strlen($message) > 255) {
136            return;
137        }
138
139        $message = strtolower($message);
140        $definition = $this->getDefinition($message);
141        $seen = array($message);
142
143        if ($definition) {
144            do {
145                $redirect = $this->getDefinition($definition);
146                if ($redirect) {
147                    $seen[] = $definition;
148                    if (in_array($redirect, $seen)) {
149                        foreach ($seen as $term) {
150                            $this->delete->execute(array('name' => $term));
151                        }
152                        $this->doAction(
153                            $this->event->getArgument(0),
154                            'puts her hands over her ears and cries, "Stop confusing me!"'
155                        );
156                        return;
157                    }
158                    $definition = $redirect;
159                }
160            } while($redirect);
161
162            $this->doPrivmsg($this->event->getSource(), $definition);
163        }
164    }
165
166    /**
167    * Performs a lookup for the contents of CTCP ACTION (/me) commands.
168    *
169    * @return void
170    */
171    public function onAction()
172    {
173        $this->checkLart($this->event->getArgument(1));
174    }
175
176    /**
177    * Performs a lookup for the contents of messages to the bot or a channel
178    * in which the bot is present.
179    *
180    * @return void
181    */
182    public function onPrivmsg()
183    {
184        $source = $this->event->getArgument(0);
185        $message = $this->event->getArgument(1);
186        $nick = $this->getIni('nick');
187        $today = date('md');
188
189        if ($this->flushed != $today) {
190            unset($this->cache);
191            $this->flushed = $today;
192            $this->cache = array();
193        }
194
195        if (preg_match('/^(' . $nick . ':?\s*)?(.*) is (.*)$/i', $message, $match)) {
196            list (, $address, $name, $definition) = $match;
197            if (empty ($address) || $source[0] == '#') {
198                $name = strtolower($name);
199                $this->replace->execute(array(':name' => $name, ':definition' => $definition));
200                $this->cache[$name] = $definition;
201            }
202        } else if (preg_match('/^(' . $nick . ':?\s*)?forget (.*)$/i', $message, $match)) {
203            list (, $address, $name) = $match;
204            if (empty ($address) || $source[0] == '#') {
205                $name = strtolower($name);
206                $this->delete->execute(array(':name' => $name));
207                unset($this->cache[$name]);
208            }
209        } else {
210            $this->checkLart($message);
211        }
212    }
213}
Note: See TracBrowser for help on using the browser.