UserController.php 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Controllers;
  4. use App\Models\Ann;
  5. use App\Models\Bought;
  6. use App\Models\Code;
  7. use App\Models\Docs;
  8. use App\Models\EmailVerify;
  9. use App\Models\InviteCode;
  10. use App\Models\Ip;
  11. use App\Models\LoginIp;
  12. use App\Models\Node;
  13. use App\Models\Payback;
  14. use App\Models\Setting;
  15. use App\Models\StreamMedia;
  16. use App\Models\User;
  17. use App\Models\UserSubscribeLog;
  18. use App\Services\Auth;
  19. use App\Services\Captcha;
  20. use App\Services\Config;
  21. use App\Services\Payment;
  22. use App\Utils\Check;
  23. use App\Utils\Cookie;
  24. use App\Utils\DatatablesHelper;
  25. use App\Utils\GA;
  26. use App\Utils\Hash;
  27. use App\Utils\QQWry;
  28. use App\Utils\ResponseHelper;
  29. use App\Utils\TelegramSessionManager;
  30. use App\Utils\Tools;
  31. use App\Utils\URL;
  32. use Ramsey\Uuid\Uuid;
  33. use Slim\Http\Request;
  34. use Slim\Http\Response;
  35. use voku\helper\AntiXSS;
  36. /**
  37. * HomeController
  38. */
  39. final class UserController extends BaseController
  40. {
  41. /**
  42. * @param array $args
  43. */
  44. public function index(Request $request, Response $response, array $args)
  45. {
  46. $captcha = [];
  47. if (Setting::obtain('enable_checkin_captcha') === true) {
  48. $captcha = Captcha::generate();
  49. }
  50. $data = [
  51. 'today_traffic_usage' => (int) $this->user->transfer_enable === 0 ? 0 : ($this->user->u + $this->user->d - $this->user->last_day_t) / $this->user->transfer_enable * 100,
  52. 'past_traffic_usage' => (int) $this->user->transfer_enable === 0 ? 0 : $this->user->last_day_t / $this->user->transfer_enable * 100,
  53. 'residual_flow' => (int) $this->user->transfer_enable === 0 ? 0 : ($this->user->transfer_enable - ($this->user->u + $this->user->d)) / $this->user->transfer_enable * 100,
  54. ];
  55. return $response->write(
  56. $this->view()
  57. ->assign('ann', Ann::orderBy('date', 'desc')->first())
  58. ->assign('getUniversalSub', SubController::getUniversalSub($this->user))
  59. ->assign('data', $data)
  60. ->assign('captcha', $captcha)
  61. ->display('user/index.tpl')
  62. );
  63. }
  64. /**
  65. * @param array $args
  66. */
  67. public function code(Request $request, Response $response, array $args)
  68. {
  69. $pageNum = $request->getQueryParams()['page'] ?? 1;
  70. $codes = Code::where('type', '<>', '-2')
  71. ->where('userid', '=', $this->user->id)
  72. ->orderBy('id', 'desc')
  73. ->paginate(15, ['*'], 'page', $pageNum);
  74. $render = Tools::paginateRender($codes);
  75. return $response->write(
  76. $this->view()
  77. ->assign('codes', $codes)
  78. ->assign('payments', Payment::getPaymentsEnabled())
  79. ->assign('render', $render)
  80. ->display('user/code.tpl')
  81. );
  82. }
  83. /**
  84. * @param array $args
  85. */
  86. public function codeCheck(Request $request, Response $response, array $args)
  87. {
  88. $time = $request->getQueryParams()['time'];
  89. $codes = Code::where('userid', '=', $this->user->id)
  90. ->where('usedatetime', '>', date('Y-m-d H:i:s', $time))
  91. ->first();
  92. if ($codes !== null && strpos($codes->code, '充值') !== false) {
  93. return $response->withJson([
  94. 'ret' => 1,
  95. ]);
  96. }
  97. return $response->withJson([
  98. 'ret' => 0,
  99. ]);
  100. }
  101. /**
  102. * @param array $args
  103. */
  104. public function codePost(Request $request, Response $response, array $args)
  105. {
  106. $code = trim($request->getParam('code'));
  107. if ($code === '') {
  108. return ResponseHelper::error($response, '请填写充值码');
  109. }
  110. $codeq = Code::where('code', $code)->where('isused', 0)->first();
  111. if ($codeq === null) {
  112. return ResponseHelper::error($response, '没有这个充值码');
  113. }
  114. $user = $this->user;
  115. $codeq->isused = 1;
  116. $codeq->usedatetime = date('Y-m-d H:i:s');
  117. $codeq->userid = $user->id;
  118. $codeq->save();
  119. if ($codeq->type === -1) {
  120. $user->money += $codeq->number;
  121. $user->save();
  122. // 返利
  123. if ($user->ref_by > 0 && Setting::obtain('invitation_mode') === 'after_recharge') {
  124. Payback::rebate($user->id, $codeq->number);
  125. }
  126. return $response->withJson([
  127. 'ret' => 1,
  128. 'msg' => '兑换成功,金额为 ' . $codeq->number . ' 元',
  129. ]);
  130. }
  131. if ($codeq->type === 10001) {
  132. $user->transfer_enable += $codeq->number * 1024 * 1024 * 1024;
  133. $user->save();
  134. }
  135. if ($codeq->type === 10002) {
  136. if (\time() > strtotime($user->expire_in)) {
  137. $user->expire_in = date('Y-m-d H:i:s', \time() + $codeq->number * 86400);
  138. } else {
  139. $user->expire_in = date('Y-m-d H:i:s', strtotime($user->expire_in) + $codeq->number * 86400);
  140. }
  141. $user->save();
  142. }
  143. if ($codeq->type >= 1 && $codeq->type <= 10000) {
  144. if ($user->class === 0 || $user->class !== $codeq->type) {
  145. $user->class_expire = date('Y-m-d H:i:s', \time());
  146. $user->save();
  147. }
  148. $user->class_expire = date('Y-m-d H:i:s', strtotime($user->class_expire) + $codeq->number * 86400);
  149. $user->class = $codeq->type;
  150. $user->save();
  151. }
  152. return $response->withJson([
  153. 'ret' => 1,
  154. 'msg' => '',
  155. ]);
  156. }
  157. /**
  158. * @param array $args
  159. */
  160. public function checkGa(Request $request, Response $response, array $args)
  161. {
  162. $code = $request->getParam('code');
  163. if ($code === '') {
  164. return $response->withJson([
  165. 'ret' => 0,
  166. 'msg' => '二维码不能为空',
  167. ]);
  168. }
  169. $user = $this->user;
  170. $ga = new GA();
  171. $rcode = $ga->verifyCode($user->ga_token, $code);
  172. if (! $rcode) {
  173. return $response->withJson([
  174. 'ret' => 0,
  175. 'msg' => '测试错误',
  176. ]);
  177. }
  178. return $response->withJson([
  179. 'ret' => 1,
  180. 'msg' => '测试成功',
  181. ]);
  182. }
  183. /**
  184. * @param array $args
  185. */
  186. public function setGa(Request $request, Response $response, array $args)
  187. {
  188. $enable = $request->getParam('enable');
  189. if ($enable === '') {
  190. return $response->withJson([
  191. 'ret' => 0,
  192. 'msg' => '选项无效',
  193. ]);
  194. }
  195. $user = $this->user;
  196. $user->ga_enable = $enable;
  197. $user->save();
  198. return $response->withJson([
  199. 'ret' => 1,
  200. 'msg' => '设置成功',
  201. ]);
  202. }
  203. /**
  204. * @param array $args
  205. */
  206. public function resetPort(Request $request, Response $response, array $args)
  207. {
  208. $temp = $this->user->resetPort();
  209. return $response->withJson([
  210. 'ret' => ($temp['ok'] === true ? 1 : 0),
  211. 'msg' => $temp['msg'],
  212. ]);
  213. }
  214. /**
  215. * @param array $args
  216. */
  217. public function specifyPort(Request $request, Response $response, array $args)
  218. {
  219. $temp = $this->user->specifyPort((int) $request->getParam('port'));
  220. return $response->withJson([
  221. 'ret' => ($temp['ok'] === true ? 1 : 0),
  222. 'msg' => $temp['msg'],
  223. ]);
  224. }
  225. /**
  226. * @param array $args
  227. */
  228. public function resetGa(Request $request, Response $response, array $args)
  229. {
  230. $ga = new GA();
  231. $secret = $ga->createSecret();
  232. $user = $this->user;
  233. $user->ga_token = $secret;
  234. $user->save();
  235. return $response->withStatus(302)->withHeader('Location', '/user/edit');
  236. }
  237. /**
  238. * @param array $args
  239. */
  240. public function profile(Request $request, Response $response, array $args)
  241. {
  242. $pageNum = $request->getQueryParams()['page'] ?? 1;
  243. $paybacks = Payback::where('ref_by', $this->user->id)
  244. ->orderBy('datetime', 'desc')
  245. ->paginate(15, ['*'], 'page', $pageNum);
  246. // 登录IP
  247. $totallogin = LoginIp::where('userid', '=', $this->user->id)->where('type', '=', 0)->orderBy('datetime', 'desc')->take(10)->get();
  248. // 使用IP
  249. $userip = [];
  250. $iplocation = new QQWry();
  251. $total = Ip::where('datetime', '>=', \time() - 300)->where('userid', '=', $this->user->id)->get();
  252. foreach ($total as $single) {
  253. $single->ip = Tools::getRealIp($single->ip);
  254. $is_node = Node::where('node_ip', $single->ip)->first();
  255. if ($is_node) {
  256. continue;
  257. }
  258. if (! isset($userip[$single->ip])) {
  259. $location = $iplocation->getlocation($single->ip);
  260. $userip[$single->ip] = iconv('gbk', 'utf-8//IGNORE', $location['country'] . $location['area']);
  261. }
  262. }
  263. if ($request->getParam('json') === 1) {
  264. return $response->withJson([
  265. 'ret' => 1,
  266. 'paybacks' => $paybacks,
  267. 'userloginip' => $totallogin,
  268. 'userip' => $userip,
  269. ]);
  270. }
  271. $boughts = Bought::where('userid', $this->user->id)->orderBy('id', 'desc')->get();
  272. return $response->write(
  273. $this->view()
  274. ->assign('boughts', $boughts)
  275. ->assign('userip', $userip)
  276. ->assign('userloginip', $totallogin)
  277. ->assign('paybacks', $paybacks)
  278. ->registerClass('Tools', Tools::class)
  279. ->display('user/profile.tpl')
  280. );
  281. }
  282. /**
  283. * @param array $args
  284. */
  285. public function announcement(Request $request, Response $response, array $args)
  286. {
  287. $Anns = Ann::orderBy('date', 'desc')->get();
  288. if ($request->getParam('json') === 1) {
  289. return $response->withJson([
  290. 'Anns' => $Anns,
  291. 'ret' => 1,
  292. ]);
  293. }
  294. return $response->write(
  295. $this->view()
  296. ->assign('anns', $Anns)
  297. ->display('user/announcement.tpl')
  298. );
  299. }
  300. /**
  301. * @param array $args
  302. */
  303. public function docs(Request $request, Response $response, array $args)
  304. {
  305. $docs = Docs::orderBy('id', 'desc')->get();
  306. if ($request->getParam('json') === 1) {
  307. return $response->withJson([
  308. 'docs' => $docs,
  309. 'ret' => 1,
  310. ]);
  311. }
  312. return $response->write(
  313. $this->view()
  314. ->assign('docs', $docs)
  315. ->display('user/docs.tpl')
  316. );
  317. }
  318. /**
  319. * @param array $args
  320. */
  321. public function media(Request $request, Response $response, array $args)
  322. {
  323. $results = [];
  324. $db = new DatatablesHelper();
  325. $nodes = $db->query('SELECT DISTINCT node_id FROM stream_media');
  326. foreach ($nodes as $node_id) {
  327. $node = Node::where('id', $node_id)->first();
  328. $unlock = StreamMedia::where('node_id', $node_id)
  329. ->orderBy('id', 'desc')
  330. ->where('created_at', '>', \time() - 86460) // 只获取最近一天零一分钟内上报的数据
  331. ->first();
  332. if ($unlock !== null && $node !== null) {
  333. $details = \json_decode($unlock->result, true);
  334. $details = str_replace('Originals Only', '仅限自制', $details);
  335. $details = str_replace('Oversea Only', '仅限海外', $details);
  336. foreach ($details as $key => $value) {
  337. $info = [
  338. 'node_name' => $node->name,
  339. 'created_at' => $unlock->created_at,
  340. 'unlock_item' => $details,
  341. ];
  342. }
  343. array_push($results, $info);
  344. }
  345. }
  346. if ($_ENV['streaming_media_unlock_multiplexing'] !== null) {
  347. foreach ($_ENV['streaming_media_unlock_multiplexing'] as $key => $value) {
  348. $key_node = Node::where('id', $key)->first();
  349. $value_node = StreamMedia::where('node_id', $value)
  350. ->orderBy('id', 'desc')
  351. ->where('created_at', '>', \time() - 86460) // 只获取最近一天零一分钟内上报的数据
  352. ->first();
  353. if ($value_node !== null) {
  354. $details = \json_decode($value_node->result, true);
  355. $details = str_replace('Originals Only', '仅限自制', $details);
  356. $details = str_replace('Oversea Only', '仅限海外', $details);
  357. $info = [
  358. 'node_name' => $key_node->name,
  359. 'created_at' => $value_node->created_at,
  360. 'unlock_item' => $details,
  361. ];
  362. array_push($results, $info);
  363. }
  364. }
  365. }
  366. array_multisort(array_column($results, 'node_name'), SORT_ASC, $results);
  367. return $this->view()
  368. ->assign('results', $results)
  369. ->display('user/media.tpl');
  370. }
  371. /**
  372. * @param array $args
  373. */
  374. public function edit(Request $request, Response $response, array $args)
  375. {
  376. $themes = Tools::getDir(BASE_PATH . '/resources/views');
  377. $bind_token = TelegramSessionManager::addBindSession($this->user);
  378. $methods = Config::getSupportParam('method');
  379. return $this->view()
  380. ->assign('user', $this->user)
  381. ->assign('themes', $themes)
  382. ->assign('bind_token', $bind_token)
  383. ->assign('methods', $methods)
  384. ->assign('telegram_bot', $_ENV['telegram_bot'])
  385. ->registerClass('Config', Config::class)
  386. ->registerClass('URL', URL::class)
  387. ->display('user/edit.tpl');
  388. }
  389. /**
  390. * @param array $args
  391. */
  392. public function invite(Request $request, Response $response, array $args)
  393. {
  394. $code = InviteCode::where('user_id', $this->user->id)->first();
  395. if ($code === null) {
  396. $this->user->addInviteCode();
  397. $code = InviteCode::where('user_id', $this->user->id)->first();
  398. }
  399. $pageNum = $request->getQueryParams()['page'] ?? 1;
  400. $paybacks = Payback::where('ref_by', $this->user->id)
  401. ->orderBy('id', 'desc')
  402. ->paginate(15, ['*'], 'page', $pageNum);
  403. $paybacks_sum = Payback::where('ref_by', $this->user->id)->sum('ref_get');
  404. if (! $paybacks_sum) {
  405. $paybacks_sum = 0;
  406. }
  407. $render = Tools::paginateRender($paybacks);
  408. $invite_url = $_ENV['baseUrl'] . '/auth/register?code=' . $code->code;
  409. return $this->view()
  410. ->assign('code', $code)
  411. ->assign('render', $render)
  412. ->assign('paybacks', $paybacks)
  413. ->assign('invite_url', $invite_url)
  414. ->assign('paybacks_sum', $paybacks_sum)
  415. ->display('user/invite.tpl');
  416. }
  417. /**
  418. * @param array $args
  419. */
  420. public function buyInvite(Request $request, Response $response, array $args)
  421. {
  422. $price = Setting::obtain('invite_price');
  423. $num = $request->getParam('num');
  424. $num = trim($num);
  425. if (! Tools::isInt($num) || $price < 0 || $num <= 0) {
  426. return ResponseHelper::error($response, '非法请求');
  427. }
  428. $amount = $price * $num;
  429. $user = $this->user;
  430. if (! $user->isLogin) {
  431. return $response->withJson([ 'ret' => -1 ]);
  432. }
  433. if ($user->money < $amount) {
  434. return ResponseHelper::error($response, '余额不足,总价为' . $amount . '元。');
  435. }
  436. $user->invite_num += $num;
  437. $user->money -= $amount;
  438. $user->save();
  439. return ResponseHelper::successfully($response, '邀请次数添加成功');
  440. }
  441. /**
  442. * @param array $args
  443. */
  444. public function customInvite(Request $request, Response $response, array $args)
  445. {
  446. $price = Setting::obtain('custom_invite_price');
  447. $customcode = $request->getParam('customcode');
  448. $customcode = trim($customcode);
  449. if (Tools::isSpecialChars($customcode) || $price < 0 || $customcode === '' || strlen($customcode) > 32) {
  450. return ResponseHelper::error(
  451. $response,
  452. '定制失败,邀请链接不能为空,后缀不能包含特殊符号且长度不能大于32字符'
  453. );
  454. }
  455. if (InviteCode::where('code', $customcode)->count() !== 0) {
  456. return ResponseHelper::error($response, '此后缀名被抢注了');
  457. }
  458. $user = $this->user;
  459. if (! $user->isLogin) {
  460. return $response->withJson([ 'ret' => -1 ]);
  461. }
  462. if ($user->money < $price) {
  463. return ResponseHelper::error(
  464. $response,
  465. '余额不足,总价为' . $price . '元。'
  466. );
  467. }
  468. $code = InviteCode::where('user_id', $user->id)->first();
  469. $code->code = $customcode;
  470. $user->money -= $price;
  471. $user->save();
  472. $code->save();
  473. return ResponseHelper::successfully($response, '定制成功');
  474. }
  475. /**
  476. * @param array $args
  477. */
  478. public function updatePassword(Request $request, Response $response, array $args)
  479. {
  480. $oldpwd = $request->getParam('oldpwd');
  481. $pwd = $request->getParam('pwd');
  482. $repwd = $request->getParam('repwd');
  483. $user = $this->user;
  484. if (! Hash::checkPassword($user->pass, $oldpwd)) {
  485. return ResponseHelper::error($response, '旧密码错误');
  486. }
  487. if ($pwd !== $repwd) {
  488. return ResponseHelper::error($response, '两次输入不符合');
  489. }
  490. if (strlen($pwd) < 8) {
  491. return ResponseHelper::error($response, '密码太短啦');
  492. }
  493. $hashPwd = Hash::passwordHash($pwd);
  494. $user->pass = $hashPwd;
  495. $user->save();
  496. if ($_ENV['enable_forced_replacement'] === true) {
  497. $user->cleanLink();
  498. }
  499. return ResponseHelper::successfully($response, '修改成功');
  500. }
  501. /**
  502. * @param array $args
  503. */
  504. public function updateEmail(Request $request, Response $response, array $args)
  505. {
  506. $user = $this->user;
  507. $newemail = $request->getParam('newemail');
  508. $oldemail = $user->email;
  509. $otheruser = User::where('email', $newemail)->first();
  510. if ($_ENV['enable_change_email'] !== true) {
  511. return ResponseHelper::error($response, '此项不允许自行修改,请联系管理员操作');
  512. }
  513. if (Setting::obtain('reg_email_verify')) {
  514. $emailcode = $request->getParam('emailcode');
  515. $mailcount = EmailVerify::where('email', '=', $newemail)->where('code', '=', $emailcode)->where('expire_in', '>', \time())->first();
  516. if ($mailcount === null) {
  517. return ResponseHelper::error($response, '您的邮箱验证码不正确');
  518. }
  519. }
  520. if ($newemail === '') {
  521. return ResponseHelper::error($response, '未填写邮箱');
  522. }
  523. $check_res = Check::isEmailLegal($newemail);
  524. if ($check_res['ret'] === 0) {
  525. return $response->withJson($check_res);
  526. }
  527. if ($otheruser !== null) {
  528. return ResponseHelper::error($response, '邮箱已经被使用了');
  529. }
  530. if ($newemail === $oldemail) {
  531. return ResponseHelper::error($response, '新邮箱不能和旧邮箱一样');
  532. }
  533. $antiXss = new AntiXSS();
  534. $user->email = $antiXss->xss_clean($newemail);
  535. $user->save();
  536. return ResponseHelper::successfully($response, '修改成功');
  537. }
  538. /**
  539. * @param array $args
  540. */
  541. public function updateUsername(Request $request, Response $response, array $args)
  542. {
  543. $newusername = $request->getParam('newusername');
  544. $user = $this->user;
  545. $antiXss = new AntiXSS();
  546. $user->user_name = $antiXss->xss_clean($newusername);
  547. $user->save();
  548. return ResponseHelper::successfully($response, '修改成功');
  549. }
  550. /**
  551. * @param array $args
  552. */
  553. public function bought(Request $request, Response $response, array $args)
  554. {
  555. $pageNum = $request->getQueryParams()['page'] ?? 1;
  556. $shops = Bought::where('userid', $this->user->id)->orderBy('id', 'desc')->paginate(15, ['*'], 'page', $pageNum);
  557. if ($request->getParam('json') === 1) {
  558. foreach ($shops as $shop) {
  559. $shop->datetime = $shop->datetime();
  560. $shop->name = $shop->shop()->name;
  561. $shop->content = $shop->shop()->content();
  562. }
  563. return $response->withJson([
  564. 'ret' => 1,
  565. 'shops' => $shops,
  566. ]);
  567. }
  568. $render = Tools::paginateRender($shops);
  569. return $this->view()
  570. ->assign('shops', $shops)
  571. ->assign('render', $render)
  572. ->display('user/bought.tpl');
  573. }
  574. /**
  575. * @param array $args
  576. */
  577. public function deleteBoughtGet(Request $request, Response $response, array $args)
  578. {
  579. $id = $request->getParam('id');
  580. $shop = Bought::where('id', $id)->where('userid', $this->user->id)->first();
  581. if ($shop === null) {
  582. return ResponseHelper::error($response, '关闭自动续费失败,订单不存在。');
  583. }
  584. if ($this->user->id === $shop->userid) {
  585. $shop->renew = 0;
  586. }
  587. if (! $shop->save()) {
  588. return ResponseHelper::error($response, '关闭自动续费失败');
  589. }
  590. return ResponseHelper::successfully($response, '关闭自动续费成功');
  591. }
  592. /**
  593. * @param array $args
  594. */
  595. public function updateContact(Request $request, Response $response, array $args)
  596. {
  597. $type = $request->getParam('imtype');
  598. $contact = trim($request->getParam('contact'));
  599. $user = $this->user;
  600. if ($user->telegram_id !== null) {
  601. return ResponseHelper::error(
  602. $response,
  603. '您绑定了 Telegram ,所以此项并不能被修改。'
  604. );
  605. }
  606. if ($contact === '' || $type === '') {
  607. return ResponseHelper::error($response, '非法输入');
  608. }
  609. $user1 = User::where('im_value', $contact)->where('im_type', $type)->first();
  610. if ($user1 !== null) {
  611. return ResponseHelper::error($response, '此联络方式已经被注册');
  612. }
  613. $user->im_type = $type;
  614. $antiXss = new AntiXSS();
  615. $user->im_value = $antiXss->xss_clean($contact);
  616. $user->save();
  617. return ResponseHelper::successfully($response, '修改成功');
  618. }
  619. /**
  620. * @param array $args
  621. */
  622. public function updateSSR(Request $request, Response $response, array $args)
  623. {
  624. $protocol = $request->getParam('protocol');
  625. $obfs = $request->getParam('obfs');
  626. $obfs_param = $request->getParam('obfs_param');
  627. $obfs_param = trim($obfs_param);
  628. $user = $this->user;
  629. if ($obfs === '' || $protocol === '') {
  630. return ResponseHelper::error($response, '非法输入');
  631. }
  632. if (! Tools::isParamValidate('obfs', $obfs)) {
  633. return ResponseHelper::error($response, '协议无效');
  634. }
  635. if (! Tools::isParamValidate('protocol', $protocol)) {
  636. return ResponseHelper::error($response, '协议无效');
  637. }
  638. $antiXss = new AntiXSS();
  639. $user->protocol = $antiXss->xss_clean($protocol);
  640. $user->obfs = $antiXss->xss_clean($obfs);
  641. $user->obfs_param = $antiXss->xss_clean($obfs_param);
  642. if (! Tools::checkNoneProtocol($user)) {
  643. return ResponseHelper::error(
  644. $response,
  645. '系统检测到您目前的加密方式为 none ,但您将要设置为的协议并不在以下协议<br>'
  646. . implode(',', Config::getSupportParam('allow_none_protocol'))
  647. . '<br>之内,请您先修改您的加密方式,再来修改此处设置。'
  648. );
  649. }
  650. if (! URL::SSCanConnect($user) && ! URL::SSRCanConnect($user)) {
  651. return ResponseHelper::error(
  652. $response,
  653. '您这样设置之后,就没有客户端能连接上了,所以系统拒绝了您的设置,请您检查您的设置之后再进行操作。'
  654. );
  655. }
  656. $user->save();
  657. if (! URL::SSCanConnect($user)) {
  658. return ResponseHelper::error(
  659. $response,
  660. '设置成功,但您目前的协议,混淆,加密方式设置会导致 Shadowsocks原版客户端无法连接,请您自行更换到 ShadowsocksR 客户端。'
  661. );
  662. }
  663. if (! URL::SSRCanConnect($user)) {
  664. return ResponseHelper::error(
  665. $response,
  666. '设置成功,但您目前的协议,混淆,加密方式设置会导致 ShadowsocksR 客户端无法连接,请您自行更换到 Shadowsocks 客户端。'
  667. );
  668. }
  669. return ResponseHelper::successfully($response, '设置成功,您可自由选用客户端来连接。');
  670. }
  671. /**
  672. * @param array $args
  673. */
  674. public function updateTheme(Request $request, Response $response, array $args)
  675. {
  676. $theme = $request->getParam('theme');
  677. $user = $this->user;
  678. if ($theme === '') {
  679. return ResponseHelper::error($response, '非法输入');
  680. }
  681. $antiXss = new AntiXSS();
  682. $user->theme = $antiXss->xss_clean($theme);
  683. $user->save();
  684. return ResponseHelper::successfully($response, '设置成功');
  685. }
  686. /**
  687. * @param array $args
  688. */
  689. public function updateMail(Request $request, Response $response, array $args)
  690. {
  691. $value = (int) $request->getParam('mail');
  692. if (\in_array($value, [0, 1, 2])) {
  693. $user = $this->user;
  694. if ($value === 2 && $_ENV['enable_telegram'] === false) {
  695. return ResponseHelper::error(
  696. $response,
  697. '修改失败,当前无法使用 Telegram 接收每日报告'
  698. );
  699. }
  700. $user->sendDailyMail = $value;
  701. $user->save();
  702. return ResponseHelper::successfully($response, '修改成功');
  703. }
  704. return ResponseHelper::error($response, '非法输入');
  705. }
  706. /**
  707. * @param array $args
  708. */
  709. public function resetPasswd(Request $request, Response $response, array $args)
  710. {
  711. $user = $this->user;
  712. $pwd = Tools::genRandomChar(16);
  713. $current_timestamp = \time();
  714. $new_uuid = Uuid::uuid3(Uuid::NAMESPACE_DNS, $user->email . '|' . $current_timestamp);
  715. $existing_uuid = User::where('uuid', $new_uuid)->first();
  716. if ($existing_uuid !== null) {
  717. return ResponseHelper::error($response, '目前出现一些问题,请稍后再试');
  718. }
  719. $user->uuid = $new_uuid;
  720. $user->passwd = $pwd;
  721. $user->save();
  722. return ResponseHelper::successfully($response, '修改成功');
  723. }
  724. /**
  725. * @param array $args
  726. */
  727. public function updateMethod(Request $request, Response $response, array $args)
  728. {
  729. $user = $this->user;
  730. $antiXss = new AntiXSS();
  731. $method = strtolower($antiXss->xss_clean($request->getParam('method')));
  732. if ($method === '') {
  733. ResponseHelper::error($response, '非法输入');
  734. }
  735. if (! Tools::isParamValidate('method', $method)) {
  736. ResponseHelper::error($response, '加密无效');
  737. }
  738. $user->method = $method;
  739. $user->save();
  740. return ResponseHelper::successfully($response, '修改成功');
  741. }
  742. /**
  743. * @param array $args
  744. */
  745. public function logout(Request $request, Response $response, array $args)
  746. {
  747. Auth::logout();
  748. return $response->withStatus(302)->withHeader('Location', '/');
  749. }
  750. /**
  751. * @param array $args
  752. */
  753. public function doCheckIn(Request $request, Response $response, array $args)
  754. {
  755. if ($_ENV['enable_checkin'] === false) {
  756. return ResponseHelper::error($response, '暂时还不能签到');
  757. }
  758. if (Setting::obtain('enable_checkin_captcha') === true) {
  759. $ret = Captcha::verify($request->getParams());
  760. if (! $ret) {
  761. return ResponseHelper::error($response, '系统无法接受您的验证结果,请刷新页面后重试');
  762. }
  763. }
  764. if (strtotime($this->user->expire_in) < \time()) {
  765. return ResponseHelper::error($response, '没有过期的账户才可以签到');
  766. }
  767. $checkin = $this->user->checkin();
  768. if ($checkin['ok'] === false) {
  769. return ResponseHelper::error($response, $checkin['msg']);
  770. }
  771. return $response->withJson([
  772. 'ret' => 1,
  773. 'trafficInfo' => [
  774. 'todayUsedTraffic' => $this->user->todayUsedTraffic(),
  775. 'lastUsedTraffic' => $this->user->lastUsedTraffic(),
  776. 'unUsedTraffic' => $this->user->unusedTraffic(),
  777. ],
  778. 'traffic' => Tools::flowAutoShow($this->user->transfer_enable),
  779. 'unflowtraffic' => $this->user->transfer_enable,
  780. 'msg' => $checkin['msg'],
  781. ]);
  782. }
  783. /**
  784. * @param array $args
  785. */
  786. public function kill(Request $request, Response $response, array $args)
  787. {
  788. return $this->view()->display('user/kill.tpl');
  789. }
  790. /**
  791. * @param array $args
  792. */
  793. public function handleKill(Request $request, Response $response, array $args)
  794. {
  795. $user = $this->user;
  796. $passwd = $request->getParam('passwd');
  797. if (! Hash::checkPassword($user->pass, $passwd)) {
  798. return ResponseHelper::error($response, '密码错误');
  799. }
  800. if ($_ENV['enable_kill'] === true) {
  801. Auth::logout();
  802. $user->killUser();
  803. return ResponseHelper::successfully($response, '您的帐号已经从我们的系统中删除。欢迎下次光临');
  804. }
  805. return ResponseHelper::error($response, '管理员不允许删除,如需删除请联系管理员。');
  806. }
  807. /**
  808. * @param array $args
  809. */
  810. public function banned(Request $request, Response $response, array $args)
  811. {
  812. $user = $this->user;
  813. return $this->view()
  814. ->assign('banned_reason', $user->banned_reason)
  815. ->display('user/banned.tpl');
  816. }
  817. /**
  818. * @param array $args
  819. */
  820. public function resetTelegram(Request $request, Response $response, array $args)
  821. {
  822. $user = $this->user;
  823. $user->telegramReset();
  824. return ResponseHelper::successfully($response, '重置成功');
  825. }
  826. /**
  827. * @param array $args
  828. */
  829. public function resetURL(Request $request, Response $response, array $args)
  830. {
  831. $user = $this->user;
  832. $user->cleanLink();
  833. return ResponseHelper::successfully($response, '重置成功');
  834. }
  835. /**
  836. * @param array $args
  837. */
  838. public function resetInviteURL(Request $request, Response $response, array $args)
  839. {
  840. $user = $this->user;
  841. $user->clearInviteCodes();
  842. return ResponseHelper::successfully($response, '重置成功');
  843. }
  844. /**
  845. * @param array $args
  846. */
  847. public function backtoadmin(Request $request, Response $response, array $args)
  848. {
  849. $userid = Cookie::get('uid');
  850. $adminid = Cookie::get('old_uid');
  851. $user = User::find($userid);
  852. $admin = User::find($adminid);
  853. if (! $admin->is_admin || ! $user) {
  854. Cookie::set([
  855. 'uid' => null,
  856. 'email' => null,
  857. 'key' => null,
  858. 'ip' => null,
  859. 'expire_in' => null,
  860. 'old_uid' => null,
  861. 'old_email' => null,
  862. 'old_key' => null,
  863. 'old_ip' => null,
  864. 'old_expire_in' => null,
  865. 'old_local' => null,
  866. ], \time() - 1000);
  867. }
  868. $expire_in = Cookie::get('old_expire_in');
  869. $local = Cookie::get('old_local');
  870. Cookie::set([
  871. 'uid' => Cookie::get('old_uid'),
  872. 'email' => Cookie::get('old_email'),
  873. 'key' => Cookie::get('old_key'),
  874. 'ip' => Cookie::get('old_ip'),
  875. 'expire_in' => $expire_in,
  876. 'old_uid' => null,
  877. 'old_email' => null,
  878. 'old_key' => null,
  879. 'old_ip' => null,
  880. 'old_expire_in' => null,
  881. 'old_local' => null,
  882. ], $expire_in);
  883. return $response->withStatus(302)->withHeader('Location', $local);
  884. }
  885. /**
  886. * @param array $args
  887. */
  888. public function getUserAllURL(Request $request, Response $response, array $args)
  889. {
  890. $user = $this->user;
  891. $type = $request->getQueryParams()['type'];
  892. $return = '';
  893. switch ($type) {
  894. case 'ss':
  895. $return .= URL::getNewAllUrl($user, ['type' => 'ss']) . PHP_EOL;
  896. break;
  897. case 'ssr':
  898. $return .= URL::getNewAllUrl($user, ['type' => 'ssr']) . PHP_EOL;
  899. break;
  900. case 'v2ray':
  901. $return .= URL::getNewAllUrl($user, ['type' => 'vmess']) . PHP_EOL;
  902. break;
  903. default:
  904. $return .= '悟空别闹!';
  905. break;
  906. }
  907. $response = $response->withHeader('Content-type', ' application/octet-stream; charset=utf-8')
  908. ->withHeader('Cache-Control', 'no-store, no-cache, must-revalidate')
  909. ->withHeader('Content-Disposition', ' attachment; filename=node.txt');
  910. return $response->write($return);
  911. }
  912. /**
  913. * 订阅记录
  914. *
  915. * @param array $args
  916. */
  917. public function subscribeLog(Request $request, Response $response, array $args)
  918. {
  919. if ($_ENV['subscribeLog_show'] === false) {
  920. return $response->withStatus(302)->withHeader('Location', '/user');
  921. }
  922. $pageNum = $request->getQueryParams()['page'] ?? 1;
  923. $logs = UserSubscribeLog::orderBy('id', 'desc')->where('user_id', $this->user->id)->paginate(15, ['*'], 'page', $pageNum);
  924. $render = Tools::paginateRender($logs);
  925. return $this->view()
  926. ->assign('logs', $logs)
  927. ->assign('render', $render)
  928. ->registerClass('Tools', Tools::class)
  929. ->fetch('user/subscribe_log.tpl');
  930. }
  931. /**
  932. * @param array $args
  933. */
  934. public function switchThemeMode(Request $request, Response $response, array $args)
  935. {
  936. $user = $this->user;
  937. if ($user->is_dark_mode === 1) {
  938. $user->is_dark_mode = 0;
  939. } else {
  940. $user->is_dark_mode = 1;
  941. }
  942. $user->save();
  943. return $response->withJson([
  944. 'ret' => 1,
  945. 'msg' => '切换成功',
  946. ]);
  947. }
  948. }