From 62510ebdc7876f57c233979eac47308d18131cdf Mon Sep 17 00:00:00 2001 From: DariusIII Date: Mon, 18 Mar 2019 13:41:07 +0100 Subject: [PATCH] Revert changes in PPA --- .../processing/post/ProcessAdditional.php | 2178 +++++++++-------- Changelog | 1 - 2 files changed, 1117 insertions(+), 1062 deletions(-) diff --git a/Blacklight/processing/post/ProcessAdditional.php b/Blacklight/processing/post/ProcessAdditional.php index 756f1e146..a547f3d72 100755 --- a/Blacklight/processing/post/ProcessAdditional.php +++ b/Blacklight/processing/post/ProcessAdditional.php @@ -28,6 +28,7 @@ use FFMpeg\Coordinate\TimeCode; use FFMpeg\Format\Audio\Vorbis; use FFMpeg\Coordinate\Dimension; use dariusiii\rarinfo\ArchiveInfo; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\File; use FFMpeg\Filters\Video\ResizeFilter; @@ -41,6 +42,11 @@ class ProcessAdditional */ public const maxCompressedFilesToCheck = 10; + /** + * @var \PDO + */ + public $pdo; + /** * @var bool */ @@ -53,7 +59,6 @@ class ProcessAdditional /** * Count of releases to work on. - * * @var int */ protected $_totalReleases; @@ -70,7 +75,6 @@ class ProcessAdditional /** * List of files with sizes/etc contained in the NZB. - * * @var array */ protected $_nzbContents; @@ -262,106 +266,88 @@ class ProcessAdditional /** * Have we created a video file for the current release? - * * @var bool */ protected $_foundVideo; /** * Have we found MediaInfo data for a Video for the current release? - * * @var bool */ protected $_foundMediaInfo; /** * Have we found MediaInfo data for a Audio file for the current release? - * * @var bool */ protected $_foundAudioInfo; /** * Have we created a short Audio file sample for the current release? - * * @var bool */ protected $_foundAudioSample; /** * Extension of the found audio file (MP3/FLAC/etc). - * * @var string */ protected $_AudioInfoExtension; /** * Have we downloaded a JPG file for the current release? - * * @var bool */ protected $_foundJPGSample; /** * Have we created a Video JPG image sample for the current release? - * * @var bool */ protected $_foundSample; /** * Have we found PAR2 info on this release? - * * @var bool */ protected $_foundPAR2Info; /** * Message ID's for found content to download. - * * @var array */ protected $_sampleMessageIDs; - protected $_JPGMessageIDs; - protected $_MediaInfoMessageIDs; - protected $_AudioInfoMessageIDs; - protected $_RARFileMessageIDs; /** * Password status of the current release. - * * @var array */ protected $_passwordStatus; /** * Does the current release have a password? - * * @var bool */ protected $_releaseHasPassword; /** * Does the current release have an NFO file? - * * @var bool */ protected $_releaseHasNoNFO; /** * Name of the current release's usenet group. - * * @var string */ protected $_releaseGroupName; /** * Number of file information added to DB (from rar/zip/par2 contents). - * * @var int */ protected $_addedFileInfo; @@ -369,28 +355,24 @@ class ProcessAdditional /** * Number of file information we found from RAR/ZIP. * (if some of it was already in DB, this count goes up, while the count above does not). - * * @var int */ protected $_totalFileInfo; /** * How many compressed (rar/zip) files have we checked. - * * @var int */ protected $_compressedFilesChecked; /** * Should we download the last rar? - * * @var bool */ protected $_fetchLastFiles; /** * Are we downloading the last rar? - * * @var bool */ protected $_reverse; @@ -400,37 +382,6 @@ class ProcessAdditional */ protected $sphinx; - /** - * @var string Main temp path to work on. - */ - protected $_mainTmpPath; - - /** - * @var string Temp path for current release. - */ - protected $tmpPath; - - /** - * Current file we are working on inside a NZB. - * - * @var array - */ - protected $_currentNZBFile; - - /** - * Does the current NZB contain a compressed (RAR/ZIP) file? - * - * @var bool - */ - protected $_NZBHasCompressedFile; - - /** - * List of message-id's we have tried for rar/zip files. - * - * @var array - */ - protected $_triedCompressedMids = []; - /** * @var \FFMpeg\FFMpeg */ @@ -450,22 +401,21 @@ class ProcessAdditional * ProcessAdditional constructor. * * @param array $options - * * @throws \Exception */ public function __construct(array $options = []) { $defaults = [ - 'Echo' => false, - 'Categorize' => null, - 'Groups' => null, - 'NameFixer' => null, - 'Nfo' => null, - 'NNTP' => null, - 'NZB' => null, + 'Echo' => false, + 'Categorize' => null, + 'Groups' => null, + 'NameFixer' => null, + 'Nfo' => null, + 'NNTP' => null, + 'NZB' => null, 'ReleaseExtra' => null, 'ReleaseImage' => null, - 'Settings' => null, + 'Settings' => null, 'SphinxSearch' => null, ]; $options += $defaults; @@ -477,10 +427,7 @@ class ProcessAdditional $this->_nzb = $options['NZB'] ?? new NZB(); $this->_archiveInfo = new ArchiveInfo(); $this->_categorize = $options['Categorize'] ?? new Categorize(); - $this->_nameFixer = $options['NameFixer'] ?? new NameFixer([ - 'Echo' => $this->_echoCLI, - 'Categorize' => $this->_categorize, - ]); + $this->_nameFixer = $options['NameFixer'] ?? new NameFixer(['Echo' =>$this->_echoCLI, 'Categorize' => $this->_categorize]); $this->_releaseExtra = $options['ReleaseExtra'] ?? new ReleaseExtra(); $this->_releaseImage = $options['ReleaseImage'] ?? new ReleaseImage(); $this->_par2Info = new Par2Info(); @@ -514,30 +461,40 @@ class ProcessAdditional $this->_killString = '"'; if (Settings::settingValue('apps..timeoutpath') !== '' && (int) Settings::settingValue('..timeoutseconds') > 0) { - $this->_killString = ('"'.Settings::settingValue('apps..timeoutpath').'" --foreground --signal=KILL '.Settings::settingValue('..timeoutseconds').' "'); + $this->_killString = ( + '"'.Settings::settingValue('apps..timeoutpath'). + '" --foreground --signal=KILL '. + Settings::settingValue('..timeoutseconds').' "' + ); } $this->_showCLIReleaseID = (PHP_BINARY.' '.__DIR__.DS.'ProcessAdditional.php ReleaseID: '); // Maximum amount of releases to fetch per run. - $this->_queryLimit = (Settings::settingValue('..maxaddprocessed') !== '') ? (int) Settings::settingValue('..maxaddprocessed') : 25; + $this->_queryLimit = + (Settings::settingValue('..maxaddprocessed') !== '') ? (int) Settings::settingValue('..maxaddprocessed') : 25; // Maximum message ID's to download per file type in the NZB (video, jpg, etc). - $this->_segmentsToDownload = (Settings::settingValue('..segmentstodownload') !== '') ? (int) Settings::settingValue('..segmentstodownload') : 2; + $this->_segmentsToDownload = + (Settings::settingValue('..segmentstodownload') !== '') ? (int) Settings::settingValue('..segmentstodownload') : 2; // Maximum message ID's to download for a RAR file. - $this->_maximumRarSegments = (Settings::settingValue('..maxpartsprocessed') !== '') ? (int) Settings::settingValue('..maxpartsprocessed') : 3; + $this->_maximumRarSegments = + (Settings::settingValue('..maxpartsprocessed') !== '') ? (int) Settings::settingValue('..maxpartsprocessed') : 3; // Maximum RAR files to check for a password before stopping. - $this->_maximumRarPasswordChecks = (Settings::settingValue('..passchkattempts') !== '') ? (int) Settings::settingValue('..passchkattempts') : 1; + $this->_maximumRarPasswordChecks = + (Settings::settingValue('..passchkattempts') !== '') ? (int) Settings::settingValue('..passchkattempts') : 1; $this->_maximumRarPasswordChecks = ($this->_maximumRarPasswordChecks < 1 ? 1 : $this->_maximumRarPasswordChecks); // Maximum size of releases in GB. - $this->_maxSize = (Settings::settingValue('..maxsizetopostprocess') !== '') ? (int) Settings::settingValue('..maxsizetopostprocess') : 100; + $this->_maxSize = + (Settings::settingValue('..maxsizetopostprocess') !== '') ? (int) Settings::settingValue('..maxsizetopostprocess') : 100; $this->_maxSize = ($this->_maxSize > 0 ? ('AND r.size < '.($this->_maxSize * 1073741824)) : ''); // Minimum size of releases in MB. - $this->_minSize = (Settings::settingValue('..minsizetopostprocess') !== '') ? (int) Settings::settingValue('..minsizetopostprocess') : 100; + $this->_minSize = + (Settings::settingValue('..minsizetopostprocess') !== '') ? (int) Settings::settingValue('..minsizetopostprocess') : 100; $this->_minSize = ($this->_minSize > 0 ? ('AND r.size > '.($this->_minSize * 1048576)) : ''); // Use the alternate NNTP provider for downloading Message-ID's ? @@ -558,7 +515,10 @@ class ProcessAdditional $this->_processJPGSample = (int) Settings::settingValue('..processjpg') !== 0; $this->_processMediaInfo = Settings::settingValue('apps..mediainfopath') !== ''; $this->_processAudioInfo = $this->_processMediaInfo; - $this->_processPasswords = (((int) Settings::settingValue('..checkpasswordedrar') !== 0) && Settings::settingValue('apps..unrarpath') !== ''); + $this->_processPasswords = ( + ((int) Settings::settingValue('..checkpasswordedrar') !== 0) && + Settings::settingValue('apps..unrarpath') !== '' + ); $this->_audioSavePath = NN_COVERS.'audiosample'.DS; @@ -576,44 +536,6 @@ class ProcessAdditional $this->_clearMainTmpPath(); } - /** - * Clear out old folders/files from the main temp folder. - */ - protected function _clearMainTmpPath(): void - { - if ($this->_mainTmpPath !== '') { - $this->_recursivePathDelete($this->_mainTmpPath, // These are folders we don't want to delete. - [ - // This is the actual temp folder. - $this->_mainTmpPath, - ]); - } - } - - /** - * Deletes files and folders recursively. - * - * @param string $path Path to a folder or file. - * @param string[] $ignoredFolders array with paths to folders to ignore. - * - * @void - */ - protected function _recursivePathDelete($path, $ignoredFolders = []): void - { - if (File::isDirectory($path)) { - if (\in_array($path, $ignoredFolders, false)) { - return; - } - foreach (File::allFiles($path) as $file) { - $this->_recursivePathDelete($file, $ignoredFolders); - } - - File::deleteDirectory($path); - } elseif (File::isFile($path)) { - File::delete($path); - } - } - /** * @param string $groupID * @param string $guidChar @@ -637,9 +559,18 @@ class ProcessAdditional } /** - * @param $guidChar + * @var string Main temp path to work on. + */ + protected $_mainTmpPath; + + /** + * @var string Temp path for current release. + */ + protected $tmpPath; + + /** + * @param $guidChar * @param string $groupID - * * @throws \RuntimeException * @throws \Exception */ @@ -675,6 +606,23 @@ class ProcessAdditional $this->tmpPath = $this->_mainTmpPath; } + /** + * Clear out old folders/files from the main temp folder. + */ + protected function _clearMainTmpPath(): void + { + if ($this->_mainTmpPath !== '') { + $this->_recursivePathDelete( + $this->_mainTmpPath, + // These are folders we don't want to delete. + [ + // This is the actual temp folder. + $this->_mainTmpPath, + ] + ); + } + } + /** * Get all releases that need to be processed. * @@ -685,10 +633,11 @@ class ProcessAdditional */ protected function _fetchReleases($groupID, &$guidChar): void { - $releasesQuery = Release::query()->where('releases.nzbstatus', '=', 1)->whereBetween('releases.passwordstatus', [ - -6, - -1, - ])->where('releases.haspreview', '=', -1)->where('categories.disablepreview', '=', 0); + $releasesQuery = Release::query() + ->where('releases.nzbstatus', '=', 1) + ->whereBetween('releases.passwordstatus', [-6, -1]) + ->where('releases.haspreview', '=', -1) + ->where('categories.disablepreview', '=', 0); if ($this->_maxSize > 0) { $releasesQuery->where('releases.size', '<', $this->_maxSize * 1073741824); } @@ -701,21 +650,11 @@ class ProcessAdditional if (! empty($guidChar)) { $releasesQuery->where('releases.leftguid', $guidChar); } - $releasesQuery->select([ - 'releases.id', - 'releases.id as releases_id', - 'releases.guid', - 'releases.name', - 'releases.size', - 'releases.groups_id', - 'releases.nfostatus', - 'releases.fromname', - 'releases.completion', - 'releases.categories_id', - 'releases.searchname', - 'releases.predb_id', - 'categories.disablepreview', - ])->leftJoin('categories', 'categories.id', '=', 'releases.categories_id')->orderBy('releases.passwordstatus')->orderByDesc('releases.postdate')->limit($this->_queryLimit); + $releasesQuery->select(['releases.id', 'releases.id as releases_id', 'releases.guid', 'releases.name', 'releases.size', 'releases.groups_id', 'releases.nfostatus', 'releases.fromname', 'releases.completion', 'releases.categories_id', 'releases.searchname', 'releases.predb_id', 'categories.disablepreview']) + ->leftJoin('categories', 'categories.id', '=', 'releases.categories_id') + ->orderBy('releases.passwordstatus') + ->orderByDesc('releases.postdate') + ->limit($this->_queryLimit); $this->_releases = $releasesQuery->get(); $this->_totalReleases = $this->_releases->count(); @@ -729,22 +668,18 @@ class ProcessAdditional protected function _echoDescription(): void { if ($this->_totalReleases > 1 && $this->_echoCLI) { - $this->_echo(PHP_EOL.'Additional post-processing, started at: '.now()->format('D M d, Y G:i a').PHP_EOL.'Downloaded: (xB) = yEnc article, f= Failed ;Processing: z = ZIP file, r = RAR file'.PHP_EOL.'Added: s = Sample image, j = JPEG image, A = Audio sample, a = Audio MediaInfo, v = Video sample'.PHP_EOL.'Added: m = Video MediaInfo, n = NFO, ^ = File details from inside the RAR/ZIP', 'header'); - } - } - - /** - * Echo a string to CLI. - * - * @param string $string String to echo. - * @param string $type Method type. - * - * @void - */ - protected function _echo($string, $type): void - { - if ($this->_echoCLI) { - (new ColorCLI())->$type($string); + $this->_echo( + PHP_EOL. + 'Additional post-processing, started at: '. + now()->format('D M d, Y G:i a'). + PHP_EOL. + 'Downloaded: (xB) = yEnc article, f= Failed ;Processing: z = ZIP file, r = RAR file'. + PHP_EOL. + 'Added: s = Sample image, j = JPEG image, A = Audio sample, a = Audio MediaInfo, v = Video sample'. + PHP_EOL. + 'Added: m = Video MediaInfo, n = NFO, ^ = File details from inside the RAR/ZIP', + 'header' + ); } } @@ -757,7 +692,11 @@ class ProcessAdditional protected function _processReleases(): void { foreach ($this->_releases as $this->_release) { - $this->_echo(PHP_EOL.'['.$this->_release->id.']['.human_filesize($this->_release->size, 1).']', 'primaryOver'); + $this->_echo( + PHP_EOL.'['.$this->_release->id.']['. + human_filesize($this->_release->size, 1).']', + 'primaryOver' + ); cli_set_process_title($this->_showCLIReleaseID.$this->_release->id); @@ -783,7 +722,8 @@ class ProcessAdditional $bookFlood = true; } - if ($this->_processPasswords || $this->_processThumbnails || $this->_processMediaInfo || $this->_processAudioInfo || $this->_processVideo) { + if ($this->_processPasswords || $this->_processThumbnails || $this->_processMediaInfo || $this->_processAudioInfo || $this->_processVideo + ) { // Process usenet Message-ID downloads. $this->_processMessageIDDownloads(); @@ -816,6 +756,30 @@ class ProcessAdditional } } + /** + * Deletes files and folders recursively. + * + * @param string $path Path to a folder or file. + * @param string[] $ignoredFolders array with paths to folders to ignore. + * + * @void + */ + protected function _recursivePathDelete($path, $ignoredFolders = []): void + { + if (File::isDirectory($path)) { + if (\in_array($path, $ignoredFolders, false)) { + return; + } + foreach (File::allFiles($path) as $file) { + $this->_recursivePathDelete($file, $ignoredFolders); + } + + File::deleteDirectory($path); + } elseif (File::isFile($path)) { + File::delete($path); + } + } + /** * Create a temporary storage folder for the current release. * @@ -836,18 +800,6 @@ class ProcessAdditional return true; } - /** - * Decrement password status for the current release. - * - * @return false - */ - protected function _decrementPasswordStatus(): bool - { - Release::whereId($this->_release->id)->decrement('passwordstatus'); - - return false; - } - /** * Get list of contents inside a release's NZB file. * @@ -883,6 +835,18 @@ class ProcessAdditional return true; } + /** + * Decrement password status for the current release. + * + * @return false + */ + protected function _decrementPasswordStatus(): bool + { + Release::whereId($this->_release->id)->decrement('passwordstatus'); + + return false; + } + /** * @return bool * @throws \Exception @@ -895,40 +859,16 @@ class ProcessAdditional } /** - * Reset some variables for the current release. + * Current file we are working on inside a NZB. + * @var array */ - protected function _resetReleaseStatus(): void - { - // Only process for samples, previews and images if not disabled. - $this->_foundVideo = $this->_processVideo ? false : true; - $this->_foundMediaInfo = $this->_processMediaInfo ? false : true; - $this->_foundAudioInfo = $this->_processAudioInfo ? false : true; - $this->_foundAudioSample = $this->_processAudioSample ? false : true; - $this->_foundJPGSample = $this->_processJPGSample ? false : true; - $this->_foundSample = $this->_processThumbnails ? false : true; - $this->_foundPAR2Info = false; + protected $_currentNZBFile; - $this->_passwordStatus = [Releases::PASSWD_NONE]; - $this->_releaseHasPassword = false; - - $this->_releaseGroupName = UsenetGroup::getNameByID($this->_release->groups_id); - - $this->_releaseHasNoNFO = false; - // Make sure we don't already have an nfo. - if ((int) $this->_release->nfostatus !== 1) { - $this->_releaseHasNoNFO = true; - } - - $this->_NZBHasCompressedFile = false; - - $this->_sampleMessageIDs = $this->_JPGMessageIDs = $this->_MediaInfoMessageIDs = []; - $this->_AudioInfoMessageIDs = $this->_RARFileMessageIDs = []; - $this->_AudioInfoExtension = ''; - - $this->_addedFileInfo = 0; - $this->_totalFileInfo = 0; - $this->_compressedFilesChecked = 0; - } + /** + * Does the current NZB contain a compressed (RAR/ZIP) file? + * @var bool + */ + protected $_NZBHasCompressedFile; /** * Process the files inside the NZB, find Message-ID's to download. @@ -947,12 +887,18 @@ class ProcessAdditional } // Check if it's a rar/zip. - if (! $this->_NZBHasCompressedFile && preg_match('/\.(part\d+|[r|z]\d+|rar|0+|0*10?|zipr\d{2,3}|zipx?)(\s*\.rar)*($|[ ")\]-])|"[a-f0-9]{32}\.[1-9]\d{1,2}".*\(\d+\/\d{2,}\)$/i', $this->_currentNZBFile['title'])) { + if (! $this->_NZBHasCompressedFile && + preg_match( + '/\.(part\d+|[r|z]\d+|rar|0+|0*10?|zipr\d{2,3}|zipx?)(\s*\.rar)*($|[ ")\]-])|"[a-f0-9]{32}\.[1-9]\d{1,2}".*\(\d+\/\d{2,}\)$/i', + $this->_currentNZBFile['title'] + ) + ) { $this->_NZBHasCompressedFile = true; } // Look for a video sample, make sure it's not an image. - if ($this->_processThumbnails && empty($this->_sampleMessageIDs) && stripos($this->_currentNZBFile['title'], 'sample') !== false && ! preg_match('/\.jpe?g$/i', $this->_currentNZBFile['title']) && isset($this->_currentNZBFile['segments'])) { + if ($this->_processThumbnails && empty($this->_sampleMessageIDs) && stripos($this->_currentNZBFile['title'], 'sample') !== false && ! preg_match('/\.jpe?g$/i', $this->_currentNZBFile['title']) && isset($this->_currentNZBFile['segments']) + ) { // Get the amount of segments for this file. $segCount = (\count($this->_currentNZBFile['segments']) - 1); // If it's more than 1 try to get up to the site specified value of segments. @@ -965,7 +911,8 @@ class ProcessAdditional } // Look for a JPG picture, make sure it's not a CD cover. - if ($this->_processJPGSample && empty($this->_JPGMessageIDs) && ! preg_match('/flac|lossless|mp3|music|inner-sanctum|sound/i', $this->_releaseGroupName) && preg_match('/\.jpe?g[. ")\]]/i', $this->_currentNZBFile['title']) && isset($this->_currentNZBFile['segments'])) { + if ($this->_processJPGSample && empty($this->_JPGMessageIDs) && ! preg_match('/flac|lossless|mp3|music|inner-sanctum|sound/i', $this->_releaseGroupName) && preg_match('/\.jpe?g[. ")\]]/i', $this->_currentNZBFile['title']) && isset($this->_currentNZBFile['segments']) + ) { // Get the amount of segments for this file. $segCount = (\count($this->_currentNZBFile['segments']) - 1); // If it's more than 1 try to get up to the site specified value of segments. @@ -978,12 +925,14 @@ class ProcessAdditional } // Look for a video file, make sure it's not a sample, for MediaInfo. - if ($this->_processMediaInfo && empty($this->_MediaInfoMessageIDs) && stripos($this->_currentNZBFile['title'], 'sample') !== false && preg_match('/'.$this->_videoFileRegex.'[. ")\]]/i', $this->_currentNZBFile['title']) && isset($this->_currentNZBFile['segments'][0])) { + if ($this->_processMediaInfo && empty($this->_MediaInfoMessageIDs) && stripos($this->_currentNZBFile['title'], 'sample') !== false && preg_match('/'.$this->_videoFileRegex.'[. ")\]]/i', $this->_currentNZBFile['title']) && isset($this->_currentNZBFile['segments'][0]) + ) { $this->_MediaInfoMessageIDs = (string) $this->_currentNZBFile['segments'][0]; } // Look for a audio file. - if ($this->_processAudioInfo && empty($this->_AudioInfoMessageIDs) && preg_match('/'.$this->_audioFileRegex.'[. ")\]]/i', $this->_currentNZBFile['title'], $type) && isset($this->_currentNZBFile['segments'])) { + if ($this->_processAudioInfo && empty($this->_AudioInfoMessageIDs) && preg_match('/'.$this->_audioFileRegex.'[. ")\]]/i', $this->_currentNZBFile['title'], $type) && isset($this->_currentNZBFile['segments']) + ) { // Get the extension. $this->_AudioInfoExtension = $type[1]; $this->_AudioInfoMessageIDs = (string) $this->_currentNZBFile['segments'][0]; @@ -998,6 +947,436 @@ class ProcessAdditional return $totalBookFiles; } + /** + * List of message-id's we have tried for rar/zip files. + * @var array + */ + protected $_triedCompressedMids = []; + + /** + * @param bool $reverse + * @throws \Exception + */ + protected function _processNZBCompressedFiles($reverse = false): void + { + $this->_reverse = $reverse; + + if ($this->_reverse) { + if (! krsort($this->_nzbContents)) { + return; + } + } else { + $this->_triedCompressedMids = []; + } + + $failed = $downloaded = 0; + // Loop through the files, attempt to find if password-ed and files. Starting with what not to process. + foreach ($this->_nzbContents as $nzbFile) { + // TODO change this to max calculated size, as segments vary in size greatly. + if ($downloaded >= $this->_maximumRarSegments) { + break; + } + + if ($failed >= $this->_maximumRarPasswordChecks) { + break; + } + + if ($this->_releaseHasPassword) { + $this->_echo('Skipping processing of rar '.$nzbFile['title'].' it has a password.', 'primaryOver'); + break; + } + + // Probably not a rar/zip. + if (! preg_match( + '/\.(part\d+|[r|z]\d+|rar|0+|0*10?|zipr\d{2,3}|zipx?)(\s*\.rar)*($|[ ")\]-])|"[a-f0-9]{32}\.[1-9]\d{1,2}".*\(\d+\/\d{2,}\)$/i', + $nzbFile['title'] + ) + ) { + continue; + } + + // Get message-id's for the rar file. + $segCount = (\count($nzbFile['segments']) - 1); + $mID = []; + for ($i = 0; $i < $this->_maximumRarSegments; $i++) { + if ($i > $segCount) { + break; + } + $segment = (string) $nzbFile['segments'][$i]; + if (! $this->_reverse) { + $this->_triedCompressedMids[] = $segment; + } elseif (\in_array($segment, $this->_triedCompressedMids, false)) { + // We already downloaded this file. + continue 2; + } + $mID[] = $segment; + } + // Nothing to download. + if (empty($mID)) { + continue; + } + + // Download the article(s) from usenet. + $fetchedBinary = $this->_nntp->getMessages($this->_releaseGroupName, $mID, $this->_alternateNNTP); + if ($this->_nntp::isError($fetchedBinary)) { + $fetchedBinary = false; + } + + if ($fetchedBinary !== false) { + + // Echo we downloaded compressed file. + if ($this->_echoCLI) { + $this->_echo('(cB)', 'primaryOver'); + } + + $downloaded++; + + // Process the compressed file. + $decompressed = $this->_processCompressedData($fetchedBinary); + + if ($decompressed || $this->_releaseHasPassword) { + break; + } + } else { + $failed++; + if ($this->_echoCLI) { + $this->_echo('f('.$failed.')', 'warningOver'); + } + } + } + } + + /** + * Check if the data is a ZIP / RAR file, extract files, get file info. + * + * @param string $compressedData + * + * @return bool + * @throws \Exception + */ + protected function _processCompressedData(&$compressedData): bool + { + $this->_compressedFilesChecked++; + // Give the data to archive info so it can check if it's a rar. + if (! $this->_archiveInfo->setData($compressedData, true)) { + if (config('app.debug') === true) { + $this->_debug('Data is probably not RAR or ZIP.'); + } + + return false; + } + + // Check if there's an error. + if ($this->_archiveInfo->error !== '') { + if (config('app.debug') === true) { + $this->_debug('ArchiveInfo Error: '.$this->_archiveInfo->error); + } + + return false; + } + + try { + // Get a summary of the compressed file. + $dataSummary = $this->_archiveInfo->getSummary(true); + } catch (\Exception $exception) { + //Log the exception and continue to next item + if (config('app.debug') === true) { + Log::warning($exception->getTraceAsString()); + } + + return false; + } + + // Check if the compressed file is encrypted. + if (! empty($this->_archiveInfo->isEncrypted) || (isset($dataSummary['is_encrypted']) && (int) $dataSummary['is_encrypted'] !== 0)) { + if (config('app.debug') === true) { + $this->_debug('ArchiveInfo: Compressed file has a password.'); + } + $this->_releaseHasPassword = true; + $this->_passwordStatus[] = Releases::PASSWD_RAR; + + return false; + } + + switch ($dataSummary['main_type']) { + case ArchiveInfo::TYPE_RAR: + if ($this->_echoCLI) { + $this->_echo('r', 'primaryOver'); + } + + if (! $this->_extractUsingRarInfo && $this->_unrarPath !== false) { + $fileName = $this->tmpPath.uniqid('', true).'.rar'; + File::put($fileName, $compressedData); + runCmd($this->_killString.$this->_unrarPath.'" e -ai -ep -c- -id -inul -kb -or -p- -r -y "'.$fileName.'" "'.$this->tmpPath.'unrar/"'); + File::delete($fileName); + } + break; + case ArchiveInfo::TYPE_ZIP: + if ($this->_echoCLI) { + $this->_echo('z', 'primaryOver'); + } + + if (! $this->_extractUsingRarInfo && $this->_7zipPath !== false) { + $fileName = $this->tmpPath.uniqid('', true).'.zip'; + File::put($fileName, $compressedData); + runCmd($this->_killString.$this->_7zipPath.'" x "'.$fileName.'" -bd -y -o"'.$this->tmpPath.'unzip/"'); + File::delete($fileName); + } + break; + default: + return false; + } + + return $this->_processCompressedFileList(); + } + + /** + * Get a list of all files in the compressed file, add the file info to the DB. + * + * @return bool + * @throws \Exception + */ + protected function _processCompressedFileList(): bool + { + // Get a list of files inside the Compressed file. + $files = $this->_archiveInfo->getArchiveFileList(); + if (! \is_array($files) || \count($files) === 0) { + return false; + } + + // Loop through the files. + foreach ($files as $file) { + if ($this->_releaseHasPassword) { + break; + } + + if (isset($file['name'])) { + if (isset($file['error'])) { + if (config('app.debug') === true) { + $this->_debug("Error: {$file['error']} (in: {$file['source']})"); + } + continue; + } + + if (isset($file['pass']) && $file['pass'] === true) { + $this->_releaseHasPassword = true; + $this->_passwordStatus[] = Releases::PASSWD_RAR; + break; + } + + if ($this->_innerFileBlacklist !== false && preg_match($this->_innerFileBlacklist, $file['name'])) { + $this->_releaseHasPassword = true; + $this->_passwordStatus[] = Releases::PASSWD_POTENTIAL; + break; + } + + $fileName = []; + if (preg_match('/[^\/\\\\]*\.[a-zA-Z0-9]*$/', $file['name'], $fileName)) { + $fileName = $fileName[0]; + } else { + $fileName = ''; + } + + if ($this->_extractUsingRarInfo) { + // Extract files from the rar. + if (isset($file['compressed']) && (int) $file['compressed'] === 0) { + File::put( + $this->tmpPath.random_int(10, 999999).'_'.$fileName, + $this->_archiveInfo->getFileData($file['name'], $file['source']) + ); + } // If the files are compressed, use a binary extractor. + else { + $this->_archiveInfo->extractFile($file['name'], $this->tmpPath.random_int(10, 999999).'_'.$fileName); + } + } + } + $this->_addFileInfo($file); + } + if ($this->_addedFileInfo > 0) { + $this->sphinx->updateRelease($this->_release->id); + } + + return $this->_totalFileInfo > 0; + } + + /** + * @param $file + * @throws \Exception + */ + protected function _addFileInfo(&$file): void + { + // Don't add rar/zip files to the DB. + if (! isset($file['error']) && isset($file['source']) && + ! preg_match($this->_supportFileRegex.'|part\d+|[r|z]\d{1,3}|zipr\d{2,3}|\d{2,3}|zipx|zip|rar)(\s*\.rar)?$/i', $file['name']) + ) { + + // Cache the amount of files we find in the RAR or ZIP, return this to say we did find RAR or ZIP content. + // This is so we don't download more RAR or ZIP files for no reason. + $this->_totalFileInfo++; + + /* Check if we already have the file or not. + * Also make sure we don't add too many files, some releases have 100's of files, like PS3 releases. + */ + if ($this->_addedFileInfo < 11 && ReleaseFile::query()->where(['releases_id' => $this->_release->id, 'name' => $file['name'], 'size' => $file + ['size'], ])->first() === null) { + if (ReleaseFile::addReleaseFiles($this->_release->id, $file['name'], $file['size'], $file['date'], $file['pass'], '', $file['crc32'] ?? '')) { + $this->_addedFileInfo++; + + if ($this->_echoCLI) { + $this->_echo('^', 'primaryOver'); + } + + // Check for "codec spam" + if (preg_match('/alt\.binaries\.movies($|\.divx$)/', $this->_releaseGroupName) && + preg_match('/[\/\\\\]Codec[\/\\\\]Setup\.exe$/i', $file['name']) + ) { + if (config('app.debug') === true) { + $this->_debug('Codec spam found, setting release to potentially passworded.'); + } + $this->_releaseHasPassword = true; + $this->_passwordStatus[] = Releases::PASSWD_POTENTIAL; + } //Run a PreDB filename check on insert to try and match the release + elseif ($file['name'] !== '' && strpos($file['name'], '.') !== 0) { + $this->_release['filename'] = $file['name']; + $this->_release['releases_id'] = $this->_release->id; + $this->_nameFixer->matchPreDbFiles($this->_release, 1, 1, true); + } + } + } + } + } + + /** + * Go through all the extracted files in the temp folder and process them. + * + * @throws \Exception + */ + protected function _processExtractedFiles(): void + { + $nestedLevels = 0; + + // Go through all the files in the temp folder, look for compressed files, extract them and the nested ones. + while ($nestedLevels < $this->_maxNestedLevels) { + + // Break out if we checked more than x compressed files. + if ($this->_compressedFilesChecked >= self::maxCompressedFilesToCheck) { + break; + } + + $foundCompressedFile = false; + + // Get all the compressed files in the temp folder. + $files = $this->_getTempDirectoryContents('/.*\.([rz]\d{2,}|rar|zipx?|0{0,2}1)($|[^a-z0-9])/i'); + + if ($files instanceof \Traversable) { + foreach ($files as $file) { + + // Check if the file exists. + if (File::isFile($file[0])) { + $rarData = @File::get($file[0]); + if ($rarData !== false) { + $this->_processCompressedData($rarData); + $foundCompressedFile = true; + } + File::delete($file[0]); + } + } + } + + // If we found no compressed files, break out. + if (! $foundCompressedFile) { + break; + } + + $nestedLevels++; + } + + $fileType = []; + + // Get all the remaining files in the temp dir. + $files = $this->_getTempDirectoryContents(); + foreach ($files as $file) { + $file = $file->getPathname(); + + // Skip /. and /.. + if (preg_match('/[\/\\\\]\.{1,2}$/', $file)) { + continue; + } + + if (File::isFile($file)) { + + // Process PAR2 files. + if (! $this->_foundPAR2Info && preg_match('/\.par2$/', $file)) { + $this->_siftPAR2Info($file); + } // Process NFO files. + elseif ($this->_releaseHasNoNFO && preg_match('/(\.(nfo|inf|ofn)|info\.txt)$/i', $file)) { + $this->_processNfoFile($file); + } // Process audio files. + elseif ( + (! $this->_foundAudioInfo || ! $this->_foundAudioSample) && + preg_match('/(.*)'.$this->_audioFileRegex.'$/i', $file, $fileType) + ) { + // Try to get audio sample/audio media info. + File::move($file, $this->tmpPath.'audiofile.'.$fileType[2]); + $this->_getAudioInfo($this->tmpPath.'audiofile.'.$fileType[2], $fileType[2]); + File::delete($this->tmpPath.'audiofile.'.$fileType[2]); + } // Process JPG files. + elseif (! $this->_foundJPGSample && preg_match('/\.jpe?g$/i', $file)) { + $this->_getJPGSample($file); + File::delete($file); + } // Video sample // video clip // video media info. + elseif ((! $this->_foundSample || ! $this->_foundVideo || ! $this->_foundMediaInfo) && + preg_match('/(.*)'.$this->_videoFileRegex.'$/i', $file) + ) { + $this->_processVideoFile($file); + } + + // Check file's magic info. + else { + $output = Utility::fileInfo($file); + if (! empty($output)) { + switch (true) { + + case ! $this->_foundJPGSample && preg_match('/^JPE?G/i', $output): + $this->_getJPGSample($file); + File::delete($file); + break; + + case + (! $this->_foundMediaInfo || ! $this->_foundSample || ! $this->_foundVideo) + && preg_match('/Matroska data|MPEG v4|MPEG sequence, v2|\WAVI\W/i', $output): + $this->_processVideoFile($file); + break; + + case + (! $this->_foundAudioSample || ! $this->_foundAudioInfo) && + preg_match('/^FLAC|layer III|Vorbis audio/i', $output, $fileType): + switch ($fileType[0]) { + case 'FLAC': + $fileType = 'FLAC'; + break; + case 'layer III': + $fileType = 'MP3'; + break; + case 'Vorbis audio': + $fileType = 'OGG'; + break; + } + File::move($file, $this->tmpPath.'audiofile.'.$fileType); + $this->_getAudioInfo($this->tmpPath.'audiofile.'.$fileType, $fileType); + File::delete($this->tmpPath.'audiofile.'.$fileType); + break; + + case ! $this->_foundPAR2Info && stripos($output, 'Parity') === 0: + $this->_siftPAR2Info($file); + break; + } + } + } + } + } + } + /** * Download all binaries from usenet and form samples / get media info / etc from them. * @@ -1059,8 +1438,464 @@ class ProcessAdditional } /** - * @param string $fileLocation + * Download and process binaries for media info from videos. * + * @void + * @throws \Exception + */ + protected function _processMediaInfoMessageIDs(): void + { + // Download and process mediainfo. Also try to get a sample if we didn't get one yet. + if (! $this->_foundMediaInfo || ! $this->_foundSample || ! $this->_foundVideo) { + if (! $this->_foundMediaInfo && ! empty($this->_MediaInfoMessageIDs)) { + + // Try to download it from usenet. + $mediaBinary = $this->_nntp->getMessages($this->_releaseGroupName, $this->_MediaInfoMessageIDs, $this->_alternateNNTP); + if ($this->_nntp::isError($mediaBinary)) { + // If error set it to false. + $mediaBinary = false; + } + + if ($mediaBinary !== false) { + if ($this->_echoCLI) { + $this->_echo('(mB)', 'primaryOver'); + } + + // If it's more than 40 bytes... + if (\strlen($mediaBinary) > 40) { + $fileLocation = $this->tmpPath.'media.avi'; + // Create a file on the disk with it. + File::put($fileLocation, $mediaBinary); + + // Try to get media info. + if (! $this->_foundMediaInfo) { + $this->_foundMediaInfo = $this->_getMediaInfo($fileLocation); + } + + // Try to get a sample picture. + if (! $this->_foundSample) { + $this->_foundSample = $this->_getSample($fileLocation); + } + + // Try to get a sample video. + if (! $this->_foundVideo) { + $this->_foundVideo = $this->_getVideo($fileLocation); + } + } + } elseif ($this->_echoCLI) { + $this->_echo('f', 'warningOver'); + } + } + } + } + + /** + * Download and process binaries for media info from songs. + * + * @void + * @throws \Exception + */ + protected function _processAudioInfoMessageIDs(): void + { + // Download audio file, use media info to try to get the artist / album. + if (! $this->_foundAudioInfo || ! $this->_foundAudioSample) { + if (! empty($this->_AudioInfoMessageIDs)) { + // Try to download it from usenet. + $audioBinary = $this->_nntp->getMessages($this->_releaseGroupName, $this->_AudioInfoMessageIDs, $this->_alternateNNTP); + if ($this->_nntp::isError($audioBinary)) { + $audioBinary = false; + } + + if ($audioBinary !== false) { + if ($this->_echoCLI) { + $this->_echo('(aB)', 'primaryOver'); + } + + $fileLocation = $this->tmpPath.'audio.'.$this->_AudioInfoExtension; + // Create a file with it. + File::put($fileLocation, $audioBinary); + + // Try to get media info / sample of the audio file. + $this->_getAudioInfo($fileLocation, $this->_AudioInfoExtension); + } elseif ($this->_echoCLI) { + $this->_echo('f', 'warningOver'); + } + } + } + } + + /** + * Download and process binaries for JPG pictures. + * + * @void + * @throws \Exception + */ + protected function _processJPGMessageIDs(): void + { + // Download JPG file. + if (! $this->_foundJPGSample && ! empty($this->_JPGMessageIDs)) { + + // Try to download it. + $jpgBinary = $this->_nntp->getMessages($this->_releaseGroupName, $this->_JPGMessageIDs, $this->_alternateNNTP); + if ($this->_nntp::isError($jpgBinary)) { + $jpgBinary = false; + } + + if ($jpgBinary !== false) { + if ($this->_echoCLI) { + $this->_echo('(jB)', 'primaryOver'); + } + + // Try to create a file with it. + File::put($this->tmpPath.'samplepicture.jpg', $jpgBinary); + + // Try to resize and move it. + $this->_foundJPGSample = ( + $this->_releaseImage->saveImage( + $this->_release->guid.'_thumb', + $this->tmpPath.'samplepicture.jpg', + $this->_releaseImage->jpgSavePath, + 650, + 650 + ) === 1 + ); + + if ($this->_foundJPGSample) { + // Update the DB to say we got it. + Release::query()->where('id', $this->_release->id)->update(['jpgstatus' => 1]); + + if ($this->_echoCLI) { + $this->_echo('j', 'primaryOver'); + } + } + + File::delete($this->tmpPath.'samplepicture.jpg'); + } elseif ($this->_echoCLI) { + $this->_echo('f', 'warningOver'); + } + } + } + + /** + * Update the release to say we processed it. + */ + protected function _finalizeRelease(): void + { + $vSQL = $jSQL = ''; + $iSQL = ', haspreview = 0'; + + // If samples exist from previous runs, set flags. + if (File::isFile($this->_releaseImage->imgSavePath.$this->_release->guid.'_thumb.jpg')) { + $iSQL = ', haspreview = 1'; + } + + if (File::isFile($this->_releaseImage->vidSavePath.$this->_release->guid.'.ogv')) { + $vSQL = ', videostatus = 1'; + } + + if (File::isFile($this->_releaseImage->jpgSavePath.$this->_release->guid.'_thumb.jpg')) { + $jSQL = ', jpgstatus = 1'; + } + + // Get the amount of files we found inside the RAR/ZIP files. + + $releaseFilesCount = ReleaseFile::whereReleasesId($this->_release->id)->count('releases_id'); + + if ($releaseFilesCount === null) { + $releaseFilesCount = 0; + } + + $this->_passwordStatus = max($this->_passwordStatus); + + // Set the release to no password if password processing is off. + if (! $this->_processPasswords) { + $this->_releaseHasPassword = false; + } + + // If we failed to get anything from the RAR/ZIPs, decrement the passwordstatus, if the rar/zip has no password. + if (! $this->_releaseHasPassword && $this->_NZBHasCompressedFile && $releaseFilesCount === 0) { + $query = sprintf( + 'UPDATE releases + SET passwordstatus = passwordstatus - 1, rarinnerfilecount = %d %s %s %s + WHERE id = %d', + $releaseFilesCount, + $iSQL, + $vSQL, + $jSQL, + $this->_release->id + ); + } // Else update the release with the password status (if the admin enabled the setting). + else { + $query = sprintf( + 'UPDATE releases + SET passwordstatus = %d, rarinnerfilecount = %d %s %s %s + WHERE id = %d', + ($this->_processPasswords ? $this->_passwordStatus : Releases::PASSWD_NONE), + $releaseFilesCount, + $iSQL, + $vSQL, + $jSQL, + $this->_release->id + ); + } + + Release::fromQuery($query); + } + + /** + * @param string $pattern + * @param string $path + * + * @return bool|string|\Symfony\Component\Finder\SplFileInfo[] + */ + protected function _getTempDirectoryContents($pattern = '', $path = '') + { + if ($path === '') { + $path = $this->tmpPath; + } + + $files = File::allFiles($path); + try { + if ($pattern !== '') { + $allFiles = []; + foreach ($files as $file) { + if (preg_match($pattern, $file->getRelativePathname())) { + $allFiles .= $file; + } + } + + return $allFiles; + } + + return $files; + } catch (\Throwable $e) { + if (config('app.debug') === true) { + Log::error($e->getTraceAsString()); + $this->_debug('ERROR: Could not open temp dir: '.$e->getMessage()); + } + + return false; + } + } + + /** + * @param $fileLocation + * @param $fileExtension + * @return bool + * @throws \Exception + */ + protected function _getAudioInfo($fileLocation, $fileExtension): bool + { + // Return values. + $retVal = $audVal = false; + + // Check if audio sample fetching is on. + if (! $this->_processAudioSample) { + $audVal = true; + } + + // Check if media info fetching is on. + if (! $this->_processAudioInfo) { + $retVal = true; + } + + $rQuery = Release::query()->where('proc_pp', '=', 0)->where('id', $this->_release->id)->select(['searchname', 'fromname', 'categories_id'])->first(); + + $musicParent = (string) Category::MUSIC_ROOT; + if ($rQuery === null || ! preg_match( + sprintf( + '/%d\d{3}|%d|%d|%d/', + $musicParent[0], + Category::OTHER_MISC, + Category::MOVIE_OTHER, + Category::TV_OTHER + ), + $rQuery->id + ) + ) { + return false; + } + + if (File::isFile($fileLocation)) { + + // Check if media info is enabled. + if (! $retVal) { + + // Get the media info for the file. + $xmlArray = $this->mediaInfo->getInfo($fileLocation, false); + + if ($xmlArray !== null) { + foreach ($xmlArray->getAudios() as $track) { + if ($track->get('album') !== null && $track->get('performer') !== null) { + if ((int) $this->_release->predb_id === 0 && config('nntmux.rename_music_mediainfo')) { + // Make the extension upper case. + $ext = strtoupper($fileExtension); + + // Form a new search name. + if (! empty($track->get('recorded_date')) && preg_match('/(?:19|20)\d\d/', $track->get('recorded_date')->getFullname(), $Year)) { + $newName = $track->get('performer')->getFullName().' - '.$track->get('album')->getFullName().' ('.$Year[0].') '.$ext; + } else { + $newName = $track->get('performer')->getFullName().' - '.$track->get('album')->getFullName().' '.$ext; + } + + // Get the category or try to determine it. + if ($ext === 'MP3') { + $newCat = Category::MUSIC_MP3; + } elseif ($ext === 'FLAC') { + $newCat = Category::MUSIC_LOSSLESS; + } else { + $newCat = $this->_categorize->determineCategory($rQuery->groups_id, $newName, $rQuery->fromname); + } + + $newTitle = escapeString(substr($newName, 0, 255)); + // Update the search name. + $release = Release::whereId($this->_release->id); + $release->update(['searchname' => $newTitle, 'categories_id' => $newCat['categories_id'], 'iscategorized' => 1, 'isrenamed' => 1, 'proc_pp' => 1]); + $release->retag($newCat['tags']); + $this->sphinx->updateRelease($this->_release->id); + + // Echo the changed name. + if ($this->_echoCLI) { + NameFixer::echoChangedReleaseName( + [ + 'new_name' => $newName, + 'old_name' => $rQuery->searchname, + 'new_category' => $newCat, + 'old_category' => $rQuery->id, + 'group' => $rQuery->groups_id, + 'releases_id' => $this->_release->id, + 'method' => 'ProcessAdditional->_getAudioInfo', + ] + ); + } + } + + // Add the media info. + $this->_releaseExtra->addFromXml($this->_release->id, $xmlArray); + + $retVal = true; + $this->_foundAudioInfo = true; + if ($this->_echoCLI) { + $this->_echo('a', 'primaryOver'); + } + break; + } + } + } + } + + // Check if creating audio samples is enabled. + if (! $audVal) { + + // File name to store audio file. + $audioFileName = ($this->_release->guid.'.ogg'); + + // Create an audio sample. + if ($this->ffprobe->isValid($fileLocation)) { + try { + $audioSample = $this->ffmpeg->open($fileLocation); + $format = new Vorbis(); + $audioSample->clip(TimeCode::fromSeconds(30), TimeCode::fromSeconds(30)); + $audioSample->save($format, $this->tmpPath.$audioFileName); + } catch (\InvalidArgumentException $e) { + if (config('app.debug') === true) { + Log::error($e->getTraceAsString()); + } + //We do nothing, just prevent displaying errors because the file cannot be open(corrupted or incomplete file) + } + } + + // Check if the new file was created. + if (File::isFile($this->tmpPath.$audioFileName)) { + + // Try to move the temp audio file. + $renamed = File::move($this->tmpPath.$audioFileName, $this->_audioSavePath.$audioFileName); + + if (! $renamed) { + // Try to copy it if it fails. + $copied = File::copy($this->tmpPath.$audioFileName, $this->_audioSavePath.$audioFileName); + + // Delete the old file. + File::delete($this->tmpPath.$audioFileName); + + // If it didn't copy continue. + if (! $copied) { + return false; + } + } + + // Try to set the file perms. + @chmod($this->_audioSavePath.$audioFileName, 0764); + + // Update DB to said we got a audio sample. + Release::query()->where('id', $this->_release->id)->update(['audiostatus' => 1]); + + $audVal = $this->_foundAudioSample = true; + + if ($this->_echoCLI) { + $this->_echo('A', 'primaryOver'); + } + } + } + } + + return $retVal && $audVal; + } + + /** + * Try to get JPG picture, resize it and store it on disk. + * + * @param string $fileLocation + */ + protected function _getJPGSample($fileLocation): void + { + // Try to resize/move the image. + $this->_foundJPGSample = ( + $this->_releaseImage->saveImage( + $this->_release->guid.'_thumb', + $fileLocation, + $this->_releaseImage->jpgSavePath, + 650, + 650 + ) === 1 + ); + + // If it's successful, tell the DB. + if ($this->_foundJPGSample) { + Release::query()->where('id', $this->_release->id)->update(['jpgstatus' => 1]); + } + } + + /** + * @param string $videoLocation + * + * @return string + */ + private function getVideoTime($videoLocation): string + { + // Get the real duration of the file. + if ($this->ffprobe->isValid($videoLocation)) { + $time = $this->ffprobe->format($videoLocation)->get('duration'); + } + + if (empty($time) || ! preg_match('/time=(\d{1,2}:\d{1,2}:)?(\d{1,2})\.(\d{1,2})\s*bitrate=/i', $time, $numbers)) { + return ''; + } + + // Reduce the last number by 1, this is to make sure we don't ask avconv/ffmpeg for non existing data. + if ($numbers[3] > 0) { + $numbers[3] -= 1; + } elseif ($numbers[1] > 0) { + $numbers[2] -= 1; + $numbers[3] = '99'; + } + + // Manually pad the numbers in case they are 1 number. to get 02 for example instead of 2. + return '00:00:'.str_pad($numbers[2], 2, '0', STR_PAD_LEFT).'.'.str_pad($numbers[3], 2, '0', STR_PAD_LEFT); + } + + /** + * @param string $fileLocation * @return bool * @throws \Exception */ @@ -1103,7 +1938,13 @@ class ProcessAdditional if (File::isFile($fileName)) { // Try to resize/move the image. - $saved = $this->_releaseImage->saveImage($this->_release->guid.'_thumb', $fileName, $this->_releaseImage->imgSavePath, 800, 600); + $saved = $this->_releaseImage->saveImage( + $this->_release->guid.'_thumb', + $fileName, + $this->_releaseImage->imgSavePath, + 800, + 600 + ); // Delete the temp file we created. File::delete($fileName); @@ -1122,37 +1963,8 @@ class ProcessAdditional return false; } - /** - * @param string $videoLocation - * - * @return string - */ - private function getVideoTime($videoLocation): string - { - // Get the real duration of the file. - if ($this->ffprobe->isValid($videoLocation)) { - $time = $this->ffprobe->format($videoLocation)->get('duration'); - } - - if (empty($time) || ! preg_match('/time=(\d{1,2}:\d{1,2}:)?(\d{1,2})\.(\d{1,2})\s*bitrate=/i', $time, $numbers)) { - return ''; - } - - // Reduce the last number by 1, this is to make sure we don't ask avconv/ffmpeg for non existing data. - if ($numbers[3] > 0) { - $numbers[3] -= 1; - } elseif ($numbers[1] > 0) { - $numbers[2] -= 1; - $numbers[3] = '99'; - } - - // Manually pad the numbers in case they are 1 number. to get 02 for example instead of 2. - return '00:00:'.str_pad($numbers[2], 2, '0', STR_PAD_LEFT).'.'.str_pad($numbers[3], 2, '0', STR_PAD_LEFT); - } - /** * @param string $fileLocation - * * @return bool * @throws \Exception */ @@ -1275,61 +2087,8 @@ class ProcessAdditional return false; } - /** - * Download and process binaries for media info from videos. - * - * @void - * @throws \Exception - */ - protected function _processMediaInfoMessageIDs(): void - { - // Download and process mediainfo. Also try to get a sample if we didn't get one yet. - if (! $this->_foundMediaInfo || ! $this->_foundSample || ! $this->_foundVideo) { - if (! $this->_foundMediaInfo && ! empty($this->_MediaInfoMessageIDs)) { - - // Try to download it from usenet. - $mediaBinary = $this->_nntp->getMessages($this->_releaseGroupName, $this->_MediaInfoMessageIDs, $this->_alternateNNTP); - if ($this->_nntp::isError($mediaBinary)) { - // If error set it to false. - $mediaBinary = false; - } - - if ($mediaBinary !== false) { - if ($this->_echoCLI) { - $this->_echo('(mB)', 'primaryOver'); - } - - // If it's more than 40 bytes... - if (\strlen($mediaBinary) > 40) { - $fileLocation = $this->tmpPath.'media.avi'; - // Create a file on the disk with it. - File::put($fileLocation, $mediaBinary); - - // Try to get media info. - if (! $this->_foundMediaInfo) { - $this->_foundMediaInfo = $this->_getMediaInfo($fileLocation); - } - - // Try to get a sample picture. - if (! $this->_foundSample) { - $this->_foundSample = $this->_getSample($fileLocation); - } - - // Try to get a sample video. - if (! $this->_foundVideo) { - $this->_foundVideo = $this->_getVideo($fileLocation); - } - } - } elseif ($this->_echoCLI) { - $this->_echo('f', 'warningOver'); - } - } - } - } - /** * @param $fileLocation - * * @return bool * @throws \Exception */ @@ -1363,709 +2122,8 @@ class ProcessAdditional return false; } - /** - * Download and process binaries for media info from songs. - * - * @void - * @throws \Exception - */ - protected function _processAudioInfoMessageIDs(): void - { - // Download audio file, use media info to try to get the artist / album. - if (! $this->_foundAudioInfo || ! $this->_foundAudioSample) { - if (! empty($this->_AudioInfoMessageIDs)) { - // Try to download it from usenet. - $audioBinary = $this->_nntp->getMessages($this->_releaseGroupName, $this->_AudioInfoMessageIDs, $this->_alternateNNTP); - if ($this->_nntp::isError($audioBinary)) { - $audioBinary = false; - } - - if ($audioBinary !== false) { - if ($this->_echoCLI) { - $this->_echo('(aB)', 'primaryOver'); - } - - $fileLocation = $this->tmpPath.'audio.'.$this->_AudioInfoExtension; - // Create a file with it. - File::put($fileLocation, $audioBinary); - - // Try to get media info / sample of the audio file. - $this->_getAudioInfo($fileLocation, $this->_AudioInfoExtension); - } elseif ($this->_echoCLI) { - $this->_echo('f', 'warningOver'); - } - } - } - } - /** * @param $fileLocation - * @param $fileExtension - * - * @return bool - * @throws \Exception - */ - protected function _getAudioInfo($fileLocation, $fileExtension): bool - { - // Return values. - $retVal = $audVal = false; - - // Check if audio sample fetching is on. - if (! $this->_processAudioSample) { - $audVal = true; - } - - // Check if media info fetching is on. - if (! $this->_processAudioInfo) { - $retVal = true; - } - - $rQuery = Release::query()->where('proc_pp', '=', 0)->where('id', $this->_release->id)->select([ - 'searchname', - 'fromname', - 'categories_id', - ])->first(); - - $musicParent = (string) Category::MUSIC_ROOT; - if ($rQuery === null || ! preg_match(sprintf('/%d\d{3}|%d|%d|%d/', $musicParent[0], Category::OTHER_MISC, Category::MOVIE_OTHER, Category::TV_OTHER), $rQuery->id)) { - return false; - } - - if (File::isFile($fileLocation)) { - - // Check if media info is enabled. - if (! $retVal) { - - // Get the media info for the file. - $xmlArray = $this->mediaInfo->getInfo($fileLocation, false); - - if ($xmlArray !== null) { - foreach ($xmlArray->getAudios() as $track) { - if ($track->get('album') !== null && $track->get('performer') !== null) { - if ((int) $this->_release->predb_id === 0 && config('nntmux.rename_music_mediainfo')) { - // Make the extension upper case. - $ext = strtoupper($fileExtension); - - // Form a new search name. - if (! empty($track->get('recorded_date')) && preg_match('/(?:19|20)\d\d/', $track->get('recorded_date')->getFullname(), $Year)) { - $newName = $track->get('performer')->getFullName().' - '.$track->get('album')->getFullName().' ('.$Year[0].') '.$ext; - } else { - $newName = $track->get('performer')->getFullName().' - '.$track->get('album')->getFullName().' '.$ext; - } - - // Get the category or try to determine it. - if ($ext === 'MP3') { - $newCat = Category::MUSIC_MP3; - } elseif ($ext === 'FLAC') { - $newCat = Category::MUSIC_LOSSLESS; - } else { - $newCat = $this->_categorize->determineCategory($rQuery->groups_id, $newName, $rQuery->fromname); - } - - $newTitle = escapeString(substr($newName, 0, 255)); - // Update the search name. - $release = Release::whereId($this->_release->id); - $release->update([ - 'searchname' => $newTitle, - 'categories_id' => $newCat['categories_id'], - 'iscategorized' => 1, - 'isrenamed' => 1, - 'proc_pp' => 1, - ]); - $release->retag($newCat['tags']); - $this->sphinx->updateRelease($this->_release->id); - - // Echo the changed name. - if ($this->_echoCLI) { - NameFixer::echoChangedReleaseName([ - 'new_name' => $newName, - 'old_name' => $rQuery->searchname, - 'new_category' => $newCat, - 'old_category' => $rQuery->id, - 'group' => $rQuery->groups_id, - 'releases_id' => $this->_release->id, - 'method' => 'ProcessAdditional->_getAudioInfo', - ]); - } - } - - // Add the media info. - $this->_releaseExtra->addFromXml($this->_release->id, $xmlArray); - - $retVal = true; - $this->_foundAudioInfo = true; - if ($this->_echoCLI) { - $this->_echo('a', 'primaryOver'); - } - break; - } - } - } - } - - // Check if creating audio samples is enabled. - if (! $audVal) { - - // File name to store audio file. - $audioFileName = ($this->_release->guid.'.ogg'); - - // Create an audio sample. - if ($this->ffprobe->isValid($fileLocation)) { - try { - $audioSample = $this->ffmpeg->open($fileLocation); - $format = new Vorbis(); - $audioSample->clip(TimeCode::fromSeconds(30), TimeCode::fromSeconds(30)); - $audioSample->save($format, $this->tmpPath.$audioFileName); - } catch (\InvalidArgumentException $e) { - if (config('app.debug') === true) { - Log::error($e->getTraceAsString()); - } - //We do nothing, just prevent displaying errors because the file cannot be open(corrupted or incomplete file) - } - } - - // Check if the new file was created. - if (File::isFile($this->tmpPath.$audioFileName)) { - - // Try to move the temp audio file. - $renamed = File::move($this->tmpPath.$audioFileName, $this->_audioSavePath.$audioFileName); - - if (! $renamed) { - // Try to copy it if it fails. - $copied = File::copy($this->tmpPath.$audioFileName, $this->_audioSavePath.$audioFileName); - - // Delete the old file. - File::delete($this->tmpPath.$audioFileName); - - // If it didn't copy continue. - if (! $copied) { - return false; - } - } - - // Try to set the file perms. - @chmod($this->_audioSavePath.$audioFileName, 0764); - - // Update DB to said we got a audio sample. - Release::query()->where('id', $this->_release->id)->update(['audiostatus' => 1]); - - $audVal = $this->_foundAudioSample = true; - - if ($this->_echoCLI) { - $this->_echo('A', 'primaryOver'); - } - } - } - } - - return $retVal && $audVal; - } - - /** - * Download and process binaries for JPG pictures. - * - * @void - * @throws \Exception - */ - protected function _processJPGMessageIDs(): void - { - // Download JPG file. - if (! $this->_foundJPGSample && ! empty($this->_JPGMessageIDs)) { - - // Try to download it. - $jpgBinary = $this->_nntp->getMessages($this->_releaseGroupName, $this->_JPGMessageIDs, $this->_alternateNNTP); - if ($this->_nntp::isError($jpgBinary)) { - $jpgBinary = false; - } - - if ($jpgBinary !== false) { - if ($this->_echoCLI) { - $this->_echo('(jB)', 'primaryOver'); - } - - // Try to create a file with it. - File::put($this->tmpPath.'samplepicture.jpg', $jpgBinary); - - // Try to resize and move it. - $this->_foundJPGSample = ($this->_releaseImage->saveImage($this->_release->guid.'_thumb', $this->tmpPath.'samplepicture.jpg', $this->_releaseImage->jpgSavePath, 650, 650) === 1); - - if ($this->_foundJPGSample) { - // Update the DB to say we got it. - Release::query()->where('id', $this->_release->id)->update(['jpgstatus' => 1]); - - if ($this->_echoCLI) { - $this->_echo('j', 'primaryOver'); - } - } - - File::delete($this->tmpPath.'samplepicture.jpg'); - } elseif ($this->_echoCLI) { - $this->_echo('f', 'warningOver'); - } - } - } - - /** - * @param bool $reverse - * - * @throws \Exception - */ - protected function _processNZBCompressedFiles($reverse = false): void - { - $this->_reverse = $reverse; - - if ($this->_reverse) { - if (! krsort($this->_nzbContents)) { - return; - } - } else { - $this->_triedCompressedMids = []; - } - - $failed = $downloaded = 0; - // Loop through the files, attempt to find if password-ed and files. Starting with what not to process. - foreach ($this->_nzbContents as $nzbFile) { - // TODO change this to max calculated size, as segments vary in size greatly. - if ($downloaded >= $this->_maximumRarSegments) { - break; - } - - if ($failed >= $this->_maximumRarPasswordChecks) { - break; - } - - if ($this->_releaseHasPassword) { - $this->_echo('Skipping processing of rar '.$nzbFile['title'].' it has a password.', 'primaryOver'); - break; - } - - // Probably not a rar/zip. - if (! preg_match('/\.(part\d+|[r|z]\d+|rar|0+|0*10?|zipr\d{2,3}|zipx?)(\s*\.rar)*($|[ ")\]-])|"[a-f0-9]{32}\.[1-9]\d{1,2}".*\(\d+\/\d{2,}\)$/i', $nzbFile['title'])) { - continue; - } - - // Get message-id's for the rar file. - $segCount = (\count($nzbFile['segments']) - 1); - $mID = []; - for ($i = 0; $i < $this->_maximumRarSegments; $i++) { - if ($i > $segCount) { - break; - } - $segment = (string) $nzbFile['segments'][$i]; - if (! $this->_reverse) { - $this->_triedCompressedMids[] = $segment; - } elseif (\in_array($segment, $this->_triedCompressedMids, false)) { - // We already downloaded this file. - continue 2; - } - $mID[] = $segment; - } - // Nothing to download. - if (empty($mID)) { - continue; - } - - // Download the article(s) from usenet. - $fetchedBinary = $this->_nntp->getMessages($this->_releaseGroupName, $mID, $this->_alternateNNTP); - if ($this->_nntp::isError($fetchedBinary)) { - $fetchedBinary = false; - } - - if ($fetchedBinary !== false) { - - // Echo we downloaded compressed file. - if ($this->_echoCLI) { - $this->_echo('(cB)', 'primaryOver'); - } - - $downloaded++; - - // Process the compressed file. - $decompressed = $this->_processCompressedData($fetchedBinary); - - if ($decompressed || $this->_releaseHasPassword) { - break; - } - } else { - $failed++; - if ($this->_echoCLI) { - $this->_echo('f('.$failed.')', 'warningOver'); - } - } - } - } - - /** - * Check if the data is a ZIP / RAR file, extract files, get file info. - * - * @param string $compressedData - * - * @return bool - * @throws \Exception - */ - protected function _processCompressedData(&$compressedData): bool - { - $this->_compressedFilesChecked++; - // Give the data to archive info so it can check if it's a rar. - if (! $this->_archiveInfo->setData($compressedData, true)) { - if (config('app.debug') === true) { - $this->_debug('Data is probably not RAR or ZIP.'); - } - - return false; - } - - // Check if there's an error. - if ($this->_archiveInfo->error !== '') { - if (config('app.debug') === true) { - $this->_debug('ArchiveInfo Error: '.$this->_archiveInfo->error); - } - - return false; - } - - try { - // Get a summary of the compressed file. - $dataSummary = $this->_archiveInfo->getSummary(true); - } catch (\Exception $exception) { - //Log the exception and continue to next item - if (config('app.debug') === true) { - Log::warning($exception->getTraceAsString()); - } - - return false; - } - - // Check if the compressed file is encrypted. - if (! empty($this->_archiveInfo->isEncrypted) || (isset($dataSummary['is_encrypted']) && (int) $dataSummary['is_encrypted'] !== 0)) { - if (config('app.debug') === true) { - $this->_debug('ArchiveInfo: Compressed file has a password.'); - } - $this->_releaseHasPassword = true; - $this->_passwordStatus[] = Releases::PASSWD_RAR; - - return false; - } - - switch ($dataSummary['main_type']) { - case ArchiveInfo::TYPE_RAR: - if ($this->_echoCLI) { - $this->_echo('r', 'primaryOver'); - } - - if (! $this->_extractUsingRarInfo && $this->_unrarPath !== false) { - $fileName = $this->tmpPath.uniqid('', true).'.rar'; - File::put($fileName, $compressedData); - runCmd($this->_killString.$this->_unrarPath.'" e -ai -ep -c- -id -inul -kb -or -p- -r -y "'.$fileName.'" "'.$this->tmpPath.'unrar/"'); - File::delete($fileName); - } - break; - case ArchiveInfo::TYPE_ZIP: - if ($this->_echoCLI) { - $this->_echo('z', 'primaryOver'); - } - - if (! $this->_extractUsingRarInfo && $this->_7zipPath !== false) { - $fileName = $this->tmpPath.uniqid('', true).'.zip'; - File::put($fileName, $compressedData); - runCmd($this->_killString.$this->_7zipPath.'" x "'.$fileName.'" -bd -y -o"'.$this->tmpPath.'unzip/"'); - File::delete($fileName); - } - break; - default: - return false; - } - - return $this->_processCompressedFileList(); - } - - /** - * Echo a string to CLI. For debugging. - * - * @param string $string - * - * @void - */ - protected function _debug($string): void - { - $this->_echo('DEBUG: '.$string, 'debug'); - } - - /** - * Get a list of all files in the compressed file, add the file info to the DB. - * - * @return bool - * @throws \Exception - */ - protected function _processCompressedFileList(): bool - { - // Get a list of files inside the Compressed file. - $files = $this->_archiveInfo->getArchiveFileList(); - if (! \is_array($files) || \count($files) === 0) { - return false; - } - - // Loop through the files. - foreach ($files as $file) { - if ($this->_releaseHasPassword) { - break; - } - - if (isset($file['name'])) { - if (isset($file['error'])) { - if (config('app.debug') === true) { - $this->_debug("Error: {$file['error']} (in: {$file['source']})"); - } - continue; - } - - if (isset($file['pass']) && $file['pass'] === true) { - $this->_releaseHasPassword = true; - $this->_passwordStatus[] = Releases::PASSWD_RAR; - break; - } - - if ($this->_innerFileBlacklist !== false && preg_match($this->_innerFileBlacklist, $file['name'])) { - $this->_releaseHasPassword = true; - $this->_passwordStatus[] = Releases::PASSWD_POTENTIAL; - break; - } - - $fileName = []; - if (preg_match('/[^\/\\\\]*\.[a-zA-Z0-9]*$/', $file['name'], $fileName)) { - $fileName = $fileName[0]; - } else { - $fileName = ''; - } - - if ($this->_extractUsingRarInfo) { - // Extract files from the rar. - if (isset($file['compressed']) && (int) $file['compressed'] === 0) { - File::put($this->tmpPath.random_int(10, 999999).'_'.$fileName, $this->_archiveInfo->getFileData($file['name'], $file['source'])); - } // If the files are compressed, use a binary extractor. - else { - $this->_archiveInfo->extractFile($file['name'], $this->tmpPath.random_int(10, 999999).'_'.$fileName); - } - } - } - $this->_addFileInfo($file); - } - if ($this->_addedFileInfo > 0) { - $this->sphinx->updateRelease($this->_release->id); - } - - return $this->_totalFileInfo > 0; - } - - /** - * @param $file - * - * @throws \Exception - */ - protected function _addFileInfo(&$file): void - { - // Don't add rar/zip files to the DB. - if (! isset($file['error']) && isset($file['source']) && ! preg_match($this->_supportFileRegex.'|part\d+|[r|z]\d{1,3}|zipr\d{2,3}|\d{2,3}|zipx|zip|rar)(\s*\.rar)?$/i', $file['name'])) { - - // Cache the amount of files we find in the RAR or ZIP, return this to say we did find RAR or ZIP content. - // This is so we don't download more RAR or ZIP files for no reason. - $this->_totalFileInfo++; - - /* Check if we already have the file or not. - * Also make sure we don't add too many files, some releases have 100's of files, like PS3 releases. - */ - if ($this->_addedFileInfo < 11 && ReleaseFile::query()->where([ - 'releases_id' => $this->_release->id, - 'name' => $file['name'], - 'size' => $file - ['size'], - ])->first() === null) { - if (ReleaseFile::addReleaseFiles($this->_release->id, $file['name'], $file['size'], $file['date'], $file['pass'], '', $file['crc32'] ?? '')) { - $this->_addedFileInfo++; - - if ($this->_echoCLI) { - $this->_echo('^', 'primaryOver'); - } - - // Check for "codec spam" - if (preg_match('/alt\.binaries\.movies($|\.divx$)/', $this->_releaseGroupName) && preg_match('/[\/\\\\]Codec[\/\\\\]Setup\.exe$/i', $file['name'])) { - if (config('app.debug') === true) { - $this->_debug('Codec spam found, setting release to potentially passworded.'); - } - $this->_releaseHasPassword = true; - $this->_passwordStatus[] = Releases::PASSWD_POTENTIAL; - } //Run a PreDB filename check on insert to try and match the release - elseif ($file['name'] !== '' && strpos($file['name'], '.') !== 0) { - $this->_release['filename'] = $file['name']; - $this->_release['releases_id'] = $this->_release->id; - $this->_nameFixer->matchPreDbFiles($this->_release, 1, 1, true); - } - } - } - } - } - - /** - * Go through all the extracted files in the temp folder and process them. - * - * @throws \Exception - */ - protected function _processExtractedFiles(): void - { - $nestedLevels = 0; - - // Go through all the files in the temp folder, look for compressed files, extract them and the nested ones. - while ($nestedLevels < $this->_maxNestedLevels) { - - // Break out if we checked more than x compressed files. - if ($this->_compressedFilesChecked >= self::maxCompressedFilesToCheck) { - break; - } - - $foundCompressedFile = false; - - // Get all the compressed files in the temp folder. - $files = $this->_getTempDirectoryContents('/.*\.([rz]\d{2,}|rar|zipx?|0{0,2}1)($|[^a-z0-9])/i'); - - if ($files instanceof \Traversable) { - foreach ($files as $file) { - - // Check if the file exists. - if (File::isFile($file[0])) { - $rarData = @File::get($file[0]); - if ($rarData !== false) { - $this->_processCompressedData($rarData); - $foundCompressedFile = true; - } - File::delete($file[0]); - } - } - } - - // If we found no compressed files, break out. - if (! $foundCompressedFile) { - break; - } - - $nestedLevels++; - } - - $fileType = []; - - // Get all the remaining files in the temp dir. - $files = $this->_getTempDirectoryContents(); - foreach ($files as $file) { - $file = $file->getPathname(); - - // Skip /. and /.. - if (preg_match('/[\/\\\\]\.{1,2}$/', $file)) { - continue; - } - - if (File::isFile($file)) { - - // Process PAR2 files. - if (! $this->_foundPAR2Info && preg_match('/\.par2$/', $file)) { - $this->_siftPAR2Info($file); - } // Process NFO files. - elseif ($this->_releaseHasNoNFO && preg_match('/(\.(nfo|inf|ofn)|info\.txt)$/i', $file)) { - $this->_processNfoFile($file); - } // Process audio files. - elseif ((! $this->_foundAudioInfo || ! $this->_foundAudioSample) && preg_match('/(.*)'.$this->_audioFileRegex.'$/i', $file, $fileType)) { - // Try to get audio sample/audio media info. - File::move($file, $this->tmpPath.'audiofile.'.$fileType[2]); - $this->_getAudioInfo($this->tmpPath.'audiofile.'.$fileType[2], $fileType[2]); - File::delete($this->tmpPath.'audiofile.'.$fileType[2]); - } // Process JPG files. - elseif (! $this->_foundJPGSample && preg_match('/\.jpe?g$/i', $file)) { - $this->_getJPGSample($file); - File::delete($file); - } // Video sample // video clip // video media info. - elseif ((! $this->_foundSample || ! $this->_foundVideo || ! $this->_foundMediaInfo) && preg_match('/(.*)'.$this->_videoFileRegex.'$/i', $file)) { - $this->_processVideoFile($file); - } // Check file's magic info. - else { - $output = Utility::fileInfo($file); - if (! empty($output)) { - switch (true) { - - case ! $this->_foundJPGSample && preg_match('/^JPE?G/i', $output): - $this->_getJPGSample($file); - File::delete($file); - break; - - case - (! $this->_foundMediaInfo || ! $this->_foundSample || ! $this->_foundVideo) && preg_match('/Matroska data|MPEG v4|MPEG sequence, v2|\WAVI\W/i', $output): - $this->_processVideoFile($file); - break; - - case - (! $this->_foundAudioSample || ! $this->_foundAudioInfo) && preg_match('/^FLAC|layer III|Vorbis audio/i', $output, $fileType): - switch ($fileType[0]) { - case 'FLAC': - $fileType = 'FLAC'; - break; - case 'layer III': - $fileType = 'MP3'; - break; - case 'Vorbis audio': - $fileType = 'OGG'; - break; - } - File::move($file, $this->tmpPath.'audiofile.'.$fileType); - $this->_getAudioInfo($this->tmpPath.'audiofile.'.$fileType, $fileType); - File::delete($this->tmpPath.'audiofile.'.$fileType); - break; - - case ! $this->_foundPAR2Info && stripos($output, 'Parity') === 0: - $this->_siftPAR2Info($file); - break; - } - } - } - } - } - } - - /** - * @param string $pattern - * @param string $path - * - * @return bool|string|\Symfony\Component\Finder\SplFileInfo[] - */ - protected function _getTempDirectoryContents($pattern = '', $path = '') - { - if ($path === '') { - $path = $this->tmpPath; - } - - $files = File::allFiles($path); - try { - if ($pattern !== '') { - $allFiles = []; - foreach ($files as $file) { - if (preg_match($pattern, $file->getRelativePathname())) { - $allFiles .= $file; - } - } - - return $allFiles; - } - - return $files; - } catch (\Throwable $e) { - if (config('app.debug') === true) { - Log::error($e->getTraceAsString()); - $this->_debug('ERROR: Could not open temp dir: '.$e->getMessage()); - } - - return false; - } - } - - /** - * @param $fileLocation - * * @throws \Exception */ protected function _siftPAR2Info($fileLocation): void @@ -2085,7 +2143,13 @@ class ProcessAdditional // Only get a new name if the category is OTHER. $foundName = true; - if ((int) $releaseInfo->proc_pp === 0 && config('nntmux.rename_par2') && \in_array((int) $this->_release->categories_id, Category::OTHERS_GROUP, false)) { + if ((int) $releaseInfo->proc_pp === 0 && config('nntmux.rename_par2') && + \in_array( + (int) $this->_release->categories_id, + Category::OTHERS_GROUP, + false + ) + ) { $foundName = false; } @@ -2104,10 +2168,8 @@ class ProcessAdditional // Add to release files. if ($this->_addPAR2Files) { - if ($filesAdded < 11 && ReleaseFile::query()->where([ - 'releases_id' => $this->_release->id, - 'name' => $file['name'], - ])->first() === null) { + if ($filesAdded < 11 && ReleaseFile::query()->where(['releases_id' => $this->_release->id, 'name' => $file['name']])->first() === null + ) { // Try to add the files to the DB. if (ReleaseFile::addReleaseFiles($this->_release->id, $file['name'], $file['size'], $postDate, 0, $file['hash_16K'])) { @@ -2134,7 +2196,6 @@ class ProcessAdditional /** * @param $fileLocation - * * @throws \Exception */ protected function _processNfoFile($fileLocation): void @@ -2145,25 +2206,8 @@ class ProcessAdditional } } - /** - * Try to get JPG picture, resize it and store it on disk. - * - * @param string $fileLocation - */ - protected function _getJPGSample($fileLocation): void - { - // Try to resize/move the image. - $this->_foundJPGSample = ($this->_releaseImage->saveImage($this->_release->guid.'_thumb', $fileLocation, $this->_releaseImage->jpgSavePath, 650, 650) === 1); - - // If it's successful, tell the DB. - if ($this->_foundJPGSample) { - Release::query()->where('id', $this->_release->id)->update(['jpgstatus' => 1]); - } - } - /** * @param $fileLocation - * * @throws \Exception */ protected function _processVideoFile($fileLocation): void @@ -2187,57 +2231,6 @@ class ProcessAdditional } } - /** - * Update the release to say we processed it. - */ - protected function _finalizeRelease(): void - { - $vSQL = $jSQL = ''; - $iSQL = ', haspreview = 0'; - - // If samples exist from previous runs, set flags. - if (File::isFile($this->_releaseImage->imgSavePath.$this->_release->guid.'_thumb.jpg')) { - $iSQL = ', haspreview = 1'; - } - - if (File::isFile($this->_releaseImage->vidSavePath.$this->_release->guid.'.ogv')) { - $vSQL = ', videostatus = 1'; - } - - if (File::isFile($this->_releaseImage->jpgSavePath.$this->_release->guid.'_thumb.jpg')) { - $jSQL = ', jpgstatus = 1'; - } - - // Get the amount of files we found inside the RAR/ZIP files. - - $releaseFilesCount = ReleaseFile::whereReleasesId($this->_release->id)->count('releases_id'); - - if ($releaseFilesCount === null) { - $releaseFilesCount = 0; - } - - $this->_passwordStatus = max($this->_passwordStatus); - - // Set the release to no password if password processing is off. - if (! $this->_processPasswords) { - $this->_releaseHasPassword = false; - } - - // If we failed to get anything from the RAR/ZIPs, decrement the passwordstatus, if the rar/zip has no password. - if (! $this->_releaseHasPassword && $this->_NZBHasCompressedFile && $releaseFilesCount === 0) { - $query = sprintf('UPDATE releases - SET passwordstatus = passwordstatus - 1, rarinnerfilecount = %d %s %s %s - WHERE id = %d', $releaseFilesCount, $iSQL, $vSQL, $jSQL, $this->_release->id); - } // Else update the release with the password status (if the admin enabled the setting). - else { - $query = sprintf('UPDATE releases - SET passwordstatus = %d, rarinnerfilecount = %d %s %s %s - WHERE id = %d', ($this->_processPasswords ? $this->_passwordStatus : Releases::PASSWD_NONE), $releaseFilesCount, $iSQL, $vSQL, $jSQL, $this->_release->id); - } - - Release::fromQuery($query); - } - /** * Comparison function for uSort, for sorting NZB files. * @@ -2295,4 +2288,67 @@ class ProcessAdditional return $pos; } + + /** + * Reset some variables for the current release. + */ + protected function _resetReleaseStatus(): void + { + // Only process for samples, previews and images if not disabled. + $this->_foundVideo = $this->_processVideo ? false : true; + $this->_foundMediaInfo = $this->_processMediaInfo ? false : true; + $this->_foundAudioInfo = $this->_processAudioInfo ? false : true; + $this->_foundAudioSample = $this->_processAudioSample ? false : true; + $this->_foundJPGSample = $this->_processJPGSample ? false : true; + $this->_foundSample = $this->_processThumbnails ? false : true; + $this->_foundPAR2Info = false; + + $this->_passwordStatus = [Releases::PASSWD_NONE]; + $this->_releaseHasPassword = false; + + $this->_releaseGroupName = UsenetGroup::getNameByID($this->_release->groups_id); + + $this->_releaseHasNoNFO = false; + // Make sure we don't already have an nfo. + if ((int) $this->_release->nfostatus !== 1) { + $this->_releaseHasNoNFO = true; + } + + $this->_NZBHasCompressedFile = false; + + $this->_sampleMessageIDs = $this->_JPGMessageIDs = $this->_MediaInfoMessageIDs = []; + $this->_AudioInfoMessageIDs = $this->_RARFileMessageIDs = []; + $this->_AudioInfoExtension = ''; + + $this->_addedFileInfo = 0; + $this->_totalFileInfo = 0; + $this->_compressedFilesChecked = 0; + } + + /** + * Echo a string to CLI. + * + * @param string $string String to echo. + * @param string $type Method type. + * + * @void + */ + protected function _echo($string, $type): void + { + if ($this->_echoCLI) { + (new ColorCLI())->$type($string); + } + } + + /** + * Echo a string to CLI. For debugging. + * + * @param string $string + * + * @void + */ + protected function _debug($string): void + { + $this->_echo('DEBUG: '.$string, 'debug'); + } } diff --git a/Changelog b/Changelog index 407f6d0b0..9999b217f 100755 --- a/Changelog +++ b/Changelog @@ -1,5 +1,4 @@ 2019-03-18 DariusIII - * Chg: Update code style of PPA class * Chg: Update package.json * Chg: Remove casting $this->_release into array on line 2204 of PPA class * Chg: Don't send activation emails if site email is not set