api
This commit is contained in:
40
docs/toolsapi/scripts/add_deletion_menu.py
Normal file
40
docs/toolsapi/scripts/add_deletion_menu.py
Normal 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()
|
||||
95
docs/toolsapi/scripts/admin_update_cli.py
Normal file
95
docs/toolsapi/scripts/admin_update_cli.py
Normal 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🎉 完成!")
|
||||
26
docs/toolsapi/scripts/test_other_routes.py
Normal file
26
docs/toolsapi/scripts/test_other_routes.py
Normal 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()
|
||||
13
docs/toolsapi/scripts/verify_hitokoto_admin.py
Normal file
13
docs/toolsapi/scripts/verify_hitokoto_admin.py
Normal 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()
|
||||
86
docs/toolsapi/scripts/verify_stats_realtime.py
Normal file
86
docs/toolsapi/scripts/verify_stats_realtime.py
Normal 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✅ 验证完成")
|
||||
Reference in New Issue
Block a user