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

Revision 59, 5.9 KB (checked in by tobias382, 5 years ago)

Unstable commit - driver seems to work, most plugins still need testing
* Modified the streams driver to correctly parse the first argument for

PRIVMSG events into an array

* Added a new debug flag setting to the bundled configuration file
* Moved the debug method from the streams driver to the base driver and

modified it to use the new debug flag setting

* Renamed CtcpAction? methods to Action in order to make logic for

construction and parsing of related requests more compatible with the
same for other commands

* Moved Event_Handler::getEventSource to Event_Request::getSource
* Added Event_Handler::tinyUrl convenience method for converting URLs to

their TinyURL equivalents

* Improved docblock coverage in various classes
* Changed all plugin calls to getConnection()->getNick() to getIni('nick')
* Fixed a memory leak in the Command plugin class
* Added alternate nick support to the Nickserv plugin
* Too many more to name!

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