diff --git a/public/index.php b/public/index.php index 7ffb10f0..484b59f1 100755 --- a/public/index.php +++ b/public/index.php @@ -21,6 +21,16 @@ use GuzzleHttp\Psr7\ServerRequest; use Slim\Factory\AppFactory; use Slim\Http\Factory\DecoratedResponseFactory; +function tomd($d, $type = 0) +{ + echo "
";
+ var_dump($d);
+
+ if ($type) {
+ exit;
+ }
+}
+
Boot::setTime();
Boot::bootSentry();
Boot::bootDb();
diff --git a/public/tests/hook.php b/public/tests/hook.php
index bf28a14d..9e1b52df 100644
--- a/public/tests/hook.php
+++ b/public/tests/hook.php
@@ -35,10 +35,36 @@ $oHttp->aData = [
'type' => 'private'
],
'date' => 1610000000,
- "text" => "\/ry 你好,网站是正常运行的。用不了一般是没配置对,调试调试。",
+ "text" => "\/tk#find 2",
]
];
+$oHttp->aData['message']['text'] = '\/tk#find 1';
+$oHttp->aData['message']['text'] = '\/node#like__id 1';
+$oHttp->aData['message']['text'] = '\/node#set__12__name jjjjjkkkk';
+$oHttp->aData['message']['text'] = '\/zf#list';
+$oHttp->aData['message']['text'] = '\/duck#list';
+$oHttp->aData['message']['text'] = '\/zf#reset__youshi 2028-01-01';
+$oHttp->aData['message']['text'] = '\/zf#set__youshi__use_width 3#tb';
+$oHttp->aData['message']['text'] = '\/duck#set__us01__use_width 1#tb';
+$oHttp->aData['message']['text'] = '\/zf#del haha';
+$oHttp->aData['message']['text'] = '\/node#del 25';
+$oHttp->aData['message']['text'] = '\/duck#del hk02';
+$oHttp->aData['message']['text'] = '\/zf#add hk0222';
+$oHttp->aData['message']['text'] = '\/duck#find hk01';
+$oHttp->aData['message']['text'] = '\/duck#add uuu';
+$oHttp->aData['message']['text'] = '\/node#list';
+$oHttp->aData['message']['text'] = '\/order#groupBySaleCode 365'; // 默认1=24小时
+$oHttp->aData['message']['text'] = '\/user#report__day__300';
+$oHttp->aData['message']['text'] = '\/user#report__date__2025-01-01';
+$oHttp->aData['message']['text'] = '\/user#report__date__2022-01-01__2029-01-01';
+$oHttp->aData['message']['text'] = '\/node#clone 24';
+$oHttp->aData['message']['text'] = '\/tk#ry__1 ajsdklfjalksjdlkf';
+$oHttp->aData['message']['text'] = '\/tk#find 1';
+$oHttp->aData['message']['text'] = '\/user#find 1';
+
+$oHttp->aData['message']['text'] = '\/cmd#list';
+
//{
// "update_id": 761180998,
// "message": {
diff --git a/src/Controllers/TestController.php b/src/Controllers/TestController.php
index bb786f94..d15516f3 100755
--- a/src/Controllers/TestController.php
+++ b/src/Controllers/TestController.php
@@ -29,7 +29,7 @@ final class TestController extends BaseController
{
$jobs = new CronService();
- $jobs->mergeBandWidth();
+ $jobs->userCount();
// $jobs->reportBandWidth();
diff --git a/src/Controllers/TomApi/Tg/HookController.php b/src/Controllers/TomApi/Tg/HookController.php
index c9515cbb..125b3ae5 100755
--- a/src/Controllers/TomApi/Tg/HookController.php
+++ b/src/Controllers/TomApi/Tg/HookController.php
@@ -20,905 +20,115 @@ use Slim\Http\Response;
use Slim\Http\ServerRequest;
use App\Utils\Tools;
-use App\Services\TomTool\Http;
+use App\Services\TomTool\Http as Http;
+use App\Services\Tg\Http as TGHttp;
final class HookController
{
- public $sApiToken;
- public $sApiChatId;
+ public function __construct()
+ {
+
+ }
+
public function cmd()
{
- $oTgStep = new TgStep();
- $this->sApiToken = Config::obtain('telegram_token');
- $this->sApiChatId = Config::obtain('telegram_chatid');
-
- $sUpdate = file_get_contents("php://input");
-
- $aUpdate = json_decode($sUpdate, true);
-
- @file_put_contents('/www/_tg/bot_log.txt', json_encode($aUpdate, JSON_PRETTY_PRINT));
-
- $aData['chatId'] = $aUpdate["message"]["chat"]["id"];
- $aData['fromId'] = $aUpdate["message"]["from"]["id"];
-
- if (!isset($aUpdate["message"]["text"])) {
- http_response_code(200);
- echo "not have text";
- exit;
- }
-
- $sText = $aUpdate["message"]["text"];
-
- // 先检查step
- if (strpos($sText, "/s ") === 0 && $oTgStep->fromIdHit($aData['fromId'])) {
+ try {
- $sText = ltrim($sText, '/s');
- $sText = trim($sText);
+ $oTGHttp = new TGHttp();
+// $oTGHttp->sApiToken = env('telegram_token');
+// $oTGHttp->sApiChatId = env('telegram_chatid');
- $aTgStepFirst = $oTgStep->find($aData["fromId"]);
+ $sUpdate = file_get_contents("php://input");
- if ($aTgStepFirst["cmd"] == "reply") {
+ $aUpdate = json_decode($sUpdate, true);
+
+ @file_put_contents('/www/_tg/bot_log.txt', json_encode($aUpdate, JSON_PRETTY_PRINT));
+
+ $aData['chatId'] = $aUpdate["message"]["chat"]["id"];
+ $aData['fromId'] = $aUpdate["message"]["from"]["id"];
+
+ if (!isset($aUpdate["message"]["text"])) {
+ throw new \Exception("?");
+ }
+
+ $sText = $aUpdate["message"]["text"];
+
+ // test
+// $sText = "\\//Article#List ni__aaa__bbb 111 222";
+// $sText = "///\\\SaleCode#SetRate__zzxx 2";
+// $sText = "///\\\SaleCode#List";
+// $sText = "///\\\SaleCode#Find zzxx";
+// $sText = "/Article#Like__sale_code zzx";
+// $sText = "////Article#Add jxxjjjj";
+// $sText = "//\\\//Article#Del 9";
+// $sText = "/Article#Set__1__user_name xxx";
+
+ @$aArg = explode(" ", $sText);
+ @$aOption = explode("__", $aArg[0]);
+
+ $sCmd = $this->cleanCmd($aOption[0]);
+
+ list($sClass, $sFunc) = explode("#", $sCmd);
+ $sClass = ucfirst($sClass);
+ $sFunc = ucfirst($sFunc);
+
+ unset($aOption[0]);
+ unset($aArg[0]);
+
+ $aParams['aOption'] = $aOption;
+ $aParams['aArg'] = $aArg;
+ $aParams['aUpdate'] = $aUpdate;
+ $aParams['aOther'] = [
+ 'chatId' => $aData['chatId'],
+ 'fromId' => $aData['fromId']
+ ];
+
+ $sClassPath = "App\\Services\\Tg\\Hook\\Mod\\".$sClass;
+
+// tomd($sFunc);
+// tomd($sClassPath, 1);
+
+ if (method_exists($sClassPath, $sFunc)) {
+ $oInstans = new $sClassPath();
+ $r = $oInstans->$sFunc($aParams);
- if ($aTgStepFirst['step'] == 1) {
- $oHttp = new Http();
-
- $oHttp->sMethod = "put";
- $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/ticket/".$aTgStepFirst['cache']['ticketId'];
- $oHttp->bIsJson = true;
- $aData['comment'] = $sText;
- $aData['admin_name'] = $aUpdate["message"]["from"]["first_name"];
- $oHttp->aData = $aData;
-
- $r = @json_decode($oHttp->send(), true);
-
- // 不论失败成功都清除step
- $oTgStep->clearByFromId($aUpdate["message"]["from"]["id"]);
-
- if ($r["ret"] == 1) {
- $sMessage = "成功";
+ // 可以不返回,里面直接send
+ if (isset($r)) {
+ if (empty($r)) { $r = 'hook的mod返回空'; }
+ // 返回可以是数组
+ if (is_array($r)) {
+ foreach ($r as $row) {
+ $oTGHttp->sendToTG($row);
+ }
} else {
- $sMessage = "失败";
- Http::response(500, json_encode($aData));
+ $oTGHttp->sendToTG($r);
}
- $this->sendMessage($sMessage);
-
Http::response(200, 'ok');
}
- }
-
- }
-
- // 打断
- if ($sText === "/break") {
-
- $oTgStep->clearByFromId($aData["fromId"]);
-
- $this->sendMessage("ok");
-
- http_response_code(200);exit;
- }
-
- // 命令列表
- // /cmdList
- if (strpos($sText, '/cmdList') === 0 || strpos($sText, '\/cmdList') === 0) {
-
- $aCmdList = [
- '流量报告' => 'reportWidth',
- '查找用户' => 'userFind 11',
- '查找订单' => 'orderFindByUser 11',
- '回复工单' => 'reply 11 + s 你好',
- '快捷回单' => 'ry 11 你好',
- '工单查找' => 'ticketFind 11',
- '用户报表' => 'reportUser_day_7 && reportUser_date_2025-02-02 && reportUser_date_2025-02-02_2025-03-03',
- 'duck添加&转发' => 'duckAdd jp02',
- 'duck删除&转发' => 'duckDel jp02',
- 'duck修改&转发' => 'duckOption|max_width|jp01 1.66#tb',
- 'duck列表&转发' => 'duckList',
- 'duck查找' => 'duckFind jp02',
- '转发重置' => 'zhuanfaReset-youshi 2025-02-02',
- 'node修改' => 'nodeOption#name#11 haha',
- '节点like' => 'nodeLike#duck jp02',
- 'node删除' => 'nodeDel 18',
- 'node复制' => 'nodeCopy 18',
- '节点列表简洁'=> 'nodeList',
- ];
-
- $this->sendMessage(json_encode($aCmdList, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
-
- Http::response(200, 'ok');
-
- }
-
- // 流量报告
- // /reportWidth
- if (strpos($sText, '/reportWidth') === 0 || strpos($sText, '\/reportWidth') === 0) {
-
- $jobs = new \App\Services\Cron();
-
- $jobs->reportBandWidth();
-
- Http::response(200, 'ok');
-
- }
-
- // 查找用户
- // /userFind 11
- if (strpos($sText, '/userFind') === 0 || strpos($sText, '\/userFind') === 0) {
-
- list(, $iUserId) = explode(" ", $sText, 2);
-
- $oUser = User::find($iUserId);
-
- if ($oUser) {
- $aUser = $oUser->toArray();
- unset($aUser['pass']);
- unset($aUser['passwd']);
- unset($aUser['uuid']);
- unset($aUser['method']);
- unset($aUser['is_admin']);
- unset($aUser['theme']);
- unset($aUser['ga_token']);
- unset($aUser['ga_enable']);
- unset($aUser['api_token']);
- unset($aUser['is_dark_mode']);
- unset($aUser['locale']);
-
- $aUser['transfer_today'] = Tools::flowToGB($aUser['transfer_today']).'GB';
- $aUser['transfer_total'] = Tools::flowToGB($aUser['transfer_total']).'GB';
- $aUser['transfer_enable'] = Tools::flowToGB($aUser['transfer_enable']).'GB';
- $aUser['last_use_time'] = date('Y-m-d H:i:s', $aUser['last_use_time']);
} else {
- $aUser = ["not have id" => $iUserId];
+ throw new \Exception("没有这个方法:".$sClass.'#'.$sFunc);
}
- $this->sendMessage(json_encode($aUser, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+ } catch (\Throwable $e) {
+ $sMessage = "错误(line:".$e->getLine()."): " . $e->getMessage();
- Http::response(200, 'ok');
+ $oTGHttp->sendToTG($sMessage);
+ Http::response(200, 'error');
}
-
- // 查找订单
- // orderFindByUser 11
- if (strpos($sText, '/orderFindByUser') === 0 || strpos($sText, '\/orderFindByUser') === 0) {
-
- list(, $iUserId) = explode(" ", $sText, 2);
-
- $aOrder = Order::where("user_id", $iUserId)->get()->toArray();
-
- if ($aOrder) {
- $aOrderNew = [];
- foreach ($aOrder as $k => $v) {
- $v['create_time'] = date("Y-m-d H:i:m", $v['create_time']);
- $v['update_time'] = date("Y-m-d H:i:m", $v['update_time']);
- $v['product_content'] = json_decode($v['product_content']);
- $aOrderNew[] = $v;
- }
- } else {
- $aOrderNew = ["not have id" => $iUserId];
- }
-
- $this->sendMessage(json_encode($aOrderNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
-
- Http::response(200, 'ok');
-
- }
-
- // 回复工单
- // /reply 11 + /s 你好
- if (strpos($sText, '/reply') === 0) {
-
- // 先清除一遍,只进行一个进程
- $oTgStep->clearByFromId($aData["fromId"]);
-
- $iTicketId = str_replace('/reply', '', $sText);
- $iTicketId = (int) trim($iTicketId);
-
- $oTgStep->add($aData['fromId'], 'reply', 1, ["ticketId" => $iTicketId]);
-
- $sMessage = "将回复工单【".$iTicketId."】,请输入回复内容。";
-
- $this->sendMessage($sMessage);
-
- Http::response(200, 'ok');
-
- }
-
- // 快捷回复工单
- // /ry 11 你好
- if (strpos($sText, '/ry') === 0 || strpos($sText, '\/ry') === 0) {
-
- try {
- $sText = $this->trimText($sText, '/ry');
-
- list($iTicketId, $sText) = explode(" ", $sText, 2);
-
- $oHttp = new Http();
-
- $oHttp->sMethod = "put";
- $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/ticket/".$iTicketId;
- $oHttp->bIsJson = true;
- $aData['comment'] = $sText;
- $aData['admin_name'] = $aUpdate["message"]["from"]["first_name"];
- $oHttp->aData = $aData;
-
- $r = @json_decode($oHttp->send(), true);
-
- // 不论失败成功都清除 step
- $oTgStep->clearByFromId($aUpdate["message"]["from"]["id"]);
-
- if ($r["ret"] == 1) {
- $sMessage = "成功";
- } else {
- $sMessage = "失败";
- Http::response(200, json_encode($aData));
- }
-
- $this->sendMessage($sMessage);
-
- Http::response(200, 'ok');
-
- } catch (Exception $e) {
-
- $sMessage = "发生错误: " . $e->getMessage();
-
- $this->sendMessage($sMessage);
-
- Http::response(200, '内部服务器错误');
-
- }
-
- }
-
- // 复制节点
- // /nodeCopy 11
- if (strpos($sText, '/nodeCopy') === 0 || strpos($sText, '\/nodeCopy') === 0) {
-
- list(, $iNodeId) = explode(" ", $sText, 2);
-
- $oHttp = new Http();
-
- $oHttp->sMethod = "post";
- $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/node/".$iNodeId."/copy";
- $oHttp->bIsJson = true;
- $oHttp->aData = $aData;
-
- $r = @json_decode($oHttp->send(), true);
-
- if ($r["ret"] == 1) {
- $sMessage = "成功";
- } else {
- $sMessage = "失败";
- Http::response(500, json_encode($aData));
- }
-
- $this->sendMessage($sMessage);
-
- Http::response(200, 'ok');
-
- }
-
- // 用户报表
- // /reportUser_day_7 && /reportUser_date_2025-02-02 && /reportUser_date_2025-02-02_2025-03-03
- if (strpos($sText, '/reportUser') === 0 || strpos($sText, '\/reportUser') === 0) {
-
- @list(, $sOption1, $sOption2, $sOption3) = explode("_", $sText, 4);
-
- $sMsg = '?';
-
- if ($sOption1 == 'day') {
-
- $sMsg = (new ServiceTgReportUser())->ByDay($sOption2);
-
- }
-
- if ($sOption1 == 'date') {
- $sMsg = (new ServiceTgReportUser())->ByDate($sOption2, $sOption3);
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 优惠卷报表
- // /reportCoupon#7
- if (strpos($sText, '/reportCoupon') === 0 || strpos($sText, '\/reportCoupon') === 0) {
- try {
- @list($sCmd, $iDay) = explode("#", $sText, 2);
-
- // 确保 $iDay 是一个有效的数字
- if (!is_numeric($iDay) || $iDay < 0) {
- $this->sendMessage('无效的天数参数');
- Http::response(200, '内部服务器错误');
- }
-
- $sStartTime = strtotime("-$iDay days");
-
- $aOrderList = Order::where('update_time', '>=', $sStartTime)
- ->whereIn('status', ['activated', 'pending_activation']) // 添加状态条件
- ->select('coupon',
- \App\Services\DB::raw('count(*) as total'),
- \App\Services\DB::raw('SUM(price) as total_price'))
- ->groupBy('coupon')
- ->get()
- ->toArray();
-
- $sMsg = '从 '.date("Y-m-d H:i:s", $sStartTime);
- foreach ($aOrderList as $row) {
- $coupon = str_replace('.', '#', $row['coupon']);
- if (!$coupon) {
- $coupon = '无';
- }
- $sMsg .= "\n\n";
- $sMsg .= $coupon . ' - ' . $row['total_price'] . ' / ' . $row['total'];
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
- } catch (Exception $e) {
- // 处理异常
- $errorMsg = '发生错误: ' . $e->getMessage();
- $this->sendMessage($errorMsg);
-
- // 返回错误响应
- Http::response(200, '内部服务器错误');
- }
- }
-
-
- // 节点列表(简洁)
- // /nodeList
- if (strpos($sText, '/nodeList') === 0 || strpos($sText, '\/nodeList') === 0) {
-
- $aNodeList = Node::where('type', 1)->orderBy('name', 'asc')->get()->toArray();
-
- $sMsg = '';
- foreach ($aNodeList as $row) {
- $sMsg .= "\n\n";
- $sMsg .= $row['name'].', id:'.$row['id'].', duck:'.$row['duck_code'].', zf:'.$row['zhuanfa_code'].', sort:'.$row['sort'];
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 添加duck
- // /duckAdd jp01
- if (strpos($sText, '/duckAdd') === 0 || strpos($sText, '\/duckAdd') === 0) {
-
- list($sCmd, $sCode) = explode(" ", $sText, 2);
-
- try {
- $oDucks = new Ducks();
- $oDucks->code = $sCode;
-
- if ($oDucks->save()) {
- $sMsg = "成功";
- } else {
- $sMsg = "失败";
- }
- } catch (\Exception $e) {
- $sMsg = json_encode($e->getMessage());
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 查找duck
- // /duckFind jp01
- if (strpos($sText, '/duckFind') === 0 || strpos($sText, '\/duckFind') === 0) {
-
- list($sCmd, $sCode) = explode(" ", $sText, 2);
-
- $aData = Ducks::where('code', $sCode)->first()->toArray();
-
- $aData['use_width'] = Tools::flowToGB($aData['use_width']).'GB';
- $aData['max_width'] = Tools::flowToGB($aData['max_width']).'GB';
- $aData['today_width'] = Tools::flowToGB($aData['today_width']).'GB';
-
- $this->sendMessage(json_encode($aData, JSON_PRETTY_PRINT));
-
- Http::response(200, 'ok');
-
- }
-
- // 添加zhuanfa
- // /zhuanfaAdd jp01
- if (strpos($sText, '/zhuanfaAdd') === 0 || strpos($sText, '\/zhuanfaAdd') === 0) {
-
- list($sCmd, $sCode) = explode(" ", $sText, 2);
-
- try {
- $oZhuanfas = new Zhuanfas();
- $oZhuanfas->code = $sCode;
-
- if ($oZhuanfas->save()) {
- $sMsg = "成功";
- } else {
- $sMsg = "失败";
- }
- } catch (\Exception $e) {
- $sMsg = json_encode($e->getMessage());
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 删除duck
- // /duckDel jp01
- if (strpos($sText, '/duckDel') === 0 || strpos($sText, '\/duckDel') === 0) {
-
- list($sCmd, $sCode) = explode(" ", $sText, 2);
-
- try {
- $oDucks = Ducks::where("code", $sCode)->first();
-
- if ($oDucks) {
- // 尝试删除记录
- $deleted = $oDucks->delete();
-
- if ($deleted) {
- // 删除成功
- $sMsg = "成功";
- } else {
- // 删除失败
- $sMsg = "失败";
- }
- } else {
- // 找不到记录
- $sMsg = "找不到记录";
- }
- } catch (\Exception $e) {
- // 捕获异常并返回错误信息
- $sMsg = json_encode($e->getMessage());
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 删除node
- // /duckDel jp01
- if (strpos($sText, '/nodeDel') === 0 || strpos($sText, '\/nodeDel') === 0) {
-
- list($sCmd, $iId) = explode(" ", $sText, 2);
-
- $sMsg = '?';
-
- try {
- $oNode = Node::where("id", $iId)->first();
-
- if ($oNode) {
- // 尝试删除记录
- $deleted = $oNode->delete();
-
- if ($deleted) {
- // 删除成功
- $sMsg = "成功";
- } else {
- // 删除失败
- $sMsg = "失败";
- }
- } else {
- // 找不到记录
- $sMsg = "找不到记录";
- }
- } catch (\Exception $e) {
- // 捕获异常并返回错误信息
- $sMsg = json_encode($e->getMessage());
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 删除zhuanfa
- // /zhuanfaDel jp01
- if (strpos($sText, '/zhuanfaDel') === 0 || strpos($sText, '\/zhuanfaDel') === 0) {
-
- list($sCmd, $sCode) = explode(" ", $sText, 2);
-
- try {
- $oZhuanfas = Zhuanfas::where("code", $sCode)->first();
-
- if ($oZhuanfas) {
- // 尝试删除记录
- $deleted = $oZhuanfas->delete();
-
- if ($deleted) {
- // 删除成功
- $sMsg = "成功";
- } else {
- // 删除失败
- $sMsg = "失败";
- }
- } else {
- // 找不到记录
- $sMsg = "找不到记录";
- }
- } catch (\Exception $e) {
- // 捕获异常并返回错误信息
- $sMsg = json_encode($e->getMessage());
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 修改duck
- // /duckOption@end_date@jp01 2025_02_02
- // /duckOption@max_width@jp01 1.66#tb
- if (strpos($sText, '/duckOption') === 0 || strpos($sText, '\/duckOption') === 0) {
-
- list($sCmd, $sSet) = explode(" ", $sText, 2);
- list(, $sField, $sCode) = explode("#", $sCmd, 3);
-
- if ($sSet) {
- @list($iWidth, $sWidthType) = explode("|", $sSet, 2);
- } else {
- $sMsg = "没有参数";
- }
-
-
- if ($sWidthType == 'tb') {
- $sSet = Tools::tomTbToB($iWidth);
- }
-
- if ($sWidthType == 'gb') {
- $sSet = Tools::tomGbToB($iWidth);
- }
-
- $sMsg = '?';
- try {
-
- $oDuck = Ducks::where('code', $sCode)->first();
-
- if (!$oDuck) {
- $sMsg = "没有这个code";
- } else {
- $oDuck->$sField = $sSet;
- if ($oDuck->save()) {
- $sMsg = "成功"; // 保存成功
- } else {
- $sMsg = "失败"; // 保存失败
- }
- }
-
- } catch (\Illuminate\Database\QueryException $e) {
-
- $sMsg = json_encode($e->getMessage());
-
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 修改zhuanfa
- // /zhuanfaOption-end_date-jp01 2025_02_02
- // /zhuanfaOption-max_width-jp01 1.66#tb
- if (strpos($sText, '/zhuanfaOption') === 0 || strpos($sText, '\/zhuanfaOption') === 0) {
-
- list($sCmd, $sSet) = explode(" ", $sText, 2);
- list(, $sField, $sCode) = explode("-", $sCmd, 3);
- @list($iWidth, $sWidthType) = explode("#", $sSet, 2);
-
- if ($sWidthType == 'tb') {
- $sSet = Tools::tomTbToB($iWidth);
- }
-
- if ($sWidthType == 'gb') {
- $sSet = Tools::tomGbToB($iWidth);
- }
-
- $sMsg = '?';
- try {
-
- $oZhuanfas = Zhuanfas::where('code', $sCode)->first();
-
- if (!$oZhuanfas) {
- $sMsg = "没有这个code";
- } else {
- $oZhuanfas->$sField = $sSet;
- if ($oZhuanfas->save()) {
- $sMsg = "成功"; // 保存成功
- } else {
- $sMsg = "失败"; // 保存失败
- }
- }
-
- } catch (\Illuminate\Database\QueryException $e) {
-
- $sMsg = json_encode($e->getMessage());
-
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 转发重置
- // /zhuanfaReset-youshi 2025-02-02
- if (strpos($sText, '/zhuanfaReset') === 0 || strpos($sText, '\/zhuanfaReset') === 0) {
-
- list($sCmd, $sDate) = explode(" ", $sText, 2);
- list(, $sCode) = explode("-", $sCmd, 2);
-
- $sMsg = '?';
- try {
-
- $oZhuanfas = Zhuanfas::where('code', $sCode)->first();
-
- if (!$oZhuanfas) {
- $sMsg = "没有这个code";
- } else {
- $oZhuanfas->use_width = 0;
- $oZhuanfas->end_date = $sDate;
- if ($oZhuanfas->save()) {
- $sMsg = "成功"; // 保存成功
- } else {
- $sMsg = "失败"; // 保存失败
- }
- }
-
- } catch (\Illuminate\Database\QueryException $e) {
-
- $sMsg = json_encode($e->getMessage());
-
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // duck list
- // /duckList
- if (strpos($sText, '/duckList') === 0 || strpos($sText, '\/duckList') === 0) {
-
- $aDuckList = Ducks::orderBy('code')->get()->toArray();
-
- $aMsgData = [];
- foreach ($aDuckList as $k => $v) {
- $v['use_width'] = Tools::flowToGB($v['use_width']).'g';
- $v['max_width'] = Tools::flowToGB($v['max_width']).'g';
- $v['today_width'] = Tools::flowToGB($v['today_width']).'g';
- $aMsgData[] = $v;
- }
-
- $this->sendMessage(json_encode($aMsgData, JSON_PRETTY_PRINT));
-
- Http::response(200, 'ok');
-
- }
-
- // zhuanfa list
- // /zhuanfaList
- if (strpos($sText, '/zhuanfaList') === 0 || strpos($sText, '\/zhuanfaList') === 0) {
-
- $aZhuanfaList = Zhuanfas::orderBy('code')->get()->toArray();
-
- $aMsgData = [];
- foreach ($aZhuanfaList as $k => $v) {
- $v['use_width'] = Tools::flowToTB($v['use_width'])."t";
- $v['max_width'] = Tools::flowToTB($v['max_width']).'t';
- $v['today_width'] = Tools::flowToGB($v['today_width']).'g';
- $aMsgData[] = $v;
- }
-
- $this->sendMessage(json_encode($aMsgData, JSON_PRETTY_PRINT));
-
- Http::response(200, 'ok');
-
- }
-
- // 节点设置变更
- // /nodeOption@name@1 haha
- if (strpos($sText, '/nodeOption') === 0 || strpos($sText, '\/nodeOption') === 0) {
-
- list($sCmd, $sSet) = explode(" ", $sText, 2);
-
- list(, $sField, $iNodeId) = explode("#", $sCmd, 3);
-
- switch ($sField) {
- case "config":
- $sField = "custom_config";
- break;
- case "duck":
- $sField = "duck_code";
- break;
- case "zhuanfa":
- $sField = "zhuanfa_code";
- break;
- default:
- $sField = $sField;
- break;
- }
-
- $sMsg = '?';
- try {
-
- $oNode = Node::find($iNodeId);
-
- if (!$oNode) {
- $sMsg = "没有这个id";
- } else {
- $oNode->$sField = $sSet;
- $oNode->save();
-
- $sMsg = "ok";
- }
-
- } catch (\Illuminate\Database\QueryException $e) {
-
- $sMsg = "数据库操作失败";
-
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 节点搜索
- // /nodeLike_duck_type1 jp02
- if (strpos($sText, '/nodeLike') === 0 || strpos($sText, '\/nodeLike') === 0) {
-
- @list($sCmd, $sLike) = explode(" ", $sText);
-
- @list(, $sField, $sMod) = explode("#", $sCmd, 3);
-
- switch ($sField) {
- case "port":
- $sField = "custom_config";
- break;
- case "config":
- $sField = "custom_config";
- break;
- case "duck":
- $sField = "duck_code";
- break;
- case "zhuanfa":
- $sField = "zhuanfa_code";
- break;
- default:
- $sField = $sField;
- break;
- }
-
- $sMsg = '?';
-
- try {
-
- $oNodeList = Node::where($sField, 'like', '%' . $sLike . '%');
-
- if ($sMod == 'type1') {
- $oNodeList->where('type', 1);
- }
-
- $aNodeList = $oNodeList->orderBy('type', 'desc')->orderBy('name', 'asc')->get()->toArray();
-
- } catch (\Illuminate\Database\QueryException $e) {
-
- $sMsg = '字段不存在';
-
- }
-
- if (empty($aNodeList)) {
-
- $sMsg = "没有";
-
- } else {
-
- $aNodeListNew = [];
- foreach ($aNodeList as $row) {
-
- $row['custom_config'] = json_decode($row['custom_config']);
- $row['dynamic_rate_config'] = json_decode($row['dynamic_rate_config']);
- $row['node_bandwidth_limit'] = Tools::flowToGB($row['node_bandwidth_limit']).'GB';
- $row['node_bandwidth'] = Tools::flowToGB($row['node_bandwidth']).'GB';
- $row['node_heartbeat'] = date('Y-m-d H:i:s', $row['node_heartbeat']);
- unset($row['is_dynamic_rate']);
- unset($row['dynamic_rate_type']);
- unset($row['dynamic_rate_config']);
- unset($row['bandwidthlimit_resetday']);
- unset($row['is_dynamic_rate']);
- unset($row['password']);
-
-// $aNodeListNew[] = $row;
-
- $sMsg = json_encode($row, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
-
- $this->sendMessage($sMsg);
- }
-
-// $sMsg = json_encode($aNodeListNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
- Http::response(200, 'ok');
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- // 工单查找
- // /ticketFind 11
- if (strpos($sText, '/ticketFind') === 0) {
-
- $iTicketId = $this->trimText($sText, '/ticketFind');
-
- $aTicket = Ticket::where("id", $iTicketId)->first()->toArray();
-
- $sMsg = "title:".$aTicket['title']."。\n";
-
- $aTicketContent = json_decode($aTicket['content'], true);
-
- if (!is_array($aTicketContent[0])) {
- $aTicketContent[] = $aTicketContent;
- }
-
- foreach ($aTicketContent as $row) {
- $sMsg .= "\n";
- $sMsg .= "name:".$row['commenter_name']."\n";
- $sMsg .= "comment:".$row['comment']."\n";
- }
-
- $this->sendMessage($sMsg);
-
- Http::response(200, 'ok');
-
- }
-
- Http::response(200, '无');
-
}
- private function trimText($sText, $sTrim)
- {
- $sText = ltrim($sText, $sTrim);
- $sText = trim($sText);
+ private function cleanCmd($input) {
- return $sText;
- }
-
- private function sendMessage($sText = '?') {
-
- if ($_ENV['is_loc'] === true) {
- echo "";
- var_dump($sText);
- } else {
- $url = "https://api.telegram.org/bot$this->sApiToken/sendMessage?chat_id=$this->sApiChatId&text=" . urlencode($sText);
- file_get_contents($url);
- }
+ $input = str_replace('\\', '', $input);
+ $input = str_replace('/', '', $input);
+ return $input;
}
}
diff --git a/src/Controllers/TomApi/Tg/HookController_back.php b/src/Controllers/TomApi/Tg/HookController_back.php
new file mode 100755
index 00000000..8841fb7c
--- /dev/null
+++ b/src/Controllers/TomApi/Tg/HookController_back.php
@@ -0,0 +1,924 @@
+sApiToken = Config::obtain('telegram_token');
+ $this->sApiChatId = Config::obtain('telegram_chatid');
+
+ $sUpdate = file_get_contents("php://input");
+
+ $aUpdate = json_decode($sUpdate, true);
+
+ @file_put_contents('/www/_tg/bot_log.txt', json_encode($aUpdate, JSON_PRETTY_PRINT));
+
+ $aData['chatId'] = $aUpdate["message"]["chat"]["id"];
+ $aData['fromId'] = $aUpdate["message"]["from"]["id"];
+
+ if (!isset($aUpdate["message"]["text"])) {
+ http_response_code(200);
+ echo "not have text";
+ exit;
+ }
+
+ $sText = $aUpdate["message"]["text"];
+
+ // 先检查step
+ if (strpos($sText, "/s ") === 0 && $oTgStep->fromIdHit($aData['fromId'])) {
+
+ $sText = ltrim($sText, '/s');
+ $sText = trim($sText);
+
+ $aTgStepFirst = $oTgStep->find($aData["fromId"]);
+
+ if ($aTgStepFirst["cmd"] == "reply") {
+
+ if ($aTgStepFirst['step'] == 1) {
+ $oHttp = new Http();
+
+ $oHttp->sMethod = "put";
+ $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/ticket/".$aTgStepFirst['cache']['ticketId'];
+ $oHttp->bIsJson = true;
+ $aData['comment'] = $sText;
+ $aData['admin_name'] = $aUpdate["message"]["from"]["first_name"];
+ $oHttp->aData = $aData;
+
+ $r = @json_decode($oHttp->send(), true);
+
+ // 不论失败成功都清除step
+ $oTgStep->clearByFromId($aUpdate["message"]["from"]["id"]);
+
+ if ($r["ret"] == 1) {
+ $sMessage = "成功";
+ } else {
+ $sMessage = "失败";
+ Http::response(500, json_encode($aData));
+ }
+
+ $this->sendMessage($sMessage);
+
+ Http::response(200, 'ok');
+ }
+
+ }
+
+ }
+
+ // 打断
+ if ($sText === "/break") {
+
+ $oTgStep->clearByFromId($aData["fromId"]);
+
+ $this->sendMessage("ok");
+
+ http_response_code(200);exit;
+ }
+
+ // 命令列表
+ // /cmdList
+ if (strpos($sText, '/cmdList') === 0 || strpos($sText, '\/cmdList') === 0) {
+
+ $aCmdList = [
+ '流量报告' => 'reportWidth',
+ '查找用户' => 'userFind 11',
+ '查找订单' => 'orderFindByUser 11',
+ '回复工单' => 'reply 11 + s 你好',
+ '快捷回单' => 'ry 11 你好',
+ '工单查找' => 'ticketFind 11',
+ '用户报表' => 'reportUser_day_7 && reportUser_date_2025-02-02 && reportUser_date_2025-02-02_2025-03-03',
+ 'duck添加&转发' => 'duckAdd jp02',
+ 'duck删除&转发' => 'duckDel jp02',
+ 'duck修改&转发' => 'duckOption|max_width|jp01 1.66#tb',
+ 'duck列表&转发' => 'duckList',
+ 'duck查找' => 'duckFind jp02',
+ '转发重置' => 'zhuanfaReset-youshi 2025-02-02',
+ 'node修改' => 'nodeOption#name#11 haha',
+ '节点like' => 'nodeLike#duck jp02',
+ 'node删除' => 'nodeDel 18',
+ 'node复制' => 'nodeCopy 18',
+ '节点列表简洁'=> 'nodeList',
+ ];
+
+ $this->sendMessage(json_encode($aCmdList, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+
+ Http::response(200, 'ok');
+
+ }
+
+ // 流量报告
+ // /reportWidth
+ if (strpos($sText, '/reportWidth') === 0 || strpos($sText, '\/reportWidth') === 0) {
+
+// $jobs = new \App\Services\Cron();
+//
+// $jobs->reportBandWidth();
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 查找用户
+ // /userFind 11
+ if (strpos($sText, '/userFind') === 0 || strpos($sText, '\/userFind') === 0) {
+
+// list(, $iUserId) = explode(" ", $sText, 2);
+//
+// $oUser = User::find($iUserId);
+//
+// if ($oUser) {
+// $aUser = $oUser->toArray();
+// unset($aUser['pass']);
+// unset($aUser['passwd']);
+// unset($aUser['uuid']);
+// unset($aUser['method']);
+// unset($aUser['is_admin']);
+// unset($aUser['theme']);
+// unset($aUser['ga_token']);
+// unset($aUser['ga_enable']);
+// unset($aUser['api_token']);
+// unset($aUser['is_dark_mode']);
+// unset($aUser['locale']);
+//
+// $aUser['transfer_today'] = Tools::flowToGB($aUser['transfer_today']).'GB';
+// $aUser['transfer_total'] = Tools::flowToGB($aUser['transfer_total']).'GB';
+// $aUser['transfer_enable'] = Tools::flowToGB($aUser['transfer_enable']).'GB';
+// $aUser['last_use_time'] = date('Y-m-d H:i:s', $aUser['last_use_time']);
+// } else {
+// $aUser = ["not have id" => $iUserId];
+// }
+//
+// $this->sendMessage(json_encode($aUser, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 查找订单
+ // orderFindByUser 11
+ if (strpos($sText, '/orderFindByUser') === 0 || strpos($sText, '\/orderFindByUser') === 0) {
+
+// list(, $iUserId) = explode(" ", $sText, 2);
+//
+// $aOrder = Order::where("user_id", $iUserId)->get()->toArray();
+//
+// if ($aOrder) {
+// $aOrderNew = [];
+// foreach ($aOrder as $k => $v) {
+// $v['create_time'] = date("Y-m-d H:i:m", $v['create_time']);
+// $v['update_time'] = date("Y-m-d H:i:m", $v['update_time']);
+// $v['product_content'] = json_decode($v['product_content']);
+// $aOrderNew[] = $v;
+// }
+// } else {
+// $aOrderNew = ["not have id" => $iUserId];
+// }
+//
+// $this->sendMessage(json_encode($aOrderNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 回复工单
+ // /reply 11 + /s 你好
+ if (strpos($sText, '/reply') === 0) {
+
+ // 先清除一遍,只进行一个进程
+ $oTgStep->clearByFromId($aData["fromId"]);
+
+ $iTicketId = str_replace('/reply', '', $sText);
+ $iTicketId = (int) trim($iTicketId);
+
+ $oTgStep->add($aData['fromId'], 'reply', 1, ["ticketId" => $iTicketId]);
+
+ $sMessage = "将回复工单【".$iTicketId."】,请输入回复内容。";
+
+ $this->sendMessage($sMessage);
+
+ Http::response(200, 'ok');
+
+ }
+
+ // 快捷回复工单
+ // /ry 11 你好
+ if (strpos($sText, '/ry') === 0 || strpos($sText, '\/ry') === 0) {
+
+// try {
+// $sText = $this->trimText($sText, '/ry');
+//
+// list($iTicketId, $sText) = explode(" ", $sText, 2);
+//
+// $oHttp = new Http();
+//
+// $oHttp->sMethod = "put";
+// $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/ticket/".$iTicketId;
+// $oHttp->bIsJson = true;
+// $aData['comment'] = $sText;
+// $aData['admin_name'] = $aUpdate["message"]["from"]["first_name"];
+// $oHttp->aData = $aData;
+//
+// $r = @json_decode($oHttp->send(), true);
+//
+// // 不论失败成功都清除 step
+// $oTgStep->clearByFromId($aUpdate["message"]["from"]["id"]);
+//
+// if ($r["ret"] == 1) {
+// $sMessage = "成功";
+// } else {
+// $sMessage = "失败";
+// Http::response(200, json_encode($aData));
+// }
+//
+// $this->sendMessage($sMessage);
+//
+// Http::response(200, 'ok');
+//
+// } catch (Exception $e) {
+//
+// $sMessage = "发生错误: " . $e->getMessage();
+//
+// $this->sendMessage($sMessage);
+//
+// Http::response(200, '内部服务器错误');
+//
+// }
+
+ }
+
+ // 复制节点
+ // /nodeCopy 11
+ if (strpos($sText, '/nodeCopy') === 0 || strpos($sText, '\/nodeCopy') === 0) {
+
+// list(, $iNodeId) = explode(" ", $sText, 2);
+//
+// $oHttp = new Http();
+//
+// $oHttp->sMethod = "post";
+// $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/node/".$iNodeId."/copy";
+// $oHttp->bIsJson = true;
+// $oHttp->aData = $aData;
+//
+// $r = @json_decode($oHttp->send(), true);
+//
+// if ($r["ret"] == 1) {
+// $sMessage = "成功";
+// } else {
+// $sMessage = "失败";
+// Http::response(500, json_encode($aData));
+// }
+//
+// $this->sendMessage($sMessage);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 用户报表
+ // /reportUser_day_7 && /reportUser_date_2025-02-02 && /reportUser_date_2025-02-02_2025-03-03
+ if (strpos($sText, '/reportUser') === 0 || strpos($sText, '\/reportUser') === 0) {
+
+// @list(, $sOption1, $sOption2, $sOption3) = explode("_", $sText, 4);
+//
+// $sMsg = '?';
+//
+// if ($sOption1 == 'day') {
+//
+// $sMsg = (new ServiceTgReportUser())->ByDay($sOption2);
+//
+// }
+//
+// if ($sOption1 == 'date') {
+// $sMsg = (new ServiceTgReportUser())->ByDate($sOption2, $sOption3);
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 优惠卷报表
+ // /reportCoupon#7
+ if (strpos($sText, '/reportCoupon') === 0 || strpos($sText, '\/reportCoupon') === 0) {
+// try {
+// @list($sCmd, $iDay) = explode("#", $sText, 2);
+//
+// // 确保 $iDay 是一个有效的数字
+// if (!is_numeric($iDay) || $iDay < 0) {
+// $this->sendMessage('无效的天数参数');
+// Http::response(200, '内部服务器错误');
+// }
+//
+// $sStartTime = strtotime("-$iDay days");
+//
+// $aOrderList = Order::where('update_time', '>=', $sStartTime)
+// ->whereIn('status', ['activated', 'pending_activation']) // 添加状态条件
+// ->select('coupon',
+// \App\Services\DB::raw('count(*) as total'),
+// \App\Services\DB::raw('SUM(price) as total_price'))
+// ->groupBy('coupon')
+// ->get()
+// ->toArray();
+//
+// $sMsg = '从 '.date("Y-m-d H:i:s", $sStartTime);
+// foreach ($aOrderList as $row) {
+// $coupon = str_replace('.', '#', $row['coupon']);
+// if (!$coupon) {
+// $coupon = '无';
+// }
+// $sMsg .= "\n\n";
+// $sMsg .= $coupon . ' - ' . $row['total_price'] . ' / ' . $row['total'];
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+// } catch (Exception $e) {
+// // 处理异常
+// $errorMsg = '发生错误: ' . $e->getMessage();
+// $this->sendMessage($errorMsg);
+//
+// // 返回错误响应
+// Http::response(200, '内部服务器错误');
+// }
+ }
+
+
+ // 节点列表(简洁)
+ // /nodeList
+ if (strpos($sText, '/nodeList') === 0 || strpos($sText, '\/nodeList') === 0) {
+
+// $aNodeList = Node::where('type', 1)->orderBy('name', 'asc')->get()->toArray();
+//
+// $sMsg = '';
+// foreach ($aNodeList as $row) {
+// $sMsg .= "\n\n";
+// $sMsg .= $row['name'].', id:'.$row['id'].', duck:'.$row['duck_code'].', zf:'.$row['zhuanfa_code'].', sort:'.$row['sort'];
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 添加duck
+ // /duckAdd jp01
+ if (strpos($sText, '/duckAdd') === 0 || strpos($sText, '\/duckAdd') === 0) {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+//
+// try {
+// $oDucks = new Ducks();
+// $oDucks->code = $sCode;
+//
+// if ($oDucks->save()) {
+// $sMsg = "成功";
+// } else {
+// $sMsg = "失败";
+// }
+// } catch (\Exception $e) {
+// $sMsg = json_encode($e->getMessage());
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 查找duck
+ // /duckFind jp01
+ if (strpos($sText, '/duckFind') === 0 || strpos($sText, '\/duckFind') === 0) {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+//
+// $aData = Ducks::where('code', $sCode)->first()->toArray();
+//
+// $aData['use_width'] = Tools::flowToGB($aData['use_width']).'GB';
+// $aData['max_width'] = Tools::flowToGB($aData['max_width']).'GB';
+// $aData['today_width'] = Tools::flowToGB($aData['today_width']).'GB';
+//
+// $this->sendMessage(json_encode($aData, JSON_PRETTY_PRINT));
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 添加zhuanfa
+ // /zhuanfaAdd jp01
+ if (strpos($sText, '/zhuanfaAdd') === 0 || strpos($sText, '\/zhuanfaAdd') === 0) {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+//
+// try {
+// $oZhuanfas = new Zhuanfas();
+// $oZhuanfas->code = $sCode;
+//
+// if ($oZhuanfas->save()) {
+// $sMsg = "成功";
+// } else {
+// $sMsg = "失败";
+// }
+// } catch (\Exception $e) {
+// $sMsg = json_encode($e->getMessage());
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 删除duck
+ // /duckDel jp01
+ if (strpos($sText, '/duckDel') === 0 || strpos($sText, '\/duckDel') === 0) {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+//
+// try {
+// $oDucks = Ducks::where("code", $sCode)->first();
+//
+// if ($oDucks) {
+// // 尝试删除记录
+// $deleted = $oDucks->delete();
+//
+// if ($deleted) {
+// // 删除成功
+// $sMsg = "成功";
+// } else {
+// // 删除失败
+// $sMsg = "失败";
+// }
+// } else {
+// // 找不到记录
+// $sMsg = "找不到记录";
+// }
+// } catch (\Exception $e) {
+// // 捕获异常并返回错误信息
+// $sMsg = json_encode($e->getMessage());
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 删除node
+ // /duckDel jp01
+ if (strpos($sText, '/nodeDel') === 0 || strpos($sText, '\/nodeDel') === 0) {
+
+// list($sCmd, $iId) = explode(" ", $sText, 2);
+//
+// $sMsg = '?';
+//
+// try {
+// $oNode = Node::where("id", $iId)->first();
+//
+// if ($oNode) {
+// // 尝试删除记录
+// $deleted = $oNode->delete();
+//
+// if ($deleted) {
+// // 删除成功
+// $sMsg = "成功";
+// } else {
+// // 删除失败
+// $sMsg = "失败";
+// }
+// } else {
+// // 找不到记录
+// $sMsg = "找不到记录";
+// }
+// } catch (\Exception $e) {
+// // 捕获异常并返回错误信息
+// $sMsg = json_encode($e->getMessage());
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 删除zhuanfa
+ // /zhuanfaDel jp01
+ if (strpos($sText, '/zhuanfaDel') === 0 || strpos($sText, '\/zhuanfaDel') === 0) {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+//
+// try {
+// $oZhuanfas = Zhuanfas::where("code", $sCode)->first();
+//
+// if ($oZhuanfas) {
+// // 尝试删除记录
+// $deleted = $oZhuanfas->delete();
+//
+// if ($deleted) {
+// // 删除成功
+// $sMsg = "成功";
+// } else {
+// // 删除失败
+// $sMsg = "失败";
+// }
+// } else {
+// // 找不到记录
+// $sMsg = "找不到记录";
+// }
+// } catch (\Exception $e) {
+// // 捕获异常并返回错误信息
+// $sMsg = json_encode($e->getMessage());
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 修改duck
+ // /duckOption@end_date@jp01 2025_02_02
+ // /duckOption@max_width@jp01 1.66#tb
+ if (strpos($sText, '/duckOption') === 0 || strpos($sText, '\/duckOption') === 0) {
+
+// list($sCmd, $sSet) = explode(" ", $sText, 2);
+// list(, $sField, $sCode) = explode("#", $sCmd, 3);
+//
+// if ($sSet) {
+// @list($iWidth, $sWidthType) = explode("|", $sSet, 2);
+// } else {
+// $sMsg = "没有参数";
+// }
+//
+//
+// if ($sWidthType == 'tb') {
+// $sSet = Tools::tomTbToB($iWidth);
+// }
+//
+// if ($sWidthType == 'gb') {
+// $sSet = Tools::tomGbToB($iWidth);
+// }
+//
+// $sMsg = '?';
+// try {
+//
+// $oDuck = Ducks::where('code', $sCode)->first();
+//
+// if (!$oDuck) {
+// $sMsg = "没有这个code";
+// } else {
+// $oDuck->$sField = $sSet;
+// if ($oDuck->save()) {
+// $sMsg = "成功"; // 保存成功
+// } else {
+// $sMsg = "失败"; // 保存失败
+// }
+// }
+//
+// } catch (\Illuminate\Database\QueryException $e) {
+//
+// $sMsg = json_encode($e->getMessage());
+//
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 修改zhuanfa
+ // /zhuanfaOption-end_date-jp01 2025_02_02
+ // /zhuanfaOption-max_width-jp01 1.66#tb
+ if (strpos($sText, '/zhuanfaOption') === 0 || strpos($sText, '\/zhuanfaOption') === 0) {
+
+// list($sCmd, $sSet) = explode(" ", $sText, 2);
+// list(, $sField, $sCode) = explode("-", $sCmd, 3);
+// @list($iWidth, $sWidthType) = explode("#", $sSet, 2);
+//
+// if ($sWidthType == 'tb') {
+// $sSet = Tools::tomTbToB($iWidth);
+// }
+//
+// if ($sWidthType == 'gb') {
+// $sSet = Tools::tomGbToB($iWidth);
+// }
+//
+// $sMsg = '?';
+// try {
+//
+// $oZhuanfas = Zhuanfas::where('code', $sCode)->first();
+//
+// if (!$oZhuanfas) {
+// $sMsg = "没有这个code";
+// } else {
+// $oZhuanfas->$sField = $sSet;
+// if ($oZhuanfas->save()) {
+// $sMsg = "成功"; // 保存成功
+// } else {
+// $sMsg = "失败"; // 保存失败
+// }
+// }
+//
+// } catch (\Illuminate\Database\QueryException $e) {
+//
+// $sMsg = json_encode($e->getMessage());
+//
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 转发重置
+ // /zhuanfaReset-youshi 2025-02-02
+ if (strpos($sText, '/zhuanfaReset') === 0 || strpos($sText, '\/zhuanfaReset') === 0) {
+
+// list($sCmd, $sDate) = explode(" ", $sText, 2);
+// list(, $sCode) = explode("-", $sCmd, 2);
+//
+// $sMsg = '?';
+// try {
+//
+// $oZhuanfas = Zhuanfas::where('code', $sCode)->first();
+//
+// if (!$oZhuanfas) {
+// $sMsg = "没有这个code";
+// } else {
+// $oZhuanfas->use_width = 0;
+// $oZhuanfas->end_date = $sDate;
+// if ($oZhuanfas->save()) {
+// $sMsg = "成功"; // 保存成功
+// } else {
+// $sMsg = "失败"; // 保存失败
+// }
+// }
+//
+// } catch (\Illuminate\Database\QueryException $e) {
+//
+// $sMsg = json_encode($e->getMessage());
+//
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // duck list
+ // /duckList
+ if (strpos($sText, '/duckList') === 0 || strpos($sText, '\/duckList') === 0) {
+
+// $aDuckList = Ducks::orderBy('code')->get()->toArray();
+//
+// $aMsgData = [];
+// foreach ($aDuckList as $k => $v) {
+// $v['use_width'] = Tools::flowToGB($v['use_width']).'g';
+// $v['max_width'] = Tools::flowToGB($v['max_width']).'g';
+// $v['today_width'] = Tools::flowToGB($v['today_width']).'g';
+// $aMsgData[] = $v;
+// }
+//
+// $this->sendMessage(json_encode($aMsgData, JSON_PRETTY_PRINT));
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // zhuanfa list
+ // /zhuanfaList
+ if (strpos($sText, '/zhuanfaList') === 0 || strpos($sText, '\/zhuanfaList') === 0) {
+
+// $aZhuanfaList = Zhuanfas::orderBy('code')->get()->toArray();
+//
+// $aMsgData = [];
+// foreach ($aZhuanfaList as $k => $v) {
+// $v['use_width'] = Tools::flowToTB($v['use_width'])."t";
+// $v['max_width'] = Tools::flowToTB($v['max_width']).'t';
+// $v['today_width'] = Tools::flowToGB($v['today_width']).'g';
+// $aMsgData[] = $v;
+// }
+//
+// $this->sendMessage(json_encode($aMsgData, JSON_PRETTY_PRINT));
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 节点设置变更
+ // /nodeOption@name@1 haha
+ if (strpos($sText, '/nodeOption') === 0 || strpos($sText, '\/nodeOption') === 0) {
+
+// list($sCmd, $sSet) = explode(" ", $sText, 2);
+//
+// list(, $sField, $iNodeId) = explode("#", $sCmd, 3);
+//
+// switch ($sField) {
+// case "config":
+// $sField = "custom_config";
+// break;
+// case "duck":
+// $sField = "duck_code";
+// break;
+// case "zhuanfa":
+// $sField = "zhuanfa_code";
+// break;
+// default:
+// $sField = $sField;
+// break;
+// }
+//
+// $sMsg = '?';
+// try {
+//
+// $oNode = Node::find($iNodeId);
+//
+// if (!$oNode) {
+// $sMsg = "没有这个id";
+// } else {
+// $oNode->$sField = $sSet;
+// $oNode->save();
+//
+// $sMsg = "ok";
+// }
+//
+// } catch (\Illuminate\Database\QueryException $e) {
+//
+// $sMsg = "数据库操作失败";
+//
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+
+ }
+
+ // 节点搜索
+ // /nodeLike_duck_type1 jp02
+ if (strpos($sText, '/nodeLike') === 0 || strpos($sText, '\/nodeLike') === 0) {
+
+// @list($sCmd, $sLike) = explode(" ", $sText);
+//
+// @list(, $sField, $sMod) = explode("#", $sCmd, 3);
+//
+// switch ($sField) {
+// case "port":
+// $sField = "custom_config";
+// break;
+// case "config":
+// $sField = "custom_config";
+// break;
+// case "duck":
+// $sField = "duck_code";
+// break;
+// case "zhuanfa":
+// $sField = "zhuanfa_code";
+// break;
+// default:
+// $sField = $sField;
+// break;
+// }
+//
+// $sMsg = '?';
+//
+// try {
+//
+// $oNodeList = Node::where($sField, 'like', '%' . $sLike . '%');
+//
+// if ($sMod == 'type1') {
+// $oNodeList->where('type', 1);
+// }
+//
+// $aNodeList = $oNodeList->orderBy('type', 'desc')->orderBy('name', 'asc')->get()->toArray();
+//
+// } catch (\Illuminate\Database\QueryException $e) {
+//
+// $sMsg = '字段不存在';
+//
+// }
+//
+// if (empty($aNodeList)) {
+//
+// $sMsg = "没有";
+//
+// } else {
+//
+// $aNodeListNew = [];
+// foreach ($aNodeList as $row) {
+//
+// $row['custom_config'] = json_decode($row['custom_config']);
+// $row['dynamic_rate_config'] = json_decode($row['dynamic_rate_config']);
+// $row['node_bandwidth_limit'] = Tools::flowToGB($row['node_bandwidth_limit']).'GB';
+// $row['node_bandwidth'] = Tools::flowToGB($row['node_bandwidth']).'GB';
+// $row['node_heartbeat'] = date('Y-m-d H:i:s', $row['node_heartbeat']);
+// unset($row['is_dynamic_rate']);
+// unset($row['dynamic_rate_type']);
+// unset($row['dynamic_rate_config']);
+// unset($row['bandwidthlimit_resetday']);
+// unset($row['is_dynamic_rate']);
+// unset($row['password']);
+//
+//// $aNodeListNew[] = $row;
+//
+// $sMsg = json_encode($row, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+//
+// $this->sendMessage($sMsg);
+// }
+//
+//// $sMsg = json_encode($aNodeListNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+// Http::response(200, 'ok');
+// }
+
+ $this->sendMessage($sMsg);
+
+ Http::response(200, 'ok');
+
+ }
+
+ // 工单查找
+ // /ticketFind 11
+// if (strpos($sText, '/ticketFind') === 0) {
+//
+// $iTicketId = $this->trimText($sText, '/ticketFind');
+//
+// $aTicket = Ticket::where("id", $iTicketId)->first()->toArray();
+//
+// $sMsg = "title:".$aTicket['title']."。\n";
+//
+// $aTicketContent = json_decode($aTicket['content'], true);
+//
+// if (!is_array($aTicketContent[0])) {
+// $aTicketContent[] = $aTicketContent;
+// }
+//
+// foreach ($aTicketContent as $row) {
+// $sMsg .= "\n";
+// $sMsg .= "name:".$row['commenter_name']."\n";
+// $sMsg .= "comment:".$row['comment']."\n";
+// }
+//
+// $this->sendMessage($sMsg);
+//
+// Http::response(200, 'ok');
+//
+// }
+
+ Http::response(200, '无');
+
+ }
+
+ private function trimText($sText, $sTrim)
+ {
+ $sText = ltrim($sText, $sTrim);
+ $sText = trim($sText);
+
+ return $sText;
+ }
+
+ private function sendMessage($sText = '?') {
+
+ if ($_ENV['is_loc'] === true) {
+ echo "";
+ var_dump($sText);
+ } else {
+ $url = "https://api.telegram.org/bot$this->sApiToken/sendMessage?chat_id=$this->sApiChatId&text=" . urlencode($sText);
+ file_get_contents($url);
+ }
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Article_.php b/src/Services/Tg/Hook/Mod/Article_.php
new file mode 100644
index 00000000..c2be152c
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Article_.php
@@ -0,0 +1,142 @@
+get()->toArray();
+
+ foreach ($aArticleList as &$row) { // 使用引用来修改原数组
+ unset($row['updated_at']); // 移除 updated_at 字段
+ unset($row['created_at']); // 移除 created_at 字段
+ $this->oTGHttp->sendToTG(json_encode($row, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+ }
+
+ $this->oHttp::response(200, 'ok');
+ }
+
+ public function Find($aParam)
+ {
+ $iId = $aParam['aArg'][1];
+
+ $aSingle = ModelArticle::find($iId)->toArray();
+
+ unset($aSingle['updated_at']);
+ unset($aSingle['created_at']);
+
+ return json_encode($aSingle, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+ }
+
+
+ public function Like($aParams)
+ {
+ $aArticleList = ModelArticle::where($this->cmdGood($aParams['aOption'][1]), 'like', '%' . $aParams['aArg'][1] . '%')
+ ->orderBy("user_name")
+ ->get()
+ ->toArray();
+
+ if (empty($aArticleList)) {
+ $this->oTGHttp->sendToTG("没有");
+ } else {
+ foreach ($aArticleList as &$row) { // 使用引用来修改原数组
+ unset($row['updated_at']); // 移除 updated_at 字段
+ unset($row['created_at']); // 移除 created_at 字段
+ $this->oTGHttp->sendToTG(json_encode($row, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+ }
+ }
+
+ $this->oHttp::response(200, 'ok');
+ }
+
+ public function Clone($aParam)
+ {
+ $iId = $aParam['aArg'][1];
+
+ // 查找文章
+ $aArticle = ModelArticle::find($iId);
+
+ if ($aArticle) {
+ // 复制文章
+ $newArticle = $aArticle->replicate();
+
+ // 如果需要,可以修改新文章的某些字段,例如标题或状态
+// $newArticle->title = $newArticle->title . ' - Copy'; // 修改标题
+ // $newArticle->status = 'draft'; // 例如,将状态设置为草稿
+
+ // 保存新文章
+ $newArticle->save();
+
+ // 发送新文章的 ID 到 Telegram
+ $sMsg = "新文章已创建,ID: " . $newArticle->id;
+ $this->oTGHttp->sendToTG($sMsg);
+
+ // 返回 HTTP 响应
+ $this->oHttp::response(200, 'ok');
+ } else {
+ throw new \Exception("没有这个id");
+ }
+ }
+
+ public function Add($aParams)
+ {
+
+ $newArticle = new ModelArticle();
+ $newArticle->user_name = $aParams['aArg'][1];
+ $r = $newArticle->save();
+
+ $this->oTGHttp->sendToTG(json_encode($r, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+
+ $this->oHttp::response(200, 'ok');
+
+ }
+
+ public function Del($aParams)
+ {
+
+ $article = ModelArticle::find($aParams['aArg'][1]);
+
+ if ($article) {
+ $r = $article->delete();
+ } else {
+ $r = false;
+ }
+
+ $this->oTGHttp->sendToTG(json_encode($r, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+
+ $this->oHttp::response(200, 'ok');
+
+ }
+
+ // /ArticleSet__id__user_name xxx
+ public function Set($aParams)
+ {
+ $sField = $this->cmdGood($aParams['aOption'][2]);
+
+ $article = ModelArticle::find($aParams['aOption'][1]);
+
+ $sSet = $aParams['aArg'][1];
+
+ if ($article) {
+ $article->$sField = $sSet;
+
+ $r = $article->save();
+ } else {
+ // 处理未找到的情况
+ throw new \Exception("Article not found");
+ }
+
+ $this->oTGHttp->sendToTG(json_encode($r, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
+
+ $this->oHttp::response(200, 'ok');
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Base.php b/src/Services/Tg/Hook/Mod/Base.php
new file mode 100644
index 00000000..81c0eda0
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Base.php
@@ -0,0 +1,43 @@
+oHttp = new Http();
+ $this->oTGHttp = new TGHttp();
+ }
+
+// protected function cmdGood($sCmd) {
+//
+// $sCmdNew = "";
+// switch ($sCmd) {
+// case "user":
+// $sCmdNew = "user_name";
+// break;
+// case "project":
+// $sCmdNew = "project_name";
+// break;
+// case "code":
+// $sCmdNew = "sale_code";
+// break;
+// case "condition":
+// $sCmdNew = "cron_condition";
+// break;
+// default:
+// $sCmdNew = $sCmd;
+// break;
+// }
+//
+// return $sCmdNew;
+//
+// }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Cmd.php b/src/Services/Tg/Hook/Mod/Cmd.php
new file mode 100644
index 00000000..042e3115
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Cmd.php
@@ -0,0 +1,47 @@
+ 'tk#find 11',
+ '工单回复' => 'tk#ry__11 你好',
+ '节点like' => 'node#like__id 1',
+ '节点set' => 'node#set__12__name 日本01',
+ '节点del' => 'node#del 25',
+ '节点list' => 'node#list',
+ '节点clone' => 'node#clone 24',
+ '转发list' => 'zf#list',
+ '转发set' => 'zf#set__youshi__use_width 3#tb',
+ '转发del' => 'zf#del hk02',
+ '转发add' => 'zf#add hk02',
+ '转发重置' => 'zf#reset__youshi 2028-01-01',
+ '机器del' => 'duck#del hk02',
+ '机器list' => 'duck#list',
+ '机器find' => 'duck#find hk01',
+ '机器add' => 'duck#add hk01',
+ '用户注册'
+ '用户报表day' => 'user#report__day__3',
+ '用户报表date' => 'user#report__date__2025-01-01',
+ '用户报表date到date' => 'user#report__date__2025-01-01__2026-01-01',
+ '用户查找' => 'user#find 1',
+ '订单从优惠码分组(默认0=24h)' => 'order#groupBySaleCode 3',
+ '访客统计day'
+ '访客统计date'
+ '访客统计date到date'
+ ];
+
+ return json_encode($aCmdList, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Duck.php b/src/Services/Tg/Hook/Mod/Duck.php
new file mode 100644
index 00000000..461b2641
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Duck.php
@@ -0,0 +1,144 @@
+get()->toArray();
+
+ $aMsgData = [];
+ foreach ($aDuckList as $k => $v) {
+ $v['use_width'] = Tools::flowToGB($v['use_width']).'g';
+ $v['max_width'] = Tools::flowToGB($v['max_width']).'g';
+ $v['today_width'] = Tools::flowToGB($v['today_width']).'g';
+ $aMsgData[] = $v;
+ }
+
+ $sMsg = json_encode($aMsgData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ return $sMsg;
+
+ }
+
+ public function Add($aParam)
+ {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+
+ $sCode = $aParam['aArg'][1];
+
+ $oDucks = new ModelDuck();
+ $oDucks->code = $sCode;
+
+ if ($oDucks->save()) {
+ $sMsg = "成功";
+ } else {
+ $sMsg = "失败";
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Find($aParam)
+ {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+
+ $sCode = $aParam['aArg'][1];
+
+ $aData = ModelDuck::where('code', $sCode)->first()->toArray();
+
+ $aData['use_width'] = Tools::flowToGB($aData['use_width']).'GB';
+ $aData['max_width'] = Tools::flowToGB($aData['max_width']).'GB';
+ $aData['today_width'] = Tools::flowToGB($aData['today_width']).'GB';
+
+ $sMsg = json_encode($aData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ return $sMsg;
+
+ }
+
+ public function Del($aParam)
+ {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+
+ $sCode = $aParam['aArg'][1];
+
+ $oDucks = ModelDuck::where("code", $sCode)->first();
+
+ if ($oDucks) {
+ // 尝试删除记录
+ $deleted = $oDucks->delete();
+
+ if ($deleted) {
+ // 删除成功
+ $sMsg = "成功";
+ } else {
+ // 删除失败
+ $sMsg = "失败";
+ }
+ } else {
+ // 找不到记录
+ $sMsg = "找不到记录";
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Set($aParam)
+ {
+
+// list($sCmd, $sSet) = explode(" ", $sText, 2);
+// list(, $sField, $sCode) = explode("#", $sCmd, 3);
+
+ $sSet = $aParam['aArg'][1];
+ $sCode = $aParam['aOption'][1];
+ $sField = $aParam['aOption'][2];
+
+ if ($sSet) {
+ @list($iWidth, $sWidthType) = explode("#", $sSet, 2);
+ } else {
+ $sMsg = "没有参数";
+ }
+
+
+ if ($sWidthType == 'tb') {
+ $sSet = Tools::tomTbToB($iWidth);
+ }
+
+ if ($sWidthType == 'gb') {
+ $sSet = Tools::tomGbToB($iWidth);
+ }
+
+ $sMsg = '?';
+
+ $oDuck = ModelDuck::where('code', $sCode)->first();
+
+ if (!$oDuck) {
+ $sMsg = "没有这个code";
+ } else {
+ $oDuck->$sField = $sSet;
+ if ($oDuck->save()) {
+ $sMsg = "成功"; // 保存成功
+ } else {
+ $sMsg = "失败"; // 保存失败
+ }
+ }
+
+ return $sMsg;
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Node.php b/src/Services/Tg/Hook/Mod/Node.php
new file mode 100644
index 00000000..f7c9e1e0
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Node.php
@@ -0,0 +1,202 @@
+sMethod = "post";
+ $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/node/".$iNodeId."/copy";
+ $oHttp->bIsJson = true;
+ $oHttp->aData = [
+ 'chatId' => $aParam['aOther']['chatId'],
+ 'fromId' => $aParam['aOther']['fromId']
+ ];
+
+ $r = @json_decode($oHttp->send(), true);
+
+ if ($r["ret"] == 1) {
+ $sMessage = "成功";
+ } else {
+ $sMessage = "失败";
+ }
+
+ return $sMessage;
+
+ }
+
+ public function List()
+ {
+
+ $aNodeList = ModelNode::where('type', 1)->orderBy('name', 'asc')->get()->toArray();
+
+ $sMsg = '';
+ foreach ($aNodeList as $row) {
+ $sMsg .= "\n\n";
+ $sMsg .= $row['name'].', id:'.$row['id'].', duck:'.$row['duck_code'].', zf:'.$row['zhuanfa_code'].', sort:'.$row['sort'];
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Like($aParam)
+ {
+
+// @list($sCmd, $sLike) = explode(" ", $sText);
+//
+// @list(, $sField, $sMod) = explode("#", $sCmd, 3);
+
+ $sLike = $aParam['aArg'][1];
+ $sField = $aParam['aOption'][1];
+ @$sMod = $aParam['aOption'][2];
+
+ switch ($sField) {
+ case "port":
+ $sField = "custom_config";
+ break;
+ case "config":
+ $sField = "custom_config";
+ break;
+ case "duck":
+ $sField = "duck_code";
+ break;
+ case "zhuanfa":
+ $sField = "zhuanfa_code";
+ break;
+ default:
+ $sField = $sField;
+ break;
+ }
+
+ $sMsg = '?';
+
+ $oNodeList = ModelNode::where($sField, 'like', '%' . $sLike . '%');
+
+ if ($sMod == 'type1') {
+ $oNodeList->where('type', 1);
+ }
+
+ $aNodeList = $oNodeList->orderBy('type', 'desc')->orderBy('name', 'asc')->get()->toArray();
+
+ if (empty($aNodeList)) {
+
+ $sMsg = "没有";
+
+ } else {
+
+ $aNodeListNew = [];
+ foreach ($aNodeList as $row) {
+
+ $row['custom_config'] = json_decode($row['custom_config']);
+ $row['dynamic_rate_config'] = json_decode($row['dynamic_rate_config']);
+ $row['node_bandwidth_limit'] = Tools::flowToGB($row['node_bandwidth_limit']).'GB';
+ $row['node_bandwidth'] = Tools::flowToGB($row['node_bandwidth']).'GB';
+ $row['node_heartbeat'] = date('Y-m-d H:i:s', $row['node_heartbeat']);
+ unset($row['is_dynamic_rate']);
+ unset($row['dynamic_rate_type']);
+ unset($row['dynamic_rate_config']);
+ unset($row['bandwidthlimit_resetday']);
+ unset($row['is_dynamic_rate']);
+ unset($row['password']);
+
+ $sMsg = json_encode($row, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ $this->oTGHttp->sendToTG($sMsg);
+
+ }
+
+ }
+ $this->oHttp::response(200, 'ok');
+ }
+
+ public function Set($aParam)
+ {
+
+// list($sCmd, $sSet) = explode(" ", $sText, 2);
+//
+// list(, $sField, $iNodeId) = explode("#", $sCmd, 3);
+
+ $sSet = $aParam['aArg'][1];
+ $iNodeId = $aParam['aOption'][1];
+ $sField = $aParam['aOption'][2];
+
+ switch ($sField) {
+ case "config":
+ $sField = "custom_config";
+ break;
+ case "duck":
+ $sField = "duck_code";
+ break;
+ case "zhuanfa":
+ $sField = "zhuanfa_code";
+ break;
+ default:
+ $sField = $sField;
+ break;
+ }
+
+ $sMsg = '?';
+
+ $oNode = ModelNode::find($iNodeId);
+
+ if (!$oNode) {
+ $sMsg = "没有这个id";
+ } else {
+ $oNode->$sField = $sSet;
+ $oNode->save();
+
+ $sMsg = "ok";
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Del($aParam)
+ {
+
+// list($sCmd, $iId) = explode(" ", $sText, 2);
+ $iId = $aParam['aArg'][1];
+
+ $sMsg = '?';
+
+ $oNode = ModelNode::where("id", $iId)->first();
+
+ if ($oNode) {
+ // 尝试删除记录
+ $deleted = $oNode->delete();
+
+ if ($deleted) {
+ // 删除成功
+ $sMsg = "成功";
+ } else {
+ // 删除失败
+ $sMsg = "失败";
+ }
+ } else {
+ // 找不到记录
+ $sMsg = "找不到记录";
+ }
+
+ return $sMsg;
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Order.php b/src/Services/Tg/Hook/Mod/Order.php
new file mode 100644
index 00000000..ace69a02
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Order.php
@@ -0,0 +1,79 @@
+get()->toArray();
+
+ if ($aOrder) {
+ $aOrderNew = [];
+ foreach ($aOrder as $k => $v) {
+ $v['create_time'] = date("Y-m-d H:i:m", $v['create_time']);
+ $v['update_time'] = date("Y-m-d H:i:m", $v['update_time']);
+ $v['product_content'] = json_decode($v['product_content']);
+ $aOrderNew[] = $v;
+ }
+ } else {
+ $aOrderNew = ["not have id" => $iUserId];
+ }
+
+ $sMsg = json_encode($aOrderNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ return $sMsg;
+
+ }
+
+ public function GroupBySaleCode($aParam)
+ {
+
+// @list($sCmd, $iDay) = explode("#", $sText, 2);
+
+ if (!isset($aParam['aArg'][1])) {
+ $iDay = 1;
+ } else {
+ $iDay = $aParam['aArg'][1];
+ }
+
+ // 确保 $iDay 是一个有效的数字
+ if (!is_numeric($iDay) || $iDay < 0) {
+ throw new \Exception("无效的天数参数");
+ }
+
+ $sStartTime = strtotime("-$iDay days");
+
+ $aOrderList = ModelOrder::where('update_time', '>=', $sStartTime)
+ ->whereIn('status', ['activated', 'pending_activation']) // 添加状态条件
+ ->select('coupon',
+ \App\Services\DB::raw('count(*) as total'),
+ \App\Services\DB::raw('SUM(price) as total_price'))
+ ->groupBy('coupon')
+ ->get()
+ ->toArray();
+
+ $sMsg = '从 '.date("Y-m-d H:i:s", $sStartTime);
+ foreach ($aOrderList as $row) {
+ $coupon = str_replace('.', '#', $row['coupon']);
+ if (!$coupon) {
+ $coupon = '无';
+ }
+ $sMsg .= "\n\n";
+ $sMsg .= $coupon . ' - ' . $row['total_price'] . ' / ' . $row['total'];
+ }
+
+ return $sMsg;
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/SaleCode.php b/src/Services/Tg/Hook/Mod/SaleCode.php
new file mode 100644
index 00000000..203219e1
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/SaleCode.php
@@ -0,0 +1,51 @@
+sendMessage('无效的天数参数');
+ Http::response(200, '内部服务器错误');
+ }
+
+ $sStartTime = strtotime("-$iDay days");
+
+ $aOrderList = Order::where('update_time', '>=', $sStartTime)
+ ->whereIn('status', ['activated', 'pending_activation']) // 添加状态条件
+ ->select('coupon',
+ \App\Services\DB::raw('count(*) as total'),
+ \App\Services\DB::raw('SUM(price) as total_price'))
+ ->groupBy('coupon')
+ ->get()
+ ->toArray();
+
+ $sMsg = '从 '.date("Y-m-d H:i:s", $sStartTime);
+ foreach ($aOrderList as $row) {
+ $coupon = str_replace('.', '#', $row['coupon']);
+ if (!$coupon) {
+ $coupon = '无';
+ }
+ $sMsg .= "\n\n";
+ $sMsg .= $coupon . ' - ' . $row['total_price'] . ' / ' . $row['total'];
+ }
+
+ $this->sendMessage($sMsg);
+
+ Http::response(200, 'ok');
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Test.php b/src/Services/Tg/Hook/Mod/Test.php
new file mode 100644
index 00000000..8e6cb8ed
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Test.php
@@ -0,0 +1,21 @@
+first()->toArray();
+
+ $sMsg = "title:".$aTicket['title']."。\n";
+
+ $aTicketContent = json_decode($aTicket['content'], true);
+
+ if (!is_array($aTicketContent[0])) {
+ $aTicketContent[] = $aTicketContent;
+ }
+
+ foreach ($aTicketContent as $row) {
+ $sMsg .= "\n";
+ $sMsg .= "name:".$row['commenter_name']."\n";
+ $sMsg .= "comment:".$row['comment']."\n";
+ }
+
+ return $sMsg;
+
+ }
+
+// public function Find($aParam)
+// {
+//
+//// list(, $iUserId) = explode(" ", $sText, 2);
+//
+// $iUserId = $aParam['aArg'][1];
+//
+// $aOrder = Order::where("user_id", $iUserId)->get()->toArray();
+//
+// if ($aOrder) {
+// $aOrderNew = [];
+// foreach ($aOrder as $k => $v) {
+// $v['create_time'] = date("Y-m-d H:i:m", $v['create_time']);
+// $v['update_time'] = date("Y-m-d H:i:m", $v['update_time']);
+// $v['product_content'] = json_decode($v['product_content']);
+// $aOrderNew[] = $v;
+// }
+// } else {
+// $aOrderNew = ["not have id" => $iUserId];
+// }
+//
+// $sMsg = json_encode($aOrderNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+//
+// return $sMsg;
+//
+// }
+
+ public function Ry($aParam)
+ {
+
+// list($iTicketId, $sText) = explode(" ", $sText, 2);
+
+ $iTicketId = $aParam['aOption'][1];
+ $sText = $aParam['aArg'][1];
+ $aUpdate = $aParam['aUpdate'];
+
+ $oHttp = new Http();
+
+ $oHttp->sMethod = "put";
+ $oHttp->sToUrl = $_ENV['baseUrl']."/api/tg/ticket/".$iTicketId;
+ $oHttp->bIsJson = true;
+ $aData['chatId'] = $aParam['aOther']['chatId'];
+ $aData['fromId'] = $aParam['aOther']['fromId'];
+ $aData['comment'] = $sText;
+ $aData['admin_name'] = $aUpdate["message"]["from"]["first_name"];
+ $oHttp->aData = $aData;
+
+ $r = @json_decode($oHttp->send(), true);
+
+ // 不论失败成功都清除 step
+// $oTgStep->clearByFromId($aUpdate["message"]["from"]["id"]);
+
+ if ($r["ret"] == 1) {
+ $sMessage = "成功";
+ } else {
+ $sMessage = "失败";
+ }
+
+ return $sMessage;
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/User.php b/src/Services/Tg/Hook/Mod/User.php
new file mode 100644
index 00000000..deaa0b28
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/User.php
@@ -0,0 +1,75 @@
+toArray();
+ unset($aUser['pass']);
+ unset($aUser['passwd']);
+ unset($aUser['uuid']);
+ unset($aUser['method']);
+ unset($aUser['is_admin']);
+ unset($aUser['theme']);
+ unset($aUser['ga_token']);
+ unset($aUser['ga_enable']);
+ unset($aUser['api_token']);
+ unset($aUser['is_dark_mode']);
+ unset($aUser['locale']);
+
+ $aUser['transfer_today'] = Tools::flowToGB($aUser['transfer_today']).'GB';
+ $aUser['transfer_total'] = Tools::flowToGB($aUser['transfer_total']).'GB';
+ $aUser['transfer_enable'] = Tools::flowToGB($aUser['transfer_enable']).'GB';
+ $aUser['last_use_time'] = date('Y-m-d H:i:s', $aUser['last_use_time']);
+ } else {
+ $aUser = ["not have id" => $iUserId];
+ }
+
+ $sMsg = json_encode($aUser, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ return $sMsg;
+
+ }
+
+ public function Report($aParam)
+ {
+
+// @list(, $sOption1, $sOption2, $sOption3) = explode("_", $sText, 4);
+
+ @$sOption1 = $aParam['aOption'][1];
+ @$sOption2 = $aParam['aOption'][2];
+ @$sOption3 = $aParam['aOption'][3];
+ @$sOption4 = $aParam['aOption'][4];
+
+ $sMsg = '?';
+
+ if ($sOption1 == 'day') {
+ $sMsg = (new ServiceTgReportUser())->ByDay($sOption2);
+ }
+
+ if ($sOption1 == 'date') {
+ $sMsg = (new ServiceTgReportUser())->ByDate($sOption2, $sOption3);
+ }
+
+ return $sMsg;
+
+ }
+
+}
diff --git a/src/Services/Tg/Hook/Mod/Zf.php b/src/Services/Tg/Hook/Mod/Zf.php
new file mode 100644
index 00000000..340dd40b
--- /dev/null
+++ b/src/Services/Tg/Hook/Mod/Zf.php
@@ -0,0 +1,150 @@
+get()->toArray();
+
+ $aMsgData = [];
+ foreach ($aZhuanfaList as $k => $v) {
+ $v['use_width'] = Tools::flowToTB($v['use_width'])."t";
+ $v['max_width'] = Tools::flowToTB($v['max_width']).'t';
+ $v['today_width'] = Tools::flowToGB($v['today_width']).'g';
+ $aMsgData[] = $v;
+ }
+
+ $sMsg = json_encode($aMsgData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
+
+ return $sMsg;
+
+ }
+
+ public function Reset($aParam)
+ {
+
+// list($sCmd, $sDate) = explode(" ", $sText, 2);
+// list(, $sCode) = explode("-", $sCmd, 2);
+
+ $sDate = $aParam['aArg'][1];
+ $sCode = $aParam['aOption'][1];
+
+ $sMsg = '?';
+
+ $oZhuanfas = Zhuanfas::where('code', $sCode)->first();
+
+ if (!$oZhuanfas) {
+ $sMsg = "没有这个code";
+ } else {
+ $oZhuanfas->use_width = 0;
+ $oZhuanfas->end_date = $sDate;
+ if ($oZhuanfas->save()) {
+ $sMsg = "成功"; // 保存成功
+ } else {
+ $sMsg = "失败"; // 保存失败
+ }
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Set($aParam)
+ {
+
+// list($sCmd, $sSet) = explode(" ", $sText, 2);
+// list(, $sField, $sCode) = explode("-", $sCmd, 3);
+// @list($iWidth, $sWidthType) = explode("#", $sSet, 2);
+
+ $sSet = $aParam['aArg'][1];
+ $sCode = $aParam['aOption'][1];
+ $sField = $aParam['aOption'][2];
+
+ @list($iWidth, $sWidthType) = explode("#", $sSet, 2);
+
+ if ($sWidthType == 'tb') {
+ $sSet = Tools::tomTbToB($iWidth);
+ }
+
+ if ($sWidthType == 'gb') {
+ $sSet = Tools::tomGbToB($iWidth);
+ }
+
+ $sMsg = '?';
+
+ $oZhuanfas = Zhuanfas::where('code', $sCode)->first();
+
+ if (!$oZhuanfas) {
+ $sMsg = "没有这个code";
+ } else {
+ $oZhuanfas->$sField = $sSet;
+ if ($oZhuanfas->save()) {
+ $sMsg = "成功"; // 保存成功
+ } else {
+ $sMsg = "失败"; // 保存失败
+ }
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Add($aParam)
+ {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+
+ $sCode = $aParam['aArg'][1];
+
+ $oZhuanfas = new Zhuanfas();
+ $oZhuanfas->code = $sCode;
+
+ if ($oZhuanfas->save()) {
+ $sMsg = "成功";
+ } else {
+ $sMsg = "失败";
+ }
+
+ return $sMsg;
+
+ }
+
+ public function Del($aParam)
+ {
+
+// list($sCmd, $sCode) = explode(" ", $sText, 2);
+
+ $sCode = $aParam['aArg'][1];
+
+ $oZhuanfas = Zhuanfas::where("code", $sCode)->first();
+
+ if ($oZhuanfas) {
+ // 尝试删除记录
+ $deleted = $oZhuanfas->delete();
+
+ if ($deleted) {
+ // 删除成功
+ $sMsg = "成功";
+ } else {
+ // 删除失败
+ $sMsg = "失败";
+ }
+ } else {
+ // 找不到记录
+ $sMsg = "找不到记录";
+ }
+
+ return $sMsg;
+
+ }
+
+}
diff --git a/src/Services/Tg/Http.php b/src/Services/Tg/Http.php
new file mode 100644
index 00000000..a9051615
--- /dev/null
+++ b/src/Services/Tg/Http.php
@@ -0,0 +1,30 @@
+sApiToken = Config::obtain('telegram_token');
+ $this->sApiChatId = Config::obtain('telegram_chatid');
+ }
+
+ public function sendToTG($sMsg)
+ {
+
+ if ($_ENV['is_loc'] === true) {
+ echo "";
+ echo($sMsg);
+ } else {
+ $url = "https://api.telegram.org/bot$this->sApiToken/sendMessage?chat_id=$this->sApiChatId&text=" . urlencode($sMsg);
+ file_get_contents($url);
+ }
+
+ }
+
+}
diff --git a/src/Services/TomTool/Http.php b/src/Services/TomTool/Http.php
index 298da54d..794e0f36 100755
--- a/src/Services/TomTool/Http.php
+++ b/src/Services/TomTool/Http.php
@@ -6,9 +6,9 @@ namespace App\Services\TomTool;
class Http
{
- public $sMethod;
+ public $sMethod = 'get';
public $aData = [];
- public $sToUrl;
+ public $sToUrl; // 必须
public $bIsJson = false; // 默认值为 false
public function send(): string
@@ -48,10 +48,15 @@ class Http
}
break;
- default:
+ case 'get':
// 默认使用 GET 请求
curl_setopt($ch, CURLOPT_HTTPGET, true); // 设置为 GET 请求
curl_setopt($ch, CURLOPT_URL, $this->sToUrl . '?' . http_build_query($this->aData)); // 设置请求 URL
+ if ($this->bIsJson) {
+ curl_setopt($ch, CURLOPT_HTTPHEADER, [
+ 'Accept: application/json' // 设置接受的内容类型为 JSON
+ ]);
+ }
break;
}