User.php 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <?php
  2. namespace App\Models;
  3. use Hash;
  4. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  5. use Illuminate\Database\Eloquent\Relations\HasMany;
  6. use Illuminate\Database\Eloquent\Relations\HasManyThrough;
  7. use Illuminate\Database\Eloquent\Relations\HasOne;
  8. use Illuminate\Foundation\Auth\User as Authenticatable;
  9. use Illuminate\Notifications\Notifiable;
  10. use Kyslik\ColumnSortable\Sortable;
  11. use Spatie\Permission\Traits\HasRoles;
  12. /**
  13. * 用户信息.
  14. */
  15. class User extends Authenticatable
  16. {
  17. use Notifiable, HasRoles, Sortable;
  18. public $sortable = ['id', 'credit', 'port', 't', 'expired_at'];
  19. protected $table = 'user';
  20. protected $casts = ['expired_at' => 'date:Y-m-d', 'reset_time' => 'date:Y-m-d', 'ban_time' => 'date:Y-m-d'];
  21. protected $guarded = [];
  22. public function routeNotificationForMail($notification)
  23. {
  24. return $this->username;
  25. }
  26. public function usedTrafficPercentage()
  27. {
  28. return round(($this->used_traffic) / $this->transfer_enable, 2);
  29. }
  30. public function getUsedTrafficAttribute(): int
  31. {
  32. return $this->d + $this->u;
  33. }
  34. public function getExpirationDateAttribute()
  35. {
  36. return $this->attributes['expired_at'];
  37. }
  38. public function getResetDateAttribute()
  39. {
  40. return $this->attributes['reset_time'];
  41. }
  42. public function getTelegramUserIdAttribute()
  43. {
  44. $telegram = $this->userAuths()->whereType('telegram')->first();
  45. return $telegram->identifier ?? null;
  46. }
  47. public function userAuths(): HasMany
  48. {
  49. return $this->hasMany(UserOauth::class);
  50. }
  51. public function profile()
  52. {
  53. return [
  54. 'id' => $this->id,
  55. 'nickname' => $this->nickname,
  56. 'account' => $this->username,
  57. 'port' => $this->port,
  58. 'passwd' => $this->passwd,
  59. 'uuid' => $this->vmess_id,
  60. 'transfer_enable' => $this->transfer_enable,
  61. 'u' => $this->u,
  62. 'd' => $this->d,
  63. 't' => $this->t,
  64. 'enable' => $this->enable,
  65. 'speed_limit' => $this->speed_limit,
  66. 'credit' => $this->credit,
  67. 'expired_at' => $this->expired_at,
  68. 'ban_time' => $this->ban_time,
  69. 'level' => $this->level_name,
  70. 'group' => $this->userGroup->name ?? null,
  71. 'last_login' => $this->last_login,
  72. 'reset_time' => $this->reset_time,
  73. 'invite_num' => $this->invite_num,
  74. 'status' => $this->status,
  75. ];
  76. }
  77. public function onlineIpLogs(): HasMany
  78. {
  79. return $this->hasMany(NodeOnlineIp::class);
  80. }
  81. public function payments(): HasMany
  82. {
  83. return $this->hasMany(Payment::class);
  84. }
  85. public function commissionSettlements(): HasMany
  86. {
  87. return $this->hasMany(ReferralApply::class);
  88. }
  89. public function commissionLogs(): HasMany
  90. {
  91. return $this->hasMany(ReferralLog::class, 'inviter_id');
  92. }
  93. public function ruleLogs(): HasMany
  94. {
  95. return $this->hasMany(RuleLog::class);
  96. }
  97. public function tickets(): HasMany
  98. {
  99. return $this->hasMany(Ticket::class);
  100. }
  101. public function ticketReplies(): HasMany
  102. {
  103. return $this->hasMany(TicketReply::class);
  104. }
  105. public function banedLogs(): HasMany
  106. {
  107. return $this->hasMany(UserBanedLog::class);
  108. }
  109. public function creditLogs(): HasMany
  110. {
  111. return $this->hasMany(UserCreditLog::class);
  112. }
  113. public function dailyDataFlows(): HasMany
  114. {
  115. return $this->hasMany(UserDailyDataFlow::class);
  116. }
  117. public function dataFlowLogs(): HasMany
  118. {
  119. return $this->hasMany(UserDataFlowLog::class);
  120. }
  121. public function dataModifyLogs(): HasMany
  122. {
  123. return $this->hasMany(UserDataModifyLog::class);
  124. }
  125. public function hourlyDataFlows(): HasMany
  126. {
  127. return $this->HasMany(UserHourlyDataFlow::class);
  128. }
  129. public function loginLogs(): HasMany
  130. {
  131. return $this->HasMany(UserLoginLog::class);
  132. }
  133. public function subscribe(): HasOne
  134. {
  135. return $this->hasOne(UserSubscribe::class);
  136. }
  137. public function subUrl()
  138. {
  139. return route('sub', $this->subscribe->code);
  140. }
  141. public function subscribeLogs(): HasManyThrough
  142. {
  143. return $this->hasManyThrough(UserSubscribeLog::class, UserSubscribe::class);
  144. }
  145. public function verify(): HasMany
  146. {
  147. return $this->hasMany(Verify::class);
  148. }
  149. public function inviter(): BelongsTo
  150. {
  151. return $this->belongsTo(__CLASS__);
  152. }
  153. public function invites(): HasMany
  154. {
  155. return $this->hasMany(Invite::class, 'inviter_id');
  156. }
  157. public function invitees(): HasMany
  158. {
  159. return $this->hasMany(__CLASS__, 'inviter_id');
  160. }
  161. public function getLevelNameAttribute(): string
  162. {
  163. return Level::whereLevel($this->attributes['level'])->first()->name;
  164. }
  165. public function getCreditAttribute()
  166. {
  167. return $this->attributes['credit'] / 100;
  168. }
  169. public function getTransferEnableFormattedAttribute()
  170. {
  171. return flowAutoShow($this->attributes['transfer_enable']);
  172. }
  173. public function getSpeedLimitAttribute()
  174. {
  175. return $this->attributes['speed_limit'] / Mbps;
  176. }
  177. public function setPasswordAttribute($password)
  178. {
  179. return $this->attributes['password'] = Hash::make($password);
  180. }
  181. public function setCreditAttribute($value)
  182. {
  183. return $this->attributes['credit'] = $value * 100;
  184. }
  185. public function setSpeedLimitAttribute($value)
  186. {
  187. return $this->attributes['speed_limit'] = $value * Mbps;
  188. }
  189. public function getAvatarAttribute(): string
  190. {
  191. if ($this->qq) {
  192. $url = "https://q1.qlogo.cn/g?b=qq&nk={$this->qq}&s=640";
  193. } elseif (stripos(strtolower($this->username), '@qq.com') !== false) {
  194. $url = "https://q1.qlogo.cn/g?b=qq&nk={$this->username}&s=640";
  195. } else {
  196. // $url = 'https://gravatar.loli.net/avatar/'.md5(strtolower(trim($this->username)))."?&d=identicon";
  197. // $url = 'https://robohash.org/'.md5(strtolower(trim($this->username))).'?set=set4&bgset=bg2&size=400x400';
  198. $url = 'https://api.btstu.cn/sjtx/api.php?lx=c1&format=images&method=zsy';
  199. }
  200. return $url;
  201. }
  202. public function scopeActiveUser($query)
  203. {
  204. return $query->where('status', '<>', -1)->whereEnable(1);
  205. }
  206. public function scopeBannedUser($query)
  207. {
  208. return $query->where('status', '>=', 0)->whereEnable(0);
  209. }
  210. public function nodes($userLevel = -1, $userGroupId = -1)
  211. {
  212. if ($userGroupId === -1 && $this->attributes['user_group_id']) {
  213. $query = $this->userGroup->nodes();
  214. } elseif ($userGroupId !== -1 && $userGroupId) {
  215. $query = UserGroup::findOrFail($userGroupId)->nodes();
  216. } else {
  217. $query = Node::query();
  218. }
  219. return $query->whereStatus(1)->where('level', '<=', $userLevel !== -1 && $userLevel !== null ? $userLevel : $this->attributes['level'] ?? 0);
  220. }
  221. public function userGroup(): BelongsTo
  222. {
  223. return $this->belongsTo(UserGroup::class);
  224. }
  225. public function getIsAvailableAttribute(): bool
  226. {
  227. return ! $this->ban_time && $this->transfer_enable && $this->expired_at > time();
  228. }
  229. public function updateCredit(float $credit): bool
  230. {
  231. $this->credit += $credit;
  232. return $this->credit >= 0 && $this->save();
  233. }
  234. public function incrementData(int $data): bool
  235. { // 添加用户流量
  236. $this->transfer_enable += $data;
  237. return $this->save();
  238. }
  239. public function isNotCompleteOrderByUserId(int $userId): bool
  240. { // 添加用户余额
  241. return Order::uid($userId)->whereIn('status', [0, 1])->exists();
  242. }
  243. public function trafficFetch(int $u, int $d): bool
  244. {
  245. $this->u += $u;
  246. $this->d += $d;
  247. return $this->save();
  248. }
  249. public function expiration_status(): int
  250. {
  251. $today = date('Y-m-d');
  252. $nextMonth = date('Y-m-d', strtotime('next month'));
  253. if ($this->expiration_date < $today) {
  254. $status = 0; // 已过期
  255. } elseif ($this->expiration_date === $today) {
  256. $status = 1; // 今日过期
  257. } elseif ($this->expiration_date <= $nextMonth) {
  258. $status = 2; // 一个月内过期
  259. }
  260. return $status ?? 3;
  261. }
  262. public function isTrafficWarning(): bool
  263. { // 流量异常警告
  264. return (sysConfig('traffic_ban_value') * GB) <= $this->recentTrafficUsed();
  265. }
  266. public function recentTrafficUsed()
  267. {
  268. return UserHourlyDataFlow::userRecentUsed($this->id)->sum('total');
  269. }
  270. public function activePayingUser()
  271. { //付费用户判断
  272. return $this->orders()->active()->where('origin_amount', '>', 0)->exists();
  273. }
  274. public function orders(): HasMany
  275. {
  276. return $this->hasMany(Order::class);
  277. }
  278. public function routeNotificationForTelegram()
  279. {
  280. return $this->telegram_user_id;
  281. }
  282. }