'datetime', 'last_fetched_at' => 'datetime', 'last_status_at' => 'datetime' ]; protected $hidden = ['private_key']; protected $visible = ['id', 'user_id', 'username', 'name']; protected $guarded = []; public function user() { return $this->belongsTo(User::class); } public function url($suffix = null) { return $this->remote_url ?? url($this->username . $suffix); } public function localUrl($suffix = null) { return url($this->username . $suffix); } public function permalink($suffix = null) { return $this->remote_url ?? url('users/' . $this->username . $suffix); } public function emailUrl() { if($this->domain) { return $this->username; } $domain = parse_url(config('app.url'), PHP_URL_HOST); return $this->username.'@'.$domain; } public function statuses() { return $this->hasMany(Status::class); } public function followingCount($short = false) { $count = Cache::remember('profile:following_count:'.$this->id, now()->addMonths(1), function() { if($this->domain == null && $this->user->settings->show_profile_following_count == false) { return 0; } $count = DB::table('followers')->where('profile_id', $this->id)->count(); if($this->following_count != $count) { $this->following_count = $count; $this->save(); } return $count; }); return $short ? PrettyNumber::convert($count) : $count; } public function followerCount($short = false) { $count = Cache::remember('profile:follower_count:'.$this->id, now()->addMonths(1), function() { if($this->domain == null && $this->user->settings->show_profile_follower_count == false) { return 0; } $count = DB::table('followers')->where('following_id', $this->id)->count(); if($this->followers_count != $count) { $this->followers_count = $count; $this->save(); } return $count; }); return $short ? PrettyNumber::convert($count) : $count; } public function statusCount() { return $this->status_count; } public function following() { return $this->belongsToMany( self::class, 'followers', 'profile_id', 'following_id' ); } public function followers() { return $this->belongsToMany( self::class, 'followers', 'following_id', 'profile_id' ); } public function follows($profile) : bool { return Follower::whereProfileId($this->id)->whereFollowingId($profile->id)->exists(); } public function followedBy($profile) : bool { return Follower::whereProfileId($profile->id)->whereFollowingId($this->id)->exists(); } public function bookmarks() { return $this->belongsToMany( Status::class, 'bookmarks', 'profile_id', 'status_id' ); } public function likes() { return $this->hasMany(Like::class); } public function avatar() { return $this->hasOne(Avatar::class)->withDefault([ 'media_path' => 'public/avatars/default.jpg', 'change_count' => 0 ]); } public function avatarUrl() { $url = Cache::remember('avatar:'.$this->id, 1209600, function () { $avatar = $this->avatar; if(!$avatar) { return url('/storage/avatars/default.jpg'); } if($avatar->cdn_url) { if(substr($avatar->cdn_url, 0, 8) === 'https://') { return $avatar->cdn_url; } else { return url('/storage/avatars/default.jpg'); } } $path = $avatar->media_path; if(!$path) { return url('/storage/avatars/default.jpg'); } if( $avatar->is_remote && $avatar->remote_url && boolval(config_cache('federation.avatars.store_local')) == true ) { return $avatar->remote_url; } if($path === 'public/avatars/default.jpg') { return url('/storage/avatars/default.jpg'); } if(substr($path, 0, 6) !== 'public') { return url('/storage/avatars/default.jpg'); } if(config('filesystems.default') !== 'local') { return Storage::url($path); } $path = "{$path}?v={$avatar->change_count}"; return url(Storage::url($path)); }); return $url; } // deprecated public function recommendFollowers() { return collect([]); } public function keyId() { if ($this->remote_url) { return; } return $this->permalink('#main-key'); } public function mutedIds() { return UserFilter::whereUserId($this->id) ->whereFilterableType('App\Profile') ->whereFilterType('mute') ->pluck('filterable_id'); } public function blockedIds() { return UserFilter::whereUserId($this->id) ->whereFilterableType('App\Profile') ->whereFilterType('block') ->pluck('filterable_id'); } public function mutedProfileUrls() { $ids = $this->mutedIds(); return $this->whereIn('id', $ids)->get()->map(function($i) { return $i->url(); }); } public function blockedProfileUrls() { $ids = $this->blockedIds(); return $this->whereIn('id', $ids)->get()->map(function($i) { return $i->url(); }); } public function reports() { return $this->hasMany(Report::class, 'profile_id'); } public function media() { return $this->hasMany(Media::class, 'profile_id'); } public function inboxUrl() { return $this->inbox_url ?? $this->permalink('/inbox'); } public function outboxUrl() { return $this->outbox_url ?? $this->permalink('/outbox'); } public function sharedInbox() { return $this->sharedInbox ?? $this->inboxUrl(); } public function getDefaultScope() { return $this->is_private == true ? 'private' : 'public'; } public function getAudience($scope = false) { if($this->remote_url) { return []; } $scope = $scope ?? $this->getDefaultScope(); $audience = []; switch ($scope) { case 'public': $audience = [ 'to' => [ 'https://www.w3.org/ns/activitystreams#Public' ], 'cc' => [ $this->permalink('/followers') ] ]; break; case 'unlisted': $audience = [ 'to' => [ ], 'cc' => [ 'https://www.w3.org/ns/activitystreams#Public', $this->permalink('/followers') ] ]; break; case 'private': $audience = [ 'to' => [ $this->permalink('/followers') ], 'cc' => [ ] ]; break; } return $audience; } public function getAudienceInbox($scope = 'public') { return FollowerService::audience($this->id, $scope); } public function circles() { return $this->hasMany(Circle::class); } public function hashtags() { return $this->hasManyThrough( Hashtag::class, StatusHashtag::class, 'profile_id', 'id', 'id', 'hashtag_id' ); } public function hashtagFollowing() { return $this->hasMany(HashtagFollow::class); } public function collections() { return $this->hasMany(Collection::class); } public function hasFollowRequestById(int $id) { return FollowRequest::whereFollowerId($id) ->whereFollowingId($this->id) ->exists(); } public function stories() { return $this->hasMany(Story::class); } public function reported() { return $this->hasMany(Report::class, 'object_id'); } public function aliases() { return $this->hasMany(ProfileAlias::class); } }