352 lines
12 KiB
PHP
Executable File
352 lines
12 KiB
PHP
Executable File
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Controllers;
|
||
|
||
use App\Models\Ann;
|
||
use App\Models\Config;
|
||
use App\Models\LoginIp;
|
||
use App\Models\Node;
|
||
use App\Models\OnlineLog;
|
||
use App\Models\Huodong;
|
||
use App\Services\Auth;
|
||
use App\Services\Captcha;
|
||
use App\Services\Reward;
|
||
use App\Services\Subscribe;
|
||
use App\Services\Maps;
|
||
use App\Services\MFA;
|
||
use App\Utils\ResponseHelper;
|
||
use App\Utils\Tools;
|
||
use Exception;
|
||
use Psr\Http\Message\ResponseInterface;
|
||
use Slim\Http\Response;
|
||
use Slim\Http\ServerRequest;
|
||
use function str_replace;
|
||
use function strtotime;
|
||
use function time;
|
||
//use voku\helper\AntiXSS;
|
||
|
||
use App\Models\VipMap as ModelVipMap;
|
||
|
||
final class UserController extends BaseController
|
||
{
|
||
|
||
public function index(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
$captcha = [];
|
||
$class_expire_days = $this->user->class > 0 ?
|
||
round((strtotime($this->user->class_expire) - time()) / 86400) : 0;
|
||
|
||
$this->user->classExpireDay = max(0, $class_expire_days);
|
||
|
||
if (Config::obtain('enable_checkin_captcha')) {
|
||
$captcha = Captcha::generate();
|
||
}
|
||
|
||
$oAnn = Ann::where("sort", ">=", 1)->orderBy('date', 'desc')->first();
|
||
$oAnnLast = Ann::orderBy('date', 'desc')->first();
|
||
|
||
// $oHuodong = Huodong::DateHit();
|
||
|
||
// if ($oHuodong) {
|
||
// $sDateStartZh = date("n月j日", strtotime($oHuodong->start_date));
|
||
// $sDateEndZh = date("n月j日", strtotime($oHuodong->end_date));
|
||
//
|
||
// $sHuodongStr = '<span style="background-color: #eccafa;">'.$oHuodong->title.":".$sDateStartZh."至".$sDateEndZh."期间,".$oHuodong->content.'</span>';
|
||
//
|
||
// $oAnn->content = str_replace("{{huodong}}", $sHuodongStr, $oAnn->content);
|
||
//
|
||
// $oAnn->date = date("Y-m-d", strtotime($oAnn->date));
|
||
// } else {
|
||
// $oAnn->content = str_replace("<p>{{huodong}}</p>", '', $oAnn->content);
|
||
// }
|
||
|
||
$this->user->classStr = Maps::classStr($this->user->class);
|
||
$this->user->vipInfo = ModelVipMap::infoByAmount($this->user->total_pay);
|
||
|
||
return $response->write(
|
||
$this->view()
|
||
->assign('ann', $oAnn)
|
||
->assign('ann_last', $oAnnLast)
|
||
->assign('captcha', $captcha)
|
||
->assign('url_doc_base', $_ENV['url_doc_base'])
|
||
// ->assign('class_expire_days', $class_expire_days)
|
||
->assign('UniversalSub', Subscribe::getUniversalSubLink($this->user))
|
||
// ->assign('class', Maps::levelToClass($this->user->class))
|
||
->fetch('user/index.tpl')
|
||
);
|
||
}
|
||
|
||
public function panelOptionSave(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
$sMenuToggle = $this->antiXss->xss_clean($request->getParam('menuToggle') ?? '');
|
||
$sThemeMod = $this->antiXss->xss_clean($request->getParam('themeMod') ?? '');
|
||
$sThemeLight = $this->antiXss->xss_clean($request->getParam('themeLight') ?? '');
|
||
$sThemeDark = $this->antiXss->xss_clean($request->getParam('themeDark') ?? '');
|
||
|
||
$aPlanOption = [
|
||
'menuToggle' => $sMenuToggle,
|
||
'themeMod' => $sThemeMod,
|
||
'themeLight' => $sThemeLight,
|
||
'themeDark' => $sThemeDark,
|
||
];
|
||
|
||
$this->user->panel_option = $aPlanOption;
|
||
$this->user->save();
|
||
|
||
return $response->withJson([
|
||
'ret' => 1,
|
||
'msg' => '设置成功'
|
||
]);
|
||
}
|
||
|
||
public function panelMenuToggle(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
|
||
$sPanelMenuStatus = $this->user->panel_option['menuToggle'] ?? 'open';
|
||
|
||
if ($sPanelMenuStatus == "open") {
|
||
$sPanelMenuStatus = "close";
|
||
} else if ($sPanelMenuStatus == "close") {
|
||
$sPanelMenuStatus = "open";
|
||
}
|
||
|
||
$sPanelMenuOption = $this->user->panel_option;
|
||
$sPanelMenuOption['menuToggle'] = $sPanelMenuStatus;
|
||
|
||
$this->user->panel_option = $sPanelMenuOption;
|
||
$this->user->save();
|
||
|
||
return $response->withJson([
|
||
'ret' => 1,
|
||
'msg' => '设置成功'
|
||
]);
|
||
}
|
||
|
||
public function panelModToggle(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
|
||
$sPanelModValue = $this->antiXss->xss_clean($request->getParam('themeMod') ?? '');
|
||
|
||
if ($sPanelModValue == "light") {
|
||
$sPanelModValue = "dark";
|
||
} else if ($sPanelModValue == "dark") {
|
||
$sPanelModValue = "light";
|
||
}
|
||
|
||
$sPanelOption = $this->user->panel_option;
|
||
$sPanelOption['themeMod'] = $sPanelModValue;
|
||
|
||
$this->user->panel_option = $sPanelOption;
|
||
$this->user->save();
|
||
|
||
return $response->withJson([
|
||
'ret' => 1,
|
||
'msg' => '设置成功'
|
||
]);
|
||
}
|
||
|
||
// public function panelModToggle_old(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
// {
|
||
// $user = $this->user;
|
||
// $user->is_dark_mode = $user->is_dark_mode === 1 ? 0 : 1;
|
||
//
|
||
// if (! $user->save()) {
|
||
// return ResponseHelper::error($response, '切换失败');
|
||
// }
|
||
//
|
||
// return $response->withHeader('HX-Refresh', 'true')->withJson([
|
||
// 'ret' => 1,
|
||
// 'msg' => '切换成功',
|
||
// ]);
|
||
// }
|
||
|
||
// public function panelOptionGet(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
// {
|
||
// $oUserPanelOption = json_decode($this->user->panel_option);
|
||
//
|
||
// return $response->withJson([
|
||
// 'ret' => 1,
|
||
// 'msg' => '设置成功'
|
||
// ]);
|
||
// }
|
||
|
||
public function profile(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
// 登录IP
|
||
$logins = (new LoginIp())->where('userid', $this->user->id)
|
||
->where('type', '=', 0)->orderBy('datetime', 'desc')->take(10)->get();
|
||
$ips = (new OnlineLog())->where('user_id', $this->user->id)
|
||
->where('last_time', '>', time() - 300)->orderByDesc('last_time')->get(); // 90改300,最近5分钟登录ip
|
||
|
||
foreach ($logins as $login) {
|
||
$login->datetime = Tools::toDateTime((int) $login->datetime);
|
||
|
||
try {
|
||
$login->location = Tools::getIpLocation($login->ip);
|
||
} catch (Exception) {
|
||
$login->location = '未知';
|
||
}
|
||
}
|
||
|
||
foreach ($ips as $ip) {
|
||
$ip->ip = str_replace('::ffff:', '', $ip->ip);
|
||
$ip->location = Tools::getIpLocation($ip->ip);
|
||
$ip->node_name = (new Node())->where('id', $ip->node_id)->first()->name;
|
||
$ip->last_time = Tools::toDateTime((int) $ip->last_time);
|
||
}
|
||
|
||
$ga_url = MFA::getGaUrl($this->user);
|
||
|
||
$this->user->vipInfo = ModelVipMap::infoByAmount($this->user->total_pay);
|
||
$this->user->gb = Tools::flowToGB($this->user->transfer_total);
|
||
|
||
return $response->write(
|
||
$this->view()
|
||
->assign('logins', $logins)
|
||
->assign('ips', $ips)
|
||
->assign('ga_url', $ga_url)
|
||
->fetch('user/profile.tpl')
|
||
);
|
||
}
|
||
|
||
public function announcement(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
$this->user->ann_last_time = time();
|
||
$this->user->save();
|
||
|
||
$anns = (new Ann())->where("status", 1)->orderBy('date', 'desc')->get();
|
||
|
||
// cmd端需要做验证,不然传错就bug了
|
||
$aMapIcon = [
|
||
"none" => "fa-volume-up",
|
||
"success" => "fa-tag",
|
||
"warning" => "fa-info",
|
||
"danger" => "fa-info"
|
||
];
|
||
|
||
return $response->write(
|
||
$this->view()
|
||
->assign('anns', $anns)
|
||
->assign('aMapIcon', $aMapIcon)
|
||
->fetch('user/announcement.tpl')
|
||
);
|
||
}
|
||
|
||
public function notifi(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
$bNotifiHas = false;
|
||
$aNotifi = [];
|
||
|
||
$sAnnDate = (new Ann())->orderBy('date', 'desc')->first()?->date;
|
||
$sAnnTime = strtotime($sAnnDate);
|
||
|
||
if ($sAnnTime > $this->user->ann_last_time) {
|
||
$aNotifi[] = [
|
||
"title" => "有新公告。",
|
||
"date" => $sAnnDate,
|
||
"icon" => "fa-code",
|
||
"url" => "/user/announcement",
|
||
];
|
||
}
|
||
|
||
$iClassShengyuTime = strtotime($this->user->class_expire) - time();
|
||
$iClassShengyuDay = $iClassShengyuTime <= 0 ? 0 : ceil($iClassShengyuTime / 86400);
|
||
|
||
if ($iClassShengyuDay <= 0) {
|
||
$aNotifi[] = [
|
||
"title" => "您的套餐已过期,请套餐商店购买新套餐。",
|
||
"date" => $this->user->class_expire,
|
||
"icon" => "fa-exclamation-triangle",
|
||
"url" => "/user/shop",
|
||
];
|
||
} else if ($iClassShengyuDay <= 10) {
|
||
$aNotifi[] = [
|
||
"title" => "您的套餐将在 ".$iClassShengyuDay." 天后过期,请及时续订。",
|
||
"date" => date("Y-m-d")." 00:00:05",
|
||
"icon" => "fa-exclamation-triangle",
|
||
"url" => "/user/plan",
|
||
];
|
||
}
|
||
|
||
if (count($aNotifi) > 0) {
|
||
$bNotifiHas = true;
|
||
}
|
||
|
||
$sNotifiView = $this->view()
|
||
->assign('aNotifiList', $aNotifi)
|
||
->fetch('user/notifi/ajax_notifi.tpl');
|
||
|
||
return $response->withJson([
|
||
'ret' => 1,
|
||
'msg' => 'ok',
|
||
'bNotifiHas' => $bNotifiHas,
|
||
'sNotifiView' => $sNotifiView,
|
||
]);
|
||
|
||
}
|
||
|
||
public function autorenew(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
$this->user->autorenew ^= 1;
|
||
$this->user->save();
|
||
|
||
return $response->withJson([
|
||
'ret' => 1,
|
||
'msg' => 'ok',
|
||
'value' => $this->user->autorenew,
|
||
]);
|
||
}
|
||
|
||
public function checkin(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
if (! Config::obtain('enable_checkin') || ! $this->user->isAbleToCheckin()) {
|
||
return ResponseHelper::error($response, '暂时还不能签到');
|
||
}
|
||
|
||
if (Config::obtain('enable_checkin_captcha')) {
|
||
$ret = Captcha::verify($request->getParams());
|
||
|
||
if (! $ret) {
|
||
return ResponseHelper::error($response, '系统无法接受你的验证结果,请刷新页面后重试');
|
||
}
|
||
}
|
||
|
||
$traffic = Reward::issueCheckinReward($this->user->id);
|
||
|
||
if (! $traffic) {
|
||
return ResponseHelper::error($response, '签到失败');
|
||
}
|
||
|
||
return $response->withJson([
|
||
'ret' => 1,
|
||
'msg' => '获得了 ' . $traffic . 'MB 流量',
|
||
'data' => [
|
||
'last-checkin-time' => Tools::toDateTime(time()),
|
||
],
|
||
]);
|
||
}
|
||
|
||
/**
|
||
* @throws Exception
|
||
*/
|
||
public function banned(ServerRequest $request, Response $response, array $args): ResponseInterface
|
||
{
|
||
$user = $this->user;
|
||
|
||
return $response->write(
|
||
$this->view()
|
||
->assign('banned_reason', $user->banned_reason)
|
||
->fetch('user/banned.tpl')
|
||
);
|
||
}
|
||
|
||
public function logout(ServerRequest $request, Response $response, array $args): Response
|
||
{
|
||
Auth::logout();
|
||
|
||
return $response->withStatus(302)->withHeader('Location', '/');
|
||
}
|
||
}
|