$nzbContents */ public function plan(array $nzbContents, string $groupName): AdditionalWorkPlan { $sampleMessageIds = []; $jpgMessageIds = []; $mediaInfoMessageId = ''; $audioInfoMessageId = ''; $audioInfoExtension = ''; $archiveCandidates = []; $bookFileCount = 0; $duplicateMessageIdCount = 0; $seenMessageIds = []; foreach (array_values($nzbContents) as $sourceIndex => $file) { if (! is_array($file)) { continue; } try { $title = (string) ($file['title'] ?? ''); $segments = is_array($file['segments'] ?? null) ? $file['segments'] : []; if (preg_match($this->config->ignoreBookRegex, $title) === 1) { $bookFileCount++; } if (preg_match(self::ARCHIVE_PATTERN, $title) === 1) { $archiveMessageIds = $this->extractSegments( $segments, $this->config->maximumRarSegments, $seenMessageIds, $duplicateMessageIdCount, ); if ($archiveMessageIds !== []) { $archiveCandidates[] = new ArchiveCandidate( title: $title, messageIds: $archiveMessageIds, likelyFirstVolume: $this->isLikelyFirstVolume($title), sourceIndex: $sourceIndex, ); } } if ($this->isSupportFile($title)) { continue; } if ($this->config->processThumbnails && $sampleMessageIds === [] && $segments !== [] && stripos($title, 'sample') !== false && preg_match('/\.(?:jpe?g|png|webp)$/i', $title) !== 1 ) { $sampleMessageIds = $this->extractSegments( $segments, $this->config->segmentsToDownload, $seenMessageIds, $duplicateMessageIdCount, ); } if ($this->config->processJPGSample && $jpgMessageIds === [] && $segments !== [] && preg_match('/flac|lossless|mp3|music|inner-sanctum|sound/i', $groupName) !== 1 && preg_match('/\.(?:jpe?g|png|webp)[. ")\]]/i', $title) === 1 ) { $jpgMessageIds = $this->extractSegments( $segments, $this->config->segmentsToDownload, $seenMessageIds, $duplicateMessageIdCount, ); } if ($this->config->processMediaInfo && $mediaInfoMessageId === '' && isset($segments[0]) && stripos($title, 'sample') !== false && preg_match('/'.$this->config->videoFileRegex.'[. ")\]]/i', $title) === 1 ) { $mediaInfoMessageId = (string) $segments[0]; $this->recordMessageId($mediaInfoMessageId, $seenMessageIds, $duplicateMessageIdCount); } if ($this->config->processAudioInfo && $audioInfoMessageId === '' && isset($segments[0]) && preg_match('/'.$this->config->audioFileRegex.'[. ")\]]/i', $title, $type) === 1 ) { $audioInfoExtension = (string) ($type[1] ?? ''); $audioInfoMessageId = (string) $segments[0]; $this->recordMessageId($audioInfoMessageId, $seenMessageIds, $duplicateMessageIdCount); } } catch (\ErrorException $e) { Log::debug($e->getTraceAsString()); } } $bookFlood = $bookFileCount > 80 && ($bookFileCount * 2) >= count($nzbContents); $unsupportedReasons = []; if ($bookFlood) { $unsupportedReasons[] = 'book-flood'; } if ($archiveCandidates === [] && $sampleMessageIds === [] && $jpgMessageIds === [] && $mediaInfoMessageId === '' && $audioInfoMessageId === '' ) { $unsupportedReasons[] = 'no-supported-candidates'; } return new AdditionalWorkPlan( sampleMessageIds: $sampleMessageIds, jpgMessageIds: $jpgMessageIds, mediaInfoMessageId: $mediaInfoMessageId, audioInfoMessageId: $audioInfoMessageId, audioInfoExtension: $audioInfoExtension, archiveCandidates: $archiveCandidates, bookFileCount: $bookFileCount, bookFlood: $bookFlood, duplicateMessageIdCount: $duplicateMessageIdCount, unsupportedReasons: $unsupportedReasons, ); } private function isSupportFile(string $title): bool { return preg_match( '/(?:'.$this->config->supportFileRegex.'|nfo\b|inf\b|ofn\b)($|[ ")]|-])(?!.{20,})/i', $title, ) === 1; } private function isLikelyFirstVolume(string $title): bool { if (preg_match('/\.part0*(\d+)/i', $title, $part) === 1) { return (int) $part[1] === 1; } if (preg_match('/"[a-f0-9]{32}\.[1-9]\d{1,2}".*\((\d+)\/\d{2,}\)$/i', $title, $position) === 1) { return (int) $position[1] === 1; } return preg_match('/\.(rar|zip)($|[ ")]|-])/i', $title) === 1; } /** * @param array $segments * @param array $seenMessageIds * @return list */ private function extractSegments( array $segments, int $limit, array &$seenMessageIds, int &$duplicateMessageIdCount, ): array { $messageIds = []; $requestMessageIds = []; foreach (array_slice($segments, 0, max($limit, 0)) as $segment) { $messageId = (string) $segment; if ($messageId === '' || isset($requestMessageIds[$messageId])) { if ($messageId !== '') { $duplicateMessageIdCount++; } continue; } $requestMessageIds[$messageId] = true; $messageIds[] = $messageId; $this->recordMessageId($messageId, $seenMessageIds, $duplicateMessageIdCount); } return $messageIds; } /** * @param array $seenMessageIds */ private function recordMessageId(string $messageId, array &$seenMessageIds, int &$duplicateMessageIdCount): void { if (isset($seenMessageIds[$messageId])) { $duplicateMessageIdCount++; return; } $seenMessageIds[$messageId] = true; } }