From a8ec8445a5639eb99d87d0c7ba6020137dd04e83 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 5 Mar 2023 08:18:22 -0700 Subject: [PATCH 1/2] Update ApiV1Controller, fix home timeline bug --- app/Http/Controllers/Api/ApiV1Controller.php | 130 +++++-------------- app/Http/Controllers/PublicApiController.php | 106 ++------------- 2 files changed, 43 insertions(+), 193 deletions(-) diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index fbf6c4765..91d778995 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -2073,10 +2073,10 @@ class ApiV1Controller extends Controller public function timelineHome(Request $request) { $this->validate($request,[ - 'page' => 'nullable|integer|max:40', - 'min_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX, - 'max_id' => 'nullable|integer|min:0|max:' . PHP_INT_MAX, - 'limit' => 'nullable|integer|max:100' + 'page' => 'sometimes|integer|max:40', + 'min_id' => 'sometimes|integer|min:0|max:' . PHP_INT_MAX, + 'max_id' => 'sometimes|integer|min:0|max:' . PHP_INT_MAX, + 'limit' => 'sometimes|integer|min:1|max:80' ]); $napi = $request->has(self::PF_API_ENTITY_KEY); @@ -2091,84 +2091,6 @@ class ApiV1Controller extends Controller return $following->push($pid)->toArray(); }); - $includeReplies = false; - if(config('exp.top')) { - $includeReplies = (bool) Redis::zscore('pf:tl:replies', $pid); - } - - if(config('instance.timeline.home.cached') && (!$min && !$max)) { - $ttl = config('instance.timeline.home.cache_ttl'); - $res = Cache::remember( - 'pf:timelines:home:' . $pid, - $ttl, - function() use( - $following, - $limit, - $pid, - $includeReplies - ) { - return Status::select( - 'id', - 'uri', - 'caption', - 'rendered', - 'profile_id', - 'type', - 'in_reply_to_id', - 'reblog_of_id', - 'is_nsfw', - 'scope', - 'local', - 'reply_count', - 'comments_disabled', - 'place_id', - 'likes_count', - 'reblogs_count', - 'created_at', - 'updated_at' - ) - ->when(!$includeReplies, function($q, $includeReplies) { - return $q->whereNull('in_reply_to_id'); - }) - ->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album']) - ->whereIn('profile_id', $following) - ->whereIn('visibility',['public', 'unlisted', 'private']) - ->orderBy('created_at', 'desc') - ->limit($limit) - ->get() - ->map(function($s) { - $status = StatusService::get($s->id, false); - if(!$status) { - return false; - } - return $status; - }) - ->filter(function($s) { - return $s && isset($s['account']['id']); - }) - ->values() - ->toArray(); - }); - - $res = collect($res) - ->map(function($s) use ($pid) { - $status = StatusService::get($s['id'], false); - if(!$status) { - return false; - } - $status['favourited'] = (bool) LikeService::liked($pid, $s['id']); - $status['bookmarked'] = (bool) BookmarkService::get($pid, $s['id']); - $status['reblogged'] = (bool) ReblogService::get($pid, $s['id']); - return $status; - }) - ->filter(function($s) { - return $s && isset($s['account']['id']); - }) - ->values() - ->take($limit) - ->toArray(); - } - if($min || $max) { $dir = $min ? '>' : '<'; $id = $min ?? $max; @@ -2177,21 +2099,24 @@ class ApiV1Controller extends Controller 'profile_id', 'type', 'visibility', - 'created_at' + 'in_reply_to_id', + 'reblog_of_id' ) - ->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album']) ->where('id', $dir, $id) - ->when(!$includeReplies, function($q, $includeReplies) { - return $q->whereNull('in_reply_to_id'); - }) - ->whereIn('profile_id', $following) + ->whereNull(['in_reply_to_id', 'reblog_of_id']) + ->whereIntegerInRaw('profile_id', $following) + ->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album']) ->whereIn('visibility',['public', 'unlisted', 'private']) - ->latest() + ->orderByDesc('id') ->take(($limit * 2)) ->get() ->map(function($s) use($pid, $napi) { - $status = $napi ? StatusService::get($s['id'], false) : StatusService::getMastodon($s['id'], false); - if(!$status || !isset($status['account']) || !isset($status['account']['id'])) { + try { + $status = $napi ? StatusService::get($s['id'], false) : StatusService::getMastodon($s['id'], false); + if(!$status || !isset($status['account']) || !isset($status['account']['id'])) { + return false; + } + } catch(\Exception $e) { return false; } @@ -2212,20 +2137,27 @@ class ApiV1Controller extends Controller 'profile_id', 'type', 'visibility', - 'created_at' + 'in_reply_to_id', + 'reblog_of_id', ) - ->when(!$includeReplies, function($q, $includeReplies) { - return $q->whereNull('in_reply_to_id'); - }) + ->whereNull(['in_reply_to_id', 'reblog_of_id']) + ->whereIntegerInRaw('profile_id', $following) ->whereIn('type', ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album']) - ->whereIn('profile_id', $following) ->whereIn('visibility',['public', 'unlisted', 'private']) - ->latest() + ->orderByDesc('id') ->take(($limit * 2)) ->get() ->map(function($s) use($pid, $napi) { - $status = $napi ? StatusService::get($s['id'], false) : StatusService::getMastodon($s['id'], false); - if(!$status || !isset($status['account']) || !isset($status['account']['id'])) { + try { + $account = AccountService::get($s['profile_id'], true); + if(!$account) { + return false; + } + $status = $napi ? StatusService::get($s['id'], false) : StatusService::getMastodon($s['id'], false); + if(!$status || !isset($status['account']) || !isset($status['account']['id'])) { + return false; + } + } catch(\Exception $e) { return false; } diff --git a/app/Http/Controllers/PublicApiController.php b/app/Http/Controllers/PublicApiController.php index ff7edd5ae..f888eb512 100644 --- a/app/Http/Controllers/PublicApiController.php +++ b/app/Http/Controllers/PublicApiController.php @@ -408,96 +408,6 @@ class PublicApiController extends Controller $textOnlyReplies = false; - if(config('exp.top')) { - $textOnlyReplies = (bool) Redis::zscore('pf:tl:replies', $pid); - $textOnlyPosts = (bool) Redis::zscore('pf:tl:top', $pid); - - if($textOnlyPosts) { - array_push($types, 'text'); - } - } - - if(config('exp.polls') == true) { - array_push($types, 'poll'); - } - - if(config('instance.timeline.home.cached') && $limit == 6 && (!$min && !$max)) { - $ttl = config('instance.timeline.home.cache_ttl'); - $res = Cache::remember( - 'pf:timelines:home:' . $pid, - $ttl, - function() use( - $types, - $textOnlyReplies, - $following, - $limit, - $filtered, - $user - ) { - return Status::select( - 'id', - 'uri', - 'caption', - 'rendered', - 'profile_id', - 'type', - 'in_reply_to_id', - 'reblog_of_id', - 'is_nsfw', - 'scope', - 'local', - 'reply_count', - 'comments_disabled', - 'place_id', - 'likes_count', - 'reblogs_count', - 'created_at', - 'updated_at' - ) - ->whereIn('type', $types) - ->when(!$textOnlyReplies, function($q, $textOnlyReplies) { - return $q->whereNull('in_reply_to_id'); - }) - ->whereIn('profile_id', $following) - ->whereIn('visibility',['public', 'unlisted', 'private']) - ->orderBy('created_at', 'desc') - ->limit($limit) - ->get() - ->map(function($s) use ($user) { - $status = StatusService::get($s->id, false); - if(!$status) { - return false; - } - return $status; - }) - ->filter(function($s) use($filtered) { - return $s && in_array($s['account']['id'], $filtered) == false; - }) - ->values() - ->toArray(); - }); - - $res = collect($res) - ->map(function($s) use ($user) { - $status = StatusService::get($s['id'], false); - if(!$status) { - return false; - } - $status['favourited'] = (bool) LikeService::liked($user->profile_id, $s['id']); - $status['bookmarked'] = (bool) BookmarkService::get($user->profile_id, $s['id']); - $status['reblogged'] = (bool) ReblogService::get($user->profile_id, $s['id']); - return $status; - }) - ->filter(function($s) use($filtered) { - return $s && in_array($s['account']['id'], $filtered) == false; - }) - ->values() - ->take($limit) - ->toArray(); - - return $res; - } - if($min || $max) { $dir = $min ? '>' : '<'; $id = $min ?? $max; @@ -532,10 +442,14 @@ class PublicApiController extends Controller ->limit($limit) ->get() ->map(function($s) use ($user) { + try { $status = StatusService::get($s->id, false); if(!$status) { return false; } + } catch(\Exception $e) { + return false; + } $status['favourited'] = (bool) LikeService::liked($user->profile_id, $s->id); $status['bookmarked'] = (bool) BookmarkService::get($user->profile_id, $s->id); $status['reblogged'] = (bool) ReblogService::get($user->profile_id, $s->id); @@ -577,10 +491,14 @@ class PublicApiController extends Controller ->limit($limit) ->get() ->map(function($s) use ($user) { - $status = StatusService::get($s->id, false); - if(!$status) { - return false; - } + try { + $status = StatusService::get($s->id, false); + if(!$status) { + return false; + } + } catch(\Exception $e) { + return false; + } $status['favourited'] = (bool) LikeService::liked($user->profile_id, $s->id); $status['bookmarked'] = (bool) BookmarkService::get($user->profile_id, $s->id); $status['reblogged'] = (bool) ReblogService::get($user->profile_id, $s->id); From b259193a04b55c799018ba0a85ccfd42f45435c2 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Sun, 5 Mar 2023 08:18:46 -0700 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d8346925..0ec1ac4fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -125,6 +125,7 @@ - Update ApiV1Controller, fix following/follower entities, use masto schema by default and update components accordingly ([4716c280](https://github.com/pixelfed/pixelfed/commit/4716c280)) - Update FollowerController, remove deprecated /i/follow endpoint ([4739d614](https://github.com/pixelfed/pixelfed/commit/4739d614)) - Update queue config, set "after_commit" to true ([304ea956](https://github.com/pixelfed/pixelfed/commit/304ea956)) +- Update ApiV1Controller, fix home timeline bug ([a8ec8445](https://github.com/pixelfed/pixelfed/commit/a8ec8445)) - ([](https://github.com/pixelfed/pixelfed/commit/)) ## [v0.11.4 (2022-10-04)](https://github.com/pixelfed/pixelfed/compare/v0.11.3...v0.11.4)