diff --git a/app/Collection.php b/app/Collection.php index 2e7b4967c..5a37648d3 100644 --- a/app/Collection.php +++ b/app/Collection.php @@ -4,7 +4,7 @@ namespace App; use Illuminate\Support\Str; use Illuminate\Database\Eloquent\Model; -use Pixelfed\Snowflake\HasSnowflakePrimary; +use App\HasSnowflakePrimary; class Collection extends Model { diff --git a/app/CollectionItem.php b/app/CollectionItem.php index d272e68a4..f357f0099 100644 --- a/app/CollectionItem.php +++ b/app/CollectionItem.php @@ -3,7 +3,7 @@ namespace App; use Illuminate\Database\Eloquent\Model; -use Pixelfed\Snowflake\HasSnowflakePrimary; +use App\HasSnowflakePrimary; class CollectionItem extends Model { diff --git a/app/HasSnowflakePrimary.php b/app/HasSnowflakePrimary.php new file mode 100644 index 000000000..97f7f510e --- /dev/null +++ b/app/HasSnowflakePrimary.php @@ -0,0 +1,19 @@ +getKey())) { + $keyName = $model->getKeyName(); + $id = SnowflakeService::next(); + $model->setAttribute($keyName, $id); + } + }); + } +} diff --git a/app/Models/Poll.php b/app/Models/Poll.php index 2b65162c0..f7398401b 100644 --- a/app/Models/Poll.php +++ b/app/Models/Poll.php @@ -4,11 +4,11 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; -use Pixelfed\Snowflake\HasSnowflakePrimary; +use App\HasSnowflakePrimary; class Poll extends Model { - use HasSnowflakePrimary, HasFactory; + use HasSnowflakePrimary, HasFactory; /** * Indicates if the IDs are auto-incrementing. @@ -17,19 +17,19 @@ class Poll extends Model */ public $incrementing = false; - protected $casts = [ - 'poll_options' => 'array', - 'cached_tallies' => 'array', - 'expires_at' => 'datetime' - ]; + protected $casts = [ + 'poll_options' => 'array', + 'cached_tallies' => 'array', + 'expires_at' => 'datetime' + ]; - public function votes() - { - return $this->hasMany(PollVote::class); - } + public function votes() + { + return $this->hasMany(PollVote::class); + } - public function getTallies() - { - return $this->cached_tallies; - } + public function getTallies() + { + return $this->cached_tallies; + } } diff --git a/app/Place.php b/app/Place.php index c1409838e..5a9cc8d16 100644 --- a/app/Place.php +++ b/app/Place.php @@ -3,7 +3,6 @@ namespace App; use Illuminate\Database\Eloquent\Model; -use Pixelfed\Snowflake\HasSnowflakePrimary; class Place extends Model { diff --git a/app/Profile.php b/app/Profile.php index cc2bacd8d..3d1bea069 100644 --- a/app/Profile.php +++ b/app/Profile.php @@ -4,324 +4,324 @@ namespace App; use Auth, Cache, DB, Storage; use App\Util\Lexer\PrettyNumber; -use Pixelfed\Snowflake\HasSnowflakePrimary; +use App\HasSnowflakePrimary; use Illuminate\Database\Eloquent\{Model, SoftDeletes}; use App\Services\FollowerService; class Profile extends Model { - use HasSnowflakePrimary, SoftDeletes; + use HasSnowflakePrimary, SoftDeletes; - /** - * Indicates if the IDs are auto-incrementing. - * - * @var bool - */ - public $incrementing = false; + /** + * Indicates if the IDs are auto-incrementing. + * + * @var bool + */ + public $incrementing = false; - protected $dates = [ - 'deleted_at', - 'last_fetched_at' - ]; - protected $hidden = ['private_key']; - protected $visible = ['id', 'user_id', 'username', 'name']; - protected $fillable = ['user_id']; + protected $dates = [ + 'deleted_at', + 'last_fetched_at' + ]; + protected $hidden = ['private_key']; + protected $visible = ['id', 'user_id', 'username', 'name']; + protected $fillable = ['user_id']; - public function user() - { - return $this->belongsTo(User::class); - } + public function user() + { + return $this->belongsTo(User::class); + } - public function url($suffix = null) - { - return $this->remote_url ?? url($this->username . $suffix); - } + 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 localUrl($suffix = null) + { + return url($this->username . $suffix); + } - public function permalink($suffix = null) - { - return $this->remote_url ?? url('users/' . $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; - } + public function emailUrl() + { + if($this->domain) { + return $this->username; + } - $domain = parse_url(config('app.url'), PHP_URL_HOST); + $domain = parse_url(config('app.url'), PHP_URL_HOST); - return $this->username.'@'.$domain; - } + return $this->username.'@'.$domain; + } - public function statuses() - { - return $this->hasMany(Status::class); - } + 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')->select('following_id')->where('following_id', $this->id)->count(); - if($this->following_count != $count) { - $this->following_count = $count; - $this->save(); - } - return $count; - }); + 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')->select('following_id')->where('following_id', $this->id)->count(); + if($this->following_count != $count) { + $this->following_count = $count; + $this->save(); + } + return $count; + }); - return $short ? PrettyNumber::convert($count) : $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 = $this->followers()->count(); - if($this->followers_count != $count) { - $this->followers_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 = $this->followers()->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 statusCount() + { + return $this->status_count; + } - public function following() - { - return $this->belongsToMany( - self::class, - 'followers', - 'profile_id', - 'following_id' - ); - } + 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 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 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 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 bookmarks() + { + return $this->belongsToMany( + Status::class, + 'bookmarks', + 'profile_id', + 'status_id' + ); + } - public function likes() - { - return $this->hasMany(Like::class); - } + 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 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, now()->addYears(1), function () { - $avatar = $this->avatar; + public function avatarUrl() + { + $url = Cache::remember('avatar:'.$this->id, now()->addYears(1), function () { + $avatar = $this->avatar; - if($avatar->cdn_url) { - return $avatar->cdn_url ?? url('/storage/avatars/default.jpg'); - } + if($avatar->cdn_url) { + return $avatar->cdn_url ?? url('/storage/avatars/default.jpg'); + } - if($avatar->is_remote) { - return $avatar->cdn_url ?? url('/storage/avatars/default.jpg'); - } - - $path = $avatar->media_path; - $path = "{$path}?v={$avatar->change_count}"; + if($avatar->is_remote) { + return $avatar->cdn_url ?? url('/storage/avatars/default.jpg'); + } + + $path = $avatar->media_path; + $path = "{$path}?v={$avatar->change_count}"; - return config('app.url') . Storage::url($path); - }); + return config('app.url') . Storage::url($path); + }); - return $url; - } + return $url; + } - // deprecated - public function recommendFollowers() - { - return collect([]); - } + // deprecated + public function recommendFollowers() + { + return collect([]); + } - public function keyId() - { - if ($this->remote_url) { - return; - } + public function keyId() + { + if ($this->remote_url) { + return; + } - return $this->permalink('#main-key'); - } + return $this->permalink('#main-key'); + } - public function mutedIds() - { - return UserFilter::whereUserId($this->id) - ->whereFilterableType('App\Profile') - ->whereFilterType('mute') - ->pluck('filterable_id'); - } + 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 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 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 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 reports() + { + return $this->hasMany(Report::class, 'profile_id'); + } - public function media() - { - return $this->hasMany(Media::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 inboxUrl() + { + return $this->inbox_url ?? $this->permalink('/inbox'); + } - public function outboxUrl() - { - return $this->outbox_url ?? $this->permalink('/outbox'); - } + public function outboxUrl() + { + return $this->outbox_url ?? $this->permalink('/outbox'); + } - public function sharedInbox() - { - return $this->sharedInbox ?? $this->inboxUrl(); - } + public function sharedInbox() + { + return $this->sharedInbox ?? $this->inboxUrl(); + } - public function getDefaultScope() - { - return $this->is_private == true ? 'private' : 'public'; - } + 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; - } - return $audience; - } + 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; + } + return $audience; + } - public function getAudienceInbox($scope = 'public') - { - return FollowerService::audience($this->id, $scope); - } + public function getAudienceInbox($scope = 'public') + { + return FollowerService::audience($this->id, $scope); + } - public function circles() - { - return $this->hasMany(Circle::class); - } + 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 hashtags() + { + return $this->hasManyThrough( + Hashtag::class, + StatusHashtag::class, + 'profile_id', + 'id', + 'id', + 'hashtag_id' + ); + } - public function hashtagFollowing() - { - return $this->hasMany(HashtagFollow::class); - } + public function hashtagFollowing() + { + return $this->hasMany(HashtagFollow::class); + } - public function collections() - { - return $this->hasMany(Collection::class); - } + public function collections() + { + return $this->hasMany(Collection::class); + } - public function hasFollowRequestById(int $id) - { - return FollowRequest::whereFollowerId($id) - ->whereFollowingId($this->id) - ->exists(); - } + public function hasFollowRequestById(int $id) + { + return FollowRequest::whereFollowerId($id) + ->whereFollowingId($this->id) + ->exists(); + } - public function stories() - { - return $this->hasMany(Story::class); - } + public function stories() + { + return $this->hasMany(Story::class); + } - public function reported() - { - return $this->hasMany(Report::class, 'object_id'); - } + public function reported() + { + return $this->hasMany(Report::class, 'object_id'); + } } diff --git a/app/Services/SnowflakeService.php b/app/Services/SnowflakeService.php index e7833e091..4aaaffd80 100644 --- a/app/Services/SnowflakeService.php +++ b/app/Services/SnowflakeService.php @@ -8,6 +8,20 @@ use Cache; class SnowflakeService { public static function byDate(Carbon $ts = null) + { + if($ts instanceOf Carbon) { + $ts = now()->parse($ts)->timestamp; + } else { + return self::next(); + } + + return ((round($ts * 1000) - 1549756800000) << 22) + | (random_int(1,31) << 17) + | (random_int(1,31) << 12) + | $seq; + } + + public static function next() { $seq = Cache::get('snowflake:seq'); @@ -19,19 +33,11 @@ class SnowflakeService { } if($seq >= 4095) { - $seq = 0; Cache::put('snowflake:seq', 0); + $seq = 0; } - if($ts == null) { - $ts = microtime(true); - } - - if($ts instanceOf Carbon) { - $ts = now()->parse($ts)->timestamp; - } - - return ((round($ts * 1000) - 1549756800000) << 22) + return ((round(microtime(true) * 1000) - 1549756800000) << 22) | (random_int(1,31) << 17) | (random_int(1,31) << 12) | $seq; diff --git a/app/Status.php b/app/Status.php index 7befcb02b..35c5820bf 100644 --- a/app/Status.php +++ b/app/Status.php @@ -4,7 +4,7 @@ namespace App; use Auth, Cache, Hashids, Storage; use Illuminate\Database\Eloquent\Model; -use Pixelfed\Snowflake\HasSnowflakePrimary; +use App\HasSnowflakePrimary; use App\Http\Controllers\StatusController; use Illuminate\Database\Eloquent\SoftDeletes; use App\Models\Poll; diff --git a/app/Story.php b/app/Story.php index f4d403e85..6f4335627 100644 --- a/app/Story.php +++ b/app/Story.php @@ -5,7 +5,7 @@ namespace App; use Auth; use Storage; use Illuminate\Database\Eloquent\Model; -use Pixelfed\Snowflake\HasSnowflakePrimary; +use App\HasSnowflakePrimary; use App\Util\Lexer\Bearcap; class Story extends Model