31 Commits
1.7.4 ... dev

Author SHA1 Message Date
7d36d47ca1 Add client middleware to subscribe route 2023-12-28 01:07:17 +08:00
532dfbf4b8 Refactor admin 2023-12-23 01:47:30 +08:00
7f2f9d1f16 Refactor payments 2023-08-23 01:33:08 +08:00
c67d015c94 Refactor admin 2023-12-23 01:38:37 +08:00
fa761f5d9a Refactor payments 2023-08-23 01:33:08 +08:00
fb338aeb96 Refactor payments 2023-08-23 01:33:08 +08:00
4f04eab073 Refactor ConfigController to use ConfigService 2023-12-19 01:26:41 +08:00
69c85983d1 update: add custom subscribe path 2023-12-08 15:27:33 +08:00
fa6670597a update: fix app 2023-10-27 03:11:47 +08:00
e980a6bbe0 update: i18n 2023-10-21 04:22:07 +08:00
80b96e730a update: remove guest plan api 2023-10-15 21:52:17 +08:00
3c372bd268 update: hytseria2 2023-10-01 22:44:31 +08:00
4434b13361 update: hysteria2 2023-09-28 13:34:58 +08:00
3f24ba9917 update: plan surplus feature 2023-08-20 03:21:33 +08:00
31c5cf1c2b update: vless 2023-08-02 01:52:25 +08:00
07de70d8ab update: set cancel order interval to 2 hours 2023-07-25 23:38:30 +08:00
e6b6d1022e update: rollback 2023-07-25 19:23:40 +08:00
c1097ad48f update: vless 2023-07-17 15:50:33 +08:00
4c865d0262 update: add vless 2023-07-17 15:40:08 +08:00
1a30aa30ad update: send email verify 2023-07-02 01:44:34 +08:00
6f8e395681 update: send email verify 2023-06-24 23:18:35 +08:00
757e605921 update: prevention of blasting 2023-06-24 23:00:02 +08:00
61f1d8a623 update: reconsitution 2023-06-14 11:38:21 +08:00
98bee6fa87 update: add v2 api 2023-06-13 18:49:40 +08:00
5ee58f32ca update: route 2023-06-13 18:43:48 +08:00
4c97d7e429 update: api version 2023-06-12 02:32:49 +08:00
32eaf301fe update: stat command 2023-06-05 14:33:58 +08:00
948177f22e update: stat service 2023-06-05 14:10:14 +08:00
b39299be23 update: stat command 2023-06-05 13:56:45 +08:00
228355a520 Merge branch 'dev' of https://github.com/v2board/v2board into dev 2023-06-05 03:43:44 +08:00
68db4f51b5 update: add system log filter 2023-06-05 03:43:34 +08:00
118 changed files with 1744 additions and 1175 deletions

View File

@ -14,7 +14,7 @@ DB_USERNAME=root
DB_PASSWORD=123456
BROADCAST_DRIVER=log
CACHE_DRIVER=file
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120

View File

@ -4,12 +4,9 @@ namespace App\Console\Commands;
use App\Models\StatServer;
use App\Models\StatUser;
use App\Models\User;
use App\Services\StatisticalService;
use Illuminate\Console\Command;
use App\Models\Order;
use App\Models\Stat;
use App\Models\CommissionLog;
use Illuminate\Support\Facades\DB;
class V2boardStatistics extends Command
@ -50,82 +47,94 @@ class V2boardStatistics extends Command
$this->statUser();
$this->statServer();
$this->stat();
$this->info('耗时' . (microtime(true) - $startAt));
info('统计任务执行完毕。耗时:' . (microtime(true) - $startAt) / 1000);
}
private function statServer()
{
$createdAt = time();
$recordAt = strtotime('-1 day', strtotime(date('Y-m-d')));
$statService = new StatisticalService();
$statService->setStartAt($recordAt);
$statService->setServerStats();
$stats = $statService->getStatServer();
DB::beginTransaction();
foreach ($stats as $stat) {
if (!StatServer::insert([
'server_id' => $stat['server_id'],
'server_type' => $stat['server_type'],
'u' => $stat['u'],
'd' => $stat['d'],
'created_at' => $createdAt,
'updated_at' => $createdAt,
'record_type' => 'd',
'record_at' => $recordAt
])) {
DB::rollback();
throw new \Exception('stat server fail');
try {
DB::beginTransaction();
$createdAt = time();
$recordAt = strtotime('-1 day', strtotime(date('Y-m-d')));
$statService = new StatisticalService();
$statService->setStartAt($recordAt);
$statService->setServerStats();
$stats = $statService->getStatServer();
foreach ($stats as $stat) {
if (!StatServer::insert([
'server_id' => $stat['server_id'],
'server_type' => $stat['server_type'],
'u' => $stat['u'],
'd' => $stat['d'],
'created_at' => $createdAt,
'updated_at' => $createdAt,
'record_type' => 'd',
'record_at' => $recordAt
])) {
throw new \Exception('stat server fail');
}
}
DB::commit();
$statService->clearStatServer();
} catch (\Exception $e) {
DB::rollback();
\Log::error($e->getMessage(), ['exception' => $e]);
}
DB::commit();
$statService->clearStatServer();
}
private function statUser()
{
$createdAt = time();
$recordAt = strtotime('-1 day', strtotime(date('Y-m-d')));
$statService = new StatisticalService();
$statService->setStartAt($recordAt);
$statService->setUserStats();
$stats = $statService->getStatUser();
DB::beginTransaction();
foreach ($stats as $stat) {
if (!StatUser::insert([
'user_id' => $stat['user_id'],
'u' => $stat['u'],
'd' => $stat['d'],
'server_rate' => $stat['server_rate'],
'created_at' => $createdAt,
'updated_at' => $createdAt,
'record_type' => 'd',
'record_at' => $recordAt
])) {
DB::rollback();
throw new \Exception('stat user fail');
try {
DB::beginTransaction();
$createdAt = time();
$recordAt = strtotime('-1 day', strtotime(date('Y-m-d')));
$statService = new StatisticalService();
$statService->setStartAt($recordAt);
$statService->setUserStats();
$stats = $statService->getStatUser();
foreach ($stats as $stat) {
if (!StatUser::insert([
'user_id' => $stat['user_id'],
'u' => $stat['u'],
'd' => $stat['d'],
'server_rate' => $stat['server_rate'],
'created_at' => $createdAt,
'updated_at' => $createdAt,
'record_type' => 'd',
'record_at' => $recordAt
])) {
throw new \Exception('stat user fail');
}
}
DB::commit();
$statService->clearStatUser();
} catch (\Exception $e) {
DB::rollback();
\Log::error($e->getMessage(), ['exception' => $e]);
}
DB::commit();
$statService->clearStatUser();
}
private function stat()
{
$endAt = strtotime(date('Y-m-d'));
$startAt = strtotime('-1 day', $endAt);
$statisticalService = new StatisticalService();
$statisticalService->setStartAt($startAt);
$statisticalService->setEndAt($endAt);
$data = $statisticalService->generateStatData();
$data['record_at'] = $startAt;
$data['record_type'] = 'd';
$statistic = Stat::where('record_at', $startAt)
->where('record_type', 'd')
->first();
if ($statistic) {
$statistic->update($data);
return;
try {
$endAt = strtotime(date('Y-m-d'));
$startAt = strtotime('-1 day', $endAt);
$statisticalService = new StatisticalService();
$statisticalService->setStartAt($startAt);
$statisticalService->setEndAt($endAt);
$data = $statisticalService->generateStatData();
$data['record_at'] = $startAt;
$data['record_type'] = 'd';
$statistic = Stat::where('record_at', $startAt)
->where('record_type', 'd')
->first();
if ($statistic) {
$statistic->update($data);
return;
}
Stat::create($data);
} catch (\Exception $e) {
\Log::error($e->getMessage(), ['exception' => $e]);
}
Stat::create($data);
}
}

View File

@ -1,18 +0,0 @@
<?php
namespace App\Http\Controllers\Guest;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Plan;
class PlanController extends Controller
{
public function fetch(Request $request)
{
$plan = Plan::where('show', 1)->get();
return response([
'data' => $plan
]);
}
}

View File

@ -0,0 +1,113 @@
<?php
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ConfigSave;
use App\Jobs\SendEmailJob;
use App\Services\ConfigService;
use App\Services\TelegramService;
use App\Utils\Dict;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Mail;
class ConfigController extends Controller
{
public function getEmailTemplate()
{
$path = resource_path('views/mail/');
$files = array_map(function ($item) use ($path) {
return str_replace($path, '', $item);
}, glob($path . '*'));
return response([
'data' => $files
]);
}
public function getThemeTemplate()
{
$path = public_path('theme/');
$files = array_map(function ($item) use ($path) {
return str_replace($path, '', $item);
}, glob($path . '*'));
return response([
'data' => $files
]);
}
public function testSendMail(Request $request)
{
$obj = new SendEmailJob([
'email' => $request->user['email'],
'subject' => 'This is v2board test email',
'template_name' => 'notify',
'template_value' => [
'name' => config('v2board.app_name', 'V2Board'),
'content' => 'This is v2board test email',
'url' => config('v2board.app_url')
]
]);
return response([
'data' => true,
'log' => $obj->handle()
]);
}
public function setTelegramWebhook(Request $request)
{
$hookUrl = url('/api/v1/guest/telegram/webhook?access_token=' . md5(config('v2board.telegram_bot_token', $request->input('telegram_bot_token'))));
$telegramService = new TelegramService($request->input('telegram_bot_token'));
$telegramService->getMe();
$telegramService->setWebhook($hookUrl);
return response([
'data' => true
]);
}
public function fetch(Request $request)
{
$key = $request->input('key');
$data = (new ConfigService)->getDefaultConfig();
if ($key && isset($data[$key])) {
return response([
'data' => [
$key => $data[$key]
]
]);
};
// TODO: default should be in Dict
return response([
'data' => $data
]);
}
public function save(ConfigSave $request)
{
$data = $request->validated();
$config = config('v2board');
foreach (ConfigSave::RULES as $k => $v) {
if (!in_array($k, array_keys(ConfigSave::RULES))) {
unset($config[$k]);
continue;
}
if (array_key_exists($k, $data)) {
$config[$k] = $data[$k];
}
}
$data = var_export($config, 1);
if (!File::put(base_path() . '/config/v2board.php', "<?php\n return $data ;")) {
abort(500, '修改失败');
}
if (function_exists('opcache_reset')) {
if (opcache_reset() === false) {
abort(500, '缓存清除失败请卸载或检查opcache配置状态');
}
}
Artisan::call('config:cache');
return response([
'data' => true
]);
}
}

View File

@ -1,15 +1,13 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Requests\Admin\CouponSave;
use App\Http\Requests\Admin\CouponGenerate;
use App\Models\Plan;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\CouponGenerate;
use App\Http\Requests\Admin\CouponSave;
use App\Models\Coupon;
use App\Utils\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class CouponController extends Controller

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\KnowledgeSave;
use App\Http\Requests\Admin\KnowledgeSort;
use App\Models\Knowledge;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class KnowledgeController extends Controller

View File

@ -1,11 +1,11 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Requests\Admin\NoticeSave;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\NoticeSave;
use App\Models\Notice;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class NoticeController extends Controller

View File

@ -1,19 +1,19 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\OrderAssign;
use App\Http\Requests\Admin\OrderUpdate;
use App\Http\Requests\Admin\OrderFetch;
use App\Http\Requests\Admin\OrderUpdate;
use App\Models\CommissionLog;
use App\Models\Order;
use App\Models\Plan;
use App\Models\User;
use App\Services\OrderService;
use App\Services\UserService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\User;
use App\Models\Plan;
use Illuminate\Support\Facades\DB;
class OrderController extends Controller

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\PaymentSave;
use App\Models\Payment;
use App\Services\PaymentService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Payment;
use Illuminate\Support\Facades\DB;
class PaymentController extends Controller

View File

@ -1,16 +1,16 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\PlanSave;
use App\Http\Requests\Admin\PlanSort;
use App\Http\Requests\Admin\PlanUpdate;
use App\Models\Order;
use App\Models\Plan;
use App\Models\User;
use App\Services\PlanService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Plan;
use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\DB;
class PlanController extends Controller

View File

@ -1,16 +1,14 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Controllers\Controller;
use App\Models\Plan;
use App\Models\ServerShadowsocks;
use App\Models\ServerTrojan;
use App\Models\ServerVmess;
use App\Models\ServerGroup;
use App\Models\ServerVmess;
use App\Models\User;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class GroupController extends Controller
{

View File

@ -1,14 +1,10 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Requests\Admin\ServerVmessSave;
use App\Http\Requests\Admin\ServerVmessUpdate;
use App\Models\ServerHysteria;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ServerVmess;
use App\Models\ServerHysteria;
use Illuminate\Http\Request;
class HysteriaController extends Controller
{
@ -28,7 +24,9 @@ class HysteriaController extends Controller
'up_mbps' => 'required|numeric|min:1',
'down_mbps' => 'required|numeric|min:1',
'server_name' => 'nullable',
'insecure' => 'required|in:0,1'
'insecure' => 'required|in:0,1',
'obfs_type' => 'nullable|in:salamander',
'ignore_client_bandwidth' => 'required|in:0,1'
]);
if ($request->input('id')) {

View File

@ -1,10 +1,10 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Controllers\Controller;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
class ManageController extends Controller

View File

@ -1,14 +1,10 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Requests\Admin\ServerShadowsocksSave;
use App\Http\Requests\Admin\ServerShadowsocksUpdate;
use App\Models\ServerRoute;
use App\Models\ServerShadowsocks;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ServerRoute;
use Illuminate\Http\Request;
class RouteController extends Controller
{

View File

@ -1,13 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ServerShadowsocksSave;
use App\Http\Requests\Admin\ServerShadowsocksUpdate;
use App\Models\ServerShadowsocks;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class ShadowsocksController extends Controller
{

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ServerTrojanSave;
use App\Http\Requests\Admin\ServerTrojanUpdate;
use App\Models\ServerTrojan;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ServerTrojan;
class TrojanController extends Controller
{

View File

@ -0,0 +1,119 @@
<?php
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Controllers\Controller;
use App\Models\ServerVless;
use Illuminate\Http\Request;
use ParagonIE_Sodium_Compat as SodiumCompat;
use App\Utils\Helper;
class VlessController extends Controller
{
public function save(Request $request)
{
$params = $request->validate([
'group_id' => 'required',
'route_id' => 'nullable|array',
'name' => 'required',
'parent_id' => 'nullable|integer',
'host' => 'required',
'port' => 'required',
'server_port' => 'required',
'tls' => 'required|in:0,1,2',
'tls_settings' => 'nullable|array',
'flow' => 'nullable|in:xtls-rprx-vision',
'network' => 'required',
'network_settings' => 'nullable|array',
'tags' => 'nullable|array',
'rate' => 'required',
'show' => 'nullable|in:0,1',
'sort' => 'nullable'
]);
if (isset($params['tls']) && (int)$params['tls'] === 2) {
$keyPair = SodiumCompat::crypto_box_keypair();
$params['tls_settings'] = $params['tls_settings'] ?? [];
if (!isset($params['tls_settings']['public_key'])) {
$params['tls_settings']['public_key'] = Helper::base64EncodeUrlSafe(SodiumCompat::crypto_box_publickey($keyPair));
}
if (!isset($params['tls_settings']['private_key'])) {
$params['tls_settings']['private_key'] = Helper::base64EncodeUrlSafe(SodiumCompat::crypto_box_secretkey($keyPair));
}
}
if ($request->input('id')) {
$server = ServerVless::find($request->input('id'));
if (!$server) {
abort(500, '服务器不存在');
}
try {
$server->update($params);
} catch (\Exception $e) {
abort(500, '保存失败');
}
return response([
'data' => true
]);
}
if (!ServerVless::create($params)) {
abort(500, '创建失败');
}
return response([
'data' => true
]);
}
public function drop(Request $request)
{
if ($request->input('id')) {
$server = ServerVless::find($request->input('id'));
if (!$server) {
abort(500, '节点ID不存在');
}
}
return response([
'data' => $server->delete()
]);
}
public function update(Request $request)
{
$params = $request->validate([
'show' => 'nullable|in:0,1',
]);
$server = ServerVless::find($request->input('id'));
if (!$server) {
abort(500, '该服务器不存在');
}
try {
$server->update($params);
} catch (\Exception $e) {
abort(500, '保存失败');
}
return response([
'data' => true
]);
}
public function copy(Request $request)
{
$server = ServerVless::find($request->input('id'));
$server->show = 0;
if (!$server) {
abort(500, '服务器不存在');
}
if (!ServerVless::create($server->toArray())) {
abort(500, '复制失败');
}
return response([
'data' => true
]);
}
}

View File

@ -1,13 +1,12 @@
<?php
namespace App\Http\Controllers\Admin\Server;
namespace App\Http\Controllers\V1\Admin\Server;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\ServerVmessSave;
use App\Http\Requests\Admin\ServerVmessUpdate;
use App\Services\ServerService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ServerVmess;
use Illuminate\Http\Request;
class VmessController extends Controller
{

View File

@ -1,97 +1,25 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Models\CommissionLog;
use App\Models\Order;
use App\Models\ServerShadowsocks;
use App\Models\ServerTrojan;
use App\Models\StatUser;
use App\Services\ServerService;
use App\Services\StatisticalService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ServerGroup;
use App\Models\ServerVmess;
use App\Models\Plan;
use App\Models\User;
use App\Models\Ticket;
use App\Models\Order;
use App\Models\Stat;
use App\Models\StatServer;
use App\Models\StatUser;
use App\Models\Ticket;
use App\Models\User;
use App\Services\StatisticalService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class StatController extends Controller
{
public function getStat(Request $request)
{
$params = $request->validate([
'start_at' => '',
'end_at' => ''
]);
if (isset($params['start_at']) && isset($params['end_at'])) {
$stats = Stat::where('record_at', '>=', $params['start_at'])
->where('record_at', '<', $params['end_at'])
->get()
->makeHidden(['record_at', 'created_at', 'updated_at', 'id', 'record_type'])
->toArray();
} else {
$statisticalService = new StatisticalService();
return [
'data' => $statisticalService->generateStatData()
];
}
$stats = array_reduce($stats, function($carry, $item) {
foreach($item as $key => $value) {
if(isset($carry[$key]) && $carry[$key]) {
$carry[$key] += $value;
} else {
$carry[$key] = $value;
}
}
return $carry;
}, []);
return [
'data' => $stats
];
}
public function getStatRecord(Request $request)
{
$request->validate([
'type' => 'required|in:paid_total,commission_total,register_count',
'start_at' => '',
'end_at' => ''
]);
$statisticalService = new StatisticalService();
$statisticalService->setStartAt($request->input('start_at'));
$statisticalService->setEndAt($request->input('end_at'));
return [
'data' => $statisticalService->getStatRecord($request->input('type'))
];
}
public function getRanking(Request $request)
{
$request->validate([
'type' => 'required|in:server_traffic_rank,user_consumption_rank,invite_rank',
'start_at' => '',
'end_at' => '',
'limit' => 'nullable|integer'
]);
$statisticalService = new StatisticalService();
$statisticalService->setStartAt($request->input('start_at'));
$statisticalService->setEndAt($request->input('end_at'));
return [
'data' => $statisticalService->getRanking($request->input('type'), $request->input('limit') ?? 20)
];
}
public function getOverride(Request $request)
{
return [

View File

@ -1,10 +1,11 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Models\Log as LogModel;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
@ -101,5 +102,18 @@ class SystemController extends Controller
return $master->status === 'paused';
})->count();
}
}
public function getSystemLog(Request $request) {
$current = $request->input('current') ? $request->input('current') : 1;
$pageSize = $request->input('page_size') >= 10 ? $request->input('page_size') : 10;
$builder = LogModel::orderBy('created_at', 'DESC')
->setFilterAllowKeys('level');
$total = $builder->count();
$res = $builder->forPage($current, $pageSize)
->get();
return response([
'data' => $res,
'total' => $total
]);
}
}

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Services\ThemeService;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
class ThemeController extends Controller
{

View File

@ -1,14 +1,13 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Jobs\SendEmailJob;
use App\Services\TicketService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ticket;
use App\Models\User;
use App\Models\TicketMessage;
use App\Models\User;
use App\Services\TicketService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

View File

@ -1,19 +1,18 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Http\Controllers\V1\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\UserFetch;
use App\Http\Requests\Admin\UserGenerate;
use App\Http\Requests\Admin\UserSendMail;
use App\Http\Requests\Admin\UserUpdate;
use App\Jobs\SendEmailJob;
use App\Models\Plan;
use App\Models\User;
use App\Services\AuthService;
use App\Services\UserService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Plan;
use Illuminate\Support\Facades\DB;
class UserController extends Controller
@ -75,7 +74,7 @@ class UserController extends Controller
$res[$i]['plan_name'] = $plan[$k]['name'];
}
}
$res[$i]['subscribe_url'] = Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $res[$i]['token']);
$res[$i]['subscribe_url'] = Helper::getSubscribeUrl($res[$i]['token']);
}
return response([
'data' => $res,
@ -166,7 +165,7 @@ class UserController extends Controller
$transferEnable = $user['transfer_enable'] ? $user['transfer_enable'] / 1073741824 : 0;
$notUseFlow = (($user['transfer_enable'] - ($user['u'] + $user['d'])) / 1073741824) ?? 0;
$planName = $user['plan_name'] ?? '无订阅';
$subscribeUrl = Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $user['token']);
$subscribeUrl = Helper::getSubscribeUrl($user['token']);
$data .= "{$user['email']},{$balance},{$commissionBalance},{$transferEnable},{$notUseFlow},{$expireDate},{$planName},{$subscribeUrl}\r\n";
}
echo "\xEF\xBB\xBF" . $data;
@ -241,7 +240,7 @@ class UserController extends Controller
$expireDate = $user['expired_at'] === NULL ? '长期有效' : date('Y-m-d H:i:s', $user['expired_at']);
$createDate = date('Y-m-d H:i:s', $user['created_at']);
$password = $request->input('password') ?? $user['email'];
$subscribeUrl = Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $user['token']);
$subscribeUrl = Helper::getSubscribeUrl($user['token']);
$data .= "{$user['email']},{$password},{$expireDate},{$user['uuid']},{$createDate},{$subscribeUrl}\r\n";
}
echo $data;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client;
namespace App\Http\Controllers\V1\Client;
use App\Http\Controllers\Controller;
use App\Services\ServerService;
@ -39,15 +39,15 @@ class AppController extends Controller
'chacha20-ietf-poly1305'
])
) {
array_push($proxy, Protocols\Clash::buildShadowsocks($user['uuid'], $item));
array_push($proxy, \App\Protocols\Clash::buildShadowsocks($user['uuid'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'vmess') {
array_push($proxy, Protocols\Clash::buildVmess($user['uuid'], $item));
array_push($proxy, \App\Protocols\Clash::buildVmess($user['uuid'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'trojan') {
array_push($proxy, Protocols\Clash::buildTrojan($user['uuid'], $item));
array_push($proxy, \App\Protocols\Clash::buildTrojan($user['uuid'], $item));
array_push($proxies, $item['name']);
}
}

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Client;
namespace App\Http\Controllers\V1\Client;
use App\Http\Controllers\Client\Protocols\General;
use App\Http\Controllers\Controller;
use App\Protocols\General;
use App\Services\ServerService;
use App\Services\UserService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use App\Services\UserService;
class ClientController extends Controller
{
@ -24,8 +24,8 @@ class ClientController extends Controller
$servers = $serverService->getAvailableServers($user);
$this->setSubscribeInfoToServers($servers, $user);
if ($flag) {
foreach (array_reverse(glob(app_path('Http//Controllers//Client//Protocols') . '/*.php')) as $file) {
$file = 'App\\Http\\Controllers\\Client\\Protocols\\' . basename($file, '.php');
foreach (array_reverse(glob(app_path('Protocols') . '/*.php')) as $file) {
$file = 'App\\Protocols\\' . basename($file, '.php');
$class = new $file($user, $servers);
if (strpos($flag, $class->flag) !== false) {
die($class->handle());

View File

@ -1,9 +1,9 @@
<?php
namespace App\Http\Controllers\Guest;
namespace App\Http\Controllers\V1\Guest;
use App\Utils\Dict;
use App\Http\Controllers\Controller;
use App\Utils\Dict;
use Illuminate\Support\Facades\Http;
class CommController extends Controller

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\Guest;
namespace App\Http\Controllers\V1\Guest;
use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Services\OrderService;
use App\Services\PaymentService;
use App\Services\TelegramService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class PaymentController extends Controller
{

View File

@ -1,10 +1,10 @@
<?php
namespace App\Http\Controllers\Guest;
namespace App\Http\Controllers\V1\Guest;
use App\Http\Controllers\Controller;
use App\Services\TelegramService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class TelegramController extends Controller
{

View File

@ -1,21 +1,21 @@
<?php
namespace App\Http\Controllers\Passport;
namespace App\Http\Controllers\V1\Passport;
use App\Http\Controllers\Controller;
use App\Http\Requests\Passport\AuthRegister;
use App\Http\Requests\Passport\AuthForget;
use App\Http\Requests\Passport\AuthLogin;
use App\Http\Requests\Passport\AuthRegister;
use App\Jobs\SendEmailJob;
use App\Services\AuthService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use App\Models\InviteCode;
use App\Models\Plan;
use App\Models\User;
use App\Models\InviteCode;
use App\Utils\Helper;
use App\Utils\Dict;
use App\Services\AuthService;
use App\Utils\CacheKey;
use App\Utils\Dict;
use App\Utils\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use ReCaptcha\ReCaptcha;
class AuthController extends Controller
@ -286,7 +286,11 @@ class AuthController extends Controller
public function forget(AuthForget $request)
{
$forgetRequestLimitKey = CacheKey::get('FORGET_REQUEST_LIMIT', $request->input('email'));
$forgetRequestLimit = (int)Cache::get($forgetRequestLimitKey);
if ($forgetRequestLimit >= 3) abort(500, __('Reset failed, Please try again later'));
if ((string)Cache::get(CacheKey::get('EMAIL_VERIFY_CODE', $request->input('email'))) !== (string)$request->input('email_code')) {
Cache::put($forgetRequestLimitKey, $forgetRequestLimit ? $forgetRequestLimit + 1 : 1, 300);
abort(500, __('Incorrect email verification code'));
}
$user = User::where('email', $request->input('email'))->first();

View File

@ -1,18 +1,18 @@
<?php
namespace App\Http\Controllers\Passport;
namespace App\Http\Controllers\V1\Passport;
use App\Http\Requests\Passport\CommSendEmailVerify;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Support\Facades\Mail;
use App\Utils\Helper;
use Illuminate\Support\Facades\Cache;
use App\Http\Requests\Passport\CommSendEmailVerify;
use App\Jobs\SendEmailJob;
use App\Models\InviteCode;
use App\Utils\Dict;
use App\Models\User;
use App\Utils\CacheKey;
use App\Utils\Dict;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Mail;
use ReCaptcha\ReCaptcha;
class CommController extends Controller

View File

@ -1,19 +1,16 @@
<?php
namespace App\Http\Controllers\Server;
namespace App\Http\Controllers\V1\Server;
use App\Http\Controllers\Controller;
use App\Models\ServerVmess;
use App\Services\ServerService;
use App\Services\StatisticalService;
use App\Services\UserService;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\ServerVmess;
use App\Models\ServerLog;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
/*
* V2ray Aurora

View File

@ -1,14 +1,13 @@
<?php
namespace App\Http\Controllers\Server;
namespace App\Http\Controllers\V1\Server;
use App\Http\Controllers\Controller;
use App\Models\ServerShadowsocks;
use App\Services\ServerService;
use App\Services\StatisticalService;
use App\Services\UserService;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Cache;
/*

View File

@ -1,19 +1,16 @@
<?php
namespace App\Http\Controllers\Server;
namespace App\Http\Controllers\V1\Server;
use App\Http\Controllers\Controller;
use App\Models\ServerTrojan;
use App\Services\ServerService;
use App\Services\StatisticalService;
use App\Services\UserService;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\ServerTrojan;
use App\Models\ServerLog;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;
/*
* Tidal Lab Trojan

View File

@ -1,17 +1,13 @@
<?php
namespace App\Http\Controllers\Server;
namespace App\Http\Controllers\V1\Server;
use App\Http\Controllers\Controller;
use App\Services\ServerService;
use App\Services\StatisticalService;
use App\Services\UserService;
use App\Utils\CacheKey;
use App\Utils\Helper;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\ServerShadowsocks;
use App\Models\ServerVmess;
use App\Models\ServerTrojan;
use Illuminate\Support\Facades\Cache;
class UniProxyController extends Controller
@ -112,7 +108,19 @@ class UniProxyController extends Controller
'server_name' => $this->nodeInfo->server_name,
'up_mbps' => $this->nodeInfo->up_mbps,
'down_mbps' => $this->nodeInfo->down_mbps,
'obfs' => Helper::getServerKey($this->nodeInfo->created_at, 16)
'obfs' => Helper::getServerKey($this->nodeInfo->created_at, 16),
'obfs_type' => $this->nodeInfo->obfs_type,
'ignore_client_bandwidth' => !!$this->nodeInfo->ignore_client_bandwidth
];
break;
case "vless":
$response = [
'server_port' => $this->nodeInfo->server_port,
'network' => $this->nodeInfo->network,
'network_settings' => $this->nodeInfo->network_settings,
'tls' => $this->nodeInfo->tls,
'flow' => $this->nodeInfo->flow,
'tls_settings' => $this->nodeInfo->tls_settings
];
break;
}

View File

@ -1,11 +1,11 @@
<?php
namespace App\Http\Controllers\Staff;
namespace App\Http\Controllers\V1\Staff;
use App\Http\Requests\Admin\NoticeSave;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\NoticeSave;
use App\Models\Notice;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class NoticeController extends Controller

View File

@ -1,15 +1,11 @@
<?php
namespace App\Http\Controllers\Staff;
namespace App\Http\Controllers\V1\Staff;
use App\Http\Requests\Admin\PlanSave;
use App\Http\Requests\Admin\PlanSort;
use App\Http\Requests\Admin\PlanUpdate;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Plan;
use App\Models\Order;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class PlanController extends Controller

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\Staff;
namespace App\Http\Controllers\V1\Staff;
use App\Services\TicketService;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ticket;
use App\Models\TicketMessage;
use App\Services\TicketService;
use Illuminate\Http\Request;
class TicketController extends Controller
{

View File

@ -1,14 +1,14 @@
<?php
namespace App\Http\Controllers\Staff;
namespace App\Http\Controllers\V1\Staff;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\UserSendMail;
use App\Http\Requests\Staff\UserUpdate;
use App\Jobs\SendEmailJob;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Plan;
use App\Models\User;
use Illuminate\Http\Request;
class UserController extends Controller
{

View File

@ -1,11 +1,11 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\Payment;
use App\Utils\Dict;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class CommController extends Controller
{

View File

@ -1,11 +1,10 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Services\CouponService;
use Illuminate\Http\Request;
use App\Models\Coupon;
class CouponController extends Controller
{

View File

@ -1,14 +1,14 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\CommissionLog;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Order;
use App\Models\InviteCode;
use App\Models\Order;
use App\Models\User;
use App\Utils\Helper;
use Illuminate\Http\Request;
class InviteController extends Controller
{

View File

@ -1,13 +1,13 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\Knowledge;
use App\Models\User;
use App\Services\UserService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use App\Models\Knowledge;
class KnowledgeController extends Controller
{
@ -24,7 +24,7 @@ class KnowledgeController extends Controller
if (!$userService->isAvailable($user)) {
$this->formatAccessData($knowledge['body']);
}
$subscribeUrl = Helper::getSubscribeUrl("/api/v1/client/subscribe?token={$user['token']}");
$subscribeUrl = Helper::getSubscribeUrl($user['token']);
$knowledge['body'] = str_replace('{{siteName}}', config('v2board.app_name', 'V2Board'), $knowledge['body']);
$knowledge['body'] = str_replace('{{subscribeUrl}}', $subscribeUrl, $knowledge['body']);
$knowledge['body'] = str_replace('{{urlEncodeSubscribeUrl}}', urlencode($subscribeUrl), $knowledge['body']);

View File

@ -1,11 +1,10 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Notice;
use App\Utils\Helper;
use Illuminate\Http\Request;
class NoticeController extends Controller
{

View File

@ -1,29 +1,28 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\User\OrderSave;
use App\Models\CommissionLog;
use App\Models\Order;
use App\Models\Payment;
use App\Models\Plan;
use App\Models\User;
use App\Services\CouponService;
use App\Services\OrderService;
use App\Services\PaymentService;
use App\Services\PlanService;
use App\Services\UserService;
use App\Utils\Helper;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use App\Models\Order;
use App\Models\Plan;
use App\Models\User;
use App\Utils\Helper;
use Omnipay\Omnipay;
use Stripe\Stripe;
use Stripe\Source;
use Library\BitpayX;
use Library\MGate;
use Library\Epay;
use Library\MGate;
use Omnipay\Omnipay;
use Stripe\Source;
use Stripe\Stripe;
class OrderController extends Controller
{

View File

@ -1,12 +1,12 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\Plan;
use App\Models\User;
use App\Services\PlanService;
use Illuminate\Http\Request;
use App\Models\Plan;
use Illuminate\Support\Facades\DB;
class PlanController extends Controller

View File

@ -1,18 +1,13 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Services\ServerService;
use App\Services\UserService;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use App\Models\ServerVmess;
use App\Models\ServerLog;
use App\Models\User;
use App\Utils\Helper;
use Illuminate\Support\Facades\DB;
class ServerController extends Controller

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\StatUser;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Models\User;

View File

@ -1,18 +1,17 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\User\TicketSave;
use App\Http\Requests\User\TicketWithdraw;
use App\Jobs\SendTelegramJob;
use App\Models\Ticket;
use App\Models\TicketMessage;
use App\Models\User;
use App\Services\TelegramService;
use App\Services\TicketService;
use App\Utils\Dict;
use Illuminate\Http\Request;
use App\Models\Ticket;
use App\Models\TicketMessage;
use Illuminate\Support\Facades\DB;
class TicketController extends Controller

View File

@ -1,20 +1,20 @@
<?php
namespace App\Http\Controllers\User;
namespace App\Http\Controllers\V1\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\User\UserChangePassword;
use App\Http\Requests\User\UserTransfer;
use App\Http\Requests\User\UserUpdate;
use App\Http\Requests\User\UserChangePassword;
use App\Models\Order;
use App\Models\Plan;
use App\Models\Ticket;
use App\Models\User;
use App\Services\AuthService;
use App\Services\UserService;
use App\Utils\CacheKey;
use Illuminate\Http\Request;
use App\Models\User;
use App\Models\Plan;
use App\Models\Ticket;
use App\Utils\Helper;
use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class UserController extends Controller
@ -151,7 +151,7 @@ class UserController extends Controller
abort(500, __('Subscription plan does not exist'));
}
}
$user['subscribe_url'] = Helper::getSubscribeUrl("/api/v1/client/subscribe?token={$user['token']}");
$user['subscribe_url'] = Helper::getSubscribeUrl($user['token']);
$userService = new UserService();
$user['reset_day'] = $userService->getResetDay($user);
return response([
@ -171,7 +171,7 @@ class UserController extends Controller
abort(500, __('Reset failed'));
}
return response([
'data' => Helper::getSubscribeUrl('/api/v1/client/subscribe?token=' . $user->token)
'data' => Helper::getSubscribeUrl($user['token'])
]);
}

View File

@ -0,0 +1,92 @@
<?php
namespace App\Http\Controllers\V2\Admin;
use App\Http\Controllers\Controller;
use App\Models\CommissionLog;
use App\Models\Order;
use App\Models\ServerShadowsocks;
use App\Models\ServerTrojan;
use App\Models\ServerVmess;
use App\Models\Stat;
use App\Models\StatServer;
use App\Models\StatUser;
use App\Models\Ticket;
use App\Models\User;
use App\Services\StatisticalService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
class StatController extends Controller
{
public function override(Request $request)
{
$params = $request->validate([
'start_at' => '',
'end_at' => ''
]);
if (isset($params['start_at']) && isset($params['end_at'])) {
$stats = Stat::where('record_at', '>=', $params['start_at'])
->where('record_at', '<', $params['end_at'])
->get()
->makeHidden(['record_at', 'created_at', 'updated_at', 'id', 'record_type'])
->toArray();
} else {
$statisticalService = new StatisticalService();
return [
'data' => $statisticalService->generateStatData()
];
}
$stats = array_reduce($stats, function($carry, $item) {
foreach($item as $key => $value) {
if(isset($carry[$key]) && $carry[$key]) {
$carry[$key] += $value;
} else {
$carry[$key] = $value;
}
}
return $carry;
}, []);
return [
'data' => $stats
];
}
public function record(Request $request)
{
$request->validate([
'type' => 'required|in:paid_total,commission_total,register_count',
'start_at' => '',
'end_at' => ''
]);
$statisticalService = new StatisticalService();
$statisticalService->setStartAt($request->input('start_at'));
$statisticalService->setEndAt($request->input('end_at'));
return [
'data' => $statisticalService->getStatRecord($request->input('type'))
];
}
public function ranking(Request $request)
{
$request->validate([
'type' => 'required|in:server_traffic_rank,user_consumption_rank,invite_rank',
'start_at' => '',
'end_at' => '',
'limit' => 'nullable|integer'
]);
$statisticalService = new StatisticalService();
$statisticalService->setStartAt($request->input('start_at'));
$statisticalService->setEndAt($request->input('end_at'));
return [
'data' => $statisticalService->getRanking($request->input('type'), $request->input('limit') ?? 20)
];
}
}

View File

@ -29,6 +29,7 @@ class ConfigSave extends FormRequest
'app_description' => '',
'app_url' => 'nullable|url',
'subscribe_url' => 'nullable',
'subscribe_path' => 'nullable',
'try_out_enable' => 'in:0,1',
'try_out_plan_id' => 'integer',
'try_out_hour' => 'numeric',
@ -38,7 +39,6 @@ class ConfigSave extends FormRequest
// subscribe
'plan_change_enable' => 'in:0,1',
'reset_traffic_method' => 'in:0,1,2,3,4',
'surplus_enable' => 'in:0,1',
'new_order_event_id' => 'in:0,1',
'renew_order_event_id' => 'in:0,1',
'change_order_event_id' => 'in:0,1',

View File

@ -1,144 +0,0 @@
<?php
namespace App\Http\Routes;
use Illuminate\Contracts\Routing\Registrar;
class AdminRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => config('v2board.secure_path', config('v2board.frontend_admin_path', hash('crc32b', config('app.key')))),
'middleware' => ['admin', 'log']
], function ($router) {
// Config
$router->get ('/config/fetch', 'Admin\\ConfigController@fetch');
$router->post('/config/save', 'Admin\\ConfigController@save');
$router->get ('/config/getEmailTemplate', 'Admin\\ConfigController@getEmailTemplate');
$router->get ('/config/getThemeTemplate', 'Admin\\ConfigController@getThemeTemplate');
$router->post('/config/setTelegramWebhook', 'Admin\\ConfigController@setTelegramWebhook');
$router->post('/config/testSendMail', 'Admin\\ConfigController@testSendMail');
// Plan
$router->get ('/plan/fetch', 'Admin\\PlanController@fetch');
$router->post('/plan/save', 'Admin\\PlanController@save');
$router->post('/plan/drop', 'Admin\\PlanController@drop');
$router->post('/plan/update', 'Admin\\PlanController@update');
$router->post('/plan/sort', 'Admin\\PlanController@sort');
// Server
$router->get ('/server/group/fetch', 'Admin\\Server\\GroupController@fetch');
$router->post('/server/group/save', 'Admin\\Server\\GroupController@save');
$router->post('/server/group/drop', 'Admin\\Server\\GroupController@drop');
$router->get ('/server/route/fetch', 'Admin\\Server\\RouteController@fetch');
$router->post('/server/route/save', 'Admin\\Server\\RouteController@save');
$router->post('/server/route/drop', 'Admin\\Server\\RouteController@drop');
$router->get ('/server/manage/getNodes', 'Admin\\Server\\ManageController@getNodes');
$router->post('/server/manage/sort', 'Admin\\Server\\ManageController@sort');
$router->group([
'prefix' => 'server/trojan'
], function ($router) {
$router->get ('fetch', 'Admin\\Server\\TrojanController@fetch');
$router->post('save', 'Admin\\Server\\TrojanController@save');
$router->post('drop', 'Admin\\Server\\TrojanController@drop');
$router->post('update', 'Admin\\Server\\TrojanController@update');
$router->post('copy', 'Admin\\Server\\TrojanController@copy');
$router->post('sort', 'Admin\\Server\\TrojanController@sort');
$router->post('viewConfig', 'Admin\\Server\\TrojanController@viewConfig');
});
$router->group([
'prefix' => 'server/vmess'
], function ($router) {
$router->get ('fetch', 'Admin\\Server\\VmessController@fetch');
$router->post('save', 'Admin\\Server\\VmessController@save');
$router->post('drop', 'Admin\\Server\\VmessController@drop');
$router->post('update', 'Admin\\Server\\VmessController@update');
$router->post('copy', 'Admin\\Server\\VmessController@copy');
$router->post('sort', 'Admin\\Server\\VmessController@sort');
});
$router->group([
'prefix' => 'server/shadowsocks'
], function ($router) {
$router->get ('fetch', 'Admin\\Server\\ShadowsocksController@fetch');
$router->post('save', 'Admin\\Server\\ShadowsocksController@save');
$router->post('drop', 'Admin\\Server\\ShadowsocksController@drop');
$router->post('update', 'Admin\\Server\\ShadowsocksController@update');
$router->post('copy', 'Admin\\Server\\ShadowsocksController@copy');
$router->post('sort', 'Admin\\Server\\ShadowsocksController@sort');
});
$router->group([
'prefix' => 'server/hysteria'
], function ($router) {
$router->get ('fetch', 'Admin\\Server\\HysteriaController@fetch');
$router->post('save', 'Admin\\Server\\HysteriaController@save');
$router->post('drop', 'Admin\\Server\\HysteriaController@drop');
$router->post('update', 'Admin\\Server\\HysteriaController@update');
$router->post('copy', 'Admin\\Server\\HysteriaController@copy');
$router->post('sort', 'Admin\\Server\\HysteriaController@sort');
});
// Order
$router->get ('/order/fetch', 'Admin\\OrderController@fetch');
$router->post('/order/update', 'Admin\\OrderController@update');
$router->post('/order/assign', 'Admin\\OrderController@assign');
$router->post('/order/paid', 'Admin\\OrderController@paid');
$router->post('/order/cancel', 'Admin\\OrderController@cancel');
$router->post('/order/detail', 'Admin\\OrderController@detail');
// User
$router->get ('/user/fetch', 'Admin\\UserController@fetch');
$router->post('/user/update', 'Admin\\UserController@update');
$router->get ('/user/getUserInfoById', 'Admin\\UserController@getUserInfoById');
$router->post('/user/generate', 'Admin\\UserController@generate');
$router->post('/user/dumpCSV', 'Admin\\UserController@dumpCSV');
$router->post('/user/sendMail', 'Admin\\UserController@sendMail');
$router->post('/user/ban', 'Admin\\UserController@ban');
$router->post('/user/resetSecret', 'Admin\\UserController@resetSecret');
$router->post('/user/setInviteUser', 'Admin\\UserController@setInviteUser');
// Stat
$router->get ('/stat/getStat', 'Admin\\StatController@getStat');
$router->get ('/stat/getOverride', 'Admin\\StatController@getOverride');
$router->get ('/stat/getServerLastRank', 'Admin\\StatController@getServerLastRank');
$router->get ('/stat/getOrder', 'Admin\\StatController@getOrder');
$router->get ('/stat/getStatUser', 'Admin\\StatController@getStatUser');
$router->get ('/stat/getRanking', 'Admin\\StatController@getRanking');
$router->get ('/stat/getStatRecord', 'Admin\\StatController@getStatRecord');
// Notice
$router->get ('/notice/fetch', 'Admin\\NoticeController@fetch');
$router->post('/notice/save', 'Admin\\NoticeController@save');
$router->post('/notice/update', 'Admin\\NoticeController@update');
$router->post('/notice/drop', 'Admin\\NoticeController@drop');
$router->post('/notice/show', 'Admin\\NoticeController@show');
// Ticket
$router->get ('/ticket/fetch', 'Admin\\TicketController@fetch');
$router->post('/ticket/reply', 'Admin\\TicketController@reply');
$router->post('/ticket/close', 'Admin\\TicketController@close');
// Coupon
$router->get ('/coupon/fetch', 'Admin\\CouponController@fetch');
$router->post('/coupon/generate', 'Admin\\CouponController@generate');
$router->post('/coupon/drop', 'Admin\\CouponController@drop');
$router->post('/coupon/show', 'Admin\\CouponController@show');
// Knowledge
$router->get ('/knowledge/fetch', 'Admin\\KnowledgeController@fetch');
$router->get ('/knowledge/getCategory', 'Admin\\KnowledgeController@getCategory');
$router->post('/knowledge/save', 'Admin\\KnowledgeController@save');
$router->post('/knowledge/show', 'Admin\\KnowledgeController@show');
$router->post('/knowledge/drop', 'Admin\\KnowledgeController@drop');
$router->post('/knowledge/sort', 'Admin\\KnowledgeController@sort');
// Payment
$router->get ('/payment/fetch', 'Admin\\PaymentController@fetch');
$router->get ('/payment/getPaymentMethods', 'Admin\\PaymentController@getPaymentMethods');
$router->post('/payment/getPaymentForm', 'Admin\\PaymentController@getPaymentForm');
$router->post('/payment/save', 'Admin\\PaymentController@save');
$router->post('/payment/drop', 'Admin\\PaymentController@drop');
$router->post('/payment/show', 'Admin\\PaymentController@show');
$router->post('/payment/sort', 'Admin\\PaymentController@sort');
// System
$router->get ('/system/getSystemStatus', 'Admin\\SystemController@getSystemStatus');
$router->get ('/system/getQueueStats', 'Admin\\SystemController@getQueueStats');
$router->get ('/system/getQueueWorkload', 'Admin\\SystemController@getQueueWorkload');
$router->get ('/system/getQueueMasters', '\\Laravel\\Horizon\\Http\\Controllers\\MasterSupervisorController@index');
$router->get ('/system/getSystemLog', 'Admin\\SystemController@getSystemLog');
// Theme
$router->get ('/theme/getThemes', 'Admin\\ThemeController@getThemes');
$router->post('/theme/saveThemeConfig', 'Admin\\ThemeController@saveThemeConfig');
$router->post('/theme/getThemeConfig', 'Admin\\ThemeController@getThemeConfig');
});
}
}

View File

@ -1,21 +0,0 @@
<?php
namespace App\Http\Routes;
use Illuminate\Contracts\Routing\Registrar;
class ClientRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'client',
'middleware' => 'client'
], function ($router) {
// Client
$router->get('/subscribe', 'Client\\ClientController@subscribe');
// App
$router->get('/app/getConfig', 'Client\\AppController@getConfig');
$router->get('/app/getVersion', 'Client\\AppController@getVersion');
});
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace App\Http\Routes;
use Illuminate\Contracts\Routing\Registrar;
class PassportRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'passport'
], function ($router) {
// Auth
$router->post('/auth/register', 'Passport\\AuthController@register');
$router->post('/auth/login', 'Passport\\AuthController@login');
$router->get ('/auth/token2Login', 'Passport\\AuthController@token2Login');
$router->post('/auth/forget', 'Passport\\AuthController@forget');
$router->post('/auth/getQuickLoginUrl', 'Passport\\AuthController@getQuickLoginUrl');
$router->post('/auth/loginWithMailLink', 'Passport\\AuthController@loginWithMailLink');
// Comm
$router->post('/comm/sendEmailVerify', 'Passport\\CommController@sendEmailVerify');
$router->post('/comm/pv', 'Passport\\CommController@pv');
});
}
}

View File

@ -1,32 +0,0 @@
<?php
namespace App\Http\Routes;
use Illuminate\Contracts\Routing\Registrar;
class StaffRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'staff',
'middleware' => 'staff'
], function ($router) {
// Ticket
$router->get ('/ticket/fetch', 'Staff\\TicketController@fetch');
$router->post('/ticket/reply', 'Staff\\TicketController@reply');
$router->post('/ticket/close', 'Staff\\TicketController@close');
// User
$router->post('/user/update', 'Staff\\UserController@update');
$router->get ('/user/getUserInfoById', 'Staff\\UserController@getUserInfoById');
$router->post('/user/sendMail', 'Staff\\UserController@sendMail');
$router->post('/user/ban', 'Staff\\UserController@ban');
// Plan
$router->get ('/plan/fetch', 'Staff\\PlanController@fetch');
// Notice
$router->get ('/notice/fetch', 'Admin\\NoticeController@fetch');
$router->post('/notice/save', 'Admin\\NoticeController@save');
$router->post('/notice/update', 'Admin\\NoticeController@update');
$router->post('/notice/drop', 'Admin\\NoticeController@drop');
});
}
}

View File

@ -1,64 +0,0 @@
<?php
namespace App\Http\Routes;
use Illuminate\Contracts\Routing\Registrar;
class UserRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'user',
'middleware' => 'user'
], function ($router) {
// User
$router->get ('/resetSecurity', 'User\\UserController@resetSecurity');
$router->get ('/info', 'User\\UserController@info');
$router->post('/changePassword', 'User\\UserController@changePassword');
$router->post('/update', 'User\\UserController@update');
$router->get ('/getSubscribe', 'User\\UserController@getSubscribe');
$router->get ('/getStat', 'User\\UserController@getStat');
$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/detail', 'User\\OrderController@detail');
$router->get ('/order/fetch', 'User\\OrderController@fetch');
$router->get ('/order/getPaymentMethod', 'User\\OrderController@getPaymentMethod');
$router->post('/order/cancel', 'User\\OrderController@cancel');
// Plan
$router->get ('/plan/fetch', 'User\\PlanController@fetch');
// Invite
$router->get ('/invite/save', 'User\\InviteController@save');
$router->get ('/invite/fetch', 'User\\InviteController@fetch');
$router->get ('/invite/details', 'User\\InviteController@details');
// Notice
$router->get ('/notice/fetch', 'User\\NoticeController@fetch');
// Ticket
$router->post('/ticket/reply', 'User\\TicketController@reply');
$router->post('/ticket/close', 'User\\TicketController@close');
$router->post('/ticket/save', 'User\\TicketController@save');
$router->get ('/ticket/fetch', 'User\\TicketController@fetch');
$router->post('/ticket/withdraw', 'User\\TicketController@withdraw');
// Server
$router->get ('/server/fetch', 'User\\ServerController@fetch');
// Coupon
$router->post('/coupon/check', 'User\\CouponController@check');
// Telegram
$router->get ('/telegram/getBotInfo', 'User\\TelegramController@getBotInfo');
// Comm
$router->get ('/comm/config', 'User\\CommController@config');
$router->Post('/comm/getStripePublicKey', 'User\\CommController@getStripePublicKey');
// Knowledge
$router->get ('/knowledge/fetch', 'User\\KnowledgeController@fetch');
$router->get ('/knowledge/getCategory', 'User\\KnowledgeController@getCategory');
// Stat
$router->get ('/stat/getTrafficLog', 'User\\StatController@getTrafficLog');
});
}
}

View File

@ -0,0 +1,143 @@
<?php
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
class AdminRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => config('v2board.secure_path', config('v2board.frontend_admin_path', hash('crc32b', config('app.key')))),
'middleware' => ['admin', 'log'],
], function ($router) {
// Config
$router->get ('/config/fetch', 'V1\\Admin\\ConfigController@fetch');
$router->post('/config/save', 'V1\\Admin\\ConfigController@save');
$router->get ('/config/getEmailTemplate', 'V1\\Admin\\ConfigController@getEmailTemplate');
$router->get ('/config/getThemeTemplate', 'V1\\Admin\\ConfigController@getThemeTemplate');
$router->post('/config/setTelegramWebhook', 'V1\\Admin\\ConfigController@setTelegramWebhook');
$router->post('/config/testSendMail', 'V1\\Admin\\ConfigController@testSendMail');
// Plan
$router->get ('/plan/fetch', 'V1\\Admin\\PlanController@fetch');
$router->post('/plan/save', 'V1\\Admin\\PlanController@save');
$router->post('/plan/drop', 'V1\\Admin\\PlanController@drop');
$router->post('/plan/update', 'V1\\Admin\\PlanController@update');
$router->post('/plan/sort', 'V1\\Admin\\PlanController@sort');
// Server
$router->get ('/server/group/fetch', 'V1\\Admin\\Server\\GroupController@fetch');
$router->post('/server/group/save', 'V1\\Admin\\Server\\GroupController@save');
$router->post('/server/group/drop', 'V1\\Admin\\Server\\GroupController@drop');
$router->get ('/server/route/fetch', 'V1\\Admin\\Server\\RouteController@fetch');
$router->post('/server/route/save', 'V1\\Admin\\Server\\RouteController@save');
$router->post('/server/route/drop', 'V1\\Admin\\Server\\RouteController@drop');
$router->get ('/server/manage/getNodes', 'V1\\Admin\\Server\\ManageController@getNodes');
$router->post('/server/manage/sort', 'V1\\Admin\\Server\\ManageController@sort');
$router->group([
'prefix' => 'server/trojan'
], function ($router) {
$router->post('save', 'V1\\Admin\\Server\\TrojanController@save');
$router->post('drop', 'V1\\Admin\\Server\\TrojanController@drop');
$router->post('update', 'V1\\Admin\\Server\\TrojanController@update');
$router->post('copy', 'V1\\Admin\\Server\\TrojanController@copy');
});
$router->group([
'prefix' => 'server/vmess'
], function ($router) {
$router->post('save', 'V1\\Admin\\Server\\VmessController@save');
$router->post('drop', 'V1\\Admin\\Server\\VmessController@drop');
$router->post('update', 'V1\\Admin\\Server\\VmessController@update');
$router->post('copy', 'V1\\Admin\\Server\\VmessController@copy');
});
$router->group([
'prefix' => 'server/shadowsocks'
], function ($router) {
$router->post('save', 'V1\\Admin\\Server\\ShadowsocksController@save');
$router->post('drop', 'V1\\Admin\\Server\\ShadowsocksController@drop');
$router->post('update', 'V1\\Admin\\Server\\ShadowsocksController@update');
$router->post('copy', 'V1\\Admin\\Server\\ShadowsocksController@copy');
});
$router->group([
'prefix' => 'server/hysteria'
], function ($router) {
$router->post('save', 'V1\\Admin\\Server\\HysteriaController@save');
$router->post('drop', 'V1\\Admin\\Server\\HysteriaController@drop');
$router->post('update', 'V1\\Admin\\Server\\HysteriaController@update');
$router->post('copy', 'V1\\Admin\\Server\\HysteriaController@copy');
});
$router->group([
'prefix' => 'server/vless'
], function ($router) {
$router->post('save', 'V1\\Admin\\Server\\VlessController@save');
$router->post('drop', 'V1\\Admin\\Server\\VlessController@drop');
$router->post('update', 'V1\\Admin\\Server\\VlessController@update');
$router->post('copy', 'V1\\Admin\\Server\\VlessController@copy');
});
// Order
$router->get ('/order/fetch', 'V1\\Admin\\OrderController@fetch');
$router->post('/order/update', 'V1\\Admin\\OrderController@update');
$router->post('/order/assign', 'V1\\Admin\\OrderController@assign');
$router->post('/order/paid', 'V1\\Admin\\OrderController@paid');
$router->post('/order/cancel', 'V1\\Admin\\OrderController@cancel');
$router->post('/order/detail', 'V1\\Admin\\OrderController@detail');
// User
$router->get ('/user/fetch', 'V1\\Admin\\UserController@fetch');
$router->post('/user/update', 'V1\\Admin\\UserController@update');
$router->get ('/user/getUserInfoById', 'V1\\Admin\\UserController@getUserInfoById');
$router->post('/user/generate', 'V1\\Admin\\UserController@generate');
$router->post('/user/dumpCSV', 'V1\\Admin\\UserController@dumpCSV');
$router->post('/user/sendMail', 'V1\\Admin\\UserController@sendMail');
$router->post('/user/ban', 'V1\\Admin\\UserController@ban');
$router->post('/user/resetSecret', 'V1\\Admin\\UserController@resetSecret');
$router->post('/user/setInviteUser', 'V1\\Admin\\UserController@setInviteUser');
// Stat
$router->get ('/stat/getStat', 'V1\\Admin\\StatController@getStat');
$router->get ('/stat/getOverride', 'V1\\Admin\\StatController@getOverride');
$router->get ('/stat/getServerLastRank', 'V1\\Admin\\StatController@getServerLastRank');
$router->get ('/stat/getOrder', 'V1\\Admin\\StatController@getOrder');
$router->get ('/stat/getStatUser', 'V1\\Admin\\StatController@getStatUser');
$router->get ('/stat/getRanking', 'V1\\Admin\\StatController@getRanking');
$router->get ('/stat/getStatRecord', 'V1\\Admin\\StatController@getStatRecord');
// Notice
$router->get ('/notice/fetch', 'V1\\Admin\\NoticeController@fetch');
$router->post('/notice/save', 'V1\\Admin\\NoticeController@save');
$router->post('/notice/update', 'V1\\Admin\\NoticeController@update');
$router->post('/notice/drop', 'V1\\Admin\\NoticeController@drop');
$router->post('/notice/show', 'V1\\Admin\\NoticeController@show');
// Ticket
$router->get ('/ticket/fetch', 'V1\\Admin\\TicketController@fetch');
$router->post('/ticket/reply', 'V1\\Admin\\TicketController@reply');
$router->post('/ticket/close', 'V1\\Admin\\TicketController@close');
// Coupon
$router->get ('/coupon/fetch', 'V1\\Admin\\CouponController@fetch');
$router->post('/coupon/generate', 'V1\\Admin\\CouponController@generate');
$router->post('/coupon/drop', 'V1\\Admin\\CouponController@drop');
$router->post('/coupon/show', 'V1\\Admin\\CouponController@show');
// Knowledge
$router->get ('/knowledge/fetch', 'V1\\Admin\\KnowledgeController@fetch');
$router->get ('/knowledge/getCategory', 'V1\\Admin\\KnowledgeController@getCategory');
$router->post('/knowledge/save', 'V1\\Admin\\KnowledgeController@save');
$router->post('/knowledge/show', 'V1\\Admin\\KnowledgeController@show');
$router->post('/knowledge/drop', 'V1\\Admin\\KnowledgeController@drop');
$router->post('/knowledge/sort', 'V1\\Admin\\KnowledgeController@sort');
// Payment
$router->get ('/payment/fetch', 'V1\\Admin\\PaymentController@fetch');
$router->get ('/payment/getPaymentMethods', 'V1\\Admin\\PaymentController@getPaymentMethods');
$router->post('/payment/getPaymentForm', 'V1\\Admin\\PaymentController@getPaymentForm');
$router->post('/payment/save', 'V1\\Admin\\PaymentController@save');
$router->post('/payment/drop', 'V1\\Admin\\PaymentController@drop');
$router->post('/payment/show', 'V1\\Admin\\PaymentController@show');
$router->post('/payment/sort', 'V1\\Admin\\PaymentController@sort');
// System
$router->get ('/system/getSystemStatus', 'V1\\Admin\\SystemController@getSystemStatus');
$router->get ('/system/getQueueStats', 'V1\\Admin\\SystemController@getQueueStats');
$router->get ('/system/getQueueWorkload', 'V1\\Admin\\SystemController@getQueueWorkload');
$router->get ('/system/getQueueMasters', '\\Laravel\\Horizon\\Http\\Controllers\\MasterSupervisorController@index');
$router->get ('/system/getSystemLog', 'V1\\Admin\\SystemController@getSystemLog');
// Theme
$router->get ('/theme/getThemes', 'V1\\Admin\\ThemeController@getThemes');
$router->post('/theme/saveThemeConfig', 'V1\\Admin\\ThemeController@saveThemeConfig');
$router->post('/theme/getThemeConfig', 'V1\\Admin\\ThemeController@getThemeConfig');
});
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
class ClientRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'client',
'middleware' => 'client'
], function ($router) {
// Client
if (!config('v2board.subscribe_path')) {
$router->get('/subscribe', 'V1\\Client\\ClientController@subscribe');
}
// App
$router->get('/app/getConfig', 'V1\\Client\\AppController@getConfig');
$router->get('/app/getVersion', 'V1\\Client\\AppController@getVersion');
});
if (config('v2board.subscribe_path')) {
\Route::get(config('v2board.subscribe_path'), 'V1\\Client\\ClientController@subscribe')->middleware('client');
}
}
}

View File

@ -1,5 +1,5 @@
<?php
namespace App\Http\Routes;
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
@ -10,14 +10,12 @@ class GuestRoute
$router->group([
'prefix' => 'guest'
], function ($router) {
// Plan
$router->get ('/plan/fetch', 'Guest\\PlanController@fetch');
// Telegram
$router->post('/telegram/webhook', 'Guest\\TelegramController@webhook');
$router->post('/telegram/webhook', 'V1\\Guest\\TelegramController@webhook');
// Payment
$router->match(['get', 'post'], '/payment/notify/{method}/{uuid}', 'Guest\\PaymentController@notify');
$router->match(['get', 'post'], '/payment/notify/{method}/{uuid}', 'V1\\Guest\\PaymentController@notify');
// Comm
$router->get ('/comm/config', 'Guest\\CommController@config');
$router->get ('/comm/config', 'V1\\Guest\\CommController@config');
});
}
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
class PassportRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'passport'
], function ($router) {
// Auth
$router->post('/auth/register', 'V1\\Passport\\AuthController@register');
$router->post('/auth/login', 'V1\\Passport\\AuthController@login');
$router->get ('/auth/token2Login', 'V1\\Passport\\AuthController@token2Login');
$router->post('/auth/forget', 'V1\\Passport\\AuthController@forget');
$router->post('/auth/getQuickLoginUrl', 'V1\\Passport\\AuthController@getQuickLoginUrl');
$router->post('/auth/loginWithMailLink', 'V1\\Passport\\AuthController@loginWithMailLink');
// Comm
$router->post('/comm/sendEmailVerify', 'V1\\Passport\\CommController@sendEmailVerify');
$router->post('/comm/pv', 'V1\\Passport\\CommController@pv');
});
}
}

View File

@ -1,5 +1,5 @@
<?php
namespace App\Http\Routes;
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
@ -11,7 +11,7 @@ class ServerRoute
'prefix' => 'server'
], function ($router) {
$router->any('/{class}/{action}', function($class, $action) {
$ctrl = \App::make("\\App\\Http\\Controllers\\Server\\" . ucfirst($class) . "Controller");
$ctrl = \App::make("\\App\\Http\\Controllers\\V1\\Server\\" . ucfirst($class) . "Controller");
return \App::call([$ctrl, $action]);
});
});

View File

@ -0,0 +1,32 @@
<?php
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
class StaffRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'staff',
'middleware' => 'staff'
], function ($router) {
// Ticket
$router->get ('/ticket/fetch', 'V1\\Staff\\TicketController@fetch');
$router->post('/ticket/reply', 'V1\\Staff\\TicketController@reply');
$router->post('/ticket/close', 'V1\\Staff\\TicketController@close');
// User
$router->post('/user/update', 'V1\\Staff\\UserController@update');
$router->get ('/user/getUserInfoById', 'V1\\Staff\\UserController@getUserInfoById');
$router->post('/user/sendMail', 'V1\\Staff\\UserController@sendMail');
$router->post('/user/ban', 'V1\\Staff\\UserController@ban');
// Plan
$router->get ('/plan/fetch', 'V1\\Staff\\PlanController@fetch');
// Notice
$router->get ('/notice/fetch', 'V1\\Admin\\NoticeController@fetch');
$router->post('/notice/save', 'V1\\Admin\\NoticeController@save');
$router->post('/notice/update', 'V1\\Admin\\NoticeController@update');
$router->post('/notice/drop', 'V1\\Admin\\NoticeController@drop');
});
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace App\Http\Routes\V1;
use Illuminate\Contracts\Routing\Registrar;
class UserRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => 'user',
'middleware' => 'user'
], function ($router) {
// User
$router->get ('/resetSecurity', 'V1\\User\\UserController@resetSecurity');
$router->get ('/info', 'V1\\User\\UserController@info');
$router->post('/changePassword', 'V1\\User\\UserController@changePassword');
$router->post('/update', 'V1\\User\\UserController@update');
$router->get ('/getSubscribe', 'V1\\User\\UserController@getSubscribe');
$router->get ('/getStat', 'V1\\User\\UserController@getStat');
$router->get ('/checkLogin', 'V1\\User\\UserController@checkLogin');
$router->post('/transfer', 'V1\\User\\UserController@transfer');
$router->post('/getQuickLoginUrl', 'V1\\User\\UserController@getQuickLoginUrl');
$router->get ('/getActiveSession', 'V1\\User\\UserController@getActiveSession');
$router->post('/removeActiveSession', 'V1\\User\\UserController@removeActiveSession');
// Order
$router->post('/order/save', 'V1\\User\\OrderController@save');
$router->post('/order/checkout', 'V1\\User\\OrderController@checkout');
$router->get ('/order/check', 'V1\\User\\OrderController@check');
$router->get ('/order/detail', 'V1\\User\\OrderController@detail');
$router->get ('/order/fetch', 'V1\\User\\OrderController@fetch');
$router->get ('/order/getPaymentMethod', 'V1\\User\\OrderController@getPaymentMethod');
$router->post('/order/cancel', 'V1\\User\\OrderController@cancel');
// Plan
$router->get ('/plan/fetch', 'V1\\User\\PlanController@fetch');
// Invite
$router->get ('/invite/save', 'V1\\User\\InviteController@save');
$router->get ('/invite/fetch', 'V1\\User\\InviteController@fetch');
$router->get ('/invite/details', 'V1\\User\\InviteController@details');
// Notice
$router->get ('/notice/fetch', 'V1\\User\\NoticeController@fetch');
// Ticket
$router->post('/ticket/reply', 'V1\\User\\TicketController@reply');
$router->post('/ticket/close', 'V1\\User\\TicketController@close');
$router->post('/ticket/save', 'V1\\User\\TicketController@save');
$router->get ('/ticket/fetch', 'V1\\User\\TicketController@fetch');
$router->post('/ticket/withdraw', 'V1\\User\\TicketController@withdraw');
// Server
$router->get ('/server/fetch', 'V1\\User\\ServerController@fetch');
// Coupon
$router->post('/coupon/check', 'V1\\User\\CouponController@check');
// Telegram
$router->get ('/telegram/getBotInfo', 'V1\\User\\TelegramController@getBotInfo');
// Comm
$router->get ('/comm/config', 'V1\\User\\CommController@config');
$router->Post('/comm/getStripePublicKey', 'V1\\User\\CommController@getStripePublicKey');
// Knowledge
$router->get ('/knowledge/fetch', 'V1\\User\\KnowledgeController@fetch');
$router->get ('/knowledge/getCategory', 'V1\\User\\KnowledgeController@getCategory');
// Stat
$router->get ('/stat/getTrafficLog', 'V1\\User\\StatController@getTrafficLog');
});
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Http\Routes\V2;
use Illuminate\Contracts\Routing\Registrar;
class AdminRoute
{
public function map(Registrar $router)
{
$router->group([
'prefix' => config('v2board.secure_path', config('v2board.frontend_admin_path', hash('crc32b', config('app.key')))),
'middleware' => ['admin', 'log'],
], function ($router) {
// Stat
$router->get ('/stat/override', 'V2\\Admin\\StatController@override');
$router->get ('/stat/record', 'V2\\Admin\\StatController@record');
$router->get ('/stat/ranking', 'V2\\Admin\\StatController@ranking');
});
}
}

View File

@ -42,7 +42,7 @@ class OrderHandleJob implements ShouldQueue
switch ($this->order->status) {
// cancel
case 0:
if ($this->order->created_at <= (time() - 1800)) {
if ($this->order->created_at <= (time() - 3600 * 2)) {
$orderService->cancel();
}
break;

View File

@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Model;
class Log extends Model
{
use \App\Scope\FilterScope;
protected $table = 'v2_log';
protected $dateFormat = 'U';
protected $guarded = ['id'];

21
app/Models/ServerVless.php Executable file
View File

@ -0,0 +1,21 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ServerVless extends Model
{
protected $table = 'v2_server_vless';
protected $dateFormat = 'U';
protected $guarded = ['id'];
protected $casts = [
'created_at' => 'timestamp',
'updated_at' => 'timestamp',
'group_id' => 'array',
'route_id' => 'array',
'tls_settings' => 'array',
'network_settings' => 'array',
'tags' => 'array'
];
}

View File

@ -1,8 +1,5 @@
<?php
/**
* 自己写别抄抄NMB抄
*/
namespace App\Payments;
class AlipayF2F {

View File

@ -25,6 +25,10 @@ class EPay {
'label' => 'KEY',
'description' => '',
'type' => 'input',
],
'alert1' => [
'type' => 'alert',
'content' => '开户请联系:<a href="https://t.me/smogate">@smogate</a>'
]
];
}

View File

@ -1,102 +0,0 @@
<?php
/**
* 自己写别抄抄NMB抄
*/
namespace App\Payments;
use \Curl\Curl;
class MGate {
private $config;
public function __construct($config)
{
$this->config = $config;
}
public function form()
{
return [
'mgate_url' => [
'label' => 'API地址',
'description' => '',
'type' => 'input',
],
'mgate_app_id' => [
'label' => 'APPID',
'description' => '',
'type' => 'input',
],
'mgate_app_secret' => [
'label' => 'AppSecret',
'description' => '',
'type' => 'input',
],
'mgate_source_currency' => [
'label' => '源货币',
'description' => '默认CNY',
'type' => 'input'
]
];
}
public function pay($order)
{
$params = [
'out_trade_no' => $order['trade_no'],
'total_amount' => $order['total_amount'],
'notify_url' => $order['notify_url'],
'return_url' => $order['return_url']
];
if (isset($this->config['mgate_source_currency'])) {
$params['source_currency'] = $this->config['mgate_source_currency'];
}
$params['app_id'] = $this->config['mgate_app_id'];
ksort($params);
$str = http_build_query($params) . $this->config['mgate_app_secret'];
$params['sign'] = md5($str);
$curl = new Curl();
$curl->setUserAgent('MGate');
$curl->setOpt(CURLOPT_SSL_VERIFYPEER, 0);
$curl->post($this->config['mgate_url'] . '/v1/gateway/fetch', http_build_query($params));
$result = $curl->response;
if (!$result) {
abort(500, '网络异常');
}
if ($curl->error) {
if (isset($result->errors)) {
$errors = (array)$result->errors;
abort(500, $errors[array_keys($errors)[0]][0]);
}
if (isset($result->message)) {
abort(500, $result->message);
}
abort(500, '未知错误');
}
$curl->close();
if (!isset($result->data->trade_no)) {
abort(500, '接口请求失败');
}
return [
'type' => 1, // 0:qrcode 1:url
'data' => $result->data->pay_url
];
}
public function notify($params)
{
$sign = $params['sign'];
unset($params['sign']);
ksort($params);
reset($params);
$str = http_build_query($params) . $this->config['mgate_app_secret'];
if ($sign !== md5($str)) {
return false;
}
return [
'trade_no' => $params['out_trade_no'],
'callback_no' => $params['trade_no']
];
}
}

View File

@ -1,8 +1,5 @@
<?php
/**
* 自己写别抄抄NMB抄
*/
namespace App\Payments;
use Stripe\Source;

View File

@ -1,8 +1,5 @@
<?php
/**
* 自己写别抄抄NMB抄
*/
namespace App\Payments;
use Stripe\Source;

View File

@ -1,8 +1,5 @@
<?php
/**
* 自己写别抄抄NMB抄
*/
namespace App\Payments;
use Stripe\Source;

View File

@ -1,8 +1,7 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Dict;
use phpDocumentor\Reflection\Types\Self_;
use Symfony\Component\Yaml\Yaml;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Helper;
use Symfony\Component\Yaml\Yaml;
@ -48,6 +48,10 @@ class ClashMeta
array_push($proxy, self::buildTrojan($user['uuid'], $item));
array_push($proxies, $item['name']);
}
if ($item['type'] === 'vless') {
array_push($proxy, self::buildVless($user['uuid'], $item));
array_push($proxies, $item['name']);
}
}
$config['proxies'] = array_merge($config['proxies'] ? $config['proxies'] : [], $proxy);
@ -160,6 +164,78 @@ class ClashMeta
return $array;
}
public static function buildVless($uuid, $server)
{
$array = [];
$array['name'] = $server['name'];
$array['type'] = 'vless';
$array['server'] = $server['host'];
$array['port'] = $server['port'];
$array['uuid'] = $uuid;
$array['udp'] = true;
if ($server['tls'] === 1) {
$array['tls'] = true;
if ($server['tls_settings']) {
$tlsSettings = $server['tls_settings'];
if (isset($tlsSettings['allow_insecure']) && !empty($tlsSettings['allow_insecure']))
$array['skip-cert-verify'] = ($tlsSettings['allow_insecure'] ? true : false);
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
$array['servername'] = $tlsSettings['server_name'];
}
}
if (isset($server['flow']) && $server['flow']) {
$array['flow'] = $server['flow'];
$array['client-fingerprint'] = 'chrome';
}
if ($server['tls'] === 2) {
$array['client-fingerprint'] = 'chrome';
$array['tls'] = true;
$array['reality-opts'] = [];
if ($server['tls_settings']) {
$tlsSettings = $server['tls_settings'];
if (isset($tlsSettings['allow_insecure']) && !empty($tlsSettings['allow_insecure']))
$array['skip-cert-verify'] = ($tlsSettings['allow_insecure'] ? true : false);
if (isset($tlsSettings['server_name']) && !empty($tlsSettings['server_name']))
$array['servername'] = $tlsSettings['server_name'];
if (isset($tlsSettings['public_key'])) $array['reality-opts']['public-key'] = $tlsSettings['public_key'];
}
}
if ($server['network'] === 'tcp') {
$tcpSettings = $server['network_settings'];
if (isset($tcpSettings['header']['type'])) $array['network'] = $tcpSettings['header']['type'];
if (isset($tcpSettings['header']['request']['path'][0])) $array['http-opts']['path'] = $tcpSettings['header']['request']['path'][0];
}
if ($server['network'] === 'ws') {
$array['network'] = 'ws';
if ($server['network_settings']) {
$wsSettings = $server['network_settings'];
$array['ws-opts'] = [];
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
$array['ws-opts']['path'] = $wsSettings['path'];
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
$array['ws-opts']['headers'] = ['Host' => $wsSettings['headers']['Host']];
if (isset($wsSettings['path']) && !empty($wsSettings['path']))
$array['ws-path'] = $wsSettings['path'];
if (isset($wsSettings['headers']['Host']) && !empty($wsSettings['headers']['Host']))
$array['ws-headers'] = ['Host' => $wsSettings['headers']['Host']];
}
}
if ($server['network'] === 'grpc') {
$array['network'] = 'grpc';
if ($server['network_settings']) {
$grpcSettings = $server['network_settings'];
$array['grpc-opts'] = [];
if (isset($grpcSettings['serviceName'])) $array['grpc-opts']['grpc-service-name'] = $grpcSettings['serviceName'];
}
}
return $array;
}
public static function buildTrojan($password, $server)
{
$array = [];

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Helper;

View File

@ -1,8 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
use App\Utils\Helper;
namespace App\Protocols;
class Loon
{

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
class Passwall

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
class QuantumultX

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
class SSRPlus

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
class SagerNet
{

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Helper;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
class Shadowsocks
{

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use Symfony\Component\Yaml\Yaml;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Helper;
@ -64,7 +64,7 @@ class Surfboard
}
// Subscription link
$subsURL = Helper::getSubscribeUrl("/api/v1/client/subscribe?token={$user['token']}");
$subsURL = Helper::getSubscribeUrl($user['token']);
$subsDomain = $_SERVER['HTTP_HOST'];
$config = str_replace('$subs_link', $subsURL, $config);

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Helper;
@ -64,7 +64,6 @@ class Surge
}
// Subscription link
$subsURL = Helper::getSubscribeUrl("/api/v1/client/subscribe?token={$user['token']}");
$subsDomain = $_SERVER['HTTP_HOST'];
$subsURL = 'https://' . $subsDomain . '/api/v1/client/subscribe?token=' . $user['token'];

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
use App\Utils\Helper;

View File

@ -1,6 +1,6 @@
<?php
namespace App\Http\Controllers\Client\Protocols;
namespace App\Protocols;
class V2rayNG

View File

@ -72,8 +72,19 @@ class RouteServiceProvider extends ServiceProvider
'middleware' => 'api',
'namespace' => $this->namespace
], function ($router) {
foreach (glob(app_path('Http//Routes') . '/*.php') as $file) {
$this->app->make('App\\Http\\Routes\\' . basename($file, '.php'))->map($router);
foreach (glob(app_path('Http//Routes//V1') . '/*.php') as $file) {
$this->app->make('App\\Http\\Routes\\V1\\' . basename($file, '.php'))->map($router);
}
});
Route::group([
'prefix' => '/api/v2',
'middleware' => 'api',
'namespace' => $this->namespace
], function ($router) {
foreach (glob(app_path('Http//Routes//V2') . '/*.php') as $file) {
$this->app->make('App\\Http\\Routes\\V2\\' . basename($file, '.php'))->map($router);
}
});
}

50
app/Scope/FilterScope.php Normal file
View File

@ -0,0 +1,50 @@
<?php
namespace App\Scope;
use Illuminate\Database\Eloquent\Builder;
trait FilterScope
{
public function scopeSetFilterAllowKeys($builder, ...$allowKeys)
{
$allowKeys = implode(',', $allowKeys);
if (!$allowKeys) return $builder;
$request = request();
$request->validate([
'filter.*.key' => "required|in:{$allowKeys}",
'filter.*.condition' => 'required|in:in,is,not,like,lt,gt',
'filter.*.value' => 'required'
]);
$filters = $request->input('filter');
if ($filters) {
foreach ($filters as $k => $filter) {
if ($filter['condition'] === 'in') {
$builder->whereIn($filter['key'], $filter['value']);
continue;
}
if ($filter['condition'] === 'is') {
$builder->where($filter['key'], $filter['value']);
continue;
}
if ($filter['condition'] === 'not') {
$builder->where($filter['key'], '!=', $filter['value']);
continue;
}
if ($filter['condition'] === 'gt') {
$builder->where($filter['key'], '>', $filter['value']);
continue;
}
if ($filter['condition'] === 'lt') {
$builder->where($filter['key'], '<', $filter['value']);
continue;
}
if ($filter['condition'] === 'like') {
$builder->where($filter['key'], 'like', "%{$filter['value']}%");
continue;
}
}
}
return $builder;
}
}

View File

@ -1,74 +1,16 @@
<?php
namespace App\Http\Controllers\Admin;
namespace App\Services;
use App\Http\Requests\Admin\ConfigSave;
use App\Jobs\SendEmailJob;
use App\Services\TelegramService;
use Illuminate\Http\Request;
use App\Utils\Dict;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Mail;
class ConfigController extends Controller
{
public function getEmailTemplate()
{
$path = resource_path('views/mail/');
$files = array_map(function ($item) use ($path) {
return str_replace($path, '', $item);
}, glob($path . '*'));
return response([
'data' => $files
]);
class ConfigService {
public function get($key) {
$config = $this->getDefaultConfig();
return \Arr::get($config, $key);
}
public function getThemeTemplate()
{
$path = public_path('theme/');
$files = array_map(function ($item) use ($path) {
return str_replace($path, '', $item);
}, glob($path . '*'));
return response([
'data' => $files
]);
}
public function testSendMail(Request $request)
{
$obj = new SendEmailJob([
'email' => $request->user['email'],
'subject' => 'This is v2board test email',
'template_name' => 'notify',
'template_value' => [
'name' => config('v2board.app_name', 'V2Board'),
'content' => 'This is v2board test email',
'url' => config('v2board.app_url')
]
]);
return response([
'data' => true,
'log' => $obj->handle()
]);
}
public function setTelegramWebhook(Request $request)
{
$hookUrl = url('/api/v1/guest/telegram/webhook?access_token=' . md5(config('v2board.telegram_bot_token', $request->input('telegram_bot_token'))));
$telegramService = new TelegramService($request->input('telegram_bot_token'));
$telegramService->getMe();
$telegramService->setWebhook($hookUrl);
return response([
'data' => true
]);
}
public function fetch(Request $request)
{
$key = $request->input('key');
$data = [
public function getDefaultConfig() {
return [
'invite' => [
'invite_force' => (int)config('v2board.invite_force', 0),
'invite_commission' => config('v2board.invite_commission', 10),
@ -92,6 +34,7 @@ class ConfigController extends Controller
'app_description' => config('v2board.app_description', 'V2Board is best!'),
'app_url' => config('v2board.app_url'),
'subscribe_url' => config('v2board.subscribe_url'),
'subscribe_path' => config('v2board.subscribe_path', '/client/subscribe'),
'try_out_plan_id' => (int)config('v2board.try_out_plan_id', 0),
'try_out_hour' => (int)config('v2board.try_out_hour', 1),
'tos_url' => config('v2board.tos_url'),
@ -101,7 +44,6 @@ class ConfigController extends Controller
'subscribe' => [
'plan_change_enable' => (int)config('v2board.plan_change_enable', 1),
'reset_traffic_method' => (int)config('v2board.reset_traffic_method', 0),
'surplus_enable' => (int)config('v2board.surplus_enable', 1),
'new_order_event_id' => (int)config('v2board.new_order_event_id', 0),
'renew_order_event_id' => (int)config('v2board.renew_order_event_id', 0),
'change_order_event_id' => (int)config('v2board.change_order_event_id', 0),
@ -159,44 +101,5 @@ class ConfigController extends Controller
'password_limit_expire' => config('v2board.password_limit_expire', 60)
]
];
if ($key && isset($data[$key])) {
return response([
'data' => [
$key => $data[$key]
]
]);
};
// TODO: default should be in Dict
return response([
'data' => $data
]);
}
public function save(ConfigSave $request)
{
$data = $request->validated();
$config = config('v2board');
foreach (ConfigSave::RULES as $k => $v) {
if (!in_array($k, array_keys(ConfigSave::RULES))) {
unset($config[$k]);
continue;
}
if (array_key_exists($k, $data)) {
$config[$k] = $data[$k];
}
}
$data = var_export($config, 1);
if (!File::put(base_path() . '/config/v2board.php', "<?php\n return $data ;")) {
abort(500, '修改失败');
}
if (function_exists('opcache_reset')) {
if (opcache_reset() === false) {
abort(500, '缓存清除失败请卸载或检查opcache配置状态');
}
}
Artisan::call('config:cache');
return response([
'data' => true
]);
}
}

View File

@ -95,7 +95,7 @@ class OrderService
} else if ($user->plan_id !== NULL && $order->plan_id !== $user->plan_id && ($user->expired_at > time() || $user->expired_at === NULL)) {
if (!(int)config('v2board.plan_change_enable', 1)) abort(500, '目前不允许更改订阅,请联系客服或提交工单操作');
$order->type = 3;
if ((int)config('v2board.surplus_enable', 1)) $this->getSurplusValue($user, $order);
$this->getSurplusValue($user, $order);
if ($order->surplus_amount >= $order->total_amount) {
$order->refund_amount = $order->surplus_amount - $order->total_amount;
$order->total_amount = 0;
@ -156,63 +156,26 @@ class OrderService
private function getSurplusValue(User $user, Order $order)
{
if ($user->expired_at === NULL) {
$this->getSurplusValueByOneTime($user, $order);
} else {
$this->getSurplusValueByPeriod($user, $order);
}
$plan = Plan::find($user->plan_id);
if (!$plan) return;
if ($user->expired_at) $this->getSurplusValueByTime($user, $order, $plan);
$this->getSurplusValueByTransfer($user, $order, $plan);
}
private function getSurplusValueByOneTime(User $user, Order $order)
private function getSurplusValueByTime(User $user, Order $order, Plan $plan)
{
$lastOneTimeOrder = Order::where('user_id', $user->id)
->where('period', 'onetime_price')
->where('status', 3)
->orderBy('id', 'DESC')
->first();
if (!$lastOneTimeOrder) return;
$nowUserTraffic = $user->transfer_enable / 1073741824;
if (!$nowUserTraffic) return;
$paidTotalAmount = ($lastOneTimeOrder->total_amount + $lastOneTimeOrder->balance_amount);
if (!$paidTotalAmount) return;
$trafficUnitPrice = $paidTotalAmount / $nowUserTraffic;
$notUsedTraffic = $nowUserTraffic - (($user->u + $user->d) / 1073741824);
$result = $trafficUnitPrice * $notUsedTraffic;
$orderModel = Order::where('user_id', $user->id)->where('period', '!=', 'reset_price')->where('status', 3);
$order->surplus_amount = $result > 0 ? $result : 0;
$order->surplus_order_ids = array_column($orderModel->get()->toArray(), 'id');
if (!$plan['daily_unit_price']) return;
$timeLeftDays = $user['expired_at'] - time() / 86400;
if (!$timeLeftDays) return;
$order->surplus_amount = $order->surplus_amount + ($timeLeftDays * $plan['daily_unit_price']);
}
private function getSurplusValueByPeriod(User $user, Order $order)
private function getSurplusValueByTransfer(User $user, Order $order, Plan $plan)
{
$orders = Order::where('user_id', $user->id)
->where('period', '!=', 'reset_price')
->where('period', '!=', 'onetime_price')
->where('status', 3)
->get()
->toArray();
if (!$orders) return;
$orderAmountSum = 0;
$orderMonthSum = 0;
$lastValidateAt = 0;
foreach ($orders as $item) {
$period = self::STR_TO_TIME[$item['period']];
if (strtotime("+{$period} month", $item['created_at']) < time()) continue;
$lastValidateAt = $item['created_at'];
$orderMonthSum = $period + $orderMonthSum;
$orderAmountSum = $orderAmountSum + ($item['total_amount'] + $item['balance_amount'] + $item['surplus_amount'] - $item['refund_amount']);
}
if (!$lastValidateAt) return;
$expiredAtByOrder = strtotime("+{$orderMonthSum} month", $lastValidateAt);
if ($expiredAtByOrder < time()) return;
$orderSurplusSecond = $expiredAtByOrder - time();
$orderRangeSecond = $expiredAtByOrder - $lastValidateAt;
$avgPrice = $orderAmountSum / $orderRangeSecond;
$orderSurplusAmount = $avgPrice * $orderSurplusSecond;
if (!$orderSurplusSecond || !$orderSurplusAmount) return;
$order->surplus_amount = $orderSurplusAmount > 0 ? $orderSurplusAmount : 0;
$order->surplus_order_ids = array_column($orders, 'id');
if (!$plan['transfer_unit_price']) return;
$transferLeft = ($user['transfer_enable'] - $user['u'] + $user['d']) / 1073741824;
if (!$transferLeft) return;
$order->surplus_amount = $order->surplus_amount + ($transferLeft * $plan['transfer_unit_price']);
}
public function paid(string $callbackNo)

View File

@ -6,6 +6,7 @@ use App\Models\ServerHysteria;
use App\Models\ServerLog;
use App\Models\ServerRoute;
use App\Models\ServerShadowsocks;
use App\Models\ServerVless;
use App\Models\User;
use App\Models\ServerVmess;
use App\Models\ServerTrojan;
@ -15,6 +16,29 @@ use Illuminate\Support\Facades\Cache;
class ServerService
{
public function getAvailableVless(User $user):array
{
$servers = [];
$model = ServerVless::orderBy('sort', 'ASC');
$server = $model->get();
foreach ($server as $key => $v) {
if (!$v['show']) continue;
$server[$key]['type'] = 'vless';
if (!in_array($user->group_id, $server[$key]['group_id'])) continue;
if (strpos($server[$key]['port'], '-') !== false) {
$server[$key]['port'] = Helper::randomPort($server[$key]['port']);
}
if ($server[$key]['parent_id']) {
$server[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_VLESS_LAST_CHECK_AT', $server[$key]['parent_id']));
} else {
$server[$key]['last_check_at'] = Cache::get(CacheKey::get('SERVER_VLESS_LAST_CHECK_AT', $server[$key]['id']));
}
$servers[] = $server[$key]->toArray();
}
return $servers;
}
public function getAvailableVmess(User $user):array
{
@ -113,7 +137,8 @@ class ServerService
$this->getAvailableShadowsocks($user),
$this->getAvailableVmess($user),
$this->getAvailableTrojan($user),
$this->getAvailableHysteria($user)
$this->getAvailableHysteria($user),
$this->getAvailableVless($user)
);
$tmp = array_column($servers, 'sort');
array_multisort($tmp, SORT_ASC, $servers);
@ -196,6 +221,17 @@ class ServerService
return $servers;
}
public function getAllVLess()
{
$servers = ServerVless::orderBy('sort', 'ASC')
->get()
->toArray();
foreach ($servers as $k => $v) {
$servers[$k]['type'] = 'vless';
}
return $servers;
}
public function getAllTrojan()
{
$servers = ServerTrojan::orderBy('sort', 'ASC')
@ -241,7 +277,8 @@ class ServerService
$this->getAllShadowsocks(),
$this->getAllVMess(),
$this->getAllTrojan(),
$this->getAllHysteria()
$this->getAllHysteria(),
$this->getAllVLess()
);
$this->mergeData($servers);
$tmp = array_column($servers, 'sort');
@ -272,6 +309,8 @@ class ServerService
return ServerTrojan::find($serverId);
case 'hysteria':
return ServerHysteria::find($serverId);
case 'vless':
return ServerVless::find($serverId);
default:
return false;
}

View File

@ -30,7 +30,7 @@ class StatisticalService {
}
public function setServerStats() {
$this->serverStats = Cache::get("stat_server_{$this->startAt}");
$this->serverStats = Cache::store('file')->get("stat_server_{$this->startAt}");
$this->serverStats = json_decode($this->serverStats, true) ?? [];
if (!is_array($this->serverStats)) {
$this->serverStats = [];
@ -38,7 +38,7 @@ class StatisticalService {
}
public function setUserStats() {
$this->userStats = Cache::get("stat_user_{$this->startAt}");
$this->userStats = Cache::store('file')->get("stat_user_{$this->startAt}");
$this->userStats = json_decode($this->userStats, true) ?? [];
if (!is_array($this->userStats)) {
$this->userStats = [];
@ -95,7 +95,7 @@ class StatisticalService {
} else {
$this->serverStats[$serverType][$serverId] = [$u, $d];
}
Cache::set("stat_server_{$this->startAt}", json_encode($this->serverStats));
Cache::store('file')->set("stat_server_{$this->startAt}", json_encode($this->serverStats));
}
public function statUser($rate, $userId, $u, $d)
@ -107,7 +107,7 @@ class StatisticalService {
} else {
$this->userStats[$rate][$userId] = [$u, $d];
}
Cache::set("stat_user_{$this->startAt}", json_encode($this->userStats));
Cache::store('file')->set("stat_user_{$this->startAt}", json_encode($this->userStats));
}
public function getStatUserByUserID($userId): array
@ -165,12 +165,12 @@ class StatisticalService {
public function clearStatUser()
{
Cache::forget("stat_user_{$this->startAt}");
Cache::store('file')->forget("stat_user_{$this->startAt}");
}
public function clearStatServer()
{
Cache::forget("stat_server_{$this->startAt}");
Cache::store('file')->forget("stat_server_{$this->startAt}");
}
public function getStatRecord($type)

View File

@ -175,8 +175,9 @@ class UserService
$statService->setUserStats();
$statService->setServerStats();
foreach (array_keys($data) as $userId) {
$u = $data[$userId][0];
$d = $data[$userId][1];
$u = (int)$data[$userId][0] ?? 0;
$d = (int)$data[$userId][1] ?? 0;
if (!$u && !$d) continue;
TrafficFetchJob::dispatch($u, $d, $userId, $server, $protocol);
$statService->statServer($server['id'], $protocol, $u, $d);
$statService->statUser($server['rate'], $userId, $u, $d);

View File

@ -19,13 +19,17 @@ class CacheKey
'SERVER_HYSTERIA_ONLINE_USER' => 'hysteria节点在线用户',
'SERVER_HYSTERIA_LAST_CHECK_AT' => 'hysteria节点最后检查时间',
'SERVER_HYSTERIA_LAST_PUSH_AT' => 'hysteria节点最后推送时间',
'SERVER_VLESS_ONLINE_USER' => 'vless节点在线用户',
'SERVER_VLESS_LAST_CHECK_AT' => 'vless节点最后检查时间',
'SERVER_VLESS_LAST_PUSH_AT' => 'vless节点最后推送时间',
'TEMP_TOKEN' => '临时令牌',
'LAST_SEND_EMAIL_REMIND_TRAFFIC' => '最后发送流量邮件提醒',
'SCHEDULE_LAST_CHECK_AT' => '计划任务最后检查时间',
'REGISTER_IP_RATE_LIMIT' => '注册频率限制',
'LAST_SEND_LOGIN_WITH_MAIL_LINK_TIMESTAMP' => '最后一次发送登入链接时间',
'PASSWORD_ERROR_LIMIT' => '密码错误次数限制',
'USER_SESSIONS' => '用户session'
'USER_SESSIONS' => '用户session',
'FORGET_REQUEST_LIMIT' => '找回密码次数限制'
];
public static function get(string $key, $uniqueValue)

View File

@ -36,9 +36,9 @@ class Helper
public static function exchange($from, $to)
{
$result = file_get_contents('https://api.exchangerate.host/latest?symbols=' . $to . '&base=' . $from);
$result = file_get_contents("https://cdn.jsdelivr.net/gh/fawazahmed0/currency-api@1/latest/currencies/" . $from . "/" . $to . ".json");
$result = json_decode($result, true);
return $result['rates'][$to];
return $result[$to];
}
public static function randomChar($len, $special = false)
@ -108,9 +108,12 @@ class Helper
}
}
public static function getSubscribeUrl($path)
public static function getSubscribeUrl($token)
{
$subscribeUrls = explode(',', config('v2board.subscribe_url'));
$c = new \App\Services\ConfigService();
$path = $c->get('site.subscribe_path');
$path = "/api/v1{$path}?token={$token}";
$subscribeUrls = explode(',', config('v2board.subscribe_url', '/client/subscribe'));
$subscribeUrl = $subscribeUrls[rand(0, count($subscribeUrls) - 1)];
if ($subscribeUrl) return $subscribeUrl . $path;
return url($path);
@ -120,4 +123,10 @@ class Helper
$portRange = explode('-', $range);
return rand($portRange[0], $portRange[1]);
}
public static function base64EncodeUrlSafe($data)
{
$encoded = base64_encode($data);
return str_replace(['+', '/', '='], ['-', '_', ''], $encoded);
}
}

View File

@ -23,7 +23,8 @@
"linfo/linfo": "^4.0",
"php-curl-class/php-curl-class": "^8.6",
"stripe/stripe-php": "^7.36.1",
"symfony/yaml": "^4.3"
"symfony/yaml": "^4.3",
"paragonie/sodium_compat": "^1.20"
},
"require-dev": {
"facade/ignition": "^2.3.6",

View File

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

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