mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
initial commit for v3
This commit is contained in:
parent
cec88182b1
commit
a93fada4d1
@ -53,14 +53,14 @@ class Handler extends ExceptionHandler
|
||||
public function render($request, Exception $e)
|
||||
{
|
||||
|
||||
Bugsnag::notifyException($e);
|
||||
if ($e instanceof HttpResponseException) {
|
||||
} elseif ($e instanceof ModelNotFoundException) {
|
||||
$e = new NotFoundHttpException($e->getMessage(), $e);
|
||||
} elseif ($e instanceof AuthorizationException) {
|
||||
$e = new HttpException(403, $e->getMessage());
|
||||
} elseif ($e instanceof ValidationException && $e->getResponse()) {
|
||||
}
|
||||
// Bugsnag::notifyException($e);
|
||||
// if ($e instanceof HttpResponseException) {
|
||||
// } elseif ($e instanceof ModelNotFoundException) {
|
||||
// $e = new NotFoundHttpException($e->getMessage(), $e);
|
||||
// } elseif ($e instanceof AuthorizationException) {
|
||||
// $e = new HttpException(403, $e->getMessage());
|
||||
// } elseif ($e instanceof ValidationException && $e->getResponse()) {
|
||||
// }
|
||||
|
||||
$fe = FlattenException::create($e);
|
||||
|
||||
|
@ -2,193 +2,42 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use http\Env\Response;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Exceptions\Handler as Handler;
|
||||
use Jikan\Jikan;
|
||||
use Bugsnag\BugsnagLaravel\Facades\Bugsnag;
|
||||
use Lazer\Classes\Database as Lazer;
|
||||
use GuzzleHttp\Client as GuzzleClient;
|
||||
|
||||
class AnimeController extends Controller
|
||||
{
|
||||
/**
|
||||
* Create a new controller instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
public $id;
|
||||
public $extend;
|
||||
public $extendArgs;
|
||||
|
||||
private $validExtends = ['episodes', 'characters_staff', 'news', 'videos', 'pictures', 'stats', 'forum', 'moreinfo'];
|
||||
private const VALID_REQUESTS = ['episodes', 'characters_staff', 'news', 'forum', 'pictures', 'videos', 'stats', 'moreinfo'];
|
||||
|
||||
public function request($id, $extend = null, $extendArgs = null) {
|
||||
public function request(int $id, $request = null, $requestArg = null) {
|
||||
|
||||
$this->id = $id;
|
||||
$this->extend = $extend;
|
||||
$this->extendArgs = is_array($extendArgs) ? $extendArgs[0] : $extendArgs;
|
||||
$this->guzzle = new GuzzleClient;
|
||||
|
||||
$this->hash = sha1('anime' . $this->id . $this->extend . $this->extendArgs);
|
||||
$this->response['request_hash'] = $this->hash;
|
||||
$this->response['request_cached'] = false;
|
||||
|
||||
if (app('redis')->exists($this->hash)) {
|
||||
$this->response['request_cached'] = true;
|
||||
return response()->json(
|
||||
$this->response + json_decode(app('redis')->get($this->hash), true)
|
||||
);
|
||||
try {
|
||||
$jikan = new Jikan($this->guzzle);
|
||||
$this->response = $jikan->Anime($id);
|
||||
} catch (\Jikan\Exception\ParserException $e) {
|
||||
return response()->json([
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
}
|
||||
|
||||
$jikan = new Jikan;
|
||||
$serializer = \JMS\Serializer\SerializerBuilder::create()->build();
|
||||
$json = $serializer->serialize($this->response, 'json');
|
||||
|
||||
if (isset($this->extend)) {
|
||||
if (!in_array($this->extend, $this->validExtends)) {
|
||||
return response()->json(
|
||||
['error' => 'Invalid extended request: "' . $this->extend . '"'], 400
|
||||
);
|
||||
}
|
||||
|
||||
switch ($this->extend) {
|
||||
case 'episodes':
|
||||
try {
|
||||
|
||||
if (!isset($this->extendArgs) || empty($this->extendArgs)) {
|
||||
$this->extendArgs = 1;
|
||||
} else {
|
||||
intval($this->extendArgs);
|
||||
}
|
||||
|
||||
$this->extendArgs = $this->extendArgs <= 0 ? 1 : $this->extendArgs;
|
||||
|
||||
$jikan->Anime($this->id, [EPISODES => $this->extendArgs]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'characters_staff':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [CHARACTERS_STAFF]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'news':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [NEWS]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'videos':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [VIDEOS]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'pictures':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [PICTURES]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'stats':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [STATS]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'moreinfo':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [MORE_INFO]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'forum':
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id, [FORUM]);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
|
||||
$jikan->Anime($this->id);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
Bugsnag::notifyException($e);
|
||||
return response()->json(
|
||||
['error' => $e->getMessage()], 404
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($jikan->response) || $jikan->response === false) {
|
||||
return response()->json(['error' => 'MyAnimeList Rate Limiting reached. Slow down!'], 429);
|
||||
}
|
||||
|
||||
$this->cache = json_encode($jikan->response);
|
||||
if ($this->cache !== false) {
|
||||
if (app('redis')->set($this->hash, $this->cache)) {
|
||||
app('redis')->expire($this->hash, CACHE_EXPIRE);
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(
|
||||
$this->response + $jikan->response
|
||||
return response(
|
||||
$json
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ namespace App\Http\Controllers;
|
||||
|
||||
use Laravel\Lumen\Routing\Controller as BaseController;
|
||||
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
private $hash;
|
||||
private $cache;
|
||||
private $response = [];
|
||||
protected $guzzle;
|
||||
protected $response;
|
||||
}
|
||||
|
@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
|
||||
class Throttle
|
||||
{
|
||||
|
||||
private $ip;
|
||||
private $hit;
|
||||
|
||||
private $sessions = [];
|
||||
private $rateLimited = false;
|
||||
|
||||
private $request_hash;
|
||||
private $request_cached;
|
||||
|
||||
public function handle($request, Closure $next)
|
||||
{
|
||||
|
||||
$response = $next($request);
|
||||
|
||||
$this->loadSessions(); // load the session
|
||||
|
||||
if (!isset($response->original['error'])) { // don't throttle errors
|
||||
|
||||
$this->request_hash = $response->original['request_hash'];
|
||||
$this->request_cached = $response->original['request_cached'];
|
||||
|
||||
if (!$this->request_cached) { // don't throttle cached requests
|
||||
$this->hit(); // increase API Call Count
|
||||
}
|
||||
}
|
||||
|
||||
$this->rateLimit(); // check if it's over the limit
|
||||
|
||||
$this->save(); // save the updated session
|
||||
|
||||
if ($this->rateLimited) {
|
||||
return response()->json(['error' => 'You have reached your limit of ' . RATE_LIMIT . ' API calls per day, please try again later'], 429);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function hit() {
|
||||
$this->ip = $_SERVER['REMOTE_ADDR'];
|
||||
$date = date("d-m-Y");
|
||||
|
||||
if (!isset($this->sessions[$this->ip])) { // register the session
|
||||
$this->sessions[$this->ip] = [
|
||||
$date => 0
|
||||
];
|
||||
}
|
||||
|
||||
if (!isset($this->sessions[$this->ip][$date])) { // register today's session
|
||||
$this->sessions[$this->ip][$date] = 0;
|
||||
}
|
||||
|
||||
$this->sessions[$this->ip][$date]++; // increase API Call count
|
||||
|
||||
$this->hit = $this->sessions[$this->ip][$date];
|
||||
}
|
||||
|
||||
public function rateLimit() {
|
||||
$this->rateLimited = ($this->hit > RATE_LIMIT) ? true : false;
|
||||
}
|
||||
|
||||
public function loadSessions() {
|
||||
$this->sessions = file_exists(SESSION_STORAGE_PATH) ? json_decode(file_get_contents(SESSION_STORAGE_PATH), true) : file_put_contents(SESSION_STORAGE_PATH, json_encode([]));
|
||||
}
|
||||
|
||||
public function save() {
|
||||
file_put_contents(SESSION_STORAGE_PATH, json_encode($this->sessions));
|
||||
}
|
||||
}
|
@ -11,7 +11,6 @@ try {
|
||||
/*
|
||||
Defines
|
||||
*/
|
||||
define('SESSION_STORAGE_PATH', '/var/www/api.jikan/storage/app/sessions.json'); // depreciated. Using Redis now
|
||||
define('BLACKLIST_PATH', '/var/www/api.jikan/storage/app/blacklist.json');
|
||||
define('RATE_LIMIT', 5000); // per day
|
||||
define('CACHE_EXPIRE', 3600 * 24 * 3); // 3 days
|
||||
@ -19,8 +18,8 @@ define('CACHE_EXPIRE_SEARCH', 3600 * 6); // 6 hours
|
||||
//define('CACHE_EXPIRE', 4); // 60 seconds | dev
|
||||
//define('CACHE_EXPIRE_SEARCH', 4); // 60 seconds | dev
|
||||
|
||||
define('REST_VERSION', '2.2');
|
||||
define('SOURCE_VERSION', '1.15.12');
|
||||
define('REST_VERSION', '3.0');
|
||||
define('SOURCE_VERSION', '2.0.0-rc.1');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -83,7 +82,6 @@ $app->middleware([App\Http\Middleware\Throttle::class]);*/
|
||||
$app->routeMiddleware([
|
||||
'blacklist' => App\Http\Middleware\Blacklist::class,
|
||||
'meta' => App\Http\Middleware\Meta::class,
|
||||
'throttle' => App\Http\Middleware\Throttle::class
|
||||
]);
|
||||
|
||||
/*
|
||||
@ -97,7 +95,6 @@ $app->routeMiddleware([
|
||||
|
|
||||
*/
|
||||
|
||||
$app->register(Bugsnag\BugsnagLaravel\BugsnagServiceProvider::class);
|
||||
$app->register(Illuminate\Redis\RedisServiceProvider::class);
|
||||
|
||||
// $app->register(App\Providers\AppServiceProvider::class);
|
||||
|
@ -9,11 +9,12 @@
|
||||
"laravel/lumen-framework": "5.5.*",
|
||||
"vlucas/phpdotenv": "~2.2",
|
||||
"jikan-me/jikan": "dev-master",
|
||||
"bugsnag/bugsnag-laravel": "^2.0",
|
||||
"danielmewes/php-rql": "dev-master",
|
||||
"illuminate/redis": "^5.5",
|
||||
"predis/predis": "^1.1",
|
||||
"voku/anti-xss": "^4.0"
|
||||
"voku/anti-xss": "^4.0",
|
||||
"divineomega/cachetphp": "^0.2.0",
|
||||
"jms/serializer": "^1.13"
|
||||
},
|
||||
"require-dev": {
|
||||
"fzaninotto/faker": "~1.4",
|
||||
|
1472
composer.lock
generated
1472
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,7 @@ $app = require __DIR__.'/../bootstrap/app.php';
|
||||
|
|
||||
*/
|
||||
|
||||
header('Content-Type: application/json');
|
||||
header("Access-Control-Allow-Origin: *");
|
||||
header("Access-Control-Allow-Methods: *");
|
||||
$app->run();
|
||||
|
@ -18,15 +18,14 @@ $router->get('/', function () use ($router) {
|
||||
return response()->json([
|
||||
'Author' => '@irfanDahir',
|
||||
'Contact' => 'irfan@jikan.moe',
|
||||
'JikanREST' => REST_VERSION,
|
||||
'JikanPHP' => SOURCE_VERSION,
|
||||
'Home' => 'https://jikan.moe/',
|
||||
'JikanREST' => '3.0',
|
||||
'JikanPHP' => '2.0.0-rc.1',
|
||||
'Home' => 'https://jikan.moe',
|
||||
'Docs' => 'https://jikan.docs.apiary.io',
|
||||
'GitHub' => 'https://github.com/jikan-me/jikan',
|
||||
'PRODUCTION_API_URL' => 'https://api.jikan.moe/',
|
||||
'STATUS_URL' => 'https://api.jikan.moe/meta/status',
|
||||
'RATE_LIMIT' => RATE_LIMIT,
|
||||
'CACHED_REQUESTS' => app('redis')->dbSize(),
|
||||
'PRODUCTION_API_URL' => 'https://api.jikan.moe',
|
||||
'STATUS_URL' => 'https://status.jikan.moe',
|
||||
// 'CACHED_REQUESTS' => app('redis')->dbSize(),
|
||||
]);
|
||||
});
|
||||
|
||||
@ -34,7 +33,7 @@ $router->get('meta/{request:[A-Za-z]+}[/{type:[A-Za-z]+}[/{period:[A-Za-z]+}[/{p
|
||||
'uses' => 'MetaLiteController@request'
|
||||
]);
|
||||
|
||||
$router->group(['middleware' => ['blacklist', 'meta', 'throttle']], function() use ($router) {
|
||||
$router->group(['middleware' => ['blacklist', 'meta']], function() use ($router) {
|
||||
|
||||
$router->get('anime[/{id:[0-9]+}[/{extend:[A-Za-z_]+}[/{extendArgs}]]]', [
|
||||
'uses' => 'AnimeController@request'
|
||||
|
Loading…
x
Reference in New Issue
Block a user