diff --git a/.env.example b/.env.example index 2a8604cc7..f5ed15a93 100644 --- a/.env.example +++ b/.env.example @@ -56,9 +56,9 @@ ACTIVITYPUB_SHAREDINBOX=false # php artisan optimize:clear # php artisan optimize -PF_COSTAR_ENABLED=false -CS_BLOCKED_DOMAINS='example.org,example.net,example.com' -CS_CW_DOMAINS='example.org,example.net,example.com' +PF_COSTAR_ENABLED=true +CS_BLOCKED_DOMAINS='gab.com,gab.ai,develop.gab.com' +CS_CW_DOMAINS='switter.at' CS_UNLISTED_DOMAINS='example.org,example.net,example.com' ## Optional diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 13d5dc030..8ddc88751 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -191,7 +191,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); @@ -242,7 +241,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); @@ -296,7 +294,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); @@ -348,7 +345,6 @@ class AccountController extends Controller $pid = $user->id; Cache::forget("user:filter:list:$pid"); - Cache::forget("feature:discover:people:$pid"); Cache::forget("feature:discover:posts:$pid"); Cache::forget("api:local:exp:rec:$pid"); diff --git a/app/Http/Controllers/PageController.php b/app/Http/Controllers/PageController.php index b3d8869ac..94d149410 100644 --- a/app/Http/Controllers/PageController.php +++ b/app/Http/Controllers/PageController.php @@ -18,6 +18,7 @@ class PageController extends Controller '/site/about' => 'site:about', '/site/privacy' => 'site:privacy', '/site/terms' => 'site:terms', + '/site/kb/community-guidelines' => 'site:help:community-guidelines' ]; } @@ -81,7 +82,7 @@ class PageController extends Controller public function generatePage(Request $request) { $this->validate($request, [ - 'page' => 'required|string|in:about,terms,privacy', + 'page' => 'required|string|in:about,terms,privacy,community_guidelines', ]); $page = $request->input('page'); @@ -98,6 +99,10 @@ class PageController extends Controller case 'terms': Page::firstOrCreate(['slug' => '/site/terms']); break; + + case 'community_guidelines': + Page::firstOrCreate(['slug' => '/site/kb/community-guidelines']); + break; } return redirect(route('admin.settings.pages')); diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index d8d13d477..6c9d4b83c 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -56,7 +56,7 @@ class SearchController extends Controller ] ]]; } else if ($type == 'Note') { - $item = Helpers::statusFirstOrFetch($tag, false); + $item = Helpers::statusFetch($tag); $tokens['posts'] = [[ 'count' => 0, 'url' => $item->url(), diff --git a/app/Http/Controllers/Settings/PrivacySettings.php b/app/Http/Controllers/Settings/PrivacySettings.php index d3283c921..99f7d4100 100644 --- a/app/Http/Controllers/Settings/PrivacySettings.php +++ b/app/Http/Controllers/Settings/PrivacySettings.php @@ -5,11 +5,13 @@ namespace App\Http\Controllers\Settings; use App\AccountLog; use App\EmailVerification; use App\Instance; +use App\Follower; use App\Media; use App\Profile; use App\User; use App\UserFilter; use App\Util\Lexer\PrettyNumber; +use App\Util\ActivityPub\Helpers; use Auth, Cache, DB; use Illuminate\Http\Request; @@ -134,9 +136,13 @@ trait PrivacySettings public function blockedInstanceStore(Request $request) { $this->validate($request, [ - 'domain' => 'required|active_url' + 'domain' => 'required|url|min:1|max:120' ]); $domain = $request->input('domain'); + if(Helpers::validateUrl($domain) == false) { + return abort(400, 'Invalid domain'); + } + $domain = parse_url($domain, PHP_URL_HOST); $instance = Instance::firstOrCreate(['domain' => $domain]); $filter = new UserFilter; $filter->user_id = Auth::user()->profile->id; @@ -165,4 +171,47 @@ trait PrivacySettings { return view('settings.privacy.blocked-keywords'); } + + public function privateAccountOptions(Request $request) + { + $this->validate($request, [ + 'mode' => 'required|string|in:keep-all,mutual-only,only-followers,remove-all', + 'duration' => 'required|integer|min:60|max:525600', + ]); + $mode = $request->input('mode'); + $duration = $request->input('duration'); + // $newRequests = $request->input('newrequests'); + + $profile = Auth::user()->profile; + $settings = Auth::user()->settings; + + if($mode !== 'keep-all') { + switch ($mode) { + case 'mutual-only': + $following = $profile->following()->pluck('profiles.id'); + Follower::whereFollowingId($profile->id)->whereNotIn('profile_id', $following)->delete(); + break; + + case 'only-followers': + $ts = now()->subMinutes($duration); + Follower::whereFollowingId($profile->id)->where('created_at', '>', $ts)->delete(); + break; + + case 'remove-all': + Follower::whereFollowingId($profile->id)->delete(); + break; + + default: + # code... + break; + } + } + $profile->is_private = true; + $settings->show_guests = false; + $settings->show_discover = false; + $settings->save(); + $profile->save(); + Cache::forget('profiles:private'); + return [200]; + } } \ No newline at end of file diff --git a/app/Http/Controllers/SiteController.php b/app/Http/Controllers/SiteController.php index c14dc1ddb..58b092b83 100644 --- a/app/Http/Controllers/SiteController.php +++ b/app/Http/Controllers/SiteController.php @@ -42,7 +42,7 @@ class SiteController extends Controller public function about() { - return Cache::remember('site:about', now()->addMinutes(120), function() { + return Cache::remember('site:about', now()->addHours(12), function() { $page = Page::whereSlug('/site/about')->whereActive(true)->first(); $stats = [ 'posts' => Status::whereLocal(true)->count(), @@ -64,24 +64,25 @@ class SiteController extends Controller public function communityGuidelines(Request $request) { - $slug = '/site/kb/community-guidelines'; - $page = Page::whereSlug($slug)->whereActive(true)->first(); - return view('site.help.community-guidelines', compact('page')); + return Cache::remember('site:help:community-guidelines', now()->addDays(120), function() { + $slug = '/site/kb/community-guidelines'; + $page = Page::whereSlug($slug)->whereActive(true)->first(); + return View::make('site.help.community-guidelines')->with(compact('page'))->render(); + }); } public function privacy(Request $request) { - return Cache::remember('site:privacy', now()->addMinutes(120), function() { + return Cache::remember('site:privacy', now()->addDays(120), function() { $slug = '/site/privacy'; $page = Page::whereSlug($slug)->whereActive(true)->first(); return View::make('site.privacy')->with(compact('page'))->render(); }); } - public function terms(Request $request) { - return Cache::remember('site:terms', now()->addMinutes(120), function() { + return Cache::remember('site:terms', now()->addDays(120), function() { $slug = '/site/terms'; $page = Page::whereSlug($slug)->whereActive(true)->first(); return View::make('site.terms')->with(compact('page'))->render(); diff --git a/app/Http/Controllers/StatusController.php b/app/Http/Controllers/StatusController.php index 65d6a2da5..c5a1c9975 100644 --- a/app/Http/Controllers/StatusController.php +++ b/app/Http/Controllers/StatusController.php @@ -30,11 +30,12 @@ class StatusController extends Controller } $status = Status::whereProfileId($user->id) + ->whereNull('reblog_of_id') ->whereNotIn('visibility',['draft','direct']) ->findOrFail($id); - if($status->uri) { - $url = $status->uri; + if($status->uri || $status->url) { + $url = $status->uri ?? $status->url; if(ends_with($url, '/activity')) { $url = str_replace('/activity', '', $url); } @@ -59,6 +60,11 @@ class StatusController extends Controller return view($template, compact('user', 'status')); } + public function showEmbed(Request $request, $username, int $id) + { + return; + } + public function showObject(Request $request, $username, int $id) { $user = Profile::whereNull('domain')->whereUsername($username)->firstOrFail(); @@ -102,109 +108,6 @@ class StatusController extends Controller public function store(Request $request) { return; - - $this->authCheck(); - $user = Auth::user(); - - $size = Media::whereUserId($user->id)->sum('size') / 1000; - $limit = (int) config('pixelfed.max_account_size'); - if ($size >= $limit) { - return redirect()->back()->with('error', 'You have exceeded your storage limit. Please click here for more info.'); - } - - $this->validate($request, [ - 'photo.*' => 'required|mimetypes:' . config('pixelfed.media_types').'|max:' . config('pixelfed.max_photo_size'), - 'caption' => 'nullable|string|max:'.config('pixelfed.max_caption_length'), - 'cw' => 'nullable|string', - 'filter_class' => 'nullable|alpha_dash|max:30', - 'filter_name' => 'nullable|string', - 'visibility' => 'required|string|min:5|max:10', - ]); - - if (count($request->file('photo')) > config('pixelfed.max_album_length')) { - return redirect()->back()->with('error', 'Too many files, max limit per post: '.config('pixelfed.max_album_length')); - } - $cw = $request->filled('cw') && $request->cw == 'on' ? true : false; - $monthHash = hash('sha1', date('Y').date('m')); - $userHash = hash('sha1', $user->id.(string) $user->created_at); - $profile = $user->profile; - $visibility = $this->validateVisibility($request->visibility); - - $cw = $profile->cw == true ? true : $cw; - $visibility = $profile->unlisted == true && $visibility == 'public' ? 'unlisted' : $visibility; - - if(config('costar.enabled') == true) { - $blockedKeywords = config('costar.keyword.block'); - if($blockedKeywords !== null) { - $keywords = config('costar.keyword.block'); - foreach($keywords as $kw) { - if(Str::contains($request->caption, $kw) == true) { - abort(400, 'Invalid object'); - } - } - } - } - - $status = new Status(); - $status->profile_id = $profile->id; - $status->caption = strip_tags($request->caption); - $status->is_nsfw = $cw; - - // TODO: remove deprecated visibility in favor of scope - $status->visibility = $visibility; - $status->scope = $visibility; - - $status->save(); - - $photos = $request->file('photo'); - $order = 1; - $mimes = []; - $medias = 0; - - foreach ($photos as $k => $v) { - - $allowedMimes = explode(',', config('pixelfed.media_types')); - if(in_array($v->getMimeType(), $allowedMimes) == false) { - continue; - } - $filter_class = $request->input('filter_class'); - $filter_name = $request->input('filter_name'); - - $storagePath = "public/m/{$monthHash}/{$userHash}"; - $path = $v->store($storagePath); - $hash = \hash_file('sha256', $v); - $media = new Media(); - $media->status_id = $status->id; - $media->profile_id = $profile->id; - $media->user_id = $user->id; - $media->media_path = $path; - $media->original_sha256 = $hash; - $media->size = $v->getSize(); - $media->mime = $v->getMimeType(); - - $media->filter_class = in_array($filter_class, Filter::classes()) ? $filter_class : null; - $media->filter_name = in_array($filter_name, Filter::names()) ? $filter_name : null; - $media->order = $order; - $media->save(); - array_push($mimes, $media->mime); - ImageOptimize::dispatch($media); - $order++; - $medias++; - } - - if($medias == 0) { - $status->delete(); - return; - } - $status->type = (new self)::mimeTypeCheck($mimes); - $status->save(); - - Cache::forget('profile:status_count:'.$profile->id); - NewStatusPipeline::dispatch($status); - - // TODO: Send to subscribers - - return redirect($status->url()); } public function delete(Request $request) @@ -238,7 +141,9 @@ class StatusController extends Controller $user = Auth::user(); $profile = $user->profile; - $status = Status::withCount('shares')->findOrFail($request->input('item')); + $status = Status::withCount('shares') + ->whereIn('scope', ['public', 'unlisted']) + ->findOrFail($request->input('item')); $count = $status->shares_count; diff --git a/app/Jobs/FollowPipeline/FollowPipeline.php b/app/Jobs/FollowPipeline/FollowPipeline.php index 17ad47889..57ed1d2e4 100644 --- a/app/Jobs/FollowPipeline/FollowPipeline.php +++ b/app/Jobs/FollowPipeline/FollowPipeline.php @@ -61,8 +61,6 @@ class FollowPipeline implements ShouldQueue $notification->item_type = "App\Profile"; $notification->save(); - Cache::forever('notification.'.$notification->id, $notification); - Cache::forget('feature:discover:people:'.$actor->id); $redis = Redis::connection(); $nkey = config('cache.prefix').':user.'.$target->id.'.notifications'; diff --git a/app/Jobs/LikePipeline/LikePipeline.php b/app/Jobs/LikePipeline/LikePipeline.php index f8aeb5c0a..896827917 100644 --- a/app/Jobs/LikePipeline/LikePipeline.php +++ b/app/Jobs/LikePipeline/LikePipeline.php @@ -2,16 +2,17 @@ namespace App\Jobs\LikePipeline; -use App\Like; -use App\Notification; -use Cache; +use Cache, Log, Redis; +use App\{Like, Notification}; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Log; -use Redis; +use App\Util\ActivityPub\Helpers; +use League\Fractal; +use League\Fractal\Serializer\ArraySerializer; +use App\Transformer\ActivityPub\Verb\Like as LikeTransformer; class LikePipeline implements ShouldQueue { @@ -48,11 +49,15 @@ class LikePipeline implements ShouldQueue $status = $this->like->status; $actor = $this->like->actor; - if (!$status || $status->url !== null) { - // Ignore notifications to remote statuses, or deleted statuses + if (!$status) { + // Ignore notifications to deleted statuses return; } + if($status->url && $actor->domain == null) { + return $this->remoteLikeDeliver(); + } + $exists = Notification::whereProfileId($status->profile_id) ->whereActorId($actor->id) ->whereAction('like') @@ -78,4 +83,20 @@ class LikePipeline implements ShouldQueue } catch (Exception $e) { } } + + public function remoteLikeDeliver() + { + $like = $this->like; + $status = $this->like->status; + $actor = $this->like->actor; + + $fractal = new Fractal\Manager(); + $fractal->setSerializer(new ArraySerializer()); + $resource = new Fractal\Resource\Item($like, new LikeTransformer()); + $activity = $fractal->createData($resource)->toArray(); + + $url = $status->profile->sharedInbox ?? $status->profile->inbox_url; + + Helpers::sendSignedObject($actor, $url, $activity); + } } diff --git a/app/Jobs/MentionPipeline/MentionPipeline.php b/app/Jobs/MentionPipeline/MentionPipeline.php index e75ede04f..ea833345d 100644 --- a/app/Jobs/MentionPipeline/MentionPipeline.php +++ b/app/Jobs/MentionPipeline/MentionPipeline.php @@ -50,7 +50,7 @@ class MentionPipeline implements ShouldQueue $exists = Notification::whereProfileId($target) ->whereActorId($actor->id) - ->whereAction('mention') + ->whereIn('action', ['mention', 'comment']) ->whereItemId($status->id) ->whereItemType('App\Status') ->count(); diff --git a/app/Jobs/SharePipeline/SharePipeline.php b/app/Jobs/SharePipeline/SharePipeline.php index 6d581eb73..b62c51268 100644 --- a/app/Jobs/SharePipeline/SharePipeline.php +++ b/app/Jobs/SharePipeline/SharePipeline.php @@ -2,16 +2,18 @@ namespace App\Jobs\SharePipeline; -use App\Status; -use App\Notification; -use Cache; +use Cache, Log, Redis; +use App\{Status, Notification}; use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; -use Log; -use Redis; +use League\Fractal; +use League\Fractal\Serializer\ArraySerializer; +use App\Transformer\ActivityPub\Verb\Announce; +use GuzzleHttp\{Pool, Client, Promise}; +use App\Util\ActivityPub\HttpSignature; class SharePipeline implements ShouldQueue { @@ -63,6 +65,8 @@ class SharePipeline implements ShouldQueue return true; } + $this->remoteAnnounceDeliver(); + try { $notification = new Notification; $notification->profile_id = $target->id; @@ -74,8 +78,6 @@ class SharePipeline implements ShouldQueue $notification->item_type = "App\Status"; $notification->save(); - Cache::forever('notification.'.$notification->id, $notification); - $redis = Redis::connection(); $key = config('cache.prefix').':user.'.$status->profile_id.'.notifications'; $redis->lpush($key, $notification->id); @@ -83,4 +85,56 @@ class SharePipeline implements ShouldQueue Log::error($e); } } + + public function remoteAnnounceDeliver() + { + $status = $this->status; + $profile = $status->profile; + + $fractal = new Fractal\Manager(); + $fractal->setSerializer(new ArraySerializer()); + $resource = new Fractal\Resource\Item($status, new Announce()); + $activity = $fractal->createData($resource)->toArray(); + + $audience = $status->profile->getAudienceInbox(); + + if(empty($audience) || $status->scope != 'public') { + // Return on profiles with no remote followers + return; + } + + $payload = json_encode($activity); + + $client = new Client([ + 'timeout' => config('federation.activitypub.delivery.timeout') + ]); + + $requests = function($audience) use ($client, $activity, $profile, $payload) { + foreach($audience as $url) { + $headers = HttpSignature::sign($profile, $url, $activity); + 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(); + + } } diff --git a/app/Jobs/StatusPipeline/StatusActivityPubDeliver.php b/app/Jobs/StatusPipeline/StatusActivityPubDeliver.php index a2b6d6f93..ec4243107 100644 --- a/app/Jobs/StatusPipeline/StatusActivityPubDeliver.php +++ b/app/Jobs/StatusPipeline/StatusActivityPubDeliver.php @@ -49,6 +49,7 @@ class StatusActivityPubDeliver implements ShouldQueue public function handle() { $status = $this->status; + $profile = $status->profile; if($status->local == false || $status->url || $status->uri) { return; @@ -56,12 +57,11 @@ class StatusActivityPubDeliver implements ShouldQueue $audience = $status->profile->getAudienceInbox(); - if(empty($audience) || $status->visibility != 'public') { + if(empty($audience) || $status->scope != 'public') { // Return on profiles with no remote followers return; } - $profile = $status->profile; $fractal = new Fractal\Manager(); $fractal->setSerializer(new ArraySerializer()); diff --git a/app/Transformer/ActivityPub/Verb/Announce.php b/app/Transformer/ActivityPub/Verb/Announce.php index b6acb31d1..682885b77 100644 --- a/app/Transformer/ActivityPub/Verb/Announce.php +++ b/app/Transformer/ActivityPub/Verb/Announce.php @@ -11,9 +11,16 @@ class Announce extends Fractal\TransformerAbstract { return [ '@context' => 'https://www.w3.org/ns/activitystreams', + 'id' => $status->permalink(), 'type' => 'Announce', 'actor' => $status->profile->permalink(), - 'object' => $status->parent()->url() + 'to' => ['https://www.w3.org/ns/activitystreams#Public'], + 'cc' => [ + $status->profile->permalink(), + $status->profile->follower_url ?? $status->profile->permalink('/followers') + ], + 'published' => $status->created_at->format(DATE_ISO8601), + 'object' => $status->parent()->url(), ]; } } \ No newline at end of file diff --git a/app/Transformer/ActivityPub/Verb/Like.php b/app/Transformer/ActivityPub/Verb/Like.php index 5662ab758..b6f699158 100644 --- a/app/Transformer/ActivityPub/Verb/Like.php +++ b/app/Transformer/ActivityPub/Verb/Like.php @@ -11,6 +11,7 @@ class Like extends Fractal\TransformerAbstract { return [ '@context' => 'https://www.w3.org/ns/activitystreams', + 'id' => $like->actor->permalink('#likes/'.$like->id), 'type' => 'Like', 'actor' => $like->actor->permalink(), 'object' => $like->status->url() diff --git a/app/Transformer/Api/StatusTransformer.php b/app/Transformer/Api/StatusTransformer.php index 1c033c1f1..8a16e4dfd 100644 --- a/app/Transformer/Api/StatusTransformer.php +++ b/app/Transformer/Api/StatusTransformer.php @@ -34,7 +34,7 @@ class StatusTransformer extends Fractal\TransformerAbstract 'muted' => null, 'sensitive' => (bool) $status->is_nsfw, 'spoiler_text' => $status->cw_summary, - 'visibility' => $status->visibility, + 'visibility' => $status->visibility ?? $status->scope, 'application' => [ 'name' => 'web', 'website' => null diff --git a/app/Util/ActivityPub/Helpers.php b/app/Util/ActivityPub/Helpers.php index f2c1169db..49a881740 100644 --- a/app/Util/ActivityPub/Helpers.php +++ b/app/Util/ActivityPub/Helpers.php @@ -146,9 +146,13 @@ class Helpers { $host = parse_url($valid, PHP_URL_HOST); + if(count(dns_get_record($host, DNS_A | DNS_AAAA)) == 0) { + return false; + } + if(config('costar.enabled') == true) { if( - (config('costar.domain.block') != null && in_array($host, config('costar.domain.block')) == true) || + (config('costar.domain.block') != null && Str::contains($host, config('costar.domain.block')) == true) || (config('costar.actor.block') != null && in_array($url, config('costar.actor.block')) == true) ) { return false; @@ -202,7 +206,7 @@ class Helpers { return self::fetchFromUrl($url); } - public static function statusFirstOrFetch($url, $replyTo = true) + public static function statusFirstOrFetch($url, $replyTo = false) { $url = self::validateUrl($url); if($url == false) { @@ -333,6 +337,11 @@ class Helpers { } } + public static function statusFetch($url) + { + return self::statusFirstOrFetch($url); + } + public static function importNoteAttachment($data, Status $status) { if(self::verifyAttachments($data) == false) { @@ -399,7 +408,10 @@ class Helpers { return; } $domain = parse_url($res['id'], PHP_URL_HOST); - $username = Purify::clean($res['preferredUsername']); + $username = (string) Purify::clean($res['preferredUsername']); + if(empty($username)) { + return; + } $remoteUsername = "@{$username}@{$domain}"; abort_if(!self::validateUrl($res['inbox']), 400); @@ -408,9 +420,9 @@ class Helpers { $profile = Profile::whereRemoteUrl($res['id'])->first(); if(!$profile) { - $profile = new Profile; + $profile = new Profile(); $profile->domain = $domain; - $profile->username = Purify::clean($remoteUsername); + $profile->username = (string) Purify::clean($remoteUsername); $profile->name = Purify::clean($res['name']) ?? 'user'; $profile->bio = Purify::clean($res['summary']); $profile->sharedInbox = isset($res['endpoints']) && isset($res['endpoints']['sharedInbox']) ? $res['endpoints']['sharedInbox'] : null; @@ -428,6 +440,11 @@ class Helpers { return $profile; } + public static function profileFetch($url) + { + return self::profileFirstOrNew($url); + } + public static function sendSignedObject($senderProfile, $url, $body) { abort_if(!self::validateUrl($url), 400); diff --git a/app/Util/ActivityPub/Inbox.php b/app/Util/ActivityPub/Inbox.php index 4731811f9..54aaa4af4 100644 --- a/app/Util/ActivityPub/Inbox.php +++ b/app/Util/ActivityPub/Inbox.php @@ -151,7 +151,7 @@ class Inbox if(Status::whereUrl($url)->exists()) { return; } - Helpers::statusFirstOrFetch($url, false); + Helpers::statusFetch($url); return; } @@ -205,21 +205,27 @@ class Inbox { $actor = $this->actorFirstOrCreate($this->payload['actor']); $activity = $this->payload['object']; + if(!$actor || $actor->domain == null) { return; } + if(Helpers::validateLocalUrl($activity) == false) { return; } - $parent = Helpers::statusFirstOrFetch($activity, true); - if(!$parent) { + + $parent = Helpers::statusFetch($activity); + + if(empty($parent)) { return; } + $status = Status::firstOrCreate([ 'profile_id' => $actor->id, 'reblog_of_id' => $parent->id, - 'type' => 'reply' + 'type' => 'share' ]); + Notification::firstOrCreate([ 'profile_id' => $parent->profile->id, 'actor_id' => $actor->id, @@ -229,6 +235,7 @@ class Inbox 'item_id' => $parent->id, 'item_type' => 'App\Status' ]); + $parent->reblogs_count = $parent->shares()->count(); $parent->save(); } @@ -267,8 +274,10 @@ class Inbox if(is_string($obj) && Helpers::validateUrl($obj)) { // actor object detected // todo delete actor + return; } else if (Helpers::validateUrl($obj['id']) && Helpers::validateObject($obj) && $obj['type'] == 'Tombstone') { // todo delete status or object + return; } } @@ -316,6 +325,21 @@ class Inbox break; case 'Announce': + $obj = $obj['object']; + abort_if(!Helpers::validateLocalUrl($obj), 400); + $status = Helpers::statusFetch($obj); + if(!$status) { + return; + } + Status::whereProfileId($profile->id) + ->whereReblogOfId($status->id) + ->forceDelete(); + Notification::whereProfileId($status->profile->id) + ->whereActorId($profile->id) + ->whereAction('share') + ->whereItemId($status->reblog_of_id) + ->whereItemType('App\Status') + ->forceDelete(); break; case 'Block': @@ -347,6 +371,6 @@ class Inbox ->forceDelete(); break; } - + return; } } diff --git a/app/Util/Lexer/Autolink.php b/app/Util/Lexer/Autolink.php index 4ec8c2ef7..4aa38d7f1 100755 --- a/app/Util/Lexer/Autolink.php +++ b/app/Util/Lexer/Autolink.php @@ -718,7 +718,7 @@ class Autolink extends Regex // Replace the username $linkText = Str::startsWith($screen_name, '@') ? $screen_name : '@'.$screen_name; $class = $this->class_user; - $url = $this->url_base_user.$screen_name;; + $url = $this->url_base_user . $screen_name; } if (!empty($class)) { $attributes['class'] = $class; diff --git a/app/Util/RateLimit/User.php b/app/Util/RateLimit/User.php index 75e4b1c6e..c93aa6c4f 100644 --- a/app/Util/RateLimit/User.php +++ b/app/Util/RateLimit/User.php @@ -48,4 +48,9 @@ trait User { { return 500; } + + public function getMaxInstanceBansPerDayAttribute() + { + return 100; + } } \ No newline at end of file diff --git a/app/Util/Webfinger/Webfinger.php b/app/Util/Webfinger/Webfinger.php index e8f10c31c..879103332 100644 --- a/app/Util/Webfinger/Webfinger.php +++ b/app/Util/Webfinger/Webfinger.php @@ -4,74 +4,43 @@ namespace App\Util\Webfinger; class Webfinger { - public $user; - public $subject; - public $aliases; - public $links; + protected $user; + protected $subject; + protected $aliases; + protected $links; - public function __construct($user) - { - $this->user = $user; - $this->subject = ''; - $this->aliases = []; - $this->links = []; - } + public function __construct($user) + { + $this->subject = 'acct:'.$user->username.'@'.parse_url(config('app.url'), PHP_URL_HOST); + $this->aliases = [ + $user->url(), + $user->permalink(), + ]; + $this->links = [ + [ + 'rel' => 'http://webfinger.net/rel/profile-page', + 'type' => 'text/html', + 'href' => $user->url(), + ], + [ + 'rel' => 'http://schemas.google.com/g/2010#updates-from', + 'type' => 'application/atom+xml', + 'href' => $user->permalink('.atom'), + ], + [ + 'rel' => 'self', + 'type' => 'application/activity+json', + 'href' => $user->permalink(), + ], + ]; + } - public function setSubject() - { - $host = parse_url(config('app.url'), PHP_URL_HOST); - $username = $this->user->username; - - $this->subject = 'acct:'.$username.'@'.$host; - - return $this; - } - - public function generateAliases() - { - $this->aliases = [ - $this->user->url(), - $this->user->permalink(), - ]; - - return $this; - } - - public function generateLinks() - { - $user = $this->user; - - $this->links = [ - [ - 'rel' => 'http://webfinger.net/rel/profile-page', - 'type' => 'text/html', - 'href' => $user->url(), - ], - [ - 'rel' => 'http://schemas.google.com/g/2010#updates-from', - 'type' => 'application/atom+xml', - 'href' => $user->permalink('.atom'), - ], - [ - 'rel' => 'self', - 'type' => 'application/activity+json', - 'href' => $user->permalink(), - ], - ]; - - return $this; - } - - public function generate() - { - $this->setSubject(); - $this->generateAliases(); - $this->generateLinks(); - - return [ - 'subject' => $this->subject, - 'aliases' => $this->aliases, - 'links' => $this->links, - ]; - } + public function generate() + { + return [ + 'subject' => $this->subject, + 'aliases' => $this->aliases, + 'links' => $this->links, + ]; + } } diff --git a/config/instance.php b/config/instance.php index 3842de358..6fc04c902 100644 --- a/config/instance.php +++ b/config/instance.php @@ -7,4 +7,9 @@ return [ 'enabled' => env('INSTANCE_CONTACT_FORM', false), 'max_per_day' => env('INSTANCE_CONTACT_MAX_PER_DAY', 1), ], + + 'announcement' => [ + 'enabled' => env('INSTANCE_ANNOUNCEMENT_ENABLED', true), + 'message' => env('INSTANCE_ANNOUNCEMENT_MESSAGE', 'Example announcement message.
Something else here') + ] ]; \ No newline at end of file diff --git a/public/js/profile.js b/public/js/profile.js index 338f6bd7d..0ddcd0afe 100644 --- a/public/js/profile.js +++ b/public/js/profile.js @@ -1 +1 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[11],{"1uk1":function(t,e,s){var i=s("4LQO");"string"==typeof i&&(i=[[t.i,i,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};s("aET+")(i,o);i.locals&&(t.exports=i.locals)},"2Jpm":function(t,e,s){"use strict";s.r(e);var i={props:["status"]},o=s("KHd+"),a=Object(o.a)(i,function(){var t=this,e=t.$createElement,s=t._self._c||e;return 1==t.status.sensitive?s("div",[s("details",{staticClass:"details-animated"},[s("summary",[s("p",{staticClass:"mb-0 lead font-weight-bold"},[t._v(t._s(t.status.spoiler_text?t.status.spoiler_text:"CW / NSFW / Hidden Media"))]),t._v(" "),s("p",{staticClass:"font-weight-light"},[t._v("(click to show)")])]),t._v(" "),s("div",{staticClass:"embed-responsive embed-responsive-16by9"},[s("video",{staticClass:"video",attrs:{preload:"none",controls:"",loop:"",poster:t.status.media_attachments[0].preview_url}},[s("source",{attrs:{src:t.status.media_attachments[0].url,type:t.status.media_attachments[0].mime}})])])])]):s("div",{staticClass:"embed-responsive embed-responsive-16by9"},[s("video",{staticClass:"video",attrs:{preload:"auto",controls:"",loop:"",poster:t.status.media_attachments[0].preview_url}},[s("source",{attrs:{src:t.status.media_attachments[0].url,type:t.status.media_attachments[0].mime}})])])},[],!1,null,null,null);e.default=a.exports},"2wtg":function(t,e,s){Vue.component("photo-presenter",s("d+I4").default),Vue.component("video-presenter",s("2Jpm").default),Vue.component("photo-album-presenter",s("Mrqh").default),Vue.component("video-album-presenter",s("9wGH").default),Vue.component("mixed-album-presenter",s("exej").default),Vue.component("post-menu",s("yric").default),Vue.component("profile",s("EHjT").default)},4:function(t,e,s){t.exports=s("2wtg")},"4LQO":function(t,e,s){(t.exports=s("I1BE")(!1)).push([t.i,"\n.card-img-top[data-v-6f591d06] {\n border-top-left-radius: 0 !important;\n border-top-right-radius: 0 !important;\n}\n",""])},"7VQl":function(t,e,s){"use strict";var i=s("DFk1");s.n(i).a},"8V6C":function(t,e,s){"use strict";var i=s("1uk1");s.n(i).a},"9tPo":function(t,e){t.exports=function(t){var e="undefined"!=typeof window&&window.location;if(!e)throw new Error("fixUrls requires window.location");if(!t||"string"!=typeof t)return t;var s=e.protocol+"//"+e.host,i=s+e.pathname.replace(/\/[^\/]*$/,"/");return t.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi,function(t,e){var o,a=e.trim().replace(/^"(.*)"$/,function(t,e){return e}).replace(/^'(.*)'$/,function(t,e){return e});return/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(a)?t:(o=0===a.indexOf("//")?a:0===a.indexOf("/")?s+a:i+a.replace(/^\.\//,""),"url("+JSON.stringify(o)+")")})}},"9wGH":function(t,e,s){"use strict";s.r(e);var i={props:["status"]},o=s("KHd+"),a=Object(o.a)(i,function(){var t=this,e=t.$createElement,s=t._self._c||e;return 1==t.status.sensitive?s("div",[s("details",{staticClass:"details-animated"},[s("summary",[s("p",{staticClass:"mb-0 lead font-weight-bold"},[t._v(t._s(t.status.spoiler_text?t.status.spoiler_text:"CW / NSFW / Hidden Media"))]),t._v(" "),s("p",{staticClass:"font-weight-light"},[t._v("(click to show)")])]),t._v(" "),s("b-carousel",{staticStyle:{"text-shadow":"1px 1px 2px #333","background-color":"#000"},attrs:{id:t.status.id+"-carousel",controls:"","img-blank":"",background:"#ffffff",interval:0}},t._l(t.status.media_attachments,function(t,e){return s("b-carousel-slide",{key:t.id+"-media"},[s("video",{staticClass:"embed-responsive-item",attrs:{slot:"img",preload:"none",controls:"",loop:"",alt:t.description,width:"100%",height:"100%",poster:t.preview_url},slot:"img"},[s("source",{attrs:{src:t.url,type:t.mime}})])])}),1)],1)]):s("div",[s("b-carousel",{staticStyle:{"text-shadow":"1px 1px 2px #333","background-color":"#000"},attrs:{id:t.status.id+"-carousel",controls:"","img-blank":"",background:"#ffffff",interval:0}},t._l(t.status.media_attachments,function(t,e){return s("b-carousel-slide",{key:t.id+"-media"},[s("video",{staticClass:"embed-responsive-item",attrs:{slot:"img",preload:"none",controls:"",loop:"",alt:t.description,width:"100%",height:"100%",poster:t.preview_url},slot:"img"},[s("source",{attrs:{src:t.url,type:t.mime}})])])}),1)],1)},[],!1,null,null,null);e.default=a.exports},DFk1:function(t,e,s){var i=s("TvDj");"string"==typeof i&&(i=[[t.i,i,""]]);var o={hmr:!0,transform:void 0,insertInto:void 0};s("aET+")(i,o);i.locals&&(t.exports=i.locals)},EHjT:function(t,e,s){"use strict";s.r(e);function i(t){return function(t){if(Array.isArray(t)){for(var e=0,s=new Array(t.length);e2&&($("nav.navbar").hide(),$("body").prepend('
'+this.profileUsername+'
'));var t=new URLSearchParams(window.location.search);t.has("ui")&&"moment"==t.get("ui")&&"moment"!=this.profileLayout&&(this.profileLayout="moment"),t.has("ui")&&"metro"==t.get("ui")&&"metro"!=this.profileLayout&&(this.profileLayout="metro")},mounted:function(){},updated:function(){},methods:{fetchProfile:function(){var t=this;axios.get("/api/v1/accounts/"+this.profileId).then(function(e){t.profile=e.data}),1==document.querySelectorAll("body")[0].classList.contains("loggedIn")&&axios.get("/api/v1/accounts/verify_credentials").then(function(e){t.user=e.data});var e="/api/v1/accounts/"+this.profileId+"/statuses";axios.get(e,{params:{only_media:!0,min_id:1}}).then(function(e){var s=e.data.filter(function(t){return t.media_attachments.length>0}),o=s.map(function(t){return t.id});t.ids=o,t.min_id=Math.max.apply(Math,i(o)),t.max_id=Math.min.apply(Math,i(o)),t.modalStatus=_.first(e.data),t.timeline=s,t.ownerCheck(),t.loading=!1}).catch(function(t){swal("Oops, something went wrong","Please release the page.","error")})},ownerCheck:function(){this.owner=this.profile.id===this.user.id},infiniteTimeline:function(t){var e=this;if(this.loading||this.timeline.length<9)t.complete();else{var s="/api/v1/accounts/"+this.profileId+"/statuses";axios.get(s,{params:{only_media:!0,max_id:this.max_id}}).then(function(s){if(s.data.length&&0==e.loading){var o=s.data,a=e;o.forEach(function(t){-1==a.ids.indexOf(t.id)&&(a.timeline.push(t),a.ids.push(t.id))}),e.min_id=Math.max.apply(Math,i(e.ids)),e.max_id=Math.min.apply(Math,i(e.ids)),t.loaded(),e.loading=!1}else t.complete()})}},previewUrl:function(t){return t.sensitive?"/storage/no-preview.png?v="+(new Date).getTime():t.media_attachments[0].preview_url},previewBackground:function(t){return"background-image: url("+this.previewUrl(t)+");"},switchMode:function(t){this.mode=_.indexOf(this.modes,t)?t:"grid","masonry"==this.mode&&$(".masonry").masonry({columnWidth:200,itemSelector:".masonry-item"})},reportProfile:function(){var t=this.profile.id;window.location.href="/i/report?type=user&id="+t},reportUrl:function(t){return"/i/report?type="+(t.in_reply_to?"comment":"post")+"&id="+t.id},commentFocus:function(t,e){var s=event.target.parentElement.parentElement.parentElement,i=s.getElementsByClassName("comments")[0];0==i.children.length&&(i.classList.add("mb-2"),this.fetchStatusComments(t,s));var o=s.querySelectorAll(".card-footer")[0],a=s.querySelectorAll(".status-reply-input")[0];1==o.classList.contains("d-none")?(o.classList.remove("d-none"),a.focus()):(o.classList.add("d-none"),a.blur())},likeStatus:function(t,e){0!=$("body").hasClass("loggedIn")&&axios.post("/i/like",{item:t.id}).then(function(e){t.favourites_count=e.data.count,1==t.favourited?t.favourited=!1:t.favourited=!0}).catch(function(t){swal("Error","Something went wrong, please try again later.","error")})},shareStatus:function(t,e){0!=$("body").hasClass("loggedIn")&&axios.post("/i/share",{item:t.id}).then(function(e){t.reblogs_count=e.data.count,1==t.reblogged?t.reblogged=!1:t.reblogged=!0}).catch(function(t){swal("Error","Something went wrong, please try again later.","error")})},timestampFormat:function(t){var e=new Date(t);return e.toDateString()+" "+e.toLocaleTimeString()},editUrl:function(t){return t.url+"/edit"},redirect:function(t){window.location.href=t},replyUrl:function(t){return"/p/"+this.profile.username+"/"+(t.account.id==this.profile.id?t.id:t.in_reply_to_id)},mentionUrl:function(t){return"/p/"+t.account.username+"/"+t.id},statusOwner:function(t){return t.account.id==this.profile.id},fetchStatusComments:function(t,e){axios.get("/api/v2/status/"+t.id+"/replies").then(function(t){var s=e.querySelectorAll(".comments")[0];t.data.forEach(function(t,e){var i=document.createElement("a");i.classList.add("font-weight-bold"),i.classList.add("text-dark"),i.classList.add("mr-2"),i.setAttribute("href",t.account.url),i.textContent=t.account.username;var o=document.createElement("span");o.innerHTML=t.content;var a=document.createElement("p");a.classList.add("read-more"),a.classList.add("mb-0"),a.appendChild(i),a.appendChild(o),s.appendChild(a)})}).catch(function(t){})},fetchRelationships:function(){var t=this;0!=document.querySelectorAll("body")[0].classList.contains("loggedIn")&&axios.get("/api/v1/accounts/relationships",{params:{"id[]":this.profileId}}).then(function(e){e.data.length&&(t.relationship=e.data[0],1==e.data[0].blocking&&(t.warning=!0))})},muteProfile:function(){var t=this;arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(0!=$("body").hasClass("loggedIn")){var e=this.profileId;axios.post("/i/mute",{type:"user",item:e}).then(function(e){t.fetchRelationships(),t.$refs.visitorContextMenu.hide(),swal("Success","You have successfully muted "+t.profile.acct,"success")}).catch(function(t){swal("Error","Something went wrong. Please try again later.","error")})}},unmuteProfile:function(){var t=this;arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(0!=$("body").hasClass("loggedIn")){var e=this.profileId;axios.post("/i/unmute",{type:"user",item:e}).then(function(e){t.fetchRelationships(),t.$refs.visitorContextMenu.hide(),swal("Success","You have successfully unmuted "+t.profile.acct,"success")}).catch(function(t){swal("Error","Something went wrong. Please try again later.","error")})}},blockProfile:function(){var t=this;arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(0!=$("body").hasClass("loggedIn")){var e=this.profileId;axios.post("/i/block",{type:"user",item:e}).then(function(e){t.warning=!0,t.fetchRelationships(),t.$refs.visitorContextMenu.hide(),swal("Success","You have successfully blocked "+t.profile.acct,"success")}).catch(function(t){swal("Error","Something went wrong. Please try again later.","error")})}},unblockProfile:function(){var t=this;arguments.length>0&&void 0!==arguments[0]&&arguments[0];if(0!=$("body").hasClass("loggedIn")){var e=this.profileId;axios.post("/i/unblock",{type:"user",item:e}).then(function(e){t.fetchRelationships(),t.$refs.visitorContextMenu.hide(),swal("Success","You have successfully unblocked "+t.profile.acct,"success")}).catch(function(t){swal("Error","Something went wrong. Please try again later.","error")})}},deletePost:function(t,e){var s=this;0!=$("body").hasClass("loggedIn")&&t.account.id===this.profile.id&&axios.post("/i/delete",{type:"status",item:t.id}).then(function(t){s.timeline.splice(e,1),swal("Success","You have successfully deleted this post","success")}).catch(function(t){swal("Error","Something went wrong. Please try again later.","error")})},commentSubmit:function(t,e){var s=this;if(0!=$("body").hasClass("loggedIn")){var i=t.id,o=e.target,a=$(o).find('input[name="comment"]'),n=a.val(),r=o.parentElement.parentElement.getElementsByClassName("comments")[0];axios.post("/i/comment",{item:i,comment:n}).then(function(t){a.val(""),a.blur();var e=document.createElement("a");e.classList.add("font-weight-bold"),e.classList.add("text-dark"),e.classList.add("mr-2"),e.setAttribute("href",s.user.url),e.textContent=s.user.username;var i=document.createElement("span");i.innerHTML=n;var o=document.createElement("p");o.classList.add("read-more"),o.classList.add("mb-0"),o.appendChild(e),o.appendChild(i),r.insertBefore(o,r.firstChild)})}},statusModal:function(t){this.modalStatus=t,this.$refs.statusModalRef.show()},masonryOrientation:function(t){var e=t.media_attachments[0].orientation;return e||(e="square"),e},followProfile:function(){var t=this;0!=$("body").hasClass("loggedIn")&&axios.post("/i/follow",{item:this.profileId}).then(function(e){t.$refs.visitorContextMenu.hide(),t.relationship.following?(t.profile.followers_count--,1==t.profile.locked&&(window.location.href="/")):t.profile.followers_count++,t.relationship.following=!t.relationship.following}).catch(function(t){t.response.data.message&&swal("Error",t.response.data.message,"error")})},followingModal:function(){var t=this;0!=$("body").hasClass("loggedIn")?0!=this.profileSettings.following.list&&(this.following.length>0?this.$refs.followingModal.show():(axios.get("/api/v1/accounts/"+this.profile.id+"/following",{params:{page:this.followingCursor}}).then(function(e){t.following=e.data,t.followingCursor++,e.data.length<10&&(t.followingMore=!1)}),this.$refs.followingModal.show())):window.location.href=encodeURI("/login?next=/"+this.profile.username+"/")},followersModal:function(){var t=this;0!=$("body").hasClass("loggedIn")?0!=this.profileSettings.followers.list&&(this.followers.length>0?this.$refs.followerModal.show():(axios.get("/api/v1/accounts/"+this.profile.id+"/followers",{params:{page:this.followerCursor}}).then(function(e){t.followers=e.data,t.followerCursor++,e.data.length<10&&(t.followerMore=!1)}),this.$refs.followerModal.show())):window.location.href=encodeURI("/login?next=/"+this.profile.username+"/")},followingLoadMore:function(){var t=this;0!=$("body").hasClass("loggedIn")?axios.get("/api/v1/accounts/"+this.profile.id+"/following",{params:{page:this.followingCursor}}).then(function(e){var s;e.data.length>0&&((s=t.following).push.apply(s,i(e.data)),t.followingCursor++);e.data.length<10&&(t.followingMore=!1)}):window.location.href=encodeURI("/login?next=/"+this.profile.username+"/")},followersLoadMore:function(){var t=this;0!=$("body").hasClass("loggedIn")&&axios.get("/api/v1/accounts/"+this.profile.id+"/followers",{params:{page:this.followerCursor}}).then(function(e){var s;e.data.length>0&&((s=t.followers).push.apply(s,i(e.data)),t.followerCursor++);e.data.length<10&&(t.followerMore=!1)})},visitorMenu:function(){0!=$("body").hasClass("loggedIn")&&this.$refs.visitorContextMenu.show()},followModalAction:function(t,e){var s=this,i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"following";axios.post("/i/follow",{item:t}).then(function(t){"following"==i&&(s.following.splice(e,1),s.profile.following_count--)}).catch(function(t){t.response.data.message&&swal("Error",t.response.data.message,"error")})},momentBackground:function(){var t="w-100 h-100 mt-n3 ";return this.profile.header_bg?t+="default"==this.profile.header_bg?"bg-pixelfed":"bg-moment-"+this.profile.header_bg:t+="bg-pixelfed",t}}},a=(s("7VQl"),s("KHd+")),n=Object(a.a)(o,function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"w-100 h-100"},[t.relationship&&t.relationship.blocking&&t.warning?s("div",{staticClass:"bg-white pt-3 border-bottom"},[s("div",{staticClass:"container"},[s("p",{staticClass:"text-center font-weight-bold"},[t._v("You are blocking this account")]),t._v(" "),s("p",{staticClass:"text-center font-weight-bold"},[t._v("Click "),s("a",{staticClass:"cursor-pointer",attrs:{href:"#"},on:{click:function(e){e.preventDefault(),t.warning=!1}}},[t._v("here")]),t._v(" to view profile")])])]):t._e(),t._v(" "),t.loading?s("div",{staticClass:"d-flex justify-content-center align-items-center",staticStyle:{height:"80vh"}},[s("img",{attrs:{src:"/img/pixelfed-icon-grey.svg"}})]):t._e(),t._v(" "),t.loading||t.warning?t._e():s("div",["metro"==t.profileLayout?s("div",[s("div",{staticClass:"bg-white py-5 border-bottom"},[s("div",{staticClass:"container"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12 col-md-4 d-flex"},[s("div",{staticClass:"profile-avatar mx-md-auto"},[s("div",{staticClass:"d-block d-md-none"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-5"},[s("img",{staticClass:"rounded-circle box-shadow mr-5",attrs:{src:t.profile.avatar,width:"77px",height:"77px"}})]),t._v(" "),s("div",{staticClass:"col-7 pl-2"},[s("p",{staticClass:"align-middle"},[s("span",{staticClass:"font-weight-ultralight h3 mb-0"},[t._v(t._s(t.profile.username))]),t._v(" "),!t.loading&&t.profile.id!=t.user.id&&t.user.hasOwnProperty("id")?s("span",{staticClass:"float-right mb-0"},[s("a",{staticClass:"fas fa-cog fa-lg text-muted text-decoration-none",attrs:{href:"#"},on:{click:function(e){return e.preventDefault(),t.visitorMenu(e)}}})]):t._e()]),t._v(" "),!t.loading&&t.profile.id==t.user.id&&t.user.hasOwnProperty("id")?s("p",[s("a",{staticClass:"btn btn-outline-dark py-0 px-4 mt-3",attrs:{href:"/settings/home"}},[t._v("Edit Profile")])]):t._e(),t._v(" "),t.profile.id!=t.user.id&&t.user.hasOwnProperty("id")?s("div",[1==t.relationship.following?s("p",{staticClass:"mt-3 mb-0"},[s("button",{staticClass:"btn btn-outline-dark font-weight-bold px-4 py-0",attrs:{type:"button","data-toggle":"tooltip",title:"Unfollow"},on:{click:function(e){return t.followProfile()}}},[t._v("Unfollow")])]):t._e(),t._v(" "),t.relationship.following?t._e():s("p",{staticClass:"mt-3 mb-0"},[s("button",{staticClass:"btn btn-outline-dark font-weight-bold px-4 py-0",attrs:{type:"button","data-toggle":"tooltip",title:"Follow"},on:{click:function(e){return t.followProfile()}}},[t._v("Follow")])])]):t._e()])])]),t._v(" "),s("div",{staticClass:"d-none d-md-block"},[s("img",{staticClass:"rounded-circle box-shadow",attrs:{src:t.profile.avatar,width:"172px",height:"172px"}})])])]),t._v(" "),s("div",{staticClass:"col-12 col-md-8 d-flex align-items-center"},[s("div",{staticClass:"profile-details"},[s("div",{staticClass:"d-none d-md-flex username-bar pb-2 align-items-center"},[s("span",{staticClass:"font-weight-ultralight h3"},[t._v(t._s(t.profile.username))]),t._v(" "),t.profile.is_admin?s("span",{staticClass:"pl-4"},[s("span",{staticClass:"btn btn-outline-secondary font-weight-bold py-0"},[t._v("ADMIN")])]):t._e(),t._v(" "),s("span",{staticClass:"pl-4"},[s("a",{staticClass:"fas fa-rss fa-lg text-muted text-decoration-none",attrs:{href:"/users/"+t.profile.username+".atom"}})]),t._v(" "),t.owner&&t.user.hasOwnProperty("id")?s("span",{staticClass:"pl-4"},[s("a",{staticClass:"fas fa-cog fa-lg text-muted text-decoration-none",attrs:{href:"/settings/home"}})]):t._e(),t._v(" "),!t.owner&&t.user.hasOwnProperty("id")?s("span",{staticClass:"pl-4"},[s("a",{staticClass:"fas fa-cog fa-lg text-muted text-decoration-none",attrs:{href:"#"},on:{click:function(e){return e.preventDefault(),t.visitorMenu(e)}}})]):t._e(),t._v(" "),t.profile.id!=t.user.id&&t.user.hasOwnProperty("id")?s("span",[1==t.relationship.following?s("span",{staticClass:"pl-4"},[s("button",{staticClass:"btn btn-outline-secondary font-weight-bold btn-sm",attrs:{type:"button","data-toggle":"tooltip",title:"Unfollow"},on:{click:function(e){return t.followProfile()}}},[s("i",{staticClass:"fas fa-user-minus"})])]):t._e(),t._v(" "),t.relationship.following?t._e():s("span",{staticClass:"pl-4"},[s("button",{staticClass:"btn btn-primary font-weight-bold btn-sm",attrs:{type:"button","data-toggle":"tooltip",title:"Follow"},on:{click:function(e){return t.followProfile()}}},[s("i",{staticClass:"fas fa-user-plus"})])])]):t._e()]),t._v(" "),s("div",{staticClass:"d-none d-md-inline-flex profile-stats pb-3 lead"},[s("div",{staticClass:"font-weight-light pr-5"},[s("a",{staticClass:"text-dark",attrs:{href:t.profile.url}},[s("span",{staticClass:"font-weight-bold"},[t._v(t._s(t.profile.statuses_count))]),t._v("\n\t\t\t\t\t\t\t\t\t\t\tPosts\n\t\t\t\t\t\t\t\t\t\t")])]),t._v(" "),t.profileSettings.followers.count?s("div",{staticClass:"font-weight-light pr-5"},[s("a",{staticClass:"text-dark cursor-pointer",on:{click:function(e){return t.followersModal()}}},[s("span",{staticClass:"font-weight-bold"},[t._v(t._s(t.profile.followers_count))]),t._v("\n\t\t\t\t\t\t\t\t\t\t\tFollowers\n\t\t\t\t\t\t\t\t\t\t")])]):t._e(),t._v(" "),t.profileSettings.following.count?s("div",{staticClass:"font-weight-light"},[s("a",{staticClass:"text-dark cursor-pointer",on:{click:function(e){return t.followingModal()}}},[s("span",{staticClass:"font-weight-bold"},[t._v(t._s(t.profile.following_count))]),t._v("\n\t\t\t\t\t\t\t\t\t\t\tFollowing\n\t\t\t\t\t\t\t\t\t\t")])]):t._e()]),t._v(" "),s("p",{staticClass:"lead mb-0 d-flex align-items-center pt-3"},[s("span",{staticClass:"font-weight-bold pr-3"},[t._v(t._s(t.profile.display_name))])]),t._v(" "),t.profile.note?s("div",{staticClass:"mb-0 lead",domProps:{innerHTML:t._s(t.profile.note)}}):t._e(),t._v(" "),t.profile.website?s("p",{staticClass:"mb-0"},[s("a",{staticClass:"font-weight-bold",attrs:{href:t.profile.website,rel:"me external nofollow noopener",target:"_blank"}},[t._v(t._s(t.profile.website))])]):t._e()])])])])]),t._v(" "),s("div",{staticClass:"d-block d-md-none bg-white my-0 py-2 border-bottom"},[s("ul",{staticClass:"nav d-flex justify-content-center"},[s("li",{staticClass:"nav-item"},[s("div",{staticClass:"font-weight-light"},[s("span",{staticClass:"text-dark text-center"},[s("p",{staticClass:"font-weight-bold mb-0"},[t._v(t._s(t.profile.statuses_count))]),t._v(" "),s("p",{staticClass:"text-muted mb-0"},[t._v("Posts")])])])]),t._v(" "),s("li",{staticClass:"nav-item px-5"},[t.profileSettings.followers.count?s("div",{staticClass:"font-weight-light"},[s("a",{staticClass:"text-dark cursor-pointer text-center",on:{click:function(e){return t.followersModal()}}},[s("p",{staticClass:"font-weight-bold mb-0"},[t._v(t._s(t.profile.followers_count))]),t._v(" "),s("p",{staticClass:"text-muted mb-0"},[t._v("Followers")])])]):t._e()]),t._v(" "),s("li",{staticClass:"nav-item"},[t.profileSettings.following.count?s("div",{staticClass:"font-weight-light"},[s("a",{staticClass:"text-dark cursor-pointer text-center",on:{click:function(e){return t.followingModal()}}},[s("p",{staticClass:"font-weight-bold mb-0"},[t._v(t._s(t.profile.following_count))]),t._v(" "),s("p",{staticClass:"text-muted mb-0"},[t._v("Following")])])]):t._e()])])]),t._v(" "),s("div",{staticClass:"bg-white"},[s("ul",{staticClass:"nav nav-topbar d-flex justify-content-center border-0"},[s("li",{staticClass:"nav-item"},[s("a",{class:"grid"==this.mode?"nav-link font-weight-bold text-uppercase text-primary":"nav-link font-weight-bold text-uppercase",attrs:{href:"#"},on:{click:function(e){return e.preventDefault(),t.switchMode("grid")}}},[s("i",{staticClass:"fas fa-th fa-lg"})])]),t._v(" "),s("li",{staticClass:"nav-item px-3"},[s("a",{class:"list"==this.mode?"nav-link font-weight-bold text-uppercase text-primary":"nav-link font-weight-bold text-uppercase",attrs:{href:"#"},on:{click:function(e){return e.preventDefault(),t.switchMode("list")}}},[s("i",{staticClass:"fas fa-th-list fa-lg"})])]),t._v(" "),t.owner?s("li",{staticClass:"nav-item"},[s("a",{staticClass:"nav-link font-weight-bold text-uppercase",attrs:{href:t.profile.url+"/saved"}},[t._v("Saved")])]):t._e()])]),t._v(" "),s("div",{staticClass:"container"},[s("div",{staticClass:"profile-timeline mt-md-4"},["grid"==t.mode?s("div",{staticClass:"row"},t._l(t.timeline,function(e,i){return s("div",{staticClass:"col-4 p-0 p-sm-2 p-md-3 p-xs-1"},[s("a",{staticClass:"card info-overlay card-md-border-0",attrs:{href:e.url}},[s("div",{staticClass:"square"},["photo:album"==e.pf_type?s("span",{staticClass:"float-right mr-3 post-icon"},[s("i",{staticClass:"fas fa-images fa-2x"})]):t._e(),t._v(" "),"video"==e.pf_type?s("span",{staticClass:"float-right mr-3 post-icon"},[s("i",{staticClass:"fas fa-video fa-2x"})]):t._e(),t._v(" "),"video:album"==e.pf_type?s("span",{staticClass:"float-right mr-3 post-icon"},[s("i",{staticClass:"fas fa-film fa-2x"})]):t._e(),t._v(" "),s("div",{staticClass:"square-content",style:t.previewBackground(e)}),t._v(" "),s("div",{staticClass:"info-overlay-text"},[s("h5",{staticClass:"text-white m-auto font-weight-bold"},[s("span",[s("span",{staticClass:"far fa-heart fa-lg p-2 d-flex-inline"}),t._v(" "),s("span",{staticClass:"d-flex-inline"},[t._v(t._s(e.favourites_count))])]),t._v(" "),s("span",[s("span",{staticClass:"fas fa-retweet fa-lg p-2 d-flex-inline"}),t._v(" "),s("span",{staticClass:"d-flex-inline"},[t._v(t._s(e.reblogs_count))])])])])])])])}),0):t._e(),t._v(" "),"list"==t.mode?s("div",{staticClass:"row"},[s("div",{staticClass:"col-md-8 col-lg-8 offset-md-2 px-0 mb-3 timeline"},t._l(t.timeline,function(e,i){return s("div",{key:e.id,staticClass:"card status-card card-md-rounded-0 my-sm-2 my-md-3 my-lg-4",attrs:{"data-status-id":e.id}},[s("div",{staticClass:"card-header d-inline-flex align-items-center bg-white"},[s("img",{staticStyle:{"border-radius":"32px"},attrs:{src:e.account.avatar,width:"32px",height:"32px"}}),t._v(" "),s("a",{staticClass:"username font-weight-bold pl-2 text-dark",attrs:{href:e.account.url}},[t._v("\n\t\t\t\t\t\t\t\t\t\t"+t._s(e.account.username)+"\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),t.user.hasOwnProperty("id")?s("div",{staticClass:"text-right",staticStyle:{"flex-grow":"1"}},[s("div",{staticClass:"dropdown"},[t._m(0,!0),t._v(" "),s("div",{staticClass:"dropdown-menu dropdown-menu-right",attrs:{"aria-labelledby":"dropdownMenuButton"}},[s("a",{staticClass:"dropdown-item font-weight-bold",attrs:{href:e.url}},[t._v("Go to post")]),t._v(" "),e.account.id!=t.user.id?s("span",[s("a",{staticClass:"dropdown-item font-weight-bold",attrs:{href:t.reportUrl(e)}},[t._v("Report")]),t._v(" "),s("a",{staticClass:"dropdown-item font-weight-bold",on:{click:function(s){return t.muteProfile(e)}}},[t._v("Mute Profile")]),t._v(" "),s("a",{staticClass:"dropdown-item font-weight-bold",on:{click:function(s){return t.blockProfile(e)}}},[t._v("Block Profile")])]):t._e(),t._v(" "),e.account.id==t.user.id||1==t.user.is_admin?s("span",[s("a",{staticClass:"dropdown-item font-weight-bold",attrs:{href:t.editUrl(e)}},[t._v("Edit")]),t._v(" "),s("a",{staticClass:"dropdown-item font-weight-bold text-danger",on:{click:function(s){return t.deletePost(e)}}},[t._v("Delete")])]):t._e()])])]):t._e()]),t._v(" "),s("div",{staticClass:"postPresenterContainer"},["photo"===e.pf_type?s("div",{staticClass:"w-100"},[s("photo-presenter",{attrs:{status:e}})],1):"video"===e.pf_type?s("div",{staticClass:"w-100"},[s("video-presenter",{attrs:{status:e}})],1):"photo:album"===e.pf_type?s("div",{staticClass:"w-100"},[s("photo-album-presenter",{attrs:{status:e}})],1):"video:album"===e.pf_type?s("div",{staticClass:"w-100"},[s("video-album-presenter",{attrs:{status:e}})],1):"photo:video:album"===e.pf_type?s("div",{staticClass:"w-100"},[s("mixed-album-presenter",{attrs:{status:e}})],1):s("div",{staticClass:"w-100"},[s("p",{staticClass:"text-center p-0 font-weight-bold text-white"},[t._v("Error: Problem rendering preview.")])])]),t._v(" "),s("div",{staticClass:"card-body"},[t.user.hasOwnProperty("id")?s("div",{staticClass:"reactions my-1"},[s("h3",{class:[e.favourited?"fas fa-heart text-danger pr-3 m-0 cursor-pointer":"far fa-heart pr-3 m-0 like-btn cursor-pointer"],attrs:{title:"Like"},on:{click:function(s){return t.likeStatus(e,s)}}}),t._v(" "),s("h3",{staticClass:"far fa-comment pr-3 m-0 cursor-pointer",attrs:{title:"Comment"},on:{click:function(s){return t.commentFocus(e,s)}}}),t._v(" "),s("h3",{class:[e.reblogged?"far fa-share-square pr-3 m-0 text-primary cursor-pointer":"far fa-share-square pr-3 m-0 share-btn cursor-pointer"],attrs:{title:"Share"},on:{click:function(s){return t.shareStatus(e,s)}}})]):t._e(),t._v(" "),s("div",{staticClass:"likes font-weight-bold"},[s("span",{staticClass:"like-count"},[t._v(t._s(e.favourites_count))]),t._v(" "+t._s(1==e.favourites_count?"like":"likes")+"\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),s("div",{staticClass:"caption"},[s("p",{staticClass:"mb-2 read-more",staticStyle:{overflow:"hidden"}},[s("span",{staticClass:"username font-weight-bold"},[s("bdi",[s("a",{staticClass:"text-dark",attrs:{href:e.account.url}},[t._v(t._s(e.account.username))])])]),t._v(" "),s("span",{domProps:{innerHTML:t._s(e.content)}})])]),t._v(" "),s("div",{staticClass:"comments"}),t._v(" "),s("div",{staticClass:"timestamp pt-1"},[s("p",{staticClass:"small text-uppercase mb-0"},[s("a",{staticClass:"text-muted",attrs:{href:e.url}},[s("timeago",{directives:[{name:"b-tooltip",rawName:"v-b-tooltip.hover.bottom",modifiers:{hover:!0,bottom:!0}}],attrs:{datetime:e.created_at,"auto-update":60,"converter-options":{includeSeconds:!0},title:t.timestampFormat(e.created_at)}})],1)])])]),t._v(" "),s("div",{staticClass:"card-footer bg-white d-none"},[s("form",{on:{submit:function(s){return s.preventDefault(),t.commentSubmit(e,s)}}},[s("input",{attrs:{type:"hidden",name:"item",value:""}}),t._v(" "),s("input",{staticClass:"form-control status-reply-input",attrs:{name:"comment",placeholder:"Add a comment…",autocomplete:"off"}})])])])}),0)]):t._e(),t._v(" "),"masonry"==t.mode?s("div",{staticClass:"masonry-grid"},t._l(t.timeline,function(e,i){return s("div",{staticClass:"d-inline p-0 p-sm-2 p-md-3 masonry-item"},[s("a",{attrs:{href:e.url},on:{click:function(s){return s.preventDefault(),t.statusModal(e)}}},[s("img",{class:"o-"+t.masonryOrientation(e),attrs:{src:t.previewUrl(e)}})])])}),0):t._e(),t._v(" "),t.timeline.length?s("div",[s("infinite-loading",{on:{infinite:t.infiniteTimeline}},[s("div",{attrs:{slot:"no-more"},slot:"no-more"}),t._v(" "),s("div",{attrs:{slot:"no-results"},slot:"no-results"})])],1):t._e()])])]):t._e(),t._v(" "),"moment"==t.profileLayout?s("div",[s("div",{class:t.momentBackground(),staticStyle:{width:"100%","min-height":"274px"}}),t._v(" "),s("div",{staticClass:"bg-white border-bottom"},[s("div",{staticClass:"container"},[s("div",{staticClass:"row"},[s("div",{staticClass:"col-12 row mx-0"},[s("div",{staticClass:"col-4"}),t._v(" "),s("div",{staticClass:"col-4 text-center"},[s("div",{staticClass:"d-block d-md-none"},[s("img",{staticClass:"rounded-circle box-shadow",staticStyle:{"margin-top":"-60px",border:"5px solid #fff"},attrs:{src:t.profile.avatar,width:"110px",height:"110px"}})]),t._v(" "),s("div",{staticClass:"d-none d-md-block"},[s("img",{staticClass:"rounded-circle box-shadow",staticStyle:{"margin-top":"-90px",border:"5px solid #fff"},attrs:{src:t.profile.avatar,width:"172px",height:"172px"}})])]),t._v(" "),s("div",{staticClass:"col-4 text-right mt-2"},[s("span",{staticClass:"d-none d-md-inline-block pl-4"},[s("a",{staticClass:"fas fa-rss fa-lg text-muted text-decoration-none",attrs:{href:"/users/"+t.profile.username+".atom"}})]),t._v(" "),t.owner?s("span",{staticClass:"pl-md-4 pl-sm-2"},[s("a",{staticClass:"fas fa-cog fa-lg text-muted text-decoration-none",attrs:{href:"/settings/home"}})]):t._e(),t._v(" "),t.profile.id!=t.user.id&&t.user.hasOwnProperty("id")?s("span",{staticClass:"pl-md-4 pl-sm-2"},[s("a",{staticClass:"fas fa-cog fa-lg text-muted text-decoration-none",attrs:{href:"#"},on:{click:function(e){return e.preventDefault(),t.visitorMenu(e)}}})]):t._e(),t._v(" "),t.profile.id!=t.user.id&&t.user.hasOwnProperty("id")?s("span",[1==t.relationship.following?s("span",{staticClass:"pl-md-4 pl-sm-2"},[s("button",{staticClass:"btn btn-outline-secondary font-weight-bold btn-sm",attrs:{type:"button","data-toggle":"tooltip",title:"Unfollow"},on:{click:function(e){return e.preventDefault(),t.followProfile()}}},[t._v("Unfollow")])]):s("span",{staticClass:"pl-md-4 pl-sm-2"},[s("button",{staticClass:"btn btn-primary font-weight-bold btn-sm",attrs:{type:"button","data-toggle":"tooltip",title:"Follow"},on:{click:function(e){return e.preventDefault(),t.followProfile()}}},[t._v("Follow")])])]):t._e()])]),t._v(" "),s("div",{staticClass:"col-12 text-center"},[s("div",{staticClass:"profile-details my-3"},[s("p",{staticClass:"font-weight-ultralight h2 text-center"},[t._v(t._s(t.profile.username))]),t._v(" "),t.profile.note?s("div",{staticClass:"text-center text-muted p-3",domProps:{innerHTML:t._s(t.profile.note)}}):t._e(),t._v(" "),s("div",{staticClass:"pb-3 text-muted text-center"},[s("a",{staticClass:"text-lighter",attrs:{href:t.profile.url}},[s("span",{staticClass:"font-weight-bold"},[t._v(t._s(t.profile.statuses_count))]),t._v("\n\t\t\t\t\t\t\t\t\t\tPosts\n\t\t\t\t\t\t\t\t\t")]),t._v(" "),t.profileSettings.followers.count?s("a",{staticClass:"text-lighter cursor-pointer px-3",on:{click:function(e){return t.followersModal()}}},[s("span",{staticClass:"font-weight-bold"},[t._v(t._s(t.profile.followers_count))]),t._v("\n\t\t\t\t\t\t\t\t\t\tFollowers\n\t\t\t\t\t\t\t\t\t")]):t._e(),t._v(" "),t.profileSettings.following.count?s("a",{staticClass:"text-lighter cursor-pointer",on:{click:function(e){return t.followingModal()}}},[s("span",{staticClass:"font-weight-bold"},[t._v(t._s(t.profile.following_count))]),t._v("\n\t\t\t\t\t\t\t\t\t\tFollowing\n\t\t\t\t\t\t\t\t\t")]):t._e()])])])])])]),t._v(" "),s("div",{staticClass:"container-fluid"},[s("div",{staticClass:"profile-timeline mt-md-4"},["grid"==t.mode?s("div",{staticClass:"card-columns"},t._l(t.timeline,function(e,i){return s("div",{staticClass:"p-sm-2 p-md-3"},[s("a",{staticClass:"card info-overlay card-md-border-0",attrs:{href:e.url}},[s("img",{staticClass:"img-fluid w-100",attrs:{src:t.previewUrl(e)}})])])}),0):t._e(),t._v(" "),t.timeline.length?s("div",[s("infinite-loading",{on:{infinite:t.infiniteTimeline}},[s("div",{attrs:{slot:"no-more"},slot:"no-more"}),t._v(" "),s("div",{attrs:{slot:"no-results"},slot:"no-results"})])],1):t._e()])])]):t._e()]),t._v(" "),s("b-modal",{ref:"followingModal",attrs:{id:"following-modal","hide-footer":"",centered:"",title:"Following","body-class":"list-group-flush p-0"}},[s("div",{staticClass:"list-group"},[t._l(t.following,function(e,i){return s("div",{key:"following_"+i,staticClass:"list-group-item border-0"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"mr-3 rounded-circle box-shadow",attrs:{src:e.avatar,alt:e.username+"’s avatar",width:"30px",loading:"lazy"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mb-0",staticStyle:{"font-size":"14px"}},[s("a",{staticClass:"font-weight-bold text-dark",attrs:{href:e.url}},[t._v("\n "+t._s(e.username)+"\n ")])]),t._v(" "),s("p",{staticClass:"text-muted mb-0",staticStyle:{"font-size":"14px"}},[t._v("\n "+t._s(e.display_name)+"\n ")])]),t._v(" "),t.owner?s("div",[s("a",{staticClass:"btn btn-outline-secondary btn-sm",attrs:{href:"#"},on:{click:function(s){return s.preventDefault(),t.followModalAction(e.id,i,"following")}}},[t._v("Unfollow")])]):t._e()])])}),t._v(" "),0==t.following.length?s("div",{staticClass:"list-group-item border-0"},[s("div",{staticClass:"list-group-item border-0"},[s("p",{staticClass:"p-3 text-center mb-0 lead"},[t._v("You are not following anyone.")])])]):t._e(),t._v(" "),t.followingMore?s("div",{staticClass:"list-group-item text-center",on:{click:function(e){return t.followingLoadMore()}}},[s("p",{staticClass:"mb-0 small text-muted font-weight-light cursor-pointer"},[t._v("Load more")])]):t._e()],2)]),t._v(" "),s("b-modal",{ref:"followerModal",attrs:{id:"follower-modal","hide-footer":"",centered:"",title:"Followers","body-class":"list-group-flush p-0"}},[s("div",{staticClass:"list-group"},[t._l(t.followers,function(e,i){return s("div",{key:"follower_"+i,staticClass:"list-group-item border-0"},[s("div",{staticClass:"media"},[s("a",{attrs:{href:e.url}},[s("img",{staticClass:"mr-3 rounded-circle box-shadow",attrs:{src:e.avatar,alt:e.username+"’s avatar",width:"30px",loading:"lazy"}})]),t._v(" "),s("div",{staticClass:"media-body"},[s("p",{staticClass:"mb-0",staticStyle:{"font-size":"14px"}},[s("a",{staticClass:"font-weight-bold text-dark",attrs:{href:e.url}},[t._v("\n "+t._s(e.username)+"\n ")])]),t._v(" "),s("p",{staticClass:"text-muted mb-0",staticStyle:{"font-size":"14px"}},[t._v("\n "+t._s(e.display_name)+"\n ")])])])])}),t._v(" "),t.followerMore?s("div",{staticClass:"list-group-item text-center",on:{click:function(e){return t.followersLoadMore()}}},[s("p",{staticClass:"mb-0 small text-muted font-weight-light cursor-pointer"},[t._v("Load more")])]):t._e()],2)]),t._v(" "),s("b-modal",{ref:"visitorContextMenu",attrs:{id:"visitor-context-menu","hide-footer":"","hide-header":"",centered:"",size:"sm","body-class":"list-group-flush p-0"}},[t.relationship?s("div",{staticClass:"list-group"},[t.owner||t.relationship.following?t._e():s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded text-primary",on:{click:t.followProfile}},[t._v("\n \tFollow\n ")]),t._v(" "),!t.owner&&t.relationship.following?s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded",on:{click:t.followProfile}},[t._v("\n \tUnfollow\n ")]):t._e(),t._v(" "),t.owner||t.relationship.muting?t._e():s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded",on:{click:t.muteProfile}},[t._v("\n \tMute\n ")]),t._v(" "),!t.owner&&t.relationship.muting?s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded",on:{click:t.unmuteProfile}},[t._v("\n \tUnmute\n ")]):t._e(),t._v(" "),t.owner?t._e():s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded text-danger",on:{click:t.reportProfile}},[t._v("\n \tReport User\n ")]),t._v(" "),t.owner||t.relationship.blocking?t._e():s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded text-danger",on:{click:t.blockProfile}},[t._v("\n \tBlock\n ")]),t._v(" "),!t.owner&&t.relationship.blocking?s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded text-danger",on:{click:t.unblockProfile}},[t._v("\n \tUnblock\n ")]):t._e(),t._v(" "),s("div",{staticClass:"list-group-item cursor-pointer text-center font-weight-bold lead rounded text-muted",on:{click:function(e){return t.$refs.visitorContextMenu.hide()}}},[t._v("\n \tClose\n ")])]):t._e()])],1)},[function(){var t=this.$createElement,e=this._self._c||t;return e("button",{staticClass:"btn btn-link text-dark no-caret dropdown-toggle",attrs:{type:"button","data-toggle":"dropdown","aria-haspopup":"true","aria-expanded":"false",title:"Post options"}},[e("span",{staticClass:"fas fa-ellipsis-v fa-lg text-muted"})])}],!1,null,"53033351",null);e.default=n.exports},Ht21:function(t,e,s){"use strict";var i=s("IJk2");s.n(i).a},I1BE:function(t,e){t.exports=function(t){var e=[];return e.toString=function(){return this.map(function(e){var s=function(t,e){var s=t[1]||"",i=t[3];if(!i)return s;if(e&&"function"==typeof btoa){var o=(n=i,"/*# sourceMappingURL=data:application/json;charset=utf-8;base64,"+btoa(unescape(encodeURIComponent(JSON.stringify(n))))+" */"),a=i.sources.map(function(t){return"/*# sourceURL="+i.sourceRoot+t+" */"});return[s].concat(a).concat([o]).join("\n")}var n;return[s].join("\n")}(e,t);return e[2]?"@media "+e[2]+"{"+s+"}":s}).join("")},e.i=function(t,s){"string"==typeof t&&(t=[[null,t,""]]);for(var i={},o=0;o