no message

This commit is contained in:
hellcat 2026-02-12 17:27:01 +08:00
parent f06e8d7742
commit c180dd2a1b
11 changed files with 501 additions and 10 deletions

View File

@ -0,0 +1,75 @@
<?php
declare(strict_types=1);
namespace App\Http\Controllers\Api\v1;
use Illuminate\Http\Request;
//use App\Models\BoxCountry as ModelCountry;
final class FreenodeCountrySpeedController
{
static $aCountry = [
"美国",
"美国",
"日本",
"日本",
"新加坡",
"新加坡",
"香港",
"香港",
"台湾",
"台湾",
"越南",
"越南",
"俄罗斯",
"新西兰",
"瑞士",
"荷兰",
"冰岛",
"爱尔兰",
"乌克兰",
"泰国",
"阿根廷",
"葡萄牙",
"美国",
"日本",
"新加坡",
"台湾",
"香港",
"韩国",
"德国",
"土耳其",
"法国",
"加拿大",
"加拿大",
];
public function build(Request $oRequest)
{
//// 地区
$iCountryLimit = rand(5, 12);
$aCountryKey = array_rand(self::$aCountry, $iCountryLimit);
$aCountry = [];
foreach ($aCountryKey as $sCountryKey) {
$aCountry[] = self::$aCountry[$sCountryKey];
}
$sNodeZone = implode("", $aCountry);
//// 速度
$iNodeSpeed = rand(config("freenode.speed_min"), config("freenode.speed_max"));
$iNodeCount = rand(config("freenode.count_min"), config("freenode.count_max"));
$sContent = "
<p>本次更新共".$iNodeCount."个可用节点,最高速度".$iNodeSpeed."M/S。</p>
<p>覆盖".$sNodeZone."等多个区域。</p>
<p>复制下方的v2ray/Clash订阅链接在客户端添加即可正常使用。<br />
";
return response()->json($sContent);
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class ArticleTemplateFreenode extends Model
{
protected $table = 'article_template_freenode';
// public $timestamps = false;
// public static function _listKey()
// {
// $aSelf = self::all()->toArray();
//
// foreach ($aSelf as &$aSelfRow) {
// unset($aSelfRow["content"]);
// }
//
// return $aSelf;
// }
}

View File

@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace App\Services;
final class CountrySpeedService
{
static $aCountry = [
"美国",
"美国",
"日本",
"日本",
"新加坡",
"新加坡",
"香港",
"香港",
"台湾",
"台湾",
"越南",
"越南",
"俄罗斯",
"新西兰",
"瑞士",
"荷兰",
"冰岛",
"爱尔兰",
"乌克兰",
"泰国",
"阿根廷",
"葡萄牙",
"美国",
"日本",
"新加坡",
"台湾",
"香港",
"韩国",
"德国",
"土耳其",
"法国",
"加拿大",
"加拿大",
];
public static function fn_b()
{
//// 地区
$iCountryLimit = rand(5, 12);
$aCountryKey = array_rand(self::$aCountry, $iCountryLimit);
$aCountry = [];
foreach ($aCountryKey as $sCountryKey) {
$aCountry[] = self::$aCountry[$sCountryKey];
}
$sNodeZone = implode("", $aCountry);
//// 速度
$iNodeSpeed = rand(config("freenode.speed_min"), config("freenode.speed_max"));
$iNodeCount = rand(config("freenode.count_min"), config("freenode.count_max"));
$sContent = "本次更新共".$iNodeCount."个可用节点,最高速度".$iNodeSpeed."M/S。
覆盖".$sNodeZone."等多个区域。
复制下方的v2ray/Clash订阅链接在客户端添加即可正常使用。";
return $sContent;
}
}

View File

@ -16,6 +16,7 @@ use App\Services\Cron\ArticleSchema as CronArticleSchema;
use App\Services\Cron\FnTgPublish as CronFnTgPublish;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
use App\Services\CacheTg as ServiceCacheTg;
use App\Services\Cron\FnSitePublish as CronFnSitePublish;
final class Cron
{
@ -50,21 +51,18 @@ final class Cron
CronFreenodeMerge::save();
CronFreenodeMerge::baseToSite();
CronFreenodeSync::run();
// CronFreenodeSync::nodehub(); 先不管她
}
if ($h == 11 && $i == 6) {
CronFnSitePublish::fn_b();
}
// if ($i === 0) {
// // ReportSender::handle();
// }
if ($h == 5 && $i === 3) {
CronFreenodeFile::clear();
}
// if ($h == 15 && $i == 3) {
//// CronFreenodeLog::fromLast();
// }
if ($h == 11 && $i == 3) { // 中午12点03发布fn的tg
if ($h == 12 && $i == 3) { // 中午12点03发布fn的tg
CronFnTgPublish::run();
}

View File

@ -0,0 +1,142 @@
<?php
declare(strict_types=1);
namespace App\Services\Cron;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
use App\Models\SiteMap as ModelSiteMap;
use App\Services\TomTool\HttpV2;
use App\Models\ArticleTemplateFreenode;
use Illuminate\Support\Carbon;
use App\Services\CountrySpeedService;
use App\Models\Ship;
use App\Services\FreenodeHelperService;
final class FnSitePublish
{
public static function fn_b()
{
echo "\n\nFnSitePublish::fn_b()";
$oSites = ModelSiteMap::where("group_code", "fn_b")->get();
$oDate = Carbon::now();
$sDateCN = $oDate->format('n月j日');
$sYear = date("Y");
$sCountrySpeed = CountrySpeedService::fn_b();
$sToken = FreenodeHelperService::tokenToday();
$aTags = [
"Shadowrocket",
"Quantumult",
"Clash",
"SSR",
"节点",
"订阅链接",
"免费节点",
"v2ray",
"SSR",
];
$aResult = [];
$aResult["site_code_short"] = '';
$aResult["article"] = [
"title" => "",
"title_sub" => "",
"content" => "",
"tags" => $aTags,
"7like" => rand(5, 55),
];
foreach ($oSites as $oSite) {
$aResult["site_code_short"] = $oSite->code_short;
$oArticleTemplate = ArticleTemplateFreenode::where("group_code", $oSite->group_code)->first();
$aSiteConfig = json_decode($oSite->config, true);
$sTelegramLink = $aSiteConfig["telegram"];
$aShipCode = $aSiteConfig["ship_code"];
$aSiteFnClient = $aSiteConfig["freenode_client"];
$aDylj = [];
foreach ($aSiteFnClient as $sSiteFnClient) {
$sFeedLink = "https://".FreenodeHelperService::urlFeedToday($oSite->code_short, $sSiteFnClient);
$str = "";
$str .= "<b>".$sSiteFnClient."订阅链接:</b>\n\n";
$str .= "<a href='javascript:;' data-clipboard-text='".$sFeedLink."' class='copy-permalink'>
<span class='subCopy'><i class='iconfont icon-link'></i> ".$sFeedLink."</span></a>";
$aDylj[$sSiteFnClient] = $str;
}
// <a href="javascript:;" data-clipboard-text="https://cfn.loc/sub/20260204-v2ray.txt" class="copy-permalink">
// <span class="subCopy">
// <i class="iconfont icon-link"></i> https://cfn.loc/sub/20260204-v2ray.txt
// </span>
// </a>
$sDylj = implode("\n\n", $aDylj);
$sJctj = "";
foreach ($aShipCode as $sShipCode) {
$sJctj .= "<h2>机场推荐:</h2>\n\n";
$oShip = Ship::where("code", $sShipCode)->first();
$aShipGood = json_decode($oShip->good, true);
$sShipGood = implode("\n\n", $aShipGood);
$sJctj .= $sShipGood;
$sJctj .= "\n\n";
$sJctj .= "<b><a target='__blank' style='color:blue;' href='https://{$oShip->www}'>点击进入机场官网:{$oShip->name}</a>。</b>";
}
$aFilter = [
'$sShipWww' => $oShip->www,
'$sShipName' => $oShip->name,
'$sDateCN' => $sDateCN,
'$sYear' => $sYear,
'$sTitleSub' => $sCountrySpeed,
'$sTelegramLink'=> $sTelegramLink,
'$sCountrySpeed'=> $sCountrySpeed,
'$sJctj' => $sJctj,
'$sDylj' => $sDylj,
];
$aResult["article"]["content"] = self::nl2p(str_replace(array_keys($aFilter), array_values($aFilter), $oArticleTemplate->content));
$aResult["article"]["title"] = str_replace(array_keys($aFilter), array_values($aFilter), $oArticleTemplate->title);
$aResult["article"]["title_sub"] = $sCountrySpeed;
// $sImagesApi = "https://".config("path.url_resource_base")."/api/images/get/url-by-num";
// todo 发送文章
$aApiPath = json_decode($oSite->api_path, true);
$sArticleReceiveFreenode = "https://".$oSite->url."/".$aApiPath["article_receive_freenode"];
// tomd($sArticleReceiveFreenode, 1);
$sFlow = HttpV2::make($sArticleReceiveFreenode, "post")->setDataA($aResult)->send();
$aFlow = json_decode($sFlow, true);
if (!isset($aFlow["isDone"]) || !$aFlow["isDone"]) {
echo $sFlow;
TeleSlave::warn()->send('FnSitePublish::fn_b()的发送文章失败');
continue;
}
}
echo "/n - ok";
}
public static function nl2p($text) {
// 将文本按换行符拆分成数组
$paragraphs = explode("\n", $text);
// 将每一段用 <p> 标签包裹
$paragraphs = array_map(function($paragraph) {
return '<p>' . trim($paragraph) . '</p>';
}, $paragraphs);
// 使用 implode 拼接成一个字符串
return implode('', $paragraphs);
}
}

View File

@ -253,7 +253,7 @@ final class FreenodeMerge
}
}
$oSiteMap = ModelSiteMap::where("group_code", "fn_a")->get();
$oSiteMap = ModelSiteMap::whereIn("group_code", ["fn_a", "fn_b"])->get();
if ($oSiteMap->isEmpty()) {
throw new \Exception("没找到siteMap的fn_a组");

View File

@ -7,6 +7,7 @@ namespace App\Services\Cron;
use App\Models\SiteMap as ModelSiteMap;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
use App\Services\TomTool\HttpV2;
use Illuminate\Support\Facades\Http;
final class FreenodeSync
{
@ -54,4 +55,118 @@ final class FreenodeSync
echo " - ok \n";
}
static function nodehub()
{
echo "\nFeenodeSync::nodehub() - 开始 \n";
$sDirBase = $_ENV["dir_base"];
$oFnSiteList = ModelSiteMap::where("group_code", "nodehub")->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)) {
$sMsg = "freenodeSync的run没有当天文件".$sFilePath;
TeleSlave::warn()->send($sMsg);
echo "\n - ".$sMsg;
continue;
}
$aFnContent[$aSiteConfigFnClientRow] = file_get_contents($sFilePath);
}
$sApiUrl = "https://".$oFnSite->url."/".$sSiteApiFreenodeReceive; //// test
$sResult = HttpV2::make($sApiUrl, "post")->setDataA($aFnContent)->enableJsonSend()->send();
$aResult = json_decode($sResult, true);
if (!isset($aResult["isDone"]) || $aResult["isDone"] != true) {
$sMsg = "freenodeSync::同步失败 ->".$oFnSite->name;
echo $sMsg.$sResult;
TeleSlave::warn()->setMsgS($sMsg)->send();
continue;
}
if (isset($aResult["sMsg"])) {
$sMsg = json_encode($aResult["sMsg"]);
TeleSlave::notify()->setMsgS($sMsg)->send();
} else {
TeleSlave::log()->setMsgS("nodehub同步完成")->send();
}
}
echo " - 完成 \n";
}
// static function run_b()
// {
// echo "\nFeenodeSync::run_b() - 开始 \n";
//
// $sDirBase = $_ENV["dir_base"];
//
// $oFnSiteList = ModelSiteMap::where("group_code", "fn_b")->get();
// $oSiteNodehub = ModelSiteMap::where("code", "nodehub")->first();
// $aSiteNodehubConfig = json_decode($oSiteNodehub->config ?? '', true);
//
// $aFreenodeClient = $aSiteNodehubConfig["freenode_client"] ?? [];
// $aNodehubApis = json_decode($oSiteNodehub->api_path, true);
// $sSiteApiFreenodeReceive = $aNodehubApis["freenode_receive"] ?? "";
//
// $aResultAll = [];
// foreach ($oFnSiteList as $oFnSite) {
//
//// $aSiteConfig = json_decode($oFnSite->config, true);
//// $aSiteConfigFnClient = $aSiteConfig["freenode_client"] ?? [];
//// $aSiteConfigFnClient = ["clash", "v2ray"];
//// $aSiteApi = json_decode($oFnSite->api_path, true);
//// $sSiteApiFreenodeReceive = $aSiteApi["freenode_receive"] ?? "";
//
// $aData = [];
// $aData["site_code_short"] = $oFnSite->code_short;
// foreach ($aFreenodeClient as $aSiteConfigFnClientRow) {
// $sFilePath = $sDirBase."public/freenode/merge/".$oFnSite->code."/".$aSiteConfigFnClientRow."/".date("Y-m-d").".txt";
//
// if (!file_exists($sFilePath)) {
// $sMsg = "freenodeSync的run没有当天文件".$sFilePath;
// TeleSlave::warn()->send($sMsg);
// echo "\n - ".$sMsg;
// continue;
// }
//
// $aData["raw"][$aSiteConfigFnClientRow] = file_get_contents($sFilePath);
// }
//
// $sApiUrl = "https://".$oSiteNodehub->url."/".$sSiteApiFreenodeReceive;
//// tomd($sApiUrl, 1);
// $sResult = HttpV2::make($sApiUrl, "post")->setDataA($aData)->enableJsonSend()->send();
// $aResult = json_decode($sResult, true);
//
// if (!isset($aResult["isDone"]) || $aResult["isDone"] != true) {
// $sMsg = "freenodeSync::同步失败 ->".$oFnSite->name."->".$sResult;
// echo $sMsg;
//// TeleSlave::warn()->setMsgS($sMsg)->send();
// continue;
// }
//
// if (isset($aResult["sMsg"])) {
// $sMsg = json_encode($aResult["sMsg"]);
//// TeleSlave::warn()->setMsgS($sMsg)->send();
// }
//
// }
//
// echo " - 完成 \n";
// }
}

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace App\Services;
use Illuminate\Support\Str;
class FreenodeHelperService
{
public static function tokenToday()
{
$sDate = date('Ymd');
$sSuffix = "nodes";
$sRawKey = $sDate . $sSuffix;
$sUniqueToken = hash_hmac('sha256', $sRawKey, 'wocaonide');
$sShortToken = Str::substr($sUniqueToken, 0, 16);
return $sShortToken;
}
public static function urlFeedToday($sSiteCodeShort, $sClient)
{
$sToken = self::tokenToday();
$sFileExt = self::clientToExt($sClient);
$sFeedUrl = config("path.url_nodehub_base")."/".$sSiteCodeShort."/".$sToken."/".date("Ymd")."-".$sClient.$sFileExt;
return $sFeedUrl;
}
public static function clientToExt($sClient)
{
switch ($sClient) {
case "v2ray":
$sExt = ".txt";
break;
case "clash":
$sExt = ".yaml";
break;
default:
$sExt = ".txt";
break;
}
return $sExt;
}
}

10
config/freenode.php Executable file
View File

@ -0,0 +1,10 @@
<?php
return [
'speed_min' => (int) env('freenode_speed_min', 0),
'speed_max' => (int) env('freenode_speed_max', 0),
'count_min' => (int) env('freenode_count_min', 0),
'count_max' => (int) env('freenode_count_max', 0),
];

7
config/path.php Executable file
View File

@ -0,0 +1,7 @@
<?php
return [
"url_nodehub_base" => env("url_nodehub_base"),
];

View File

@ -19,10 +19,13 @@ 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;
use App\Http\Controllers\Api\v1\FreenodeCountrySpeedController;
//Route::get('/', [ArticleListController::class, 'fn'])->middleware('test');
// /api/telegram/post
Route::any('/api/v1/freenode/country_speed', [FreenodeCountrySpeedController::class, 'build']);
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']);