freenode_merge
This commit is contained in:
parent
6843f40b78
commit
a93beaa48e
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ public/fn/
|
||||
README.md
|
||||
_env/
|
||||
public/upload/
|
||||
public/freenode/
|
||||
|
||||
94
app/Http/Controllers/Api/FreenodeController.php
Executable file
94
app/Http/Controllers/Api/FreenodeController.php
Executable file
@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
//use App\Models\Article;
|
||||
//use App\Services\TomTool\Http;
|
||||
//use App\Services\TG\Http as TGHttp;
|
||||
//use App\Models\Ship as ModelShip;
|
||||
use App\Models\Option as ModelOption;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
final class FreenodeController
|
||||
{
|
||||
|
||||
public function sub($sSiteCode, $sClient, $sDate = "")
|
||||
{
|
||||
header('Content-Type: application/x-yaml; charset=utf-8');
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
|
||||
// $aData = $request->json()->all();
|
||||
|
||||
// $sSiteCode = $sSiteCode ?? "base";
|
||||
// $sClient = $aData["client"] ?? "";
|
||||
$sDate = $sDate ?? date("Y-m-d");
|
||||
|
||||
//// *test
|
||||
$sDate = "2025-12-22";
|
||||
// $sClient = "clash";
|
||||
//// test end
|
||||
|
||||
$aClient = [];
|
||||
|
||||
if ($sClient == "_all") {
|
||||
$sFnClient = ModelOption::_hit("freenode_client");
|
||||
$aFnClient = explode(",", $sFnClient);
|
||||
foreach ($aFnClient as $sFnClient) {
|
||||
$aClient[] = $sFnClient;
|
||||
}
|
||||
} else {
|
||||
$aClient[] = $sClient;
|
||||
}
|
||||
|
||||
$aContent = [];
|
||||
foreach ($aClient as $sClient) {
|
||||
$sFilePath = $this->pathReal($sSiteCode, $sClient, $sDate);
|
||||
$sFileContent = file_get_contents($sFilePath); // data
|
||||
$aContent[$sClient] = $sFileContent;
|
||||
}
|
||||
|
||||
$iContentCount = count($aContent);
|
||||
|
||||
if ($iContentCount == 1) {
|
||||
$k = array_key_first($aContent);
|
||||
$sContent = $aContent[$k];
|
||||
|
||||
if ($k == "clash") {
|
||||
header('Content-Type: application/x-yaml; charset=utf-8');
|
||||
} else {
|
||||
header('Content-Type: text/plain; charset=utf-8');
|
||||
}
|
||||
|
||||
} else {
|
||||
$sContent = json_encode($aContent);
|
||||
}
|
||||
|
||||
echo $sContent;
|
||||
exit;
|
||||
}
|
||||
|
||||
private function pathReal($sSiteCode, $sClient, $sDate, $iDeep = 0)
|
||||
{
|
||||
if ($iDeep > 30) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
$sFilePath = $sDirBase."public/freenode/merge/".$sSiteCode."/".$sClient."/".$sDate.".txt";
|
||||
|
||||
if (file_exists($sFilePath)) {
|
||||
return $sFilePath;
|
||||
} else {
|
||||
$oData = new \DateTime($sDate);
|
||||
$oData->modify('-1 day');
|
||||
$sDatePrev = $oData->format('Y-m-d');
|
||||
|
||||
return $this->pathReal($sSiteCode, $sClient, $sDatePrev, ++$iDeep);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
22
app/Models/CrawlFreenode.php
Executable file
22
app/Models/CrawlFreenode.php
Executable file
@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class CrawlFreenode extends Model
|
||||
{
|
||||
protected $table = 'crawl_freenode';
|
||||
public $timestamps = false;
|
||||
|
||||
// public static function _listKey()
|
||||
// {
|
||||
// $aSelf = self::all()->toArray();
|
||||
//
|
||||
// foreach ($aSelf as &$aSelfRow) {
|
||||
// unset($aSelfRow["content"]);
|
||||
// }
|
||||
//
|
||||
// return $aSelf;
|
||||
// }
|
||||
}
|
||||
12
app/Models/FreenodePool.php
Executable file
12
app/Models/FreenodePool.php
Executable file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class FreenodePool extends Model
|
||||
{
|
||||
protected $table = 'freenode_pool';
|
||||
public $timestamps = false;
|
||||
|
||||
}
|
||||
@ -6,6 +6,12 @@ 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;
|
||||
|
||||
@ -18,31 +24,67 @@ final class Cron
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$h = (int) date("H");
|
||||
$i = (int) date("i");
|
||||
$s = (int) date("s");
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if ($this->bIsTest) {
|
||||
$h = (int) ($this->iTestH ?? $h);
|
||||
$i = (int) ($this->iTestI ?? $i);
|
||||
$s = (int) ($this->iTestS ?? $s);
|
||||
}
|
||||
|
||||
echo "cron开始执行\n\n";
|
||||
|
||||
if ($h % 6 === 0 && $i === 3) {
|
||||
CronBook::randbox_notify();
|
||||
}
|
||||
|
||||
if ($i % 3 === 0) {
|
||||
CronArticleSchema::cacheTgSave();
|
||||
CronArticleSchema::pushToSlave();
|
||||
CronHttpQueue::pop();
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
// ReportSender::handle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function setTestH(int $h): void
|
||||
|
||||
229
app/Services/Cron/FreenodeCrawl.php
Normal file
229
app/Services/Cron/FreenodeCrawl.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Cron;
|
||||
|
||||
use App\Models\CrawlFreenode as ModelCrawlFreenode;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
//use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
final class FreenodeCrawl
|
||||
{
|
||||
|
||||
// 自有系
|
||||
// 必然获取到,但是密码会变,暂定每天8点变,意味着8袋内03分获取的是新密码
|
||||
private static function getFile___my($aFrom)
|
||||
{
|
||||
$aFileContent = [];
|
||||
|
||||
foreach ($aFrom["url_file"] as $k => $sFileName) {
|
||||
|
||||
$sUrlSend = "https://".$aFrom["url_base"].$aFrom["url_node"].$sFileName;
|
||||
|
||||
$sFileContent = self::curl($sUrlSend) ?? "";
|
||||
|
||||
if ($sFileContent) {
|
||||
$aFileContent[] = [
|
||||
"type" => $k,
|
||||
"file_name" => $sFileName,
|
||||
"file_content" => $sFileContent
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $aFileContent;
|
||||
}
|
||||
|
||||
// stairnode系
|
||||
// ripaojiedian系,stairnode本源
|
||||
// 这个可能会没有,没有就不更新
|
||||
private static function getFile__A($aFrom)
|
||||
{
|
||||
$aFileContent = [];
|
||||
|
||||
foreach ($aFrom["url_file"] as $k => $v) {
|
||||
|
||||
$sFileName = str_replace("{{Ymd}}", date("Ymd"), $v);
|
||||
|
||||
$sUrlSend = "http://".$aFrom["url_base"].$aFrom["url_node"].$sFileName;
|
||||
|
||||
$sFileContent = self::curl($sUrlSend) ?? "";
|
||||
|
||||
if (!$sFileContent) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($k == "v2ray") {
|
||||
$sFileContent = base64_decode($sFileContent);
|
||||
}
|
||||
|
||||
if ($sFileContent) {
|
||||
$aFileContent[] = [
|
||||
"type" => $k,
|
||||
"file_name" => $sFileName,
|
||||
"file_content" => $sFileContent
|
||||
];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $aFileContent;
|
||||
}
|
||||
|
||||
// v2rayshare系
|
||||
// 这必然有,和下一天一致说明没更新(但是好像改了,现在它是一次生成很多天)
|
||||
private static function getFile__B($aFrom)
|
||||
{
|
||||
$aFileContent = [];
|
||||
$sTime = time();
|
||||
$sTimeNext = strtotime("+1 day", $sTime);
|
||||
|
||||
$sUrlBase = $aFrom["url_base"];
|
||||
$sUrlNode = $aFrom["url_node"];
|
||||
$sUrlNode = str_replace("{{Y}}", date("Y"), $sUrlNode);
|
||||
$sUrlNode = str_replace("{{m}}", date("m"), $sUrlNode);
|
||||
$sUrlNodeNext = str_replace("{{Y}}", date("Y", $sTimeNext), $sUrlNode);
|
||||
$sUrlNodeNext = str_replace("{{m}}", date("m", $sTimeNext), $sUrlNode);
|
||||
|
||||
|
||||
foreach ($aFrom["url_file"] as $k => $v) {
|
||||
$sUrlFile = str_replace("{{Ymd}}", date("Ymd"), $v);
|
||||
$sUrlFileNext = str_replace("{{Ymd}}", date("Ymd"), $v);
|
||||
|
||||
$sHouzhui = ".".$k;
|
||||
if ($k == "v2ray") {
|
||||
$sHouzhui = ".txt";
|
||||
} else if ($k == "clash") {
|
||||
$sHouzhui = ".yaml";
|
||||
}
|
||||
|
||||
$sFileName = date("Ymd")."-".$k.$sHouzhui;
|
||||
|
||||
$sUrlSend = "https://".$sUrlBase.$sUrlNode.$sUrlFile;
|
||||
$sUrlSendNext = "https://".$sUrlBase.$sUrlNodeNext.$sUrlFileNext;
|
||||
|
||||
$sFileContent = self::curl($sUrlSend) ?? "";
|
||||
// $sFileContentNext = self::curl($sUrlSendNext) ?? "";
|
||||
|
||||
if (!$sFileContent) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($k == "v2ray") {
|
||||
$sFileContent = base64_decode($sFileContent);
|
||||
}
|
||||
|
||||
$sFileContentMd5 = md5($sFileContent);
|
||||
// $sFileContentMd5Next = md5($sFileContentNext);
|
||||
|
||||
// if ($sFileContentMd5 != $sFileContentMd5Next) {
|
||||
$aFileContent[] = [
|
||||
"type" => $k,
|
||||
"file_name" => $sFileName,
|
||||
"file_content" => $sFileContent
|
||||
];
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
return $aFileContent;
|
||||
}
|
||||
|
||||
private static function fileRealUpd($iId, $sType, $sFileName)
|
||||
{
|
||||
$oFrom = ModelCrawlFreenode::where("id", $iId)->first();
|
||||
|
||||
$aFileReal = json_decode($oFrom->file_real ?? "[]", true);
|
||||
|
||||
$aFileReal[$sType] = $sFileName;
|
||||
|
||||
$oFrom->file_real = $aFileReal;
|
||||
|
||||
return $oFrom->save();
|
||||
}
|
||||
|
||||
public static function run()
|
||||
{
|
||||
echo "\nCrawlFreenode::caseA - 开始\n";
|
||||
|
||||
$aFromList = ModelCrawlFreenode::where("status", 1)->get()->toArray();
|
||||
|
||||
foreach ($aFromList as $aFrom) {
|
||||
|
||||
$aFrom["url_file"] = json_decode($aFrom["url_file"], true);
|
||||
|
||||
$sMethod = "getFile__".$aFrom["group"];
|
||||
$aFileList = self::$sMethod($aFrom); // 没有就返回空数组,所以不用判断,直接foreach
|
||||
|
||||
foreach ($aFileList as $sFileRow) {
|
||||
$sType = $sFileRow["type"];
|
||||
|
||||
$sHouzhui = "";
|
||||
if ($sType == "v2ray") {
|
||||
$sHouzhui = ".txt";
|
||||
} else if ($sType == "clash") {
|
||||
$sHouzhui = ".yaml";
|
||||
}
|
||||
|
||||
$sFileName = date("Ymd")."-".$sType.$sHouzhui;
|
||||
|
||||
$sFileContent = $sFileRow["file_content"];
|
||||
|
||||
$sDir = "freenode/from/".$aFrom["name"];
|
||||
$sPath = $sDir."/".$sFileName;
|
||||
|
||||
if (!is_dir($sDir)) {
|
||||
mkdir($sDir, 0777, true);
|
||||
}
|
||||
|
||||
// if ($sType == "v2ray") {
|
||||
// $sFileContent = base64_decode($sFileContent);
|
||||
// }
|
||||
|
||||
file_put_contents($sPath, $sFileContent);
|
||||
|
||||
self::fileRealUpd($aFrom["id"], $sType, $sFileName);
|
||||
|
||||
echo "- ".$aFrom["name"]."::".$sFileName."\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static function curl($sUrl)
|
||||
{
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $sUrl);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 返回内容而不是直接输出
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 如果是 https,可以关闭证书验证(测试用)
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // 关闭主机名验证
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // 关闭主机名验证
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
|
||||
|
||||
$sContent = curl_exec($ch);
|
||||
|
||||
if ($sContent === false) {
|
||||
$error = curl_error($ch);
|
||||
$errno = curl_errno($ch);
|
||||
$sMsg = "cURL error ({$errno}): {$error}";
|
||||
echo $sMsg;
|
||||
TeleSlave::log()->send($sMsg);
|
||||
}
|
||||
|
||||
curl_close($ch);
|
||||
return $sContent;
|
||||
}
|
||||
|
||||
private static function fileGet($sUrl)
|
||||
{
|
||||
$sContent = file_get_contents($sUrl);
|
||||
|
||||
return $sContent;
|
||||
}
|
||||
|
||||
}
|
||||
105
app/Services/Cron/FreenodeFile.php
Normal file
105
app/Services/Cron/FreenodeFile.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Cron;
|
||||
|
||||
use App\Models\FreenodePool as ModelFreenodePool;
|
||||
use App\Models\CrawlFreenode as ModelCrawlFreenode;
|
||||
use App\Models\SiteMap as ModelSiteMap;
|
||||
use App\Models\Option as ModelOption;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
|
||||
final class FreenodeFile
|
||||
{
|
||||
|
||||
private static $aBaseProtocol = [
|
||||
"clash",
|
||||
"v2ray"
|
||||
];
|
||||
|
||||
public static function clear()
|
||||
{
|
||||
echo "\nFreenodeFile::clear - 开始\n";
|
||||
|
||||
self::clear_from();
|
||||
self::clear_merge__fn_a();
|
||||
|
||||
}
|
||||
|
||||
public static function clear_merge__fn_a()
|
||||
{
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
|
||||
$sPrevDay = 30;
|
||||
|
||||
$sTimePrevX = strtotime("-$sPrevDay days");
|
||||
$sDatePrevX = date("Y-m-d", $sTimePrevX);
|
||||
|
||||
$aFnSiteList = ModelSiteMap::where("group_code", "fn_a")->pluck("code")->toArray();
|
||||
$aFnSiteList[] = "base";
|
||||
|
||||
$sFnClient = ModelOption::_hit("freenode_client-fn_a");
|
||||
$aFnClient = explode(",", $sFnClient);
|
||||
|
||||
foreach ($aFnSiteList as $sFnSiteName) {
|
||||
foreach ($aFnClient as $sClient) {
|
||||
$sFileDir = $sDirBase."public/freenode/merge/".$sFnSiteName."/".$sClient;
|
||||
|
||||
foreach (scandir($sFileDir) as $sFileName) {
|
||||
if ($sFileName === '.' || $sFileName == '..') continue;
|
||||
$sFilePath = $sFileDir.'/'.$sFileName;
|
||||
|
||||
if (preg_match('/(\d{4}-\d{2}-\d{2})/', $sFileName, $matches)) {
|
||||
$sDateCode = $matches[1];
|
||||
|
||||
$sFileDate = \DateTime::createFromFormat('Y-m-d', $sDateCode);
|
||||
if ($sFileDate && $sFileDate->getTimestamp() < $sTimePrevX) {
|
||||
if (unlink($sFilePath)) {
|
||||
echo " - 已删除: $sFilePath\n";
|
||||
} else {
|
||||
echo " - 删除失败: $sFilePath\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
echo " - fn的merge里的".$sFnSiteName."里的".$sClient."的file清理完成 \n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function clear_from()
|
||||
{
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
|
||||
$sPrevDay = 30;
|
||||
|
||||
$sTimePrevX = strtotime("-$sPrevDay days");
|
||||
$sDateCodePrevX = date("Ymd", $sTimePrevX);
|
||||
|
||||
$oFromList = ModelCrawlFreenode::where("status", 1)->get();
|
||||
|
||||
foreach ($oFromList as $oFrom) {
|
||||
$aFileLast = json_decode($oFrom->file_real, true);
|
||||
$sFileDir = $sDirBase."public/freenode/from/".$oFrom->name;
|
||||
|
||||
foreach (scandir($sFileDir) as $sFileName) {
|
||||
if ($sFileName === '.' || $sFileName == '..') continue;
|
||||
$sFilePath = $sFileDir.'/'.$sFileName;
|
||||
|
||||
if (preg_match('/(\d{8})/', $sFileName, $matches)) {
|
||||
$sDateCode = $matches[1]; // 提取到的日期字符串
|
||||
$sFileDate = \DateTime::createFromFormat('Ymd', $sDateCode);
|
||||
if ($sFileDate && $sFileDate->getTimestamp() < $sTimePrevX) {
|
||||
if (unlink($sFilePath)) {
|
||||
echo " - 已删除: $sFilePath\n";
|
||||
} else {
|
||||
echo " - 删除失败: $sFilePath\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
echo " - fn的from的".$oFrom->name."里的file清理完成 \n";
|
||||
}
|
||||
}
|
||||
}
|
||||
23
app/Services/Cron/FreenodeLog.php
Normal file
23
app/Services/Cron/FreenodeLog.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Cron;
|
||||
|
||||
//use App\Models\CrawlFreenode as ModelCrawlFreenode;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
use App\Models\CrawlFreenode as ModelCrawlFreenode;
|
||||
//use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
final class FreenodeLog
|
||||
{
|
||||
public static function fromLast()
|
||||
{
|
||||
$oFrom = ModelCrawlFreenode::where("status", 1)->get();
|
||||
|
||||
tomd($oFrom->toArray());
|
||||
|
||||
exit;
|
||||
}
|
||||
|
||||
}
|
||||
419
app/Services/Cron/FreenodeMerge.php
Normal file
419
app/Services/Cron/FreenodeMerge.php
Normal file
@ -0,0 +1,419 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Cron;
|
||||
|
||||
use App\Models\CrawlFreenode as ModelCrawlFreenode;
|
||||
use App\Models\FreenodePool as ModelFreenodePool;
|
||||
use App\Services\Cron\FreenodePool as CronFreenodePool;
|
||||
use App\Models\SiteMap as ModelSiteMap;
|
||||
use App\Models\Option as ModelOption;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
final class FreenodeMerge
|
||||
{
|
||||
private static $aCountryOrder = [
|
||||
"{{slogan_siteUrl}}",
|
||||
"{{slogan_telegram}}",
|
||||
"{{slogan_date}}",
|
||||
"美国",
|
||||
"日本",
|
||||
"台湾",
|
||||
"香港",
|
||||
"新加坡",
|
||||
];
|
||||
|
||||
private static $aCountryFlag = [
|
||||
"美国" => "🇺🇸",
|
||||
"日本" => "🇯🇵",
|
||||
"台湾" => "🇹🇼",
|
||||
"香港" => "🇭🇰",
|
||||
"新加坡" => "🇸🇬",
|
||||
"越南" => "🇻🇳",
|
||||
"俄罗斯" => "🇷🇺",
|
||||
"韩国" => "🇰🇷",
|
||||
];
|
||||
|
||||
// public static function buildSogan($aNode)
|
||||
// {
|
||||
// // todo 广告位,这样就固定了
|
||||
// }
|
||||
|
||||
private static function isSlogan($s)
|
||||
{
|
||||
if ($s == "{{slogan_siteUrl}}" || $s == "{{slogan_telegram}}" || $s == "{{slogan_date}}") {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function save()
|
||||
{
|
||||
echo "\nFreenodeFile::save - 开始 \n";
|
||||
|
||||
//// test
|
||||
// $a = ["a", "b", "c"];
|
||||
// $b = ["b", "c", "d"];
|
||||
// $c = array_merge($a, $b);
|
||||
// $c = array_unique($c);
|
||||
// $c = array_values($c);
|
||||
// tomd($c, 1);
|
||||
//// test end
|
||||
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
|
||||
$sDate = date("Y-m-d");
|
||||
// $sDate = "2025-12-12"; // *test
|
||||
|
||||
$oPool = ModelFreenodePool::whereDate("date", $sDate)->first();
|
||||
|
||||
$aPoolContentList = json_decode($oPool->content, true);
|
||||
|
||||
foreach ($aPoolContentList as $sPoolClient => $aPoolContent) {
|
||||
|
||||
$aNodeGroupCountry = [];
|
||||
$aLastNode = [];
|
||||
$aLastNodeMy = [];
|
||||
foreach ($aPoolContent as $sMd5 => $aNode) {
|
||||
$sFromName = $aNode["fromName"];
|
||||
$sCountry = $aNode["country"];
|
||||
$sProtocolType = $aNode["protocolType"];
|
||||
$sConfig = $aNode["config"];
|
||||
|
||||
$sCountryClear = self::strReplace($sCountry, $sFromName);
|
||||
|
||||
$aNodeGroupCountry[$sCountryClear][] = $aNode;
|
||||
|
||||
if ($sFromName == "_my") {
|
||||
$aLastNodeMy = $aNode;
|
||||
}
|
||||
|
||||
$aLastNode = $aNode;
|
||||
}
|
||||
|
||||
$aSloganNode = $aLastNode;
|
||||
if ($aLastNodeMy) {
|
||||
$aSloganNode = $aLastNodeMy;
|
||||
}
|
||||
|
||||
$aNodeGroupCountry["{{slogan_siteUrl}}"][] = $aSloganNode;
|
||||
$aNodeGroupCountry["{{slogan_telegram}}"][] = $aSloganNode;
|
||||
$aNodeGroupCountry["{{slogan_date}}"][] = $aSloganNode;
|
||||
|
||||
$aNodeSortCountry = [];
|
||||
|
||||
foreach (self::$aCountryOrder as $sCountryOrder) {
|
||||
if (array_key_exists($sCountryOrder, $aNodeGroupCountry)) {
|
||||
if (self::isSlogan($sCountryOrder)) {
|
||||
$aNodeSortCountry[$sCountryOrder] = [
|
||||
$aNodeGroupCountry[$sCountryOrder][0] // 得到多个slogan只要第一个,按理不用处理,保险
|
||||
];
|
||||
} else {
|
||||
$aNodeSortCountry[$sCountryOrder] = $aNodeGroupCountry[$sCountryOrder];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($aNodeGroupCountry as $sCountry => $aNode) {
|
||||
if (!array_key_exists($sCountry, self::$aCountryOrder)) {
|
||||
$aNodeSortCountry[$sCountry] = $aNode;
|
||||
}
|
||||
}
|
||||
|
||||
$aNodeMerge = [];
|
||||
$aNodeCountryList = [];
|
||||
foreach ($aNodeSortCountry as $sCountry => $aNodeList) {
|
||||
$i = 1;
|
||||
foreach ($aNodeList as $aNode) {
|
||||
if (self::isSlogan($sCountry)) {
|
||||
$aNode["country"] = $sCountry;
|
||||
} else {
|
||||
$aNode["country"] = $sCountry." ".sprintf('%02d', $i);
|
||||
}
|
||||
|
||||
$aNode["country"] = $aNode["country"]." :[".$aNode["fromName"]."]:";
|
||||
|
||||
if ($sPoolClient == "v2ray") {
|
||||
$sConfig = $aNode["config"];
|
||||
if (is_array($sConfig)) {
|
||||
$sConfig = json_encode($sConfig);
|
||||
}
|
||||
$sNode = $aNode["protocolType"]."://".$sConfig."#".urlencode($aNode["country"]);
|
||||
$aNodeMerge[] = $sNode;
|
||||
} else if ($sPoolClient == "clash") {
|
||||
$sFlagCountry = self::countryJoinFlag($aNode["country"]);
|
||||
$aNode["config"]["name"] = $sFlagCountry;
|
||||
$aNodeMerge[] = $aNode["config"];
|
||||
$aNodeCountryList[] = $sFlagCountry;
|
||||
} else {
|
||||
$aNodeMerge[] = json_encode($aNode);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sPoolClient == "v2ray") {
|
||||
|
||||
$sMerge = implode("\n", $aNodeMerge);
|
||||
$sMerge = base64_encode($sMerge);
|
||||
|
||||
} else if ($sPoolClient == "clash") {
|
||||
|
||||
$sFile = $sDirBase."public/freenode/template/clash.txt";
|
||||
|
||||
if (file_exists($sFile) && is_readable($sFile)) {
|
||||
$sClashTemplate = file_get_contents($sFile); // data
|
||||
} else {
|
||||
$sMsg = "clash的template不存在,这不应该 \n";
|
||||
TeleSlave::warn()->send($sMsg);
|
||||
echo $sMsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
$aClashTemplate = Yaml::parse($sClashTemplate);
|
||||
|
||||
$aClashTemplate["proxies"] = $aNodeMerge;
|
||||
|
||||
$aProxyGroupList = &$aClashTemplate["proxy-groups"];
|
||||
|
||||
foreach ($aProxyGroupList as &$aProxyGroup) {
|
||||
|
||||
if (!isset($aProxyGroup["proxies"])) {
|
||||
$aProxyGroup["proxies"] = [];
|
||||
}
|
||||
|
||||
if ($aProxyGroup["name"] == "🍃 应用净化") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($aProxyGroup["name"] == "🛑 全球拦截") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($aProxyGroup["name"] == "🎯 全球直连") {
|
||||
continue;
|
||||
}
|
||||
|
||||
$aProxyGroup["proxies"] = self::arrMerge($aProxyGroup["proxies"], $aNodeCountryList);
|
||||
}
|
||||
|
||||
$sMerge = Yaml::dump($aClashTemplate, 4);
|
||||
}
|
||||
|
||||
$sFileDir = $sDirBase."public/freenode/merge/base/".$sPoolClient;
|
||||
if (!is_dir($sFileDir)) {
|
||||
mkdir($sFileDir, 0777, true);
|
||||
}
|
||||
|
||||
$sFilePath = $sFileDir."/".$sDate.".txt"; // 都是txt,解析的时候另处理
|
||||
file_put_contents($sFilePath, $sMerge);
|
||||
|
||||
echo " - base::".$sFilePath." 已保存 \n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static function baseToSite()
|
||||
{
|
||||
echo "\nFreenodeMerge::baseToSite - 开始 \n";
|
||||
|
||||
$sDate = date("Y-m-d");
|
||||
// $sDateCode = date("Ymd");
|
||||
// $sDate = "2025-12-12"; // *test
|
||||
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
|
||||
$sFnClientList = ModelOption::_hit("freenode_client-fn_a");
|
||||
|
||||
if (!$sFnClientList) {
|
||||
throw new \Exception("未设置option的freenode_client?");
|
||||
}
|
||||
|
||||
$aFnClientList = explode(",", $sFnClientList);
|
||||
|
||||
$aMerge = [];
|
||||
foreach ($aFnClientList as $sFnClient) {
|
||||
$sMergeFilePath = $sDirBase."public/freenode/merge/base/".$sFnClient."/".$sDate.".txt";
|
||||
|
||||
if (file_exists($sMergeFilePath)) {
|
||||
$aMerge[$sFnClient] = file_get_contents($sMergeFilePath);
|
||||
} else {
|
||||
throw new \Exception("baseToSite里没找到merge文件? - $sMergeFilePath");
|
||||
}
|
||||
}
|
||||
|
||||
$oSiteMap = ModelSiteMap::where("group_code", "fn_a")->get();
|
||||
|
||||
if ($oSiteMap->isEmpty()) {
|
||||
throw new \Exception("没找到siteMap的fn_a组?");
|
||||
}
|
||||
|
||||
$aSiteMap = $oSiteMap->toArray();
|
||||
$aSiteMap[] = [
|
||||
"code" => "_admin",
|
||||
"url" => "_admin.loc",
|
||||
"name" => "_admin",
|
||||
];
|
||||
|
||||
$iH4Rand = rand(1, 21600); // 6小时
|
||||
$iH4Time = time() - $iH4Rand;
|
||||
|
||||
$sSloganDate = date("Y-m-d H:i:s", $iH4Time);
|
||||
|
||||
foreach ($aSiteMap as $aSiteMapRow) {
|
||||
$aSiteConfig = json_decode($aSiteMapRow["config"] ?? "", true);
|
||||
|
||||
$sSiteConfigTelegram = $aSiteConfig["telegram"] ?? "";
|
||||
|
||||
$sSiteConfigSloganUrl = $aSiteConfig["freenode_slogan"]["siteUrl"] ?? "";
|
||||
$sSiteConfigSloganTelegram = $aSiteConfig["freenode_slogan"]["telegram"] ?? "";
|
||||
|
||||
if ($sSiteConfigSloganUrl) {
|
||||
$sSlogan_siteUrl = str_replace('{{siteUrl}}', $aSiteMapRow["url"], $sSiteConfigSloganUrl);
|
||||
} else {
|
||||
$sSlogan_siteUrl = "美国".uniqid();
|
||||
}
|
||||
|
||||
if ($sSiteConfigSloganTelegram) {
|
||||
$sSlogan_telegram = str_replace('{{telegram}}', $sSiteConfigTelegram, $sSiteConfigSloganTelegram);
|
||||
} else {
|
||||
$sSlogan_telegram = "美国".uniqid();
|
||||
}
|
||||
|
||||
foreach ($aMerge as $sClient => $sFeedContent) {
|
||||
$sFileSaveDir = $sDirBase."public/freenode/merge/".$aSiteMapRow["code"]."/".$sClient;
|
||||
|
||||
if (!is_dir($sFileSaveDir)) {
|
||||
mkdir($sFileSaveDir, 0777, true);
|
||||
}
|
||||
|
||||
$sFileSavePath = $sFileSaveDir."/".$sDate.".txt";
|
||||
|
||||
if ($sClient == "v2ray") {
|
||||
$sFeedContent = self::v2rayFeedToStr($sFeedContent);
|
||||
}
|
||||
|
||||
$sFeedContent = str_replace('{{slogan_siteUrl}}', $sSlogan_siteUrl, $sFeedContent);
|
||||
$sFeedContent = str_replace('{{slogan_telegram}}', $sSlogan_telegram, $sFeedContent);
|
||||
$sFeedContent = str_replace('{{slogan_date}}', "更新于:".$sSloganDate, $sFeedContent);
|
||||
|
||||
if ($aSiteMapRow["code"] !== "_admin") {
|
||||
$sFeedContent = preg_replace('/ :\[.*?\]:/su', '', $sFeedContent);
|
||||
}
|
||||
|
||||
if ($sClient == "v2ray") {
|
||||
$sFeedContent = self::v2rayFeedByStr($sFeedContent);
|
||||
}
|
||||
|
||||
file_put_contents($sFileSavePath, $sFeedContent);
|
||||
|
||||
echo " - fn的".$aSiteMapRow["code"]."的{$sClient}的{$sDate} 保存成功 \n";
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function v2rayFeedByStr($s)
|
||||
{
|
||||
$a = explode("\n", $s);
|
||||
|
||||
$aFeed = [];
|
||||
foreach ($a as $sConfig) {
|
||||
if (!$sConfig) {continue;}
|
||||
$aTmp = CronFreenodePool::v2ray_chai($sConfig);
|
||||
$sConfig = $aTmp[0];
|
||||
$sName = $aTmp[1];
|
||||
$sName = rawurlencode($sName);
|
||||
$aFeed[] = $sConfig."#".$sName;
|
||||
}
|
||||
|
||||
$sFeed = implode("\n", $aFeed);
|
||||
$sFeed = base64_encode($sFeed);
|
||||
|
||||
return $sFeed;
|
||||
}
|
||||
|
||||
public static function v2rayFeedToStr($sV2rayFeed)
|
||||
{
|
||||
$sV2rayFeed = base64_decode($sV2rayFeed);
|
||||
$aV2rayFeed = explode("\n", $sV2rayFeed);
|
||||
|
||||
$aFeed = [];
|
||||
foreach ($aV2rayFeed as $sConfig) {
|
||||
if (!$sConfig) {continue;}
|
||||
$aTmp = CronFreenodePool::v2ray_chai($sConfig);
|
||||
$sConfig = $aTmp[0];
|
||||
$sName = $aTmp[1];
|
||||
$sName = urldecode($sName);
|
||||
|
||||
$aFeed[] = $sConfig."#".$sName;
|
||||
}
|
||||
|
||||
$sFeed = implode("\n", $aFeed);
|
||||
|
||||
return $sFeed;
|
||||
}
|
||||
|
||||
private static function arrMerge($aBase, $aNew)
|
||||
{
|
||||
$aMerge = array_merge($aBase, $aNew);
|
||||
$aMerge = array_unique($aMerge);
|
||||
$aMerge = array_values($aMerge);
|
||||
return $aMerge;
|
||||
}
|
||||
|
||||
public static function strReplace($sStr, $sFromName)
|
||||
{
|
||||
if (preg_match('/机场/u', $sStr)) {
|
||||
tomd($sStr);
|
||||
$sStr = "美国"; // 原本的slogan直接视为美国
|
||||
}
|
||||
|
||||
if (preg_match('/频道/u', $sStr)) {
|
||||
$sStr = "美国";
|
||||
}
|
||||
|
||||
if ($sFromName == "ripaojiedian") {
|
||||
$sStr = preg_replace('/\|\@ripaojiedian/', '', $sStr);
|
||||
} else if ($sFromName == "stairnode") {
|
||||
$sStr = preg_replace('/\|\@stairnode/', '', $sStr);
|
||||
} else {
|
||||
// 其他
|
||||
}
|
||||
|
||||
// $sStr = preg_replace('/\d+/', '', $sStr); // 去数字
|
||||
// $sStr = preg_replace('/[\x{1F1E6}-\x{1F1FF}]{2}\s*/u', '', $sStr); // 去国旗
|
||||
// $sStr = preg_replace('/[a-zA-Z_]+/', '', $sStr); // 去下划线和字母
|
||||
|
||||
if (preg_match('/\p{Han}/u', $sStr)) {
|
||||
$sStr = preg_replace('/[^\p{Han}]/u', '', $sStr);// 只留中文
|
||||
} else { // 没有中文,再处理一下
|
||||
$sStr = preg_replace('/^.*HK.*$/i', '香港', $sStr);
|
||||
}
|
||||
|
||||
return $sStr;
|
||||
}
|
||||
|
||||
private static function countryJoinFlag($str)
|
||||
{
|
||||
$aCountryFlagList = self::$aCountryFlag;
|
||||
|
||||
$sFlag = "";
|
||||
foreach ($aCountryFlagList as $sCountryName => $sCountryFlag) {
|
||||
if (str_contains($str, $sCountryName)) {
|
||||
$sFlag = $sCountryFlag;
|
||||
}
|
||||
}
|
||||
|
||||
if ($sFlag) {
|
||||
$str = $sFlag." ".$str;
|
||||
}
|
||||
|
||||
return $str;
|
||||
}
|
||||
|
||||
}
|
||||
498
app/Services/Cron/FreenodePool.php
Normal file
498
app/Services/Cron/FreenodePool.php
Normal file
@ -0,0 +1,498 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Cron;
|
||||
|
||||
use App\Models\CrawlFreenode as ModelCrawlFreenode;
|
||||
use App\Models\FreenodePool as ModelFreenodePool;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
final class FreenodePool
|
||||
{
|
||||
|
||||
public static function save()
|
||||
{
|
||||
echo "FreenodePoll::save - 开始 \n";
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
$sDate = date("Y-m-d");
|
||||
// $sDate = "2025-12-12"; // *test
|
||||
|
||||
$oPool = ModelFreenodePool::whereDate("date", $sDate)->first();
|
||||
|
||||
if (!$oPool) {
|
||||
$oPool = new ModelFreenodePool();
|
||||
$oPool->date = $sDate;
|
||||
$oPool->save();
|
||||
}
|
||||
|
||||
$oFromList = ModelCrawlFreenode::where("status", 1)->get();
|
||||
|
||||
$aMerge = [];
|
||||
foreach ($oFromList as $oFrom) {
|
||||
$aFromFileReal = json_decode($oFrom->file_real, true);
|
||||
foreach ($aFromFileReal as $sFromFileRealClient => $aFromFileName) {
|
||||
|
||||
$sFromFilePath = $sDirBase."public/freenode/from/".$oFrom->name."/".$aFromFileName;
|
||||
|
||||
if (file_exists($sFromFilePath) && is_readable($sFromFilePath)) {
|
||||
$sFromFileContent = file_get_contents($sFromFilePath); // data
|
||||
} else {
|
||||
$sMsg = "file_real不存在,这不应该 -> ".$sFromFilePath." \n";
|
||||
TeleSlave::warn()->send($sMsg);
|
||||
echo $sMsg;
|
||||
continue;
|
||||
}
|
||||
|
||||
$aNodeFormat = [
|
||||
"fromName" => $oFrom->name,
|
||||
"country" => "",
|
||||
"protocolType" => "",
|
||||
"config" => "",
|
||||
];
|
||||
|
||||
if ($sFromFileRealClient == "v2ray") {
|
||||
$aFromFileContent = explode("\n", $sFromFileContent);
|
||||
foreach ($aFromFileContent as $sNode) {
|
||||
if (!$sNode) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$aTmp = explode("://", $sNode, 2);
|
||||
$aNodeFormat["protocolType"] = $sProtocolType = $aTmp[0]; // data
|
||||
$sConfig = $aTmp[1];
|
||||
|
||||
if ($sProtocolType == "vmess") {
|
||||
$sConfig = base64_decode($sConfig);
|
||||
$aConfig = json_decode($sConfig, true);
|
||||
$aNodeFormat["country"] = $sCountry = $aConfig["ps"]; // data
|
||||
$aConfig["ps"] = "";
|
||||
$aNodeFormat["config"] = $aConfig; // data
|
||||
$sConfigMd5 = md5(json_encode($aConfig));
|
||||
} else if ($sProtocolType == "ss") {
|
||||
$sConfig = urldecode($sConfig);
|
||||
$aTmp = self::v2ray_chai($sConfig);
|
||||
$aNodeFormat["config"] = $sConfig = $aTmp[0]; // data
|
||||
$aNodeFormat["country"] = $sCountry = $aTmp[1]; // data
|
||||
// if ($oFrom->group == "A") { // ripaojiedian系ss协议bug修复
|
||||
// $aTmp = explode("@", $sConfig);
|
||||
// $qian = $aTmp[0];
|
||||
// $hou = $aTmp[1];
|
||||
// $qian = base64_decode($qian);
|
||||
// $he = $qian."@".$hou;
|
||||
// $he = base64_encode($he);
|
||||
// $sConfig = $he;
|
||||
// $aNodeFormat["config"] = $sConfig;
|
||||
// }
|
||||
|
||||
$sConfigMd5 = md5($sConfig);
|
||||
} else {
|
||||
$sConfig = urldecode($sConfig);
|
||||
$aTmp = self::v2ray_chai($sConfig);
|
||||
$aNodeFormat["config"] = $sConfig = $aTmp[0]; // data
|
||||
$aNodeFormat["country"] = $sCountry = $aTmp[1]; // data
|
||||
$sConfigMd5 = md5($sConfig);
|
||||
}
|
||||
|
||||
$aMerge[$sFromFileRealClient][$sConfigMd5] = $aNodeFormat;
|
||||
}
|
||||
} else if ($sFromFileRealClient == "clash") {
|
||||
$aFromFileContent = Yaml::parse($sFromFileContent);
|
||||
$aFromFileContent = $aFromFileContent["proxies"];
|
||||
|
||||
foreach ($aFromFileContent as $aNode) {
|
||||
$aNodeFormat["protocolType"] = $aNode["type"];
|
||||
$aNodeFormat["country"] = $aNode["name"]; // data
|
||||
$aNode["name"] = "";
|
||||
$aNodeFormat["config"] = $aNode; // data
|
||||
$sConfigMd5 = md5(json_encode($aNode));
|
||||
$aMerge[$sFromFileRealClient][$sConfigMd5] = $aNodeFormat;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$oPool->content = $aMerge;
|
||||
$oPool->save();
|
||||
|
||||
echo " - freenode_pool更新完成 \n";
|
||||
}
|
||||
|
||||
// public static function contentFormat($aContentFrom, $sClientType)
|
||||
// {
|
||||
// $aDataMerge = [];
|
||||
// foreach ($aContentFrom as $sFromName => $aContent) {
|
||||
// foreach ($aContent as $mContent) {
|
||||
// $aNodeData = [];
|
||||
// $sProtocolType = "";
|
||||
// $mConfig = "";
|
||||
// $sCountry = "";
|
||||
// $sConfig = "";
|
||||
//
|
||||
// if ($sClientType == "v2ray") {
|
||||
// $aTmp = self::v2ray_chai($mContent);
|
||||
// $sTmp = $aTmp[0] ?? "none";
|
||||
// $sCountry = $aTmp[1] ?? "none"; // common
|
||||
// $aTmp = explode("://", $sTmp, 2);
|
||||
// $sProtocolType = $aTmp[0] ?? "none"; // common
|
||||
// $mConfig = $aTmp[1] ?? "none"; // common
|
||||
// $sConfig = $mConfig; // common
|
||||
// } else if ($sClientType == "clash") {
|
||||
// $sCountry = $mContent["name"]; // common
|
||||
// $sProtocolType = $mContent["type"]; // common
|
||||
// $mConfig = $mContent; // common
|
||||
// $mConfig["name"] = "";
|
||||
// $sConfig = json_encode($mContent); // common
|
||||
// }
|
||||
//
|
||||
// $aNodeData = [
|
||||
// "from" => $sFromName,
|
||||
// "clientType" => $sClientType,
|
||||
// "country" => $sCountry,
|
||||
// "protocolType" => $sProtocolType,
|
||||
// "config" => $mConfig,
|
||||
// ];
|
||||
//
|
||||
// $sConfigMd5 = md5($sConfig);
|
||||
//
|
||||
// $aDataMerge[$sConfigMd5] = [$aNodeData];
|
||||
//
|
||||
//// tomd($mConfig);
|
||||
//
|
||||
//// tomd($sContent);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// tomd($aDataMerge, 1);
|
||||
// }
|
||||
|
||||
public static function v2ray_chai($sFromContentRow)
|
||||
{
|
||||
$pos = strrpos($sFromContentRow, "#");
|
||||
if ($pos !== false) {
|
||||
$aTmp = [
|
||||
substr($sFromContentRow, 0, $pos),
|
||||
substr($sFromContentRow, $pos + 1)
|
||||
];
|
||||
} else {
|
||||
$aTmp = [$sFromContentRow]; // 没有分隔符时,返回原字符串
|
||||
}
|
||||
|
||||
return $aTmp;
|
||||
}
|
||||
|
||||
// public static function save_old()
|
||||
// {
|
||||
// self::save_custom();
|
||||
// self::save_v2ray();
|
||||
// self::save_clash();
|
||||
// }
|
||||
|
||||
// public static function save_clash()
|
||||
// {
|
||||
// $sDate = date("Y-m-d");
|
||||
//
|
||||
// $oPool = ModelFreenodePool::whereDate("date", $sDate)->first();
|
||||
//
|
||||
// if (!$oPool) {
|
||||
// $oPool = new ModelFreenodePool();
|
||||
// $oPool->date = $sDate;
|
||||
// $oPool->save();
|
||||
// }
|
||||
//
|
||||
// if (!$oPool->content_custom) {
|
||||
// $oPool->content_clash = "[]";
|
||||
// $oPool->save();
|
||||
// }
|
||||
//
|
||||
// $aPoolContent = json_decode($oPool->content_clash, true);
|
||||
//
|
||||
// $oFromList = ModelCrawlFreenode::where("status", 1)->get();
|
||||
//
|
||||
// foreach ($oFromList as $oFrom) {
|
||||
// $sFromName = $oFrom->name;
|
||||
// $aFromFileReal = json_decode($oFrom->file_real, true);
|
||||
// $sFromFileClash = $aFromFileReal["clash"];
|
||||
//
|
||||
// $sFromFilePath = "freenode/from/".$sFromName."/".$sFromFileClash;
|
||||
//
|
||||
// if (file_exists($sFromFilePath) && is_readable($sFromFilePath)) {
|
||||
// $sFromFileContent = file_get_contents($sFromFilePath);
|
||||
//
|
||||
// } else {
|
||||
// $sMsg = "file_real不存在,这不应该 -> ".json_encode($oFrom->toArray());
|
||||
// TeleSlave::warn()->send($sMsg);
|
||||
// echo $sMsg;
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// $aFromFileContent = Yaml::parse($sFromFileContent);
|
||||
//
|
||||
// $aFn = $aFromFileContent["proxies"];
|
||||
//
|
||||
// $aPoolContent[$sFromName] = $aFn;
|
||||
//
|
||||
// $oPool->content_clash = $aPoolContent;
|
||||
// $oPool->save();
|
||||
//
|
||||
// echo " - {$sFromName}的clash更新完成 \n";
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
// public static function save_v2ray()
|
||||
// {
|
||||
// $sDate = date("Y-m-d");
|
||||
//
|
||||
// $oPool = ModelFreenodePool::whereDate("date", $sDate)->first();
|
||||
//
|
||||
// if (!$oPool) {
|
||||
// $oPool = new ModelFreenodePool();
|
||||
// $oPool->date = $sDate;
|
||||
// $oPool->save();
|
||||
// }
|
||||
//
|
||||
// if (!$oPool->content_custom) {
|
||||
// $oPool->content_v2ray = "[]";
|
||||
// $oPool->save();
|
||||
// }
|
||||
//
|
||||
// $aPoolContent = json_decode($oPool->content_v2ray, true);
|
||||
//
|
||||
// $oFromList = ModelCrawlFreenode::where("status", 1)->get();
|
||||
//
|
||||
// foreach ($oFromList as $oFrom) {
|
||||
// $sFromName = $oFrom->name;
|
||||
// $aFromFileReal = json_decode($oFrom->file_real, true);
|
||||
// $sFromFileV2ray = $aFromFileReal["v2ray"];
|
||||
//
|
||||
// $sFromFilePath = "freenode/from/".$sFromName."/".$sFromFileV2ray;
|
||||
//
|
||||
// if (file_exists($sFromFilePath) && is_readable($sFromFilePath)) {
|
||||
// $sFromFileContent = file_get_contents($sFromFilePath);
|
||||
//
|
||||
// } else {
|
||||
// $sMsg = "file_real不存在,这不应该 -> ".json_encode($oFrom->toArray());
|
||||
// TeleSlave::warn()->send($sMsg);
|
||||
// echo $sMsg;
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
// $aFromFileContent = explode("\n", $sFromFileContent);
|
||||
//
|
||||
// foreach ($aFromFileContent as &$sFromFileContentRow) {
|
||||
// if (!$sFromFileContentRow) {
|
||||
// continue;
|
||||
// }
|
||||
//
|
||||
//// $aTmp = explode("://", $sFromFileContentRow, 2);
|
||||
//// $sVtype = $aTmp[0];
|
||||
//// $sVconfig = $aTmp[1];
|
||||
//// if ($sVtype == "vmess") {
|
||||
//// $s = base64_decode($sVconfig);
|
||||
//// tomd($s, 1);
|
||||
//// }
|
||||
//
|
||||
// $sFromFileContentRow = urldecode($sFromFileContentRow);
|
||||
// }
|
||||
//
|
||||
// $aPoolContent[$sFromName] = $aFromFileContent;
|
||||
//
|
||||
// $oPool->content_v2ray = $aPoolContent;
|
||||
// $oPool->save();
|
||||
//
|
||||
// echo " - {$sFromName}的v2ray更新完成 \n";
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
public static function save_custom()
|
||||
{
|
||||
$sDate = date("Y-m-d");
|
||||
|
||||
$oPool = ModelFreenodePool::whereDate("date", $sDate)->first();
|
||||
|
||||
if (!$oPool) {
|
||||
$oPool = new ModelFreenodePool();
|
||||
$oPool->date = $sDate;
|
||||
$oPool->save();
|
||||
}
|
||||
|
||||
if (!$oPool->content_custom) {
|
||||
$oPool->content_custom = "[]";
|
||||
$oPool->save();
|
||||
}
|
||||
|
||||
$aPoolContent = json_decode($oPool->content_custom, true);
|
||||
|
||||
$oFromList = ModelCrawlFreenode::where("status", 1)->get();
|
||||
|
||||
foreach ($oFromList as $oFrom) {
|
||||
$sFromName = $oFrom->name;
|
||||
$aFromFileReal = json_decode($oFrom->file_real, true);
|
||||
$sFromFileV2ray = $aFromFileReal["v2ray"];
|
||||
|
||||
$sFromFilePath = "freenode/from/".$sFromName."/".$sFromFileV2ray;
|
||||
|
||||
if (file_exists($sFromFilePath) && is_readable($sFromFilePath)) {
|
||||
$sFromFileContent = file_get_contents($sFromFilePath);
|
||||
} else {
|
||||
$sMsg = "file_real不存在,这不应该 -> ".json_encode($oFrom->toArray());
|
||||
TeleSlave::warn()->send($sMsg);
|
||||
echo $sMsg;
|
||||
}
|
||||
|
||||
$aFromFileContent = explode("\n", $sFromFileContent);
|
||||
|
||||
|
||||
$i = 0;
|
||||
$aFnNew = [];
|
||||
foreach ($aFromFileContent as $sFromFileContentRow) {
|
||||
if (!$sFromFileContentRow) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ss = explode("://", $sFromFileContentRow, 2);
|
||||
|
||||
list($sProtocolType, $sFn) = explode("://", $sFromFileContentRow, 2);
|
||||
|
||||
$sMethod = $sProtocolType . "ToArr";
|
||||
|
||||
if (method_exists(__CLASS__, $sMethod)) {
|
||||
$aFn = self::$sMethod($sFn);
|
||||
} else {
|
||||
TeleSlave::warn()->send("未设处理方式的协议 -> ".$sFromFileContentRow);
|
||||
continue;
|
||||
}
|
||||
|
||||
$aFnNew[] = $aFn;
|
||||
}
|
||||
|
||||
$aPoolContent[$sFromName] = $aFnNew;
|
||||
$oPool->content_custom = $aPoolContent;
|
||||
$oPool->save();
|
||||
|
||||
echo " - {$sFromName}的custom更新完成 \n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static function vmessToArr($sStr)
|
||||
{
|
||||
$sStr = base64_decode($sStr);
|
||||
$a = json_decode($sStr, true);
|
||||
$a["vtype"] = "vmess";
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
private static function ssToArr($sStr)
|
||||
{
|
||||
// YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU@63.180.254.10:443#8%E5%85%83%E8%80%81%E7%89%8C%E4%B8%93%E7%BA%BF%E6%9C%BA%E5%9C%BA%EF%BC%9Acczzuu.top
|
||||
$sStr = urldecode($sStr);
|
||||
list($sPwd, $sStr) = explode("@", $sStr, 2);
|
||||
$sPwd = base64_decode($sPwd);
|
||||
list($sCipher, $sPwd) = explode(":", $sPwd, 2);
|
||||
list($sServer, $sStr) = explode("#", $sStr, 2);
|
||||
list($sServer, $sPort) = explode(":", $sServer, 2);
|
||||
$aPort = explode("/?", $sPort, 2);
|
||||
$sPort = $aPort[0];
|
||||
$sOption = $aPort[1] ?? "";
|
||||
|
||||
if ($sOption) {
|
||||
$aOptionList = explode(";", $sOption);
|
||||
} else {
|
||||
$aOptionList = [];
|
||||
}
|
||||
|
||||
$aOptionArr = [];
|
||||
foreach ($aOptionList as $sOption) {
|
||||
if (!$sOption) {
|
||||
continue;
|
||||
}
|
||||
$aTmp = explode("=", $sOption, 2);
|
||||
$k = $aTmp[0] ?? "";
|
||||
$v = $aTmp[1] ?? "";
|
||||
$aOptionArr[$k] = $v;
|
||||
}
|
||||
|
||||
$sName = $sStr;
|
||||
|
||||
$a = [
|
||||
"vtype" => "ss",
|
||||
"server" => $sServer,
|
||||
"port" => $sPort,
|
||||
"cipher" => $sCipher,
|
||||
"password" => $sPwd,
|
||||
"name" => $sName,
|
||||
"option" => $aOptionArr,
|
||||
];
|
||||
|
||||
return $a;
|
||||
|
||||
}
|
||||
|
||||
private static function trojanToArr($sStr)
|
||||
{
|
||||
// 76d630f2af6619c4a5de0ef953df3c6a@58.152.110.154:443?allowInsecure=0&sni=www.nintendogames.net#%F0%9F%87%AD%F0%9F%87%B0%20%E9%A6%99%E6%B8%AF3%7C%40stairnode
|
||||
$sStr = urldecode($sStr);
|
||||
$aTmp = explode("@", $sStr, 2);
|
||||
$sPwd = $aTmp[0] ?? "";
|
||||
$sStr = $aTmp[1] ?? "";
|
||||
|
||||
$aTmp = explode("#", $sStr, 2);
|
||||
$sStr = $aTmp[0] ?? "";
|
||||
$sName = $aTmp[1] ?? "";
|
||||
|
||||
$aTmp = explode("?", $sStr, 2);
|
||||
$sServer = $aTmp[0] ?? "";
|
||||
$sStr = $aTmp[1] ?? "";
|
||||
|
||||
$aTmp = explode(":", $sServer, 2);
|
||||
$sServer = $aTmp[0] ?? "";
|
||||
$sPort = $aTmp[1] ?? "";
|
||||
|
||||
$aOptionList = explode("&", $sStr, 2);
|
||||
|
||||
$aOptionArr = [];
|
||||
foreach ($aOptionList as $sOption) {
|
||||
if (!$sOption) {
|
||||
continue;
|
||||
}
|
||||
$aTmp = explode("=", $sOption, 2);
|
||||
$k = $aTmp[0] ?? "";
|
||||
$v = $aTmp[1] ?? "";
|
||||
$aOptionArr[$k] = $v;
|
||||
}
|
||||
|
||||
$a = [
|
||||
"vtype" => "trojan",
|
||||
"name" => $sName,
|
||||
"server" => $sServer,
|
||||
"port" => $sPort,
|
||||
"password" => $sPwd,
|
||||
"option" => $aOptionArr,
|
||||
];
|
||||
|
||||
return $a;
|
||||
}
|
||||
|
||||
// public static function show($sDate = "")
|
||||
// {
|
||||
// if (!$sDate) {
|
||||
// $sDate = date("Y-m-d");
|
||||
// }
|
||||
//
|
||||
// $oPool = ModelFreenodePool::whereDate("date", $sDate)->first();
|
||||
//
|
||||
// if (!$oPool) {
|
||||
// return "没有?";
|
||||
// }
|
||||
//
|
||||
// return $oPool->content_custom;
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
56
app/Services/Cron/FreenodeSync.php
Normal file
56
app/Services/Cron/FreenodeSync.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\Cron;
|
||||
|
||||
use App\Models\SiteMap as ModelSiteMap;
|
||||
use App\Services\TomTool\Telegram\Slave as TeleSlave;
|
||||
use App\Services\TomTool\HttpV2;
|
||||
|
||||
final class FreenodeSync
|
||||
{
|
||||
static function run()
|
||||
{
|
||||
echo "\nFeenodeSync::run() - 开始 \n";
|
||||
|
||||
$sDirBase = $_ENV["dir_base"];
|
||||
|
||||
$oFnSiteList = ModelSiteMap::where("group_code", "fn_a")->get();
|
||||
|
||||
$aResultAll = [];
|
||||
foreach ($oFnSiteList as $oFnSite) {
|
||||
|
||||
$aSiteConfig = json_decode($oFnSite->config, true);
|
||||
$aSiteConfigFnClient = $aSiteConfig["freenode_client"] ?? [];
|
||||
$aSiteApi = json_decode($oFnSite->api_path, true);
|
||||
$sSiteApiFreenodeReceive = $aSiteApi["freenode_receive"] ?? "";
|
||||
|
||||
$aFnContent = [];
|
||||
foreach ($aSiteConfigFnClient as $aSiteConfigFnClientRow) {
|
||||
$sFilePath = $sDirBase."public/freenode/merge/".$oFnSite->code."/".$aSiteConfigFnClientRow."/".date("Y-m-d").".txt";
|
||||
|
||||
if (file_exists($sFilePath)) {
|
||||
$aFnContent[$aSiteConfigFnClientRow] = file_get_contents($sFilePath);
|
||||
} else {
|
||||
$sMsg = "freenodeSync的run没有当天文件".$sFilePath;
|
||||
TeleSlave::warn()->send($sMsg);
|
||||
}
|
||||
}
|
||||
|
||||
$sApiUrl = "https://".$oFnSite->url."/".$sSiteApiFreenodeReceive;
|
||||
$sResult = HttpV2::make($sApiUrl, "post")->setDataA($aFnContent)->enableJsonSend()->send();
|
||||
|
||||
$aResult = json_decode($sResult, true);
|
||||
|
||||
if (!isset($aResult["is_done"]) || $aResult["is_done"] != true) {
|
||||
$sMsg = "freenodeSync::同步失败 ->".json_encode($oFnSite->toArray())."->".json_encode($aResult);
|
||||
TeleSlave::warn()->setMsgS($sMsg)->send();
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo " - ok \n";
|
||||
}
|
||||
}
|
||||
@ -34,7 +34,7 @@ class Cron extends Base {
|
||||
$oServicesCron = new ServicesCron();
|
||||
|
||||
$oServicesCron->setTestH('06');
|
||||
$oServicesCron->setTestI('00');
|
||||
$oServicesCron->setTestI('03');
|
||||
$oServicesCron->setTestS('00');
|
||||
|
||||
if ($sType == "h") {
|
||||
|
||||
187
app/Services/Tg/Hook/Mod/Freenode.php
Normal file
187
app/Services/Tg/Hook/Mod/Freenode.php
Normal file
File diff suppressed because one or more lines are too long
@ -15,7 +15,7 @@ class SiteMap extends Base {
|
||||
$this->oDog = new Dog(new ModelSiteMap());
|
||||
$this->oDog->_setDogName("siteMap");
|
||||
$this->oDog->_setPrimaryKey("code"); // 可选,默认id
|
||||
// $this->oDog->_setJsonField(["use_from"]);
|
||||
$this->oDog->_setJsonField(["config"]);
|
||||
// $this->oDog->_setStrField(["content"]);
|
||||
// $this->aUpdate = $aUpdate;
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
// 版本:25-12-12
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool;
|
||||
@ -19,7 +21,7 @@ use Exception;
|
||||
HttpV2::make($url)->send()
|
||||
|
||||
进阶:
|
||||
HttpV2::make($url)->aData($aData)->setJsonAs()->setAsync()->setMethod("get")->send();
|
||||
HttpV2::make($url, "get")->setDataA($aData)->enableJsonAs()->enableAsync()->optMethod("get")->send();
|
||||
|
||||
action:
|
||||
send()
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
|
||||
// 版本 25/12/12
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Services\TomTool\Telegram;
|
||||
@ -64,12 +66,15 @@ class Slave
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -193,6 +198,11 @@ class Slave
|
||||
// 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);
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
"irazasyed/telegram-bot-sdk": "^3.15",
|
||||
"laravel/framework": "^11.31",
|
||||
"laravel/tinker": "^2.9",
|
||||
"symfony/yaml": "^7.4",
|
||||
"voku/anti-xss": "^4.1"
|
||||
},
|
||||
"require-dev": {
|
||||
|
||||
150
composer.lock
generated
150
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c2355b2300bdecd7969bd0274b53bde4",
|
||||
"content-hash": "0276bc3b1e98a844fc7c078b38dc44f8",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
@ -5814,6 +5814,82 @@
|
||||
],
|
||||
"time": "2024-11-08T15:48:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v7.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "6c84a4b55aee4cd02034d1c528e83f69ddf63810"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/6c84a4b55aee4cd02034d1c528e83f69ddf63810",
|
||||
"reference": "6c84a4b55aee4cd02034d1c528e83f69ddf63810",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<6.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"bin": [
|
||||
"Resources/bin/yaml-lint"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v7.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-16T10:14:42+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tijsverkoyen/css-to-inline-styles",
|
||||
"version": "v2.2.7",
|
||||
@ -8420,78 +8496,6 @@
|
||||
],
|
||||
"time": "2024-10-20T05:08:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v7.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "099581e99f557e9f16b43c5916c26380b54abb22"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22",
|
||||
"reference": "099581e99f557e9f16b43c5916c26380b54abb22",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3.0",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<6.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^6.4|^7.0"
|
||||
},
|
||||
"bin": [
|
||||
"Resources/bin/yaml-lint"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v7.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-10-23T06:56:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.3",
|
||||
|
||||
10
fn的tg策略.md
Normal file
10
fn的tg策略.md
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
汇集还是分散?
|
||||
方案1:各站的自页面和fn都slogan都指向自己
|
||||
方案2:各站的自页面指向自己,fn的slogan指向master
|
||||
方案3:各站的自页面和fn的slogan都指向master
|
||||
感觉,还是方案1合理,都指向自己?
|
||||
好像只该指向自己,因为频道发布节点时,应该要发送网站链接(提高点击率等于提高排名),你master就没法这么做
|
||||
对,这是关键票
|
||||
|
||||
另外github弄纯公益节点,不带广告,纯分享,然后在fn里加slogen,应该会有搞头
|
||||
19
fn逻辑.md
Executable file
19
fn逻辑.md
Executable file
@ -0,0 +1,19 @@
|
||||
|
||||
1.CronFreenodeCrawl :: 爬各来源,根据crawl_freenode,存到public/freenode/from/xxx文件。
|
||||
数据:
|
||||
v2ray只是base64_decode一下,便于查看
|
||||
clash没动,纯原始数据
|
||||
动机:
|
||||
保存一份原始数据,合理
|
||||
逻辑:
|
||||
如果没有crawl到,就直接忽视,pool是直接找file_real
|
||||
找到就更新file_real
|
||||
也就意味着,即便当天没更新到,pool也会直接找file_real最后有效更新的
|
||||
|
||||
2.CronFreenodePool :: 读各来源文件,根据crawl_freenode,存到freenode_pool。
|
||||
动机:
|
||||
合并与格式化,成为标准通用数据
|
||||
|
||||
3.CronFreenodeMerge :: 读freenode_pool,存到public/freenode/merge/base/xxx文件。
|
||||
动机:
|
||||
各site定制化,生成最终fn文件
|
||||
@ -18,6 +18,7 @@ use App\Http\Controllers\Api\GoodController;
|
||||
use App\Http\Controllers\Api\GithubController;
|
||||
use App\Services\OpenApi\Telegram as ServiceOpenApiTelegram;
|
||||
use App\Services\Article\Schema as ServiceArticleSchema;
|
||||
use App\Http\Controllers\Api\FreenodeController as ApiFreenodeController;
|
||||
|
||||
//Route::get('/', [ArticleListController::class, 'fn'])->middleware('test');
|
||||
// /api/telegram/post
|
||||
@ -25,6 +26,7 @@ use App\Services\Article\Schema as ServiceArticleSchema;
|
||||
Route::any('/api/telegram/post', [ServiceOpenApiTelegram::class, 'post']);
|
||||
Route::any('/api/article/schema/build', [ServiceArticleSchema::class, 'api_buildArticle']);
|
||||
Route::any('/api/article/schema/build/receive', [ServiceArticleSchema::class, 'api_build_receive']);
|
||||
Route::get('/sub/{siteCode}/{client}/{date?}', [ApiFreenodeController::class, "sub"]);
|
||||
|
||||
Route::get('/cmd', [CmdController::class, 'index']);
|
||||
Route::post('/cmd/send', [CmdController::class, 'ajaxSend']);
|
||||
|
||||
74
vendor/composer/autoload_classmap.php
vendored
74
vendor/composer/autoload_classmap.php
vendored
@ -10,15 +10,17 @@ return array(
|
||||
'App\\Http\\Controllers\\Api\\GithubController' => $baseDir . '/app/Http/Controllers/Api/GithubController.php',
|
||||
'App\\Http\\Controllers\\Api\\GoodController' => $baseDir . '/app/Http/Controllers/Api/GoodController.php',
|
||||
'App\\Http\\Controllers\\Api\\ShipController' => $baseDir . '/app/Http/Controllers/Api/ShipController.php',
|
||||
'App\\Http\\Controllers\\Api\\TG\\HookController' => $baseDir . '/app/Http/Controllers/Api/TG/HookController.php',
|
||||
'App\\Http\\Controllers\\Api\\Tg\\HookController' => $baseDir . '/app/Http/Controllers/Api/Tg/HookController.php',
|
||||
'App\\Http\\Controllers\\CmdController' => $baseDir . '/app/Http/Controllers/CmdController.php',
|
||||
'App\\Http\\Controllers\\CronController' => $baseDir . '/app/Http/Controllers/CronController.php',
|
||||
'App\\Http\\Controllers\\SakaiController' => $baseDir . '/app/Http/Controllers/SakaiController.php',
|
||||
'App\\Http\\Middleware\\Test' => $baseDir . '/app/Http/Middleware/Test.php',
|
||||
'App\\Models\\Article' => $baseDir . '/app/Models/Article.php',
|
||||
'App\\Models\\ArticleCache' => $baseDir . '/app/Models/ArticleCache.php',
|
||||
'App\\Models\\ArticleCacheTime' => $baseDir . '/app/Models/ArticleCacheTime.php',
|
||||
'App\\Models\\ArticleConfig' => $baseDir . '/app/Models/ArticleConfig.php',
|
||||
'App\\Models\\ArticleOption' => $baseDir . '/app/Models/ArticleOption.php',
|
||||
'App\\Models\\ArticleSchema' => $baseDir . '/app/Models/ArticleSchema.php',
|
||||
'App\\Models\\ArticleSiteMapGroup' => $baseDir . '/app/Models/ArticleSiteMapGroup.php',
|
||||
'App\\Models\\Blade' => $baseDir . '/app/Models/Blade.php',
|
||||
'App\\Models\\BladeJctj' => $baseDir . '/app/Models/BladeJctj.php',
|
||||
'App\\Models\\BladeJctjOption' => $baseDir . '/app/Models/BladeJctjOption.php',
|
||||
@ -27,6 +29,7 @@ return array(
|
||||
'App\\Models\\BookOption' => $baseDir . '/app/Models/BookOption.php',
|
||||
'App\\Models\\BookPage' => $baseDir . '/app/Models/BookPage.php',
|
||||
'App\\Models\\BoxGithubTag' => $baseDir . '/app/Models/BoxGithubTag.php',
|
||||
'App\\Models\\CrawlFreenode' => $baseDir . '/app/Models/CrawlFreenode.php',
|
||||
'App\\Models\\DogOption' => $baseDir . '/app/Models/DogOption.php',
|
||||
'App\\Models\\DoveSite' => $baseDir . '/app/Models/DoveSite.php',
|
||||
'App\\Models\\GoodPool' => $baseDir . '/app/Models/GoodPool.php',
|
||||
@ -37,39 +40,58 @@ return array(
|
||||
'App\\Models\\NoteOption' => $baseDir . '/app/Models/NoteOption.php',
|
||||
'App\\Models\\Option' => $baseDir . '/app/Models/Option.php',
|
||||
'App\\Models\\Ship' => $baseDir . '/app/Models/Ship.php',
|
||||
'App\\Models\\SiteMap' => $baseDir . '/app/Models/SiteMap.php',
|
||||
'App\\Models\\SitePathMap' => $baseDir . '/app/Models/SitePathMap.php',
|
||||
'App\\Models\\TelegramKey' => $baseDir . '/app/Models/TelegramKey.php',
|
||||
'App\\Providers\\AppServiceProvider' => $baseDir . '/app/Providers/AppServiceProvider.php',
|
||||
'App\\Services\\Article' => $baseDir . '/app/Services/Article.php',
|
||||
'App\\Services\\Article\\CacheTg' => $baseDir . '/app/Services/Article/CacheTg.php',
|
||||
'App\\Services\\Article\\Cmd' => $baseDir . '/app/Services/Article/Cmd.php',
|
||||
'App\\Services\\Article\\Schema' => $baseDir . '/app/Services/Article/Schema.php',
|
||||
'App\\Services\\Cron' => $baseDir . '/app/Services/Cron.php',
|
||||
'App\\Services\\Cron\\ArticleSchema' => $baseDir . '/app/Services/Cron/ArticleSchema.php',
|
||||
'App\\Services\\Cron\\CrawlFreenode' => $baseDir . '/app/Services/Cron/CrawlFreenode.php',
|
||||
'App\\Services\\Cron\\HttpQueue' => $baseDir . '/app/Services/Cron/HttpQueue.php',
|
||||
'App\\Services\\HttpQueue' => $baseDir . '/app/Services/HttpQueue.php',
|
||||
'App\\Services\\OpenApi\\Telegram' => $baseDir . '/app/Services/OpenApi/Telegram.php',
|
||||
'App\\Services\\SDK\\Master\\Telegram' => $baseDir . '/app/Services/SDK/Master/Telegram.php',
|
||||
'App\\Services\\TG\\Hook\\Dog' => $baseDir . '/app/Services/TG/Hook/Dog.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Article' => $baseDir . '/app/Services/TG/Hook/Mod/Article.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Base' => $baseDir . '/app/Services/TG/Hook/Mod/Base.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Blade' => $baseDir . '/app/Services/TG/Hook/Mod/Blade.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Book' => $baseDir . '/app/Services/TG/Hook/Mod/Book.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Box' => $baseDir . '/app/Services/TG/Hook/Mod/Box.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Cron' => $baseDir . '/app/Services/TG/Hook/Mod/Cron.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Db' => $baseDir . '/app/Services/TG/Hook/Mod/Db.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Dove' => $baseDir . '/app/Services/TG/Hook/Mod/Dove.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\DoveSite' => $baseDir . '/app/Services/TG/Hook/Mod/DoveSite.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Good' => $baseDir . '/app/Services/TG/Hook/Mod/Good.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Hook' => $baseDir . '/app/Services/TG/Hook/Mod/Hook.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Jctj' => $baseDir . '/app/Services/TG/Hook/Mod/Jctj.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\JctjOption' => $baseDir . '/app/Services/TG/Hook/Mod/JctjOption.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Note' => $baseDir . '/app/Services/TG/Hook/Mod/Note.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Option' => $baseDir . '/app/Services/TG/Hook/Mod/Option.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Ship' => $baseDir . '/app/Services/TG/Hook/Mod/Ship.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Test1' => $baseDir . '/app/Services/TG/Hook/Mod/Test1.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Tool' => $baseDir . '/app/Services/TG/Hook/Mod/Tool.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Upload' => $baseDir . '/app/Services/TG/Hook/Mod/Upload.php',
|
||||
'App\\Services\\TG\\Http' => $baseDir . '/app/Services/TG/Http.php',
|
||||
'App\\Services\\SlaveMap' => $baseDir . '/app/Services/SlaveMap.php',
|
||||
'App\\Services\\Tg\\Hook\\Dog' => $baseDir . '/app/Services/Tg/Hook/Dog.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Article' => $baseDir . '/app/Services/Tg/Hook/Mod/Article.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleCache' => $baseDir . '/app/Services/Tg/Hook/Mod/ArticleCache.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleConfig' => $baseDir . '/app/Services/Tg/Hook/Mod/ArticleConfig.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleSchema' => $baseDir . '/app/Services/Tg/Hook/Mod/ArticleSchema.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleSiteMapGroup' => $baseDir . '/app/Services/Tg/Hook/Mod/ArticleSiteMapGroup.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Base' => $baseDir . '/app/Services/Tg/Hook/Mod/Base.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Blade' => $baseDir . '/app/Services/Tg/Hook/Mod/Blade.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Book' => $baseDir . '/app/Services/Tg/Hook/Mod/Book.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Box' => $baseDir . '/app/Services/Tg/Hook/Mod/Box.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Cron' => $baseDir . '/app/Services/Tg/Hook/Mod/Cron.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Db' => $baseDir . '/app/Services/Tg/Hook/Mod/Db.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Dev' => $baseDir . '/app/Services/Tg/Hook/Mod/Dev.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Dove' => $baseDir . '/app/Services/Tg/Hook/Mod/Dove.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\DoveSite' => $baseDir . '/app/Services/Tg/Hook/Mod/DoveSite.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Good' => $baseDir . '/app/Services/Tg/Hook/Mod/Good.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Hook' => $baseDir . '/app/Services/Tg/Hook/Mod/Hook.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Jctj' => $baseDir . '/app/Services/Tg/Hook/Mod/Jctj.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\JctjOption' => $baseDir . '/app/Services/Tg/Hook/Mod/JctjOption.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Note' => $baseDir . '/app/Services/Tg/Hook/Mod/Note.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Option' => $baseDir . '/app/Services/Tg/Hook/Mod/Option.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Ship' => $baseDir . '/app/Services/Tg/Hook/Mod/Ship.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\SiteMap' => $baseDir . '/app/Services/Tg/Hook/Mod/SiteMap.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\SitePathMap' => $baseDir . '/app/Services/Tg/Hook/Mod/SitePathMap.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\TelegramKey' => $baseDir . '/app/Services/Tg/Hook/Mod/TelegramKey.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Test' => $baseDir . '/app/Services/Tg/Hook/Mod/Test.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Tool' => $baseDir . '/app/Services/Tg/Hook/Mod/Tool.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Upload' => $baseDir . '/app/Services/Tg/Hook/Mod/Upload.php',
|
||||
'App\\Services\\Tg\\Http' => $baseDir . '/app/Services/Tg/Http.php',
|
||||
'App\\Services\\TomTool\\Flow' => $baseDir . '/app/Services/TomTool/Flow.php',
|
||||
'App\\Services\\TomTool\\Http' => $baseDir . '/app/Services/TomTool/Http.php',
|
||||
'App\\Services\\TomTool\\HttpV2' => $baseDir . '/app/Services/TomTool/HttpV2.php',
|
||||
'App\\Services\\TomTool\\Result' => $baseDir . '/app/Services/TomTool/Result.php',
|
||||
'App\\Services\\TomTool\\TelegramVdb' => $baseDir . '/app/Services/TomTool/TelegramVdb.php',
|
||||
'App\\Services\\TomTool\\Telegram\\Master' => $baseDir . '/app/Services/TomTool/Telegram/Master.php',
|
||||
'App\\Services\\TomTool\\Telegram\\Sdk' => $baseDir . '/app/Services/TomTool/Telegram/Sdk.php',
|
||||
'App\\Services\\TomTool\\Telegram\\Slave' => $baseDir . '/app/Services/TomTool/Telegram/Slave.php',
|
||||
'App\\Services\\TomTool\\ThrowableHandler' => $baseDir . '/app/Services/TomTool/ThrowableHandler.php',
|
||||
'App\\Services\\TomTool\\Tom' => $baseDir . '/app/Services/TomTool/Tom.php',
|
||||
'Attribute' => $vendorDir . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Brick\\Math\\BigDecimal' => $vendorDir . '/brick/math/src/BigDecimal.php',
|
||||
'Brick\\Math\\BigInteger' => $vendorDir . '/brick/math/src/BigInteger.php',
|
||||
|
||||
74
vendor/composer/autoload_static.php
vendored
74
vendor/composer/autoload_static.php
vendored
@ -543,15 +543,17 @@ class ComposerStaticInit626b9e7ddd47fb7eff9aaa53cce0c9ad
|
||||
'App\\Http\\Controllers\\Api\\GithubController' => __DIR__ . '/../..' . '/app/Http/Controllers/Api/GithubController.php',
|
||||
'App\\Http\\Controllers\\Api\\GoodController' => __DIR__ . '/../..' . '/app/Http/Controllers/Api/GoodController.php',
|
||||
'App\\Http\\Controllers\\Api\\ShipController' => __DIR__ . '/../..' . '/app/Http/Controllers/Api/ShipController.php',
|
||||
'App\\Http\\Controllers\\Api\\TG\\HookController' => __DIR__ . '/../..' . '/app/Http/Controllers/Api/TG/HookController.php',
|
||||
'App\\Http\\Controllers\\Api\\Tg\\HookController' => __DIR__ . '/../..' . '/app/Http/Controllers/Api/Tg/HookController.php',
|
||||
'App\\Http\\Controllers\\CmdController' => __DIR__ . '/../..' . '/app/Http/Controllers/CmdController.php',
|
||||
'App\\Http\\Controllers\\CronController' => __DIR__ . '/../..' . '/app/Http/Controllers/CronController.php',
|
||||
'App\\Http\\Controllers\\SakaiController' => __DIR__ . '/../..' . '/app/Http/Controllers/SakaiController.php',
|
||||
'App\\Http\\Middleware\\Test' => __DIR__ . '/../..' . '/app/Http/Middleware/Test.php',
|
||||
'App\\Models\\Article' => __DIR__ . '/../..' . '/app/Models/Article.php',
|
||||
'App\\Models\\ArticleCache' => __DIR__ . '/../..' . '/app/Models/ArticleCache.php',
|
||||
'App\\Models\\ArticleCacheTime' => __DIR__ . '/../..' . '/app/Models/ArticleCacheTime.php',
|
||||
'App\\Models\\ArticleConfig' => __DIR__ . '/../..' . '/app/Models/ArticleConfig.php',
|
||||
'App\\Models\\ArticleOption' => __DIR__ . '/../..' . '/app/Models/ArticleOption.php',
|
||||
'App\\Models\\ArticleSchema' => __DIR__ . '/../..' . '/app/Models/ArticleSchema.php',
|
||||
'App\\Models\\ArticleSiteMapGroup' => __DIR__ . '/../..' . '/app/Models/ArticleSiteMapGroup.php',
|
||||
'App\\Models\\Blade' => __DIR__ . '/../..' . '/app/Models/Blade.php',
|
||||
'App\\Models\\BladeJctj' => __DIR__ . '/../..' . '/app/Models/BladeJctj.php',
|
||||
'App\\Models\\BladeJctjOption' => __DIR__ . '/../..' . '/app/Models/BladeJctjOption.php',
|
||||
@ -560,6 +562,7 @@ class ComposerStaticInit626b9e7ddd47fb7eff9aaa53cce0c9ad
|
||||
'App\\Models\\BookOption' => __DIR__ . '/../..' . '/app/Models/BookOption.php',
|
||||
'App\\Models\\BookPage' => __DIR__ . '/../..' . '/app/Models/BookPage.php',
|
||||
'App\\Models\\BoxGithubTag' => __DIR__ . '/../..' . '/app/Models/BoxGithubTag.php',
|
||||
'App\\Models\\CrawlFreenode' => __DIR__ . '/../..' . '/app/Models/CrawlFreenode.php',
|
||||
'App\\Models\\DogOption' => __DIR__ . '/../..' . '/app/Models/DogOption.php',
|
||||
'App\\Models\\DoveSite' => __DIR__ . '/../..' . '/app/Models/DoveSite.php',
|
||||
'App\\Models\\GoodPool' => __DIR__ . '/../..' . '/app/Models/GoodPool.php',
|
||||
@ -570,39 +573,58 @@ class ComposerStaticInit626b9e7ddd47fb7eff9aaa53cce0c9ad
|
||||
'App\\Models\\NoteOption' => __DIR__ . '/../..' . '/app/Models/NoteOption.php',
|
||||
'App\\Models\\Option' => __DIR__ . '/../..' . '/app/Models/Option.php',
|
||||
'App\\Models\\Ship' => __DIR__ . '/../..' . '/app/Models/Ship.php',
|
||||
'App\\Models\\SiteMap' => __DIR__ . '/../..' . '/app/Models/SiteMap.php',
|
||||
'App\\Models\\SitePathMap' => __DIR__ . '/../..' . '/app/Models/SitePathMap.php',
|
||||
'App\\Models\\TelegramKey' => __DIR__ . '/../..' . '/app/Models/TelegramKey.php',
|
||||
'App\\Providers\\AppServiceProvider' => __DIR__ . '/../..' . '/app/Providers/AppServiceProvider.php',
|
||||
'App\\Services\\Article' => __DIR__ . '/../..' . '/app/Services/Article.php',
|
||||
'App\\Services\\Article\\CacheTg' => __DIR__ . '/../..' . '/app/Services/Article/CacheTg.php',
|
||||
'App\\Services\\Article\\Cmd' => __DIR__ . '/../..' . '/app/Services/Article/Cmd.php',
|
||||
'App\\Services\\Article\\Schema' => __DIR__ . '/../..' . '/app/Services/Article/Schema.php',
|
||||
'App\\Services\\Cron' => __DIR__ . '/../..' . '/app/Services/Cron.php',
|
||||
'App\\Services\\Cron\\ArticleSchema' => __DIR__ . '/../..' . '/app/Services/Cron/ArticleSchema.php',
|
||||
'App\\Services\\Cron\\CrawlFreenode' => __DIR__ . '/../..' . '/app/Services/Cron/CrawlFreenode.php',
|
||||
'App\\Services\\Cron\\HttpQueue' => __DIR__ . '/../..' . '/app/Services/Cron/HttpQueue.php',
|
||||
'App\\Services\\HttpQueue' => __DIR__ . '/../..' . '/app/Services/HttpQueue.php',
|
||||
'App\\Services\\OpenApi\\Telegram' => __DIR__ . '/../..' . '/app/Services/OpenApi/Telegram.php',
|
||||
'App\\Services\\SDK\\Master\\Telegram' => __DIR__ . '/../..' . '/app/Services/SDK/Master/Telegram.php',
|
||||
'App\\Services\\TG\\Hook\\Dog' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Dog.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Article' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Article.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Base' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Base.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Blade' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Blade.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Book' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Book.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Box' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Box.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Cron' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Cron.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Db' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Db.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Dove' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Dove.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\DoveSite' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/DoveSite.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Good' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Good.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Hook' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Hook.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Jctj' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Jctj.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\JctjOption' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/JctjOption.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Note' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Note.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Option' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Option.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Ship' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Ship.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Test1' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Test1.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Tool' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Tool.php',
|
||||
'App\\Services\\TG\\Hook\\Mod\\Upload' => __DIR__ . '/../..' . '/app/Services/TG/Hook/Mod/Upload.php',
|
||||
'App\\Services\\TG\\Http' => __DIR__ . '/../..' . '/app/Services/TG/Http.php',
|
||||
'App\\Services\\SlaveMap' => __DIR__ . '/../..' . '/app/Services/SlaveMap.php',
|
||||
'App\\Services\\Tg\\Hook\\Dog' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Dog.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Article' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Article.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleCache' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/ArticleCache.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleConfig' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/ArticleConfig.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleSchema' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/ArticleSchema.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\ArticleSiteMapGroup' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/ArticleSiteMapGroup.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Base' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Base.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Blade' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Blade.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Book' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Book.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Box' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Box.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Cron' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Cron.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Db' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Db.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Dev' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Dev.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Dove' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Dove.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\DoveSite' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/DoveSite.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Good' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Good.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Hook' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Hook.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Jctj' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Jctj.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\JctjOption' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/JctjOption.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Note' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Note.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Option' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Option.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Ship' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Ship.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\SiteMap' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/SiteMap.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\SitePathMap' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/SitePathMap.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\TelegramKey' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/TelegramKey.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Test' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Test.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Tool' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Tool.php',
|
||||
'App\\Services\\Tg\\Hook\\Mod\\Upload' => __DIR__ . '/../..' . '/app/Services/Tg/Hook/Mod/Upload.php',
|
||||
'App\\Services\\Tg\\Http' => __DIR__ . '/../..' . '/app/Services/Tg/Http.php',
|
||||
'App\\Services\\TomTool\\Flow' => __DIR__ . '/../..' . '/app/Services/TomTool/Flow.php',
|
||||
'App\\Services\\TomTool\\Http' => __DIR__ . '/../..' . '/app/Services/TomTool/Http.php',
|
||||
'App\\Services\\TomTool\\HttpV2' => __DIR__ . '/../..' . '/app/Services/TomTool/HttpV2.php',
|
||||
'App\\Services\\TomTool\\Result' => __DIR__ . '/../..' . '/app/Services/TomTool/Result.php',
|
||||
'App\\Services\\TomTool\\TelegramVdb' => __DIR__ . '/../..' . '/app/Services/TomTool/TelegramVdb.php',
|
||||
'App\\Services\\TomTool\\Telegram\\Master' => __DIR__ . '/../..' . '/app/Services/TomTool/Telegram/Master.php',
|
||||
'App\\Services\\TomTool\\Telegram\\Sdk' => __DIR__ . '/../..' . '/app/Services/TomTool/Telegram/Sdk.php',
|
||||
'App\\Services\\TomTool\\Telegram\\Slave' => __DIR__ . '/../..' . '/app/Services/TomTool/Telegram/Slave.php',
|
||||
'App\\Services\\TomTool\\ThrowableHandler' => __DIR__ . '/../..' . '/app/Services/TomTool/ThrowableHandler.php',
|
||||
'App\\Services\\TomTool\\Tom' => __DIR__ . '/../..' . '/app/Services/TomTool/Tom.php',
|
||||
'Attribute' => __DIR__ . '/..' . '/symfony/polyfill-php80/Resources/stubs/Attribute.php',
|
||||
'Brick\\Math\\BigDecimal' => __DIR__ . '/..' . '/brick/math/src/BigDecimal.php',
|
||||
'Brick\\Math\\BigInteger' => __DIR__ . '/..' . '/brick/math/src/BigInteger.php',
|
||||
|
||||
23
vendor/composer/installed.json
vendored
23
vendor/composer/installed.json
vendored
@ -8282,31 +8282,31 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v7.2.0",
|
||||
"version_normalized": "7.2.0.0",
|
||||
"version": "v7.4.0",
|
||||
"version_normalized": "7.4.0.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "099581e99f557e9f16b43c5916c26380b54abb22"
|
||||
"reference": "6c84a4b55aee4cd02034d1c528e83f69ddf63810"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/099581e99f557e9f16b43c5916c26380b54abb22",
|
||||
"reference": "099581e99f557e9f16b43c5916c26380b54abb22",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/6c84a4b55aee4cd02034d1c528e83f69ddf63810",
|
||||
"reference": "6c84a4b55aee4cd02034d1c528e83f69ddf63810",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<6.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^6.4|^7.0"
|
||||
"symfony/console": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"time": "2024-10-23T06:56:12+00:00",
|
||||
"time": "2025-11-16T10:14:42+00:00",
|
||||
"bin": [
|
||||
"Resources/bin/yaml-lint"
|
||||
],
|
||||
@ -8337,7 +8337,7 @@
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v7.2.0"
|
||||
"source": "https://github.com/symfony/yaml/tree/v7.4.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@ -8348,6 +8348,10 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
@ -8917,7 +8921,6 @@
|
||||
"sebastian/type",
|
||||
"sebastian/version",
|
||||
"staabm/side-effects-detector",
|
||||
"symfony/yaml",
|
||||
"theseer/tokenizer"
|
||||
]
|
||||
}
|
||||
|
||||
12
vendor/composer/installed.php
vendored
12
vendor/composer/installed.php
vendored
@ -3,7 +3,7 @@
|
||||
'name' => 'laravel/laravel',
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '01b8e3cd12bcd4f049e32ce5ec54aea8c40fae41',
|
||||
'reference' => '6843f40b786f201ee5dec7fe59e77678399fbc3a',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -397,7 +397,7 @@
|
||||
'laravel/laravel' => array(
|
||||
'pretty_version' => 'dev-master',
|
||||
'version' => 'dev-master',
|
||||
'reference' => '01b8e3cd12bcd4f049e32ce5ec54aea8c40fae41',
|
||||
'reference' => '6843f40b786f201ee5dec7fe59e77678399fbc3a',
|
||||
'type' => 'project',
|
||||
'install_path' => __DIR__ . '/../../',
|
||||
'aliases' => array(),
|
||||
@ -1293,13 +1293,13 @@
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'symfony/yaml' => array(
|
||||
'pretty_version' => 'v7.2.0',
|
||||
'version' => '7.2.0.0',
|
||||
'reference' => '099581e99f557e9f16b43c5916c26380b54abb22',
|
||||
'pretty_version' => 'v7.4.0',
|
||||
'version' => '7.4.0.0',
|
||||
'reference' => '6c84a4b55aee4cd02034d1c528e83f69ddf63810',
|
||||
'type' => 'library',
|
||||
'install_path' => __DIR__ . '/../symfony/yaml',
|
||||
'aliases' => array(),
|
||||
'dev_requirement' => true,
|
||||
'dev_requirement' => false,
|
||||
),
|
||||
'theseer/tokenizer' => array(
|
||||
'pretty_version' => '1.2.3',
|
||||
|
||||
7
vendor/symfony/yaml/CHANGELOG.md
vendored
Executable file → Normal file
7
vendor/symfony/yaml/CHANGELOG.md
vendored
Executable file → Normal file
@ -1,10 +1,17 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
7.3
|
||||
---
|
||||
|
||||
* Add compact nested mapping support by using the `Yaml::DUMP_COMPACT_NESTED_MAPPING` flag
|
||||
* Add the `Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES` flag to enforce double quotes around string values
|
||||
|
||||
7.2
|
||||
---
|
||||
|
||||
* Deprecate parsing duplicate mapping keys whose value is `null`
|
||||
* Add support for dumping `null` as an empty value by using the `Yaml::DUMP_NULL_AS_EMPTY` flag
|
||||
|
||||
7.1
|
||||
---
|
||||
|
||||
28
vendor/symfony/yaml/Command/LintCommand.php
vendored
Executable file → Normal file
28
vendor/symfony/yaml/Command/LintCommand.php
vendored
Executable file → Normal file
@ -58,30 +58,30 @@ class LintCommand extends Command
|
||||
->addOption('exclude', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Path(s) to exclude')
|
||||
->addOption('parse-tags', null, InputOption::VALUE_NEGATABLE, 'Parse custom tags', null)
|
||||
->setHelp(<<<EOF
|
||||
The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
|
||||
the first encountered syntax error.
|
||||
The <info>%command.name%</info> command lints a YAML file and outputs to STDOUT
|
||||
the first encountered syntax error.
|
||||
|
||||
You can validates YAML contents passed from STDIN:
|
||||
You can validates YAML contents passed from STDIN:
|
||||
|
||||
<info>cat filename | php %command.full_name% -</info>
|
||||
<info>cat filename | php %command.full_name% -</info>
|
||||
|
||||
You can also validate the syntax of a file:
|
||||
You can also validate the syntax of a file:
|
||||
|
||||
<info>php %command.full_name% filename</info>
|
||||
<info>php %command.full_name% filename</info>
|
||||
|
||||
Or of a whole directory:
|
||||
Or of a whole directory:
|
||||
|
||||
<info>php %command.full_name% dirname</info>
|
||||
<info>php %command.full_name% dirname</info>
|
||||
|
||||
The <info>--format</info> option specifies the format of the command output:
|
||||
The <info>--format</info> option specifies the format of the command output:
|
||||
|
||||
<info>php %command.full_name% dirname --format=json</info>
|
||||
<info>php %command.full_name% dirname --format=json</info>
|
||||
|
||||
You can also exclude one or more specific files:
|
||||
You can also exclude one or more specific files:
|
||||
|
||||
<info>php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml"</info>
|
||||
<info>php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml"</info>
|
||||
|
||||
EOF
|
||||
EOF
|
||||
)
|
||||
;
|
||||
}
|
||||
@ -224,7 +224,7 @@ EOF
|
||||
}
|
||||
|
||||
foreach ($this->getDirectoryIterator($fileOrDirectory) as $file) {
|
||||
if (!\in_array($file->getExtension(), ['yml', 'yaml'])) {
|
||||
if (!\in_array($file->getExtension(), ['yml', 'yaml'], true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
28
vendor/symfony/yaml/Dumper.php
vendored
Executable file → Normal file
28
vendor/symfony/yaml/Dumper.php
vendored
Executable file → Normal file
@ -41,6 +41,15 @@ class Dumper
|
||||
* @param int-mask-of<Yaml::DUMP_*> $flags A bit field of Yaml::DUMP_* constants to customize the dumped YAML string
|
||||
*/
|
||||
public function dump(mixed $input, int $inline = 0, int $indent = 0, int $flags = 0): string
|
||||
{
|
||||
if ($flags & Yaml::DUMP_NULL_AS_EMPTY && $flags & Yaml::DUMP_NULL_AS_TILDE) {
|
||||
throw new \InvalidArgumentException('The Yaml::DUMP_NULL_AS_EMPTY and Yaml::DUMP_NULL_AS_TILDE flags cannot be used together.');
|
||||
}
|
||||
|
||||
return $this->doDump($input, $inline, $indent, $flags);
|
||||
}
|
||||
|
||||
private function doDump(mixed $input, int $inline = 0, int $indent = 0, int $flags = 0, int $nestingLevel = 0): string
|
||||
{
|
||||
$output = '';
|
||||
$prefix = $indent ? str_repeat(' ', $indent) : '';
|
||||
@ -51,11 +60,12 @@ class Dumper
|
||||
}
|
||||
|
||||
if ($inline <= 0 || (!\is_array($input) && !$input instanceof TaggedValue && $dumpObjectAsInlineMap) || !$input) {
|
||||
$output .= $prefix.Inline::dump($input, $flags);
|
||||
$output .= $prefix.Inline::dump($input, $flags, 0 === $nestingLevel);
|
||||
} elseif ($input instanceof TaggedValue) {
|
||||
$output .= $this->dumpTaggedValue($input, $inline, $indent, $flags, $prefix);
|
||||
$output .= $this->dumpTaggedValue($input, $inline, $indent, $flags, $prefix, $nestingLevel);
|
||||
} else {
|
||||
$dumpAsMap = Inline::isHash($input);
|
||||
$compactNestedMapping = Yaml::DUMP_COMPACT_NESTED_MAPPING & $flags && !$dumpAsMap;
|
||||
|
||||
foreach ($input as $key => $value) {
|
||||
if ('' !== $output && "\n" !== $output[-1]) {
|
||||
@ -105,10 +115,10 @@ class Dumper
|
||||
}
|
||||
|
||||
if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
|
||||
$output .= ' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n";
|
||||
$output .= ' '.$this->doDump($value->getValue(), $inline - 1, 0, $flags, $nestingLevel + 1)."\n";
|
||||
} else {
|
||||
$output .= "\n";
|
||||
$output .= $this->dump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags);
|
||||
$output .= $this->doDump($value->getValue(), $inline - 1, $dumpAsMap ? $indent + $this->indentation : $indent + 2, $flags, $nestingLevel + 1);
|
||||
}
|
||||
|
||||
continue;
|
||||
@ -125,8 +135,8 @@ class Dumper
|
||||
$output .= \sprintf('%s%s%s%s',
|
||||
$prefix,
|
||||
$dumpAsMap ? Inline::dump($key, $flags).':' : '-',
|
||||
$willBeInlined ? ' ' : "\n",
|
||||
$this->dump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags)
|
||||
$willBeInlined || ($compactNestedMapping && \is_array($value) && Inline::isHash($value)) ? ' ' : "\n",
|
||||
$compactNestedMapping && \is_array($value) && Inline::isHash($value) ? substr($this->doDump($value, $inline - 1, $indent + 2, $flags, $nestingLevel + 1), $indent + 2) : $this->doDump($value, $inline - 1, $willBeInlined ? 0 : $indent + $this->indentation, $flags, $nestingLevel + 1)
|
||||
).($willBeInlined ? "\n" : '');
|
||||
}
|
||||
}
|
||||
@ -134,7 +144,7 @@ class Dumper
|
||||
return $output;
|
||||
}
|
||||
|
||||
private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, int $flags, string $prefix): string
|
||||
private function dumpTaggedValue(TaggedValue $value, int $inline, int $indent, int $flags, string $prefix, int $nestingLevel): string
|
||||
{
|
||||
$output = \sprintf('%s!%s', $prefix ? $prefix.' ' : '', $value->getTag());
|
||||
|
||||
@ -150,10 +160,10 @@ class Dumper
|
||||
}
|
||||
|
||||
if ($inline - 1 <= 0 || null === $value->getValue() || \is_scalar($value->getValue())) {
|
||||
return $output.' '.$this->dump($value->getValue(), $inline - 1, 0, $flags)."\n";
|
||||
return $output.' '.$this->doDump($value->getValue(), $inline - 1, 0, $flags, $nestingLevel + 1)."\n";
|
||||
}
|
||||
|
||||
return $output."\n".$this->dump($value->getValue(), $inline - 1, $indent, $flags);
|
||||
return $output."\n".$this->doDump($value->getValue(), $inline - 1, $indent, $flags, $nestingLevel + 1);
|
||||
}
|
||||
|
||||
private function getBlockIndentationIndicator(string $value): string
|
||||
|
||||
36
vendor/symfony/yaml/Escaper.php
vendored
Executable file → Normal file
36
vendor/symfony/yaml/Escaper.php
vendored
Executable file → Normal file
@ -28,22 +28,24 @@ class Escaper
|
||||
// first to ensure proper escaping because str_replace operates iteratively
|
||||
// on the input arrays. This ordering of the characters avoids the use of strtr,
|
||||
// which performs more slowly.
|
||||
private const ESCAPEES = ['\\', '\\\\', '\\"', '"',
|
||||
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
|
||||
"\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
|
||||
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
|
||||
"\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
|
||||
"\x7f",
|
||||
"\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9",
|
||||
];
|
||||
private const ESCAPED = ['\\\\', '\\"', '\\\\', '\\"',
|
||||
'\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a',
|
||||
'\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f',
|
||||
'\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17',
|
||||
'\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f',
|
||||
'\\x7f',
|
||||
'\\N', '\\_', '\\L', '\\P',
|
||||
];
|
||||
private const ESCAPEES = [
|
||||
'\\', '\\\\', '\\"', '"',
|
||||
"\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
|
||||
"\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
|
||||
"\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
|
||||
"\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
|
||||
"\x7f",
|
||||
"\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9",
|
||||
];
|
||||
private const ESCAPED = [
|
||||
'\\\\', '\\"', '\\\\', '\\"',
|
||||
'\\0', '\\x01', '\\x02', '\\x03', '\\x04', '\\x05', '\\x06', '\\a',
|
||||
'\\b', '\\t', '\\n', '\\v', '\\f', '\\r', '\\x0e', '\\x0f',
|
||||
'\\x10', '\\x11', '\\x12', '\\x13', '\\x14', '\\x15', '\\x16', '\\x17',
|
||||
'\\x18', '\\x19', '\\x1a', '\\e', '\\x1c', '\\x1d', '\\x1e', '\\x1f',
|
||||
'\\x7f',
|
||||
'\\N', '\\_', '\\L', '\\P',
|
||||
];
|
||||
|
||||
/**
|
||||
* Determines if a PHP value would require double quoting in YAML.
|
||||
@ -74,7 +76,7 @@ class Escaper
|
||||
{
|
||||
// Determines if a PHP value is entirely composed of a value that would
|
||||
// require single quoting in YAML.
|
||||
if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'])) {
|
||||
if (\in_array(strtolower($value), ['null', '~', 'true', 'false', 'y', 'n', 'yes', 'no', 'on', 'off'], true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
0
vendor/symfony/yaml/Exception/DumpException.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/DumpException.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/ExceptionInterface.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/ExceptionInterface.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/ParseException.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/ParseException.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/RuntimeException.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Exception/RuntimeException.php
vendored
Executable file → Normal file
48
vendor/symfony/yaml/Inline.php
vendored
Executable file → Normal file
48
vendor/symfony/yaml/Inline.php
vendored
Executable file → Normal file
@ -100,7 +100,7 @@ class Inline
|
||||
*
|
||||
* @throws DumpException When trying to dump PHP resource
|
||||
*/
|
||||
public static function dump(mixed $value, int $flags = 0): string
|
||||
public static function dump(mixed $value, int $flags = 0, bool $rootLevel = false): string
|
||||
{
|
||||
switch (true) {
|
||||
case \is_resource($value):
|
||||
@ -138,7 +138,7 @@ class Inline
|
||||
case \is_array($value):
|
||||
return self::dumpArray($value, $flags);
|
||||
case null === $value:
|
||||
return self::dumpNull($flags);
|
||||
return self::dumpNull($flags, $rootLevel);
|
||||
case true === $value:
|
||||
return 'true';
|
||||
case false === $value:
|
||||
@ -173,6 +173,7 @@ class Inline
|
||||
case self::isBinaryString($value):
|
||||
return '!!binary '.base64_encode($value);
|
||||
case Escaper::requiresDoubleQuoting($value):
|
||||
case Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES & $flags:
|
||||
return Escaper::escapeWithDoubleQuotes($value);
|
||||
case Escaper::requiresSingleQuoting($value):
|
||||
$singleQuoted = Escaper::escapeWithSingleQuotes($value);
|
||||
@ -242,23 +243,28 @@ class Inline
|
||||
private static function dumpHashArray(array|\ArrayObject|\stdClass $value, int $flags): string
|
||||
{
|
||||
$output = [];
|
||||
$keyFlags = $flags & ~Yaml::DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES;
|
||||
foreach ($value as $key => $val) {
|
||||
if (\is_int($key) && Yaml::DUMP_NUMERIC_KEY_AS_STRING & $flags) {
|
||||
$key = (string) $key;
|
||||
}
|
||||
|
||||
$output[] = \sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags));
|
||||
$output[] = \sprintf('%s: %s', self::dump($key, $keyFlags), self::dump($val, $flags));
|
||||
}
|
||||
|
||||
return \sprintf('{ %s }', implode(', ', $output));
|
||||
}
|
||||
|
||||
private static function dumpNull(int $flags): string
|
||||
private static function dumpNull(int $flags, bool $rootLevel = false): string
|
||||
{
|
||||
if (Yaml::DUMP_NULL_AS_TILDE & $flags) {
|
||||
return '~';
|
||||
}
|
||||
|
||||
if (Yaml::DUMP_NULL_AS_EMPTY & $flags && !$rootLevel) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return 'null';
|
||||
}
|
||||
|
||||
@ -453,7 +459,7 @@ class Inline
|
||||
}
|
||||
|
||||
if ('!php/const' === $key || '!php/enum' === $key) {
|
||||
$key .= ' '.self::parseScalar($mapping, $flags, [':'], $i, false);
|
||||
$key .= ' '.self::parseScalar($mapping, $flags, ['(?<!:):(?!:)'], $i, false);
|
||||
$key = self::evaluateScalar($key, $flags);
|
||||
}
|
||||
|
||||
@ -708,6 +714,10 @@ class Inline
|
||||
switch (true) {
|
||||
case ctype_digit($scalar):
|
||||
case '-' === $scalar[0] && ctype_digit(substr($scalar, 1)):
|
||||
if ($scalar < \PHP_INT_MIN || \PHP_INT_MAX < $scalar) {
|
||||
return $scalar;
|
||||
}
|
||||
|
||||
$cast = (int) $scalar;
|
||||
|
||||
return ($scalar === (string) $cast) ? $cast : $scalar;
|
||||
@ -744,7 +754,7 @@ class Inline
|
||||
if (false !== $scalar = $time->getTimestamp()) {
|
||||
return $scalar;
|
||||
}
|
||||
} catch (\ValueError) {
|
||||
} catch (\DateRangeError|\ValueError) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
@ -823,19 +833,19 @@ class Inline
|
||||
private static function getTimestampRegex(): string
|
||||
{
|
||||
return <<<EOF
|
||||
~^
|
||||
(?P<year>[0-9][0-9][0-9][0-9])
|
||||
-(?P<month>[0-9][0-9]?)
|
||||
-(?P<day>[0-9][0-9]?)
|
||||
(?:(?:[Tt]|[ \t]+)
|
||||
(?P<hour>[0-9][0-9]?)
|
||||
:(?P<minute>[0-9][0-9])
|
||||
:(?P<second>[0-9][0-9])
|
||||
(?:\.(?P<fraction>[0-9]*))?
|
||||
(?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
|
||||
(?::(?P<tz_minute>[0-9][0-9]))?))?)?
|
||||
$~x
|
||||
EOF;
|
||||
~^
|
||||
(?P<year>[0-9][0-9][0-9][0-9])
|
||||
-(?P<month>[0-9][0-9]?)
|
||||
-(?P<day>[0-9][0-9]?)
|
||||
(?:(?:[Tt]|[ \t]+)
|
||||
(?P<hour>[0-9][0-9]?)
|
||||
:(?P<minute>[0-9][0-9])
|
||||
:(?P<second>[0-9][0-9])
|
||||
(?:\.(?P<fraction>[0-9]*))?
|
||||
(?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
|
||||
(?::(?P<tz_minute>[0-9][0-9]))?))?)?
|
||||
$~x
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
0
vendor/symfony/yaml/LICENSE
vendored
Executable file → Normal file
0
vendor/symfony/yaml/LICENSE
vendored
Executable file → Normal file
44
vendor/symfony/yaml/Parser.php
vendored
Executable file → Normal file
44
vendor/symfony/yaml/Parser.php
vendored
Executable file → Normal file
@ -198,7 +198,7 @@ class Parser
|
||||
}
|
||||
} elseif (
|
||||
self::preg_match('#^(?P<key>(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{!].*?)) *\:(( |\t)++(?P<value>.+))?$#u', rtrim($this->currentLine), $values)
|
||||
&& (!str_contains($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"]))
|
||||
&& (!str_contains($values['key'], ' #') || \in_array($values['key'][0], ['"', "'"], true))
|
||||
) {
|
||||
if ($context && 'sequence' == $context) {
|
||||
throw new ParseException('You cannot define a mapping item when in a sequence.', $this->currentLineNb + 1, $this->currentLine, $this->filename);
|
||||
@ -769,6 +769,11 @@ class Parser
|
||||
$lines = [];
|
||||
|
||||
while ($this->moveToNextLine()) {
|
||||
if ($this->isCurrentLineBlank()) {
|
||||
$lines[] = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// unquoted strings end before the first unindented line
|
||||
if (0 === $this->getCurrentLineIndentation()) {
|
||||
$this->moveToPreviousLine();
|
||||
@ -776,6 +781,10 @@ class Parser
|
||||
break;
|
||||
}
|
||||
|
||||
if ($this->isCurrentLineComment()) {
|
||||
break;
|
||||
}
|
||||
|
||||
$lines[] = trim($this->currentLine);
|
||||
}
|
||||
|
||||
@ -1165,7 +1174,18 @@ class Parser
|
||||
private function lexUnquotedString(int &$cursor): string
|
||||
{
|
||||
$offset = $cursor;
|
||||
$cursor += strcspn($this->currentLine, '[]{},: ', $cursor);
|
||||
|
||||
while ($cursor < \strlen($this->currentLine)) {
|
||||
if (\in_array($this->currentLine[$cursor], ['[', ']', '{', '}', ',', ':'], true)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (\in_array($this->currentLine[$cursor], [' ', "\t"], true) && '#' === ($this->currentLine[$cursor + 1] ?? '')) {
|
||||
break;
|
||||
}
|
||||
|
||||
++$cursor;
|
||||
}
|
||||
|
||||
if ($cursor === $offset) {
|
||||
throw new ParseException('Malformed unquoted YAML string.');
|
||||
@ -1174,17 +1194,17 @@ class Parser
|
||||
return substr($this->currentLine, $offset, $cursor - $offset);
|
||||
}
|
||||
|
||||
private function lexInlineMapping(int &$cursor = 0): string
|
||||
private function lexInlineMapping(int &$cursor = 0, bool $consumeUntilEol = true): string
|
||||
{
|
||||
return $this->lexInlineStructure($cursor, '}');
|
||||
return $this->lexInlineStructure($cursor, '}', $consumeUntilEol);
|
||||
}
|
||||
|
||||
private function lexInlineSequence(int &$cursor = 0): string
|
||||
private function lexInlineSequence(int &$cursor = 0, bool $consumeUntilEol = true): string
|
||||
{
|
||||
return $this->lexInlineStructure($cursor, ']');
|
||||
return $this->lexInlineStructure($cursor, ']', $consumeUntilEol);
|
||||
}
|
||||
|
||||
private function lexInlineStructure(int &$cursor, string $closingTag): string
|
||||
private function lexInlineStructure(int &$cursor, string $closingTag, bool $consumeUntilEol = true): string
|
||||
{
|
||||
$value = $this->currentLine[$cursor];
|
||||
++$cursor;
|
||||
@ -1204,15 +1224,19 @@ class Parser
|
||||
++$cursor;
|
||||
break;
|
||||
case '{':
|
||||
$value .= $this->lexInlineMapping($cursor);
|
||||
$value .= $this->lexInlineMapping($cursor, false);
|
||||
break;
|
||||
case '[':
|
||||
$value .= $this->lexInlineSequence($cursor);
|
||||
$value .= $this->lexInlineSequence($cursor, false);
|
||||
break;
|
||||
case $closingTag:
|
||||
$value .= $this->currentLine[$cursor];
|
||||
++$cursor;
|
||||
|
||||
if ($consumeUntilEol && isset($this->currentLine[$cursor]) && ($whitespaces = strspn($this->currentLine, ' ', $cursor) + $cursor) < \strlen($this->currentLine) && '#' !== $this->currentLine[$whitespaces]) {
|
||||
throw new ParseException(\sprintf('Unexpected token "%s".', trim(substr($this->currentLine, $cursor))));
|
||||
}
|
||||
|
||||
return $value;
|
||||
case '#':
|
||||
break 2;
|
||||
@ -1238,7 +1262,7 @@ class Parser
|
||||
$whitespacesConsumed = 0;
|
||||
|
||||
do {
|
||||
$whitespaceOnlyTokenLength = strspn($this->currentLine, ' ', $cursor);
|
||||
$whitespaceOnlyTokenLength = strspn($this->currentLine, " \t", $cursor);
|
||||
$whitespacesConsumed += $whitespaceOnlyTokenLength;
|
||||
$cursor += $whitespaceOnlyTokenLength;
|
||||
|
||||
|
||||
9
vendor/symfony/yaml/Resources/bin/yaml-lint
vendored
9
vendor/symfony/yaml/Resources/bin/yaml-lint
vendored
@ -42,8 +42,13 @@ if (!class_exists(Application::class)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
(new Application())->add($command = new LintCommand())
|
||||
->getApplication()
|
||||
$command = new LintCommand();
|
||||
if (method_exists($app = new Application(), 'addCommand')) {
|
||||
$app->addCommand($command);
|
||||
} else {
|
||||
$app->add($command);
|
||||
}
|
||||
$app
|
||||
->setDefaultCommand($command->getName(), true)
|
||||
->run()
|
||||
;
|
||||
|
||||
0
vendor/symfony/yaml/Tag/TaggedValue.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Tag/TaggedValue.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Unescaper.php
vendored
Executable file → Normal file
0
vendor/symfony/yaml/Unescaper.php
vendored
Executable file → Normal file
3
vendor/symfony/yaml/Yaml.php
vendored
Executable file → Normal file
3
vendor/symfony/yaml/Yaml.php
vendored
Executable file → Normal file
@ -35,6 +35,9 @@ class Yaml
|
||||
public const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024;
|
||||
public const DUMP_NULL_AS_TILDE = 2048;
|
||||
public const DUMP_NUMERIC_KEY_AS_STRING = 4096;
|
||||
public const DUMP_NULL_AS_EMPTY = 8192;
|
||||
public const DUMP_COMPACT_NESTED_MAPPING = 16384;
|
||||
public const DUMP_FORCE_DOUBLE_QUOTES_ON_VALUES = 32768;
|
||||
|
||||
/**
|
||||
* Parses a YAML file into a PHP value.
|
||||
|
||||
4
vendor/symfony/yaml/composer.json
vendored
Executable file → Normal file
4
vendor/symfony/yaml/composer.json
vendored
Executable file → Normal file
@ -17,11 +17,11 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=8.2",
|
||||
"symfony/deprecation-contracts": "^2.5|^3.0",
|
||||
"symfony/deprecation-contracts": "^2.5|^3",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^6.4|^7.0"
|
||||
"symfony/console": "^6.4|^7.0|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<6.4"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user