Node.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. namespace App\Models;
  3. use App\Casts\data_rate;
  4. use App\Utils\IP;
  5. use Illuminate\Database\Eloquent\Collection;
  6. use Illuminate\Database\Eloquent\Model;
  7. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  8. use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  9. use Illuminate\Database\Eloquent\Relations\HasMany;
  10. use Illuminate\Database\Eloquent\Relations\HasOne;
  11. use Log;
  12. /**
  13. * 节点配置信息.
  14. */
  15. class Node extends Model
  16. {
  17. protected $table = 'node';
  18. protected $guarded = [];
  19. protected $casts = ['speed_limit' => data_rate::class, 'profile' => 'array'];
  20. public function labels(): BelongsToMany
  21. {
  22. return $this->belongsToMany(Label::class);
  23. }
  24. public function heartbeats(): HasMany
  25. {
  26. return $this->hasMany(NodeHeartbeat::class);
  27. }
  28. public function onlineIps(): HasMany
  29. {
  30. return $this->hasMany(NodeOnlineIp::class);
  31. }
  32. public function onlineLogs(): HasMany
  33. {
  34. return $this->hasMany(NodeOnlineLog::class);
  35. }
  36. public function userDataFlowLogs(): HasMany
  37. {
  38. return $this->hasMany(UserDataFlowLog::class);
  39. }
  40. public function ruleLogs(): HasMany
  41. {
  42. return $this->hasMany(RuleLog::class);
  43. }
  44. public function dailyDataFlows(): HasMany
  45. {
  46. return $this->hasMany(NodeDailyDataFlow::class);
  47. }
  48. public function hourlyDataFlows(): HasMany
  49. {
  50. return $this->hasMany(NodeHourlyDataFlow::class);
  51. }
  52. public function country(): HasOne
  53. {
  54. return $this->HasOne(Country::class, 'code', 'country_code');
  55. }
  56. public function ruleGroup(): BelongsTo
  57. {
  58. return $this->belongsTo(RuleGroup::class);
  59. }
  60. public function relayNode(): BelongsTo
  61. {
  62. return $this->belongsTo(__CLASS__);
  63. }
  64. public function childNodes(): hasMany
  65. {
  66. return $this->hasMany(__CLASS__, 'relay_node_id', 'id');
  67. }
  68. public function userGroups(): BelongsToMany
  69. {
  70. return $this->belongsToMany(UserGroup::class);
  71. }
  72. public function auth(): HasOne
  73. {
  74. return $this->hasOne(NodeAuth::class);
  75. }
  76. public function level_table(): HasOne
  77. {
  78. return $this->hasOne(Level::class, 'level', 'level');
  79. }
  80. public function users(): Collection
  81. {
  82. return User::activeUser()
  83. ->where('level', '>=', $this->attributes['level'])
  84. ->where(function ($query) {
  85. $query->whereIn('user_group_id', $this->userGroups->pluck('id'))->orWhereNull('user_group_id');
  86. })
  87. ->get();
  88. }
  89. public function refresh_geo(): bool
  90. {
  91. $ip = $this->ips();
  92. if ($ip !== []) {
  93. $data = IP::getIPGeo($ip[0]); // 复数IP都以第一个为准
  94. if ($data !== null) {
  95. self::withoutEvents(function () use ($data) {
  96. $this->update(['geo' => ($data['latitude'] ?? null).','.($data['longitude'] ?? null)]);
  97. });
  98. return true;
  99. }
  100. }
  101. return false;
  102. }
  103. public function ips(int $type = 4): array
  104. {
  105. // 使用DDNS的node先通过gethostbyname获取ip地址
  106. if ($this->attributes['is_ddns'] ?? 0) { // When ddns is enabled, only domain can be used to check the ip
  107. $ip = gethostbyname($this->attributes['server']);
  108. if (strcmp($ip, $this->attributes['server']) === 0) {
  109. Log::warning('获取 【'.$this->attributes['server'].'】 IP失败'.$ip);
  110. $ip = '';
  111. }
  112. } else {
  113. $ip = $type === 4 ? $this->attributes['ip'] : $this->attributes['ipv6']; // check the multiple existing of ip
  114. }
  115. return array_map('trim', explode(',', $ip));
  116. }
  117. public function getTypeLabelAttribute(): string
  118. {
  119. return match ($this->attributes['type']) {
  120. 0 => 'Shadowsocks',
  121. 1 => 'ShadowsocksR',
  122. 2 => 'V2Ray',
  123. 3 => 'Trojan',
  124. 4 => 'VNet',
  125. default => 'UnKnown',
  126. };
  127. }
  128. public function getHostAttribute(): string
  129. {
  130. return $this->server ?? $this->ip ?? $this->ipv6;
  131. }
  132. public function getSSRConfig(): array
  133. {
  134. return [
  135. 'id' => $this->id,
  136. 'method' => $this->profile['method'] ?? '',
  137. 'protocol' => $this->profile['protocol'] ?? '',
  138. 'obfs' => $this->profile['obfs'] ?? '',
  139. 'obfs_param' => $this->profile['obfs_param'] ?? '',
  140. 'is_udp' => (int) $this->is_udp,
  141. 'speed_limit' => $this->getRawOriginal('speed_limit'),
  142. 'client_limit' => $this->client_limit,
  143. 'single' => isset($this->profile['passwd']) ? 1 : 0,
  144. 'port' => (string) $this->port,
  145. 'passwd' => $this->profile['passwd'] ?? '',
  146. 'push_port' => $this->push_port,
  147. 'secret' => $this->auth->secret,
  148. 'redirect_url' => sysConfig('redirect_url'),
  149. ];
  150. }
  151. }