ClientController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <?php
  2. namespace App\Http\Controllers\Api\Client;
  3. use App\Components\Helpers;
  4. use App\Helpers\ClientApiResponse;
  5. use App\Helpers\ResponseEnum;
  6. use App\Models\Article;
  7. use App\Models\GoodsCategory;
  8. use App\Models\Level;
  9. use App\Models\ReferralLog;
  10. use App\Models\Ticket;
  11. use App\Services\ProxyService;
  12. use App\Services\UserService;
  13. use Arr;
  14. use Artisan;
  15. use Illuminate\Database\Eloquent\Builder;
  16. use Illuminate\Http\JsonResponse;
  17. use Illuminate\Http\Request;
  18. use Illuminate\Routing\Controller;
  19. use Illuminate\Support\Facades\Cache;
  20. use function config;
  21. class ClientController extends Controller
  22. {
  23. use ClientApiResponse;
  24. private static $method;
  25. public function __construct(Request $request)
  26. {
  27. if (str_contains($request->userAgent(), 'bob_vpn')) {
  28. $this->setClient('bob');
  29. }
  30. }
  31. public function getUserInfo()
  32. {
  33. $user = auth()->user();
  34. if (! $user) {
  35. return false;
  36. }
  37. $userInfo = UserService::getInstance()->getProfile();
  38. $userInfo['user_name'] = $user->nickname;
  39. $userInfo['email'] = $user->username;
  40. $userInfo['class_expire'] = $user->expiration_date;
  41. $userInfo['money'] = $user->credit;
  42. $userInfo['plan']['name'] = $user->orders()->activePlan()->latest()->first()->goods->name ?? '无';
  43. $ann = Article::type(2)->latest()->first();
  44. $user_expire = now()->diffInDays($user->expired_at, false) < 0;
  45. $total = $user->u + $user->d;
  46. $transfer_enable = $user->transfer_enable;
  47. $expired_days = now()->diffInDays($user->expired_at, false);
  48. $userInfo['class_expire_notice'] = '';
  49. if ($expired_days < 0) {
  50. $userInfo['class_expire_notice'] = '账号会员已过期,请先续费再使用~';
  51. } elseif ($expired_days > 0 && $expired_days <= config('client.class_expire_notice.days')) {
  52. $userInfo['class_expire_notice'] = sprintf(config('client.class_expire_notice.msg'), $expired_days);
  53. }
  54. $data['info'] = [
  55. 'user' => $userInfo,
  56. 'ssrSubToken' => $user->subscribe->code,
  57. 'user_expire' => $user_expire,
  58. 'subUrl' => route('sub', $user->subscribe->code),
  59. 'baseUrl' => sysConfig('subscribe_domain') ?? sysConfig('website_url'),
  60. 'ann' => $ann,
  61. 'avatar' => $user->avatar,
  62. 'usedTraffic' => flowAutoShow($total),
  63. 'enableTraffic' => flowAutoShow($transfer_enable),
  64. 'unUsedTraffic' => flowAutoShow($transfer_enable - $total),
  65. 'reset_time' => now()->diffInDays($user->reset_time, false),
  66. 'android_index_button' => config('client.android_index_button'),
  67. ];
  68. return $this->succeed(null, $data);
  69. }
  70. public function getOrders(Request $request)
  71. {
  72. $user = $request->user();
  73. $orders = $user->orders()->orderByDesc('id')->limit(8)->get();
  74. $data = [];
  75. foreach ($orders as $order) {
  76. $data[] = [
  77. 'id' => $order->id,
  78. 'total_amount' => $order->amount * 100,
  79. 'plan' => ['name' => $order->goods()->value('name') ?? '余额充值'],
  80. 'status' => [-1 => 2, 0 => 0, 1 => 1, 2 => 3, 3 => 4][$order->status],
  81. 'created_at' => strtotime($order->created_at),
  82. ];
  83. }
  84. return $this->succeed($data);
  85. }
  86. public function getUserTransfer()
  87. {
  88. $user = auth()->user();
  89. return $this->succeed(null, [
  90. 'arr' => [
  91. 'todayUsedTraffic' => flowAutoShow($user->d),
  92. 'lastUsedTraffic' => flowAutoShow($user->u),
  93. 'unUsedTraffic' => flowAutoShow($user->transfer_enable - $user->d - $user->u),
  94. ],
  95. ]);
  96. }
  97. public function shop()
  98. {
  99. $shops = [
  100. 'keys' => [],
  101. 'data' => [],
  102. ];
  103. foreach (GoodsCategory::query()->whereStatus(1)->whereHas('goods')->get() as $category) {
  104. $shops['keys'][] = $category['name'];
  105. $shops['data'][$category['name']] = $category->goods()->get(['name', 'price', 'traffic'])->append('traffic_label')->toArray();
  106. }
  107. return $this->succeed($shops);
  108. }
  109. public function getInvite()
  110. {
  111. $user = auth()->user();
  112. $referral_traffic = flowAutoShow(sysConfig('referral_traffic') * MB);
  113. $referral_percent = sysConfig('referral_percent');
  114. // 邀请码
  115. $code = $user->invites()->whereStatus(0)->value('code');
  116. $data['invite_gift'] = trans('user.invite.promotion', [
  117. 'traffic' => $referral_traffic,
  118. 'referral_percent' => $referral_percent * 100,
  119. ]);
  120. $data['invite_code'] = $code ?? UserService::getInstance()->inviteURI(true);
  121. $data['invite_url'] = UserService::getInstance()->inviteURI();
  122. $data['invite_text'] = $data['invite_url'].'&(复制整段文字到浏览器打开即可访问),找梯子最重要的就是稳定,这个已经上线三年了,一直稳定没有被封过,赶紧下载备用吧!'.($code ? '安装后打开填写我的邀请码【'.$code.'】,你还能多得3天会员.' : '');
  123. // 累计数据
  124. $data['back_sum'] = ReferralLog::uid()->sum('commission') / 100;
  125. $data['user_num'] = $user->invitees()->count();
  126. $data['list'] = $user->invitees()->whereHas('orders', function (Builder $query) {
  127. $query->where('status', '>=', 2)->where('amount', '>', 0);
  128. })->selectRaw('username as user_name, UNIX_TIMESTAMP(created_at) as datetime, id')->orderByDesc('created_at')->limit(10)->get()->toArray();
  129. foreach ($data['list'] as &$item) {
  130. $item['ref_get'] = ReferralLog::uid()->where('invitee_id', $item['id'])->sum('commission') / 100;
  131. }
  132. return $this->succeed(null, $data);
  133. }
  134. public function checkIn(Request $request): JsonResponse
  135. {
  136. $user = $request->user();
  137. // 系统开启登录加积分功能才可以签到
  138. if (! sysConfig('is_checkin')) {
  139. return response()->json(['ret' => 0, 'title' => trans('common.failed'), 'msg' => trans('user.home.attendance.disable')]);
  140. }
  141. // 已签到过,验证是否有效
  142. if (Cache::has('userCheckIn_'.$user->id)) {
  143. return response()->json(['ret' => 0, 'title' => trans('common.success'), 'msg' => trans('user.home.attendance.done')]);
  144. }
  145. $traffic = random_int((int) sysConfig('min_rand_traffic'), (int) sysConfig('max_rand_traffic')) * MB;
  146. if (! $user->incrementData($traffic)) {
  147. return response()->json(['ret' => 0, 'title' => trans('common.failed'), 'msg' => trans('user.home.attendance.failed')]);
  148. }
  149. Helpers::addUserTrafficModifyLog($user->id, $user->transfer_enable, $user->transfer_enable + $traffic, trans('user.home.attendance.attribute'));
  150. // 多久后可以再签到
  151. $ttl = sysConfig('traffic_limit_time') ? sysConfig('traffic_limit_time') * Minute : Day;
  152. Cache::put('userCheckIn_'.$user->id, '1', $ttl);
  153. return $this->succeed(null, null, [200, trans('user.home.attendance.success', ['data' => flowAutoShow($traffic)])]);
  154. }
  155. public function proxyCheck(Request $request)
  156. {
  157. $md5 = $request->get('md5', '');
  158. $proxy = ProxyService::getInstance()->getProxyCode('clash');
  159. if (strtolower(md5(json_encode($proxy))) === strtolower($md5)) {
  160. return $this->succeed(false);
  161. }
  162. return $this->succeed(true, ['md5' => strtolower(md5(json_encode($proxy)))]);
  163. }
  164. public function downloadProxies(Request $request)
  165. {
  166. $flag = strtolower($request->input('flag') ?? ($request->userAgent() ?? ''));
  167. return ProxyService::getInstance()->getProxyText($flag === 'v2rayng' ? 'v2rayng' : 'clash', $request->input('type'));
  168. }
  169. public function getProxyList()
  170. {
  171. $proxyServer = ProxyService::getInstance();
  172. $servers = [];
  173. foreach ($proxyServer->getNodeList(null, false) as $node) {
  174. $server = $proxyServer->getProxyConfig($node);
  175. if ($server['type'] === '`shadowsocks`' || $server['type'] === 'shadowsocksr') {
  176. $server['type'] = 1;
  177. }
  178. $online_log = $node->onlineLogs->where('log_time', '>=', strtotime('-5 minutes'))->sortBy('log_time')->first(); // 在线人数
  179. $server['node_ip'] = filter_var($server['host'], FILTER_VALIDATE_IP) ? $server['host'] : gethostbyname($server['host']);
  180. $server['online'] = $online_log->online_user ?? 0;
  181. $this->getOnlineCount($server, $server['online']);
  182. $servers[] = $server;
  183. }
  184. return $this->succeed($servers);
  185. }
  186. private function getOnlineCount(&$node, int $online)
  187. {
  188. $node['flag'] = $node['area'];
  189. if ($online < 15) {
  190. $node['text'] = '⭐ 畅 通';
  191. $node['color'] = '#28a745';
  192. } elseif ($online < 30) {
  193. $node['text'] = '💫 拥 挤';
  194. $node['color'] = '#ffc107';
  195. } else {
  196. $node['text'] = '🔥 爆 满';
  197. $node['color'] = '#dc3545';
  198. }
  199. }
  200. public function getconfig()
  201. {
  202. $config = $this->clientConfig();
  203. Arr::forget($config, ['read', 'configured']);
  204. return $this->succeed(null, ['config' => $config]);
  205. }
  206. private function clientConfig($key = '')
  207. {
  208. if (! config('client')) {
  209. Artisan::call('config:cache');
  210. }
  211. if (config('client.configured') !== true && config('client.read')) {
  212. $this->setClientConfig();
  213. }
  214. return $key ? config('client.'.$key) : config('client');
  215. }
  216. private function setClientConfig() //
  217. {
  218. $ann = Article::type(2)->latest()->first();
  219. if ($ann) {
  220. config(['client.notice.title' => $ann->title, 'client.notice.content' => $ann->content]);
  221. }
  222. config([
  223. 'client.configured' => true,
  224. 'client.name' => sysConfig('website_name'),
  225. 'client.node_class_name' => Level::all()->pluck('name', 'level')->toArray(),
  226. 'client.baseUrl' => sysConfig('website_url'),
  227. 'client.subscribe_url' => sysConfig('subscribe_domain') ?: sysConfig('website_url'),
  228. 'client.checkinMin' => sysConfig('min_rand_traffic'),
  229. 'client.checkinMax' => sysConfig('max_rand_traffic'),
  230. 'client.invite_gift' => sysConfig('default_traffic') / 1024,
  231. ]);
  232. }
  233. public function checkClientVersion(Request $request)
  234. {
  235. $version = $request->input('version');
  236. $type = $request->input('type');
  237. $config = $this->clientConfig('vpn_update');
  238. if (! isset($version, $type)) {
  239. return $this->failed(ResponseEnum::CLIENT_PARAMETER_ERROR);
  240. }
  241. $vpn = $config[$type];
  242. if (! $config['enable'] || $vpn['version'] === $version) {
  243. return $this->succeed(null, ['enable' => false]);
  244. }
  245. return $this->succeed(null, ['enable' => true, 'download_url' => $vpn['download_url'], 'must' => $vpn['must'], 'message' => $vpn['message']], [200, $vpn['message']]);
  246. }
  247. public function ticketList()
  248. {
  249. $ticket = Ticket::where('user_id', auth()->user()->id)->selectRaw('id, title, UNIX_TIMESTAMP(created_at) as datetime, status')->orderBy('created_at', 'DESC')->get();
  250. return $this->succeed($ticket);
  251. }
  252. }