From d04d398ac0343005bb80a96452b10367ba4704ee Mon Sep 17 00:00:00 2001 From: "Abdulmhsen B. A. A" Date: Wed, 1 Jun 2022 14:12:34 +0300 Subject: [PATCH] Added more strict date checks. --- src/Libs/Initializer.php | 8 +----- src/Libs/Servers/JellyfinServer.php | 33 +++++++++++++++-------- src/Libs/Servers/PlexServer.php | 42 ++++++++++++++++------------- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/src/Libs/Initializer.php b/src/Libs/Initializer.php index f857dac2..0d356654 100644 --- a/src/Libs/Initializer.php +++ b/src/Libs/Initializer.php @@ -371,15 +371,9 @@ final class Initializer ); } - if ($local->updated > $entity->updated) { - $message = sprintf('%s date is older than the recorded date in storage.', ucfirst($entity->type)); - } else { - $message = '[D] No difference detected.'; - } - return new Response( status: 200, - headers: $responseHeaders + ['X-Status' => $message] + headers: $responseHeaders + ['X-Status' => '[D] No difference detected.'] ); } diff --git a/src/Libs/Servers/JellyfinServer.php b/src/Libs/Servers/JellyfinServer.php index cff335be..ea9773f5 100644 --- a/src/Libs/Servers/JellyfinServer.php +++ b/src/Libs/Servers/JellyfinServer.php @@ -316,7 +316,7 @@ class JellyfinServer implements ServerInterface try { $isPlayed = (bool)ag($json, 'Played'); - $lastPlayedAt = ag($json, 'LastPlayedDate'); + $lastPlayedAt = true === $isPlayed ? ag($json, 'LastPlayedDate') : null; $fields = [ iFace::COLUMN_EXTRA => [ @@ -465,7 +465,7 @@ class JellyfinServer implements ServerInterface 'title' => $episodeNumber . mb_substr(ag($item, ['Name', 'OriginalTitle'], '??'), 0, 50), 'year' => $year, 'addedAt' => makeDate(ag($item, 'DateCreated', 'now'))->format('Y-m-d H:i:s T'), - 'watchedAt' => null !== $watchedAt ? makeDate($watchedAt)->format('Y-m-d H:i:s T') : 'None', + 'watchedAt' => null !== $watchedAt ? makeDate($watchedAt)->format('Y-m-d H:i:s T') : 'Never', ]; if (true === (bool)ag($opts, Options::RAW_RESPONSE)) { @@ -1179,7 +1179,8 @@ class JellyfinServer implements ServerInterface } if (false === (bool)ag($this->options, Options::IGNORE_DATE, false)) { - $date = ag($json, ['UserData.LastPlayedDate', 'DateCreated'], null); + $isPlayed = true === (bool)ag($json, 'UserData.Played'); + $date = ag($json, true === $isPlayed ? 'UserData.LastPlayedDate' : 'DateCreated'); if (null === $date) { $this->logger->error( @@ -1673,7 +1674,9 @@ class JellyfinServer implements ServerInterface ]); } - if (null === ag($item, ['UserData.LastPlayedDate', 'DateCreated'])) { + $isPlayed = true === (bool)ag($item, 'UserData.Played'); + + if (null === ag($item, true === $isPlayed ? 'UserData.LastPlayedDate' : 'DateCreated')) { $this->logger->warning( sprintf('%s: Ignoring \'%s\'. Date is not set on backend object.', $this->name, $iName), [ @@ -1775,7 +1778,9 @@ class JellyfinServer implements ServerInterface ); } - if (null === ag($item, ['UserData.LastPlayedDate', 'DateCreated'])) { + $isPlayed = true === (bool)ag($item, 'UserData.Played'); + + if (null === ag($item, true === $isPlayed ? 'UserData.LastPlayedDate' : 'DateCreated')) { $this->logger->notice( sprintf('%s: Ignoring \'%s\'. Date is not set on backend object.', $this->name, $iName), [ @@ -1979,7 +1984,11 @@ class JellyfinServer implements ServerInterface protected function createEntity(array $item, string $type, array $opts = []): StateEntity { - if (null === ($date = ag($item, ['UserData.LastPlayedDate', 'DateCreated', 'PremiereDate'], null))) { + $isPlayed = (bool)ag($item, 'UserData.Played', false); + + $date = ag($item, true === $isPlayed ? 'UserData.LastPlayedDate' : 'DateCreated'); + + if (null === $date) { throw new RuntimeException('No date was set on object.'); } @@ -1989,7 +1998,7 @@ class JellyfinServer implements ServerInterface $builder = [ iFace::COLUMN_TYPE => $type, iFace::COLUMN_UPDATED => makeDate($date)->getTimestamp(), - iFace::COLUMN_WATCHED => (int)(bool)ag($item, 'UserData.Played', false), + iFace::COLUMN_WATCHED => (int)$isPlayed, iFace::COLUMN_VIA => $this->name, iFace::COLUMN_TITLE => ag($item, ['Name', 'OriginalTitle'], '??'), iFace::COLUMN_GUIDS => $guids, @@ -1997,7 +2006,7 @@ class JellyfinServer implements ServerInterface $this->name => [ iFace::COLUMN_ID => (string)ag($item, 'Id'), iFace::COLUMN_TYPE => $type, - iFace::COLUMN_WATCHED => (string)(int)(bool)ag($item, 'UserData.Played', false), + iFace::COLUMN_WATCHED => true === $isPlayed ? '1' : '0', iFace::COLUMN_VIA => $this->name, iFace::COLUMN_TITLE => ag($item, ['Name', 'OriginalTitle'], '??'), iFace::COLUMN_GUIDS => array_change_key_case((array)ag($item, 'ProviderIds', []), CASE_LOWER), @@ -2045,13 +2054,15 @@ class JellyfinServer implements ServerInterface $metadataExtra[iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate($PremieredAt)->format('Y-m-d'); } - if (null !== ($playedAt = ag($item, 'UserData.LastPlayedDate'))) { - $metadata[iFace::COLUMN_META_DATA_PLAYED_AT] = (string)makeDate($playedAt)->getTimestamp(); + if (true === $isPlayed) { + $metadata[iFace::COLUMN_META_DATA_PLAYED_AT] = (string)makeDate($date)->getTimestamp(); } unset($metadata, $metadataExtra); - $builder = array_replace_recursive($builder, $opts['override'] ?? []); + if (null !== ($opts['override'] ?? null)) { + $builder = array_replace_recursive($builder, $opts['override'] ?? []); + } return Container::get(iFace::class)::fromArray($builder); } diff --git a/src/Libs/Servers/PlexServer.php b/src/Libs/Servers/PlexServer.php index 9d59aa33..2050e1e4 100644 --- a/src/Libs/Servers/PlexServer.php +++ b/src/Libs/Servers/PlexServer.php @@ -363,7 +363,7 @@ class PlexServer implements ServerInterface try { $isPlayed = (bool)ag($item, 'viewCount', false); - $lastPlayedAt = ag($item, 'lastViewedAt'); + $lastPlayedAt = true === $isPlayed ? ag($item, 'lastViewedAt') : null; $fields = [ iFace::COLUMN_EXTRA => [ @@ -505,7 +505,7 @@ class PlexServer implements ServerInterface 'title' => $episodeNumber . mb_substr(ag($item, ['title', 'originalTitle'], '??'), 0, 50), 'year' => $year, 'addedAt' => makeDate(ag($item, 'addedAt'))->format('Y-m-d H:i:s T'), - 'watchedAt' => null !== $watchedAt ? makeDate($watchedAt)->format('Y-m-d H:i:s T') : 'None', + 'watchedAt' => null !== $watchedAt ? makeDate($watchedAt)->format('Y-m-d H:i:s T') : 'Never', ]; if (true === (bool)ag($opts, Options::RAW_RESPONSE)) { @@ -553,7 +553,7 @@ class PlexServer implements ServerInterface 'title' => $episodeNumber . mb_substr(ag($metadata, ['title', 'originalTitle'], '??'), 0, 50), 'year' => $year, 'addedAt' => makeDate(ag($metadata, 'addedAt'))->format('Y-m-d H:i:s T'), - 'watchedAt' => null !== $watchedAt ? makeDate($watchedAt)->format('Y-m-d H:i:s T') : 'None', + 'watchedAt' => null !== $watchedAt ? makeDate($watchedAt)->format('Y-m-d H:i:s T') : 'Never', 'duration' => ag($metadata, 'duration') ? formatDuration(ag($metadata, 'duration')) : 'None', ]; @@ -1198,9 +1198,9 @@ class PlexServer implements ServerInterface $isWatched = (int)(bool)ag($json, 'viewCount', 0); if (false === (bool)ag($this->options, Options::IGNORE_DATE, false)) { - $date = max((int)ag($json, 'lastViewedAt', 0), (int)ag($json, 'addedAt', 0)); + $date = ag($json, true === (bool)ag($json, 'viewCount', false) ? 'lastViewedAt' : 'addedAt'); - if (0 === $date) { + if (null === $date) { $this->logger->error( sprintf( '%s: Ignoring \'%s\'. No date is set on backend object.', @@ -1683,9 +1683,7 @@ class PlexServer implements ServerInterface ]); } - $date = max((int)ag($item, 'lastViewedAt', 0), (int)ag($item, 'addedAt', 0)); - - if (0 === $date) { + if (null === ag($item, true === (bool)ag($item, 'viewCount', false) ? 'lastViewedAt' : 'addedAt')) { $this->logger->debug( sprintf('%s: Ignoring \'%s\'. Date is not set on backend object.', $this->name, $iName), [ @@ -1772,9 +1770,7 @@ class PlexServer implements ServerInterface ); } - $date = max((int)ag($item, 'lastViewedAt', 0), (int)ag($item, 'addedAt', 0)); - - if (0 === $date) { + if (null === ag($item, true === (bool)ag($item, 'viewCount', false) ? 'lastViewedAt' : 'addedAt')) { $this->logger->notice( sprintf('%s: Ignoring \'%s\'. Date is not set on backend object.', $this->name, $iName), [ @@ -2139,21 +2135,27 @@ class PlexServer implements ServerInterface $item = (array)$item; } + // -- Plex does not send played flag, so we have to rely on viewCount. + $isPlayed = (bool)ag($item, 'viewCount', false); + $date = ag($item, true === $isPlayed ? 'lastViewedAt' : 'addedAt'); + + if (null === $date) { + throw new RuntimeException('No date was set on object.'); + } + if (null === ag($item, 'Guid')) { $item['Guid'] = [['id' => ag($item, 'guid')]]; } else { $item['Guid'][] = ['id' => ag($item, 'guid')]; } - $date = max((int)ag($item, 'lastViewedAt', 0), (int)(ag($item, 'addedAt', 0))); - $guids = $this->getGuids(ag($item, 'Guid', [])); $guids += Guid::makeVirtualGuid($this->name, (string)ag($item, 'ratingKey')); $builder = [ iFace::COLUMN_TYPE => $type, - iFace::COLUMN_UPDATED => $date, - iFace::COLUMN_WATCHED => (int)(bool)ag($item, 'viewCount', false), + iFace::COLUMN_UPDATED => (int)$date, + iFace::COLUMN_WATCHED => (int)$isPlayed, iFace::COLUMN_VIA => $this->name, iFace::COLUMN_TITLE => ag($item, ['title', 'originalTitle'], '??'), iFace::COLUMN_GUIDS => $guids, @@ -2161,7 +2163,7 @@ class PlexServer implements ServerInterface $this->name => [ iFace::COLUMN_ID => (string)ag($item, 'ratingKey'), iFace::COLUMN_TYPE => $type, - iFace::COLUMN_WATCHED => (string)(int)(bool)ag($item, 'viewCount', false), + iFace::COLUMN_WATCHED => true === $isPlayed ? '1' : '0', iFace::COLUMN_VIA => $this->name, iFace::COLUMN_TITLE => ag($item, ['title', 'originalTitle'], '??'), iFace::COLUMN_GUIDS => $this->parseGuids(ag($item, 'Guid', [])), @@ -2206,13 +2208,15 @@ class PlexServer implements ServerInterface $metadataExtra[iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate($PremieredAt)->format('Y-m-d'); } - if (null !== ($playedAt = ag($item, 'lastViewedAt'))) { - $metadata[iFace::COLUMN_META_DATA_PLAYED_AT] = (string)$playedAt; + if (true === $isPlayed) { + $metadata[iFace::COLUMN_META_DATA_PLAYED_AT] = (string)$date; } unset($metadata, $metadataExtra); - $builder = array_replace_recursive($builder, $opts['override'] ?? []); + if (null !== ($opts['override'] ?? null)) { + $builder = array_replace_recursive($builder, $opts['override'] ?? []); + } return Container::get(iFace::class)::fromArray($builder); }