diff --git a/.gitignore b/.gitignore index 6558a36f..37561b44 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ public/fn/ README.md _env/ public/upload/ +public/freenode/ diff --git a/app/Http/Controllers/Api/FreenodeController.php b/app/Http/Controllers/Api/FreenodeController.php new file mode 100755 index 00000000..01eba4a0 --- /dev/null +++ b/app/Http/Controllers/Api/FreenodeController.php @@ -0,0 +1,94 @@ +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); + } + } + + +} diff --git a/app/Models/CrawlFreenode.php b/app/Models/CrawlFreenode.php new file mode 100755 index 00000000..370b7c44 --- /dev/null +++ b/app/Models/CrawlFreenode.php @@ -0,0 +1,22 @@ +toArray(); +// +// foreach ($aSelf as &$aSelfRow) { +// unset($aSelfRow["content"]); +// } +// +// return $aSelf; +// } +} diff --git a/app/Models/FreenodePool.php b/app/Models/FreenodePool.php new file mode 100755 index 00000000..9ea67b0e --- /dev/null +++ b/app/Models/FreenodePool.php @@ -0,0 +1,12 @@ +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 diff --git a/app/Services/Cron/FreenodeCrawl.php b/app/Services/Cron/FreenodeCrawl.php new file mode 100644 index 00000000..a14f35b0 --- /dev/null +++ b/app/Services/Cron/FreenodeCrawl.php @@ -0,0 +1,229 @@ + $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; + } + +} diff --git a/app/Services/Cron/FreenodeFile.php b/app/Services/Cron/FreenodeFile.php new file mode 100644 index 00000000..de0be814 --- /dev/null +++ b/app/Services/Cron/FreenodeFile.php @@ -0,0 +1,105 @@ +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"; + } + } +} diff --git a/app/Services/Cron/FreenodeLog.php b/app/Services/Cron/FreenodeLog.php new file mode 100644 index 00000000..a5e1a523 --- /dev/null +++ b/app/Services/Cron/FreenodeLog.php @@ -0,0 +1,23 @@ +get(); + + tomd($oFrom->toArray()); + + exit; + } + +} diff --git a/app/Services/Cron/FreenodeMerge.php b/app/Services/Cron/FreenodeMerge.php new file mode 100644 index 00000000..ed96eade --- /dev/null +++ b/app/Services/Cron/FreenodeMerge.php @@ -0,0 +1,419 @@ + "🇺🇸", + "日本" => "🇯🇵", + "台湾" => "🇹🇼", + "香港" => "🇭🇰", + "新加坡" => "🇸🇬", + "越南" => "🇻🇳", + "俄罗斯" => "🇷🇺", + "韩国" => "🇰🇷", + ]; + +// 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; + } + +} diff --git a/app/Services/Cron/FreenodePool.php b/app/Services/Cron/FreenodePool.php new file mode 100644 index 00000000..fcfffc11 --- /dev/null +++ b/app/Services/Cron/FreenodePool.php @@ -0,0 +1,498 @@ +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; +// } + + +} diff --git a/app/Services/Cron/FreenodeSync.php b/app/Services/Cron/FreenodeSync.php new file mode 100644 index 00000000..68f6dc19 --- /dev/null +++ b/app/Services/Cron/FreenodeSync.php @@ -0,0 +1,56 @@ +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"; + } +} diff --git a/app/Services/Tg/Hook/Mod/Cron.php b/app/Services/Tg/Hook/Mod/Cron.php index 89d2adb2..ac2657f3 100644 --- a/app/Services/Tg/Hook/Mod/Cron.php +++ b/app/Services/Tg/Hook/Mod/Cron.php @@ -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") { diff --git a/app/Services/Tg/Hook/Mod/Freenode.php b/app/Services/Tg/Hook/Mod/Freenode.php new file mode 100644 index 00000000..615529e0 --- /dev/null +++ b/app/Services/Tg/Hook/Mod/Freenode.php @@ -0,0 +1,187 @@ +oDog = new Dog(new ModelFreenodePool()); + $this->oDog->_setDogName("FreenodePool"); + $this->oDog->_setJsonField(["content"]); +// $this->oDog->_setStrField(["content"]); + $this->aUpdate = $aUpdate; + } + + public function __call($sName, $aArg) + { + return $this->oDog->$sName($aArg[0]); + } + + public function testF() + { + $a = [ + "telegram" => "ttttgggg", + "freenode_slogan" => [ + "siteUrl" => "每天更新免费节点:{{siteUrl}}", + "telegram" => "tg频道:{{telegram}}", + ], + ]; + + $s = json_encode($a, JSON_UNESCAPED_UNICODE); + + echo $s; + exit; + } + + public function testC() + { + $str = "ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDU@63.180.254.10:443#tg%E9%A2%91%E9%81%93%3A%40ripaojiedian +vmess://eyJhZGQiOiJ2MTAuaGRhY2QuY29tIiwiYWlkIjoiMiIsImFscG4iOiIiLCJob3N0IjoiIiwiaWQiOiJjYmIzZjg3Ny1kMWZiLTM0NGMtODdhOS1kMTUzYmZmZDU0ODQiLCJuZXQiOiJ0Y3AiLCJwYXRoIjoiLyIsInBvcnQiOiIzMDgwNyIsInBzIjoi6aaZ5rivfEByaXBhb2ppZWRpYW4iLCJzY3kiOiJhdXRvIiwic25pIjoiIiwidGxzIjoiIiwidHlwZSI6Im5vbmUiLCJ2IjoiMiJ9 +trojan://76d630f2af6619c4a5de0ef953df3c6a@112.118.116.127:443/?type=tcp&security=tls&sni=www.nintendogames.net#%E9%A6%99%E6%B8%AF3%7C%40ripaojiedian +trojan://BxceQaOe@58.152.53.174:443/?type=tcp&security=tls&sni=t.me%2Fripaojiedian&allowInsecure=1#%E9%A6%99%E6%B8%AF4%7C%40ripaojiedian +trojan://BxceQaOe@219.78.209.224:443/?type=tcp&security=tls&sni=t.me%2Fripaojiedian&allowInsecure=1#%E9%A6%99%E6%B8%AF5%7C%40ripaojiedian +trojan://BxceQaOe@3.112.202.47:26378/?type=tcp&security=tls&sni=t.me%2Fripaojiedian&allowInsecure=1#%E6%97%A5%E6%9C%AC%7C%40ripaojiedian +trojan://76d630f2af6619c4a5de0ef953df3c6a@153.121.65.107:3093/?type=tcp&security=tls&sni=www.nintendogames.net#%E6%97%A5%E6%9C%AC2%7C%40ripaojiedian +trojan://76d630f2af6619c4a5de0ef953df3c6a@153.121.53.187:3093/?type=tcp&security=tls&sni=www.nintendogames.net#%E6%97%A5%E6%9C%AC3%7C%40ripaojiedian +trojan://76d630f2af6619c4a5de0ef953df3c6a@160.16.144.208:507/?type=tcp&security=tls&sni=www.nintendogames.net#%E6%96%B0%E5%8A%A0%E5%9D%A1%7C%40ripaojiedian +trojan://76d630f2af6619c4a5de0ef953df3c6a@52.195.224.88:3145/?type=tcp&security=tls&sni=www.nintendogames.net#%E6%96%B0%E5%8A%A0%E5%9D%A12%7C%40ripaojiedian +trojan://BxceQaOe@52.195.5.65:804/?type=tcp&security=tls&sni=t.me%252Fripaojiedian&allowInsecure=1#%E6%96%B0%E5%8A%A0%E5%9D%A13%7C%40ripaojiedian +trojan://76d630f2af6619c4a5de0ef953df3c6a@160.16.236.32:4054/?type=tcp&security=tls&sni=www.nintendogames.net#%E7%BE%8E%E5%9B%BD%7C%40ripaojiedian +trojan://76d630f2af6619c4a5de0ef953df3c6a@153.121.51.29:2890/?type=tcp&security=tls&sni=www.nintendogames.net&allowInsecure=1#%E7%BE%8E%E5%9B%BD2%7C%40ripaojiedian +trojan://BxceQaOe@52.195.5.65:4569/?type=tcp&security=tls&sni=t.me%2Fripaojiedian&allowInsecure=1#%E7%BE%8E%E5%9B%BD3%7C%40ripaojiedian +ss://YWVzLTI1Ni1jZmI6WG44aktkbURNMDBJZU8lIyQjZkpBTXRzRUFFVU9wSC9ZV1l0WXFERm5UMFNW@103.186.155.205:38388#%E8%B6%8A%E5%8D%97%7C%40ripaojiedian +"; + $str = base64_decode($str); + echo $str; + exit; + } + + public function testE() + { + $s = "ss://YWVzLTI1Ni1jZmI6YW1hem9uc2tyMDVANjMuMTgwLjI1NC4xMDo0NDM=#%F0%9F%87%B8%F0%9F%87%AC%20%E6%96%B0%E5%8A%A0%E5%9D%A1%20SG-17"; + $s = "ss://YWVzLTEyOC1nY206YzAyMzYyZWE5NGJjYWY4ZEBydGdkZnNnZGZzLmZzZHRnYWVydC5zdXJmOjUwMzA1#%F0%9F%87%B8%F0%9F%87%AC%20%E6%96%B0%E5%8A%A0%E5%9D%A1%20SG-17"; + $aTmp = explode("#", $s); + $sName = $aTmp[1]; + $sConfig = $aTmp[0]; + + $aTmp = explode("://", $sConfig); + $sProtocol = $aTmp[0]; + $sConfig = $aTmp[1]; + + $sConfig = base64_decode($sConfig); +// $sConfig = "aes-256-cfb:amazonskr05@63.180.254.10:443"; + $sConfig = "aes-128-gcm:amazonskr05@63.180.254.10:443"; + + $a = [ + "protocol" => $sProtocol, + "config" => $sConfig, + "name" => $sName + ]; + + $sConfig = base64_encode($sConfig); + tomd($a); + $s = $sProtocol."://".$sConfig."#".$sName; + echo $s; + exit; + } + + public function testD() + { + $s = "ss://YWVzLTEyOC1nY206YzAyMzYyZWE5NGJjYWY4ZEBydGdkZnNnZGZzLmZzZHRnYWVydC5zdXJmOjUwMzA1#%F0%9F%87%B8%F0%9F%87%AC%20%E6%96%B0%E5%8A%A0%E5%9D%A1%20SG-17"; + +// $ + + $s = base64_decode($s); + + echo $s; + exit; + } + + public function testB() + { + $str = "c3M6Ly9ZV1Z6TFRJMU5pMWpabUk2WVcxaGVtOXVjMnR5TURVQDYzLjE4MC4yNTQuMTA6NDQzIyVFNiVBRiU4RiVFNSVBNCVBOSVFNiU5QiVCNCVFNiU5NiVCMCVFNSU4NSU4RCVFOCVCNCVCOSVFOCU4QSU4MiVFNyU4MiVCOSVFRiVCQyU5QV9hZG1pbi5sb2MrJTNBJTVCcmlwYW9qaWVkaWFuJTVEJTNBCnRyb2phbjovLzc2ZDYzMGYyYWY2NjE5YzRhNWRlMGVmOTUzZGYzYzZhQDE2MC4xNi4yMzYuMzI6NDA1ND9hbGxvd0luc2VjdXJlPTAmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCMlRTclQkUlOEUlRTUlOUIlQkQrMDErJTNBJTVCc3RhaXJub2RlJTVEJTNBCnRyb2phbjovLzc2ZDYzMGYyYWY2NjE5YzRhNWRlMGVmOTUzZGYzYzZhQDE1My4xMjEuNTEuMjk6Mjg5MD9hbGxvd0luc2VjdXJlPTAmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCMlRTclQkUlOEUlRTUlOUIlQkQrMDIrJTNBJTVCc3RhaXJub2RlJTVEJTNBCnRyb2phbjovL0J4Y2VRYU9lQDUyLjE5NS41LjY1OjQ1Njk/YWxsb3dJbnNlY3VyZT0xJnNuaT10Lm1lL3JpcGFvamllZGlhbiMlRTclQkUlOEUlRTUlOUIlQkQrMDMrJTNBJTVCc3RhaXJub2RlJTVEJTNBCmh5c3RlcmlhOi8vNTEuMTU5LjIyNi4xOjQ5MDAzP2FscG49aDMmYXV0aD1kb25ndGFpd2FuZy5jb20mYXV0aF9zdHI9ZG9uZ3RhaXdhbmcuY29tJmRlbGF5PTE1NDcmZG93bm1icHM9NTUmcHJvdG9jb2w9dWRwJmluc2VjdXJlPTEmcGVlcj1hcHBsZS5jb20mdWRwPXRydWUmdXBtYnBzPTExIyVFNyVCRSU4RSVFNSU5QiVCRCswNCslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnZsZXNzOi8vYmU1MjA2MGUtNzkzNC00YmM2LTg5YjMtMGI2Y2Y0Y2RhNzg5QDY5Ljg0LjE4Mi4xMzo0NDM/c2VjdXJpdHk9dGxzJnR5cGU9d3MmcGF0aD0va2JqYy9mcjEmaG9zdD1mci0xLWZyLTEuYWlvcGVuLnNicyZzbmk9ZnItMS1mci0xLmFpb3Blbi5zYnMmZnA9Y2hyb21lIyVFNyVCRSU4RSVFNSU5QiVCRCswNSslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCmh5c3RlcmlhMjovL2JlNTIwNjBlLTc5MzQtNGJjNi04OWIzLTBiNmNmNGNkYTc4OUAxMzQuMTk1LjEwMS4xOTE6MzUwMDA/aW5zZWN1cmU9MSZzbmk9d3d3LmFwcGxlLmNvbSZtcG9ydD0zNTAwMC0zOTAwMCMlRTclQkUlOEUlRTUlOUIlQkQrMDYrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovL2Y4MWQ1YjliLWM1YjctNDZjYi04NzEwLTBjZjQxYWIzMzU3MEBhbnRpbWFnZS5mb25peGFwcC5vcmc6NDQzP3NlY3VyaXR5PXJlYWxpdHkmZW5jcnlwdGlvbj1ub25lJnBiaz1XZU5sZl9oUHNjQkxTd3RnMVBnT211cksxZjdWeVFTTlBtT1llRzB3SVF3JmhlYWRlclR5cGU9bm9uZSZmcD1jaHJvbWUmc3B4PS8mdHlwZT10Y3AmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNuaT1hamF4LmNsb3VkZmxhcmUuY29tJnNpZD02NTkwY2IjJUU3JUJFJThFJUU1JTlCJUJEKzA3KyUzQSU1QnYycmF5c2hhcmUlNUQlM0EKdmxlc3M6Ly9lM2FmNDliYS02YTQxLTRmYTEtOGYyMS1mNDBkMWYxNTRjNjhAbGlmZXN0ZWFsZXIuZm9uaXhhcHAub3JnOjQ0Mz9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9REoxbDFiZ3Z3cGotU29IdUM2ZUxWZnpkM3JwMXpRbUNWNzZmZFZhek1nYyZoZWFkZXJUeXBlPW5vbmUmZnA9Y2hyb21lJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9Y29uZmlndXJhdGlvbi5hcHBsZS5jb20mc2lkPTE3M2M1OCMlRTclQkUlOEUlRTUlOUIlQkQrMDgrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp0cm9qYW46Ly83NmQ2MzBmMmFmNjYxOWM0YTVkZTBlZjk1M2RmM2M2YUAxNjAuMTYuMjM2LjMyOjQwNTQvP3R5cGU9dGNwJnNlY3VyaXR5PXRscyZzbmk9d3d3Lm5pbnRlbmRvZ2FtZXMubmV0IyVFNyVCRSU4RSVFNSU5QiVCRCswOSslM0ElNUJyaXBhb2ppZWRpYW4lNUQlM0EKdHJvamFuOi8vNzZkNjMwZjJhZjY2MTljNGE1ZGUwZWY5NTNkZjNjNmFAMTUzLjEyMS41MS4yOToyODkwLz90eXBlPXRjcCZzZWN1cml0eT10bHMmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCZhbGxvd0luc2VjdXJlPTEjJUU3JUJFJThFJUU1JTlCJUJEKzEwKyUzQSU1QnJpcGFvamllZGlhbiU1RCUzQQp0cm9qYW46Ly9CeGNlUWFPZUA1Mi4xOTUuNS42NTo0NTY5Lz90eXBlPXRjcCZzZWN1cml0eT10bHMmc25pPXQubWUvcmlwYW9qaWVkaWFuJmFsbG93SW5zZWN1cmU9MSMlRTclQkUlOEUlRTUlOUIlQkQrMTErJTNBJTVCcmlwYW9qaWVkaWFuJTVEJTNBCnRyb2phbjovL0J4Y2VRYU9lQDMuMTEyLjIwMi40NzoyNjM3OD9hbGxvd0luc2VjdXJlPTEmc25pPXQubWUvcmlwYW9qaWVkaWFuIyVFNiU5NyVBNSVFNiU5QyVBQyswMSslM0ElNUJzdGFpcm5vZGUlNUQlM0EKdHJvamFuOi8vNzZkNjMwZjJhZjY2MTljNGE1ZGUwZWY5NTNkZjNjNmFAMTUzLjEyMS42NS4xMDc6MzA5Mz9hbGxvd0luc2VjdXJlPTAmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCMlRTYlOTclQTUlRTYlOUMlQUMrMDIrJTNBJTVCc3RhaXJub2RlJTVEJTNBCnRyb2phbjovLzc2ZDYzMGYyYWY2NjE5YzRhNWRlMGVmOTUzZGYzYzZhQDE1My4xMjEuNTMuMTg3OjMwOTM/YWxsb3dJbnNlY3VyZT0wJnNuaT13d3cubmludGVuZG9nYW1lcy5uZXQjJUU2JTk3JUE1JUU2JTlDJUFDKzAzKyUzQSU1QnN0YWlybm9kZSU1RCUzQQp0cm9qYW46Ly9CeGNlUWFPZUAzLjExMi4yMDIuNDc6MjYzNzgvP3R5cGU9dGNwJnNlY3VyaXR5PXRscyZzbmk9dC5tZS9yaXBhb2ppZWRpYW4mYWxsb3dJbnNlY3VyZT0xIyVFNiU5NyVBNSVFNiU5QyVBQyswNCslM0ElNUJyaXBhb2ppZWRpYW4lNUQlM0EKdHJvamFuOi8vNzZkNjMwZjJhZjY2MTljNGE1ZGUwZWY5NTNkZjNjNmFAMTUzLjEyMS42NS4xMDc6MzA5My8/dHlwZT10Y3Amc2VjdXJpdHk9dGxzJnNuaT13d3cubmludGVuZG9nYW1lcy5uZXQjJUU2JTk3JUE1JUU2JTlDJUFDKzA1KyUzQSU1QnJpcGFvamllZGlhbiU1RCUzQQp0cm9qYW46Ly83NmQ2MzBmMmFmNjYxOWM0YTVkZTBlZjk1M2RmM2M2YUAxNTMuMTIxLjUzLjE4NzozMDkzLz90eXBlPXRjcCZzZWN1cml0eT10bHMmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCMlRTYlOTclQTUlRTYlOUMlQUMrMDYrJTNBJTVCcmlwYW9qaWVkaWFuJTVEJTNBCnZtZXNzOi8veyJ2IjoiMiIsInBzIjoiIiwiYWRkIjoidjEwLmhkYWNkLmNvbSIsInBvcnQiOiIzMDgwNyIsInR5cGUiOiJub25lIiwiaWQiOiJjYmIzZjg3Ny1kMWZiLTM0NGMtODdhOS1kMTUzYmZmZDU0ODQiLCJhaWQiOiJcdTAwMDIiLCJuZXQiOiJ0Y3AiLCJwYXRoIjoiXC8iLCJob3N0IjoidjEwLmhkYWNkLmNvbSIsInRscyI6IiJ9IyVFOSVBNiU5OSVFNiVCOCVBRiswMSslM0ElNUJzdGFpcm5vZGUlNUQlM0EKdHJvamFuOi8vNzZkNjMwZjJhZjY2MTljNGE1ZGUwZWY5NTNkZjNjNmFAMTEyLjExOC4xMTYuMTI3OjQ0Mz9hbGxvd0luc2VjdXJlPTAmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCMlRTklQTYlOTklRTYlQjglQUYrMDIrJTNBJTVCc3RhaXJub2RlJTVEJTNBCnRyb2phbjovL0J4Y2VRYU9lQDU4LjE1Mi41My4xNzQ6NDQzP2FsbG93SW5zZWN1cmU9MSZzbmk9dC5tZS9yaXBhb2ppZWRpYW4jJUU5JUE2JTk5JUU2JUI4JUFGKzAzKyUzQSU1QnN0YWlybm9kZSU1RCUzQQp0cm9qYW46Ly9CeGNlUWFPZUAyMTkuNzguMjA5LjIyNDo0NDM/YWxsb3dJbnNlY3VyZT0xJnNuaT10Lm1lL3JpcGFvamllZGlhbiMlRTklQTYlOTklRTYlQjglQUYrMDQrJTNBJTVCc3RhaXJub2RlJTVEJTNBCnZtZXNzOi8veyJhZGQiOiJ2MTAuaGRhY2QuY29tIiwiYWlkIjoiMiIsImFscG4iOiIiLCJob3N0IjoiIiwiaWQiOiJjYmIzZjg3Ny1kMWZiLTM0NGMtODdhOS1kMTUzYmZmZDU0ODQiLCJuZXQiOiJ0Y3AiLCJwYXRoIjoiXC8iLCJwb3J0IjoiMzA4MDciLCJwcyI6IiIsInNjeSI6ImF1dG8iLCJzbmkiOiIiLCJ0bHMiOiIiLCJ0eXBlIjoibm9uZSIsInYiOiIyIn0jJUU5JUE2JTk5JUU2JUI4JUFGKzA1KyUzQSU1QnJpcGFvamllZGlhbiU1RCUzQQp0cm9qYW46Ly83NmQ2MzBmMmFmNjYxOWM0YTVkZTBlZjk1M2RmM2M2YUAxMTIuMTE4LjExNi4xMjc6NDQzLz90eXBlPXRjcCZzZWN1cml0eT10bHMmc25pPXd3dy5uaW50ZW5kb2dhbWVzLm5ldCMlRTklQTYlOTklRTYlQjglQUYrMDYrJTNBJTVCcmlwYW9qaWVkaWFuJTVEJTNBCnRyb2phbjovL0J4Y2VRYU9lQDU4LjE1Mi41My4xNzQ6NDQzLz90eXBlPXRjcCZzZWN1cml0eT10bHMmc25pPXQubWUvcmlwYW9qaWVkaWFuJmFsbG93SW5zZWN1cmU9MSMlRTklQTYlOTklRTYlQjglQUYrMDcrJTNBJTVCcmlwYW9qaWVkaWFuJTVEJTNBCnRyb2phbjovL0J4Y2VRYU9lQDIxOS43OC4yMDkuMjI0OjQ0My8/dHlwZT10Y3Amc2VjdXJpdHk9dGxzJnNuaT10Lm1lL3JpcGFvamllZGlhbiZhbGxvd0luc2VjdXJlPTEjJUU5JUE2JTk5JUU2JUI4JUFGKzA4KyUzQSU1QnJpcGFvamllZGlhbiU1RCUzQQp0cm9qYW46Ly83NmQ2MzBmMmFmNjYxOWM0YTVkZTBlZjk1M2RmM2M2YUAxNjAuMTYuMTQ0LjIwODo1MDc/YWxsb3dJbnNlY3VyZT0wJnNuaT13d3cubmludGVuZG9nYW1lcy5uZXQjJUU2JTk2JUIwJUU1JThBJUEwJUU1JTlEJUExKzAxKyUzQSU1QnN0YWlybm9kZSU1RCUzQQp0cm9qYW46Ly83NmQ2MzBmMmFmNjYxOWM0YTVkZTBlZjk1M2RmM2M2YUA1Mi4xOTUuMjI0Ljg4OjMxNDU/YWxsb3dJbnNlY3VyZT0wJnNuaT13d3cubmludGVuZG9nYW1lcy5uZXQjJUU2JTk2JUIwJUU1JThBJUEwJUU1JTlEJUExKzAyKyUzQSU1QnN0YWlybm9kZSU1RCUzQQp0cm9qYW46Ly9CeGNlUWFPZUA1Mi4xOTUuNS42NTo4MDQ/YWxsb3dJbnNlY3VyZT0xJnNuaT10Lm1lJTJGcmlwYW9qaWVkaWFuIyVFNiU5NiVCMCVFNSU4QSVBMCVFNSU5RCVBMSswMyslM0ElNUJzdGFpcm5vZGUlNUQlM0EKdmxlc3M6Ly9mZjgzMTk4OC1iNjRhLTRiYzMtOTNkZC01ODM4OWM5MWEwM2FAc2cuZmx1eGNvbW11bml0eS5teS5pZDoyMDgyPyZzZWN1cml0eT1mYWxzZSZmcD1jaHJvbWUmdHlwZT13cyZoZWFkZXJUeXBlPW5vbmUmaG9zdD1zZy5mbHV4Y29tbXVuaXR5Lm15LmlkJnBhdGg9L3ZsZXNzIyVFNiU5NiVCMCVFNSU4QSVBMCVFNSU5RCVBMSswNCslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnRyb2phbjovLzc2ZDYzMGYyYWY2NjE5YzRhNWRlMGVmOTUzZGYzYzZhQDE2MC4xNi4xNDQuMjA4OjUwNy8/dHlwZT10Y3Amc2VjdXJpdHk9dGxzJnNuaT13d3cubmludGVuZG9nYW1lcy5uZXQjJUU2JTk2JUIwJUU1JThBJUEwJUU1JTlEJUExKzA1KyUzQSU1QnJpcGFvamllZGlhbiU1RCUzQQp0cm9qYW46Ly83NmQ2MzBmMmFmNjYxOWM0YTVkZTBlZjk1M2RmM2M2YUA1Mi4xOTUuMjI0Ljg4OjMxNDUvP3R5cGU9dGNwJnNlY3VyaXR5PXRscyZzbmk9d3d3Lm5pbnRlbmRvZ2FtZXMubmV0IyVFNiU5NiVCMCVFNSU4QSVBMCVFNSU5RCVBMSswNislM0ElNUJyaXBhb2ppZWRpYW4lNUQlM0EKdHJvamFuOi8vQnhjZVFhT2VANTIuMTk1LjUuNjU6ODA0Lz90eXBlPXRjcCZzZWN1cml0eT10bHMmc25pPXQubWUlMkZyaXBhb2ppZWRpYW4mYWxsb3dJbnNlY3VyZT0xIyVFNiU5NiVCMCVFNSU4QSVBMCVFNSU5RCVBMSswNyslM0ElNUJyaXBhb2ppZWRpYW4lNUQlM0EKc3M6Ly9ZV1Z6TFRJMU5pMWpabUk2V0c0NGFrdGtiVVJOTURCSlpVOGxJeVFqWmtwQlRYUnpSVUZGVlU5d1NDOVpWMWwwV1hGRVJtNVVNRk5XQDEwMy4xODYuMTU1LjIwNTozODM4OCMlRTglQjYlOEElRTUlOEQlOTcrMDErJTNBJTVCcmlwYW9qaWVkaWFuJTVEJTNBCmh5c3RlcmlhOi8vMTk1LjE1NC4yMDAuNDA6MTUwMTA/YWxwbj1oMyZhdXRoPWRvbmd0YWl3YW5nLmNvbSZhdXRoX3N0cj1kb25ndGFpd2FuZy5jb20mZG93bm1icHM9MTAwJnByb3RvY29sPXVkcCZpbnNlY3VyZT0xJnBlZXI9YXBwbGUuY29tJnVkcD10cnVlJnVwbWJwcz0xMDAjJUU2JUIzJTk1JUU1JTlCJUJEKzAxKyUzQSU1QnYycmF5c2hhcmUlNUQlM0EKaHlzdGVyaWE6Ly82Mi4yMTAuMTAuMTg2OjUwMDExP2FscG49aDMmYXV0aD1kb25ndGFpd2FuZy5jb20mZG93bm1icHM9NTUgTWJwcyZwcm90b2NvbD11ZHAmaW5zZWN1cmU9MSZwZWVyPWFwcGxlLmNvbSZ1cG1icHM9MTEgTWJwcyMlRTYlQjMlOTUlRTUlOUIlQkQrMDIrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQpoeXN0ZXJpYTovLzYyLjIxMC4xMC4xODY6MzU1MTE/YWxwbj1oMyZhdXRoPWRvbmd0YWl3YW5nLmNvbSZhdXRoX3N0cj1kb25ndGFpd2FuZy5jb20mZG93bm1icHM9NTUmcHJvdG9jb2w9dWRwJmluc2VjdXJlPTEmcGVlcj1hcHBsZS5jb20mdWRwPXRydWUmdXBtYnBzPTExIyVFNiVCMyU5NSVFNSU5QiVCRCswMyslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCmh5c3RlcmlhMjovL2JkNTE1NTc0LTNiMTAtMTFlZS1hYzE0LWYyM2M5MTY0Y2E1ZEBmODcwM2QxYS10NnI1czAtdGIwMTZiLTFtN2w0LmhrMi5oeWh1YXdlaS5jb206NDQzP3NuaT1mODcwM2QxYS10NnI1czAtdGIwMTZiLTFtN2w0LmhrMi5oeWh1YXdlaS5jb20mbXBvcnQ9MzAwMDAtNjAwMDAjJUU0JUI4JUFEJUU1JTlCJUJEKzAxKyUzQSU1QnYycmF5c2hhcmUlNUQlM0EKaHlzdGVyaWEyOi8vMGRlMzdjZGMtYWJmZi0xMWVmLWI3YzYtZjIzYzkxM2M4ZDJiQGRmOWFkNGRhLXQ2dDBnMC10ODBvcWQtMXJzdXcuaGsyLmh5aHVhd2VpLmNvbTo0NDM/c25pPWRmOWFkNGRhLXQ2dDBnMC10ODBvcWQtMXJzdXcuaGsyLmh5aHVhd2VpLmNvbSZtcG9ydD0zMDAwMC02MDAwMCMlRTQlQjglQUQlRTUlOUIlQkQrMDIrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQpoeXN0ZXJpYTI6Ly85ZTFkZGMwNC0wNzNiLTExZWQtYmQ3Yy1mMjNjOTEzYzhkMmJAMjJkNmY4MmYtdDZ0MGcwLXRrZ2s0dy0xZnZkaC5oazIuaHlodWF3ZWkuY29tOjQ0Mz9zbmk9MjJkNmY4MmYtdDZ0MGcwLXRrZ2s0dy0xZnZkaC5oazIuaHlodWF3ZWkuY29tJm1wb3J0PTMwMDAwLTYwMDAwIyVFNCVCOCVBRCVFNSU5QiVCRCswMyslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCmh5c3RlcmlhMjovLzM0ZjBjZjQyLTBmOGEtMTFlYy1hOGJmLWYyM2M5MWNmYmJjOUAyMWQ5NDIyMS10NnBiNDAtdGRwczlsLTE1NWQ5LmhrMi5oeWh1YXdlaS5jb206NDQzP3NuaT0yMWQ5NDIyMS10NnBiNDAtdGRwczlsLTE1NWQ5LmhrMi5oeWh1YXdlaS5jb20mbXBvcnQ9MzAwMDAtNjAwMDAjJUU0JUI4JUFEJUU1JTlCJUJEKzA0KyUzQSU1QnYycmF5c2hhcmUlNUQlM0EKaHlzdGVyaWEyOi8vYWFmZWRjNjQtOWMyMy0xMWVmLWE3OWYtZjIzYzkxY2ZiYmM5QDY3NjFlMmFkLXQ2cGI0MC10bmZlMnotMXM0aGMuaGsyLmh5aHVhd2VpLmNvbTo0NDM/c25pPTY3NjFlMmFkLXQ2cGI0MC10bmZlMnotMXM0aGMuaGsyLmh5aHVhd2VpLmNvbSZtcG9ydD0zMDAwMC02MDAwMCMlRTQlQjglQUQlRTUlOUIlQkQrMDUrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQpoeXN0ZXJpYTI6Ly84OWIwZWE4Yy04MDZiLTExZWQtOTRiYS1mMjNjOTEzYzhkMmJAYTcyYjRlOWItdDZ0MGcwLXQ3YzA1by1uMDlmLmhrMi5oeWh1YXdlaS5jb206NDQzP3NuaT1hNzJiNGU5Yi10NnQwZzAtdDdjMDVvLW4wOWYuaGsyLmh5aHVhd2VpLmNvbSZtcG9ydD0zMDAwMC02MDAwMCMlRTQlQjglQUQlRTUlOUIlQkQrMDYrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQpoeXN0ZXJpYTI6Ly85NmM3OThmNi00NjQ1LTExZWUtYjhhMS1mMjNjOTE2NGNhNWRAMTFjNzZlZjAtdDZyNXMwLXRoOWt4OS0xb3M0My5oazIuaHlodWF3ZWkuY29tOjQ0Mz9zbmk9MTFjNzZlZjAtdDZyNXMwLXRoOWt4OS0xb3M0My5oazIuaHlodWF3ZWkuY29tJm1wb3J0PTMwMDAwLTYwMDAwIyVFNCVCOCVBRCVFNSU5QiVCRCswNyslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCmh5c3RlcmlhMjovL2QyZjBiZWUyLTAyZjEtMTFmMC04ZWIwLWYyM2M5MTY0Y2E1ZEBkMTViMGEyZi10NnBiNDAtdGM2MWNzLTF0amE4LmhrMi5oeWh1YXdlaS5jb206NDQzP3NuaT1kMTViMGEyZi10NnBiNDAtdGM2MWNzLTF0amE4LmhrMi5oeWh1YXdlaS5jb20mbXBvcnQ9MzAwMDAtNjAwMDAjJUU0JUI4JUFEJUU1JTlCJUJEKzA4KyUzQSU1QnYycmF5c2hhcmUlNUQlM0EKaHlzdGVyaWEyOi8vY2U0ODFjNmUtZjRjOC0xMWVmLWJiYjAtZjIzYzkxY2ZiYmM5QDg0MDQxYjlmLXQ2cGI0MC10NnowZXQtMXQ2MG8uaGsyLmh5aHVhd2VpLmNvbTo0NDM/c25pPTg0MDQxYjlmLXQ2cGI0MC10NnowZXQtMXQ2MG8uaGsyLmh5aHVhd2VpLmNvbSZtcG9ydD0zMDAwMC02MDAwMCMlRTQlQjglQUQlRTUlOUIlQkQrMDkrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovLzA5NGU2NmE5LThkOTItNDFmZS04NWFkLThlN2JmOWI1ZmNhYUBubC03OHctYy5zb3V0aG5ldHdvcmtzLmNsb3VkOjgwPyZ0eXBlPXdzJmhlYWRlclR5cGU9bm9uZSZob3N0PW5sLTc4dy1jLnNvdXRobmV0d29ya3MuY2xvdWQmcGF0aD0vZ2V0V29ya2VyVXBkYXRlcyMlRTQlQkYlODQlRTclQkQlOTclRTYlOTYlQUYrMDErJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovLzJhMmE2MDYyLTAwM2MtMDAwNC1iMjkzLWVlMGQwNDE2YWZlZUAxNzYuMTIzLjE2Mi4yNTM6ODQ0Mz9zZWN1cml0eT1yZWFsaXR5JnR5cGU9dGNwJnNuaT1waW1nLm15Y2RuLm1lJmZwPWNocm9tZSZmbG93PXh0bHMtcnByeC12aXNpb24mc2lkPWFlYTEwNGU3MzAmcGJrPTczWGdsUjlsT2FYQklTZDdtR2dURVA2MHYyOG16OHBtQ0RpdmNEQUZfV1UmZW5jcnlwdGlvbj1ub25lIyVFNCVCRiU4NCVFNyVCRCU5NyVFNiU5NiVBRiswMislM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnZsZXNzOi8vY2I3MTg4Y2YtMmMzYS00M2E1LWFmOTAtZDg5MzkyMmU0OTE3QGlzdGFuYnVsLmZvbml4YXBwLm9yZzo0NDM/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPWVTME5xSkNBbzZKbjRQdVUzblU0QTVEN1J5TmJuM1d5aGlwWFZpZGRuekkmaGVhZGVyVHlwZT1ub25lJmZwPWNocm9tZSZzcHg9LyZ0eXBlPXRjcCZmbG93PXh0bHMtcnByeC12aXNpb24mc25pPWZvbnRzLmdzdGF0aWMuY29tJnNpZD01NDU3IyVFNCVCRiU4NCVFNyVCRCU5NyVFNiU5NiVBRiswMyslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnRyb2phbjovL2FmNGIwNjRhOWMzOTQ3MmZiMzRhZDhiMTEzYWNkYzZiQDQ2LjI5LjE2MS4yMzc6NDQzP3NuaT00Ni4yOS4xNjEuMjM3JmFsbG93SW5zZWN1cmU9MSMlRTQlQkYlODQlRTclQkQlOTclRTYlOTYlQUYrMDQrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovLzJhMmE2MDYyLTAwM2MtNGY0NC1iMjkzLWVlMGQwNDE2YWZlZUA5MS44NC4xMTguMTMwOjE0NDM/c2VjdXJpdHk9cmVhbGl0eSZ0eXBlPWdycGMmbW9kZT1ndW4mc2VydmljZU5hbWU9YWRtaW4mc25pPW96b24ucnUmZnA9Y2hyb21lJnNpZD00N2U5MmE0YjA1MTNiMjdmJnBiaz1KdURyVVpzZ0h0MGlfaHoza09oUWJpWDcwOHZialI5dUhIRndpM2ZXcVNjJmVuY3J5cHRpb249bm9uZSMlRTglOEIlQjElRTUlOUIlQkQrMDErJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovLzRhNmRlMTgzLTJhZDMtNDU2Yy1iNDIwLWZlZWFjODFmNjI1N0A1MS4yNTAuMjUuMTE6MTQ4OD9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9U2JWS09FTWpLMHNJbGJ3ZzRha3lCZzVtTDVLWnd3Qi1lZDRlRUU3WW5SYyZoZWFkZXJUeXBlPW5vbmUmZnA9Y2hyb21lJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YWRzLng1LnJ1JnNpZD02YmE4NTE3OWUzMGQ0ZmMyIyVFOCU4QiVCMSVFNSU5QiVCRCswMislM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnZsZXNzOi8vNGE2ZGUxODMtMmFkMy00NTZjLWI0MjAtZmVlYWM4MWY2MjU3QDUxLjI1MC4xMDkuNDc6MTQ4OD9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9U2JWS09FTWpLMHNJbGJ3ZzRha3lCZzVtTDVLWnd3Qi1lZDRlRUU3WW5SYyZoZWFkZXJUeXBlPW5vbmUmZnA9Y2hyb21lJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YWRzLng1LnJ1JnNpZD02YmE4NTE3OWUzMGQ0ZmMyIyVFOCU4QiVCMSVFNSU5QiVCRCswMyslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnZsZXNzOi8vNGE2ZGUxODMtMmFkMy00NTZjLWI0MjAtZmVlYWM4MWY2MjU3QDUxLjI1MC45OS4xOTA6MTQ4OD9zZWN1cml0eT1yZWFsaXR5JmVuY3J5cHRpb249bm9uZSZwYms9U2JWS09FTWpLMHNJbGJ3ZzRha3lCZzVtTDVLWnd3Qi1lZDRlRUU3WW5SYyZoZWFkZXJUeXBlPW5vbmUmZnA9Y2hyb21lJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9YWRzLng1LnJ1IyVFOCU4QiVCMSVFNSU5QiVCRCswNCslM0ElNUJ2MnJheXNoYXJlJTVEJTNBCnZsZXNzOi8vMmEyYTYwNjItMDAzYy00ZjQ0LWIyOTMtZWUwZDA0MTZhZmVlQDE0NC4xMjQuMjU0LjMxOjE0NDM/c2VjdXJpdHk9cmVhbGl0eSZ0eXBlPWdycGMmbW9kZT1ndW4mc2VydmljZU5hbWU9YWRtaW4mc25pPW96b24ucnUmZnA9Y2hyb21lJnNpZD00N2U5MmE0YjA1MTNiMjdmJnBiaz1KdURyVVpzZ0h0MGlfaHoza09oUWJpWDcwOHZialI5dUhIRndpM2ZXcVNjJmVuY3J5cHRpb249bm9uZSMlRTglOEIlQjElRTUlOUIlQkQrMDUrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovLzkzN2Y4OTQwLWFkOGEtNDA5Zi05M2MzLTRkNjI0OWFmNjI4ZkB1azEub29tei5ydTo0NDM/c2VjdXJpdHk9cmVhbGl0eSZlbmNyeXB0aW9uPW5vbmUmcGJrPV9kc091X3Z4RVU3cFkzc0llR0p4SXBSMEFjMktvcUl5Qm9yMkJ4MEN3R0EmaGVhZGVyVHlwZT1ub25lJmZwPXFxJnR5cGU9dGNwJmZsb3c9eHRscy1ycHJ4LXZpc2lvbiZzbmk9d3d3LmJwLmNvbSZzaWQ9ZDkyMyMlRTglOEIlQjElRTUlOUIlQkQrMDYrJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovLzU1OTc1NDE1LTQzYzAtNDYxYy04NzUyLWQ1YjgwMTMzNjRlM0AxNjcuMTcuNzAuMTY6ODQ0Mz9zZWN1cml0eT1yZWFsaXR5JnR5cGU9dGNwJnNuaT13d3cubWljcm9zb2Z0LmNvbSZmcD1jaHJvbWUmZmxvdz14dGxzLXJwcngtdmlzaW9uJnNpZD04NGY3MGYxMTc3OTgxNTYzJnBiaz04VzlyMmFYR2hLTnR2UHhuTDZFaVBwUXVTbTlPSlQxN3gyeHl4d3hJbzMwJmVuY3J5cHRpb249bm9uZSMlRTUlOEElQTAlRTYlOEIlQkYlRTUlQTQlQTcrMDErJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQp2bGVzczovL2UwM2I1MzhhLTkxYzktNGQzYy1hMmNiLThhNmIxZDhkZjU0ZkAyMTMuMTY1LjYzLjIzNDo2MjcyOD9zZWN1cml0eT1yZWFsaXR5JnR5cGU9dGNwJnNuaT15YW5kZXgucnUmZnA9Y2hyb21lJnNpZD1kOGVkZmFkYjM1ZWNkZjAwJnBiaz1JVGRlX0t0bjdTbEhMeWttUTR2elZYTFhaZDBKN1p4dVMzT2M0Yk5IRmc4JmVuY3J5cHRpb249bm9uZSMlRTYlQjIlOTklRTclODklQjklRTklOTglQkYlRTYlOEIlODklRTQlQkMlQUYrMDErJTNBJTVCdjJyYXlzaGFyZSU1RCUzQQ=="; + + echo base64_decode($str); + exit; + } + + public function testA() + { + $aData = [ + "siteCode" => "cfn", + "client" => "v2ray", +// "date" => "2025-12-12", + ]; + +// $sUrl = "https://dd.loc/api/fn/merge/get"; + $sUrl = "https://dd.loc/sub/cfn/v2ray"; + + $r = HttpV2::make($sUrl, "get")->setDataA($aData)->enableJsonAs()->send(); + + tomd($r); + + +// HttpV2::make($url)->aData($aData)->setJsonAs()->setAsync()->setMethod("get")->send(); + } + + public function showPool($aParam) + { + $sDate = $aParam["aArg"][1] ?? date("Y-m-d"); + $sVtype = $aParam["aOption"][1] ?? "custom"; + + $sContentType = "content_".$sVtype; + + $aPool = ModelFreenodePool::where("date", $sDate)->first()->toArray(); + + $sContent = $aPool[$sContentType]; + + $aContent = json_decode($sContent, true); + + return $this->toJson($aContent); + } + + public function show($aParam) + { + $sSiteCode = $aParam["aOption"][1] ?? "cfn"; + $sClient = $aParam["aOption"][2] ?? "v2ray"; + $sDate = $aParam["aArg"][1] ?? date("Y-m-d"); + + + if ($sDate == "?") { + return "show__[siteCode]__[client] [Y-m-d]"; + } + + $sDirBase = $_ENV["dir_base"]; + + $sFilePath = $sDirBase."public/freenode/merge/{$sSiteCode}/{$sClient}/{$sDate}.txt"; + + $sContent = file_get_contents($sFilePath); + + $sFeed = ""; + if ($sClient == "v2ray") { + $sFeed = CronFreenodeMerge::v2rayFeedToStr($sContent); +// $sContent = base64_decode($sContent); +// $aContent = explode("\n", $sContent); +// foreach ($aContent as $sNode) { +// $aTmp = explode("#", $sNode); +// $sName = $aTmp[1]; +// $sName = urldecode($sName); +// $sNode = $aTmp[0]."#".$sName; +// $sFeed .= $sNode."\n"; +// } + } else if ($sClient == "clash") { + $sFeed = $sContent; + } + + return $sFeed; + } + +} diff --git a/app/Services/Tg/Hook/Mod/SiteMap.php b/app/Services/Tg/Hook/Mod/SiteMap.php index 1d1df797..60e13235 100644 --- a/app/Services/Tg/Hook/Mod/SiteMap.php +++ b/app/Services/Tg/Hook/Mod/SiteMap.php @@ -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; } diff --git a/app/Services/TomTool/HttpV2.php b/app/Services/TomTool/HttpV2.php index 2cef8286..c05ae1e2 100755 --- a/app/Services/TomTool/HttpV2.php +++ b/app/Services/TomTool/HttpV2.php @@ -1,5 +1,7 @@ send() 进阶: - HttpV2::make($url)->aData($aData)->setJsonAs()->setAsync()->setMethod("get")->send(); + HttpV2::make($url, "get")->setDataA($aData)->enableJsonAs()->enableAsync()->optMethod("get")->send(); action: send() diff --git a/app/Services/TomTool/Telegram/Slave.php b/app/Services/TomTool/Telegram/Slave.php index 35f521c7..00ca8af4 100755 --- a/app/Services/TomTool/Telegram/Slave.php +++ b/app/Services/TomTool/Telegram/Slave.php @@ -1,5 +1,7 @@ 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); diff --git a/composer.json b/composer.json index 276cacee..284e66a8 100755 --- a/composer.json +++ b/composer.json @@ -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": { diff --git a/composer.lock b/composer.lock index 6ba52950..1cd220dc 100755 --- a/composer.lock +++ b/composer.lock @@ -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", diff --git a/fn的tg策略.md b/fn的tg策略.md new file mode 100644 index 00000000..857a5803 --- /dev/null +++ b/fn的tg策略.md @@ -0,0 +1,10 @@ + +汇集还是分散? + 方案1:各站的自页面和fn都slogan都指向自己 + 方案2:各站的自页面指向自己,fn的slogan指向master + 方案3:各站的自页面和fn的slogan都指向master +感觉,还是方案1合理,都指向自己? + 好像只该指向自己,因为频道发布节点时,应该要发送网站链接(提高点击率等于提高排名),你master就没法这么做 + 对,这是关键票 + +另外github弄纯公益节点,不带广告,纯分享,然后在fn里加slogen,应该会有搞头 diff --git a/fn逻辑.md b/fn逻辑.md new file mode 100755 index 00000000..841f6a12 --- /dev/null +++ b/fn逻辑.md @@ -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文件 diff --git a/routes/web.php b/routes/web.php index f29267c0..01c2ea90 100755 --- a/routes/web.php +++ b/routes/web.php @@ -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']); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 8bd0ba6c..dc222020 100755 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -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', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 7999c0f9..d4af8bdd 100755 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -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', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 822d66b6..bec9380d 100755 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -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" ] } diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 83715f39..adcbbbe6 100755 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -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', diff --git a/vendor/symfony/yaml/CHANGELOG.md b/vendor/symfony/yaml/CHANGELOG.md old mode 100755 new mode 100644 index 05b23cd7..364bf66d --- a/vendor/symfony/yaml/CHANGELOG.md +++ b/vendor/symfony/yaml/CHANGELOG.md @@ -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 --- diff --git a/vendor/symfony/yaml/Command/LintCommand.php b/vendor/symfony/yaml/Command/LintCommand.php old mode 100755 new mode 100644 index 0fab77c5..2088d2f1 --- a/vendor/symfony/yaml/Command/LintCommand.php +++ b/vendor/symfony/yaml/Command/LintCommand.php @@ -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(<<%command.name% command lints a YAML file and outputs to STDOUT -the first encountered syntax error. + The %command.name% 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: - cat filename | php %command.full_name% - + cat filename | php %command.full_name% - -You can also validate the syntax of a file: + You can also validate the syntax of a file: - php %command.full_name% filename + php %command.full_name% filename -Or of a whole directory: + Or of a whole directory: - php %command.full_name% dirname + php %command.full_name% dirname -The --format option specifies the format of the command output: + The --format option specifies the format of the command output: - php %command.full_name% dirname --format=json + php %command.full_name% dirname --format=json -You can also exclude one or more specific files: + You can also exclude one or more specific files: - php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml" + php %command.full_name% dirname --exclude="dirname/foo.yaml" --exclude="dirname/bar.yaml" -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; } diff --git a/vendor/symfony/yaml/Dumper.php b/vendor/symfony/yaml/Dumper.php old mode 100755 new mode 100644 index f8ea205a..cd5a1f6c --- a/vendor/symfony/yaml/Dumper.php +++ b/vendor/symfony/yaml/Dumper.php @@ -41,6 +41,15 @@ class Dumper * @param int-mask-of $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 diff --git a/vendor/symfony/yaml/Escaper.php b/vendor/symfony/yaml/Escaper.php old mode 100755 new mode 100644 index e42034aa..921d62ff --- a/vendor/symfony/yaml/Escaper.php +++ b/vendor/symfony/yaml/Escaper.php @@ -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; } diff --git a/vendor/symfony/yaml/Exception/DumpException.php b/vendor/symfony/yaml/Exception/DumpException.php old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Exception/ExceptionInterface.php b/vendor/symfony/yaml/Exception/ExceptionInterface.php old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Exception/ParseException.php b/vendor/symfony/yaml/Exception/ParseException.php old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Exception/RuntimeException.php b/vendor/symfony/yaml/Exception/RuntimeException.php old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Inline.php b/vendor/symfony/yaml/Inline.php old mode 100755 new mode 100644 index 34ef66e6..38ff95ad --- a/vendor/symfony/yaml/Inline.php +++ b/vendor/symfony/yaml/Inline.php @@ -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, ['(?getTimestamp()) { return $scalar; } - } catch (\ValueError) { + } catch (\DateRangeError|\ValueError) { // no-op } @@ -823,19 +833,19 @@ class Inline private static function getTimestampRegex(): string { return <<[0-9][0-9][0-9][0-9]) - -(?P[0-9][0-9]?) - -(?P[0-9][0-9]?) - (?:(?:[Tt]|[ \t]+) - (?P[0-9][0-9]?) - :(?P[0-9][0-9]) - :(?P[0-9][0-9]) - (?:\.(?P[0-9]*))? - (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) - (?::(?P[0-9][0-9]))?))?)? - $~x -EOF; + ~^ + (?P[0-9][0-9][0-9][0-9]) + -(?P[0-9][0-9]?) + -(?P[0-9][0-9]?) + (?:(?:[Tt]|[ \t]+) + (?P[0-9][0-9]?) + :(?P[0-9][0-9]) + :(?P[0-9][0-9]) + (?:\.(?P[0-9]*))? + (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) + (?::(?P[0-9][0-9]))?))?)? + $~x + EOF; } /** diff --git a/vendor/symfony/yaml/LICENSE b/vendor/symfony/yaml/LICENSE old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Parser.php b/vendor/symfony/yaml/Parser.php old mode 100755 new mode 100644 index f82f2b57..40bd941b --- a/vendor/symfony/yaml/Parser.php +++ b/vendor/symfony/yaml/Parser.php @@ -198,7 +198,7 @@ class Parser } } elseif ( self::preg_match('#^(?P(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{!].*?)) *\:(( |\t)++(?P.+))?$#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; diff --git a/vendor/symfony/yaml/Resources/bin/yaml-lint b/vendor/symfony/yaml/Resources/bin/yaml-lint index 143869e0..eca04976 100755 --- a/vendor/symfony/yaml/Resources/bin/yaml-lint +++ b/vendor/symfony/yaml/Resources/bin/yaml-lint @@ -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() ; diff --git a/vendor/symfony/yaml/Tag/TaggedValue.php b/vendor/symfony/yaml/Tag/TaggedValue.php old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Unescaper.php b/vendor/symfony/yaml/Unescaper.php old mode 100755 new mode 100644 diff --git a/vendor/symfony/yaml/Yaml.php b/vendor/symfony/yaml/Yaml.php old mode 100755 new mode 100644 index 36b45198..57625a53 --- a/vendor/symfony/yaml/Yaml.php +++ b/vendor/symfony/yaml/Yaml.php @@ -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. diff --git a/vendor/symfony/yaml/composer.json b/vendor/symfony/yaml/composer.json old mode 100755 new mode 100644 index 2ceac946..93164240 --- a/vendor/symfony/yaml/composer.json +++ b/vendor/symfony/yaml/composer.json @@ -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"