diff --git a/app/Http/Controllers/FederationController.php b/app/Http/Controllers/FederationController.php
index 55c7b4393..54ad03227 100644
--- a/app/Http/Controllers/FederationController.php
+++ b/app/Http/Controllers/FederationController.php
@@ -2,57 +2,42 @@
namespace App\Http\Controllers;
-use App\Jobs\InboxPipeline\{
- DeleteWorker,
- InboxWorker,
- InboxValidator
-};
-use App\Jobs\RemoteFollowPipeline\RemoteFollowPipeline;
-use App\{
- AccountLog,
- Like,
- Profile,
- Status,
- User
-};
-use App\Util\Lexer\Nickname;
-use App\Util\Webfinger\Webfinger;
-use Auth;
-use Cache;
-use Carbon\Carbon;
-use Illuminate\Http\Request;
-use League\Fractal;
-use App\Util\Site\Nodeinfo;
-use App\Util\ActivityPub\{
- Helpers,
- HttpSignature,
- Outbox
-};
-use Zttp\Zttp;
-use App\Services\InstanceService;
+use App\Jobs\InboxPipeline\DeleteWorker;
+use App\Jobs\InboxPipeline\InboxValidator;
+use App\Jobs\InboxPipeline\InboxWorker;
+use App\Profile;
use App\Services\AccountService;
+use App\Services\InstanceService;
+use App\Status;
+use App\Util\Lexer\Nickname;
+use App\Util\Site\Nodeinfo;
+use App\Util\Webfinger\Webfinger;
+use Cache;
+use Illuminate\Http\Request;
class FederationController extends Controller
{
public function nodeinfoWellKnown()
{
- abort_if(!config('federation.nodeinfo.enabled'), 404);
+ abort_if(! config('federation.nodeinfo.enabled'), 404);
+
return response()->json(Nodeinfo::wellKnown(), 200, [], JSON_UNESCAPED_SLASHES)
- ->header('Access-Control-Allow-Origin','*');
+ ->header('Access-Control-Allow-Origin', '*');
}
public function nodeinfo()
{
- abort_if(!config('federation.nodeinfo.enabled'), 404);
+ abort_if(! config('federation.nodeinfo.enabled'), 404);
+
return response()->json(Nodeinfo::get(), 200, [], JSON_UNESCAPED_SLASHES)
- ->header('Access-Control-Allow-Origin','*');
+ ->header('Access-Control-Allow-Origin', '*');
}
public function webfinger(Request $request)
{
- if (!config('federation.webfinger.enabled') ||
- !$request->has('resource') ||
- !$request->filled('resource')
+ if (! config('federation.webfinger.enabled') ||
+ ! $request->has('resource') ||
+ ! $request->filled('resource')
) {
return response('', 400);
}
@@ -60,55 +45,56 @@ class FederationController extends Controller
$resource = $request->input('resource');
$domain = config('pixelfed.domain.app');
- if(config('federation.activitypub.sharedInbox') &&
- $resource == 'acct:' . $domain . '@' . $domain) {
+ if (config('federation.activitypub.sharedInbox') &&
+ $resource == 'acct:'.$domain.'@'.$domain) {
$res = [
- 'subject' => 'acct:' . $domain . '@' . $domain,
+ 'subject' => 'acct:'.$domain.'@'.$domain,
'aliases' => [
- 'https://' . $domain . '/i/actor'
+ 'https://'.$domain.'/i/actor',
],
'links' => [
[
'rel' => 'http://webfinger.net/rel/profile-page',
'type' => 'text/html',
- 'href' => 'https://' . $domain . '/site/kb/instance-actor'
+ 'href' => 'https://'.$domain.'/site/kb/instance-actor',
],
[
'rel' => 'self',
'type' => 'application/activity+json',
- 'href' => 'https://' . $domain . '/i/actor'
- ]
- ]
+ 'href' => 'https://'.$domain.'/i/actor',
+ ],
+ ],
];
+
return response()->json($res, 200, [], JSON_UNESCAPED_SLASHES);
}
$hash = hash('sha256', $resource);
- $key = 'federation:webfinger:sha256:' . $hash;
- if($cached = Cache::get($key)) {
+ $key = 'federation:webfinger:sha256:'.$hash;
+ if ($cached = Cache::get($key)) {
return response()->json($cached, 200, [], JSON_UNESCAPED_SLASHES);
}
- if(strpos($resource, $domain) == false) {
+ if (strpos($resource, $domain) == false) {
return response('', 400);
}
$parsed = Nickname::normalizeProfileUrl($resource);
- if(empty($parsed) || $parsed['domain'] !== $domain) {
+ if (empty($parsed) || $parsed['domain'] !== $domain) {
return response('', 400);
}
$username = $parsed['username'];
$profile = Profile::whereNull('domain')->whereUsername($username)->first();
- if(!$profile || $profile->status !== null) {
+ if (! $profile || $profile->status !== null) {
return response('', 400);
}
$webfinger = (new Webfinger($profile))->generate();
Cache::put($key, $webfinger, 1209600);
return response()->json($webfinger, 200, [], JSON_UNESCAPED_SLASHES)
- ->header('Access-Control-Allow-Origin','*');
+ ->header('Access-Control-Allow-Origin', '*');
}
public function hostMeta(Request $request)
{
- abort_if(!config('federation.webfinger.enabled'), 404);
+ abort_if(! config('federation.webfinger.enabled'), 404);
$path = route('well-known.webfinger');
$xml = '';
@@ -118,19 +104,19 @@ class FederationController extends Controller
public function userOutbox(Request $request, $username)
{
- abort_if(!config_cache('federation.activitypub.enabled'), 404);
+ abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
- if(!$request->wantsJson()) {
- return redirect('/' . $username);
+ if (! $request->wantsJson()) {
+ return redirect('/'.$username);
}
$id = AccountService::usernameToId($username);
- abort_if(!$id, 404);
+ abort_if(! $id, 404);
$account = AccountService::get($id);
- abort_if(!$account || !isset($account['statuses_count']), 404);
+ abort_if(! $account || ! isset($account['statuses_count']), 404);
$res = [
'@context' => 'https://www.w3.org/ns/activitystreams',
- 'id' => 'https://' . config('pixelfed.domain.app') . '/users/' . $username . '/outbox',
+ 'id' => 'https://'.config('pixelfed.domain.app').'/users/'.$username.'/outbox',
'type' => 'OrderedCollection',
'totalItems' => $account['statuses_count'] ?? 0,
];
@@ -140,135 +126,145 @@ class FederationController extends Controller
public function userInbox(Request $request, $username)
{
- abort_if(!config_cache('federation.activitypub.enabled'), 404);
- abort_if(!config('federation.activitypub.inbox'), 404);
+ abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
+ abort_if(! config('federation.activitypub.inbox'), 404);
$headers = $request->headers->all();
$payload = $request->getContent();
- if(!$payload || empty($payload)) {
+ if (! $payload || empty($payload)) {
return;
}
$obj = json_decode($payload, true, 8);
- if(!isset($obj['id'])) {
+ if (! isset($obj['id'])) {
return;
}
$domain = parse_url($obj['id'], PHP_URL_HOST);
- if(in_array($domain, InstanceService::getBannedDomains())) {
+ if (in_array($domain, InstanceService::getBannedDomains())) {
return;
}
- if(isset($obj['type']) && $obj['type'] === 'Delete') {
- if(isset($obj['object']) && isset($obj['object']['type']) && isset($obj['object']['id'])) {
- if($obj['object']['type'] === 'Person') {
- if(Profile::whereRemoteUrl($obj['object']['id'])->exists()) {
+ if (isset($obj['type']) && $obj['type'] === 'Delete') {
+ if (isset($obj['object']) && isset($obj['object']['type']) && isset($obj['object']['id'])) {
+ if ($obj['object']['type'] === 'Person') {
+ if (Profile::whereRemoteUrl($obj['object']['id'])->exists()) {
dispatch(new DeleteWorker($headers, $payload))->onQueue('inbox');
+
return;
}
}
- if($obj['object']['type'] === 'Tombstone') {
- if(Status::whereObjectUrl($obj['object']['id'])->exists()) {
+ if ($obj['object']['type'] === 'Tombstone') {
+ if (Status::whereObjectUrl($obj['object']['id'])->exists()) {
dispatch(new DeleteWorker($headers, $payload))->onQueue('delete');
+
return;
}
}
- if($obj['object']['type'] === 'Story') {
+ if ($obj['object']['type'] === 'Story') {
dispatch(new DeleteWorker($headers, $payload))->onQueue('story');
+
return;
}
}
+
return;
- } else if( isset($obj['type']) && in_array($obj['type'], ['Follow', 'Accept'])) {
+ } elseif (isset($obj['type']) && in_array($obj['type'], ['Follow', 'Accept'])) {
dispatch(new InboxValidator($username, $headers, $payload))->onQueue('follow');
} else {
dispatch(new InboxValidator($username, $headers, $payload))->onQueue('high');
}
- return;
+
}
public function sharedInbox(Request $request)
{
- abort_if(!config_cache('federation.activitypub.enabled'), 404);
- abort_if(!config('federation.activitypub.sharedInbox'), 404);
+ abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
+ abort_if(! config('federation.activitypub.sharedInbox'), 404);
$headers = $request->headers->all();
$payload = $request->getContent();
- if(!$payload || empty($payload)) {
+ if (! $payload || empty($payload)) {
return;
}
$obj = json_decode($payload, true, 8);
- if(!isset($obj['id'])) {
+ if (! isset($obj['id'])) {
return;
}
$domain = parse_url($obj['id'], PHP_URL_HOST);
- if(in_array($domain, InstanceService::getBannedDomains())) {
+ if (in_array($domain, InstanceService::getBannedDomains())) {
return;
}
- if(isset($obj['type']) && $obj['type'] === 'Delete') {
- if(isset($obj['object']) && isset($obj['object']['type']) && isset($obj['object']['id'])) {
- if($obj['object']['type'] === 'Person') {
- if(Profile::whereRemoteUrl($obj['object']['id'])->exists()) {
+ if (isset($obj['type']) && $obj['type'] === 'Delete') {
+ if (isset($obj['object']) && isset($obj['object']['type']) && isset($obj['object']['id'])) {
+ if ($obj['object']['type'] === 'Person') {
+ if (Profile::whereRemoteUrl($obj['object']['id'])->exists()) {
dispatch(new DeleteWorker($headers, $payload))->onQueue('inbox');
+
return;
}
}
- if($obj['object']['type'] === 'Tombstone') {
- if(Status::whereObjectUrl($obj['object']['id'])->exists()) {
+ if ($obj['object']['type'] === 'Tombstone') {
+ if (Status::whereObjectUrl($obj['object']['id'])->exists()) {
dispatch(new DeleteWorker($headers, $payload))->onQueue('delete');
+
return;
}
}
- if($obj['object']['type'] === 'Story') {
+ if ($obj['object']['type'] === 'Story') {
dispatch(new DeleteWorker($headers, $payload))->onQueue('story');
+
return;
}
}
+
return;
- } else if( isset($obj['type']) && in_array($obj['type'], ['Follow', 'Accept'])) {
+ } elseif (isset($obj['type']) && in_array($obj['type'], ['Follow', 'Accept'])) {
dispatch(new InboxWorker($headers, $payload))->onQueue('follow');
} else {
dispatch(new InboxWorker($headers, $payload))->onQueue('shared');
}
- return;
+
}
public function userFollowing(Request $request, $username)
{
- abort_if(!config_cache('federation.activitypub.enabled'), 404);
+ abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
$id = AccountService::usernameToId($username);
- abort_if(!$id, 404);
+ abort_if(! $id, 404);
$account = AccountService::get($id);
- abort_if(!$account || !isset($account['following_count']), 404);
+ abort_if(! $account || ! isset($account['following_count']), 404);
$obj = [
'@context' => 'https://www.w3.org/ns/activitystreams',
- 'id' => $request->getUri(),
- 'type' => 'OrderedCollection',
+ 'id' => $request->getUri(),
+ 'type' => 'OrderedCollection',
'totalItems' => $account['following_count'] ?? 0,
];
+
return response()->json($obj)->header('Content-Type', 'application/activity+json');
}
public function userFollowers(Request $request, $username)
{
- abort_if(!config_cache('federation.activitypub.enabled'), 404);
+ abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
$id = AccountService::usernameToId($username);
- abort_if(!$id, 404);
+ abort_if(! $id, 404);
$account = AccountService::get($id);
- abort_if(!$account || !isset($account['followers_count']), 404);
+ abort_if(! $account || ! isset($account['followers_count']), 404);
$obj = [
'@context' => 'https://www.w3.org/ns/activitystreams',
- 'id' => $request->getUri(),
- 'type' => 'OrderedCollection',
+ 'id' => $request->getUri(),
+ 'type' => 'OrderedCollection',
'totalItems' => $account['followers_count'] ?? 0,
];
+
return response()->json($obj)->header('Content-Type', 'application/activity+json');
}
}
diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php
index cbf21518b..9388d3abd 100644
--- a/app/Http/Controllers/SearchController.php
+++ b/app/Http/Controllers/SearchController.php
@@ -2,368 +2,367 @@
namespace App\Http\Controllers;
-use Auth;
use App\Hashtag;
use App\Place;
use App\Profile;
+use App\Services\WebfingerService;
use App\Status;
-use Illuminate\Http\Request;
use App\Util\ActivityPub\Helpers;
+use Auth;
+use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Str;
-use App\Transformer\Api\{
- AccountTransformer,
- HashtagTransformer,
- StatusTransformer,
-};
-use App\Services\WebfingerService;
class SearchController extends Controller
{
- public $tokens = [];
- public $term = '';
- public $hash = '';
- public $cacheKey = 'api:search:tag:';
+ public $tokens = [];
- public function __construct()
- {
- $this->middleware('auth');
- }
+ public $term = '';
- public function searchAPI(Request $request)
- {
- $this->validate($request, [
- 'q' => 'required|string|min:3|max:120',
- 'src' => 'required|string|in:metro',
- 'v' => 'required|integer|in:2',
- 'scope' => 'required|in:all,hashtag,profile,remote,webfinger'
- ]);
+ public $hash = '';
- $scope = $request->input('scope') ?? 'all';
- $this->term = e(urldecode($request->input('q')));
- $this->hash = hash('sha256', $this->term);
+ public $cacheKey = 'api:search:tag:';
- switch ($scope) {
- case 'all':
- $this->getHashtags();
- $this->getPosts();
- $this->getProfiles();
- // $this->getPlaces();
- break;
+ public function __construct()
+ {
+ $this->middleware('auth');
+ }
- case 'hashtag':
- $this->getHashtags();
- break;
+ public function searchAPI(Request $request)
+ {
+ $this->validate($request, [
+ 'q' => 'required|string|min:3|max:120',
+ 'src' => 'required|string|in:metro',
+ 'v' => 'required|integer|in:2',
+ 'scope' => 'required|in:all,hashtag,profile,remote,webfinger',
+ ]);
- case 'profile':
- $this->getProfiles();
- break;
+ $scope = $request->input('scope') ?? 'all';
+ $this->term = e(urldecode($request->input('q')));
+ $this->hash = hash('sha256', $this->term);
- case 'webfinger':
- $this->webfingerSearch();
- break;
+ switch ($scope) {
+ case 'all':
+ $this->getHashtags();
+ $this->getPosts();
+ $this->getProfiles();
+ // $this->getPlaces();
+ break;
- case 'remote':
- $this->remoteLookupSearch();
- break;
+ case 'hashtag':
+ $this->getHashtags();
+ break;
- case 'place':
- $this->getPlaces();
- break;
+ case 'profile':
+ $this->getProfiles();
+ break;
- default:
- break;
- }
+ case 'webfinger':
+ $this->webfingerSearch();
+ break;
- return response()->json($this->tokens, 200, [], JSON_PRETTY_PRINT);
- }
+ case 'remote':
+ $this->remoteLookupSearch();
+ break;
- protected function getPosts()
- {
- $tag = $this->term;
- $hash = hash('sha256', $tag);
- if( Helpers::validateUrl($tag) != false &&
- Helpers::validateLocalUrl($tag) != true &&
- config_cache('federation.activitypub.enabled') == true &&
- config('federation.activitypub.remoteFollow') == true
- ) {
- $remote = Helpers::fetchFromUrl($tag);
- if( isset($remote['type']) &&
- $remote['type'] == 'Note') {
- $item = Helpers::statusFetch($tag);
- $this->tokens['posts'] = [[
- 'count' => 0,
- 'url' => $item->url(),
- 'type' => 'status',
- 'value' => "by {$item->profile->username} {$item->created_at->diffForHumans(null, true, true)}",
- 'tokens' => [$item->caption],
- 'name' => $item->caption,
- 'thumb' => $item->thumb(),
- ]];
- }
- } else {
- $posts = Status::select('id', 'profile_id', 'caption', 'created_at')
- ->whereHas('media')
- ->whereNull('in_reply_to_id')
- ->whereNull('reblog_of_id')
- ->whereProfileId(Auth::user()->profile_id)
- ->where('caption', 'like', '%'.$tag.'%')
- ->latest()
- ->limit(10)
- ->get();
+ case 'place':
+ $this->getPlaces();
+ break;
- if($posts->count() > 0) {
- $posts = $posts->map(function($item, $key) {
- return [
- 'count' => 0,
- 'url' => $item->url(),
- 'type' => 'status',
- 'value' => "by {$item->profile->username} {$item->created_at->diffForHumans(null, true, true)}",
- 'tokens' => [$item->caption],
- 'name' => $item->caption,
- 'thumb' => $item->thumb(),
- 'filter' => $item->firstMedia()->filter_class
- ];
- });
- $this->tokens['posts'] = $posts;
- }
- }
- }
+ default:
+ break;
+ }
- protected function getHashtags()
- {
- $tag = $this->term;
- $key = $this->cacheKey . 'hashtags:' . $this->hash;
- $ttl = now()->addMinutes(1);
- $tokens = Cache::remember($key, $ttl, function() use($tag) {
- $htag = Str::startsWith($tag, '#') == true ? mb_substr($tag, 1) : $tag;
- $hashtags = Hashtag::select('id', 'name', 'slug')
- ->where('slug', 'like', '%'.$htag.'%')
- ->whereHas('posts')
- ->limit(20)
- ->get();
- if($hashtags->count() > 0) {
- $tags = $hashtags->map(function ($item, $key) {
- return [
- 'count' => $item->posts()->count(),
- 'url' => $item->url(),
- 'type' => 'hashtag',
- 'value' => $item->name,
- 'tokens' => '',
- 'name' => null,
- ];
- });
- return $tags;
- }
- });
- $this->tokens['hashtags'] = $tokens;
- }
+ return response()->json($this->tokens, 200, [], JSON_PRETTY_PRINT);
+ }
- protected function getPlaces()
- {
- $tag = $this->term;
- // $key = $this->cacheKey . 'places:' . $this->hash;
- // $ttl = now()->addHours(12);
- // $tokens = Cache::remember($key, $ttl, function() use($tag) {
- $htag = Str::contains($tag, ',') == true ? explode(',', $tag) : [$tag];
- $hashtags = Place::select('id', 'name', 'slug', 'country')
- ->where('name', 'like', '%'.$htag[0].'%')
- ->paginate(20);
- $tags = [];
- if($hashtags->count() > 0) {
- $tags = $hashtags->map(function ($item, $key) {
- return [
- 'count' => null,
- 'url' => $item->url(),
- 'type' => 'place',
- 'value' => $item->name . ', ' . $item->country,
- 'tokens' => '',
- 'name' => null,
- 'city' => $item->name,
- 'country' => $item->country
- ];
- });
- // return $tags;
- }
- // });
- $this->tokens['places'] = $tags;
- $this->tokens['placesPagination'] = [
- 'total' => $hashtags->total(),
- 'current_page' => $hashtags->currentPage(),
- 'last_page' => $hashtags->lastPage()
- ];
- }
+ protected function getPosts()
+ {
+ $tag = $this->term;
+ $hash = hash('sha256', $tag);
+ if (Helpers::validateUrl($tag) != false &&
+ Helpers::validateLocalUrl($tag) != true &&
+ (bool) config_cache('federation.activitypub.enabled') == true &&
+ config('federation.activitypub.remoteFollow') == true
+ ) {
+ $remote = Helpers::fetchFromUrl($tag);
+ if (isset($remote['type']) &&
+ in_array($remote['type'], ['Note', 'Question'])
+ ) {
+ $item = Helpers::statusFetch($tag);
+ $this->tokens['posts'] = [[
+ 'count' => 0,
+ 'url' => $item->url(),
+ 'type' => 'status',
+ 'value' => "by {$item->profile->username} {$item->created_at->diffForHumans(null, true, true)}",
+ 'tokens' => [$item->caption],
+ 'name' => $item->caption,
+ 'thumb' => $item->thumb(),
+ ]];
+ }
+ } else {
+ $posts = Status::select('id', 'profile_id', 'caption', 'created_at')
+ ->whereHas('media')
+ ->whereNull('in_reply_to_id')
+ ->whereNull('reblog_of_id')
+ ->whereProfileId(Auth::user()->profile_id)
+ ->where('caption', 'like', '%'.$tag.'%')
+ ->latest()
+ ->limit(10)
+ ->get();
- protected function getProfiles()
- {
- $tag = $this->term;
- $remoteKey = $this->cacheKey . 'profiles:remote:' . $this->hash;
- $key = $this->cacheKey . 'profiles:' . $this->hash;
- $remoteTtl = now()->addMinutes(15);
- $ttl = now()->addHours(2);
- if( Helpers::validateUrl($tag) != false &&
- Helpers::validateLocalUrl($tag) != true &&
- config_cache('federation.activitypub.enabled') == true &&
- config('federation.activitypub.remoteFollow') == true
- ) {
- $remote = Helpers::fetchFromUrl($tag);
- if( isset($remote['type']) &&
- $remote['type'] == 'Person'
- ) {
- $this->tokens['profiles'] = Cache::remember($remoteKey, $remoteTtl, function() use($tag) {
- $item = Helpers::profileFirstOrNew($tag);
- $tokens = [[
- 'count' => 1,
- 'url' => $item->url(),
- 'type' => 'profile',
- 'value' => $item->username,
- 'tokens' => [$item->username],
- 'name' => $item->name,
- 'entity' => [
- 'id' => (string) $item->id,
- 'following' => $item->followedBy(Auth::user()->profile),
- 'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
- 'thumb' => $item->avatarUrl(),
- 'local' => (bool) !$item->domain,
- 'post_count' => $item->statuses()->count()
- ]
- ]];
- return $tokens;
- });
- }
- }
+ if ($posts->count() > 0) {
+ $posts = $posts->map(function ($item, $key) {
+ return [
+ 'count' => 0,
+ 'url' => $item->url(),
+ 'type' => 'status',
+ 'value' => "by {$item->profile->username} {$item->created_at->diffForHumans(null, true, true)}",
+ 'tokens' => [$item->caption],
+ 'name' => $item->caption,
+ 'thumb' => $item->thumb(),
+ 'filter' => $item->firstMedia()->filter_class,
+ ];
+ });
+ $this->tokens['posts'] = $posts;
+ }
+ }
+ }
- else {
- $this->tokens['profiles'] = Cache::remember($key, $ttl, function() use($tag) {
- if(Str::startsWith($tag, '@')) {
- $tag = substr($tag, 1);
- }
- $users = Profile::select('status', 'domain', 'username', 'name', 'id')
- ->whereNull('status')
- ->where('username', 'like', '%'.$tag.'%')
- ->limit(20)
- ->orderBy('domain')
- ->get();
+ protected function getHashtags()
+ {
+ $tag = $this->term;
+ $key = $this->cacheKey.'hashtags:'.$this->hash;
+ $ttl = now()->addMinutes(1);
+ $tokens = Cache::remember($key, $ttl, function () use ($tag) {
+ $htag = Str::startsWith($tag, '#') == true ? mb_substr($tag, 1) : $tag;
+ $hashtags = Hashtag::select('id', 'name', 'slug')
+ ->where('slug', 'like', '%'.$htag.'%')
+ ->whereHas('posts')
+ ->limit(20)
+ ->get();
+ if ($hashtags->count() > 0) {
+ $tags = $hashtags->map(function ($item, $key) {
+ return [
+ 'count' => $item->posts()->count(),
+ 'url' => $item->url(),
+ 'type' => 'hashtag',
+ 'value' => $item->name,
+ 'tokens' => '',
+ 'name' => null,
+ ];
+ });
- if($users->count() > 0) {
- return $users->map(function ($item, $key) {
- return [
- 'count' => 0,
- 'url' => $item->url(),
- 'type' => 'profile',
- 'value' => $item->username,
- 'tokens' => [$item->username],
- 'name' => $item->name,
- 'avatar' => $item->avatarUrl(),
- 'id' => (string) $item->id,
- 'entity' => [
- 'id' => (string) $item->id,
- 'following' => $item->followedBy(Auth::user()->profile),
- 'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
- 'thumb' => $item->avatarUrl(),
- 'local' => (bool) !$item->domain,
- 'post_count' => $item->statuses()->count()
- ]
- ];
- });
- }
- });
- }
- }
+ return $tags;
+ }
+ });
+ $this->tokens['hashtags'] = $tokens;
+ }
- public function results(Request $request)
- {
- $this->validate($request, [
- 'q' => 'required|string|min:1',
- ]);
+ protected function getPlaces()
+ {
+ $tag = $this->term;
+ // $key = $this->cacheKey . 'places:' . $this->hash;
+ // $ttl = now()->addHours(12);
+ // $tokens = Cache::remember($key, $ttl, function() use($tag) {
+ $htag = Str::contains($tag, ',') == true ? explode(',', $tag) : [$tag];
+ $hashtags = Place::select('id', 'name', 'slug', 'country')
+ ->where('name', 'like', '%'.$htag[0].'%')
+ ->paginate(20);
+ $tags = [];
+ if ($hashtags->count() > 0) {
+ $tags = $hashtags->map(function ($item, $key) {
+ return [
+ 'count' => null,
+ 'url' => $item->url(),
+ 'type' => 'place',
+ 'value' => $item->name.', '.$item->country,
+ 'tokens' => '',
+ 'name' => null,
+ 'city' => $item->name,
+ 'country' => $item->country,
+ ];
+ });
+ // return $tags;
+ }
+ // });
+ $this->tokens['places'] = $tags;
+ $this->tokens['placesPagination'] = [
+ 'total' => $hashtags->total(),
+ 'current_page' => $hashtags->currentPage(),
+ 'last_page' => $hashtags->lastPage(),
+ ];
+ }
- return view('search.results');
- }
+ protected function getProfiles()
+ {
+ $tag = $this->term;
+ $remoteKey = $this->cacheKey.'profiles:remote:'.$this->hash;
+ $key = $this->cacheKey.'profiles:'.$this->hash;
+ $remoteTtl = now()->addMinutes(15);
+ $ttl = now()->addHours(2);
+ if (Helpers::validateUrl($tag) != false &&
+ Helpers::validateLocalUrl($tag) != true &&
+ (bool) config_cache('federation.activitypub.enabled') == true &&
+ config('federation.activitypub.remoteFollow') == true
+ ) {
+ $remote = Helpers::fetchFromUrl($tag);
+ if (isset($remote['type']) &&
+ $remote['type'] == 'Person'
+ ) {
+ $this->tokens['profiles'] = Cache::remember($remoteKey, $remoteTtl, function () use ($tag) {
+ $item = Helpers::profileFirstOrNew($tag);
+ $tokens = [[
+ 'count' => 1,
+ 'url' => $item->url(),
+ 'type' => 'profile',
+ 'value' => $item->username,
+ 'tokens' => [$item->username],
+ 'name' => $item->name,
+ 'entity' => [
+ 'id' => (string) $item->id,
+ 'following' => $item->followedBy(Auth::user()->profile),
+ 'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
+ 'thumb' => $item->avatarUrl(),
+ 'local' => (bool) ! $item->domain,
+ 'post_count' => $item->statuses()->count(),
+ ],
+ ]];
- protected function webfingerSearch()
- {
- $wfs = WebfingerService::lookup($this->term);
+ return $tokens;
+ });
+ }
+ } else {
+ $this->tokens['profiles'] = Cache::remember($key, $ttl, function () use ($tag) {
+ if (Str::startsWith($tag, '@')) {
+ $tag = substr($tag, 1);
+ }
+ $users = Profile::select('status', 'domain', 'username', 'name', 'id')
+ ->whereNull('status')
+ ->where('username', 'like', '%'.$tag.'%')
+ ->limit(20)
+ ->orderBy('domain')
+ ->get();
- if(empty($wfs)) {
- return;
- }
+ if ($users->count() > 0) {
+ return $users->map(function ($item, $key) {
+ return [
+ 'count' => 0,
+ 'url' => $item->url(),
+ 'type' => 'profile',
+ 'value' => $item->username,
+ 'tokens' => [$item->username],
+ 'name' => $item->name,
+ 'avatar' => $item->avatarUrl(),
+ 'id' => (string) $item->id,
+ 'entity' => [
+ 'id' => (string) $item->id,
+ 'following' => $item->followedBy(Auth::user()->profile),
+ 'follow_request' => $item->hasFollowRequestById(Auth::user()->profile_id),
+ 'thumb' => $item->avatarUrl(),
+ 'local' => (bool) ! $item->domain,
+ 'post_count' => $item->statuses()->count(),
+ ],
+ ];
+ });
+ }
+ });
+ }
+ }
- $this->tokens['profiles'] = [
- [
- 'count' => 1,
- 'url' => $wfs['url'],
- 'type' => 'profile',
- 'value' => $wfs['username'],
- 'tokens' => [$wfs['username']],
- 'name' => $wfs['display_name'],
- 'entity' => [
- 'id' => (string) $wfs['id'],
- 'following' => null,
- 'follow_request' => null,
- 'thumb' => $wfs['avatar'],
- 'local' => (bool) $wfs['local']
- ]
- ]
- ];
- return;
- }
+ public function results(Request $request)
+ {
+ $this->validate($request, [
+ 'q' => 'required|string|min:1',
+ ]);
- protected function remotePostLookup()
- {
- $tag = $this->term;
- $hash = hash('sha256', $tag);
- $local = Helpers::validateLocalUrl($tag);
- $valid = Helpers::validateUrl($tag);
+ return view('search.results');
+ }
- if($valid == false || $local == true) {
- return;
- }
+ protected function webfingerSearch()
+ {
+ $wfs = WebfingerService::lookup($this->term);
- if(Status::whereUri($tag)->whereLocal(false)->exists()) {
- $item = Status::whereUri($tag)->first();
- $media = $item->firstMedia();
- $url = null;
- if($media) {
- $url = $media->remote_url;
- }
- $this->tokens['posts'] = [[
- 'count' => 0,
- 'url' => "/i/web/post/_/$item->profile_id/$item->id",
- 'type' => 'status',
- 'username' => $item->profile->username,
- 'caption' => $item->rendered ?? $item->caption,
- 'thumb' => $url,
- 'timestamp' => $item->created_at->diffForHumans()
- ]];
- }
+ if (empty($wfs)) {
+ return;
+ }
- $remote = Helpers::fetchFromUrl($tag);
+ $this->tokens['profiles'] = [
+ [
+ 'count' => 1,
+ 'url' => $wfs['url'],
+ 'type' => 'profile',
+ 'value' => $wfs['username'],
+ 'tokens' => [$wfs['username']],
+ 'name' => $wfs['display_name'],
+ 'entity' => [
+ 'id' => (string) $wfs['id'],
+ 'following' => null,
+ 'follow_request' => null,
+ 'thumb' => $wfs['avatar'],
+ 'local' => (bool) $wfs['local'],
+ ],
+ ],
+ ];
- if(isset($remote['type']) && $remote['type'] == 'Note') {
- $item = Helpers::statusFetch($tag);
- $media = $item->firstMedia();
- $url = null;
- if($media) {
- $url = $media->remote_url;
- }
- $this->tokens['posts'] = [[
- 'count' => 0,
- 'url' => "/i/web/post/_/$item->profile_id/$item->id",
- 'type' => 'status',
- 'username' => $item->profile->username,
- 'caption' => $item->rendered ?? $item->caption,
- 'thumb' => $url,
- 'timestamp' => $item->created_at->diffForHumans()
- ]];
- }
- }
+ }
- protected function remoteLookupSearch()
- {
- if(!Helpers::validateUrl($this->term)) {
- return;
- }
- $this->getProfiles();
- $this->remotePostLookup();
- }
+ protected function remotePostLookup()
+ {
+ $tag = $this->term;
+ $hash = hash('sha256', $tag);
+ $local = Helpers::validateLocalUrl($tag);
+ $valid = Helpers::validateUrl($tag);
+
+ if ($valid == false || $local == true) {
+ return;
+ }
+
+ if (Status::whereUri($tag)->whereLocal(false)->exists()) {
+ $item = Status::whereUri($tag)->first();
+ $media = $item->firstMedia();
+ $url = null;
+ if ($media) {
+ $url = $media->remote_url;
+ }
+ $this->tokens['posts'] = [[
+ 'count' => 0,
+ 'url' => "/i/web/post/_/$item->profile_id/$item->id",
+ 'type' => 'status',
+ 'username' => $item->profile->username,
+ 'caption' => $item->rendered ?? $item->caption,
+ 'thumb' => $url,
+ 'timestamp' => $item->created_at->diffForHumans(),
+ ]];
+ }
+
+ $remote = Helpers::fetchFromUrl($tag);
+
+ if (isset($remote['type']) && $remote['type'] == 'Note') {
+ $item = Helpers::statusFetch($tag);
+ $media = $item->firstMedia();
+ $url = null;
+ if ($media) {
+ $url = $media->remote_url;
+ }
+ $this->tokens['posts'] = [[
+ 'count' => 0,
+ 'url' => "/i/web/post/_/$item->profile_id/$item->id",
+ 'type' => 'status',
+ 'username' => $item->profile->username,
+ 'caption' => $item->rendered ?? $item->caption,
+ 'thumb' => $url,
+ 'timestamp' => $item->created_at->diffForHumans(),
+ ]];
+ }
+ }
+
+ protected function remoteLookupSearch()
+ {
+ if (! Helpers::validateUrl($this->term)) {
+ return;
+ }
+ $this->getProfiles();
+ $this->remotePostLookup();
+ }
}
diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php
index 4a3b3552d..7f77f9a81 100644
--- a/app/Http/Controllers/StatusController.php
+++ b/app/Http/Controllers/StatusController.php
@@ -78,7 +78,7 @@ class StatusController extends Controller
]);
}
- if ($request->wantsJson() && config_cache('federation.activitypub.enabled')) {
+ if ($request->wantsJson() && (bool) config_cache('federation.activitypub.enabled')) {
return $this->showActivityPub($request, $status);
}
diff --git a/app/Jobs/SharePipeline/SharePipeline.php b/app/Jobs/SharePipeline/SharePipeline.php
index 4eca4e1ab..734c44231 100644
--- a/app/Jobs/SharePipeline/SharePipeline.php
+++ b/app/Jobs/SharePipeline/SharePipeline.php
@@ -2,9 +2,15 @@
namespace App\Jobs\SharePipeline;
-use Cache, Log;
-use Illuminate\Support\Facades\Redis;
-use App\{Status, Notification};
+use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
+use App\Notification;
+use App\Services\ReblogService;
+use App\Services\StatusService;
+use App\Status;
+use App\Transformer\ActivityPub\Verb\Announce;
+use App\Util\ActivityPub\HttpSignature;
+use GuzzleHttp\Client;
+use GuzzleHttp\Pool;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -12,141 +18,136 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use League\Fractal;
use League\Fractal\Serializer\ArraySerializer;
-use App\Transformer\ActivityPub\Verb\Announce;
-use GuzzleHttp\{Pool, Client, Promise};
-use App\Util\ActivityPub\HttpSignature;
-use App\Services\ReblogService;
-use App\Services\StatusService;
-use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
class SharePipeline implements ShouldQueue
{
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- protected $status;
+ protected $status;
- /**
- * Delete the job if its models no longer exist.
- *
- * @var bool
- */
- public $deleteWhenMissingModels = true;
+ /**
+ * Delete the job if its models no longer exist.
+ *
+ * @var bool
+ */
+ public $deleteWhenMissingModels = true;
- /**
- * Create a new job instance.
- *
- * @return void
- */
- public function __construct(Status $status)
- {
- $this->status = $status;
- }
+ /**
+ * Create a new job instance.
+ *
+ * @return void
+ */
+ public function __construct(Status $status)
+ {
+ $this->status = $status;
+ }
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- $status = $this->status;
- $parent = Status::find($this->status->reblog_of_id);
- if(!$parent) {
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $status = $this->status;
+ $parent = Status::find($this->status->reblog_of_id);
+ if (! $parent) {
return;
}
- $actor = $status->profile;
- $target = $parent->profile;
+ $actor = $status->profile;
+ $target = $parent->profile;
- if ($status->uri !== null) {
- // Ignore notifications to remote statuses
- return;
- }
+ if ($status->uri !== null) {
+ // Ignore notifications to remote statuses
+ return;
+ }
- if($target->id === $status->profile_id) {
- $this->remoteAnnounceDeliver();
- return true;
- }
+ if ($target->id === $status->profile_id) {
+ $this->remoteAnnounceDeliver();
- ReblogService::addPostReblog($parent->profile_id, $status->id);
+ return true;
+ }
- $parent->reblogs_count = $parent->reblogs_count + 1;
- $parent->save();
- StatusService::del($parent->id);
+ ReblogService::addPostReblog($parent->profile_id, $status->id);
- Notification::firstOrCreate(
- [
- 'profile_id' => $target->id,
- 'actor_id' => $actor->id,
- 'action' => 'share',
- 'item_type' => 'App\Status',
- 'item_id' => $status->reblog_of_id ?? $status->id,
- ]
- );
+ $parent->reblogs_count = $parent->reblogs_count + 1;
+ $parent->save();
+ StatusService::del($parent->id);
- FeedInsertPipeline::dispatch($status->id, $status->profile_id)->onQueue('feed');
+ Notification::firstOrCreate(
+ [
+ 'profile_id' => $target->id,
+ 'actor_id' => $actor->id,
+ 'action' => 'share',
+ 'item_type' => 'App\Status',
+ 'item_id' => $status->reblog_of_id ?? $status->id,
+ ]
+ );
- return $this->remoteAnnounceDeliver();
- }
+ FeedInsertPipeline::dispatch($status->id, $status->profile_id)->onQueue('feed');
- public function remoteAnnounceDeliver()
- {
- if(config('app.env') !== 'production' || config_cache('federation.activitypub.enabled') == false) {
- return true;
- }
- $status = $this->status;
- $profile = $status->profile;
+ return $this->remoteAnnounceDeliver();
+ }
- $fractal = new Fractal\Manager();
- $fractal->setSerializer(new ArraySerializer());
- $resource = new Fractal\Resource\Item($status, new Announce());
- $activity = $fractal->createData($resource)->toArray();
+ public function remoteAnnounceDeliver()
+ {
+ if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) {
+ return true;
+ }
+ $status = $this->status;
+ $profile = $status->profile;
- $audience = $status->profile->getAudienceInbox();
+ $fractal = new Fractal\Manager();
+ $fractal->setSerializer(new ArraySerializer());
+ $resource = new Fractal\Resource\Item($status, new Announce());
+ $activity = $fractal->createData($resource)->toArray();
- if(empty($audience) || $status->scope != 'public') {
- // Return on profiles with no remote followers
- return;
- }
+ $audience = $status->profile->getAudienceInbox();
- $payload = json_encode($activity);
+ if (empty($audience) || $status->scope != 'public') {
+ // Return on profiles with no remote followers
+ return;
+ }
- $client = new Client([
- 'timeout' => config('federation.activitypub.delivery.timeout')
- ]);
+ $payload = json_encode($activity);
- $version = config('pixelfed.version');
- $appUrl = config('app.url');
- $userAgent = "(Pixelfed/{$version}; +{$appUrl})";
+ $client = new Client([
+ 'timeout' => config('federation.activitypub.delivery.timeout'),
+ ]);
- $requests = function($audience) use ($client, $activity, $profile, $payload, $userAgent) {
- foreach($audience as $url) {
- $headers = HttpSignature::sign($profile, $url, $activity, [
- 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
- 'User-Agent' => $userAgent,
- ]);
- yield function() use ($client, $url, $headers, $payload) {
- return $client->postAsync($url, [
- 'curl' => [
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_POSTFIELDS => $payload,
- CURLOPT_HEADER => true
- ]
- ]);
- };
- }
- };
+ $version = config('pixelfed.version');
+ $appUrl = config('app.url');
+ $userAgent = "(Pixelfed/{$version}; +{$appUrl})";
- $pool = new Pool($client, $requests($audience), [
- 'concurrency' => config('federation.activitypub.delivery.concurrency'),
- 'fulfilled' => function ($response, $index) {
- },
- 'rejected' => function ($reason, $index) {
- }
- ]);
+ $requests = function ($audience) use ($client, $activity, $profile, $payload, $userAgent) {
+ foreach ($audience as $url) {
+ $headers = HttpSignature::sign($profile, $url, $activity, [
+ 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ 'User-Agent' => $userAgent,
+ ]);
+ yield function () use ($client, $url, $headers, $payload) {
+ return $client->postAsync($url, [
+ 'curl' => [
+ CURLOPT_HTTPHEADER => $headers,
+ CURLOPT_POSTFIELDS => $payload,
+ CURLOPT_HEADER => true,
+ ],
+ ]);
+ };
+ }
+ };
- $promise = $pool->promise();
+ $pool = new Pool($client, $requests($audience), [
+ 'concurrency' => config('federation.activitypub.delivery.concurrency'),
+ 'fulfilled' => function ($response, $index) {
+ },
+ 'rejected' => function ($reason, $index) {
+ },
+ ]);
- $promise->wait();
+ $promise = $pool->promise();
- }
+ $promise->wait();
+
+ }
}
diff --git a/app/Jobs/SharePipeline/UndoSharePipeline.php b/app/Jobs/SharePipeline/UndoSharePipeline.php
index 1435688d9..af3239953 100644
--- a/app/Jobs/SharePipeline/UndoSharePipeline.php
+++ b/app/Jobs/SharePipeline/UndoSharePipeline.php
@@ -2,9 +2,15 @@
namespace App\Jobs\SharePipeline;
-use Cache, Log;
-use Illuminate\Support\Facades\Redis;
-use App\{Status, Notification};
+use App\Jobs\HomeFeedPipeline\FeedRemovePipeline;
+use App\Notification;
+use App\Services\ReblogService;
+use App\Services\StatusService;
+use App\Status;
+use App\Transformer\ActivityPub\Verb\UndoAnnounce;
+use App\Util\ActivityPub\HttpSignature;
+use GuzzleHttp\Client;
+use GuzzleHttp\Pool;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -12,128 +18,125 @@ use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use League\Fractal;
use League\Fractal\Serializer\ArraySerializer;
-use App\Transformer\ActivityPub\Verb\UndoAnnounce;
-use GuzzleHttp\{Pool, Client, Promise};
-use App\Util\ActivityPub\HttpSignature;
-use App\Services\ReblogService;
-use App\Services\StatusService;
-use App\Jobs\HomeFeedPipeline\FeedRemovePipeline;
class UndoSharePipeline implements ShouldQueue
{
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- protected $status;
- public $deleteWhenMissingModels = true;
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- public function __construct(Status $status)
- {
- $this->status = $status;
- }
+ protected $status;
- public function handle()
- {
- $status = $this->status;
- $actor = $status->profile;
- $parent = Status::find($status->reblog_of_id);
+ public $deleteWhenMissingModels = true;
- FeedRemovePipeline::dispatch($status->id, $status->profile_id)->onQueue('feed');
+ public function __construct(Status $status)
+ {
+ $this->status = $status;
+ }
- if($parent) {
- $target = $parent->profile_id;
- ReblogService::removePostReblog($parent->profile_id, $status->id);
+ public function handle()
+ {
+ $status = $this->status;
+ $actor = $status->profile;
+ $parent = Status::find($status->reblog_of_id);
- if($parent->reblogs_count > 0) {
- $parent->reblogs_count = $parent->reblogs_count - 1;
- $parent->save();
- StatusService::del($parent->id);
- }
+ FeedRemovePipeline::dispatch($status->id, $status->profile_id)->onQueue('feed');
- $notification = Notification::whereProfileId($target)
- ->whereActorId($status->profile_id)
- ->whereAction('share')
- ->whereItemId($status->reblog_of_id)
- ->whereItemType('App\Status')
- ->first();
+ if ($parent) {
+ $target = $parent->profile_id;
+ ReblogService::removePostReblog($parent->profile_id, $status->id);
- if($notification) {
- $notification->forceDelete();
- }
- }
+ if ($parent->reblogs_count > 0) {
+ $parent->reblogs_count = $parent->reblogs_count - 1;
+ $parent->save();
+ StatusService::del($parent->id);
+ }
- if ($status->uri != null) {
- return;
- }
+ $notification = Notification::whereProfileId($target)
+ ->whereActorId($status->profile_id)
+ ->whereAction('share')
+ ->whereItemId($status->reblog_of_id)
+ ->whereItemType('App\Status')
+ ->first();
- if(config('app.env') !== 'production' || config_cache('federation.activitypub.enabled') == false) {
- return $status->delete();
- } else {
- return $this->remoteAnnounceDeliver();
- }
- }
+ if ($notification) {
+ $notification->forceDelete();
+ }
+ }
- public function remoteAnnounceDeliver()
- {
- if(config('app.env') !== 'production' || config_cache('federation.activitypub.enabled') == false) {
+ if ($status->uri != null) {
+ return;
+ }
+
+ if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) {
+ return $status->delete();
+ } else {
+ return $this->remoteAnnounceDeliver();
+ }
+ }
+
+ public function remoteAnnounceDeliver()
+ {
+ if (config('app.env') !== 'production' || (bool) config_cache('federation.activitypub.enabled') == false) {
$status->delete();
- return 1;
- }
- $status = $this->status;
- $profile = $status->profile;
+ return 1;
+ }
- $fractal = new Fractal\Manager();
- $fractal->setSerializer(new ArraySerializer());
- $resource = new Fractal\Resource\Item($status, new UndoAnnounce());
- $activity = $fractal->createData($resource)->toArray();
+ $status = $this->status;
+ $profile = $status->profile;
- $audience = $status->profile->getAudienceInbox();
+ $fractal = new Fractal\Manager();
+ $fractal->setSerializer(new ArraySerializer());
+ $resource = new Fractal\Resource\Item($status, new UndoAnnounce());
+ $activity = $fractal->createData($resource)->toArray();
- if(empty($audience) || $status->scope != 'public') {
- return 1;
- }
+ $audience = $status->profile->getAudienceInbox();
- $payload = json_encode($activity);
+ if (empty($audience) || $status->scope != 'public') {
+ return 1;
+ }
- $client = new Client([
- 'timeout' => config('federation.activitypub.delivery.timeout')
- ]);
+ $payload = json_encode($activity);
- $version = config('pixelfed.version');
- $appUrl = config('app.url');
- $userAgent = "(Pixelfed/{$version}; +{$appUrl})";
+ $client = new Client([
+ 'timeout' => config('federation.activitypub.delivery.timeout'),
+ ]);
- $requests = function($audience) use ($client, $activity, $profile, $payload, $userAgent) {
- foreach($audience as $url) {
- $headers = HttpSignature::sign($profile, $url, $activity, [
- 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
- 'User-Agent' => $userAgent,
- ]);
- yield function() use ($client, $url, $headers, $payload) {
- return $client->postAsync($url, [
- 'curl' => [
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_POSTFIELDS => $payload,
- CURLOPT_HEADER => true
- ]
- ]);
- };
- }
- };
+ $version = config('pixelfed.version');
+ $appUrl = config('app.url');
+ $userAgent = "(Pixelfed/{$version}; +{$appUrl})";
- $pool = new Pool($client, $requests($audience), [
- 'concurrency' => config('federation.activitypub.delivery.concurrency'),
- 'fulfilled' => function ($response, $index) {
- },
- 'rejected' => function ($reason, $index) {
- }
- ]);
+ $requests = function ($audience) use ($client, $activity, $profile, $payload, $userAgent) {
+ foreach ($audience as $url) {
+ $headers = HttpSignature::sign($profile, $url, $activity, [
+ 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ 'User-Agent' => $userAgent,
+ ]);
+ yield function () use ($client, $url, $headers, $payload) {
+ return $client->postAsync($url, [
+ 'curl' => [
+ CURLOPT_HTTPHEADER => $headers,
+ CURLOPT_POSTFIELDS => $payload,
+ CURLOPT_HEADER => true,
+ ],
+ ]);
+ };
+ }
+ };
- $promise = $pool->promise();
+ $pool = new Pool($client, $requests($audience), [
+ 'concurrency' => config('federation.activitypub.delivery.concurrency'),
+ 'fulfilled' => function ($response, $index) {
+ },
+ 'rejected' => function ($reason, $index) {
+ },
+ ]);
- $promise->wait();
+ $promise = $pool->promise();
- $status->delete();
+ $promise->wait();
- return 1;
- }
+ $status->delete();
+
+ return 1;
+ }
}
diff --git a/app/Jobs/StatusPipeline/StatusDelete.php b/app/Jobs/StatusPipeline/StatusDelete.php
index dbbfad5ac..d85ebdc4a 100644
--- a/app/Jobs/StatusPipeline/StatusDelete.php
+++ b/app/Jobs/StatusPipeline/StatusDelete.php
@@ -2,126 +2,122 @@
namespace App\Jobs\StatusPipeline;
-use DB, Cache, Storage;
-use App\{
- AccountInterstitial,
- Bookmark,
- CollectionItem,
- DirectMessage,
- Like,
- Media,
- MediaTag,
- Mention,
- Notification,
- Report,
- Status,
- StatusArchived,
- StatusHashtag,
- StatusView
-};
+use App\AccountInterstitial;
+use App\Bookmark;
+use App\CollectionItem;
+use App\DirectMessage;
+use App\Jobs\MediaPipeline\MediaDeletePipeline;
+use App\Like;
+use App\Media;
+use App\MediaTag;
+use App\Mention;
+use App\Notification;
+use App\Report;
+use App\Services\CollectionService;
+use App\Services\NotificationService;
+use App\Services\StatusService;
+use App\Status;
+use App\StatusArchived;
+use App\StatusHashtag;
+use App\StatusView;
+use App\Transformer\ActivityPub\Verb\DeleteNote;
+use App\Util\ActivityPub\HttpSignature;
+use Cache;
+use GuzzleHttp\Client;
+use GuzzleHttp\Pool;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use League\Fractal;
-use Illuminate\Support\Str;
use League\Fractal\Serializer\ArraySerializer;
-use App\Transformer\ActivityPub\Verb\DeleteNote;
-use App\Util\ActivityPub\Helpers;
-use GuzzleHttp\Pool;
-use GuzzleHttp\Client;
-use GuzzleHttp\Promise;
-use App\Util\ActivityPub\HttpSignature;
-use App\Services\CollectionService;
-use App\Services\StatusService;
-use App\Services\NotificationService;
-use App\Jobs\MediaPipeline\MediaDeletePipeline;
class StatusDelete implements ShouldQueue
{
- use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
+ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
- protected $status;
+ protected $status;
- /**
- * Delete the job if its models no longer exist.
- *
- * @var bool
- */
- public $deleteWhenMissingModels = true;
+ /**
+ * Delete the job if its models no longer exist.
+ *
+ * @var bool
+ */
+ public $deleteWhenMissingModels = true;
public $timeout = 900;
+
public $tries = 2;
- /**
- * Create a new job instance.
- *
- * @return void
- */
- public function __construct(Status $status)
- {
- $this->status = $status;
- }
+ /**
+ * Create a new job instance.
+ *
+ * @return void
+ */
+ public function __construct(Status $status)
+ {
+ $this->status = $status;
+ }
- /**
- * Execute the job.
- *
- * @return void
- */
- public function handle()
- {
- $status = $this->status;
- $profile = $this->status->profile;
+ /**
+ * Execute the job.
+ *
+ * @return void
+ */
+ public function handle()
+ {
+ $status = $this->status;
+ $profile = $this->status->profile;
- StatusService::del($status->id, true);
- if($profile) {
- if(in_array($status->type, ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])) {
- $profile->status_count = $profile->status_count - 1;
- $profile->save();
- }
- }
+ StatusService::del($status->id, true);
+ if ($profile) {
+ if (in_array($status->type, ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])) {
+ $profile->status_count = $profile->status_count - 1;
+ $profile->save();
+ }
+ }
- Cache::forget('pf:atom:user-feed:by-id:' . $status->profile_id);
+ Cache::forget('pf:atom:user-feed:by-id:'.$status->profile_id);
- if(config_cache('federation.activitypub.enabled') == true) {
- return $this->fanoutDelete($status);
- } else {
- return $this->unlinkRemoveMedia($status);
- }
- }
+ if ((bool) config_cache('federation.activitypub.enabled') == true) {
+ return $this->fanoutDelete($status);
+ } else {
+ return $this->unlinkRemoveMedia($status);
+ }
+ }
- public function unlinkRemoveMedia($status)
- {
+ public function unlinkRemoveMedia($status)
+ {
Media::whereStatusId($status->id)
- ->get()
- ->each(function($media) {
- MediaDeletePipeline::dispatch($media);
- });
+ ->get()
+ ->each(function ($media) {
+ MediaDeletePipeline::dispatch($media);
+ });
- if($status->in_reply_to_id) {
- $parent = Status::findOrFail($status->in_reply_to_id);
- --$parent->reply_count;
- $parent->save();
- StatusService::del($parent->id);
- }
+ if ($status->in_reply_to_id) {
+ $parent = Status::findOrFail($status->in_reply_to_id);
+ $parent->reply_count--;
+ $parent->save();
+ StatusService::del($parent->id);
+ }
Bookmark::whereStatusId($status->id)->delete();
CollectionItem::whereObjectType('App\Status')
->whereObjectId($status->id)
->get()
- ->each(function($col) {
+ ->each(function ($col) {
CollectionService::removeItem($col->collection_id, $col->object_id);
$col->delete();
- });
+ });
$dms = DirectMessage::whereStatusId($status->id)->get();
- foreach($dms as $dm) {
+ foreach ($dms as $dm) {
$not = Notification::whereItemType('App\DirectMessage')
->whereItemId($dm->id)
->first();
- if($not) {
+ if ($not) {
NotificationService::del($not->profile_id, $not->id);
$not->forceDeleteQuietly();
}
@@ -130,11 +126,11 @@ class StatusDelete implements ShouldQueue
Like::whereStatusId($status->id)->delete();
$mediaTags = MediaTag::where('status_id', $status->id)->get();
- foreach($mediaTags as $mtag) {
+ foreach ($mediaTags as $mtag) {
$not = Notification::whereItemType('App\MediaTag')
->whereItemId($mtag->id)
->first();
- if($not) {
+ if ($not) {
NotificationService::del($not->profile_id, $not->id);
$not->forceDeleteQuietly();
}
@@ -142,85 +138,85 @@ class StatusDelete implements ShouldQueue
}
Mention::whereStatusId($status->id)->forceDelete();
- Notification::whereItemType('App\Status')
- ->whereItemId($status->id)
- ->forceDelete();
+ Notification::whereItemType('App\Status')
+ ->whereItemId($status->id)
+ ->forceDelete();
- Report::whereObjectType('App\Status')
- ->whereObjectId($status->id)
- ->delete();
+ Report::whereObjectType('App\Status')
+ ->whereObjectId($status->id)
+ ->delete();
StatusArchived::whereStatusId($status->id)->delete();
StatusHashtag::whereStatusId($status->id)->delete();
StatusView::whereStatusId($status->id)->delete();
- Status::whereInReplyToId($status->id)->update(['in_reply_to_id' => null]);
+ Status::whereInReplyToId($status->id)->update(['in_reply_to_id' => null]);
- AccountInterstitial::where('item_type', 'App\Status')
- ->where('item_id', $status->id)
- ->delete();
+ AccountInterstitial::where('item_type', 'App\Status')
+ ->where('item_id', $status->id)
+ ->delete();
- $status->delete();
-
- return 1;
- }
-
- public function fanoutDelete($status)
- {
- $profile = $status->profile;
-
- if(!$profile) {
- return;
- }
-
- $audience = $status->profile->getAudienceInbox();
-
- $fractal = new Fractal\Manager();
- $fractal->setSerializer(new ArraySerializer());
- $resource = new Fractal\Resource\Item($status, new DeleteNote());
- $activity = $fractal->createData($resource)->toArray();
-
- $this->unlinkRemoveMedia($status);
-
- $payload = json_encode($activity);
-
- $client = new Client([
- 'timeout' => config('federation.activitypub.delivery.timeout')
- ]);
-
- $version = config('pixelfed.version');
- $appUrl = config('app.url');
- $userAgent = "(Pixelfed/{$version}; +{$appUrl})";
-
- $requests = function($audience) use ($client, $activity, $profile, $payload, $userAgent) {
- foreach($audience as $url) {
- $headers = HttpSignature::sign($profile, $url, $activity, [
- 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
- 'User-Agent' => $userAgent,
- ]);
- yield function() use ($client, $url, $headers, $payload) {
- return $client->postAsync($url, [
- 'curl' => [
- CURLOPT_HTTPHEADER => $headers,
- CURLOPT_POSTFIELDS => $payload,
- CURLOPT_HEADER => true
- ]
- ]);
- };
- }
- };
-
- $pool = new Pool($client, $requests($audience), [
- 'concurrency' => config('federation.activitypub.delivery.concurrency'),
- 'fulfilled' => function ($response, $index) {
- },
- 'rejected' => function ($reason, $index) {
- }
- ]);
-
- $promise = $pool->promise();
-
- $promise->wait();
+ $status->delete();
return 1;
- }
+ }
+
+ public function fanoutDelete($status)
+ {
+ $profile = $status->profile;
+
+ if (! $profile) {
+ return;
+ }
+
+ $audience = $status->profile->getAudienceInbox();
+
+ $fractal = new Fractal\Manager();
+ $fractal->setSerializer(new ArraySerializer());
+ $resource = new Fractal\Resource\Item($status, new DeleteNote());
+ $activity = $fractal->createData($resource)->toArray();
+
+ $this->unlinkRemoveMedia($status);
+
+ $payload = json_encode($activity);
+
+ $client = new Client([
+ 'timeout' => config('federation.activitypub.delivery.timeout'),
+ ]);
+
+ $version = config('pixelfed.version');
+ $appUrl = config('app.url');
+ $userAgent = "(Pixelfed/{$version}; +{$appUrl})";
+
+ $requests = function ($audience) use ($client, $activity, $profile, $payload, $userAgent) {
+ foreach ($audience as $url) {
+ $headers = HttpSignature::sign($profile, $url, $activity, [
+ 'Content-Type' => 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ 'User-Agent' => $userAgent,
+ ]);
+ yield function () use ($client, $url, $headers, $payload) {
+ return $client->postAsync($url, [
+ 'curl' => [
+ CURLOPT_HTTPHEADER => $headers,
+ CURLOPT_POSTFIELDS => $payload,
+ CURLOPT_HEADER => true,
+ ],
+ ]);
+ };
+ }
+ };
+
+ $pool = new Pool($client, $requests($audience), [
+ 'concurrency' => config('federation.activitypub.delivery.concurrency'),
+ 'fulfilled' => function ($response, $index) {
+ },
+ 'rejected' => function ($reason, $index) {
+ },
+ ]);
+
+ $promise = $pool->promise();
+
+ $promise->wait();
+
+ return 1;
+ }
}
diff --git a/app/Jobs/StatusPipeline/StatusEntityLexer.php b/app/Jobs/StatusPipeline/StatusEntityLexer.php
index 872594a96..5c37838dc 100644
--- a/app/Jobs/StatusPipeline/StatusEntityLexer.php
+++ b/app/Jobs/StatusPipeline/StatusEntityLexer.php
@@ -3,12 +3,16 @@
namespace App\Jobs\StatusPipeline;
use App\Hashtag;
+use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
use App\Jobs\MentionPipeline\MentionPipeline;
use App\Mention;
use App\Profile;
+use App\Services\AdminShadowFilterService;
+use App\Services\PublicTimelineService;
+use App\Services\StatusService;
+use App\Services\UserFilterService;
use App\Status;
use App\StatusHashtag;
-use App\Services\PublicTimelineService;
use App\Util\Lexer\Autolink;
use App\Util\Lexer\Extractor;
use App\Util\Sentiment\Bouncer;
@@ -19,18 +23,15 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
-use App\Services\StatusService;
-use App\Services\UserFilterService;
-use App\Services\AdminShadowFilterService;
-use App\Jobs\HomeFeedPipeline\FeedInsertPipeline;
-use App\Jobs\HomeFeedPipeline\HashtagInsertFanoutPipeline;
class StatusEntityLexer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $status;
+
protected $entities;
+
protected $autolink;
/**
@@ -60,12 +61,12 @@ class StatusEntityLexer implements ShouldQueue
$profile = $this->status->profile;
$status = $this->status;
- if(in_array($status->type, ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])) {
+ if (in_array($status->type, ['photo', 'photo:album', 'video', 'video:album', 'photo:video:album'])) {
$profile->status_count = $profile->status_count + 1;
$profile->save();
}
- if($profile->no_autolink == false) {
+ if ($profile->no_autolink == false) {
$this->parseEntities();
}
}
@@ -103,16 +104,16 @@ class StatusEntityLexer implements ShouldQueue
$status = $this->status;
foreach ($tags as $tag) {
- if(mb_strlen($tag) > 124) {
+ if (mb_strlen($tag) > 124) {
continue;
}
DB::transaction(function () use ($status, $tag) {
$slug = str_slug($tag, '-', false);
$hashtag = Hashtag::firstOrCreate([
- 'slug' => $slug
+ 'slug' => $slug,
], [
- 'name' => $tag
+ 'name' => $tag,
]);
StatusHashtag::firstOrCreate(
@@ -136,11 +137,11 @@ class StatusEntityLexer implements ShouldQueue
foreach ($mentions as $mention) {
$mentioned = Profile::whereUsername($mention)->first();
- if (empty($mentioned) || !isset($mentioned->id)) {
+ if (empty($mentioned) || ! isset($mentioned->id)) {
continue;
}
$blocks = UserFilterService::blocks($mentioned->id);
- if($blocks && in_array($status->profile_id, $blocks)) {
+ if ($blocks && in_array($status->profile_id, $blocks)) {
continue;
}
@@ -161,8 +162,8 @@ class StatusEntityLexer implements ShouldQueue
$status = $this->status;
StatusService::refresh($status->id);
- if(config('exp.cached_home_timeline')) {
- if( $status->in_reply_to_id === null &&
+ if (config('exp.cached_home_timeline')) {
+ if ($status->in_reply_to_id === null &&
in_array($status->scope, ['public', 'unlisted', 'private'])
) {
FeedInsertPipeline::dispatch($status->id, $status->profile_id)->onQueue('feed');
@@ -179,28 +180,28 @@ class StatusEntityLexer implements ShouldQueue
'photo:album',
'video',
'video:album',
- 'photo:video:album'
+ 'photo:video:album',
];
- if(config_cache('pixelfed.bouncer.enabled')) {
+ if (config_cache('pixelfed.bouncer.enabled')) {
Bouncer::get($status);
}
- Cache::forget('pf:atom:user-feed:by-id:' . $status->profile_id);
+ Cache::forget('pf:atom:user-feed:by-id:'.$status->profile_id);
$hideNsfw = config('instance.hide_nsfw_on_public_feeds');
- if( $status->uri == null &&
+ if ($status->uri == null &&
$status->scope == 'public' &&
in_array($status->type, $types) &&
$status->in_reply_to_id === null &&
$status->reblog_of_id === null &&
($hideNsfw ? $status->is_nsfw == false : true)
) {
- if(AdminShadowFilterService::canAddToPublicFeedByProfileId($status->profile_id)) {
+ if (AdminShadowFilterService::canAddToPublicFeedByProfileId($status->profile_id)) {
PublicTimelineService::add($status->id);
}
}
- if(config_cache('federation.activitypub.enabled') == true && config('app.env') == 'production') {
+ if ((bool) config_cache('federation.activitypub.enabled') == true && config('app.env') == 'production') {
StatusActivityPubDeliver::dispatch($status);
}
}
diff --git a/app/Services/LandingService.php b/app/Services/LandingService.php
index 213e63910..f51822df2 100644
--- a/app/Services/LandingService.php
+++ b/app/Services/LandingService.php
@@ -85,7 +85,7 @@ class LandingService
'media_types' => config_cache('pixelfed.media_types'),
],
'features' => [
- 'federation' => config_cache('federation.activitypub.enabled'),
+ 'federation' => (bool) config_cache('federation.activitypub.enabled'),
'timelines' => [
'local' => true,
'network' => (bool) config_cache('federation.network_timeline'),
diff --git a/app/Util/ActivityPub/Outbox.php b/app/Util/ActivityPub/Outbox.php
index 43adb36e3..aba34955e 100644
--- a/app/Util/ActivityPub/Outbox.php
+++ b/app/Util/ActivityPub/Outbox.php
@@ -2,34 +2,32 @@
namespace App\Util\ActivityPub;
-use App\Profile;
-use App\Status;
-use League\Fractal;
use App\Http\Controllers\ProfileController;
-use App\Transformer\ActivityPub\ProfileOutbox;
+use App\Status;
use App\Transformer\ActivityPub\Verb\CreateNote;
+use League\Fractal;
-class Outbox {
+class Outbox
+{
+ public static function get($profile)
+ {
+ abort_if(! (bool) config_cache('federation.activitypub.enabled'), 404);
+ abort_if(! config('federation.activitypub.outbox'), 404);
- public static function get($profile)
- {
- abort_if(!config_cache('federation.activitypub.enabled'), 404);
- abort_if(!config('federation.activitypub.outbox'), 404);
-
- if($profile->status != null) {
+ if ($profile->status != null) {
return ProfileController::accountCheck($profile);
}
- if($profile->is_private) {
- return ['error'=>'403', 'msg' => 'private profile'];
+ if ($profile->is_private) {
+ return ['error' => '403', 'msg' => 'private profile'];
}
$timeline = $profile
- ->statuses()
- ->whereScope('public')
- ->orderBy('created_at', 'desc')
- ->take(10)
- ->get();
+ ->statuses()
+ ->whereScope('public')
+ ->orderBy('created_at', 'desc')
+ ->take(10)
+ ->get();
$count = Status::whereProfileId($profile->id)->count();
@@ -38,14 +36,14 @@ class Outbox {
$res = $fractal->createData($resource)->toArray();
$outbox = [
- '@context' => 'https://www.w3.org/ns/activitystreams',
- '_debug' => 'Outbox only supports latest 10 objects, pagination is not supported',
- 'id' => $profile->permalink('/outbox'),
- 'type' => 'OrderedCollection',
- 'totalItems' => $count,
- 'orderedItems' => $res['data']
+ '@context' => 'https://www.w3.org/ns/activitystreams',
+ '_debug' => 'Outbox only supports latest 10 objects, pagination is not supported',
+ 'id' => $profile->permalink('/outbox'),
+ 'type' => 'OrderedCollection',
+ 'totalItems' => $count,
+ 'orderedItems' => $res['data'],
];
- return $outbox;
- }
+ return $outbox;
+ }
}
diff --git a/resources/views/admin/diagnostics/home.blade.php b/resources/views/admin/diagnostics/home.blade.php
index 0d8b21e47..2f592b1cc 100644
--- a/resources/views/admin/diagnostics/home.blade.php
+++ b/resources/views/admin/diagnostics/home.blade.php
@@ -298,7 +298,7 @@
FEDERATION |
ACTIVITY_PUB |
- {{config_cache('federation.activitypub.enabled') ? '✅ true' : '❌ false' }} |
+ {{(bool) config_cache('federation.activitypub.enabled') ? '✅ true' : '❌ false' }} |
FEDERATION |