From 96a6c063f23ed7a7165c6c23b26ed1a1508c1b96 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 19:47:00 -0700 Subject: [PATCH 01/10] Update FollowerService --- app/Services/FollowerService.php | 45 ++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/app/Services/FollowerService.php b/app/Services/FollowerService.php index 4c0826114..3a7120ef5 100644 --- a/app/Services/FollowerService.php +++ b/app/Services/FollowerService.php @@ -12,8 +12,8 @@ use App\{ class FollowerService { protected $profile; - protected $follower_prefix; - protected $following_prefix; + static $follower_prefix = 'px:profile:followers-v1.3:'; + static $following_prefix = 'px:profile:following-v1.3:'; public static function build() { @@ -23,35 +23,48 @@ class FollowerService { public function profile(Profile $profile) { $this->profile = $profile; - $this->follower_prefix = config('cache.prefix').':profile:followers:'.$profile->id; - $this->following_prefix = config('cache.prefix').':profile:following:'.$profile->id; + self::$follower_prefix .= $profile->id; + self::$following_prefix .= $profile->id; return $this; } - public function followers($limit = 100, $offset = 0) + public function followers($limit = 100, $offset = 1) { - if(Redis::llen($this->follower_prefix) == 0) { - $followers = $this->profile->followers; + if(Redis::zcard(self::$follower_prefix) == 0) { + $followers = $this->profile->followers()->pluck('profile_id'); $followers->map(function($i) { - Redis::lpush($this->follower_prefix, $i->id); + Redis::zadd(self::$follower_prefix, $i, $i); }); - return $followers; + return Redis::zrevrange(self::$follower_prefix, $offset, $limit); } else { - return Redis::lrange($this->follower_prefix, $offset, $limit); + return Redis::zrevrange(self::$follower_prefix, $offset, $limit); } } - public function following($limit = 100, $offset = 0) + public function following($limit = 100, $offset = 1) { - if(Redis::llen($this->following_prefix) == 0) { - $following = $this->profile->following; + if(Redis::zcard(self::$following_prefix) == 0) { + $following = $this->profile->following()->pluck('following_id'); $following->map(function($i) { - Redis::lpush($this->following_prefix, $i->id); + Redis::zadd(self::$following_prefix, $i, $i); }); - return $following; + return Redis::zrevrange(self::$following_prefix, $offset, $limit); } else { - return Redis::lrange($this->following_prefix, $offset, $limit); + return Redis::zrevrange(self::$following_prefix, $offset, $limit); + } + } + + 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); } } From 293b806afcdb324882991531ce57f22015942a23 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 19:54:26 -0700 Subject: [PATCH 02/10] Update DiscoverController --- app/Http/Controllers/DiscoverController.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/DiscoverController.php b/app/Http/Controllers/DiscoverController.php index ccb042d98..92d488386 100644 --- a/app/Http/Controllers/DiscoverController.php +++ b/app/Http/Controllers/DiscoverController.php @@ -115,8 +115,8 @@ class DiscoverController extends Controller abort_if(!config('instance.discover.tags.is_public') && !$auth, 403); $this->validate($request, [ - 'hashtag' => 'required|alphanum|min:2|max:124', - 'page' => 'nullable|integer|min:1|max:' . ($auth ? 19 : 3) + 'hashtag' => 'required|alphanum|min:1|max:124', + 'page' => 'nullable|integer|min:1|max:' . ($auth ? 29 : 10) ]); $page = $request->input('page') ?? '1'; From e9c67e337d37c3f8b6d746affa952b7c5adb48b8 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 20:22:37 -0700 Subject: [PATCH 03/10] Add follow intent view --- resources/views/site/intents/follow.blade.php | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 resources/views/site/intents/follow.blade.php diff --git a/resources/views/site/intents/follow.blade.php b/resources/views/site/intents/follow.blade.php new file mode 100644 index 000000000..6b474e06e --- /dev/null +++ b/resources/views/site/intents/follow.blade.php @@ -0,0 +1,53 @@ +@extends('layouts.blank') + +@section('content') +
+
+
+

Follow {{$profile->username}} on Pixelfed

+
+
+
+
+
+
+ +
+

{{$profile->username}}

+

{{$profile->followers->count()}} followers

+
+ @if($following == true) +
+ @csrf + + + +
+ @else +
+ @csrf + + + +
+ @endif + View Profile +
+
+
+ @auth + + @endauth +
+
+
+@endsection \ No newline at end of file From ad8fc77e6c939f5d7fc6b61785f6ff2f9c7f8338 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 20:24:08 -0700 Subject: [PATCH 04/10] Update FollowerController --- app/Http/Controllers/FollowerController.php | 36 ++++++++++++--------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/FollowerController.php b/app/Http/Controllers/FollowerController.php index f19790809..f08fd689f 100644 --- a/app/Http/Controllers/FollowerController.php +++ b/app/Http/Controllers/FollowerController.php @@ -23,18 +23,20 @@ class FollowerController extends Controller public function store(Request $request) { $this->validate($request, [ - 'item' => 'required|string', + 'item' => 'required|string', + 'force' => 'nullable|boolean', ]); + $force = (bool) $request->input('force', true); $item = (int) $request->input('item'); - $this->handleFollowRequest($item); - if($request->wantsJson()) { + $url = $this->handleFollowRequest($item, $force); + if($request->wantsJson() == true) { return response()->json(200); } else { - return redirect()->back(); + return redirect($url); } } - protected function handleFollowRequest($item) + protected function handleFollowRequest($item, $force) { $user = Auth::user()->profile; @@ -87,17 +89,19 @@ class FollowerController extends Controller } FollowPipeline::dispatch($follower); } else { - $request = FollowRequest::whereFollowerId($user->id)->whereFollowingId($target->id)->exists(); - $follower = Follower::whereProfileId($user->id)->whereFollowingId($target->id)->exists(); - if($remote == true && $request && !$follower) { - $this->sendFollow($user, $target); + if($force == true) { + $request = FollowRequest::whereFollowerId($user->id)->whereFollowingId($target->id)->exists(); + $follower = Follower::whereProfileId($user->id)->whereFollowingId($target->id)->exists(); + if($remote == true && $request && !$follower) { + $this->sendFollow($user, $target); + } + if($remote == true && $follower) { + $this->sendUndoFollow($user, $target); + } + Follower::whereProfileId($user->id) + ->whereFollowingId($target->id) + ->delete(); } - if($remote == true && $follower) { - $this->sendUndoFollow($user, $target); - } - Follower::whereProfileId($user->id) - ->whereFollowingId($target->id) - ->delete(); } Cache::forget('profile:following:'.$target->id); @@ -107,6 +111,8 @@ class FollowerController extends Controller Cache::forget('api:local:exp:rec:'.$user->id); Cache::forget('user:account:id:'.$target->user_id); Cache::forget('user:account:id:'.$user->user_id); + + return $target->url(); } public function sendFollow($user, $target) From d9ff794932d46803ad221c3d0498a70270b259c8 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 20:24:27 -0700 Subject: [PATCH 05/10] Update SiteController --- app/Http/Controllers/SiteController.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index 68d92fc30..93b4b1e54 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -7,6 +7,7 @@ use App, Auth, Cache, View; use App\Util\Lexer\PrettyNumber; use App\{Follower, Page, Profile, Status, User, UserFilter}; use App\Util\Localization\Localization; +use App\Services\FollowerService; class SiteController extends Controller { @@ -98,4 +99,24 @@ class SiteController extends Controller }); return View::make('site.terms')->with(compact('page'))->render(); } + + public function redirectUrl(Request $request) + { + $this->validate($request, [ + 'url' => 'required|url' + ]); + $url = urldecode(request()->input('url')); + return view('site.redirect', compact('url')); + } + + public function followIntent(Request $request) + { + $this->validate($request, [ + 'user' => 'string|min:1|max:15|exists:users,username', + ]); + $profile = Profile::whereUsername($request->input('user'))->firstOrFail(); + $user = $request->user(); + $following = $user != null ? FollowerService::follows($user->profile_id, $profile->id) : false; + return view('site.intents.follow', compact('profile', 'user', 'following')); + } } From 19cb81cf2658609b1d51f35f5d327c78930f591d Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 20:26:11 -0700 Subject: [PATCH 06/10] Update web routes --- routes/web.php | 1 + 1 file changed, 1 insertion(+) diff --git a/routes/web.php b/routes/web.php index 2237da4ea..26b20c558 100644 --- a/routes/web.php +++ b/routes/web.php @@ -227,6 +227,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact Route::get('collections/create', 'CollectionController@create'); Route::get('me', 'ProfileController@meRedirect'); + Route::get('intent/follow', 'SiteController@followIntent'); }); Route::group(['prefix' => 'account'], function () { From 8e9b544f5084bdce36976da00bf36505faca77f9 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 20:30:04 -0700 Subject: [PATCH 07/10] Update SiteController, return 404 for users attempting to view their own Follow Intent --- app/Http/Controllers/SiteController.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index 93b4b1e54..cba27894a 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -116,6 +116,7 @@ class SiteController extends Controller ]); $profile = Profile::whereUsername($request->input('user'))->firstOrFail(); $user = $request->user(); + abort_if($profile->id == $user->profile_id, 404); $following = $user != null ? FollowerService::follows($user->profile_id, $profile->id) : false; return view('site.intents.follow', compact('profile', 'user', 'following')); } From b793f9c4bbe71dd57c14208c262dd2ea37016452 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 20:55:42 -0700 Subject: [PATCH 08/10] Update SiteController --- app/Http/Controllers/SiteController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index cba27894a..b44a6761d 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -116,7 +116,7 @@ class SiteController extends Controller ]); $profile = Profile::whereUsername($request->input('user'))->firstOrFail(); $user = $request->user(); - abort_if($profile->id == $user->profile_id, 404); + abort_if($user && $profile->id == $user->profile_id, 404); $following = $user != null ? FollowerService::follows($user->profile_id, $profile->id) : false; return view('site.intents.follow', compact('profile', 'user', 'following')); } From fb7a3cf0e4e6336fc0d51184ab74bcc4d1377aae Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 21:21:08 -0700 Subject: [PATCH 09/10] Add Profile Embeds --- app/Http/Controllers/ProfileController.php | 26 +++++ .../views/profile/embed-removed.blade.php | 46 ++++++++ resources/views/profile/embed.blade.php | 101 ++++++++++++++++++ routes/web.php | 1 + 4 files changed, 174 insertions(+) create mode 100644 resources/views/profile/embed-removed.blade.php create mode 100644 resources/views/profile/embed.blade.php diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 59fc4f451..7e66211d2 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -5,6 +5,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use Auth; use Cache; +use View; use App\Follower; use App\FollowRequest; use App\Profile; @@ -189,4 +190,29 @@ class ProfileController extends Controller abort_if(!Auth::check(), 404); return redirect(Auth::user()->url()); } + + public function embed(Request $request, $username) + { + $res = view('profile.embed-removed'); + + if(strlen($username) > 15 || strlen($username) < 2) { + return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']); + } + + $profile = Profile::whereUsername($username) + ->whereIsPrivate(false) + ->whereNull('status') + ->whereNull('domain') + ->first(); + + if(!$profile) { + return response($res)->withHeaders(['X-Frame-Options' => 'ALLOWALL']); + } + + $content = Cache::remember('profile:embed:'.$profile->id, now()->addHours(12), function() use($profile) { + return View::make('profile.embed')->with(compact('profile'))->render(); + }); + + return response($content)->withHeaders(['X-Frame-Options' => 'ALLOWALL']); + } } diff --git a/resources/views/profile/embed-removed.blade.php b/resources/views/profile/embed-removed.blade.php new file mode 100644 index 000000000..5cb28218b --- /dev/null +++ b/resources/views/profile/embed-removed.blade.php @@ -0,0 +1,46 @@ + + + + + + + + + + Pixelfed | 404 Embed Not Found + + + + + + + + + + + + +
+
+
+ +

Pixelfed

+

Cannot display profile embed, it may be deleted or set to private.

+

Visit Pixelfed

+
+
+
+ + + diff --git a/resources/views/profile/embed.blade.php b/resources/views/profile/embed.blade.php new file mode 100644 index 000000000..3d5e3de11 --- /dev/null +++ b/resources/views/profile/embed.blade.php @@ -0,0 +1,101 @@ + + + + + + + + + + {{ $title ?? config('app.name', 'Pixelfed') }} + + + + + + + + + + + + + + +
+
+ +
+
+
+

{{$profile->statuses()->count()}}

+

Posts

+
+
+

{{$profile->followers()->count()}}

+

Followers

+
+
+

{{$profile->following()->count()}}

+

Following

+
+
+

Follow

+
+
+
+ @foreach($profile->statuses()->latest()->whereScope('public')->whereIsNsfw(false)->has('media')->whereType('photo')->take(9)->get() as $post) + + @endforeach +
+
+ +
+
+ + + + + + + + diff --git a/routes/web.php b/routes/web.php index 26b20c558..a2dc0bc23 100644 --- a/routes/web.php +++ b/routes/web.php @@ -382,5 +382,6 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact Route::post('p/{username}/{id}/edit', 'StatusController@editStore'); Route::get('p/{username}/{id}.json', 'StatusController@showObject'); Route::get('p/{username}/{id}', 'StatusController@show'); + Route::get('{username}/embed', 'ProfileController@embed'); Route::get('{username}', 'ProfileController@show'); }); From b2005bd4b0bee5b2d63b52087bd8fee3f7d8a666 Mon Sep 17 00:00:00 2001 From: Daniel Supernault Date: Wed, 4 Dec 2019 21:21:43 -0700 Subject: [PATCH 10/10] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00b045b5f..dd6af630b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Added drafts API endpoint for Camera Roll ([bad2ecde](https://github.com/pixelfed/pixelfed/commit/bad2ecde)) - Added AccountService ([885a1258](https://github.com/pixelfed/pixelfed/commit/885a1258)) - Added post embeds ([1fecf717](https://github.com/pixelfed/pixelfed/commit/1fecf717)) +- Added profile embeds ([fb7a3cf0](https://github.com/pixelfed/pixelfed/commit/fb7a3cf0)) ### Fixed - Fixed like and share/reblog count on profiles ([86cb7d09](https://github.com/pixelfed/pixelfed/commit/86cb7d09)) @@ -51,6 +52,7 @@ - Updated ApiV1Controller, add ```mobile_apis``` to /api/v1/instance endpoint ([57407463](https://github.com/pixelfed/pixelfed/commit/57407463)) - Updated PublicTimelineService, add video media scopes ([7b00eba3](https://github.com/pixelfed/pixelfed/commit/7b00eba3)) - Updated PublicApiController, add AccountService ([5ebd2c8a](https://github.com/pixelfed/pixelfed/commit/5ebd2c8a)) +- Update CommentController, fix scope bug ([45ecad2a](https://github.com/pixelfed/pixelfed/45ecad2a)) ## Deprecated