diff --git a/composer.lock b/composer.lock index 6278c035..7f5c9890 100644 --- a/composer.lock +++ b/composer.lock @@ -3342,12 +3342,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "504a245ede435b003e091df51766403ed446f5bf" + "reference": "0e5a0abdd695cd45870e442647ef03a70f2ec1e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/504a245ede435b003e091df51766403ed446f5bf", - "reference": "504a245ede435b003e091df51766403ed446f5bf", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/0e5a0abdd695cd45870e442647ef03a70f2ec1e5", + "reference": "0e5a0abdd695cd45870e442647ef03a70f2ec1e5", "shasum": "" }, "conflict": { @@ -3440,7 +3440,7 @@ "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.27", "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1", - "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.12", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.17", "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", "ezsystems/ezplatform-richtext": ">=2.3,<=2.3.7", "ezsystems/ezplatform-user": ">=1,<1.0.1", @@ -3450,7 +3450,7 @@ "ezsystems/repository-forms": ">=2.3,<2.3.2.1", "ezyang/htmlpurifier": "<4.1.1", "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", - "facturascripts/facturascripts": "<2022.4", + "facturascripts/facturascripts": "<2022.6", "feehi/cms": "<=2.1.1", "feehi/feehicms": "<=0.1.3", "fenom/fenom": "<=2.12.1", @@ -3821,7 +3821,7 @@ "type": "tidelift" } ], - "time": "2022-04-29T16:08:59+00:00" + "time": "2022-04-29T21:04:00+00:00" }, { "name": "sebastian/cli-parser", diff --git a/config/config.php b/config/config.php index 39152c19..5b816fb6 100644 --- a/config/config.php +++ b/config/config.php @@ -107,7 +107,7 @@ return (function () { 'type' => 'syslog', 'docker' => false, 'facility' => env('WS_LOGGER_SYSLOG_FACILITY', LOG_USER), - 'enabled' => env('WS_LOGGER_SYSLOG_ENABLED', false), + 'enabled' => env('WS_LOGGER_SYSLOG_ENABLED', !env('IN_DOCKER')), 'level' => env('WS_LOGGER_SYSLOG_LEVEL', Logger::ERROR), 'name' => env('WS_LOGGER_SYSLOG_NAME', ag($config, 'name')), ], diff --git a/src/Libs/Servers/JellyfinServer.php b/src/Libs/Servers/JellyfinServer.php index 1598b3a6..d1117179 100644 --- a/src/Libs/Servers/JellyfinServer.php +++ b/src/Libs/Servers/JellyfinServer.php @@ -1632,7 +1632,7 @@ class JellyfinServer implements ServerInterface } if (!empty($this->cacheShowKey)) { - $this->cache->set($this->cacheShowKey, $this->cacheShow, new DateInterval('PT5M')); + $this->cache->set($this->cacheShowKey, $this->cacheShow, new DateInterval('PT30M')); } } diff --git a/src/Libs/Servers/PlexServer.php b/src/Libs/Servers/PlexServer.php index 1c8c8532..0656c09d 100644 --- a/src/Libs/Servers/PlexServer.php +++ b/src/Libs/Servers/PlexServer.php @@ -15,6 +15,7 @@ use App\Libs\Mappers\ImportInterface; use Closure; use DateInterval; use DateTimeInterface; +use Exception; use JsonException; use JsonMachine\Exception\PathNotFoundException; use JsonMachine\Items; @@ -86,6 +87,8 @@ class PlexServer implements ServerInterface protected string|int|null $user = null; protected array $showInfo = []; + protected array $cacheShow = []; + protected string $cacheShowKey = ''; public function __construct( protected HttpClientInterface $http, @@ -117,11 +120,16 @@ class PlexServer implements ServerInterface $cloned->options = $options; $cloned->persist = $persist; $cloned->cacheKey = $opts['cache_key'] ?? md5(__CLASS__ . '.' . $name . $url); + $cloned->cacheShowKey = $cloned->cacheKey . '_show'; if ($cloned->cache->has($cloned->cacheKey)) { $cloned->cacheData = $cloned->cache->get($cloned->cacheKey); } + if ($cloned->cache->has($cloned->cacheShowKey)) { + $cloned->cacheShow = $cloned->cache->get($cloned->cacheShowKey); + } + $cloned->initialized = true; return $cloned; @@ -302,6 +310,8 @@ class PlexServer implements ServerInterface throw new HttpException(sprintf('%s: Not allowed event [%s]', afterLast(__CLASS__, '\\'), $event), 200); } + $isTainted = in_array($event, self::WEBHOOK_TAINTED_EVENTS); + $ignoreIds = null; if (null !== ($this->options['ignore'] ?? null)) { @@ -370,12 +380,18 @@ class PlexServer implements ServerInterface ); } - $guids = $this->getGuids($type, $json['Metadata']['Guid'] ?? []); + $guids = $this->getGuids($json['Metadata']['Guid'] ?? [], $type); foreach (Guid::fromArray($guids)->getPointers() as $guid) { $this->cacheData[$guid] = ag($json, 'Metadata.guid'); } + if (false === $isTainted && StateInterface::TYPE_EPISODE === $type) { + $meta['parent'] = $this->getParentGUIDs( + $json['Metadata']['grandparentRatingKey'] ?? $json['Metadata']['parentRatingKey'] + ); + } + $row = [ 'type' => $type, 'updated' => $date, @@ -388,9 +404,85 @@ class PlexServer implements ServerInterface saveWebhookPayload($request, "{$this->name}.{$event}", $json + ['entity' => $row]); } - return Container::get(StateInterface::class)::fromArray($row)->setIsTainted( - in_array($event, self::WEBHOOK_TAINTED_EVENTS) - ); + return Container::get(StateInterface::class)::fromArray($row)->setIsTainted($isTainted); + } + + protected function getParentGUIDs(mixed $id): array + { + if (array_key_exists($id, $this->cacheShow)) { + return $this->cacheShow[$id]; + } + + try { + $response = $this->http->request( + 'GET', + (string)$this->url->withPath('/library/metadata/' . $id), + $this->getHeaders() + ); + + if (200 !== $response->getStatusCode()) { + return []; + } + + $json = json_decode($response->getContent(), true, flags: JSON_THROW_ON_ERROR); + + $json = ag($json, 'MediaContainer.Metadata')[0] ?? []; + + if (null === ($type = ag($json, 'type'))) { + return []; + } + + if ('show' !== strtolower($type)) { + return []; + } + + if (null === ($json['Guid'] ?? null)) { + $json['Guid'] = [['id' => $json['guid']]]; + } else { + $json['Guid'][] = ['id' => $json['guid']]; + } + + + if (!$this->hasSupportedIds($json['Guid'])) { + $this->cacheShow[$id] = []; + return $this->cacheShow[$id]; + } + + $guids = []; + + foreach (Guid::fromArray($this->getGuids($json['Guid']))->getPointers() as $guid) { + [$type, $id] = explode('://', $guid); + $guids[$type] = $id; + } + + $this->cacheShow[$id] = $guids; + + return $this->cacheShow[$id]; + } catch (ExceptionInterface $e) { + $this->logger->error($e->getMessage(), [ + 'file' => $e->getFile(), + 'line' => $e->getLine() + ]); + return []; + } catch (JsonException $e) { + $this->logger->error( + sprintf('Unable to decode %s response. Reason: \'%s\'.', $this->name, $e->getMessage()), + [ + 'file' => $e->getFile(), + 'line' => $e->getLine() + ] + ); + return []; + } catch (Exception $e) { + $this->logger->error( + sprintf('ERROR: %s response. Reason: \'%s\'.', $this->name, $e->getMessage()), + [ + 'file' => $e->getFile(), + 'line' => $e->getLine() + ] + ); + return []; + } } private function getHeaders(): array @@ -1617,6 +1709,10 @@ class PlexServer implements ServerInterface if (!empty($this->cacheKey) && !empty($this->cacheData) && true === $this->initialized) { $this->cache->set($this->cacheKey, $this->cacheData, new DateInterval('P1Y')); } + + if (!empty($this->cacheShowKey) && !empty($this->cacheShow) && true === $this->initialized) { + $this->cache->set($this->cacheShowKey, $this->cacheShow, new DateInterval('PT30M')); + } } /**