diff --git a/app/Http/Controllers/PublicApiController.php b/app/Http/Controllers/PublicApiController.php index e017a980..a3ce37ee 100644 --- a/app/Http/Controllers/PublicApiController.php +++ b/app/Http/Controllers/PublicApiController.php @@ -573,9 +573,13 @@ class PublicApiController extends Controller { abort_unless(Auth::check(), 403); $profile = Profile::with('user')->whereNull('status')->whereNull('domain')->findOrFail($id); + $owner = Auth::id() == $profile->user_id; if(Auth::id() != $profile->user_id && $profile->is_private || !$profile->user->settings->show_profile_followers) { return response()->json([]); } + if(!$owner && $request->page > 5) { + return []; + } $followers = $profile->followers()->orderByDesc('followers.created_at')->paginate(10); $resource = new Fractal\Resource\Collection($followers, new AccountTransformer()); $res = $this->fractal->createData($resource)->toArray(); @@ -600,6 +604,10 @@ class PublicApiController extends Controller abort_if($owner == false && $profile->is_private == true && !$profile->followedBy(Auth::user()->profile), 404); abort_if($profile->user->settings->show_profile_following == false && $owner == false, 404); + if(!$owner && $request->page > 5) { + return []; + } + if($search) { abort_if(!$owner, 404); $following = $profile->following() diff --git a/app/Services/FollowerService.php b/app/Services/FollowerService.php index 4f938c74..68ecb118 100644 --- a/app/Services/FollowerService.php +++ b/app/Services/FollowerService.php @@ -6,66 +6,95 @@ use Illuminate\Support\Facades\Redis; use App\{ Follower, - Profile + Profile, + User }; -class FollowerService { +class FollowerService +{ + const FOLLOWING_KEY = 'pf:services:follow:following:id:'; + const FOLLOWERS_KEY = 'pf:services:follow:followers:id:'; - protected $profile; - public static $follower_prefix = 'px:profile:followers-v1.3:'; - public static $following_prefix = 'px:profile:following-v1.3:'; - - public static function build() + public static function add($actor, $target) { - return new self(); + Redis::zadd(self::FOLLOWING_KEY . $actor, $target, $target); + Redis::zadd(self::FOLLOWERS_KEY . $target, $actor, $actor); } - public function profile(Profile $profile) + public static function remove($actor, $target) { - $this->profile = $profile; - self::$follower_prefix .= $profile->id; - self::$following_prefix .= $profile->id; - return $this; + Redis::zrem(self::FOLLOWING_KEY . $actor, $target); + Redis::zrem(self::FOLLOWERS_KEY . $target, $actor); } - public function followers($limit = 100, $offset = 1) + public static function followers($id, $start = 0, $stop = 10) { - if(Redis::zcard(self::$follower_prefix) == 0) { - $followers = $this->profile->followers()->pluck('profile_id'); - $followers->map(function($i) { - Redis::zadd(self::$follower_prefix, $i, $i); - }); - return Redis::zrevrange(self::$follower_prefix, $offset, $limit); - } else { - return Redis::zrevrange(self::$follower_prefix, $offset, $limit); - } + return Redis::zrange(self::FOLLOWERS_KEY . $id, $start, $stop); } - - public function following($limit = 100, $offset = 1) + public static function following($id, $start = 0, $stop = 10) { - if(Redis::zcard(self::$following_prefix) == 0) { - $following = $this->profile->following()->pluck('following_id'); - $following->map(function($i) { - Redis::zadd(self::$following_prefix, $i, $i); - }); - return Redis::zrevrange(self::$following_prefix, $offset, $limit); - } else { - return Redis::zrevrange(self::$following_prefix, $offset, $limit); - } + return Redis::zrange(self::FOLLOWING_KEY . $id, $start, $stop); } public static function follows(string $actor, string $target) { - $key = self::$follower_prefix . $target; - if(Redis::zcard($key) == 0) { - $p = Profile::findOrFail($target); - self::build()->profile($p)->followers(1); - self::build()->profile($p)->following(1); - return (bool) Redis::zrank($key, $actor); - } else { - return (bool) Redis::zrank($key, $actor); + return Follower::whereProfileId($actor)->whereFollowingId($target)->exists(); + } + + public static function audience($profile) + { + return (new self)->getAudienceInboxes($profile); + } + + protected function getAudienceInboxes($profile) + { + if($profile instanceOf User) { + return $profile + ->profile + ->followers() + ->whereLocalProfile(false) + ->get() + ->map(function($follow) { + return $follow->sharedInbox ?? $follow->inbox_url; + }) + ->unique() + ->values() + ->toArray(); } + + if($profile instanceOf Profile) { + return $profile + ->followers() + ->whereLocalProfile(false) + ->get() + ->map(function($follow) { + return $follow->sharedInbox ?? $follow->inbox_url; + }) + ->unique() + ->values() + ->toArray(); + } + + if(is_string($profile) || is_integer($profile)) { + $profile = Profile::whereNull('domain')->find($profile); + if(!$profile) { + return []; + } + + return $profile + ->followers() + ->whereLocalProfile(false) + ->get() + ->map(function($follow) { + return $follow->sharedInbox ?? $follow->inbox_url; + }) + ->unique() + ->values() + ->toArray(); + } + + return []; } } diff --git a/resources/assets/js/components/Profile.vue b/resources/assets/js/components/Profile.vue index 862cb200..6545a8ea 100644 --- a/resources/assets/js/components/Profile.vue +++ b/resources/assets/js/components/Profile.vue @@ -85,10 +85,10 @@