Browse Source

refactor: merge xcat commands & code clean up

Cat 3 năm trước cách đây
mục cha
commit
ba0b3fd52d

+ 0 - 6
config/.config.example.php

@@ -38,12 +38,6 @@ $_ENV['streaming_media_unlock_multiplexing'] = [
 $_ENV['mail_filter']        = 0;            //0: 关闭; 1: 白名单模式; 2; 黑名单模式;
 $_ENV['mail_filter_list']   = array("qq.com", "vip.qq.com", "foxmail.com");
 
-
-//备份设置--------------------------------------------------------------------------------------------
-$_ENV['auto_backup_email']  = '';                               //接收备份的邮箱
-$_ENV['auto_backup_password'] = '';                               //备份的压缩密码
-$_ENV['backup_notify']      = false;                            //备份通知到TG群中
-
 //已注册用户设置---------------------------------------------------------------------------------------
 #基础
 $_ENV['enable_checkin']             = true;         //是否啓用簽到功能

+ 0 - 30
config/settings.json

@@ -569,26 +569,6 @@
         "default": "",
         "mark": "aws ses发送者"
     },
-    {
-        "id": null,
-        "item": "auto_backup_email",
-        "value": "",
-        "class": "backup",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "接收备份的邮箱"
-    },
-    {
-        "id": null,
-        "item": "auto_backup_password",
-        "value": "",
-        "class": "backup",
-        "is_public": 0,
-        "type": "string",
-        "default": "",
-        "mark": "备份的压缩密码"
-    },
     {
         "id": null,
         "item": "enable_admin_contact",
@@ -759,16 +739,6 @@
         "default": "350px",
         "mark": "pmw_height"
     },
-    {
-        "id": null,
-        "item": "auto_backup_notify",
-        "value": "0",
-        "class": "backup",
-        "is_public": 0,
-        "type": "bool",
-        "default": "0",
-        "mark": "备份是否通知到用户群中"
-    },
     {
         "id": null,
         "item": "reg_mode",

+ 0 - 1
phpinsights.php

@@ -33,7 +33,6 @@ return [
         PHP_CodeSniffer\Standards\PSR1\Sniffs\Methods\CamelCapsMethodNameSniff::class => [
             'exclude' => [
                 'src/Command/Job.php',
-                'src/Command/PortAutoChange.php',
             ],
         ],
         // Db migration should not have a class declaration

+ 0 - 123
public/assets/css/index.css

@@ -1,123 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Roboto+Mono');
-@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC');
-
-.center-xy {
-  // width: inherit;
-  top: 10%;
-  left: 20%;
-  right: 20%;
-  position: absolute;
-  padding-bottom: 5%;
-}
-
-html, body {
-  font-family: 'Roboto Mono', 'Noto Sans SC', monospace;
-  font-size: 16px;
-}
-
-html {
-  box-sizing: border-box;
-  user-select: none;
-}
-
-body {
-  background-color: #000;
-}
-
-.container {
-  width: 100%;
-}
-
-.copy-container {
-  text-align: center;
-}
-
-.logo img {
-	max-width: 100px;
-	border-radius: 50%;
-	margin: 1em 0 1em 0;
-	box-shadow: 0 0 5px 0 #afafaf;
-	user-select: none;
-}
-
-table, td, th {
-  color: white;
-  border: 2px solid white;
-  height: 60px;
-}
-
-table {
-  margin-left: auto;
-  margin-right: auto;
-  width: 60%;
-  border-collapse: collapse;
-}
-
-.btn {
-  border: 2px solid white;
-  background-color: black;
-  color: black;
-  padding: 14px 28px;
-  font-size: 22px;
-  cursor: pointer;
-}
-
-.white {
-  border-color: #e7e7e7;
-}
-
-.white:hover {
-  color: #000;
-  background: #e7e7e7;
-}
-
-.white:hover a {
-  color: #000;
-  text-decoration: none;
-}
-
-ul {
-  list-style-type: none;
-  padding: 0;
-  margin: 0;
-}
-
-h {
-  color: #fff;
-  font-size: 40px;
-  letter-spacing: .2px;
-  margin: 0;
-}
-
-h1 {
-  color: #fff;
-  font-size: 24px;
-  letter-spacing: .2px;
-  margin: 0;
-}
-
-h2 {
-  color: #fff;
-  font-size: 22px;
-  letter-spacing: .2px;
-  margin: 0;
-}
-
-li {
-   color: #fff;
-   font-size: 22px;
-   letter-spacing: .2px;
-   margin: 0;
-}
-
-p {
-  color: #fff;
-  font-size: 20px;
-  letter-spacing: .2px;
-  margin: 0;
-}
-
-a {
-  color: #fff;
-  text-decoration: none;
-}

+ 0 - 1
public/assets/css/index.min.css

@@ -1 +0,0 @@
-@import url(https://fonts.googleapis.com/css2?family=Roboto+Mono);@import url(https://fonts.googleapis.com/css2?family=Noto+Sans+SC);.center-xy{top:10%;left:20%;right:20%;position:absolute;padding-bottom:5%}body,html{font-family:'Roboto Mono','Noto Sans SC',monospace;font-size:16px}html{box-sizing:border-box;user-select:none}body{background-color:#000}.container{width:100%}.copy-container{text-align:center}.logo img{max-width:100px;border-radius:50%;margin:1em 0 1em 0;box-shadow:0 0 5px 0 #afafaf;user-select:none}table,td,th{color:#fff;border:2px solid #fff;height:60px}table{margin-left:auto;margin-right:auto;width:60%;border-collapse:collapse}.btn{border:2px solid #fff;background-color:#000;color:#000;padding:14px 28px;font-size:22px;cursor:pointer}.white{border-color:#e7e7e7}.white:hover{color:#000;background:#e7e7e7}.white:hover a{color:#000;text-decoration:none}ul{list-style-type:none;padding:0;margin:0}h{color:#fff;font-size:40px;letter-spacing:.2px;margin:0}h1{color:#fff;font-size:24px;letter-spacing:.2px;margin:0}h2{color:#fff;font-size:22px;letter-spacing:.2px;margin:0}li{color:#fff;font-size:22px;letter-spacing:.2px;margin:0}p{color:#fff;font-size:20px;letter-spacing:.2px;margin:0}a{color:#fff;text-decoration:none}

+ 0 - 57
public/assets/css/mikufont.css

@@ -1,57 +0,0 @@
-
-/* source-sans-pro-300italic */
-@font-face {
-  font-family: 'Source Sans Pro';
-  font-style: italic;
-  font-weight: 300;
-  src: url('../fonts/source-sans-pro-300italic.eot'); /* IE9 Compat Modes */
-  src: local('Source Sans Pro'), local('SourceSans Pro-Italic'),
-       url('../fonts/source-sans-pro-300italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('../fonts/source-sans-pro-300italic.woff2') format('woff2'), /* Super Modern Browsers */
-       url('../fonts/source-sans-pro-300italic.woff') format('woff'), /* Modern Browsers */
-       url('../fonts/source-sans-pro-300italic.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('../fonts/source-sans-pro-300italic.svg#SourceSans Pro') format('svg'); /* Legacy iOS */
-}
-  
-/* source-sans-pro-600italic */
-@font-face {
-  font-family: 'Source Sans Pro';
-  font-style: italic;
-  font-weight: 600;
-  src: url('../fonts/source-sans-pro-600italic.eot'); /* IE9 Compat Modes */
-  src: local('Source Sans Pro'), local('SourceSans Pro-Italic'),
-       url('../fonts/source-sans-pro-600italic.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('../fonts/source-sans-pro-600italic.woff2') format('woff2'), /* Super Modern Browsers */
-       url('../fonts/source-sans-pro-600italic.woff') format('woff'), /* Modern Browsers */
-       url('../fonts/source-sans-pro-600italic.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('../fonts/source-sans-pro-600italic.svg#SourceSans Pro') format('svg'); /* Legacy iOS */
-}
-  
-/* source-sans-pro-300 */
-@font-face {
-  font-family: 'Source Sans Pro';
-  font-style: normal;
-  font-weight: 300;
-  src: url('../fonts/source-sans-pro-300.eot'); /* IE9 Compat Modes */
-  src: local('Source Sans Pro'), local('SourceSans Pro-Normal'),
-       url('../fonts/source-sans-pro-300.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('../fonts/source-sans-pro-300.woff2') format('woff2'), /* Super Modern Browsers */
-       url('../fonts/source-sans-pro-300.woff') format('woff'), /* Modern Browsers */
-       url('../fonts/source-sans-pro-300.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('../fonts/source-sans-pro-300.svg#SourceSans Pro') format('svg'); /* Legacy iOS */
-}
-  
-/* source-sans-pro-600 */
-@font-face {
-  font-family: 'Source Sans Pro';
-  font-style: normal;
-  font-weight: 600;
-  src: url('../fonts/source-sans-pro-600.eot'); /* IE9 Compat Modes */
-  src: local('Source Sans Pro'), local('SourceSans Pro-Normal'),
-       url('../fonts/source-sans-pro-600.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
-       url('../fonts/source-sans-pro-600.woff2') format('woff2'), /* Super Modern Browsers */
-       url('../fonts/source-sans-pro-600.woff') format('woff'), /* Modern Browsers */
-       url('../fonts/source-sans-pro-600.ttf') format('truetype'), /* Safari, Android, iOS */
-       url('../fonts/source-sans-pro-600.svg#SourceSans Pro') format('svg'); /* Legacy iOS */
-}
-  

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
public/assets/css/mikufont.min.css


+ 0 - 58
resources/views/material/admin/setting.tpl

@@ -49,9 +49,6 @@
                                             <li class="active">
                                                 <a data-toggle="tab" href="#email_auth_settings">&nbsp;设置</a>
                                             </li>
-                                            <li>
-                                                <a data-toggle="tab" href="#email_backup_settings">&nbsp;备份</a>
-                                            </li>
                                             <li>
                                                 <a data-toggle="tab" href="#smtp">&nbsp;smtp</a>
                                             </li>
@@ -94,31 +91,6 @@
                                         
                                         <button id="submit_email_test" type="submit" class="btn btn-brand btn-dense" {if $settings['mail_driver'] == "none"}disabled{/if}>测试</button>
                                     </div>
-                                    <div class="tab-pane fade" id="email_backup_settings">
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>需添加定时任务:php /this/is/your/website/path/xcat Backup full / simple</p>
-                                        <p class="form-control-guide"><i class="mdi mdi-information"></i>full 将整体数据备份;simple 将只备份核心数据</p>
-                                        <!-- auto_backup_email -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">接收备份的邮箱</label>
-                                            <input class="form-control maxwidth-edit" id="auto_backup_email" value="{$settings['auto_backup_email']}">
-                                        </div>
-                                        <!-- auto_backup_password -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">备份的压缩密码</label>
-                                            <input class="form-control maxwidth-edit" id="auto_backup_password" value="{$settings['auto_backup_password']}">
-                                            <p class="form-control-guide"><i class="mdi mdi-information"></i>留空将不加密备份压缩包</p>
-                                        </div>
-                                        <!-- auto_backup_notify -->
-                                        <div class="form-group form-group-label">
-                                            <label class="floating-label">备份是否通知到TG群中</label>
-                                            <select id="auto_backup_notify" class="form-control maxwidth-edit">
-                                                <option value="0" {if $settings['auto_backup_notify'] == "0"}selected{/if}>关闭</option>
-                                                <option value="1" {if $settings['auto_backup_notify'] == "1"}selected{/if}>开启</option>
-                                            </select>
-                                        </div>
-                                        
-                                        <button id="submit_email_backup" type="submit" class="btn btn-brand btn-dense">提交</button>
-                                    </div>
                                     <div class="tab-pane fade" id="smtp">
                                         <!-- smtp_host -->
                                         <div class="form-group form-group-label">
@@ -1567,36 +1539,6 @@
     })
 </script>
 
-<script>
-    window.addEventListener('load', () => {
-        $$.getElementById('submit_email_backup').addEventListener('click', () => {
-            $.ajax({
-                type: "POST",
-                url: "/admin/setting",
-                dataType: "json",
-                data: {
-                    class: 'email_backup',
-                    auto_backup_email: $$getValue('auto_backup_email'),
-                    auto_backup_password: $$getValue('auto_backup_password'),
-                    auto_backup_notify: $$getValue('auto_backup_notify')
-                },
-                success: data => {
-                    $("#result").modal();
-                    $$.getElementById('msg').innerHTML = data.msg;
-                    if (data.ret) {
-                        window.setTimeout("location.href='/admin/setting'", {$config['jump_delay']});
-                    }
-                },
-                error: jqXHR => {
-                    alert(`发生错误:${
-                            jqXHR.status
-                            }`);
-                }
-            })
-        })
-    })
-</script>
-
 <script>
     window.addEventListener('load', () => {
         $$.getElementById('submit_payjs_pay').addEventListener('click', () => {

+ 0 - 1
resources/views/material/index.tpl

@@ -12,6 +12,5 @@
         window.location.href = "/auth/login"
     </script>
     {/if}
-    <link rel="stylesheet" href="/assets/css/index.min.css">
 </head>
 </html>

+ 2 - 4
resources/views/material/tos.tpl

@@ -14,12 +14,10 @@
         <p>{$config['appName']},以下简称本站。</p>
         <br>
         <h2>隐私安全</h2>
-        <p>邮箱为本站服务的唯一凭证,请自行保管。</p>
-        <p>本站会以SHA256加密存储用户密码,所有服务器无日志形式运行。</p>
+        <p>邮箱为本站服务的唯一凭证,请妥善保管。</p>
         <br>
         <h2>使用条款</h2>
-        <p>禁止使用本站服务进行任何违法恶意活动。</p>
-        <p>使用任何服务,需遵循服务所属国家的相关法律。</p>
+        <p>在使用服务时,需遵循站点和节点所在国家的相关法律。</p>
         <p>对于免费用户,我们有权在不通知的情况下删除账户。</p>
         <p>任何违反使用条款的用户,我们将会删除违规账户并收回使用本站服务的权利。</p>
     </div>

+ 0 - 83
src/Command/Backup.php

@@ -1,83 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Command;
-
-use App\Models\Setting;
-use App\Services\Mail;
-use App\Utils\Telegram;
-use Exception;
-use RuntimeException;
-
-final class Backup extends Command
-{
-    public $description = <<<EOL
-├─=: php xcat Backup [选项]
-│ ├─ full                    - 整体数据备份
-│ ├─ simple                  - 只备份核心数据
-EOL;
-
-    public function boot(): void
-    {
-        if (count($this->argv) === 2) {
-            echo $this->description;
-        } else {
-            $methodName = $this->argv[2];
-            if ($methodName === 'full') {
-                $this->backup(true);
-            } else {
-                $this->backup(false);
-            }
-        }
-    }
-
-    public function backup($full = false)
-    {
-        $configs = Setting::getClass('backup');
-
-        ini_set('memory_limit', '-1');
-        $to = $configs['auto_backup_email'];
-        if ($to === null) {
-            return false;
-        }
-        if (! mkdir('/tmp/ssmodbackup/') && ! is_dir('/tmp/ssmodbackup/')) {
-            throw new RuntimeException(sprintf('Directory "%s" was not created', '/tmp/ssmodbackup/'));
-        }
-        $db_address_array = explode(':', $_ENV['db_host']);
-        if ($full) {
-            system('mysqldump --user=' . $_ENV['db_username'] . ' --password=' . $_ENV['db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . ' ' . $_ENV['db_database'] . ' > /tmp/ssmodbackup/mod.sql');
-        } else {
-            system(
-                'mysqldump --user=' . $_ENV['db_username'] . ' --password=' . $_ENV['db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . ' ' . $_ENV['db_database'] . ' announcement blockip bought code coupon link login_ip payback shop user_invite_code node user_password_reset ticket unblockip user user_token email_verify detect_list paylist > /tmp/ssmodbackup/mod.sql',
-                $ret
-            );
-            system(
-                'mysqldump --opt --user=' . $_ENV['db_username'] . ' --password=' . $_ENV['db_password'] . ' --host=' . $db_address_array[0] . ' ' . (isset($db_address_array[1]) ? '-P ' . $db_address_array[1] : '') . ' -d ' . $_ENV['db_database'] . ' alive_ip node_online_log detect_log telegram_session >> /tmp/ssmodbackup/mod.sql',
-                $ret
-            );
-        }
-
-        system('cp ' . BASE_PATH . '/config/.config.php /tmp/ssmodbackup/configbak.php', $ret);
-        echo $ret;
-        $backup_passwd = $configs['auto_backup_password'] === '' ? '' : ' -P ' . $configs['auto_backup_password'];
-        system('zip -r /tmp/ssmodbackup.zip /tmp/ssmodbackup/* ' . $backup_passwd, $ret);
-        $subject = $_ENV['appName'] . '-备份成功';
-        $text = '您好,系统已经为您自动备份,请查看附件,用您设定的密码解压。';
-        try {
-            Mail::send($to, $subject, 'news/backup.tpl', [
-                'text' => $text,
-            ], [
-                '/tmp/ssmodbackup.zip',
-            ]);
-        } catch (Exception $e) {
-            echo $e->getMessage();
-        }
-        system('rm -rf /tmp/ssmodbackup', $ret);
-        system('rm /tmp/ssmodbackup.zip', $ret);
-
-        if ($configs['auto_backup_notify'] === true) {
-            Telegram::send('备份工作已经完成');
-        }
-    }
-}

+ 0 - 239
src/Command/PortAutoChange.php

@@ -1,239 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-/**
- * [实验性] 检测到端口被墙则自动更换端口
- *
- * // 实验性,可能会有惊喜,请确保拥有承受能力
- * // 请通过 Crontab 启动,间隔建议 60 分钟以上
- */
-
-namespace App\Command;
-
-use App\Models\Node;
-use App\Models\User;
-
-final class PortAutoChange extends Command
-{
-    public $description = '├─=: php xcat PortAutoChange - 端口被墙则自动更换端口' . PHP_EOL;
-
-    /**
-     *  配置
-     */
-    private $Config = [
-        // 取端口范围最小值,新的端口将是之间的随机数
-        'port_min' => 23333,
-
-        // 取端口范围最大值,新的端口将是之间的随机数
-        'port_max' => 65535,
-
-        // 当某个使用的端口的被墙节点数量超过该端口使用总数量的百分比
-        // 超过该百分比时,直接更换单端口多用户节点(sort=9)和承载用户的端口
-        // 未超过时,对已被墙该端口的节点进行端口偏移
-        'mu_node_port_change_percent' => 60,
-
-        // 例外的节点,填写节点 ID,英文逗号分隔
-        // 此处提供的节点将不会进行端口更换
-        // 即使当原先的承载端口被更换时,也会将例外节点的端口偏移回去
-        'exception_node_id' => [],
-    ];
-
-    public function boot(): void
-    {
-        $gfw_port_nodes = [];
-        $nodes = Node::where(
-            static function ($query): void {
-                $query->where('sort', 0)
-                    ->orwhere('sort', 10);
-            }
-        )
-            ->where('mu_only', '>=', '0')
-            ->where('type', '1')
-            ->get();
-        foreach ($nodes as $node) {
-            $mu_nodes = Node::where('sort', 9)->where('type', '1')
-                ->where(
-                    static function ($query) use ($node): void {
-                        $query->Where('node_group', '=', $node->node_group)
-                            ->orWhere('node_group', '=', 0);
-                    }
-                )
-                ->where('node_class', '<=', $node->node_class)
-                ->get();
-            foreach ($mu_nodes as $mu_node) {
-                $mu_user = User::where('enable', 1)->where('is_multi_user', '<>', 0)->where('port', '=', $mu_node->server)->first();
-                if ($mu_user === null) {
-                    continue;
-                }
-                $port = $this->outPort($node, $mu_node->server);
-                $api_url = $_ENV['detect_gfw_url'];
-                $api_url = str_replace(
-                    ['{ip}', '{port}'],
-                    [$node->node_ip, $port],
-                    $api_url
-                );
-                $result_tcping = $this->DetectPort($api_url);
-                if ($result_tcping) {
-                    continue;
-                }
-                $gfw_port_nodes[$mu_node->server][] = $node->id;
-                echo '#' . $node->id . ' --- ' . $node->name . ' --- ' . $port . ' 端口不通' . PHP_EOL;
-            }
-        }
-        foreach ($gfw_port_nodes as $port => $array) {
-            $mu_node = Node::where('sort', 9)->where('server', '=', $port)->where('type', '1')->first();
-            $mu_user = User::where('enable', 1)->where('is_multi_user', '<>', 0)->where('port', '=', $port)->first();
-            if ($mu_node === null || $mu_user === null) {
-                continue;
-            }
-            $mu_port_nodes = Node::where(
-                static function ($query): void {
-                    $query->where('sort', 0)
-                        ->orwhere('sort', 10);
-                }
-            )
-                ->where(
-                    static function ($query) use ($mu_node): void {
-                        if ($mu_node->node_group === 0) {
-                            $query->where('node_group', '>=', 0);
-                        } else {
-                            $query->where('node_group', '=', $mu_node->node_group);
-                        }
-                    }
-                )
-                ->where('node_class', '>=', $mu_node->node_class)
-                ->where('mu_only', '>=', '0')
-                ->where('type', '1')
-                ->get();
-            for ($i = 0; $i <= 10; $i++) {
-                $new_port = rand((int) $this->Config['port_min'], (int) $this->Config['port_max']);
-                if (Node::where('sort', 9)->where('server', '=', $new_port)->first() === null && User::where('port', '=', $new_port)->first() === null) {
-                    break;
-                }
-            }
-            $number = count($array) / count($mu_port_nodes) * 100;
-            if ($number >= $this->Config['mu_node_port_change_percent']) {
-                echo '超过百分比:' . $number . '%' . PHP_EOL;
-                echo '#' . $mu_node->id . ' - 单端口承载节点 - ' . $mu_node->name . ' - 更换了新的端口 ' . $new_port . PHP_EOL;
-                $mu_node->server = $new_port;
-                $mu_node->save();
-                echo '#' . $mu_user->id . ' - 单端口承载用户 - ' . $mu_user->user_name . ' - 更换了新的端口 ' . $new_port . PHP_EOL;
-                $mu_user->port = $new_port;
-                $mu_user->save();
-                foreach ($mu_port_nodes as $mu_port_node) {
-                    $node_port = $this->outPort($mu_port_node, $port);
-                    if (\in_array($mu_port_node->id, $array) && ! \in_array($mu_port_node->id, $this->Config['exception_node_id'])) {
-                        if ($node_port !== $port) {
-                            if ($node_port === $new_port) {
-                                if (strpos($mu_port_node->server, $port . '#') !== false) {
-                                    for ($i = 0; $i <= 10; $i++) {
-                                        $new_mu_node_port = rand((int) $this->Config['port_min'], (int) $this->Config['port_max']);
-                                        if ($new_mu_node_port !== $new_port && Node::where('port', '=', $new_mu_node_port)->first() === null && User::where('port', '=', $new_mu_node_port)->first() === null) {
-                                            break;
-                                        }
-                                    }
-                                    $mu_port_node->server = str_replace(($port . '#' . $node_port), ($new_port . '#' . $new_mu_node_port), $mu_port_node->server);
-                                    echo '#' . $mu_port_node->id . ' - 节点 - ' . $mu_port_node->name . ' - 端口从 ' . $node_port . ' 偏移到了新的端口 ' . $new_mu_node_port . PHP_EOL;
-                                }
-                            } else {
-                                if (strpos($mu_port_node->server, $port . '#') !== false) {
-                                    $mu_port_node->server = str_replace(('+' . $port . '#' . $node_port), '', $mu_port_node->server);
-                                    $mu_port_node->server = str_replace(($port . '#' . $node_port . '+'), '', $mu_port_node->server);
-                                    $mu_port_node->server = str_replace(($port . '#' . $node_port), '', $mu_port_node->server);
-                                    echo '#' . $mu_port_node->id . ' - 节点 - ' . $mu_port_node->name . ' - 端口从 ' . $node_port . ' 偏移到了新的端口 ' . $new_port . PHP_EOL;
-                                }
-                            }
-                        }
-                    } else {
-                        if ($node_port === $port) {
-                            if (strpos($mu_port_node->server, ';') !== false) {
-                                if (strpos($mu_port_node->server, 'port=') !== false) {
-                                    $mu_port_node->server = str_replace('port=', ('port=' . $new_port . '#' . $port . '+'), $mu_port_node->server);
-                                } else {
-                                    $mu_port_node->server .= ';port=' . $new_port . '#' . $port;
-                                }
-                            } else {
-                                $mu_port_node->server .= ';port=' . $new_port . '#' . $port;
-                            }
-                        } else {
-                            if (strpos($mu_port_node->server, $port . '#') !== false) {
-                                $mu_port_node->server = str_replace($port . '#', $new_port . '#', $mu_port_node->server);
-                            }
-                        }
-                        echo '#' . $mu_port_node->id . ' - 节点 - ' . $mu_port_node->name . ' - 由于端口未被墙或例外设置,已将端口偏移回原端口 ' . $node_port . PHP_EOL;
-                    }
-                    $mu_port_node->save();
-                }
-            } else {
-                foreach ($array as $node_id) {
-                    if (\in_array($node_id, $this->Config['exception_node_id'])) {
-                        continue;
-                    }
-                    $node = Node::find($node_id);
-                    $node_port = $this->outPort($node, $port);
-                    if ($node_port !== $port) {
-                        if (strpos($node->server, '#' . $node_port) !== false) {
-                            echo '#' . $node->id . ' - 节点 - ' . $node->name . ' - 端口从' . $node_port . '偏移到了新的端口 ' . $new_port . PHP_EOL;
-                            $node->server = str_replace('#' . $node_port, '#' . $new_port, $node->server);
-                        }
-                    } else {
-                        if (strpos($node->server, ';') !== false) {
-                            if (strpos($node->server, 'port=') !== false) {
-                                $node->server = str_replace('port=', ('port=' . $port . '#' . $new_port . '+'), $node->server);
-                            } else {
-                                $node->server .= ';port=' . $port . '#' . $new_port;
-                            }
-                        } else {
-                            $node->server .= ';port=' . $port . '#' . $new_port;
-                        }
-                        echo '#' . $node->id . ' - 节点 - ' . $node->name . ' - 端口从' . $node_port . '偏移到了新的端口 ' . $new_port . PHP_EOL;
-                    }
-                    $node->save();
-                }
-            }
-        }
-    }
-
-    public function outPort($node, $mu_port)
-    {
-        $node_port = $mu_port;
-        $item = $node->getArgs();
-
-        if (isset($item['port'])) {
-            if (strpos($item['port'], '#') !== false) {
-                if (strpos($item['port'], '+') !== false) {
-                    $args_explode = explode('+', $item['port']);
-                    foreach ($args_explode as $arg) {
-                        if ((int) substr($arg, 0, strpos($arg, '#')) === $mu_port) {
-                            $node_port = (int) substr($arg, strpos($arg, '#') + 1);
-                        }
-                    }
-                } else {
-                    if ((int) substr($item['port'], 0, strpos($item['port'], '#')) === $mu_port) {
-                        $node_port = (int) substr($item['port'], strpos($item['port'], '#') + 1);
-                    }
-                }
-            } else {
-                $node_port = $mu_port + (int) $item['port'];
-            }
-        }
-
-        return $node_port;
-    }
-
-    public function DetectPort($api_url)
-    {
-        $result_tcping = false;
-        $detect_time = $_ENV['detect_gfw_count'];
-        for ($i = 1; $i <= $detect_time; $i++) {
-            $json_tcping = \json_decode(file_get_contents($api_url), true);
-            if ($json_tcping['status'] === 'true') {
-                $result_tcping = true;
-                break;
-            }
-        }
-
-        return $result_tcping;
-    }
-}

+ 175 - 0
src/Command/Tool.php

@@ -6,8 +6,13 @@ namespace App\Command;
 
 use App\Models\Node;
 use App\Models\Setting;
+use App\Models\User as ModelsUser;
+use App\Utils\GA;
+use App\Utils\Hash;
 use App\Utils\QQWry;
 use App\Utils\Tools;
+use Exception;
+use Ramsey\Uuid\Uuid;
 
 final class Tool extends Command
 {
@@ -20,6 +25,13 @@ final class Tool extends Command
 │ ├─ importAllSettings       - 导入所有设置
 │ ├─ upgradeDatabase         - 升级(如果不存在的话初始化) 数据库
 │ ├─ resetNodePassword       - 重置所有节点通讯密钥
+│ ├─ getCookie               - 获取指定用户的 Cookie
+│ ├─ resetPort               - 重置单个用户端口
+│ ├─ createAdmin             - 创建管理员帐号
+│ ├─ resetAllPort            - 重置所有用户端口
+│ ├─ resetTraffic            - 重置所有用户流量
+│ ├─ generateUUID            - 为所有用户生成新的 UUID
+│ ├─ generateGa              - 为所有用户生成新的 Ga Secret;
 
 EOL;
 
@@ -173,4 +185,167 @@ EOL;
         }
         echo '已重置所有节点密码.' . PHP_EOL;
     }
+
+    /**
+     * 重置用户端口
+     */
+    public function resetPort(): void
+    {
+        fwrite(STDOUT, '请输入用户id: ');
+        $user = ModelsUser::find(trim(fgets(STDIN)));
+        if ($user !== null) {
+            $user->port = Tools::getAvPort();
+            if ($user->save()) {
+                echo '重置成功!';
+            }
+        } else {
+            echo 'not found user.';
+        }
+    }
+
+    /**
+     * 重置所有用户端口
+     */
+    public function resetAllPort(): void
+    {
+        $users = ModelsUser::all();
+        foreach ($users as $user) {
+            $origin_port = $user->port;
+            $user->port = Tools::getAvPort();
+            echo '$origin_port=' . $origin_port . '&$user->port=' . $user->port . PHP_EOL;
+            $user->save();
+        }
+    }
+
+    /**
+     * 重置所有用户流量
+     */
+    public function resetTraffic(): void
+    {
+        try {
+            ModelsUser::where('enable', 1)->update([
+                'd' => 0,
+                'u' => 0,
+                'last_day_t' => 0,
+            ]);
+        } catch (Exception $e) {
+            echo $e->getMessage();
+            return;
+        }
+        echo 'reset traffic successful';
+    }
+
+    /**
+     * 为所有用户生成新的UUID
+     */
+    public function generateUUID(): void
+    {
+        $users = ModelsUser::all();
+        $current_timestamp = \time();
+        foreach ($users as $user) {
+            /** @var ModelsUser $user */
+            $user->generateUUID($current_timestamp);
+        }
+        echo 'generate UUID successful';
+    }
+
+    /**
+     * 二次验证
+     */
+    public function generateGa(): void
+    {
+        $users = ModelsUser::all();
+        foreach ($users as $user) {
+            $ga = new GA();
+            $secret = $ga->createSecret();
+
+            $user->ga_token = $secret;
+            $user->save();
+        }
+        echo 'generate Ga Secret successful';
+    }
+
+    /**
+     * 创建 Admin 账户
+     */
+    public function createAdmin(): void
+    {
+        if (count($this->argv) === 3) {
+            // ask for input
+            fwrite(STDOUT, '(1/3) 请输入管理员邮箱:') . PHP_EOL;
+            // get input
+            $email = trim(fgets(STDIN));
+            if ($email === null) {
+                die("必须输入管理员邮箱.\r\n");
+            }
+
+            // write input back
+            fwrite(STDOUT, '(2/3) 请输入管理员账户密码:') . PHP_EOL;
+            $passwd = trim(fgets(STDIN));
+            if ($passwd === null) {
+                die("必须输入管理员密码.\r\n");
+            }
+
+            fwrite(STDOUT, '(3/3) 按 Y 或 y 确认创建:');
+            $y = trim(fgets(STDIN));
+        } elseif (count($this->argv) === 5) {
+            [,,, $email, $passwd] = $this->argv;
+            $y = 'y';
+        }
+
+        if (strtolower($y) === 'y') {
+            $current_timestamp = \time();
+            // create admin user
+            $configs = Setting::getClass('register');
+            // do reg user
+            $user = new ModelsUser();
+            $user->user_name = 'admin';
+            $user->email = $email;
+            $user->remark = 'admin';
+            $user->pass = Hash::passwordHash($passwd);
+            $user->passwd = Tools::genRandomChar(16);
+            $user->uuid = Uuid::uuid3(Uuid::NAMESPACE_DNS, $email . '|' . $current_timestamp);
+            $user->port = Tools::getLastPort() + 1;
+            $user->t = 0;
+            $user->u = 0;
+            $user->d = 0;
+            $user->transfer_enable = Tools::toGB($configs['sign_up_for_free_traffic']);
+            $user->invite_num = $configs['sign_up_for_invitation_codes'];
+            $user->ref_by = 0;
+            $user->is_admin = 1;
+            $user->expire_in = date('Y-m-d H:i:s', \time() + $configs['sign_up_for_free_time'] * 86400);
+            $user->reg_date = date('Y-m-d H:i:s');
+            $user->money = 0;
+            $user->im_type = 1;
+            $user->im_value = '';
+            $user->class = 0;
+            $user->node_speedlimit = 0;
+            $user->theme = $_ENV['theme'];
+
+            $ga = new GA();
+            $secret = $ga->createSecret();
+            $user->ga_token = $secret;
+            $user->ga_enable = 0;
+
+            if ($user->save()) {
+                echo '创建成功,请在主页登录' . PHP_EOL;
+            } else {
+                echo '创建失败,请检查数据库配置' . PHP_EOL;
+            }
+        } else {
+            echo '已取消创建' . PHP_EOL;
+        }
+    }
+
+    /**
+     * 获取 USERID 的 Cookie
+     */
+    public function getCookie(): void
+    {
+        if (count($this->argv) === 4) {
+            $user = ModelsUser::find($this->argv[3]);
+            $expire_in = 86400 + \time();
+            echo Hash::cookieHash($user->pass, $expire_in) . ' ' . $expire_in;
+        }
+    }
 }

+ 0 - 203
src/Command/User.php

@@ -1,203 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace App\Command;
-
-use App\Models\Setting;
-use App\Models\User as ModelsUser;
-use App\Utils\GA;
-use App\Utils\Hash;
-use App\Utils\Tools;
-use Exception;
-use Ramsey\Uuid\Uuid;
-
-final class User extends Command
-{
-    public $description = <<<EOL
-├─=: php xcat User [选项]
-│ ├─ getCookie               - 获取指定用户的 Cookie
-│ ├─ resetPort               - 重置单个用户端口
-│ ├─ createAdmin             - 创建管理员帐号
-│ ├─ resetAllPort            - 重置所有用户端口
-│ ├─ resetTraffic            - 重置所有用户流量
-│ ├─ generateUUID            - 为所有用户生成新的 UUID
-│ ├─ generateGa              - 为所有用户生成新的 Ga Secret;
-EOL;
-    public function boot(): void
-    {
-        if (count($this->argv) === 2) {
-            echo $this->description;
-        } else {
-            $methodName = $this->argv[2];
-            if (method_exists($this, $methodName)) {
-                $this->$methodName();
-            } else {
-                echo '方法不存在.';
-            }
-        }
-    }
-
-    /**
-     * 重置用户端口
-     */
-    public function resetPort(): void
-    {
-        fwrite(STDOUT, '请输入用户id: ');
-        $user = ModelsUser::find(trim(fgets(STDIN)));
-        if ($user !== null) {
-            $user->port = Tools::getAvPort();
-            if ($user->save()) {
-                echo '重置成功!';
-            }
-        } else {
-            echo 'not found user.';
-        }
-    }
-
-    /**
-     * 重置所有用户端口
-     */
-    public function resetAllPort(): void
-    {
-        $users = ModelsUser::all();
-        foreach ($users as $user) {
-            $origin_port = $user->port;
-            $user->port = Tools::getAvPort();
-            echo '$origin_port=' . $origin_port . '&$user->port=' . $user->port . PHP_EOL;
-            $user->save();
-        }
-    }
-
-    /**
-     * 重置所有用户流量
-     */
-    public function resetTraffic(): void
-    {
-        try {
-            ModelsUser::where('enable', 1)->update([
-                'd' => 0,
-                'u' => 0,
-                'last_day_t' => 0,
-            ]);
-        } catch (Exception $e) {
-            echo $e->getMessage();
-            return;
-        }
-        echo 'reset traffic successful';
-    }
-
-    /**
-     * 为所有用户生成新的UUID
-     */
-    public function generateUUID(): void
-    {
-        $users = ModelsUser::all();
-        $current_timestamp = \time();
-        foreach ($users as $user) {
-            /** @var ModelsUser $user */
-            $user->generateUUID($current_timestamp);
-        }
-        echo 'generate UUID successful';
-    }
-
-    /**
-     * 二次验证
-     */
-    public function generateGa(): void
-    {
-        $users = ModelsUser::all();
-        foreach ($users as $user) {
-            $ga = new GA();
-            $secret = $ga->createSecret();
-
-            $user->ga_token = $secret;
-            $user->save();
-        }
-        echo 'generate Ga Secret successful';
-    }
-
-    /**
-     * 创建 Admin 账户
-     */
-    public function createAdmin(): void
-    {
-        if (count($this->argv) === 3) {
-            // ask for input
-            fwrite(STDOUT, '(1/3) 请输入管理员邮箱:') . PHP_EOL;
-            // get input
-            $email = trim(fgets(STDIN));
-            if ($email === null) {
-                die("必须输入管理员邮箱.\r\n");
-            }
-
-            // write input back
-            fwrite(STDOUT, '(2/3) 请输入管理员账户密码:') . PHP_EOL;
-            $passwd = trim(fgets(STDIN));
-            if ($passwd === null) {
-                die("必须输入管理员密码.\r\n");
-            }
-
-            fwrite(STDOUT, '(3/3) 按 Y 或 y 确认创建:');
-            $y = trim(fgets(STDIN));
-        } elseif (count($this->argv) === 5) {
-            [,,, $email, $passwd] = $this->argv;
-            $y = 'y';
-        }
-
-        if (strtolower($y) === 'y') {
-            $current_timestamp = \time();
-            // create admin user
-            $configs = Setting::getClass('register');
-            // do reg user
-            $user = new ModelsUser();
-            $user->user_name = 'admin';
-            $user->email = $email;
-            $user->remark = 'admin';
-            $user->pass = Hash::passwordHash($passwd);
-            $user->passwd = Tools::genRandomChar(16);
-            $user->uuid = Uuid::uuid3(Uuid::NAMESPACE_DNS, $email . '|' . $current_timestamp);
-            $user->port = Tools::getLastPort() + 1;
-            $user->t = 0;
-            $user->u = 0;
-            $user->d = 0;
-            $user->transfer_enable = Tools::toGB($configs['sign_up_for_free_traffic']);
-            $user->invite_num = $configs['sign_up_for_invitation_codes'];
-            $user->ref_by = 0;
-            $user->is_admin = 1;
-            $user->expire_in = date('Y-m-d H:i:s', \time() + $configs['sign_up_for_free_time'] * 86400);
-            $user->reg_date = date('Y-m-d H:i:s');
-            $user->money = 0;
-            $user->im_type = 1;
-            $user->im_value = '';
-            $user->class = 0;
-            $user->node_speedlimit = 0;
-            $user->theme = $_ENV['theme'];
-
-            $ga = new GA();
-            $secret = $ga->createSecret();
-            $user->ga_token = $secret;
-            $user->ga_enable = 0;
-
-            if ($user->save()) {
-                echo '创建成功,请在主页登录' . PHP_EOL;
-            } else {
-                echo '创建失败,请检查数据库配置' . PHP_EOL;
-            }
-        } else {
-            echo '已取消创建' . PHP_EOL;
-        }
-    }
-
-    /**
-     * 获取 USERID 的 Cookie
-     */
-    public function getCookie(): void
-    {
-        if (count($this->argv) === 4) {
-            $user = ModelsUser::find($this->argv[3]);
-            $expire_in = 86400 + \time();
-            echo Hash::cookieHash($user->pass, $expire_in) . ' ' . $expire_in;
-        }
-    }
-}

+ 0 - 4
src/Controllers/Admin/SettingController.php

@@ -87,10 +87,6 @@ final class SettingController extends BaseController
             case 'verify_code_geetest':
                 $list = ['geetest_id', 'geetest_key'];
                 break;
-                // 备份
-            case 'email_backup':
-                $list = ['auto_backup_email', 'auto_backup_password', 'auto_backup_notify'];
-                break;
                 // 客户服务
             case 'admin_contact':
                 $list = ['enable_admin_contact', 'admin_contact1', 'admin_contact2', 'admin_contact3'];

+ 1 - 1
src/Services/Mail/SendGrid.php

@@ -46,7 +46,7 @@ final class SendGrid extends Base
                 'application/octet-stream',
                 basename($file),
                 'attachment',
-                'backup'
+                'attachment'
             );
         }
 

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác