github/app/Http/Controllers/TomApi/Tg/HookController.php
2025-04-12 19:11:43 +08:00

925 lines
31 KiB
PHP
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace App\Controllers\TomApi\Tg;
use App\Models\Config;
use App\Models\TgStep;
use App\Models\Ticket;
use App\Models\Node;
use App\Models\User;
use App\Models\Order;
use App\Models\Ducks;
use App\Models\Zhuanfas;
use App\Services\Tg\ReportUser as ServiceTgReportUser;
use GuzzleHttp\Exception\GuzzleException;
use Psr\Http\Client\ClientExceptionInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Http\Response;
use Slim\Http\ServerRequest;
use App\Utils\Tools;
use App\Services\TomTool\Http;
final class HookController
{
public $sApiToken;
public $sApiChatId;
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'])) {
$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 "<pre>";
var_dump($sText);
} else {
$url = "https://api.telegram.org/bot$this->sApiToken/sendMessage?chat_id=$this->sApiChatId&text=" . urlencode($sText);
file_get_contents($url);
}
}
}