Update ApiV1Controller, use cursor pagination for favourited_by and reblogged_by endpoints

This commit is contained in:
Daniel Supernault 2023-02-08 02:07:35 -07:00
parent 620ee826d1
commit e1c7e7015e
No known key found for this signature in database
GPG key ID: 0DEF1C662C9033F7

View file

@ -2471,15 +2471,21 @@ class ApiV1Controller extends Controller
abort_if(!$request->user(), 403); abort_if(!$request->user(), 403);
$this->validate($request, [ $this->validate($request, [
'page' => 'nullable|integer|min:1|max:40',
'limit' => 'nullable|integer|min:1|max:100' 'limit' => 'nullable|integer|min:1|max:100'
]); ]);
$limit = $request->input('limit') ?? 40; $limit = $request->input('limit') ?? 10;
$user = $request->user(); $user = $request->user();
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
$author = intval($status->profile_id) === intval($user->profile_id) || $user->is_admin;
if(intval($status->profile_id) !== intval($user->profile_id)) { abort_if(
!$status->type ||
!in_array($status->type, ['photo','photo:album', 'photo:video:album', 'reply', 'text', 'video', 'video:album']),
404,
);
if(!$author) {
if($status->scope == 'private') { if($status->scope == 'private') {
abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403); abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403);
} else { } else {
@ -2487,35 +2493,41 @@ class ApiV1Controller extends Controller
} }
} }
$page = $request->input('page', 1); $res = Status::where('reblog_of_id', $status->id)
$start = $page == 1 ? 0 : (($page * $limit) - $limit); ->orderByDesc('id')
$end = $start + $limit - 1; ->cursorPaginate($limit)
->withQueryString();
$ids = ReblogService::getPostReblogs($id, $start, $end); if(!$res) {
if(empty($ids)) { return $this->json([]);
return [];
} }
$res = collect($ids) $headers = [];
->map(function($id) { if($author && $res->hasPages()) {
$status = StatusService::get($id); $links = '';
if($status) { if($res->previousPageUrl()) {
return AccountService::get($status['account']['id']); $links = '<' . $res->previousPageUrl() .'>; rel="prev"';
} }
return;
if($res->nextPageUrl()) {
if(!empty($links)) {
$links .= ', ';
}
$links .= '<' . $res->nextPageUrl() .'>; rel="next"';
}
$headers = ['Link' => $links];
}
$res = $res->map(function($status) {
return AccountService::get($status->profile_id);
}) })
->filter(function($account) { ->filter(function($account) {
return $account && isset($account['id']); return $account && isset($account['id']);
}) })
->values(); ->values();
$url = $request->url(); return $this->json($res, 200, $headers);
$page = $request->input('page', 1);
$next = $page < 40 ? $page + 1 : 40;
$prev = $page > 1 ? $page - 1 : 1;
$links = '<'.$url.'?page='.$next.'&limit='.$limit.'>; rel="next", <'.$url.'?page='.$prev.'&limit='.$limit.'>; rel="prev"';
return $this->json($res, 200, ['Link' => $links]);
} }
/** /**
@ -2530,42 +2542,59 @@ class ApiV1Controller extends Controller
abort_if(!$request->user(), 403); abort_if(!$request->user(), 403);
$this->validate($request, [ $this->validate($request, [
'page' => 'nullable|integer|min:1|max:40',
'limit' => 'nullable|integer|min:1|max:100' 'limit' => 'nullable|integer|min:1|max:100'
]); ]);
$page = $request->input('page', 1); $limit = $request->input('limit') ?? 10;
$limit = $request->input('limit') ?? 40;
$user = $request->user(); $user = $request->user();
$status = Status::findOrFail($id); $status = Status::findOrFail($id);
$offset = $page == 1 ? 0 : ($page * $limit - $limit); $author = intval($status->profile_id) === intval($user->profile_id) || $user->is_admin;
if($offset > 100) {
if($user->profile_id != $status->profile_id) {
return [];
}
}
if(intval($status->profile_id) !== intval($user->profile_id)) { abort_if(
!$status->type ||
!in_array($status->type, ['photo','photo:album', 'photo:video:album', 'reply', 'text', 'video', 'video:album']),
404,
);
if(!$author) {
if($status->scope == 'private') { if($status->scope == 'private') {
abort_if(!$status->profile->followedBy($user->profile), 403); abort_if(!FollowerService::follows($user->profile_id, $status->profile_id), 403);
} else { } else {
abort_if(!in_array($status->scope, ['public','unlisted']), 403); abort_if(!in_array($status->scope, ['public','unlisted']), 403);
} }
if($request->has('cursor')) {
return $this->json([]);
}
} }
$res = DB::table('likes') $res = Like::where('status_id', $status->id)
->select('likes.id', 'likes.profile_id', 'likes.status_id', 'followers.created_at') ->orderByDesc('id')
->leftJoin('followers', function($join) use($user, $status) { ->cursorPaginate($limit)
return $join->on('likes.profile_id', '=', 'followers.following_id') ->withQueryString();
->where('followers.profile_id', $user->profile_id)
->where('likes.status_id', $status->id); if(!$res) {
}) return $this->json([]);
->whereStatusId($status->id) }
->orderByDesc('followers.created_at')
->offset($offset) $headers = [];
->limit($limit) if($author && $res->hasPages()) {
->get() $links = '';
->map(function($like) { if($res->previousPageUrl()) {
$links = '<' . $res->previousPageUrl() .'>; rel="prev"';
}
if($res->nextPageUrl()) {
if(!empty($links)) {
$links .= ', ';
}
$links .= '<' . $res->nextPageUrl() .'>; rel="next"';
}
$headers = ['Link' => $links];
}
$res = $res->map(function($like) {
$account = AccountService::getMastodon($like->profile_id, true); $account = AccountService::getMastodon($like->profile_id, true);
$account['follows'] = isset($like->created_at); $account['follows'] = isset($like->created_at);
return $account; return $account;
@ -2575,13 +2604,7 @@ class ApiV1Controller extends Controller
}) })
->values(); ->values();
$url = $request->url(); return $this->json($res, 200, $headers);
$page = $request->input('page', 1);
$next = $page < 40 ? $page + 1 : 40;
$prev = $page > 1 ? $page - 1 : 1;
$links = '<'.$url.'?page='.$next.'&limit='.$limit.'>; rel="next", <'.$url.'?page='.$prev.'&limit='.$limit.'>; rel="prev"';
return $this->json($res, 200, ['Link' => $links]);
} }
/** /**