mirror of
https://github.com/NeteaseCloudMusicApiEnhanced/api-clawer.git
synced 2026-03-21 09:53:10 +00:00
feat: 支持清空抓包信息
This commit is contained in:
parent
3dea10d82f
commit
1e1111c112
125
example.html
125
example.html
@ -1,125 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<link rel="icon" href="docs/netease.png">
|
||||
<title>网易云音乐 API Enhanced</title>
|
||||
<style>
|
||||
:root {
|
||||
--fg: #333;
|
||||
--muted: #666;
|
||||
--border: #ddd;
|
||||
--bg: #f5f5f5;
|
||||
--panel: #ffffff;
|
||||
--accent: #333;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html, body { height: 100%; }
|
||||
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: var(--fg); background: var(--bg); line-height: 1.6; }
|
||||
.container { max-width: 960px; margin: 40px auto; padding: 0 20px; }
|
||||
@media (max-width: 480px) {
|
||||
.container { margin: 20px auto; padding: 0 16px; }
|
||||
header.site-header h1 { font-size: 22px; }
|
||||
.block { padding: 16px; }
|
||||
}
|
||||
header.site-header { margin-bottom: 24px; }
|
||||
header.site-header h1 { font-size: 28px; font-weight: 600; margin: 0; }
|
||||
.badge { display: inline-block; margin-left: 8px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 12px; font-size: 12px; color: var(--muted); }
|
||||
.sub { margin-top: 8px; color: var(--muted); font-size: 14px; }
|
||||
.block { background: var(--panel); border: 1px solid var(--border); border-radius: 12px; padding: 20px; margin-bottom: 16px; box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); }
|
||||
.block h2 { margin: 0 0 12px; font-size: 18px; font-weight: 600; }
|
||||
.kvs { display: grid; grid-template-columns: 100px 1fr; gap: 8px 12px; align-items: start; }
|
||||
.kvs div:first-child { color: var(--muted); flex-shrink: 0; }
|
||||
.kvs div:last-child { word-break: break-all; overflow-wrap: anywhere; min-width: 0; overflow: hidden; }
|
||||
@media (max-width: 480px) {
|
||||
.kvs { grid-template-columns: 1fr; gap: 4px 12px; }
|
||||
.kvs div:first-child { font-weight: 500; }
|
||||
}
|
||||
ul.links { list-style: none; padding: 0; margin: 0; }
|
||||
ul.links li { margin: 8px 0; }
|
||||
ul.links a { color: var(--fg); text-decoration: none; border-bottom: 1px dotted var(--border); transition: all 0.2s ease; }
|
||||
ul.links a:hover { color: var(--accent); border-bottom-color: var(--accent); }
|
||||
pre { margin: 0; background: #f9f9f9; border: 1px solid var(--border); border-radius: 6px; padding: 12px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; }
|
||||
code { font-family: 'Courier New', monospace; font-size: 13px; }
|
||||
@media (max-width: 480px) {
|
||||
code { font-size: 12px; }
|
||||
}
|
||||
footer.site-footer { margin-top: 24px; padding-top: 12px; border-top: 1px solid var(--border); color: var(--muted); text-align: center; }
|
||||
footer.site-footer a { color: var(--fg); text-decoration: none; transition: color 0.2s ease; }
|
||||
footer.site-footer a:hover { color: var(--accent); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<header class="site-header">
|
||||
<h1>网易云音乐 API Enhanced <span id="api-version" class="badge"></span></h1>
|
||||
<p class="sub">🔍 A revival project for NeteaseCloudMusicApi Node.js Api Services || 网易云音乐 API 备份 + 增强 || 本项目自原版v4.28.0版本后开始自行维护</p>
|
||||
</header>
|
||||
|
||||
<section class="block">
|
||||
<h2>状态</h2>
|
||||
<div class="kvs">
|
||||
<div>Base URL</div><div id="base-url">—</div>
|
||||
<div>当前页</div><div id="current-url">—</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
<h2>文档</h2>
|
||||
<p><a href="/docs" target="_blank">查看在线文档</a></p>
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
<h2>常用接口</h2>
|
||||
<ul class="links">
|
||||
<li><a href="/search?keywords=妖精小姐的魔法邀约">搜索音乐: <code>GET /search</code></a></li>
|
||||
<li><a href="/song/detail?ids=2756058128">获取音乐详情: <code>GET /song/detail</code></a></li>
|
||||
<li><a href="/comment/music?id=2756058128&limit=1">获取音乐评论: <code>GET /comment/music</code></a></li>
|
||||
<li><a href="/song/url/v1?id=2756058128&level=exhigh">获取音乐播放链接: <code>GET /song/url/v1</code></a></li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section class="block">
|
||||
<h2>调试部分</h2>
|
||||
<pre><code>curl -s {origin}/inner/version
|
||||
curl -s {origin}/search?keywords=网易云</code></pre>
|
||||
<div style="margin-top:10px; line-height:2;">
|
||||
<a href="/api.html">交互式调试</a> ·
|
||||
<a href="/qrlogin.html">二维码登录示例</a> ·
|
||||
<a href="/unblock_test.html">解灰测试</a> ·
|
||||
<a href="/audio_match_demo/index.html">听歌识曲 Demo</a> ·
|
||||
<a href="/cloud.html">云盘上传</a> ·
|
||||
<a href="/playlist_import.html">歌单导入</a> ·
|
||||
<a href="/eapi_decrypt.html">EAPI 解密</a> ·
|
||||
<a href="/listen_together_host.html">一起听示例</a> ·
|
||||
<a href="/playlist_cover_update.html">更新歌单封面示例</a> ·
|
||||
<a href="/avatar_update.html">头像更新示例</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<footer class="site-footer">
|
||||
<a href="https://github.com/neteasecloudmusicapienhanced/api-enhanced" target="_blank">GitHub</a>
|
||||
</footer>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
var origin = window.location.origin;
|
||||
document.getElementById('base-url').textContent = origin;
|
||||
document.getElementById('current-url').textContent = window.location.href;
|
||||
|
||||
fetch('/inner/version', { method: 'POST' })
|
||||
.then(function (r) { return r.json(); })
|
||||
.then(function (data) {
|
||||
var v = data && data.data && data.data.version;
|
||||
if (v) document.getElementById('api-version').textContent = 'v' + v;
|
||||
var pre = document.querySelector('pre code');
|
||||
if (pre) pre.textContent = pre.textContent.replace(/\{origin\}/g, origin);
|
||||
})
|
||||
.catch(function () {});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -26,6 +26,24 @@ app.get('/api/data', (req, res) => {
|
||||
res.json(capturedData);
|
||||
});
|
||||
|
||||
// 版本信息端点
|
||||
app.get('/api/version', (req, res) => {
|
||||
try {
|
||||
const packageJson = require('../../package.json');
|
||||
res.json({ version: packageJson.version });
|
||||
} catch (error) {
|
||||
console.error('Failed to read package.json:', error);
|
||||
res.json({ version: '0.1.0' });
|
||||
}
|
||||
});
|
||||
|
||||
// 清空数据端点
|
||||
app.post('/api/clear', (req, res) => {
|
||||
capturedData = [];
|
||||
broadcastData();
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
// SSE 端点
|
||||
app.get('/api/events', (req, res) => {
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
|
||||
@ -301,13 +301,36 @@
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.clear-btn {
|
||||
display: inline-block;
|
||||
padding: 4px 10px;
|
||||
background: #f5f5f5;
|
||||
color: var(--muted);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.clear-btn:hover {
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.clear-btn:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main-container">
|
||||
<div class="left-panel">
|
||||
<div class="header">
|
||||
<h1>网易云音乐抓包工具 <span class="badge">v0.1.0</span></h1>
|
||||
<h1>网易云音乐抓包工具 <span class="badge" id="version-badge">加载中...</span></h1>
|
||||
<p class="sub">🔍 简易网易云音乐客户端抓包工具</p>
|
||||
</div>
|
||||
<div class="left-content">
|
||||
@ -330,7 +353,7 @@
|
||||
</section>
|
||||
|
||||
<div class="capture-list">
|
||||
<h2>抓包列表</h2>
|
||||
<h2>抓包列表 <button class="clear-btn" onclick="clearCaptures()">清空</button></h2>
|
||||
<div id="capture-list"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -485,6 +508,62 @@
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function fetchVersion() {
|
||||
fetch('/api/version')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.version) {
|
||||
document.getElementById('version-badge').textContent = 'v' + data.version;
|
||||
} else {
|
||||
document.getElementById('version-badge').textContent = 'v0.1.0';
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Failed to fetch version:', err);
|
||||
document.getElementById('version-badge').textContent = 'v0.1.0';
|
||||
});
|
||||
}
|
||||
|
||||
function clearCaptures() {
|
||||
if (!capturedData || capturedData.length === 0) {
|
||||
showToast('暂无抓包数据可清空');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm('确定要清空所有抓包信息吗?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
capturedData = [];
|
||||
selectedIndex = -1;
|
||||
renderCaptureList();
|
||||
|
||||
// 重置右侧详情面板
|
||||
const detailPanel = document.getElementById('detail-panel');
|
||||
detailPanel.innerHTML = `
|
||||
<div class="no-selection">
|
||||
<span class="icon">📡</span>
|
||||
<span>请从左侧选择一个抓包记录查看详情</span>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 向服务器发送清空请求
|
||||
fetch('/api/clear', { method: 'POST' })
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
showToast('已清空所有抓包信息');
|
||||
} else {
|
||||
showToast('清空失败: ' + (data.message || '未知错误'));
|
||||
}
|
||||
showToast('已清空所有抓包信息');
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Clear failed:', err);
|
||||
showToast('清空失败,请重试');
|
||||
});
|
||||
}
|
||||
|
||||
function setupSSE() {
|
||||
const eventSource = new EventSource('/api/events');
|
||||
|
||||
@ -495,20 +574,25 @@
|
||||
// 更新状态为已连接
|
||||
updateStatus();
|
||||
|
||||
// 检查是否有新数据(比较最后一个时间戳或数量)
|
||||
const hasNewData = !capturedData.length ||
|
||||
data.length > capturedData.length ||
|
||||
(data.length > 0 && capturedData.length > 0 &&
|
||||
data[data.length - 1].timestamp !== capturedData[capturedData.length - 1].timestamp);
|
||||
|
||||
if (hasNewData) {
|
||||
// 直接使用服务器返回的数据
|
||||
capturedData = data;
|
||||
renderCaptureList();
|
||||
|
||||
// 如果是新数据且当前没有选中,自动选中第一个
|
||||
// 如果当前没有选中且数据不为空,自动选中第一个
|
||||
if (selectedIndex === -1 && data.length > 0) {
|
||||
selectCapture(0);
|
||||
}
|
||||
|
||||
// 如果选中的索引超出了数据范围,重置选中状态
|
||||
if (selectedIndex >= data.length) {
|
||||
selectedIndex = -1;
|
||||
const detailPanel = document.getElementById('detail-panel');
|
||||
detailPanel.innerHTML = `
|
||||
<div class="no-selection">
|
||||
<span class="icon">📡</span>
|
||||
<span>请从左侧选择一个抓包记录查看详情</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to parse SSE data:', e);
|
||||
@ -524,6 +608,9 @@
|
||||
var origin = window.location.origin;
|
||||
document.getElementById('base-url').textContent = origin;
|
||||
|
||||
// 获取版本信息
|
||||
fetchVersion();
|
||||
|
||||
// 设置 SSE 连接
|
||||
setupSSE();
|
||||
});
|
||||
|
||||
16
src/index.js
16
src/index.js
@ -143,6 +143,22 @@ const startClient = () => {
|
||||
res.json(capturedData);
|
||||
});
|
||||
|
||||
app.get('/api/version', (req, res) => {
|
||||
try {
|
||||
const packageJson = require('../package.json');
|
||||
res.json({ version: packageJson.version });
|
||||
} catch (error) {
|
||||
console.error('Failed to read package.json:', error);
|
||||
res.json({ version: '0.1.0' });
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/api/clear', (req, res) => {
|
||||
capturedData = [];
|
||||
broadcastData();
|
||||
res.json({ success: true });
|
||||
});
|
||||
|
||||
app.get('/api/events', (req, res) => {
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user