mirror of
https://github.com/jikan-me/jikan-rest.git
synced 2025-02-20 11:23:35 +08:00
WIP: add insights
This commit is contained in:
parent
21535a403a
commit
f161bcb486
@ -61,7 +61,5 @@ class Kernel extends ConsoleKernel
|
||||
// Update common indexes daily
|
||||
$schedule->command('indexer:common')
|
||||
->daily();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
155
app/Http/Controllers/V4DB/InsightsController.php
Normal file
155
app/Http/Controllers/V4DB/InsightsController.php
Normal file
@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\V4DB;
|
||||
|
||||
use App\Http\Resources\V4\InsightsCollection;
|
||||
use App\Http\Resources\V4\TrendsCollection;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Pagination\Paginator;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use MongoDB\BSON\Regex;
|
||||
|
||||
class InsightsController extends Controller
|
||||
{
|
||||
|
||||
public function main(Request $request)
|
||||
{
|
||||
if (!env('INSIGHTS')) {
|
||||
return response()->json([
|
||||
'status' => 403,
|
||||
'type' => 'InsightsRuntimeException',
|
||||
'message' => 'Insights service is disabled',
|
||||
'error' => null
|
||||
], 403);
|
||||
}
|
||||
|
||||
$maxResultsPerPage = (int) env('MAX_RESULTS_PER_PAGE', 25);
|
||||
|
||||
$page = $request->get('page') ?? 1;
|
||||
$limit = $request->get('limit') ?? $maxResultsPerPage;
|
||||
|
||||
$limit = (int) $limit;
|
||||
|
||||
if ($limit <= 0) {
|
||||
$limit = 1;
|
||||
}
|
||||
|
||||
if ($limit > $maxResultsPerPage) {
|
||||
$limit = $maxResultsPerPage;
|
||||
}
|
||||
|
||||
$results = DB::table('insights')
|
||||
->where('timestamp', '>', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
|
||||
->orderBy('timestamp', 'desc')
|
||||
->paginate(
|
||||
$limit,
|
||||
['*'],
|
||||
null,
|
||||
$page
|
||||
);
|
||||
|
||||
return new InsightsCollection(
|
||||
$results
|
||||
);
|
||||
}
|
||||
|
||||
const TRENDS = [
|
||||
'anime',
|
||||
'manga',
|
||||
'people',
|
||||
'characters',
|
||||
];
|
||||
|
||||
public function trends(Request $request)
|
||||
{
|
||||
if (!env('INSIGHTS')) {
|
||||
return response()->json([
|
||||
'status' => 403,
|
||||
'type' => 'InsightsRuntimeException',
|
||||
'message' => 'Insights service is disabled',
|
||||
'error' => null
|
||||
], 403);
|
||||
}
|
||||
|
||||
$maxResultsPerPage = (int) env('MAX_RESULTS_PER_PAGE', 25);
|
||||
|
||||
$page = $request->get('page') ?? 1;
|
||||
$limit = $request->get('limit') ?? $maxResultsPerPage;
|
||||
$trend = $request->get('trend') ?? null;
|
||||
|
||||
$limit = (int) $limit;
|
||||
|
||||
if ($limit <= 0) {
|
||||
$limit = 1;
|
||||
}
|
||||
|
||||
if ($limit > $maxResultsPerPage) {
|
||||
$limit = $maxResultsPerPage;
|
||||
}
|
||||
|
||||
if (is_null($trend) || !in_array($trend, self::TRENDS)) {
|
||||
return response()->json([
|
||||
'status' => 400,
|
||||
'type' => 'BadRequestException',
|
||||
'message' => 'Trend value is invalid',
|
||||
'error' => null
|
||||
], 400);
|
||||
}
|
||||
|
||||
// $results = DB::table('insights')
|
||||
// ->where('url', 'regexp',"/\/v(\d)\/{$trend}\/(\d+).*/i")
|
||||
// ->where('timestamp', '>', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
|
||||
// ->orderBy('timestamp', 'desc')
|
||||
// ->paginate(
|
||||
// $limit,
|
||||
// ['*'],
|
||||
// null,
|
||||
// $page
|
||||
// );
|
||||
|
||||
$results = DB::table('insights')
|
||||
// ->where('url', 'regexp',"/\/v(\d)\/{$trend}\/(\d+).*/i")
|
||||
->where('timestamp', '>', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
|
||||
->orderBy('timestamp', 'desc')
|
||||
->raw(fn($collection) => $collection->aggregate([
|
||||
[
|
||||
'$group' => [
|
||||
'_id' => [
|
||||
'url' => '$url',
|
||||
'timestamp' => '$timestamp'
|
||||
],
|
||||
'urlCount' => [ '$sum' => 1 ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'$group' => [
|
||||
'_id' => '$_id.url',
|
||||
'count' => [ '$sum' => '$urlCount' ]
|
||||
]
|
||||
],
|
||||
[
|
||||
'$sort' => [ 'count' => -1 ]
|
||||
],
|
||||
['$skip' => ($page - 1) * $maxResultsPerPage],
|
||||
['$limit' => $maxResultsPerPage],
|
||||
]));
|
||||
// ->raw(fn($collection) => $collection->aggregate([
|
||||
// [
|
||||
// '$group' => [
|
||||
// '_id' => '$_id',
|
||||
// 'url' => ['$first' => '$url'],
|
||||
// 'count' => [ '$sum' => 1 ]
|
||||
// ]
|
||||
// ]
|
||||
// ]));
|
||||
|
||||
return new TrendsCollection(
|
||||
new LengthAwarePaginator(
|
||||
$results, DB::table('insights')->count(), $maxResultsPerPage, $page
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -2,24 +2,12 @@
|
||||
|
||||
namespace App\Http\Controllers\V4DB;
|
||||
|
||||
use App\Anime;
|
||||
use App\Http\HttpHelper;
|
||||
use App\Http\HttpResponse;
|
||||
use App\Http\QueryBuilder\SearchQueryBuilderAnime;
|
||||
use App\Http\QueryBuilder\SearchQueryBuilderMagazine;
|
||||
use App\Http\Resources\V4\AnimeCollection;
|
||||
use App\Http\Resources\V4\MagazineCollection;
|
||||
use App\Http\Resources\V4\MangaCollection;
|
||||
use App\Http\Resources\V4\NewsResource;
|
||||
use App\Magazine;
|
||||
use App\Manga;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Jenssegers\Mongodb\Eloquent\Builder;
|
||||
use Jikan\Request\Anime\AnimeNewsRequest;
|
||||
use Jikan\Request\Magazine\MagazineRequest;
|
||||
use Jikan\Request\Magazine\MagazinesRequest;
|
||||
use MongoDB\BSON\UTCDateTime;
|
||||
|
||||
class MagazineController extends Controller
|
||||
{
|
||||
|
@ -5,11 +5,9 @@ namespace App\Http\Controllers\V4DB;
|
||||
use App\Anime;
|
||||
use App\Http\QueryBuilder\SearchQueryBuilderProducer;
|
||||
use App\Http\Resources\V4\AnimeCollection;
|
||||
use App\Http\Resources\V4\MagazineCollection;
|
||||
use App\Http\Resources\V4\ProducerCollection;
|
||||
use App\Producer;
|
||||
use Illuminate\Http\Request;
|
||||
use Jikan\Request\Producer\ProducersRequest;
|
||||
|
||||
class ProducerController extends Controller
|
||||
{
|
||||
|
52
app/Http/Middleware/Insights.php
Normal file
52
app/Http/Middleware/Insights.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* Class Insights
|
||||
* @package App\Http\Middleware
|
||||
*/
|
||||
class Insights
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Closure $next
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $response
|
||||
* @return void
|
||||
*/
|
||||
public function terminate(Request $request, $response)
|
||||
{
|
||||
if (isset($response->original['error'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @todo scaling: implement as scheduled event if needed
|
||||
// Delete requests older than INSIGHTS_MAX_STORE
|
||||
DB::table('insights')
|
||||
->where('timestamp', '<', time() - env('INSIGHTS_MAX_STORE_TIME', 172800) )
|
||||
->delete();
|
||||
|
||||
DB::table('insights')
|
||||
->insert([
|
||||
'timestamp' => time(),
|
||||
'url' => $request->getRequestUri(),
|
||||
'type' =>
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
55
app/Http/Resources/V4/InsightsCollection.php
Normal file
55
app/Http/Resources/V4/InsightsCollection.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Resources\V4;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
class InsightsCollection extends ResourceCollection
|
||||
{
|
||||
|
||||
/**
|
||||
* The resource that this resource collects.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $collects = 'App\Http\Resources\V4\InsightsResource';
|
||||
|
||||
|
||||
private $pagination;
|
||||
|
||||
public function __construct(LengthAwarePaginator $resource)
|
||||
{
|
||||
$this->pagination = [
|
||||
'last_visible_page' => $resource->lastPage(),
|
||||
'has_next_page' => $resource->hasMorePages()
|
||||
];
|
||||
|
||||
$this->collection = $resource->getCollection();
|
||||
|
||||
parent::__construct($resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'pagination' => $this->pagination,
|
||||
'data' => $this->collection
|
||||
];
|
||||
}
|
||||
|
||||
public function withResponse($request, $response)
|
||||
{
|
||||
$jsonResponse = json_decode($response->getContent(), true);
|
||||
unset($jsonResponse['links'],$jsonResponse['meta']);
|
||||
$response->setContent(json_encode($jsonResponse));
|
||||
}
|
||||
}
|
17
app/Http/Resources/V4/InsightsResource.php
Normal file
17
app/Http/Resources/V4/InsightsResource.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\V4;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class InsightsResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'timestamp' => $this['timestamp'],
|
||||
'url' => $this['url'],
|
||||
];
|
||||
}
|
||||
}
|
55
app/Http/Resources/V4/TrendsCollection.php
Normal file
55
app/Http/Resources/V4/TrendsCollection.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace App\Http\Resources\V4;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\ResourceCollection;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
|
||||
class TrendsCollection extends ResourceCollection
|
||||
{
|
||||
|
||||
/**
|
||||
* The resource that this resource collects.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $collects = 'App\Http\Resources\V4\TrendsResource';
|
||||
|
||||
|
||||
private $pagination;
|
||||
|
||||
public function __construct(LengthAwarePaginator $resource)
|
||||
{
|
||||
$this->pagination = [
|
||||
'last_visible_page' => $resource->lastPage(),
|
||||
'has_next_page' => $resource->hasMorePages()
|
||||
];
|
||||
|
||||
$this->collection = $resource->getCollection();
|
||||
|
||||
parent::__construct($resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the resource collection into an array.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'pagination' => $this->pagination,
|
||||
'data' => $this->collection
|
||||
];
|
||||
}
|
||||
|
||||
public function withResponse($request, $response)
|
||||
{
|
||||
$jsonResponse = json_decode($response->getContent(), true);
|
||||
unset($jsonResponse['links'],$jsonResponse['meta']);
|
||||
$response->setContent(json_encode($jsonResponse));
|
||||
}
|
||||
}
|
17
app/Http/Resources/V4/TrendsResource.php
Normal file
17
app/Http/Resources/V4/TrendsResource.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Resources\V4;
|
||||
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
class TrendsResource extends JsonResource
|
||||
{
|
||||
|
||||
public function toArray($request)
|
||||
{
|
||||
return [
|
||||
'url' => $this['_id'],
|
||||
'count' => $this['count'],
|
||||
];
|
||||
}
|
||||
}
|
@ -70,6 +70,14 @@ $app->singleton(
|
||||
|
|
||||
*/
|
||||
|
||||
$globalMiddleware = [];
|
||||
|
||||
if (env('INSIGHTS', false)) {
|
||||
$globalMiddleware[] = \App\Http\Middleware\Insights::class;
|
||||
}
|
||||
|
||||
$app->middleware($globalMiddleware);
|
||||
|
||||
$app->routeMiddleware([
|
||||
// 'slave-auth' => App\Http\Middleware\SlaveAuthentication::class,
|
||||
// 'meta' => App\Http\Middleware\Meta::class,
|
||||
@ -77,7 +85,7 @@ $app->routeMiddleware([
|
||||
// 'throttle' => App\Http\Middleware\Throttle::class,
|
||||
// 'etag' => \App\Http\Middleware\EtagMiddleware::class,
|
||||
'microcaching' => \App\Http\Middleware\MicroCaching::class,
|
||||
'source-health-monitor' => SourceHeartbeatMonitor::class
|
||||
'source-health-monitor' => SourceHeartbeatMonitor::class,
|
||||
]);
|
||||
|
||||
/*
|
||||
@ -145,7 +153,7 @@ $commonMiddleware = [
|
||||
// 'cache-resolver',
|
||||
// 'throttle'
|
||||
'source-health-monitor',
|
||||
'microcaching'
|
||||
'microcaching',
|
||||
];
|
||||
|
||||
|
||||
|
@ -501,4 +501,20 @@ $router->group(
|
||||
'uses' => 'RandomController@users',
|
||||
]);
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
$router->group(
|
||||
[
|
||||
'prefix' => 'insights'
|
||||
],
|
||||
function() use ($router) {
|
||||
$router->get('/', [
|
||||
'uses' => 'InsightsController@main'
|
||||
]);
|
||||
|
||||
$router->get('/trends', [
|
||||
'uses' => 'InsightsController@trends'
|
||||
]);
|
||||
}
|
||||
);
|
Loading…
x
Reference in New Issue
Block a user