Browse Source

儿童节更新 (#668)

Master 儿童节更新

注意加入新的 config 选项
Anankke 6 years ago
parent
commit
246ab2f392
100 changed files with 4162 additions and 3894 deletions
  1. 22 0
      .editorconfig
  2. 0 47
      .github/ISSUE_TEMPLATE/new-issue.md
  3. 14 10
      .github/issue_template.md
  4. 3 4
      .gitignore
  5. 13 9
      .travis.yml
  6. 17 13
      README.md
  7. 26 26
      app/Command/DailyMail.php
  8. 15 14
      app/Command/ExtMail.php
  9. 178 191
      app/Command/FinanceMail.php
  10. 390 356
      app/Command/Job.php
  11. 64 67
      app/Command/SyncRadius.php
  12. 128 129
      app/Command/Update.php
  13. 136 115
      app/Command/XCat.php
  14. 64 46
      app/Controllers/Admin/AnnController.php
  15. 15 16
      app/Controllers/Admin/AutoController.php
  16. 34 35
      app/Controllers/Admin/CodeController.php
  17. 33 34
      app/Controllers/Admin/DetectController.php
  18. 43 45
      app/Controllers/Admin/IpController.php
  19. 134 140
      app/Controllers/Admin/NodeController.php
  20. 101 48
      app/Controllers/Admin/RelayController.php
  21. 106 110
      app/Controllers/Admin/ShopController.php
  22. 40 43
      app/Controllers/Admin/TicketController.php
  23. 364 189
      app/Controllers/Admin/UserController.php
  24. 73 47
      app/Controllers/AdminController.php
  25. 57 59
      app/Controllers/ApiController.php
  26. 145 122
      app/Controllers/AuthController.php
  27. 23 13
      app/Controllers/BaseController.php
  28. 13 12
      app/Controllers/Client/ClientApiController.php
  29. 51 26
      app/Controllers/HomeController.php
  30. 116 535
      app/Controllers/LinkController.php
  31. 80 47
      app/Controllers/Mod_Mu/FuncController.php
  32. 29 29
      app/Controllers/Mod_Mu/NodeController.php
  33. 62 65
      app/Controllers/Mod_Mu/UserController.php
  34. 9 9
      app/Controllers/Mu/NodeController.php
  35. 37 39
      app/Controllers/Mu/UserController.php
  36. 7 8
      app/Controllers/PasswordController.php
  37. 0 104
      app/Controllers/QuickPayFunction.php
  38. 182 103
      app/Controllers/RelayController.php
  39. 1 1
      app/Controllers/ResController.php
  40. 225 283
      app/Controllers/UserController.php
  41. 440 0
      app/Controllers/VueController.php
  42. 1 2
      app/Middleware/Admin.php
  43. 5 5
      app/Middleware/Api.php
  44. 2 4
      app/Middleware/Auth.php
  45. 1 2
      app/Middleware/Guest.php
  46. 10 11
      app/Middleware/Mod_Mu.php
  47. 10 11
      app/Middleware/Mu.php
  48. 2 5
      app/Models/Ann.php
  49. 4 7
      app/Models/Auto.php
  50. 6 9
      app/Models/BlockIp.php
  51. 11 11
      app/Models/Bought.php
  52. 2 2
      app/Models/CheckInLog.php
  53. 4 8
      app/Models/Code.php
  54. 1 1
      app/Models/Config.php
  55. 10 10
      app/Models/Coupon.php
  56. 14 20
      app/Models/DetectLog.php
  57. 2 3
      app/Models/DetectRule.php
  58. 2 3
      app/Models/Disconnect.php
  59. 2 3
      app/Models/EmailVerify.php
  60. 2 3
      app/Models/InviteCode.php
  61. 14 17
      app/Models/Ip.php
  62. 2 2
      app/Models/Link.php
  63. 9 12
      app/Models/LoginIp.php
  64. 0 1
      app/Models/Model.php
  65. 18 32
      app/Models/Node.php
  66. 6 5
      app/Models/NodeInfoLog.php
  67. 2 2
      app/Models/NodeOnlineLog.php
  68. 1 1
      app/Models/PasswordReset.php
  69. 5 5
      app/Models/Payback.php
  70. 1 1
      app/Models/Paylist.php
  71. 2 2
      app/Models/RadiusBan.php
  72. 2 2
      app/Models/RadiusNas.php
  73. 2 2
      app/Models/RadiusRadAcct.php
  74. 2 2
      app/Models/RadiusRadCheck.php
  75. 2 2
      app/Models/RadiusRadPostauth.php
  76. 2 2
      app/Models/RadiusRadUserGroup.php
  77. 14 15
      app/Models/Relay.php
  78. 2 3
      app/Models/Role.php
  79. 82 111
      app/Models/Shop.php
  80. 21 27
      app/Models/Speedtest.php
  81. 7 8
      app/Models/TelegramSession.php
  82. 8 9
      app/Models/Ticket.php
  83. 2 2
      app/Models/Token.php
  84. 13 13
      app/Models/TrafficLog.php
  85. 8 10
      app/Models/UnblockIp.php
  86. 94 82
      app/Models/User.php
  87. 0 17
      app/Models/YftOrder.php
  88. 1 1
      app/Services/Analytic.php
  89. 33 33
      app/Services/Analytics.php
  90. 2 0
      app/Services/Auth/Base.php
  91. 34 26
      app/Services/Auth/Cookie.php
  92. 5 5
      app/Services/Auth/JwtToken.php
  93. 9 10
      app/Services/Auth/Redis.php
  94. 2 2
      app/Services/Aws/Client.php
  95. 3 3
      app/Services/Aws/Factory.php
  96. 43 0
      app/Services/BitPayment.php
  97. 9 5
      app/Services/Boot.php
  98. 57 55
      app/Services/Config.php
  99. 39 36
      app/Services/Gateway/AbstractPayment.php
  100. 23 22
      app/Services/Gateway/AopF2F.php

+ 22 - 0
.editorconfig

@@ -0,0 +1,22 @@
+# https://editorconfig.org/
+
+root = true
+
+[*]
+tab_width                = 4
+
+[*.php]
+charset                  = utf-8
+end_of_line              = lf
+indent_size              = 4
+indent_style             = space
+trim_trailing_whitespace = true
+insert_final_newline     = true
+
+[*.md]
+charset                  = utf-8
+end_of_line              = lf
+indent_style             = space
+trim_trailing_whitespace = true
+insert_final_newline     = true
+max_line_length          = 80

+ 0 - 47
.github/ISSUE_TEMPLATE/new-issue.md

@@ -1,47 +0,0 @@
----
-name: New Issue
-about: Issue
-
----
-
-<!--
-
-如果你不填充下面的内容,我们可能会直接关闭你的 issue。
-
-请在标题简单描述内容
-
-如果你没有仔细阅读  Wiki ,或者无关问题,我们可能会直接关闭你的 issue。
-
-注意:Wiki 可能随时都会更新。在提交一个 issue 前,请重新查看相关内容。
--->
-
-
-
-**我确认我已经阅读了** (使用 "x" 选择)
-
-- [ ] [项目 Wiki ](https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki)
-- [ ] [项目其他 issue](https://github.com/NimaQu/ss-panel-v3-mod_Uim/issues?utf8=%E2%9C%93&q=is%3Aissue)
-
-**我确认我做到了** (使用 "x" 选择)
-
-- [ ] [将项目升级到当前分支最新版本](https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki/%E5%8D%87%E7%B4%9A%E7%89%88%E6%9C%AC)
-- [ ] 在[项目演示站](https://demo.nimaqu.com)成功复现问题
-
-**我正在申请**  (使用 "x" 选择)
-
-- [ ] 反馈一个 bug
-- [ ] 申请添加新的特性或功能或者好的想法
-
-
-
-<!-- ----------- -->
-
-**反馈BUG**
-
-1.请在面板路径下运行`git show HEAD`,然后贴出输出内容
-
-2.如果是页面问题(500 或 Slim Application Error ),请在 config 开启 debug 模式后截图或贴出输出内容,如果是某个按钮点击没反应,请打开浏览器开发者控制台(通常为 F12 ) ,贴出 console 输出内容
-
-<!-- ----------- -->
-
-**申请添加新的特性或功能或者好的想法**

+ 14 - 10
.github/ISSUE_TEMPLATE/issue.md → .github/issue_template.md

@@ -6,23 +6,28 @@ about: temlpate
 
 <!--
 
-如果你不填充下面的内容,我们可能会直接关闭你的 issue。
+如果你不仔细填写下面的内容,我们可能会直接关闭你的 issue。
 
 如果你没有仔细阅读  Wiki ,或者无关问题,我们可能会直接关闭你的 issue。
 
 注意:Wiki 可能随时都会更新。在提交一个 issue 前,请重新查看相关内容。
+
+如果你还有什么别的小问题请加入群组 https://t.me/SSUnion
+
+不要用你的 issue 污染几百个 watchers 的邮箱
+
 -->
 
 
 
 **我确认我已经阅读了** (使用 "x" 选择)
 
-- [ ] [项目 Wiki ](https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki)
-- [ ] [项目其他 issue](https://github.com/NimaQu/ss-panel-v3-mod_Uim/issues?utf8=%E2%9C%93&q=is%3Aissue)
+- [ ] [项目 Wiki ](https://github.com/Anankke/ss-panel-v3-mod_Uim/wiki)
+- [ ] [项目其他 issue](https://github.com/Anankke/ss-panel-v3-mod_Uim/issues?utf8=%E2%9C%93&q=is%3Aissue)
 
 **我确认我做到了** (使用 "x" 选择)
 
-- [ ] [将项目升级到当前分支最新版本](https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki/%E5%8D%87%E7%B4%9A%E7%89%88%E6%9C%AC)
+- [ ] [将项目升级到当前分支最新版本](https://github.com/Anankke/ss-panel-v3-mod_Uim/wiki/%E5%8D%87%E7%B4%9A%E7%89%88%E6%9C%AC)
 - [ ] 在[项目演示站](https://demo.nimaqu.com)成功复现问题
 
 **我正在申请**  (使用 "x" 选择)
@@ -31,15 +36,14 @@ about: temlpate
 - [ ] 申请添加新的特性或功能或者好的想法
 
 
-
-<!-- ----------- -->
+<!-- 
 
 **反馈BUG**
 
-1.请在面板路径下运行`git show HEAD`,然后贴出输出内容
+1. 反馈之前先升级到分支的最新版本。
 
-2.如果是页面问题(500 或 Slim Application Error ),请在 config 开启 debug 模式后截图或贴出输出内容,如果是某个按钮点击没反应,请打开浏览器开发者控制台(通常为 F12 ) ,贴出 console 输出内容
+2.如果是页面问题(500 或 Slim Application Error ),请在 config 开启 debug 模式后截图或贴出输出内容,如果是某个按钮点击没反应,请打开浏览器开发者控制台(通常为 F12 ) ,贴出 console 输出内容
 
-<!-- ----------- -->
+-->
 
-**申请添加新的特性或功能或者好的想法**
+<!--从这一行往下写--我是分割线-->

+ 3 - 4
.gitignore

@@ -8,10 +8,9 @@ index.html
 public/ssr-download/
 public/images/*.*
 public/theme/material/css/images/bg
-storage/trimepay_notify.log
-storage/traffic_notified/
+storage
 .idea
-storage/qqwry.*
 .vs/
 .htaccess
-php_errors.log
+php_errors.log
+composer.lock

+ 13 - 9
.travis.yml

@@ -1,8 +1,6 @@
 language: php
 php:
-  # - '5.4'
-  # - '5.6'
-  - '7.1'
+  - 7.1
 sudo: enabled
 dist: xenial
 before_install:
@@ -14,20 +12,26 @@ before_install:
   - sudo sed -i 's|http://us-central1.gce.archive.ubuntu.com|https://ubuntu.mirror.noc.one|g' /etc/apt/sources.list
   - sudo sed -i 's|http://ppa.launchpad.net|https://launchpad.proxy.noc.one|g' /etc/apt/sources.list.d/*.list
   - curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
-  - sudo apt upgrade
+  - sudo apt clean all && sudo apt -qq -y update
   - sudo apt install -y nodejs
-  - composer config -g repos.packagist composer https://packagist.noc.one
 install:
   - sudo chmod -R 755 *
-  - echo "==========================================================="
-  - echo "Comoposer install"
-  - echo "==========================================================="
   - php composer.phar install
+  - cd uim-index-dev
+  - npm i
 before_script:
   - npm i -g phplint
+  - cd ..
 script:
-  - cp config/.config.php.example config/.config.php
+  - cp config/.config.example.php config/.config.php
   - phplint '**/*.php' '!vendor/**'
   - php xcat initdownload
   - php xcat initQQWry
   - php xcat update
+  - cd uim-index-dev
+  - npm run lint
+  - npm run build
+cache:
+  directories:
+    - uim-index-dev/node_modules
+    - $HOME/.composer/cache/files

+ 17 - 13
README.md

@@ -3,24 +3,26 @@
 
 **ss-panel-v3-mod**是一款专为shadowsocks设计的web前端面板,再次感谢ss-panel-v3-mod 的制作者,修改后的功能简介:
 
-- **支付系统集成**:集成 支付宝当面付  易付通 码支付 TrimePay 等多种支付系统,使用方法见项目[wiki](https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki/)
+- **支付系统集成**:集成 支付宝当面付  易付通 码支付 TrimePay 等多种支付系统,使用方法见项目[wiki](https://github.com/Anankke/ss-panel-v3-mod_Uim/wiki/)
 - **UI** :修改为 ~~援交~~ 圆角、并自定义了几个图标的显示,节点列表等級0可见等級1节点但无法看见节点详情,增加了国家图标显示
 - **商店**:商品增加同时连接设备数,用户限速属性
 - 从肥羊那里**抄**来的:新用户注册现金奖励|高等级节点体验|设备数量限制
 - **优化**:css和js等置入本地提升加载速度
-- 增加**v2Ray** 功能,详情请看 [wiki](https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki/v2ray-%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B)
+- 增加**v2Ray** 功能,详情请看 wiki: [Indexyz 版](https://github.com/Anankke/ss-panel-v3-mod_Uim/wiki/v2ray---indexyz-%E7%89%88%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B)  |  [Rico 版](https://github.com/Anankke/ss-panel-v3-mod_Uim/wiki/v2ray---Rico-%E7%89%88%E4%BD%BF%E7%94%A8%E6%95%99%E7%A8%8B)
 
-Telegram 频道 :https://t.me/sspanel_Uim 
+Telegram 频道 :https://t.me/sspanel_Uim
 
-演示站: [demo.nimaqu.com](https://demo.nimaqu.com) 账号和密码都是 admin  对接节点的 mukey=NimaQu
+Telegram ~~可能是个官方~~水群 :https://t.me/SSUnion
+
+演示站: [sspanel.host](https://sspanel.host) 账号和密码都是 admin  对接节点的 mukey=NimaQu
 
 **原作者** [galaxychuck](https://github.com/galaxychuck)
 
-[支持开发者请点我](https://github.com/NimaQu/ss-panel-v3-mod_UIM#%E5%85%B3%E4%BA%8E%E6%8D%90%E8%B5%A0)
+[支持开发者请点我](https://github.com/Anankke/ss-panel-v3-mod_Uim#%E5%85%B3%E4%BA%8E%E6%8D%90%E8%B5%A0)
 
 ## 搭建教程
 
-GitHub Wiki : https://github.com/NimaQu/ss-panel-v3-mod_Uim/wiki/%E5%89%8D%E7%AB%AF%E5%AE%89%E8%A3%85
+GitHub Wiki : https://github.com/Anankke/ss-panel-v3-mod_Uim/wiki/%E5%89%8D%E7%AB%AF%E5%AE%89%E8%A3%85
 
 Wiki已经启用,欢迎为此面板维护wiki
 
@@ -67,8 +69,6 @@ Wiki已经启用,欢迎为此面板维护wiki
 
 [**CGDF**](https://github.com/CGDF-GitHub)
 
-- 一键国旗
-- 财务报表
 - xcat一键update
 - 适配SSD
 - 用户列表分页加载
@@ -89,11 +89,13 @@ Wiki已经启用,欢迎为此面板维护wiki
 
 您对我们的帮助将是支持我们做下去的动力,只需您在购买部分产品或向他人推荐产品时从我们的返利链接购买,这就是对我们很大的支持了。~~没有钱了,肯定要做啊,不做没有钱用啊,打工是不可能打工的,这辈子不可能打工的~~
 
-##### dumplin
+##### Anankke
 
-- [码支付-微信收款功能开通](https://codepay.fateqq.com/i/39756)
+- [Anankke 很可爱请给 Anankke 钱](https://t.me/anankke/5)
 
+##### dumplin
 
+- [码支付-微信收款功能开通](https://codepay.fateqq.com/i/39756)
 
 ##### galaxychuck
 
@@ -101,8 +103,10 @@ Wiki已经启用,欢迎为此面板维护wiki
 - [冲上云霄云主机](http://console.soar-clouds.com/aff.php?aff=94)
 - [Vultr](https://www.vultr.com/?ref=7205737)
 
-[Nymph 的前端课程报名](t.me/kinokonominoco)
+[laurieryayoi 的前端课程报名](https://t.me/kinokonominoco)
+
+
 
-# 免责声明
+## 免责声明
 
-本程序由 MIT License 授权。**不提供任何担保**。使用本程序即表明,您知情并同意:程序开发者不对此程序导致的任何服务中断、数据损失或任何少见未列出的事故负责。
+本程序由 MIT License 授权。**不提供任何担保**。使用本程序即表明,您知情并同意:程序开发者不对此程序导致的任何服务中断、数据损失或任何少见未列出的事故负责。

+ 26 - 26
app/Command/DailyMail.php

@@ -10,6 +10,7 @@ use App\Services\Mail;
 use App\Utils\Telegram;
 use App\Utils\Tools;
 use App\Services\Analytics;
+use Exception;
 
 class DailyMail
 {
@@ -17,46 +18,45 @@ class DailyMail
     {
         $users = User::all();
         $logs = Ann::orderBy('id', 'desc')->get();
-        $text1="";
-        
+        $text1 = '';
+
         foreach ($logs as $log) {
-            if (strpos($log->content, "Links")===false) {
-                $text1=$text1.$log->content."<br><br>";
+            if (strpos($log->content, 'Links') === false) {
+                $text1 = $text1 . $log->content . '<br><br>';
             }
         }
-        
+
         $lastday_total = 0;
-        
+
         foreach ($users as $user) {
-            $lastday = (($user->u+$user->d)-$user->last_day_t)/1024/1024;
-            $lastday_total += (($user->u+$user->d)-$user->last_day_t);
-            
-            if ($user->sendDailyMail==1) {
-                echo "Send daily mail to user: ".$user->id;
-                $subject = Config::get('appName')."-每日流量报告以及公告";
+            $lastday = (($user->u + $user->d) - $user->last_day_t) / 1024 / 1024;
+            $lastday_total += (($user->u + $user->d) - $user->last_day_t);
+
+            if ($user->sendDailyMail == 1) {
+                echo 'Send daily mail to user: ' . $user->id;
+                $subject = Config::get('appName') . '-每日流量报告以及公告';
                 $to = $user->email;
-                $text = "下面是系统中目前的公告:<br><br>".$text1."<br><br>晚安!";
-                
+                $text = '下面是系统中目前的公告:<br><br>' . $text1 . '<br><br>晚安!';
+
                 try {
                     Mail::send($to, $subject, 'news/daily-traffic-report.tpl', [
-                        "user" => $user,"text" => $text,"lastday"=>$lastday
+                        'user' => $user, 'text' => $text, 'lastday' => $lastday
                     ], [
                     ]);
-                } catch (\Exception $e) {
+                } catch (Exception $e) {
                     echo $e->getMessage();
                 }
-                $text="";
+                $text = '';
             }
         }
-        
+
         $sts = new Analytics();
-        
-        Telegram::Send("各位老爷少奶奶,我来为大家报告一下系统今天的运行状况哈~".
-        PHP_EOL.
-        "今日签到人数:".$sts->getTodayCheckinUser().PHP_EOL.
-        "今日使用总流量:".Tools::flowAutoShow($lastday_total).PHP_EOL.
-        "晚安~"
-        );
+
+        Telegram::Send('各位老爷少奶奶,我来为大家报告一下系统今天的运行状况哈~' .
+            PHP_EOL .
+            '今日签到人数:' . $sts->getTodayCheckinUser() . PHP_EOL .
+            '今日使用总流量:' . Tools::flowAutoShow($lastday_total) . PHP_EOL .
+            '晚安~');
     }
 
 
@@ -64,7 +64,7 @@ class DailyMail
     {
         $users = User::all();
         foreach ($users as $user) {
-            $user->last_day_t=($user->u+$user->d);
+            $user->last_day_t = ($user->u + $user->d);
             $user->save();
         }
     }

+ 15 - 14
app/Command/ExtMail.php

@@ -6,6 +6,7 @@ namespace App\Command;
 use App\Models\User;
 use App\Services\Config;
 use App\Services\Mail;
+use Exception;
 
 class ExtMail
 {
@@ -13,17 +14,17 @@ class ExtMail
     {
         $users = User::all();
         foreach ($users as $user) {
-            if ($user->t==0) {
-                echo "Send daily mail to user: ".$user->id;
-                $subject = Config::get('appName')."-期待您的回归";
+            if ($user->t == 0) {
+                echo 'Send daily mail to user: ' . $user->id;
+                $subject = Config::get('appName') . '-期待您的回归';
                 $to = $user->email;
-                $text = "似乎您在".Config::get('appName')."上的流量一直是 0 呢(P.S:也可能是您没有使用 ss 而使用了其他还不能计入流量的方式....),如果您在使用上遇到了任何困难,请不要犹豫,登录到".Config::get('appName').",您就会知道如何使用了,特别是对于 iOS 用户,最近在使用的优化上大家都付出了很多的努力。期待您的回归~" ;
+                $text = '似乎您在' . Config::get('appName') . '上的流量一直是 0 呢(P.S:也可能是您没有使用 ss 而使用了其他还不能计入流量的方式....),如果您在使用上遇到了任何困难,请不要犹豫,登录到' . Config::get('appName') . ',您就会知道如何使用了,特别是对于 iOS 用户,最近在使用的优化上大家都付出了很多的努力。期待您的回归~';
                 try {
                     Mail::send($to, $subject, 'ext/back.tpl', [
-                    "user" => $user,"text" => $text
-                ], [
-                ]);
-                } catch (\Exception $e) {
+                        'user' => $user, 'text' => $text
+                    ], [
+                    ]);
+                } catch (Exception $e) {
                     echo $e->getMessage();
                 }
             }
@@ -34,17 +35,17 @@ class ExtMail
     {
         $users = User::all();
         foreach ($users as $user) {
-            if ($user->t!=0&&$user->t<1451577599) {
-                echo "Send daily mail to user: ".$user->id;
-                $subject = Config::get('appName')."-期待您的回归";
+            if ($user->t != 0 && $user->t < 1451577599) {
+                echo 'Send daily mail to user: ' . $user->id;
+                $subject = Config::get('appName') . '-期待您的回归';
                 $to = $user->email;
-                $text = "似乎您在 2017 年以来就没有使用过".Config::get('appName')."了呢,如果您在使用上遇到了任何困难,请不要犹豫,登录到".Config::get('appName').",您就会知道如何使用了,特别是对于 iOS 用户,最近在使用的优化上大家都付出了很多的努力。期待您的回归~" ;
+                $text = '似乎您在 2017 年以来就没有使用过' . Config::get('appName') . '了呢,如果您在使用上遇到了任何困难,请不要犹豫,登录到' . Config::get('appName') . ',您就会知道如何使用了,特别是对于 iOS 用户,最近在使用的优化上大家都付出了很多的努力。期待您的回归~';
                 try {
                     Mail::send($to, $subject, 'ext/back.tpl', [
-                        "user" => $user,"text" => $text
+                        'user' => $user, 'text' => $text
                     ], [
                     ]);
-                } catch (\Exception $e) {
+                } catch (Exception $e) {
                     echo $e->getMessage();
                 }
             }

+ 178 - 191
app/Command/FinanceMail.php

@@ -4,14 +4,12 @@
 namespace App\Command;
 
 use App\Models\User;
-use App\Models\Ann;
-use App\Models\Code;
 use App\Services\Config;
 use App\Services\Mail;
 use App\Services\Analytics;
 use App\Utils\Telegram;
-use App\Utils\Tools;
 
+use Exception;
 use Ozdemir\Datatables\Datatables;
 use App\Utils\DatatablesHelper;
 
@@ -19,205 +17,194 @@ class FinanceMail
 {
     public static function sendFinanceMail_day()
     {
-		$datatables = new Datatables(new DatatablesHelper());
+        $datatables = new Datatables(new DatatablesHelper());
         $datatables->query(
-		'select code.number, code.userid, code.usedatetime from code
-		where TO_DAYS(NOW()) - TO_DAYS(code.usedatetime) = 1 and code.type = -1 and code.isused= 1');
-		$text_json=$datatables->generate();
-        $text_array=json_decode($text_json,true);
-        $codes=$text_array['data'];
-        $text_html='<table border=1><tr><td>金额</td><td>用户ID</td><td>用户名</td><td>充值时间</td>';
-		$income_count=0;
-		$income_total=0.00;
-		foreach($codes as $code){
-			$text_html.='<tr>';
-			$text_html.='<td>'.$code['number'].'</td>';
-			$text_html.='<td>'.$code['userid'].'</td>';
-			$user=User::find($code['userid']);
-			$text_html.='<td>'.$user->user_name.'</td>';
-			$text_html.='<td>'.$code['usedatetime'].'</td>';
-			$text_html.='</tr>';
-			$income_count+=1;
-			$income_total+=$code['number'];
-		}
-		//易付通的单独表
-		$datatables2 = new Datatables(new DatatablesHelper());
-		$datatables2->query('select COUNT(*) as "count_yft" from INFORMATION_SCHEMA.TABLES where TABLE_NAME = "yft_order_info"');
-		$count_yft=$datatables2->generate();
-		if(strpos($count_yft,'"count_yft":1')){
-			$datatables2->query(
-				'select yft_order_info.price, yft_order_info.user_id, yft_order_info.create_time from yft_order_info
-				where TO_DAYS(NOW()) - TO_DAYS(yft_order_info.create_time) = 1 and yft_order_info.state= 1');
-			$text_json2=$datatables2->generate();
-			$text_array2=json_decode($text_json2,true);
-			$codes2=$text_array2['data'];
-			foreach($codes2 as $code2){
-				$text_html.='<tr>';
-				$text_html.='<td>'.$code2['price'].'</td>';
-				$text_html.='<td>'.$code2['user_id'].'</td>';
-				$user=User::find($code2['user_id']);
-				$text_html.='<td>'.$user->user_name.'</td>';
-				$text_html.='<td>'.$code2['create_time'].'</td>';
-				$text_html.='</tr>';
-				$income_count+=1;
-				$income_total+=$code['price'];
-			}
-		}
-		$text_html.='</table>';
-		$text_html.='<br>昨日总收入笔数:'.$income_count.'<br>昨日总收入金额:'.$income_total;
+            'select code.number, code.userid, code.usedatetime from code
+		where TO_DAYS(NOW()) - TO_DAYS(code.usedatetime) = 1 and code.type = -1 and code.isused= 1'
+        );
+        $text_json = $datatables->generate();
+        $text_array = json_decode($text_json, true);
+        $codes = $text_array['data'];
+        $text_html = '<table border=1><tr><td>金额</td><td>用户ID</td><td>用户名</td><td>充值时间</td>';
+        $income_count = 0;
+        $income_total = 0.00;
+        foreach ($codes as $code) {
+            $text_html .= '<tr>';
+            $text_html .= '<td>' . $code['number'] . '</td>';
+            $text_html .= '<td>' . $code['userid'] . '</td>';
+            $user = User::find($code['userid']);
+            $text_html .= '<td>' . $user->user_name . '</td>';
+            $text_html .= '<td>' . $code['usedatetime'] . '</td>';
+            $text_html .= '</tr>';
+            ++$income_count;
+            $income_total += $code['number'];
+        }
+        //易付通的单独表
+        $datatables2 = new Datatables(new DatatablesHelper());
+        $datatables2->query('select COUNT(*) as "count_yft" from INFORMATION_SCHEMA.TABLES where TABLE_NAME = "yft_order_info"');
+        $count_yft = $datatables2->generate();
+        if (strpos($count_yft, '"count_yft":1')) {
+            $datatables2->query(
+                'select yft_order_info.price, yft_order_info.user_id, yft_order_info.create_time from yft_order_info
+				where TO_DAYS(NOW()) - TO_DAYS(yft_order_info.create_time) = 1 and yft_order_info.state= 1'
+            );
+            $text_json2 = $datatables2->generate();
+            $text_array2 = json_decode($text_json2, true);
+            $codes2 = $text_array2['data'];
+            foreach ($codes2 as $code2) {
+                $text_html .= '<tr>';
+                $text_html .= '<td>' . $code2['price'] . '</td>';
+                $text_html .= '<td>' . $code2['user_id'] . '</td>';
+                $user = User::find($code2['user_id']);
+                $text_html .= '<td>' . $user->user_name . '</td>';
+                $text_html .= '<td>' . $code2['create_time'] . '</td>';
+                $text_html .= '</tr>';
+                ++$income_count;
+                $income_total += $code['price'];
+            }
+        }
+        $text_html .= '</table>';
+        $text_html .= '<br>昨日总收入笔数:' . $income_count . '<br>昨日总收入金额:' . $income_total;
 
-        $adminUser = User::where("is_admin", "=", "1")->get();
+        $adminUser = User::where('is_admin', '=', '1')->get();
         foreach ($adminUser as $user) {
-			echo "Send offline mail to user: ".$user->id;
-			$subject = Config::get('appName')."-财务日报";
-			$to = $user->email;
-			$title='财务日报';
-			$text = $text_html;
-			try {
-			Mail::send($to, $subject, 'news/finance.tpl', [
-			"user" => $user,"title"=>$title,"text" => $text
-			], [
-			]);
-			} catch (\Exception $e) {
-			echo $e->getMessage();
-			}
-		}
-        
-		if (Config::get("finance_public")=="true") {
-			$sts = new Analytics();    
-			Telegram::Send(
-				"新鲜出炉的财务日报~".PHP_EOL.
-				"昨日总收入笔数:".$income_count.PHP_EOL.
-				"昨日总收入金额:".$income_total.PHP_EOL.
-				"凌晨也在努力工作~"
-			);
-		}
+            echo 'Send offline mail to user: ' . $user->id;
+            $subject = Config::get('appName') . '-财务日报';
+            $to = $user->email;
+            $title = '财务日报';
+            $text = $text_html;
+            try {
+                Mail::send($to, $subject, 'news/finance.tpl', [
+                    'user' => $user, 'title' => $title, 'text' => $text
+                ], [
+                ]);
+            } catch (Exception $e) {
+                echo $e->getMessage();
+            }
+        }
+
+        if (Config::get('finance_public') == 'true') {
+            $sts = new Analytics();
+            Telegram::Send(
+                '新鲜出炉的财务日报~' . PHP_EOL .
+                '昨日总收入笔数:' . $income_count . PHP_EOL .
+                '昨日总收入金额:' . $income_total . PHP_EOL .
+                '凌晨也在努力工作~'
+            );
+        }
     }
 
-	public static function sendFinanceMail_week()
-	{
-		$datatables = new Datatables(new DatatablesHelper());
+    public static function sendFinanceMail_week()
+    {
+        $datatables = new Datatables(new DatatablesHelper());
         $datatables->query(
-		'select code.number from code
-		where yearweek(date_format(code.usedatetime,\'%Y-%m-%d\')) = yearweek(now())-1 and code.isused= 1');
-		//每周的第一天是周日,因此统计周日~周六的七天
-		$text_json=$datatables->generate();
-        $text_array=json_decode($text_json,true);
-        $codes=$text_array['data'];
-        $text_html='';
-		$income_count=0;
-		$income_total=0.00;
-		foreach($codes as $code){
-			$income_count+=1;
-			$income_total+=$code['number'];
-		}
-		//易付通的单独表
-		$datatables2 = new Datatables(new DatatablesHelper());
-		$datatables2->query('select COUNT(*) as "count_yft" from INFORMATION_SCHEMA.TABLES where TABLE_NAME = "yft_order_info"');
-		$count_yft=$datatables2->generate();
-		if(strpos($count_yft,'"count_yft":1')){
-			$datatables2->query(
-				'select yft_order_info.price from yft_order_info
-				where yearweek(date_format(yft_order_info.create_time,\'%Y-%m-%d\')) = yearweek(now())-1 and yft_order_info.state= 1');
-				//每周的第一天是周日,因此统计周日~周六的七天
-			$text_json2=$datatables2->generate();
-			$text_array2=json_decode($text_json2,true);
-			$codes2=$text_array2['data'];
-			foreach($codes2 as $code2){
-				$income_count+=1;
-				$income_total+=$code2['price'];
-			}
-		}
+            'SELECT code.number FROM code
+		WHERE DATEDIFF(NOW(),code.usedatetime) <=7 AND DATEDIFF(NOW(),code.usedatetime) >=1 AND code.isused = 1'
+        );
+        //每周的第一天是周日,因此统计周日~周六的七天
+        $text_json = $datatables->generate();
+        $text_array = json_decode($text_json, true);
+        $codes = $text_array['data'];
+        $text_html = '';
+        $income_count = 0;
+        $income_total = 0.00;
+        foreach ($codes as $code) {
+            ++$income_count;
+            $income_total += $code['number'];
+        }
+        //易付通的单独表
+        $datatables2 = new Datatables(new DatatablesHelper());
+        $datatables2->query('select COUNT(*) as "count_yft" from INFORMATION_SCHEMA.TABLES where TABLE_NAME = "yft_order_info"');
+        $count_yft = $datatables2->generate();
+        if (strpos($count_yft, '"count_yft":1')) {
+            $datatables2->query(
+                'select yft_order_info.price from yft_order_info
+				where yearweek(date_format(yft_order_info.create_time,\'%Y-%m-%d\')) = yearweek(now())-1 and yft_order_info.state= 1'
+            );
+            //每周的第一天是周日,因此统计周日~周六的七天
+            $text_json2 = $datatables2->generate();
+            $text_array2 = json_decode($text_json2, true);
+            $codes2 = $text_array2['data'];
+            foreach ($codes2 as $code2) {
+                ++$income_count;
+                $income_total += $code2['price'];
+            }
+        }
 
-		$text_html.='<br>上周总收入笔数:'.$income_count.'<br>上周总收入金额:'.$income_total;
+        $text_html .= '<br>上周总收入笔数:' . $income_count . '<br>上周总收入金额:' . $income_total;
 
-        $adminUser = User::where("is_admin", "=", "1")->get();
+        $adminUser = User::where('is_admin', '=', '1')->get();
         foreach ($adminUser as $user) {
-			echo "Send offline mail to user: ".$user->id;
-			$subject = Config::get('appName').'-财务周报';
-			$to = $user->email;
-			$title='财务周报';
-			$text = $text_html;
-			try {
-			Mail::send($to, $subject, 'news/finance.tpl', [
-			"user" => $user,"title"=>$title,"text" => $text
-			], [
-			]);
-			} catch (\Exception $e) {
-			echo $e->getMessage();
-			}
-		}
-        
-		if (Config::get("finance_public")=="true") {
-			$sts = new Analytics();    
-			Telegram::Send(
-				"新鲜出炉的财务周报~".PHP_EOL.
-				"上周总收入笔数:".$income_count.PHP_EOL.
-				"上周总收入金额:".$income_total.PHP_EOL.
-				"周末也在努力工作~"
-			);
-		}
-	}
+            echo 'Send offline mail to user: ' . $user->id;
+            $subject = Config::get('appName') . '-财务周报';
+            $to = $user->email;
+            $title = '财务周报';
+            $text = $text_html;
+            try {
+                Mail::send($to, $subject, 'news/finance.tpl', [
+                    'user' => $user, 'title' => $title, 'text' => $text
+                ], [
+                ]);
+            } catch (Exception $e) {
+                echo $e->getMessage();
+            }
+        }
+
+        if (Config::get('finance_public') == 'true') {
+            $sts = new Analytics();
+            Telegram::Send(
+                '新鲜出炉的财务周报~' . PHP_EOL .
+                '上周总收入笔数:' . $income_count . PHP_EOL .
+                '上周总收入金额:' . $income_total . PHP_EOL .
+                '周末也在努力工作~'
+            );
+        }
+    }
 
-	public static function sendFinanceMail_month()
-	{
-		$datatables = new Datatables(new DatatablesHelper());
+    public static function sendFinanceMail_month()
+    {
+        $datatables = new Datatables(new DatatablesHelper());
         $datatables->query(
-		'select code.number from code
-		where date_format(code.usedatetime,\'%Y-%m\')=date_format(date_sub(curdate(), interval 1 month),\'%Y-%m\') and code.type = -1 and code.isused= 1');
-		$text_json=$datatables->generate();
-        $text_array=json_decode($text_json,true);
-        $codes=$text_array['data'];
-        $text_html='';
-		$income_count=0;
-		$income_total=0.00;
-		foreach($codes as $code){
-			$income_count+=1;
-			$income_total+=$code['number'];
-		}
-		$datatables2 = new Datatables(new DatatablesHelper());
-				$datatables2->query('select COUNT(*) as "count_yft" from INFORMATION_SCHEMA.TABLES where TABLE_NAME = "yft_order_info"');
-		$count_yft=$datatables2->generate();
-		if(strpos($count_yft,'"count_yft":1')){
-			$datatables2->query(
-				'select yft_order_info.price from yft_order_info
-				where date_format(yft_order_info.create_time,\'%Y-%m\') =date_format(date_sub(curdate(), interval 1 month),\'%Y-%m\') and yft_order_info.state= 1');
-				//每周的第一天是周日,因此统计周日~周六的七天
-			$text_json2=$datatables2->generate();
-			$text_array2=json_decode($text_json2,true);
-			$codes2=$text_array2['data'];
-			foreach($codes2 as $code2){
-				$income_count+=1;
-				$income_total+=$code2['price'];
-			}
-		}
-		$text_html.='<br>上月总收入笔数:'.$income_count.'<br>上月总收入金额:'.$income_total;
+            'select code.number from code
+		where date_format(code.usedatetime,\'%Y-%m\')=date_format(date_sub(curdate(), interval 1 month),\'%Y-%m\') and code.type = -1 and code.isused= 1'
+        );
+        $text_json = $datatables->generate();
+        $text_array = json_decode($text_json, true);
+        $codes = $text_array['data'];
+        $text_html = '';
+        $income_count = 0;
+        $income_total = 0.00;
+        foreach ($codes as $code) {
+            ++$income_count;
+            $income_total += $code['number'];
+        }
+        $text_html .= '<br>上月总收入笔数:' . $income_count . '<br>上月总收入金额:' . $income_total;
 
-        $adminUser = User::where("is_admin", "=", "1")->get();
+        $adminUser = User::where('is_admin', '=', '1')->get();
         foreach ($adminUser as $user) {
-			echo "Send offline mail to user: ".$user->id;
-			$subject = Config::get('appName').'-财务月报';
-			$to = $user->email;
-			$title='财务月报';
-			$text = $text_html;
-			try {
-			Mail::send($to, $subject, 'news/finance.tpl', [
-			"user" => $user,"title"=>$title,"text" => $text
-			], [
-			]);
-			} catch (\Exception $e) {
-			echo $e->getMessage();
-			}
-		}
-        
-		if (Config::get("finance_public")=="true") {
-			$sts = new Analytics();    
-			Telegram::Send(
-				"新鲜出炉的财务月报~".PHP_EOL.
-				"上月总收入笔数:".$income_count.PHP_EOL.
-				"上月总收入金额:".$income_total.PHP_EOL.
-				"月初也在努力工作~"
-			);
-		}
-	}
+            echo 'Send offline mail to user: ' . $user->id;
+            $subject = Config::get('appName') . '-财务月报';
+            $to = $user->email;
+            $title = '财务月报';
+            $text = $text_html;
+            try {
+                Mail::send($to, $subject, 'news/finance.tpl', [
+                    'user' => $user, 'title' => $title, 'text' => $text
+                ], [
+                ]);
+            } catch (Exception $e) {
+                echo $e->getMessage();
+            }
+        }
+
+        if (Config::get('finance_public') == 'true') {
+            $sts = new Analytics();
+            Telegram::Send(
+                '新鲜出炉的财务月报~' . PHP_EOL .
+                '上月总收入笔数:' . $income_count . PHP_EOL .
+                '上月总收入金额:' . $income_total . PHP_EOL .
+                '月初也在努力工作~'
+            );
+        }
+    }
 }

File diff suppressed because it is too large
+ 390 - 356
app/Command/Job.php


+ 64 - 67
app/Command/SyncRadius.php

@@ -1,9 +1,6 @@
 <?php
 
 
-
-
-
 namespace App\Command;
 
 use App\Models\User;
@@ -17,22 +14,23 @@ use App\Models\TrafficLog;
 use App\Utils\Tools;
 use App\Utils\Radius;
 use App\Utils\Da;
+use Exception;
 
 class SyncRadius
 {
     public static function synclogin()
     {
-        if (Config::get('enable_radius')=="false") {
+        if (Config::get('enable_radius') == 'false') {
             return;
         }
-        $tempuserbox=array();
+        $tempuserbox = array();
         $users = User::all();
         foreach ($users as $user) {
-            $email=$user->email;
-            $email=Radius::GetUserName($email);
-            $tempuserbox[$email]=$user->id;
+            $email = $user->email;
+            $email = Radius::GetUserName($email);
+            $tempuserbox[$email] = $user->id;
         }
-        
+
         /*$tempnodebox=array();
         $nodes = Node::all();
         foreach($nodes as $node){
@@ -42,11 +40,10 @@ class SyncRadius
                 $tempnodebox[$ip]=$node->id;
             }
         }*/
-        
-        
-        
-        $logs = RadiusRadPostauth::where('authdate', '<', date("Y-m-d H:i:s"))->where('authdate', '>', date("Y-m-d H:i:s", time()-60))->get();
-        
+
+
+        $logs = RadiusRadPostauth::where('authdate', '<', date('Y-m-d H:i:s'))->where('authdate', '>', date('Y-m-d H:i:s', time() - 60))->get();
+
         foreach ($logs as $log) {
             if (isset($tempuserbox[$log->username])) {
                 $traffic = new TrafficLog();
@@ -58,16 +55,16 @@ class SyncRadius
                 $traffic->traffic = Tools::flowAutoShow(10000);
                 $traffic->log_time = time();
                 $traffic->save();
-                
-                $user=User::find($tempuserbox[$log->username]);
+
+                $user = User::find($tempuserbox[$log->username]);
                 $user->t = time();
-                $user->u = $user->u + 0;
-                $user->d = $user->d + 10000;
+                $user->u += 0;
+                $user->d += 10000;
                 $user->save();
             }
         }
-        
-        
+
+
         /*$stmt = $db->query("SELECT * FROM `radacct` WHERE `acctstoptime`<'".date("Y-m-d H:i:s")."' AND `acctstoptime`>'".date("Y-m-d H:i:s",time()-60)."'");
         $result = $stmt->fetchAll();
 
@@ -89,22 +86,22 @@ class SyncRadius
             $user->save();
         }  */
     }
-    
-    
+
+
     public static function syncvpn()
     {
-        if (Config::get('radius_db_host')=="") {
+        if (Config::get('radius_db_host') == '') {
             return;
         }
-        
-        $tempuserbox=array();
+
+        $tempuserbox = array();
         $users = User::all();
         foreach ($users as $user) {
-            $email=$user->email;
-            $email=Radius::GetUserName($email);
-            $tempuserbox[$email]=$user->id;
+            $email = $user->email;
+            $email = Radius::GetUserName($email);
+            $tempuserbox[$email] = $user->id;
         }
-        
+
         /*$tempnodebox=array();
         $nodes = Node::all();
         foreach($nodes as $node){
@@ -114,7 +111,7 @@ class SyncRadius
                 $tempnodebox[$ip]=$node->id;
             }
         }*/
-        
+
         /*$stmt = $db->query("SELECT * FROM `radpostauth` WHERE `authdate`<'".date("Y-m-d H:i:s")."' AND`authdate`>'".date("Y-m-d H:i:s",time()-60)."'");
         $result = $stmt->fetchAll();
 
@@ -139,10 +136,10 @@ class SyncRadius
             }
         }
         */
-        
-        
-        $logs = RadiusRadAcct::where('acctstoptime', '<', date("Y-m-d H:i:s"))->where('acctstoptime', '>', date("Y-m-d H:i:s", time()-60))->get();
-        
+
+
+        $logs = RadiusRadAcct::where('acctstoptime', '<', date('Y-m-d H:i:s'))->where('acctstoptime', '>', date('Y-m-d H:i:s', time() - 60))->get();
+
         foreach ($logs as $log) {
             $traffic = new TrafficLog();
             $traffic->user_id = $tempuserbox[$log->username];
@@ -150,76 +147,76 @@ class SyncRadius
             $traffic->d = $log->acctoutputoctets;
             $traffic->node_id = 2;
             $traffic->rate = 1;
-            $traffic->traffic = Tools::flowAutoShow(($log->acctinputoctets + $log->acctoutputoctets));
+            $traffic->traffic = Tools::flowAutoShow($log->acctinputoctets + $log->acctoutputoctets);
             $traffic->log_time = time();
             $traffic->save();
-            
-            $user=User::find($tempuserbox[$log->username]);
+
+            $user = User::find($tempuserbox[$log->username]);
             $user->t = time();
-            $user->u = $user->u + $log->acctinputoctets;
-            $user->d = $user->d + $log->acctoutputoctets;
+            $user->u += $log->acctinputoctets;
+            $user->d += $log->acctoutputoctets;
             $user->save();
         }
     }
-    
+
     public static function syncusers()
     {
         $users = User::all();
         foreach ($users as $user) {
             Radius::Add($user, $user->passwd);
 
-            echo "Send sync mail to user: ".$user->id;
-            $subject = Config::get('appName')."-密码更新通知";
+            echo 'Send sync mail to user: ' . $user->id;
+            $subject = Config::get('appName') . '-密码更新通知';
             $to = $user->email;
-            $text = "您好,为了保证密码系统的统一,刚刚系统已经将您 vpn 等连接方式的用户名已经重置为:".Radius::GetUserName($user->email).",密码自动重置为您 ss 的密码:". $user->passwd."  了,以后您修改 ss 密码就会自动修改 vpn 等连接方式的密码了,感谢您的支持。 " ;
+            $text = '您好,为了保证密码系统的统一,刚刚系统已经将您 vpn 等连接方式的用户名已经重置为:' . Radius::GetUserName($user->email) . ',密码自动重置为您 ss 的密码:' . $user->passwd . '  了,以后您修改 ss 密码就会自动修改 vpn 等连接方式的密码了,感谢您的支持。 ';
             try {
                 Mail::send($to, $subject, 'password/vpn.tpl', [
-                    "user" => $user,"text" => $text
+                    'user' => $user, 'text' => $text
                 ], [
                 ]);
-            } catch (\Exception $e) {
+            } catch (Exception $e) {
                 echo $e->getMessage();
             }
         }
     }
-    
+
     public static function syncnas()
     {
-        if (Config::get('radius_db_host')!="") {
-            $md5txt="";
-            
+        if (Config::get('radius_db_host') != '') {
+            $md5txt = '';
+
             $nases = RadiusNas::all();
-        
+
             foreach ($nases as $nas) {
                 //if($row["pass"]!="")
                 {
-                    $md5txt=$md5txt.$nas->id.$nas->nasname.$nas->shortname.$nas->secret.$nas->description;
+                    $md5txt = $md5txt . $nas->id . $nas->nasname . $nas->shortname . $nas->secret . $nas->description;
                 }
             }
-            
-            $md5=MD5($md5txt);
-            
-            
-            $oldmd5=file_get_contents(BASE_PATH."/storage/nas.md5");
-            
-            if ($oldmd5!=$md5) {
+
+            $md5 = MD5($md5txt);
+
+
+            $oldmd5 = file_get_contents(BASE_PATH . '/storage/nas.md5');
+
+            if ($oldmd5 != $md5) {
                 //Restart radius
-                $myfile = fopen(BASE_PATH."/storage/nas.md5", "w+") or die("Unable to open file!");
-                echo("Restarting...");
-                system("/bin/bash /sbin/service radiusd restart", $retval);
+                $myfile = fopen(BASE_PATH . '/storage/nas.md5', 'wb+') or die('Unable to open file!');
+                echo('Restarting...');
+                system('/bin/bash /sbin/service radiusd restart', $retval);
                 echo($retval);
                 $txt = $md5;
                 fwrite($myfile, $txt);
                 fclose($myfile);
             }
         }
-        
-        $Nodes = Node::where('sort', 0)->where('node_ip', "<>", "")->where('node_ip', "<>", 'NULL')->get();
+
+        $Nodes = Node::where('sort', 0)->where('node_ip', '<>', '')->where('node_ip', '<>', 'NULL')->get();
         foreach ($Nodes as $Node) {
-            if (file_exists("/usr/local/psionic/portsentry/portsentry.ignore")) {
-                $content=file_get_contents("/usr/local/psionic/portsentry/portsentry.ignore");
-                if (strpos($content, $Node->node_ip)===false) {
-                    file_put_contents("/usr/local/psionic/portsentry/portsentry.ignore", "\n".$Node->node_ip."/32", FILE_APPEND);
+            if (file_exists('/usr/local/psionic/portsentry/portsentry.ignore')) {
+                $content = file_get_contents('/usr/local/psionic/portsentry/portsentry.ignore');
+                if (strpos($content, $Node->node_ip) === false) {
+                    file_put_contents('/usr/local/psionic/portsentry/portsentry.ignore', "\n" . $Node->node_ip . '/32', FILE_APPEND);
                 }
             }
         }

+ 128 - 129
app/Command/Update.php

@@ -4,139 +4,138 @@ namespace App\Command;
 
 use App\Services\Config;
 
-use Ozdemir\Datatables\Datatables;
-use App\Utils\DatatablesHelper;
-
 class Update
 {
-	public static function update($xcat)
+    public static function update($xcat)
     {
         global $System_Config;
-	    $copy_result=copy(BASE_PATH."/config/.config.php",BASE_PATH."/config/.config.php.bak");
-		if($copy_result==true){
-			echo('备份成功'.PHP_EOL);
-		}
-		else{
-			echo('备份失败,迁移终止'.PHP_EOL);
-			return false;
-		}
-
-		echo(PHP_EOL);
-
-		echo('开始升级ssrdownload...'.PHP_EOL);
-		Job::updatedownload();
-		echo('升级ssrdownload结束'.PHP_EOL);
-
-		echo('开始升级QQWry...'.PHP_EOL);
-		$xcat->initQQWry();
-		echo('升级QQWry结束'.PHP_EOL);
-
-		echo(PHP_EOL);
-
-		$config_old=file_get_contents(BASE_PATH."/config/.config.php");
-		$config_new=file_get_contents(BASE_PATH."/config/.config.php.example");
-
-		//执行版本升级
-		$version_old=0;
-		if(isset($System_Config['version'])){
-			$version_old=$System_Config['version'];
-		}		
-		Update::old_to_new($version_old);
-
-		//将旧config迁移到新config上
-		$migrated=array();
-		foreach($System_Config as $key => $value_reserve){
-			if($key=='config_migrate_notice'||$key=='version'){
-				continue;
-			}
-
-			$regex='/System_Config\[\''.$key.'\'\].*?;/s';
-			$matches_new=array();
-			preg_match($regex,$config_new,$matches_new);
-			if(isset($matches_new[0])==false){
-				echo('未找到配置项:'.$key.' 未能在新config文件中找到,可能已被更名或废弃'.PHP_EOL);
-				continue;
-			}
-
-			$matches_old=array();
-			preg_match($regex,$config_old,$matches_old);
-
-			$config_new=str_replace($matches_new[0],$matches_old[0],$config_new);
-			array_push($migrated,'System_Config[\''.$key.'\']');
-		}
-		echo(PHP_EOL);
-
-		//检查新增了哪些config
-		$regex_new='/System_Config\[\'.*?\'\]/s';
-		$matches_new_all=array();
-		preg_match_all($regex_new,$config_new,$matches_new_all);
-		$differences=array_diff($matches_new_all[0],$migrated);
-		foreach($differences as $difference){
-			if($difference=='System_Config[\'config_migrate_notice\']'||
-			$difference=='System_Config[\'version\']'){
-				continue;
-			}
-			//匹配注释
-			$regex_comment='/'.$difference.'.*?;.*?(?=\n)/s';
-			$regex_comment=str_replace('[','\[',$regex_comment);
-			$regex_comment=str_replace(']','\]',$regex_comment);
-			$matches_comment=array();
-			preg_match($regex_comment,$config_new,$matches_comment);
-			$comment="";
-			if(isset($matches_comment[0])){
-				$comment=$matches_comment[0];
-				$comment=substr(
-					$comment,strpos(
-						$comment,'//',strpos($comment,';') //查找';'之后的第一个'//',然后substr其后面的comment
-					)+2
-				);
-			}
-			//裁去首尾
-			$difference=substr($difference,15);
-			$difference=substr($difference, 0, -2);
-
-			echo('新增配置项:'.$difference.':'.$comment.PHP_EOL);
-		}
-		echo('新增配置项通常带有默认值,因此通常即使不作任何改动网站也可以正常运行'.PHP_EOL);
-
-		//输出notice
-		$regex_notice='/System_Config\[\'config_migrate_notice\'\].*?(?=\';)/s';
-		$matches_notice=array();
-		preg_match($regex_notice,$config_new,$matches_notice);
-		$notice_new=$matches_notice[0];
-		$notice_new=substr(
-			$notice_new,strpos(
-				$notice_new,'\'',strpos($notice_new,'=') //查找'='之后的第一个'\'',然后substr其后面的notice
-			)+1
-		);
-		echo('以下是迁移附注:');
-		if(isset($System_Config['config_migrate_notice'])){
-		    if($System_Config['config_migrate_notice']!=$notice_new){
-			    echo($notice_new);
-			}
-		}
-		else{
-			echo($notice_new);
-		}
-		echo(PHP_EOL);
-
-		file_put_contents(BASE_PATH."/config/.config.php",$config_new);
-		echo(PHP_EOL.'迁移完成'.PHP_EOL);
-
-		echo(PHP_EOL);
-
-		echo('开始升级composer依赖...'.PHP_EOL);
-		system('php '.BASE_PATH.'/composer.phar selfupdate');
-		system('php '.BASE_PATH.'/composer.phar install -d '.BASE_PATH);
-		echo('升级composer依赖结束,请自行根据上方输出确认是否升级成功'.PHP_EOL);
-		system('rm -rf '.BASE_PATH.'/storage/framework/smarty/compile/*');
-		system('chown -R www:www '.BASE_PATH.'/storage');
+        $copy_result = copy(BASE_PATH . '/config/.config.php', BASE_PATH . '/config/.config.php.bak');
+        if ($copy_result == true) {
+            echo('备份成功' . PHP_EOL);
+        } else {
+            echo('备份失败,迁移终止' . PHP_EOL);
+            return false;
+        }
+
+        echo(PHP_EOL);
+
+        echo('开始升级ssrdownload...' . PHP_EOL);
+        Job::updatedownload();
+        echo('升级ssrdownload结束' . PHP_EOL);
+
+        echo('开始升级QQWry...' . PHP_EOL);
+        $xcat->initQQWry();
+        echo('升级QQWry结束' . PHP_EOL);
+
+        echo(PHP_EOL);
+
+        $config_old = file_get_contents(BASE_PATH . '/config/.config.php');
+        $config_new = file_get_contents(BASE_PATH . '/config/.config.example.php');
+
+        //执行版本升级
+        $version_old = $System_Config['version'] ?? 0;
+        self::old_to_new($version_old);
+
+        //将旧config迁移到新config上
+        $migrated = array();
+        foreach ($System_Config as $key => $value_reserve) {
+            if ($key == 'config_migrate_notice' || $key == 'version') {
+                continue;
+            }
+
+            $regex = '/System_Config\[\'' . $key . '\'\].*?;/s';
+            $matches_new = array();
+            preg_match($regex, $config_new, $matches_new);
+            if (isset($matches_new[0]) == false) {
+                echo('未找到配置项:' . $key . ' 未能在新config文件中找到,可能已被更名或废弃' . PHP_EOL);
+                continue;
+            }
+
+            $matches_old = array();
+            preg_match($regex, $config_old, $matches_old);
+
+            $config_new = str_replace($matches_new[0], $matches_old[0], $config_new);
+            $migrated[] = 'System_Config[\'' . $key . '\']';
+        }
+        echo(PHP_EOL);
+
+        //检查新增了哪些config
+        $regex_new = '/System_Config\[\'.*?\'\]/s';
+        $matches_new_all = array();
+        preg_match_all($regex_new, $config_new, $matches_new_all);
+        $differences = array_diff($matches_new_all[0], $migrated);
+        foreach ($differences as $difference) {
+            if ($difference == 'System_Config[\'config_migrate_notice\']' ||
+                $difference == 'System_Config[\'version\']') {
+                continue;
+            }
+            //匹配注释
+            $regex_comment = '/' . $difference . '.*?;.*?(?=\n)/s';
+            $regex_comment = str_replace(array('[', ']'), array('\[', '\]'), $regex_comment);
+            $matches_comment = array();
+            preg_match($regex_comment, $config_new, $matches_comment);
+            $comment = '';
+            if (isset($matches_comment[0])) {
+                $comment = $matches_comment[0];
+                $comment = substr(
+                    $comment,
+                    strpos(
+                        $comment,
+                        '//',
+                        strpos($comment, ';') //查找';'之后的第一个'//',然后substr其后面的comment
+                    ) + 2
+                );
+            }
+            //裁去首尾
+            $difference = substr($difference, 15);
+            $difference = substr($difference, 0, -2);
+
+            echo('新增配置项:' . $difference . ':' . $comment . PHP_EOL);
+        }
+        echo('新增配置项通常带有默认值,因此通常即使不作任何改动网站也可以正常运行' . PHP_EOL);
+
+        //输出notice
+        $regex_notice = '/System_Config\[\'config_migrate_notice\'\].*?(?=\';)/s';
+        $matches_notice = array();
+        preg_match($regex_notice, $config_new, $matches_notice);
+        $notice_new = $matches_notice[0];
+        $notice_new = substr(
+            $notice_new,
+            strpos(
+                $notice_new,
+                '\'',
+                strpos($notice_new, '=') //查找'='之后的第一个'\'',然后substr其后面的notice
+            ) + 1
+        );
+        echo('以下是迁移附注:');
+        if (isset($System_Config['config_migrate_notice'])) {
+            if ($System_Config['config_migrate_notice'] != $notice_new) {
+                echo($notice_new);
+            }
+        } else {
+            echo($notice_new);
+        }
+        echo(PHP_EOL);
+
+        file_put_contents(BASE_PATH . '/config/.config.php', $config_new);
+        echo(PHP_EOL . '迁移完成' . PHP_EOL);
+
+        echo(PHP_EOL);
+
+        echo('开始升级composer依赖...' . PHP_EOL);
+        system('php ' . BASE_PATH . '/composer.phar selfupdate');
+        system('php ' . BASE_PATH . '/composer.phar install -d ' . BASE_PATH);
+        echo('升级composer依赖结束,请自行根据上方输出确认是否升级成功' . PHP_EOL);
+        system('rm -rf ' . BASE_PATH . '/storage/framework/smarty/compile/*');
+        system('chown -R www:www ' . BASE_PATH . '/storage');
     }
 
-	public static function old_to_new($version_old)
-	{
-		if($version_old<=0){
-		
-		}
-	}
+    public static function old_to_new($version_old)
+    {
+        if ($version_old <= 0) {
+            echo('执行升级:0 -> 1');
+            $conn = mysqli_connect(Config::get('db_host'), Config::get('db_username'), Config::get('db_password'), Config::get('db_database'));
+            mysqli_query($conn, 'ALTER TABLE user ADD discord BIGINT NULL AFTER telegram_id');
+        }
+    }
 }

+ 136 - 115
app/Command/XCat.php

@@ -12,10 +12,12 @@ use App\Models\Relay;
 use App\Services\Gateway\ChenPay;
 use App\Utils\Hash;
 use App\Utils\Tools;
+use App\Utils\Discord;
 use App\Services\Config;
 
 use App\Utils\GA;
-use App\Utils\QRcode;
+use Exception;
+use TelegramBot\Api\BotApi;
 
 class XCat
 {
@@ -29,90 +31,99 @@ class XCat
     public function boot()
     {
         switch ($this->argv[1]) {
-            case("alipay"):
+            case ('alipay'):
                 return (new ChenPay())->AliPayListen();
-            case("wxpay"):
+            case ('wxpay'):
                 return (new ChenPay())->WxPayListen();
-            case("createAdmin"):
+            case ('createAdmin'):
                 return $this->createAdmin();
-            case("resetTraffic"):
+            case ('resetTraffic'):
                 return $this->resetTraffic();
-            case("setTelegram"):
+            case ('setDiscord'):
+                return Discord::set();
+            case ('setTelegram'):
                 return $this->setTelegram();
-            case("initQQWry"):
-                 return $this->initQQWry();
-            case("sendDiaryMail"):
+            case ('initQQWry'):
+                return $this->initQQWry();
+            case ('sendDiaryMail'):
                 return DailyMail::sendDailyMail();
-			case("sendFinanceMail_day"):
-			    return FinanceMail::sendFinanceMail_day();
-			case("sendFinanceMail_week"):
-			    return FinanceMail::sendFinanceMail_week();
-			case("sendFinanceMail_month"):
-			    return FinanceMail::sendFinanceMail_month();
-            case("reall"):
-                    return DailyMail::reall();
-            case("syncusers"):
-                    return SyncRadius::syncusers();
-            case("synclogin"):
-                    return SyncRadius::synclogin();
-            case("syncvpn"):
+            case ('sendFinanceMail_day'):
+                return FinanceMail::sendFinanceMail_day();
+            case ('sendFinanceMail_week'):
+                return FinanceMail::sendFinanceMail_week();
+            case ('sendFinanceMail_month'):
+                return FinanceMail::sendFinanceMail_month();
+            case ('reall'):
+                return DailyMail::reall();
+            case ('syncusers'):
+                return SyncRadius::syncusers();
+            case ('synclogin'):
+                return SyncRadius::synclogin();
+            case ('syncvpn'):
                 return SyncRadius::syncvpn();
-            case("nousers"):
-                    return ExtMail::sendNoMail();
-            case("oldusers"):
-                    return ExtMail::sendOldMail();
-            case("syncnode"):
-                    return Job::syncnode();
-            case("syncnasnode"):
-                    return Job::syncnasnode();
-			case("detectGFW"):
-				return Job::detectGFW();
-            case("syncnas"):
-                    return SyncRadius::syncnas();
-            case("dailyjob"):
+            case ('nousers'):
+                return ExtMail::sendNoMail();
+            case ('oldusers'):
+                return ExtMail::sendOldMail();
+            case ('syncnode'):
+                return Job::syncnode();
+            case ('syncnasnode'):
+                return Job::syncnasnode();
+            case ('detectGFW'):
+                return Job::detectGFW();
+            case ('syncnas'):
+                return SyncRadius::syncnas();
+            case ('dailyjob'):
                 return Job::DailyJob();
-            case("checkjob"):
+            case ('checkjob'):
                 return Job::CheckJob();
-            case("userga"):
+            case ('userga'):
                 return Job::UserGa();
-            case("backup"):
-                return Job::backup();
-            case("initdownload"):
+            case ('backup'):
+                return Job::backup(false);
+            case ('backupfull'):
+                return Job::backup(true);
+            case ('initdownload'):
                 return $this->initdownload();
-            case("updatedownload"):
+            case ('updatedownload'):
                 return Job::updatedownload();
-            case("cleanRelayRule"):
+            case ('cleanRelayRule'):
                 return $this->cleanRelayRule();
-            case("resetPort"):
+            case ('resetPort'):
                 return $this->resetPort();
-	        case("resetAllPort"):
+            case ('resetAllPort'):
                 return $this->resetAllPort();
-			case("update"):
-			    return Update::update($this);
-			default:
+            case ('update'):
+                return Update::update($this);
+            case ('sendDailyUsageByTG'):
+                return $this->sendDailyUsageByTG();
+            case ('npmbuild'):
+                return $this->npmbuild();
+            default:
                 return $this->defaultAction();
         }
     }
 
     public function defaultAction()
     {
-        echo(PHP_EOL."用法: php xcat [选项]".PHP_EOL);
-		echo("常用选项:".PHP_EOL);
-		echo("  createAdmin - 创建管理员帐号".PHP_EOL);
-		echo("  setTelegram - 设置 Telegram 机器人".PHP_EOL);
-		echo("  cleanRelayRule - 清除所有中转规则".PHP_EOL);
-		echo("  resetPort - 重置单个用户端口".PHP_EOL);
-		echo("  resetAllPort - 重置所有用户端口".PHP_EOL);
-		echo("  initdownload - 下载 SSR 程序至服务器".PHP_EOL);
-		echo("  initQQWry - 下载 IP 解析库".PHP_EOL);
-		echo("  resetTraffic - 重置所有用户流量".PHP_EOL);
-		echo("  update - 更新并迁移配置".PHP_EOL);
+        echo(PHP_EOL . '用法: php xcat [选项]' . PHP_EOL);
+        echo('常用选项:' . PHP_EOL);
+        echo('  createAdmin - 创建管理员帐号' . PHP_EOL);
+        echo('  setDiscord - 设置 Discord 机器人' . PHP_EOL);
+        echo('  setTelegram - 设置 Telegram 机器人' . PHP_EOL);
+        echo('  cleanRelayRule - 清除所有中转规则' . PHP_EOL);
+        echo('  resetPort - 重置单个用户端口' . PHP_EOL);
+        echo('  resetAllPort - 重置所有用户端口' . PHP_EOL);
+        echo('  initdownload - 下载 SSR 程序至服务器' . PHP_EOL);
+        echo('  initQQWry - 下载 IP 解析库' . PHP_EOL);
+        echo('  resetTraffic - 重置所有用户流量' . PHP_EOL);
+        echo('  update - 更新并迁移配置' . PHP_EOL);
     }
 
-	public function resetPort()
+    public function resetPort()
     {
-		fwrite(STDOUT, "请输入用户id: ");
-        $user=User::Where("id", "=", trim(fgets(STDIN)))->first();
+        fwrite(STDOUT, '请输入用户id: ');
+        $user = User::Where('id', '=', trim(fgets(STDIN)))->first();
         $origin_port = $user->port;
 
         $user->port = Tools::getAvPort();
@@ -122,19 +133,19 @@ class XCat
             $rule->port = $user->port;
             $rule->save();
         }
-		
-		if ($user->save()) {
+
+        if ($user->save()) {
             echo "重置成功!\n";
-		}
+        }
     }
-	
+
     public function resetAllPort()
     {
         $users = User::all();
         foreach ($users as $user) {
             $origin_port = $user->port;
             $user->port = Tools::getAvPort();
-            echo '$origin_port='.$origin_port.'&$user->port='.$user->port."\n";
+            echo '$origin_port=' . $origin_port . '&$user->port=' . $user->port . "\n";
             $user->save();
         }
     }
@@ -143,9 +154,9 @@ class XCat
     {
         $rules = Relay::all();
         foreach ($rules as $rule) {
-            echo($rule->id."\n");
+            echo($rule->id . "\n");
             if ($rule->source_node_id == 0) {
-                echo($rule->id."被删除!\n");
+                echo($rule->id . "被删除!\n");
                 $rule->delete();
                 continue;
             }
@@ -153,7 +164,7 @@ class XCat
             $ruleset = Relay::where('user_id', $rule->user_id)->orwhere('user_id', 0)->get();
             $maybe_rule_id = Tools::has_conflict_rule($rule, $ruleset, $rule->id);
             if ($maybe_rule_id != 0) {
-                echo($rule->id."被删除!\n");
+                echo($rule->id . "被删除!\n");
                 $rule->delete();
             }
         }
@@ -161,15 +172,15 @@ class XCat
 
     public function initdownload()
     {
-        system('git clone https://github.com/xcxnig/ssr-download.git '.BASE_PATH."/public/ssr-download/", $ret);
+        system('git clone https://github.com/xcxnig/ssr-download.git ' . BASE_PATH . '/public/ssr-download/', $ret);
         echo $ret;
     }
 
     public function createAdmin()
     {
-        echo "add admin/ 创建管理员帐号.....";
+        echo 'add admin/ 创建管理员帐号.....';
         // ask for input
-        fwrite(STDOUT, "Enter your email/输入管理员邮箱: ");
+        fwrite(STDOUT, 'Enter your email/输入管理员邮箱: ');
         // get input
         $email = trim(fgets(STDIN));
         // write input back
@@ -178,16 +189,16 @@ class XCat
         echo "Email: $email, Password: $passwd! ";
         fwrite(STDOUT, "Press [Y] to create admin..... 按下[Y]确认来确认创建管理员账户..... \n");
         $y = trim(fgets(STDIN));
-        if (strtolower($y) == "y") {
-            echo "start create admin account";
+        if (strtolower($y) == 'y') {
+            echo 'start create admin account';
             // create admin user
             // do reg user
             $user = new User();
-            $user->user_name = "admin";
+            $user->user_name = 'admin';
             $user->email = $email;
             $user->pass = Hash::passwordHash($passwd);
             $user->passwd = Tools::genRandomChar(6);
-            $user->port = Tools::getLastPort()+1;
+            $user->port = Tools::getLastPort() + 1;
             $user->t = 0;
             $user->u = 0;
             $user->d = 0;
@@ -195,78 +206,88 @@ class XCat
             $user->invite_num = Config::get('inviteNum');
             $user->ref_by = 0;
             $user->is_admin = 1;
-            $user->expire_in=date("Y-m-d H:i:s", time()+Config::get('user_expire_in_default')*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->plan='A';
-            $user->node_speedlimit=0;
-            $user->theme=Config::get('theme');
+            $user->expire_in = date('Y-m-d H:i:s', time() + Config::get('user_expire_in_default') * 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->plan = 'A';
+            $user->node_speedlimit = 0;
+            $user->theme = Config::get('theme');
 
             $ga = new GA();
             $secret = $ga->createSecret();
-            $user->ga_token=$secret;
-            $user->ga_enable=0;
+            $user->ga_token = $secret;
+            $user->ga_enable = 0;
 
             if ($user->save()) {
                 echo "Successful/添加成功!\n";
                 return true;
             }
-            echo "添加失败";
+            echo '添加失败';
             return false;
         }
-        echo "cancel";
+        echo 'cancel';
         return false;
     }
 
     public function resetTraffic()
     {
         try {
-            User::where("enable", 1)->update([
-            'd' => 0,
-            'u' => 0,
-            'last_day_t' => 0,
+            User::where('enable', 1)->update([
+                'd' => 0,
+                'u' => 0,
+                'last_day_t' => 0,
             ]);
-        } catch (\Exception $e) {
+        } catch (Exception $e) {
             echo $e->getMessage();
             return false;
         }
-        return "reset traffic successful";
+        return 'reset traffic successful';
     }
 
-
     public function setTelegram()
     {
-        $bot = new \TelegramBot\Api\BotApi(Config::get('telegram_token'));
-        if ($bot->setWebhook(Config::get('baseUrl')."/telegram_callback?token=".Config::get('telegram_request_token')) == 1) {
-            echo("设置成功!");
+        $bot = new BotApi(Config::get('telegram_token'));
+        if ($bot->setWebhook(Config::get('baseUrl') . '/telegram_callback?token=' . Config::get('telegram_request_token')) == 1) {
+            echo('设置成功!' . PHP_EOL);
         }
     }
 
     public function initQQWry()
     {
-        echo("downloading....");
-        $copywrite = file_get_contents("https://qqwry.mirror.noc.one/copywrite.rar");
-        $newmd5 = md5($copywrite);
-        file_put_contents(BASE_PATH."/storage/qqwry.md5", $newmd5);
-        $qqwry = file_get_contents("https://qqwry.mirror.noc.one/qqwry.rar");
-        if ($qqwry != "") {
-            $key = unpack("V6", $copywrite)[6];
-            for ($i=0; $i<0x200; $i++) {
-                $key *= 0x805;
-                $key ++;
-                $key = $key & 0xFF;
-                $qqwry[$i] = chr(ord($qqwry[$i]) ^ $key);
-            }
-            $qqwry = gzuncompress($qqwry);
-            $fp = fopen(BASE_PATH."/storage/qqwry.dat", "wb");
+        echo('downloading....');
+        $qqwry = file_get_contents('https://qqwry.mirror.noc.one/QQWry.Dat');
+        if ($qqwry != '') {
+            $fp = fopen(BASE_PATH . '/storage/qqwry.dat', 'wb');
             if ($fp) {
                 fwrite($fp, $qqwry);
                 fclose($fp);
             }
-            echo("finish....");
+            echo('finish....');
         }
     }
+
+    public function sendDailyUsageByTG()
+    {
+        $bot = new BotApi(Config::get('telegram_token'));
+        $users = User::where('telegram_id', '>', 0)->get();
+        foreach ($users as $user) {
+            $reply_message = '您当前的流量状况:
+今日已使用 ' . $user->TodayusedTraffic() . ' ' . number_format(($user->u + $user->d - $user->last_day_t) / $user->transfer_enable * 100, 2) . '%
+今日之前已使用 ' . $user->LastusedTraffic() . ' ' . number_format($user->last_day_t / $user->transfer_enable * 100, 2) . '%
+未使用 ' . $user->unusedTraffic() . ' ' . number_format(($user->transfer_enable - ($user->u + $user->d)) / $user->transfer_enable * 100, 2) . '%
+					                        ';
+            $bot->sendMessage($user->get_user_attributes('telegram_id'), $reply_message, $parseMode = null, $disablePreview = false, $replyToMessageId = null);
+        }
+    }
+
+    public function npmbuild()
+    {
+        chdir(BASE_PATH . '/uim-index-dev');
+        system('npm install');
+        system('npm run build');
+        system('cp -u ../public/vuedist/index.html ../resources/views/material/index.tpl');
+    }
 }

+ 64 - 46
app/Controllers/Admin/AnnController.php

@@ -8,6 +8,7 @@ use App\Utils\Telegram;
 use App\Services\Config;
 use App\Services\Mail;
 use App\Models\User;
+use Exception;
 use Ozdemir\Datatables\Datatables;
 use App\Utils\DatatablesHelper;
 
@@ -15,10 +16,10 @@ class AnnController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID",
-                              "date" => "日期", "content" => "内容");
-        $table_config['default_show_column'] = array("op", "id",
-                                                    "date", "content");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID',
+            'date' => '日期', 'content' => '内容');
+        $table_config['default_show_column'] = array('op', 'id',
+            'date', 'content');
         $table_config['ajax_url'] = 'announcement/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/announcement/index.tpl');
     }
@@ -31,63 +32,80 @@ class AnnController extends AdminController
     public function add($request, $response, $args)
     {
         $issend = $request->getParam('issend');
+        $PushBear = $request->getParam('PushBear');
         $vip = $request->getParam('vip');
         $content = $request->getParam('content');
-        $beginSend = (int)($request->getParam('page') - 1) * Config::get('sendPageLimit');
-        $users = User::where('class', ">=", $vip)->skip($beginSend)->limit(Config::get('sendPageLimit'))->get();
-        if($request->getParam('page') == 1){
+        $subject = Config::get('appName') . '-公告';
+
+        if ($request->getParam('page') == 1) {
             $ann = new Ann();
-            $ann->date =  date("Y-m-d H:i:s");
-            $ann->content =  $content;
-            $ann->markdown =  $request->getParam('markdown');
+            $ann->date = date('Y-m-d H:i:s');
+            $ann->content = $content;
+            $ann->markdown = $request->getParam('markdown');
 
             if (!$ann->save()) {
                 $rs['ret'] = 0;
-                $rs['msg'] = "添加失败";
+                $rs['msg'] = '添加失败';
                 return $response->getBody()->write(json_encode($rs));
             }
         }
-        if ($issend == 1){
-            foreach($users as $user){
-                $subject = Config::get('appName')."-公告";
+        if ($PushBear == 1) {
+            $PushBear_sendkey = Config::get('PushBear_sendkey');
+            $postdata = http_build_query(
+                array(
+                    'text' => $subject,
+                    'desp' => $request->getParam('markdown'),
+                    'sendkey' => $PushBear_sendkey
+                )
+            );
+            file_get_contents('https://pushbear.ftqq.com/sub?' . $postdata, false);
+        }
+        if ($issend == 1) {
+            $beginSend = ($request->getParam('page') - 1) * Config::get('sendPageLimit');
+            $users = User::where('class', '>=', $vip)->skip($beginSend)->limit(Config::get('sendPageLimit'))->get();
+            foreach ($users as $user) {
                 $to = $user->email;
                 if (!filter_var($to, FILTER_VALIDATE_EMAIL)) {
-                	continue;
+                    continue;
                 }
                 $text = $content;
                 try {
                     Mail::send($to, $subject, 'news/warn.tpl', [
-                        "user" => $user,"text" => $text
+                        'user' => $user, 'text' => $text
                     ], [
                     ]);
-                } catch (\Exception $e) {
+                } catch (Exception $e) {
                     continue;
                 }
             }
+            if (count($users) == Config::get('sendPageLimit')) {
+                $rs['ret'] = 2;
+                $rs['msg'] = $request->getParam('page') + 1;
+                return $response->getBody()->write(json_encode($rs));
+            }
         }
-        if(count($users) == Config::get('sendPageLimit')){
-            $rs['ret'] = 2;
-            $rs['msg'] = $request->getParam('page') + 1;
-            return $response->getBody()->write(json_encode($rs));
-        }else{
-            Telegram::SendMarkdown("新公告:".PHP_EOL.$request->getParam('markdown'));
-            $rs['ret'] = 1;
-			if ($issend == 1){
-				$rs['msg'] = "公告添加成功,邮件发送成功";
-			}
-			else{
-				$rs['msg'] = "公告添加成功";
-			}
-            return $response->getBody()->write(json_encode($rs));
+
+        Telegram::SendMarkdown('新公告:' . PHP_EOL . $request->getParam('markdown'));
+        $rs['ret'] = 1;
+        if ($issend == 1 && $PushBear == 1) {
+            $rs['msg'] = '公告添加成功,邮件发送和PushBear推送成功';
+        }
+        if ($issend == 1 && $PushBear != 1) {
+            $rs['msg'] = '公告添加成功,邮件发送成功';
+        }
+        if ($issend != 1 && $PushBear == 1) {
+            $rs['msg'] = '公告添加成功,PushBear推送成功';
         }
+        if ($issend != 1 && $PushBear != 1) {
+            $rs['msg'] = '公告添加成功';
+        }
+        return $response->getBody()->write(json_encode($rs));
     }
 
     public function edit($request, $response, $args)
     {
         $id = $args['id'];
         $ann = Ann::find($id);
-        if ($ann == null) {
-        }
         return $this->view()->assign('ann', $ann)->display('admin/announcement/edit.tpl');
     }
 
@@ -96,20 +114,20 @@ class AnnController extends AdminController
         $id = $args['id'];
         $ann = Ann::find($id);
 
-        $ann->content =  $request->getParam('content');
-        $ann->markdown =  $request->getParam('markdown');
-        $ann->date =  date("Y-m-d H:i:s");
+        $ann->content = $request->getParam('content');
+        $ann->markdown = $request->getParam('markdown');
+        $ann->date = date('Y-m-d H:i:s');
 
         if (!$ann->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "修改失败";
+            $rs['msg'] = '修改失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
-        Telegram::SendMarkdown("公告更新:".PHP_EOL.$request->getParam('markdown'));
+        Telegram::SendMarkdown('公告更新:' . PHP_EOL . $request->getParam('markdown'));
 
         $rs['ret'] = 1;
-        $rs['msg'] = "修改成功";
+        $rs['msg'] = '修改成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -120,11 +138,11 @@ class AnnController extends AdminController
         $ann = Ann::find($id);
         if (!$ann->delete()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -133,13 +151,13 @@ class AnnController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select id as op,id,date,content from announcement');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand" href="/admin/announcement/'.$data['id'].'/edit">编辑</a>
-                    <a class="btn btn-brand-accent" id="delete" value="'.$data['id'].'" href="javascript:void(0);" onClick="delete_modal_show(\''.$data['id'].'\')">删除</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand" href="/admin/announcement/' . $data['id'] . '/edit">编辑</a>
+                    <a class="btn btn-brand-accent" id="delete" value="' . $data['id'] . '" href="javascript:void(0);" onClick="delete_modal_show(\'' . $data['id'] . '\')">删除</a>';
         });
 
-        $datatables->edit('DT_RowId', function ($data) {
-            return 'row_1_'.$data['id'];
+        $datatables->edit('DT_RowId', static function ($data) {
+            return 'row_1_' . $data['id'];
         });
 
         $body = $response->getBody();

+ 15 - 16
app/Controllers/Admin/AutoController.php

@@ -4,18 +4,17 @@ namespace App\Controllers\Admin;
 
 use App\Models\Auto;
 use App\Controllers\AdminController;
-
 use Ozdemir\Datatables\Datatables;
 use App\Utils\DatatablesHelper;
 
-class autoController extends AdminController
+class AutoController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID",
-                              "datetime" => "时间", "type" => "类型", "value" => "内容");
-        $table_config['default_show_column'] = array("op", "id",
-                                  "datetime", "type", "value");
+        $table_config['total_column'] = array('id' => 'ID',
+            'datetime' => '时间', 'type' => '类型', 'value' => '内容');
+        $table_config['default_show_column'] = array('op', 'id',
+            'datetime', 'type', 'value');
         $table_config['ajax_url'] = 'auto/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/auto/index.tpl');
     }
@@ -28,18 +27,18 @@ class autoController extends AdminController
     public function add($request, $response, $args)
     {
         $auto = new Auto();
-        $auto->datetime =  time();
-        $auto->value =  $request->getParam('content');
-        $auto->sign =  $request->getParam('sign');
-        $auto->type =  1;
+        $auto->datetime = time();
+        $auto->value = $request->getParam('content');
+        $auto->sign = $request->getParam('sign');
+        $auto->type = 1;
 
         if (!$auto->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "添加失败";
+            $rs['msg'] = '添加失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "添加成功";
+        $rs['msg'] = '添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -50,11 +49,11 @@ class autoController extends AdminController
         $auto = Auto::find($id);
         if (!$auto->delete()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -63,11 +62,11 @@ class autoController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select id,datetime,type,value from auto');
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
-        $datatables->edit('type', function ($data) {
+        $datatables->edit('type', static function ($data) {
             return $data['type'] == 1 ? '命令下发' : '命令被执行';
         });
 

+ 34 - 35
app/Controllers/Admin/CodeController.php

@@ -15,13 +15,13 @@ class CodeController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "code" => "内容",
-                        "type" => "类型", "number" => "操作",
-                        "isused" => "是否已经使用", "userid" => "用户ID",
-                        "user_name" => "用户名", "usedatetime" => "使用时间");
+        $table_config['total_column'] = array('id' => 'ID', 'code' => '内容',
+            'type' => '类型', 'number' => '操作',
+            'isused' => '是否已经使用', 'userid' => '用户ID',
+            'user_name' => '用户名', 'usedatetime' => '使用时间');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'code/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/code/index.tpl');
@@ -43,11 +43,11 @@ class CodeController extends AdminController
         $type = $request->getParam('type');
         $number = $request->getParam('number');
 
-		if(Tools::isInt($n)==false){
-		    $rs['ret'] = 0;
-            $rs['msg'] = "非法请求";
+        if (Tools::isInt($n) == false) {
+            $rs['ret'] = 0;
+            $rs['msg'] = '非法请求';
             return $response->getBody()->write(json_encode($rs));
-		}
+        }
 
         for ($i = 0; $i < $n; $i++) {
             $char = Tools::genRandomChar(32);
@@ -55,15 +55,14 @@ class CodeController extends AdminController
             $code->code = time() . $char;
             $code->type = -1;
             $code->number = $number;
-            $code->userid=0;
-            $code->usedatetime="1989:06:04 02:30:00";
+            $code->userid = 0;
+            $code->usedatetime = '1989:06:04 02:30:00';
             $code->save();
         }
 
 
-
         $rs['ret'] = 1;
-        $rs['msg'] = "充值码添加成功";
+        $rs['msg'] = '充值码添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -80,12 +79,12 @@ class CodeController extends AdminController
         $code->number = $amount;
         $code->userid = Auth::getUser()->id;
         $code->isused = 1;
-        $code->usedatetime = date("Y:m:d H:i:s");
+        $code->usedatetime = date('Y:m:d H:i:s');
 
         $code->save();
 
         $rs['ret'] = 1;
-        $rs['msg'] = "添加成功";
+        $rs['msg'] = '添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -94,51 +93,51 @@ class CodeController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select code.id,code.code,code.type,code.number,code.isused,code.userid,code.userid as user_name,code.usedatetime from code');
 
-        $datatables->edit('number', function ($data) {
+        $datatables->edit('number', static function ($data) {
             switch ($data['type']) {
-              case -1:
-                return "充值 ".$data['number']." 元";
+                case -1:
+                    return '充值 ' . $data['number'] . ' 元';
 
-              case -2:
-                return "支出 ".$data['number']." 元";
+                case -2:
+                    return '支出 ' . $data['number'] . ' 元';
 
-              default:
-                return "已经废弃";
+                default:
+                    return '已经废弃';
             }
         });
 
-        $datatables->edit('isused', function ($data) {
+        $datatables->edit('isused', static function ($data) {
             return $data['isused'] == 1 ? '已使用' : '未使用';
         });
 
-        $datatables->edit('userid', function ($data) {
+        $datatables->edit('userid', static function ($data) {
             return $data['userid'] == 0 ? '未使用' : $data['userid'];
         });
 
-        $datatables->edit('user_name', function ($data) {
+        $datatables->edit('user_name', static function ($data) {
             $user = User::find($data['user_name']);
             if ($user == null) {
-                return "未使用";
+                return '未使用';
             }
 
             return $user->user_name;
         });
 
-        $datatables->edit('type', function ($data) {
+        $datatables->edit('type', static function ($data) {
             switch ($data['type']) {
-              case -1:
-                return "充值金额";
+                case -1:
+                    return '充值金额';
 
-              case -2:
-                return "财务支出";
+                case -2:
+                    return '财务支出';
 
-              default:
-                return "已经废弃";
+                default:
+                    return '已经废弃';
             }
         });
 
-        $datatables->edit('usedatetime', function ($data) {
-            return $data['usedatetime'] > '2000-1-1 0:0:0' ? $data['usedatetime'] : "未使用";
+        $datatables->edit('usedatetime', static function ($data) {
+            return $data['usedatetime'] > '2000-1-1 0:0:0' ? $data['usedatetime'] : '未使用';
         });
 
         $body = $response->getBody();

+ 33 - 34
app/Controllers/Admin/DetectController.php

@@ -2,7 +2,6 @@
 
 namespace App\Controllers\Admin;
 
-use App\Models\DetectLog;
 use App\Models\DetectRule;
 use App\Utils\Telegram;
 use App\Controllers\AdminController;
@@ -14,12 +13,12 @@ class DetectController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID", "name" => "名称",
-                          "text" => "介绍", "regex" => "正则表达式",
-                          "type" => "类型");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID', 'name' => '名称',
+            'text' => '介绍', 'regex' => '正则表达式',
+            'type' => '类型');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'detect/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/detect/index.tpl');
@@ -27,15 +26,15 @@ class DetectController extends AdminController
 
     public function log($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "user_id" => "用户ID",
-                          "user_name" => "用户名", "node_id" => "节点ID",
-                          "node_name" => "节点名", "rule_id" => "规则ID",
-                          "rule_name" => "规则名", "rule_text" => "规则描述",
-                          "rule_regex" => "规则正则表达式", "rule_type" => "规则类型",
-                          "datetime" => "时间");
+        $table_config['total_column'] = array('id' => 'ID', 'user_id' => '用户ID',
+            'user_name' => '用户名', 'node_id' => '节点ID',
+            'node_name' => '节点名', 'rule_id' => '规则ID',
+            'rule_name' => '规则名', 'rule_text' => '规则描述',
+            'rule_regex' => '规则正则表达式', 'rule_type' => '规则类型',
+            'datetime' => '时间');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'log/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/detect/log.tpl');
@@ -49,21 +48,21 @@ class DetectController extends AdminController
     public function add($request, $response, $args)
     {
         $rule = new DetectRule();
-        $rule->name =  $request->getParam('name');
-        $rule->text =  $request->getParam('text');
-        $rule->regex =  $request->getParam('regex');
-        $rule->type =  $request->getParam('type');
+        $rule->name = $request->getParam('name');
+        $rule->text = $request->getParam('text');
+        $rule->regex = $request->getParam('regex');
+        $rule->type = $request->getParam('type');
 
         if (!$rule->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "添加失败";
+            $rs['msg'] = '添加失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
-        Telegram::SendMarkdown("有新的审计规则:".$rule->name);
+        Telegram::SendMarkdown('有新的审计规则:' . $rule->name);
 
         $rs['ret'] = 1;
-        $rs['msg'] = "添加成功";
+        $rs['msg'] = '添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -79,21 +78,21 @@ class DetectController extends AdminController
         $id = $args['id'];
         $rule = DetectRule::find($id);
 
-        $rule->name =  $request->getParam('name');
-        $rule->text =  $request->getParam('text');
-        $rule->regex =  $request->getParam('regex');
-        $rule->type =  $request->getParam('type');
+        $rule->name = $request->getParam('name');
+        $rule->text = $request->getParam('text');
+        $rule->regex = $request->getParam('regex');
+        $rule->type = $request->getParam('type');
 
         if (!$rule->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "修改失败";
+            $rs['msg'] = '修改失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
-        Telegram::SendMarkdown("规则更新:".PHP_EOL.$request->getParam('name'));
+        Telegram::SendMarkdown('规则更新:' . PHP_EOL . $request->getParam('name'));
 
         $rs['ret'] = 1;
-        $rs['msg'] = "修改成功";
+        $rs['msg'] = '修改成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -104,11 +103,11 @@ class DetectController extends AdminController
         $rule = DetectRule::find($id);
         if (!$rule->delete()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -117,12 +116,12 @@ class DetectController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select id as op,id,name,text,regex,type from detect_list');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand" href="/admin/detect/'.$data['id'].'/edit">编辑</a>
-                    <a class="btn btn-brand-accent" id="delete" value="'.$data['id'].'" href="javascript:void(0);" onClick="delete_modal_show(\''.$data['id'].'\')">删除</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand" href="/admin/detect/' . $data['id'] . '/edit">编辑</a>
+                    <a class="btn btn-brand-accent" id="delete" value="' . $data['id'] . '" href="javascript:void(0);" onClick="delete_modal_show(\'' . $data['id'] . '\')">删除</a>';
         });
 
-        $datatables->edit('type', function ($data) {
+        $datatables->edit('type', static function ($data) {
             return $data['type'] == 1 ? '数据包明文匹配' : '数据包十六进制匹配';
         });
 
@@ -135,11 +134,11 @@ class DetectController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select detect_log.id,user_id,user.user_name,node_id,node.name as node_name,list.id as rule_id,list.name as rule_name,list.text as rule_text,list.regex as rule_regex,list.type as rule_type,detect_log.datetime from detect_log,user,ss_node as node,detect_list as list where user.id=detect_log.user_id and node.id = detect_log.node_id and list.id = detect_log.list_id');
 
-        $datatables->edit('rule_type', function ($data) {
+        $datatables->edit('rule_type', static function ($data) {
             return $data['rule_type'] == 1 ? '数据包明文匹配' : '数据包十六进制匹配';
         });
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 

+ 43 - 45
app/Controllers/Admin/IpController.php

@@ -2,8 +2,6 @@
 
 namespace App\Controllers\Admin;
 
-use App\Models\Ip;
-use App\Models\LoginIp;
 use App\Models\BlockIp;
 use App\Models\UnblockIp;
 use App\Models\Node;
@@ -19,12 +17,12 @@ class IpController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "userid" => "用户ID",
-                          "user_name" => "用户名", "ip" => "IP",
-                          "location" => "归属地", "datetime" => "时间", "type" => "类型");
+        $table_config['total_column'] = array('id' => 'ID', 'userid' => '用户ID',
+            'user_name' => '用户名', 'ip' => 'IP',
+            'location' => '归属地', 'datetime' => '时间', 'type' => '类型');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'login/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/ip/login.tpl');
@@ -32,13 +30,13 @@ class IpController extends AdminController
 
     public function alive($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "userid" => "用户ID",
-                          "user_name" => "用户名", "nodeid" => "节点ID",
-                          "node_name" => "节点名", "ip" => "IP",
-                          "location" => "归属地", "datetime" => "时间", "is_node" => "是否为中转连接");
+        $table_config['total_column'] = array('id' => 'ID', 'userid' => '用户ID',
+            'user_name' => '用户名', 'nodeid' => '节点ID',
+            'node_name' => '节点名', 'ip' => 'IP',
+            'location' => '归属地', 'datetime' => '时间', 'is_node' => '是否为中转连接');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'alive/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/ip/alive.tpl');
@@ -46,12 +44,12 @@ class IpController extends AdminController
 
     public function block($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID",
-                        "name" => "节点名称", "ip" => "IP",
-                        "location" => "归属地", "datetime" => "时间");
+        $table_config['total_column'] = array('id' => 'ID',
+            'name' => '节点名称', 'ip' => 'IP',
+            'location' => '归属地', 'datetime' => '时间');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'block/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/ip/block.tpl');
@@ -59,12 +57,12 @@ class IpController extends AdminController
 
     public function unblock($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "userid" => "用户ID",
-                          "user_name" => "用户名", "ip" => "IP",
-                          "location" => "归属地", "datetime" => "时间");
+        $table_config['total_column'] = array('id' => 'ID', 'userid' => '用户ID',
+            'user_name' => '用户名', 'ip' => 'IP',
+            'location' => '归属地', 'datetime' => '时间');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'unblock/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/ip/unblock.tpl');
@@ -75,7 +73,7 @@ class IpController extends AdminController
         $ip = $request->getParam('ip');
 
         $user = Auth::getUser();
-        $BIP = BlockIp::where("ip", $ip)->get();
+        $BIP = BlockIp::where('ip', $ip)->get();
         foreach ($BIP as $bi) {
             $bi->delete();
         }
@@ -88,7 +86,7 @@ class IpController extends AdminController
 
 
         $res['ret'] = 1;
-        $res['msg'] = "发送解封命令解封 ".$ip." 成功";
+        $res['msg'] = '发送解封命令解封 ' . $ip . ' 成功';
         return $this->echoJson($response, $res);
     }
 
@@ -97,15 +95,15 @@ class IpController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select blockip.id,node.name,blockip.ip,blockip.ip as location,datetime from blockip,ss_node as node WHERE blockip.nodeid = node.id');
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
         $iplocation = new QQWry();
 
-        $datatables->edit('location', function ($data) use ($iplocation) {
-            $location=$iplocation->getlocation($data['location']);
-            return iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
+        $datatables->edit('location', static function ($data) use ($iplocation) {
+            $location = $iplocation->getlocation($data['location']);
+            return iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
         });
 
         $body = $response->getBody();
@@ -117,15 +115,15 @@ class IpController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select unblockip.id,userid,user.user_name,unblockip.ip,unblockip.ip as location,datetime from unblockip,user WHERE unblockip.userid = user.id');
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
         $iplocation = new QQWry();
 
-        $datatables->edit('location', function ($data) use ($iplocation) {
-            $location=$iplocation->getlocation($data['location']);
-            return iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
+        $datatables->edit('location', static function ($data) use ($iplocation) {
+            $location = $iplocation->getlocation($data['location']);
+            return iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
         });
 
         $body = $response->getBody();
@@ -137,18 +135,18 @@ class IpController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select login_ip.id,login_ip.userid,user.user_name,login_ip.ip,login_ip.ip as location,login_ip.datetime,login_ip.type from login_ip,user WHERE login_ip.userid = user.id');
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
 
         $iplocation = new QQWry();
-        $datatables->edit('location', function ($data) use ($iplocation) {
-            $location=$iplocation->getlocation($data['location']);
-            return iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
+        $datatables->edit('location', static function ($data) use ($iplocation) {
+            $location = $iplocation->getlocation($data['location']);
+            return iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
         });
 
-        $datatables->edit('type', function ($data) {
+        $datatables->edit('type', static function ($data) {
             return $data['type'] == 0 ? '成功' : '失败';
         });
 
@@ -162,28 +160,28 @@ class IpController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select alive_ip.id,alive_ip.userid,user.user_name,alive_ip.nodeid,ss_node.name as node_name,alive_ip.ip,alive_ip.ip as location,alive_ip.datetime,alive_ip.id as is_node from alive_ip,user,ss_node WHERE alive_ip.userid = user.id and alive_ip.nodeid = ss_node.id and `datetime` > UNIX_TIMESTAMP() - 60');
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
         $iplocation = new QQWry();
 
-        $datatables->edit('ip', function ($data){
+        $datatables->edit('ip', static function ($data) {
             return Tools::getRealIp($data['ip']);
         });
 
-        $datatables->edit('is_node', function ($data){
-            $is_node = Node::where("node_ip", Tools::getRealIp($data['ip']))->first();
-            if($is_node) {
-                return "是";
-            } else {
-                return "否";
+        $datatables->edit('is_node', static function ($data) {
+            $is_node = Node::where('node_ip', Tools::getRealIp($data['ip']))->first();
+            if ($is_node) {
+                return '是';
             }
+
+            return '否';
         });
 
-        $datatables->edit('location', function ($data) use ($iplocation) {
-            $location=$iplocation->getlocation(Tools::getRealIp($data['location']));
-            return iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
+        $datatables->edit('location', static function ($data) use ($iplocation) {
+            $location = $iplocation->getlocation(Tools::getRealIp($data['location']));
+            return iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
         });
 
         $body = $response->getBody();

+ 134 - 140
app/Controllers/Admin/NodeController.php

@@ -16,17 +16,17 @@ class NodeController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = Array("op" => "操作", "id" => "ID", "name" => "节点名称",
-                            "type" => "显示与隐藏", "sort" => "类型",
-                            "server" => "节点地址", "node_ip" => "节点IP",
-                            "info" => "节点信息",
-                            "status" => "状态", "traffic_rate" => "流量比率", "node_group" => "节点群组",
-                            "node_class" => "节点等级", "node_speedlimit" => "节点限速/Mbps",
-                            "node_bandwidth" => "已走流量/GB", "node_bandwidth_limit" => "流量限制/GB",
-                            "bandwidthlimit_resetday" => "流量重置日", "node_heartbeat" => "上一次活跃时间",
-                            "custom_method" => "自定义加密", "custom_rss" => "自定义协议以及混淆",
-                            "mu_only" => "只启用单端口多用户");
-        $table_config['default_show_column'] = Array("op", "id", "name", "sort");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID', 'name' => '节点名称',
+            'type' => '显示与隐藏', 'sort' => '类型',
+            'server' => '节点地址', 'node_ip' => '节点IP',
+            'info' => '节点信息',
+            'status' => '状态', 'traffic_rate' => '流量比率', 'node_group' => '节点群组',
+            'node_class' => '节点等级', 'node_speedlimit' => '节点限速/Mbps',
+            'node_bandwidth' => '已走流量/GB', 'node_bandwidth_limit' => '流量限制/GB',
+            'bandwidthlimit_resetday' => '流量重置日', 'node_heartbeat' => '上一次活跃时间',
+            'custom_method' => '自定义加密', 'custom_rss' => '自定义协议以及混淆',
+            'mu_only' => '只启用单端口多用户');
+        $table_config['default_show_column'] = array('op', 'id', 'name', 'sort');
         $table_config['ajax_url'] = 'node/ajax';
 
         return $this->view()->assign('table_config', $table_config)->display('admin/node/index.tpl');
@@ -40,12 +40,12 @@ class NodeController extends AdminController
     public function add($request, $response, $args)
     {
         $node = new Node();
-        $node->name =  $request->getParam('name');
-        $node->server =  trim($request->getParam('server'));
-        $node->method =  $request->getParam('method');
-        $node->custom_method =  $request->getParam('custom_method');
-        $node->custom_rss =  $request->getParam('custom_rss');
-        $node->mu_only =  $request->getParam('mu_only');
+        $node->name = $request->getParam('name');
+        $node->server = trim($request->getParam('server'));
+        $node->method = $request->getParam('method');
+        $node->custom_method = $request->getParam('custom_method');
+        $node->custom_rss = $request->getParam('custom_rss');
+        $node->mu_only = $request->getParam('mu_only');
         $node->traffic_rate = $request->getParam('rate');
         $node->info = $request->getParam('info');
         $node->type = $request->getParam('type');
@@ -54,52 +54,45 @@ class NodeController extends AdminController
         $node->status = $request->getParam('status');
         $node->sort = $request->getParam('sort');
 
-		$req_node_ip = trim($request->getParam('node_ip'));
-		if($req_node_ip==""){
-			$req_node_ip=$node->server;
-		}
-                  
-        if ($node->sort == 11) {
-            $server_list = explode(";", $node->server);
-			if(!Tools::is_ip($server_list[0])){
-				$node->node_ip = gethostbyname($server_list[0]);
-			}else{
-				$node->node_ip = $req_node_ip;
-			}
-        } else if ($node->sort == 0 || $node->sort == 1 || $node->sort == 10){
-			if(!Tools::is_ip($node->server)){
-				$node->node_ip = gethostbyname($node->server);
-			}else{
-				$node->node_ip = $req_node_ip;
-			}                        
-        } else {
-            $node->node_ip="";
+        $req_node_ip = trim($request->getParam('node_ip'));
+        if ($req_node_ip == '') {
+            $req_node_ip = $node->server;
         }
 
-		if($node->node_ip==""&&($node->sort == 11||$node->sort == 0 || $node->sort == 1 || $node->sort == 10)){
-			$rs['ret'] = 0;
-            $rs['msg'] = "获取节点IP失败,请检查您输入的节点地址是否正确!";
-            return $response->getBody()->write(json_encode($rs));
-		}
+        if (in_array($node->sort, array(0, 1, 10, 11, 12, 13))) {
+            $server_list = explode(';', $node->server);
+            if (!Tools::is_ip($server_list[0])) {
+                $node->node_ip = gethostbyname($server_list[0]);
+            } else {
+                $node->node_ip = $req_node_ip;
+            }
+            if ($node->node_ip == '') {
+                $rs['ret'] = 0;
+                $rs['msg'] = '获取节点IP失败,请检查您输入的节点地址是否正确!';
+                return $response->getBody()->write(json_encode($rs));
+            }
+        } else {
+            $node->node_ip = '';
+        }
 
-        if ($node->sort==1) {
+        if ($node->sort == 1) {
             Radius::AddNas($node->node_ip, $request->getParam('server'));
         }
-        $node->node_class=$request->getParam('class');
-        $node->node_bandwidth_limit=$request->getParam('node_bandwidth_limit')*1024*1024*1024;
-        $node->bandwidthlimit_resetday=$request->getParam('bandwidthlimit_resetday');
+        $node->node_class = $request->getParam('class');
+        $node->node_bandwidth_limit = $request->getParam('node_bandwidth_limit') * 1024 * 1024 * 1024;
+        $node->bandwidthlimit_resetday = $request->getParam('bandwidthlimit_resetday');
 
         $node->save();
 
-        $domain_name = explode('.'.Config::get('cloudflare_name'), $node->server);
+        $domain_name = explode('.' . Config::get('cloudflare_name'), $node->server);
         if (Config::get('cloudflare_enable') == 'true') {
             CloudflareDriver::updateRecord($domain_name[0], $node->node_ip);
         }
 
-        Telegram::Send("新节点添加~".$request->getParam('name'));
+        Telegram::Send('新节点添加~' . $request->getParam('name'));
 
         $rs['ret'] = 1;
-        $rs['msg'] = "节点添加成功";
+        $rs['msg'] = '节点添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -107,8 +100,6 @@ class NodeController extends AdminController
     {
         $id = $args['id'];
         $node = Node::find($id);
-        if ($node == null) {
-        }
         return $this->view()->assign('node', $node)->display('admin/node/edit.tpl');
     }
 
@@ -117,71 +108,68 @@ class NodeController extends AdminController
         $id = $args['id'];
         $node = Node::find($id);
 
-        $node->name =  $request->getParam('name');
-        $node->node_group =  $request->getParam('group');
-        $node->server =  trim($request->getParam('server'));
-        $node->method =  $request->getParam('method');
-        $node->custom_method =  $request->getParam('custom_method');
-        $node->custom_rss =  $request->getParam('custom_rss');
-        $node->mu_only =  $request->getParam('mu_only');
+        $node->name = $request->getParam('name');
+        $node->node_group = $request->getParam('group');
+        $node->server = trim($request->getParam('server'));
+        $node->method = $request->getParam('method');
+        $node->custom_method = $request->getParam('custom_method');
+        $node->custom_rss = $request->getParam('custom_rss');
+        $node->mu_only = $request->getParam('mu_only');
         $node->traffic_rate = $request->getParam('rate');
         $node->info = $request->getParam('info');
         $node->node_speedlimit = $request->getParam('node_speedlimit');
         $node->type = $request->getParam('type');
         $node->sort = $request->getParam('sort');
 
-		$req_node_ip=trim($request->getParam('node_ip'));
-		if($req_node_ip==""){
-			$req_node_ip=$node->server;
-		}
-
-		$success=true;
-		if ($node->sort == 11) {
-            $server_list = explode(";", $node->server);
-			if(!Tools::is_ip($server_list[0])){
-				$success=$node->changeNodeIp($server_list[0]);
-			}else{
-				$success=$node->changeNodeIp($req_node_ip);
-			}
-        } else if ($node->sort == 0 || $node->sort == 1 || $node->sort == 10){
-			if(!Tools::is_ip($node->server)){
-				$success=$node->changeNodeIp($node->server);
-			}else{
-				$success=$node->changeNodeIp($req_node_ip);
-			}                        
+        $req_node_ip = trim($request->getParam('node_ip'));
+        if ($req_node_ip == '') {
+            $req_node_ip = $node->server;
+        }
+
+        $success = true;
+        if (in_array($node->sort, array(0, 1, 10, 11, 12, 13))) {
+            $server_list = explode(';', $node->server);
+            if (!Tools::is_ip($server_list[0])) {
+                $success = $node->changeNodeIp($server_list[0]);
+            } else {
+                $success = $node->changeNodeIp($req_node_ip);
+            }
         } else {
-            $node->node_ip="";
+            $node->node_ip = '';
         }
 
-		if (!$success) {
-			$rs['ret'] = 0;
-            $rs['msg'] = "更新节点IP失败,请检查您输入的节点地址是否正确!";
+        if (!$success) {
+            $rs['ret'] = 0;
+            $rs['msg'] = '更新节点IP失败,请检查您输入的节点地址是否正确!';
             return $response->getBody()->write(json_encode($rs));
-        }      
+        }
+
+        if (in_array($node->sort, array(0, 10, 11, 12, 13))) {
+            Tools::updateRelayRuleIp($node);
+        }
 
-        if ($node->sort==1) {
-            $SS_Node=Node::where('sort', '=', 0)->where('server', '=', $request->getParam('server'))->first();
-            if ($SS_Node!=null) {
-                if (time()-$SS_Node->node_heartbeat<300||$SS_Node->node_heartbeat==0) {
+        if ($node->sort == 1) {
+            $SS_Node = Node::where('sort', '=', 0)->where('server', '=', $request->getParam('server'))->first();
+            if ($SS_Node != null) {
+                if ($SS_Node->node_heartbeat == 0 || time() - $SS_Node->node_heartbeat < 300) {
                     Radius::AddNas(gethostbyname($request->getParam('server')), $request->getParam('server'));
                 }
-            } 
-			else {
+            } else {
                 Radius::AddNas(gethostbyname($request->getParam('server')), $request->getParam('server'));
             }
         }
 
         $node->status = $request->getParam('status');
-        $node->node_class=$request->getParam('class');
-        $node->node_bandwidth_limit=$request->getParam('node_bandwidth_limit')*1024*1024*1024;
-        $node->bandwidthlimit_resetday=$request->getParam('bandwidthlimit_resetday');
+        $node->node_class = $request->getParam('class');
+        $node->node_bandwidth_limit = $request->getParam('node_bandwidth_limit') * 1024 * 1024 * 1024;
+        $node->bandwidthlimit_resetday = $request->getParam('bandwidthlimit_resetday');
 
         $node->save();
 
-        Telegram::Send("节点信息被修改~".$request->getParam('name'));
+        Telegram::Send('节点信息被修改~' . $request->getParam('name'));
 
         $rs['ret'] = 1;
-        $rs['msg'] = "修改成功";
+        $rs['msg'] = '修改成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -190,7 +178,7 @@ class NodeController extends AdminController
     {
         $id = $request->getParam('id');
         $node = Node::find($id);
-        if ($node->sort==1) {
+        if ($node->sort == 1) {
             Radius::DelNas($node->node_ip);
         }
 
@@ -198,14 +186,14 @@ class NodeController extends AdminController
 
         if (!$node->delete()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
-        Telegram::Send("节点被删除~".$name);
+        Telegram::Send('节点被删除~' . $name);
 
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -214,92 +202,98 @@ class NodeController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
 
 
-        $total_column = Array("op" => "操作", "id" => "ID", "name" => "节点名称",
-                              "type" => "显示与隐藏", "sort" => "类型",
-                              "server" => "节点地址", "node_ip" => "节点IP",
-                              "info" => "节点信息",
-                              "status" => "状态", "traffic_rate" => "流量比率", "node_group" => "节点群组",
-                              "node_class" => "节点等级", "node_speedlimit" => "节点限速/Mbps",
-                              "node_bandwidth" => "已走流量/GB", "node_bandwidth_limit" => "流量限制/GB",
-                              "bandwidthlimit_resetday" => "流量重置日", "node_heartbeat" => "上一次活跃时间",
-                              "custom_method" => "自定义加密", "custom_rss" => "自定义协议以及混淆",
-                              "mu_only" => "只启用单端口多用户");
+        $total_column = array('op' => '操作', 'id' => 'ID', 'name' => '节点名称',
+            'type' => '显示与隐藏', 'sort' => '类型',
+            'server' => '节点地址', 'node_ip' => '节点IP',
+            'info' => '节点信息',
+            'status' => '状态', 'traffic_rate' => '流量比率', 'node_group' => '节点群组',
+            'node_class' => '节点等级', 'node_speedlimit' => '节点限速/Mbps',
+            'node_bandwidth' => '已走流量/GB', 'node_bandwidth_limit' => '流量限制/GB',
+            'bandwidthlimit_resetday' => '流量重置日', 'node_heartbeat' => '上一次活跃时间',
+            'custom_method' => '自定义加密', 'custom_rss' => '自定义协议以及混淆',
+            'mu_only' => '只启用单端口多用户');
         $key_str = '';
-        foreach($total_column as $single_key => $single_value) {
-            if($single_key == 'op') {
+        foreach ($total_column as $single_key => $single_value) {
+            if ($single_key == 'op') {
                 $key_str .= 'id as op';
                 continue;
             }
 
-            $key_str .= ','.$single_key;
+            $key_str .= ',' . $single_key;
         }
-        $datatables->query('Select '.$key_str.' from ss_node');
+        $datatables->query('Select ' . $key_str . ' from ss_node');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand" '.($data['sort'] == 999 ? 'disabled' : 'href="/admin/node/'.$data['id'].'/edit"').'>编辑</a>
-                    <a class="btn btn-brand-accent" '.($data['sort'] == 999 ? 'disabled' : 'id="delete" value="'.$data['id'].'" href="javascript:void(0);" onClick="delete_modal_show(\''.$data['id'].'\')"').'>删除</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand" ' . ($data['sort'] == 999 ? 'disabled' : 'href="/admin/node/' . $data['id'] . '/edit"') . '>编辑</a>
+                    <a class="btn btn-brand-accent" ' . ($data['sort'] == 999 ? 'disabled' : 'id="delete" value="' . $data['id'] . '" href="javascript:void(0);" onClick="delete_modal_show(\'' . $data['id'] . '\')"') . '>删除</a>';
         });
 
-        $datatables->edit('node_bandwidth', function ($data) {
+        $datatables->edit('node_bandwidth', static function ($data) {
             return Tools::flowToGB($data['node_bandwidth']);
         });
 
-        $datatables->edit('node_bandwidth_limit', function ($data) {
+        $datatables->edit('node_bandwidth_limit', static function ($data) {
             return Tools::flowToGB($data['node_bandwidth_limit']);
         });
 
-        $datatables->edit('sort', function ($data) {
+        $datatables->edit('sort', static function ($data) {
             $sort = '';
-            switch($data['sort']) {
+            switch ($data['sort']) {
                 case 0:
-                  $sort = 'Shadowsocks';
-                  break;
+                    $sort = 'Shadowsocks';
+                    break;
                 case 1:
-                  $sort = 'VPN/Radius基础';
-                  break;
+                    $sort = 'VPN/Radius基础';
+                    break;
                 case 2:
-                  $sort = 'SSH';
-                  break;
+                    $sort = 'SSH';
+                    break;
                 case 5:
-                  $sort = 'Anyconnect';
-                  break;
+                    $sort = 'Anyconnect';
+                    break;
                 case 9:
-                  $sort = 'Shadowsocks - 单端口多用户';
-                  break;
+                    $sort = 'Shadowsocks - 单端口多用户';
+                    break;
                 case 10:
-                  $sort = 'Shadowsocks - 中转';
-                  break;
+                    $sort = 'Shadowsocks - 中转';
+                    break;
                 case 11:
-                  $sort = 'V2Ray 节点';
-                  break;
+                    $sort = 'V2Ray 节点';
+                    break;
+                case 12:
+                    $sort = 'V2Ray - 中转';
+                    break;
+                case 13:
+                    $sort = 'Shadowsocks - V2Ray-Plugin';
+                    break;
                 default:
-                  $sort = '系统保留';
+                    $sort = '系统保留';
             }
             return $sort;
         });
 
-        $datatables->edit('type', function ($data) {
+        $datatables->edit('type', static function ($data) {
             return $data['type'] == 1 ? '显示' : '隐藏';
         });
 
-        $datatables->edit('custom_method', function ($data) {
+        $datatables->edit('custom_method', static function ($data) {
             return $data['custom_method'] == 1 ? '启用' : '关闭';
         });
 
-        $datatables->edit('custom_rss', function ($data) {
+        $datatables->edit('custom_rss', static function ($data) {
             return $data['custom_rss'] == 1 ? '启用' : '关闭';
         });
 
-        $datatables->edit('mu_only', function ($data) {
+        $datatables->edit('mu_only', static function ($data) {
             return $data['mu_only'] == 1 ? '启用' : '关闭';
         });
 
-        $datatables->edit('node_heartbeat', function ($data) {
+        $datatables->edit('node_heartbeat', static function ($data) {
             return date('Y-m-d H:i:s', $data['node_heartbeat']);
         });
 
-        $datatables->edit('DT_RowId', function ($data) {
-            return 'row_1_'.$data['id'];
+        $datatables->edit('DT_RowId', static function ($data) {
+            return 'row_1_' . $data['id'];
         });
 
         $body = $response->getBody();

+ 101 - 48
app/Controllers/Admin/RelayController.php

@@ -8,7 +8,7 @@ use App\Models\User;
 use App\Utils\Tools;
 use App\Services\Auth;
 use App\Controllers\AdminController;
-
+use ArrayObject;
 use Ozdemir\Datatables\Datatables;
 use App\Utils\DatatablesHelper;
 
@@ -16,12 +16,12 @@ class RelayController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID", "user_id" => "用户ID",
-                          "user_name" => "用户名", "source_node_name" => "起源节点",
-                          "dist_node_name" => "目标节点", "port" => "端口", "priority" => "优先级");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID', 'user_id' => '用户ID',
+            'user_name' => '用户名', 'source_node_name' => '起源节点',
+            'dist_node_name' => '目标节点', 'port' => '端口', 'priority' => '优先级');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'relay/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/relay/index.tpl');
@@ -30,15 +30,34 @@ class RelayController extends AdminController
     public function create($request, $response, $args)
     {
         $user = Auth::getUser();
-        $source_nodes = Node::where('sort', 10)->orderBy('name')->get();
-
+        $source_nodes = Node::where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
+            }
+        )->orderBy('name')->get();
+        foreach ($source_nodes as $node) {
+            if ($node->sort == 12) {
+                $node->name .= ' 正在使用V2ray后端 ';
+            }
+        }
         $dist_nodes = Node::where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', 0)
-                    ->orWhere('sort', 10);
+                    ->orWhere('sort', 10)
+                    ->orWhere('sort', 11)
+                    ->orWhere('sort', 12);
             }
         )->orderBy('name')->get();
 
+        foreach ($dist_nodes as $node) {
+            if ($node->sort == 11 || $node->sort == 12) {
+                $node_explode = Tools::ssv2Array($node->server);
+                $node->name = $node->name . ' 如果是V2ray后端 请设置成 ' . $node_explode['port'];
+            } else {
+                $node->name .= ' 如果是V2ray后端 请不要设置,用户页面设置 ';
+            }
+        }
 
         return $this->view()->assign('source_nodes', $source_nodes)->assign('dist_nodes', $dist_nodes)->display('admin/relay/add.tpl');
     }
@@ -54,14 +73,22 @@ class RelayController extends AdminController
         $source_node = Node::where('id', $source_node_id)->first();
         if ($source_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "起源节点错误。";
+            $rs['msg'] = '起源节点错误。';
             return $response->getBody()->write(json_encode($rs));
         }
 
+        if ($source_node->sort == 12) {
+            $rules = Relay::Where('source_node_id', $source_node_id)->get();
+            if (count($rules) > 0) {
+                $rs['ret'] = 0;
+                $rs['msg'] = 'v2ray中转一个起点一个rule';
+                return $response->getBody()->write(json_encode($rs));
+            }
+        }
         $dist_node = Node::where('id', $dist_node_id)->first();
         if ($dist_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "目标节点错误。";
+            $rs['msg'] = '目标节点错误。';
             return $response->getBody()->write(json_encode($rs));
         }
 
@@ -84,21 +111,21 @@ class RelayController extends AdminController
         $maybe_rule_id = Tools::has_conflict_rule($rule, $ruleset, 0, $rule->source_node_id);
         if ($maybe_rule_id != 0) {
             $rs['ret'] = 0;
-            $rs['msg'] = "您即将添加的规则与规则 ID:".$maybe_rule_id." 冲突!";
+            $rs['msg'] = '您即将添加的规则与规则 ID:' . $maybe_rule_id . ' 冲突!';
             if ($maybe_rule_id == -1) {
-                $rs['msg'] = "您即将添加的规则可能会造成冲突!";
+                $rs['msg'] = '您即将添加的规则可能会造成冲突!';
             }
             return $response->getBody()->write(json_encode($rs));
         }
 
         if (!$rule->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "添加失败";
+            $rs['msg'] = '添加失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $rs['ret'] = 1;
-        $rs['msg'] = "添加成功";
+        $rs['msg'] = '添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -113,15 +140,36 @@ class RelayController extends AdminController
             exit(0);
         }
 
-        $source_nodes = Node::where('sort', 10)->orderBy('name')->get();
+        $source_nodes = Node::where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
+            }
+        )->orderBy('name')->get();
+        foreach ($source_nodes as $node) {
+            if ($node->sort == 12) {
+                $node->name .= ' 正在使用V2ray后端 ';
+            }
+        }
 
         $dist_nodes = Node::where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', 0)
-                    ->orWhere('sort', 10);
+                    ->orWhere('sort', 10)
+                    ->orWhere('sort', 11)
+                    ->orWhere('sort', 12);
             }
         )->orderBy('name')->get();
 
+        foreach ($dist_nodes as $node) {
+            if ($node->sort == 11 || $node->sort == 12) {
+                $node_explode = Tools::ssv2Array($node->server);
+                $node->name = $node->name . ' 如果是V2ray后端 请设置成' . $node_explode['port'];
+            } else {
+                $node->name .= ' 如果是V2ray后端 请不要设置,用户页面设置 ';
+            }
+        }
+
         return $this->view()->assign('rule', $rule)->assign('source_nodes', $source_nodes)->assign('dist_nodes', $dist_nodes)->display('admin/relay/edit.tpl');
     }
 
@@ -143,14 +191,14 @@ class RelayController extends AdminController
         $source_node = Node::where('id', $source_node_id)->first();
         if ($source_node == null && $source_node_id != 0) {
             $rs['ret'] = 0;
-            $rs['msg'] = "起源节点 ID 错误。";
+            $rs['msg'] = '起源节点 ID 错误。';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $dist_node = Node::where('id', $dist_node_id)->first();
         if ($dist_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "目标节点 ID 错误。";
+            $rs['msg'] = '目标节点 ID 错误。';
             return $response->getBody()->write(json_encode($rs));
         }
 
@@ -172,9 +220,9 @@ class RelayController extends AdminController
         $maybe_rule_id = Tools::has_conflict_rule($rule, $ruleset, $rule->id, $rule->source_node_id);
         if ($maybe_rule_id != 0) {
             $rs['ret'] = 0;
-            $rs['msg'] = "您即将添加的规则与规则 ID:".$maybe_rule_id." 冲突!";
+            $rs['msg'] = '您即将添加的规则与规则 ID:' . $maybe_rule_id . ' 冲突!';
             if ($maybe_rule_id == -1) {
-                $rs['msg'] = "您即将添加的规则可能会造成冲突!";
+                $rs['msg'] = '您即将添加的规则可能会造成冲突!';
             }
             return $response->getBody()->write(json_encode($rs));
         }
@@ -182,12 +230,12 @@ class RelayController extends AdminController
 
         if (!$rule->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "修改失败";
+            $rs['msg'] = '修改失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $rs['ret'] = 1;
-        $rs['msg'] = "修改成功";
+        $rs['msg'] = '修改成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -204,39 +252,44 @@ class RelayController extends AdminController
 
         if (!$rule->delete()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
     public function path_search($request, $response, $args)
     {
-        $uid=$args["id"];
+        $uid = $args['id'];
 
         $user = User::find($uid);
 
         if ($user == null) {
-            $pathset = new \ArrayObject();
+            $pathset = new ArrayObject();
             return $this->view()->assign('pathset', $pathset)->display('admin/relay/search.tpl');
         }
 
         $nodes = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                      ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
+            }
+        )->where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
             }
-        )->where("sort", "=", 10)->where("node_class", "<=", $user->class)->orderBy('name')->get();
+        )->where('node_class', '<=', $user->class)->orderBy('name')->get();
 
-        $pathset = new \ArrayObject();
+        $pathset = new ArrayObject();
 
         $relay_rules = Relay::where('user_id', $user->id)->orwhere('user_id', 0)->get();
-        $mu_nodes = Node::where('sort', 9)->where('node_class', '<=', $user->class)->where("type", "1")->where(
-            function ($query) use ($user) {
-                $query->where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+        $mu_nodes = Node::where('sort', 9)->where('node_class', '<=', $user->class)->where('type', '1')->where(
+            static function ($query) use ($user) {
+                $query->where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
         )->get();
 
@@ -278,11 +331,11 @@ class RelayController extends AdminController
                     if ($single_path->end_node->id == $path->begin_node->id) {
                         $path->begin_node = $single_path->begin_node;
                         if ($path->begin_node->isNodeAccessable() == false) {
-                            $path->path = '<font color="#FF0000">'.$single_path->begin_node->name.'</font>'." → ".$path->path;
-                            $path->status = "阻断";
+                            $path->path = '<font color="#FF0000">' . $single_path->begin_node->name . '</font>' . ' → ' . $path->path;
+                            $path->status = '阻断';
                         } else {
-                            $path->path = $single_path->begin_node->name." → ".$path->path;
-                            $path->status = "通畅";
+                            $path->path = $single_path->begin_node->name . ' → ' . $path->path;
+                            $path->status = '通畅';
                         }
 
                         $pathset->offsetUnset($index);
@@ -292,10 +345,10 @@ class RelayController extends AdminController
                     if ($path->end_node->id == $single_path->begin_node->id) {
                         $path->end_node = $single_path->end_node;
                         if ($single_path->end_node->isNodeAccessable() == false) {
-                            $path->path = $path->path." → ".'<font color="#FF0000">'.$single_path->end_node->name.'</font>';
-                            $path->status = "阻断";
+                            $path->path = $path->path . ' → ' . '<font color="#FF0000">' . $single_path->end_node->name . '</font>';
+                            $path->status = '阻断';
                         } else {
-                            $path->path = $path->path." → ".$single_path->end_node->name;
+                            $path->path = $path->path . ' → ' . $single_path->end_node->name;
                         }
 
                         $pathset->offsetUnset($index);
@@ -313,12 +366,12 @@ class RelayController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select relay.id as op,relay.id,relay.user_id,user.user_name,source_node.name as source_node_name,dist_node.name as dist_node_name,relay.port,relay.priority from relay,user,ss_node as source_node,ss_node as dist_node WHERE (relay.user_id = user.id or relay.user_id = 0) and source_node.id = relay.source_node_id and dist_node.id = relay.dist_node_id group by id');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand" href="/admin/relay/'.$data['id'].'/edit">编辑</a>
-                    <a class="btn btn-brand-accent" id="delete" value="'.$data['id'].'" href="javascript:void(0);" onClick="delete_modal_show(\''.$data['id'].'\')">删除</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand" href="/admin/relay/' . $data['id'] . '/edit">编辑</a>
+                    <a class="btn btn-brand-accent" id="delete" value="' . $data['id'] . '" href="javascript:void(0);" onClick="delete_modal_show(\'' . $data['id'] . '\')">删除</a>';
         });
 
-        $datatables->edit('user_name', function ($data) {
+        $datatables->edit('user_name', static function ($data) {
             return ($data['user_id'] == 0 ? '全体用户' : $data['user_name']);
         });
 

+ 106 - 110
app/Controllers/Admin/ShopController.php

@@ -6,7 +6,6 @@ use App\Models\Shop;
 use App\Models\Bought;
 use App\Controllers\AdminController;
 use App\Services\Config;
-
 use Ozdemir\Datatables\Datatables;
 use App\Utils\DatatablesHelper;
 
@@ -14,13 +13,13 @@ class ShopController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID", "name" => "商品名称",
-                        "price" => "价格", "content" => "商品内容",
-                        "auto_renew" => "自动续费", "auto_reset_bandwidth" => "续费时是否重置流量",
-                        "status" => "状态", "period_sales" => "周期销量");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID', 'name' => '商品名称',
+            'price' => '价格', 'content' => '商品内容',
+            'auto_renew' => '自动续费', 'auto_reset_bandwidth' => '续费时是否重置流量',
+            'status' => '状态', 'period_sales' => '周期销量');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'shop/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/shop/index.tpl');
@@ -34,62 +33,62 @@ class ShopController extends AdminController
     public function add($request, $response, $args)
     {
         $shop = new Shop();
-        $shop->name =  $request->getParam('name');
-        $shop->price =  $request->getParam('price');
-        $shop->auto_renew =  $request->getParam('auto_renew');
-        $shop->auto_reset_bandwidth =  $request->getParam('auto_reset_bandwidth');
-
-        $content=array();
-        if ($request->getParam('bandwidth')!=0) {
-            $content["bandwidth"]=$request->getParam('bandwidth');
+        $shop->name = $request->getParam('name');
+        $shop->price = $request->getParam('price');
+        $shop->auto_renew = $request->getParam('auto_renew');
+        $shop->auto_reset_bandwidth = $request->getParam('auto_reset_bandwidth');
+
+        $content = array();
+        if ($request->getParam('bandwidth') != 0) {
+            $content['bandwidth'] = $request->getParam('bandwidth');
         }
 
-        if ($request->getParam('expire')!=0) {
-            $content["expire"]=$request->getParam('expire');
+        if ($request->getParam('expire') != 0) {
+            $content['expire'] = $request->getParam('expire');
         }
 
-        if ($request->getParam('class')!=0) {
-            $content["class"]=$request->getParam('class');
+        if ($request->getParam('class') != 0) {
+            $content['class'] = $request->getParam('class');
         }
 
-        if ($request->getParam('class_expire')!=0) {
-            $content["class_expire"]=$request->getParam('class_expire');
+        if ($request->getParam('class_expire') != 0) {
+            $content['class_expire'] = $request->getParam('class_expire');
         }
 
-        if ($request->getParam('reset')!=0) {
-            $content["reset"]=$request->getParam('reset');
+        if ($request->getParam('reset') != 0) {
+            $content['reset'] = $request->getParam('reset');
         }
 
-        if ($request->getParam('reset_value')!=0) {
-            $content["reset_value"]=$request->getParam('reset_value');
+        if ($request->getParam('reset_value') != 0) {
+            $content['reset_value'] = $request->getParam('reset_value');
         }
 
-        if ($request->getParam('reset_exp')!=0) {
-            $content["reset_exp"]=$request->getParam('reset_exp');
+        if ($request->getParam('reset_exp') != 0) {
+            $content['reset_exp'] = $request->getParam('reset_exp');
         }
 
         //if ($request->getParam('speedlimit')!=0) {
-            $content["speedlimit"]=$request->getParam('speedlimit');
+        $content['speedlimit'] = $request->getParam('speedlimit');
         //}
 
         //if ($request->getParam('connector')!=0) {
-            $content["connector"]=$request->getParam('connector');
+        $content['connector'] = $request->getParam('connector');
         //}
 
-        if ($request->getParam('content_extra')!='') {
-            $content["content_extra"]=$request->getParam('content_extra');
+        if ($request->getParam('content_extra') != '') {
+            $content['content_extra'] = $request->getParam('content_extra');
         }
 
-        $shop->content=json_encode($content);
+        $shop->content = json_encode($content);
 
 
         if (!$shop->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "添加失败";
+            $rs['msg'] = '添加失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "添加成功";
+        $rs['msg'] = '添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -97,8 +96,6 @@ class ShopController extends AdminController
     {
         $id = $args['id'];
         $shop = Shop::find($id);
-        if ($shop == null) {
-        }
         return $this->view()->assign('shop', $shop)->display('admin/shop/edit.tpl');
     }
 
@@ -107,110 +104,109 @@ class ShopController extends AdminController
         $id = $args['id'];
         $shop = Shop::find($id);
 
-        $shop->name =  $request->getParam('name');
-        $shop->price =  $request->getParam('price');
-        $shop->auto_renew =  $request->getParam('auto_renew');
+        $shop->name = $request->getParam('name');
+        $shop->price = $request->getParam('price');
+        $shop->auto_renew = $request->getParam('auto_renew');
 
         if ($shop->auto_reset_bandwidth == 1 && $request->getParam('auto_reset_bandwidth') == 0) {
-            $boughts = Bought::where("shopid", $id)->get();
+            $boughts = Bought::where('shopid', $id)->get();
 
             foreach ($boughts as $bought) {
-                $bought->renew=0;
+                $bought->renew = 0;
                 $bought->save();
             }
         }
 
-        $shop->auto_reset_bandwidth =  $request->getParam('auto_reset_bandwidth');
-        $shop->status=1;
+        $shop->auto_reset_bandwidth = $request->getParam('auto_reset_bandwidth');
+        $shop->status = 1;
 
-        $content=array();
-        if ($request->getParam('bandwidth')!=0) {
-            $content["bandwidth"]=$request->getParam('bandwidth');
+        $content = array();
+        if ($request->getParam('bandwidth') != 0) {
+            $content['bandwidth'] = $request->getParam('bandwidth');
         }
 
-        if ($request->getParam('expire')!=0) {
-            $content["expire"]=$request->getParam('expire');
+        if ($request->getParam('expire') != 0) {
+            $content['expire'] = $request->getParam('expire');
         }
 
-        if ($request->getParam('class')!=0) {
-            $content["class"]=$request->getParam('class');
+        if ($request->getParam('class') != 0) {
+            $content['class'] = $request->getParam('class');
         }
 
-        if ($request->getParam('class_expire')!=0) {
-            $content["class_expire"]=$request->getParam('class_expire');
+        if ($request->getParam('class_expire') != 0) {
+            $content['class_expire'] = $request->getParam('class_expire');
         }
 
-        if ($request->getParam('reset')!=0) {
-            $content["reset"]=$request->getParam('reset');
+        if ($request->getParam('reset') != 0) {
+            $content['reset'] = $request->getParam('reset');
         }
 
-        if ($request->getParam('reset_value')!=0) {
-            $content["reset_value"]=$request->getParam('reset_value');
+        if ($request->getParam('reset_value') != 0) {
+            $content['reset_value'] = $request->getParam('reset_value');
         }
 
-        if ($request->getParam('reset_exp')!=0) {
-            $content["reset_exp"]=$request->getParam('reset_exp');
+        if ($request->getParam('reset_exp') != 0) {
+            $content['reset_exp'] = $request->getParam('reset_exp');
         }
-        
+
         //if ($request->getParam('speedlimit')!=0) {
-            $content["speedlimit"]=$request->getParam('speedlimit');
+        $content['speedlimit'] = $request->getParam('speedlimit');
         //}
 
         //if ($request->getParam('connector')!=0) {
-            $content["connector"]=$request->getParam('connector');
+        $content['connector'] = $request->getParam('connector');
         //}
 
-        if ($request->getParam('content_extra')!='') {
-            $content["content_extra"]=$request->getParam('content_extra');
+        if ($request->getParam('content_extra') != '') {
+            $content['content_extra'] = $request->getParam('content_extra');
         }
 
-        $shop->content=json_encode($content);
+        $shop->content = json_encode($content);
 
         if (!$shop->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "保存失败";
+            $rs['msg'] = '保存失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "保存成功";
+        $rs['msg'] = '保存成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
 
-
     public function deleteGet($request, $response, $args)
     {
         $id = $request->getParam('id');
         $shop = Shop::find($id);
-        $shop->status=0;
+        $shop->status = 0;
         if (!$shop->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "下架失败";
+            $rs['msg'] = '下架失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
-        $boughts = Bought::where("shopid", $id)->get();
+        $boughts = Bought::where('shopid', $id)->get();
 
         foreach ($boughts as $bought) {
-            $bought->renew=0;
+            $bought->renew = 0;
             $bought->save();
         }
 
         $rs['ret'] = 1;
-        $rs['msg'] = "下架成功";
+        $rs['msg'] = '下架成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
     public function bought($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID", 
-						"datetime" => "购买日期","content" => "内容",
-                        "price" => "价格", "user_id" => "用户ID",
-                        "user_name" => "用户名", "renew" => "自动续费时间", 
-                        "auto_reset_bandwidth" => "续费时是否重置流量");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID',
+            'datetime' => '购买日期', 'content' => '内容',
+            'price' => '价格', 'user_id' => '用户ID',
+            'user_name' => '用户名', 'renew' => '自动续费时间',
+            'auto_reset_bandwidth' => '续费时是否重置流量');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'bought/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/shop/bought.tpl');
@@ -220,14 +216,14 @@ class ShopController extends AdminController
     {
         $id = $request->getParam('id');
         $shop = Bought::find($id);
-        $shop->renew=0;
+        $shop->renew = 0;
         if (!$shop->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "退订失败";
+            $rs['msg'] = '退订失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "退订成功";
+        $rs['msg'] = '退订成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -236,43 +232,43 @@ class ShopController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select id as op,id,name,price,content,auto_renew,auto_reset_bandwidth,status,id as period_sales from shop');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand" href="/admin/shop/'.$data['id'].'/edit">编辑</a>
-                    <a class="btn btn-brand-accent" '.($data['status'] == 0 ? "disabled" : 'id="row_delete_'.$data['id'].'" href="javascript:void(0);" onClick="delete_modal_show(\''.$data['id'].'\')"').'>下架</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand" href="/admin/shop/' . $data['id'] . '/edit">编辑</a>
+                    <a class="btn btn-brand-accent" ' . ($data['status'] == 0 ? 'disabled' : 'id="row_delete_' . $data['id'] . '" href="javascript:void(0);" onClick="delete_modal_show(\'' . $data['id'] . '\')"') . '>下架</a>';
         });
 
-        $datatables->edit('content', function ($data) {
+        $datatables->edit('content', static function ($data) {
             $shop = Shop::find($data['id']);
             return $shop->content();
         });
 
-        $datatables->edit('auto_renew', function ($data) {
+        $datatables->edit('auto_renew', static function ($data) {
             if ($data['auto_renew'] == 0) {
-                return "不自动续费";
-            } else {
-                return $data['auto_renew']." 天后续费";
+                return '不自动续费';
             }
+
+            return $data['auto_renew'] . ' 天后续费';
         });
 
-        $datatables->edit('auto_reset_bandwidth', function ($data) {
+        $datatables->edit('auto_reset_bandwidth', static function ($data) {
             return $data['auto_reset_bandwidth'] == 0 ? '不自动重置' : '自动重置';
         });
-		
-        $datatables->edit('status', function ($data) {
+
+        $datatables->edit('status', static function ($data) {
             return $data['status'] == 1 ? '上架' : '下架';
         });
 
-        $datatables->edit('period_sales', function ($data) {
-			$shop = Shop::find($data['id']);
-			$period=Config::get('sales_period');
+        $datatables->edit('period_sales', static function ($data) {
+            $shop = Shop::find($data['id']);
+            $period = Config::get('sales_period');
 
-			if($period=='expire'){
-				$period=json_decode($shop->content,true)['class_expire'];
-			}
+            if ($period == 'expire') {
+                $period = json_decode($shop->content, true)['class_expire'];
+            }
 
-			$period=$period*24*60*60;
-			$sales = Bought::where('shopid',$shop->id)->where('datetime','>' ,time()-$period)->count();
-			return $sales;
+            $period = $period * 24 * 60 * 60;
+            $sales = Bought::where('shopid', $shop->id)->where('datetime', '>', time() - $period)->count();
+            return $sales;
         });
 
         $body = $response->getBody();
@@ -282,30 +278,30 @@ class ShopController extends AdminController
     public function ajax_bought($request, $response, $args)
     {
         $datatables = new Datatables(new DatatablesHelper());
-        $datatables->query('Select bought.id as op,bought.id as id,shop.id as content,bought.price,user.id as user_id,user.user_name,renew,shop.auto_reset_bandwidth,bought.datetime from bought,user,shop where bought.shopid = shop.id and bought.userid = user.id');
+        $datatables->query('Select bought.id as op,bought.id as id,bought.datetime,shop.id as content,bought.price,user.id as user_id,user.user_name,renew,shop.auto_reset_bandwidth from bought,user,shop where bought.shopid = shop.id and bought.userid = user.id');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand-accent" '.($data['renew'] == 0 ? "disabled" : ' id="row_delete_'.$data['id'].'" href="javascript:void(0);" onClick="delete_modal_show(\''.$data['id'].'\')"').'>中止</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand-accent" ' . ($data['renew'] == 0 ? 'disabled' : ' id="row_delete_' . $data['id'] . '" href="javascript:void(0);" onClick="delete_modal_show(\'' . $data['id'] . '\')"') . '>中止</a>';
         });
 
-        $datatables->edit('content', function ($data) {
+        $datatables->edit('content', static function ($data) {
             $shop = Shop::find($data['content']);
             return $shop->content();
         });
 
-        $datatables->edit('renew', function ($data) {
+        $datatables->edit('renew', static function ($data) {
             if ($data['renew'] == 0) {
-                return "不自动续费";
-            } else {
-                return date('Y-m-d H:i:s', $data['renew'])." 续费";
+                return '不自动续费';
             }
+
+            return date('Y-m-d H:i:s', $data['renew']) . ' 续费';
         });
 
-        $datatables->edit('auto_reset_bandwidth', function ($data) {
+        $datatables->edit('auto_reset_bandwidth', static function ($data) {
             return $data['auto_reset_bandwidth'] == 0 ? '不自动重置' : '自动重置';
         });
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 

+ 40 - 43
app/Controllers/Admin/TicketController.php

@@ -5,6 +5,7 @@ namespace App\Controllers\Admin;
 use App\Models\Ticket;
 use App\Models\User;
 
+use Exception;
 use voku\helper\AntiXSS;
 use App\Services\Auth;
 
@@ -20,17 +21,16 @@ class TicketController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID",
-                              "datetime" => "时间", "title" => "标题", "userid" => "用户ID",
-                              "user_name" => "用户名", "status" => "状态");
-        $table_config['default_show_column'] = array("op", "id",
-                                  "datetime", "title", "userid", "user_name", "status");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID',
+            'datetime' => '时间', 'title' => '标题', 'userid' => '用户ID',
+            'user_name' => '用户名', 'status' => '状态');
+        $table_config['default_show_column'] = array('op', 'id',
+            'datetime', 'title', 'userid', 'user_name', 'status');
         $table_config['ajax_url'] = 'ticket/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/ticket/index.tpl');
     }
 
 
-
     public function update($request, $response, $args)
     {
         $id = $args['id'];
@@ -38,54 +38,54 @@ class TicketController extends AdminController
         $status = $request->getParam('status');
 
 
-        if ($content==""||$status=="") {
+        if ($content == '' || $status == '') {
             $res['ret'] = 0;
-            $res['msg'] = "请填全";
+            $res['msg'] = '请填全';
             return $this->echoJson($response, $res);
         }
 
-        if (strpos($content, "admin")!=false||strpos($content, "user")!=false) {
+        if (strpos($content, 'admin') != false || strpos($content, 'user') != false) {
             $res['ret'] = 0;
-            $res['msg'] = "请求中有不正当的词语。";
+            $res['msg'] = '请求中有不正当的词语。';
             return $this->echoJson($response, $res);
         }
 
 
-        $ticket_main=Ticket::where("id", "=", $id)->where("rootid", "=", 0)->first();
+        $ticket_main = Ticket::where('id', '=', $id)->where('rootid', '=', 0)->first();
 
         //if($status==1&&$ticket_main->status!=$status)
         {
-            $adminUser = User::where("id", "=", $ticket_main->userid)->get();
-            foreach ($adminUser as $user) {
-                $subject = Config::get('appName')."-工单被回复";
-                $to = $user->email;
-                $text = "您好,有人回复了<a href=\"".Config::get('baseUrl')."/user/ticket/".$ticket_main->id."/view\">工单</a>,请您查看。" ;
-                try {
-                    Mail::send($to, $subject, 'news/warn.tpl', [
-                        "user" => $user,"text" => $text
-                    ], [
-                    ]);
-                } catch (\Exception $e) {
-                    echo $e->getMessage();
-                }
+            $adminUser = User::where('id', '=', $ticket_main->userid)->get();
+        foreach ($adminUser as $user) {
+            $subject = Config::get('appName') . '-工单被回复';
+            $to = $user->email;
+            $text = '您好,有人回复了<a href="' . Config::get('baseUrl') . '/user/ticket/' . $ticket_main->id . '/view">工单</a>,请您查看。';
+            try {
+                Mail::send($to, $subject, 'news/warn.tpl', [
+                    'user' => $user, 'text' => $text
+                ], [
+                ]);
+            } catch (Exception $e) {
+                echo $e->getMessage();
             }
         }
+        }
 
         $antiXss = new AntiXSS();
 
-        $ticket=new Ticket();
-        $ticket->title=$antiXss->xss_clean($ticket_main->title);
-        $ticket->content=$antiXss->xss_clean($content);
-        $ticket->rootid=$ticket_main->id;
-        $ticket->userid=Auth::getUser()->id;
-        $ticket->datetime=time();
-        $ticket_main->status=$status;
+        $ticket = new Ticket();
+        $ticket->title = $antiXss->xss_clean($ticket_main->title);
+        $ticket->content = $antiXss->xss_clean($content);
+        $ticket->rootid = $ticket_main->id;
+        $ticket->userid = Auth::getUser()->id;
+        $ticket->datetime = time();
+        $ticket_main->status = $status;
 
         $ticket_main->save();
         $ticket->save();
 
         $res['ret'] = 1;
-        $res['msg'] = "提交成功";
+        $res['msg'] = '提交成功';
         return $this->echoJson($response, $res);
     }
 
@@ -93,16 +93,13 @@ class TicketController extends AdminController
     {
         $id = $args['id'];
 
-        $pageNum = 1;
-        if (isset($request->getQueryParams()["page"])) {
-            $pageNum = $request->getQueryParams()["page"];
-        }
+        $pageNum = $request->getQueryParams()['page'] ?? 1;
 
 
-        $ticketset=Ticket::where("id", $id)->orWhere("rootid", "=", $id)->orderBy("datetime", "desc")->paginate(5, ['*'], 'page', $pageNum);
-        $ticketset->setPath('/admin/ticket/'.$id."/view");
+        $ticketset = Ticket::where('id', $id)->orWhere('rootid', '=', $id)->orderBy('datetime', 'desc')->paginate(5, ['*'], 'page', $pageNum);
+        $ticketset->setPath('/admin/ticket/' . $id . '/view');
 
-        return $this->view()->assign('ticketset', $ticketset)->assign("id", $id)->display('admin/ticket/view.tpl');
+        return $this->view()->assign('ticketset', $ticketset)->assign('id', $id)->display('admin/ticket/view.tpl');
     }
 
     public function ajax($request, $response, $args)
@@ -110,15 +107,15 @@ class TicketController extends AdminController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select ticket.id as op,ticket.id,ticket.datetime,ticket.title,ticket.userid,user.user_name,ticket.status from ticket,user where ticket.userid = user.id and ticket.rootid = 0');
 
-        $datatables->edit('op', function ($data) {
-            return '<a class="btn btn-brand" href="/admin/ticket/'.$data['id'].'/view">查看</a>';
+        $datatables->edit('op', static function ($data) {
+            return '<a class="btn btn-brand" href="/admin/ticket/' . $data['id'] . '/view">查看</a>';
         });
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
-        $datatables->edit('status', function ($data) {
+        $datatables->edit('status', static function ($data) {
             return $data['status'] == 1 ? '开启' : '关闭';
         });
 

+ 364 - 189
app/Controllers/Admin/UserController.php

@@ -4,130 +4,261 @@ namespace App\Controllers\Admin;
 
 use App\Models\User;
 use App\Models\Ip;
-use App\Models\RadiusBan;
+use App\Models\Bought;
 use App\Models\Relay;
 use App\Controllers\AdminController;
 use App\Services\Config;
 use App\Services\Auth;
+use App\Services\Mail;
 use App\Utils;
 use App\Utils\Hash;
 use App\Utils\Radius;
 use App\Utils\QQWry;
+use App\Utils\Check;
 use App\Utils\Tools;
+use App\Utils\GA;
+use Exception;
 
 class UserController extends AdminController
 {
     public function index($request, $response, $args)
     {
-        $table_config['total_column'] = array("op" => "操作", "id" => "ID", "user_name" => "用户名",
-                            "remark" => "备注", "email" => "邮箱", "money" => "金钱",
-                            "im_type" => "联络方式类型", "im_value" => "联络方式详情",
-                            "node_group" => "群组", "expire_in" => "账户过期时间",
-                            "class" => "等级", "class_expire" => "等级过期时间",
-                            "passwd" => "连接密码","port" => "连接端口", "method" => "加密方式",
-                            "protocol" => "连接协议", "obfs" => "连接混淆方式",
-                            "online_ip_count" => "在线IP数", "last_ss_time" => "上次使用时间",
-                            "used_traffic" => "已用流量/GB", "enable_traffic" => "总流量/GB",
-                            "last_checkin_time" => "上次签到时间", "today_traffic" => "今日流量/MB",
-                            "enable" => "是否启用", "reg_date" => "注册时间",
-                            "reg_ip" => "注册IP", "auto_reset_day" => "自动重置流量日",
-                            "auto_reset_bandwidth" => "自动重置流量/GB", "ref_by" => "邀请人ID", "ref_by_user_name" => "邀请人用户名");
-        $table_config['default_show_column'] = array("op", "id", "user_name", "remark", "email");
+        $table_config['total_column'] = array('op' => '操作', 'id' => 'ID', 'user_name' => '用户名',
+            'remark' => '备注', 'email' => '邮箱', 'money' => '金钱',
+            'im_type' => '联络方式类型', 'im_value' => '联络方式详情',
+            'node_group' => '群组', 'expire_in' => '账户过期时间',
+            'class' => '等级', 'class_expire' => '等级过期时间',
+            'passwd' => '连接密码', 'port' => '连接端口', 'method' => '加密方式',
+            'protocol' => '连接协议', 'obfs' => '连接混淆方式',
+            'online_ip_count' => '在线IP数', 'last_ss_time' => '上次使用时间',
+            'used_traffic' => '已用流量/GB', 'enable_traffic' => '总流量/GB',
+            'last_checkin_time' => '上次签到时间', 'today_traffic' => '今日流量/MB',
+            'enable' => '是否启用', 'reg_date' => '注册时间',
+            'reg_ip' => '注册IP', 'auto_reset_day' => '自动重置流量日',
+            'auto_reset_bandwidth' => '自动重置流量/GB', 'ref_by' => '邀请人ID', 'ref_by_user_name' => '邀请人用户名',
+            'top_up' => '累计充值');
+        $table_config['default_show_column'] = array('op', 'id', 'user_name', 'remark', 'email');
         $table_config['ajax_url'] = 'user/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/user/index.tpl');
     }
 
+    public function createNewUser($request, $response, $args)
+    {
+        # 需要一个 userEmail
+        $email = $request->getParam('userEmail');
+        $email = trim($email);
+        $email = strtolower($email);
+        // check email format
+        if (!Check::isEmailLegal($email)) {
+            $res['ret'] = 0;
+            $res['msg'] = '邮箱无效';
+            return $response->getBody()->write(json_encode($res));
+        }
+        // check email
+        $user = User::where('email', $email)->first();
+        if ($user != null) {
+            $res['ret'] = 0;
+            $res['msg'] = '邮箱已经被注册了';
+            return $response->getBody()->write(json_encode($res));
+        }
+        // do reg user
+        $user = new User();
+        $pass = Tools::genRandomChar();
+        $user->user_name = $email;
+        $user->email = $email;
+        $user->pass = Hash::passwordHash($pass);
+        $user->passwd = Tools::genRandomChar(6);
+        $user->port = Tools::getAvPort();
+        $user->t = 0;
+        $user->u = 0;
+        $user->d = 0;
+        $user->method = Config::get('reg_method');
+        $user->protocol = Config::get('reg_protocol');
+        $user->protocol_param = Config::get('reg_protocol_param');
+        $user->obfs = Config::get('reg_obfs');
+        $user->obfs_param = Config::get('reg_obfs_param');
+        $user->forbidden_ip = Config::get('reg_forbidden_ip');
+        $user->forbidden_port = Config::get('reg_forbidden_port');
+        $user->im_type = 2;
+        $user->im_value = $email;
+        $user->transfer_enable = Tools::toGB(Config::get('defaultTraffic'));
+        $user->invite_num = Config::get('inviteNum');
+        $user->auto_reset_day = Config::get('reg_auto_reset_day');
+        $user->auto_reset_bandwidth = Config::get('reg_auto_reset_bandwidth');
+        $user->money = 0;
+        $user->class_expire = date('Y-m-d H:i:s', time() + Config::get('user_class_expire_default') * 3600);
+        $user->class = Config::get('user_class_default');
+        $user->node_connector = Config::get('user_conn');
+        $user->node_speedlimit = Config::get('user_speedlimit');
+        $user->expire_in = date('Y-m-d H:i:s', time() + Config::get('user_expire_in_default') * 86400);
+        $user->reg_date = date('Y-m-d H:i:s');
+        $user->reg_ip = $_SERVER['REMOTE_ADDR'];
+        $user->plan = 'A';
+        $user->theme = Config::get('theme');
+
+        $groups = explode(',', Config::get('ramdom_group'));
+
+        $user->node_group = $groups[array_rand($groups)];
+
+        $ga = new GA();
+        $secret = $ga->createSecret();
+
+        $user->ga_token = $secret;
+        $user->ga_enable = 0;
+        if ($user->save()) {
+            $res['ret'] = 1;
+            $res['msg'] = '新用户注册成功 用户名: ' . $email . ' 随机初始密码: ' . $pass;
+            $res['email_error'] = 'success';
+            $subject = Config::get('appName') . '-新用户注册通知';
+            $to = $user->email;
+            $text = '您好,管理员已经为您生成账户,用户名: ' . $email . ',登录密码为:' . $pass . ',感谢您的支持。 ';
+            try {
+                Mail::send($to, $subject, 'newuser.tpl', [
+                    'user' => $user, 'text' => $text
+                ], [
+                ]);
+            } catch (Exception $e) {
+                $res['email_error'] = $e->getMessage();
+            }
+            return $response->getBody()->write(json_encode($res));
+        }
+        $res['ret'] = 0;
+        $res['msg'] = '未知错误';
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function buy($request, $response, $args)
+    {
+        #shop 信息可以通过 App\Controllers\UserController:shop 获得
+        # 需要shopId,disableothers,autorenew,userEmail
+
+        $shopId = $request->getParam('shopId');
+        $shop = Shop::where('id', $shopId)->where('status', 1)->first();
+        $disableothers = $request->getParam('disableothers');
+        $autorenew = $request->getParam('autorenew');
+        $email = $request->getParam('userEmail');
+        $user = User::where('email', '=', $email)->first();
+        if ($user == null) {
+            $result['ret'] = 0;
+            $result['msg'] = '未找到该用户';
+            return $response->getBody()->write(json_encode($result));
+        }
+        if ($shop == null) {
+            $result['ret'] = 0;
+            $result['msg'] = '请选择套餐';
+            return $response->getBody()->write(json_encode($result));
+        }
+        if ($disableothers == 1) {
+            $boughts = Bought::where('userid', $user->id)->get();
+            foreach ($boughts as $disable_bought) {
+                $disable_bought->renew = 0;
+                $disable_bought->save();
+            }
+        }
+        $bought = new Bought();
+        $bought->userid = $user->id;
+        $bought->shopid = $shop->id;
+        $bought->datetime = time();
+        if ($autorenew == 0 || $shop->auto_renew == 0) {
+            $bought->renew = 0;
+        } else {
+            $bought->renew = time() + $shop->auto_renew * 86400;
+        }
+
+        $price = $shop->price;
+        $bought->price = $price;
+        $bought->save();
+
+        $shop->buy($user);
+        $result['ret'] = 1;
+        $result['msg'] = '套餐添加成功';
+        return $response->getBody()->write(json_encode($result));
+    }
+
+
     public function search($request, $response, $args)
     {
         $pageNum = 1;
-        $text=$args["text"];
-        if (isset($request->getQueryParams()["page"])) {
-            $pageNum = $request->getQueryParams()["page"];
+        $text = $args['text'];
+        if (isset($request->getQueryParams()['page'])) {
+            $pageNum = $request->getQueryParams()['page'];
         }
 
-        $users = User::where("email", "LIKE", "%".$text."%")->orWhere("user_name", "LIKE", "%".$text."%")->orWhere("im_value", "LIKE", "%".$text."%")->orWhere("port", "LIKE", "%".$text."%")->orWhere("remark", "LIKE", "%".$text."%")->paginate(20, ['*'], 'page', $pageNum);
-        $users->setPath('/admin/user/search/'.$text);
-
+        $users = User::where('email', 'LIKE', '%' . $text . '%')->orWhere('user_name', 'LIKE', '%' . $text . '%')->orWhere('im_value', 'LIKE', '%' . $text . '%')->orWhere('port', 'LIKE', '%' . $text . '%')->orWhere('remark', 'LIKE', '%' . $text . '%')->paginate(20, ['*'], 'page', $pageNum);
+        $users->setPath('/admin/user/search/' . $text);
 
 
         //Ip::where("datetime","<",time()-90)->get()->delete();
-        $total = Ip::where("datetime", ">=", time()-90)->orderBy('userid', 'desc')->get();
+        $total = Ip::where('datetime', '>=', time() - 90)->orderBy('userid', 'desc')->get();
 
 
-        $userip=array();
-        $useripcount=array();
-        $regloc=array();
+        $userip = array();
+        $useripcount = array();
+        $regloc = array();
 
         $iplocation = new QQWry();
         foreach ($users as $user) {
-            $useripcount[$user->id]=0;
-            $userip[$user->id]=array();
+            $useripcount[$user->id] = 0;
+            $userip[$user->id] = array();
 
-            $location=$iplocation->getlocation($user->reg_ip);
-            $regloc[$user->id]=iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
+            $location = $iplocation->getlocation($user->reg_ip);
+            $regloc[$user->id] = iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
         }
 
 
-
         foreach ($total as $single) {
-            if (isset($useripcount[$single->userid])) {
-                if (!isset($userip[$single->userid][$single->ip])) {
-                    $useripcount[$single->userid]=$useripcount[$single->userid]+1;
-                    $location=$iplocation->getlocation($single->ip);
-                    $userip[$single->userid][$single->ip]=iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
-                }
+            if (isset($useripcount[$single->userid]) && !isset($userip[$single->userid][$single->ip])) {
+                ++$useripcount[$single->userid];
+                $location = $iplocation->getlocation($single->ip);
+                $userip[$single->userid][$single->ip] = iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
             }
         }
 
 
-        return $this->view()->assign('users', $users)->assign("regloc", $regloc)->assign("useripcount", $useripcount)->assign("userip", $userip)->display('admin/user/index.tpl');
+        return $this->view()->assign('users', $users)->assign('regloc', $regloc)->assign('useripcount', $useripcount)->assign('userip', $userip)->display('admin/user/index.tpl');
     }
 
     public function sort($request, $response, $args)
     {
         $pageNum = 1;
-        $text=$args["text"];
-        $asc=$args["asc"];
-        if (isset($request->getQueryParams()["page"])) {
-            $pageNum = $request->getQueryParams()["page"];
+        $text = $args['text'];
+        $asc = $args['asc'];
+        if (isset($request->getQueryParams()['page'])) {
+            $pageNum = $request->getQueryParams()['page'];
         }
 
 
-        $users->setPath('/admin/user/sort/'.$text."/".$asc);
-
+        $users->setPath('/admin/user/sort/' . $text . '/' . $asc);
 
 
         //Ip::where("datetime","<",time()-90)->get()->delete();
-        $total = Ip::where("datetime", ">=", time()-90)->orderBy('userid', 'desc')->get();
+        $total = Ip::where('datetime', '>=', time() - 90)->orderBy('userid', 'desc')->get();
 
 
-        $userip=array();
-        $useripcount=array();
-        $regloc=array();
+        $userip = array();
+        $useripcount = array();
+        $regloc = array();
 
         $iplocation = new QQWry();
         foreach ($users as $user) {
-            $useripcount[$user->id]=0;
-            $userip[$user->id]=array();
+            $useripcount[$user->id] = 0;
+            $userip[$user->id] = array();
 
-            $location=$iplocation->getlocation($user->reg_ip);
-            $regloc[$user->id]=iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
+            $location = $iplocation->getlocation($user->reg_ip);
+            $regloc[$user->id] = iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
         }
 
 
-
         foreach ($total as $single) {
-            if (isset($useripcount[$single->userid])) {
-                if (!isset($userip[$single->userid][$single->ip])) {
-                    $useripcount[$single->userid]=$useripcount[$single->userid]+1;
-                    $location=$iplocation->getlocation($single->ip);
-                    $userip[$single->userid][$single->ip]=iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
-                }
+            if (isset($useripcount[$single->userid]) && !isset($userip[$single->userid][$single->ip])) {
+                ++$useripcount[$single->userid];
+                $location = $iplocation->getlocation($single->ip);
+                $userip[$single->userid][$single->ip] = iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
             }
         }
 
 
-        return $this->view()->assign('users', $users)->assign("regloc", $regloc)->assign("useripcount", $useripcount)->assign("userip", $userip)->display('admin/user/index.tpl');
+        return $this->view()->assign('users', $users)->assign('regloc', $regloc)->assign('useripcount', $useripcount)->assign('userip', $userip)->display('admin/user/index.tpl');
     }
 
 
@@ -135,8 +266,6 @@ class UserController extends AdminController
     {
         $id = $args['id'];
         $user = User::find($id);
-        if ($user == null) {
-        }
         return $this->view()->assign('edit_user', $user)->display('admin/user/edit.tpl');
     }
 
@@ -145,13 +274,13 @@ class UserController extends AdminController
         $id = $args['id'];
         $user = User::find($id);
 
-        $email1=$user->email;
+        $email1 = $user->email;
 
-        $user->email =  $request->getParam('email');
+        $user->email = $request->getParam('email');
 
-        $email2=$request->getParam('email');
+        $email2 = $request->getParam('email');
 
-        $passwd=$request->getParam('passwd');
+        $passwd = $request->getParam('passwd');
 
         Radius::ChangeUserName($email1, $email2, $passwd);
 
@@ -161,10 +290,10 @@ class UserController extends AdminController
             $user->clean_link();
         }
 
-        $user->auto_reset_day =  $request->getParam('auto_reset_day');
+        $user->auto_reset_day = $request->getParam('auto_reset_day');
         $user->auto_reset_bandwidth = $request->getParam('auto_reset_bandwidth');
         $origin_port = $user->port;
-        $user->port =  $request->getParam('port');
+        $user->port = $request->getParam('port');
 
         $relay_rules = Relay::where('user_id', $user->id)->where('port', $origin_port)->get();
         foreach ($relay_rules as $rule) {
@@ -194,16 +323,16 @@ class UserController extends AdminController
         $user->class_expire = $request->getParam('class_expire');
         $user->expire_in = $request->getParam('expire_in');
 
-        $user->forbidden_ip = str_replace(PHP_EOL, ",", $request->getParam('forbidden_ip'));
-        $user->forbidden_port = str_replace(PHP_EOL, ",", $request->getParam('forbidden_port'));
+        $user->forbidden_ip = str_replace(PHP_EOL, ',', $request->getParam('forbidden_ip'));
+        $user->forbidden_port = str_replace(PHP_EOL, ',', $request->getParam('forbidden_port'));
 
         if (!$user->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "修改失败";
+            $rs['msg'] = '修改失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "修改成功";
+        $rs['msg'] = '修改成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -212,52 +341,52 @@ class UserController extends AdminController
         $id = $request->getParam('id');
         $user = User::find($id);
 
-        $email1=$user->email;
+        $email1 = $user->email;
 
         if (!$user->kill_user()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
-    
+
     public function changetouser($request, $response, $args)
     {
         $userid = $request->getParam('userid');
         $adminid = $request->getParam('adminid');
         $user = User::find($userid);
         $admin = User::find($adminid);
-        $expire_in = time()+60*60;
-      
+        $expire_in = time() + 60 * 60;
+
         if (!$admin->is_admin || !$user || !Auth::getUser()->isLogin) {
             $rs['ret'] = 0;
-            $rs['msg'] = "非法请求";
+            $rs['msg'] = '非法请求';
             return $response->getBody()->write(json_encode($rs));
         }
-        
+
         Utils\Cookie::set([
-            "uid" => $user->id,
-            "email" => $user->email,
-            "key" => Hash::cookieHash($user->pass),
-            "ip" => md5($_SERVER["REMOTE_ADDR"].Config::get('key').$user.$expire_in),
-            "expire_in" =>  $expire_in,
-            "old_uid" => Utils\Cookie::get('uid'),
-            "old_email" => Utils\Cookie::get('email'),
-            "old_key" => Utils\Cookie::get('key'),
-            "old_ip" => Utils\Cookie::get('ip'),
-            "old_expire_in" => Utils\Cookie::get('expire_in'),
-            "old_local" =>  $request->getParam('local')
-        ],  $expire_in);
+            'uid' => $user->id,
+            'email' => $user->email,
+            'key' => Hash::cookieHash($user->pass, $expire_in),
+            'ip' => md5($_SERVER['REMOTE_ADDR'] . Config::get('key') . $user->id . $expire_in),
+            'expire_in' => $expire_in,
+            'old_uid' => Utils\Cookie::get('uid'),
+            'old_email' => Utils\Cookie::get('email'),
+            'old_key' => Utils\Cookie::get('key'),
+            'old_ip' => Utils\Cookie::get('ip'),
+            'old_expire_in' => Utils\Cookie::get('expire_in'),
+            'old_local' => $request->getParam('local')
+        ], $expire_in);
         $rs['ret'] = 1;
-        $rs['msg'] = "切换成功";
+        $rs['msg'] = '切换成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
-	public function ajax($request, $response, $args)
-	{		
+    public function ajax($request, $response, $args)
+    {
         //得到排序的方式
         $order = $request->getParam('order')[0]['dir'];
         //得到排序字段的下标
@@ -267,108 +396,154 @@ class UserController extends AdminController
         $limit_start = $request->getParam('start');
         $limit_length = $request->getParam('length');
         $search = $request->getParam('search')['value'];
-        
-		$users=array();
-		$count_filtered=0;
+
+        if ($order_field == 'used_traffic') {
+            $order_field = 'u + d';
+        } elseif ($order_field == 'enable_traffic') {
+            $order_field = 'transfer_enable';
+        } elseif ($order_field == 'today_traffic') {
+            $order_field = 'u +d - last_day_t';
+        }
+
+        $users = array();
+        $count_filtered = 0;
 
         if ($search) {
-            $users = User::orderBy($order_field,$order)
-                    ->skip($limit_start)->limit($limit_length)
-                    ->where(
-                        function ($query) use ($search) {
-                            $query->where('id','LIKE',"%$search%")
-								->orwhere('user_name','LIKE',"%$search%")
-								->orwhere('email','LIKE',"%$search%")
-								->orwhere('im_value','LIKE',"%$search%")
-								->orwhere('port','LIKE',"%$search%");
-							}
-						)
-                    ->get();
+            $users = User::where(
+                static function ($query) use ($search) {
+                    $query->where('id', 'LIKE', "%$search%")
+                        ->orwhere('user_name', 'LIKE', "%$search%")
+                        ->orwhere('email', 'LIKE', "%$search%")
+                        ->orwhere('passwd', 'LIKE', "%$search%")
+                        ->orwhere('port', 'LIKE', "%$search%")
+                        ->orwhere('reg_date', 'LIKE', "%$search%")
+                        ->orwhere('invite_num', 'LIKE', "%$search%")
+                        ->orwhere('money', 'LIKE', "%$search%")
+                        ->orwhere('ref_by', 'LIKE', "%$search%")
+                        ->orwhere('method', 'LIKE', "%$search%")
+                        ->orwhere('reg_ip', 'LIKE', "%$search%")
+                        ->orwhere('node_speedlimit', 'LIKE', "%$search%")
+                        ->orwhere('im_value', 'LIKE', "%$search%")
+                        ->orwhere('class', 'LIKE', "%$search%")
+                        ->orwhere('class_expire', 'LIKE', "%$search%")
+                        ->orwhere('expire_in', 'LIKE', "%$search%")
+                        ->orwhere('remark', 'LIKE', "%$search%")
+                        ->orwhere('node_group', 'LIKE', "%$search%")
+                        ->orwhere('auto_reset_day', 'LIKE', "%$search%")
+                        ->orwhere('auto_reset_bandwidth', 'LIKE', "%$search%")
+                        ->orwhere('protocol', 'LIKE', "%$search%")
+                        ->orwhere('protocol_param', 'LIKE', "%$search%")
+                        ->orwhere('obfs', 'LIKE', "%$search%")
+                        ->orwhere('obfs_param', 'LIKE', "%$search%");
+                }
+            )
+                ->orderByRaw($order_field . ' ' . $order)
+                ->skip($limit_start)->limit($limit_length)
+                ->get();
             $count_filtered = User::where(
-                        function ($query)use($search) {
-                            $query->where('id','LIKE',"%$search%")
-								->orwhere('user_name','LIKE',"%$search%")
-								->orwhere('email','LIKE',"%$search%")
-								->orwhere('im_value','LIKE',"%$search%")
-								->orwhere('port','LIKE',"%$search%");
-							}
-						)->count();
-		}
-		else{
-            $users = User::orderBy($order_field,$order)
+                static function ($query) use ($search) {
+                    $query->where('id', 'LIKE', "%$search%")
+                        ->orwhere('user_name', 'LIKE', "%$search%")
+                        ->orwhere('email', 'LIKE', "%$search%")
+                        ->orwhere('passwd', 'LIKE', "%$search%")
+                        ->orwhere('port', 'LIKE', "%$search%")
+                        ->orwhere('reg_date', 'LIKE', "%$search%")
+                        ->orwhere('invite_num', 'LIKE', "%$search%")
+                        ->orwhere('money', 'LIKE', "%$search%")
+                        ->orwhere('ref_by', 'LIKE', "%$search%")
+                        ->orwhere('method', 'LIKE', "%$search%")
+                        ->orwhere('reg_ip', 'LIKE', "%$search%")
+                        ->orwhere('node_speedlimit', 'LIKE', "%$search%")
+                        ->orwhere('im_value', 'LIKE', "%$search%")
+                        ->orwhere('class', 'LIKE', "%$search%")
+                        ->orwhere('class_expire', 'LIKE', "%$search%")
+                        ->orwhere('expire_in', 'LIKE', "%$search%")
+                        ->orwhere('remark', 'LIKE', "%$search%")
+                        ->orwhere('node_group', 'LIKE', "%$search%")
+                        ->orwhere('auto_reset_day', 'LIKE', "%$search%")
+                        ->orwhere('auto_reset_bandwidth', 'LIKE', "%$search%")
+                        ->orwhere('protocol', 'LIKE', "%$search%")
+                        ->orwhere('protocol_param', 'LIKE', "%$search%")
+                        ->orwhere('obfs', 'LIKE', "%$search%")
+                        ->orwhere('obfs_param', 'LIKE', "%$search%");
+                }
+            )->count();
+        } else {
+            $users = User::orderByRaw($order_field . ' ' . $order)
                 ->skip($limit_start)->limit($limit_length)
                 ->get();
             $count_filtered = User::count();
         }
-		        
-		$data=array();
-		foreach ($users as $user) {
-			$tempdata=array();
-			//model里是casts所以没法直接 $tempdata=(array)$user
-			$tempdata['op']='<a class="btn btn-brand" href="/admin/user/'.$user->id.'/edit">编辑</a>
-                    <a class="btn btn-brand-accent" id="delete" href="javascript:void(0);" onClick="delete_modal_show(\''.$user->id.'\')">删除</a>
-                    <a class="btn btn-brand" id="changetouser" href="javascript:void(0);" onClick="changetouser_modal_show(\''.$user->id.'\')">切换为该用户</a>';;
-			$tempdata['id']=$user->id;
-			$tempdata['user_name']=$user->user_name;
-			$tempdata['remark']=$user->remark;
-			$tempdata['email']=$user->email;
-			$tempdata['money']=$user->money;
-			$tempdata['im_value']=$user->im_value;			
-			switch($user->im_type) {
-				case 1:
-				$tempdata['im_type'] = '微信';
-				break;
-            case 2:
-				$tempdata['im_type'] = 'QQ';
-				break;
-            case 3:
-				$tempdata['im_type'] = 'Google+';
-				break;
-            default:
-				$tempdata['im_type'] = 'Telegram';
-				$tempdata['im_value'] = '<a href="https://telegram.me/'.$user->im_value.'">'.$user->im_value.'</a>';
-			}
-			$tempdata['node_group']=$user->node_group;
-			$tempdata['expire_in']=$user->expire_in;
-			$tempdata['class']=$user->class;
-			$tempdata['class_expire']=$user->class_expire;
-			$tempdata['passwd']=$user->passwd;
-			$tempdata['port']=$user->port;
-			$tempdata['method']=$user->method;
-			$tempdata['protocol']=$user->protocol;
-			$tempdata['obfs']=$user->obfs;
-			$tempdata['online_ip_count']=$user->online_ip_count();
-			$tempdata['last_ss_time']=$user->lastSsTime();
-			$tempdata['used_traffic']=Tools::flowToGB($user->u + $user->d);
-			$tempdata['enable_traffic']=Tools::flowToGB($user->transfer_enable);
-			$tempdata['last_checkin_time']=$user->lastCheckInTime();
-			$tempdata['today_traffic']=Tools::flowToMB($user->u + $user->d-$user->last_day_t);
-			$tempdata['enable']=$user->enable == 1 ? "可用" : "禁用";
-			$tempdata['reg_date']=$user->reg_date;
-			$tempdata['reg_ip']=$user->reg_ip;
-			$tempdata['auto_reset_day']=$user->auto_reset_day;
-			$tempdata['auto_reset_bandwidth']=$user->auto_reset_bandwidth;			
-            $tempdata['ref_by']= $user->ref_by;
-			if ($user->ref_by == 0) {
-				$tempdata['ref_by_user_name'] = "系统邀请";
-			}
-			else {
-				$ref_user = User::find($user->ref_by);
-				if ($ref_user == null) {
-					$tempdata['ref_by_user_name'] = "邀请人已经被删除";
-				}
-				else {
-					$tempdata['ref_by_user_name'] = $ref_user->user_name;
-				}
-			}
-			array_push($data,$tempdata);
-		}         
+
+        $data = array();
+        foreach ($users as $user) {
+            $tempdata = array();
+            //model里是casts所以没法直接 $tempdata=(array)$user
+            $tempdata['op'] = '<a class="btn btn-brand" href="/admin/user/' . $user->id . '/edit">编辑</a>
+                    <a class="btn btn-brand-accent" id="delete" href="javascript:void(0);" onClick="delete_modal_show(\'' . $user->id . '\')">删除</a>
+                    <a class="btn btn-brand" id="changetouser" href="javascript:void(0);" onClick="changetouser_modal_show(\'' . $user->id . '\')">切换为该用户</a>';
+            $tempdata['id'] = $user->id;
+            $tempdata['user_name'] = $user->user_name;
+            $tempdata['remark'] = $user->remark;
+            $tempdata['email'] = $user->email;
+            $tempdata['money'] = $user->money;
+            $tempdata['im_value'] = $user->im_value;
+            switch ($user->im_type) {
+                case 1:
+                    $tempdata['im_type'] = '微信';
+                    break;
+                case 2:
+                    $tempdata['im_type'] = 'QQ';
+                    break;
+                case 3:
+                    $tempdata['im_type'] = 'Google+';
+                    break;
+                default:
+                    $tempdata['im_type'] = 'Telegram';
+                    $tempdata['im_value'] = '<a href="https://telegram.me/' . $user->im_value . '">' . $user->im_value . '</a>';
+            }
+            $tempdata['node_group'] = $user->node_group;
+            $tempdata['expire_in'] = $user->expire_in;
+            $tempdata['class'] = $user->class;
+            $tempdata['class_expire'] = $user->class_expire;
+            $tempdata['passwd'] = $user->passwd;
+            $tempdata['port'] = $user->port;
+            $tempdata['method'] = $user->method;
+            $tempdata['protocol'] = $user->protocol;
+            $tempdata['obfs'] = $user->obfs;
+            $tempdata['online_ip_count'] = $user->online_ip_count();
+            $tempdata['last_ss_time'] = $user->lastSsTime();
+            $tempdata['used_traffic'] = Tools::flowToGB($user->u + $user->d);
+            $tempdata['enable_traffic'] = Tools::flowToGB($user->transfer_enable);
+            $tempdata['last_checkin_time'] = $user->lastCheckInTime();
+            $tempdata['today_traffic'] = Tools::flowToMB($user->u + $user->d - $user->last_day_t);
+            $tempdata['enable'] = $user->enable == 1 ? '可用' : '禁用';
+            $tempdata['reg_date'] = $user->reg_date;
+            $tempdata['reg_ip'] = $user->reg_ip;
+            $tempdata['auto_reset_day'] = $user->auto_reset_day;
+            $tempdata['auto_reset_bandwidth'] = $user->auto_reset_bandwidth;
+            $tempdata['ref_by'] = $user->ref_by;
+            if ($user->ref_by == 0) {
+                $tempdata['ref_by_user_name'] = '系统邀请';
+            } else {
+                $ref_user = User::find($user->ref_by);
+                if ($ref_user == null) {
+                    $tempdata['ref_by_user_name'] = '邀请人已经被删除';
+                } else {
+                    $tempdata['ref_by_user_name'] = $ref_user->user_name;
+                }
+            }
+
+            $tempdata['top_up'] = $user->get_top_up();
+
+            $data[] = $tempdata;
+        }
         $info = [
-           'draw'=> $request->getParam('draw'), // ajax请求次数,作为标识符
-           'recordsTotal'=>User::count(),
-           'recordsFiltered'=>$count_filtered,
-           'data'=>$data,
+            'draw' => $request->getParam('draw'), // ajax请求次数,作为标识符
+            'recordsTotal' => User::count(),
+            'recordsFiltered' => $count_filtered,
+            'data' => $data,
         ];
-        return json_encode($info,true);
-	}
+        return json_encode($info, true);
+    }
 }

+ 73 - 47
app/Controllers/AdminController.php

@@ -2,10 +2,7 @@
 
 namespace App\Controllers;
 
-use App\Models\InviteCode;
 use App\Models\Node;
-use App\Models\TrafficLog;
-use App\Models\Payback;
 use App\Models\Coupon;
 use App\Models\User;
 use App\Services\Gateway\ChenPay;
@@ -51,62 +48,62 @@ class AdminController extends UserController
 
     public function invite($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID",
-                        "total" => "原始金额", "event_user_id" => "发起用户ID",
-                        "event_user_name" => "发起用户名", "ref_user_id" => "获利用户ID",
-                        "ref_user_name" => "获利用户名", "ref_get" => "获利金额",
-                        "datetime" => "时间");
+        $table_config['total_column'] = array('id' => 'ID',
+            'total' => '原始金额', 'event_user_id' => '发起用户ID',
+            'event_user_name' => '发起用户名', 'ref_user_id' => '获利用户ID',
+            'ref_user_name' => '获利用户名', 'ref_get' => '获利金额',
+            'datetime' => '时间');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'payback/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/invite.tpl');
     }
-	
+
     public function addInvite($request, $response, $args)
     {
         $num = $request->getParam('num');
         $prefix = $request->getParam('prefix');
 
-		if(Tools::isInt($num)==false){
-		    $res['ret'] = 0;
-            $res['msg'] = "非法请求";
+        if (Tools::isInt($num) == false) {
+            $res['ret'] = 0;
+            $res['msg'] = '非法请求';
             return $response->getBody()->write(json_encode($res));
-		}
+        }
 
-        if ($request->getParam('uid')!="0") {
-            if (strpos($request->getParam('uid'), "@")!=false) {
-                $user=User::where("email", "=", $request->getParam('uid'))->first();
+        if ($request->getParam('uid') != '0') {
+            if (strpos($request->getParam('uid'), '@') != false) {
+                $user = User::where('email', '=', $request->getParam('uid'))->first();
             } else {
-                $user=User::Where("id", "=", $request->getParam('uid'))->first();
+                $user = User::Where('id', '=', $request->getParam('uid'))->first();
             }
 
-            if ($user==null) {
+            if ($user == null) {
                 $res['ret'] = 0;
-                $res['msg'] = "邀请次数添加失败,检查用户id或者用户邮箱是否输入正确";
+                $res['msg'] = '邀请次数添加失败,检查用户id或者用户邮箱是否输入正确';
                 return $response->getBody()->write(json_encode($res));
             }
             $uid = $user->id;
         } else {
-            $uid=0;
+            $uid = 0;
         }
-		$user->invite_num += $num;
-		$user->save();
+        $user->invite_num += $num;
+        $user->save();
         $res['ret'] = 1;
-        $res['msg'] = "邀请次数添加成功";
+        $res['msg'] = '邀请次数添加成功';
         return $response->getBody()->write(json_encode($res));
     }
 
 
     public function coupon($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "code" => "优惠码",
-                          "expire" => "过期时间", "shop" => "限定商品ID",
-                          "credit" => "额度", "onetime" => "次数");
+        $table_config['total_column'] = array('id' => 'ID', 'code' => '优惠码',
+            'expire' => '过期时间', 'shop' => '限定商品ID',
+            'credit' => '额度', 'onetime' => '次数');
         $table_config['default_show_column'] = array();
         foreach ($table_config['total_column'] as $column => $value) {
-            array_push($table_config['default_show_column'], $column);
+            $table_config['default_show_column'][] = $column;
         }
         $table_config['ajax_url'] = 'coupon/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/coupon.tpl');
@@ -115,31 +112,60 @@ class AdminController extends UserController
     public function addCoupon($request, $response, $args)
     {
         $code = new Coupon();
-        $code->onetime=$request->getParam('onetime');
+        $code->onetime = $request->getParam('onetime');
+        $generate_type = $request->getParam('generate_type');
+        $final_code = $request->getParam('prefix');
+
+        if (empty($final_code) && ($generate_type == 1 || $generate_type == 3)) {
+            $res['ret'] = 0;
+            $res['msg'] = '优惠码不能为空';
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        if ($generate_type == 1) {
+            if (Coupon::where('code', $final_code)->count() != 0) {
+                $res['ret'] = 0;
+                $res['msg'] = '优惠码已存在';
+                return $response->getBody()->write(json_encode($res));
+            }
+        } else {
+            while (true) {
+                if ($generate_type == 2) {
+                    $temp_code = Tools::genRandomChar(8);
+                } elseif ($generate_type == 3) {
+                    $temp_code = $final_code . Tools::genRandomChar(8);
+                }
+
+                if (Coupon::where('code', $temp_code)->count() == 0) {
+                    $final_code = $temp_code;
+                    break;
+                }
+            }
+        }
 
-        $code->code = $request->getParam('prefix');
-        $code->expire=time()+$request->getParam('expire')*3600;
-        $code->shop=$request->getParam('shop');
-        $code->credit=$request->getParam('credit');
+        $code->code = $final_code;
+        $code->expire = time() + $request->getParam('expire') * 3600;
+        $code->shop = $request->getParam('shop');
+        $code->credit = $request->getParam('credit');
 
         $code->save();
 
         $res['ret'] = 1;
-        $res['msg'] = "优惠码添加成功";
+        $res['msg'] = '优惠码添加成功';
         return $response->getBody()->write(json_encode($res));
     }
 
     public function trafficLog($request, $response, $args)
     {
-        $table_config['total_column'] = array("id" => "ID", "user_id" => "用户ID",
-                          "user_name" => "用户名", "node_name" => "使用节点",
-                          "rate" => "倍率", "origin_traffic" => "实际使用流量",
-                          "traffic" => "结算流量",
-                          "log_time" => "记录时间");
-        $table_config['default_show_column'] = array("id", "user_id",
-                                  "user_name", "node_name",
-                                  "rate", "origin_traffic",
-                                  "traffic", "log_time");
+        $table_config['total_column'] = array('id' => 'ID', 'user_id' => '用户ID',
+            'user_name' => '用户名', 'node_name' => '使用节点',
+            'rate' => '倍率', 'origin_traffic' => '实际使用流量',
+            'traffic' => '结算流量',
+            'log_time' => '记录时间');
+        $table_config['default_show_column'] = array('id', 'user_id',
+            'user_name', 'node_name',
+            'rate', 'origin_traffic',
+            'traffic', 'log_time');
         $table_config['ajax_url'] = 'trafficlog/ajax';
         return $this->view()->assign('table_config', $table_config)->display('admin/trafficlog.tpl');
     }
@@ -149,11 +175,11 @@ class AdminController extends UserController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select log.id,log.user_id,user.user_name,node.name as node_name,log.rate,(log.u + log.d) as origin_traffic,log.traffic,log.log_time from user_traffic_log as log,user,ss_node as node WHERE log.user_id = user.id AND log.node_id = node.id');
 
-        $datatables->edit('log_time', function ($data) {
+        $datatables->edit('log_time', static function ($data) {
             return date('Y-m-d H:i:s', $data['log_time']);
         });
 
-        $datatables->edit('origin_traffic', function ($data) {
+        $datatables->edit('origin_traffic', static function ($data) {
             return Tools::flowAutoShow($data['origin_traffic']);
         });
 
@@ -166,7 +192,7 @@ class AdminController extends UserController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select payback.id,payback.total,payback.userid as event_user_id,event_user.user_name as event_user_name,payback.ref_by as ref_user_id,ref_user.user_name as ref_user_name,payback.ref_get,payback.datetime from payback,user as event_user,user as ref_user where event_user.id = payback.userid and ref_user.id = payback.ref_by');
 
-        $datatables->edit('datetime', function ($data) {
+        $datatables->edit('datetime', static function ($data) {
             return date('Y-m-d H:i:s', $data['datetime']);
         });
 
@@ -179,7 +205,7 @@ class AdminController extends UserController
         $datatables = new Datatables(new DatatablesHelper());
         $datatables->query('Select id,code,expire,shop,credit,onetime from coupon');
 
-        $datatables->edit('expire', function ($data) {
+        $datatables->edit('expire', static function ($data) {
             return date('Y-m-d H:i:s', $data['expire']);
         });
 

+ 57 - 59
app/Controllers/ApiController.php

@@ -2,7 +2,6 @@
 
 namespace App\Controllers;
 
-use App\Models\InviteCode;
 use App\Models\Node;
 use App\Models\User;
 use App\Services\Factory;
@@ -14,7 +13,6 @@ use App\Utils\Helper;
 /**
  *  ApiController
  */
-
 class ApiController extends BaseController
 {
     public function index()
@@ -26,13 +24,13 @@ class ApiController extends BaseController
         $accessToken = $id = $args['token'];
         $storage = Factory::createTokenStorage();
         $token = $storage->get($accessToken);
-        if ($token==null) {
+        if ($token == null) {
             $res['ret'] = 0;
-            $res['msg'] = "token is null";
+            $res['msg'] = 'token is null';
             return $this->echoJson($response, $res);
         }
         $res['ret'] = 1;
-        $res['msg'] = "ok";
+        $res['msg'] = 'ok';
         $res['data'] = $token;
         return $this->echoJson($response, $res);
     }
@@ -40,8 +38,8 @@ class ApiController extends BaseController
     public function newToken($request, $response, $args)
     {
         // $data = $request->post('sdf');
-        $email =  $request->getParam('email');
-        
+        $email = $request->getParam('email');
+
         $email = strtolower($email);
         $passwd = $request->getParam('passwd');
 
@@ -50,27 +48,27 @@ class ApiController extends BaseController
 
         if ($user == null) {
             $res['ret'] = 0;
-            $res['msg'] = "401 邮箱或者密码错误";
+            $res['msg'] = '401 邮箱或者密码错误';
             return $this->echoJson($response, $res);
         }
 
         if (!Hash::checkPassword($user->pass, $passwd)) {
             $res['ret'] = 0;
-            $res['msg'] = "402 邮箱或者密码错误";
+            $res['msg'] = '402 邮箱或者密码错误';
             return $this->echoJson($response, $res);
         }
         $tokenStr = Tools::genToken();
         $storage = Factory::createTokenStorage();
-        $expireTime = time() + 3600*24*7;
+        $expireTime = time() + 3600 * 24 * 7;
         if ($storage->store($tokenStr, $user, $expireTime)) {
             $res['ret'] = 1;
-            $res['msg'] = "ok";
+            $res['msg'] = 'ok';
             $res['data']['token'] = $tokenStr;
             $res['data']['user_id'] = $user->id;
             return $this->echoJson($response, $res);
         }
         $res['ret'] = 0;
-        $res['msg'] = "system error";
+        $res['msg'] = 'system error';
         return $this->echoJson($response, $res);
     }
 
@@ -80,64 +78,64 @@ class ApiController extends BaseController
         $storage = Factory::createTokenStorage();
         $token = $storage->get($accessToken);
         $user = User::find($token->userId);
-        $nodes = Node::where('sort', 0)->where("type", "1")->where(
-            function ($query) use ($user) {
-                $query->where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+        $nodes = Node::where('sort', 0)->where('type', '1')->where(
+            static function ($query) use ($user) {
+                $query->where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->get();
-        
-        $mu_nodes = Node::where('sort', 9)->where('node_class', '<=', $user->class)->where("type", "1")->where(
-            function ($query) use ($user) {
-                $query->where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+        )->orderBy('name')->get();
+
+        $mu_nodes = Node::where('sort', 9)->where('node_class', '<=', $user->class)->where('type', '1')->where(
+            static function ($query) use ($user) {
+                $query->where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->get();
-        
-        $temparray=array();
+        )->orderBy('name')->get();
+
+        $temparray = array();
         foreach ($nodes as $node) {
             if ($node->mu_only == 0) {
-                array_push($temparray, array("remarks"=>$node->name,
-                                            "server"=>$node->server,
-                                            "server_port"=>$user->port,
-                                            "method"=>($node->custom_method==1?$user->method:$node->method),
-                                            "obfs"=>str_replace("_compatible", "", (($node->custom_rss==1&&!($user->obfs=='plain'&&$user->protocol=='origin'))?$user->obfs:"plain")),
-                                            "obfsparam"=>(($node->custom_rss==1&&!($user->obfs=='plain'&&$user->protocol=='origin'))?$user->obfs_param:""),
-                                            "remarks_base64"=>base64_encode($node->name),
-                                            "password"=>$user->passwd,
-                                            "tcp_over_udp"=>false,
-                                            "udp_over_tcp"=>false,
-                                            "group"=>Config::get('appName'),
-                                            "protocol"=>str_replace("_compatible", "", (($node->custom_rss==1&&!($user->obfs=='plain'&&$user->protocol=='origin'))?$user->protocol:"origin")),
-                                            "obfs_udp"=>false,
-                                            "enable"=>true));
+                $temparray[] = array('remarks' => $node->name,
+                    'server' => $node->server,
+                    'server_port' => $user->port,
+                    'method' => $node->custom_method == 1 ? $user->method : $node->method,
+                    'obfs' => str_replace('_compatible', '', (($node->custom_rss == 1 && !($user->obfs == 'plain' && $user->protocol == 'origin')) ? $user->obfs : 'plain')),
+                    'obfsparam' => ($node->custom_rss == 1 && !($user->obfs == 'plain' && $user->protocol == 'origin')) ? $user->obfs_param : '',
+                    'remarks_base64' => base64_encode($node->name),
+                    'password' => $user->passwd,
+                    'tcp_over_udp' => false,
+                    'udp_over_tcp' => false,
+                    'group' => Config::get('appName'),
+                    'protocol' => str_replace('_compatible', '', (($node->custom_rss == 1 && !($user->obfs == 'plain' && $user->protocol == 'origin')) ? $user->protocol : 'origin')),
+                    'obfs_udp' => false,
+                    'enable' => true);
             }
-            
+
             if ($node->custom_rss == 1) {
                 foreach ($mu_nodes as $mu_node) {
                     $mu_user = User::where('port', '=', $mu_node->server)->first();
                     $mu_user->obfs_param = $user->getMuMd5();
-                    
-                    array_push($temparray, array("remarks"=>$node->name."- ".$mu_node->server." 单端口",
-                                        "server"=>$node->server,
-                                        "server_port"=>$mu_user->port,
-                                        "method"=>$mu_user->method,
-                                        "group"=>Config::get('appName'),
-                                        "obfs"=>str_replace("_compatible", "", (($node->custom_rss==1&&!($mu_user->obfs=='plain'&&$mu_user->protocol=='origin'))?$mu_user->obfs:"plain")),
-                                        "obfsparam"=>(($node->custom_rss==1&&!($mu_user->obfs=='plain'&&$mu_user->protocol=='origin'))?$mu_user->obfs_param:""),
-                                        "remarks_base64"=>base64_encode($node->name."- ".$mu_node->server." 单端口"),
-                                        "password"=>$mu_user->passwd,
-                                        "tcp_over_udp"=>false,
-                                        "udp_over_tcp"=>false,
-                                        "protocol"=>str_replace("_compatible", "", (($node->custom_rss==1&&!($mu_user->obfs=='plain'&&$mu_user->protocol=='origin'))?$mu_user->protocol:"origin")),
-                                        "obfs_udp"=>false,
-                                        "enable"=>true));
+
+                    $temparray[] = array('remarks' => $node->name . '- ' . $mu_node->server . ' 单端口',
+                        'server' => $node->server,
+                        'server_port' => $mu_user->port,
+                        'method' => $mu_user->method,
+                        'group' => Config::get('appName'),
+                        'obfs' => str_replace('_compatible', '', (($node->custom_rss == 1 && !($mu_user->obfs == 'plain' && $mu_user->protocol == 'origin')) ? $mu_user->obfs : 'plain')),
+                        'obfsparam' => ($node->custom_rss == 1 && !($mu_user->obfs == 'plain' && $mu_user->protocol == 'origin')) ? $mu_user->obfs_param : '',
+                        'remarks_base64' => base64_encode($node->name . '- ' . $mu_node->server . ' 单端口'),
+                        'password' => $mu_user->passwd,
+                        'tcp_over_udp' => false,
+                        'udp_over_tcp' => false,
+                        'protocol' => str_replace('_compatible', '', (($node->custom_rss == 1 && !($mu_user->obfs == 'plain' && $mu_user->protocol == 'origin')) ? $mu_user->protocol : 'origin')),
+                        'obfs_udp' => false,
+                        'enable' => true);
                 }
             }
         }
-        
+
         $res['ret'] = 1;
-        $res['msg'] = "ok";
+        $res['msg'] = 'ok';
         $res['data'] = $temparray;
         return $this->echoJson($response, $res);
     }
@@ -150,14 +148,14 @@ class ApiController extends BaseController
         $token = $storage->get($accessToken);
         if ($id != $token->userId) {
             $res['ret'] = 0;
-            $res['msg'] = "access denied";
+            $res['msg'] = 'access denied';
             return $this->echoJson($response, $res);
         }
         $user = User::find($token->userId);
         $user->pass = null;
         $data = $user;
         $res['ret'] = 1;
-        $res['msg'] = "ok";
+        $res['msg'] = 'ok';
         $res['data'] = $data;
         return $this->echoJson($response, $res);
     }

+ 145 - 122
app/Controllers/AuthController.php

@@ -7,10 +7,8 @@ use App\Services\Config;
 use App\Utils\Check;
 use App\Utils\Tools;
 use App\Utils\Radius;
+use Exception;
 use voku\helper\AntiXSS;
-use Psr\Http\Message\ServerRequestInterface;
-use Psr\Http\Message\ResponseInterface;
-
 use App\Utils\Hash;
 use App\Utils\Da;
 use App\Services\Auth;
@@ -31,22 +29,21 @@ class AuthController extends BaseController
     {
         $GtSdk = null;
         $recaptcha_sitekey = null;
-        if (Config::get('enable_login_captcha') == 'true'){
-            switch(Config::get('captcha_provider'))
-            {
+        if (Config::get('enable_login_captcha') === 'true') {
+            switch (Config::get('captcha_provider')) {
                 case 'recaptcha':
                     $recaptcha_sitekey = Config::get('recaptcha_sitekey');
                     break;
                 case 'geetest':
-                    $uid = time().rand(1, 10000) ;
+                    $uid = time() . random_int(1, 10000);
                     $GtSdk = Geetest::get($uid);
                     break;
             }
         }
 
-        if (Config::get('enable_telegram') == 'true') {
+        if (Config::get('enable_telegram') === 'true') {
             $login_text = TelegramSessionManager::add_login_session();
-            $login = explode("|", $login_text);
+            $login = explode('|', $login_text);
             $login_token = $login[0];
             $login_number = $login[1];
         } else {
@@ -64,25 +61,46 @@ class AuthController extends BaseController
             ->display('auth/login.tpl');
     }
 
+    public function getCaptcha($request, $response, $args)
+    {
+        $GtSdk = null;
+        $recaptcha_sitekey = null;
+        if (Config::get('captcha_provider') != '') {
+            switch (Config::get('captcha_provider')) {
+                case 'recaptcha':
+                    $recaptcha_sitekey = Config::get('recaptcha_sitekey');
+                    $res['recaptchaKey'] = $recaptcha_sitekey;
+                    break;
+                case 'geetest':
+                    $uid = time() . random_int(1, 10000);
+                    $GtSdk = Geetest::get($uid);
+                    $res['GtSdk'] = $GtSdk;
+                    break;
+            }
+        }
+
+        $res['respon'] = 1;
+        return $response->getBody()->write(json_encode($res));
+    }
+
     public function loginHandle($request, $response, $args)
     {
         // $data = $request->post('sdf');
         $email = $request->getParam('email');
-		$email = trim($email);
+        $email = trim($email);
         $email = strtolower($email);
         $passwd = $request->getParam('passwd');
         $code = $request->getParam('code');
         $rememberMe = $request->getParam('remember_me');
 
-        if (Config::get('enable_login_captcha') == 'true') {
-            switch(Config::get('captcha_provider'))
-            {
+        if (Config::get('enable_login_captcha') === 'true') {
+            switch (Config::get('captcha_provider')) {
                 case 'recaptcha':
                     $recaptcha = $request->getParam('recaptcha');
-                    if ($recaptcha == ''){
+                    if ($recaptcha == '') {
                         $ret = false;
-                    }else{
-                        $json = file_get_contents("https://recaptcha.net/recaptcha/api/siteverify?secret=".Config::get('recaptcha_secret')."&response=".$recaptcha);
+                    } else {
+                        $json = file_get_contents('https://recaptcha.net/recaptcha/api/siteverify?secret=' . Config::get('recaptcha_secret') . '&response=' . $recaptcha);
                         $ret = json_decode($json)->success;
                     }
                     break;
@@ -92,7 +110,7 @@ class AuthController extends BaseController
             }
             if (!$ret) {
                 $res['ret'] = 0;
-                $res['msg'] = "系统无法接受您的验证结果,请刷新页面后重试。";
+                $res['msg'] = '系统无法接受您的验证结果,请刷新页面后重试。';
                 return $response->getBody()->write(json_encode($res));
             }
         }
@@ -102,28 +120,28 @@ class AuthController extends BaseController
 
         if ($user == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "邮箱或者密码错误";
+            $rs['msg'] = '邮箱不存在';
             return $response->getBody()->write(json_encode($rs));
         }
 
         if (!Hash::checkPassword($user->pass, $passwd)) {
             $rs['ret'] = 0;
-            $rs['msg'] = "邮箱或者密码错误.";
+            $rs['msg'] = '邮箱或者密码错误';
 
 
-            $loginip = new LoginIp();
-            $loginip->ip = $_SERVER["REMOTE_ADDR"];
-            $loginip->userid = $user->id;
-            $loginip->datetime = time();
-            $loginip->type = 1;
-            $loginip->save();
+            $loginIP = new LoginIp();
+            $loginIP->ip = $_SERVER['REMOTE_ADDR'];
+            $loginIP->userid = $user->id;
+            $loginIP->datetime = time();
+            $loginIP->type = 1;
+            $loginIP->save();
 
             return $response->getBody()->write(json_encode($rs));
         }
-        // @todo
+
         $time = 3600 * 24;
         if ($rememberMe) {
-            $time = 3600 * 24 * 7;
+            $time = 3600 * 24 * (Config::get('rememberMeDuration') ?: 7);
         }
 
         if ($user->ga_enable == 1) {
@@ -132,21 +150,21 @@ class AuthController extends BaseController
 
             if (!$rcode) {
                 $res['ret'] = 0;
-                $res['msg'] = "两步验证码错误,如果您是丢失了生成器或者错误地设置了这个选项,您可以尝试重置密码,即可取消这个选项。";
+                $res['msg'] = '两步验证码错误,如果您是丢失了生成器或者错误地设置了这个选项,您可以尝试重置密码,即可取消这个选项。';
                 return $response->getBody()->write(json_encode($res));
             }
         }
 
         Auth::login($user->id, $time);
         $rs['ret'] = 1;
-        $rs['msg'] = "登录成功";
+        $rs['msg'] = '登录成功';
 
-        $loginip = new LoginIp();
-        $loginip->ip = $_SERVER["REMOTE_ADDR"];
-        $loginip->userid = $user->id;
-        $loginip->datetime = time();
-        $loginip->type = 0;
-        $loginip->save();
+        $loginIP = new LoginIp();
+        $loginIP->ip = $_SERVER['REMOTE_ADDR'];
+        $loginIP->userid = $user->id;
+        $loginIP->datetime = time();
+        $loginIP->type = 0;
+        $loginIP->save();
 
         return $response->getBody()->write(json_encode($rs));
     }
@@ -160,7 +178,7 @@ class AuthController extends BaseController
         $ret = TelegramSessionManager::step2_verify_login_session($token, $number);
         if (!$ret) {
             $res['ret'] = 0;
-            $res['msg'] = "此令牌无法被使用。";
+            $res['msg'] = '此令牌无法被使用。';
             return $response->getBody()->write(json_encode($res));
         }
 
@@ -172,9 +190,9 @@ class AuthController extends BaseController
 
         Auth::login($user->id, $time);
         $rs['ret'] = 1;
-        $rs['msg'] = "登录成功";
+        $rs['msg'] = '登录成功';
 
-        $this->logUserIp($user->id, $_SERVER["REMOTE_ADDR"]);
+        $this->logUserIp($user->id, $_SERVER['REMOTE_ADDR']);
 
         return $response->getBody()->write(json_encode($rs));
     }
@@ -192,7 +210,7 @@ class AuthController extends BaseController
     public function register($request, $response, $next)
     {
         $ary = $request->getQueryParams();
-        $code = "";
+        $code = '';
         if (isset($ary['code'])) {
             $antiXss = new AntiXSS();
             $code = $antiXss->xss_clean($ary['code']);
@@ -200,14 +218,13 @@ class AuthController extends BaseController
 
         $GtSdk = null;
         $recaptcha_sitekey = null;
-        if (Config::get('enable_reg_captcha') == 'true'){
-            switch(Config::get('captcha_provider'))
-            {
+        if (Config::get('enable_reg_captcha') === 'true') {
+            switch (Config::get('captcha_provider')) {
                 case 'recaptcha':
                     $recaptcha_sitekey = Config::get('recaptcha_sitekey');
                     break;
                 case 'geetest':
-                    $uid = time().rand(1, 10000) ;
+                    $uid = time() . random_int(1, 10000);
                     $GtSdk = Geetest::get($uid);
                     break;
             }
@@ -225,34 +242,34 @@ class AuthController extends BaseController
 
     public function sendVerify($request, $response, $next)
     {
-        if (Config::get('enable_email_verify') == 'true') {
+        if (Config::get('enable_email_verify') === 'true') {
             $email = $request->getParam('email');
-			$email = trim($email);
+            $email = trim($email);
 
-            if ($email == "") {
+            if ($email == '') {
                 $res['ret'] = 0;
-                $res['msg'] = "未填写邮箱";
+                $res['msg'] = '未填写邮箱';
                 return $response->getBody()->write(json_encode($res));
             }
 
             // check email format
             if (!Check::isEmailLegal($email)) {
                 $res['ret'] = 0;
-                $res['msg'] = "邮箱无效";
+                $res['msg'] = '邮箱无效';
                 return $response->getBody()->write(json_encode($res));
             }
 
             $user = User::where('email', '=', $email)->first();
             if ($user != null) {
                 $res['ret'] = 0;
-                $res['msg'] = "此邮箱已经注册";
+                $res['msg'] = '此邮箱已经注册';
                 return $response->getBody()->write(json_encode($res));
             }
 
-            $ipcount = EmailVerify::where('ip', '=', $_SERVER["REMOTE_ADDR"])->where('expire_in', '>', time())->count();
+            $ipcount = EmailVerify::where('ip', '=', $_SERVER['REMOTE_ADDR'])->where('expire_in', '>', time())->count();
             if ($ipcount >= (int)Config::get('email_verify_iplimit')) {
                 $res['ret'] = 0;
-                $res['msg'] = "此IP请求次数过多";
+                $res['msg'] = '此IP请求次数过多';
                 return $response->getBody()->write(json_encode($res));
             }
 
@@ -260,7 +277,7 @@ class AuthController extends BaseController
             $mailcount = EmailVerify::where('email', '=', $email)->where('expire_in', '>', time())->count();
             if ($mailcount >= 3) {
                 $res['ret'] = 0;
-                $res['msg'] = "此邮箱请求次数过多";
+                $res['msg'] = '此邮箱请求次数过多';
                 return $response->getBody()->write(json_encode($res));
             }
 
@@ -268,63 +285,64 @@ class AuthController extends BaseController
 
             $ev = new EmailVerify();
             $ev->expire_in = time() + Config::get('email_verify_ttl');
-            $ev->ip = $_SERVER["REMOTE_ADDR"];
+            $ev->ip = $_SERVER['REMOTE_ADDR'];
             $ev->email = $email;
             $ev->code = $code;
             $ev->save();
 
-            $subject = Config::get('appName') . "- 验证邮件";
+            $subject = Config::get('appName') . '- 验证邮件';
 
             try {
                 Mail::send($email, $subject, 'auth/verify.tpl', [
-                    "code" => $code, "expire" => date("Y-m-d H:i:s", time() + Config::get('email_verify_ttl'))
+                    'code' => $code, 'expire' => date('Y-m-d H:i:s', time() + Config::get('email_verify_ttl'))
                 ], [
                     //BASE_PATH.'/public/assets/email/styles.css'
                 ]);
-            } catch (\Exception $e) {
+            } catch (Exception $e) {
                 $res['ret'] = 1;
-                $res['msg'] = "邮件发送失败,请联系网站管理员。";
+                $res['msg'] = '邮件发送失败,请联系网站管理员。';
                 return $response->getBody()->write(json_encode($res));
             }
 
             $res['ret'] = 1;
-            $res['msg'] = "验证码发送成功,请查收邮件。";
+            $res['msg'] = '验证码发送成功,请查收邮件。';
             return $response->getBody()->write(json_encode($res));
         }
+        $res['ret'] = 0;
+        return $response->getBody()->write(json_encode($res));
     }
 
     public function registerHandle($request, $response)
     {
-		if(Config::get('register_mode')=='close'){
-			$res['ret'] = 0;
-            $res['msg'] = "未开放注册。";
+        if (Config::get('register_mode') === 'close') {
+            $res['ret'] = 0;
+            $res['msg'] = '未开放注册。';
             return $response->getBody()->write(json_encode($res));
-		}
+        }
         $name = $request->getParam('name');
         $email = $request->getParam('email');
-		$email = trim($email);
+        $email = trim($email);
         $email = strtolower($email);
         $passwd = $request->getParam('passwd');
         $repasswd = $request->getParam('repasswd');
         $code = $request->getParam('code');
-		$code = trim($code);
+        $code = trim($code);
         $imtype = $request->getParam('imtype');
         $emailcode = $request->getParam('emailcode');
-		$emailcode = trim($emailcode);
+        $emailcode = trim($emailcode);
         $wechat = $request->getParam('wechat');
-		$wechat = trim($wechat);
+        $wechat = trim($wechat);
         // check code
 
 
-        if (Config::get('enable_reg_captcha') == 'true') {
-            switch(Config::get('captcha_provider'))
-            {
+        if (Config::get('enable_reg_captcha') === 'true') {
+            switch (Config::get('captcha_provider')) {
                 case 'recaptcha':
                     $recaptcha = $request->getParam('recaptcha');
-                    if ($recaptcha == ''){
+                    if ($recaptcha == '') {
                         $ret = false;
-                    }else{
-                        $json = file_get_contents("https://recaptcha.net/recaptcha/api/siteverify?secret=".Config::get('recaptcha_secret')."&response=".$recaptcha);
+                    } else {
+                        $json = file_get_contents('https://recaptcha.net/recaptcha/api/siteverify?secret=' . Config::get('recaptcha_secret') . '&response=' . $recaptcha);
                         $ret = json_decode($json)->success;
                     }
                     break;
@@ -334,7 +352,7 @@ class AuthController extends BaseController
             }
             if (!$ret) {
                 $res['ret'] = 0;
-                $res['msg'] = "系统无法接受您的验证结果,请刷新页面后重试。";
+                $res['msg'] = '系统无法接受您的验证结果,请刷新页面后重试。';
                 return $response->getBody()->write(json_encode($res));
             }
         }
@@ -343,49 +361,52 @@ class AuthController extends BaseController
         //dumplin:1、邀请人等级为0则邀请码不可用;2、邀请人invite_num为可邀请次数,填负数则为无限
         $c = InviteCode::where('code', $code)->first();
         if ($c == null) {
-            if (Config::get('register_mode') == 'invite') {
+            if (Config::get('register_mode') === 'invite') {
                 $res['ret'] = 0;
-                $res['msg'] = "邀请码无效";
+                $res['msg'] = '邀请码无效';
                 return $response->getBody()->write(json_encode($res));
             }
-        } else if ($c->user_id != 0) {
-            $gift_user = User::where("id", "=", $c->user_id)->first();
+        } elseif ($c->user_id != 0) {
+            $gift_user = User::where('id', '=', $c->user_id)->first();
             if ($gift_user == null) {
                 $res['ret'] = 0;
-                $res['msg'] = "邀请人不存在";
+                $res['msg'] = '邀请人不存在';
                 return $response->getBody()->write(json_encode($res));
-            } else if ($gift_user->class == 0) {
+            }
+
+            if ($gift_user->class == 0) {
                 $res['ret'] = 0;
-                $res['msg'] = "邀请人不是VIP";
+                $res['msg'] = '邀请人不是VIP';
                 return $response->getBody()->write(json_encode($res));
-            } else if ($gift_user->invite_num == 0) {
+            }
+
+            if ($gift_user->invite_num == 0) {
                 $res['ret'] = 0;
-                $res['msg'] = "邀请人可用邀请次数为0";
+                $res['msg'] = '邀请人可用邀请次数为0';
                 return $response->getBody()->write(json_encode($res));
             }
         }
 
 
-
         // check email format
         if (!Check::isEmailLegal($email)) {
             $res['ret'] = 0;
-            $res['msg'] = "邮箱无效";
+            $res['msg'] = '邮箱无效';
             return $response->getBody()->write(json_encode($res));
         }
         // check email
         $user = User::where('email', $email)->first();
         if ($user != null) {
             $res['ret'] = 0;
-            $res['msg'] = "邮箱已经被注册了";
+            $res['msg'] = '邮箱已经被注册了';
             return $response->getBody()->write(json_encode($res));
         }
 
-        if (Config::get('enable_email_verify') == 'true') {
+        if (Config::get('enable_email_verify') === 'true') {
             $mailcount = EmailVerify::where('email', '=', $email)->where('code', '=', $emailcode)->where('expire_in', '>', time())->first();
             if ($mailcount == null) {
                 $res['ret'] = 0;
-                $res['msg'] = "您的邮箱验证码不正确";
+                $res['msg'] = '您的邮箱验证码不正确';
                 return $response->getBody()->write(json_encode($res));
             }
         }
@@ -393,30 +414,30 @@ class AuthController extends BaseController
         // check pwd length
         if (strlen($passwd) < 8) {
             $res['ret'] = 0;
-            $res['msg'] = "密码请大于8位";
+            $res['msg'] = '密码请大于8位';
             return $response->getBody()->write(json_encode($res));
         }
 
         // check pwd re
         if ($passwd != $repasswd) {
             $res['ret'] = 0;
-            $res['msg'] = "两次密码输入不符";
+            $res['msg'] = '两次密码输入不符';
             return $response->getBody()->write(json_encode($res));
         }
 
-        if ($imtype == "" || $wechat == "") {
+        if ($imtype == '' || $wechat == '') {
             $res['ret'] = 0;
-            $res['msg'] = "请填上你的联络方式";
+            $res['msg'] = '请填上你的联络方式';
             return $response->getBody()->write(json_encode($res));
         }
 
         $user = User::where('im_value', $wechat)->where('im_type', $imtype)->first();
         if ($user != null) {
             $res['ret'] = 0;
-            $res['msg'] = "此联络方式已注册";
+            $res['msg'] = '此联络方式已注册';
             return $response->getBody()->write(json_encode($res));
         }
-        if (Config::get('enable_email_verify') == 'true') {
+        if (Config::get('enable_email_verify') === 'true') {
             EmailVerify::where('email', '=', $email)->delete();
         }
         // do reg user
@@ -450,31 +471,29 @@ class AuthController extends BaseController
 
         //dumplin:填写邀请人,写入邀请奖励
         $user->ref_by = 0;
-        if ($c != null) {
-            if ($c->user_id != 0) {
-                $gift_user = User::where("id", "=", $c->user_id)->first();
-                $user->ref_by = $c->user_id;
-                $user->money = Config::get('invite_get_money');
-                $gift_user->transfer_enable = ($gift_user->transfer_enable + Config::get('invite_gift') * 1024 * 1024 * 1024);
-                $gift_user->invite_num -= 1;
-                $gift_user->save();
-            }
+        if (($c != null) && $c->user_id != 0) {
+            $gift_user = User::where('id', '=', $c->user_id)->first();
+            $user->ref_by = $c->user_id;
+            $user->money = Config::get('invite_get_money');
+            $gift_user->transfer_enable += Config::get('invite_gift') * 1024 * 1024 * 1024;
+            --$gift_user->invite_num;
+            $gift_user->save();
         }
 
 
-        $user->class_expire = date("Y-m-d H:i:s", time() + Config::get('user_class_expire_default') * 3600);
+        $user->class_expire = date('Y-m-d H:i:s', time() + Config::get('user_class_expire_default') * 3600);
         $user->class = Config::get('user_class_default');
         $user->node_connector = Config::get('user_conn');
         $user->node_speedlimit = Config::get('user_speedlimit');
-        $user->expire_in = date("Y-m-d H:i:s", time() + Config::get('user_expire_in_default') * 86400);
-        $user->reg_date = date("Y-m-d H:i:s");
-        $user->reg_ip = $_SERVER["REMOTE_ADDR"];
+        $user->expire_in = date('Y-m-d H:i:s', time() + Config::get('user_expire_in_default') * 86400);
+        $user->reg_date = date('Y-m-d H:i:s');
+        $user->reg_ip = $_SERVER['REMOTE_ADDR'];
         $user->plan = 'A';
         $user->theme = Config::get('theme');
 
-        $groups=explode(",", Config::get('ramdom_group'));
+        $groups = explode(',', Config::get('ramdom_group'));
 
-        $user->node_group=$groups[array_rand($groups)];
+        $user->node_group = $groups[array_rand($groups)];
 
         $ga = new GA();
         $secret = $ga->createSecret();
@@ -485,50 +504,54 @@ class AuthController extends BaseController
 
         if ($user->save()) {
             $res['ret'] = 1;
-            $res['msg'] = "注册成功!正在进入登录界面";
+            $res['msg'] = '注册成功!正在进入登录界面';
             Radius::Add($user, $user->passwd);
             return $response->getBody()->write(json_encode($res));
         }
 
         $res['ret'] = 0;
-        $res['msg'] = "未知错误";
+        $res['msg'] = '未知错误';
         return $response->getBody()->write(json_encode($res));
     }
 
     public function logout($request, $response, $next)
     {
         Auth::logout();
-        $newResponse = $response->withStatus(302)->withHeader('Location', '/auth/login');
-        return $newResponse;
+        return $response->withStatus(302)->withHeader('Location', '/auth/login');
     }
 
     public function qrcode_check($request, $response, $args)
     {
-        $token = $request->getQueryParams()["token"];
-        $number = $request->getQueryParams()["number"];
+        $token = $request->getParam('token');
+        $number = $request->getParam('number');
+        $user = Auth::getUser();
+        if ($user->isLogin) {
+            $res['ret'] = 0;
+            return $response->getBody()->write(json_encode($res));
+        }
 
-        if (Config::get('enable_telegram') == 'true') {
+        if (Config::get('enable_telegram') === 'true') {
             $ret = TelegramSessionManager::check_login_session($token, $number);
             $res['ret'] = $ret;
             return $response->getBody()->write(json_encode($res));
-        } else {
-            $res['ret'] = 0;
-            return $response->getBody()->write(json_encode($res));
         }
+
+        $res['ret'] = 0;
+        return $response->getBody()->write(json_encode($res));
     }
 
     public function telegram_oauth($request, $response, $args)
     {
-        if (Config::get('enable_telegram') == 'true') {
+        if (Config::get('enable_telegram') === 'true') {
             $auth_data = $request->getQueryParams();
             if ($this->telegram_oauth_check($auth_data) === true) { // Looks good, proceed.
                 $telegram_id = $auth_data['id'];
                 $user = User::query()->where('telegram_id', $telegram_id)->firstOrFail(); // Welcome Back :)
-                if($user == null){
+                if ($user == null) {
                     return $this->view()->assign('title', '您需要先进行邮箱注册后绑定Telegram才能使用授权登录')->assign('message', '很抱歉带来的不便,请重新试试')->assign('redirect', '/auth/login')->display('telegram_error.tpl');
                 }
                 Auth::login($user->id, 3600);
-                $this->logUserIp($user->id, $_SERVER["REMOTE_ADDR"]);
+                $this->logUserIp($user->id, $_SERVER['REMOTE_ADDR']);
 
                 // 登陆成功!
                 return $this->view()->assign('title', '登录成功')->assign('message', '正在前往仪表盘')->assign('redirect', '/user')->display('telegram_success.tpl');
@@ -542,7 +565,7 @@ class AuthController extends BaseController
     private function telegram_oauth_check($auth_data)
     {
         $check_hash = $auth_data['hash'];
-        $bot_token = Config::get('telegram_token');;
+        $bot_token = Config::get('telegram_token');
         unset($auth_data['hash']);
         $data_check_arr = [];
         foreach ($auth_data as $key => $value) {

+ 23 - 13
app/Controllers/BaseController.php

@@ -2,34 +2,44 @@
 
 namespace App\Controllers;
 
-use App\Services\Auth;
+use App\Models\User;
 use App\Services\View;
+use App\Services\Auth;
+use Smarty;
 
 /**
  * BaseController
  */
-
 class BaseController
 {
-    public $view;
+    /**
+     * @var Smarty
+     */
+    protected $view;
 
-    public $smarty;
-    
-    public function construct__()
-    {
-    }
+    /**
+     * @var User
+     */
+    protected $user;
 
-    public function smarty()
+    /**
+     * Construct page renderer
+     */
+    public function __construct()
     {
-        $this->smarty = View::getSmarty();
-        return $this->smarty;
+        $this->view = View::getSmarty();
+        $this->user = Auth::getUser();
     }
 
+    /**
+     * Get smarty
+     *
+     * @return Smarty
+     */
     public function view()
     {
-        return $this->smarty();
+        return $this->view;
     }
-
     /**
      * @param $response
      * @param $res

+ 13 - 12
app/Controllers/Client/ClientApiController.php

@@ -28,25 +28,26 @@ class ClientApiController extends BaseController
         $user = User::find($token->userId);
         $Anns = Ann::orderBy('date', 'desc')->first();
         $res['ret'] = 1;
-        $res['msg'] = "ok";
+        $res['msg'] = 'ok';
         $res['data'] = $Anns;
         return $this->echoJson($response, $res);
     }
 
-    public function Redirect($request, $response, $args){
+    public function Redirect($request, $response, $args)
+    {
         $user = Auth::getUser();
-        $url = $request->getQueryParams()["target"];
-        if(!$user->isLogin){
+        $url = $request->getQueryParams()['target'];
+        if (!$user->isLogin) {
             $accessToken = Helper::getTokenFromReq($request);
             $storage = Factory::createTokenStorage();
             $token = $storage->get($accessToken);
-            if ($token==null) {
+            if ($token == null) {
                 $res['ret'] = 0;
-                $res['msg'] = "token is null";
+                $res['msg'] = 'token is null';
                 return $this->echoJson($response, $res);
             }
             $user = User::find($token->userId);
-            $time =  3600*24;
+            $time = 3600 * 24;
             Auth::login($user->id, $time);
         }
         return $response->withRedirect($url);
@@ -60,12 +61,12 @@ class ClientApiController extends BaseController
         $user = User::find($token->userId);
         $ssr_sub_token = LinkController::GenerateSSRSubCode($user->id, 0);
         $mu = 0;
-        if($request->getQueryParams()["mu"]!=""){
-            $mu = $request->getQueryParams()["mu"];
+        if ($request->getQueryParams()['mu'] != '') {
+            $mu = $request->getQueryParams()['mu'];
         }
         $res['ret'] = 1;
-        $res['msg'] = "ok";
-        $res['data'] = Config::get('baseUrl').'/link/'.$ssr_sub_token.'?mu='.$mu;
+        $res['msg'] = 'ok';
+        $res['data'] = Config::get('subUrl') . $ssr_sub_token . '?mu=' . $mu;
         return $this->echoJson($response, $res);
     }
-}
+}

+ 51 - 26
app/Controllers/HomeController.php

@@ -3,22 +3,12 @@
 namespace App\Controllers;
 
 use App\Models\InviteCode;
-use App\Models\User;
-use App\Models\Code;
-use App\Models\Payback;
-use App\Models\Paylist;
-use App\Services\Auth;
 use App\Services\Config;
-use App\Services\Payment;
 use App\Utils\AliPay;
-use App\Utils\Tools;
-use App\Utils\Telegram;
-use App\Utils\Tuling;
 use App\Utils\TelegramSessionManager;
-use App\Utils\QRcode;
-use App\Utils\Pay;
 use App\Utils\TelegramProcess;
 use App\Utils\Spay_tool;
+use App\Utils\Geetest;
 
 /**
  *  HomeController
@@ -27,7 +17,45 @@ class HomeController extends BaseController
 {
     public function index()
     {
-        return $this->view()->display('index.tpl');
+        $GtSdk = null;
+        $recaptcha_sitekey = null;
+        if (Config::get('captcha_provider') != '') {
+            switch (Config::get('captcha_provider')) {
+                case 'recaptcha':
+                    $recaptcha_sitekey = Config::get('recaptcha_sitekey');
+                    break;
+                case 'geetest':
+                    $uid = time() . random_int(1, 10000);
+                    $GtSdk = Geetest::get($uid);
+                    break;
+            }
+        }
+
+        if (Config::get('enable_telegram') == 'true') {
+            $login_text = TelegramSessionManager::add_login_session();
+            $login = explode('|', $login_text);
+            $login_token = $login[0];
+            $login_number = $login[1];
+        } else {
+            $login_token = '';
+            $login_number = '';
+        }
+
+        return $this->view()
+            ->assign('geetest_html', $GtSdk)
+            ->assign('login_token', $login_token)
+            ->assign('login_number', $login_number)
+            ->assign('telegram_bot', Config::get('telegram_bot'))
+            ->assign('enable_logincaptcha', Config::get('enable_login_captcha'))
+            ->assign('enable_regcaptcha', Config::get('enable_reg_captcha'))
+            ->assign('base_url', Config::get('baseUrl'))
+            ->assign('recaptcha_sitekey', $recaptcha_sitekey)
+            ->display('index.tpl');
+    }
+
+    public function indexold()
+    {
+        return $this->view()->display('indexold.tpl');
     }
 
     public function code()
@@ -44,39 +72,36 @@ class HomeController extends BaseController
     {
         return $this->view()->display('tos.tpl');
     }
-    
+
     public function staff()
     {
         return $this->view()->display('staff.tpl');
     }
-    
+
     public function telegram($request, $response, $args)
     {
-        $token = "";
-        if (isset($request->getQueryParams()["token"])) {
-            $token = $request->getQueryParams()["token"];
-        }
-        
+        $token = $request->getQueryParams()['token'] ?? '';
+
         if ($token == Config::get('telegram_request_token')) {
             TelegramProcess::process();
         } else {
-            echo("不正确请求!");
+            echo('不正确请求!');
         }
     }
-    
+
     public function page404($request, $response, $args)
     {
         return $this->view()->display('404.tpl');
     }
-    
+
     public function page405($request, $response, $args)
     {
         return $this->view()->display('405.tpl');
     }
-    
+
     public function page500($request, $response, $args)
     {
-		return $this->view()->display('500.tpl');
+        return $this->view()->display('500.tpl');
     }
 
     public function getOrderList($request, $response, $args)
@@ -84,7 +109,7 @@ class HomeController extends BaseController
         $key = $request->getParam('key');
         if (!$key || $key != Config::get('key')) {
             $res['ret'] = 0;
-            $res['msg'] = "错误";
+            $res['msg'] = '错误';
             return $response->getBody()->write(json_encode($res));
         }
         return $response->getBody()->write(json_encode(['data' => AliPay::getList()]));
@@ -97,7 +122,7 @@ class HomeController extends BaseController
         $url = $request->getParam('url');
         if (!$key || $key != Config::get('key')) {
             $res['ret'] = 0;
-            $res['msg'] = "错误";
+            $res['msg'] = '错误';
             return $response->getBody()->write(json_encode($res));
         }
         return $response->getBody()->write(json_encode(['res' => AliPay::setOrder($sn, $url)]));

+ 116 - 535
app/Controllers/LinkController.php

@@ -6,29 +6,21 @@ namespace App\Controllers;
 
 use App\Models\Link;
 use App\Models\User;
-use App\Models\Node;
-use App\Models\Relay;
 use App\Models\Smartline;
 use App\Utils\ConfRender;
 use App\Utils\Tools;
 use App\Utils\URL;
-use App\Services\Config;
 
 /**
  *  HomeController
  */
 class LinkController extends BaseController
 {
-    public function __construct()
-    {
-    }
-
     public static function GenerateRandomLink()
     {
-        $i =0;
         for ($i = 0; $i < 10; $i++) {
             $token = Tools::genRandomChar(16);
-            $Elink = Link::where("token", "=", $token)->first();
+            $Elink = Link::where('token', '=', $token)->first();
             if ($Elink == null) {
                 return $token;
             }
@@ -37,61 +29,21 @@ class LinkController extends BaseController
         return "couldn't alloc token";
     }
 
-    public static function GenerateAclCode($address, $port, $userid, $geo, $method)
-    {
-        $Elink = Link::where("type", "=", 9)->where("address", "=", $address)->where("port", "=", $port)->where("userid", "=", $userid)->where("geo", "=", $geo)->where("method", "=", $method)->first();
-        if ($Elink != null) {
-            return $Elink->token;
-        }
-        $NLink = new Link();
-        $NLink->type = 9;
-        $NLink->address = $address;
-        $NLink->port = $port;
-        $NLink->ios = 0;
-        $NLink->geo = $geo;
-        $NLink->method = $method;
-        $NLink->userid = $userid;
-        $NLink->token = LinkController::GenerateRandomLink();
-        $NLink->save();
-
-        return $NLink->token;
-    }
-
-    public static function GenerateRouterCode($userid, $without_mu)
-    {
-        $Elink = Link::where("type", "=", 10)->where("userid", "=", $userid)->where("geo", $without_mu)->first();
-        if ($Elink != null) {
-            return $Elink->token;
-        }
-        $NLink = new Link();
-        $NLink->type = 10;
-        $NLink->address = "";
-        $NLink->port = 0;
-        $NLink->ios = 0;
-        $NLink->geo = $without_mu;
-        $NLink->method = "";
-        $NLink->userid = $userid;
-        $NLink->token = LinkController::GenerateRandomLink();
-        $NLink->save();
-
-        return $NLink->token;
-    }
-
     public static function GenerateSSRSubCode($userid, $without_mu)
     {
-        $Elink = Link::where("type", "=", 11)->where("userid", "=", $userid)->where("geo", $without_mu)->first();
+        $Elink = Link::where('type', '=', 11)->where('userid', '=', $userid)->where('geo', $without_mu)->first();
         if ($Elink != null) {
             return $Elink->token;
         }
         $NLink = new Link();
         $NLink->type = 11;
-        $NLink->address = "";
+        $NLink->address = '';
         $NLink->port = 0;
         $NLink->ios = 0;
         $NLink->geo = $without_mu;
-        $NLink->method = "";
+        $NLink->method = '';
         $NLink->userid = $userid;
-        $NLink->token = LinkController::GenerateRandomLink();
+        $NLink->token = self::GenerateRandomLink();
         $NLink->save();
 
         return $NLink->token;
@@ -102,515 +54,144 @@ class LinkController extends BaseController
         $token = $args['token'];
 
         //$builder->getPhrase();
-        $Elink = Link::where("token", "=", $token)->first();
+        $Elink = Link::where('token', '=', $token)->first();
         if ($Elink == null) {
             return null;
         }
 
-        switch ($Elink->type) {
-            case 9:
-                $newResponse = $response->withHeader('Content-type', ' application/octet-stream; charset=utf-8')->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate')->withHeader('Content-Disposition', ' attachment; filename='.$token.'.acl');//->getBody()->write($builder->output());
-                $newResponse->getBody()->write(LinkController::GetAcl(User::where("id", "=", $Elink->userid)->first()));
-                return $newResponse;
-            case 10:
-                $user=User::where("id", $Elink->userid)->first();
-                if ($user == null) {
-                    return null;
-                }
-
-                $is_ss = 0;
-                if (isset($request->getQueryParams()["is_ss"])) {
-                    $is_ss = $request->getQueryParams()["is_ss"];
-                }
-
-                $newResponse = $response->withHeader('Content-type', ' application/octet-stream; charset=utf-8')->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate')->withHeader('Content-Disposition', ' attachment; filename='.$token.'.sh');//->getBody()->write($builder->output());
-                $newResponse->getBody()->write(LinkController::GetRouter(User::where("id", "=", $Elink->userid)->first(), $Elink->geo, $is_ss));
-                return $newResponse;
-            case 11:
-                $user=User::where("id", $Elink->userid)->first();
-                if ($user == null) {
-                    return null;
-                }
-
-                $max = 0;
-                if (isset($request->getQueryParams()["max"])) {
-                    $max = (int)$request->getQueryParams()["max"];
-                }
+        if ($Elink->type != 11) {
+            return null;
+        }
 
-                $mu = 0;
-                if (isset($request->getQueryParams()["mu"])) {
-                    $mu = (int)$request->getQueryParams()["mu"];
-                }
+        $user = User::where('id', $Elink->userid)->first();
+        if ($user == null) {
+            return null;
+        }
 
-                $newResponse = $response->withHeader('Content-type', ' application/octet-stream; charset=utf-8')->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate')->withHeader('Content-Disposition', ' attachment; filename='.$token.'.txt');
-                $newResponse->getBody()->write(LinkController::GetSSRSub(User::where("id", "=", $Elink->userid)->first(), $mu, $max));
-                return $newResponse;
-            default:
-                break;
+        $mu = 0;
+        if (isset($request->getQueryParams()['mu'])) {
+            $mu = (int)$request->getQueryParams()['mu'];
         }
-        $newResponse = $response->withHeader('Content-type', ' application/x-ns-proxy-autoconfig; charset=utf-8')->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate');//->getBody()->write($builder->output());
-        $newResponse->getBody()->write(LinkController::GetPac($type, $Elink->address, $Elink->port, User::where("id", "=", $Elink->userid)->first()->pac));
+
+        $newResponse = $response->withHeader('Content-type', ' application/octet-stream; charset=utf-8')->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate')->withHeader('Content-Disposition', ' attachment; filename=' . $token . '.txt');
+        $newResponse->getBody()->write(self::GetSSRSub(User::where('id', '=', $Elink->userid)->first(), $mu));
         return $newResponse;
     }
 
-    public static function GetPcConf($user, $is_mu = 0, $is_ss = 0)
-    {
-    if ($is_ss==0) {
-        $string='
-            {
-                "index" : 0,
-                "random" : false,
-                "sysProxyMode" : 0,
-                "shareOverLan" : false,
-                "bypassWhiteList" : false,
-                "localPort" : 1080,
-                "localAuthPassword" : "'.Tools::genRandomChar(26).'",
-                "dns_server" : "",
-                "reconnectTimes" : 4,
-                "randomAlgorithm" : 0,
-                "TTL" : 60,
-                "connect_timeout" : 5,
-                "proxyRuleMode" : 1,
-                "proxyEnable" : false,
-                "pacDirectGoProxy" : false,
-                "proxyType" : 0,
-                "proxyHost" : "",
-                "proxyPort" : 0,
-                "proxyAuthUser" : "",
-                "proxyAuthPass" : "",
-                "proxyUserAgent" : "",
-                "authUser" : "",
-                "authPass" : "",
-                "autoBan" : false,
-                "sameHostForSameTarget" : true,
-                "keepVisitTime" : 180,
-                "isHideTips" : true,
-                "token" : {
-
-                },
-                "portMap" : {
+    public const V2RYA_MU = 2;
+    public const SSD_MU = 3;
+    public const CLASH_MU = 4;
 
-                }
-            }
-        ';
-    } else {
-        $string='
-            {
-                "strategy": null,
-                "index": 6,
-                "global": false,
-                "enabled": false,
-                "shareOverLan": false,
-                "isDefault": false,
-                "localPort": 1080,
-                "pacUrl": null,
-                "useOnlinePac": false,
-                "secureLocalPac": true,
-                "availabilityStatistics": false,
-                "autoCheckUpdate": false,
-                "checkPreRelease": false,
-                "isVerboseLogging": true,
-                "logViewer": {
-                "topMost": false,
-                "wrapText": false,
-                "toolbarShown": false,
-                "Font": "Consolas, 8pt",
-                "BackgroundColor": "Black",
-                "TextColor": "White"
-                },
-                "proxy": {
-                "useProxy": false,
-                "proxyType": 0,
-                "proxyServer": "",
-                "proxyPort": 0,
-                "proxyTimeout": 3
-                },
-                "hotkey": {
-                "SwitchSystemProxy": "",
-                "SwitchSystemProxyMode": "",
-                "SwitchAllowLan": "",
-                "ShowLogs": "",
-                "ServerMoveUp": "",
-                "ServerMoveDown": ""
-                }
-            }
-        ';
-    }
-
-        $json=json_decode($string, true);
-        $temparray=array();
+    public static function GetSSRSub($user, $mu = 0)
+    {
+        if ($mu == 0 || $mu == 1) {
+            return Tools::base64_url_encode(URL::getAllUrl($user, $mu, 0));
+        }
 
-        $items = URL::getAllItems($user, $is_mu, $is_ss);
-        foreach($items as $item) {
-            if ($is_ss==0) {
-                array_push($temparray, array("remarks"=>$item['remark'],
-                                            "server"=>$item['address'],
-                                            "server_port"=>$item['port'],
-                                            "method"=>$item['method'],
-                                            "obfs"=>$item['obfs'],
-                                            "obfsparam"=>$item['obfs_param'],
-                                            "remarks_base64"=>base64_encode($item['remark']),
-                                            "password"=>$item['passwd'],
-                                            "tcp_over_udp"=>false,
-                                            "udp_over_tcp"=>false,
-                                            "group"=>$item['group'],
-                                            "protocol"=>$item['protocol'],
-                                            "protoparam"=>$item['protocol_param'],
-                                            "protocolparam"=>$item['protocol_param'],
-                                            "obfs_udp"=>false,
-                                            "enable"=>true));
-            } else {
-                array_push($temparray, array("server"=>$item['address'],
-                                            "server_port"=>$item['port'],
-                                            "password"=>$item['passwd'],
-                                            "method"=>$item['method'],
-                                            "plugin"=>"obfs-local",
-                                            "plugin_opts"=>str_replace(',',';',URL::getSurgeObfs($item)),
-                                            "remarks"=>$item['remark'],
-                                            "timeout"=>5));
-            }
+        if ($mu == self::V2RYA_MU) {
+            return Tools::base64_url_encode(URL::getAllVMessUrl($user));
         }
 
-        $json["configs"]=$temparray;
-        return json_encode($json, JSON_PRETTY_PRINT);
-    }
+        if ($mu == self::SSD_MU) {
+            return URL::getAllSSDUrl($user);
+        }
 
-    private static function GetPac($type, $address, $port, $defined)
-    {
-        header('Content-type: application/x-ns-proxy-autoconfig; charset=utf-8');
-        return LinkController::get_pac($type, $address, $port, true, $defined);
+        if ($mu == self::CLASH_MU) {
+            // Clash
+            return self::GetClash($user);
+        }
     }
 
-    private static function GetAcl($user)
+    public static function GetClash($user)
     {
-        $rulelist = base64_decode(file_get_contents("https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"))."\n".$user->pac;
-        $gfwlist = explode("\n", $rulelist);
-
-        $count = 0;
-        $acl_content = '';
-        $find_function_content = '
-#Generated by sspanel-glzjin-mod v3
-#Time:'.date('Y-m-d H:i:s').'
-
-[bypass_all]
-
-';
-
-        $proxy_list = '[proxy_list]
-
-';
-        $bypass_list = '[bypass_list]
-
-';
-        $outbound_block_list = '[outbound_block_list]
-
-';
-
-        $isget=array();
-        foreach ($gfwlist as $index=>$rule) {
-            if (empty($rule)) {
-                continue;
-            } elseif (substr($rule, 0, 1) == '!' || substr($rule, 0, 1) == '[') {
-                continue;
-            }
-
-            if (substr($rule, 0, 2) == '@@') {
-                // ||开头表示前面还有路径
-                if (substr($rule, 2, 2) =='||') {
-                    //$rule_reg = preg_match("/^((http|https):\/\/)?([^\/]+)/i",substr($rule, 2), $matches);
-                    $host = substr($rule, 4);
-                    //preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
-                    if (isset($isget[$host])) {
-                        continue;
-                    }
-                    $isget[$host]=1;
-                    //$find_function_content.="DOMAIN,".$host.",DIRECT,force-remote-dns\n";
-                    $bypass_list .= $host."\n";
-                    continue;
-                // !开头相当于正则表达式^
-                } elseif (substr($rule, 2, 1) == '|') {
-                    preg_match("/(\d{1,3}\.){3}\d{1,3}/", substr($rule, 3), $matches);
-                    if (!isset($matches[0])) {
-                        continue;
-                    }
-
-                    $host = $matches[0];
-                    if ($host != "") {
-                        if (isset($isget[$host])) {
-                            continue;
+        $confs = [];
+        $proxy_confs = [];
+        // ss
+        $items = array_merge(URL::getAllItems($user, 0, 1), URL::getAllItems($user, 1, 1));
+        foreach ($items as $item) {
+            $sss = [
+                'name' => $item['remark'],
+                'type' => 'ss',
+                'server' => $item['address'],
+                'port' => $item['port'],
+                'cipher' => $item['method'],
+                'password' => $item['passwd'],
+            ];
+            if ($item['obfs'] != 'plain') {
+                switch ($item['obfs']) {
+                    case 'simple_obfs_http':
+                        $sss['plugin'] = 'obfs';
+                        $sss['plugin-opts']['mode'] = 'http';
+                        break;
+                    case 'simple_obfs_tls':
+                        $sss['plugin'] = 'obfs';
+                        $sss['plugin-opts']['mode'] = 'tls';
+                        break;
+                    case 'v2ray':
+                        $sss['plugin'] = 'v2ray-plugin';
+                        $sss['plugin-opts']['mode'] = 'websocket';
+                        if (strpos($item['obfs_param'], 'security=tls')) {
+                            $sss['plugin-opts']['tls'] = true;
                         }
-                        $isget[$host]=1;
-                        //$find_function_content.="IP-CIDR,".$host."/32,DIRECT,no-resolve \n";
-                        $bypass_list .= $host."/32\n";
-                        continue;
-                    } else {
-                        preg_match_all("~^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?~i", substr($rule, 3), $matches);
-
-                        if (!isset($matches[4][0])) {
-                            continue;
-                        }
-
-                        $host = $matches[4][0];
-                        if ($host != "") {
-                            if (isset($isget[$host])) {
-                                continue;
-                            }
-                            $isget[$host]=1;
-                            //$find_function_content.="DOMAIN-SUFFIX,".$host.",DIRECT,force-remote-dns\n";
-                            $bypass_list .= $host."\n";
-                            continue;
-                        }
-                    }
-                } elseif (substr($rule, 2, 1) == '.') {
-                    $host = substr($rule, 3);
-                    if ($host != "") {
-                        if (isset($isget[$host])) {
-                            continue;
-                        }
-                        $isget[$host]=1;
-                        //$find_function_content.="DOMAIN-SUFFIX,".$host.",DIRECT,force-remote-dns \n";
-                        $bypass_list .= $host."\n";
-                        continue;
-                    }
+                        $sss['plugin-opts']['host'] = $user->getMuMd5();
+                        $sss['plugin-opts']['path'] = $item['path'];
+                        break;
                 }
-            }
-
-            // ||开头表示前面还有路径
-            if (substr($rule, 0, 2) =='||') {
-                //$rule_reg = preg_match("/^((http|https):\/\/)?([^\/]+)/i",substr($rule, 2), $matches);
-                $host = substr($rule, 2);
-                //preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
-
-                if (strpos($host, "*")!==false) {
-                    $host = substr($host, strpos($host, "*")+1);
-                    if (strpos($host, ".")!==false) {
-                        $host = substr($host, strpos($host, ".")+1);
-                    }
-                    if (isset($isget[$host])) {
-                        continue;
-                    }
-                    $isget[$host]=1;
-                    //$find_function_content.="DOMAIN-KEYWORD,".$host.",Proxy,force-remote-dns\n";
-                    $proxy_list .= $host."\n";
-                    continue;
-                }
-
-                if (isset($isget[$host])) {
-                    continue;
-                }
-                $isget[$host]=1;
-                //$find_function_content.="DOMAIN,".$host.",Proxy,force-remote-dns\n";
-                $proxy_list .= $host."\n";
-            // !开头相当于正则表达式^
-            } elseif (substr($rule, 0, 1) == '|') {
-                preg_match("/(\d{1,3}\.){3}\d{1,3}/", substr($rule, 1), $matches);
-
-                if (!isset($matches[0])) {
-                    continue;
-                }
-
-                $host = $matches[0];
-                if ($host != "") {
-                    if (isset($isget[$host])) {
-                        continue;
-                    }
-                    $isget[$host]=1;
-
-                    preg_match("/(\d{1,3}\.){3}\d{1,3}\/\d{1,2}/", substr($rule, 1), $matches_ips);
-
-                    if (!isset($matches_ips[0])) {
-                        $proxy_list .= $host."/32\n";
+                if ($item['obfs'] != 'v2ray') {
+                    if ($item['obfs_param'] != '') {
+                        $sss['plugin-opts']['host'] = $item['obfs_param'];
+                    } elseif ($user->obfs_param != '') {
+                        $sss['plugin-opts']['host'] = $user->obfs_param;
                     } else {
-                        $host = $matches_ips[0];
-                        $proxy_list .= $host."\n";
-                    }
-
-                    //$find_function_content.="IP-CIDR,".$host."/32,Proxy,no-resolve \n";
-
-                    continue;
-                } else {
-                    preg_match_all("~^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?~i", substr($rule, 1), $matches);
-
-                    if (!isset($matches[4][0])) {
-                        continue;
-                    }
-
-                    $host = $matches[4][0];
-                    if (strpos($host, "*")!==false) {
-                        $host = substr($host, strpos($host, "*")+1);
-                        if (strpos($host, ".")!==false) {
-                            $host = substr($host, strpos($host, ".")+1);
-                        }
-                        if (isset($isget[$host])) {
-                            continue;
-                        }
-                        $isget[$host]=1;
-                        //$find_function_content.="DOMAIN-KEYWORD,".$host.",Proxy,force-remote-dns\n";
-                        $proxy_list .= $host."\n";
-                        continue;
-                    }
-
-                    if ($host != "") {
-                        if (isset($isget[$host])) {
-                            continue;
-                        }
-                        $isget[$host]=1;
-                        //$find_function_content.="DOMAIN-SUFFIX,".$host.",Proxy,force-remote-dns\n";
-                        $proxy_list .= $host."\n";
-                        continue;
-                    }
-                }
-            } else {
-                $host = substr($rule, 0);
-                if (strpos($host, "/")!==false) {
-                    $host = substr($host, 0, strpos($host, "/"));
-                }
-
-                if ($host != "") {
-                    if (isset($isget[$host])) {
-                        continue;
+                        $sss['plugin-opts']['host'] = 'wns.windows.com';
                     }
-                    $isget[$host]=1;
-                    //$find_function_content.="DOMAIN-KEYWORD,".$host.",PROXY,force-remote-dns \n";
-                    $proxy_list .= $host."\n";
-                    continue;
                 }
             }
-
-
-            $count = $count + 1;
-        }
-
-        $acl_content .= $find_function_content."\n".$proxy_list."\n".$bypass_list."\n".$outbound_block_list;
-        return $acl_content;
-    }
-	   
-    /**
-     * This is a php implementation of autoproxy2pac
-     */
-    private static function reg_encode($str)
-    {
-        $tmp_str = $str;
-        $tmp_str = str_replace('/', "\\/", $tmp_str);
-        $tmp_str = str_replace('.', "\\.", $tmp_str);
-        $tmp_str = str_replace(':', "\\:", $tmp_str);
-        $tmp_str = str_replace('%', "\\%", $tmp_str);
-        $tmp_str = str_replace('*', ".*", $tmp_str);
-        $tmp_str = str_replace('-', "\\-", $tmp_str);
-        $tmp_str = str_replace('&', "\\&", $tmp_str);
-        $tmp_str = str_replace('?', "\\?", $tmp_str);
-        $tmp_str = str_replace('+', "\\+", $tmp_str);
-
-        return $tmp_str;
-    }
-
-    private static function get_pac($proxy_type, $proxy_host, $proxy_port, $proxy_google, $defined)
-    {
-        $rulelist = base64_decode(file_get_contents("https://raw.githubusercontent.com/gfwlist/gfwlist/master/gfwlist.txt"))."\n".$defined;
-        $gfwlist = explode("\n", $rulelist);
-        if ($proxy_google == "true") {
-            $gfwlist[] = ".google.com";
+            $proxy_confs[] = $sss;
+            $confs[] = $sss;
         }
-
-        $count = 0;
-        $pac_content = '';
-        $find_function_content = 'function FindProxyForURL(url, host) { var PROXY = "'.$proxy_type.' '.$proxy_host.':'.$proxy_port.'; DIRECT"; var DEFAULT = "DIRECT";'."\n";
-        foreach ($gfwlist as $index=>$rule) {
-            if (empty($rule)) {
-                continue;
-            } elseif (substr($rule, 0, 1) == '!' || substr($rule, 0, 1) == '[') {
+        // v2
+        $items = URL::getAllVMessUrl($user, 1);
+        foreach ($items as $item) {
+            if (in_array($item['net'], array('kcp', 'http', 'quic'))) {
                 continue;
             }
-            $return_proxy = 'PROXY';
-        // @@开头表示默认是直接访问
-        if (substr($rule, 0, 2) == '@@') {
-            $rule = substr($rule, 2);
-            $return_proxy = "DEFAULT";
-        }
-
-        // ||开头表示前面还有路径
-        if (substr($rule, 0, 2) =='||') {
-            $rule_reg = "^[\\w\\-]+:\\/+(?!\\/)(?:[^\\/]+\\.)?".LinkController::reg_encode(substr($rule, 2));
-        // !开头相当于正则表达式^
-        } elseif (substr($rule, 0, 1) == '|') {
-            $rule_reg = "^" . LinkController::reg_encode(substr($rule, 1));
-        // 前后匹配的/表示精确匹配
-        } elseif (substr($rule, 0, 1) == '/' && substr($rule, -1) == '/') {
-            $rule_reg = substr($rule, 1, strlen($rule) - 2);
-        } else {
-            $rule_reg = LinkController::reg_encode($rule);
-        }
-        // 以|结尾,替换为$结尾
-        if (preg_match("/\|$/i", $rule_reg)) {
-            $rule_reg = substr($rule_reg, 0, strlen($rule_reg) - 1)."$";
-        }
-            $find_function_content.='if (/' . $rule_reg . '/i.test(url)) return '.$return_proxy.';'."\n";
-            $count = $count + 1;
-        }
-        $find_function_content.='return DEFAULT;'."}";
-        $pac_content.=$find_function_content;
-        return $pac_content;
-    }
-
-    public static function GetRouter($user, $is_mu = 0, $is_ss = 0)
-    {
-        $bash = '#!/bin/sh'."\n";
-        $bash .= 'export PATH=\'/opt/usr/sbin:/opt/usr/bin:/opt/sbin:/opt/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin\''."\n";
-        $bash .= 'export LD_LIBRARY_PATH=/lib:/opt/lib'."\n";
-        $bash .= 'nvram set ss_type='.($is_ss == 1 ? '0' : '1')."\n";
-
-        $count = 0;
-
-        $items = URL::getAllItems($user, $is_mu, $is_ss);
-        foreach($items as $item) {
-            if($is_ss == 0) {
-                $bash .= 'nvram set rt_ss_name_x'.$count.'="'.$item['remark']."\"\n";
-                $bash .= 'nvram set rt_ss_port_x'.$count.'='.$item['port']."\n";
-                $bash .= 'nvram set rt_ss_password_x'.$count.'="'.$item['passwd']."\"\n";
-                $bash .= 'nvram set rt_ss_server_x'.$count.'='.$item['address']."\n";
-                $bash .= 'nvram set rt_ss_usage_x'.$count.'="'."-o ".$item['obfs']." -g ".$item['obfs_param']." -O ".$item['protocol']." -G ".$item['protocol_param']."\"\n";
-                $bash .= 'nvram set rt_ss_method_x'.$count.'='.$item['method']."\n";
-                $count += 1;
-            }else{
-                $bash .= 'nvram set rt_ss_name_x'.$count.'="'.$item['remark']."\"\n";
-                $bash .= 'nvram set rt_ss_port_x'.$count.'='.$item['port']."\n";
-                $bash .= 'nvram set rt_ss_password_x'.$count.'="'.$item['passwd']."\"\n";
-                $bash .= 'nvram set rt_ss_server_x'.$count.'='.$item['address']."\n";
-                $bash .= 'nvram set rt_ss_usage_x'.$count.'=""'."\n";
-                $bash .= 'nvram set rt_ss_method_x'.$count.'='.$item['method']."\n";
-                $count += 1;
+            $v2rays = [
+                'name' => $item['ps'],
+                'type' => 'vmess',
+                'server' => $item['add'],
+                'port' => $item['port'],
+                'uuid' => $item['id'],
+                'alterId' => $item['aid'],
+                'cipher' => 'auto',
+            ];
+            if ($item['net'] == 'ws') {
+                $v2rays['network'] = 'ws';
+                $v2rays['ws-path'] = $item['path'];
+                if ($item['tls'] == 'tls') {
+                    $v2rays['tls'] = true;
+                }
+                if ($item['host'] != '') {
+                    $v2rays['ws-headers']['Host'] = $item['host'];
+                }
+            } elseif ($item['net'] == 'tls') {
+                $v2rays['tls'] = true;
             }
-        }
-
-        $bash .= "nvram set rt_ssnum_x=".$count."\n";
-
-        return $bash;
-    }
-
-    const V2RYA_MU = 2;
-    const SSD_MU = 3;
-    const CLASH_MU = 4;
-
-    public static function GetSSRSub($user, $mu = 0, $max = 0)
-    {
-        if ($mu==0||$mu==1) {
-            return Tools::base64_url_encode(URL::getAllUrl($user, $mu, 0, 1));
-        } 
-		elseif ($mu == LinkController::V2RYA_MU){
-            return Tools::base64_url_encode(URL::getAllVMessUrl($user));
-        }
-		elseif ($mu==LinkController::SSD_MU) {
-			return URL::getAllSSDUrl($user);
-		} elseif ($mu==LinkController::CLASH_MU) {
-            // Clash
-            $render = ConfRender::getTemplateRender();
-            $confs = URL::getClashInfo($user);
-
-            $render->assign('user', $user)->assign('confs', $confs)->assign('proxies', array_map(function ($conf) {
-                return $conf['name'];
-            }, $confs));
-
-            return $render->fetch('clash.tpl');
-        }
+            $proxy_confs[] = $v2rays;
+            $confs[] = $v2rays;
+        }
+        $render = ConfRender::getTemplateRender();
+        $render->assign('user', $user)
+            ->assign('confs', $confs)
+            ->assign(
+                'proxies',
+                array_map(
+                    static function ($conf) {
+                        return $conf['name'];
+                    },
+                    $proxy_confs
+                )
+            );
+        return $render->fetch('clash.tpl');
     }
 }

+ 80 - 47
app/Controllers/Mod_Mu/FuncController.php

@@ -10,15 +10,14 @@ use App\Models\Speedtest;
 use App\Models\Node;
 use App\Models\Auto;
 use App\Controllers\BaseController;
-use App\Utils\Tools;
 
 class FuncController extends BaseController
 {
     public function ping($request, $response, $args)
     {
         $res = [
-            "ret" => 1,
-            "data" => 'pong'
+            'ret' => 1,
+            'data' => 'pong'
         ];
         return $this->echoJson($response, $res);
     }
@@ -28,26 +27,60 @@ class FuncController extends BaseController
         $rules = DetectRule::all();
 
         $res = [
-            "ret" => 1,
-            "data" => $rules
+            'ret' => 1,
+            'data' => $rules
         ];
         return $this->echoJson($response, $res);
     }
 
+    public function get_dis_node_info($nodeid)
+    {
+        $node = Node::where('id', $nodeid)->first();
+        if ($node == null) {
+            return null;
+        }
+
+        return $node;
+    }
+
     public function get_relay_rules($request, $response, $args)
     {
         $params = $request->getQueryParams();
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        } else {
+            $node = Node::where('id', $node_id)->first();
+        }
         $rules = Relay::Where('source_node_id', $node_id)->get();
+        if (count($rules) > 0) {
+            if ($rules[0]['dist_node_id'] == -1) {
+                $server = null;
+            }
+            foreach ($rules as $rule) {
+                $dis = $this->get_dis_node_info($rule['dist_node_id']);
+                if ($dis != null) {
+                    $rule['source_node_sort'] = $node->sort;
+                    $rule['dist_node_sort'] = $dis->sort;
+                    $rule['dist_node_server'] = $dis->server;
+                } else {
+                    $rule['source_node_sort'] = $node->sort;
+                    $rule['dist_node_sort'] = null;
+                    $rule['dist_node_server'] = null;
+                }
+            }
+            $res = [
+                'ret' => 1,
+                'data' => $rules,
+            ];
+        } else {
+            $res = [
+                'ret' => 1,
+                'data' => array(),
+            ];
+        }
 
-        $res = [
-            "ret" => 1,
-            "data" => $rules
-        ];
         return $this->echoJson($response, $res);
     }
 
@@ -56,8 +89,8 @@ class FuncController extends BaseController
         $block_ips = BlockIp::Where('datetime', '>', time() - 60)->get();
 
         $res = [
-            "ret" => 1,
-            "data" => $block_ips
+            'ret' => 1,
+            'data' => $block_ips
         ];
         return $this->echoJson($response, $res);
     }
@@ -67,8 +100,8 @@ class FuncController extends BaseController
         $unblock_ips = UnblockIp::Where('datetime', '>', time() - 60)->get();
 
         $res = [
-            "ret" => 1,
-            "data" => $unblock_ips
+            'ret' => 1,
+            'data' => $unblock_ips
         ];
         return $this->echoJson($response, $res);
     }
@@ -79,14 +112,14 @@ class FuncController extends BaseController
 
         $data = $request->getParam('data');
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -110,8 +143,8 @@ class FuncController extends BaseController
         }
 
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }
@@ -122,14 +155,14 @@ class FuncController extends BaseController
 
         $data = $request->getParam('data');
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -156,8 +189,8 @@ class FuncController extends BaseController
         }
 
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }
@@ -167,14 +200,14 @@ class FuncController extends BaseController
         $params = $request->getQueryParams();
 
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -184,15 +217,15 @@ class FuncController extends BaseController
         $autos = array();
 
         foreach ($autos_raw as $auto_raw) {
-            $has_exec = Auto::where('sign', $node_id.'-'.$auto_raw->id)->where('type', '2')->first();
+            $has_exec = Auto::where('sign', $node_id . '-' . $auto_raw->id)->where('type', '2')->first();
             if ($has_exec == null) {
-                array_push($autos, $auto_raw);
+                $autos[] = $auto_raw;
             }
         }
 
         $res = [
-            "ret" => 1,
-            "data" => $autos,
+            'ret' => 1,
+            'data' => $autos,
         ];
         return $this->echoJson($response, $res);
     }
@@ -203,14 +236,14 @@ class FuncController extends BaseController
 
         $data = $request->getParam('data');
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -228,8 +261,8 @@ class FuncController extends BaseController
         }
 
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }

+ 29 - 29
app/Controllers/Mod_Mu/NodeController.php

@@ -4,7 +4,6 @@
 namespace App\Controllers\Mod_Mu;
 
 use App\Controllers\BaseController;
-use App\Models\NodeOnlineLog;
 use App\Models\NodeInfoLog;
 use App\Models\Node;
 
@@ -13,10 +12,10 @@ class NodeController extends BaseController
     public function info($request, $response, $args)
     {
         $node_id = $args['id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $load = $request->getParam('load');
         $uptime = $request->getParam('uptime');
         $log = new NodeInfoLog();
@@ -26,14 +25,14 @@ class NodeController extends BaseController
         $log->log_time = time();
         if (!$log->save()) {
             $res = [
-                "ret" => 0,
-                "data" => "update failed",
+                'ret' => 0,
+                'data' => 'update failed',
             ];
             return $this->echoJson($response, $res);
         }
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }
@@ -41,28 +40,28 @@ class NodeController extends BaseController
     public function get_info($request, $response, $args)
     {
         $node_id = $args['id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id = $node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
         $res = [
-            "ret" => 1,
-            "data" => [
-                "node_group" => $node->node_group,
-                "node_class" => $node->node_class,
-                "node_speedlimit" => $node->node_speedlimit,
-                "traffic_rate" => $node->traffic_rate,
-                "mu_only" => $node->mu_only,
-                "sort" => $node->sort,
-                "server" => $node->server,
-                "type" => "ss-panel-v3-mod_Uim"
+            'ret' => 1,
+            'data' => [
+                'node_group' => $node->node_group,
+                'node_class' => $node->node_class,
+                'node_speedlimit' => $node->node_speedlimit,
+                'traffic_rate' => $node->traffic_rate,
+                'mu_only' => $node->mu_only,
+                'sort' => $node->sort,
+                'server' => $node->server,
+                'type' => 'ss-panel-v3-mod_Uim'
             ],
         ];
         return $this->echoJson($response, $res);
@@ -71,14 +70,15 @@ class NodeController extends BaseController
     public function get_all_info($request, $response, $args)
     {
         $nodes = Node::where('node_ip', '<>', null)->where(
-            function ($query) {
-                $query->where("sort", "=", 0)
-                    ->orWhere("sort", "=", 10);
+            static function ($query) {
+                $query->where('sort', '=', 0)
+                    ->orWhere('sort', '=', 10)
+                    ->orWhere('sort', '=', 12);
             }
         )->get();
         $res = [
-            "ret" => 1,
-            "data" => $nodes
+            'ret' => 1,
+            'data' => $nodes
         ];
         return $this->echoJson($response, $res);
     }

+ 62 - 65
app/Controllers/Mod_Mu/UserController.php

@@ -19,75 +19,72 @@ class UserController extends BaseController
         $params = $request->getQueryParams();
 
         $node_id = $params['node_id'];
-		$node=new Node();
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
-		else{
-			$node = Node::where("id", "=", $node_id)->first();
-			if ($node == null) {
-				$res = [
-					"ret" => 0
-				];
-				return $this->echoJson($response, $res);
-			}
-		}
-        $node->node_heartbeat=time();
+        $node = new Node();
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        } else {
+            $node = Node::where('id', '=', $node_id)->first();
+            if ($node == null) {
+                $res = [
+                    'ret' => 0
+                ];
+                return $this->echoJson($response, $res);
+            }
+        }
+        $node->node_heartbeat = time();
         $node->save();
 
-        if ($node->node_group!=0) {
+        if ($node->node_group != 0) {
             $users_raw = User::where(
-                function ($query) use ($node){
+                static function ($query) use ($node) {
                     $query->where(
-                      function ($query1) use ($node){
-                          $query1->where("class", ">=", $node->node_class)
-                              ->where("node_group", "=", $node->node_group);
-                      }
+                        static function ($query1) use ($node) {
+                            $query1->where('class', '>=', $node->node_class)
+                                ->where('node_group', '=', $node->node_group);
+                        }
                     )->orwhere('is_admin', 1);
                 }
             )
-            ->where("enable", 1)->where("expire_in", ">", date("Y-m-d H:i:s"))->get();
+                ->where('enable', 1)->where('expire_in', '>', date('Y-m-d H:i:s'))->get();
         } else {
             $users_raw = User::where(
-                function ($query) use ($node){
+                static function ($query) use ($node) {
                     $query->where(
-                      function ($query1) use ($node){
-                          $query1->where("class", ">=", $node->node_class);
-                      }
+                        static function ($query1) use ($node) {
+                            $query1->where('class', '>=', $node->node_class);
+                        }
                     )->orwhere('is_admin', 1);
                 }
-            )->where("enable", 1)->where("expire_in", ">", date("Y-m-d H:i:s"))->get();
+            )->where('enable', 1)->where('expire_in', '>', date('Y-m-d H:i:s'))->get();
         }
-        if ($node->node_bandwidth_limit!=0) {
-            if ($node->node_bandwidth_limit < $node->node_bandwidth) {
-                $users=null;
+        if (($node->node_bandwidth_limit != 0) && $node->node_bandwidth_limit < $node->node_bandwidth) {
+            $users = null;
 
-                $res = [
-                    "ret" => 1,
-                    "data" => $users
-                ];
-                return $this->echoJson($response, $res);
-            }
+            $res = [
+                'ret' => 1,
+                'data' => $users
+            ];
+            return $this->echoJson($response, $res);
         }
 
         $users = array();
 
         $key_list = array('email', 'method', 'obfs', 'obfs_param', 'protocol', 'protocol_param',
-                'forbidden_ip', 'forbidden_port', 'node_speedlimit', 'disconnect_ip',
-                'is_multi_user', 'id', 'port', 'passwd', 'u', 'd');
+            'forbidden_ip', 'forbidden_port', 'node_speedlimit', 'disconnect_ip',
+            'is_multi_user', 'id', 'port', 'passwd', 'u', 'd');
 
         foreach ($users_raw as $user_raw) {
             if ($user_raw->transfer_enable > $user_raw->u + $user_raw->d) {
                 $user_raw = Tools::keyFilter($user_raw, $key_list);
                 $user_raw->uuid = $user_raw->getUuid();
-                array_push($users, $user_raw);
+                $users[] = $user_raw;
             }
         }
 
         $res = [
-            "ret" => 1,
-            "data" => $users
+            'ret' => 1,
+            'data' => $users
         ];
         return $this->echoJson($response, $res);
     }
@@ -100,15 +97,15 @@ class UserController extends BaseController
         $data = $request->getParam('data');
         $this_time_total_bandwidth = 0;
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
 
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -121,7 +118,7 @@ class UserController extends BaseController
 
                 $user = User::find($user_id);
 
-                if($user == NULL) {
+                if ($user == null) {
                     continue;
                 }
 
@@ -131,8 +128,8 @@ class UserController extends BaseController
                 $this_time_total_bandwidth += $u + $d;
                 if (!$user->save()) {
                     $res = [
-                        "ret" => 0,
-                        "data" => "update failed",
+                        'ret' => 0,
+                        'data' => 'update failed',
                     ];
                     return $this->echoJson($response, $res);
                 }
@@ -160,8 +157,8 @@ class UserController extends BaseController
         $online_log->save();
 
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }
@@ -172,15 +169,15 @@ class UserController extends BaseController
 
         $data = $request->getParam('data');
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
 
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -200,8 +197,8 @@ class UserController extends BaseController
         }
 
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }
@@ -212,15 +209,15 @@ class UserController extends BaseController
 
         $data = $request->getParam('data');
         $node_id = $params['node_id'];
-		if($node_id=='0'){
-			$node = Node::where("node_ip",$_SERVER["REMOTE_ADDR"])->first();
-			$node_id=$node->id;
-		}
+        if ($node_id == '0') {
+            $node = Node::where('node_ip', $_SERVER['REMOTE_ADDR'])->first();
+            $node_id = $node->id;
+        }
         $node = Node::find($node_id);
 
         if ($node == null) {
             $res = [
-                "ret" => 0
+                'ret' => 0
             ];
             return $this->echoJson($response, $res);
         }
@@ -241,8 +238,8 @@ class UserController extends BaseController
         }
 
         $res = [
-            "ret" => 1,
-            "data" => "ok",
+            'ret' => 1,
+            'data' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }

+ 9 - 9
app/Controllers/Mu/NodeController.php

@@ -19,18 +19,18 @@ class NodeController extends BaseController
         $log->log_time = time();
         if (!$log->save()) {
             $res = [
-                "ret" => 0,
-                "msg" => "update failed",
+                'ret' => 0,
+                'msg' => 'update failed',
             ];
             return $this->echoJson($response, $res);
         }
         $res = [
-            "ret" => 1,
-            "msg" => "ok",
+            'ret' => 1,
+            'msg' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }
-    
+
     public function info($request, $response, $args)
     {
         $node_id = $args['id'];
@@ -43,14 +43,14 @@ class NodeController extends BaseController
         $log->log_time = time();
         if (!$log->save()) {
             $res = [
-                "ret" => 0,
-                "msg" => "update failed",
+                'ret' => 0,
+                'msg' => 'update failed',
             ];
             return $this->echoJson($response, $res);
         }
         $res = [
-            "ret" => 1,
-            "msg" => "ok",
+            'ret' => 1,
+            'msg' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }

+ 37 - 39
app/Controllers/Mu/UserController.php

@@ -13,66 +13,64 @@ class UserController extends BaseController
     // User List
     public function index($request, $response, $args)
     {
-        $node = Node::where("node_ip", "=", $_SERVER["REMOTE_ADDR"])->where(
-            function ($query) {
-                $query->where("sort", "=", 0)
-                    ->orWhere("sort", "=", 10);
+        $node = Node::where('node_ip', '=', $_SERVER['REMOTE_ADDR'])->where(
+            static function ($query) {
+                $query->where('sort', '=', 0)
+                    ->orWhere('sort', '=', 10)->orWhere('sort', '=', 12);
             }
         )->first();
-        $node->node_heartbeat=time();
+        $node->node_heartbeat = time();
         $node->save();
 
-        if ($node->node_group!=0) {
+        if ($node->node_group != 0) {
             $users_raw = User::where(
-                function ($query) use ($node){
+                static function ($query) use ($node) {
                     $query->where(
-                      function ($query1) use ($node){
-                          $query1->where("class", ">=", $node->node_class)
-                              ->where("node_group", "=", $node->node_group);
-                      }
+                        static function ($query1) use ($node) {
+                            $query1->where('class', '>=', $node->node_class)
+                                ->where('node_group', '=', $node->node_group);
+                        }
                     )->orwhere('is_admin', 1);
                 }
             )
-            ->where("enable", 1)->where("expire_in", ">", date("Y-m-d H:i:s"))->get();
+                ->where('enable', 1)->where('expire_in', '>', date('Y-m-d H:i:s'))->get();
         } else {
             $users_raw = User::where(
-                function ($query) use ($node){
+                static function ($query) use ($node) {
                     $query->where(
-                      function ($query1) use ($node){
-                          $query1->where("class", ">=", $node->node_class);
-                      }
+                        static function ($query1) use ($node) {
+                            $query1->where('class', '>=', $node->node_class);
+                        }
                     )->orwhere('is_admin', 1);
                 }
-            )->where("enable", 1)->where("expire_in", ">", date("Y-m-d H:i:s"))->get();
+            )->where('enable', 1)->where('expire_in', '>', date('Y-m-d H:i:s'))->get();
         }
-        if ($node->node_bandwidth_limit!=0) {
-            if ($node->node_bandwidth_limit<$node->node_bandwidth) {
-                $users=null;
-
-                $res = [
-                    "ret" => 1,
-                    "data" => $users
-                ];
-                return $this->echoJson($response, $res);
-            }
+        if (($node->node_bandwidth_limit != 0) && $node->node_bandwidth_limit < $node->node_bandwidth) {
+            $users = null;
+
+            $res = [
+                'ret' => 1,
+                'data' => $users
+            ];
+            return $this->echoJson($response, $res);
         }
 
         $key_list = array('method', 'id', 'port', 'passwd', 'u', 'd', 'enable',
-                          't', 'transfer_enable', 'switch', 'email');
+            't', 'transfer_enable', 'switch', 'email');
 
         $users_output = array();
 
         foreach ($users_raw as $user_raw) {
             if ($user_raw->transfer_enable > $user_raw->u + $user_raw->d) {
                 $user_raw = Tools::keyFilter($user_raw, $key_list);
-                array_push($users_output, $user_raw);
+                $users_output[] = $user_raw;
             }
         }
 
         $res = [
-            "ret" => 1,
-            "msg" => "ok",
-            "data" => $users_output
+            'ret' => 1,
+            'msg' => 'ok',
+            'data' => $users_output
         ];
         return $this->echoJson($response, $res);
     }
@@ -86,7 +84,7 @@ class UserController extends BaseController
         $nodeId = $request->getParam('node_id');
         $node = Node::find($nodeId);
 
-        $node->node_bandwidth=$node->node_bandwidth+$d+$u;
+        $node->node_bandwidth = $node->node_bandwidth + $d + $u;
 
         $node->save();
 
@@ -95,12 +93,12 @@ class UserController extends BaseController
         $user = User::find($id);
 
         $user->t = time();
-        $user->u = $user->u + ($u * $rate);
-        $user->d = $user->d + ($d * $rate);
+        $user->u += ($u * $rate);
+        $user->d += ($d * $rate);
         if (!$user->save()) {
             $res = [
-                "ret" => 0,
-                "msg" => "update failed",
+                'ret' => 0,
+                'msg' => 'update failed',
             ];
             //return $this->echoJson($response, $res);
         }
@@ -116,8 +114,8 @@ class UserController extends BaseController
         $traffic->save();
 
         $res = [
-            "ret" => 1,
-            "msg" => "ok",
+            'ret' => 1,
+            'msg' => 'ok',
         ];
         return $this->echoJson($response, $res);
     }

+ 7 - 8
app/Controllers/PasswordController.php

@@ -12,7 +12,6 @@ use App\Utils\Hash;
  * @package App\Controllers
  * 密码重置
  */
-
 class PasswordController extends BaseController
 {
     public function reset()
@@ -22,7 +21,7 @@ class PasswordController extends BaseController
 
     public function handleReset($request, $response, $args)
     {
-        $email =  $request->getParam('email');
+        $email = $request->getParam('email');
         // check limit
 
         // send email
@@ -35,7 +34,7 @@ class PasswordController extends BaseController
         $rs['ret'] = 1;
         $rs['msg'] = '重置邮件已经发送,请检查邮箱.';
         if (Password::sendResetEmail($email)) {
-            $res['msg'] = "邮件发送失败,请联系网站管理员。";
+            $res['msg'] = '邮件发送失败,请联系网站管理员。';
         }
 
         return $response->getBody()->write(json_encode($rs));
@@ -50,23 +49,23 @@ class PasswordController extends BaseController
     public function handleToken($request, $response, $args)
     {
         $tokenStr = $args['token'];
-        $password =  $request->getParam('password');
-        $repasswd =  $request->getParam('repasswd');
+        $password = $request->getParam('password');
+        $repasswd = $request->getParam('repasswd');
 
         if ($password != $repasswd) {
             $res['ret'] = 0;
-            $res['msg'] = "两次输入不符合";
+            $res['msg'] = '两次输入不符合';
             return $response->getBody()->write(json_encode($res));
         }
 
         if (strlen($password) < 8) {
             $res['ret'] = 0;
-            $res['msg'] = "密码太短啦";
+            $res['msg'] = '密码太短啦';
             return $response->getBody()->write(json_encode($res));
         }
 
         // check token
-        $token = PasswordReset::where('token', $tokenStr)->first();
+        $token = PasswordReset::where('token', $tokenStr)->orderBy('id', 'desc')->first();
         if ($token == null || $token->expire_time < time()) {
             $rs['ret'] = 0;
             $rs['msg'] = '链接已经失效,请重新获取';

+ 0 - 104
app/Controllers/QuickPayFunction.php

@@ -1,104 +0,0 @@
-<?php
-
-namespace App\Controllers;
-
-class QuickPayFunction{
-    public function md5Verify($p1, $p2,$p3,$p4,$sign) {
-        $preStr = $p1 . $p2 . $p3 . $p4 . "yft";
-        $mySign = md5($preStr);
-        if ($mySign == $sign) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     * 建立请求,以表单HTML形式构造(默认)
-     * @param $para_temp 请求参数数组
-     *
-     */
-    public function buildRequestForm($para_temp,$ss_order_no,$pay_config) {
-        //待请求参数数组
-        $para = QuickPayFunction::buildRequestPara($para_temp);
-
-
-        $sHtml = "<form id='paysubmit' name='paysubmit' action='https://pay.anypay.me/pay/subOrder/zfb' accept-charset='utf-8' method='POST'>";
-        while (list ($key, $val) = each ($para)) {
-            $sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
-        }
-        if ($pay_config->pay_config["type"] == "aliPay"){
-            $sHtml .= "<input type='hidden' name='subject' value='余额充值'/>";
-        }else{
-            $sHtml .= "<input type='hidden' name='trade_no' value='".$ss_order_no."'/>";
-        }
-        //submit按钮控件请不要含有name属性
-        $sHtml = $sHtml."</form>";
-
-        $sHtml = $sHtml."<script>document.forms['paysubmit'].submit();</script>";
-
-        return $sHtml;
-    }
-    /**
-     * 生成要请求给云通付的参数数组
-     * @param $para_temp 请求前的参数数组
-     * @return 要请求的参数数组
-     */
-    static function buildRequestPara($para_temp) {
-        //除去待签名参数数组中的空值和签名参数
-        $para_filter = QuickPayFunction::paraFilter($para_temp);
-        //生成签名结果
-        $mysign = QuickPayFunction::buildRequestMysign($para_filter);
-
-        //签名结果与签名方式加入请求提交参数组中
-        $para_filter['sign'] = $mysign;
-
-        return $para_filter;
-    }
-    /**
-     * 除去数组中的空值和签名参数
-     * @param $para 签名参数组
-     * return 去掉空值与签名参数后的新签名参数组
-     */
-    static function paraFilter($para) {
-        $para_filter = array();
-        while (list ($key, $val) = each ($para)) {
-            if($key == "sign" || $val == "")continue;
-            else	$para_filter[$key] = $para[$key];
-        }
-        return $para_filter;
-    }
-    /**
-     * 生成签名结果
-     * @param $para_filter 要签名的数组
-     * return 签名结果字符串
-     */
-    static function buildRequestMysign($para_filter) {
-        //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
-        $prestr = QuickPayFunction::createLinkstring($para_filter);
-        $mysign = MD5($prestr);
-        return $mysign;
-    }
-    static function md5Sign($prestr) {
-        return md5($prestr);
-    }
-    /**
-     * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
-     * @param $para 需要拼接的数组
-     * return 拼接完成以后的字符串
-     */
-    static function createLinkstring($para) {
-        $arg  = "";
-        while (list ($key, $val) = each ($para)) {
-            $arg.=$key."=".$val."&";
-        }
-        //去掉最后一个&字符
-        $arg = substr($arg,0,count($arg)-2);
-
-        //如果存在转义字符,那么去掉转义
-        if(get_magic_quotes_gpc()){$arg = stripslashes($arg);}
-
-        return $arg;
-    }
-
-}

+ 182 - 103
app/Controllers/RelayController.php

@@ -6,9 +6,9 @@ use App\Models\Relay;
 use App\Models\Node;
 use App\Models\User;
 use App\Services\Auth;
-use App\Controllers\UserController;
 use App\Utils\Tools;
 use App\Services\Config;
+use ArrayObject;
 
 class RelayController extends UserController
 {
@@ -16,8 +16,8 @@ class RelayController extends UserController
     {
         $pageNum = 1;
         $user = Auth::getUser();
-        if (isset($request->getQueryParams()["page"])) {
-            $pageNum = $request->getQueryParams()["page"];
+        if (isset($request->getQueryParams()['page'])) {
+            $pageNum = $request->getQueryParams()['page'];
         }
         $logs = Relay::where('user_id', $user->id)->orwhere('user_id', 0)->paginate(15, ['*'], 'page', $pageNum);
         $logs->setPath('/user/relay');
@@ -27,19 +27,24 @@ class RelayController extends UserController
         //链路表部分
 
         $nodes = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                      ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where("sort", "=", 10)->where("node_class", "<=", $user->class)->orderBy('name')->get();
+        )->where('type', 1)->where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
+            }
+        )->where('node_class', '<=', $user->class)->orderBy('name')->get();
 
-        $pathset = new \ArrayObject();
+        $pathset = new ArrayObject();
 
         $relay_rules = Relay::where('user_id', $user->id)->orwhere('user_id', 0)->get();
-        $mu_nodes = Node::where('sort', 9)->where('node_class', '<=', $user->class)->where("type", "1")->where(
-            function ($query) use ($user) {
-                $query->where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+        $mu_nodes = Node::where('sort', 9)->where('node_class', '<=', $user->class)->where('type', '1')->where(
+            static function ($query) use ($user) {
+                $query->where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
         )->get();
 
@@ -81,11 +86,11 @@ class RelayController extends UserController
                     if ($single_path->end_node->id == $path->begin_node->id) {
                         $path->begin_node = $single_path->begin_node;
                         if ($path->begin_node->isNodeAccessable() == false) {
-                            $path->path = '<font color="#FF0000">'.$single_path->begin_node->name.'</font>'." → ".$path->path;
-                            $path->status = "阻断";
+                            $path->path = '<font color="#FF0000">' . $single_path->begin_node->name . '</font>' . ' → ' . $path->path;
+                            $path->status = '阻断';
                         } else {
-                            $path->path = $single_path->begin_node->name." → ".$path->path;
-                            $path->status = "通畅";
+                            $path->path = $single_path->begin_node->name . ' → ' . $path->path;
+                            $path->status = '通畅';
                         }
 
                         $pathset->offsetUnset($index);
@@ -95,10 +100,10 @@ class RelayController extends UserController
                     if ($path->end_node->id == $single_path->begin_node->id) {
                         $path->end_node = $single_path->end_node;
                         if ($single_path->end_node->isNodeAccessable() == false) {
-                            $path->path = $path->path." → ".'<font color="#FF0000">'.$single_path->end_node->name.'</font>';
-                            $path->status = "阻断";
+                            $path->path = $path->path . ' → ' . '<font color="#FF0000">' . $single_path->end_node->name . '</font>';
+                            $path->status = '阻断';
                         } else {
-                            $path->path = $path->path." → ".$single_path->end_node->name;
+                            $path->path = $path->path . ' → ' . $single_path->end_node->name;
                         }
 
                         $pathset->offsetUnset($index);
@@ -115,41 +120,62 @@ class RelayController extends UserController
     {
         $user = Auth::getUser();
         $source_nodes = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 10)->where("node_class", "<=", $user->class)->orderBy('name')->get();
-
+        )->where('type', 1)->where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
+            }
+        )->where('node_class', '<=', $user->class)->orderBy('name')->get();
+        foreach ($source_nodes as $node) {
+            if ($node->sort == 12) {
+                $node->name .= ' 正在使用V2ray后端 ';
+            }
+        }
         $dist_nodes = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
         )->where('type', 1)->where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', 0)
-                    ->orWhere('sort', 10);
+                    ->orWhere('sort', 10)
+                    ->orWhere('sort', 11)
+                    ->orWhere('sort', 12);
             }
-        )->where("node_class", "<=", $user->class)->orderBy('name')->get();
+        )->where('node_class', '<=', $user->class)->orderBy('name')->get();
 
         $ports_raw = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 9)->where("node_class", "<=", $user->class)->orderBy('name')->get();
+        )->where('type', 1)->where('sort', 9)->where('node_class', '<=', $user->class)->orderBy('name')->get();
 
         $ports = array();
         foreach ($ports_raw as $port_raw) {
             $mu_user = User::where('port', $port_raw->server)->first();
             if ($mu_user->is_multi_user == 1) {
-                array_push($ports, $port_raw->server);
+                $ports[] = $port_raw->server;
             }
         }
 
-        array_push($ports, $user->port);
+        foreach ($dist_nodes as $node) {
+            if ($node->sort == 11 || $node->sort == 12) {
+                $node_explode = Tools::ssv2Array($node->server);
+                $ports[] = $node_explode['port'];
+                $node->name = $node->name . ' 如果是V2ray后端 请设置成 ' . $node_explode['port'];
+            } else {
+                $node->name = $node->name . ' 如果是V2ray后端 请设置成 ' . $user->port;
+            }
+        }
 
+        $ports[] = $user->port;
+        $ports = array_unique($ports);
         return $this->view()->assign('source_nodes', $source_nodes)->assign('dist_nodes', $dist_nodes)->assign('ports', $ports)->display('user/relay/add.tpl');
     }
 
@@ -163,51 +189,72 @@ class RelayController extends UserController
         $priority = $request->getParam('priority');
 
         $source_node = Node::where('id', $source_node_id)->where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
+            }
+        )->where('type', 1)->where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
             }
-        )->where('type', 1)->where('sort', 10)->where("node_class", "<=", $user->class)->first();
+        )->where('node_class', '<=', $user->class)->first();
         if ($source_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "美国的华莱士";
+            $rs['msg'] = '起源节点错误';
             return $response->getBody()->write(json_encode($rs));
         }
-
+        if ($source_node->sort == 12) {
+            $rules = Relay::Where('source_node_id', $source_node_id)->get();
+            foreach ($rules as $rule) {
+                if ($rule['user_id'] == 0 || $rule['user_id'] = $user->id) {
+                    $rs['ret'] = 0;
+                    $rs['msg'] = 'v2ray中转一个起点一个rule';
+                    return $response->getBody()->write(json_encode($rs));
+                }
+            }
+        }
         $dist_node = Node::where('id', $dist_node_id)->where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
         )->where('type', 1)->where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', 0)
-                    ->orWhere('sort', 10);
+                    ->orWhere('sort', 10)
+                    ->orWhere('sort', 11)
+                    ->orWhere('sort', 12);
             }
-        )->where("node_class", "<=", $user->class)->first();
+        )->where('node_class', '<=', $user->class)->first();
 
         if ($dist_node_id == -1) {
             $dist_node = new Node();
             $dist_node->id = -1;
-            $dist_node->node_ip = "0.0.0.0";
+            $dist_node->node_ip = '0.0.0.0';
             $dist_node->sort = 10;
         }
 
         if ($dist_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "不知道比你们高到哪里去了";
+            $rs['msg'] = '目标节点错误';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $port_raw = Node::where('server', $port)->where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 9)->where("node_class", "<=", $user->class)->first();
-        if ($port_raw == null && $port != $user->port) {
+        )->where('type', 1)->where('sort', 9)->where('node_class', '<=', $user->class)->first();
+        $v2ray_port_raw = '';
+        if ($dist_node->sort == 12 || $dist_node->sort == 11) {
+            $node_explode = Tools::ssv2Array($dist_node->server);
+            $v2ray_port_raw = $node_explode['port'];
+        }
+        if (($port_raw == null && $port != $user->port && $v2ray_port_raw == '') || ($v2ray_port_raw != '' && ($port != $user->port && $port != $v2ray_port_raw))) {
             $rs['ret'] = 0;
-            $rs['msg'] = "我和他谈笑风生";
+            $rs['msg'] = '端口错误';
             return $response->getBody()->write(json_encode($rs));
         }
 
@@ -232,21 +279,21 @@ class RelayController extends UserController
         $maybe_rule_id = Tools::has_conflict_rule($rule, $ruleset, 0, $rule->source_node_id);
         if ($maybe_rule_id != 0) {
             $rs['ret'] = 0;
-            $rs['msg'] = "您即将添加的规则与规则 ID:".$maybe_rule_id." 冲突!";
+            $rs['msg'] = '您即将添加的规则与规则 ID:' . $maybe_rule_id . ' 冲突!';
             if ($maybe_rule_id == -1) {
-                $rs['msg'] = "您即将添加的规则可能会造成冲突!";
+                $rs['msg'] = '您即将添加的规则可能会造成冲突!';
             }
             return $response->getBody()->write(json_encode($rs));
         }
 
         if (!$rule->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "添加失败";
+            $rs['msg'] = '添加失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $rs['ret'] = 1;
-        $rs['msg'] = "添加成功";
+        $rs['msg'] = '添加成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -263,41 +310,61 @@ class RelayController extends UserController
 
         $user = Auth::getUser();
         $source_nodes = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 10)->where("node_class", "<=", $user->class)->orderBy('name')->get();
-
+        )->where('type', 1)->where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
+            }
+        )->where('node_class', '<=', $user->class)->orderBy('name')->get();
+        foreach ($source_nodes as $node) {
+            if ($node->sort == 12) {
+                $node->name .= ' 正在使用V2ray后端 ';
+            }
+        }
         $dist_nodes = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
         )->where('type', 1)->where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', 0)
-                    ->orWhere('sort', 10);
+                    ->orWhere('sort', 10)
+                    ->orWhere('sort', 11)
+                    ->orWhere('sort', 12);
             }
-        )->where("node_class", "<=", $user->class)->orderBy('name')->get();
+        )->where('node_class', '<=', $user->class)->orderBy('name')->get();
 
         $ports_raw = Node::where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 9)->where("node_class", "<=", $user->class)->orderBy('name')->get();
+        )->where('type', 1)->where('sort', 9)->where('node_class', '<=', $user->class)->orderBy('name')->get();
 
         $ports = array();
         foreach ($ports_raw as $port_raw) {
             $mu_user = User::where('port', $port_raw->server)->first();
             if ($mu_user->is_multi_user == 1) {
-                array_push($ports, $port_raw->server);
+                $ports[] = $port_raw->server;
+            }
+        }
+        foreach ($dist_nodes as $node) {
+            if ($node->sort == 11 || $node->sort == 12) {
+                $node_explode = Tools::ssv2Array($node->server);
+                $ports[] = $node_explode['port'];
+                $node->name = $node->name . ' 如果是V2ray后端 请设置成: ' . $node_explode['port'];
+            } else {
+                $node->name = $node->name . ' 如果是V2ray后端 请设置成 ' . $user->port;
             }
         }
 
-        array_push($ports, $user->port);
-
+        $ports[] = $user->port;
+        $ports = array_unique($ports);
         return $this->view()->assign('rule', $rule)->assign('source_nodes', $source_nodes)->assign('dist_nodes', $dist_nodes)->assign('ports', $ports)->display('user/relay/edit.tpl');
     }
 
@@ -317,51 +384,63 @@ class RelayController extends UserController
         $priority = $request->getParam('priority');
 
         $source_node = Node::where('id', $source_node_id)->where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 10)->where("node_class", "<=", $user->class)->first();
+        )->where('type', 1)->where(
+            static function ($query) {
+                $query->Where('sort', 10)
+                    ->orWhere('sort', 12);
+            }
+        )->where('node_class', '<=', $user->class)->first();
         if ($source_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "我告诉你们我是身经百战了";
+            $rs['msg'] = '起源节点错误';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $dist_node = Node::where('id', $dist_node_id)->where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
         )->where('type', 1)->where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', 0)
-                    ->orWhere('sort', 10);
+                    ->orWhere('sort', 10)
+                    ->orWhere('sort', 11)
+                    ->orWhere('sort', 12);
             }
-        )->where("node_class", "<=", $user->class)->first();
+        )->where('node_class', '<=', $user->class)->first();
 
         if ($dist_node_id == -1) {
             $dist_node = new Node();
             $dist_node->id = -1;
-            $dist_node->node_ip = "0.0.0.0";
+            $dist_node->node_ip = '0.0.0.0';
             $dist_node->sort = 10;
         }
 
         if ($dist_node == null) {
             $rs['ret'] = 0;
-            $rs['msg'] = "见得多了";
+            $rs['msg'] = '目标节点错误';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $port_raw = Node::where('server', $port)->where(
-            function ($query) use ($user) {
-                $query->Where("node_group", "=", $user->node_group)
-                    ->orWhere("node_group", "=", 0);
+            static function ($query) use ($user) {
+                $query->Where('node_group', '=', $user->node_group)
+                    ->orWhere('node_group', '=', 0);
             }
-        )->where('type', 1)->where('sort', 9)->where("node_class", "<=", $user->class)->first();
-        if ($port_raw == null && $port != $user->port) {
+        )->where('type', 1)->where('sort', 9)->where('node_class', '<=', $user->class)->first();
+        $v2ray_port_raw = '';
+        if ($dist_node->sort == 12 || $dist_node->sort == 11) {
+            $node_explode = Tools::ssv2Array($dist_node->server);
+            $v2ray_port_raw = $node_explode['port'];
+        }
+        if (($port_raw == null && $port != $user->port && $v2ray_port_raw == '') || ($v2ray_port_raw != '' && ($port != $user->port && $port != $v2ray_port_raw))) {
             $rs['ret'] = 0;
-            $rs['msg'] = "西方的哪个国家我没去过";
+            $rs['msg'] = '端口错误';
             return $response->getBody()->write(json_encode($rs));
         }
 
@@ -385,21 +464,21 @@ class RelayController extends UserController
         $maybe_rule_id = Tools::has_conflict_rule($rule, $ruleset, $rule->id, $rule->source_node_id);
         if ($maybe_rule_id != 0) {
             $rs['ret'] = 0;
-            $rs['msg'] = "您即将添加的规则与规则 ID:".$maybe_rule_id." 冲突!";
+            $rs['msg'] = '您即将添加的规则与规则 ID:' . $maybe_rule_id . ' 冲突!';
             if ($maybe_rule_id == -1) {
-                $rs['msg'] = "您即将添加的规则可能会造成冲突!";
+                $rs['msg'] = '您即将添加的规则可能会造成冲突!';
             }
             return $response->getBody()->write(json_encode($rs));
         }
 
         if (!$rule->save()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "修改失败";
+            $rs['msg'] = '修改失败';
             return $response->getBody()->write(json_encode($rs));
         }
 
         $rs['ret'] = 1;
-        $rs['msg'] = "修改成功";
+        $rs['msg'] = '修改成功';
         return $response->getBody()->write(json_encode($rs));
     }
 
@@ -416,11 +495,11 @@ class RelayController extends UserController
 
         if (!$rule->delete()) {
             $rs['ret'] = 0;
-            $rs['msg'] = "删除失败";
+            $rs['msg'] = '删除失败';
             return $response->getBody()->write(json_encode($rs));
         }
         $rs['ret'] = 1;
-        $rs['msg'] = "删除成功";
+        $rs['msg'] = '删除成功';
         return $response->getBody()->write(json_encode($rs));
     }
 }

+ 1 - 1
app/Controllers/ResController.php

@@ -10,7 +10,7 @@ class ResController
     public function captcha($request, $response, $args)
     {
         $id = $args['id'];
-        $builder = new CaptchaBuilder;
+        $builder = new CaptchaBuilder();
         $builder->build();
         //$builder->getPhrase();
         $newResponse = $response->withHeader('Content-type', ' image/jpeg');//->getBody()->write($builder->output());

File diff suppressed because it is too large
+ 225 - 283
app/Controllers/UserController.php


+ 440 - 0
app/Controllers/VueController.php

@@ -0,0 +1,440 @@
+<?php
+
+namespace App\Controllers;
+
+use App\Models\InviteCode;
+use App\Models\User;
+use App\Models\Code;
+use App\Models\Payback;
+use App\Models\Ann;
+use App\Models\Shop;
+use App\Services\Auth;
+use App\Services\Config;
+use App\Utils\AliPay;
+use App\Utils\Tools;
+use App\Utils\TelegramSessionManager;
+use App\Utils\Spay_tool;
+use App\Utils\Geetest;
+
+use App\Utils\URL;
+use App\Models\Node;
+use App\Models\Relay;
+
+class VueController extends BaseController
+{
+    public function getGlobalConfig($request, $response, $args)
+    {
+        $GtSdk = null;
+        $recaptcha_sitekey = null;
+        $user = $this->user;
+        if (Config::get('captcha_provider') != '') {
+            switch (Config::get('captcha_provider')) {
+                case 'recaptcha':
+                    $recaptcha_sitekey = Config::get('recaptcha_sitekey');
+                    break;
+                case 'geetest':
+                    $uid = time() . random_int(1, 10000);
+                    $GtSdk = Geetest::get($uid);
+                    break;
+            }
+        }
+
+        if (Config::get('enable_telegram') == 'true') {
+            $login_text = TelegramSessionManager::add_login_session();
+            $login = explode('|', $login_text);
+            $login_token = $login[0];
+            $login_number = $login[1];
+        } else {
+            $login_token = '';
+            $login_number = '';
+        }
+
+        $res['globalConfig'] = array(
+            'geetest_html' => $GtSdk,
+            'login_token' => $login_token,
+            'login_number' => $login_number,
+            'telegram_bot' => Config::get('telegram_bot'),
+            'enable_logincaptcha' => Config::get('enable_login_captcha'),
+            'enable_regcaptcha' => Config::get('enable_reg_captcha'),
+            'enable_checkin_captcha' => Config::get('enable_checkin_captcha'),
+            'base_url' => Config::get('baseUrl'),
+            'recaptcha_sitekey' => $recaptcha_sitekey,
+            'captcha_provider' => Config::get('captcha_provider'),
+            'jump_delay' => Config::get('jump_delay'),
+            'register_mode' => Config::get('register_mode'),
+            'enable_email_verify' => Config::get('enable_email_verify'),
+            'appName' => Config::get('appName'),
+            'dateY' => date('Y'),
+            'isLogin' => $user->isLogin,
+            'enable_telegram' => Config::get('enable_telegram'),
+            'enable_mylivechat' => Config::get('enable_mylivechat'),
+            'payment_type' => Config::get('payment_system'),
+        );
+
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function vuelogout($request, $response, $args)
+    {
+        Auth::logout();
+        $res['ret'] = 1;
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getUserInfo($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $pre_user = URL::cloneUser($user);
+        $user->ssr_url_all = URL::getAllUrl($pre_user, 0, 0);
+        $user->ssr_url_all_mu = URL::getAllUrl($pre_user, 1, 0);
+        $user->ss_url_all = URL::getAllUrl($pre_user, 0, 2);
+        $ssinfo = URL::getSSConnectInfo($pre_user);
+        $user->ssd_url_all = URL::getAllSSDUrl($ssinfo);
+        $user->isAbleToCheckin = $user->isAbleToCheckin();
+        $ssr_sub_token = LinkController::GenerateSSRSubCode($this->user->id, 0);
+        $GtSdk = null;
+        $recaptcha_sitekey = null;
+        if (Config::get('captcha_provider') != '') {
+            switch (Config::get('captcha_provider')) {
+                case 'recaptcha':
+                    $recaptcha_sitekey = Config::get('recaptcha_sitekey');
+                    break;
+                case 'geetest':
+                    $uid = time() . random_int(1, 10000);
+                    $GtSdk = Geetest::get($uid);
+                    break;
+            }
+        }
+        $Ann = Ann::orderBy('date', 'desc')->first();
+        $display_ios_class = Config::get('display_ios_class');
+        $ios_account = Config::get('ios_account');
+        $ios_password = Config::get('ios_password');
+        $mergeSub = Config::get('mergeSub');
+        $subUrl = Config::get('subUrl');
+        $baseUrl = Config::get('baseUrl');
+        $user['online_ip_count'] = $user->online_ip_count();
+
+        $res['info'] = array(
+            'user' => $user,
+            'ssrSubToken' => $ssr_sub_token,
+            'displayIosClass' => $display_ios_class,
+            'iosAccount' => $ios_account,
+            'iosPassword' => $ios_password,
+            'mergeSub' => $mergeSub,
+            'subUrl' => $subUrl,
+            'baseUrl' => $baseUrl,
+            'ann' => $Ann,
+            'recaptchaSitekey' => $recaptcha_sitekey,
+            'GtSdk' => $GtSdk,
+        );
+
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getUserInviteInfo($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $code = InviteCode::where('user_id', $user->id)->first();
+        if ($code == null) {
+            $user->addInviteCode();
+            $code = InviteCode::where('user_id', $user->id)->first();
+        }
+
+        $pageNum = $request->getParam('current');
+
+        $paybacks = Payback::where('ref_by', $user->id)->orderBy('id', 'desc')->paginate(15, ['*'], 'page', $pageNum);
+        if (!$paybacks_sum = Payback::where('ref_by', $user->id)->sum('ref_get')) {
+            $paybacks_sum = 0;
+        }
+        $paybacks->setPath('/#/user/panel');
+
+        $res['inviteInfo'] = array(
+            'code' => $code,
+            'paybacks' => $paybacks,
+            'paybacks_sum' => $paybacks_sum,
+            'invite_num' => $user->invite_num,
+            'invitePrice' => Config::get('invite_price'),
+            'customPrice' => Config::get('custom_invite_price'),
+            'invite_gift' => Config::get('invite_gift'),
+            'invite_get_money' => Config::get('invite_get_money'),
+            'code_payback' => Config::get('code_payback'),
+        );
+
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getUserShops($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $shops = Shop::where('status', 1)->orderBy('name')->get();
+
+        $res['arr'] = array(
+            'shops' => $shops,
+        );
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getAllResourse($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $res['resourse'] = array(
+            'money' => $user->money,
+            'class' => $user->class,
+            'class_expire' => $user->class_expire,
+            'expire_in' => $user->expire_in,
+            'online_ip_count' => $user->online_ip_count(),
+            'node_speedlimit' => $user->node_speedlimit,
+            'node_connector' => $user->node_connector,
+        );
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getNewSubToken($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $user->clean_link();
+        $ssr_sub_token = LinkController::GenerateSSRSubCode($this->user->id, 0);
+
+        $res['arr'] = array(
+            'ssr_sub_token' => $ssr_sub_token,
+        );
+
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getNewInviteCode($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $user->clear_inviteCodes();
+        $code = InviteCode::where('user_id', $this->user->id)->first();
+        if ($code == null) {
+            $this->user->addInviteCode();
+            $code = InviteCode::where('user_id', $this->user->id)->first();
+        }
+
+        $res['arr'] = array(
+            'code' => $code,
+        );
+
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getTransfer($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $res['arr'] = array(
+            'todayUsedTraffic' => $user->TodayusedTraffic(),
+            'lastUsedTraffic' => $user->LastusedTraffic(),
+            'unUsedTraffic' => $user->unusedTraffic(),
+        );
+
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getCaptcha($request, $response, $args)
+    {
+        $GtSdk = null;
+        $recaptcha_sitekey = null;
+        if (Config::get('captcha_provider') != '') {
+            switch (Config::get('captcha_provider')) {
+                case 'recaptcha':
+                    $recaptcha_sitekey = Config::get('recaptcha_sitekey');
+                    $res['recaptchaKey'] = $recaptcha_sitekey;
+                    break;
+                case 'geetest':
+                    $uid = time() . random_int(1, 10000);
+                    $GtSdk = Geetest::get($uid);
+                    $res['GtSdk'] = $GtSdk;
+                    break;
+            }
+        }
+
+        $res['respon'] = 1;
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getChargeLog($request, $response, $args)
+    {
+        $user = $this->user;
+
+        if (!$user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $pageNum = $request->getParam('current');
+
+        $codes = Code::where('type', '<>', '-2')->where('userid', '=', $user->id)->orderBy('id', 'desc')->paginate(15, ['*'], 'page', $pageNum);
+        $codes->setPath('/#/user/code');
+
+        $res['codes'] = $codes;
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+
+    public function getNodeList($request, $response, $args)
+    {
+        $user = Auth::getUser();
+
+        if (!$this->user->isLogin) {
+            $res['ret'] = -1;
+            return $response->getBody()->write(json_encode($res));
+        }
+
+        $nodes = Node::where('type', 1)->orderBy('node_class')->orderBy('name')->get();
+        $relay_rules = Relay::where('user_id', $this->user->id)->orwhere('user_id', 0)->orderBy('id', 'asc')->get();
+        if (!Tools::is_protocol_relay($user)) {
+            $relay_rules = array();
+        }
+
+        $array_nodes = array();
+        $nodes_muport = array();
+
+        foreach ($nodes as $node) {
+            if ($node->node_group != $user->node_group && $node->node_group != 0) {
+                continue;
+            }
+            if ($node->sort == 9) {
+                $mu_user = User::where('port', '=', $node->server)->first();
+                $mu_user->obfs_param = $this->user->getMuMd5();
+                $nodes_muport[] = array('server' => $node, 'user' => $mu_user);
+                continue;
+            }
+            $array_node = array();
+
+            $array_node['id'] = $node->id;
+            $array_node['class'] = $node->node_class;
+            $array_node['name'] = $node->name;
+            if ($this->user->class < $node->node_class) {
+                $array_node['server'] = '***.***.***.***';
+            } elseif ($node->sort == 13) {
+                $server = Tools::ssv2Array($node->server);
+                $array_node['server'] = $server['add'];
+            } else {
+                $array_node['server'] = $node->server;
+            }
+
+            $array_node['sort'] = $node->sort;
+            $array_node['info'] = $node->info;
+            $array_node['mu_only'] = $node->mu_only;
+            $array_node['group'] = $node->node_group;
+
+            $array_node['raw_node'] = $node;
+            $regex = Config::get('flag_regex');
+            $matches = array();
+            preg_match($regex, $node->name, $matches);
+            if (isset($matches[0])) {
+                $array_node['flag'] = $matches[0] . '.png';
+            } else {
+                $array_node['flag'] = 'unknown.png';
+            }
+
+            $node_online = $node->isNodeOnline();
+            if ($node_online === null) {
+                $array_node['online'] = 0;
+            } elseif ($node_online === true) {
+                $array_node['online'] = 1;
+            } elseif ($node_online === false) {
+                $array_node['online'] = -1;
+            }
+
+            if (in_array($node->sort, array(0, 7, 8, 10, 11, 12, 13))) {
+                $array_node['online_user'] = $node->getOnlineUserCount();
+            } else {
+                $array_node['online_user'] = -1;
+            }
+
+            $nodeLoad = $node->getNodeLoad();
+            if (isset($nodeLoad[0]['load'])) {
+                $array_node['latest_load'] = (explode(' ', $nodeLoad[0]['load']))[0] * 100;
+            } else {
+                $array_node['latest_load'] = -1;
+            }
+
+            $array_node['traffic_used'] = (int)Tools::flowToGB($node->node_bandwidth);
+            $array_node['traffic_limit'] = (int)Tools::flowToGB($node->node_bandwidth_limit);
+            if ($node->node_speedlimit == 0.0) {
+                $array_node['bandwidth'] = 0;
+            } elseif ($node->node_speedlimit >= 1024.00) {
+                $array_node['bandwidth'] = round($node->node_speedlimit / 1024.00, 1) . 'Gbps';
+            } else {
+                $array_node['bandwidth'] = $node->node_speedlimit . 'Mbps';
+            }
+
+            $array_node['traffic_rate'] = $node->traffic_rate;
+            $array_node['status'] = $node->status;
+
+            $array_nodes[] = $array_node;
+        }
+
+        $res['nodeinfo'] = array(
+            'nodes' => $array_nodes,
+            'nodes_muport' => $nodes_muport,
+            'relay_rules' => $relay_rules,
+            'user' => $user,
+            'tools' => new Tools(),
+        );
+        $res['ret'] = 1;
+
+        return $response->getBody()->write(json_encode($res));
+    }
+}

+ 1 - 2
app/Middleware/Admin.php

@@ -5,7 +5,6 @@ namespace App\Middleware;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use App\Services\Auth as AuthService;
-use App\Services\Config;
 
 class Admin
 {
@@ -22,7 +21,7 @@ class Admin
             $newResponse = $response->withStatus(302)->withHeader('Location', '/user');
             return $newResponse;
         }
-        
+
         $response = $next($request, $response);
         return $response;
     }

+ 5 - 5
app/Middleware/Api.php

@@ -12,23 +12,23 @@ class Api
     public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $next)
     {
         $accessToken = Helper::getTokenFromReq($request);
-        if ($accessToken==null) {
+        if ($accessToken == null) {
             $res['ret'] = 0;
-            $res['msg'] = "token is null";
+            $res['msg'] = 'token is null';
             $response->getBody()->write(json_encode($res));
             return $response;
         }
         $storage = Factory::createTokenStorage();
         $token = $storage->get($accessToken);
-        if ($token==null) {
+        if ($token == null) {
             $res['ret'] = 0;
-            $res['msg'] = "token is null";
+            $res['msg'] = 'token is null';
             $response->getBody()->write(json_encode($res));
             return $response;
         }
         if ($token->expireTime < time()) {
             $res['ret'] = 0;
-            $res['msg'] = "token is expire";
+            $res['msg'] = 'token is expire';
             $response->getBody()->write(json_encode($res));
             return $response;
         }

+ 2 - 4
app/Middleware/Auth.php

@@ -5,9 +5,6 @@ namespace App\Middleware;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
 use App\Services\Auth as AuthService;
-use App\Services\Config;
-
-use App\Services\Jwt;
 
 class Auth
 {
@@ -18,7 +15,8 @@ class Auth
             $newResponse = $response->withStatus(302)->withHeader('Location', '/auth/login');
             return $newResponse;
         }
-        if ($user->enable == 0 && $_SERVER["REQUEST_URI"] != "/user/disable") {
+        $enablePages = array('/user/disable', '/user/backtoadmin', '/user/logout');
+        if ($user->enable == 0 && !in_array($_SERVER['REQUEST_URI'], $enablePages)) {
             $newResponse = $response->withStatus(302)->withHeader('Location', '/user/disable');
             return $newResponse;
         }

+ 1 - 2
app/Middleware/Guest.php

@@ -12,8 +12,7 @@ class Guest
     {
         $user = AuthService::getUser();
         if ($user->isLogin) {
-            $newResponse = $response->withStatus(302)->withHeader('Location', '/user');
-            return $newResponse;
+            return $response->withStatus(302)->withHeader('Location', '/user');
         }
         $response = $next($request, $response);
         return $response;

+ 10 - 11
app/Middleware/Mod_Mu.php

@@ -6,7 +6,6 @@ namespace App\Middleware;
 use App\Services\Config;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
-use App\Services\Factory;
 use App\Utils\Helper;
 use App\Models\Node;
 
@@ -17,31 +16,31 @@ class Mod_Mu
         $key = Helper::getMuKeyFromReq($request);
         if ($key == null) {
             $res['ret'] = 0;
-            $res['data'] = "key is null";
+            $res['data'] = 'key is null';
             $response->getBody()->write(json_encode($res));
             return $response;
         }
 
-        $auth=false;
-        $keyset=explode(",", Config::get('muKey'));
+        $auth = false;
+        $keyset = explode(',', Config::get('muKey'));
         foreach ($keyset as $sinkey) {
-            if ($key==$sinkey) {
-                $auth=true;
+            if ($key == $sinkey) {
+                $auth = true;
                 break;
             }
         }
 
-        if ($auth==false) {
+        if ($auth == false) {
             $res['ret'] = 0;
-            $res['data'] = "token or source is invalid";
+            $res['data'] = 'token or source is invalid';
             $response->getBody()->write(json_encode($res));
             return $response;
         }
 
-        $node = Node::where("node_ip", "LIKE", $_SERVER["REMOTE_ADDR"].'%')->first();
-        if ($node==null && $_SERVER["REMOTE_ADDR"] != '127.0.0.1') {
+        $node = Node::where('node_ip', 'LIKE', $_SERVER['REMOTE_ADDR'] . '%')->first();
+        if ($node == null && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
             $res['ret'] = 0;
-            $res['data'] = "token or source is invalid, Your ip address is ". $_SERVER["REMOTE_ADDR"];
+            $res['data'] = 'token or source is invalid, Your ip address is ' . $_SERVER['REMOTE_ADDR'];
             $response->getBody()->write(json_encode($res));
             return $response;
         }

+ 10 - 11
app/Middleware/Mu.php

@@ -6,7 +6,6 @@ namespace App\Middleware;
 use App\Services\Config;
 use Psr\Http\Message\ServerRequestInterface;
 use Psr\Http\Message\ResponseInterface;
-use App\Services\Factory;
 use App\Utils\Helper;
 use App\Models\Node;
 
@@ -17,31 +16,31 @@ class Mu
         $key = Helper::getMuKeyFromReq($request);
         if ($key == null) {
             $res['ret'] = 0;
-            $res['msg'] = "key is null";
+            $res['msg'] = 'key is null';
             $response->getBody()->write(json_encode($res));
             return $response;
         }
 
-        $auth=false;
-        $keyset=explode(",", Config::get('muKey'));
+        $auth = false;
+        $keyset = explode(',', Config::get('muKey'));
         foreach ($keyset as $sinkey) {
-            if ($key==$sinkey) {
-                $auth=true;
+            if ($key == $sinkey) {
+                $auth = true;
                 break;
             }
         }
 
-        if ($auth==false) {
+        if ($auth == false) {
             $res['ret'] = 0;
-            $res['msg'] = "token or source is invalid";
+            $res['msg'] = 'token or source is invalid';
             $response->getBody()->write(json_encode($res));
             return $response;
         }
 
-        $node = Node::where("node_ip", "LIKE", $_SERVER["REMOTE_ADDR"].'%')->first();
-        if ($node==null && $_SERVER["REMOTE_ADDR"] != '127.0.0.1') {
+        $node = Node::where('node_ip', 'LIKE', $_SERVER['REMOTE_ADDR'] . '%')->first();
+        if ($node == null && $_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
             $res['ret'] = 0;
-            $res['msg'] = "token or source is invalid";
+            $res['msg'] = 'token or source is invalid';
             $response->getBody()->write(json_encode($res));
             return $response;
         }

+ 2 - 5
app/Models/Ann.php

@@ -5,11 +5,8 @@ namespace App\Models;
 /**
  * Ann Model
  */
-
-use App\Utils\Tools;
-
 class Ann extends Model
 {
-    protected $connection = "default";
-    protected $table = "announcement";
+    protected $connection = 'default';
+    protected $table = 'announcement';
 }

+ 4 - 7
app/Models/Auto.php

@@ -2,20 +2,17 @@
 
 namespace App\Models;
 
-use App\Utils\Tools;
-
 class Auto extends Model
 {
-    protected $connection = "default";
-    protected $table = "auto";
-
+    protected $connection = 'default';
+    protected $table = 'auto';
 
 
     public function datetime()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
-    
+
     public function content()
     {
         return str_replace(PHP_EOL, '<br>', $this->attributes['value']);

+ 6 - 9
app/Models/BlockIp.php

@@ -3,22 +3,19 @@
 
 namespace App\Models;
 
-use App\Utils\Tools;
-
 class BlockIp extends Model
 {
-    protected $connection = "default";
-    protected $table = "blockip";
+    protected $connection = 'default';
+    protected $table = 'blockip';
+
 
-    
-    
     public function node()
     {
-        return Node::where("id", $this->attributes['nodeid'])->first();
+        return Node::where('id', $this->attributes['nodeid'])->first();
     }
-    
+
     public function time()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
 }

+ 11 - 11
app/Models/Bought.php

@@ -4,32 +4,32 @@ namespace App\Models;
 
 class Bought extends Model
 {
-    protected $connection = "default";
-    protected $table = "bought";
+    protected $connection = 'default';
+    protected $table = 'bought';
 
     public function renew_date()
     {
-        return date("Y-m-d H:i:s", $this->attributes['renew']);
+        return date('Y-m-d H:i:s', $this->attributes['renew']);
     }
 
     public function datetime()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
-    
+
     public function user()
     {
-        $user = User::where("id", $this->attributes['userid'])->first();
+        $user = User::where('id', $this->attributes['userid'])->first();
         if ($user == null) {
-            Bought::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
-    
+
     public function shop()
     {
-        return Shop::where("id", $this->attributes['shopid'])->first();
+        return Shop::where('id', $this->attributes['shopid'])->first();
     }
 }

+ 2 - 2
app/Models/CheckInLog.php

@@ -5,6 +5,6 @@ namespace App\Models;
 
 class CheckInLog
 {
-    protected $connection = "default";
-    protected $table = "ss_checkin_log";
+    protected $connection = 'default';
+    protected $table = 'ss_checkin_log';
 }

+ 4 - 8
app/Models/Code.php

@@ -5,18 +5,14 @@ namespace App\Models;
 /**
  * Code Model
  */
-
-use App\Utils\Tools;
-
 class Code extends Model
 {
-    protected $connection = "default";
-    protected $table = "code";
+    protected $connection = 'default';
+    protected $table = 'code';
+
 
-    
-    
     public function user()
     {
-        return User::where("id", $this->attributes['userid'])->first();
+        return User::where('id', $this->attributes['userid'])->first();
     }
 }

+ 1 - 1
app/Models/Config.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class Config extends Model
 {
-    protected $connection = "default";
+    protected $connection = 'default';
     protected $table = 'config';
 }

+ 10 - 10
app/Models/Coupon.php

@@ -4,28 +4,28 @@ namespace App\Models;
 
 class Coupon extends Model
 {
-    protected $connection = "default";
-    protected $table = "coupon";
-    
+    protected $connection = 'default';
+    protected $table = 'coupon';
+
     public function expire()
     {
-        return date("Y-m-d H:i:s", $this->attributes['expire']);
+        return date('Y-m-d H:i:s', $this->attributes['expire']);
     }
 
     public function order($shop)
     {
-        if ($this->attributes['shop']=="") {
+        if ($this->attributes['shop'] == '') {
             return true;
         }
-        
-        $shop_array=explode(",", $this->attributes['shop']);
-        
+
+        $shop_array = explode(',', $this->attributes['shop']);
+
         foreach ($shop_array as $shopid) {
-            if ($shopid==$shop) {
+            if ($shopid == $shop) {
                 return true;
             }
         }
-        
+
         return false;
     }
 }

+ 14 - 20
app/Models/DetectLog.php

@@ -2,47 +2,41 @@
 
 namespace App\Models;
 
-/**
- * DetectLog Model
- */
-
-use App\Utils\Tools;
-
 class DetectLog extends Model
 {
-    protected $connection = "default";
-    protected $table = "detect_log";
+    protected $connection = 'default';
+    protected $table = 'detect_log';
 
     public function DetectRule()
     {
-        $rule = DetectRule::where("id", $this->attributes['list_id'])->first();
+        $rule = DetectRule::where('id', $this->attributes['list_id'])->first();
         if ($rule == null) {
-            DetectLog::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $rule;
         }
+
+        return $rule;
     }
 
     public function User()
     {
-        $user = User::where("id", $this->attributes['user_id'])->first();
+        $user = User::where('id', $this->attributes['user_id'])->first();
         if ($user == null) {
-            DetectLog::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 
     public function Node()
     {
-        $node = Node::where("id", $this->attributes['node_id'])->first();
+        $node = Node::where('id', $this->attributes['node_id'])->first();
         if ($node == null) {
-            DetectLog::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $node;
         }
+
+        return $node;
     }
 }

+ 2 - 3
app/Models/DetectRule.php

@@ -5,9 +5,8 @@ namespace App\Models;
 /**
  * DetectLog Model
  */
-
 class DetectRule extends Model
 {
-    protected $connection = "default";
-    protected $table = "detect_list";
+    protected $connection = 'default';
+    protected $table = 'detect_list';
 }

+ 2 - 3
app/Models/Disconnect.php

@@ -5,9 +5,8 @@ namespace App\Models;
 /**
  * Disconnect Model
  */
-
 class Disconnect extends Model
 {
-    protected $connection = "default";
-    protected $table = "disconnect_ip";
+    protected $connection = 'default';
+    protected $table = 'disconnect_ip';
 }

+ 2 - 3
app/Models/EmailVerify.php

@@ -5,9 +5,8 @@ namespace App\Models;
 /**
  * EmailVerify Model
  */
-
 class EmailVerify extends Model
 {
-    protected $connection = "default";
-    protected $table = "email_verify";
+    protected $connection = 'default';
+    protected $table = 'email_verify';
 }

+ 2 - 3
app/Models/InviteCode.php

@@ -5,9 +5,8 @@ namespace App\Models;
 /**
  * InviteCode Model
  */
-
 class InviteCode extends Model
 {
-    protected $connection = "default";
-    protected $table = "ss_invite_code";
+    protected $connection = 'default';
+    protected $table = 'ss_invite_code';
 }

+ 14 - 17
app/Models/Ip.php

@@ -5,39 +5,36 @@ namespace App\Models;
 /**
  * Ip Model
  */
-
-use App\Utils\Tools;
-
 class Ip extends Model
 {
-    protected $connection = "default";
-    protected $table = "alive_ip";
-    
+    protected $connection = 'default';
+    protected $table = 'alive_ip';
+
     public function user()
     {
-        $user = User::where("id", $this->attributes['userid'])->first();
+        $user = User::where('id', $this->attributes['userid'])->first();
         if ($user == null) {
-            Ip::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 
     public function Node()
     {
-        $node = Node::where("id", $this->attributes['nodeid'])->first();
+        $node = Node::where('id', $this->attributes['nodeid'])->first();
         if ($node == null) {
-            Ip::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $node;
         }
+
+        return $node;
     }
-    
-    
+
+
     public function ip()
     {
-        return str_replace("::ffff:", "", $this->attributes['ip']);
+        return str_replace('::ffff:', '', $this->attributes['ip']);
     }
 }

+ 2 - 2
app/Models/Link.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class Link extends Model
 {
-    protected $connection = "default";
-    protected $table = "link";
+    protected $connection = 'default';
+    protected $table = 'link';
 }

+ 9 - 12
app/Models/LoginIp.php

@@ -5,27 +5,24 @@ namespace App\Models;
 /**
  * Ip Model
  */
-
-use App\Utils\Tools;
-
 class LoginIp extends Model
 {
-    protected $connection = "default";
-    protected $table = "login_ip";
-    
+    protected $connection = 'default';
+    protected $table = 'login_ip';
+
     public function user()
     {
-        $user = User::where("id", $this->attributes['userid'])->first();
+        $user = User::where('id', $this->attributes['userid'])->first();
         if ($user == null) {
-            LoginIp::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
-    
+
     public function datetime()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
 }

+ 0 - 1
app/Models/Model.php

@@ -7,7 +7,6 @@ use Illuminate\Database\Eloquent\Model as EloquentMedel;
 /**
  * Base Model
  */
-
 class Model extends EloquentMedel
 {
     public $timestamps = false;

+ 18 - 32
app/Models/Node.php

@@ -10,8 +10,8 @@ use App\Utils\Tools;
 
 class Node extends Model
 {
-    protected $connection = "default";
-    protected $table = "ss_node";
+    protected $connection = 'default';
+    protected $table = 'ss_node';
 
     protected $casts = [
         'node_speedlimit' => 'float',
@@ -34,7 +34,7 @@ class Node extends Model
     {
         $log = $this->getLastNodeInfoLog();
         if ($log == null) {
-            return "暂无数据";
+            return '暂无数据';
         }
         return Tools::secondsToTime((int)$log->uptime);
     }
@@ -43,9 +43,9 @@ class Node extends Model
     public function getNodeUpRate()
     {
         $id = $this->attributes['id'];
-        $log = NodeOnlineLog::where('node_id', $id)->where('log_time', '>=', time()-86400)->count();
+        $log = NodeOnlineLog::where('node_id', $id)->where('log_time', '>=', time() - 86400)->count();
 
-        return $log/1440;
+        return $log / 1440;
     }
 
     public function getNodeLoad()
@@ -65,7 +65,7 @@ class Node extends Model
     public function getOnlineUserCount()
     {
         $id = $this->attributes['id'];
-        $log = NodeOnlineLog::where('node_id', $id)->where("log_time",">",time()-300)->orderBy('id', 'desc')->first();
+        $log = NodeOnlineLog::where('node_id', $id)->where('log_time', '>', time() - 300)->orderBy('id', 'desc')->first();
         if ($log == null) {
             return 0;
         }
@@ -77,13 +77,13 @@ class Node extends Model
         $id = $this->attributes['id'];
         $log = Speedtest::where('nodeid', $id)->orderBy('datetime', 'desc')->first();
         if ($log == null) {
-            return "暂无数据";
+            return '暂无数据';
         }
 
 
-        return "电信延迟:".$log->telecomping." 下载:".$log->telecomeupload." 上传:".$log->telecomedownload."<br>
-		联通延迟:".$log->unicomping." 下载:".$log->unicomupload." 上传:".$log->unicomdownload."<br>
-		移动延迟:".$log->cmccping." 下载:".$log->cmccupload." 上传:".$log->cmccdownload."<br>定时测试,仅供参考";
+        return '电信延迟:' . $log->telecomping . ' 下载:' . $log->telecomeupload . ' 上传:' . $log->telecomedownload . '<br>
+		联通延迟:' . $log->unicomping . ' 下载:' . $log->unicomupload . ' 上传:' . $log->unicomdownload . '<br>
+		移动延迟:' . $log->cmccping . ' 下载:' . $log->cmccupload . ' 上传:' . $log->cmccdownload . '<br>定时测试,仅供参考';
     }
 
     public function getSpeedtestResult()
@@ -91,7 +91,7 @@ class Node extends Model
         $id = $this->attributes['id'];
         $log = Speedtest::where('nodeid', $id)->orderBy('id', 'desc')->limit(48)->get();
         if ($log == null) {
-            return "暂无数据";
+            return '暂无数据';
         }
 
 
@@ -105,7 +105,7 @@ class Node extends Model
         $traffic = TrafficLog::where('node_id', $id)->sum('u') + TrafficLog::where('node_id', $id)->sum('d');
 
         if ($traffic == 0) {
-            return "暂无数据";
+            return '暂无数据';
         }
 
         return Tools::flowAutoShow($traffic);
@@ -117,10 +117,10 @@ class Node extends Model
         $id = $this->attributes['id'];
         $sort = $this->attributes['sort'];
         $node_heartbeat = $this->attributes['node_heartbeat'];
-        $log = NodeOnlineLog::where('node_id', $id)->where("log_time",">",time()-300)->orderBy('id', 'desc')->first();
-        if(!($sort == 0 || $sort == 7 || $sort == 8 || $sort==10 || $sort==11) || $node_heartbeat == 0){
+        $log = NodeOnlineLog::where('node_id', $id)->where('log_time', '>', time() - 300)->orderBy('id', 'desc')->first();
+        if (!($sort == 0 || $sort == 7 || $sort == 8 || $sort == 10 || $sort == 11 || $sort == 12 || $sort == 13) || $node_heartbeat == 0) {
             $result = null;
-        }else if ($log != null && $log->log_time + 300 > time()) {
+        } elseif ($log != null && $log->log_time + 300 > time()) {
             $result = true;
         }
         return $result;
@@ -131,20 +131,12 @@ class Node extends Model
         $node_bandwidth = $this->attributes['node_bandwidth'];
         $node_bandwidth_limit = $this->attributes['node_bandwidth_limit'];
 
-        if ($node_bandwidth_limit == 0 || $node_bandwidth < $node_bandwidth_limit) {
-            return false;
-        } else {
-            return true;
-        }
+        return !($node_bandwidth_limit == 0 || $node_bandwidth < $node_bandwidth_limit);
     }
 
     public function isNodeAccessable()
     {
-        if ($this->isNodeTrafficOut() == false && $this->isNodeOnline() == true) {
-            return true;
-        } else {
-            return false;
-        }
+        return $this->isNodeTrafficOut() == false && $this->isNodeOnline() == true;
     }
 
     public function changeNodeIp($server_name)
@@ -152,16 +144,10 @@ class Node extends Model
         $ip = gethostbyname($server_name);
         $node_id = $this->attributes['id'];
 
-        if ($ip == "") {
+        if ($ip == '') {
             return false;
         }
 
-        $relay_rules = Relay::where('dist_node_id', $node_id)->get();
-        foreach ($relay_rules as $relay_rule) {
-            $relay_rule->dist_ip = $ip;
-            $relay_rule->save();
-        }
-
         $this->attributes['node_ip'] = $ip;
         return true;
     }

+ 6 - 5
app/Models/NodeInfoLog.php

@@ -1,18 +1,19 @@
 <?php
+
 namespace App\Models;
 
 class NodeInfoLog extends Model
 {
-    protected $connection = "default";
-    protected $table = "ss_node_info";
-    
+    protected $connection = 'default';
+    protected $table = 'ss_node_info';
+
     public function getNodeLoad()
     {
         $load = $this->attributes['load'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getTime()
     {
         $time = $this->attributes['log_time'];

+ 2 - 2
app/Models/NodeOnlineLog.php

@@ -5,6 +5,6 @@ namespace App\Models;
 
 class NodeOnlineLog extends Model
 {
-    protected $connection = "default";
-    protected $table = "ss_node_online_log";
+    protected $connection = 'default';
+    protected $table = 'ss_node_online_log';
 }

+ 1 - 1
app/Models/PasswordReset.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class PasswordReset extends Model
 {
-    protected $connection = "default";
+    protected $connection = 'default';
     protected $table = 'ss_password_reset';
 }

+ 5 - 5
app/Models/Payback.php

@@ -4,17 +4,17 @@ namespace App\Models;
 
 class Payback extends Model
 {
-    protected $connection = "default";
+    protected $connection = 'default';
     protected $table = 'payback';
-    
+
     public function user()
     {
-        $user = User::where("id", $this->attributes['userid'])->first();
+        $user = User::where('id', $this->attributes['userid'])->first();
         if ($user == null) {
             Bought::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 }

+ 1 - 1
app/Models/Paylist.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class Paylist extends Model
 {
-    protected $connection = "default";
+    protected $connection = 'default';
     protected $table = 'paylist';
 }

+ 2 - 2
app/Models/RadiusBan.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class RadiusBan extends Model
 {
-    protected $connection = "default";
-    protected $table = "radius_ban";
+    protected $connection = 'default';
+    protected $table = 'radius_ban';
 }

+ 2 - 2
app/Models/RadiusNas.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class RadiusNas extends Model
 {
-    protected $connection = "radius";
-    protected $table = "nas";
+    protected $connection = 'radius';
+    protected $table = 'nas';
 }

+ 2 - 2
app/Models/RadiusRadAcct.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class RadiusRadAcct extends Model
 {
-    protected $connection = "radius";
-    protected $table = "radacct";
+    protected $connection = 'radius';
+    protected $table = 'radacct';
 }

+ 2 - 2
app/Models/RadiusRadCheck.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class RadiusRadCheck extends Model
 {
-    protected $connection = "radius";
-    protected $table = "radcheck";
+    protected $connection = 'radius';
+    protected $table = 'radcheck';
 }

+ 2 - 2
app/Models/RadiusRadPostauth.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class RadiusRadPostauth extends Model
 {
-    protected $connection = "radius";
-    protected $table = "radpostauth";
+    protected $connection = 'radius';
+    protected $table = 'radpostauth';
 }

+ 2 - 2
app/Models/RadiusRadUserGroup.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class RadiusRadUserGroup extends Model
 {
-    protected $connection = "radius";
-    protected $table = "radusergroup";
+    protected $connection = 'radius';
+    protected $table = 'radusergroup';
 }

+ 14 - 15
app/Models/Relay.php

@@ -5,32 +5,31 @@ namespace App\Models;
 /**
  * DetectLog Model
  */
-
 class Relay extends Model
 {
-    protected $connection = "default";
-    protected $table = "relay";
+    protected $connection = 'default';
+    protected $table = 'relay';
 
     public function User()
     {
-        $user = User::where("id", $this->attributes['user_id'])->first();
+        $user = User::where('id', $this->attributes['user_id'])->first();
         if ($user == null) {
-            Relay::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 
     public function Source_Node()
     {
-        $node = Node::where("id", $this->attributes['source_node_id'])->first();
+        $node = Node::where('id', $this->attributes['source_node_id'])->first();
         if ($node == null && $this->attributes['source_node_id'] != 0) {
-            Relay::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $node;
         }
+
+        return $node;
     }
 
     public function Dist_Node()
@@ -39,12 +38,12 @@ class Relay extends Model
             return null;
         }
 
-        $node = Node::where("id", $this->attributes['dist_node_id'])->first();
+        $node = Node::where('id', $this->attributes['dist_node_id'])->first();
         if ($node == null) {
-            Relay::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $node;
         }
+
+        return $node;
     }
 }

+ 2 - 3
app/Models/Role.php

@@ -5,9 +5,8 @@ namespace App\Models;
 /**
  * Node Model
  */
-
 class Role extends Model
 {
-    protected $connection = "default";
-    protected $table = "user_role";
+    protected $connection = 'default';
+    protected $table = 'user_role';
 }

+ 82 - 111
app/Models/Shop.php

@@ -6,54 +6,54 @@ use App\Services\Config;
 
 class Shop extends Model
 {
-    protected $connection = "default";
-    protected $table = "shop";
+    protected $connection = 'default';
+    protected $table = 'shop';
 
     public function content()
     {
         $content = json_decode($this->attributes['content'], true);
-        $content_text="";
+        $content_text = '';
         $i = 0;
-        foreach ($content as $key=>$value) {
+        foreach ($content as $key => $value) {
             switch ($key) {
-                case "bandwidth":
-                    $content_text .= "添加流量 ".$value." G ";
+                case 'bandwidth':
+                    $content_text .= '添加流量 ' . $value . ' G ';
                     break;
-                case "expire":
-                    $content_text .= ", 为账号的有效期添加 ".$value." 天 ";
+                case 'expire':
+                    $content_text .= ', 为账号的有效期添加 ' . $value . ' 天 ';
                     break;
-                case "class":
-                    $content_text .= ", 为账号升级为等级 ".$value." , 有效期 ".$content["class_expire"]." 天 ";
+                case 'class':
+                    $content_text .= ', 为账号升级为等级 ' . $value . ' , 有效期 ' . $content['class_expire'] . ' 天 ';
                     break;
-                case "reset":
-                    $content_text .= ", 在 ".$content["reset_exp"]." 天内 ,每 ".$value." 天重置流量为 ".$content["reset_value"]." G ";
+                case 'reset':
+                    $content_text .= ', 在 ' . $content['reset_exp'] . ' 天内 ,每 ' . $value . ' 天重置流量为 ' . $content['reset_value'] . ' G ';
                     break;
-                case "speedlimit":
-                    if ($value == 0){
-                        $content_text .= ", 用户端口不限速 " ;
-                    }else{
-                        $content_text .= ", 用户端口限速变为".$value." Mbps ";
+                case 'speedlimit':
+                    if ($value == 0) {
+                        $content_text .= ', 用户端口不限速 ';
+                    } else {
+                        $content_text .= ', 用户端口限速变为' . $value . ' Mbps ';
                     }
                     break;
-                case "connector":
-                    if ($value == 0){
-                        $content_text .= ", 用户IP不限制";
-                    }else{
-                        $content_text .= ", 用户IP限制变为 ".$value." 个";
+                case 'connector':
+                    if ($value == 0) {
+                        $content_text .= ', 用户IP不限制';
+                    } else {
+                        $content_text .= ', 用户IP限制变为 ' . $value . ' 个';
                     }
                     break;
                 default:
             }
 
             //if ($i<count($content)&&$key!="connector") {
-                //$content_text .= ",";
+            //$content_text .= ",";
             //}
 
             $i++;
         }
 
-        if (substr($content_text, -1, 1)==",") {
-            $content_text=substr($content_text, 0, -1);
+        if ($content_text[strlen($content_text) - 1] == ',') {
+            $content_text = substr($content_text, 0, -1);
         }
 
         return $content_text;
@@ -61,159 +61,130 @@ class Shop extends Model
 
     public function bandwidth()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->bandwidth)) {
-            return $content->bandwidth;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->bandwidth ?? 0;
     }
 
     public function expire()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->expire)) {
-            return $content->expire;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->expire ?? 0;
     }
 
     public function reset()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->reset)) {
-            return $content->reset;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->reset ?? 0;
     }
 
     public function reset_value()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->reset_value)) {
-            return $content->reset_value;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->reset_value ?? 0;
     }
 
     public function reset_exp()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->reset_exp)) {
-            return $content->reset_exp;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->reset_exp ?? 0;
     }
 
     public function content_extra()
     {
-        $content =  json_decode($this->attributes['content']);
+        $content = json_decode($this->attributes['content']);
         if (isset($content->content_extra)) {
             $content_extra = $content->content_extra;
-            $content_extra = explode(';',$content_extra);
+            $content_extra = explode(';', $content_extra);
             $content_extra_new = array();
             foreach ($content_extra as $innerContent) {
-                if (!strstr($innerContent,'-')) {
+                if (false === strpos($innerContent, '-')) {
                     $innerContent = 'check-' . $innerContent;
                 }
-                $innerContent = explode('-',$innerContent);
-                array_push($content_extra_new,$innerContent);
+                $innerContent = explode('-', $innerContent);
+                $content_extra_new[] = $innerContent;
             }
             $content_extra = $content_extra_new;
             return $content_extra;
-        } else {
-            return 0;
         }
+
+        return 0;
     }
 
     public function user_class()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->class)) {
-            return $content->class;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->class ?? 0;
     }
 
     public function class_expire()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->class_expire)) {
-            return $content->class_expire;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->class_expire ?? 0;
     }
 
     public function speedlimit()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->speedlimit)) {
-            return $content->speedlimit;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->speedlimit ?? 0;
     }
 
     public function connector()
     {
-        $content =  json_decode($this->attributes['content']);
-        if (isset($content->connector)) {
-            return $content->connector;
-        } else {
-            return 0;
-        }
+        $content = json_decode($this->attributes['content']);
+        return $content->connector ?? 0;
     }
 
     public function buy($user, $is_renew = 0)
     {
         $content = json_decode($this->attributes['content'], true);
-        $content_text="";
+        $content_text = '';
 
-        foreach ($content as $key=>$value) {
+        foreach ($content as $key => $value) {
             switch ($key) {
-                case "bandwidth":
+                case 'bandwidth':
                     if ($is_renew == 0) {
                         if (Config::get('enable_bought_reset') == 'true') {
-                            $user->transfer_enable=$value*1024*1024*1024;
+                            $user->transfer_enable = $value * 1024 * 1024 * 1024;
                             $user->u = 0;
                             $user->d = 0;
                             $user->last_day_t = 0;
                         } else {
-                            $user->transfer_enable=$user->transfer_enable+$value*1024*1024*1024;
+                            $user->transfer_enable += $value * 1024 * 1024 * 1024;
                         }
+                    } elseif ($this->attributes['auto_reset_bandwidth'] == 1) {
+                        $user->transfer_enable = $value * 1024 * 1024 * 1024;
+                        $user->u = 0;
+                        $user->d = 0;
+                        $user->last_day_t = 0;
                     } else {
-                        if ($this->attributes['auto_reset_bandwidth'] == 1) {
-                            $user->transfer_enable=$value*1024*1024*1024;
-                            $user->u = 0;
-                            $user->d = 0;
-                            $user->last_day_t = 0;
-                        } else {
-                            $user->transfer_enable=$user->transfer_enable+$value*1024*1024*1024;
-                        }
+                        $user->transfer_enable += $value * 1024 * 1024 * 1024;
                     }
                     break;
-                case "expire":
-                    if (time()>strtotime($user->expire_in)) {
-                        $user->expire_in=date("Y-m-d H:i:s", time()+$value*86400);
+                case 'expire':
+                    if (time() > strtotime($user->expire_in)) {
+                        $user->expire_in = date('Y-m-d H:i:s', time() + $value * 86400);
                     } else {
-                        $user->expire_in=date("Y-m-d H:i:s", strtotime($user->expire_in)+$value*86400);
+                        $user->expire_in = date('Y-m-d H:i:s', strtotime($user->expire_in) + $value * 86400);
                     }
                     break;
-                case "class":
-                    $user->class=$value;
-                    $user->class_expire=date("Y-m-d H:i:s", time()+$content["class_expire"]*86400);
-                    break;
-                case "speedlimit":
-                    $user->node_speedlimit=$value;
+                case 'class':
+                    if (Config::get('enable_bought_extend') == 'true') {
+                        if ($user->class == $value) {
+                            $user->class_expire = date('Y-m-d H:i:s', strtotime($user->class_expire) + $content['class_expire'] * 86400);
+                        } else {
+                            $user->class_expire = date('Y-m-d H:i:s', time() + $content['class_expire'] * 86400);
+                        }
+                        $user->class = $value;
+                    } else {
+                        $user->class = $value;
+                        $user->class_expire = date('Y-m-d H:i:s', time() + $content['class_expire'] * 86400);
+                        break;
+                    }
+                case 'speedlimit':
+                    $user->node_speedlimit = $value;
                     break;
-                case "connector":
-                    $user->node_connector=$value;
+                case 'connector':
+                    $user->node_connector = $value;
                     break;
                 default:
             }

+ 21 - 27
app/Models/Speedtest.php

@@ -2,84 +2,78 @@
 
 namespace App\Models;
 
-/**
- * Node Model
- */
-
-use App\Utils\Tools;
-
 class Speedtest extends Model
 {
-    protected $connection = "default";
-    protected $table = "speedtest";
-    
+    protected $connection = 'default';
+    protected $table = 'speedtest';
+
     public function node()
     {
         return Node::find($this->attributes['nodeid']);
     }
 
-    
+
     public function getTelecomPing()
     {
         $load = $this->attributes['telecomping'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getUnicomPing()
     {
         $load = $this->attributes['unicomping'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getCmccPing()
     {
         $load = $this->attributes['cmccping'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
 
     public function getTelecomUpload()
     {
         $load = $this->attributes['telecomeupload'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getTelecomDownload()
     {
         $load = $this->attributes['telecomedownload'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getUnicomUpload()
     {
         $load = $this->attributes['unicomupload'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getUnicomDownload()
     {
         $load = $this->attributes['unicomdownload'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getCmccDownload()
     {
         $load = $this->attributes['cmccdownload'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
-    
+
     public function getCmccUpload()
     {
         $load = $this->attributes['cmccupload'];
-        $exp = explode(" ", $load);
+        $exp = explode(' ', $load);
         return $exp[0];
     }
 }

+ 7 - 8
app/Models/TelegramSession.php

@@ -5,25 +5,24 @@ namespace App\Models;
 /**
  * TelegramSession Model
  */
-
 class TelegramSession extends Model
 {
-    protected $connection = "default";
-    protected $table = "telegram_session";
+    protected $connection = 'default';
+    protected $table = 'telegram_session';
 
     public function datetime()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
-    
+
     public function User()
     {
-        $user = User::where("id", $this->attributes['user_id'])->first();
+        $user = User::where('id', $this->attributes['user_id'])->first();
         if ($user == null) {
             Ticket::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 }

+ 8 - 9
app/Models/Ticket.php

@@ -5,25 +5,24 @@ namespace App\Models;
 /**
  * Ticket Model
  */
-
 class Ticket extends Model
 {
-    protected $connection = "default";
-    protected $table = "ticket";
+    protected $connection = 'default';
+    protected $table = 'ticket';
 
     public function datetime()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
-    
+
     public function User()
     {
-        $user = User::where("id", $this->attributes['userid'])->first();
+        $user = User::where('id', $this->attributes['userid'])->first();
         if ($user == null) {
-            Ticket::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 }

+ 2 - 2
app/Models/Token.php

@@ -4,6 +4,6 @@ namespace App\Models;
 
 class Token extends Model
 {
-    protected $connection = "default";
-    protected $table = "user_token";
+    protected $connection = 'default';
+    protected $table = 'user_token';
 }

+ 13 - 13
app/Models/TrafficLog.php

@@ -7,39 +7,39 @@ use App\Utils\Tools;
 
 class TrafficLog extends Model
 {
-    protected $connection = "default";
-    protected $table = "user_traffic_log";
+    protected $connection = 'default';
+    protected $table = 'user_traffic_log';
 
     public function node()
     {
-        $node = Node::where("id", $this->attributes['node_id'])->first();
+        $node = Node::where('id', $this->attributes['node_id'])->first();
         if ($node == null) {
-            TrafficLog::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $node;
         }
+
+        return $node;
     }
-    
+
     public function user()
     {
-        $user = User::where("id", $this->attributes['user_id'])->first();
+        $user = User::where('id', $this->attributes['user_id'])->first();
         if ($user == null) {
-            TrafficLog::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
 
     public function totalUsed()
     {
         return Tools::flowAutoShow($this->attributes['u'] + $this->attributes['d']);
     }
-    
+
     public function totalUsedRaw()
     {
-        return number_format(($this->attributes['u'] + $this->attributes['d'])/1024, 2, ".", "");
+        return number_format(($this->attributes['u'] + $this->attributes['d']) / 1024, 2, '.', '');
     }
 
     public function logTime()

+ 8 - 10
app/Models/UnblockIp.php

@@ -3,26 +3,24 @@
 
 namespace App\Models;
 
-use App\Utils\Tools;
-
 class UnblockIp extends Model
 {
-    protected $connection = "default";
-    protected $table = "unblockip";
+    protected $connection = 'default';
+    protected $table = 'unblockip';
 
     public function user()
     {
-        $user = User::where("id", $this->attributes['userid'])->first();
+        $user = User::where('id', $this->attributes['userid'])->first();
         if ($user == null) {
-            UnblockIp::where('id', '=', $this->attributes['id'])->delete();
+            self::where('id', '=', $this->attributes['id'])->delete();
             return null;
-        } else {
-            return $user;
         }
+
+        return $user;
     }
-    
+
     public function time()
     {
-        return date("Y-m-d H:i:s", $this->attributes['datetime']);
+        return date('Y-m-d H:i:s', $this->attributes['datetime']);
     }
 }

+ 94 - 82
app/Models/User.php

@@ -8,30 +8,28 @@ namespace App\Models;
 
 use App\Utils\Tools;
 use App\Utils\Hash;
-use App\Models\InviteCode;
 use App\Services\Config;
 use App\Utils\GA;
 use App\Utils\QQWry;
-use App\Models\Link;
 use App\Utils\Radius;
 use Ramsey\Uuid\Uuid;
 
 class User extends Model
 {
-    protected $connection = "default";
-    protected $table = "user";
+    protected $connection = 'default';
+    protected $table = 'user';
 
     public $isLogin;
 
     public $isAdmin;
 
     protected $casts = [
-        "t" => 'float',
-        "u" => 'float',
-        "d" => 'float',
-        "port" => 'int',
-        "transfer_enable" => 'float',
-        "enable" => 'int',
+        't' => 'float',
+        'u' => 'float',
+        'd' => 'float',
+        'port' => 'int',
+        'transfer_enable' => 'float',
+        'enable' => 'int',
         'is_admin' => 'boolean',
         'is_multi_user' => 'int',
         'node_speedlimit' => 'float',
@@ -39,8 +37,8 @@ class User extends Model
 
     public function getGravatarAttribute()
     {
-      //  $hash = md5(strtolower(trim($this->attributes['email'])));
-        return "/images/Avatar.jpg";//.$hash;
+        //  $hash = md5(strtolower(trim($this->attributes['email'])));
+        return '/images/Avatar.jpg';//.$hash;
     }
 
     public function isAdmin()
@@ -51,22 +49,22 @@ class User extends Model
     public function lastSsTime()
     {
         if ($this->attributes['t'] == 0) {
-            return "从未使用喵";
+            return '从未使用喵';
         }
         return Tools::toDateTime($this->attributes['t']);
     }
 
     public function getMuMd5()
     {
-        $str = str_replace("%id", $this->attributes['id'], Config::get('mu_regex'));
-        $str = str_replace("%suffix", Config::get('mu_suffix'), $str);
+        $str = str_replace(array('%id', '%suffix'), array($this->attributes['id'], Config::get('mu_suffix')), Config::get('mu_regex'));
         preg_match_all("|%-?[1-9]\d*m|U", $str, $matches, PREG_PATTERN_ORDER);
         foreach ($matches[0] as $key) {
-            $key_match = str_replace("%", "", $key);
-            $key_match = str_replace("m", "", $key_match);
-            $md5 = substr(MD5($this->attributes['id'].$this->attributes['passwd'].$this->attributes['method'].$this->attributes['obfs'].$this->attributes['protocol']),
-            ($key_match < 0 ? $key_match : 0),
-            abs($key_match));
+            $key_match = str_replace(array('%', 'm'), '', $key);
+            $md5 = substr(
+                MD5($this->attributes['id'] . $this->attributes['passwd'] . $this->attributes['method'] . $this->attributes['obfs'] . $this->attributes['protocol']),
+                ($key_match < 0 ? $key_match : 0),
+                abs($key_match)
+            );
             $str = str_replace($key, $md5, $str);
         }
         return $str;
@@ -75,7 +73,7 @@ class User extends Model
     public function lastCheckInTime()
     {
         if ($this->attributes['last_check_in_time'] == 0) {
-            return "从未签到";
+            return '从未签到';
         }
         return Tools::toDateTime($this->attributes['last_check_in_time']);
     }
@@ -93,12 +91,12 @@ class User extends Model
 
     public function get_forbidden_ip()
     {
-        return str_replace(",", PHP_EOL, $this->attributes['forbidden_ip']);
+        return str_replace(',', PHP_EOL, $this->attributes['forbidden_ip']);
     }
 
     public function get_forbidden_port()
     {
-        return str_replace(",", PHP_EOL, $this->attributes['forbidden_port']);
+        return str_replace(',', PHP_EOL, $this->attributes['forbidden_port']);
     }
 
     public function updateSsPwd($pwd)
@@ -117,19 +115,20 @@ class User extends Model
     {
         $uid = $this->attributes['id'];
         $code = new InviteCode();
-		while(true){
-			$temp_code=Tools::genRandomChar(4);
-			if(InviteCode::where('user_id', $uid)->count()==0){
-				break;
-			}
-		}
+        while (true) {
+            $temp_code = Tools::genRandomChar(4);
+            if (InviteCode::where('user_id', $uid)->count() == 0) {
+                break;
+            }
+        }
         $code->code = $temp_code;
         $code->user_id = $uid;
         $code->save();
     }
 
-    public function getUuid() {
-        return Uuid::uuid3(Uuid::NAMESPACE_DNS, $this->attributes['id']. '|' .$this->attributes['passwd'])->toString();
+    public function getUuid()
+    {
+        return Uuid::uuid3(Uuid::NAMESPACE_DNS, $this->attributes['id'] . '|' . $this->attributes['passwd'])->toString();
     }
 
     public function trafficUsagePercent()
@@ -141,7 +140,7 @@ class User extends Model
         }
         $percent = $total / $transferEnable;
         $percent = round($percent, 2);
-        $percent = $percent * 100;
+        $percent *= 100;
         return $percent;
     }
 
@@ -150,16 +149,19 @@ class User extends Model
         $transfer_enable = $this->attributes['transfer_enable'];
         return Tools::flowAutoShow($transfer_enable);
     }
+
     public function enableTrafficInGB()
     {
         $transfer_enable = $this->attributes['transfer_enable'];
         return Tools::flowToGB($transfer_enable);
     }
+
     public function usedTraffic()
     {
         $total = $this->attributes['u'] + $this->attributes['d'];
         return Tools::flowAutoShow($total);
     }
+
     public function unusedTraffic()
     {
         $total = $this->attributes['u'] + $this->attributes['d'];
@@ -169,7 +171,7 @@ class User extends Model
 
     public function TodayusedTraffic()
     {
-        $total = $this->attributes['u'] + $this->attributes['d']-$this->attributes['last_day_t'];
+        $total = $this->attributes['u'] + $this->attributes['d'] - $this->attributes['last_day_t'];
         return Tools::flowAutoShow($total);
     }
 
@@ -184,10 +186,7 @@ class User extends Model
         $last = $this->attributes['last_check_in_time'];
 
         $now = time();
-        if (date("Ymd", $now)!= date("Ymd", $last)) {
-            return true;
-        }
-        return false;
+        return date('Ymd', $now) != date('Ymd', $last);
     }
 
     /*
@@ -200,7 +199,7 @@ class User extends Model
     public function getGAurl()
     {
         $ga = new GA();
-        $url = $ga->getUrl(urlencode(Config::get('appName')."-".$this->attributes['user_name']."-两步验证码"), $this->attributes['ga_token']);
+        $url = $ga->getUrl(urlencode(Config::get('appName') . '-' . $this->attributes['user_name'] . '-两步验证码'), $this->attributes['ga_token']);
         return $url;
     }
 
@@ -213,7 +212,7 @@ class User extends Model
     public function ref_by_user()
     {
         $uid = $this->attributes['ref_by'];
-        return User::where('id', $uid)->first();
+        return self::where('id', $uid)->first();
     }
 
     public function clean_link()
@@ -221,7 +220,7 @@ class User extends Model
         $uid = $this->attributes['id'];
         Link::where('userid', $uid)->delete();
     }
-    
+
     public function clear_inviteCodes()
     {
         $uid = $this->attributes['id'];
@@ -231,17 +230,17 @@ class User extends Model
     public function online_ip_count()
     {
         $uid = $this->attributes['id'];
-        $total = Ip::where("datetime", ">=", time()-90)->where('userid', $uid)->orderBy('userid', 'desc')->get();
+        $total = Ip::where('datetime', '>=', time() - 90)->where('userid', $uid)->orderBy('userid', 'desc')->get();
         $unique_ip_list = array();
         foreach ($total as $single_record) {
             $single_record->ip = Tools::getRealIp($single_record->ip);
-            $is_node = Node::where("node_ip", $single_record->ip)->first();
-            if($is_node) {
+            $is_node = Node::where('node_ip', $single_record->ip)->first();
+            if ($is_node) {
                 continue;
             }
 
             if (!in_array($single_record->ip, $unique_ip_list)) {
-                array_push($unique_ip_list, $single_record->ip);
+                $unique_ip_list[] = $single_record->ip;
             }
         }
 
@@ -280,7 +279,7 @@ class User extends Model
     {
         $id = $this->attributes['id'];
         $today_traffic = Tools::flowToMB($this->attributes['u'] + $this->attributes['d'] - $this->attributes['last_day_t']);
-        $is_enable = $this->attributes['enable'] == 1 ? "可用" : "禁用";
+        $is_enable = $this->attributes['enable'] == 1 ? '可用' : '禁用';
         $reg_location = $this->attributes['reg_ip'];
         $account_expire_in = $this->attributes['expire_in'];
         $class_expire_in = $this->attributes['class_expire'];
@@ -289,56 +288,69 @@ class User extends Model
 
         $im_type = '';
         $im_value = $this->attributes['im_value'];
-        switch($this->attributes['im_type']) {
+        switch ($this->attributes['im_type']) {
             case 1:
-              $im_type = '微信';
-              break;
+                $im_type = '微信';
+                break;
             case 2:
-              $im_type = 'QQ';
-              break;
+                $im_type = 'QQ';
+                break;
             case 3:
-              $im_type = 'Google+';
-              break;
+                $im_type = 'Google+';
+                break;
             default:
-              $im_type = 'Telegram';
-              $im_value = '<a href="https://telegram.me/'.$im_value.'">'.$im_value.'</a>';
+                $im_type = 'Telegram';
+                $im_value = '<a href="https://telegram.me/' . $im_value . '">' . $im_value . '</a>';
         }
 
-        $ref_user = User::find($this->attributes['ref_by']);
+        $ref_user = self::find($this->attributes['ref_by']);
 
         if ($this->attributes['ref_by'] == 0) {
             $ref_user_id = 0;
-            $ref_user_name = "系统邀请";
+            $ref_user_name = '系统邀请';
+        } elseif ($ref_user == null) {
+            $ref_user_id = $this->attributes['ref_by'];
+            $ref_user_name = '邀请人已经被删除';
         } else {
-            if ($ref_user == null) {
-                $ref_user_id = $this->attributes['ref_by'];
-                $ref_user_name = "邀请人已经被删除";
-            } else {
-                $ref_user_id = $this->attributes['ref_by'];
-                $ref_user_name = $ref_user->user_name;
-            }
+            $ref_user_id = $this->attributes['ref_by'];
+            $ref_user_name = $ref_user->user_name;
         }
 
         $iplocation = new QQWry();
-        $location=$iplocation->getlocation($reg_location);
-        $reg_location .= "\n".iconv('gbk', 'utf-8//IGNORE', $location['country'].$location['area']);
-
-        $return_array = Array('DT_RowId' => 'row_1_'.$id, $id, $id,
-                              $this->attributes['user_name'], $this->attributes['remark'],
-                              $this->attributes['email'], $this->attributes['money'],
-                              $im_type, $im_value,
-                              $this->attributes['node_group'], $account_expire_in,
-                              $this->attributes['class'], $class_expire_in,
-                              $this->attributes['passwd'], $this->attributes['port'],
-                              $this->attributes['method'],
-                              $this->attributes['protocol'], $this->attributes['obfs'],
-                              $this->online_ip_count(), $this->lastSsTime(),
-                              $used_traffic, $enable_traffic,
-                              $this->lastCheckInTime(), $today_traffic,
-                              $is_enable, $this->attributes['reg_date'],
-                              $reg_location,
-                              $this->attributes['auto_reset_day'], $this->attributes['auto_reset_bandwidth'],
-                              $ref_user_id, $ref_user_name);
+        $location = $iplocation->getlocation($reg_location);
+        $reg_location .= "\n" . iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
+
+        $return_array = array('DT_RowId' => 'row_1_' . $id, $id, $id,
+            $this->attributes['user_name'], $this->attributes['remark'],
+            $this->attributes['email'], $this->attributes['money'],
+            $im_type, $im_value,
+            $this->attributes['node_group'], $account_expire_in,
+            $this->attributes['class'], $class_expire_in,
+            $this->attributes['passwd'], $this->attributes['port'],
+            $this->attributes['method'],
+            $this->attributes['protocol'], $this->attributes['obfs'],
+            $this->online_ip_count(), $this->lastSsTime(),
+            $used_traffic, $enable_traffic,
+            $this->lastCheckInTime(), $today_traffic,
+            $is_enable, $this->attributes['reg_date'],
+            $reg_location,
+            $this->attributes['auto_reset_day'], $this->attributes['auto_reset_bandwidth'],
+            $ref_user_id, $ref_user_name);
         return $return_array;
     }
+
+    public function get_user_attributes($key)
+    {
+        return $this->attributes[$key];
+    }
+
+    public function get_top_up()
+    {
+        $codes = Code::where('userid', $this->attributes['id'])->get();
+        $top_up = 0;
+        foreach ($codes as $code) {
+            $top_up += $code->number;
+        }
+        return round($top_up, 2);
+    }
 }

+ 0 - 17
app/Models/YftOrder.php

@@ -1,17 +0,0 @@
-<?php
-/**
- * Created by 傲慢与偏见.
- * OSUser: D-L
- * Date: 2017/10/22
- * Time: 21:09
- */
-
-namespace App\Models;
-
-
-class YftOrder extends Model
-{
-    protected $connection = "default";
-    protected $table = "yft_order_info";
-    protected $primaryKey = 'id';
-}

+ 1 - 1
app/Services/Analytic.php

@@ -9,7 +9,7 @@ class Analytic
 {
     public function userCount()
     {
-        return  User::all()->count();
+        return User::all()->count();
     }
 
     public function checkinUserCount()

+ 33 - 33
app/Services/Analytics.php

@@ -17,7 +17,7 @@ class Analytics
     {
         return User::where('last_check_in_time', '>', 0)->count();
     }
-    
+
     public function getTodayCheckinUser()
     {
         return User::where('last_check_in_time', '>', strtotime('today'))->count();
@@ -28,56 +28,52 @@ class Analytics
         $total = User::sum('u') + User::sum('d');
         return Tools::flowAutoShow($total);
     }
-    
+
     public function getTodayTrafficUsage()
     {
         $total = User::sum('u') + User::sum('d') - User::sum('last_day_t');
         return Tools::flowAutoShow($total);
     }
-    
-    
+
+
     public function getRawTodayTrafficUsage()
     {
-        $total = User::sum('u') + User::sum('d') - User::sum('last_day_t');
-        return $total;
+        return User::sum('u') + User::sum('d') - User::sum('last_day_t');
     }
-    
+
     public function getLastTrafficUsage()
     {
         $total = User::sum('last_day_t');
         return Tools::flowAutoShow($total);
     }
-    
-    
+
+
     public function getRawLastTrafficUsage()
     {
-        $total = User::sum('last_day_t');
-        return $total;
+        return User::sum('last_day_t');
     }
-    
+
     public function getUnusedTrafficUsage()
     {
         $total = User::sum('transfer_enable') - User::sum('u') - User::sum('d');
         return Tools::flowAutoShow($total);
     }
-    
+
     public function getRawUnusedTrafficUsage()
     {
-        $total = User::sum('transfer_enable') - User::sum('u') - User::sum('d');
-        return $total;
+        return User::sum('transfer_enable') - User::sum('u') - User::sum('d');
     }
-    
-    
+
+
     public function getTotalTraffic()
     {
         $total = User::sum('transfer_enable');
         return Tools::flowAutoShow($total);
     }
-    
+
     public function getRawTotalTraffic()
     {
-        $total = User::sum('transfer_enable');
-        return $total;
+        return User::sum('transfer_enable');
     }
 
     public function getOnlineUser($time)
@@ -85,7 +81,7 @@ class Analytics
         $time = time() - $time;
         return User::where('t', '>', $time)->count();
     }
-    
+
     public function getUnusedUser()
     {
         return User::where('t', '=', 0)->count();
@@ -95,26 +91,30 @@ class Analytics
     {
         return Node::count();
     }
-    
+
     public function getTotalNodes()
     {
         return Node::where('node_heartbeat', '>', 0)->where(
-                    function ($query) {
-                        $query->Where('sort', '=', 0)
-                            ->orWhere('sort', '=', 10)
-                            ->orWhere('sort', '=', 11);
-                    }
-                )->count();
-    }
-    
+            static function ($query) {
+                $query->Where('sort', '=', 0)
+                    ->orWhere('sort', '=', 10)
+                    ->orWhere('sort', '=', 11)
+                    ->orWhere('sort', '=', 12)
+                    ->orWhere('sort', '=', 13);
+            }
+        )->count();
+    }
+
     public function getAliveNodes()
     {
         return Node::where(
-            function ($query) {
+            static function ($query) {
                 $query->Where('sort', '=', 0)
                     ->orWhere('sort', '=', 10)
-                ->orWhere('sort', '=', 11);
+                    ->orWhere('sort', '=', 11)
+                    ->orWhere('sort', '=', 12)
+                    ->orWhere('sort', '=', 13);
             }
-        )->where('node_heartbeat', '>', time()-90)->count();
+        )->where('node_heartbeat', '>', time() - 90)->count();
     }
 }

+ 2 - 0
app/Services/Auth/Base.php

@@ -5,6 +5,8 @@ namespace App\Services\Auth;
 abstract class Base
 {
     abstract public function login($uid, $time);
+
     abstract public function logout();
+
     abstract public function getUser();
 }

+ 34 - 26
app/Services/Auth/Cookie.php

@@ -13,42 +13,41 @@ class Cookie extends Base
     public function login($uid, $time)
     {
         $user = User::find($uid);
-        $key = Hash::cookieHash($user->pass);
-        $expire_in = $time+time();
+        $expire_in = $time + time();
+        $key = Hash::cookieHash($user->pass, $expire_in);
         Utils\Cookie::set([
-            "uid" => $uid,
-            "email" => $user->email,
-            "key" => $key,
-            "ip" => md5($_SERVER["REMOTE_ADDR"].Config::get('key').$uid.$expire_in),
-            "expire_in" => $expire_in
+            'uid' => $uid,
+            'email' => $user->email,
+            'key' => $key,
+            'ip' => md5($_SERVER['REMOTE_ADDR'] . Config::get('key') . $uid . $expire_in),
+            'expire_in' => $expire_in
         ], $expire_in);
     }
 
     public function getUser()
     {
         $uid = Utils\Cookie::get('uid');
+        $email = Utils\Cookie::get('email');
         $key = Utils\Cookie::get('key');
-        $ip = Utils\Cookie::get('ip');
-        
+        $ipHash = Utils\Cookie::get('ip');
         $expire_in = Utils\Cookie::get('expire_in');
-        
+
+        $user = new User();
+        $user->isLogin = false;
+
         if ($uid == null) {
-            $user = new User();
-            $user->isLogin = false;
             return $user;
         }
-        
-        $nodes=Node::where("node_ip", "=", $_SERVER["REMOTE_ADDR"])->first();
-        if ($ip != md5($_SERVER["REMOTE_ADDR"].Config::get('key').$uid.$expire_in) && $nodes==null && Config::get('enable_login_bind_ip')=='true') {
-            $user = new User();
-            $user->isLogin = false;
+
+        if ($expire_in < time()) {
             return $user;
         }
-        
-        if ($expire_in<time()) {
-            $user = new User();
-            $user->isLogin = false;
-            return $user;
+
+        if (Config::get('enable_login_bind_ip') == 'true') {
+            $nodes = Node::where('node_ip', '=', $_SERVER['REMOTE_ADDR'])->first();
+            if (($nodes == null) && $ipHash != md5($_SERVER['REMOTE_ADDR'] . Config::get('key') . $uid . $expire_in)) {
+                return $user;
+            }
         }
 
         $user = User::find($uid);
@@ -58,10 +57,19 @@ class Cookie extends Base
             return $user;
         }
 
-        if (Hash::cookieHash($user->pass) != $key) {
+        if ($user->email != $email) {
+            $user = new User();
+            $user->isLogin = false;
+        }
+
+
+        if (Hash::cookieHash($user->pass, $expire_in) != $key) {
+            $user = new User();
             $user->isLogin = false;
             return $user;
         }
+
+
         $user->isLogin = true;
         return $user;
     }
@@ -70,9 +78,9 @@ class Cookie extends Base
     {
         $time = time() - 1000;
         Utils\Cookie::set([
-            "uid" => null,
-            "email" => null,
-            "key" => null
+            'uid' => null,
+            'email' => null,
+            'key' => null
         ], $time);
     }
 }

+ 5 - 5
app/Services/Auth/JwtToken.php

@@ -11,13 +11,13 @@ class JwtToken extends Base
     {
         $expireTime = time() + $time;
         $ary = [
-          "uid" => $uid,
-          "expire_time" => $expireTime
+            'uid' => $uid,
+            'expire_time' => $expireTime
         ];
         $decode = Jwt::encode($ary);
         Utils\Cookie::set([
             //"uid" => $uid,
-            "token" => $decode
+            'token' => $decode
         ], $expireTime);
     }
 
@@ -25,8 +25,8 @@ class JwtToken extends Base
     {
         Utils\Cookie::set([
             //"uid" => $uid,
-            "token" => ""
-        ], time()-3600);
+            'token' => ''
+        ], time() - 3600);
     }
 
     public function getUser()

+ 9 - 10
app/Services/Auth/Redis.php

@@ -21,8 +21,7 @@ class Redis extends Base
 
     public function getClient()
     {
-        $client = new RedisClient();
-        return $client;
+        return new RedisClient();
     }
 
     public function login($uid, $time)
@@ -30,10 +29,10 @@ class Redis extends Base
         $sid = Tools::genSID();
         Cookie::set([
             'sid' => $sid
-        ], $time+time());
+        ], $time + time());
         $value = $uid;
         $this->client->setex($sid, $time, $value);
-        $this->client->setex($sid."ip", $time, $_SERVER["REMOTE_ADDR"]);
+        $this->client->setex($sid . 'ip', $time, $_SERVER['REMOTE_ADDR']);
     }
 
     public function logout()
@@ -46,22 +45,22 @@ class Redis extends Base
     {
         $sid = Cookie::get('sid');
         $value = $this->client->get($sid);
-        
-        $ip = $this->client->get($sid."ip");
-        $nodes=Node::where("node_ip", "=", $_SERVER["REMOTE_ADDR"])->first();
-        if ($ip != $_SERVER["REMOTE_ADDR"] && $nodes==null && Config::get('enable_login_bind_ip')=='true') {
+
+        $ip = $this->client->get($sid . 'ip');
+        $nodes = Node::where('node_ip', '=', $_SERVER['REMOTE_ADDR'])->first();
+        if ($ip != $_SERVER['REMOTE_ADDR'] && $nodes == null && Config::get('enable_login_bind_ip') == 'true') {
             $user = new User();
             $user->isLogin = false;
             return $user;
         }
-        
+
         if ($value == null) {
             $user = new User();
             $user->isLogin = false;
             return $user;
         }
         $uid = $value;
-        $user =  User::find($uid);
+        $user = User::find($uid);
         if ($user == null) {
             $user = new User();
             $user->isLogin = false;

+ 2 - 2
app/Services/Aws/Client.php

@@ -9,8 +9,8 @@ class Client
     public function getClient()
     {
         $sdk = new Sdk([
-            'region'   => 'us-west-2',
-            'version'  => 'latest',
+            'region' => 'us-west-2',
+            'version' => 'latest',
             'DynamoDb' => [
                 'region' => 'eu-central-1'
             ]

+ 3 - 3
app/Services/Aws/Factory.php

@@ -11,11 +11,11 @@ class Factory
     {
         $sdk = new Sdk([
             'credentials' => array(
-                'key'    => Config::get('aws_access_key_id'),
+                'key' => Config::get('aws_access_key_id'),
                 'secret' => Config::get('aws_secret_access_key'),
             ),
-            'region'   => Config::get('aws_region'),
-            'version'  => 'latest',
+            'region' => Config::get('aws_region'),
+            'version' => 'latest',
             'DynamoDb' => [
                 'region' => Config::get('aws_region')
             ]

+ 43 - 0
app/Services/BitPayment.php

@@ -0,0 +1,43 @@
+<?php
+/**
+ * BitPayment - 数字货币支付接口
+ *
+ * Date: 2019/5/24
+ * Time: 11:08 AM PST
+ */
+namespace App\Services;
+
+use App\Services\Gateway\BitPay;
+
+class BitPayment
+{
+    public static function getClient()
+    {
+        return new BitPay(Config::get('bitpay_secret'));
+    }
+    public static function notify($request, $response, $args)
+    {
+        return self::getClient()->notify($request, $response, $args);
+    }
+    public static function returnHTML($request, $response, $args)
+    {
+        return self::getClient()->getReturnHTML($request, $response, $args);
+    }
+    public static function purchaseHTML()
+    {
+        $bitpayConfig = Config::get('bitpay_secret');
+        if (self::getClient() != null && $bitpayConfig != '') {
+            return self::getClient()->getPurchaseHTML();
+        }
+
+        return '';
+    }
+    public static function getStatus($request, $response, $args)
+    {
+        return self::getClient()->getStatus($request, $response, $args);
+    }
+    public static function purchase($request, $response, $args)
+    {
+        return self::getClient()->purchase($request, $response, $args);
+    }
+}

+ 9 - 5
app/Services/Boot.php

@@ -9,9 +9,10 @@ class Boot
     public static function setDebug()
     {
         // debug
-        if (Config::get('debug') == "true") {
-            define("DEBUG", true);
+        if (Config::get('debug') == 'true') {
+            define('DEBUG', true);
         }
+        View::$beginTime = microtime(true);
     }
 
     public static function setVersion($version)
@@ -28,11 +29,14 @@ class Boot
     public static function bootDb()
     {
         // Init Eloquent ORM Connection
-        $capsule = new Capsule;
-        $capsule->addConnection(Config::getDbConfig(), 'default');
-        if (Config::get('enable_radius')=='true') {
+        $capsule = new Capsule();
+        $capsule->addConnection(Config::getDbConfig());
+        if (Config::get('enable_radius') == 'true') {
             $capsule->addConnection(Config::getRadiusDbConfig(), 'radius');
         }
         $capsule->bootEloquent();
+
+        View::$connection = $capsule->getDatabaseManager();
+        $capsule->getDatabaseManager()->connection('default')->enableQueryLog();
     }
 }

+ 57 - 55
app/Services/Config.php

@@ -19,63 +19,65 @@ class Config
     public static function getPublicConfig()
     {
         return [
-            "appName" => self::get("appName"),
-            "version" => VERSION,
-            "baseUrl" => self::get("baseUrl"),
-			"min_port" => self::get("min_port"),
-			"max_port" => self::get("max_port"),
-            "checkinMin" => self::get("checkinMin"),
-            "checkinMax" => self::get("checkinMax"),
-			"invite_price"=>self::get("invite_price"),
-			"invite_get_money"=>self::get("invite_get_money"),
-            "code_payback" => self::get("code_payback"),
-			"invite_gift"=>self::get("invite_gift"),
-			"port_price" => self::get("port_price"),
-			"port_price_specify" => self::get("port_price_specify"),
-            "jump_delay" => self::get("jump_delay"),
-            "enable_analytics_code" => self::get("enable_analytics_code"),
-            "sspanelAnalysis" => self::get("sspanelAnalysis"),
-            "enable_donate" => self::get("enable_donate"),
-            "enable_telegram" => self::get("enable_telegram"),
-            "payment_system" => self::get("payment_system"),
-          	"enable_crisp" => self::get("enable_crisp"),
-          	"crisp_id" => self::get("crisp_id"),
-          	"enable_ticket"=> self::get("enable_ticket"),
-			"enable_admin_contact" => self::get("enable_admin_contact"),
-			"admin_contact1" => self::get("admin_contact1"),
-			"admin_contact2" => self::get("admin_contact2"),
-			"admin_contact3" => self::get("admin_contact3"),
-			"register_mode" => self::get("register_mode"),
-            "enable_flag" => self::get("enable_flag"),
-            "enable_kill" => self::get("enable_kill"),
-            "custom_invite_price" => self::get("custom_invite_price"),
-            "telegram_grouplink" => self::get("telegram_grouplink")
-         ];
+            'appName' => self::get('appName'),
+            'version' => VERSION,
+            'baseUrl' => self::get('baseUrl'),
+            'min_port' => self::get('min_port'),
+            'max_port' => self::get('max_port'),
+            'checkinMin' => self::get('checkinMin'),
+            'checkinMax' => self::get('checkinMax'),
+            'invite_price' => self::get('invite_price'),
+            'invite_get_money' => self::get('invite_get_money'),
+            'code_payback' => self::get('code_payback'),
+            'invite_gift' => self::get('invite_gift'),
+            'port_price' => self::get('port_price'),
+            'port_price_specify' => self::get('port_price_specify'),
+            'jump_delay' => self::get('jump_delay'),
+            'enable_analytics_code' => self::get('enable_analytics_code'),
+            'sspanelAnalysis' => self::get('sspanelAnalysis'),
+            'enable_donate' => self::get('enable_donate'),
+            'enable_telegram' => self::get('enable_telegram'),
+            'enable_discord' => self::get('enable_discord'),
+            'payment_system' => self::get('payment_system'),
+            'enable_mylivechat' => self::get('enable_mylivechat'),
+            'mylivechat_id' => self::get('mylivechat_id'),
+            'enable_ticket' => self::get('enable_ticket'),
+            'enable_admin_contact' => self::get('enable_admin_contact'),
+            'admin_contact1' => self::get('admin_contact1'),
+            'admin_contact2' => self::get('admin_contact2'),
+            'admin_contact3' => self::get('admin_contact3'),
+            'register_mode' => self::get('register_mode'),
+            'enable_flag' => self::get('enable_flag'),
+            'enable_kill' => self::get('enable_kill'),
+            'custom_invite_price' => self::get('custom_invite_price'),
+            'captcha_provider' => self::get('captcha_provider'),
+            'enable_email_verify' => self::get('enable_email_verify')
+        ];
     }
 
     public static function getDbConfig()
     {
         return [
-            'driver'    => self::get('db_driver'),
-            'host'      => self::get('db_host'),
-            'database'  => self::get('db_database'),
-            'username'  => self::get('db_username'),
-            'password'  => self::get('db_password'),
-            'charset'   => self::get('db_charset'),
+            'driver' => self::get('db_driver'),
+            'host' => self::get('db_host'),
+            'database' => self::get('db_database'),
+            'username' => self::get('db_username'),
+            'password' => self::get('db_password'),
+            'charset' => self::get('db_charset'),
             'collation' => self::get('db_collation'),
-            'prefix'    => self::get('db_prefix')
+            'prefix' => self::get('db_prefix')
         ];
     }
 
     public static function getRadiusDbConfig()
     {
         return [
-            'driver'    => self::get('db_driver'),
-            'host'      => self::get('radius_db_host'),
-            'database'  => self::get('radius_db_database'),
-            'username'  => self::get('radius_db_user'),
-            'password'  => self::get('radius_db_password'),
-            'charset'   => self::get('db_charset'),
+            'driver' => self::get('db_driver'),
+            'host' => self::get('radius_db_host'),
+            'database' => self::get('radius_db_database'),
+            'username' => self::get('radius_db_user'),
+            'password' => self::get('radius_db_password'),
+            'charset' => self::get('db_charset'),
             'collation' => self::get('db_collation')
         ];
     }
@@ -85,32 +87,32 @@ class Config
         switch ($type) {
             case 'obfs':
                 $list = array('plain', 'http_simple', 'http_simple_compatible', 'http_post', 'http_post_compatible',
-                            'tls1.2_ticket_auth', 'tls1.2_ticket_auth_compatible', 'tls1.2_ticket_fastauth', 'tls1.2_ticket_fastauth_compatible',
-                            'simple_obfs_http', 'simple_obfs_http_compatible', 'simple_obfs_tls', 'simple_obfs_tls_compatible');
+                    'tls1.2_ticket_auth', 'tls1.2_ticket_auth_compatible', 'tls1.2_ticket_fastauth', 'tls1.2_ticket_fastauth_compatible',
+                    'simple_obfs_http', 'simple_obfs_http_compatible', 'simple_obfs_tls', 'simple_obfs_tls_compatible');
                 return $list;
             case 'protocol':
                 $list = array('origin', 'verify_deflate',
-                            'auth_sha1_v4', 'auth_sha1_v4_compatible', 'auth_aes128_sha1', 'auth_aes128_md5', 'auth_chain_a', 'auth_chain_b','auth_chain_c','auth_chain_d','auth_chain_e','auth_chain_f');
+                    'auth_sha1_v4', 'auth_sha1_v4_compatible', 'auth_aes128_sha1', 'auth_aes128_md5', 'auth_chain_a', 'auth_chain_b', 'auth_chain_c', 'auth_chain_d', 'auth_chain_e', 'auth_chain_f');
                 return $list;
             case 'allow_none_protocol':
-                $list = array('auth_chain_a', 'auth_chain_b','auth_chain_c','auth_chain_d','auth_chain_e','auth_chain_f');
+                $list = array('auth_chain_a', 'auth_chain_b', 'auth_chain_c', 'auth_chain_d', 'auth_chain_e', 'auth_chain_f');
                 return $list;
             case 'relay_able_protocol':
-                $list = array('auth_aes128_md5', 'auth_aes128_sha1', 'auth_chain_a', 'auth_chain_b','auth_chain_c','auth_chain_d','auth_chain_e','auth_chain_f');
+                $list = array('auth_aes128_md5', 'auth_aes128_sha1', 'auth_chain_a', 'auth_chain_b', 'auth_chain_c', 'auth_chain_d', 'auth_chain_e', 'auth_chain_f');
                 return $list;
             case 'ss_aead_method':
                 $list = array('aes-128-gcm', 'aes-192-gcm',
-                'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305');
+                    'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305');
                 return $list;
             case 'ss_obfs':
                 $list = array('simple_obfs_http', 'simple_obfs_http_compatible', 'simple_obfs_tls', 'simple_obfs_tls_compatible');
                 return $list;
             default:
                 $list = array('rc4-md5', 'rc4-md5-6', 'aes-128-cfb', 'aes-192-cfb', 'aes-256-cfb',
-                            'aes-128-ctr', 'aes-192-ctr', 'aes-256-ctr', 'camellia-128-cfb', 'camellia-192-cfb', 'camellia-256-cfb',
-                            'bf-cfb', 'cast5-cfb', 'des-cfb', 'des-ede3-cfb', 'idea-cfb',
-                            'rc2-cfb', 'seed-cfb', 'salsa20', 'chacha20', 'xsalsa20', 'chacha20-ietf', 'aes-128-gcm', 'aes-192-gcm', 'none',
-                            'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305');
+                    'aes-128-ctr', 'aes-192-ctr', 'aes-256-ctr', 'camellia-128-cfb', 'camellia-192-cfb', 'camellia-256-cfb',
+                    'bf-cfb', 'cast5-cfb', 'des-cfb', 'des-ede3-cfb', 'idea-cfb',
+                    'rc2-cfb', 'seed-cfb', 'salsa20', 'chacha20', 'xsalsa20', 'chacha20-ietf', 'aes-128-gcm', 'aes-192-gcm', 'none',
+                    'aes-256-gcm', 'chacha20-ietf-poly1305', 'xchacha20-ietf-poly1305');
                 return $list;
         }
     }

+ 39 - 36
app/Services/Gateway/AbstractPayment.php

@@ -18,71 +18,74 @@ use App\Utils\Telegram;
 abstract class AbstractPayment
 {
     abstract public function purchase($request, $response, $args);
+
     abstract public function notify($request, $response, $args);
+
     abstract public function getPurchaseHTML();
+
     abstract public function getReturnHTML($request, $response, $args);
+
     abstract public function getStatus($request, $response, $args);
 
-    public function postPayment($pid, $method){
-        $p = Paylist::where("tradeno", $pid)->first();
+    public function postPayment($pid, $method)
+    {
+        $p = Paylist::where('tradeno', $pid)->first();
 
-        if($p->status==1){
-            return json_encode(['errcode'=>0]);
+        if ($p->status == 1) {
+            return json_encode(['errcode' => 0]);
         }
 
-        $p->status=1;
+        $p->status = 1;
         $p->save();
         $user = User::find($p->userid);
         $user->money += $p->total;
         $user->save();
-        $codeq=new Code();
-        $codeq->code=$method;
-        $codeq->isused=1;
-        $codeq->type=-1;
-        $codeq->number=$p->total;
-        $codeq->usedatetime=date("Y-m-d H:i:s");
-        $codeq->userid=$user->id;
+        $codeq = new Code();
+        $codeq->code = $method;
+        $codeq->isused = 1;
+        $codeq->type = -1;
+        $codeq->number = $p->total;
+        $codeq->usedatetime = date('Y-m-d H:i:s');
+        $codeq->userid = $user->id;
         $codeq->save();
 
         if ($user->ref_by >= 1) {
-            $gift_user=User::where("id", "=", $user->ref_by)->first();
-            $gift_user->money=($gift_user->money+($codeq->number*(Config::get('code_payback')/100)));
+            $gift_user = User::where('id', '=', $user->ref_by)->first();
+            $gift_user->money += ($codeq->number * (Config::get('code_payback') / 100));
             $gift_user->save();
-            $Payback=new Payback();
-            $Payback->total=$codeq->number;
-            $Payback->userid=$user->id;
-            $Payback->ref_by=$user->ref_by;
-            $Payback->ref_get=$codeq->number*(Config::get('code_payback')/100);
-            $Payback->datetime=time();
+            $Payback = new Payback();
+            $Payback->total = $codeq->number;
+            $Payback->userid = $user->id;
+            $Payback->ref_by = $user->ref_by;
+            $Payback->ref_get = $codeq->number * (Config::get('code_payback') / 100);
+            $Payback->datetime = time();
             $Payback->save();
         }
 
         if (Config::get('enable_donate') == 'true') {
             if ($user->is_hide == 1) {
-                Telegram::Send("一位不愿透露姓名的大老爷给我们捐了 ".$codeq->number." 元!");
+                Telegram::Send('一位不愿透露姓名的大老爷给我们捐了 ' . $codeq->number . ' 元!');
             } else {
-                Telegram::Send($user->user_name." 大老爷给我们捐了 ".$codeq->number." 元!");
+                Telegram::Send($user->user_name . ' 大老爷给我们捐了 ' . $codeq->number . ' 元!');
             }
         }
         return 0;
-
     }
 
-    public static function generateGuid() {
-        mt_srand((double)microtime()*10000);
-        $charid = strtoupper(md5(uniqid(rand() + time(), true)));
+    public static function generateGuid()
+    {
+        mt_srand((double)microtime() * 10000);
+        $charid = strtoupper(md5(uniqid(mt_rand() + time(), true)));
         $hyphen = chr(45);
-        $uuid   = chr(123)
-            .substr($charid, 0, 8).$hyphen
-            .substr($charid, 8, 4).$hyphen
-            .substr($charid,12, 4).$hyphen
-            .substr($charid,16, 4).$hyphen
-            .substr($charid,20,12)
-            .chr(125);
-        $uuid = str_replace(['}', '{', '-'],'',$uuid);
+        $uuid = chr(123)
+            . substr($charid, 0, 8) . $hyphen
+            . substr($charid, 8, 4) . $hyphen
+            . substr($charid, 12, 4) . $hyphen
+            . substr($charid, 16, 4) . $hyphen
+            . substr($charid, 20, 12)
+            . chr(125);
+        $uuid = str_replace(['}', '{', '-'], '', $uuid);
         $uuid = substr($uuid, 0, 8);
         return $uuid;
     }
-
-
 }

+ 23 - 22
app/Services/Gateway/AopF2F.php

@@ -10,32 +10,33 @@ namespace App\Services\Gateway;
 
 use App\Services\Auth;
 use App\Services\Config;
-use App\Models\Code;
 use App\Models\Paylist;
 use App\Services\View;
+use Exception;
 use Omnipay\Omnipay;
 
 class AopF2F extends AbstractPayment
 {
-    private function createGateway(){
+    private function createGateway()
+    {
         $gateway = Omnipay::create('Alipay_AopF2F');
         $gateway->setSignType('RSA2'); //RSA/RSA2
-        $gateway->setAppId(Config::get("f2fpay_app_id"));
-        $gateway->setPrivateKey(Config::get("merchant_private_key")); // 可以是路径,也可以是密钥内容
-        $gateway->setAlipayPublicKey(Config::get("alipay_public_key")); // 可以是路径,也可以是密钥内容
-        $gateway->setNotifyUrl(Config::get("baseUrl")."/payment/notify");
+        $gateway->setAppId(Config::get('f2fpay_app_id'));
+        $gateway->setPrivateKey(Config::get('merchant_private_key')); // 可以是路径,也可以是密钥内容
+        $gateway->setAlipayPublicKey(Config::get('alipay_public_key')); // 可以是路径,也可以是密钥内容
+        $gateway->setNotifyUrl(Config::get('baseUrl') . '/payment/notify');
 
         return $gateway;
     }
 
 
-    function purchase($request, $response, $args)
+    public function purchase($request, $response, $args)
     {
         $amount = $request->getParam('amount');
         $user = Auth::getUser();
-        if ($amount == "") {
+        if ($amount == '') {
             $res['ret'] = 0;
-            $res['msg'] = "订单金额错误:" . $amount;
+            $res['msg'] = '订单金额错误:' . $amount;
             return $response->getBody()->write(json_encode($res));
         }
 
@@ -45,11 +46,11 @@ class AopF2F extends AbstractPayment
         $pl->total = $amount;
         $pl->save();
 
-        $gateway = self::createGateway();
+        $gateway = $this->createGateway();
 
         $request = $gateway->purchase();
         $request->setBizContent([
-            'subject'      => "¥".$pl->total." - ".Config::get("appName")." - {$user->user_name}({$user->email})",
+            'subject' => $pl->tradeno,
             'out_trade_no' => $pl->tradeno,
             'total_amount' => $pl->total
         ]);
@@ -68,9 +69,9 @@ class AopF2F extends AbstractPayment
         return json_encode($return);
     }
 
-    function notify($request, $response, $args)
+    public function notify($request, $response, $args)
     {
-        $gateway = self::createGateway();
+        $gateway = $this->createGateway();
         $aliRequest = $gateway->completePurchase();
         $aliRequest->setParams($_POST);
 
@@ -78,31 +79,31 @@ class AopF2F extends AbstractPayment
             /** @var \Omnipay\Alipay\Responses\AopCompletePurchaseResponse $response */
             $aliResponse = $aliRequest->send();
             $pid = $aliResponse->data('out_trade_no');
-            if($aliResponse->isPaid()){
-                self::postPayment($pid, "支付宝当面付");
+            if ($aliResponse->isPaid()) {
+                $this->postPayment($pid, '支付宝当面付');
                 die('success'); //The response should be 'success' only
             }
-        } catch (\Exception $e) {
+        } catch (Exception $e) {
             die('fail');
         }
     }
 
 
-    function getPurchaseHTML()
+    public function getPurchaseHTML()
     {
-        return View::getSmarty()->fetch("user/aopf2f.tpl");
+        return View::getSmarty()->fetch('user/aopf2f.tpl');
     }
 
-    function getReturnHTML($request, $response, $args)
+    public function getReturnHTML($request, $response, $args)
     {
         return 0;
     }
 
-    function getStatus($request, $response, $args)
+    public function getStatus($request, $response, $args)
     {
-        $p = Paylist::where("tradeno", $_POST['pid'])->first();
+        $p = Paylist::where('tradeno', $_POST['pid'])->first();
         $return['ret'] = 1;
         $return['result'] = $p->status;
         return json_encode($return);
     }
-}
+}

Some files were not shown because too many files changed in this diff