From f0e648b7b8ae933e9a37fd3e26d8f6ab72f4f812 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 27 Jan 2023 00:53:47 -0700 Subject: [PATCH 1/4] Update ApiV1Controller, fix bookmarks endpoint --- app/Http/Controllers/Api/ApiV1Controller.php | 30 +++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index 11ab3a01b..b35ce35ff 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -2935,24 +2935,20 @@ class ApiV1Controller extends Controller $dir = $min_id ? '>' : '<'; $id = $min_id ?? $max_id; - if($id) { - $bookmarks = Bookmark::whereProfileId($pid) - ->where('status_id', $dir, $id) - ->limit($limit) - ->pluck('status_id'); - } else { - $bookmarks = Bookmark::whereProfileId($pid) - ->latest() - ->limit($limit) - ->pluck('status_id'); - } + $bookmarks = Bookmark::whereProfileId($pid) + ->when($id, function($id, $query) use($dir) { + return $query->where('status_id', $dir, $id); + }) + ->limit($limit) + ->pluck('status_id') + ->map(function($id) { + return \App\Services\StatusService::getMastodon($id); + }) + ->filter() + ->values() + ->toArray(); - $res = []; - foreach($bookmarks as $id) { - $res[] = \App\Services\StatusService::getMastodon($id); - } - - return $this->json($res); + return $this->json($bookmarks); } /** From 94395be9c4f2c7b56f042a9a20a0291d32f868a8 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 27 Jan 2023 19:29:44 -0700 Subject: [PATCH 2/4] Add archive api endpoints --- .../Controllers/Api/ApiV1Dot1Controller.php | 70 +++++++++++++++++ app/Http/Resources/StatusStateless.php | 76 +++++++++++++++++++ routes/api.php | 6 ++ 3 files changed, 152 insertions(+) create mode 100644 app/Http/Resources/StatusStateless.php diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index b46fd38cd..5de1bc54f 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -14,6 +14,7 @@ use App\EmailVerification; use App\Status; use App\Report; use App\Profile; +use App\StatusArchived; use App\User; use App\Services\AccountService; use App\Services\StatusService; @@ -26,6 +27,7 @@ use Jenssegers\Agent\Agent; use Mail; use App\Mail\PasswordChange; use App\Mail\ConfirmAppEmail; +use App\Http\Resources\StatusStateless; class ApiV1Dot1Controller extends Controller { @@ -563,4 +565,72 @@ class ApiV1Dot1Controller extends Controller 'access_token' => $token->accessToken ]); } + + public function archive(Request $request, $id) + { + abort_if(!$request->user(), 403); + + $status = Status::whereNull('in_reply_to_id') + ->whereNull('reblog_of_id') + ->whereProfileId($request->user()->profile_id) + ->findOrFail($id); + + if($status->scope === 'archived') { + return [200]; + } + + $archive = new StatusArchived; + $archive->status_id = $status->id; + $archive->profile_id = $status->profile_id; + $archive->original_scope = $status->scope; + $archive->save(); + + $status->scope = 'archived'; + $status->visibility = 'draft'; + $status->save(); + StatusService::del($status->id, true); + AccountService::syncPostCount($status->profile_id); + + return [200]; + } + + + public function unarchive(Request $request, $id) + { + abort_if(!$request->user(), 403); + + $status = Status::whereNull('in_reply_to_id') + ->whereNull('reblog_of_id') + ->whereProfileId($request->user()->profile_id) + ->findOrFail($id); + + if($status->scope !== 'archived') { + return [200]; + } + + $archive = StatusArchived::whereStatusId($status->id) + ->whereProfileId($status->profile_id) + ->firstOrFail(); + + $status->scope = $archive->original_scope; + $status->visibility = $archive->original_scope; + $status->save(); + $archive->delete(); + StatusService::del($status->id, true); + AccountService::syncPostCount($status->profile_id); + + return [200]; + } + + public function archivedPosts(Request $request) + { + abort_if(!$request->user(), 403); + + $statuses = Status::whereProfileId($request->user()->profile_id) + ->whereScope('archived') + ->orderByDesc('id') + ->cursorPaginate(10); + + return StatusStateless::collection($statuses); + } } diff --git a/app/Http/Resources/StatusStateless.php b/app/Http/Resources/StatusStateless.php new file mode 100644 index 000000000..be39c1fed --- /dev/null +++ b/app/Http/Resources/StatusStateless.php @@ -0,0 +1,76 @@ +id); + $poll = $status->type === 'poll' ? PollService::get($status->id) : null; + + return [ + '_v' => 1, + 'id' => (string) $status->id, + //'gid' => $status->group_id ? (string) $status->group_id : null, + 'shortcode' => HashidService::encode($status->id), + 'uri' => $status->url(), + 'url' => $status->url(), + 'in_reply_to_id' => $status->in_reply_to_id ? (string) $status->in_reply_to_id : null, + 'in_reply_to_account_id' => $status->in_reply_to_profile_id ? (string) $status->in_reply_to_profile_id : null, + 'reblog' => null, + 'content' => $status->rendered ?? $status->caption, + 'content_text' => $status->caption, + // 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), + 'emojis' => CustomEmoji::scan($status->caption), + 'reblogs_count' => $status->reblogs_count ?? 0, + 'favourites_count' => $status->likes_count ?? 0, + 'reblogged' => null, + 'favourited' => null, + 'muted' => null, + 'sensitive' => (bool) $status->is_nsfw, + 'spoiler_text' => $status->cw_summary ?? '', + 'visibility' => $status->scope ?? $status->visibility, + 'application' => [ + 'name' => 'web', + 'website' => null + ], + 'language' => null, + 'mentions' => StatusMentionService::get($status->id), + 'pf_type' => $status->type ?? $status->setType(), + 'reply_count' => (int) $status->reply_count, + 'comments_disabled' => (bool) $status->comments_disabled, + 'thread' => false, + 'replies' => [], + 'parent' => [], + 'place' => $status->place, + 'local' => (bool) $status->local, + 'taggedPeople' => $taggedPeople, + 'liked_by' => LikeService::likedBy($status), + 'media_attachments' => MediaService::get($status->id), + 'account' => AccountService::get($status->profile_id, true), + 'tags' => StatusHashtagService::statusTags($status->id), + 'poll' => $poll + ]; + } +} diff --git a/routes/api.php b/routes/api.php index 72fbf53c1..1ae507a8c 100644 --- a/routes/api.php +++ b/routes/api.php @@ -131,6 +131,12 @@ Route::group(['prefix' => 'api'], function() use($middleware) { Route::post('lookup', 'DirectMessageController@composeLookup')->middleware($middleware); }); + Route::group(['prefix' => 'archive'], function () use($middleware) { + Route::post('add/{id}', 'Api\ApiV1Dot1Controller@archive')->middleware($middleware); + Route::post('remove/{id}', 'Api\ApiV1Dot1Controller@unarchive')->middleware($middleware); + Route::get('list', 'Api\ApiV1Dot1Controller@archivedPosts')->middleware($middleware); + }); + Route::group(['prefix' => 'stories'], function () use($middleware) { Route::get('recent', 'StoryController@recent')->middleware($middleware); }); From 9ab9ffbafecd6a38b5064795f3a26b669a90a39d Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Fri, 27 Jan 2023 20:52:12 -0700 Subject: [PATCH 3/4] Add places api endpoints --- .../Controllers/Api/ApiV1Dot1Controller.php | 32 +++++++++++++++++++ app/Http/Controllers/PlaceController.php | 4 +++ routes/api.php | 4 +++ 3 files changed, 40 insertions(+) diff --git a/app/Http/Controllers/Api/ApiV1Dot1Controller.php b/app/Http/Controllers/Api/ApiV1Dot1Controller.php index 5de1bc54f..43364312b 100644 --- a/app/Http/Controllers/Api/ApiV1Dot1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Dot1Controller.php @@ -11,6 +11,7 @@ use League\Fractal\Serializer\ArraySerializer; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use App\AccountLog; use App\EmailVerification; +use App\Place; use App\Status; use App\Report; use App\Profile; @@ -633,4 +634,35 @@ class ApiV1Dot1Controller extends Controller return StatusStateless::collection($statuses); } + + public function placesById(Request $request, $id, $slug) + { + abort_if(!$request->user(), 403); + + $place = Place::whereSlug($slug)->findOrFail($id); + + $posts = Cache::remember('pf-api:v1.1:places-by-id:' . $place->id, 3600, function() use($place) { + return Status::wherePlaceId($place->id) + ->whereNull('uri') + ->whereScope('public') + ->orderByDesc('created_at') + ->limit(60) + ->pluck('id'); + }); + + $posts = $posts->map(function($id) { + return StatusService::get($id); + }) + ->filter() + ->values(); + + return ['place' => [ + 'id' => $place->id, + 'name' => $place->name, + 'slug' => $place->slug, + 'country' => $place->country, + 'lat' => $place->lat, + 'long' => $place->long + ], 'posts' => $posts]; + } } diff --git a/app/Http/Controllers/PlaceController.php b/app/Http/Controllers/PlaceController.php index 8bbf456b0..6b7760fdc 100644 --- a/app/Http/Controllers/PlaceController.php +++ b/app/Http/Controllers/PlaceController.php @@ -17,6 +17,10 @@ class PlaceController extends Controller public function show(Request $request, $id, $slug) { + $this->validate($request, [ + 'page' => 'sometimes|max:10' + ]); + $place = Place::whereSlug($slug)->findOrFail($id); $posts = Status::wherePlaceId($place->id) ->whereNull('uri') diff --git a/routes/api.php b/routes/api.php index 1ae507a8c..652440de3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -137,6 +137,10 @@ Route::group(['prefix' => 'api'], function() use($middleware) { Route::get('list', 'Api\ApiV1Dot1Controller@archivedPosts')->middleware($middleware); }); + Route::group(['prefix' => 'places'], function () use($middleware) { + Route::get('posts/{id}/{slug}', 'Api\ApiV1Dot1Controller@placesById')->middleware($middleware); + }); + Route::group(['prefix' => 'stories'], function () use($middleware) { Route::get('recent', 'StoryController@recent')->middleware($middleware); }); From ddbabddd836a822f47c86aab453e383612c51578 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sat, 28 Jan 2023 20:53:58 -0700 Subject: [PATCH 4/4] Update StatusStateless resource --- app/Http/Resources/StatusStateless.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Resources/StatusStateless.php b/app/Http/Resources/StatusStateless.php index be39c1fed..df451cc53 100644 --- a/app/Http/Resources/StatusStateless.php +++ b/app/Http/Resources/StatusStateless.php @@ -41,7 +41,7 @@ class StatusStateless extends JsonResource 'reblog' => null, 'content' => $status->rendered ?? $status->caption, 'content_text' => $status->caption, - // 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), + 'created_at' => str_replace('+00:00', 'Z', $status->created_at->format(DATE_RFC3339_EXTENDED)), 'emojis' => CustomEmoji::scan($status->caption), 'reblogs_count' => $status->reblogs_count ?? 0, 'favourites_count' => $status->likes_count ?? 0,