diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index d142575c0..d7139ea21 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -70,6 +70,7 @@ use App\Services\{ BouncerService, CollectionService, FollowerService, + HashtagService, InstanceService, LikeService, NetworkTimelineService, @@ -3847,4 +3848,88 @@ class ApiV1Controller extends Controller } return response()->json(FollowedTagResource::collection($res)->collection); } + + /** + * POST /api/v1/tags/:id/follow + * + * + * @return object + */ + public function followHashtag(Request $request, $id) + { + abort_if(!$request->user(), 403); + + if(config('pixelfed.bouncer.cloud_ips.ban_api')) { + abort_if(BouncerService::checkIp($request->ip()), 404); + } + $pid = $request->user()->profile_id; + $account = AccountService::get($pid); + + $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; + $tag = Hashtag::where('name', $operator, $id) + ->orWhere('slug', $operator, $id) + ->first(); + + abort_if(!$tag, 422, 'Unknown hashtag'); + + $follows = HashtagFollow::updateOrCreate( + [ + 'profile_id' => $account['id'], + 'hashtag_id' => $tag->id + ], + [ + 'user_id' => $request->user()->id + ] + ); + + HashtagService::follow($pid, $tag->id); + + return response()->json(FollowedTagResource::make($follows)->toArray($request)); + } + + /** + * POST /api/v1/tags/:id/unfollow + * + * + * @return object + */ + public function unfollowHashtag(Request $request, $id) + { + abort_if(!$request->user(), 403); + + if(config('pixelfed.bouncer.cloud_ips.ban_api')) { + abort_if(BouncerService::checkIp($request->ip()), 404); + } + $pid = $request->user()->profile_id; + $account = AccountService::get($pid); + + $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; + $tag = Hashtag::where('name', $operator, $id) + ->orWhere('slug', $operator, $id) + ->first(); + + abort_if(!$tag, 422, 'Unknown hashtag'); + + $follows = HashtagFollow::whereProfileId($pid) + ->whereHashtagId($tag->id) + ->first(); + + if(!$follows) { + return [ + 'name' => $tag->name, + 'url' => config('app.url') . '/i/web/hashtag/' . $tag->slug, + 'history' => [], + 'following' => false + ]; + } + + if($follows) { + HashtagService::unfollow($pid, $tag->id); + $follows->delete(); + } + + $res = FollowedTagResource::make($follows)->toArray($request); + $res['following'] = false; + return response()->json($res); + } } diff --git a/app/Services/HashtagService.php b/app/Services/HashtagService.php index de58fae59..9c455deb0 100644 --- a/app/Services/HashtagService.php +++ b/app/Services/HashtagService.php @@ -64,4 +64,9 @@ class HashtagService { { return Redis::zrem(self::FOLLOW_KEY . $pid, $hid); } + + public static function following($pid, $start = 0, $limit = 10) + { + return Redis::zrevrange(self::FOLLOW_KEY . $pid, $start, $limit); + } } diff --git a/routes/web.php b/routes/web.php index 6f5d1fc33..73bc7c24c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -407,6 +407,7 @@ Route::domain(config('pixelfed.domain.app'))->middleware(['validemail', 'twofact Route::get('web/username/{id}', 'SpaController@usernameRedirect'); Route::get('web/post/{id}', 'SpaController@webPost'); Route::get('web/profile/{id}', 'SpaController@webProfile'); + Route::get('web/{q}', 'SpaController@index')->where('q', '.*'); Route::get('web', 'SpaController@index'); });