Update History to use GraphQL, resolves #29,#30

This commit is contained in:
Timothy Warren 2020-08-24 19:17:41 -04:00
parent e944ddc75c
commit e890f978db
5 changed files with 64 additions and 97 deletions

View File

@ -102,10 +102,7 @@ trait AnimeTrait {
{ {
$raw = $this->getRawHistoryList('anime'); $raw = $this->getRawHistoryList('anime');
$organized = JsonAPI::organizeData($raw); $list = (new AnimeHistoryTransformer())->transform($raw);
$organized = array_filter($organized, fn ($item) => array_key_exists('relationships', $item));
$list = (new AnimeHistoryTransformer())->transform($organized);
$this->cache->set($key, $list); $this->cache->set($key, $list);

View File

@ -97,10 +97,7 @@ trait MangaTrait {
if ($list === NULL) if ($list === NULL)
{ {
$raw = $this->getRawHistoryList('manga'); $raw = $this->getRawHistoryList('manga');
$organized = JsonAPI::organizeData($raw); $list = (new MangaHistoryTransformer())->transform($raw);
$organized = array_filter($organized, fn ($item) => array_key_exists('relationships', $item));
$list = (new MangaHistoryTransformer())->transform($organized);
$this->cache->set($key, $list); $this->cache->set($key, $list);
} }

View File

@ -355,67 +355,12 @@ final class Model {
/** /**
* Get the aggregated pages of anime or manga history * Get the aggregated pages of anime or manga history
* *
* @param string $type
* @param int $entries
* @return array * @return array
* @throws InvalidArgumentException
* @throws Throwable
*/ */
protected function getRawHistoryList(string $type = 'anime', int $entries = 120): array protected function getRawHistoryList(): array
{ {
$size = 20; return $this->requestBuilder->runQuery('GetUserHistory', [
$pages = ceil($entries / $size); 'slug' => $this->getUsername(),
$requester = new ParallelAPIRequest();
// Set up requests
for ($i = 0; $i < $pages; $i++)
{
$offset = $i * $size;
$requester->addRequest($this->getRawHistoryPage($type, $offset, $size));
}
$responses = $requester->makeRequests();
$output = [];
foreach($responses as $response)
{
$data = Json::decode($response);
$output[] = $data;
}
return array_merge_recursive(...$output);
}
/**
* Retrieve one page of the anime or manga history
*
* @param string $type
* @param int $offset
* @param int $limit
* @return Request
* @throws InvalidArgumentException
*/
protected function getRawHistoryPage(string $type, int $offset, int $limit = 20): Request
{
return $this->requestBuilder->setUpRequest('GET', 'library-events', [
'query' => [
'filter' => [
'kind' => 'progressed,updated',
'userId' => $this->getUserId(),
],
'page' => [
'offset' => $offset,
'limit' => $limit,
],
'fields' => [
'anime' => 'canonicalTitle,titles,slug,posterImage',
'manga' => 'canonicalTitle,titles,slug,posterImage',
'libraryEntry' => 'reconsuming,reconsumeCount',
],
'sort' => '-updated_at',
'include' => 'anime,manga,libraryEntry',
],
]); ]);
} }

View File

@ -0,0 +1,35 @@
query ($slug: String!) {
findProfileBySlug(slug: $slug) {
libraryEvents {
nodes {
id
changedData
kind
libraryEntry {
reconsumeCount
reconsuming
private
notes
}
media {
__typename
id
slug
posterImage {
views {
width
height
url
}
}
titles {
alternatives
canonical
localized
}
}
updatedAt
}
}
}
}

View File

@ -60,18 +60,25 @@ abstract class HistoryTransformer {
*/ */
public function transform(array $data): array public function transform(array $data): array
{ {
$base = $data['data']['findProfileBySlug']['libraryEvents']['nodes'] ?? [];
$output = []; $output = [];
foreach ($data as $entry) foreach ($base as $entry)
{ {
if ( ! isset($entry['relationships'][$this->type])) if ( ! (strtolower($entry['media']['__typename']) === $this->type))
{ {
continue; continue;
} }
$kind = $entry['attributes']['kind']; // Hide private library entries
if ($entry['libraryEntry']['private'] === true)
{
continue;
}
if ($kind === 'progressed' && ! empty($entry['attributes']['changedData']['progress'])) $kind = strtolower($entry['kind']);
if ($kind === 'progressed' && ! empty($entry['changedData']['progress']))
{ {
$transformed = $this->transformProgress($entry); $transformed = $this->transformProgress($entry);
if ($transformed !== NULL) if ($transformed !== NULL)
@ -130,7 +137,7 @@ abstract class HistoryTransformer {
foreach ($entries as $e) foreach ($entries as $e)
{ {
$progressItem = $e['original']['attributes']['changedData']['progress']; $progressItem = $e['original']['changedData']['progress'];
$items[] = array_pop($progressItem); $items[] = array_pop($progressItem);
$updated[] = $e['updated']; $updated[] = $e['updated'];
} }
@ -176,11 +183,11 @@ abstract class HistoryTransformer {
protected function transformProgress (array $entry): ?HistoryItem protected function transformProgress (array $entry): ?HistoryItem
{ {
$id = array_keys($entry['relationships'][$this->type])[0]; $id = $entry['media']['id'];
$data = $entry['relationships'][$this->type][$id]['attributes']; $data = $entry['media'];
$title = $this->linkTitle($data); $title = $this->linkTitle($data);
$imgUrl = "images/{$this->type}/{$id}.webp"; $imgUrl = "images/{$this->type}/{$id}.webp";
$item = end($entry['attributes']['changedData']['progress']); $item = end($entry['changedData']['progress']);
// No showing episode 0 nonsense // No showing episode 0 nonsense
if (((int)$item) === 0) if (((int)$item) === 0)
@ -198,23 +205,23 @@ abstract class HistoryTransformer {
'kind' => 'progressed', 'kind' => 'progressed',
'original' => $entry, 'original' => $entry,
'title' => $title, 'title' => $title,
'updated' => $this->parseDate($entry['attributes']['updatedAt']), 'updated' => $this->parseDate($entry['updatedAt']),
'url' => $this->getUrl($data), 'url' => $this->getUrl($data),
]); ]);
} }
protected function transformUpdated($entry): HistoryItem protected function transformUpdated($entry): HistoryItem
{ {
$id = array_keys($entry['relationships'][$this->type])[0]; $id = $entry['media']['id'];
$data = $entry['relationships'][$this->type][$id]['attributes']; $data = $entry['media'];
$title = $this->linkTitle($data); $title = $this->linkTitle($data);
$imgUrl = "images/{$this->type}/{$id}.webp"; $imgUrl = "images/{$this->type}/{$id}.webp";
$kind = array_key_first($entry['attributes']['changedData']); $kind = array_key_first($entry['changedData']);
if ($kind === 'status') if ($kind === 'status')
{ {
$status = array_pop($entry['attributes']['changedData']['status']); $status = array_pop($entry['changedData']['status']);
$statusName = $this->statusMap[$status]; $statusName = $this->statusMap[$status];
if ($this->isReconsuming($entry)) if ($this->isReconsuming($entry))
@ -230,7 +237,7 @@ abstract class HistoryTransformer {
'kind' => 'updated', 'kind' => 'updated',
'original' => $entry, 'original' => $entry,
'title' => $title, 'title' => $title,
'updated' => $this->parseDate($entry['attributes']['updatedAt']), 'updated' => $this->parseDate($entry['updatedAt']),
'url' => $this->getUrl($data), 'url' => $this->getUrl($data),
]); ]);
} }
@ -240,13 +247,13 @@ abstract class HistoryTransformer {
protected function linkTitle (array $data): string protected function linkTitle (array $data): string
{ {
return $data['canonicalTitle']; return $data['titles']['canonical'];
} }
protected function parseDate (string $date): DateTimeImmutable protected function parseDate (string $date): DateTimeImmutable
{ {
$dateTime = DateTimeImmutable::createFromFormat( $dateTime = DateTimeImmutable::createFromFormat(
DateTimeInterface::RFC3339_EXTENDED, DateTimeInterface::RFC3339,
$date $date
); );
@ -260,20 +267,6 @@ abstract class HistoryTransformer {
protected function isReconsuming ($entry): bool protected function isReconsuming ($entry): bool
{ {
$le = $this->getLibraryEntry($entry); return $entry['libraryEntry']['reconsuming'];
return $le['reconsuming'];
}
private function getLibraryEntry ($entry): ?array
{
if ( ! isset($entry['relationships']['libraryEntry']['libraryEntries']))
{
return NULL;
}
$libraryEntries = $entry['relationships']['libraryEntry']['libraryEntries'];
$id = array_keys($libraryEntries)[0];
return $libraryEntries[$id]['attributes'];
} }
} }