发一个稻壳巴巴下载器源码

@Ta 12小时前发布,12小时前修改 185点击
如题,下载出来的是xdf文件,需要使用稻壳阅读器打开,转为pdf即可
<?php
/**
 * 稻壳阅读器辅助工具 - 单文件PHP版
 * 道客巴巴文档下载链接生成器
 * 
 * 内置Token: cc60gZ3OkRfwIVyDdiZ-NBoXhoL9YtYc49sv0VrpSZfci5IX1LRK0bPdp4_a5kMxYVF6xW8u0g61m3Nj5oXHw99mgWaOChi4HiaPfPHJmbwbyqJ8Lu8xBON8Uca4EIHNIeGVsScnUkHVjU7QXiE
 */

// ==================== 配置 ====================
error_reporting(0);
session_start();
header('Content-Type: text/html; charset=utf-8');

// 内置Token
define('DEFAULT_TOKEN', 'cc60gZ3OkRfwIVyDdiZ-NBoXhoL9YtYc49sv0VrpSZfci5IX1LRK0bPdp4_a5kMxYVF6xW8u0g61m3Nj5oXHw99mgWaOChi4HiaPfPHJmbwbyqJ8Lu8xBON8Uca4EIHNIeGVsScnUkHVjU7QXiE');

// ==================== API接口 ====================
if (isset($_GET['api'])) {
    header('Content-Type: application/json; charset=utf-8');

    $docId = $_GET['docId'] ?? '';
    $token = $_GET['token'] ?? DEFAULT_TOKEN;

    // 提取docId
    if (preg_match('/p-(\d+)/', $docId, $matches)) {
        $docId = $matches[1];
    }

    if (empty($docId)) {
        echo json_encode(['success' => false, 'error' => '无效的文档ID']);
        exit;
    }

    // 构建API URL
    $apiUrl = 'https://www.doc88.com/doc.php?act=xdfdownload&p_code=' . $docId . '&token=' . urlencode($token);

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $apiUrl,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_HTTPHEADER => [
            'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept: application/json, text/javascript, */*; q=0.01',
            'X-Requested-With: XMLHttpRequest',
            'Referer: https://www.doc88.com/p-' . $docId . '.html'
        ]
    ]);

    $response = curl_exec($ch);
    $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($response, true);

    // result=0 表示成功
    if ($data && isset($data['result']) && $data['result'] == 0 && !empty($data['doclink'])) {
        $doclink = $data['doclink'];
        
        // 解析下载链接
        if (preg_match('/dl\.doc88\.com\/download\/([a-f0-9]{16})\/(.+)\.xdf/i', $doclink, $matches)) {
            $hash = $matches[1];
            $filename = $matches[2] . '.xdf';
            $downloadUrl = 'https://dl.doc88.com/download/' . $hash . '/' . $filename;
            
            echo json_encode([
                'success' => true,
                'docId' => $docId,
                'download' => [
                    'hash' => $hash,
                    'filename' => $filename,
                    'url' => $downloadUrl,
                    'size' => $data['filesize'] ?? ''
                ]
            ], JSON_UNESCAPED_UNICODE);
        } else {
            echo json_encode([
                'success' => true,
                'docId' => $docId,
                'download' => [
                    'url' => $doclink,
                    'filename' => basename($doclink),
                    'raw' => $doclink
                ]
            ], JSON_UNESCAPED_UNICODE);
        }
    } else {
        echo json_encode([
            'success' => false,
            'error' => $data['doclink'] ?? $data['message'] ?? '获取失败',
            'docId' => $docId,
            'raw' => $data
        ], JSON_UNESCAPED_UNICODE);
    }
    exit;
}

// ==================== 直接下载接口 ====================
if (isset($_GET['download'])) {
    $docId = $_GET['download'];
    $token = $_GET['token'] ?? DEFAULT_TOKEN;

    // 提取docId
    if (preg_match('/p-(\d+)/', $docId, $matches)) {
        $docId = $matches[1];
    }

    // 调用API获取下载链接
    $apiUrl = 'https://www.doc88.com/doc.php?act=xdfdownload&p_code=' . $docId . '&token=' . urlencode($token);

    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $apiUrl,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_FOLLOWLOCATION => true,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_HTTPHEADER => [
            'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'Accept: application/json',
            'X-Requested-With: XMLHttpRequest',
            'Referer: https://www.doc88.com/p-' . $docId . '.html'
        ]
    ]);

    $response = curl_exec($ch);
    curl_close($ch);

    $data = json_decode($response, true);

    // result=0 表示成功
    if ($data && isset($data['result']) && $data['result'] == 0 && !empty($data['doclink'])) {
        // 重定向到下载链接
        header('Location: ' . $data['doclink']);
        exit;
    } else {
        echo '获取下载链接失败: ' . ($data['doclink'] ?? $data['message'] ?? '未知错误');
        exit;
    }
}

// ==================== HTML页面 ====================
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>稻壳阅读器辅助工具 - PHP版</title>
    <style>
        * { margin: 0; padding: 0; box-sizing: border-box; }
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Microsoft YaHei", sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }
        .container { max-width: 700px; margin: 0 auto; }
        .header { text-align: center; color: white; margin-bottom: 30px; }
        .header h1 { font-size: 2em; margin-bottom: 8px; }
        .header p { opacity: 0.9; }
        .card {
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 60px rgba(0,0,0,0.3);
            padding: 30px;
            margin-bottom: 20px;
        }
        .card h2 { margin-bottom: 15px; color: #333; }
        .input-group { margin-bottom: 18px; }
        .input-group label {
            display: block;
            margin-bottom: 6px;
            font-weight: 600;
            color: #333;
        }
        .input-group input {
            width: 100%;
            padding: 14px;
            border: 2px solid #e0e0e0;
            border-radius: 10px;
            font-size: 15px;
            font-family: inherit;
            transition: border-color 0.3s;
        }
        .input-group input:focus {
            outline: none;
            border-color: #667eea;
        }
        .input-group input::placeholder { color: #999; }
        .input-hint { font-size: 12px; color: #666; margin-top: 4px; line-height: 1.6; }
        .btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            padding: 14px 28px;
            border: none;
            border-radius: 10px;
            font-size: 15px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
        }
        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            width: 100%;
        }
        .btn-primary:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(102, 126, 234, 0.4); }
        .btn-success {
            background: linear-gradient(135deg, #27ae60 0%, #2ecc71 100%);
            color: white;
            text-decoration: none;
            font-size: 18px;
            padding: 20px 50px;
        }
        .btn-success:hover { transform: translateY(-3px); box-shadow: 0 15px 40px rgba(39, 174, 96, 0.4); }
        .btn-group { display: flex; gap: 10px; flex-wrap: wrap; }
        .result-box { margin-top: 20px; padding: 20px; border-radius: 10px; display: none; }
        .result-box.success { background: #d4edda; border: 1px solid #c3e6cb; color: #155724; }
        .result-box.error { background: #f8d7da; border: 1px solid #f5c6cb; color: #721c24; }
        .result-box.loading { background: #cce5ff; border: 1px solid #b8daff; color: #004085; text-align: center; }
        .result-box.show { display: block; }
        .download-card {
            background: white;
            border: 3px solid #27ae60;
            border-radius: 15px;
            padding: 40px;
            text-align: center;
            margin: 20px 0;
            transition: all 0.3s;
        }
        .download-card:hover { transform: translateY(-5px); box-shadow: 0 15px 40px rgba(39, 174, 96, 0.3); }
        .download-card .icon { font-size: 70px; margin-bottom: 15px; }
        .download-card .title { font-size: 24px; font-weight: 600; color: #27ae60; margin-bottom: 10px; }
        .download-card .filename { font-size: 16px; color: #666; margin-bottom: 25px; word-break: break-all; padding: 0 20px; }
        .doc-info { background: #f8f9fa; border-radius: 8px; padding: 15px; margin-top: 15px; }
        .doc-info .row { display: flex; padding: 8px 0; border-bottom: 1px solid #eee; }
        .doc-info .row:last-child { border-bottom: none; }
        .doc-info .label { width: 80px; font-weight: 600; color: #666; flex-shrink: 0; }
        .doc-info .value { flex: 1; color: #333; word-break: break-all; font-size: 14px; }
        .info-box { background: #e7f3ff; border-radius: 10px; padding: 15px; margin: 15px 0; }
        .info-box h4 { color: #333; margin-bottom: 10px; }
        .info-box ol { margin-left: 20px; color: #555; line-height: 1.8; }
        .note { background: #fff3cd; border: 1px solid #ffc107; border-radius: 8px; padding: 12px; margin-top: 15px; font-size: 13px; color: #856404; }
        .api-debug { background: #2c3e50; color: #ecf0f1; border-radius: 8px; padding: 15px; margin: 10px 0; }
        .api-debug pre { font-size: 12px; overflow-x: auto; white-space: pre-wrap; word-break: break-all; }
        .spinner {
            width: 40px; height: 40px;
            border: 4px solid rgba(255,255,255,0.3);
            border-top-color: white;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin: 0 auto 15px;
        }
        @keyframes spin { to { transform: rotate(360deg); } }
        .sample-btn {
            background: #f39c12;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 13px;
            margin-left: 10px;
        }
        .sample-btn:hover { background: #e67e22; }
        .direct-download {
            background: linear-gradient(135deg, #3498db 0%, #2980b9 100%);
            color: white;
            padding: 12px 24px;
            border-radius: 8px;
            text-decoration: none;
            display: inline-block;
            margin-top: 15px;
            font-size: 14px;
        }
        .direct-download:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(52, 152, 219, 0.4); }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>📥 稻壳阅读器辅助工具</h1>
            <p>道客巴巴文档下载链接生成器 · 内置Token</p>
        </div>

        <div class="card">
            <h2>📎 输入文档链接</h2>
            <div class="input-group">
                <label for="docUrl">道客巴巴文档链接</label>
                <div style="display:flex;gap:10px;">
                    <input type="text" id="docUrl" placeholder="例如: https://www.doc88.com/p-2651690899469.html" style="flex:1;">
                    <button class="sample-btn" onclick="loadSample()">加载示例</button>
                </div>
                <div class="input-hint">支持完整链接或纯ID,如: p-2651690899469 或 2651690899469</div>
            </div>
            <button class="btn btn-primary" onclick="getDownloadLink()">
                🔍 获取下载链接
            </button>

            <div id="resultBox" class="result-box"></div>
        </div>

        <div class="card">
            <div class="info-box">
                <h4>💡 使用说明</h4>
                <ol>
                    <li>输入文档链接,点击"获取下载链接"</li>
                    <li>Token已内置,直接使用</li>
                    <li>点击"直接下载"按钮下载文件</li>
                </ol>
            </div>
            <div class="note">
                <strong>⚠️ 注意:</strong> Token可能有过期时间,如果下载失败可能需要更新Token
            </div>
        </div>
    </div>

    <script>
        // 示例数据
        const samples = [
            { url: 'https://www.doc88.com/p-2651690899469.html', name: '示例文档1' },
            { url: 'https://www.doc88.com/p-9116601893972.html', name: '示例文档2' },
            { url: 'https://www.doc88.com/p-2148414045355.html', name: '示例文档3' }
        ];
        let sampleIndex = 0;

        function loadSample() {
            const sample = samples[sampleIndex % samples.length];
            document.getElementById('docUrl').value = sample.url;
            sampleIndex++;
        }

        function showResult(html, type) {
            const box = document.getElementById('resultBox');
            box.className = 'result-box ' + type + ' show';
            box.innerHTML = html;
        }

        function showLoading(msg) {
            showResult('<div class="spinner"></div><div>' + msg + '</div>', 'loading');
        }

        async function getDownloadLink() {
            const docUrl = document.getElementById('docUrl').value.trim();

            let docId = '';
            const match = docUrl.match(/doc88\.com\/p-(\d+)/);
            if (match) docId = match[1];
            else {
                const simpleMatch = docUrl.match(/p-(\d+)/);
                if (simpleMatch) docId = simpleMatch[1];
                else if (/^\d+$/.test(docUrl)) docId = docUrl;
            }

            if (!docId) {
                showResult('请输入有效的文档链接', 'error');
                return;
            }

            showLoading('正在获取下载链接...');

            try {
                const response = await fetch('?api=get_download&docId=' + encodeURIComponent(docId));
                const data = await response.json();

                if (data.success && data.download) {
                    displayDownloadResult(data.download, docId);
                } else {
                    displayError(data, docId);
                }
            } catch (err) {
                showResult('请求失败: ' + err.message, 'error');
            }
        }

        function displayDownloadResult(download, docId) {
            const filename = download.filename || 'document_' + docId.slice(-8);
            const downloadUrl = download.url || download.raw;
            
            // 生成直接下载链接
            const directUrl = '?download=' + docId;

            const html = '<div class="download-card">' +
                '<div class="icon">✅</div>' +
                '<div class="title">下载链接获取成功!</div>' +
                '<div class="filename">' + filename + '</div>' +
                '<div>' +
                '<a href="' + downloadUrl + '" class="btn btn-success" target="_blank" download>📥 直接下载</a>' +
                '</div>' +
                '<a href="' + directUrl + '" class="direct-download">🔄 代理下载 (备用)</a>' +
                '</div>' +
                '<div class="doc-info">' +
                '<div class="row"><span class="label">文件名</span><span class="value">' + filename + '</span></div>' +
                '<div class="row"><span class="label">Hash</span><span class="value">' + (download.hash || 'N/A') + '</span></div>' +
                '<div class="row"><span class="label">文档ID</span><span class="value">' + docId + '</span></div>' +
                (download.size ? '<div class="row"><span class="label">大小</span><span class="value">' + formatSize(download.size) + '</span></div>' : '') +
                '</div>' +
                '<div style="margin-top:15px;text-align:center;"><button class="btn btn-secondary" onclick="copyToClipboard(\'' + downloadUrl + '\')">📋 复制下载链接</button></div>';

            showResult(html, 'success');
        }

        function displayError(data, docId) {
            const html = '<div style="margin-bottom:15px;"><h3>❌ 获取失败</h3><p>' + (data.error || '未知错误') + '</p></div>' +
                '<div class="api-debug"><strong>API响应:</strong><pre>' + JSON.stringify(data, null, 2) + '</pre></div>' +
                '<div class="note"><strong>可能原因:</strong> Token过期、文档需VIP权限、或文档不存在</div>';
            showResult(html, 'error');
        }

        function formatSize(bytes) {
            if (!bytes) return 'N/A';
            const b = parseInt(bytes);
            if (b < 1024) return b + ' B';
            if (b < 1024 * 1024) return (b / 1024).toFixed(1) + ' KB';
            return (b / 1024 / 1024).toFixed(1) + ' MB';
        }

        function copyToClipboard(text) {
            navigator.clipboard.writeText(text).then(() => alert('下载链接已复制!')).catch(() => {
                const ta = document.createElement('textarea');
                ta.value = text;
                document.body.appendChild(ta);
                ta.select();
                document.execCommand('copy');
                document.body.removeChild(ta);
                alert('下载链接已复制!');
            });
        }

        document.getElementById('docUrl')?.addEventListener('keypress', e => { if (e.key === 'Enter') getDownloadLink(); });
    </script>
</body>
</html>

回复列表(2|隐藏机器人聊天)
添加新回复
回复需要登录