← 返回博客 / 数据同步

数据同步

从有道云听获取最新歌单 → 自动同步到 CDN
使用说明
1 打开 yunting.youdao.com 并扫码登录
2 F12 打开开发者工具,切换到 Console / 控制台 标签
3 复制下方脚本,粘贴到控制台,按 Enter 执行
因为浏览器安全策略(CORS),必须在 yunting.youdao.com 页面上执行才能调用其 API。脚本会自动:调 API → 转格式 → 推送到 CDN。
同步脚本 (复制粘贴到 yunting 页面控制台)
// === 粘贴到 yunting.youdao.com 控制台执行 === (async () => { const SCF = 'https://1301799822-evm3jl87lp.ap-guangzhou.tencentscf.com'; const TOKEN = 'yunr9e7n6jr'; console.log('%c[Sync] 正在获取歌单...', 'color:#3b82f6;font-weight:bold'); // 1. Fetch API (same-origin, cookies auto-included) const resp = await fetch('/cloud/column/getAllArticleAndTextFileList?product=apollo&sortKey=alphabeticIncrease&'); const raw = await resp.json(); let data = null; if (raw.code === 200 && raw.data && Array.isArray(raw.data)) data = raw.data; else if (raw.code === 200 && raw.result && Array.isArray(raw.result)) data = raw.result; else if (Array.isArray(raw)) data = raw; if (!data) { console.error('[Sync] 无法解析数据:', raw); return alert('获取失败:数据结构未知,请查看控制台'); } // 2. Transform const folders = data.map(f => ({ name: f.name, key: f.key || f.columnKey || '', songs: (f.songs || f.articleList || []).map(s => ({ t: s.t || s.title || s.name || '', ak: s.ak || s.articleKey || '', ck: s.ck || s.columnKey || f.key || '', url: s.url || s.audioUrl || '', d: typeof s.d === 'number' ? s.d : (s.duration || 0), sz: typeof s.sz === 'number' ? s.sz : (s.size || 0), lrc: !!s.lrc || false })) })); const totalFolders = folders.length; const totalSongs = folders.reduce((s, f) => s + (f.songs ? f.songs.length : 0), 0); const content = '// Music data\n// ' + totalFolders + ' folders, ' + totalSongs + ' songs\n\nwindow.YUNTING_DATA = ' + JSON.stringify(folders) + ';\n// Compatibility: app.js expects window.MUSIC_DATA.folders\nwindow.MUSIC_DATA = { folders: window.YUNTING_DATA };\n'; const sizeKB = (new Blob([content]).size / 1024).toFixed(1); console.log('%c[Sync] %c' + totalFolders + ' 文件夹, ' + totalSongs + ' 首歌, ' + sizeKB + ' KB', 'color:#3b82f6;font-weight:bold', 'color:#52c41a'); // 3. Push to SCF console.log('%c[Sync] 正在推送到 CDN...', 'color:#3b82f6'); const pushResp = await fetch(SCF, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content, folders: totalFolders, songs: totalSongs, token: TOKEN }) }); const result = await pushResp.json(); if (result.ok) { console.log('%c[Sync] ✓ 同步成功!', 'color:#30d158;font-size:16px;font-weight:bold'); console.log('[Sync] CDN:', result.publicUrl); alert('✓ 同步成功!\n\n' + totalFolders + ' 个文件夹\n' + totalSongs + ' 首歌\n' + sizeKB + ' KB\n\n' + result.publicUrl); } else { console.error('[Sync] 失败:', result.error || result); alert('✗ 推送失败: ' + (result.error || 'unknown')); } })();