adding initial code to support marking items as unplayed via state:import

This commit is contained in:
Abdulmhsen B. A. A
2022-05-23 08:41:59 +03:00
parent 75a00d4ae9
commit d02efab94b
8 changed files with 136 additions and 160 deletions

View File

@@ -263,6 +263,24 @@ final class StateEntity implements iFace
return $this->tainted;
}
public function getMetadata(string|null $via = null): array
{
if (null === $via) {
return $this->metadata;
}
return $this->metadata[$via] ?? [];
}
public function getExtra(string|null $via = null): array
{
if (null === $via) {
return $this->extra;
}
return $this->extra[$via] ?? [];
}
private function isEqual(iFace $entity): bool
{
foreach (iFace::ENTITY_KEYS as $key) {

View File

@@ -24,12 +24,14 @@ interface StateInterface
public const COLUMN_PARENT = 'parent';
public const COLUMN_GUIDS = 'guids';
public const COLUMN_META_DATA = 'metadata';
public const COLUMN_META_DATA_ADDED_AT = 'added_at';
public const COLUMN_META_DATA_PLAYED_AT = 'played_at';
public const COLUMN_META_DATA_EXTRA = 'extra';
public const COLUMN_META_DATA_EXTRA_TITLE = 'title';
public const COLUMN_META_DATA_EXTRA_DATE = 'date';
public const COLUMN_EXTRA = 'extra';
public const COLUMN_EXTRA_EVENT = 'event';
public const COLUMN_EXTRA_DATE = 'received_at';
public const COLUMN_META_DATA_EXTRA_DATE = 'date';
/**
* List of table keys.
@@ -239,4 +241,22 @@ interface StateInterface
* @return bool
*/
public function isTainted(): bool;
/**
* Get Metadata
*
* @param string|null $via if via is omitted, the entire "metadata" will be returned.
*
* @return array
*/
public function getMetadata(string|null $via = null): array;
/**
* Get extra.
*
* @param string|null $via if via is omitted, the entire "extra" will be returned.
*
* @return array
*/
public function getExtra(string|null $via = null): array;
}

View File

@@ -120,13 +120,15 @@ class EmbyServer extends JellyfinServer
}
$isTainted = in_array($event, self::WEBHOOK_TAINTED_EVENTS);
$playedAt = null;
if ('item.markplayed' === $event || 'playback.scrobble' === $event) {
$isWatched = 1;
$playedAt = time();
$isPlayed = 1;
} elseif ('item.markunplayed' === $event) {
$isWatched = 0;
$isPlayed = 0;
} else {
$isWatched = (int)(bool)ag($json, ['Item.Played', 'Item.PlayedToCompletion'], false);
$isPlayed = (int)(bool)ag($json, ['Item.Played', 'Item.PlayedToCompletion'], false);
}
$providersId = ag($json, 'Item.ProviderIds', []);
@@ -134,7 +136,7 @@ class EmbyServer extends JellyfinServer
$row = [
iFace::COLUMN_TYPE => $type,
iFace::COLUMN_UPDATED => time(),
iFace::COLUMN_WATCHED => $isWatched,
iFace::COLUMN_WATCHED => $isPlayed,
iFace::COLUMN_VIA => $this->name,
iFace::COLUMN_TITLE => ag($json, ['Item.Name', 'Item.OriginalTitle'], '??'),
iFace::COLUMN_YEAR => (int)ag($json, 'Item.ProductionYear', 0000),
@@ -146,7 +148,7 @@ class EmbyServer extends JellyfinServer
$this->name => [
iFace::COLUMN_ID => (string)ag($json, 'Item.ItemId'),
iFace::COLUMN_TYPE => $type,
iFace::COLUMN_WATCHED => (string)$isWatched,
iFace::COLUMN_WATCHED => (string)$isPlayed,
iFace::COLUMN_VIA => $this->name,
iFace::COLUMN_TITLE => ag($json, ['Item.Name', 'Item.OriginalTitle'], '??'),
iFace::COLUMN_YEAR => (string)ag($json, 'Item.ProductionYear', 0000),
@@ -165,6 +167,7 @@ class EmbyServer extends JellyfinServer
$row[iFace::COLUMN_TITLE] = ag($json, 'Item.SeriesName', '??');
$row[iFace::COLUMN_SEASON] = ag($json, 'Item.ParentIndexNumber', 0);
$row[iFace::COLUMN_EPISODE] = ag($json, 'Item.IndexNumber', 0);
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_TITLE] = ag($json, 'Item.SeriesName', '??');
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_SEASON] = (string)$row[iFace::COLUMN_SEASON];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_EPISODE] = (string)$row[iFace::COLUMN_EPISODE];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_TITLE] = ag(
@@ -178,9 +181,21 @@ class EmbyServer extends JellyfinServer
}
}
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
ag($json, ['Item.PremiereDate', 'Item.ProductionYear', 'Item.DateCreated'], 'now')
)->format('Y-m-d');
if (null !== ($premiereDate = ag($json, 'Item.PremiereDate'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
$premiereDate
)->format('Y-m-d');
}
if (null !== ($addedAt = ag($json, 'Item.DateCreated'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_ADDED_AT] = makeDate(
$addedAt
)->getTimestamp();
}
if (null !== $playedAt) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_PLAYED_AT] = $playedAt;
}
$entity = Container::get(iFace::class)::fromArray($row)->setIsTainted($isTainted);

View File

@@ -270,7 +270,7 @@ class JellyfinServer implements ServerInterface
'ITEM_ID' => ag($json, 'ItemId', ''),
'SERVER_ID' => ag($json, 'ServerId', ''),
'SERVER_NAME' => ag($json, 'ServerName', ''),
'SERVER_VERSION' => afterLast($userAgent, '/'),
'SERVER_VERSION' => ag($json, 'ServerVersion', fn() => afterLast($userAgent, '/')),
'USER_ID' => ag($json, 'UserId', ''),
'USER_NAME' => ag($json, 'NotificationUsername', ''),
'WH_EVENT' => ag($json, 'NotificationType', 'not_set'),
@@ -323,8 +323,8 @@ class JellyfinServer implements ServerInterface
$row = [
iFace::COLUMN_TYPE => $type,
iFace::COLUMN_UPDATED => strtotime(ag($json, ['UtcTimestamp', 'Timestamp'], 'now')),
iFace::COLUMN_WATCHED => (int)(bool)ag($json, ['Played', 'PlayedToCompletion'], 0),
iFace::COLUMN_UPDATED => strtotime(ag($json, ['LastPlayedDate', 'UtcTimestamp', 'Timestamp'], 'now')),
iFace::COLUMN_WATCHED => (int)(bool)ag($json, 'Played', 0),
iFace::COLUMN_VIA => $this->name,
iFace::COLUMN_TITLE => ag($json, ['Name', 'OriginalTitle'], '??'),
iFace::COLUMN_YEAR => (int)ag($json, 'Year', 0000),
@@ -336,7 +336,7 @@ class JellyfinServer implements ServerInterface
$this->name => [
iFace::COLUMN_ID => (string)ag($json, 'ItemId'),
iFace::COLUMN_TYPE => $type,
iFace::COLUMN_WATCHED => (string)(int)(bool)ag($json, ['Played', 'PlayedToCompletion'], 0),
iFace::COLUMN_WATCHED => (string)(int)(bool)ag($json, 'Played', 0),
iFace::COLUMN_VIA => $this->name,
iFace::COLUMN_TITLE => ag($json, ['Name', 'OriginalTitle'], '??'),
iFace::COLUMN_YEAR => (string)ag($json, 'Year', 0000),
@@ -357,6 +357,7 @@ class JellyfinServer implements ServerInterface
$row[iFace::COLUMN_TITLE] = $seriesName ?? '??';
$row[iFace::COLUMN_SEASON] = ag($json, 'SeasonNumber', 0);
$row[iFace::COLUMN_EPISODE] = ag($json, 'EpisodeNumber', 0);
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_TITLE] = $seriesName ?? '??';
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_SEASON] = (string)$row[iFace::COLUMN_SEASON];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_EPISODE] = (string)$row[iFace::COLUMN_EPISODE];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_TITLE] = ag(
@@ -373,9 +374,23 @@ class JellyfinServer implements ServerInterface
}
}
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
ag($json, ['PremiereDate', 'ProductionYear', 'DateCreated'], 'now')
)->format('Y-m-d');
if (null !== ($premiereDate = ag($json, 'PremiereDate'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
$premiereDate
)->format('Y-m-d');
}
if (null !== ($addedAt = ag($json, 'DateCreated'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_ADDED_AT] = makeDate(
$addedAt
)->getTimestamp();
}
if (null !== ($lastPlayedAt = ag($json, 'LastPlayedDate'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_PLAYED_AT] = makeDate(
$lastPlayedAt
)->getTimestamp();
}
$entity = Container::get(iFace::class)::fromArray($row)->setIsTainted($isTainted);
@@ -809,7 +824,7 @@ class JellyfinServer implements ServerInterface
}
if (false === (bool)ag($this->options, Options::IGNORE_DATE, false)) {
$date = ag($json, ['UserData.LastPlayedDate', 'DateCreated', 'PremiereDate'], null);
$date = ag($json, ['UserData.LastPlayedDate', 'DateCreated'], null);
if (null === $date) {
$this->logger->error(
@@ -986,100 +1001,6 @@ class JellyfinServer implements ServerInterface
);
}
public function cache(): array
{
return $this->getLibraries(
ok: function (string $cName, string $type) {
return function (ResponseInterface $response) use ($cName, $type) {
if (200 !== $response->getStatusCode()) {
$this->logger->error(
sprintf(
'%s: Request to \'%s\' responded with unexpected http status code \'%d\'.',
$this->name,
$cName,
$response->getStatusCode()
)
);
return;
}
try {
$this->logger->info(sprintf('%s: Parsing \'%s\' response.', $this->name, $cName));
$it = Items::fromIterable(
httpClientChunks($this->http->stream($response)),
[
'pointer' => '/Items',
'decoder' => new ErrorWrappingDecoder(
new ExtJsonDecoder(options: JSON_INVALID_UTF8_IGNORE)
)
]
);
foreach ($it as $entity) {
if ($entity instanceof DecodingError) {
$this->logger->warning(
sprintf(
'%s: Failed to decode one of \'%s\' items. %s',
$this->name,
$cName,
$entity->getErrorMessage()
),
[
'payload' => $entity->getMalformedJson()
]
);
continue;
}
$this->processCache($entity, $type, $cName);
}
} catch (PathNotFoundException $e) {
$this->logger->error(
sprintf(
'%s: Failed to find items in \'%s\' response. %s',
$this->name,
$cName,
$e->getMessage()
),
[
'file' => $e->getFile(),
'line' => $e->getLine(),
'kind' => get_class($e),
],
);
} catch (Throwable $e) {
$this->logger->error(
sprintf(
'%s: Failed to handle \'%s\' response. %s',
$this->name,
$cName,
$e->getMessage(),
),
[
'file' => $e->getFile(),
'line' => $e->getLine(),
'kind' => get_class($e),
],
);
}
$this->logger->info(sprintf('%s: Parsing \'%s\' response is complete.', $this->name, $cName));
};
},
error: function (string $cName, string $type, UriInterface|string $url) {
return fn(Throwable $e) => $this->logger->error(
sprintf('%s: Error encountered in \'%s\' request. %s', $this->name, $cName, $e->getMessage()),
[
'url' => $url,
'file' => $e->getFile(),
'line' => $e->getLine(),
]
);
},
includeParent: true
);
}
/**
* @throws InvalidArgumentException
*/
@@ -1365,7 +1286,7 @@ class JellyfinServer implements ServerInterface
]);
}
$date = $item->UserData?->LastPlayedDate ?? $item->DateCreated ?? $item->PremiereDate ?? null;
$date = $item->UserData->LastPlayedDate ?? $item->DateCreated ?? null;
if (null === $date) {
$this->logger->warning(
@@ -1433,30 +1354,6 @@ class JellyfinServer implements ServerInterface
}
}
protected function processCache(StdClass $item, string $type, string $library): void
{
try {
if ('show' === $type) {
$this->processShow($item, $library);
return;
}
$date = $item->UserData?->LastPlayedDate ?? $item->DateCreated ?? $item->PremiereDate ?? null;
if (null === $date) {
return;
}
$this->createEntity($item, $type);
} catch (Throwable $e) {
$this->logger->error(sprintf('%s: %s', $this->name, $e->getMessage()), [
'file' => $e->getFile(),
'line' => $e->getLine(),
'kind' => get_class($e),
]);
}
}
protected function processExport(
ExportInterface $mapper,
string $type,
@@ -1486,7 +1383,7 @@ class JellyfinServer implements ServerInterface
);
}
$date = $item->UserData?->LastPlayedDate ?? $item->DateCreated ?? $item->PremiereDate ?? null;
$date = $item->UserData?->LastPlayedDate ?? $item->DateCreated ?? null;
if (null === $date) {
$this->logger->notice(
@@ -1700,12 +1597,16 @@ class JellyfinServer implements ServerInterface
protected function createEntity(stdClass $item, string $type): StateEntity
{
$date = strtotime($item->UserData?->LastPlayedDate ?? $item->DateCreated ?? $item->PremiereDate);
$date = $item->UserData->LastPlayedDate ?? $item->DateCreated ?? null;
if (null === $date) {
throw new RuntimeException('No date was set on object.');
}
$row = [
iFace::COLUMN_TYPE => $type,
iFace::COLUMN_UPDATED => $date,
iFace::COLUMN_WATCHED => (int)(bool)($item->UserData?->Played ?? false),
iFace::COLUMN_UPDATED => makeDate($date)->getTimestamp(),
iFace::COLUMN_WATCHED => (int)(bool)($item->UserData->Played ?? false),
iFace::COLUMN_VIA => $this->name,
iFace::COLUMN_TITLE => $item->Name ?? $item->OriginalTitle ?? '??',
iFace::COLUMN_YEAR => (int)($item->ProductionYear ?? 0000),
@@ -1717,11 +1618,12 @@ class JellyfinServer implements ServerInterface
$this->name => [
iFace::COLUMN_ID => (string)$item->Id,
iFace::COLUMN_TYPE => $type,
iFace::COLUMN_WATCHED => (string)(int)(bool)($item->UserData?->Played ?? false),
iFace::COLUMN_WATCHED => (string)(int)(bool)($item->UserData->Played ?? false),
iFace::COLUMN_VIA => $this->name,
iFace::COLUMN_TITLE => $item->Name ?? $item->OriginalTitle ?? '??',
iFace::COLUMN_YEAR => (string)($item->ProductionYear ?? 0000),
iFace::COLUMN_GUIDS => array_change_key_case((array)($item->ProviderIds ?? []), CASE_LOWER),
iFace::COLUMN_META_DATA_ADDED_AT => (string)makeDate($item->DateCreated)->getTimestamp(),
],
],
iFace::COLUMN_EXTRA => [],
@@ -1731,6 +1633,7 @@ class JellyfinServer implements ServerInterface
$row[iFace::COLUMN_TITLE] = $item->SeriesName ?? '??';
$row[iFace::COLUMN_SEASON] = $item->ParentIndexNumber ?? 0;
$row[iFace::COLUMN_EPISODE] = $item->IndexNumber ?? 0;
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_TITLE] = $item->SeriesName ?? '??';
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_SEASON] = (string)$row[iFace::COLUMN_SEASON];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_EPISODE] = (string)$row[iFace::COLUMN_EPISODE];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_TITLE] = $item->Name ?? $item->OriginalTitle ?? '??';
@@ -1741,9 +1644,17 @@ class JellyfinServer implements ServerInterface
}
}
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
$item->PremiereDate ?? $item->ProductionYear ?? 'now'
)->format('Y-m-d');
if (null !== ($item->PremiereDate ?? null)) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
$item->PremiereDate
)->format('Y-m-d');
}
if (null !== ($item->UserData->LastPlayedDate ?? null)) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_PLAYED_AT] = (string)makeDate(
$item->UserData->LastPlayedDate
)->getTimestamp();
}
return Container::get(iFace::class)::fromArray($row);
}

View File

@@ -385,6 +385,7 @@ class PlexServer implements ServerInterface
iFace::COLUMN_TITLE => ag($item, ['title', 'originalTitle'], '??'),
iFace::COLUMN_YEAR => (string)ag($item, ['grandParentYear', 'parentYear', 'year'], 0000),
iFace::COLUMN_GUIDS => $this->parseGuids(ag($item, 'Guid', [])),
iFace::COLUMN_META_DATA_ADDED_AT => (string)ag($item, 'addedAt'),
],
],
iFace::COLUMN_EXTRA => [
@@ -399,6 +400,7 @@ class PlexServer implements ServerInterface
$row[iFace::COLUMN_TITLE] = ag($item, 'grandparentTitle', '??');
$row[iFace::COLUMN_SEASON] = ag($item, 'parentIndex', 0);
$row[iFace::COLUMN_EPISODE] = ag($item, 'index', 0);
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_TITLE] = ag($item, 'grandparentTitle', '??');
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_SEASON] = (string)$row[iFace::COLUMN_SEASON];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_EPISODE] = (string)$row[iFace::COLUMN_EPISODE];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_TITLE] = ag(
@@ -413,11 +415,15 @@ class PlexServer implements ServerInterface
}
}
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
ag($item, 'originallyAvailableAt', 'now')
)->format(
'Y-m-d'
);
if (null !== ($premiereDate = ag($item, 'originallyAvailableAt'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
$premiereDate
)->format('Y-m-d');
}
if (null !== ($lastPlayedAt = ag($item, 'lastViewedAt'))) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_PLAYED_AT] = (string)$lastPlayedAt;
}
$entity = Container::get(iFace::class)::fromArray($row)->setIsTainted($isTainted);
@@ -835,11 +841,7 @@ 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, 'updatedAt', 0),
(int)ag($json, 'addedAt', 0)
);
$date = max((int)ag($json, 'lastViewedAt', 0), (int)ag($json, 'addedAt', 0));
if (0 === $date) {
$this->logger->error(
@@ -1298,7 +1300,7 @@ class PlexServer implements ServerInterface
]);
}
$date = (int)($item->lastViewedAt ?? $item->updatedAt ?? $item->addedAt ?? 0);
$date = max((int)($item->lastViewedAt ?? 0), (int)($item->addedAt ?? 0));
if (0 === $date) {
$this->logger->debug(
@@ -1385,9 +1387,9 @@ class PlexServer implements ServerInterface
);
}
$date = $item->lastViewedAt ?? $item->updatedAt ?? $item->addedAt ?? null;
$date = max((int)($item->lastViewedAt ?? 0), (int)($item->addedAt ?? 0));
if (null === $date) {
if (0 === $date) {
$this->logger->notice(
sprintf('%s: Ignoring \'%s\'. Date is not set on backend object.', $this->name, $iName),
[
@@ -1752,7 +1754,7 @@ class PlexServer implements ServerInterface
$item->Guid[] = ['id' => $item->guid];
}
$date = (int)($item->lastViewedAt ?? $item->updatedAt ?? $item->addedAt ?? 0);
$date = max((int)($item->lastViewedAt ?? 0), (int)($item->addedAt ?? 0));
$row = [
iFace::COLUMN_TYPE => $type,
@@ -1774,6 +1776,7 @@ class PlexServer implements ServerInterface
iFace::COLUMN_TITLE => $item->title ?? $item->originalTitle ?? '??',
iFace::COLUMN_YEAR => (string)($item->grandParentYear ?? $item->parentYear ?? $item->year ?? 0000),
iFace::COLUMN_GUIDS => $this->parseGuids($item->Guid ?? []),
iFace::COLUMN_META_DATA_ADDED_AT => (string)$item->addedAt,
],
],
iFace::COLUMN_EXTRA => [],
@@ -1783,6 +1786,7 @@ class PlexServer implements ServerInterface
$row[iFace::COLUMN_TITLE] = $item->grandparentTitle ?? '??';
$row[iFace::COLUMN_SEASON] = $item->parentIndex ?? 0;
$row[iFace::COLUMN_EPISODE] = $item->index ?? 0;
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_TITLE] = $item->grandparentTitle ?? '??';
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_SEASON] = (string)$row[iFace::COLUMN_SEASON];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_EPISODE] = (string)$row[iFace::COLUMN_EPISODE];
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_TITLE] = $item->title ?? $item->originalTitle ?? '??';
@@ -1797,10 +1801,14 @@ class PlexServer implements ServerInterface
if (null !== ($item->originallyAvailableAt ?? null)) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_EXTRA][iFace::COLUMN_META_DATA_EXTRA_DATE] = makeDate(
$item->originallyAvailableAt ?? 'now'
$item->originallyAvailableAt
)->format('Y-m-d');
}
if (null !== ($item->lastViewedAt ?? null)) {
$row[iFace::COLUMN_META_DATA][$this->name][iFace::COLUMN_META_DATA_PLAYED_AT] = (string)$item->lastViewedAt;
}
return Container::get(iFace::class)::fromArray($row);
}

View File

@@ -258,7 +258,7 @@ if (!function_exists('saveWebhookPayload')) {
Config::get('tmpDir') . '/webhooks/' . sprintf(
'webhook.%s.%s.%s.json',
$name,
ag($state->extra, 'webhook.event', 'unknown'),
ag($state->getExtra(), 'event', 'unknown'),
ag($request->getServerParams(), 'X_REQUEST_ID', time())
),
json_encode(value: $content, flags: JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)