mirror of
https://github.com/pixelfed/pixelfed.git
synced 2024-11-22 22:41:27 +00:00
Update FollowerController, remove deprecated /i/follow endpoint
This commit is contained in:
parent
60fbf0e7d5
commit
4739d6146f
4 changed files with 63 additions and 144 deletions
|
@ -23,109 +23,7 @@ class FollowerController extends Controller
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$this->validate($request, [
|
abort(422, 'Deprecated API Endpoint, use /api/v1/accounts/{id}/follow or /api/v1/accounts/{id}/unfollow instead.');
|
||||||
'item' => 'required|string',
|
|
||||||
'force' => 'nullable|boolean',
|
|
||||||
]);
|
|
||||||
$force = (bool) $request->input('force', true);
|
|
||||||
$item = (int) $request->input('item');
|
|
||||||
$url = $this->handleFollowRequest($item, $force);
|
|
||||||
if($request->wantsJson() == true) {
|
|
||||||
return response()->json(200);
|
|
||||||
} else {
|
|
||||||
return redirect($url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function handleFollowRequest($item, $force)
|
|
||||||
{
|
|
||||||
$user = Auth::user()->profile;
|
|
||||||
|
|
||||||
$target = Profile::where('id', '!=', $user->id)->whereNull('status')->findOrFail($item);
|
|
||||||
$private = (bool) $target->is_private;
|
|
||||||
$remote = (bool) $target->domain;
|
|
||||||
$blocked = UserFilter::whereUserId($target->id)
|
|
||||||
->whereFilterType('block')
|
|
||||||
->whereFilterableId($user->id)
|
|
||||||
->whereFilterableType('App\Profile')
|
|
||||||
->exists();
|
|
||||||
|
|
||||||
if($blocked == true) {
|
|
||||||
abort(400, 'You cannot follow this user.');
|
|
||||||
}
|
|
||||||
|
|
||||||
$isFollowing = Follower::whereProfileId($user->id)->whereFollowingId($target->id)->exists();
|
|
||||||
|
|
||||||
if($private == true && $isFollowing == 0) {
|
|
||||||
if($user->following()->count() >= Follower::MAX_FOLLOWING) {
|
|
||||||
abort(400, 'You cannot follow more than ' . Follower::MAX_FOLLOWING . ' accounts');
|
|
||||||
}
|
|
||||||
|
|
||||||
if($user->following()->where('followers.created_at', '>', now()->subHour())->count() >= Follower::FOLLOW_PER_HOUR) {
|
|
||||||
abort(400, 'You can only follow ' . Follower::FOLLOW_PER_HOUR . ' users per hour');
|
|
||||||
}
|
|
||||||
|
|
||||||
$follow = FollowRequest::firstOrCreate([
|
|
||||||
'follower_id' => $user->id,
|
|
||||||
'following_id' => $target->id
|
|
||||||
]);
|
|
||||||
if($remote == true && config('federation.activitypub.remoteFollow') == true) {
|
|
||||||
$this->sendFollow($user, $target);
|
|
||||||
}
|
|
||||||
|
|
||||||
FollowerService::add($user->id, $target->id);
|
|
||||||
} elseif ($private == false && $isFollowing == 0) {
|
|
||||||
if($user->following()->count() >= Follower::MAX_FOLLOWING) {
|
|
||||||
abort(400, 'You cannot follow more than ' . Follower::MAX_FOLLOWING . ' accounts');
|
|
||||||
}
|
|
||||||
|
|
||||||
if($user->following()->where('followers.created_at', '>', now()->subHour())->count() >= Follower::FOLLOW_PER_HOUR) {
|
|
||||||
abort(400, 'You can only follow ' . Follower::FOLLOW_PER_HOUR . ' users per hour');
|
|
||||||
}
|
|
||||||
$follower = new Follower();
|
|
||||||
$follower->profile_id = $user->id;
|
|
||||||
$follower->following_id = $target->id;
|
|
||||||
$follower->save();
|
|
||||||
|
|
||||||
if($remote == true && config('federation.activitypub.remoteFollow') == true) {
|
|
||||||
$this->sendFollow($user, $target);
|
|
||||||
}
|
|
||||||
FollowerService::add($user->id, $target->id);
|
|
||||||
FollowPipeline::dispatch($follower);
|
|
||||||
} else {
|
|
||||||
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();
|
|
||||||
FollowerService::remove($user->id, $target->id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Cache::forget('profile:following:'.$target->id);
|
|
||||||
Cache::forget('profile:followers:'.$target->id);
|
|
||||||
Cache::forget('profile:following:'.$user->id);
|
|
||||||
Cache::forget('profile:followers:'.$user->id);
|
|
||||||
Cache::forget('api:local:exp:rec:'.$user->id);
|
|
||||||
Cache::forget('user:account:id:'.$target->user_id);
|
|
||||||
Cache::forget('user:account:id:'.$user->user_id);
|
|
||||||
Cache::forget('px:profile:followers-v1.3:'.$user->id);
|
|
||||||
Cache::forget('px:profile:followers-v1.3:'.$target->id);
|
|
||||||
Cache::forget('px:profile:following-v1.3:'.$user->id);
|
|
||||||
Cache::forget('px:profile:following-v1.3:'.$target->id);
|
|
||||||
Cache::forget('profile:follower_count:'.$target->id);
|
|
||||||
Cache::forget('profile:follower_count:'.$user->id);
|
|
||||||
Cache::forget('profile:following_count:'.$target->id);
|
|
||||||
Cache::forget('profile:following_count:'.$user->id);
|
|
||||||
|
|
||||||
return $target->url();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendFollow($user, $target)
|
public function sendFollow($user, $target)
|
||||||
|
|
|
@ -122,12 +122,6 @@
|
||||||
</a>
|
</a>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
<!-- <div v-else-if="n.type == 'follow' && n.relationship.following == false">
|
|
||||||
<a href="#" class="btn btn-primary py-0 font-weight-bold" @click.prevent="followProfile(n);">
|
|
||||||
Follow
|
|
||||||
</a>
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- <div v-else-if="n.status && n.status.parent && !n.status.parent.media_attachments && n.type == 'like' && n.relationship.following == false">
|
<!-- <div v-else-if="n.status && n.status.parent && !n.status.parent.media_attachments && n.type == 'like' && n.relationship.following == false">
|
||||||
<a href="#" class="btn btn-primary py-0 font-weight-bold">
|
<a href="#" class="btn btn-primary py-0 font-weight-bold">
|
||||||
Follow
|
Follow
|
||||||
|
@ -290,24 +284,6 @@ export default {
|
||||||
return '/p/' + username + '/' + id;
|
return '/p/' + username + '/' + id;
|
||||||
},
|
},
|
||||||
|
|
||||||
followProfile(n) {
|
|
||||||
let self = this;
|
|
||||||
let id = n.account.id;
|
|
||||||
axios.post('/i/follow', {
|
|
||||||
item: id
|
|
||||||
}).then(res => {
|
|
||||||
self.notifications.map(notification => {
|
|
||||||
if(notification.account.id === id) {
|
|
||||||
notification.relationship.following = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).catch(err => {
|
|
||||||
if(err.response.data.message) {
|
|
||||||
swal('Error', err.response.data.message, 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
viewContext(n) {
|
viewContext(n) {
|
||||||
switch(n.type) {
|
switch(n.type) {
|
||||||
case 'follow':
|
case 'follow':
|
||||||
|
|
|
@ -131,14 +131,20 @@
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'unfollow':
|
case 'unfollow':
|
||||||
axios.post('/i/follow', {
|
axios.post('/api/v1/accounts/' + id + '/unfollow')
|
||||||
item: id
|
.then(res => {
|
||||||
}).then(res => {
|
|
||||||
swal(
|
swal(
|
||||||
'Unfollow Successful',
|
'Unfollow Successful',
|
||||||
'You have successfully unfollowed that user',
|
'You have successfully unfollowed that user',
|
||||||
'success'
|
'success'
|
||||||
);
|
);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
swal(
|
||||||
|
'Error',
|
||||||
|
'An error occured when attempting to unfollow this user',
|
||||||
|
'error'
|
||||||
|
);
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -11,25 +11,35 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="text-center mt-n5 mb-4">
|
<div class="text-center mt-n5 mb-4">
|
||||||
<img class="rounded-circle p-1 border mt-n4 bg-white shadow" src="{{$profile->avatarUrl()}}" width="90px" height="90px;">
|
<img
|
||||||
|
class="rounded-circle p-1 border mt-n4 bg-white shadow"
|
||||||
|
src="{{$profile->avatarUrl()}}"
|
||||||
|
width="90"
|
||||||
|
height="90"
|
||||||
|
loading="lazy"
|
||||||
|
onerror="this.src='/storage/avatars/default.jpg?v=0';this.onerror=null;">
|
||||||
</div>
|
</div>
|
||||||
<p class="text-center lead font-weight-bold mb-1">{{$profile->username}}</p>
|
<p class="text-center lead font-weight-bold mb-1">{{$profile->username}}</p>
|
||||||
<p class="text-center text-muted small text-uppercase mb-4">{{$profile->followerCount()}} followers</p>
|
<p class="text-center text-muted small text-uppercase mb-4">{{$profile->followerCount()}} followers</p>
|
||||||
<div class="d-flex justify-content-center">
|
<div class="d-flex justify-content-center">
|
||||||
@if($following == true)
|
@if($following == true)
|
||||||
<form class="d-inline-block" action="/i/follow" method="post">
|
<button
|
||||||
@csrf
|
id="unfollow"
|
||||||
<input type="hidden" name="item" value="{{(string)$profile->id}}">
|
type="button"
|
||||||
<input type="hidden" name="force" value="0">
|
class="btn btn-outline-secondary btn-sm py-1 px-4 text-uppercase font-weight-bold mr-3"
|
||||||
<button type="submit" class="btn btn-outline-secondary btn-sm py-1 px-4 text-uppercase font-weight-bold mr-3" style="font-weight: 500">Unfollow</button>
|
style="font-weight: 500"
|
||||||
</form>
|
onclick="unfollowProfile()">
|
||||||
|
Unfollow
|
||||||
|
</button>
|
||||||
@else
|
@else
|
||||||
<form class="d-inline-block" action="/i/follow" method="post">
|
<button
|
||||||
@csrf
|
id="follow"
|
||||||
<input type="hidden" name="item" value="{{(string)$profile->id}}">
|
type="button"
|
||||||
<input type="hidden" name="force" value="0">
|
class="btn btn-primary btn-sm py-1 px-4 text-uppercase font-weight-bold mr-3"
|
||||||
<button type="submit" class="btn btn-primary btn-sm py-1 px-4 text-uppercase font-weight-bold mr-3" style="font-weight: 500">Follow</button>
|
style="font-weight: 500"
|
||||||
</form>
|
onclick="followProfile()">
|
||||||
|
Follow
|
||||||
|
</button>
|
||||||
@endif
|
@endif
|
||||||
<a class="btn btn-outline-primary btn-sm py-1 px-4 text-uppercase font-weight-bold" href="{{$profile->url()}}" style="font-weight: 500">View Profile</a>
|
<a class="btn btn-outline-primary btn-sm py-1 px-4 text-uppercase font-weight-bold" href="{{$profile->url()}}" style="font-weight: 500">View Profile</a>
|
||||||
</div>
|
</div>
|
||||||
|
@ -51,3 +61,32 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script type="text/javascript">
|
||||||
|
function followProfile() {
|
||||||
|
let btn = document.querySelector('#follow');
|
||||||
|
btn.setAttribute('disabled', 'disabled');
|
||||||
|
axios.post('/api/v1/accounts/{{$profile->id}}/follow')
|
||||||
|
.then(res => {
|
||||||
|
setTimeout(() => location.reload(), 1000);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
location.href = '/login?next=' + encodeURI(location.href);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function unfollowProfile() {
|
||||||
|
let btn = document.querySelector('#unfollow');
|
||||||
|
btn.setAttribute('disabled', 'disabled');
|
||||||
|
axios.post('/api/v1/accounts/{{$profile->id}}/unfollow')
|
||||||
|
.then(res => {
|
||||||
|
setTimeout(() => location.reload(), 1000);
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
location.href = '/login?next=' + encodeURI(location.href);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
|
Loading…
Reference in a new issue