Browse Source

1.优化定时任务
2.V2Ray Mu API

bingo 7 years ago
parent
commit
71e3bc805a
38 changed files with 811 additions and 1490 deletions
  1. 8 7
      app/Components/Namesilo.php
  2. 3 3
      app/Components/ServerChan.php
  3. 0 91
      app/Console/Commands/AutoBanSubscribeJob.php
  4. 0 67
      app/Console/Commands/AutoBanUserJob.php
  5. 0 100
      app/Console/Commands/AutoCheckNodeStatusJob.php
  6. 4 4
      app/Console/Commands/AutoClearLog.php
  7. 0 52
      app/Console/Commands/AutoCloseOrderJob.php
  8. 13 11
      app/Console/Commands/AutoDecGoodsTraffic.php
  9. 0 45
      app/Console/Commands/AutoDisableExpireUserJob.php
  10. 0 44
      app/Console/Commands/AutoDisableUserJob.php
  11. 0 30
      app/Console/Commands/AutoExpireCouponJob.php
  12. 0 30
      app/Console/Commands/AutoExpireInviteJob.php
  13. 318 0
      app/Console/Commands/AutoJob.php
  14. 0 81
      app/Console/Commands/AutoRegetPortJob.php
  15. 0 49
      app/Console/Commands/AutoReleasePortJob.php
  16. 0 32
      app/Console/Commands/AutoRemoveDisabledUserLabelsJob.php
  17. 0 58
      app/Console/Commands/AutoReopenUserJob.php
  18. 75 0
      app/Console/Commands/AutoResetUserTraffic.php
  19. 0 72
      app/Console/Commands/AutoResetUserTrafficJob.php
  20. 2 2
      app/Console/Commands/AutoStatisticsNodeDailyTraffic.php
  21. 2 2
      app/Console/Commands/AutoStatisticsNodeHourlyTraffic.php
  22. 3 3
      app/Console/Commands/AutoStatisticsUserDailyTraffic.php
  23. 3 3
      app/Console/Commands/AutoStatisticsUserHourlyTraffic.php
  24. 3 3
      app/Console/Commands/UserExpireAutoWarning.php
  25. 3 3
      app/Console/Commands/UserTrafficAbnormalAutoWarning.php
  26. 3 3
      app/Console/Commands/UserTrafficAutoWarning.php
  27. 28 44
      app/Console/Kernel.php
  28. 0 301
      app/Http/Controllers/Api/V2rayController.php
  29. 0 240
      app/Http/Controllers/Mu/v2ray/NodeController.php
  30. 0 78
      app/Http/Controllers/Mu/v2ray/UserController.php
  31. 230 0
      app/Http/Controllers/Muv2/NodeController.php
  32. 77 0
      app/Http/Controllers/Muv2/UserController.php
  33. 5 5
      app/Http/Middleware/Muv2.php
  34. 1 1
      app/Http/Middleware/VerifyCsrfToken.php
  35. 1 1
      app/Http/V2ray/EmptyClass.php
  36. 18 17
      app/Http/V2ray/Generator.php
  37. 2 0
      routes/api.php
  38. 9 8
      routes/web.php

+ 8 - 7
app/Components/Namesilo.php

@@ -9,10 +9,12 @@ use Log;
 
 class Namesilo
 {
+    protected static $host;
     protected static $config;
 
     function __construct()
     {
+        self::$host = 'https://www.namesilo.com/api/';
         self::$config = $this->systemConfig();
     }
 
@@ -77,26 +79,25 @@ class Namesilo
         $params = [
             'version' => 1,
             'type'    => 'xml',
-            //'key'     => self::$config['namesilo_key']
-            'key'     => '12d47532c95c7013b1ecc9a06'
+            'key'     => self::$config['namesilo_key']
         ];
         $query = array_merge($params, $data);
 
         $content = '请求操作:[' . $operation . '] --- 请求数据:[' . http_build_query($query) . ']';
 
         try {
-            $result = $this->curlRequest('https://www.namesilo.com/api/' . $operation . '?' . http_build_query($query));
+            $result = $this->curlRequest(self::$host . $operation . '?' . http_build_query($query));
             $result = XML2Array::createArray($result);
 
             // 出错
             if (empty($result['namesilo']) || $result['namesilo']['reply']['code'] != 300 || $result['namesilo']['reply']['detail'] != 'success') {
-                $this->sendEmailLog(1, '[Namesilo API] - [' . $operation . ']', $content, 0, $result['namesilo']['reply']['detail']);
+                $this->addEmailLog(1, '[Namesilo API] - [' . $operation . ']', $content, 0, $result['namesilo']['reply']['detail']);
             }
 
             return $result['namesilo']['reply'];
         } catch (\Exception $e) {
             Log::error('CURL请求失败:' . $e->getMessage() . ' --- ' . $e->getLine());
-            $this->sendEmailLog(1, '[Namesilo API] - [' . $operation . ']', $content, 0, $e->getMessage());
+            $this->addEmailLog(1, '[Namesilo API] - [' . $operation . ']', $content, 0, $e->getMessage());
 
             return false;
         }
@@ -111,7 +112,7 @@ class Namesilo
      * @param int    $status  投递状态
      * @param string $error   投递失败时记录的异常信息
      */
-    private function sendEmailLog($user_id, $title, $content, $status = 1, $error = '')
+    private function addEmailLog($user_id, $title, $content, $status = 1, $error = '')
     {
         $emailLogObj = new EmailLog();
         $emailLogObj->user_id = $user_id;
@@ -136,7 +137,7 @@ class Namesilo
     }
 
     // 发起一个CURL请求
-    private function curlRequest($url, $data = null)
+    private function curlRequest($url, $data = [])
     {
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

+ 3 - 3
app/Components/ServerChan.php

@@ -37,9 +37,9 @@ class ServerChan
 
             $result = json_decode($response->getBody());
             if (!$result->errno) {
-                $this->sendEmailLog(1, '[ServerChan]' . $title, $content);
+                $this->addEmailLog(1, '[ServerChan]' . $title, $content);
             } else {
-                $this->sendEmailLog(1, '[ServerChan]' . $title, $content, 0, $result->errmsg);
+                $this->addEmailLog(1, '[ServerChan]' . $title, $content, 0, $result->errmsg);
             }
         } catch (RequestException $e) {
             Log::error(Psr7\str($e->getRequest()));
@@ -58,7 +58,7 @@ class ServerChan
      * @param int    $status  投递状态
      * @param string $error   投递失败时记录的异常信息
      */
-    private function sendEmailLog($user_id, $title, $content, $status = 1, $error = '')
+    private function addEmailLog($user_id, $title, $content, $status = 1, $error = '')
     {
         $emailLogObj = new EmailLog();
         $emailLogObj->user_id = $user_id;

+ 0 - 91
app/Console/Commands/AutoBanSubscribeJob.php

@@ -1,91 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\Config;
-use App\Http\Models\UserSubscribe;
-use App\Http\Models\UserSubscribeLog;
-use Log;
-
-class AutoBanSubscribeJob extends Command
-{
-    protected $signature = 'autoBanSubscribeJob';
-    protected $description = '自动封禁异常订阅链接';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        /*
-         * 客户端请求头有多种,常见如下:
-         * SSR、SSRR安卓客户端:
-         *      okhttp/3.8.0
-         *      Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; MX4 Pro Build/KTU84P) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
-         *
-         * Shadowrocket:
-         *      Shadowrocket/516 CFNetwork/893.14.2 Darwin/17.3.0
-         *      Shadowrocket/510 CFNetwork/893.14.2 Darwin/17.3.0
-         *      Shadowrocket/510 CFNetwork/889.9 Darwin/17.2.0
-         *      Shadowrocket/510 CFNetwork/811.5.4 Darwin/16.7.0
-         *      Shadowrocket/510 CFNetwork/811.5.4 Darwin/16.6.0
-         *      Shadowrocket/510 CFNetwork/808.0.2 Darwin/16.0.0
-         *      Shadowrocket/510 CFNetwork/758.4.3 Darwin/15.5.0
-         *      Shadowrocket/510 CFNetwork/897.15 Darwin/17.5.0
-         *      Shadowrocket/2.1.11 (iPhone; iOS 10.3.3; Scale/3.00)
-         *      Shadowrocket/2.1.10 (iPhone; iOS 11.1.2; Scale/2.00)
-         *      Shadowrocket/2.1.12 (iPhone; iOS 10.3.2; Scale/3.00)
-         *      Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H143 Safari/600.1.4
-         * ShadowsocksR win版:
-         *      Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.3319.102 Safari/537.36
-         *      Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
-         *      Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
-         * 梅林固件:
-         *      curl/7.21.7 (arm-unknown-linux-gnu) libcurl/7.54.1 OpenSSL/1.0.2n zlib/1.2.5
-         *      curl/7.21.7 (arm-unknown-linux-gnu) libcurl/7.54.1 OpenSSL/1.0.2l zlib/1.2.5
-         *  curl/7.59.0
-         * curl/7.60.0
-         * curl/7.37.1
-         * Mac SSR:
-         *      ShadowsocksX-NG-R
-         *      ShadowsocksX-NG-R 1.4.1-R8 Version 4
-         *      ShadowsocksX-NG-R 1.4.3-R8 Version 2
-         *      ShadowsocksX-NG-R 1.4.3-R8 Version 3
-         *      Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36
-         *      Mozilla/5.0 (Linux; Android 8.0.0; BLA-AL00 Build/HUAWEIBLA-AL00; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/62.0.3202.84 Mobile Safari/537.36 MicroMessenger/6.6.1.1220(0x26060135) NetType/4G Language/zh_CN
-         * 带Cloudflare CDN:Cf-Connecting-Ip Cf-Ray Cf-Visitor
-         */
-
-        $config = $this->systemConfig();
-
-        // 封禁24小时访问异常的订阅链接
-        if ($config['is_subscribe_ban']) {
-            $subscribeList = UserSubscribe::query()->where('status', 1)->get();
-            if (!$subscribeList->isEmpty()) {
-                foreach ($subscribeList as $subscribe) {
-                    // 24小时内不同IP的请求次数
-                    $request_times = UserSubscribeLog::query()->where('sid', $subscribe->id)->where('request_time', '>=', date("Y-m-d H:i:s", strtotime("-24 hours")))->distinct('request_ip')->count('request_ip');
-                    if ($request_times >= $config['subscribe_ban_times']) {
-                        UserSubscribe::query()->where('id', $subscribe->id)->update(['status' => 0, 'ban_time' => time(), 'ban_desc' => '存在异常,自动封禁']);
-                    }
-                }
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    // 系统配置
-    private function systemConfig() {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-}

+ 0 - 67
app/Console/Commands/AutoBanUserJob.php

@@ -1,67 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\Config;
-use App\Http\Models\UserBanLog;
-use App\Http\Models\User;
-use App\Http\Models\UserTrafficHourly;
-use Log;
-
-class AutoBanUserJob extends Command
-{
-    protected $signature = 'autoBanUserJob';
-    protected $description = '自动封禁用户';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $config = $this->systemConfig();
-
-        // 封禁24小时内流量异常账号
-        if ($config['is_traffic_ban']) {
-            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->where('ban_time', '>=', 0)->get();
-            if (!$userList->isEmpty()) {
-                foreach ($userList as $user) {
-                    $time = date('Y-m-d H:i:s', time() - 24 * 60 * 60);
-                    $totalTraffic = UserTrafficHourly::query()->where('user_id', $user->id)->where('node_id', 0)->where('created_at', '>=', $time)->sum('total');
-                    if ($totalTraffic >= ($config['traffic_ban_value'] * 1024 * 1024 * 1024)) {
-                        $ban_time = strtotime(date('Y-m-d H:i:s', strtotime("+" . $config['traffic_ban_time'] . " minutes")));
-                        User::query()->where('id', $user->id)->update(['enable' => 0, 'ban_time' => $ban_time]);
-
-                        // 写入日志
-                        $this->log($user->id, $config['traffic_ban_time'], '【自动封禁】-24小时内流量异常');
-                    }
-                }
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    // 系统配置
-    private function systemConfig()
-    {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-
-    private function log($user_id, $minutes, $desc)
-    {
-        $log = new UserBanLog();
-        $log->user_id = $user_id;
-        $log->minutes = $minutes;
-        $log->desc = $desc;
-        $log->save();
-    }
-}

+ 0 - 100
app/Console/Commands/AutoCheckNodeStatusJob.php

@@ -1,100 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use App\Components\ServerChan;
-use Illuminate\Console\Command;
-use App\Http\Models\Config;
-use App\Http\Models\SsNode;
-use App\Http\Models\SsNodeInfo;
-use App\Http\Models\EmailLog;
-use App\Mail\nodeCrashWarning;
-use Cache;
-use Mail;
-use Log;
-
-class AutoCheckNodeStatusJob extends Command
-{
-    protected $signature = 'autoCheckNodeStatusJob';
-    protected $description = '自动监测节点是否宕机';
-    protected $cacheKey = 'node_shutdown_warning_';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $config = $this->systemConfig();
-
-        $nodeList = SsNode::query()->where('status', 1)->get();
-        foreach ($nodeList as $node) {
-            // 10分钟内无节点负载信息则认为是宕机
-            $node_info = SsNodeInfo::query()->where('node_id', $node->id)->where('log_time', '>=', strtotime("-10 minutes"))->orderBy('id', 'desc')->first();
-            if (empty($node_info) || empty($node_info->load)) {
-                // 10分钟内已发警告,则不再发
-                if (Cache::has($this->cacheKey . $node->id)) {
-                    continue;
-                }
-
-                $title = "节点宕机警告";
-                $content = "节点**{$node->name}【{$node->server}】({$node->ip})**可能宕机,请及时检查。";
-
-                // 发邮件通知管理员
-                if ($config['is_node_crash_warning'] && $config['crash_warning_email']) {
-                    try {
-                        Mail::to($config['crash_warning_email'])->send(new nodeCrashWarning($config['website_name'], $node->name, $node->server));
-                        $this->sendEmailLog(1, $title, $content);
-                    } catch (\Exception $e) {
-                        $this->sendEmailLog(1, $title, $content, 0, $e->getMessage());
-                    }
-                }
-
-                // 通过ServerChan发微信消息提醒管理员
-                if ($config['is_server_chan'] && $config['server_chan_key']) {
-                    $serverChan = new ServerChan();
-                    $serverChan->send($title, $content);
-                }
-
-                // 写入发信缓存
-                Cache::put($this->cacheKey . $node->id, $node->name . '(' . $node->server . ')', 10);
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    /**
-     * 写入邮件发送日志
-     *
-     * @param int    $user_id 接收者用户ID
-     * @param string $title   标题
-     * @param string $content 内容
-     * @param int    $status  投递状态
-     * @param string $error   投递失败时记录的异常信息
-     */
-    private function sendEmailLog($user_id, $title, $content, $status = 1, $error = '')
-    {
-        $emailLogObj = new EmailLog();
-        $emailLogObj->user_id = $user_id;
-        $emailLogObj->title = $title;
-        $emailLogObj->content = $content;
-        $emailLogObj->status = $status;
-        $emailLogObj->error = $error;
-        $emailLogObj->created_at = date('Y-m-d H:i:s');
-        $emailLogObj->save();
-    }
-
-    // 系统配置
-    private function systemConfig()
-    {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-}

+ 4 - 4
app/Console/Commands/AutoClearLogJob.php → app/Console/Commands/AutoClearLog.php

@@ -2,18 +2,18 @@
 
 namespace App\Console\Commands;
 
+use Illuminate\Console\Command;
+use App\Http\Models\Config;
 use App\Http\Models\SsNodeInfo;
 use App\Http\Models\SsNodeOnlineLog;
 use App\Http\Models\SsNodeTrafficHourly;
 use App\Http\Models\UserTrafficLog;
-use Illuminate\Console\Command;
-use App\Http\Models\Config;
 use App\Http\Models\UserTrafficHourly;
 use Log;
 
-class AutoClearLogJob extends Command
+class AutoClearLog extends Command
 {
-    protected $signature = 'autoClearLogJob';
+    protected $signature = 'autoClearLog';
     protected $description = '自动清除日志';
 
     public function __construct()

+ 0 - 52
app/Console/Commands/AutoCloseOrderJob.php

@@ -1,52 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use App\Http\Models\Coupon;
-use App\Http\Models\Order;
-use App\Http\Models\Payment;
-use Illuminate\Console\Command;
-use Log;
-use DB;
-
-class AutoCloseOrderJob extends Command
-{
-    protected $signature = 'autoCloseOrderJob';
-    protected $description = '自动关闭超时未支付订单';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        // 有赞云超过60分钟未支付则自动关闭,我们这则只给30分钟
-        $paymentList = Payment::query()->with(['order'])->where('status', 0)->where('created_at', '<=', date("Y-m-d H:i:s", strtotime("-30 minutes")))->get();
-        if (!$paymentList->isEmpty()) {
-            DB::beginTransaction();
-            try {
-                foreach ($paymentList as $payment) {
-                    // 关闭支付单
-                    Payment::query()->where('id', $payment->id)->update(['status' => -1]);
-
-                    // 关闭订单
-                    Order::query()->where('oid', $payment->oid)->update(['status' => -1]);
-
-                    // 退回优惠券
-                    if ($payment->order->coupon_id) {
-                        Coupon::query()->where('id', $payment->order->coupon_id)->update(['status' => 0]);
-                    }
-                }
-
-                DB::commit();
-            } catch (\Exception $e) {
-                Log::info('【异常】自动关闭超时未支付订单:' . $e->getMessage());
-
-                DB::rollBack();
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-}

+ 13 - 11
app/Console/Commands/AutoDecGoodsTrafficJob.php → app/Console/Commands/AutoDecGoodsTraffic.php

@@ -2,17 +2,18 @@
 
 namespace App\Console\Commands;
 
-use App\Http\Models\Config;
-use App\Http\Models\GoodsLabel;
-use App\Http\Models\UserLabel;
 use Illuminate\Console\Command;
+use App\Http\Models\Config;
 use App\Http\Models\Order;
 use App\Http\Models\User;
+use App\Http\Models\UserLabel;
+use App\Http\Models\GoodsLabel;
+
 use Log;
 
-class AutoDecGoodsTrafficJob extends Command
+class AutoDecGoodsTraffic extends Command
 {
-    protected $signature = 'autoDecGoodsTrafficJob';
+    protected $signature = 'autoDecGoodsTraffic';
     protected $description = '自动扣减用户到期流量包的流量';
 
     public function __construct()
@@ -22,7 +23,7 @@ class AutoDecGoodsTrafficJob extends Command
 
     public function handle()
     {
-        $orderList = Order::query()->with(['user', 'goods'])->where('status', 2)->where('is_expire', 0)->get();
+        $orderList = Order::query()->with(['user', 'goods'])->where('status', 2)->where('is_expire', 0)->where('expire_at', '>=', date('Y-m-d H:i:s'))->get();
         if (!$orderList->isEmpty()) {
             $config = $this->systemConfig();
 
@@ -48,13 +49,14 @@ class AutoDecGoodsTrafficJob extends Command
                     // 删除该商品对应用户的所有标签
                     UserLabel::query()->where('user_id', $order->user->id)->delete();
 
-                    // 取出用户的全部其他商品并打上对应的标签
-                    $goodsIds = Order::query()->where('user_id', $order->user->id)->where('oid', '<>', $order->oid)->where('is_expire', 0)->groupBy('goods_id')->pluck('goods_id')->toArray();
+                    // 取出用户的其他商品带有的标签
+                    $goodsIds = Order::query()->where('user_id', $order->user->id)->where('oid', '<>', $order->oid)->where('status', 2)->where('is_expire', 0)->groupBy('goods_id')->pluck('goods_id')->toArray();
                     $goodsLabels = GoodsLabel::query()->whereIn('goods_id', $goodsIds)->groupBy('label_id')->pluck('label_id')->toArray();
 
-                    // 合并默认标签
-                    $labels = $defaultLabels ? array_merge($goodsLabels, $defaultLabels) : $goodsLabels;
-                    $labels = array_unique($labels); // 去重
+                    // 标签去重
+                    $labels = array_merge($goodsLabels, $defaultLabels);
+                    $labels = array_unique($labels);
+                    $labels = array_values($labels);
                     foreach ($labels as $vo) {
                         $userLabel = new UserLabel();
                         $userLabel->user_id = $order->user->id;

+ 0 - 45
app/Console/Commands/AutoDisableExpireUserJob.php

@@ -1,45 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\Config;
-use App\Http\Models\User;
-use Log;
-
-class autoDisableExpireUserJob extends Command
-{
-    protected $signature = 'autoDisableExpireUserJob';
-    protected $description = '自动禁用到期用户';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        // 到期账号禁用
-        $config = $this->systemConfig();
-
-        if ($config['is_ban_status']) {
-            User::query()->where('enable', 1)->where('expire_time', '<=', date('Y-m-d'))->update(['enable' => 0, 'status' => -1]);
-        } else {
-            User::query()->where('enable', 1)->where('expire_time', '<=', date('Y-m-d'))->update(['enable' => 0]);
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    // 系统配置
-    private function systemConfig()
-    {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-}

+ 0 - 44
app/Console/Commands/AutoDisableUserJob.php

@@ -1,44 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\UserBanLog;
-use App\Http\Models\User;
-use Log;
-
-class autoDisableUserJob extends Command
-{
-    protected $signature = 'autoDisableUserJob';
-    protected $description = '自动禁用流量超限的用户';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        // 禁用流量超限账号
-        $userList = User::query()->where('enable', 1)->whereRaw("u + d >= transfer_enable")->get();
-        if (!$userList->isEmpty()) {
-            foreach ($userList as $user) {
-                User::query()->where('id', $user->id)->update(['enable' => 0, 'ban_time' => -1]);
-
-                // 写入日志
-                $this->log($user->id, '【自动封禁】-流量超限');
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    private function log($user_id, $desc)
-    {
-        $log = new UserBanLog();
-        $log->user_id = $user_id;
-        $log->minutes = 0;
-        $log->desc = $desc;
-        $log->save();
-    }
-}

+ 0 - 30
app/Console/Commands/AutoExpireCouponJob.php

@@ -1,30 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\Coupon;
-use Log;
-
-class AutoExpireCouponJob extends Command
-{
-    protected $signature = 'autoExpireCouponJob';
-    protected $description = '优惠券到期自动置无效';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $couponList = Coupon::query()->where('status', 0)->where('available_end', '<=', time())->get();
-        if (!$couponList->isEmpty()) {
-            foreach ($couponList as $coupon) {
-                Coupon::query()->where('id', $coupon->id)->update(['status' => 2]);
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-}

+ 0 - 30
app/Console/Commands/AutoExpireInviteJob.php

@@ -1,30 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\Invite;
-use Log;
-
-class AutoExpireInviteJob extends Command
-{
-    protected $signature = 'autoExpireInviteJob';
-    protected $description = '邀请码过期自动置无效';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $inviteList = Invite::query()->where('status', 0)->where('dateline', '<=', date('Y-m-d H:i:s'))->get();
-        if (!$inviteList->isEmpty()) {
-            foreach ($inviteList as $invite) {
-                Invite::query()->where('id', $invite->id)->update(['status' => 2]);
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-}

+ 318 - 0
app/Console/Commands/AutoJob.php

@@ -0,0 +1,318 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use App\Components\ServerChan;
+use App\Http\Models\Coupon;
+use App\Http\Models\EmailLog;
+use App\Http\Models\Invite;
+use App\Http\Models\Order;
+use App\Http\Models\Payment;
+use App\Http\Models\Config;
+use App\Http\Models\SsNode;
+use App\Http\Models\SsNodeInfo;
+use App\Http\Models\User;
+use App\Http\Models\UserLabel;
+use App\Http\Models\UserBanLog;
+use App\Http\Models\UserSubscribe;
+use App\Http\Models\UserSubscribeLog;
+use App\Http\Models\UserTrafficHourly;
+use App\Mail\nodeCrashWarning;
+use Cache;
+use Mail;
+use Log;
+use DB;
+
+class AutoJob extends Command
+{
+    protected $signature = 'autoJob';
+    protected $description = '自动化任务';
+    protected $cacheKey = 'node_shutdown_warning_';
+
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    /*
+     * 以下操作顺序如果随意挪动可能导致出现异常
+     */
+    public function handle()
+    {
+        $config = $this->systemConfig();
+
+        // 优惠券到期自动置无效
+        $couponList = Coupon::query()->where('status', 0)->where('available_end', '<=', time())->get();
+        if (!$couponList->isEmpty()) {
+            foreach ($couponList as $coupon) {
+                Coupon::query()->where('id', $coupon->id)->update(['status' => 2]);
+            }
+        }
+
+        // 邀请码到期自动置无效
+        $inviteList = Invite::query()->where('status', 0)->where('dateline', '<=', date('Y-m-d H:i:s'))->get();
+        if (!$inviteList->isEmpty()) {
+            foreach ($inviteList as $invite) {
+                Invite::query()->where('id', $invite->id)->update(['status' => 2]);
+            }
+        }
+
+        // 封禁24小时访问异常的订阅链接
+        if ($config['is_subscribe_ban']) {
+            $subscribeList = UserSubscribe::query()->where('status', 1)->get();
+            if (!$subscribeList->isEmpty()) {
+                foreach ($subscribeList as $subscribe) {
+                    // 24小时内不同IP的请求次数
+                    $request_times = UserSubscribeLog::query()->where('sid', $subscribe->id)->where('request_time', '>=', date("Y-m-d H:i:s", strtotime("-24 hours")))->distinct('request_ip')->count('request_ip');
+                    if ($request_times >= $config['subscribe_ban_times']) {
+                        UserSubscribe::query()->where('id', $subscribe->id)->update(['status' => 0, 'ban_time' => time(), 'ban_desc' => '存在异常,自动封禁']);
+
+                        // 记录封禁日志
+                        $this->addUserBanLog($subscribe->user_id, 0, '【完全封禁订阅】-订阅24小时内请求异常');
+                    }
+                }
+            }
+        }
+
+        // 封禁24小时内流量异常账号
+        if ($config['is_traffic_ban']) {
+            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->where('ban_time', '>=', 0)->get();
+            if (!$userList->isEmpty()) {
+                foreach ($userList as $user) {
+                    $time = date('Y-m-d H:i:s', time() - 24 * 60 * 60);
+                    $totalTraffic = UserTrafficHourly::query()->where('user_id', $user->id)->where('node_id', 0)->where('created_at', '>=', $time)->sum('total');
+                    if ($totalTraffic >= ($config['traffic_ban_value'] * 1024 * 1024 * 1024)) {
+                        $ban_time = strtotime(date('Y-m-d H:i:s', strtotime("+" . $config['traffic_ban_time'] . " minutes")));
+                        User::query()->where('id', $user->id)->update(['enable' => 0, 'ban_time' => $ban_time]);
+
+                        // 写入日志
+                        $this->addUserBanLog($user->id, $config['traffic_ban_time'], '【临时封禁代理】-24小时内流量异常');
+                    }
+                }
+            }
+        }
+
+        // SSR(R)被启用说明用户购买了流量,需要重置ban_time,防止异常
+        User::query()->where('enable', 1)->where('ban_time', -1)->update(['ban_time' => 0]);
+
+        // 禁用流量超限用户
+        $userList = User::query()->where('enable', 1)->whereRaw("u + d >= transfer_enable")->get();
+        if (!$userList->isEmpty()) {
+            foreach ($userList as $user) {
+                User::query()->where('id', $user->id)->update(['enable' => 0, 'ban_time' => -1]);
+
+                // 写入日志
+                $this->addUserBanLog($user->id, 0, '【完全封禁代理】-流量已用完');
+            }
+        }
+
+        // 自动禁用过期用户
+        $userList = User::query()->where('enable', 1)->where('expire_time', '<=', date('Y-m-d'))->get();
+        if (!$userList->isEmpty()) {
+            foreach ($userList as $user) {
+                if ($config['is_ban_status']) {
+                    User::query()->where('id', $user->id)->update(['enable' => 0, 'status' => -1, 'ban_time' => -1]);
+
+                    $this->addUserBanLog($user->id, 0, '【完全封禁账号及代理】-账号已过期');
+                } else {
+                    User::query()->where('id', $user->id)->update(['enable' => 0, 'ban_time' => -1]);
+
+                    $this->addUserBanLog($user->id, 0, '【完全封禁代理】-账号已过期');
+                }
+            }
+        }
+
+        // 自动移除被封禁账号的标签
+        $userList = User::query()->where('enable', 0)->where('ban_time', -1)->get();
+        if (!$userList->isEmpty()) {
+            foreach ($userList as $user) {
+                UserLabel::query()->where('user_id', $user->id)->delete();
+            }
+        }
+
+        // 解封被临时封禁的账号(ban_time > 0)
+        $userList = User::query()->where('status', '>=', 0)->where('ban_time', '>', 0)->get();
+        foreach ($userList as $user) {
+            if ($user->ban_time < time()) {
+                User::query()->where('id', $user->id)->update(['enable' => 1, 'ban_time' => 0]);
+
+                // 写入操作日志
+                $this->addUserBanLog($user->id, 0, '【自动解封】-封禁到期');
+            }
+        }
+
+        // 用户购买了流量(可用大于已用)也解封
+        $userList = User::query()->where('status', '>=', 0)->where('enable', 0)->where('ban_time', -1)->whereRaw("u + d < transfer_enable")->get();
+        if (!$userList->isEmpty()) {
+            foreach ($userList as $user) {
+                User::query()->where('id', $user->id)->update(['enable' => 1, 'ban_time' => 0]);
+
+                // 写入操作日志
+                $this->addUserBanLog($user->id, 0, '【自动解封】-有流量解封');
+            }
+        }
+
+        // 自动分配端口
+        if ($config['auto_release_port']) {
+            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->where('port', 0)->get();
+            if (!$userList->isEmpty()) {
+                foreach ($userList as $user) {
+                    $port = $config['is_rand_port'] ? $this->getRandPort() : $this->getOnlyPort();
+
+                    User::query()->where('id', $user->id)->update(['port' => $port]);
+                }
+            }
+        }
+
+        // 被封禁账号自动释放端口
+        if ($config['auto_release_port']) {
+            $userList = User::query()->where('enabled', 0)->where('ban_time', -1)->get();
+            if (!$userList->isEmpty()) {
+                foreach ($userList as $user) {
+                    if ($user->port) {
+                        User::query()->where('id', $user->id)->update(['port' => 0]);
+                    }
+                }
+            }
+        }
+
+        // 自动关闭超时未支付订单(有赞云收款二维码超过60分钟自动关闭,我们限制30分钟内必须付款)
+        $paymentList = Payment::query()->with(['order'])->where('status', 0)->where('created_at', '<=', date("Y-m-d H:i:s", strtotime("-30 minutes")))->get();
+        if (!$paymentList->isEmpty()) {
+            DB::beginTransaction();
+            try {
+                foreach ($paymentList as $payment) {
+                    // 关闭支付单
+                    Payment::query()->where('id', $payment->id)->update(['status' => -1]);
+
+                    // 关闭订单
+                    Order::query()->where('oid', $payment->oid)->update(['status' => -1]);
+
+                    // 退回优惠券
+                    if ($payment->order->coupon_id) {
+                        Coupon::query()->where('id', $payment->order->coupon_id)->update(['status' => 0]);
+                    }
+                }
+
+                DB::commit();
+            } catch (\Exception $e) {
+                Log::info('【异常】自动关闭超时未支付订单:' . $e->getMessage());
+
+                DB::rollBack();
+            }
+        }
+
+        // 自动监测节点状态
+        $nodeList = SsNode::query()->where('status', 1)->get();
+        foreach ($nodeList as $node) {
+            // 10分钟内无节点负载信息则认为是宕机
+            $node_info = SsNodeInfo::query()->where('node_id', $node->id)->where('log_time', '>=', strtotime("-10 minutes"))->orderBy('id', 'desc')->first();
+            if (empty($node_info) || empty($node_info->load)) {
+                // 10分钟内已发警告,则不再发
+                if (Cache::has($this->cacheKey . $node->id)) {
+                    continue;
+                }
+
+                $title = "节点宕机警告";
+                $content = "节点**{$node->name}【{$node->server}】({$node->ip})**可能宕机,请及时检查。";
+
+                // 发邮件通知管理员
+                if ($config['is_node_crash_warning'] && $config['crash_warning_email']) {
+                    try {
+                        Mail::to($config['crash_warning_email'])->send(new nodeCrashWarning($config['website_name'], $node->name, $node->server));
+                        $this->addEmailLog(1, $title, $content);
+                    } catch (\Exception $e) {
+                        $this->addEmailLog(1, $title, $content, 0, $e->getMessage());
+                    }
+                }
+
+                // 通过ServerChan发微信消息提醒管理员
+                if ($config['is_server_chan'] && $config['server_chan_key']) {
+                    $serverChan = new ServerChan();
+                    $serverChan->send($title, $content);
+                }
+
+                // 写入发信缓存
+                Cache::put($this->cacheKey . $node->id, $node->name . '(' . $node->server . ')', 10);
+            }
+        }
+
+        Log::info('定时任务:' . $this->description);
+    }
+
+    // 添加用户封禁日志
+    private function addUserBanLog($userId, $minutes, $desc)
+    {
+        $log = new UserBanLog();
+        $log->user_id = $userId;
+        $log->minutes = $minutes;
+        $log->desc = $desc;
+        $log->save();
+    }
+
+    /**
+     * 写入邮件发送日志
+     *
+     * @param int    $user_id 接收者用户ID
+     * @param string $title   标题
+     * @param string $content 内容
+     * @param int    $status  投递状态
+     * @param string $error   投递失败时记录的异常信息
+     */
+    private function addEmailLog($userId, $title, $content, $status = 1, $error = '')
+    {
+        $emailLogObj = new EmailLog();
+        $emailLogObj->user_id = $userId;
+        $emailLogObj->title = $title;
+        $emailLogObj->content = $content;
+        $emailLogObj->status = $status;
+        $emailLogObj->error = $error;
+        $emailLogObj->created_at = date('Y-m-d H:i:s');
+        $emailLogObj->save();
+    }
+
+    // 系统配置
+    private function systemConfig()
+    {
+        $config = Config::query()->get();
+        $data = [];
+        foreach ($config as $vo) {
+            $data[$vo->name] = $vo->value;
+        }
+
+        return $data;
+    }
+
+    // 获取一个随机端口
+    public function getRandPort()
+    {
+        $config = $this->systemConfig();
+
+        $port = mt_rand($config['min_port'], $config['max_port']);
+        $deny_port = [1068, 1109, 1434, 3127, 3128, 3129, 3130, 3332, 4444, 5554, 6669, 8080, 8081, 8082, 8181, 8282, 9996, 17185, 24554, 35601, 60177, 60179]; // 不生成的端口
+
+        $exists_port = User::query()->pluck('port')->toArray();
+        if (in_array($port, $exists_port) || in_array($port, $deny_port)) {
+            $port = $this->getRandPort();
+        }
+
+        return $port;
+    }
+
+    // 获取一个端口
+    public function getOnlyPort()
+    {
+        $config = $this->systemConfig();
+
+        $port = $config['min_port'];
+        $deny_port = [1068, 1109, 1434, 3127, 3128, 3129, 3130, 3332, 4444, 5554, 6669, 8080, 8081, 8082, 8181, 8282, 9996, 17185, 24554, 35601, 60177, 60179]; // 不生成的端口
+
+        $exists_port = User::query()->where('port', '>=', $config['min_port'])->where('port', '<=', $config['max_port'])->pluck('port')->toArray();
+        while (in_array($port, $exists_port) || in_array($port, $deny_port)) {
+            $port = $port + 1;
+        }
+
+        return $port;
+    }
+}

+ 0 - 81
app/Console/Commands/AutoRegetPortJob.php

@@ -1,81 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\User;
-use App\Http\Models\Config;
-use Log;
-
-class AutoRegetPortJob extends Command
-{
-    protected $signature = 'autoRegetPortJob';
-    protected $description = '自动获取端口';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $config = $this->systemConfig();
-
-        if ($config['auto_release_port']) {
-            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->where('port', 0)->get();
-            if (!$userList->isEmpty()) {
-                foreach ($userList as $user) {
-                    $port = $config['is_rand_port'] ? $this->getRandPort() : $this->getOnlyPort();
-
-                    User::query()->where('id', $user->id)->update(['port' => $port]);
-                }
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    // 系统配置
-    private function systemConfig()
-    {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-
-    // 获取一个随机端口
-    public function getRandPort()
-    {
-        $config = $this->systemConfig();
-
-        $port = mt_rand($config['min_port'], $config['max_port']);
-        $deny_port = [1068, 1109, 1434, 3127, 3128, 3129, 3130, 3332, 4444, 5554, 6669, 8080, 8081, 8082, 8181, 8282, 9996, 17185, 24554, 35601, 60177, 60179]; // 不生成的端口
-
-        $exists_port = User::query()->pluck('port')->toArray();
-        if (in_array($port, $exists_port) || in_array($port, $deny_port)) {
-            $port = $this->getRandPort();
-        }
-
-        return $port;
-    }
-
-    // 获取一个端口
-    public function getOnlyPort()
-    {
-        $config = $this->systemConfig();
-
-        $port = $config['min_port'];
-        $deny_port = [1068, 1109, 1434, 3127, 3128, 3129, 3130, 3332, 4444, 5554, 6669, 8080, 8081, 8082, 8181, 8282, 9996, 17185, 24554, 35601, 60177, 60179]; // 不生成的端口
-
-        $exists_port = User::query()->where('port', '>=', $config['min_port'])->where('port', '<=', $config['max_port'])->pluck('port')->toArray();
-        while (in_array($port, $exists_port) || in_array($port, $deny_port)) {
-            $port = $port + 1;
-        }
-
-        return $port;
-    }
-}

+ 0 - 49
app/Console/Commands/AutoReleasePortJob.php

@@ -1,49 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\User;
-use App\Http\Models\Config;
-use Log;
-
-class AutoReleasePortJob extends Command
-{
-    protected $signature = 'autoReleasePortJob';
-    protected $description = '自动释放端口';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $config = $this->systemConfig();
-
-        if ($config['auto_release_port']) {
-            $userList = User::query()->where('status', '<', 0)->get();
-            if (!$userList->isEmpty()) {
-                foreach ($userList as $user) {
-                    if ($user->port) {
-                        User::query()->where('id', $user->id)->update(['port' => 0]);
-                    }
-                }
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    // 系统配置
-    private function systemConfig()
-    {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-}

+ 0 - 32
app/Console/Commands/AutoRemoveDisabledUserLabelsJob.php

@@ -1,32 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use App\Http\Models\User;
-use App\Http\Models\UserLabel;
-use Illuminate\Console\Command;
-use Log;
-
-class AutoRemoveDisabledUserLabelsJob extends Command
-{
-    protected $signature = 'autoRemoveDisabledUserLabelsJob';
-    protected $description = '自动移除被禁用用户的标签';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        // 账号被禁用,则删除所有标签
-        $userList = User::query()->where('enable', 0)->where('ban_time', 0)->get();
-        if (!$userList->isEmpty()) {
-            foreach ($userList as $user) {
-                UserLabel::query()->where('user_id', $user->id)->delete();
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-}

+ 0 - 58
app/Console/Commands/AutoReopenUserJob.php

@@ -1,58 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\UserBanLog;
-use App\Http\Models\User;
-use Log;
-
-class AutoReopenUserJob extends Command
-{
-    protected $signature = 'autoReopenUserJob';
-    protected $description = '自动解封用户';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        // 解封账号
-        $userList = User::query()->where('status', '>=', 0)->where('ban_time', '>', 0)->get();
-        foreach ($userList as $user) {
-            if ($user->ban_time < time()) {
-                User::query()->where('id', $user->id)->update(['enable' => 1, 'ban_time' => 0]);
-
-                // 写入操作日志
-                $this->log($user->id, 0, '【自动解封】-封禁到期');
-            }
-        }
-
-        // SSR(R)被启用说明用户购买了流量
-        User::query()->where('enable', 1)->where('ban_time', -1)->update(['ban_time' => 0]); // 重置ban_time
-
-        $userList = User::query()->where('status', '>=', 0)->where('enable', 0)->where('ban_time', -1)->whereRaw("u + d < transfer_enable")->get();
-        if (!$userList->isEmpty()) {
-            foreach ($userList as $user) {
-                User::query()->where('id', $user->id)->update(['enable' => 1, 'ban_time' => 0]);
-
-                // 写入操作日志
-                $this->log($user->id, 0, '【自动解封】-有流量解封');
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-
-    private function log($user_id, $minutes, $desc)
-    {
-        $log = new UserBanLog();
-        $log->user_id = $user_id;
-        $log->minutes = $minutes;
-        $log->desc = $desc;
-        $log->save();
-    }
-}

+ 75 - 0
app/Console/Commands/AutoResetUserTraffic.php

@@ -0,0 +1,75 @@
+<?php
+
+namespace App\Console\Commands;
+
+use Illuminate\Console\Command;
+use App\Http\Models\Config;
+use App\Http\Models\Order;
+use App\Http\Models\User;
+use Log;
+
+class AutoResetUserTraffic extends Command
+{
+    protected $signature = 'autoResetUserTraffic';
+    protected $description = '自动重置用户可用流量';
+
+    public function __construct()
+    {
+        parent::__construct();
+    }
+
+    public function handle()
+    {
+        $config = $this->systemConfig();
+
+        if ($config['reset_traffic']) {
+            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->get();
+            if (!$userList->isEmpty()) {
+                foreach ($userList as $user) {
+                    if (!$user->traffic_reset_day) {
+                        continue;
+                    }
+
+                    // 取出用户最后购买的有效套餐 TODO:需要改掉,不应该是最后购买的套餐
+                    $order = Order::query()->with(['user', 'goods'])->whereHas('goods', function ($q) {
+                        $q->where('type', 2);
+                    })->where('user_id', $user->id)->where('is_expire', 0)->orderBy('oid', 'desc')->first();
+
+                    if (!$order) {
+                        continue;
+                    }
+
+                    // TODO:需要改掉,改成下一次重置日,每月不定时,类似搬瓦工
+                    $today = abs(date('d'));
+                    $reset_days = [$today, 29, 30, 31];
+                    if (in_array($order->user->traffic_reset_day, $reset_days)) {
+                        // 跳过本月,防止异常重置
+                        if (date('m') == date('m', strtotime($order->expire_at))) {
+                            continue;
+                        }
+
+                        if (date('m') == date('m', strtotime($order->created_at))) {
+                            continue;
+                        }
+
+                        User::query()->where('id', $user->id)->update(['u' => 0, 'd' => 0]);
+                    }
+                }
+            }
+        }
+
+        Log::info('定时任务:' . $this->description);
+    }
+
+    // 系统配置
+    private function systemConfig()
+    {
+        $config = Config::query()->get();
+        $data = [];
+        foreach ($config as $vo) {
+            $data[$vo->name] = $vo->value;
+        }
+
+        return $data;
+    }
+}

+ 0 - 72
app/Console/Commands/AutoResetUserTrafficJob.php

@@ -1,72 +0,0 @@
-<?php
-
-namespace App\Console\Commands;
-
-use Illuminate\Console\Command;
-use App\Http\Models\Order;
-use App\Http\Models\Config;
-use App\Http\Models\User;
-use Log;
-
-class AutoResetUserTrafficJob extends Command
-{
-    protected $signature = 'autoResetUserTrafficJob';
-    protected $description = '自动重置用户可用流量';
-
-    public function __construct()
-    {
-        parent::__construct();
-    }
-
-    public function handle()
-    {
-        $config = $this->systemConfig();
-
-        if ($config['reset_traffic']) {
-            $userList = User::query()->where('status', '>=', 0)->where('enable', 1)->get();
-            foreach ($userList as $user) {
-                if (!$user->traffic_reset_day) {
-                    continue;
-                }
-
-                // 取出用户最后购买的有效套餐
-                $order = Order::query()->with(['user', 'goods'])->whereHas('goods', function ($q) {
-                    $q->where('type', 2);
-                })->where('user_id', $user->id)->where('is_expire', 0)->orderBy('oid', 'desc')->first();
-
-                if (!$order) {
-                    continue;
-                }
-
-                $today = abs(date('d'));
-                $reset_days = [$today, 29, 30, 31];
-                if (in_array($order->user->traffic_reset_day, $reset_days)) {
-                    // 跳过本月,防止异常重置
-                    if (date('m') == date('m', strtotime($order->expire_at))) {
-                        continue;
-                    }
-
-                    if (date('m') == date('m', strtotime($order->created_at))) {
-                        continue;
-                    }
-
-                    User::query()->where('id', $user->id)->update(['u' => 0, 'd' => 0]);
-                }
-            }
-        }
-
-        Log::info('定时任务:' . $this->description);
-    }
-
-    // 系统配置
-    private function systemConfig()
-    {
-        $config = Config::query()->get();
-        $data = [];
-        foreach ($config as $vo) {
-            $data[$vo->name] = $vo->value;
-        }
-
-        return $data;
-    }
-}

+ 2 - 2
app/Console/Commands/AutoStatisticsNodeDailyTrafficJob.php → app/Console/Commands/AutoStatisticsNodeDailyTraffic.php

@@ -8,9 +8,9 @@ use App\Http\Models\SsNodeTrafficDaily;
 use App\Http\Models\UserTrafficLog;
 use Log;
 
-class AutoStatisticsNodeDailyTrafficJob extends Command
+class AutoStatisticsNodeDailyTraffic extends Command
 {
-    protected $signature = 'autoStatisticsNodeDailyTrafficJob';
+    protected $signature = 'autoStatisticsNodeDailyTraffic';
     protected $description = '自动统计节点每日流量';
 
     public function __construct()

+ 2 - 2
app/Console/Commands/AutoStatisticsNodeHourlyTrafficJob.php → app/Console/Commands/AutoStatisticsNodeHourlyTraffic.php

@@ -8,9 +8,9 @@ use App\Http\Models\SsNodeTrafficHourly;
 use App\Http\Models\UserTrafficLog;
 use Log;
 
-class AutoStatisticsNodeHourlyTrafficJob extends Command
+class AutoStatisticsNodeHourlyTraffic extends Command
 {
-    protected $signature = 'autoStatisticsNodeHourlyTrafficJob';
+    protected $signature = 'autoStatisticsNodeHourlyTraffic';
     protected $description = '自动统计节点每小时流量';
 
     public function __construct()

+ 3 - 3
app/Console/Commands/AutoStatisticsUserDailyTrafficJob.php → app/Console/Commands/AutoStatisticsUserDailyTraffic.php

@@ -3,15 +3,15 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use App\Http\Models\User;
 use App\Http\Models\SsNode;
+use App\Http\Models\User;
 use App\Http\Models\UserTrafficDaily;
 use App\Http\Models\UserTrafficLog;
 use Log;
 
-class AutoStatisticsUserDailyTrafficJob extends Command
+class AutoStatisticsUserDailyTraffic extends Command
 {
-    protected $signature = 'autoStatisticsUserDailyTrafficJob';
+    protected $signature = 'autoStatisticsUserDailyTraffic';
     protected $description = '自动统计用户每日流量';
 
     public function __construct()

+ 3 - 3
app/Console/Commands/AutoStatisticsUserHourlyTrafficJob.php → app/Console/Commands/AutoStatisticsUserHourlyTraffic.php

@@ -3,15 +3,15 @@
 namespace App\Console\Commands;
 
 use Illuminate\Console\Command;
-use App\Http\Models\User;
 use App\Http\Models\SsNode;
+use App\Http\Models\User;
 use App\Http\Models\UserTrafficLog;
 use App\Http\Models\UserTrafficHourly;
 use Log;
 
-class AutoStatisticsUserHourlyTrafficJob extends Command
+class AutoStatisticsUserHourlyTraffic extends Command
 {
-    protected $signature = 'autoStatisticsUserHourlyTrafficJob';
+    protected $signature = 'autoStatisticsUserHourlyTraffic';
     protected $description = '自动统计用户每小时流量';
 
     public function __construct()

+ 3 - 3
app/Console/Commands/UserExpireWarningJob.php → app/Console/Commands/UserExpireAutoWarning.php

@@ -10,10 +10,10 @@ use App\Mail\userExpireWarning;
 use Mail;
 use Log;
 
-class UserExpireWarningJob extends Command
+class UserExpireAutoWarning extends Command
 {
-    protected $signature = 'userExpireWarningJob';
-    protected $description = '自动发邮件提醒用户临近到期';
+    protected $signature = 'userExpireAutoWarning';
+    protected $description = '用户临近到期自动发邮件提醒';
 
     protected static $config;
 

+ 3 - 3
app/Console/Commands/UserTrafficAbnormalWarningJob.php → app/Console/Commands/UserTrafficAbnormalAutoWarning.php

@@ -4,15 +4,15 @@ namespace App\Console\Commands;
 
 use App\Components\ServerChan;
 use Illuminate\Console\Command;
+use App\Http\Models\Config;
 use App\Http\Models\User;
 use App\Http\Models\UserTrafficHourly;
-use App\Http\Models\Config;
 use Cache;
 use Log;
 
-class UserTrafficAbnormalWarningJob extends Command
+class UserTrafficAbnormalAutoWarning extends Command
 {
-    protected $signature = 'userTrafficAbnormalWarningJob';
+    protected $signature = 'userTrafficAbnormalAutoWarning';
     protected $description = '用户流量异常警告';
 
     public function __construct()

+ 3 - 3
app/Console/Commands/UserTrafficWarningJob.php → app/Console/Commands/UserTrafficAutoWarning.php

@@ -10,10 +10,10 @@ use App\Mail\userTrafficWarning;
 use Mail;
 use Log;
 
-class UserTrafficWarningJob extends Command
+class UserTrafficAutoWarning extends Command
 {
-    protected $signature = 'userTrafficWarningJob';
-    protected $description = '自动发邮件提醒用户流量超过警告阈值';
+    protected $signature = 'userTrafficAutoWarning';
+    protected $description = '用户流量超过警告阈值自动发邮件提醒';
 
     protected static $config;
 

+ 28 - 44
app/Console/Kernel.php

@@ -13,28 +13,20 @@ class Kernel extends ConsoleKernel
      * @var array
      */
     protected $commands = [
-        \App\Console\Commands\AutoBanSubscribeJob::class,
-        \App\Console\Commands\AutoBanUserJob::class,
-        \App\Console\Commands\AutoCheckNodeStatusJob::class,
-        \App\Console\Commands\AutoClearLogJob::class,
-        \App\Console\Commands\AutoCloseOrderJob::class,
-        \App\Console\Commands\AutoDecGoodsTrafficJob::class,
-        \App\Console\Commands\AutoDisableExpireUserJob::class,
-        \App\Console\Commands\AutoDisableUserJob::class,
-        \App\Console\Commands\AutoExpireCouponJob::class,
-        \App\Console\Commands\AutoExpireInviteJob::class,
-        \App\Console\Commands\AutoReleasePortJob::class,
-        \App\Console\Commands\AutoRegetPortJob::class,
-        \App\Console\Commands\AutoRemoveDisabledUserLabelsJob::class,
-        \App\Console\Commands\AutoReopenUserJob::class,
-        \App\Console\Commands\AutoResetUserTrafficJob::class,
-        \App\Console\Commands\AutoStatisticsNodeDailyTrafficJob::class,
-        \App\Console\Commands\AutoStatisticsNodeHourlyTrafficJob::class,
-        \App\Console\Commands\AutoStatisticsUserDailyTrafficJob::class,
-        \App\Console\Commands\AutoStatisticsUserHourlyTrafficJob::class,
-        \App\Console\Commands\UserExpireWarningJob::class,
-        \App\Console\Commands\UserTrafficAbnormalWarningJob::class,
-        \App\Console\Commands\UserTrafficWarningJob::class,
+        \App\Console\Commands\AutoJob::class,
+        \App\Console\Commands\AutoClearLog::class,
+
+        \App\Console\Commands\AutoDecGoodsTraffic::class,
+        \App\Console\Commands\AutoResetUserTraffic::class,
+
+        \App\Console\Commands\AutoStatisticsNodeDailyTraffic::class,
+        \App\Console\Commands\AutoStatisticsNodeHourlyTraffic::class,
+        \App\Console\Commands\AutoStatisticsUserDailyTraffic::class,
+        \App\Console\Commands\AutoStatisticsUserHourlyTraffic::class,
+
+        \App\Console\Commands\UserTrafficAbnormalAutoWarning::class,
+        \App\Console\Commands\UserExpireAutoWarning::class,
+        \App\Console\Commands\UserTrafficAutoWarning::class,
     ];
 
     /**
@@ -46,28 +38,20 @@ class Kernel extends ConsoleKernel
      */
     protected function schedule(Schedule $schedule)
     {
-        $schedule->command('autoReopenUserJob')->everyMinute();
-        $schedule->command('autoBanSubscribeJob')->everyThirtyMinutes();
-        $schedule->command('autoBanUserJob')->everyTenMinutes();
-        $schedule->command('autoCheckNodeStatusJob')->everyMinute();
-        $schedule->command('autoClearLogJob')->everyThirtyMinutes();
-        $schedule->command('autoCloseOrderJob')->everyMinute();
-        $schedule->command('autoDecGoodsTrafficJob')->everyTenMinutes();
-        $schedule->command('autoDisableExpireUserJob')->everyMinute();
-        $schedule->command('autoDisableUserJob')->everyMinute();
-        $schedule->command('autoExpireCouponJob')->everyThirtyMinutes();
-        $schedule->command('autoExpireInviteJob')->everyThirtyMinutes();
-        $schedule->command('autoRemoveDisabledUserLabelsJob')->everyMinute();
-        $schedule->command('autoReleasePortJob')->everyMinute();
-        $schedule->command('autoRegetPortJob')->everyMinute();
-        $schedule->command('autoResetUserTrafficJob')->everyFiveMinutes();
-        $schedule->command('autoStatisticsNodeDailyTrafficJob')->dailyAt('23:55');
-        $schedule->command('autoStatisticsNodeHourlyTrafficJob')->hourly();
-        $schedule->command('autoStatisticsUserDailyTrafficJob')->dailyAt('23:50');
-        $schedule->command('autoStatisticsUserHourlyTrafficJob')->hourly();
-        $schedule->command('userExpireWarningJob')->daily();
-        $schedule->command('userTrafficAbnormalWarningJob')->everyThirtyMinutes();
-        $schedule->command('userTrafficWarningJob')->daily();
+        $schedule->command('autoJob')->everyMinute();
+        $schedule->command('autoClearLog')->everyThirtyMinutes();
+
+        $schedule->command('autoDecGoodsTraffic')->everyTenMinutes();
+        $schedule->command('autoResetUserTraffic')->everyFiveMinutes();
+
+        $schedule->command('autoStatisticsNodeDailyTraffic')->dailyAt('23:55');
+        $schedule->command('autoStatisticsNodeHourlyTraffic')->hourly();
+        $schedule->command('autoStatisticsUserDailyTraffic')->dailyAt('23:50');
+        $schedule->command('autoStatisticsUserHourlyTraffic')->hourly();
+
+        $schedule->command('userTrafficAbnormalAutoWarning')->everyThirtyMinutes();
+        $schedule->command('userExpireAutoWarning')->daily();
+        $schedule->command('userTrafficAutoWarning')->daily();
     }
 
     /**

+ 0 - 301
app/Http/Controllers/Api/V2rayController.php

@@ -1,301 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\Api;
-
-use App\Http\Controllers\Controller;
-use App\Http\Models\SsNode;
-use App\Http\Models\SsNodeInfo;
-use App\Http\Models\SsNodeLabel;
-use App\Http\Models\SsNodeOnlineLog;
-use App\Http\Models\User;
-use App\Http\Models\UserLabel;
-use App\Http\Models\UserTrafficLog;
-use App\Http\V2ray\V2rayGenerator;
-use Illuminate\Http\Request;
-use Response;
-use Log;
-use DB;
-
-class V2rayController extends Controller
-{
-    // V2ray 用户
-    public function users(Request $request)
-    {
-        $node_id = $request->route('id');
-        $ssr_node = SsNode::query()->where('id', $node_id)->first(); // 节点是否存在
-        if ($ssr_node == null) {
-            $res = [
-                "ret" => 0
-            ];
-
-            return Response::json($res, 400);
-        }
-
-        // 找出该节点的标签id
-        $ssr_node_label = SsNodeLabel::query()->where('node_id', $node_id)->pluck('label_id');
-
-        //找出有这个标签的用户
-        $user_with_label = UserLabel::query()->whereIn('label_id', $ssr_node_label)->pluck('user_id');
-
-        //提取用户信息
-        $userids = User::query()->whereIn('id', $user_with_label)->where('enable', 1)->where('id', '<>', $this->systemConfig['free_node_users_id'])->pluck('id')->toArray();
-        $users = User::query()->where('id', '<>', $this->systemConfig['free_node_users_id'])->select(
-            "id", "username", "passwd", "t", "u", "d", "transfer_enable",
-            "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
-            "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->get();
-
-        $data = [];
-        foreach ($users as $user) {
-            //datetime 转timestamp
-            $user['switch'] = 1;
-            $user['email'] = $user['username'];
-            $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp());
-            if (in_array($user->id, $userids)) {
-                $user->enable = 1;
-            } else {
-                $user->enable = 0;
-            }
-
-            //v2ray用户信息
-            $user->v2ray_user = [
-                "uuid" => $user->v2ray_uuid,
-                "email" => sprintf("%[email protected]", $user->v2ray_uuid),
-                "alter_id" => $user->v2ray_alter_id,
-                "level" => $user->v2ray_level,
-            ];
-
-            array_push($data, $user);
-        }
-
-        if ($this->systemConfig['is_free_node']) {
-            if ($this->systemConfig['free_node_id'] == $node_id) {
-                $user = User::query()->whereIn('id', $user_with_label)->where('id', $this->systemConfig['free_node_users_id'])->select(
-                    "id", "enable", "username", "passwd", "t", "u", "d", "transfer_enable",
-                    "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
-                    "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->first();
-
-                //datetime 转timestamp
-                $user['switch'] = 1;
-                $user['email'] = $user['username'];
-                $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp());
-
-                //v2ray用户信息
-                $user->v2ray_user = [
-                    "uuid" => $user->v2ray_uuid,
-                    "email" => sprintf("%[email protected]", $user->v2ray_uuid),
-                    "alter_id" => $user->v2ray_alter_id,
-                    "level" => $user->v2ray_level,
-                ];
-
-                array_push($data, $user);
-            }
-        }
-
-        $load = '1';
-        $uptime = time();
-
-        $log = new SsNodeInfo();
-        $log->node_id = $node_id;
-        $log->load = $load;
-        $log->uptime = $uptime;
-        $log->log_time = time();
-        $log->save();
-
-        $res = [
-            'msg' => 'ok',
-            'data' => $data,
-        ];
-
-        return Response::json($res);
-    }
-
-    //写在线用户日志
-    public function onlineUserLog(Request $request)
-    {
-        $node_id = $request->route('id');
-        $count = $request->get('count');
-        $log = new SsNodeOnlineLog();
-        $log->node_id = $node_id;
-        $log->online_user = $count;
-        $log->log_time = time();
-
-        if (!$log->save()) {
-            $res = [
-                "ret" => 0,
-                "msg" => "update failed",
-            ];
-
-            return response()->json($res);
-        }
-
-        $res = [
-            "ret" => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-
-    //节点信息
-    public function info(Request $request)
-    {
-        $node_id = $request->route('id');
-        $load = $request->get('load');
-        $uptime = $request->get('uptime');
-
-        $log = new SsNodeInfo();
-        $log->node_id = $node_id;
-        $log->load = $load;
-        $log->uptime = $uptime;
-        $log->log_time = time();
-
-        if (!$log->save()) {
-            $res = [
-                "ret" => 0,
-                "msg" => "update failed",
-            ];
-
-            return response()->json($res);
-        }
-
-        $res = [
-            "ret" => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-
-    //PostTraffic
-    public function postTraffic(Request $request)
-    {
-        $nodeId = $request->route('id');
-        $node = SsNode::query()->where('id', $nodeId)->first();
-        $rate = $node->traffic_rate;
-        $input = $request->getContent();
-        $datas = json_decode($input, true);
-
-        foreach ($datas as $data) {
-            $user = User::query()->where('id', $data['user_id'])->first();
-            if (!$user) {
-                continue;
-            }
-
-            $user->t = time();
-            $user->u = $user->u + ($data['u'] * $rate);
-            $user->d = $user->d + ($data['d'] * $rate);
-            $user->save();
-
-            // 写usertrafficlog
-            $totalTraffic = flowAutoShow(($data['u'] + $data['d']) * $rate);
-            $traffic = new UserTrafficLog();
-            $traffic->user_id = $data['user_id'];
-            $traffic->u = $data['u'];
-            $traffic->d = $data['d'];
-            $traffic->node_id = $nodeId;
-            $traffic->rate = $rate;
-            $traffic->traffic = $totalTraffic;
-            $traffic->log_time = time();
-            $traffic->save();
-        }
-
-        $res = [
-            'ret' => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-
-    //V2ray Users
-    public function v2rayUsers(Request $request)
-    {
-        $node = SsNode::query()->where('id', $request->route('id'))->first();
-        $users = User::query()->where('enable', 1)->where('id', '<>', $this->systemConfig['free_node_users_id'])->get();
-
-        $v = new V2rayGenerator();
-        $v->setPort($node->v2ray_port);
-
-        foreach ($users as $user) {
-            $email = sprintf("%[email protected]", $user->v2ray_uuid);
-            $v->addUser($user->v2ray_uuid, $user->v2ray_level, $user->v2ray_alter_id, $email);
-        }
-
-        if ($this->systemConfig['is_free_node']) {
-            if ($request->route('id') == $this->systemConfig['free_node_id']) {
-                $freeuser = User::query()->where('enable', 1)->where('id', $this->systemConfig['free_node_users_id'])->first();
-                $email = sprintf("%[email protected]", $freeuser->v2ray_uuid);
-                $v->addUser($freeuser->v2ray_uuid, $freeuser->v2ray_level, $freeuser->v2ray_alter_id, $email);
-            }
-        }
-
-        return Response::json($v->getArr());
-    }
-
-    //用户列表
-    public function index()
-    {
-        $users = User::query()->where('enable', 1)->select(
-            "id", "username", "passwd", "t", "u", "d", "transfer_enable",
-            "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
-            "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->get();
-
-        foreach ($users as $user) {
-            //datetime 转timestamp
-            $user['switch'] = 1;
-            $user['email'] = $user['username'];
-            $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp());
-        }
-
-        $res = [
-            "data" => $users
-        ];
-
-        return response()->json($res);
-    }
-
-    //更新流量到user表
-    public function addTraffic(Request $request, $response, $args)
-    {
-        $id = $request->route('id');
-        $u = $request->get('u');
-        $d = $request->get('d');
-        $nodeId = $request->get('node_id');
-
-        $node = SsNode::query()->find($nodeId)->get();
-        $rate = $node->traffic_rate;
-
-        $user = User::query()->find($id)->get();
-
-        $user->t = time();
-        $user->u = $user->u + ($u * $rate);
-        $user->d = $user->d + ($d * $rate);
-
-        if (!$user->save()) {
-            $res = [
-                "msg" => "update failed",
-            ];
-
-            return response()->json($res, 400);
-        }
-
-        // 写usertrafficlog
-        $totalTraffic = flowAutoShow(($u + $d) * $rate);
-        $traffic = new UserTrafficLog();
-        $traffic->user_id = $id;
-        $traffic->u = $u;
-        $traffic->d = $d;
-        $traffic->node_id = $nodeId;
-        $traffic->rate = $rate;
-        $traffic->traffic = $totalTraffic;
-        $traffic->log_time = time();
-        $traffic->save();
-
-        $res = [
-            'ret' => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-}

+ 0 - 240
app/Http/Controllers/Mu/v2ray/NodeController.php

@@ -1,240 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\Muv2;
-
-use App\Http\Controllers\Controller;
-use App\Http\Models\SsNode;
-use App\Http\Models\SsNodeInfo;
-use App\Http\Models\SsNodeLabel;
-use App\Http\Models\SsNodeOnlineLog;
-use App\Http\Models\User;
-use App\Http\Models\UserLabel;
-use App\Http\Models\UserTrafficLog;
-use App\Http\V2ray\V2rayGenerator;
-use Illuminate\Http\Request;
-use Response;
-
-class NodeController extends Controller
-{
-    protected static $config;
-    protected static $userLevel;
-
-    function __construct()
-    {
-        self::$config = $this->systemConfig();
-    }
-
-    //V2ray 用户
-    public function users(Request $request)
-    {
-        $node_id = $request->route('id');
-        $ssr_node = SsNode::query()->where('id', $node_id)->first(); // 节点是否存在
-        if ($ssr_node == null) {
-            $res = [
-                "ret" => 0
-            ];
-
-            return Response::json($res, 400);
-        }
-
-        // 找出该节点的标签id
-        $ssr_node_label = SsNodeLabel::query()->where('node_id', $node_id)->pluck('label_id');
-
-        //找出有这个标签的用户
-        $user_with_label = UserLabel::query()->whereIn('label_id', $ssr_node_label)->pluck('user_id');
-
-        //提取用户信息
-        $userids = User::query()->whereIn('id', $user_with_label)->where('enable', 1)->where('id', '<>', self::$config['free_node_users_id'])->pluck('id')->toArray();
-        $users = User::query()->where('id', '<>', self::$config['free_node_users_id'])->select(
-                "id", "username", "passwd", "t", "u", "d", "transfer_enable",
-                "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
-                "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->get();
-
-        $data = [];
-        foreach ($users as $user) {
-            //datetime 转timestamp
-            $user['switch'] = 1;
-            $user['email'] = $user['username'];
-            $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp());
-            if (in_array($user->id, $userids)) {
-                $user->enable = 1;
-            } else {
-                $user->enable = 0;
-            }
-
-            //v2ray用户信息
-            $user->v2ray_user = [
-                "uuid"     => $user->v2ray_uuid,
-                "email"    => sprintf("%[email protected]", $user->v2ray_uuid),
-                "alter_id" => $user->v2ray_alter_id,
-                "level"    => $user->v2ray_level,
-            ];
-
-            array_push($data, $user);
-        }
-
-        if (self::$config['is_free_node']) {
-            if (self::$config['free_node_id'] == $node_id) {
-                $user = User::query()->whereIn('id', $user_with_label)->where('id', self::$config['free_node_users_id'])->select(
-                        "id", "enable", "username", "passwd", "t", "u", "d", "transfer_enable",
-                        "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
-                        "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->first();
-
-                //datetime 转timestamp
-                $user['switch'] = 1;
-                $user['email'] = $user['username'];
-                $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp());
-
-                //v2ray用户信息
-                $user->v2ray_user = [
-                    "uuid"     => $user->v2ray_uuid,
-                    "email"    => sprintf("%[email protected]", $user->v2ray_uuid),
-                    "alter_id" => $user->v2ray_alter_id,
-                    "level"    => $user->v2ray_level,
-                ];
-
-                array_push($data, $user);
-            }
-        }
-
-        $load = '1';
-        $uptime = time();
-
-        $log = new SsNodeInfo();
-        $log->node_id = $node_id;
-        $log->load = $load;
-        $log->uptime = $uptime;
-        $log->log_time = time();
-        $log->save();
-
-        $res = [
-            'msg'  => 'ok',
-            'data' => $data,
-        ];
-
-        return Response::json($res);
-    }
-
-    //写在线用户日志
-    public function onlineUserLog(Request $request)
-    {
-        $node_id = $request->route('id');
-        $count = $request->get('count');
-        $log = new SsNodeOnlineLog();
-        $log->node_id = $node_id;
-        $log->online_user = $count;
-        $log->log_time = time();
-
-        if (!$log->save()) {
-            $res = [
-                "ret" => 0,
-                "msg" => "update failed",
-            ];
-
-            return response()->json($res);
-        }
-
-        $res = [
-            "ret" => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-
-    //节点信息
-    public function info(Request $request)
-    {
-        $node_id = $request->route('id');
-        $load = $request->get('load');
-        $uptime = $request->get('uptime');
-
-        $log = new SsNodeInfo();
-        $log->node_id = $node_id;
-        $log->load = $load;
-        $log->uptime = $uptime;
-        $log->log_time = time();
-
-        if (!$log->save()) {
-            $res = [
-                "ret" => 0,
-                "msg" => "update failed",
-            ];
-
-            return response()->json($res);
-        }
-
-        $res = [
-            "ret" => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-
-    //PostTraffic
-    public function postTraffic(Request $request)
-    {
-        $nodeId = $request->route('id');
-        $node = SsNode::query()->where('id', $nodeId)->first();
-        $rate = $node->traffic_rate;
-        $input = $request->getContent();
-        $datas = json_decode($input, true);
-
-        foreach ($datas as $data) {
-            $user = User::query()->where('id', $data['user_id'])->first();
-            if (!$user) {
-                continue;
-            }
-
-            $user->t = time();
-            $user->u = $user->u + ($data['u'] * $rate);
-            $user->d = $user->d + ($data['d'] * $rate);
-            $user->save();
-
-            // 写usertrafficlog
-            $totalTraffic = flowAutoShow(($data['u'] + $data['d']) * $rate);
-            $traffic = new UserTrafficLog();
-            $traffic->user_id = $data['user_id'];
-            $traffic->u = $data['u'];
-            $traffic->d = $data['d'];
-            $traffic->node_id = $nodeId;
-            $traffic->rate = $rate;
-            $traffic->traffic = $totalTraffic;
-            $traffic->log_time = time();
-            $traffic->save();
-        }
-
-        $res = [
-            'ret' => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-
-    //V2ray Users
-    public function v2rayUsers(Request $request)
-    {
-        $node = SsNode::query()->where('id', $request->route('id'))->first();
-        $users = User::query()->where('enable', 1)->where('id', '<>', self::$config['free_node_users_id'])->get();
-
-        $v = new V2rayGenerator();
-        $v->setPort($node->v2ray_port);
-
-        foreach ($users as $user) {
-            $email = sprintf("%[email protected]", $user->v2ray_uuid);
-            $v->addUser($user->v2ray_uuid, $user->v2ray_level, $user->v2ray_alter_id, $email);
-        }
-
-        if (self::$config['is_free_node']) {
-            if ($request->route('id') == self::$config['free_node_id']) {
-                $freeuser = User::query()->where('enable', 1)->where('id', self::$config['free_node_users_id'])->first();
-                $email = sprintf("%[email protected]", $freeuser->v2ray_uuid);
-                $v->addUser($freeuser->v2ray_uuid, $freeuser->v2ray_level, $freeuser->v2ray_alter_id, $email);
-            }
-        }
-
-        return Response::json($v->getArr());
-    }
-}

+ 0 - 78
app/Http/Controllers/Mu/v2ray/UserController.php

@@ -1,78 +0,0 @@
-<?php
-
-namespace App\Http\Controllers\Muv2;
-use App\Http\Controllers\Controller;
-use App\Http\Models\SsNode;
-use App\Http\Models\User;
-use App\Http\Models\UserTrafficLog;
-use Illuminate\Http\Request;
-
-class UserController extends Controller
-{
-    //用户列表
-    public function index()
-    {
-        $users= User::query()->where('enable',1)->select(
-            "id","username","passwd","t","u","d","transfer_enable",
-            "port","protocol","obfs","enable","expire_time as expire_time_d","method",
-            "v2ray_uuid","v2ray_level","v2ray_alter_id")->get();
-
-        foreach($users as $user){
-            //datetime 转timestamp
-            $user['switch']=1;
-            $user['email']=$user['username'];
-            $user['expire_time']=strval((new \DateTime($user['expire_time_d']))->getTimestamp());
-        }
-
-        $res = [
-            "data" => $users
-        ];
-
-        return response()->json($res);
-    }
-
-    //更新流量到user表
-    public function addTraffic(Request $request, $response, $args)
-    {
-        $id = $request->route('id');
-        $u = $request->get('u');
-        $d = $request->get('d');
-        $nodeId = $request->get('node_id');
-
-        $node = SsNode::query()->find($nodeId)->get();
-        $rate = $node->traffic_rate;
-
-        $user = User::query()->find($id)->get();
-
-        $user->t = time();
-        $user->u = $user->u + ($u * $rate);
-        $user->d = $user->d + ($d * $rate);
-
-        if (!$user->save()) {
-            $res = [
-                "msg" => "update failed",
-            ];
-
-            return response()->json($res,400);
-        }
-
-        // 写usertrafficlog
-        $totalTraffic = flowAutoShow(($u + $d) * $rate);
-        $traffic = new UserTrafficLog();
-        $traffic->user_id = $id;
-        $traffic->u = $u;
-        $traffic->d = $d;
-        $traffic->node_id = $nodeId;
-        $traffic->rate = $rate;
-        $traffic->traffic = $totalTraffic;
-        $traffic->log_time = time();
-        $traffic->save();
-
-        $res = [
-            'ret' => 1,
-            "msg" => "ok",
-        ];
-
-        return response()->json($res);
-    }
-}

+ 230 - 0
app/Http/Controllers/Muv2/NodeController.php

@@ -0,0 +1,230 @@
+<?php
+
+namespace App\Http\Controllers\Muv2;
+
+use App\Http\Controllers\Controller;
+use App\Http\Models\SsNode;
+use App\Http\Models\SsNodeInfo;
+use App\Http\Models\SsNodeLabel;
+use App\Http\Models\SsNodeOnlineLog;
+use App\Http\Models\User;
+use App\Http\Models\UserLabel;
+use App\Http\Models\UserTrafficLog;
+use App\Http\V2Ray\Generator;
+use Illuminate\Http\Request;
+use Response;
+
+class NodeController extends Controller
+{
+    protected static $userLevel;
+
+    // 获取节点用户列表
+    public function users(Request $request)
+    {
+        $nodeId = $request->route('id');
+
+        $node = SsNode::query()->where('id', $nodeId)->first(); // 节点是否存在
+        if (!$node) {
+            return Response::json([
+                "ret" => 0
+            ], 400);
+        }
+
+        // 找出该节点的标签
+        $nodeLabels = SsNodeLabel::query()->where('node_id', $nodeId)->pluck('label_id');
+
+        // 找出有相同标签的用户
+        $userLabels = UserLabel::query()->whereIn('label_id', $nodeLabels)->pluck('user_id');
+
+        //提取用户信息
+        $userIds = User::query()->where('enable', 1)->whereIn('id', $userLabels)->where('id', '<>', $this->systemConfig['free_node_users_id'])->pluck('id')->toArray();
+        $users = User::query()->where('id', '<>', $this->systemConfig['free_node_users_id'])->select(
+            "id", "username", "passwd", "t", "u", "d", "transfer_enable",
+            "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
+            "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->get();
+
+        $data = [];
+        foreach ($users as $user) {
+            $user['switch'] = 1;
+            $user['email'] = $user['username'];
+            $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp()); // datetime 转timestamp
+
+            if (in_array($user->id, $userIds)) {
+                $user->enable = 1;
+            } else {
+                $user->enable = 0;
+            }
+
+            // 用户信息
+            $user->v2ray_user = [
+                "uuid"     => $user->v2ray_uuid,
+                "email"    => sprintf("%[email protected]", $user->v2ray_uuid),
+                "alter_id" => $user->v2ray_alter_id,
+                "level"    => $user->v2ray_level,
+            ];
+
+            array_push($data, $user);
+        }
+
+        if ($this->systemConfig['is_free_node']) {
+            if ($this->systemConfig['free_node_id'] == $nodeId) {
+                $user = User::query()->whereIn('id', $userLabels)->where('id', $this->systemConfig['free_node_users_id'])->select(
+                    "id", "enable", "username", "passwd", "t", "u", "d", "transfer_enable",
+                    "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
+                    "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->first();
+
+                //datetime 转timestamp
+                $user['switch'] = 1;
+                $user['email'] = $user['username'];
+                $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp());
+
+                //v2ray用户信息
+                $user->v2ray_user = [
+                    "uuid"     => $user->v2ray_uuid,
+                    "email"    => sprintf("%[email protected]", $user->v2ray_uuid),
+                    "alter_id" => $user->v2ray_alter_id,
+                    "level"    => $user->v2ray_level,
+                ];
+
+                array_push($data, $user);
+            }
+        }
+
+        $load = '1';
+        $uptime = time();
+
+        $log = new SsNodeInfo();
+        $log->node_id = $nodeId;
+        $log->load = $load;
+        $log->uptime = $uptime;
+        $log->log_time = time();
+        $log->save();
+
+        return Response::json([
+            'msg'  => 'ok',
+            'data' => $data,
+        ]);
+    }
+
+    // 写在线用户日志
+    public function onlineUserLog(Request $request)
+    {
+        $nodeId = $request->route('id');
+        $count = $request->get('count');
+        $log = new SsNodeOnlineLog();
+        $log->node_id = $nodeId;
+        $log->online_user = $count;
+        $log->log_time = time();
+
+        if (!$log->save()) {
+            return response()->json([
+                "ret" => 0,
+                "msg" => "update failed",
+            ]);
+        }
+
+        return response()->json([
+            "ret" => 1,
+            "msg" => "ok",
+        ]);
+    }
+
+    // 节点信息
+    public function info(Request $request)
+    {
+        $nodeId = $request->route('id');
+        $load = $request->get('load');
+        $uptime = $request->get('uptime');
+
+        $log = new SsNodeInfo();
+        $log->node_id = $nodeId;
+        $log->load = $load;
+        $log->uptime = $uptime;
+        $log->log_time = time();
+
+        if (!$log->save()) {
+            return response()->json([
+                "ret" => 0,
+                "msg" => "update failed",
+            ]);
+        }
+
+        return response()->json([
+            "ret" => 1,
+            "msg" => "ok",
+        ]);
+    }
+
+    // PostTraffic
+    public function postTraffic(Request $request)
+    {
+        $nodeId = $request->route('id');
+        $input = $request->getContent();
+        $data = json_decode($input, true);
+
+        $node = SsNode::query()->where('id', $nodeId)->first();
+
+        foreach ($data as $vo) {
+            $user = User::query()->where('id', $vo['user_id'])->first();
+            if (!$user) {
+                continue;
+            }
+
+            $user->t = time();
+            $user->u = $user->u + ($vo['u'] * $node->traffic_rate);
+            $user->d = $user->d + ($vo['d'] * $node->traffic_rate);
+            $user->save();
+
+            // 记录流量日志
+            $this->addUserTrafficLog($vo['user_id'], $nodeId, $vo['u'], $vo['d'], $node->traffic_rate);
+        }
+
+        return response()->json([
+            'ret' => 1,
+            "msg" => "ok",
+        ]);
+    }
+
+    // V2ray Users
+    public function v2rayUsers(Request $request)
+    {
+        $nodeId = $request->route('id');
+
+        $node = SsNode::query()->where('id', $nodeId)->first();
+        $users = User::query()->whereIn('status', [0, 1])->where('enable', 1)->where('id', '<>', $this->systemConfig['free_node_users_id'])->get();
+
+        $v2ray = new Generator();
+        $v2ray->setPort($node->v2ray_port);
+
+        foreach ($users as $user) {
+            $email = sprintf("%[email protected]", $user->v2ray_uuid);
+            $v2ray->addUser($user->v2ray_uuid, $user->v2ray_level, $user->v2ray_alter_id, $email);
+        }
+
+        if ($this->systemConfig['is_free_node']) {
+            if ($request->route('id') == $this->systemConfig['free_node_id']) {
+                $freeuser = User::query()->where('enable', 1)->where('id', $this->systemConfig['free_node_users_id'])->first();
+                $email = sprintf("%[email protected]", $freeuser->v2ray_uuid);
+                $v2ray->addUser($freeuser->v2ray_uuid, $freeuser->v2ray_level, $freeuser->v2ray_alter_id, $email);
+            }
+        }
+
+        return Response::json($v2ray->getArr());
+    }
+
+    // 写入流量日志
+    private function addUserTrafficLog($userId, $nodeId, $u, $d, $rate)
+    {
+        $totalTraffic = flowAutoShow(($u + $d) * $rate);
+        $traffic = new UserTrafficLog();
+        $traffic->user_id = $userId;
+        $traffic->u = $u;
+        $traffic->d = $d;
+        $traffic->node_id = $nodeId;
+        $traffic->rate = $rate;
+        $traffic->traffic = $totalTraffic;
+        $traffic->log_time = time();
+
+        return $traffic->save();
+    }
+}

+ 77 - 0
app/Http/Controllers/Muv2/UserController.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace App\Http\Controllers\Muv2;
+
+use App\Http\Controllers\Controller;
+use App\Http\Models\SsNode;
+use App\Http\Models\User;
+use App\Http\Models\UserTrafficLog;
+use Illuminate\Http\Request;
+
+class UserController extends Controller
+{
+    // 用户列表
+    public function index()
+    {
+        $users = User::query()->where('enable', 1)->select(
+            "id", "username", "passwd", "t", "u", "d", "transfer_enable",
+            "port", "protocol", "obfs", "enable", "expire_time as expire_time_d", "method",
+            "v2ray_uuid", "v2ray_level", "v2ray_alter_id")->get();
+
+        foreach ($users as $user) {
+            $user['switch'] = 1;
+            $user['email'] = $user['username'];
+            $user['expire_time'] = strval((new \DateTime($user['expire_time_d']))->getTimestamp()); // datetime 转timestamp
+        }
+
+        return response()->json([
+            "data" => $users
+        ]);
+    }
+
+    // 更新流量到user表
+    public function addTraffic(Request $request)
+    {
+        $userId = $request->route('id');
+        $u = $request->get('u');
+        $d = $request->get('d');
+        $nodeId = $request->get('node_id');
+
+        $node = SsNode::query()->where('id', $nodeId)->first();
+        $user = User::query()->where('id', $userId)->first();
+
+        $user->t = time();
+        $user->u = $user->u + ($u * $node->traffic_rate);
+        $user->d = $user->d + ($d * $node->traffic_rate);
+
+        if (!$user->save()) {
+            return response()->json([
+                "msg" => "update failed",
+            ], 400);
+        }
+
+        // 记录流量日志
+        $this->addUserTrafficLog($userId, $nodeId, $u, $d, $node->traffic_rate);
+
+        return response()->json([
+            'ret' => 1,
+            "msg" => "ok",
+        ]);
+    }
+
+    // 写入流量日志
+    private function addUserTrafficLog($userId, $nodeId, $u, $d, $rate)
+    {
+        $totalTraffic = flowAutoShow(($u + $d) * $rate);
+        $traffic = new UserTrafficLog();
+        $traffic->user_id = $userId;
+        $traffic->u = $u;
+        $traffic->d = $d;
+        $traffic->node_id = $nodeId;
+        $traffic->rate = $rate;
+        $traffic->traffic = $totalTraffic;
+        $traffic->log_time = time();
+
+        return $traffic->save();
+    }
+}

+ 5 - 5
app/Http/Middleware/Muv2.php

@@ -18,18 +18,18 @@ class Muv2
      */
     public function handle($request, Closure $next)
     {
-        //验证muKey
+        // 验证mukey
         $muKey = $request->header("Token", '');
-        if ($muKey != $_ENV['MU_KEY']) {
+        if ($muKey != $_ENV['MU_KEY']) { // TODO:改造成每个节点都有一个mukey
             return response()->json([
                 'ret' => 0,
                 'msg' => 'token or source is invalid'
             ], 401);
         }
 
-        //验证ip是否在节点ip列表当中
-        $ssnode = SsNode::query()->where('ip', $_SERVER["REMOTE_ADDR"])->orWhere('ipv6', $_SERVER["REMOTE_ADDR"])->first();
-        if ($ssnode == null && $_SERVER["REMOTE_ADDR"] != '127.0.0.1') {
+        // 验证IP是否在节点IP列表当中
+        $node = SsNode::query()->where('ip', $_SERVER["REMOTE_ADDR"])->orWhere('ipv6', $_SERVER["REMOTE_ADDR"])->first();
+        if (!$node && $_SERVER["REMOTE_ADDR"] != '127.0.0.1') {
             return response()->json([
                 'ret' => 0,
                 'msg' => 'token or source is invalid'

+ 1 - 1
app/Http/Middleware/VerifyCsrfToken.php

@@ -12,6 +12,6 @@ class VerifyCsrfToken extends BaseVerifier
      * @var array
      */
     protected $except = [
-        "payment/*", "mu/v2/*"
+        "payment/*", "Muv2/*"
     ];
 }

+ 1 - 1
app/Http/V2ray/EmptyClass.php

@@ -1,7 +1,7 @@
 <?php
 
 
-namespace App\Http\V2ray;
+namespace App\Http\V2Ray;
 
 
 class EmptyClass

+ 18 - 17
app/Http/V2ray/V2rayGenerator.php → app/Http/V2ray/Generator.php

@@ -1,47 +1,48 @@
 <?php
 
 
-namespace App\Http\V2ray;
+namespace App\Http\V2Ray;
 
 
-use App\Http\V2ray\EmptyClass;
+use App\Http\V2Ray\EmptyClass;
 
-class V2rayGenerator
+//https://www.v2ray.com/ui_client/service.html
+class Generator
 {
 
     private $arr = [
-        "log" => [
-            "access" => "/var/log/access.log",
-            "error" => "/var/log/error.log",
+        "log"            => [
+            "access"   => "/var/log/access.log",
+            "error"    => "/var/log/error.log",
             "loglevel" => "warning"
         ],
-        "inbound" => [
-            "port" => 8300,
+        "inbound"        => [
+            "port"     => 8300,
             "protocol" => "vmess",
             "settings" => [
                 "clients" => [
                 ]
             ]
         ],
-        "outbound" => [
+        "outbound"       => [
             "protocol" => "freedom",
             // "settings" => ,
         ],
-        "inboundDetour" => [],
+        "inboundDetour"  => [],
         "outboundDetour" => [
             [
                 "protocol" => "blackhole",
                 // "settings" => [],
-                "tag" => "blocked"
+                "tag"      => "blocked"
             ]
         ],
-        "routing" => [
+        "routing"        => [
             "strategy" => "rules",
             "settings" => [
                 "rules" => [
                     [
-                        "type" => "field",
-                        "ip" => [
+                        "type"        => "field",
+                        "ip"          => [
                             "0.0.0.0/8",
                             "10.0.0.0/8",
                             "100.64.0.0/10",
@@ -69,10 +70,10 @@ class V2rayGenerator
     public function addUser($uuid, $level, $alertId, $email)
     {
         $user = [
-            "id" => $uuid,
-            "level" => $level,
+            "id"      => $uuid,
+            "level"   => $level,
             "alterId" => $alertId,
-            "email" => $email
+            "email"   => $email
         ];
         array_push($this->arr["inbound"]['settings']['clients'], $user);
     }

+ 2 - 0
routes/api.php

@@ -4,5 +4,7 @@ Route::group(['namespace' => 'Api'], function () {
     Route::any('yzy/create', 'YzyController@create');
     Route::resource('yzy', 'YzyController');
 
+    // 定制客户端
     Route::get('login', 'LoginController@login');
+
 });

+ 9 - 8
routes/web.php

@@ -127,12 +127,13 @@ Route::group(['middleware' => ['forbidden', 'user', 'affiliate']], function () {
 
 });
 
-Route::group(['middleware' => ['Muv2']], function (){ //Muv2 for V2ray
-    Route::get('mu/v2/users','Muv2\UserController@index');
-    Route::post('mu/v2/users/{id}/traffic','Muv2\UserController@addTraffic');
-    Route::post('mu/v2/nodes/{id}/online_count','Muv2\NodeController@onlineUserLog');
-    Route::post('mu/v2/nodes/{id}/info','Muv2\NodeController@info');
-    Route::get('mu/v2/nodes/{id}/users','Muv2\NodeController@users');
-    Route::get('mu/v2/nodes/{id}/v2rayUsers','Muv2\NodeController@v2rayUsers');
-    Route::post('mu/v2/nodes/{id}/traffic','Muv2\NodeController@postTraffic');
+// V2Ray
+Route::group(['namespaces' => 'Muv2', 'prefix' => 'mu/v2', 'middleware' => ['Muv2']], function () {
+    Route::get('users', 'UserController@index');
+    Route::post('users/{id}/traffic', 'UserController@addTraffic');
+    Route::post('nodes/{id}/online_count', 'NodeController@onlineUserLog');
+    Route::post('nodes/{id}/info', 'NodeController@info');
+    Route::get('nodes/{id}/users', 'NodeController@users');
+    Route::get('nodes/{id}/v2rayUsers', 'NodeController@v2rayUsers');
+    Route::post('nodes/{id}/traffic', 'NodeController@postTraffic');
 });