This commit is contained in:
Developer
2026-04-27 23:47:18 +08:00
parent a5b997aecb
commit b6441a8919
5108 changed files with 787008 additions and 7056 deletions

View File

@@ -0,0 +1,40 @@
"""
@File: add_deletion_menu.py
@Time: 2026-04-27
@Description: 添加用户注销审核管理员菜单
@LastUpdate: 初始创建
"""
import paramiko
HOST = "123.207.67.197"
PORT = 22
USERNAME = "root"
PASSWORD = "520Kiss123"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, port=PORT, username=USERNAME, password=PASSWORD)
sqls = [
"SELECT MAX(id) as max_id FROM tool_auth_rule;",
]
cmd = f'mysql -u tools -ptools tools -e "SELECT MAX(id) as max_id FROM tool_auth_rule;"'
stdin, stdout, stderr = ssh.exec_command(cmd)
out = stdout.read().decode('utf-8', 'ignore')
print(f"当前最大ID: {out}")
insert_sql = """
INSERT INTO tool_auth_rule (id, `type`, pid, name, title, icon, condition, remark, ismenu, createtime, updatetime, weigh, `status`)
VALUES (NULL, 'file', 0, 'userdeletion', '用户注销审核', 'fa fa-user-times', '', '审核用户注销申请通过秒注销3天未审核自动注销', 1, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), 0, 'normal');
"""
cmd2 = f'mysql -u tools -ptools tools -e "{insert_sql}"'
stdin, stdout, stderr = ssh.exec_command(cmd2)
err = stderr.read().decode('utf-8', 'ignore')
if err:
print(f"Error: {err}")
else:
print("✅ 管理员菜单添加成功")
ssh.close()

View File

@@ -0,0 +1,95 @@
"""
@name 通过PHP命令行模拟管理员更新一言句子(修复版)
@author AI Coder
@date 2026-04-27
@desc 使用原生PDO操作数据库
@update 修复DB调用方式
"""
import paramiko
from io import BytesIO
HOST = "123.207.67.197"
PORT = 22
USERNAME = "root"
PASSWORD = "520Kiss123"
REMOTE_BASE = "/www/wwwroot/tools.wktyl.com"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, PORT, USERNAME, PASSWORD)
php_script = r'''<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(300);
echo "=== 开始从官方源更新一言句子 ===\n";
$categories = [
'a' => '动画', 'b' => '漫画', 'c' => '游戏', 'd' => '文学',
'e' => '原创', 'f' => '来自网络', 'g' => '其他', 'h' => '影视',
'i' => '诗词', 'j' => '网易云', 'k' => '哲学', 'l' => '抖机灵',
];
$total_new = 0;
$total_dup = 0;
$now = time();
$pdo = new PDO('mysql:host=127.0.0.1;dbname=tools;charset=utf8mb4', 'tools', 'tools');
foreach ($categories as $code => $name) {
$url = "https://cdn.jsdelivr.net/gh/hitokoto-osc/sentences-bundle@latest/sentences/{$code}.json";
echo "[{$name}] 正在获取...\n";
$json = @file_get_contents($url);
if ($json === false) { echo "[{$name}] 获取失败\n"; continue; }
$data = json_decode($json, true);
if (!is_array($data)) { echo "[{$name}] 解析失败\n"; continue; }
$cat_new = 0;
$cat_dup = 0;
foreach ($data as $item) {
$uuid = isset($item['uuid']) ? $item['uuid'] : '';
if (!$uuid) continue;
$stmt = $pdo->prepare("SELECT id FROM tool_hitokoto WHERE uuid=? LIMIT 1");
$stmt->execute([$uuid]);
if ($stmt->fetch()) { $cat_dup++; $total_dup++; continue; }
$hitokoto = isset($item['hitokoto']) ? mb_substr($item['hitokoto'], 0, 2000) : '';
$from_source = isset($item['from']) ? mb_substr($item['from'], 0, 200) : '';
$from_who = isset($item['from_who']) ? mb_substr($item['from_who'], 0, 200) : '';
$created_at = isset($item['created_at']) ? intval($item['created_at']) : 0;
$stmt2 = $pdo->prepare("INSERT INTO tool_hitokoto (uuid,hitokoto,type,type_name,from_source,from_who,created_at,local_time,views,switch) VALUES (?,?,?,?,?,?,?,?,?,1)");
$stmt2->execute([$uuid,$hitokoto,$code,$name,$from_source,$from_who,$created_at,$now,0]);
$cat_new++;
$total_new++;
}
echo "[{$name}] 新增:{$cat_new} 跳过:{$cat_dup}\n";
}
$stmt = $pdo->query("SELECT COUNT(*) FROM tool_hitokoto WHERE switch=1");
$total = $stmt->fetchColumn();
echo "\n=== 更新完成 ===\n";
echo "新增:{$total_new} 重复:{$total_dup} 总数:{$total}\n";
'''
remote_script = f"{REMOTE_BASE}/runtime/update_hitokoto.php"
sftp = ssh.open_sftp()
sftp.putfo(BytesIO(php_script.encode('utf-8')), remote_script)
sftp.close()
print("\n⏳ 正在从官方源更新一言句子...")
print("(从CDN下载12个分类数据请耐心等待)\n")
cmd = f"php {remote_script} 2>&1"
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=300)
out = stdout.read().decode('utf-8', errors='replace')
print(out)
ssh.exec_command(f"rm -f {remote_script}")
ssh.exec_command(f"rm -rf {REMOTE_BASE}/runtime/*")
ssh.close()
print("\n🎉 完成!")

View File

@@ -0,0 +1,26 @@
"""测试其他工具路由"""
import paramiko
HOST = "123.207.67.197"
PORT = 22
USERNAME = "root"
PASSWORD = "520Kiss123"
REMOTE_BASE = "/www/wwwroot/tools.wktyl.com"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, PORT, USERNAME, PASSWORD)
cmds = [
f"cd {REMOTE_BASE}/public && php index.php /moyu 2>&1 | head -c 200",
f"cd {REMOTE_BASE}/public && php index.php /joke 2>&1 | head -c 200",
f"cd {REMOTE_BASE}/public && php index.php /hanzi 2>&1 | head -c 200",
f"cd {REMOTE_BASE}/public && php index.php / 2>&1 | head -c 200",
]
for cmd in cmds:
print(f"\n$ {cmd}")
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=15)
print(f" {stdout.read().decode().strip()[:200]}")
ssh.close()

View File

@@ -0,0 +1,13 @@
"""获取完整错误信息"""
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("123.207.67.197", 22, "root", "520Kiss123")
cmd = """curl -sk 'https://tools.wktyl.com/admin.php/hitokoto?ref=addtabs' 2>&1"""
stdin, stdout, stderr = ssh.exec_command(cmd, timeout=15)
out = stdout.read().decode('utf-8', errors='replace')
print(out)
ssh.close()

View File

@@ -0,0 +1,86 @@
"""
@File: verify_stats_realtime.py
@Time: 2026-04-27
@Description: 验证统计页面懒加载和实时统计API
@LastUpdate: 测试所有统计API和页面
"""
import requests
import json
import time
BASE = 'https://tools.wktyl.com/api/webapi'
def test_api(name, url, expect_keys=None):
try:
r = requests.get(url, timeout=10)
data = r.json()
if data.get('code') == 1:
print(f'{name}: OK')
if expect_keys:
for k in expect_keys:
if k in data.get('data', {}):
print(f' {k}: {data["data"][k]}')
else:
print(f' ⚠️ {k}: missing')
return True
else:
print(f'{name}: code={data.get("code")} msg={data.get("msg")}')
return False
except Exception as e:
print(f'{name}: {e}')
return False
print("=" * 60)
print(" 统计API验证")
print("=" * 60)
test_api('概览', f'{BASE}/stats_overview', ['user', 'article', 'tool', 'signin', 'attachment'])
test_api('内容统计', f'{BASE}/stats_content')
test_api('热门工具(50)', f'{BASE}/stats_hot_tools?limit=50')
test_api('热门文章(50)', f'{BASE}/stats_hot_articles?limit=50')
test_api('接口使用', f'{BASE}/stats_api_usage?days=7')
test_api('趋势', f'{BASE}/stats_trend?days=7')
test_api('用户活跃', f'{BASE}/stats_user_activity')
print("\n" + "=" * 60)
print(" 实时统计API验证")
print("=" * 60)
r1 = requests.get(f'{BASE}/stats_realtime', timeout=10).json()
if r1.get('code') == 1:
d = r1['data']
print(f' ✅ stats_realtime: OK')
print(f' 累计请求: {d["total_requests"]}')
print(f' 今日请求: {d["today_requests"]}')
print(f' QPS: {d["qps"]}')
print(f' 接口数: {len(d["apis"])}')
for api in d['apis'][:5]:
print(f' - {api["name"]}: {api["count"]}')
else:
print(f' ❌ stats_realtime: {r1.get("msg")}')
time.sleep(2)
r2 = requests.get(f'{BASE}/stats_realtime', timeout=10).json()
if r2.get('code') == 1:
d2 = r2['data']
diff = d2['total_requests'] - d['total_requests']
print(f'\n 2秒后再次请求:')
print(f' 累计请求: {d2["total_requests"]} (差值: +{diff})')
print(f' QPS: {d2["qps"]}')
print("\n" + "=" * 60)
print(" 页面验证")
print("=" * 60)
try:
r = requests.get('https://tools.wktyl.com/stats.html', timeout=10)
if r.status_code == 200 and '实时请求监控' in r.text:
print(' ✅ stats.html: 页面正常,包含实时面板')
else:
print(f' ❌ stats.html: status={r.status_code}')
except Exception as e:
print(f' ❌ stats.html: {e}')
print("\n✅ 验证完成")