mirror of
https://github.com/Evil0ctal/WeChat-Channels-Video-File-Decryption.git
synced 2026-10-26 01:54:46 +08:00
552 lines
19 KiB
HTML
552 lines
19 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>WeChat Decrypt API - 接口文档</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica', 'Arial', sans-serif;
|
||
line-height: 1.6;
|
||
color: #333;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh;
|
||
padding: 20px;
|
||
}
|
||
|
||
.container {
|
||
max-width: 1200px;
|
||
margin: 0 auto;
|
||
background: white;
|
||
border-radius: 12px;
|
||
box-shadow: 0 20px 60px rgba(0,0,0,0.3);
|
||
overflow: hidden;
|
||
}
|
||
|
||
.header {
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
padding: 40px;
|
||
text-align: center;
|
||
}
|
||
|
||
.header h1 {
|
||
font-size: 2.5em;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.header .subtitle {
|
||
font-size: 1.2em;
|
||
opacity: 0.9;
|
||
}
|
||
|
||
.status-badge {
|
||
display: inline-block;
|
||
padding: 8px 16px;
|
||
background: rgba(255,255,255,0.2);
|
||
border-radius: 20px;
|
||
margin-top: 20px;
|
||
font-size: 0.9em;
|
||
}
|
||
|
||
.status-badge.online {
|
||
background: rgba(72,187,120,0.3);
|
||
}
|
||
|
||
.content {
|
||
padding: 40px;
|
||
}
|
||
|
||
.section {
|
||
margin-bottom: 40px;
|
||
}
|
||
|
||
.section h2 {
|
||
color: #667eea;
|
||
font-size: 1.8em;
|
||
margin-bottom: 20px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 2px solid #f0f0f0;
|
||
}
|
||
|
||
.section h3 {
|
||
color: #764ba2;
|
||
font-size: 1.3em;
|
||
margin-top: 30px;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.info-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||
gap: 20px;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.info-card {
|
||
background: #f8f9fa;
|
||
padding: 20px;
|
||
border-radius: 8px;
|
||
border-left: 4px solid #667eea;
|
||
}
|
||
|
||
.info-card .label {
|
||
font-weight: bold;
|
||
color: #666;
|
||
font-size: 0.9em;
|
||
margin-bottom: 5px;
|
||
}
|
||
|
||
.info-card .value {
|
||
font-size: 1.1em;
|
||
color: #333;
|
||
}
|
||
|
||
.endpoint {
|
||
background: #f8f9fa;
|
||
padding: 25px;
|
||
border-radius: 8px;
|
||
margin-bottom: 25px;
|
||
border-left: 4px solid #764ba2;
|
||
}
|
||
|
||
.endpoint-header {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.method {
|
||
display: inline-block;
|
||
padding: 6px 12px;
|
||
border-radius: 4px;
|
||
font-weight: bold;
|
||
font-size: 0.85em;
|
||
margin-right: 10px;
|
||
}
|
||
|
||
.method.get {
|
||
background: #48bb78;
|
||
color: white;
|
||
}
|
||
|
||
.method.post {
|
||
background: #4299e1;
|
||
color: white;
|
||
}
|
||
|
||
.endpoint-path {
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 1.1em;
|
||
color: #333;
|
||
}
|
||
|
||
.endpoint-desc {
|
||
color: #666;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.params, .response {
|
||
margin-top: 15px;
|
||
}
|
||
|
||
.params h4, .response h4 {
|
||
color: #764ba2;
|
||
font-size: 1em;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.param-item {
|
||
background: white;
|
||
padding: 12px;
|
||
border-radius: 4px;
|
||
margin-bottom: 8px;
|
||
border: 1px solid #e2e8f0;
|
||
}
|
||
|
||
.param-name {
|
||
font-family: 'Courier New', monospace;
|
||
font-weight: bold;
|
||
color: #667eea;
|
||
}
|
||
|
||
.param-required {
|
||
color: #e53e3e;
|
||
font-size: 0.85em;
|
||
margin-left: 5px;
|
||
}
|
||
|
||
.param-type {
|
||
color: #48bb78;
|
||
font-size: 0.9em;
|
||
margin-left: 5px;
|
||
}
|
||
|
||
.param-desc {
|
||
color: #666;
|
||
margin-top: 5px;
|
||
font-size: 0.95em;
|
||
}
|
||
|
||
.code-block {
|
||
background: #2d3748;
|
||
color: #e2e8f0;
|
||
padding: 20px;
|
||
border-radius: 6px;
|
||
overflow-x: auto;
|
||
font-family: 'Courier New', monospace;
|
||
font-size: 0.9em;
|
||
line-height: 1.5;
|
||
margin-top: 10px;
|
||
white-space: pre;
|
||
}
|
||
|
||
.code-block .comment {
|
||
color: #68d391;
|
||
}
|
||
|
||
.code-block .string {
|
||
color: #f6ad55;
|
||
}
|
||
|
||
.code-block .keyword {
|
||
color: #9f7aea;
|
||
}
|
||
|
||
.feature-list {
|
||
list-style: none;
|
||
padding: 0;
|
||
}
|
||
|
||
.feature-list li {
|
||
padding: 12px 0;
|
||
padding-left: 30px;
|
||
position: relative;
|
||
}
|
||
|
||
.feature-list li:before {
|
||
content: "✅";
|
||
position: absolute;
|
||
left: 0;
|
||
}
|
||
|
||
.footer {
|
||
background: #f8f9fa;
|
||
padding: 30px;
|
||
text-align: center;
|
||
color: #666;
|
||
}
|
||
|
||
.footer a {
|
||
color: #667eea;
|
||
text-decoration: none;
|
||
}
|
||
|
||
.footer a:hover {
|
||
text-decoration: underline;
|
||
}
|
||
|
||
.quick-links {
|
||
display: flex;
|
||
gap: 15px;
|
||
flex-wrap: wrap;
|
||
margin-top: 20px;
|
||
}
|
||
|
||
.btn {
|
||
display: inline-block;
|
||
padding: 10px 20px;
|
||
background: #667eea;
|
||
color: white;
|
||
text-decoration: none;
|
||
border-radius: 6px;
|
||
transition: background 0.3s;
|
||
}
|
||
|
||
.btn:hover {
|
||
background: #764ba2;
|
||
}
|
||
|
||
.btn-secondary {
|
||
background: #4299e1;
|
||
}
|
||
|
||
.btn-secondary:hover {
|
||
background: #3182ce;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
.header h1 {
|
||
font-size: 1.8em;
|
||
}
|
||
|
||
.content {
|
||
padding: 20px;
|
||
}
|
||
|
||
.info-grid {
|
||
grid-template-columns: 1fr;
|
||
}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<h1>🎬 WeChat Decrypt API</h1>
|
||
<div class="subtitle">基于 Playwright 浏览器自动化的 RPC 解密服务</div>
|
||
<div class="status-badge online" id="statusBadge">
|
||
🟢 服务运行中
|
||
</div>
|
||
</div>
|
||
|
||
<div class="content">
|
||
<!-- 服务信息 -->
|
||
<div class="section">
|
||
<h2>📊 服务信息</h2>
|
||
<div class="info-grid">
|
||
<div class="info-card">
|
||
<div class="label">服务名称</div>
|
||
<div class="value" id="serviceName">WeChat Decrypt API</div>
|
||
</div>
|
||
<div class="info-card">
|
||
<div class="label">版本</div>
|
||
<div class="value" id="version">2.0.0</div>
|
||
</div>
|
||
<div class="info-card">
|
||
<div class="label">引擎</div>
|
||
<div class="value" id="engine">Playwright + Chromium</div>
|
||
</div>
|
||
<div class="info-card">
|
||
<div class="label">WASM 状态</div>
|
||
<div class="value" id="wasmStatus">检查中...</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 特性 -->
|
||
<div class="section">
|
||
<h2>✨ 核心特性</h2>
|
||
<ul class="feature-list">
|
||
<li>100% 兼容微信官方 WASM 模块 (v1.2.46)</li>
|
||
<li>在真实 Chromium 浏览器中执行 Isaac64 算法</li>
|
||
<li>RPC 架构:Node.js ↔ Browser 通信</li>
|
||
<li>支持最大 500MB 视频文件</li>
|
||
<li>RESTful API 设计,易于集成</li>
|
||
<li>Docker 容器化部署</li>
|
||
<li>自动健康检查和监控</li>
|
||
</ul>
|
||
</div>
|
||
|
||
<!-- API 端点 -->
|
||
<div class="section">
|
||
<h2>🔌 API 端点</h2>
|
||
|
||
<!-- GET / -->
|
||
<div class="endpoint">
|
||
<div class="endpoint-header">
|
||
<span class="method get">GET</span>
|
||
<span class="endpoint-path">/</span>
|
||
</div>
|
||
<div class="endpoint-desc">获取服务信息和可用端点列表</div>
|
||
|
||
<div class="response">
|
||
<h4>响应示例:</h4>
|
||
<div class="code-block">{
|
||
<span class="string">"service"</span>: <span class="string">"WeChat Channels Video Decryption API"</span>,
|
||
<span class="string">"version"</span>: <span class="string">"2.0.0"</span>,
|
||
<span class="string">"engine"</span>: <span class="string">"Playwright + Chromium"</span>,
|
||
<span class="string">"endpoints"</span>: { ... }
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- GET /health -->
|
||
<div class="endpoint">
|
||
<div class="endpoint-header">
|
||
<span class="method get">GET</span>
|
||
<span class="endpoint-path">/health</span>
|
||
</div>
|
||
<div class="endpoint-desc">健康检查,返回服务和 WASM 模块状态</div>
|
||
|
||
<div class="response">
|
||
<h4>响应示例:</h4>
|
||
<div class="code-block">{
|
||
<span class="string">"status"</span>: <span class="string">"ok"</span>,
|
||
<span class="string">"wasm"</span>: {
|
||
<span class="string">"loaded"</span>: <span class="keyword">true</span>,
|
||
<span class="string">"timestamp"</span>: <span class="string">"2024-01-15T10:30:00.000Z"</span>
|
||
}
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- POST /api/keystream -->
|
||
<div class="endpoint">
|
||
<div class="endpoint-header">
|
||
<span class="method post">POST</span>
|
||
<span class="endpoint-path">/api/keystream</span>
|
||
</div>
|
||
<div class="endpoint-desc">生成 Isaac64 密钥流(128KB)</div>
|
||
|
||
<div class="params">
|
||
<h4>请求参数:</h4>
|
||
<div class="param-item">
|
||
<span class="param-name">decode_key</span>
|
||
<span class="param-required">(必需)</span>
|
||
<span class="param-type">string/number</span>
|
||
<div class="param-desc">解密密钥,从 API 响应的 $.data.object_desc.media[0].decode_key 获取</div>
|
||
</div>
|
||
<div class="param-item">
|
||
<span class="param-name">format</span>
|
||
<span class="param-type">string</span>
|
||
<div class="param-desc">输出格式:'hex'(默认)或 'base64'</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="code-block">curl -X POST http://localhost:3000/api/keystream \
|
||
-H <span class="string">"Content-Type: application/json"</span> \
|
||
-d <span class="string">'{"decode_key": "2136343393", "format": "hex"}'</span></div>
|
||
|
||
<div class="response">
|
||
<h4>响应示例:</h4>
|
||
<div class="code-block">{
|
||
<span class="string">"decode_key"</span>: <span class="string">"2136343393"</span>,
|
||
<span class="string">"keystream"</span>: <span class="string">"9c87e6946a410182..."</span>,
|
||
<span class="string">"format"</span>: <span class="string">"hex"</span>,
|
||
<span class="string">"size"</span>: 131072,
|
||
<span class="string">"duration_ms"</span>: 45
|
||
}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- POST /api/decrypt -->
|
||
<div class="endpoint">
|
||
<div class="endpoint-header">
|
||
<span class="method post">POST</span>
|
||
<span class="endpoint-path">/api/decrypt</span>
|
||
</div>
|
||
<div class="endpoint-desc">完整视频解密(前 128KB XOR 解密)</div>
|
||
|
||
<div class="params">
|
||
<h4>请求参数(multipart/form-data):</h4>
|
||
<div class="param-item">
|
||
<span class="param-name">decode_key</span>
|
||
<span class="param-required">(必需)</span>
|
||
<span class="param-type">string</span>
|
||
<div class="param-desc">解密密钥</div>
|
||
</div>
|
||
<div class="param-item">
|
||
<span class="param-name">video</span>
|
||
<span class="param-required">(必需)</span>
|
||
<span class="param-type">file</span>
|
||
<div class="param-desc">加密的 MP4 视频文件(最大 500MB)</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="code-block">curl -X POST http://localhost:3000/api/decrypt \
|
||
-F <span class="string">"decode_key=2136343393"</span> \
|
||
-F <span class="string">"video=@encrypted.mp4"</span> \
|
||
-o decrypted.mp4</div>
|
||
|
||
<div class="response">
|
||
<h4>响应:</h4>
|
||
<div class="code-block"><span class="comment"># 返回解密后的 MP4 视频文件(binary)</span>
|
||
Content-Type: video/mp4
|
||
Content-Disposition: attachment; filename=<span class="string">"decrypted_xxxxx.mp4"</span>
|
||
X-Decrypt-Duration: <span class="string">1295</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 使用示例 -->
|
||
<div class="section">
|
||
<h2>💡 使用示例</h2>
|
||
|
||
<h3>Python 示例</h3>
|
||
<div class="code-block"><span class="keyword">import</span> requests
|
||
|
||
<span class="comment"># 解密视频</span>
|
||
url = <span class="string">'http://localhost:3000/api/decrypt'</span>
|
||
files = {<span class="string">'video'</span>: open(<span class="string">'encrypted.mp4'</span>, <span class="string">'rb'</span>)}
|
||
data = {<span class="string">'decode_key'</span>: <span class="string">'2136343393'</span>}
|
||
|
||
response = requests.post(url, files=files, data=data)
|
||
|
||
<span class="keyword">if</span> response.status_code == 200:
|
||
<span class="keyword">with</span> open(<span class="string">'decrypted.mp4'</span>, <span class="string">'wb'</span>) <span class="keyword">as</span> f:
|
||
f.write(response.content)
|
||
print(<span class="string">'✅ 解密成功'</span>)</div>
|
||
|
||
<h3>JavaScript/Node.js 示例</h3>
|
||
<div class="code-block"><span class="keyword">const</span> FormData = require(<span class="string">'form-data'</span>);
|
||
<span class="keyword">const</span> fs = require(<span class="string">'fs'</span>);
|
||
<span class="keyword">const</span> axios = require(<span class="string">'axios'</span>);
|
||
|
||
<span class="keyword">async function</span> decryptVideo() {
|
||
<span class="keyword">const</span> form = <span class="keyword">new</span> FormData();
|
||
form.append(<span class="string">'decode_key'</span>, <span class="string">'2136343393'</span>);
|
||
form.append(<span class="string">'video'</span>, fs.createReadStream(<span class="string">'encrypted.mp4'</span>));
|
||
|
||
<span class="keyword">const</span> response = <span class="keyword">await</span> axios.post(
|
||
<span class="string">'http://localhost:3000/api/decrypt'</span>,
|
||
form,
|
||
{ headers: form.getHeaders(), responseType: <span class="string">'stream'</span> }
|
||
);
|
||
|
||
response.data.pipe(fs.createWriteStream(<span class="string">'decrypted.mp4'</span>));
|
||
}</div>
|
||
</div>
|
||
|
||
<!-- 快速链接 -->
|
||
<div class="section">
|
||
<h2>🔗 快速链接</h2>
|
||
<div class="quick-links">
|
||
<a href="/health" class="btn" target="_blank">健康检查</a>
|
||
<a href="https://github.com/Evil0ctal/WeChat-Channels-Video-File-Decryption" class="btn btn-secondary" target="_blank">GitHub 仓库</a>
|
||
<a href="https://evil0ctal.github.io/WeChat-Channels-Video-File-Decryption/" class="btn btn-secondary" target="_blank">在线工具</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="footer">
|
||
<p><strong>WeChat Decrypt API</strong> v2.0.0</p>
|
||
<p>Made with ❤️ by <a href="https://github.com/Evil0ctal" target="_blank">Evil0ctal</a></p>
|
||
<p>License: MIT | <a href="https://github.com/Evil0ctal/WeChat-Channels-Video-File-Decryption" target="_blank">View on GitHub</a></p>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// 获取服务状态
|
||
fetch('/health')
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
document.getElementById('serviceName').textContent = data.service || 'WeChat Decrypt API';
|
||
document.getElementById('version').textContent = data.version || '2.0.0';
|
||
document.getElementById('engine').textContent = data.engine || 'Playwright';
|
||
|
||
if (data.wasm && data.wasm.loaded) {
|
||
document.getElementById('wasmStatus').textContent = '✅ 已加载';
|
||
document.getElementById('statusBadge').textContent = '🟢 服务运行中';
|
||
} else {
|
||
document.getElementById('wasmStatus').textContent = '❌ 未加载';
|
||
document.getElementById('statusBadge').textContent = '🔴 WASM 未就绪';
|
||
document.getElementById('statusBadge').classList.remove('online');
|
||
}
|
||
})
|
||
.catch(err => {
|
||
console.error('Failed to fetch service status:', err);
|
||
document.getElementById('wasmStatus').textContent = '❌ 检查失败';
|
||
document.getElementById('statusBadge').textContent = '🔴 服务不可用';
|
||
document.getElementById('statusBadge').classList.remove('online');
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|