add v4 search

This commit is contained in:
Irfan 2020-06-11 12:53:26 +05:00
parent 304617c8d1
commit a2caeb6987
26 changed files with 1317 additions and 12 deletions

View File

@ -3,6 +3,9 @@
namespace App\Http\Controllers\V4; namespace App\Http\Controllers\V4;
use App\Http\HttpHelper; use App\Http\HttpHelper;
use App\Http\HttpResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Jikan\Request\Anime\AnimeCharactersAndStaffRequest; use Jikan\Request\Anime\AnimeCharactersAndStaffRequest;
use Jikan\Request\Anime\AnimeEpisodeRequest; use Jikan\Request\Anime\AnimeEpisodeRequest;
use Jikan\Request\Anime\AnimeEpisodesRequest; use Jikan\Request\Anime\AnimeEpisodesRequest;
@ -16,10 +19,11 @@ use Jikan\Request\Anime\AnimeRequest;
use Jikan\Request\Anime\AnimeReviewsRequest; use Jikan\Request\Anime\AnimeReviewsRequest;
use Jikan\Request\Anime\AnimeStatsRequest; use Jikan\Request\Anime\AnimeStatsRequest;
use Jikan\Request\Anime\AnimeVideosRequest; use Jikan\Request\Anime\AnimeVideosRequest;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AnimeController extends Controller class AnimeController extends Controller
{ {
public function main(int $id) public function main(Request $request, int $id)
{ {
$anime = $this->jikan->getAnime(new AnimeRequest($id)); $anime = $this->jikan->getAnime(new AnimeRequest($id));

View File

@ -11,6 +11,10 @@ use JMS\Serializer\Context;
use JMS\Serializer\Serializer; use JMS\Serializer\Serializer;
use Laravel\Lumen\Routing\Controller as BaseController; use Laravel\Lumen\Routing\Controller as BaseController;
/**
* Class Controller
* @package App\Http\Controllers\V4
*/
class Controller extends BaseController class Controller extends BaseController
{ {
/** /**

View File

@ -0,0 +1,120 @@
<?php
namespace App\Http\Controllers\V4DB;
use App\Http\HttpHelper;
use App\Http\HttpResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Jikan\Request\Anime\AnimeCharactersAndStaffRequest;
use Jikan\Request\Anime\AnimeEpisodeRequest;
use Jikan\Request\Anime\AnimeEpisodesRequest;
use Jikan\Request\Anime\AnimeForumRequest;
use Jikan\Request\Anime\AnimeMoreInfoRequest;
use Jikan\Request\Anime\AnimeNewsRequest;
use Jikan\Request\Anime\AnimePicturesRequest;
use Jikan\Request\Anime\AnimeRecentlyUpdatedByUsersRequest;
use Jikan\Request\Anime\AnimeRecommendationsRequest;
use Jikan\Request\Anime\AnimeRequest;
use Jikan\Request\Anime\AnimeReviewsRequest;
use Jikan\Request\Anime\AnimeStatsRequest;
use Jikan\Request\Anime\AnimeVideosRequest;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class AnimeController extends Controller
{
public function main(Request $request, int $id)
{
$result = DB::table('anime')
->where('mal_id', $id)
->get([
'mal_id','url','image_url','trailer_url','title','title_english','title_japanese','title_synonyms','type','source','episodes','status','airing','aired','duration','rating','score','scored_by','rank','popularity','members','favorites','synopsis','background','premiered','broadcast','related','producers','licensors','studios','genres','opening_themes','ending_themes'
]);
$response = $result->toArray();
if (!empty($response)) {
$response = $response[0];
return response(
$this->prepareResponse($request, $response)
);
}
return HttpResponse::notFound($request);
}
public function characters_staff(int $id)
{
$anime = $this->jikan->getAnimeCharactersAndStaff(new AnimeCharactersAndStaffRequest($id));
return response($this->serializer->serialize($anime, 'json'));
}
public function episode(int $id, int $episodeId)
{
$anime = $this->jikan->getAnimeEpisode(new AnimeEpisodeRequest($id, $episodeId));
return response($this->serializer->serialize($anime, 'json'));
}
public function episodes(int $id)
{
$page = $_GET['page'] ?? 1;
$anime = $this->jikan->getAnimeEpisodes(new AnimeEpisodesRequest($id, $page));
return response($this->serializer->serialize($anime, 'json'));
}
public function news(int $id)
{
$anime = ['articles' => $this->jikan->getNewsList(new AnimeNewsRequest($id))];
return response($this->serializer->serialize($anime, 'json'));
}
public function forum(int $id)
{
$anime = ['topics' => $this->jikan->getAnimeForum(new AnimeForumRequest($id))];
return response($this->serializer->serialize($anime, 'json'));
}
public function videos(int $id)
{
$anime = $this->jikan->getAnimeVideos(new AnimeVideosRequest($id));
return response($this->serializer->serialize($anime, 'json'));
}
public function pictures(int $id)
{
$anime = ['pictures' => $this->jikan->getAnimePictures(new AnimePicturesRequest($id))];
return response($this->serializer->serialize($anime, 'json'));
}
public function stats(int $id)
{
$anime = $this->jikan->getAnimeStats(new AnimeStatsRequest($id));
return response($this->serializer->serialize($anime, 'json'));
}
public function moreInfo(int $id)
{
$anime = ['moreinfo' => $this->jikan->getAnimeMoreInfo(new AnimeMoreInfoRequest($id))];
return response(json_encode($anime));
}
public function recommendations(int $id)
{
$anime = ['recommendations' => $this->jikan->getAnimeRecommendations(new AnimeRecommendationsRequest($id))];
return response($this->serializer->serialize($anime, 'json'));
}
public function userupdates(int $id, int $page = 1)
{
$anime = ['users' => $this->jikan->getAnimeRecentlyUpdatedByUsers(new AnimeRecentlyUpdatedByUsersRequest($id, $page))];
return response($this->serializer->serialize($anime, 'json'));
}
public function reviews(int $id, int $page = 1)
{
$anime = ['reviews' => $this->jikan->getAnimeReviews(new AnimeReviewsRequest($id, $page))];
return response($this->serializer->serialize($anime, 'json'));
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Character\CharacterRequest;
use Jikan\Request\Character\CharacterPicturesRequest;
class CharacterController extends Controller
{
public function main(int $id)
{
$character = $this->jikan->getCharacter(new CharacterRequest($id));
return response($this->serializer->serialize($character, 'json'));
}
public function pictures(int $id)
{
$character = ['pictures' => $this->jikan->getCharacterPictures(new CharacterPicturesRequest($id))];
return response($this->serializer->serialize($character, 'json'));
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Club\ClubRequest;
use Jikan\Request\Club\UserListRequest;
class ClubController extends Controller
{
public function main(int $id)
{
$club = $this->jikan->getClub(new ClubRequest($id));
return response($this->serializer->serialize($club, 'json'));
}
public function members(int $id, int $page = 1)
{
$club = ['members' => $this->jikan->getClubUsers(new UserListRequest($id, $page))];
return response($this->serializer->serialize($club, 'json'));
}
}

View File

@ -0,0 +1,99 @@
<?php
namespace App\Http\Controllers\V4DB;
use App\Http\HttpHelper;
use App\Providers\SerializerFactory;
use App\Providers\SerializerServiceProdivder;
use App\Providers\SerializerServiceProviderV3;
use Illuminate\Http\Request;
use Jikan\Jikan;
use Jikan\MyAnimeList\MalClient;
use JMS\Serializer\Context;
use JMS\Serializer\Serializer;
use Laravel\Lumen\Routing\Controller as BaseController;
/**
* Class Controller
* @package App\Http\Controllers\V4DB
*/
class Controller extends BaseController
{
/**
* @var Serializer
*/
protected $serializer;
/**
* @var MalClient
*/
protected $jikan;
/**
* @var Request
*/
private $request;
/**
* @var array
*/
private $response;
/**
* AnimeController constructor.
*
* @param Serializer $serializer
* @param MalClient $jikan
*/
public function __construct(MalClient $jikan)
{
$this->serializer = SerializerFactory::createV4();
$this->jikan = $jikan;
}
/**
* @param array $response
* @return array
*/
protected function prepareResponse(Request $request, array $response) : array
{
$this->request = $request;
$this->response = $response;
unset($this->response['_id']);
$this->mutation();
$this->response = ['data' => $this->response];
return $this->response;
}
/**
* @param Request $request
* @param array $response
* @return array
*/
private function mutation() : void
{
$requestType = HttpHelper::requestType($this->request);
if (($requestType === 'anime' || $requestType === 'manga')) {
// Fix JSON response for empty related object
if (isset($this->response['related']) && \count($this->response['related']) === 0) {
$this->response['related'] = new \stdClass();
}
if (isset($this->response['related']) && !is_object($this->response['related']) && !empty($this->response['related'])) {
$relation = [];
foreach ($this->response['related'] as $relationType => $related) {
$relation[] = [
'relation' => $relationType,
'items' => $related
];
}
$this->response['related'] = $relation;
}
}
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Genre\AnimeGenreRequest;
use Jikan\Request\Genre\AnimeGenresRequest;
use Jikan\Request\Genre\MangaGenreRequest;
class GenreController extends Controller
{
public function anime(int $id, int $page = 1)
{
$person = $this->jikan->getAnimeGenre(new AnimeGenreRequest($id, $page));
return response($this->serializer->serialize($person, 'json'));
}
public function manga(int $id, int $page = 1)
{
$person = $this->jikan->getMangaGenre(new MangaGenreRequest($id, $page));
return response($this->serializer->serialize($person, 'json'));
}
public function animeListing()
{
$results = $this->jikan->getAnimeGenres(new AnimeGenresRequest());
return response($this->serializer->serialize($results, 'json'));
}
public function mangaListing()
{
$results = $this->jikan->getAnimeGenres(new AnimeGenresRequest());
return response($this->serializer->serialize($results, 'json'));
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Magazine\MagazineRequest;
use Jikan\Request\Magazine\MagazinesRequest;
class MagazineController extends Controller
{
public function main()
{
$results = $this->jikan->getMagazines(new MagazinesRequest());
return response($this->serializer->serialize($results, 'json'));
}
public function resource(int $id, int $page = 1)
{
$magazine = $this->jikan->getMagazine(new MagazineRequest($id, $page));
return response($this->serializer->serialize($magazine, 'json'));
}
}

View File

@ -0,0 +1,84 @@
<?php
namespace App\Http\Controllers\V4DB;
use App\Http\HttpHelper;
use Jikan\Request\Manga\MangaCharactersRequest;
use Jikan\Request\Manga\MangaForumRequest;
use Jikan\Request\Manga\MangaMoreInfoRequest;
use Jikan\Request\Manga\MangaNewsRequest;
use Jikan\Request\Manga\MangaPicturesRequest;
use Jikan\Request\Manga\MangaRecentlyUpdatedByUsersRequest;
use Jikan\Request\Manga\MangaRecommendationsRequest;
use Jikan\Request\Manga\MangaRequest;
use Jikan\Request\Manga\MangaReviewsRequest;
use Jikan\Request\Manga\MangaStatsRequest;
class MangaController extends Controller
{
public function main(int $id)
{
$manga = $this->jikan->getManga(new MangaRequest($id));
$mangaSerialized = $this->serializer->serialize($manga, 'json');
$mangaSerialized = HttpHelper::serializeEmptyObjectsControllerLevel(
json_decode($mangaSerialized, true)
);
return response($this->serializer->serialize($mangaSerialized, 'json'));
}
public function characters(int $id)
{
$manga = ['characters' => $this->jikan->getMangaCharacters(new MangaCharactersRequest($id))];
return response($this->serializer->serialize($manga, 'json'));
}
public function news(int $id)
{
$manga = ['articles' => $this->jikan->getNewsList(new MangaNewsRequest($id))];
return response($this->serializer->serialize($manga, 'json'));
}
public function forum(int $id)
{
$manga = ['topics' => $this->jikan->getMangaForum(new MangaForumRequest($id))];
return response($this->serializer->serialize($manga, 'json'));
}
public function pictures(int $id)
{
$manga = ['pictures' => $this->jikan->getMangaPictures(new MangaPicturesRequest($id))];
return response($this->serializer->serialize($manga, 'json'));
}
public function stats(int $id)
{
$manga = $this->jikan->getMangaStats(new MangaStatsRequest($id));
return response($this->serializer->serialize($manga, 'json'));
}
public function moreInfo(int $id)
{
$manga = ['moreinfo' => $this->jikan->getMangaMoreInfo(new MangaMoreInfoRequest($id))];
return response($this->serializer->serialize($manga, 'json'));
}
public function recommendations(int $id)
{
$manga = ['recommendations' => $this->jikan->getMangaRecommendations(new MangaRecommendationsRequest($id))];
return response($this->serializer->serialize($manga, 'json'));
}
public function userupdates(int $id, int $page = 1)
{
$manga = ['users' => $this->jikan->getMangaRecentlyUpdatedByUsers(new MangaRecentlyUpdatedByUsersRequest($id, $page))];
return response($this->serializer->serialize($manga, 'json'));
}
public function reviews(int $id, int $page = 1)
{
$manga = ['reviews' => $this->jikan->getMangaReviews(new MangaReviewsRequest($id, $page))];
return response($this->serializer->serialize($manga, 'json'));
}
}

View File

@ -0,0 +1,50 @@
<?php
namespace App\Http\Controllers\V4DB;
class MetaController extends Controller
{
public function status()
{
$info = app('redis')->info();
return response()->json([
'cached_requests' => count(app('redis')->keys('request:*')),
'requests_today' => count(app('redis')->keys('requests:today:*')),
'requests_this_week' => count(app('redis')->keys('requests:weekly:*')),
'requests_this_month' => count(app('redis')->keys('requests:monthly:*')),
'connected_clients' => $info['Clients']['connected_clients'],
'total_connections_received' => $info['Stats']['total_connections_received'],
]);
}
public function requests($type, $period, $offset = 0)
{
if (!\in_array($type, [
'anime', 'manga', 'character', 'person', 'people', 'search', 'top', 'season', 'schedule', 'user', 'producer', 'magazine', 'genre'
])) {
return response()->json([
'error' => 'Bad Request'
], 400);
}
if (!\in_array($period, ['today', 'weekly', 'monthly'])) {
return response()->json([
'error' => 'Bad Request'
], 400);
}
$requests = [];
$data = app('redis')->keys("requests:{$period}:*{$type}*");
foreach ($data as $key) {
$requests[explode(":", $key)[2]] = (int) app('redis')->get($key);
}
arsort($requests);
return response()->json(
\array_slice($requests, $offset, 1000)
);
}
}

View File

@ -0,0 +1,21 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Person\PersonRequest;
use Jikan\Request\Person\PersonPicturesRequest;
class PersonController extends Controller
{
public function main(int $id)
{
$person = $this->jikan->getPerson(new PersonRequest($id));
return response($this->serializer->serialize($person, 'json'));
}
public function pictures(int $id)
{
$person = ['pictures' => $this->jikan->getPersonPictures(new PersonPicturesRequest($id))];
return response($this->serializer->serialize($person, 'json'));
}
}

View File

@ -0,0 +1,22 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Producer\ProducerRequest;
use Jikan\Request\Producer\ProducersRequest;
class ProducerController extends Controller
{
public function main()
{
$results = $this->jikan->getProducers(new ProducersRequest());
return response($this->serializer->serialize($results, 'json'));
}
public function resource(int $id, int $page = 1)
{
$producer = $this->jikan->getProducer(new ProducerRequest($id, $page));
return response($this->serializer->serialize($producer, 'json'));
}
}

View File

@ -0,0 +1,34 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Helper\Constants;
use Jikan\Request\Recommendations\RecentRecommendationsRequest;
class RecommendationsController extends Controller
{
public function anime()
{
$page = $_GET['page'] ?? 1;
$results = [
'recommendations' => $this->jikan->getRecentRecommendations(
new RecentRecommendationsRequest(Constants::RECENT_RECOMMENDATION_ANIME, $page)
)
];
return response($this->serializer->serialize($results, 'json'));
}
public function manga()
{
$page = $_GET['page'] ?? 1;
$results = [
'recommendations' => $this->jikan->getRecentRecommendations(
new RecentRecommendationsRequest(Constants::RECENT_RECOMMENDATION_MANGA, $page)
)
];
return response($this->serializer->serialize($results, 'json'));
}
}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Helper\Constants;
use Jikan\Request\Reviews\RecentReviewsRequest;
class ReviewsController extends Controller
{
public function bestVoted()
{
$page = $_GET['page'] ?? 1;
$results = $this->jikan->getRecentReviews(
new RecentReviewsRequest(Constants::RECENT_REVIEW_BEST_VOTED, $page)
);
return response($this->serializer->serialize($results, 'json'));
}
public function anime()
{
$page = $_GET['page'] ?? 1;
$results = $this->jikan->getRecentReviews(
new RecentReviewsRequest(Constants::RECENT_REVIEW_ANIME, $page)
);
return response($this->serializer->serialize($results, 'json'));
}
public function manga()
{
$page = $_GET['page'] ?? 1;
$results = $this->jikan->getRecentReviews(
new RecentReviewsRequest(Constants::RECENT_REVIEW_MANGA, $page)
);
return response($this->serializer->serialize($results, 'json'));
}
}

View File

@ -0,0 +1,39 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Schedule\ScheduleRequest;
class ScheduleController extends Controller
{
private const VALID_DAYS = [
'monday',
'tuesday',
'wednesday',
'thursday',
'friday',
'saturday',
'sunday',
'other',
'unknown',
];
public function main(?string $day = null)
{
if (null !== $day && !\in_array(strtolower($day), self::VALID_DAYS, true)) {
return response()->json([
'error' => 'Bad Request',
])->setStatusCode(400);
}
$schedule = $this->jikan->getSchedule(new ScheduleRequest());
if (null !== $day) {
$schedule = [
strtolower($day) => $schedule->{'get'.ucfirst(strtolower($day))}(),
];
}
return response($this->serializer->serialize($schedule, 'json'));
}
}

View File

@ -0,0 +1,114 @@
<?php
namespace App\Http\Controllers\V4DB;
use App\Http\Middleware\Throttle;
use App\Http\QueryBuilder\SearchQueryBuilderAnime;
use App\Http\SearchQueryBuilder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Jikan\Jikan;
use Jikan\MyAnimeList\MalClient;
use Jikan\Request\Search\AnimeSearchRequest;
use Jikan\Request\Search\MangaSearchRequest;
use Jikan\Request\Search\CharacterSearchRequest;
use Jikan\Request\Search\PersonSearchRequest;
use Jikan\Helper\Constants as JikanConstants;
use Jikan\Request\Search\UserSearchRequest;
use Jikan\Request\User\UsernameByIdRequest;
use JMS\Serializer\Serializer;
use phpDocumentor\Reflection\Types\Object_;
class SearchController extends Controller
{
private $request;
const MAX_RESULTS_PER_PAGE = 50;
public function anime(Request $request)
{
$this->request = $request;
$results = SearchQueryBuilderAnime::query(
$request,
DB::table('anime')
->select([
'mal_id','url','image_url','trailer_url','title','title_english','title_japanese','title_synonyms','type','source','episodes','status','airing','aired','duration','rating','score','scored_by','rank','popularity','members','favorites','synopsis','background','premiered','broadcast','related','producers','licensors','studios','genres','opening_themes','ending_themes'
])
);
return response(
SearchQueryBuilderAnime::paginate($request, $results)
);
}
public function manga(int $page = 1)
{
$search = $this->jikan->getMangaSearch(
SearchQueryBuilder::create(
(new MangaSearchRequest())->setPage($page)
)
);
return response($this->filter($search));
}
public function people(int $page = 1)
{
$search = $this->jikan->getPersonSearch(
SearchQueryBuilder::create(
(new PersonSearchRequest())->setPage($page)
)
);
return response($this->filter($search));
}
public function character(int $page = 1)
{
$search = $this->jikan->getCharacterSearch(
SearchQueryBuilder::create(
(new CharacterSearchRequest())->setPage($page)
)
);
return response($this->filter($search));
}
public function users()
{
$search = $this->jikan->getUserSearch(
SearchQueryBuilder::create(
new UserSearchRequest()
)
);
return response($this->filter($search));
}
public function userById(int $id)
{
$search = $this->jikan->getUsernameById(
new UsernameByIdRequest($id)
);
return response($this->filter($search));
}
private function filter($object)
{
$limit = $_GET['limit'] ?? null;
$data = json_decode(
$this->serializer->serialize($object, 'json'),
true
);
if (!is_null($limit)) {
$data['results'] = array_slice($data['results'], 0, $limit);
}
return json_encode(
$data
);
}
}

View File

@ -0,0 +1,45 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Seasonal\SeasonalRequest;
use Jikan\Request\SeasonList\SeasonListRequest;
class SeasonController extends Controller
{
private const VALID_SEASONS = [
'summer',
'spring',
'winter',
'fall'
];
public function main(?int $year = null, ?string $season = null)
{
if (!is_null($season) && !\in_array(strtolower($season), self::VALID_SEASONS)) {
return response()->json([
'error' => 'Bad Request'
])->setStatusCode(400);
}
$season = $this->jikan->getSeasonal(new SeasonalRequest($year, $season));
return response($this->serializer->serialize($season, 'json'));
}
public function archive()
{
return response(
$this->serializer->serialize(
['archive' => $this->jikan->getSeasonList(new SeasonListRequest())],
'json'
)
);
}
public function later()
{
$season = $this->jikan->getSeasonal(new SeasonalRequest(null, null, true));
return response($this->serializer->serialize($season, 'json'));
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\Top\TopAnimeRequest;
use Jikan\Request\Top\TopMangaRequest;
use Jikan\Request\Top\TopCharactersRequest;
use Jikan\Request\Top\TopPeopleRequest;
use Jikan\Helper\Constants as JikanConstants;
class TopController extends Controller
{
public function anime(int $page = 1, string $type = null)
{
if (!is_null($type) && !\in_array(strtolower($type), [
JikanConstants::TOP_AIRING,
JikanConstants::TOP_UPCOMING,
JikanConstants::TOP_TV,
JikanConstants::TOP_MOVIE,
JikanConstants::TOP_OVA,
JikanConstants::TOP_SPECIAL,
JikanConstants::TOP_BY_POPULARITY,
JikanConstants::TOP_BY_FAVORITES,
])) {
return response()->json([
'error' => 'Bad Request'
])->setStatusCode(400);
}
$anime = $this->jikan->getTopAnime(new TopAnimeRequest($page, $type));
$top = ['top' => $this->jikan->getTopAnime(new TopAnimeRequest($page, $type))];
return response($this->serializer->serialize($top, 'json'));
}
public function manga(int $page = 1, string $type = null)
{
if (!is_null($type) && !\in_array(
strtolower($type),
[
JikanConstants::TOP_MANGA,
JikanConstants::TOP_NOVEL,
JikanConstants::TOP_ONE_SHOT,
JikanConstants::TOP_DOUJINSHI,
JikanConstants::TOP_MANHWA,
JikanConstants::TOP_MANHUA,
JikanConstants::TOP_BY_POPULARITY,
JikanConstants::TOP_BY_FAVORITES,
]
)) {
return response()->json([
'error' => 'Bad Request'
])->setStatusCode(400);
}
$top = ['top' => $this->jikan->getTopManga(new TopMangaRequest($page, $type))];
return response($this->serializer->serialize($top, 'json'));
}
public function people(int $page = 1)
{
$top = ['top' => $this->jikan->getTopPeople(new TopPeopleRequest($page))];
return response($this->serializer->serialize($top, 'json'));
}
public function characters(int $page = 1)
{
$top = ['top' => $this->jikan->getTopCharacters(new TopCharactersRequest($page))];
return response($this->serializer->serialize($top, 'json'));
}
}

View File

@ -0,0 +1,161 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Request\User\RecentlyOnlineUsersRequest;
use Jikan\Request\User\UserAnimeListRequest;
use Jikan\Request\User\UserClubsRequest;
use Jikan\Request\User\UserMangaListRequest;
use Jikan\Request\User\UserProfileRequest;
use Jikan\Request\User\UserFriendsRequest;
use Jikan\Request\User\UserHistoryRequest;
use Jikan\Request\User\UserRecommendationsRequest;
use Jikan\Request\User\UserReviewsRequest;
class UserController extends Controller
{
public function profile(string $username)
{
$user = $this->jikan->getUserProfile(new UserProfileRequest($username));
return response($this->serializer->serialize($user, 'json'));
}
public function history(string $username, ?string $type = null)
{
if (!is_null($type) && !\in_array(strtolower($type), ['anime', 'manga'])) {
return response()->json([
'error' => 'Bad Request'
])->setStatusCode(400);
}
$person = ['history' => $this->jikan->getUserHistory(new UserHistoryRequest($username, $type))];
return response($this->serializer->serialize($person, 'json'));
}
public function friends(string $username, int $page = 1)
{
$person = ['friends' => $this->jikan->getUserFriends(new UserFriendsRequest($username, $page))];
return response($this->serializer->serialize($person, 'json'));
}
public function animelist(string $username, ?string $status = null, int $page = 1)
{
if (!is_null($status)) {
$status = strtolower($status);
if (!\in_array($status, ['all', 'watching', 'completed', 'onhold', 'dropped', 'plantowatch', 'ptw'])) {
return response()->json([
'error' => 'Bad Request'
])->setStatusCode(400);
}
}
$status = $this->listStatusToId($status);
return response(
$this->serializer->serialize(
[
'anime' => $this->jikan->getUserAnimeList(
new UserAnimeListRequest($username, $page, $status)
)
],
'json'
)
);
}
public function mangalist(string $username, ?string $status = null, int $page = 1)
{
if (!is_null($status)) {
$status = strtolower($status);
if (!\in_array($status, ['all', 'reading', 'completed', 'onhold', 'dropped', 'plantoread', 'ptr'])) {
return response()->json([
'error' => 'Bad Request'
])->setStatusCode(400);
}
}
$status = $this->listStatusToId($status);
return response(
$this->serializer->serialize(
[
'manga' => $this->jikan->getUserMangaList(
new UserMangaListRequest($username, $page, $status)
)
],
'json'
)
);
}
public function reviews(string $username)
{
$page = $_GET['page'] ?? 1;
$results = $this->jikan->getUserReviews(
new UserReviewsRequest($username, $page)
);
return response($this->serializer->serialize($results, 'json'));
}
public function recommendations(string $username)
{
$page = $_GET['page'] ?? 1;
$results = $this->jikan->getUserRecommendations(
new UserRecommendationsRequest($username, $page)
);
return response($this->serializer->serialize($results, 'json'));
}
public function clubs(string $username)
{
$results = [
'clubs' => $this->jikan->getUserClubs(
new UserClubsRequest($username)
)
];
return response($this->serializer->serialize($results, 'json'));
}
public function recentlyOnline()
{
$results = [
'users' => $this->jikan->getRecentOnlineUsers(
new RecentlyOnlineUsersRequest()
)
];
return response($this->serializer->serialize($results, 'json'));
}
private function listStatusToId(?string $status) : int
{
if (is_null($status)) {
return 7;
}
switch ($status) {
case 'all':
return 7;
case 'watching':
case 'reading':
return 1;
case 'completed':
return 2;
case 'onhold':
return 3;
case 'dropped':
return 4;
case 'plantowatch':
case 'ptw':
case 'plantoread':
case 'ptr':
return 6;
default:
return 7;
}
}
}

View File

@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers\V4DB;
use Jikan\Helper\Constants;
use Jikan\Request\Watch\PopularEpisodesRequest;
use Jikan\Request\Watch\PopularPromotionalVideosRequest;
use Jikan\Request\Watch\RecentEpisodesRequest;
use Jikan\Request\Watch\RecentPromotionalVideosRequest;
class WatchController extends Controller
{
public function recentEpisodes()
{
$results = $this->jikan->getRecentEpisodes(
new RecentEpisodesRequest()
);
return response($this->serializer->serialize($results, 'json'));
}
public function popularEpisodes()
{
$results = $this->jikan->getPopularEpisodes(
new PopularEpisodesRequest()
);
return response($this->serializer->serialize($results, 'json'));
}
public function recentPromos()
{
$page = $_GET['page'] ?? 1;
$results = $this->jikan->getRecentPromotionalVideos(
new RecentPromotionalVideosRequest($page)
);
return response($this->serializer->serialize($results, 'json'));
}
public function popularPromos()
{
$results = $this->jikan->getPopularPromotionalVideos(
new PopularPromotionalVideosRequest()
);
return response($this->serializer->serialize($results, 'json'));
}
}

View File

@ -19,7 +19,7 @@ class HttpHelper
public static function requestType(Request $request): string public static function requestType(Request $request): string
{ {
$requestType = $request->segments()[1]; $requestType = $request->segments()[1];
if (!\in_array($request->segments()[0], ['v1', 'v2', 'v3'])) { if (!\in_array($request->segments()[0], ['v1', 'v2', 'v3', 'v4'])) {
$requestType = $request->segments()[0]; $requestType = $request->segments()[0];
} }

23
app/Http/HttpResponse.php Normal file
View File

@ -0,0 +1,23 @@
<?php
namespace App\Http;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class HttpResponse
{
public static function notFound(Request $request) : Response
{
return response(
\json_encode([
'status' => 404,
'type' => 'BadResponseException',
'message' => 'Resource not found',
'error' => '404 on ' . $request->getUri()
]),
404
);
}
}

View File

@ -82,6 +82,10 @@ class DatabaseResolver
return $next($request); return $next($request);
} }
if (HttpHelper::requestAPIVersion($request) >= 4) {
return $next($request);
}
$this->requestUriHash = HttpHelper::getRequestUriHash($request); $this->requestUriHash = HttpHelper::getRequestUriHash($request);
$this->requestType = HttpHelper::requestType($request); $this->requestType = HttpHelper::requestType($request);
$this->requestCacheTtl = HttpHelper::requestCacheExpiry($this->requestType); $this->requestCacheTtl = HttpHelper::requestCacheExpiry($this->requestType);

View File

@ -0,0 +1,204 @@
<?php
namespace App\Http\QueryBuilder;
use App\Http\HttpHelper;
use Illuminate\Database\Query\Builder;
use Illuminate\Http\Request;
class SearchQueryBuilderAnime implements SearchQueryBuilderInterface
{
const MAX_RESULTS_PER_PAGE = 50;
const MAP_TYPES = [
'tv' => 'TV',
'movie' => 'Movie',
'ova' => 'OVA',
'special' => 'Special',
'ona' => 'ONA',
'music' => 'Music'
];
const MAP_STATUS = [
'airing' => 'Currently Airing',
'completed' => 'Finished Airing',
'upcoming' => 'Not yet aired',
];
const MAP_RATING = [
'g' => 'G - All Ages',
'pg' => 'PG - Children',
'pg13' => 'PG-13 - Teens 13 or older',
'r17' => 'R - 17+ (violence & profanity)',
'r' => 'R+ - Mild Nudity',
'rx' => 'Rx - Hentai'
];
const ORDER_BY = [
'mal_id', 'title', 'aired.from', 'aired.to', 'episodes', 'score', 'scored_by', 'rank', 'popularity', 'members', 'favorites'
];
public static function query(Request $request, Builder $results) : Builder
{
$requestType = HttpHelper::requestType($request);
$query = $request->get('q');
$type = self::mapType($request->get('type'));
$score = $request->get('score') ?? 0;
$status = self::mapStatus($request->get('status'));
$rating = self::mapRating($request->get('rating'));
$sfw = $request->get('sfw');
$genres = $request->get('genre');
$orderBy = $request->get('order_by');
$sort = self::mapSort($request->get('sort'));
if (!empty($query)) {
$results = $results
->where('title', 'like', "%{$query}%")
->where('title_english', 'like', "%{$query}%")
->where('title_japanese', 'like', "%{$query}%")
->where('title_synonyms', 'like', "%{$query}%");
}
if (empty($query)) {
$results = $results
->orderBy('mal_id');
}
if (!is_null($type)) {
$results = $results
->where('type', $type);
}
if ($score !== 0) {
$score = (float) $score;
$results = $results
->where('score', '>=', $score);
}
if (!is_null($status)) {
$results = $results
->where('status', $status);
}
if (!is_null($rating)) {
$results = $results
->where('rating', $rating);
}
if (!is_null($sfw)) {
$results = $results
->where('rating', '!=', self::MAP_RATING['rx']);
}
if (!is_null($genres)) {
$genres = explode(',', $genres);
foreach ($genres as $genre) {
if (empty($genre)) {
continue;
}
$genre = (int) $genre;
$results = $results
->where('genres.mal_id', $genre);
}
}
if (!is_null($orderBy)) {
$results = $results
->orderBy($orderBy, $sort ?? 'asc');
}
return $results;
}
public static function paginate(Request $request, Builder $results)
{
$page = $request->get('page') ?? 1;
$limit = $request->get('limit') ?? self::MAX_RESULTS_PER_PAGE;
$limit = (int) $limit;
if ($limit <= 0) {
$limit = 1;
}
if ($limit > self::MAX_RESULTS_PER_PAGE) {
$limit = self::MAX_RESULTS_PER_PAGE;
}
if ($page <= 0) {
$page = 1;
}
$paginated = $results
->paginate(
$limit,
null,
null,
$page
);
$items = $paginated->items();
foreach ($items as &$item) {
unset($item['_id']);
}
return [
'per_page' => $paginated->perPage(),
'total' => $paginated->total(),
'current_page' => $paginated->currentPage(),
'last_page' => $paginated->lastPage(),
'data' => $items
];
}
public static function mapType(?string $type = null) : ?string
{
if (!is_null($type)) {
return null;
}
$type = strtolower($type);
return self::MAP_TYPES[$type] ?? null;
}
public static function mapStatus(?string $status = null) : ?string
{
if (!is_null($status)) {
return null;
}
$status = strtolower($status);
return self::MAP_STATUS[$status] ?? null;
}
public static function mapRating(?string $rating = null) : ?string
{
if (!is_null($rating)) {
return null;
}
$rating = strtolower($rating);
return self::MAP_RATING[$rating] ?? null;
}
public static function mapSort(?string $sort = null) : ?string
{
if (!is_null($sort)) {
return null;
}
$sort = strtolower($sort);
return $sort === 'desc' ? 'desc' : 'asc';
}
}

View File

@ -0,0 +1,12 @@
<?php
namespace App\Http\QueryBuilder;
use Illuminate\Database\Query\Builder;
use Illuminate\Http\Request;
interface SearchQueryBuilderInterface
{
static function query(Request $request, Builder $results) : Builder;
static function paginate(Request $request, Builder $results);
}

View File

@ -142,16 +142,17 @@ $commonMiddleware = [
// 'source-health-monitor' // 'source-health-monitor'
]; ];
//$app->router->group( $app->router->group(
// [ [
// 'prefix' => 'v4', 'prefix' => 'v4',
// 'namespace' => 'App\Http\Controllers\V4', 'namespace' => env('SOURCE') === 'local' ? 'App\Http\Controllers\V4DB' : 'App\Http\Controllers\V4',
// 'middleware' => $commonMiddleware 'middleware' => $commonMiddleware
// ],
// function ($router) { ],
// require __DIR__.'/../routes/web.v4.php'; function ($router) {
// } require __DIR__.'/../routes/web.v4.php';
//); }
);
$app->router->group( $app->router->group(
[ [