// ==UserScript== // @name Kdocs batch download 金山文档批量下载 // @namespace http://tampermonkey.net/ // @version 2024-02-23 // @description Download a directory in kdocs. 金山文档批量下载。 // @author yusanshi // @match https://www.kdocs.cn/team/* // @icon https://www.google.com/s2/favicons?sz=64&domain=kdocs.cn // @grant none // @require https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js // @license MIT // @downloadURL none // ==/UserScript== const teamID = window.location.pathname.split('/')[2]; const zip = new JSZip(); async function dfs(initialState, paths) { const files = initialState.file.list.map((e) => ({ name: e.fname, id: e.id, type: e.ftype, })); for (const file of files) { await new Promise((r) => setTimeout(() => r(), 500)); if (['file', 'sharefile'].includes(file.type)) { let url; try { url = ( await fetch( `https://www.kdocs.cn/api/v3/office/file/${file.id}/download` ).then((response) => { if (!response.ok) { throw new Error(response.status); } return response.json(); }) ).url; } catch (error) { console.error( `Failed to download ${file.name} (${error.message}), skipped` ); continue; } const filepath = [...paths, file.name].join('/'); console.log(`Download ${filepath} at ${url}`); const blob = await fetch(url).then((response) => response.blob()); zip.file(filepath, blob); } else if (['folder', 'linkfolder'].includes(file.type)) { await new Promise((r) => setTimeout(() => r(), 1000)); const dom = await fetch(`https://www.kdocs.cn/team/${teamID}/${file.id}`) .then((response) => response.text()) .then((data) => new DOMParser().parseFromString(data, 'text/html')); // TODO how to use the `window` object? const scriptContent = dom.body.querySelectorAll('script')[2].innerText; const newInitialState = JSON.parse(scriptContent.slice(25, -122)); // TODO await dfs(newInitialState, [...paths, file.name]); } else { console.error(`Unknown file type ${file.type}`); } } } window.downloadDirectory = async function () { document.querySelector('#downloadDirectory').innerText = 'Downloading (see console for details)'; await dfs(__INITIAL_STATE__, []); zip.generateAsync({ type: 'base64' }).then(function (content) { window.location.href = 'data:application/zip;base64,' + content; }); document.querySelector('#downloadDirectory').innerText = 'Download finished'; }; (function () { 'use strict'; document.body.insertAdjacentHTML( 'beforeend', `
` ); })();