2022_01_22_231856_improve_node_table.php 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. <?php
  2. use App\Components\MigrationToolBox;
  3. use App\Models\Config;
  4. use App\Models\Node;
  5. use Illuminate\Database\Migrations\Migration;
  6. use Illuminate\Database\Schema\Blueprint;
  7. use Illuminate\Support\Facades\Schema;
  8. class ImproveNodeTable extends Migration
  9. {
  10. /**
  11. * Run the migrations.
  12. *
  13. * @return void
  14. */
  15. protected $configs = [
  16. 'stripe_currency',
  17. ];
  18. public function up()
  19. {
  20. foreach ($this->configs as $config) {
  21. Config::insertOrIgnore(['name' => $config]);
  22. }
  23. // 插入新字段
  24. Schema::table('node', function (Blueprint $table) {
  25. if ((new MigrationToolBox())->versionCheck()) {
  26. $table->json('profile')->comment('节点设置选项')->after('description');
  27. } else {
  28. $table->text('profile')->comment('节点设置选项')->after('description');
  29. }
  30. $table->unsignedInteger('relay_node_id')->nullable()->comment('中转节点对接母节点, 默认NULL')->after('is_relay');
  31. });
  32. foreach (Node::all() as $node) {
  33. $profile = null;
  34. switch ($node->type) {
  35. case 0:
  36. $profile = [
  37. 'method' => $node->method,
  38. ];
  39. break;
  40. case 2:
  41. $profile = [
  42. 'method' => $node->v2_method,
  43. 'v2_alter_id' => $node->v2_alter_id,
  44. 'v2_net' => $node->v2_net,
  45. 'v2_type' => $node->v2_type,
  46. 'v2_host' => $node->v2_host,
  47. 'v2_path' => $node->v2_path,
  48. 'v2_tls' => $node->v2_tls ? 'tls' : '',
  49. 'v2_sni' => $node->v2_sni,
  50. ];
  51. break;
  52. case 3:
  53. $profile = [
  54. 'allow_insecure' => false,
  55. ];
  56. break;
  57. case 1:
  58. case 4:
  59. $profile = [
  60. 'method' => $node->method,
  61. 'protocol' => $node->protocol,
  62. 'obfs' => $node->obfs,
  63. 'obfs_param' => $node->obfs_param,
  64. 'protocol_param' => $node->protocol_param,
  65. 'passwd' => $node->passwd,
  66. ];
  67. break;
  68. default:
  69. }
  70. $node->update(['profile' => $profile]);
  71. if ($node->relay_server && $node->relay_port) { // 创建 中转线路
  72. $relayNodeData = [
  73. 'type' => 0,
  74. 'name' => $node->name.'↔️',
  75. 'country_code' => $node->country_code,
  76. 'port' => $node->relay_port,
  77. 'level' => $node->level,
  78. 'rule_group_id' => $node->rule_group_id,
  79. 'speed_limit' => $node->speed_limit,
  80. 'client_limit' => $node->client_limit,
  81. 'description' => $node->description,
  82. 'geo' => $node->geo,
  83. 'traffic_rate' => $node->traffic_rate,
  84. 'relay_node_id' => $node->id,
  85. 'is_udp' => $node->is_udp,
  86. 'push_port' => $node->push_port,
  87. 'detection_type' => $node->detection_type,
  88. 'sort' => $node->sort,
  89. 'status' => $node->status,
  90. ];
  91. if (filter_var($node->relay_server, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  92. $relayNodeData['ip'] = $node->relay_server;
  93. } elseif (filter_var($node->relay_server, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
  94. $relayNodeData['ipv6'] = $node->relay_server;
  95. } else {
  96. $relayNodeData['server'] = $node->relay_server;
  97. $ip = gethostbyname($node->relay_server);
  98. if ($ip) {
  99. $relayNodeData['ip'] = $ip;
  100. }
  101. }
  102. Node::create($relayNodeData);
  103. }
  104. }
  105. // 销毁老字段
  106. Schema::table('node', function (Blueprint $table) {
  107. $table->dropColumn('relay_server', 'relay_port', 'method', 'protocol', 'protocol_param', 'obfs', 'obfs_param', 'compatible', 'single', 'passwd', 'v2_alter_id',
  108. 'v2_method', 'v2_net', 'v2_type', 'v2_host', 'v2_path', 'v2_tls', 'v2_sni', 'tls_provider', 'is_relay');
  109. });
  110. }
  111. /**
  112. * Reverse the migrations.
  113. *
  114. * @return void
  115. */
  116. public function down()
  117. {
  118. Config::destroy($this->configs);
  119. Schema::table('node', function (Blueprint $table) { // 回滚老字段
  120. $table->string('relay_server')->nullable()->comment('中转地址');
  121. $table->unsignedSmallInteger('relay_port')->nullable()->comment('中转端口');
  122. $table->string('method', 32)->default('aes-256-cfb')->comment('加密方式');
  123. $table->string('protocol', 64)->default('origin')->comment('协议');
  124. $table->string('protocol_param', 128)->nullable()->comment('协议参数');
  125. $table->string('obfs', 64)->default('plain')->comment('混淆');
  126. $table->string('obfs_param')->nullable()->comment('混淆参数');
  127. $table->boolean('compatible')->default(0)->comment('兼容SS');
  128. $table->boolean('single')->default(0)->comment('启用单端口功能:0-否、1-是');
  129. $table->string('passwd')->nullable()->comment('单端口的连接密码');
  130. $table->unsignedSmallInteger('v2_alter_id')->default(16)->comment('V2Ray额外ID');
  131. $table->string('v2_method', 32)->default('aes-128-gcm')->comment('V2Ray加密方式');
  132. $table->string('v2_net', 16)->default('tcp')->comment('V2Ray传输协议');
  133. $table->string('v2_type', 32)->default('none')->comment('V2Ray伪装类型');
  134. $table->string('v2_host')->nullable()->comment('V2Ray伪装的域名');
  135. $table->string('v2_path')->nullable()->comment('V2Ray的WS/H2路径');
  136. $table->boolean('v2_tls')->default(0)->comment('V2Ray连接TLS:0-未开启、1-开启');
  137. $table->string('v2_sni', 191)->nullable()->comment('V2Ray的SNI配置');
  138. $table->text('tls_provider')->nullable()->comment('V2Ray节点的TLS提供商授权信息');
  139. $table->boolean('is_relay')->default(0)->comment('是否中转节点:0-否、1-是');
  140. });
  141. foreach (Node::all() as $node) {
  142. if ($node->relay_node_id) { // 回滚中转节点
  143. $pNode = Node::find($node->relay_node_id);
  144. $pNode->is_relay = 1;
  145. $pNode->relay_server = $node->server ?: $node->ip;
  146. $pNode->relay_port = $node->port;
  147. $pNode->save();
  148. try {
  149. $node->delete();
  150. } catch (Exception $e) {
  151. Log::emergency('中转删除失败,请手动在数据库中删除; '.$e->getMessage());
  152. }
  153. continue;
  154. }
  155. switch ($node->type) { // 回滚节点配置
  156. case 0:
  157. $node->method = $node->profile['method'];
  158. break;
  159. case 2:
  160. $node->v2_method = $node->profile['method'];
  161. $node->v2_alter_id = $node->profile['v2_alter_id'];
  162. $node->v2_net = $node->profile['v2_net'];
  163. $node->v2_type = $node->profile['v2_type'];
  164. $node->v2_host = $node->profile['v2_host'];
  165. $node->v2_path = $node->profile['v2_path'];
  166. $node->v2_tls = $node->profile['v2_tls'] ? 1 : 0;
  167. $node->v2_sni = $node->profile['v2_sni'];
  168. break;
  169. case 1:
  170. case 4:
  171. $node->method = $node->profile['method'];
  172. $node->protocol = $node->profile['protocol'];
  173. $node->obfs = $node->profile['obfs'];
  174. $node->obfs_param = $node->profile['obfs_param'];
  175. $node->protocol_param = $node->profile['protocol_param'];
  176. $node->single = $node->profile['passwd'] ? 1 : 0;
  177. $node->passwd = $node->profile['passwd'];
  178. break;
  179. default:
  180. }
  181. $node->save();
  182. }
  183. // 回滚新字段
  184. Schema::table('node', function (Blueprint $table) {
  185. $table->dropColumn('profile', 'relay_node_id');
  186. });
  187. }
  188. }