db = new PDO('sqlite:' . $this->dir . 'norris.db'); if (!$this->db) { return; } // Populate the database if necessary // Checks to see if the table exists, if not create it if ($this->findChuckNorris()) { // Retrieves a list of Chuck Norris facts if ($this->getChuckNorris()) { // Inserts all the retrieved facts into the database $this->feedChuckNorris(); } } } catch (PDOException $e) { } $this->chance = intval($this->chance); $this->floodCheck = intval($this->floodCheck); } /** * Returns whether or not the plugin's dependencies are met. * * @param Phergie_Driver_Abstract $client Client instance * @param array $plugins List of short names for plugins that the * bootstrap file intends to instantiate * @see Phergie_Plugin_Abstract_Base::checkDependencies() * @return bool TRUE if dependencies are met, FALSE otherwise */ public static function checkDependencies(Phergie_Driver_Abstract $client, array $plugins) { $errors = array(); if (!extension_loaded('PDO')) { $errors[] = 'PDO php extension is required'; } if (!extension_loaded('pdo_sqlite')) { $errors[] = 'pdo_sqlite php extension is required'; } return empty($errors) ? true : $errors; } /** * Connects to the Chuck Norris facts page and scrapes the facts from it * * @return bool True is successful, else false */ private function getChuckNorris($doCrawl = true) { // The current page to retrieve $page = trim($this->factHost . $this->crawlPage); $this->debug('Retrieving page ' . $this->crawlNum . ' => ' . $this->crawlPage); $contents = @file_get_contents($page); if ($contents !== false) { $this->debug('Parsing page ' . $this->crawlNum . ' => ' . $this->crawlPage); preg_match_all('#
  • \s*([^<]+)\s*(?:
    \s* )?<\/li>#im', $contents, $matches); // Format the returned facts to be stored later in a database foreach($matches[1] as $key => $fact) { $fact = trim(preg_replace("/( |[\r\n\s])+/", ' ', html_entity_decode($fact, ENT_QUOTES))); $fact = str_replace(array('’','“','”','…'), array("'",'"','"','...'), $fact); if (!empty($fact)) { $this->norrisFacts[] = $fact; } } // If crawling is set, crawl and scrape the remaining fact pages if ($doCrawl) { preg_match_all('##im', $contents, $matches); // Make sure we don't have any duplicates $pages = array_unique(array_combine($matches[2], $matches[1])); ksort($pages, SORT_NUMERIC); // Start the crawling processs foreach($pages as $page => $url) { if ($page > $this->crawlNum) { $this->crawlNum = $page; $this->crawlPage = $url; // Return false if there was a problem with the crawling if (!$this->getChuckNorris(false)) { return false; } } } } unset($contents); return true; } $this->debug('Could not retrieve page ' . $this->crawlNum . ' => ' . $this->crawlPage); return false; } /** * Determines if the chuckfacts does not exist or empty * * @return bool TRUE if the table does not exist or is empty, FALSE * otherwise */ private function findChuckNorris() { if (!$this->db) { return false; } // Checks to see if the chuckfacts table exists $table = $this->db->query('SELECT COUNT(*) FROM sqlite_master WHERE name = ' . $this->db->quote('chuckfacts'))->fetchColumn(); // If the table doesn't exist, create them and return true for the next step if (!$table) { $this->debug('Creating the database schema'); $this->db->exec('CREATE TABLE chuckfacts (facts VARCHAR(255))'); $this->db->exec('CREATE UNIQUE INDEX chuckfacts_name ON chuckfacts (facts)'); return true; } // Checks to see if anything is stored in the chuckfacts table return !$this->db->query('SELECT COUNT(*) FROM chuckfacts')->fetchColumn(); } /** * Populates the chuckfacts table with the given array of facts * * @return bool True is successful, else false */ private function feedChuckNorris() { if (!$this->db) { return false; } // Check to see if there are any facts to insert if (count($this->norrisFacts) > 0) { $stmt = $this->db->prepare('INSERT INTO chuckfacts (facts) VALUES (:fact)'); $this->db->beginTransaction(); // Go through the facs and insert them if available foreach(array_unique($this->norrisFacts) as $fact) { if (!empty($fact)) { $stmt->execute(array(':fact' => $fact)); $this->debug('Inserted fact: ' . $fact); } } $this->db->commit(); // Unset the facts array to free up memory unset($this->norrisFacts); return true; } return false; } /** * Returns a random fact from the chuckfacts table. * * @return string A random fact */ private function praiseChuckNorris() { if (!$this->db) { return; } return $this->db->query('SELECT facts FROM chuckfacts ORDER BY Random() LIMIT 1')->fetchColumn(); } /** * Parses incoming messages for the word "Chuck Norris" and respond with a * random Chuck Norris fact retrieved from the Chuck Norris fact page. * * @return void */ public function onPrivmsg() { if (!$this->db) { return; } $source = $this->event->getSource(); $message = $this->event->getArgument(1); // Check to see if the message includes the word Chuck Norris. If so, check to see if // it was a bot request by checking for Fact: at the begiining and also do a floodpro check if (preg_match('{^('.preg_quote($this->getIni('nick')).'\s*[:,>]?\s+)?\s*(chuck\s+norris)}ix', $message, $m) && strtolower(substr($message, 0, 5)) != 'fact:' && ($source[0] != '#' || (!empty($m[1]) || $this->chance <= 0 || $this->chance >= 100 || mt_rand(1, 100) < $this->chance) && ($this->floodCheck <= 0 || !isset($this->floodCache[$source]) || ($this->floodCache[$source] < (time() - $this->floodCheck))))) { $fact = $this->praiseChuckNorris(); if (!empty($fact)) { $this->doPrivmsg($source, 'Fact: ' . $fact); if ($source[0] == '#') { $this->floodCache[$source] = time(); } unset($m, $fact); } } } /** * Parses incoming CTCP request for the word "Chuck Norris" and respond with * a random Chuck Norris fact retrieved from the Chuck Norris fact page. * * @return void */ public function onCtcp() { $source = $this->event->getSource(); $ctcp = $this->event->getArgument(1); if (!$this->db) { return; } if (preg_match('{chuck[\s_+-]*norris}ix', $ctcp, $m)) { $fact = $this->praiseChuckNorris(); if (!empty($fact)) { $this->doCtcpReply($source, 'CHUCKNORRIS', $fact); } } } }