HummingBirdAnimeClient/src/API/Kitsu/Model.php

988 lines
21 KiB
PHP
Raw Normal View History

2016-12-21 12:46:20 -05:00
<?php declare(strict_types=1);
/**
2017-02-15 16:13:32 -05:00
* Hummingbird Anime List Client
2016-12-21 12:46:20 -05:00
*
2018-08-22 13:48:27 -04:00
* An API client for Kitsu to manage anime and manga watch lists
2016-12-21 12:46:20 -05:00
*
2018-10-01 11:35:51 -04:00
* PHP version 7.1
2016-12-21 12:46:20 -05:00
*
2017-02-15 16:13:32 -05:00
* @package HummingbirdAnimeClient
2017-01-06 23:34:56 -05:00
* @author Timothy J. Warren <tim@timshomepage.net>
2018-01-15 14:43:15 -05:00
* @copyright 2015 - 2018 Timothy J. Warren
2017-01-06 23:34:56 -05:00
* @license http://www.opensource.org/licenses/mit-license.html MIT License
2018-10-01 11:35:51 -04:00
* @version 4.1
* @link https://git.timshomepage.net/timw4mail/HummingBirdAnimeClient
*/
namespace Aviat\AnimeClient\API\Kitsu;
2016-12-21 12:46:20 -05:00
use function Amp\Promise\wait;
2017-03-07 17:51:08 -05:00
use Amp\Artax\Request;
use Aviat\AnimeClient\API\{
CacheTrait,
JsonAPI,
Kitsu as K,
ParallelAPIRequest
};
2017-03-07 18:41:51 -05:00
use Aviat\AnimeClient\API\Enum\{
AnimeWatchingStatus\Kitsu as KitsuWatchingStatus,
2017-03-07 18:41:51 -05:00
MangaReadingStatus\Kitsu as KitsuReadingStatus
2017-02-20 13:37:08 -05:00
};
use Aviat\AnimeClient\API\Mapping\{AnimeWatchingStatus, MangaReadingStatus};
2017-01-03 21:06:49 -05:00
use Aviat\AnimeClient\API\Kitsu\Transformer\{
2017-02-04 15:18:34 -05:00
AnimeTransformer,
AnimeListTransformer,
MangaTransformer,
2017-01-27 12:35:28 -05:00
MangaListTransformer
2017-01-03 21:06:49 -05:00
};
use Aviat\AnimeClient\Types\{
Anime,
2018-08-08 13:05:38 -04:00
FormItem,
MangaPage
};
use Aviat\Ion\{Di\ContainerAware, Json};
2016-12-21 12:46:20 -05:00
/**
* Kitsu API Model
*/
final class Model {
use CacheTrait;
use ContainerAware;
2016-12-21 12:46:20 -05:00
use KitsuTrait;
private const LIST_PAGE_SIZE = 100;
2017-03-07 17:51:08 -05:00
2016-12-21 12:46:20 -05:00
/**
* Class to map anime list items
* to a common format used by
* templates
*
* @var AnimeListTransformer
*/
private $animeListTransformer;
2016-12-21 12:46:20 -05:00
/**
* @var AnimeTransformer
*/
private $animeTransformer;
/**
* @var ListItem
*/
private $listItem;
/**
* @var MangaTransformer
*/
private $mangaTransformer;
2017-01-04 13:16:58 -05:00
/**
* @var MangaListTransformer
*/
private $mangaListTransformer;
2017-02-04 15:18:34 -05:00
/**
2017-02-17 11:37:22 -05:00
* Constructor
*
* @param ListItem $listItem
*/
public function __construct(ListItem $listItem)
2016-12-21 12:46:20 -05:00
{
$this->animeTransformer = new AnimeTransformer();
2016-12-21 12:46:20 -05:00
$this->animeListTransformer = new AnimeListTransformer();
$this->listItem = $listItem;
2017-01-04 13:16:58 -05:00
$this->mangaTransformer = new MangaTransformer();
2017-01-03 21:06:49 -05:00
$this->mangaListTransformer = new MangaListTransformer();
2016-12-21 12:46:20 -05:00
}
2017-03-28 14:34:33 -04:00
/**
* Get the access token from the Kitsu API
*
* @param string $username
* @param string $password
* @return bool|array
2017-03-28 14:34:33 -04:00
*/
public function authenticate(string $username, string $password)
{
// K::AUTH_URL
2017-03-28 14:34:33 -04:00
$response = $this->getResponse('POST', K::AUTH_URL, [
'headers' => [
'accept' => NULL,
'Content-type' => 'application/x-www-form-urlencoded',
'client_id' => NULL,
'client_secret' => NULL
],
2017-03-28 14:34:33 -04:00
'form_params' => [
'grant_type' => 'password',
'username' => $username,
'password' => $password
]
]);
$data = Json::decode(wait($response->getBody()));
2018-01-16 14:58:07 -05:00
if (array_key_exists('error', $data))
{
dump($data['error']);
dump($response);
die();
}
2018-10-05 14:32:05 -04:00
if (array_key_exists('access_token', $data))
{
return $data;
}
2017-03-28 14:34:33 -04:00
return FALSE;
}
/**
* Extend the current session with a refresh token
*
* @param string $token
* @return bool|array
*/
public function reAuthenticate(string $token)
{
$response = $this->getResponse('POST', K::AUTH_URL, [
'headers' => [
'Accept-encoding' => '*'
],
'form_params' => [
'grant_type' => 'refresh_token',
'refresh_token' => $token
]
]);
$data = Json::decode(wait($response->getBody()));
if (array_key_exists('access_token', $data))
{
return $data;
}
return FALSE;
}
/**
* Get the userid for a username from Kitsu
*
* @param string $username
* @return string
*/
2017-03-08 12:55:49 -05:00
public function getUserIdByUsername(string $username = NULL): string
{
2018-02-02 09:50:58 -05:00
if ($username === NULL)
2017-01-27 12:35:28 -05:00
{
$username = $this->getUsername();
}
2017-02-04 15:18:34 -05:00
2017-01-27 12:35:28 -05:00
$cacheItem = $this->cache->getItem(K::AUTH_USER_ID_KEY);
2017-02-04 15:18:34 -05:00
if ( ! $cacheItem->isHit())
{
$data = $this->getRequest('users', [
'query' => [
'filter' => [
'name' => $username
]
]
]);
$cacheItem->set($data['data'][0]['id']);
$cacheItem->save();
}
2017-02-04 15:18:34 -05:00
return $cacheItem->get();
}
2017-03-08 12:55:49 -05:00
/**
* Get information about a character
*
* @param string $slug
* @return array
*/
public function getCharacter(string $slug): array
{
$data = $this->getRequest('characters', [
2017-03-08 12:55:49 -05:00
'query' => [
'filter' => [
2017-04-05 13:01:51 -04:00
'slug' => $slug,
2017-03-08 12:55:49 -05:00
],
2017-04-05 13:01:51 -04:00
'fields' => [
'anime' => 'canonicalTitle,titles,slug,posterImage',
'manga' => 'canonicalTitle,titles,slug,posterImage'
],
'include' => 'castings.person,castings.media'
2017-03-08 12:55:49 -05:00
]
]);
return $data;
}
/**
* Get information about a person
*
* @param string $id
* @return array
*/
public function getPerson(string $id): array
{
$cacheItem = $this->cache->getItem("kitsu-person-{$id}");
if ( ! $cacheItem->isHit())
{
$data = $this->getRequest("people/{$id}", [
'query' => [
'fields' => [
'characters' => 'canonicalName,slug,image',
'anime' => 'canonicalTitle,titles,slug,posterImage',
'manga' => 'canonicalTitle,titles,slug,posterImage',
],
'include' => 'castings.character,castings.media'
],
]);
$cacheItem->set($data);
$cacheItem->save();
}
return $cacheItem->get();
}
2017-03-08 13:46:50 -05:00
/**
* Get profile information for the configured user
*
* @param string $username
* @return array
*/
2017-03-08 12:55:49 -05:00
public function getUserData(string $username): array
{
2017-03-31 13:37:53 -04:00
// $userId = $this->getUserIdByUsername($username);
$data = $this->getRequest("users", [
2017-03-08 12:55:49 -05:00
'query' => [
2017-03-31 13:37:53 -04:00
'filter' => [
'name' => $username,
],
'fields' => [
// 'anime' => 'slug,name,canonicalTitle',
'characters' => 'slug,name,image'
],
'include' => 'waifu,pinnedPost,blocks,linkedAccounts,profileLinks,profileLinks.profileLinkSite,userRoles,favorites.item'
2017-03-08 12:55:49 -05:00
]
]);
return $data;
}
2016-12-21 12:46:20 -05:00
/**
2017-03-28 14:34:33 -04:00
* Search for an anime or manga
2016-12-21 12:46:20 -05:00
*
2017-03-28 14:34:33 -04:00
* @param string $type - 'anime' or 'manga'
* @param string $query - name of the item to search for
* @return array
2016-12-21 12:46:20 -05:00
*/
2017-03-28 14:34:33 -04:00
public function search(string $type, string $query): array
2016-12-21 12:46:20 -05:00
{
2017-03-28 14:34:33 -04:00
$options = [
'query' => [
'filter' => [
'text' => $query,
2017-03-28 14:34:33 -04:00
],
'page' => [
'offset' => 0,
'limit' => 20
],
'include' => 'mappings'
]
2017-03-28 14:34:33 -04:00
];
2016-12-21 12:46:20 -05:00
2017-03-28 14:34:33 -04:00
$raw = $this->getRequest($type, $options);
$raw['included'] = JsonAPI::organizeIncluded($raw['included']);
2017-03-28 14:34:33 -04:00
foreach ($raw['data'] as &$item)
{
2017-03-28 14:34:33 -04:00
$item['attributes']['titles'] = K::filterTitles($item['attributes']);
array_shift($item['attributes']['titles']);
// Map the mal_id if it exists for syncing with other APIs
foreach($item['relationships']['mappings']['data'] as $rel)
{
$mapping = $raw['included']['mappings'][$rel['id']];
if ($mapping['attributes']['externalSite'] === "myanimelist/{$type}")
{
$item['mal_id'] = $mapping['attributes']['externalId'];
}
}
2016-12-21 12:46:20 -05:00
}
2017-03-28 14:34:33 -04:00
return $raw;
2016-12-21 12:46:20 -05:00
}
/**
* Find a media item on Kitsu by its associated MAL id
*
* @param string $malId
* @param string $type "anime" or "manga"
2017-04-10 15:31:35 -04:00
* @return string|NULL
*/
2017-04-10 15:31:35 -04:00
public function getKitsuIdFromMALId(string $malId, string $type="anime")
{
$options = [
'query' => [
'filter' => [
'external_site' => "myanimelist/{$type}",
'external_id' => $malId
],
'fields' => [
'media' => 'id,slug'
],
'include' => 'item'
]
];
$raw = $this->getRequest('mappings', $options);
2017-04-10 15:31:35 -04:00
if ( ! array_key_exists('included', $raw))
{
return NULL;
}
return $raw['included'][0]['id'];
}
2017-03-28 14:34:33 -04:00
// -------------------------------------------------------------------------
// ! Anime-specific methods
// -------------------------------------------------------------------------
/**
* Get information about a particular anime
*
2017-01-16 13:49:51 -05:00
* @param string $slug
* @return Anime
*/
public function getAnime(string $slug): Anime
{
2017-01-16 13:49:51 -05:00
$baseData = $this->getRawMediaData('anime', $slug);
if (empty($baseData))
{
return new Anime();
}
return $this->animeTransformer->transform($baseData);
// $transformed['included'] = JsonAPI::organizeIncluded($baseData['included']);
// return $transformed;
2017-01-16 13:49:51 -05:00
}
2017-02-04 15:18:34 -05:00
/**
* Get information about a particular anime
*
* @param string $animeId
2018-08-20 13:01:16 -04:00
* @return Anime
*/
2018-08-20 13:01:16 -04:00
public function getAnimeById(string $animeId): Anime
2017-01-16 13:49:51 -05:00
{
$baseData = $this->getRawMediaDataById('anime', $animeId);
return $this->animeTransformer->transform($baseData);
}
2017-02-04 15:18:34 -05:00
/**
2017-03-28 14:34:33 -04:00
* Get the anime list for the configured user
2017-02-04 15:18:34 -05:00
*
2017-03-28 14:34:33 -04:00
* @param string $status - The watching status to filter the list with
* @return array
2017-02-04 15:18:34 -05:00
*/
2017-03-28 14:34:33 -04:00
public function getAnimeList(string $status): array
2017-02-04 15:18:34 -05:00
{
2017-03-28 14:34:33 -04:00
$cacheItem = $this->cache->getItem("kitsu-anime-list-{$status}");
2017-02-04 15:18:34 -05:00
2017-03-28 14:34:33 -04:00
if ( ! $cacheItem->isHit())
2017-02-04 15:18:34 -05:00
{
2017-03-28 14:34:33 -04:00
$data = $this->getRawAnimeList($status) ?? [];
// Bail out on no data
if (empty($data))
2017-02-04 15:18:34 -05:00
{
2018-10-05 14:32:05 -04:00
return [];
2017-02-04 15:18:34 -05:00
}
2017-03-28 14:34:33 -04:00
$included = JsonAPI::organizeIncludes($data['included']);
$included = JsonAPI::inlineIncludedRelationships($included, 'anime');
2017-02-04 15:18:34 -05:00
2017-03-28 14:34:33 -04:00
foreach($data['data'] as $i => &$item)
{
$item['included'] = $included;
}
$transformed = $this->animeListTransformer->transformCollection($data['data']);
2017-03-24 10:59:07 -04:00
2017-03-28 14:34:33 -04:00
$cacheItem->set($transformed);
$cacheItem->save();
2017-03-24 10:59:07 -04:00
}
2017-03-28 14:34:33 -04:00
return $cacheItem->get();
}
/**
* Get the number of anime list items
*
2017-03-14 14:28:08 -04:00
* @param string $status - Optional status to filter by
* @return int
*/
2017-03-14 14:28:08 -04:00
public function getAnimeListCount(string $status = '') : int
{
$options = [
'query' => [
'filter' => [
'user_id' => $this->getUserIdByUsername(),
'media_type' => 'Anime'
],
'page' => [
'limit' => 1
],
'sort' => '-updated_at'
]
];
2017-03-14 14:28:08 -04:00
if ( ! empty($status))
{
$options['query']['filter']['status'] = $status;
}
$response = $this->getRequest('library-entries', $options);
return $response['meta']['count'];
2017-02-04 15:18:34 -05:00
}
2017-03-07 17:51:08 -05:00
/**
* Get the full anime list
*
2017-03-14 14:28:08 -04:00
* @param array $options
* @return array
2017-03-07 17:51:08 -05:00
*/
public function getFullRawAnimeList(array $options = [
'include' => 'anime.mappings'
2017-03-14 14:28:08 -04:00
]): array
2017-03-07 17:51:08 -05:00
{
$status = $options['filter']['status'] ?? '';
$count = $this->getAnimeListCount($status);
2017-04-17 16:13:36 -04:00
$size = static::LIST_PAGE_SIZE;
2017-03-07 17:51:08 -05:00
$pages = ceil($count / $size);
$requester = new ParallelAPIRequest();
2017-03-07 17:51:08 -05:00
// Set up requests
for ($i = 0; $i < $pages; $i++)
{
$offset = $i * $size;
$requester->addRequest($this->getPagedAnimeList($size, $offset, $options));
2017-03-07 17:51:08 -05:00
}
$responses = $requester->makeRequests();
2017-03-07 17:51:08 -05:00
$output = [];
foreach($responses as $response)
{
$data = Json::decode($response);
$output[] = $data;
2017-03-07 17:51:08 -05:00
}
return array_merge_recursive(...$output);
2017-03-07 17:51:08 -05:00
}
2017-02-04 15:18:34 -05:00
/**
2018-08-20 13:01:16 -04:00
* Get all the anime entries, that are organized for output to html
*
* @return array
*/
2017-03-28 14:34:33 -04:00
public function getFullOrganizedAnimeList(): array
{
2017-03-28 14:34:33 -04:00
$output = [];
2017-03-28 14:34:33 -04:00
$statuses = KitsuWatchingStatus::getConstList();
2017-02-04 15:18:34 -05:00
2017-03-28 14:34:33 -04:00
foreach ($statuses as $key => $status)
{
$mappedStatus = AnimeWatchingStatus::KITSU_TO_TITLE[$status];
$output[$mappedStatus] = $this->getAnimeList($status) ?? [];
}
return $output;
2017-01-27 12:35:28 -05:00
}
/**
2017-03-28 14:34:33 -04:00
* Get the mal id for the anime represented by the kitsu id
* to enable updating MyAnimeList
*
2017-03-28 14:34:33 -04:00
* @param string $kitsuAnimeId The id of the anime on Kitsu
* @return string|null Returns the mal id if it exists, otherwise null
*/
2017-03-28 14:34:33 -04:00
public function getMalIdForAnime(string $kitsuAnimeId)
2017-03-07 17:51:08 -05:00
{
2017-03-28 14:34:33 -04:00
$options = [
'query' => [
'include' => 'mappings'
]
];
$data = $this->getRequest("anime/{$kitsuAnimeId}", $options);
if ( ! array_key_exists('included', $data))
{
return NULL;
}
2017-03-28 14:34:33 -04:00
$mappings = array_column($data['included'], 'attributes');
2017-03-07 17:51:08 -05:00
2017-03-28 14:34:33 -04:00
foreach($mappings as $map)
2017-03-07 17:51:08 -05:00
{
2017-03-28 14:34:33 -04:00
if ($map['externalSite'] === 'myanimelist/anime')
2017-03-22 16:53:46 -04:00
{
2017-03-28 14:34:33 -04:00
return $map['externalId'];
2017-03-22 16:53:46 -04:00
}
2017-03-07 17:51:08 -05:00
}
2017-03-28 14:34:33 -04:00
return NULL;
2017-03-07 17:51:08 -05:00
}
2017-01-27 12:35:28 -05:00
/**
2017-03-28 14:34:33 -04:00
* Get the full anime list in paginated form
2017-01-27 12:35:28 -05:00
*
2017-03-28 14:34:33 -04:00
* @param int $limit
* @param int $offset
* @param array $options
* @return Request
2017-01-27 12:35:28 -05:00
*/
2017-04-17 16:13:36 -04:00
public function getPagedAnimeList(int $limit, int $offset = 0, array $options = [
2017-03-28 14:34:33 -04:00
'include' => 'anime.mappings'
]): Request
2017-01-27 12:35:28 -05:00
{
2017-03-28 14:34:33 -04:00
$defaultOptions = [
'filter' => [
'user_id' => $this->getUserIdByUsername($this->getUsername()),
'media_type' => 'Anime'
],
'page' => [
'offset' => $offset,
'limit' => $limit
],
'sort' => '-updated_at'
];
$options = array_merge($defaultOptions, $options);
2017-03-22 16:53:46 -04:00
2017-03-28 14:34:33 -04:00
return $this->setUpRequest('GET', 'library-entries', ['query' => $options]);
}
2017-03-28 14:34:33 -04:00
/**
* Get the raw (unorganized) anime list for the configured user
*
* @param string $status - The watching status to filter the list with
* @return array
*/
public function getRawAnimeList(string $status): array
{
$options = [
'filter' => [
'user_id' => $this->getUserIdByUsername($this->getUsername()),
'media_type' => 'Anime',
'status' => $status,
],
'include' => 'media,media.categories,media.mappings,anime.streamingLinks',
2017-03-28 14:34:33 -04:00
'sort' => '-updated_at'
];
2016-12-21 12:46:20 -05:00
return $this->getFullRawAnimeList($options);
2016-12-21 12:46:20 -05:00
}
2017-03-28 14:34:33 -04:00
// -------------------------------------------------------------------------
// ! Manga-specific methods
// -------------------------------------------------------------------------
/**
2017-03-28 14:34:33 -04:00
* Get information about a particular manga
*
2017-03-28 14:34:33 -04:00
* @param string $slug
2018-08-08 13:05:38 -04:00
* @return MangaPage
*/
2018-08-08 13:05:38 -04:00
public function getManga(string $slug): MangaPage
2017-03-07 18:41:51 -05:00
{
2017-03-28 14:34:33 -04:00
$baseData = $this->getRawMediaData('manga', $slug);
if (empty($baseData))
2017-03-07 18:41:51 -05:00
{
2018-08-08 13:05:38 -04:00
return new MangaPage([]);
2017-03-07 18:41:51 -05:00
}
2017-03-28 14:34:33 -04:00
$transformed = $this->mangaTransformer->transform($baseData);
$transformed['included'] = JsonAPI::organizeIncluded($baseData['included']);
2017-03-28 14:34:33 -04:00
return $transformed;
2017-03-07 18:41:51 -05:00
}
/**
* Get information about a particular manga
*
* @param string $mangaId
* @return array
*/
2018-08-08 13:05:38 -04:00
public function getMangaById(string $mangaId): MangaPage
{
$baseData = $this->getRawMediaDataById('manga', $mangaId);
return $this->mangaTransformer->transform($baseData);
}
/**
* Get the manga list for the configured user
*
* @param string $status - The reading status by which to filter the list
* @param int $limit - The number of list items to fetch per page
* @param int $offset - The page offset
* @return array
*/
public function getMangaList(string $status, int $limit = 200, int $offset = 0): array
2017-01-04 13:16:58 -05:00
{
$options = [
'query' => [
'filter' => [
'user_id' => $this->getUserIdByUsername($this->getUsername()),
2017-01-04 13:16:58 -05:00
'media_type' => 'Manga',
'status' => $status,
],
'include' => 'media,media.categories,media.mappings',
2017-01-04 13:16:58 -05:00
'page' => [
'offset' => $offset,
'limit' => $limit
2017-01-04 13:16:58 -05:00
],
'sort' => '-updated_at'
]
];
2017-02-04 15:18:34 -05:00
2017-03-10 12:50:29 -05:00
$cacheItem = $this->cache->getItem("kitsu-manga-list-{$status}");
2017-01-04 13:16:58 -05:00
2017-01-16 14:14:45 -05:00
if ( ! $cacheItem->isHit())
2017-01-04 13:16:58 -05:00
{
$data = $this->getRequest('library-entries', $options) ?? [];
// Bail out on no data
if (empty($data) || ( ! array_key_exists('included', $data)))
{
2018-10-05 14:32:05 -04:00
return [];
}
2017-01-04 13:16:58 -05:00
$included = JsonAPI::organizeIncludes($data['included']);
$included = JsonAPI::inlineIncludedRelationships($included, 'manga');
foreach($data['data'] as $i => &$item)
{
$item['included'] = $included;
}
$transformed = $this->mangaListTransformer->transformCollection($data['data']);
2017-01-04 13:16:58 -05:00
2017-01-16 14:14:45 -05:00
$cacheItem->set($transformed);
$cacheItem->save();
}
2017-02-04 15:18:34 -05:00
2017-01-16 14:14:45 -05:00
return $cacheItem->get();
2017-01-04 13:16:58 -05:00
}
2017-01-03 21:06:49 -05:00
/**
* Get the number of manga list items
*
* @param string $status - Optional status to filter by
* @return int
*/
public function getMangaListCount(string $status = '') : int
{
$options = [
'query' => [
'filter' => [
'user_id' => $this->getUserIdByUsername(),
'media_type' => 'Manga'
],
'page' => [
'limit' => 1
],
'sort' => '-updated_at'
]
];
if ( ! empty($status))
{
$options['query']['filter']['status'] = $status;
}
$response = $this->getRequest('library-entries', $options);
return $response['meta']['count'];
}
/**
* Get the full manga list
*
* @param array $options
* @return array
*/
public function getFullRawMangaList(array $options = [
'include' => 'manga.mappings'
]): array
{
$status = $options['filter']['status'] ?? '';
$count = $this->getMangaListCount($status);
2017-04-17 16:13:36 -04:00
$size = static::LIST_PAGE_SIZE;
$pages = ceil($count / $size);
$requester = new ParallelAPIRequest();
// Set up requests
for ($i = 0; $i < $pages; $i++)
{
$offset = $i * $size;
$requester->addRequest($this->getPagedMangaList($size, $offset, $options));
}
$responses = $requester->makeRequests();
$output = [];
foreach($responses as $response)
{
$data = Json::decode($response);
$output[] = $data;
}
return array_merge_recursive(...$output);
}
/**
2017-03-28 14:34:33 -04:00
* Get all Manga lists
*
* @return array
*/
2017-03-28 14:34:33 -04:00
public function getFullOrganizedMangaList(): array
{
$statuses = KitsuReadingStatus::getConstList();
$output = [];
foreach ($statuses as $status)
{
$mappedStatus = MangaReadingStatus::KITSU_TO_TITLE[$status];
$output[$mappedStatus] = $this->getMangaList($status);
}
return $output;
}
/**
* Get the full manga list in paginated form
*
* @param int $limit
* @param int $offset
* @param array $options
* @return Request
*/
2017-04-17 16:13:36 -04:00
public function getPagedMangaList(int $limit, int $offset = 0, array $options = [
'include' => 'manga.mappings'
]): Request
{
$defaultOptions = [
'filter' => [
'user_id' => $this->getUserIdByUsername($this->getUsername()),
'media_type' => 'Manga'
],
'page' => [
'offset' => $offset,
'limit' => $limit
],
'sort' => '-updated_at'
];
$options = array_merge($defaultOptions, $options);
return $this->setUpRequest('GET', 'library-entries', ['query' => $options]);
}
2017-03-28 14:34:33 -04:00
/**
* Get the mal id for the manga represented by the kitsu id
* to enable updating MyAnimeList
*
2018-01-16 14:58:07 -05:00
* @param string $kitsuMangaId The id of the manga on Kitsu
2017-03-28 14:34:33 -04:00
* @return string|null Returns the mal id if it exists, otherwise null
*/
public function getMalIdForManga(string $kitsuMangaId)
{
$options = [
'query' => [
2017-03-28 14:34:33 -04:00
'include' => 'mappings'
2017-01-10 21:13:44 -05:00
]
];
2017-03-28 14:34:33 -04:00
$data = $this->getRequest("manga/{$kitsuMangaId}", $options);
$mappings = array_column($data['included'], 'attributes');
2017-03-28 14:34:33 -04:00
foreach($mappings as $map)
{
if ($map['externalSite'] === 'myanimelist/manga')
2017-03-28 14:34:33 -04:00
{
return $map['externalId'];
}
}
2017-03-28 14:34:33 -04:00
return NULL;
}
2017-03-28 14:34:33 -04:00
// -------------------------------------------------------------------------
// ! Generic API calls
// -------------------------------------------------------------------------
/**
* Create a list item
*
* @param array $data
* @return Request
*/
public function createListItem(array $data): Request
2017-01-10 21:13:44 -05:00
{
$data['user_id'] = $this->getUserIdByUsername($this->getUsername());
return $this->listItem->create($data);
}
/**
* Get the data for a specific list item, generally for editing
*
* @param string $listId - The unique identifier of that list item
* @return mixed
*/
public function getListItem(string $listId)
{
$baseData = $this->listItem->get($listId);
$included = JsonAPI::organizeIncludes($baseData['included']);
2018-10-19 10:40:11 -04:00
if (array_key_exists('anime', $included))
{
$included = JsonAPI::inlineIncludedRelationships($included, 'anime');
$baseData['data']['included'] = $included;
return $this->animeListTransformer->transform($baseData['data']);
}
2018-10-19 10:40:11 -04:00
if (array_key_exists('manga', $included))
{
2018-10-19 10:40:11 -04:00
$included = JsonAPI::inlineIncludedRelationships($included, 'manga');
$baseData['data']['included'] = $included;
$baseData['data']['manga'] = $baseData['included'][0];
return $this->mangaListTransformer->transform($baseData['data']);
}
2018-10-19 10:40:11 -04:00
return $baseData['data'];
}
/**
* Increase the progress count for a list item
*
* @param FormItem $data
* @return Request
*/
public function incrementListItem(FormItem $data): Request
{
return $this->listItem->increment($data['id'], $data['data']);
}
/**
* Modify a list item
*
2018-08-08 13:05:38 -04:00
* @param FormItem $data
* @return Request
*/
2018-08-08 13:05:38 -04:00
public function updateListItem(FormItem $data): Request
{
return $this->listItem->update($data['id'], $data['data']);
}
/**
* Remove a list item
*
* @param string $id - The id of the list item to remove
* @return Request
*/
public function deleteListItem(string $id): Request
{
return $this->listItem->delete($id);
}
/**
* Get the kitsu username from config
*
* @return string
*/
private function getUsername(): string
{
return $this->getContainer()
->get('config')
->get(['kitsu_username']);
}
2017-02-04 15:18:34 -05:00
/**
* Get the raw data for the anime id
*
* @param string $type
* @param string $id
* @return array
*/
2017-01-16 13:49:51 -05:00
private function getRawMediaDataById(string $type, string $id): array
{
$options = [
'query' => [
'include' => ($type === 'anime')
? 'categories,mappings,streamingLinks'
: 'categories,mappings',
2017-01-16 13:49:51 -05:00
]
];
$data = $this->getRequest("{$type}/{$id}", $options);
2017-03-24 10:59:07 -04:00
if (empty($data['data']))
{
return [];
}
2017-01-16 13:49:51 -05:00
$baseData = $data['data']['attributes'];
$baseData['id'] = $id;
2017-01-16 13:49:51 -05:00
$baseData['included'] = $data['included'];
return $baseData;
}
/**
* Get media item by slug
*
* @param string $type
* @param string $slug
* @return array
*/
private function getRawMediaData(string $type, string $slug): array
{
$options = [
'query' => [
'filter' => [
'slug' => $slug
],
2017-03-31 13:37:53 -04:00
'fields' => [
'categories' => 'slug,title',
'characters' => 'slug,name,image',
'mappings' => 'externalSite,externalId',
'animeCharacters' => 'character,role',
2017-03-31 13:37:53 -04:00
],
'include' => ($type === 'anime')
? 'staff,staff.person,categories,mappings,streamingLinks,animeCharacters.character'
: 'staff,staff.person,categories,mappings,mangaCharacters.character',
]
];
$data = $this->getRequest($type, $options);
if (empty($data['data']))
{
return [];
}
$baseData = $data['data'][0]['attributes'];
$baseData['id'] = $data['data'][0]['id'];
$baseData['included'] = $data['included'];
return $baseData;
}
2016-12-21 12:46:20 -05:00
}