no message

This commit is contained in:
hellcat 2026-08-13 15:19:00 +08:00
parent 8c5daf2abb
commit addd2662d8
3 changed files with 168 additions and 8 deletions

View File

@ -12,7 +12,8 @@ use App\Services\CountrySpeedService;
use App\Services\ServiceFnPoolV2rayTo;
use App\Models\FreenodePool as ModelFreenodePool;
use App\Services\Cron\ReportTraffic;
use App\Services\Cron\ReportUmami;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
class SakaiController
{
@ -26,16 +27,25 @@ class SakaiController
public function test1()
{
$s = "vmess://eyJ2IjoiMiIsInBzIjoi8J+HuvCfh7hVU18yNHwxMDNLQi9zfEIwMDctMjYwNjE4IiwiYWRkIjoiMTI5LjE0Ni43Ny4yNDgiLCJwb3J0IjoiMzk0OTUiLCJpZCI6ImY4MzZjNzM2LTg3ZmMtNGZkZS1hYWJjLTAwODU3ZWNkZmYzZSIsImFpZCI6IjAiLCJzY3kiOiJhdXRvIiwibmV0Ijoid3MiLCJ0eXBlIjoiIiwidGxzIjoiIiwicGF0aCI6Ii9jY3R2MTMubTN1OCJ9";
// TeleSlave::warn()->send("⚠️ [Umami 报表失败]: 无法获取 Auth Token请检查账号密码。");
// echo 111;
// exit;
$s = explode("://", $s);
$oReportUmami = new ReportUmami();
$oReportUmami->handle();
$a = $s[0];
$b = $s[1];
exit;
$s = base64_decode($b);
tt($s);
// $s = "vmess://eyJ2IjoiMiIsInBzIjoi8J+HuvCfh7hVU18yNHwxMDNLQi9zfEIwMDctMjYwNjE4IiwiYWRkIjoiMTI5LjE0Ni43Ny4yNDgiLCJwb3J0IjoiMzk0OTUiLCJpZCI6ImY4MzZjNzM2LTg3ZmMtNGZkZS1hYWJjLTAwODU3ZWNkZmYzZSIsImFpZCI6IjAiLCJzY3kiOiJhdXRvIiwibmV0Ijoid3MiLCJ0eXBlIjoiIiwidGxzIjoiIiwicGF0aCI6Ii9jY3R2MTMubTN1OCJ9";
//
// $s = explode("://", $s);
//
// $a = $s[0];
// $b = $s[1];
//
// $s = base64_decode($b);
//
// tt($s);
// $oReportTraffic = new ReportTraffic();
//

149
app/Services/Cron/ReportUmami.php Executable file
View File

@ -0,0 +1,149 @@
<?php
declare(strict_types=1);
namespace App\Services\Cron;
use App\Services\TomTool\Telegram\Slave as TeleSlave;
/**
* 定时获取 Umami 统计信息并发送至 Telegram 机器人
*/
final class ReportUmami
{
private string $baseUrl;
private string $username = 'admin';
private string $password = 'taonihouzi#';
public function __construct()
{
$this->baseUrl = (string) config('path.url_umami_base');
}
/**
* 定时任务入口方法
*/
public function handle(): void
{
try {
// 1. 获取 API 认证 Token
$token = $this->getAuthToken();
if (!$token) {
TeleSlave::log()->send("⚠️ [Umami 报表失败]: 无法获取 Auth Token请检查账号密码。");
return;
}
// 2. 获取网站列表
$websites = $this->getWebsites($token);
if (empty($websites)) {
TeleSlave::log()->send(" [Umami 报表]: 数据库中未找到任何网站。");
return;
}
// 3. 统计过去 24 小时的数据
$endAt = microtime(true) * 1000; // 当前时间戳 (毫秒)
$startAt = $endAt - (24 * 3600 * 1000); // 24小时前的时间戳 (毫秒)
$msg = "<b>📊 Umami 每日站点数据日报</b>\n";
$msg .= "----------------------------\n";
foreach ($websites as $site) {
$siteId = $site['id'];
$siteName = $site['name'];
$domain = $site['domain'] ?? '';
// 获取单个网站的统计指标
$stats = $this->getWebsiteStats($token, $siteId, (int)$startAt, (int)$endAt);
if ($stats) {
$pageviews = $stats['pageviews']['value'] ?? 0;
$visitors = $stats['visitors']['value'] ?? 0;
$visits = $stats['visits']['value'] ?? 0;
$bounces = $stats['bounces']['value'] ?? 0;
// 计算跳出率
$bounceRate = $visits > 0 ? round(($bounces / $visits) * 100, 1) : 0;
$msg .= "🌐 <b>{$siteName}</b> ({$domain})\n";
$msg .= "├ 👁️ 页面浏览 (PV): <b>{$pageviews}</b>\n";
$msg .= "├ 👤 独立访客 (UV): <b>{$visitors}</b>\n";
$msg .= "├ 🔄 会话次数: <b>{$visits}</b>\n";
$msg .= "└ 📉 跳出率: <b>{$bounceRate}%</b>\n\n";
}
}
// 4. 发送日志至 Telegram
TeleSlave::log()->send($msg);
} catch (\Throwable $e) {
TeleSlave::log()->send("❌ [Umami 报表异常]: " . $e->getMessage());
}
}
/**
* 1. 登录 Umami 获取 JWT Token
*/
private function getAuthToken(): ?string
{
$response = $this->curlRequest('POST', '/api/auth/login', [
'username' => $this->username,
'password' => $this->password,
]);
return $response['token'] ?? null;
}
/**
* 2. 获取网站列表
*/
private function getWebsites(string $token): array
{
$response = $this->curlRequest('GET', '/api/websites', [], $token);
return $response['data'] ?? $response ?? [];
}
/**
* 3. 获取指定网站的统计数据
*/
private function getWebsiteStats(string $token, string $siteId, int $startAt, int $endAt): ?array
{
$endpoint = sprintf('/api/websites/%s/stats?startAt=%d&endAt=%d', $siteId, $startAt, $endAt);
return $this->curlRequest('GET', $endpoint, [], $token);
}
/**
* 通用 cURL 请求工具方法
*/
private function curlRequest(string $method, string $path, array $data = [], ?string $token = null): ?array
{ organize:
$ch = curl_init($this->baseUrl . $path);
$headers = [
'Content-Type: application/json',
'Accept: application/json',
];
if ($token) {
$headers[] = 'Authorization: Bearer ' . $token;
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
if ($method === 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode >= 200 && $httpCode < 300 && $result) {
return json_decode($result, true);
}
return null;
}
}

View File

@ -12,4 +12,5 @@ return [
'cvf' => env('url_fn_cvf', 'clashv2rayfree.com'),
'vcf' => env('url_fn_vcf', 'v2rayclashfree.com')
],
'url_umami_base' => env("url_umami_base"),
];