浏览代码

Merge branch 'dev' of https://github.com/v2board/v2board into dev

v2board 2 年之前
父节点
当前提交
c8f3684312

+ 2 - 1
app/Console/Commands/V2boardUpdate.php

@@ -57,6 +57,7 @@ class V2boardUpdate extends Command
             } catch (\Exception $e) {
             }
         }
-        $this->info('更新完毕,请重新启动队列服务。');
+        \Artisan::call('horizon:terminate');
+        $this->info('更新完毕,队列服务已重启,你无需进行任何操作。');
     }
 }

+ 17 - 2
app/Http/Controllers/Admin/Server/RouteController.php

@@ -15,6 +15,12 @@ class RouteController extends Controller
     public function fetch(Request $request)
     {
         $routes = ServerRoute::get();
+        // TODO: remove on 1.8.0
+        foreach ($routes as $k => $route) {
+            $array = json_decode($route->match, true);
+            if (is_array($array)) $routes[$k]['match'] = $array;
+        }
+        // TODO: remove on 1.8.0
         return [
             'data' => $routes
         ];
@@ -24,10 +30,19 @@ class RouteController extends Controller
     {
         $params = $request->validate([
             'remarks' => 'required',
-            'match' => 'required',
-            'action' => 'required',
+            'match' => 'required|array',
+            'action' => 'required|in:block,dns',
             'action_value' => 'nullable'
+        ], [
+            'remarks.required' => '备注不能为空',
+            'match.required' => '匹配值不能为空',
+            'action.required' => '动作类型不能为空',
+            'action.in' => '动作类型参数有误'
         ]);
+        $params['match'] = array_filter($params['match']);
+        // TODO: remove on 1.8.0
+        $params['match'] = json_encode($params['match']);
+        // TODO: remove on 1.8.0
         if ($request->input('id')) {
             try {
                 $route = ServerRoute::find($request->input('id'));

+ 5 - 4
app/Http/Controllers/Admin/ThemeController.php

@@ -25,9 +25,9 @@ class ThemeController extends Controller
     {
         $themeConfigs = [];
         foreach ($this->themes as $theme) {
-            $themeConfigFile = $this->path . "{$theme}/config.php";
+            $themeConfigFile = $this->path . "{$theme}/config.json";
             if (!File::exists($themeConfigFile)) continue;
-            $themeConfig = include($themeConfigFile);
+            $themeConfig = json_decode(File::get($themeConfigFile), true);
             if (!isset($themeConfig['configs']) || !is_array($themeConfig)) continue;
             $themeConfigs[$theme] = $themeConfig;
             if (config("theme.{$theme}")) continue;
@@ -60,9 +60,10 @@ class ThemeController extends Controller
         ]);
         $payload['config'] = json_decode(base64_decode($payload['config']), true);
         if (!$payload['config'] || !is_array($payload['config'])) abort(500, '参数有误');
-        $themeConfigFile = public_path("theme/{$payload['name']}/config.php");
+        $themeConfigFile = public_path("theme/{$payload['name']}/config.json");
         if (!File::exists($themeConfigFile)) abort(500, '主题不存在');
-        $themeConfig = include($themeConfigFile);
+        $themeConfig = json_decode(File::get($themeConfigFile), true);
+        if (!isset($themeConfig['configs']) || !is_array($themeConfig)) abort(500, '主题配置文件有误');
         $validateFields = array_column($themeConfig['configs'], 'field_name');
         $config = [];
         foreach ($validateFields as $validateField) {

+ 9 - 0
app/Http/Controllers/Client/Protocols/Surfboard.php

@@ -71,6 +71,15 @@ class Surfboard
         $config = str_replace('$subs_domain', $subsDomain, $config);
         $config = str_replace('$proxies', $proxies, $config);
         $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
+
+        $upload = round($user['u'] / (1024*1024*1024), 2);
+        $download = round($user['d'] / (1024*1024*1024), 2);
+        $useTraffic = $upload + $download;
+        $totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
+        $expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
+        $subscribeInfo = "title={$appName}订阅信息, content=上传流量:{$upload}GB\\n下载流量:{$download}GB\\n剩余流量:{$useTraffic}GB\\n套餐流量:{$totalTraffic}GB\\n到期时间:{$expireDate}";
+        $config = str_replace('$subscribe_info', $subscribeInfo, $config);
+
         return $config;
     }
 

+ 9 - 0
app/Http/Controllers/Client/Protocols/Surge.php

@@ -72,6 +72,15 @@ class Surge
         $config = str_replace('$subs_domain', $subsDomain, $config);
         $config = str_replace('$proxies', $proxies, $config);
         $config = str_replace('$proxy_group', rtrim($proxyGroup, ', '), $config);
+
+        $upload = round($user['u'] / (1024*1024*1024), 2);
+        $download = round($user['d'] / (1024*1024*1024), 2);
+        $useTraffic = $upload + $download;
+        $totalTraffic = round($user['transfer_enable'] / (1024*1024*1024), 2);
+        $expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
+        $subscribeInfo = "title={$appName}订阅信息, content=上传流量:{$upload}GB\\n下载流量:{$download}GB\\n剩余流量:{$useTraffic}GB\\n套餐流量:{$totalTraffic}GB\\n到期时间:{$expireDate}";
+        $config = str_replace('$subscribe_info', $subscribeInfo, $config);
+
         return $config;
     }
 

+ 25 - 0
app/Http/Controllers/User/UserController.php

@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
 use App\Http\Requests\User\UserTransfer;
 use App\Http\Requests\User\UserUpdate;
 use App\Http\Requests\User\UserChangePassword;
+use App\Services\AuthService;
 use App\Services\UserService;
 use App\Utils\CacheKey;
 use Illuminate\Http\Request;
@@ -18,6 +19,30 @@ use Illuminate\Support\Facades\Cache;
 
 class UserController extends Controller
 {
+    public function getActiveSession(Request $request)
+    {
+        $user = User::find($request->user['id']);
+        if (!$user) {
+            abort(500, __('The user does not exist'));
+        }
+        $authService = new AuthService($user);
+        return response([
+            'data' => $authService->getSessions()
+        ]);
+    }
+
+    public function removeActiveSession(Request $request)
+    {
+        $user = User::find($request->user['id']);
+        if (!$user) {
+            abort(500, __('The user does not exist'));
+        }
+        $authService = new AuthService($user);
+        return response([
+            'data' => $authService->delSession($request->input('session_id'))
+        ]);
+    }
+
     public function checkLogin(Request $request)
     {
         $data = [

+ 2 - 1
app/Http/Routes/UserRoute.php

@@ -21,11 +21,12 @@ class UserRoute
             $router->get ('/checkLogin', 'User\\UserController@checkLogin');
             $router->post('/transfer', 'User\\UserController@transfer');
             $router->post('/getQuickLoginUrl', 'User\\UserController@getQuickLoginUrl');
+            $router->get ('/getActiveSession', 'User\\UserController@getActiveSession');
+            $router->post('/removeActiveSession', 'User\\UserController@removeActiveSession');
             // Order
             $router->post('/order/save', 'User\\OrderController@save');
             $router->post('/order/checkout', 'User\\OrderController@checkout');
             $router->get ('/order/check', 'User\\OrderController@check');
-            $router->get ('/order/details', 'User\\OrderController@detail');                                            // TODO: 1.7.0 remove
             $router->get ('/order/detail', 'User\\OrderController@detail');
             $router->get ('/order/fetch', 'User\\OrderController@fetch');
             $router->get ('/order/getPaymentMethod', 'User\\OrderController@getPaymentMethod');

+ 14 - 1
app/Services/AuthService.php

@@ -14,7 +14,7 @@ class AuthService
 {
     private $user;
 
-    public function __construct($user)
+    public function __construct(User $user)
     {
         $this->user = $user;
     }
@@ -76,10 +76,23 @@ class AuthService
             $cacheKey,
             $sessions
         )) return false;
+        return true;
     }
 
     public function getSessions()
     {
         return (array)Cache::get(CacheKey::get("USER_SESSIONS", $this->user->id), []);
     }
+
+    public function delSession($sessionId)
+    {
+        $cacheKey = CacheKey::get("USER_SESSIONS", $this->user->id);
+        $sessions = (array)Cache::get($cacheKey, []);
+        unset($sessions[$sessionId]);
+        if (!Cache::put(
+            $cacheKey,
+            $sessions
+        )) return false;
+        return true;
+    }
 }

+ 8 - 1
app/Services/ServerService.php

@@ -221,7 +221,14 @@ class ServerService
 
     public function getRoutes(array $routeIds)
     {
-        return ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get();
+        $routes = ServerRoute::select(['id', 'match', 'action', 'action_value'])->whereIn('id', $routeIds)->get();
+        // TODO: remove on 1.8.0
+        foreach ($routes as $k => $route) {
+            $array = json_decode($route->match, true);
+            if (is_array($array)) $routes[$k]['match'] = $array;
+        }
+        // TODO: remove on 1.8.0
+        return $routes;
     }
 
     public function getServer($serverId, $serverType)

+ 4 - 3
app/Services/ThemeService.php

@@ -18,9 +18,10 @@ class ThemeService
 
     public function init()
     {
-        $themeConfigFile = $this->path . "{$this->theme}/config.php";
-        if (!File::exists($themeConfigFile)) return;
-        $themeConfig = include($themeConfigFile);
+        $themeConfigFile = $this->path . "{$this->theme}/config.json";
+        if (!File::exists($themeConfigFile)) abort(500, "{$this->theme}主题不存在");
+        $themeConfig = json_decode(File::get($themeConfigFile), true);
+        if (!isset($themeConfig['configs']) || !is_array($themeConfig)) abort(500, "{$this->theme}主题配置文件有误");
         $configs = $themeConfig['configs'];
         $data = [];
         foreach ($configs as $config) {

+ 1 - 1
config/app.php

@@ -237,5 +237,5 @@ return [
     | The only modification by laravel config
     |
     */
-    'version' => '1.7.2'
+    'version' => '1.7.2.1671294313058'
 ];

文件差异内容过多而无法显示
+ 0 - 0
public/assets/admin/components.async.js


文件差异内容过多而无法显示
+ 0 - 0
public/assets/admin/components.chunk.css


文件差异内容过多而无法显示
+ 0 - 0
public/assets/admin/umi.js


文件差异内容过多而无法显示
+ 0 - 0
public/assets/admin/vendors.async.js


文件差异内容过多而无法显示
+ 0 - 0
public/theme/v2board/assets/components.async.js


文件差异内容过多而无法显示
+ 0 - 0
public/theme/v2board/assets/umi.js


文件差异内容过多而无法显示
+ 0 - 0
public/theme/v2board/assets/vendors.async.js


+ 49 - 0
public/theme/v2board/config.json

@@ -0,0 +1,49 @@
+{
+    "name": "v2board",
+    "description": "v2board",
+    "version": "1.7.2",
+    "images": "https://images.unsplash.com/photo-1515405295579-ba7b45403062?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2160&q=80",
+    "configs": [{
+        "label": "主题色",
+        "placeholder": "请选择主题颜色",
+        "field_name": "theme_color",
+        "field_type": "select",
+        "select_options": {
+            "default": "默认(蓝色)",
+            "green": "奶绿色",
+            "black": "黑色",
+            "darkblue": "暗蓝色"
+        },
+        "default_value": "default"
+    }, {
+        "label": "背景",
+        "placeholder": "请输入背景图片URL",
+        "field_name": "background_url",
+        "field_type": "input"
+    }, {
+        "label": "边栏风格",
+        "placeholder": "请选择边栏风格",
+        "field_name": "theme_sidebar",
+        "field_type": "select",
+        "select_options": {
+            "light": "亮",
+            "dark": "暗"
+        },
+        "default_value": "light"
+    }, {
+        "label": "顶部风格",
+        "placeholder": "请选择顶部风格",
+        "field_name": "theme_header",
+        "field_type": "select",
+        "select_options": {
+            "light": "亮",
+            "dark": "暗"
+        },
+        "default_value": "dark"
+    }, {
+        "label": "自定义页脚HTML",
+        "placeholder": "可以实现客服JS代码的加入等",
+        "field_name": "custom_html",
+        "field_type": "textarea"
+    }]
+}

+ 0 - 53
public/theme/v2board/config.php

@@ -1,53 +0,0 @@
-<?php
-
-return [
-    'name' => 'V2board',
-    'description' => 'V2board默认主题',
-    'version' => '1.5.6',
-    'images' => 'https://images.unsplash.com/photo-1515405295579-ba7b45403062?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2160&q=80',
-    'configs' => [
-        [
-            'label' => '主题色',                               // 标签
-            'placeholder' => '请选择主题颜色',                   // 描述
-            'field_name' => 'theme_color',                    // 字段名 作为数据key使用
-            'field_type' => 'select',                         // 字段类型: select,input,switch
-            'select_options' => [                             // 当字段类型为select时有效
-                'default' => '默认(蓝色)',
-                'green' => '奶绿色',
-                'black' => '黑色',
-                'darkblue' => '暗蓝色',
-            ],
-            'default_value' => 'default'                       // 字段默认值,将会在首次进行初始化
-        ], [
-            'label' => '背景',
-            'placeholder' => '请输入背景图片URL',
-            'field_name' => 'background_url',
-            'field_type' => 'input'
-        ], [
-            'label' => '边栏风格',
-            'placeholder' => '请选择边栏风格',
-            'field_name' => 'theme_sidebar',
-            'field_type' => 'select',
-            'select_options' => [
-                'light' => '亮',
-                'dark' => '暗'
-            ],
-            'default_value' => 'light'
-        ], [
-            'label' => '顶部风格',
-            'placeholder' => '请选择顶部风格',
-            'field_name' => 'theme_header',
-            'field_type' => 'select',
-            'select_options' => [
-                'light' => '亮',
-                'dark' => '暗'
-            ],
-            'default_value' => 'dark'
-        ], [
-            'label' => '自定义页脚HTML',
-            'placeholder' => '可以实现客服JS代码的加入等',
-            'field_name' => 'custom_html',
-            'field_type' => 'textarea'
-        ]
-    ]
-];

+ 0 - 13
public/theme/v2board/dashboard.blade.php

@@ -59,19 +59,6 @@
 <script src="/theme/{{$theme}}/assets/vendors.async.js?v={{$version}}"></script>
 <script src="/theme/{{$theme}}/assets/components.async.js?v={{$version}}"></script>
 <script src="/theme/{{$theme}}/assets/umi.js?v={{$version}}"></script>
-<!-- Global site tag (gtag.js) - Google Analytics -->
-<script async src="https://www.googletagmanager.com/gtag/js?id=G-P1E9Z5LRRK"></script>
-<script>
-    window.dataLayer = window.dataLayer || [];
-
-    function gtag() {
-        dataLayer.push(arguments);
-    }
-
-    gtag('js', new Date());
-
-    gtag('config', 'G-P1E9Z5LRRK');
-</script>
 @if (file_exists(public_path("/theme/{$theme}/assets/custom.js")))
     <script src="/theme/{{$theme}}/assets/custom.js?v={{$version}}"></script>
 @endif

+ 4 - 7
readme.md

@@ -9,19 +9,16 @@
 - Laravel
 
 ## Demo
-[Demo](https://v2board.com)
+[Demo](https://demo.v2board.com)
 
 ## Document
-[Click](https://docs.v2board.com)
+[Click](https://v2board.com)
 
 ## Sponsors
 Thanks to the open source project license provided by [Jetbrains](https://www.jetbrains.com/)
 
 ## Community
-Telegram Channel: [@v2board](https://t.me/v2board)  
-Telegram Group: [@v2board_official](https://t.me/v2board_official)
+🔔Telegram Channel: [@v2board](https://t.me/v2board)  
 
 ## How to Feedback
-We have closed issues due to too much invalid feedback, you can give us your feedback in the following way.
- - Contact us through Community
- - Fork Dev branch commit pull request
+Follow the template in the issue to submit your question correctly, and we will have someone follow up with you.

+ 3 - 0
resources/rules/default.surfboard.conf

@@ -12,6 +12,9 @@ test-timeout = 5
 internet-test-url = http://bing.com
 proxy-test-url = http://bing.com
 
+[Panel]
+SubscribeInfo = $subscribe_info, style=info
+
 # Surfboard 的服务器和策略组配置方式与 Surge 类似, 可以参考 Surge 的规则配置手册: https://manual.nssurge.com/
 
 [Proxy]

+ 3 - 0
resources/rules/default.surge.conf

@@ -36,6 +36,9 @@ hide-crashlytics-request = true
 use-keyword-filter = false
 hide-udp = false
 
+[Panel]
+SubscribeInfo = $subscribe_info, style=info
+
 # -----------------------------
 # Surge 的几种策略配置规范,请参考 https://manual.nssurge.com/policy/proxy.html
 # 不同的代理策略有*很多*可选参数,请参考上方连接的 Parameters 一段,根据需求自行添加参数。

+ 0 - 13
resources/views/admin.blade.php

@@ -31,19 +31,6 @@
 <script src="/assets/admin/vendors.async.js?v={{$version}}"></script>
 <script src="/assets/admin/components.async.js?v={{$version}}"></script>
 <script src="/assets/admin/umi.js?v={{$version}}"></script>
-<!-- Global site tag (gtag.js) - Google Analytics -->
-<script async src="https://www.googletagmanager.com/gtag/js?id=G-P1E9Z5LRRK"></script>
-<script>
-    window.dataLayer = window.dataLayer || [];
-
-    function gtag() {
-        dataLayer.push(arguments);
-    }
-
-    gtag('js', new Date());
-
-    gtag('config', 'G-P1E9Z5LRRK');
-</script>
 </body>
 
 </html>

部分文件因为文件数量过多而无法显示