no message
This commit is contained in:
parent
f6ed0fb75c
commit
d8c015d8cf
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,5 +2,6 @@
|
||||
public/fn/
|
||||
public/client/
|
||||
public/feed/
|
||||
public/sub/
|
||||
README.md
|
||||
_env/
|
||||
|
||||
230
app/Http/Controllers/Api/FreenodeController.php
Executable file
230
app/Http/Controllers/Api/FreenodeController.php
Executable file
@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
//use voku\helper\AntiXSS;
|
||||
use App\Models\ArticleList as ArticleList;
|
||||
use App\Services\TomTool\HttpV2;
|
||||
use App\Models\Option as ModelOption;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
|
||||
class FreenodeController extends Controller
|
||||
{
|
||||
static $sEnding = [
|
||||
"clash" => ".yaml",
|
||||
"v2ray" => ".txt",
|
||||
];
|
||||
|
||||
static $aCountry = [
|
||||
"美国",
|
||||
"美国",
|
||||
"日本",
|
||||
"日本",
|
||||
"新加坡",
|
||||
"新加坡",
|
||||
"香港",
|
||||
"香港",
|
||||
"台湾",
|
||||
"台湾",
|
||||
"越南",
|
||||
"越南",
|
||||
"俄罗斯",
|
||||
"新西兰",
|
||||
"瑞士",
|
||||
"荷兰",
|
||||
"冰岛",
|
||||
"爱尔兰",
|
||||
"乌克兰",
|
||||
"泰国",
|
||||
"阿根廷",
|
||||
"葡萄牙",
|
||||
"美国",
|
||||
"日本",
|
||||
"新加坡",
|
||||
"台湾",
|
||||
"香港",
|
||||
"韩国",
|
||||
"德国",
|
||||
"土耳其",
|
||||
"法国",
|
||||
"加拿大",
|
||||
"加拿大",
|
||||
];
|
||||
|
||||
public function receive(Request $request)
|
||||
{
|
||||
$aData = $request->all();
|
||||
|
||||
$sData = json_encode($aData);
|
||||
|
||||
$sFnDir = "sub";
|
||||
$sDateCode = date("Ymd");
|
||||
$aResult = [];
|
||||
foreach ($aData as $sFnClient => $sFnContent) {
|
||||
$sFnFilePath = $sFnDir."/".$sDateCode."-".$sFnClient.$this->endingByClient($sFnClient);
|
||||
file_put_contents($sFnFilePath, $sFnContent);
|
||||
$aResult[$sFnClient] = "以更新:".env("APP_URL")."/".$sFnFilePath;
|
||||
}
|
||||
|
||||
$this->saveArticleHtml();
|
||||
|
||||
TeleSlave::warn()->enableSlaveQueue(false)->setMsgA($aResult)->send();
|
||||
|
||||
return ["is_done" => true];
|
||||
}
|
||||
|
||||
private function saveArticleHtml()
|
||||
{
|
||||
$sDateCode = date("Ymd");
|
||||
|
||||
/// test
|
||||
// ArticleList::where("code", $sDateCode)->delete();
|
||||
//// test end
|
||||
|
||||
$oArticleList = ArticleList::where("code", $sDateCode)->first();
|
||||
|
||||
if ($oArticleList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->_saveArticle($sDateCode);
|
||||
|
||||
$sHtmlUrl = $this->_saveHtml($sDateCode);
|
||||
|
||||
TeleSlave::log()->enableSlaveQueue(false)->send("新fn文章:".$sHtmlUrl);
|
||||
|
||||
return $sHtmlUrl;
|
||||
}
|
||||
|
||||
private function _saveHtml($sDateCode)
|
||||
{
|
||||
$sFreenodeNewUrl = env("APP_URL")."/fn/single/".$sDateCode;
|
||||
$sFreeNodePath = "fn/".$sDateCode.".html";
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $sFreenodeNewUrl);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
|
||||
$sFreeNodeNewView = curl_exec($ch);
|
||||
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // 获取 HTTP 响应代码
|
||||
|
||||
if ($httpCode !== 200) {
|
||||
ArticleList::where("code", $sDateCode)->delete();
|
||||
$sMsg = "fn站saveHtml时发生了 $httpCode 错误 -> ".$sFreenodeNewUrl;
|
||||
TeleSlave::warn()->enableSlaveQueue(false)->send($sMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
file_put_contents($sFreeNodePath, $sFreeNodeNewView);
|
||||
|
||||
$sHtmlUrl = env("APP_URL")."/fn/".$sDateCode.".html";
|
||||
|
||||
return $sHtmlUrl;
|
||||
}
|
||||
|
||||
private function endingByClient($sFnClient)
|
||||
{
|
||||
if (isset(self::$sEnding[$sFnClient])) {
|
||||
$sEnding = self::$sEnding[$sFnClient];
|
||||
} else {
|
||||
$sEnding = ".none";
|
||||
}
|
||||
|
||||
return $sEnding;
|
||||
}
|
||||
|
||||
private function _saveArticle($sDateCode)
|
||||
{
|
||||
|
||||
$sTime = time();
|
||||
$sTimePrev = strtotime("-1 day");
|
||||
$sDateCode = date("Ymd", $sTime);
|
||||
$sDateCodePrev = date("Ymd", $sTimePrev);
|
||||
|
||||
$aOption = ModelOption::_all();
|
||||
|
||||
//// 图片
|
||||
$iPrevImgId = ArticleList::where("code", $sDateCodePrev)->first()?->img_id;
|
||||
if ($iPrevImgId >= env('article_img_count')) {
|
||||
$iImgId = 1;
|
||||
} else {
|
||||
$iImgId = $iPrevImgId + 1;
|
||||
}
|
||||
|
||||
//// 地区
|
||||
$iCountryLimit = rand(5, 12);
|
||||
$aCountryKey = array_rand(self::$aCountry, $iCountryLimit);
|
||||
|
||||
$aCountry = [];
|
||||
foreach ($aCountryKey as $sCountryKey) {
|
||||
$aCountry[] = self::$aCountry[$sCountryKey];
|
||||
}
|
||||
|
||||
$sNodeZone = implode("、", $aCountry);
|
||||
|
||||
//// 标题
|
||||
$aTitlePool = [
|
||||
date('Y', $sTime).$aOption["freenode_title"]
|
||||
];
|
||||
$iTitlePoolRandKey = array_rand($aTitlePool);
|
||||
$sTitle = $aTitlePool[$iTitlePoolRandKey];
|
||||
|
||||
//// 内容
|
||||
$aOptionFnClient = explode(",", $aOption["freenode_client"]);
|
||||
|
||||
$iNodeSpeed = rand((int) env("freenode_speed_min"), (int) env("freenode_speed_max"));
|
||||
$iNodeCount = rand((int) env("freenode_count_min"), (int) env("freenode_count_max"));
|
||||
|
||||
$sContent = "
|
||||
<p>本次更新共".$iNodeCount."个可用节点,最高速度".$iNodeSpeed."M/S。</p>
|
||||
<p>覆盖".$sNodeZone."等多个区域。</p>
|
||||
<p>复制下方的v2ray/Clash订阅链接,在客户端添加即可正常使用。<br />
|
||||
";
|
||||
|
||||
// 副标题
|
||||
$sTitleSub = "
|
||||
本次更新共".$iNodeCount."个可用节点,最高速度".$iNodeSpeed."M/S。
|
||||
覆盖".$sNodeZone."等多个区域。
|
||||
复制下方的v2ray/Clash订阅链接,在客户端添加即可正常使用。
|
||||
";
|
||||
|
||||
// 标签
|
||||
$aTagPool = [
|
||||
'[1][2][3][4][5][6][7][8][11]',
|
||||
'[11][3][1][2][5][6][4][8][7]',
|
||||
'[3][2][1][4][7][8][6][5][4]',
|
||||
'[4][3][1][2][5][8][7][6][5]',
|
||||
];
|
||||
$iTagPoolRandKey = array_rand($aTagPool);
|
||||
$sTag = $aTagPool[$iTagPoolRandKey];
|
||||
|
||||
$oFreenoodList = new ArticleList();
|
||||
$oFreenoodList->img_id = $iImgId;
|
||||
$oFreenoodList->date_str = date('n月j日', $sTime);
|
||||
$oFreenoodList->created_at = $sTime;
|
||||
$oFreenoodList->title = $sTitle;
|
||||
$oFreenoodList->code = $sDateCode;
|
||||
$oFreenoodList->tags = $sTag;
|
||||
$oFreenoodList->type = 'node';
|
||||
$oFreenoodList->content = $sContent;
|
||||
$oFreenoodList->title_sub = $sTitleSub;
|
||||
|
||||
$r = $oFreenoodList->save();
|
||||
|
||||
if ($r != true) {
|
||||
$sMsg = " - article insert - fail.";
|
||||
echo $sMsg;
|
||||
TeleSlave::warn()->enableSlaveQueue(false)->send($sMsg);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -84,9 +84,25 @@ class SingleController extends Controller
|
||||
|
||||
$this->aData['pageKw'] = "Clash,Quantumult,Shadowrocket,SSR,v2ray,免费节点,节点,订阅链接";
|
||||
|
||||
$this->aData['v2rayPath'] = env('APP_URL')."/feed/v2ray-".$iCode.".txt";
|
||||
// $this->aData['v2rayPath'] = env('APP_URL')."/feed/v2ray-".$iCode.".txt";
|
||||
//
|
||||
// $this->aData['clashPath'] = env('APP_URL')."/feed/clash-".$iCode.".yaml";
|
||||
|
||||
$this->aData['clashPath'] = env('APP_URL')."/feed/clash-".$iCode.".yaml";
|
||||
$aOption = Option::_all();
|
||||
$aOptionFreenodeClient = explode(",", $aOption["freenode_client"]);
|
||||
|
||||
foreach ($aOptionFreenodeClient as $sFnClient) {
|
||||
|
||||
$sEnding = ".txt";
|
||||
if ($sFnClient == "v2ray") {
|
||||
$sEnding = ".txt";
|
||||
} else if ($sFnClient == "clash") {
|
||||
$sEnding = ".yaml";
|
||||
}
|
||||
|
||||
$this->aData["fnFilePath"][$sFnClient] = env('APP_URL')."/sub/".$iCode."-v2ray.txt";
|
||||
|
||||
}
|
||||
|
||||
$this->aData['jichang'] = Jichang::first()->toArray();
|
||||
|
||||
|
||||
15
app/Http/Controllers/Exec/ExecFreenodeController.php
Executable file
15
app/Http/Controllers/Exec/ExecFreenodeController.php
Executable file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
//namespace App\Http\Controllers;
|
||||
//
|
||||
//use Illuminate\Http\Request;
|
||||
////use App\Models\ArticleList;
|
||||
////use App\Models\Tags;
|
||||
////use App\Services\Time;
|
||||
////use App\Models\Option as ModelOption;
|
||||
//
|
||||
//class ExecFreenodeController
|
||||
//{
|
||||
//
|
||||
//}
|
||||
|
||||
114
app/Services/Cron.php
Normal file
114
app/Services/Cron.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
//use App\Services\Cron\HttpQueue as CronHttpQueue;
|
||||
//use App\Services\Cron\Book as CronBook;
|
||||
//use App\Services\Cron\FreenodeCrawl as CronFreenodeCrawl;
|
||||
//use App\Services\Cron\FreenodePool as CronFreenodePool;
|
||||
//use App\Services\Cron\FreenodeFile as CronFreenodeFile;
|
||||
//use App\Services\Cron\FreenodeMerge as CronFreenodeMerge;
|
||||
//use App\Services\Cron\FreenodeLog as CronFreenodeLog;
|
||||
//use App\Services\Cron\FreenodeSync as CronFreenodeSync;
|
||||
//use App\Services\Cron\ArticleSchema as CronArticleSchema;
|
||||
//use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
//use App\Services\Cron\FreenodeSync as CronFreenodeSync;
|
||||
|
||||
final class Cron
|
||||
{
|
||||
public bool $bIsTest = false;
|
||||
public ?int $iTestH = null;
|
||||
public ?int $iTestI = null;
|
||||
public ?int $iTestS = null;
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
try {
|
||||
|
||||
$h = (int) date("H");
|
||||
$i = (int) date("i");
|
||||
$s = (int) date("s");
|
||||
|
||||
if ($this->bIsTest) {
|
||||
$h = (int) ($this->iTestH ?? $h);
|
||||
$i = (int) ($this->iTestI ?? $i);
|
||||
$s = (int) ($this->iTestS ?? $s);
|
||||
}
|
||||
|
||||
echo "cron开始执行 \n";
|
||||
|
||||
if ($h % 8 === 0 && $i === 3) {
|
||||
// CronBook::randbox_notify();
|
||||
// CronFreenodeSync::
|
||||
}
|
||||
|
||||
if ($h % 6 === 0 && $i === 3) {
|
||||
// CronFreenodeCrawl::run();
|
||||
// CronFreenodePool::save();
|
||||
// CronFreenodeMerge::save();
|
||||
// CronFreenodeMerge::baseToSite();
|
||||
// CronFreenodeSync::run();
|
||||
}
|
||||
|
||||
if ($i % 3 === 0) {
|
||||
// CronArticleSchema::cacheTgSave();
|
||||
// CronArticleSchema::pushToSlave();
|
||||
// CronHttpQueue::pop();
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
// ReportSender::handle();
|
||||
}
|
||||
|
||||
if ($h == 5 && $i === 3) {
|
||||
// CronFreenodeFile::clear();
|
||||
}
|
||||
|
||||
if ($h == 15 && $i == 3) {
|
||||
// CronFreenodeLog::fromLast();
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
|
||||
$sMsg = "";
|
||||
$sMsg .= "--- cron 异常 ---\n";
|
||||
$sMsg .= "类型: " . get_class($e) . "\n";
|
||||
$sMsg .= "信息: " . $e->getMessage() . "\n";
|
||||
$sMsg .= "文件: " . $e->getFile() . " 在第 " . $e->getLine() . " 行\n";
|
||||
$sMsg .= "代码跟踪:\n" . $e->getTraceAsString() . "\n";
|
||||
$sMsg .= "-----------------------------\n";
|
||||
|
||||
echo $sMsg;
|
||||
|
||||
TeleSlave::fail()->send($sMsg);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function setTestH(int $h): void
|
||||
{
|
||||
$this->enableTestMode();
|
||||
$this->iTestH = $h;
|
||||
}
|
||||
|
||||
public function setTestI(int $i): void
|
||||
{
|
||||
$this->enableTestMode();
|
||||
$this->iTestI = $i;
|
||||
}
|
||||
|
||||
public function setTestS(int $s): void
|
||||
{
|
||||
$this->enableTestMode();
|
||||
$this->iTestS = $s;
|
||||
}
|
||||
|
||||
public function enableTestMode(bool $enable = true): void
|
||||
{
|
||||
$this->bIsTest = $enable;
|
||||
}
|
||||
}
|
||||
22
app/Services/Freenode/ServicesFreenodeSync.php
Executable file
22
app/Services/Freenode/ServicesFreenodeSync.php
Executable file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
namespace App\Services;
|
||||
use App\Models\Freenode;
|
||||
|
||||
class ServicesFreenodeSync {
|
||||
|
||||
// public static function strToNames($sTagsStr)
|
||||
// {
|
||||
//
|
||||
// $sTagsStr = substr($sTagsStr, 1, -1);
|
||||
// $aTagsId = explode('][', $sTagsStr);
|
||||
// $aTagsMap = Tags::all()->toArray();
|
||||
//
|
||||
// foreach ($aTagsId as $aTagsIdRow) {
|
||||
// $aTagNames[] = $aTagsMap[$aTagsIdRow-1];
|
||||
// }
|
||||
//
|
||||
// return $aTagNames;
|
||||
//
|
||||
// }
|
||||
|
||||
}
|
||||
415
app/Services/TomTool/Flow.php
Executable file
415
app/Services/TomTool/Flow.php
Executable file
@ -0,0 +1,415 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool;
|
||||
|
||||
use App\Services\TomTool\TelegramVdb;
|
||||
|
||||
/**
|
||||
|
||||
默认:
|
||||
name:none
|
||||
isDone:false
|
||||
|
||||
new:
|
||||
$oResult = Flow::make("name");
|
||||
|
||||
快速:
|
||||
Flow::make("name")->fail("kkkkkkk");
|
||||
|
||||
进阶:
|
||||
Flow::make("name")->noDone()->msg("哟哟哟哟哟哟")->sendTg()->fetch();
|
||||
|
||||
业务:
|
||||
step()
|
||||
msg()
|
||||
data()
|
||||
aData()
|
||||
jData()
|
||||
sData()
|
||||
code()
|
||||
put()
|
||||
merge()
|
||||
toDone()
|
||||
noDone()
|
||||
step("start")
|
||||
|
||||
action:
|
||||
reset()
|
||||
done(?$msg)
|
||||
fail(?$msg, ?$aParentResult)
|
||||
sendTg() 伪action
|
||||
fetch() or get()
|
||||
fetchAll() or geAll()
|
||||
|
||||
set:
|
||||
enableTg();
|
||||
parent($aParentResult);
|
||||
|
||||
with:
|
||||
withTraceId();
|
||||
withTimestamp();
|
||||
withStep();
|
||||
|
||||
判断:
|
||||
::isDone($aResult);
|
||||
::isFail($aResult);
|
||||
|
||||
*/
|
||||
|
||||
class Flow
|
||||
{
|
||||
protected array $aStep = [];
|
||||
protected array $aParent = [];
|
||||
protected bool $isToTg = false;
|
||||
protected bool $isToTgOne = false;
|
||||
protected array $aResult = [
|
||||
'isDone' => false,
|
||||
];
|
||||
protected string $sName;
|
||||
private bool $isChain = false;
|
||||
|
||||
public function __construct(string $name = 'none')
|
||||
{
|
||||
$this->sName = $name;
|
||||
$this->aStep[] = "{$this->sName}::start";
|
||||
}
|
||||
|
||||
// new
|
||||
public static function make(string $name = 'none'): self
|
||||
{
|
||||
return new self($name);
|
||||
}
|
||||
|
||||
// new
|
||||
public static function start($sName = 'none')
|
||||
{
|
||||
$oInstance = new self($sName);
|
||||
$oInstance->isChain = true;
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
// option
|
||||
public function enableTg(bool $flag = true): self
|
||||
{
|
||||
$this->isToTg = $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// option
|
||||
public function enableTgOne(bool $flag = true): self
|
||||
{
|
||||
$this->enableTg(true);
|
||||
$this->isToTgOne = $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// option
|
||||
public function parent(array $aParentResult): self
|
||||
{
|
||||
$this->aParent = $aParentResult;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function step(string $step): self
|
||||
{
|
||||
$this->aStep[] = "{$this->sName}::{$step}";
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function msg($msg = "msg未设置"): self
|
||||
{
|
||||
if (is_array($msg)) {
|
||||
$msg = json_encode($msg);
|
||||
}
|
||||
$this->put('sMsg', $msg);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function aData(array $data): self
|
||||
{
|
||||
$this->put('aData', $data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function aDataPut($k, $v)
|
||||
{
|
||||
$this->aResult["aData"][$k] = $v;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function sData(string $data): self
|
||||
{
|
||||
$this->put('sData', $data);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function code(string $code): self
|
||||
{
|
||||
$this->put('sCode', $code);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function put(string $key, mixed $value, $sDataKey = ''): self
|
||||
{
|
||||
if ($sDataKey) {
|
||||
$this->aResult[$sDataKey][$key] = $value;
|
||||
} else {
|
||||
$this->aResult[$key] = $value;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function merge(array $data): self
|
||||
{
|
||||
foreach ($data as $k => $v) {
|
||||
$this->put($k, $v);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function setDone(bool $b = true): self
|
||||
{
|
||||
$this->aResult['isDone'] = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// data
|
||||
public function setFail(string $step = ''): self
|
||||
{
|
||||
if ($step) {
|
||||
$this->step($step);
|
||||
}
|
||||
$this->aResult['isDone'] = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// with
|
||||
public function withTraceId(string $id = null): self
|
||||
{
|
||||
$this->aResult['sTraceId'] = $id ?? uniqid('trace_', true);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// with
|
||||
public function withTimestamp(): self
|
||||
{
|
||||
$this->aResult['sTimestamp'] = (new \DateTime())->format(\DateTime::ATOM);
|
||||
return $this;
|
||||
}
|
||||
|
||||
// with
|
||||
public function withStep(bool $flag = true): self
|
||||
{
|
||||
if ($flag) {
|
||||
$this->withParentStep();
|
||||
$this->aResult['aStep'] = $this->aStep;
|
||||
} else {
|
||||
unset($this->aResult['aStep']);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
// action
|
||||
public function reset(): self
|
||||
{
|
||||
$this->aStep = [$this->sName . '::start'];
|
||||
$this->aParent = [];
|
||||
$this->isToTg = false;
|
||||
$this->isToTgOne = false;
|
||||
$this->aResult = ['isDone' => false];
|
||||
return $this;
|
||||
}
|
||||
|
||||
// action
|
||||
public function done(mixed $msg = null)
|
||||
{
|
||||
$this->setDone();
|
||||
if ($msg) {
|
||||
$this->msg($msg);
|
||||
}
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
// action
|
||||
public function fail(mixed $msg = null, array $aParentResult = [])
|
||||
{
|
||||
$this->setFail('fail');
|
||||
if ($aParentResult) {
|
||||
$this->aParent = $aParentResult;
|
||||
}
|
||||
if ($msg) {
|
||||
$this->msg($msg);
|
||||
}
|
||||
return $this->getFull();
|
||||
}
|
||||
|
||||
// action
|
||||
// public function sendTg() // 伪装成非set
|
||||
// {
|
||||
// $this->enableTgOne();
|
||||
// return $this;
|
||||
// }
|
||||
|
||||
// action
|
||||
public function sendTg($sBotCode = 'base', $sChatCode = 'base')
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public function getDataA()
|
||||
{
|
||||
return $this->aResult["aData"] ?? [];
|
||||
}
|
||||
|
||||
public function getDataS()
|
||||
{
|
||||
return (string) $this->aResult["sData"] ?? '';
|
||||
}
|
||||
|
||||
public function getDataI()
|
||||
{
|
||||
return (int) $this->aResult["iData"] ?? 0;
|
||||
}
|
||||
|
||||
public function getDataB()
|
||||
{
|
||||
return (bool) $this->aResult["bData"] ?? false;
|
||||
}
|
||||
|
||||
public function getDataX()
|
||||
{
|
||||
return $this->aResult["xData"] ?? '';
|
||||
}
|
||||
|
||||
public function setDataA(array $aData): self
|
||||
{
|
||||
$this->aData($aData);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataB(bool $bData): self
|
||||
{
|
||||
$this->aResult["bData"] = $bData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataS(string $sData): self
|
||||
{
|
||||
$this->aResult["sData"] = $sData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataI(int $iData): self
|
||||
{
|
||||
$this->aResult["iData"] = $iData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataX($xData): self
|
||||
{
|
||||
$this->aResult["xData"] = $xData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getResult(): array
|
||||
{
|
||||
return $this->aResult;
|
||||
}
|
||||
|
||||
// action
|
||||
public function get()
|
||||
{
|
||||
if ($this->isToTg) {
|
||||
$this->_sendTg();
|
||||
}
|
||||
|
||||
if ($this->isToTgOne) {
|
||||
$this->isToTg = false;
|
||||
$this->isToTgOne = false;
|
||||
}
|
||||
|
||||
if ($this->isChain) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->aResult;
|
||||
}
|
||||
|
||||
// action
|
||||
public function getFull()
|
||||
{
|
||||
$this->withStep();
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
// action
|
||||
public function toArray()
|
||||
{
|
||||
return $this->aResult;
|
||||
}
|
||||
|
||||
// helper
|
||||
public function isDone()
|
||||
{
|
||||
return $this->aResult["isDone"] ?? false;
|
||||
}
|
||||
|
||||
// helper
|
||||
public function isFail()
|
||||
{
|
||||
return !$this->isDone();
|
||||
}
|
||||
|
||||
// helper
|
||||
public static function isDoneResult(array $aResult): bool
|
||||
{
|
||||
return $aResult['isDone'] ?? false;
|
||||
}
|
||||
|
||||
// helper
|
||||
public static function isFailResult(array $aResult): bool
|
||||
{
|
||||
return !self::isDoneResult($aResult);
|
||||
}
|
||||
|
||||
// shell
|
||||
public function fetch()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
// shell
|
||||
public function fetchAll()
|
||||
{
|
||||
return $this->getFull();
|
||||
}
|
||||
|
||||
private function _sendTg()
|
||||
{
|
||||
TelegramVdb::make()->dataArr($this->aResult)->save();
|
||||
}
|
||||
|
||||
protected function addStepParent(): void
|
||||
{
|
||||
$this->aStep[] = $this->aParent;
|
||||
}
|
||||
|
||||
protected function withParentStep(): void
|
||||
{
|
||||
if ($this->aParent) {
|
||||
$this->addStepParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
261
app/Services/TomTool/HttpV2.php
Executable file
261
app/Services/TomTool/HttpV2.php
Executable file
@ -0,0 +1,261 @@
|
||||
<?php
|
||||
|
||||
// 版本:25-12-12
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool;
|
||||
|
||||
use App\Services\TomTool\Flow;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
|
||||
默认:
|
||||
method:post
|
||||
|
||||
new:
|
||||
HttpV2::make($url)
|
||||
|
||||
基本:
|
||||
HttpV2::make($url)->send()
|
||||
|
||||
进阶:
|
||||
HttpV2::make($url, "get")->setDataA($aData)->enableJsonAs()->enableAsync()->optMethod("get")->send();
|
||||
|
||||
action:
|
||||
send()
|
||||
|
||||
data:
|
||||
xData()
|
||||
sData()
|
||||
jData()
|
||||
sData()
|
||||
|
||||
set:
|
||||
optMethod()
|
||||
enableJsonAs()
|
||||
enableJsonSend()
|
||||
enableJsonReturn()
|
||||
|
||||
@note:
|
||||
默认关闭 SSL 验证(适用于开发环境),生产环境建议开启
|
||||
异步模式下不会返回响应内容,仅快速触发请求
|
||||
|
||||
*/
|
||||
|
||||
|
||||
class HttpV2
|
||||
{
|
||||
protected string $method;
|
||||
protected $data = [];
|
||||
protected string $url;
|
||||
protected bool $sendJson = false;
|
||||
protected bool $returnJson = false;
|
||||
protected bool $async = false;
|
||||
// private bool $isChain = false;
|
||||
// private array $aResult = [
|
||||
// "isDone" = false
|
||||
// ];
|
||||
|
||||
public static function make(string $url, string $method = 'post'): self
|
||||
{
|
||||
$instance = new self();
|
||||
$instance->url = $url;
|
||||
$instance->optMethod($method);
|
||||
return $instance;
|
||||
}
|
||||
|
||||
// public static function start(string $sUrl, string $sMethod = 'post'): self
|
||||
// {
|
||||
// $oInstance = new self();
|
||||
// $oInstance->url = $sUrl;
|
||||
// $oInstance->method = $sMethod;
|
||||
// $oInstance->isChain = true;
|
||||
// return $oInstance;
|
||||
// }
|
||||
//
|
||||
// public function isDone()
|
||||
// {
|
||||
// return $this->aResult["isDone"] ?? false;
|
||||
// }
|
||||
//
|
||||
// public function isFail()
|
||||
// {
|
||||
// return !$this->isDone();
|
||||
// }
|
||||
|
||||
// public function getResult()
|
||||
// {
|
||||
// return $this->aResult;
|
||||
// }
|
||||
|
||||
public function optMethod(string $method): self
|
||||
{
|
||||
$this->method = strtolower($method);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataX($xData)
|
||||
{
|
||||
$this->setData($xData);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataA($aData)
|
||||
{
|
||||
$this->setData($aData);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDataS($sData)
|
||||
{
|
||||
$this->setData($sData);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setData($xData)
|
||||
{
|
||||
// if (is_array($xData)) {
|
||||
// json_encode($xData)
|
||||
// }
|
||||
$this->data = $xData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// public function aData($aData = [])
|
||||
// {
|
||||
// $this->data($aData);
|
||||
// return $this;
|
||||
// }
|
||||
//
|
||||
// public function sData($sData = '')
|
||||
// {
|
||||
// $this->data($sData);
|
||||
// return $this;
|
||||
// }
|
||||
//
|
||||
// public function jData($jData = '')
|
||||
// {
|
||||
// $this->data($jData);
|
||||
// return $this;
|
||||
// }
|
||||
//
|
||||
// public function xData($xData = '')
|
||||
// {
|
||||
// $this->data($xData);
|
||||
// return $this;
|
||||
// }
|
||||
//
|
||||
// public function data($data = ''): self
|
||||
// {
|
||||
// $this->data = $data;
|
||||
// return $this;
|
||||
// }
|
||||
|
||||
public function enableJsonSend(bool $flag = true): self
|
||||
{
|
||||
$this->sendJson = $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function enableJsonReturn(bool $flag = true): self
|
||||
{
|
||||
$this->returnJson = $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function enableJsonAs(): self
|
||||
{
|
||||
$this->sendJson = true;
|
||||
$this->returnJson = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function enableAsync(bool $flag = true): self
|
||||
{
|
||||
$this->async = $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send(): string
|
||||
{
|
||||
$oFlow = Flow::make("HttpV2::send");
|
||||
|
||||
$ch = curl_init();
|
||||
$headers = [];
|
||||
|
||||
// 构建 URL 和请求体
|
||||
if ($this->method === 'get') {
|
||||
$url = $this->url . '?' . http_build_query($this->data);
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_HTTPGET, true);
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_URL, $this->url);
|
||||
$payload = $this->sendJson ? json_encode($this->data) : http_build_query($this->data);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
||||
|
||||
if ($this->method === 'post') {
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
} else {
|
||||
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, strtoupper($this->method));
|
||||
}
|
||||
|
||||
if ($this->sendJson) {
|
||||
$headers[] = 'Content-Type: application/json';
|
||||
$headers[] = 'Content-Length: ' . strlen($payload);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->returnJson) {
|
||||
$headers[] = 'Accept: application/json';
|
||||
}
|
||||
|
||||
if (!empty($headers)) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
|
||||
// SSL 设置
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
|
||||
// 异步发送
|
||||
if ($this->async) {
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 200);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 200);
|
||||
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, false);
|
||||
curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return 'sent';
|
||||
}
|
||||
|
||||
// 阻塞执行
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
$error = curl_error($ch);
|
||||
curl_close($ch);
|
||||
throw new Exception("cURL Error: {$error}");
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
|
||||
return $response;
|
||||
// $this->aResult = $oFlow->sData($response)->done();
|
||||
//
|
||||
// if ($this->isChain) {
|
||||
// return $this;
|
||||
// }
|
||||
//
|
||||
// return $this->aResult;
|
||||
}
|
||||
|
||||
// public static function response(int $code, string $message = ''): void
|
||||
// {
|
||||
// http_response_code($code);
|
||||
// echo $message;
|
||||
// exit;
|
||||
// }
|
||||
}
|
||||
139
app/Services/TomTool/Telegram/Master.php
Executable file
139
app/Services/TomTool/Telegram/Master.php
Executable file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool\Telegram;
|
||||
|
||||
use App\Services\HttpQueue as ServiceHttpQueue;
|
||||
use App\Services\TomTool\Flow;
|
||||
use App\Services\TomTool\Telegram\Sdk as ServiceTelegramSdk;
|
||||
use App\Models\TelegramKey as ModelTelegramKey;
|
||||
|
||||
/**
|
||||
|
||||
注意是master服务器端专用的,这里会对code找map,slave不会。
|
||||
|
||||
new:
|
||||
start(?$sBodeCode, ?$sChatCode)
|
||||
|
||||
set:
|
||||
setBotCode()
|
||||
setChatCode()
|
||||
setBotToken()
|
||||
setChatId()
|
||||
setMsgS()
|
||||
|
||||
action:
|
||||
send()
|
||||
|
||||
*/
|
||||
|
||||
final class Master
|
||||
{
|
||||
public string $sBotCode = "base";
|
||||
public string $sChatCode = "base";
|
||||
public string $sBotToken = '';
|
||||
public int $iChatId = 0;
|
||||
|
||||
public string $sMsg = '';
|
||||
|
||||
public bool $enableQueue = false; // 应该用不到了
|
||||
|
||||
public bool $bKeyBegin = false;
|
||||
|
||||
public static function start($sBotCode = 'base', $sChatCode = 'base'): self
|
||||
{
|
||||
$oInstance = new self();
|
||||
$oInstance->sBotCode = $sBotCode;
|
||||
$oInstance->sChatCode = $sChatCode;
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
public function setBotCode(string $sBotCode): self
|
||||
{
|
||||
$this->sBotCode = $sBotCode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setChatCode(string $sChatCode): self
|
||||
{
|
||||
$this->sChatCode = $sChatCode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBotToken(string $sBotToken): self
|
||||
{
|
||||
$this->sBotToken = $sBotToken;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setChatId(int $iChatId): self
|
||||
{
|
||||
$this->iChatId = $iChatId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMsgS(string $sMsg): self
|
||||
{
|
||||
$this->sMsg = $sMsg;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send($sMsg = ''): Flow
|
||||
{
|
||||
if ($sMsg) {
|
||||
$this->sMsg = $sMsg;
|
||||
}
|
||||
|
||||
if (!$this->sMsg) {
|
||||
throw new \Exception("未设置msg");
|
||||
}
|
||||
|
||||
$this->keyBegin();
|
||||
|
||||
if ($this->enableQueue) {
|
||||
$aData = $this->buildDataTom();
|
||||
$oFlow = ServiceHttpQueue::start("telegram_local")->arg($aData)->save();
|
||||
} else {
|
||||
$oFlow = ServiceTelegramSdk::start()
|
||||
->setBotToken($this->sBotToken)
|
||||
->setChatId($this->iChatId)
|
||||
->setMsgS($this->sMsg)
|
||||
->send();
|
||||
}
|
||||
|
||||
return $oFlow;
|
||||
}
|
||||
|
||||
private function keyBegin()
|
||||
{
|
||||
if (!$this->bKeyBegin) {
|
||||
if (!$this->sBotToken) {
|
||||
$this->sBotToken = ModelTelegramKey::botTokenByCode($this->sBotCode);
|
||||
}
|
||||
|
||||
if (!$this->iChatId) {
|
||||
$this->iChatId = ModelTelegramKey::chatIdByCode($this->sChatCode);
|
||||
}
|
||||
|
||||
if (!$this->sBotToken || !$this->iChatId) {
|
||||
throw new \RuntimeException("botToken或chatId没找到,botCode={$this->sBotCode},chatCode={$this->sChatCode}");
|
||||
}
|
||||
|
||||
$this->bKeyBegin = true;
|
||||
}
|
||||
}
|
||||
|
||||
private function buildDataTom(): array
|
||||
{
|
||||
return [
|
||||
"sBotCode" => $this->sBotCode ?? '',
|
||||
"sChatCode" => $this->sChatCode ?? '',
|
||||
"sBotToken" => $this->sBotToken ?? '',
|
||||
"iChatId" => $this->iChatId ?? '',
|
||||
"sMsg" => $this->sMsg ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
134
app/Services/TomTool/Telegram/Sdk.php
Executable file
134
app/Services/TomTool/Telegram/Sdk.php
Executable file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool\Telegram;
|
||||
use Telegram\Bot\Api;
|
||||
use Telegram\Bot\Exceptions\TelegramSDKException;
|
||||
use App\Services\TomTool\Flow;
|
||||
|
||||
class Sdk
|
||||
{
|
||||
public $sMsgFormat = [];
|
||||
public $sMsgFormatType = 'none';
|
||||
public $sBotToken = '';
|
||||
public $iChatId = 0;
|
||||
public $sMsg;
|
||||
public $oApi;
|
||||
|
||||
private const ALLOWED_FORMATS = ['none', 'html', 'markdown', 'markdownV2'];
|
||||
|
||||
public static function start()
|
||||
{
|
||||
$oInstance = new self();
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
public function setBotToken($sBotToken)
|
||||
{
|
||||
$this->oApi = new Api($sBotToken);
|
||||
$this->sBotToken = $sBotToken;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setChatId($iChatId)
|
||||
{
|
||||
$this->iChatId = $iChatId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMsgS($sMsg = '')
|
||||
{
|
||||
$this->sMsg = $sMsg;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function send()
|
||||
{
|
||||
$oFlow = Flow::start("tg_sdk_send");
|
||||
|
||||
$this->msgFormat();
|
||||
|
||||
try {
|
||||
$r = $this->oApi->sendMessage($this->sMsgFormat);
|
||||
if (!$r->isOk()) {
|
||||
return $oFlow->fail();
|
||||
}
|
||||
} catch (TelegramSDKException $e) {
|
||||
return $oFlow->fail(['error' => $e->getMessage()]);
|
||||
}
|
||||
|
||||
return $oFlow->done();
|
||||
}
|
||||
|
||||
public function getMsgFormat()
|
||||
{
|
||||
$this->msgFormat();
|
||||
|
||||
return $this->sMsgFormat;
|
||||
}
|
||||
|
||||
public function msgFormat()
|
||||
{
|
||||
if (!in_array($this->sMsgFormatType, self::ALLOWED_FORMATS, true)) {
|
||||
throw new \RuntimeException("不支持的格式类型: {$this->sMsgFormatType}");
|
||||
}
|
||||
|
||||
$method = 'msgFormat_' . $this->sMsgFormatType;
|
||||
$this->sMsgFormat = $this->$method();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function msgFormat_none()
|
||||
{
|
||||
return [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => $this->sMsg,
|
||||
'parse_mode' => '',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
}
|
||||
|
||||
private function msgFormat_html()
|
||||
{
|
||||
return [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => strip_tags($this->sMsg, [
|
||||
'b', 'strong', 'i', 'em', 'u', 'ins', 's', 'strike', 'del', 'span', 'tg-spoiler', 'a', 'tg-emoji',
|
||||
'code', 'pre',
|
||||
]),
|
||||
'parse_mode' => 'HTML',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
}
|
||||
|
||||
private function msgFormat_markdown()
|
||||
{
|
||||
return [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => $this->sMsg,
|
||||
'parse_mode' => 'Markdown',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
}
|
||||
|
||||
private function msgFormat_markdownV2()
|
||||
{
|
||||
return [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => $this->sMsg,
|
||||
'parse_mode' => 'MarkdownV2',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
322
app/Services/TomTool/Telegram/Slave.php
Executable file
322
app/Services/TomTool/Telegram/Slave.php
Executable file
@ -0,0 +1,322 @@
|
||||
<?php
|
||||
|
||||
// 版本 25/12/12
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool\Telegram;
|
||||
|
||||
use App\Services\TomTool\HttpV2;
|
||||
use App\Services\TomTool\Telegram\Sdk as ServiceTelegramSdk;
|
||||
use App\Services\TomTool\Flow;
|
||||
use App\Services\HttpQueue as ServiceHttpQueue;
|
||||
|
||||
/**
|
||||
|
||||
提醒:
|
||||
master自身已经没有队列了,收到slave消息直接转发
|
||||
|
||||
默认:
|
||||
走本地队列,发送到master
|
||||
走异步
|
||||
|
||||
new:
|
||||
start()
|
||||
log()
|
||||
warn()
|
||||
fail()
|
||||
notify()
|
||||
|
||||
opt:
|
||||
enableMaster(:true)
|
||||
enableMasterQueue(:true)
|
||||
enableSlaveQueue(:true)
|
||||
enableDetail(:true)
|
||||
|
||||
set:
|
||||
setMsgS()
|
||||
setMsgA()
|
||||
setBotCode()
|
||||
setChatCode()
|
||||
setBotToken()
|
||||
setChatId()
|
||||
|
||||
action:
|
||||
send()
|
||||
sendMaster()
|
||||
sendLocal()
|
||||
|
||||
*/
|
||||
|
||||
class Slave
|
||||
{
|
||||
public string $sBotCode;
|
||||
public string $sChatCode;
|
||||
|
||||
public string $sBotToken = '';
|
||||
public int $iChatId = 0;
|
||||
|
||||
public string $sMsg = '';
|
||||
|
||||
public bool $enableMaster = true;
|
||||
public bool $enableMasterQueue = false; // 这里之前想错了,不会有master队列,只在slave有,master转发就行了
|
||||
public bool $enableSlaveQueue = true;
|
||||
|
||||
public bool $enableDetail = true;
|
||||
|
||||
public bool $enableAsync = true;
|
||||
|
||||
private bool $enableSend = true;
|
||||
|
||||
// new
|
||||
public static function start(string $sBotCode = 'base', string $sChatCode = 'base'): self
|
||||
{
|
||||
$oInstance = new self;
|
||||
$oInstance->sBotCode = $sBotCode;
|
||||
$oInstance->sChatCode = $sChatCode;
|
||||
$oInstance->enableSend = filter_var($_ENV["tg_send_enable"] ?? true, FILTER_VALIDATE_BOOLEAN);
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
// new
|
||||
public static function log(string $sChatCode = 'admin'): self
|
||||
{
|
||||
return self::start("log", $sChatCode);
|
||||
}
|
||||
|
||||
// new
|
||||
public static function warn(string $sChatCode = 'admin'): self
|
||||
{
|
||||
return self::start("warn", $sChatCode);
|
||||
}
|
||||
|
||||
// new
|
||||
public static function fail(string $sChatCode = 'admin'): self
|
||||
{
|
||||
return self::start("fail", $sChatCode);
|
||||
}
|
||||
|
||||
// new
|
||||
public static function notify(string $sChatCode = 'admin'): self
|
||||
{
|
||||
return self::start("fail", $sChatCode);
|
||||
}
|
||||
|
||||
|
||||
// opt
|
||||
public function enableAsync(bool $b = true): self
|
||||
{
|
||||
$this->enableAsync = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// opt
|
||||
public function enableDetail(bool $b = true): self
|
||||
{
|
||||
$this->enableDetail = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// opt
|
||||
public function enableSlaveQueue(bool $b = true): self
|
||||
{
|
||||
$this->enableSlaveQueue = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// opt
|
||||
public function enableMaster(bool $b = true): self
|
||||
{
|
||||
$this->enableMaster = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// opt
|
||||
public function enableMasterQueue(bool $b = true): self
|
||||
{
|
||||
$this->enableMasterQueue = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// set
|
||||
public function setMsgS(string $sMsg = ''): self
|
||||
{
|
||||
if ($this->enableDetail) {
|
||||
$sMsg = "[ ".$this->getEnvSiteCode()." | ".date("d:H:i:s")." ] ".$sMsg;
|
||||
}
|
||||
|
||||
$this->sMsg = $sMsg;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// set
|
||||
public function setMsgA(array $aMsg = []): self
|
||||
{
|
||||
$aMsgNew = $aMsg;
|
||||
|
||||
if ($this->enableDetail) {
|
||||
$aMsgNew = [];
|
||||
$aMsgNew["site_code"] = $this->getEnvSiteCode();
|
||||
$aMsgNew["date"] = date("Y-m-d H:i:s");
|
||||
$aMsgNew["data"] = $aMsg;
|
||||
}
|
||||
|
||||
$this->sMsg = json_encode($aMsgNew, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// set
|
||||
public function setBotCode(string $sBotCode): self
|
||||
{
|
||||
$this->sBotCode = $sBotCode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// set
|
||||
public function setChatCode(string $sChatCode): self
|
||||
{
|
||||
$this->sChatCode = $sChatCode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// set
|
||||
public function setBotToken(string $sBotToken): self
|
||||
{
|
||||
$this->sBotToken = $sBotToken;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// set
|
||||
public function setChatId(int $iChatId): self
|
||||
{
|
||||
$this->iChatId = $iChatId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
// action
|
||||
public function send($xMsg = ''): Flow
|
||||
{
|
||||
if ($this->enableSend == false) {
|
||||
$oFlow = Flow::start();
|
||||
return $oFlow->done("不发送");
|
||||
}
|
||||
|
||||
if ($xMsg) {
|
||||
if (is_array($xMsg)) {
|
||||
$this->setMsgA($xMsg);
|
||||
} else {
|
||||
$this->setMsgS($xMsg);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->sMsg) {
|
||||
throw new Exception("未设置msg");
|
||||
}
|
||||
|
||||
if ($this->enableMaster) {
|
||||
$oFlow = $this->_send_master();
|
||||
} else {
|
||||
$oFlow = $this->_send_local();
|
||||
}
|
||||
|
||||
return $oFlow;
|
||||
}
|
||||
|
||||
// action
|
||||
public function sendMaster($xMsg = ''): Flow
|
||||
{
|
||||
$this->enableMaster(true);
|
||||
return $this->send($xMsg);
|
||||
}
|
||||
|
||||
// action
|
||||
public function sendLocal($xMsg = ''): Flow
|
||||
{
|
||||
$this->enableMaster(false);
|
||||
return $this->send($xMsg);
|
||||
}
|
||||
|
||||
private function _send_master(): Flow
|
||||
{
|
||||
$aData = $this->buildDataTom();
|
||||
|
||||
if ($this->enableSlaveQueue) {
|
||||
$oFlow = ServiceHttpQueue::start("telegram_master")->arg($aData)->save();
|
||||
} else {
|
||||
|
||||
$oFlow = Flow::start("_send_master");
|
||||
$sUrlMaSterBase = $_ENV["url_master_base"] ?? "";
|
||||
|
||||
if (!$sUrlMaSterBase) {
|
||||
throw new \Exception("未设置env的url_master_base");
|
||||
}
|
||||
|
||||
$sUrlMasterPost = "https://".$sUrlMaSterBase."/api/telegram/post";
|
||||
|
||||
try {
|
||||
|
||||
$oHttpV2 = HttpV2::make($sUrlMasterPost);
|
||||
|
||||
if ($this->enableAsync) {
|
||||
$oHttpV2 = $oHttpV2->enableAsync();
|
||||
}
|
||||
|
||||
$r = $oHttpV2->enableJsonAs()->setData($aData)->send();
|
||||
|
||||
if ($this->enableAsync) {
|
||||
return $oFlow->sData("async")->done("async");
|
||||
} else {
|
||||
$a = json_decode($r, true);
|
||||
$isDone = $a["isDone"] ?? false;
|
||||
|
||||
if ($isDone) {
|
||||
return $oFlow->done();
|
||||
} else {
|
||||
return $oFlow->fail($r);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
$oFlow = $oFlow->fail($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return $oFlow;
|
||||
}
|
||||
|
||||
private function _send_local(): Flow
|
||||
{
|
||||
if ($this->enableSlaveQueue) {
|
||||
$aData = $this->buildDataTom();
|
||||
$oFlow = ServiceHttpQueue::start("telegram_local")->arg($aData)->save();
|
||||
} else {
|
||||
$oFlow = ServiceTelegramSdk::start($this->sBotToken, $this->iChatId)->setMsgS($this->sMsg)->send();
|
||||
}
|
||||
|
||||
return $oFlow;
|
||||
}
|
||||
|
||||
private function buildDataTom(): array
|
||||
{
|
||||
return [
|
||||
"sBotCode" => $this->sBotCode ?? '',
|
||||
"sChatCode" => $this->sChatCode ?? '',
|
||||
"sBotToken" => $this->sBotToken ?? '',
|
||||
"iChatId" => $this->iChatId ?? '',
|
||||
"enableMasterQueue" => $this->enableMasterQueue ?? '',
|
||||
"enableMaster" => $this->enableMaster,
|
||||
"sMsg" => $this->sMsg ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
private function getEnvSiteCode(): string
|
||||
{
|
||||
$sEnvSiteCode = $_ENV["site_code"] ?? "未设置env的site_code";
|
||||
|
||||
return $sEnvSiteCode;
|
||||
}
|
||||
|
||||
}
|
||||
121
app/Services/TomTool/TelegramV2.php
Executable file
121
app/Services/TomTool/TelegramV2.php
Executable file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\IM;
|
||||
|
||||
use App\Models\Config;
|
||||
use Telegram\Bot\Api;
|
||||
use Telegram\Bot\Exceptions\TelegramSDKException;
|
||||
use function strip_tags;
|
||||
|
||||
// 没有必须,默认使用base配置
|
||||
final class TelegramV2
|
||||
{
|
||||
private Api $bot;
|
||||
public $iTo;
|
||||
public $sToken;
|
||||
public $sMsgType = false;
|
||||
|
||||
public function __construct($sToken = "base", $sTo = "base")
|
||||
{
|
||||
$this->setToken($sToken);
|
||||
|
||||
$this->setTo($sTo);
|
||||
|
||||
// $this->bot = new Api($this->sToken);
|
||||
}
|
||||
|
||||
public function setMsgType($sMsgType)
|
||||
{
|
||||
$this->sMsgType = $sMsgType;
|
||||
}
|
||||
|
||||
public function setTo($xTo, $sType = "code")
|
||||
{
|
||||
$iChatId = $xTo;
|
||||
|
||||
if ($sType == "code") {
|
||||
// $sEnvKey = "tgChat_".$xTo;
|
||||
$iChatId = $_ENV['tgChat'][$iChatId];
|
||||
}
|
||||
|
||||
$this->iTo = $iChatId;
|
||||
}
|
||||
|
||||
public function setToken($xToken, $sType = "code")
|
||||
{
|
||||
$sToken = $xToken;
|
||||
|
||||
if ($sType == "code") {
|
||||
// $sEnvKey = "tgToken_".$xToken;
|
||||
$sToken = $_ENV['tgToken'][$sToken];
|
||||
}
|
||||
|
||||
$this->sToken = $sToken;
|
||||
|
||||
$this->bot = new Api($this->sToken);
|
||||
}
|
||||
|
||||
public function send($sMsg, $sMsgType = 'str')
|
||||
{
|
||||
if ($sMsgType == "arr") {
|
||||
$sMsg = json_encode($sMsg, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
if ($this->sMsgType === false) {
|
||||
$sendMessage = [
|
||||
'chat_id' => $this->iTo,
|
||||
'text' => $sMsg,
|
||||
'parse_mode' => '',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
} else if ($this->sMsgType === "html") {
|
||||
$sendMessage = [
|
||||
'chat_id' => $this->iTo,
|
||||
'text' => strip_tags(
|
||||
$sMsg,
|
||||
['b', 'strong', 'i', 'em', 'u', 'ins', 's', 'strike','del', 'span','tg-spoiler', 'a', 'tg-emoji',
|
||||
'code', 'pre',
|
||||
]
|
||||
),
|
||||
'parse_mode' => 'HTML',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
} else if ($this->sMsgType === "markdown") {
|
||||
$sendMessage = [
|
||||
'chat_id' => $this->iTo,
|
||||
'text' => $sMsg,
|
||||
'parse_mode' => 'Markdown',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
} else if ($this->sMsgType === "markdownV2") {
|
||||
$sendMessage = [
|
||||
'chat_id' => $this->iTo,
|
||||
'text' => $sMsg,
|
||||
'parse_mode' => 'MarkdownV2',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
} else {
|
||||
$sendMessage = [
|
||||
'chat_id' => $this->iTo,
|
||||
'text' => $sMsg,
|
||||
'parse_mode' => '',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
}
|
||||
|
||||
return $this->bot->sendMessage($sendMessage);
|
||||
}
|
||||
|
||||
}
|
||||
362
app/Services/TomTool/TelegramVdb_rengle.php
Executable file
362
app/Services/TomTool/TelegramVdb_rengle.php
Executable file
@ -0,0 +1,362 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool;
|
||||
|
||||
use App\Services\HttpQueue as ServiceHttpQueue;
|
||||
use App\Services\TomTool\Flow;
|
||||
use App\Models\TelegramKey as ModelTelegramKey;
|
||||
use Telegram\Bot\Api;
|
||||
use Telegram\Bot\Exceptions\TelegramSDKException;
|
||||
use function strip_tags;
|
||||
|
||||
/**
|
||||
|
||||
更新:
|
||||
data会save清空,不再属于set
|
||||
|
||||
new:
|
||||
TelegramVdb::make(?$botCode, ?$chatCode)
|
||||
|
||||
快速:
|
||||
TelegramVdb::make()->save($sData)
|
||||
|
||||
进阶:
|
||||
TelegramVdb::make()->dataArr($aData)->setFormat("html")->save();
|
||||
TelegramVdb::make()->setFormat()->data($xData)->toJson()->save();
|
||||
|
||||
data:
|
||||
data[Arr/Str/Json]($data)
|
||||
data($aData)->toJson()
|
||||
|
||||
action:
|
||||
save()
|
||||
|
||||
set:
|
||||
setChatCode($code)
|
||||
setBotCode($code)
|
||||
setChatId($id) 覆盖code
|
||||
setBotToken($token) 覆盖code
|
||||
setFormat($type)
|
||||
enableDate()
|
||||
|
||||
*/
|
||||
|
||||
final class TelegramVdb
|
||||
{
|
||||
public $sBotCode;
|
||||
public $sChatCode;
|
||||
public $sBotToken = null;
|
||||
public $iChatId = null;
|
||||
public $sMsg = '';
|
||||
public $sMsgFormat = '';
|
||||
public $sMsgFormatType = 'none';
|
||||
public $bEnableDate = false;
|
||||
private $bKeyBegin = false;
|
||||
public $sClient = "master";
|
||||
|
||||
private const ALLOWED_FORMATS = ['none', 'html', 'markdown', 'markdownV2'];
|
||||
|
||||
public static function log()
|
||||
{
|
||||
return self::make("log", "admin");
|
||||
}
|
||||
|
||||
public static function warn()
|
||||
{
|
||||
return self::make("warn", "admin");
|
||||
}
|
||||
|
||||
public static function fail()
|
||||
{
|
||||
return self::make("fail", "admin");
|
||||
}
|
||||
|
||||
public static function notify()
|
||||
{
|
||||
return self::make("notify", "admin");
|
||||
}
|
||||
|
||||
public static function make($sBotCode = "base", $sChatCode = "base")
|
||||
{
|
||||
$oInstance = new self();
|
||||
$oInstance->sBotCode = $sBotCode;
|
||||
$oInstance->sChatCode = $sChatCode;
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
public function send($sMsg = '')
|
||||
{
|
||||
return $this->_ok($sMsg, true);
|
||||
}
|
||||
|
||||
public function save($sMsg = '')
|
||||
{
|
||||
return $this->_ok($sMsg);
|
||||
}
|
||||
|
||||
private function sendNow()
|
||||
{
|
||||
$oResult = Flow::make("send");
|
||||
$oBot = new Api($this->sBotToken);
|
||||
|
||||
$r = $oBot->sendMessage($this->sMsgFormat);
|
||||
|
||||
if ($r->isOk()){
|
||||
return $oResult->done();
|
||||
} else {
|
||||
return $oResult->fail("send失败");
|
||||
}
|
||||
}
|
||||
|
||||
private function HttpQueueSave()
|
||||
{
|
||||
$aTelegramArg = [
|
||||
"bot_token" => $this->sBotToken,
|
||||
"chat_id" => $this->iChatId,
|
||||
"msg" => $this->sMsgFormat,
|
||||
];
|
||||
|
||||
$aReturn = ServiceHttpQueue::start("telegram")->arg($aTelegramArg)->save()->getResult();
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
public function _ok($sMsg = '', $bSendNow = false)
|
||||
{
|
||||
$bTgSendEnable = $_ENV["tg_send_enable"] ?? false;
|
||||
if (!$bTgSendEnable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$oResult = Flow::make("save");
|
||||
|
||||
$this->keyBegin();
|
||||
|
||||
if ($sMsg) {
|
||||
if (is_array($sMsg)) {
|
||||
$this->aData($sMsg);
|
||||
} else {
|
||||
$this->sData($sMsg);
|
||||
}
|
||||
}
|
||||
|
||||
$this->msgFormat();
|
||||
|
||||
if ($bSendNow) {
|
||||
$aReturn = $this->sendNow();
|
||||
} else {
|
||||
$aReturn = $this->HttpQueueSave();
|
||||
}
|
||||
|
||||
$this->sMsg = '';
|
||||
|
||||
return $aReturn;
|
||||
}
|
||||
|
||||
public function enableDate($b = true)
|
||||
{
|
||||
$this->bEnableDate = $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function data($xData)
|
||||
{
|
||||
$this->sMsg = $xData;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function jData($sMsg = '')
|
||||
{
|
||||
$this->dataJson($sMsg);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function aData($sMsg = [])
|
||||
{
|
||||
$this->dataArr($sMsg);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function sData($sMsg = '')
|
||||
{
|
||||
$this->dataStr($sMsg);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toJson()
|
||||
{
|
||||
$this->withDateArr();
|
||||
$this->sMsg = json_encode($this->sMsg, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dataStr($sMsg = '')
|
||||
{
|
||||
$this->withDateStr();
|
||||
$this->sMsg = $sMsg;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dataArr($sMsg = [])
|
||||
{
|
||||
$this->withDateArr();
|
||||
$this->sMsg = json_encode($sMsg, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dataJson($sMsg = '')
|
||||
{
|
||||
$this->dataStr($sMsg);
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function withDateArr()
|
||||
{
|
||||
if ($this->bEnableDate) {
|
||||
$this->sMsg["date"] = date("Y-m-d H:i:s");
|
||||
}
|
||||
}
|
||||
|
||||
private function withDateStr()
|
||||
{
|
||||
if ($this->bEnableDate) {
|
||||
$this->sMsg = '['.date("Y-m-d H:i:s").'] '.$this->sMsg;
|
||||
}
|
||||
}
|
||||
|
||||
public function setFormat($sMsgFormatType = "none")
|
||||
{
|
||||
$this->sMsgFormatType = $sMsgFormatType;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBotCode($sBotCode)
|
||||
{
|
||||
$this->sBotCode = $sBotCode;
|
||||
$this->bKeyBegin = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setChatCode($sChatCode)
|
||||
{
|
||||
$this->sChatCode = $sChatCode;
|
||||
$this->bKeyBegin = false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setBotToken($sBotToken)
|
||||
{
|
||||
$this->sBotToken = $sBotToken;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setChatId($iChatId)
|
||||
{
|
||||
$this->iChatId = $iChatId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function keyBegin()
|
||||
{
|
||||
if (!$this->bKeyBegin) {
|
||||
if (!$this->sBotToken) {
|
||||
$this->sBotToken = $this->botTokenByCode();
|
||||
}
|
||||
|
||||
if (!$this->iChatId) {
|
||||
$this->iChatId = $this->chatIdByCode();
|
||||
}
|
||||
|
||||
if (!$this->sBotToken || !$this->iChatId) {
|
||||
throw new \RuntimeException("botToken或chatId没找到,botCode={$this->sBotCode},chatCode={$this->sChatCode}");
|
||||
}
|
||||
|
||||
$this->bKeyBegin = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function msgFormat()
|
||||
{
|
||||
if (!in_array($this->sMsgFormatType, self::ALLOWED_FORMATS, true)) {
|
||||
throw new \RuntimeException("不支持的格式类型: {$this->sMsgFormatType}");
|
||||
}
|
||||
|
||||
$method = 'msgFormat_' . $this->sMsgFormatType;
|
||||
$this->$method();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function botTokenByCode()
|
||||
{
|
||||
return ModelTelegramKey::botTokenByCode($this->sBotCode);
|
||||
}
|
||||
|
||||
private function chatIdByCode()
|
||||
{
|
||||
return ModelTelegramKey::chatIdByCode($this->sChatCode);
|
||||
}
|
||||
|
||||
private function msgFormat_none()
|
||||
{
|
||||
$this->sMsgFormat = [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => $this->sMsg,
|
||||
'parse_mode' => '',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function msgFormat_html()
|
||||
{
|
||||
$this->sMsgFormat = [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => strip_tags($this->sMsg, [
|
||||
'b', 'strong', 'i', 'em', 'u', 'ins', 's', 'strike', 'del', 'span', 'tg-spoiler', 'a', 'tg-emoji',
|
||||
'code', 'pre',
|
||||
]),
|
||||
'parse_mode' => 'HTML',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function msgFormat_markdown()
|
||||
{
|
||||
$this->sMsgFormat = [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => $this->sMsg,
|
||||
'parse_mode' => 'Markdown',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function msgFormat_markdownV2()
|
||||
{
|
||||
$this->sMsgFormat = [
|
||||
'chat_id' => $this->iChatId,
|
||||
'text' => $this->sMsg,
|
||||
'parse_mode' => 'MarkdownV2',
|
||||
'disable_web_page_preview' => false,
|
||||
'reply_to_message_id' => null,
|
||||
'reply_markup' => null,
|
||||
];
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
130
app/Services/TomTool/ThrowableHandler.php
Executable file
130
app/Services/TomTool/ThrowableHandler.php
Executable file
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool;
|
||||
|
||||
use Throwable as ThrowableBase;
|
||||
use Illuminate\Database\QueryException;
|
||||
use App\Services\TomTool\TelegramVdb;
|
||||
|
||||
/**
|
||||
|
||||
new:
|
||||
$oThrowableHandler = ThrowableHandler::make($e);
|
||||
|
||||
快速:
|
||||
$aResult = ThrowableHandler::make($e)->toArr();
|
||||
|
||||
action:
|
||||
fetch() or get()
|
||||
|
||||
set:
|
||||
enableTg()
|
||||
enableTrace()
|
||||
setMaxDepth()
|
||||
|
||||
*/
|
||||
|
||||
class ThrowableHandler
|
||||
{
|
||||
protected bool $tgEnable = false;
|
||||
protected bool $showTrace = false;
|
||||
protected int $maxDepth = 3;
|
||||
protected ThrowableBase $e;
|
||||
|
||||
public static function make(ThrowableBase $e): self
|
||||
{
|
||||
$oInstance = new self();
|
||||
$oInstance->e = $e;
|
||||
return $oInstance;
|
||||
}
|
||||
|
||||
public function fetch()
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
public function get(): array
|
||||
{
|
||||
$data = $this->buildExceptionData($this->e, 0);
|
||||
|
||||
if ($this->tgEnable) {
|
||||
$this->sendTelegram($data);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function toArr(): array
|
||||
{
|
||||
return $this->get();
|
||||
}
|
||||
|
||||
public function toJson(): string
|
||||
{
|
||||
return json_encode($this->get(), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
public function enableTg(bool $enable = true): self
|
||||
{
|
||||
$this->tgEnable = $enable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function enableTrace(bool $enable = true): self
|
||||
{
|
||||
$this->showTrace = $enable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setMaxDepth(int $depth): self
|
||||
{
|
||||
$this->maxDepth = max(1, $depth);
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function buildExceptionData(ThrowableBase $e, int $depth): array
|
||||
{
|
||||
$data = [
|
||||
'message' => $e->getMessage(),
|
||||
'file' => $e->getFile(),
|
||||
'line' => $e->getLine(),
|
||||
];
|
||||
|
||||
$code = $e->getCode();
|
||||
if ($code !== null && $code !== 0) {
|
||||
$data['code'] = $code;
|
||||
}
|
||||
|
||||
if ($this->showTrace) {
|
||||
$filteredTrace = array_filter($e->getTrace(), function ($frame) {
|
||||
return empty($frame['file']) || !str_contains($frame['file'], '/vendor/');
|
||||
});
|
||||
|
||||
$traceLines = [];
|
||||
foreach ($filteredTrace as $frame) {
|
||||
$file = $frame['file'] ?? '[internal]';
|
||||
$line = $frame['line'] ?? '';
|
||||
$func = isset($frame['class'], $frame['function'])
|
||||
? "{$frame['class']}{$frame['type']}{$frame['function']}"
|
||||
: ($frame['function'] ?? '[unknown]');
|
||||
$traceLines[] = "{$file}:{$line} {$func}()";
|
||||
}
|
||||
|
||||
$data['trace'] = implode("\n", $traceLines);
|
||||
}
|
||||
|
||||
if ($depth < $this->maxDepth && $e->getPrevious() instanceof ThrowableBase) {
|
||||
$data['previous'] = $this->buildExceptionData($e->getPrevious(), $depth + 1);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function sendTelegram(array $data): void
|
||||
{
|
||||
TelegramVdb::make()->aData($data)->save();
|
||||
}
|
||||
}
|
||||
|
||||
21
app/Services/TomTool/Tom.php
Executable file
21
app/Services/TomTool/Tom.php
Executable file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool;
|
||||
|
||||
class Tom
|
||||
{
|
||||
public static function toJson($aData)
|
||||
{
|
||||
return json_encode($aData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
public static function toJsonBr($aData)
|
||||
{
|
||||
$sData = self::toJson($aData);
|
||||
$sData = str_replace("\\n", "<br>", $sData);
|
||||
|
||||
return $sData;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,2 +1,2 @@
|
||||
User-agent: *
|
||||
Disallow:
|
||||
Allow: /
|
||||
|
||||
@ -95,24 +95,16 @@
|
||||
|
||||
<h2>免费节点订阅链接:</h2>
|
||||
|
||||
<p><strong>v2ray订阅链接:</strong></p>
|
||||
|
||||
<p>
|
||||
<a href='javascript:;' data-clipboard-text="{{$aData['v2rayPath']}}" class='copy-permalink'>
|
||||
<span class='subCopy'>
|
||||
<i class='iconfont icon-link'></i> {{$aData['v2rayPath']}}
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p><strong>clash订阅链接:</strong></p>
|
||||
<p>
|
||||
<a href='javascript:;' data-clipboard-text="{{$aData['clashPath']}}" class='copy-permalink'>
|
||||
<span class='subCopy'>
|
||||
<i class='iconfont icon-link'></i> {{$aData['clashPath']}}
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@foreach ($aData["fnFilePath"] as $sFnClient => $sFilePath)
|
||||
<p><strong>{{$sFnClient}}订阅链接:</strong></p>
|
||||
<p>
|
||||
<a href='javascript:;' data-clipboard-text="{{$sFilePath}}" class='copy-permalink'>
|
||||
<span class='subCopy'>
|
||||
<i class='iconfont icon-link'></i> {{$sFilePath}}
|
||||
</span>
|
||||
</a>
|
||||
</p>
|
||||
@endforeach
|
||||
|
||||
<p>温馨提示:</p>
|
||||
<p>本站提供的都是免费且公共的节点,稳定性与长时间连接速率无法与收费版的高速机场节点相提并论,不能奢望太多。</p>
|
||||
|
||||
@ -10,9 +10,12 @@ use App\Http\Controllers\HtmlController;
|
||||
use App\Http\Controllers\SakaiController;
|
||||
use App\Http\Controllers\Api\GithubController;
|
||||
use App\Http\Controllers\Api\TG\HookController;
|
||||
use App\Http\Controllers\Api\FreenodeController as ApiFreenodeController;
|
||||
|
||||
//Route::get('/', [ArticleListController::class, 'fn'])->middleware('test');
|
||||
|
||||
Route::any('/api/freenode/receive', [ApiFreenodeController::class, 'receive']);
|
||||
|
||||
Route::get('/test1', [SakaiController::class, 'test1']);
|
||||
Route::get('/test2', [SakaiController::class, 'test2']);
|
||||
Route::get('/test3', [SakaiController::class, 'test3']);
|
||||
|
||||
14
scripts/cron.php
Normal file
14
scripts/cron.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
error_reporting(E_ALL & ~E_DEPRECATED);
|
||||
|
||||
require __DIR__ . '/../vendor/autoload.php';
|
||||
$app = require_once __DIR__ . '/../bootstrap/app.php';
|
||||
|
||||
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
||||
|
||||
$service = $app->make(App\Services\Cron::class);
|
||||
//$service->setTestI(5);
|
||||
$result = $service->run();
|
||||
|
||||
print_r($result);
|
||||
Loading…
Reference in New Issue
Block a user