2018-04-18 02:17:42 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace App;
|
|
|
|
|
2018-12-18 06:28:46 +00:00
|
|
|
use Auth, Cache, Storage;
|
2018-05-31 22:03:31 +00:00
|
|
|
use App\Util\Lexer\PrettyNumber;
|
2018-12-18 06:28:46 +00:00
|
|
|
use Illuminate\Database\Eloquent\{Model, SoftDeletes};
|
2018-04-18 02:17:42 +00:00
|
|
|
|
|
|
|
class Profile extends Model
|
|
|
|
{
|
2018-06-14 00:52:42 +00:00
|
|
|
use SoftDeletes;
|
|
|
|
|
|
|
|
protected $dates = ['deleted_at'];
|
2018-12-18 06:28:46 +00:00
|
|
|
protected $hidden = ['private_key'];
|
2019-01-12 07:47:00 +00:00
|
|
|
protected $visible = ['id', 'user_id', 'username', 'name'];
|
2018-05-22 23:56:20 +00:00
|
|
|
|
2018-06-09 23:31:48 +00:00
|
|
|
public function user()
|
|
|
|
{
|
|
|
|
return $this->belongsTo(User::class);
|
|
|
|
}
|
|
|
|
|
2018-12-18 06:28:46 +00:00
|
|
|
public function url($suffix = null)
|
2018-07-12 16:40:25 +00:00
|
|
|
{
|
2018-12-18 06:28:46 +00:00
|
|
|
return $this->remote_url ?? url($this->username . $suffix);
|
2018-07-12 16:40:25 +00:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:28:46 +00:00
|
|
|
public function localUrl($suffix = null)
|
2018-04-19 05:57:16 +00:00
|
|
|
{
|
2018-12-18 06:28:46 +00:00
|
|
|
return url($this->username . $suffix);
|
2018-05-22 23:56:20 +00:00
|
|
|
}
|
|
|
|
|
2018-12-18 06:28:46 +00:00
|
|
|
public function permalink($suffix = null)
|
2018-05-22 23:56:20 +00:00
|
|
|
{
|
2018-12-18 06:28:46 +00:00
|
|
|
return $this->remote_url ?? url('users/' . $this->username . $suffix);
|
2018-04-19 05:57:16 +00:00
|
|
|
}
|
2018-05-31 22:03:31 +00:00
|
|
|
|
2018-05-22 23:56:20 +00:00
|
|
|
public function emailUrl()
|
|
|
|
{
|
2018-10-10 01:25:27 +00:00
|
|
|
if($this->domain) {
|
|
|
|
return $this->username;
|
|
|
|
}
|
|
|
|
|
2018-05-22 23:56:20 +00:00
|
|
|
$domain = parse_url(config('app.url'), PHP_URL_HOST);
|
2018-08-28 03:07:36 +00:00
|
|
|
|
|
|
|
return $this->username.'@'.$domain;
|
2018-05-22 23:56:20 +00:00
|
|
|
}
|
|
|
|
|
2018-04-18 02:17:42 +00:00
|
|
|
public function statuses()
|
|
|
|
{
|
2018-05-31 22:03:31 +00:00
|
|
|
return $this->hasMany(Status::class);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function followingCount($short = false)
|
|
|
|
{
|
|
|
|
$count = $this->following()->count();
|
2018-08-28 03:07:36 +00:00
|
|
|
if ($short) {
|
2018-05-31 22:03:31 +00:00
|
|
|
return PrettyNumber::convert($count);
|
|
|
|
} else {
|
|
|
|
return $count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function followerCount($short = false)
|
|
|
|
{
|
|
|
|
$count = $this->followers()->count();
|
2018-08-28 03:07:36 +00:00
|
|
|
if ($short) {
|
2018-05-31 22:03:31 +00:00
|
|
|
return PrettyNumber::convert($count);
|
|
|
|
} else {
|
|
|
|
return $count;
|
|
|
|
}
|
2018-04-18 02:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function following()
|
|
|
|
{
|
2018-05-31 22:03:31 +00:00
|
|
|
return $this->belongsToMany(
|
2018-08-28 03:07:36 +00:00
|
|
|
self::class,
|
2018-05-31 22:03:31 +00:00
|
|
|
'followers',
|
|
|
|
'profile_id',
|
|
|
|
'following_id'
|
|
|
|
);
|
2018-04-18 02:17:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function followers()
|
|
|
|
{
|
2018-05-31 22:03:31 +00:00
|
|
|
return $this->belongsToMany(
|
2018-08-28 03:07:36 +00:00
|
|
|
self::class,
|
2018-05-31 22:03:31 +00:00
|
|
|
'followers',
|
|
|
|
'following_id',
|
|
|
|
'profile_id'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2018-09-03 01:29:31 +00:00
|
|
|
public function follows($profile) : bool
|
2018-05-31 22:03:31 +00:00
|
|
|
{
|
2018-09-03 01:29:31 +00:00
|
|
|
return Follower::whereProfileId($this->id)->whereFollowingId($profile->id)->exists();
|
2018-05-31 22:03:31 +00:00
|
|
|
}
|
|
|
|
|
2018-09-03 01:29:31 +00:00
|
|
|
public function followedBy($profile) : bool
|
2018-05-31 22:03:31 +00:00
|
|
|
{
|
2018-09-03 01:29:31 +00:00
|
|
|
return Follower::whereProfileId($profile->id)->whereFollowingId($this->id)->exists();
|
2018-05-31 22:03:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function bookmarks()
|
|
|
|
{
|
|
|
|
return $this->belongsToMany(
|
|
|
|
Status::class,
|
|
|
|
'bookmarks',
|
|
|
|
'profile_id',
|
|
|
|
'status_id'
|
|
|
|
);
|
2018-04-18 02:17:42 +00:00
|
|
|
}
|
2018-04-19 05:57:16 +00:00
|
|
|
|
|
|
|
public function likes()
|
|
|
|
{
|
|
|
|
return $this->hasMany(Like::class);
|
|
|
|
}
|
2018-05-22 23:56:20 +00:00
|
|
|
|
|
|
|
public function avatar()
|
|
|
|
{
|
2018-08-16 00:21:42 +00:00
|
|
|
return $this->hasOne(Avatar::class)->withDefault([
|
2018-08-28 03:07:36 +00:00
|
|
|
'media_path' => 'public/avatars/default.png',
|
2018-08-16 00:21:42 +00:00
|
|
|
]);
|
2018-05-22 23:56:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function avatarUrl()
|
|
|
|
{
|
2018-08-28 03:07:36 +00:00
|
|
|
$url = Cache::remember("avatar:{$this->id}", 1440, function () {
|
2018-08-16 00:21:42 +00:00
|
|
|
$path = optional($this->avatar)->media_path;
|
2018-10-10 01:25:27 +00:00
|
|
|
$version = hash('sha1', $this->avatar->updated_at);
|
2018-08-13 03:51:05 +00:00
|
|
|
$path = "{$path}?v={$version}";
|
2018-08-28 03:07:36 +00:00
|
|
|
|
2018-08-13 03:51:05 +00:00
|
|
|
return url(Storage::url($path));
|
|
|
|
});
|
2018-08-28 03:07:36 +00:00
|
|
|
|
2018-05-22 23:56:20 +00:00
|
|
|
return $url;
|
|
|
|
}
|
2018-07-12 16:40:25 +00:00
|
|
|
|
|
|
|
public function statusCount()
|
|
|
|
{
|
2018-08-26 06:00:45 +00:00
|
|
|
return $this->statuses()
|
2018-12-11 03:45:44 +00:00
|
|
|
->getQuery()
|
2018-08-26 06:00:45 +00:00
|
|
|
->whereHas('media')
|
|
|
|
->whereNull('in_reply_to_id')
|
|
|
|
->whereNull('reblog_of_id')
|
|
|
|
->count();
|
2018-07-12 16:40:25 +00:00
|
|
|
}
|
2018-08-10 02:10:16 +00:00
|
|
|
|
|
|
|
public function recommendFollowers()
|
|
|
|
{
|
|
|
|
$follows = $this->following()->pluck('followers.id');
|
|
|
|
$following = $this->following()
|
|
|
|
->orderByRaw('rand()')
|
|
|
|
->take(3)
|
|
|
|
->pluck('following_id');
|
|
|
|
$following->push(Auth::id());
|
|
|
|
$following = Follower::whereNotIn('profile_id', $follows)
|
|
|
|
->whereNotIn('following_id', $following)
|
|
|
|
->whereNotIn('following_id', $follows)
|
|
|
|
->whereIn('profile_id', $following)
|
|
|
|
->orderByRaw('rand()')
|
2018-08-26 06:00:45 +00:00
|
|
|
->distinct('id')
|
2018-08-10 02:10:16 +00:00
|
|
|
->limit(3)
|
|
|
|
->pluck('following_id');
|
|
|
|
$recommended = [];
|
2018-08-28 03:07:36 +00:00
|
|
|
foreach ($following as $follow) {
|
|
|
|
$recommended[] = self::findOrFail($follow);
|
2018-08-10 02:10:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return $recommended;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function keyId()
|
|
|
|
{
|
2018-08-28 03:07:36 +00:00
|
|
|
if ($this->remote_url) {
|
2018-08-10 02:10:16 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-08-28 03:07:36 +00:00
|
|
|
|
2018-08-10 02:10:16 +00:00
|
|
|
return $this->permalink('#main-key');
|
|
|
|
}
|
2018-09-03 01:29:31 +00:00
|
|
|
|
|
|
|
public function mutedIds()
|
|
|
|
{
|
|
|
|
return UserFilter::whereUserId($this->id)
|
|
|
|
->whereFilterableType('App\Profile')
|
|
|
|
->whereFilterType('mute')
|
|
|
|
->pluck('filterable_id');
|
|
|
|
}
|
|
|
|
|
2018-09-23 23:25:33 +00:00
|
|
|
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();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-09-03 01:29:31 +00:00
|
|
|
public function reports()
|
|
|
|
{
|
|
|
|
return $this->hasMany(Report::class, 'profile_id');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function media()
|
|
|
|
{
|
|
|
|
return $this->hasMany(Media::class, 'profile_id');
|
|
|
|
}
|
2018-09-16 00:37:11 +00:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
2018-11-04 03:20:11 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
2018-11-14 02:16:59 +00:00
|
|
|
return $audience;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAudienceInbox($scope = 'public')
|
|
|
|
{
|
|
|
|
return $this
|
|
|
|
->followers()
|
|
|
|
->whereLocalProfile(false)
|
|
|
|
->get()
|
|
|
|
->map(function($follow) {
|
|
|
|
return $follow->sharedInbox ?? $follow->inbox_url;
|
|
|
|
})
|
|
|
|
->unique()
|
|
|
|
->toArray();
|
2018-11-04 03:20:11 +00:00
|
|
|
}
|
2018-04-18 02:17:42 +00:00
|
|
|
}
|