$currencies * @property-read Ban|null $ban * @property-read Permission $permission * @property-read UserReferral|null $referrals * @property-read Collection $userReferrals * @property-read Collection $claimedReferralLog * @property-read Collection $badges * @property-read Collection $rooms * @property-read Collection $friends * @property-read Ban|null $banRelation * @property-read WebsiteBetaCode|null $betaCode * @property-read WebsiteTeam|null $team * @property-read Collection $applications * @property-read UserSubscription|null $hcSubscription * @property-read Collection $articleComments * @property-read Collection $transactions * @property-read Collection $usedShopVouchers * @property-read Collection $items * @property-read Collection $tickets * @property-read Collection $photos * @property-read Collection $profileGuestbook * @property-read Collection $guestbook * @property-read Collection $chatLogs * @property-read Collection $chatLogsPrivate * @property-read Collection $articles * @property-read Collection $sessions * * @extends Factory */ class User extends Authenticatable implements FilamentUser, HasName { use HasApiTokens; use HasFactory; use LogsActivity; use Notifiable; use TwoFactorAuthenticatable; #[\Override] public $timestamps = false; #[\Override] protected $fillable = ['username', 'mail', 'password', 'account_created', 'last_login', 'motto', 'look', 'credits', 'last_username_change', 'auth_ticket', 'home_room', 'ip_register', 'ip_current', 'referral_code', 'preferences', 'team_id', 'avatar_background', 'home_background', 'pincode', 'secret_key', 'extra_rank', 'is_hidden', 'background_id', 'background_stand_id', 'background_overlay_id', 'radio_points', 'pixels', 'points', 'online', 'gender', 'rank', 'mail_verified', 'two_factor_secret', 'two_factor_recovery_codes', 'two_factor_confirmed_at']; #[\Override] protected $hidden = ['id', 'password', 'remember_token']; /** * @return array */ #[\Override] protected function casts(): array { return [ 'email_verified_at' => 'datetime', 'password' => 'hashed', 'hidden_staff' => 'boolean', 'online' => 'boolean', 'preferences' => 'array', ]; } public function currencies(): HasMany { return $this->hasMany(UserCurrency::class, 'user_id'); } public function sessions(): HasMany { return $this->hasMany(Session::class); } public function currency(string $currency): int { if (! $this->relationLoaded('currencies')) { $this->load('currencies'); } $type = match ($currency) { 'duckets' => 0, 'diamonds' => 5, 'points' => 101, default => 0, }; return $this->currencies->where('type', $type)->first()->amount ?? 0; } public function permission(): HasOne { return $this->hasOne(Permission::class, 'id', 'rank'); } public function articles(): HasMany { return $this->hasMany(WebsiteArticle::class); } public function referrals(): HasOne { return $this->hasOne(UserReferral::class); } public function userReferrals(): HasMany { return $this->hasMany(Referral::class); } public function claimedReferralLog(): HasMany { return $this->hasMany(ClaimedReferralLog::class); } public function badges(): HasMany { return $this->hasMany(UserBadge::class); } public function rooms(): HasMany { return $this->hasMany(Room::class, 'owner_id'); } public function friends(): HasMany { return $this->hasMany(MessengerFriendship::class, 'user_one_id'); } public function referralsNeeded(): int { $referrals = $this->referrals?->referrals_total ?? 0; return (int) setting('referrals_needed') - (int) $referrals; } public function ban(): HasOne { return $this->hasOne(Ban::class, 'user_id') ->where('ban_expire', '>', time()) ->whereIn('type', ['account', 'super']) ->withoutGlobalScopes(); } public function settings(): HasOne { return $this->hasOne(UserSetting::class); } public function ssoTicket(): string { $hotelName = Str::replace(' ', '', (string) setting('hotel_name')); $sso = sprintf('%s-%s', $hotelName, Str::uuid()->toString()); $this->update([ 'auth_ticket' => $sso, 'ip_current' => request()->ip(), ]); return $sso; } public function betaCode(): HasOne { return $this->hasOne(WebsiteBetaCode::class); } public function team(): BelongsTo { return $this->belongsTo(WebsiteTeam::class, 'team_id'); } public function applications(): HasMany { return $this->hasMany(WebsiteStaffApplications::class, 'user_id'); } public function hcSubscription(): HasOne { return $this->hasOne(UserSubscription::class); } public function articleComments(): HasMany { return $this->hasMany(WebsiteArticleComment::class); } public function transactions(): HasMany { return $this->hasMany(WebsitePaypalTransaction::class); } public function usedShopVouchers(): HasMany { return $this->hasMany(WebsiteUsedShopVoucher::class); } public function items(): HasMany { return $this->hasMany(Item::class, 'user_id'); } public function tickets(): HasMany { return $this->hasMany(WebsiteHelpCenterTicket::class); } public function photos(): HasMany { return $this->hasMany(CameraWeb::class); } public function guilds(): HasMany { return $this->hasMany(GuildMember::class, 'user_id'); } public function profileGuestbook(): HasMany { return $this->hasMany(WebsiteUserGuestbook::class, 'profile_id'); } public function guestbook(): HasMany { return $this->hasMany(WebsiteUserGuestbook::class, 'user_id'); } public function chatLogs(): HasMany { return $this->hasMany(ChatlogRoom::class, 'user_from_id'); } public function chatLogsPrivate(): HasMany { return $this->hasMany(ChatlogPrivate::class, 'user_from_id'); } public function socialAccounts(): HasMany { return $this->hasMany(SocialAccount::class); } public function hasSocialAccount(string $provider): bool { return $this->socialAccounts()->where('provider', $provider)->exists(); } public function getOnlineFriends(int $total = 10): Collection { return $this->friends() ->select(['user_two_id', 'users.id', 'users.username', 'users.look', 'users.motto', 'users.last_online']) ->join('users', 'users.id', '=', 'user_two_id') ->where('users.online', '1') ->inRandomOrder() ->limit($total) ->get() ->map(fn ($item) => (new User)->forceFill([ 'id' => $item->id, 'username' => $item->username, 'look' => $item->look, 'motto' => $item->motto, 'last_online' => $item->last_online, ])); } public function confirmTwoFactorAuthentication(string $code): bool { $secret = $this->two_factor_secret; if ($secret === null) { return false; } $codeIsValid = app(TwoFactorAuthenticationProvider::class) ->verify(decrypt((string) $secret), $code); if (! $codeIsValid) { return false; } $this->update(['two_factor_confirmed' => true]); return true; } public function hasAppliedForPosition(int $rankId): bool { return $this->applications()->where('rank_id', $rankId)->exists(); } public function changePassword(string $newPassword): void { $this->password = Hash::make($newPassword); $this->save(); } public function getFilamentName(): string { return $this->username ?? 'Guest'; } public function canAccessPanel(Panel $panel): bool { return hasHousekeepingPermission('can_access_housekeeping'); } public function getActivitylogOptions(): LogOptions { return LogOptions::defaults() ->logOnly(['id', 'username', 'motto', 'rank', 'credits']) ->logOnlyDirty(); } /** * @param array $options */ #[\Override] public function save(array $options = []): bool { if (! $this->isDirty()) { return false; } return parent::save($options); } public function hasAppliedForTeam(int $teamId): bool { if ($teamId === 0) { return false; } return $this->applications() ->where('team_id', $teamId) ->exists(); } }