Node.php 5.9 KB

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