/** * @param string $imdbId * * @return array|bool */ protected function fetchIMDBProperties($imdbId) { $imdb_regex = ['title' => '/<title>(.*?)\\s?\\(.*?<\\/title>/i', 'tagline' => '/taglines:<\\/h4>\\s([^<]+)/i', 'plot' => '/<p itemprop="description">\\s*?(.*?)\\s*?<\\/p>/i', 'rating' => '/"ratingValue">([\\d.]+)<\\/span>/i', 'year' => '/<title>.*?\\(.*?(\\d{4}).*?<\\/title>/i', 'cover' => '/<link rel=\'image_src\' href="(http:\\/\\/ia\\.media-imdb\\.com.+\\.jpg)">/']; $imdb_regex_multi = ['genre' => '/href="\\/genre\\/(.*?)\\?/i', 'language' => '/<a href="\\/language\\/.+?\'url\'>(.+?)<\\/a>/s', 'type' => '/<meta property=\'og\\:type\' content=\\"(.+)\\" \\/>/i']; $buffer = Misc::getUrl(['url' => 'http://' . ($this->imdburl === false ? 'www' : 'akas') . '.imdb.com/title/tt' . $imdbId . '/', 'language' => $this->pdo->getSetting('imdblanguage') != '' ? $this->pdo->getSetting('imdblanguage') : 'en', 'useragent' => 'Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) ' . 'Version/4.0.4 Mobile/7B334b Safari/531.21.102011-10-16 20:23:10', 'foo=bar']); if ($buffer !== false) { $ret = []; foreach ($imdb_regex as $field => $regex) { if (preg_match($regex, $buffer, $matches)) { $match = $matches[1]; $match1 = trim(strip_tags($match)); if ($match1 != '') { $ret[$field] = $match1; } } } $matches = []; foreach ($imdb_regex_multi as $field => $regex) { if (preg_match_all($regex, $buffer, $matches)) { $match2 = $matches[1]; $match3 = array_filter(array_map('trim', $match2)); if (!empty($match3)) { $ret[$field] = $match3; } } } if ($this->currentTitle !== '' && isset($ret['title'])) { // Check the similarity. similar_text($this->currentTitle, $ret['title'], $percent); if ($percent < 40) { if ($this->debug) { $this->debugging->log(get_class(), __FUNCTION__, 'Found (' . $ret['title'] . ') from IMDB, but it\'s only ' . $percent . '% similar to (' . $this->currentTitle . ')', Logger::LOG_INFO); } return false; } } // Actors. if (preg_match('/<table class="cast_list">(.+?)<\\/table>/s', $buffer, $hit)) { if (preg_match_all('/<span class="itemprop" itemprop="name">\\s*(.+?)\\s*<\\/span>/i', $hit[0], $results, PREG_PATTERN_ORDER)) { $results[1] = array_filter(array_map('trim', $results[1])); $ret['actors'] = $results[1]; } } // Directors. if (preg_match('/itemprop="directors?".+?<\\/div>/s', $buffer, $hit)) { if (preg_match_all('/"name">(.*?)<\\/span>/is', $hit[0], $results, PREG_PATTERN_ORDER)) { $results[1] = array_filter(array_map('trim', $results[1])); $ret['director'] = $results[1]; } } if ($this->echooutput && isset($ret['title'])) { $this->pdo->log->doEcho($this->pdo->log->headerOver("IMDb Found ") . $this->pdo->log->primaryOver($ret['title']), true); } return $ret; } return false; }
/** * Download an article body (an article without the header). * * @param string $groupName The name of the group the article is in. * @param mixed $identifier (string) The message-ID of the article to download. * (int) The article number. * * @return string On success : (string) The article's body. * On failure : (object) PEAR_Error. * * @access protected */ protected function _getMessage($groupName, $identifier) { // Make sure the requested group is already selected, if not select it. if (parent::group() !== $groupName) { // Select the group. $summary = $this->selectGroup($groupName); // If there was an error selecting the group, return PEAR error object. if ($this->isError($summary)) { if ($this->_debugBool) { $this->_debugging->log(get_class(), __FUNCTION__, $summary->getMessage(), Logger::LOG_WARNING); } return $summary; } } // Check if this is an article number or message-id. if (!is_numeric($identifier)) { // It's a message-id so check if it has the triangular brackets. $identifier = $this->_formatMessageID($identifier); } // Tell the news server we want the body of an article. $response = $this->_sendCommand('BODY ' . $identifier); if ($this->isError($response)) { return $response; } $body = ''; switch ($response) { // 222, RFC977: 'n <a> article retrieved - body follows' case NET_NNTP_PROTOCOL_RESPONSECODE_BODY_FOLLOWS: // Continue until connection is lost while (!feof($this->_socket)) { // Retrieve and append up to 1024 characters from the server. $line = fgets($this->_socket, 1024); // If the socket is empty/ an error occurs, false is returned. // Since the socket is blocking, the socket should not be empty, so it's definitely an error. if ($line === false) { return $this->throwError('Failed to read line from socket.', null); } // Check if the line terminates the text response. if ($line === ".\r\n") { if ($this->_debugBool) { $this->_debugging->log(get_class(), __FUNCTION__, 'Fetched body for article ' . $identifier, Logger::LOG_INFO); } // Attempt to yEnc decode and return the body. return $this->_decodeIgnoreYEnc($body); } // Check for line that starts with double period, remove one. if ($line[0] === '.' && $line[1] === '.') { $line = substr($line, 1); } // Add the line to the rest of the lines. $body .= $line; } return $this->throwError('End of stream! Connection lost?', null); default: return $this->_handleErrorResponse($response); } }
/** * Log / Echo message. * * @param string $message Message to log. * @param string $method Method that called this. * @param int $level Logger severity level constant. * @param string $color ColorCLI method name. */ private function log($message, $method, $level, $color) { if ($this->_echoCLI) { $this->_colorCLI->doEcho($this->_colorCLI->{$color}($message . ' [' . get_class() . "::{$method}]"), true); } if ($this->_debug) { $this->_debugging->log(get_class(), $method, $message, $level); } }
/** * Log / Echo message. * * @param string $message Message to log. * @param string $method Method that called this. * @param int $level Logger severity level constant. * @param string $color ColorCLI method name. */ private function log($message, $method, $level, $color) { if ($this->_echoCLI) { $this->_colorCLI->doEcho($this->_colorCLI->{$color}($message), true); } if ($this->_debug) { $this->_debugging->log('Binaries', $method, $message, $level); } }
/** * Safe backfill using posts. Going back to a date specified by the user on the site settings. * This does 1 group for x amount of parts until it reaches the date. * * @param string $articles * * @return void */ public function safeBackfill($articles = '') { $groupname = $this->pdo->queryOneRow(sprintf(' SELECT name FROM groups WHERE first_record_postdate BETWEEN %s AND NOW() AND backfill = 1 ORDER BY name ASC', $this->pdo->escapeString($this->_safeBackFillDate))); if (!$groupname) { $dMessage = 'No groups to backfill, they are all at the target date ' . $this->_safeBackFillDate . ", or you have not enabled them to be backfilled in the groups page.\n"; if ($this->_debug) { $this->_debugging->log(get_class(), __FUNCTION__, $dMessage, Logger::LOG_FATAL); } exit($dMessage); } else { $this->backfillAllGroups($groupname['name'], $articles); } }
/** * Attempt to get a better name from a par2 file and categorize the release. * * @note Called from NZBContents.php * * @param string $messageID MessageID from NZB file. * @param int $relID ID of the release. * @param int $groupID Group ID of the release. * @param \nzedb\NNTP $nntp Class NNTP * @param int $show Only show result or apply iy. * * @return bool */ public function parsePAR2($messageID, $relID, $groupID, &$nntp, $show) { if ($messageID === '') { return false; } $query = $this->pdo->queryOneRow(sprintf(' SELECT id, group_id, categoryid, name, searchname, UNIX_TIMESTAMP(postdate) AS post_date, id AS releaseid FROM releases WHERE isrenamed = 0 AND id = %d', $relID)); if ($query === false) { return false; } // Only get a new name if the category is OTHER. $foundName = true; if (!in_array((int) $query['categoryid'], [Category::CAT_BOOKS_OTHER, Category::CAT_GAME_OTHER, Category::CAT_MOVIE_OTHER, Category::CAT_MUSIC_OTHER, Category::CAT_PC_PHONE_OTHER, Category::CAT_TV_OTHER, Category::CAT_OTHER_HASHED, Category::CAT_XXX_OTHER, Category::CAT_MISC])) { $foundName = false; } // Get the PAR2 file. $par2 = $nntp->getMessages($this->groups->getByNameByID($groupID), $messageID, $this->alternateNNTP); if ($nntp->isError($par2)) { return false; } // Put the PAR2 into Par2Info, check if there's an error. $this->_par2Info->setData($par2); if ($this->_par2Info->error) { return false; } // Get the file list from Par2Info. $files = $this->_par2Info->getFileList(); if ($files !== false && count($files) > 0) { $filesAdded = 0; // Loop through the files. foreach ($files as $file) { if (!isset($file['name'])) { continue; } // If we found a name and added 10 files, stop. if ($foundName === true && $filesAdded > 10) { break; } if ($this->addpar2) { // Add to release files. if ($filesAdded < 11 && $this->pdo->queryOneRow(sprintf(' SELECT id FROM release_files WHERE releaseid = %d AND name = %s', $relID, $this->pdo->escapeString($file['name']))) === false) { // Try to add the files to the DB. if ($this->releaseFiles->add($relID, $file['name'], $file['size'], $query['post_date'], 0)) { $filesAdded++; } } } else { $filesAdded++; } // Try to get a new name. if ($foundName === false) { $query['textstring'] = $file['name']; if ($this->nameFixer->checkName($query, 1, 'PAR2, ', 1, $show) === true) { $foundName = true; } } } // If we found some files. if ($filesAdded > 0) { $this->debugging->log('PostProcess', 'parsePAR2', 'Added ' . $filesAdded . ' release_files from PAR2 for ' . $query['searchname'], Logger::LOG_INFO); // Update the file count with the new file count + old file count. $this->pdo->queryExec(sprintf(' UPDATE releases SET rarinnerfilecount = rarinnerfilecount + %d WHERE id = %d', $filesAdded, $relID)); } if ($foundName === true) { return true; } } return false; }