From 3afb38c2b78be83de1fbaea6a5c1959f98cb6c7f Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 24 Nov 2019 20:17:52 +0800 Subject: [PATCH 01/10] Introduce aria2 dependency --- web/package.json | 1 + web/yarn.lock | 25 +++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/web/package.json b/web/package.json index 1ca0b622..eb75fb31 100644 --- a/web/package.json +++ b/web/package.json @@ -7,6 +7,7 @@ "lint": "vue-cli-service lint" }, "dependencies": { + "aria2": "^4.1.0", "core-js": "^2.6.5", "date-fns": "^2.4.1", "inline-resource": "^0.1.7", diff --git a/web/yarn.lock b/web/yarn.lock index c4af7703..cee4e420 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -1345,6 +1345,15 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +aria2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/aria2/-/aria2-4.1.0.tgz#d9511e2e944e40549b0996ec6b345c4ce0ecd284" + integrity sha512-8BFq3xtK/uLEji4p+7nzMcaK1jrmu8ykAXrRcsxGv8U6gg48gc5+jJ5zzg2eN2p3GEr1rznHNNQ5YIGGvZHvIg== + dependencies: + commander "^3.0.1" + node-fetch "^2.6.0" + ws "^7.1.2" + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -1436,7 +1445,7 @@ async-each@^1.0.1: resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== -async-limiter@~1.0.0: +async-limiter@^1.0.0, async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== @@ -2257,6 +2266,11 @@ commander@^2.18.0, commander@^2.20.0: resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.1.tgz#3863ce3ca92d0831dcf2a102f5fb4b5926afd0f9" integrity sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg== +commander@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" + integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== + commander@~2.19.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -5830,7 +5844,7 @@ no-case@^2.2.0: dependencies: lower-case "^1.1.1" -node-fetch@^2.2.0: +node-fetch@^2.2.0, node-fetch@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== @@ -9093,6 +9107,13 @@ ws@^6.0.0, ws@^6.2.1: dependencies: async-limiter "~1.0.0" +ws@^7.1.2: + version "7.2.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.0.tgz#422eda8c02a4b5dba7744ba66eebbd84bcef0ec7" + integrity sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg== + dependencies: + async-limiter "^1.0.0" + xdg-basedir@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-2.0.0.tgz#edbc903cc385fc04523d966a335504b5504d1bd2" From 7baa4ce116aafbf20deb4f4ff00d840d9388e820 Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 24 Nov 2019 20:18:44 +0800 Subject: [PATCH 02/10] Add aria2 support object --- web/src/aria2.js | 92 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 web/src/aria2.js diff --git a/web/src/aria2.js b/web/src/aria2.js new file mode 100644 index 00000000..6f88b18e --- /dev/null +++ b/web/src/aria2.js @@ -0,0 +1,92 @@ +// a simple module provides aria2 supports + +import Aria2 from 'aria2' + +const KEY_ARIA2_RPC_HOST = 'ARIA2_RPC_HOST' +const KEY_ARIA2_RPC_PORT = 'ARIA2_RPC_PORT' +const KEY_ARIA2_RPC_PATH = 'ARIA2_RPC_PATH' +const KEY_ARIA2_RPC_TOKEN = 'ARIA2_RPC_TOKEN' +const KEY_ARIA2_DOWNLOAD_PATH = 'ARIA2_DOWNLOAD_PATH' + +function getStringFromLocalStorage(key, defaultValue) { + return localStorage.getItem(key) || defaultValue +} + +function setStringToLocalStorage(key, value) { + return localStorage.setItem(key, value) +} + +const aria2Support = { + rawInstance: null, + getRpcHost: function() { + return getStringFromLocalStorage(KEY_ARIA2_RPC_HOST) + }, + setRpcHost: function(host) { + return setStringToLocalStorage(KEY_ARIA2_RPC_HOST, host) + }, + getRpcPort: function() { + let port = getStringFromLocalStorage(KEY_ARIA2_RPC_PORT) + if (!port) { + port = 6800 + } + return port + }, + setRpcPort: function(port) { + if (Number.isNaN(Number(port))) { + return false + } + + return setStringToLocalStorage(KEY_ARIA2_RPC_PORT, port) + }, + getRpcPath: function() { + return getStringFromLocalStorage(KEY_ARIA2_RPC_PATH, '/jsonrpc') + }, + setRpcPath: function(path) { + return setStringToLocalStorage(KEY_ARIA2_RPC_PATH, path) + }, + getRpcToken: function() { + return getStringFromLocalStorage(KEY_ARIA2_RPC_TOKEN) + }, + setRpcToken: function(token) { + return setStringToLocalStorage(KEY_ARIA2_RPC_TOKEN, token) + }, + getDownloadPath: function() { + return getStringFromLocalStorage(KEY_ARIA2_DOWNLOAD_PATH) + }, + setDownloadPath: function(path) { + return setStringToLocalStorage(KEY_ARIA2_DOWNLOAD_PATH, path) + }, + prepare: function() { + if (this.rawInstance) { + return + } + + const options = { + host: this.getRpcHost(), + port: this.getRpcPort(), + secure: false, + secret: this.getRpcToken(), + path: this.getRpcPath() + } + this.aria2 = new Aria2(options) + }, + test: async function() { + if (!this.rawInstance) { + this.prepare() + } + + return await this.aria2.call('getVersion') + }, + addDownload: async function(url, downloadPath) { + if (!this.rawInstance) { + this.prepare() + } + const option = { + dir: downloadPath + } + + return await this.aria2.call('addUri', [url], option) + } +} + +export default aria2Support From 1299d91fd4eabc160c28f07dafbfabea220dc334 Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 24 Nov 2019 20:21:35 +0800 Subject: [PATCH 03/10] Supports downloading with aria2 --- web/src/components/Aria2DownloadDialog.vue | 276 +++++++++++++++++++++ web/src/components/Aria2SettingsDialog.vue | 148 +++++++++++ web/src/components/FileViewer.vue | 22 +- 3 files changed, 443 insertions(+), 3 deletions(-) create mode 100644 web/src/components/Aria2DownloadDialog.vue create mode 100644 web/src/components/Aria2SettingsDialog.vue diff --git a/web/src/components/Aria2DownloadDialog.vue b/web/src/components/Aria2DownloadDialog.vue new file mode 100644 index 00000000..fd6cee08 --- /dev/null +++ b/web/src/components/Aria2DownloadDialog.vue @@ -0,0 +1,276 @@ + + + diff --git a/web/src/components/Aria2SettingsDialog.vue b/web/src/components/Aria2SettingsDialog.vue new file mode 100644 index 00000000..9f047c53 --- /dev/null +++ b/web/src/components/Aria2SettingsDialog.vue @@ -0,0 +1,148 @@ + + + diff --git a/web/src/components/FileViewer.vue b/web/src/components/FileViewer.vue index 15b7acbe..3ab5c552 100644 --- a/web/src/components/FileViewer.vue +++ b/web/src/components/FileViewer.vue @@ -19,13 +19,16 @@ :uploadUrl="uploadUrl" @uploaded="uploadComplete" /> - - + + + + @@ -85,6 +88,8 @@ import api from '../api' import ImageViewer from 'viewerjs' import 'viewerjs/dist/viewer.css' import FileUploadDialog from './FileUploadDialog' +import Aria2DownloadDialog from './Aria2DownloadDialog' +import Aria2SettingsDialog from './Aria2SettingsDialog' const SUPPORTED_TYPES = { 'application/epub+zip': 'epub', @@ -153,6 +158,7 @@ export default { class: 'hidden-sm-and-down' } ], + rootId: '', renderStart: null, uploadEnabled: window.props.upload, showUploadDialog: false @@ -307,6 +313,10 @@ export default { } }, created() { + this.rootId = this.$route.query.rootId + if (!this.rootId) { + this.rootId = window.props.default_root_id + } this.handlePath(this.path, this.$route.query) }, beforeRouteUpdate(to, from, next) { @@ -320,7 +330,9 @@ export default { } }, components: { - FileUploadDialog + FileUploadDialog, + Aria2DownloadDialog, + Aria2SettingsDialog } } @@ -357,4 +369,8 @@ export default { text-overflow: ellipsis; white-space: nowrap; } + +#actions > button { + margin-right: 10px; +} From 98265cf6a4ffa53b7228260b803f596074145926 Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 24 Nov 2019 20:39:31 +0800 Subject: [PATCH 04/10] Add language resources --- web/src/locales/en.js | 26 +++++++++++++++++++++++++- web/src/locales/zh-CN.js | 25 ++++++++++++++++++++++++- web/src/locales/zh-TW.js | 25 ++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/web/src/locales/en.js b/web/src/locales/en.js index 23807bd3..705bcae1 100644 --- a/web/src/locales/en.js +++ b/web/src/locales/en.js @@ -4,6 +4,9 @@ export default { fileSize: 'File Size', mainDrive: 'Main Drive', search: 'Search', + save: 'Save', + close: 'Close', + start: 'Start', fileUpload: 'File Upload', urlUpload: 'Upload from url', upload: 'Upload', @@ -11,5 +14,26 @@ export default { uploading: 'Uploading...', serverProcessing: 'Server is processing the file now', bigFileUploadWarning: - "Due to CloudFlare Workers' limitation, uploading bigfiles may randomly failed." + "Due to CloudFlare Workers' limitation, uploading bigfiles may randomly failed.", + aria2Download: 'Download with Aria2', + aria2DownloadRecursive: 'Recursive download subfolders', + aria2FetchingFiles: + 'Fetching files, remaining {remainingFolderCount} folders', + aria2DownloadStats: + 'Will download {fileCount} files(in {folderCount} folders), {totalDownloadSize} in total', + aria2DownloadProgress: + 'Adding download tasks, remaining {remainingFileCount} files', + aria2DownloadSuccess: 'All files added', + aria2DownloadFailed: 'Fail adding download tasks, reason: {failReason}', + aria2FetchFileFailed: 'Fail fetching files, reason: {failReason}', + aria2RPCSettings: 'Aria2 RPC Settings', + aria2RPCHost: 'Host', + aria2RPCPort: 'Port', + aria2RPCPath: 'Path', + aria2RPCToken: 'Token', + aria2RPCDownloadPath: 'Download Path', + aria2TestConnection: 'Test Connection', + aria2Testing: 'Testing', + aria2TestFailed: 'Connect failed, reason: {reason}', + aria2TestSucceed: 'Connect succeed, version: {version}' } diff --git a/web/src/locales/zh-CN.js b/web/src/locales/zh-CN.js index 3b2fabc9..706885ef 100644 --- a/web/src/locales/zh-CN.js +++ b/web/src/locales/zh-CN.js @@ -6,6 +6,9 @@ export default { fileSize: '文件大小', mainDrive: '主要硬盘', search: '搜寻', + save: '保存', + close: '关闭', + start: '开始', fileUpload: '文件上传', urlUpload: '从网址上传', upload: '上传', @@ -14,5 +17,25 @@ export default { serverProcessing: '服务器正在处里文件', bigFileUploadWarning: '由于 CloudFlare Workers 的限制,上传大档案可能会随机失败', - $vuetify + $vuetify, + aria2Download: '使用 Aria2 下载', + aria2DownloadRecursive: '包含子文件夹', + aria2FetchingFiles: + '正在获取文件,还剩 {remainingFolderCount} 个文件夹待获取', + aria2DownloadStats: + '将会下载 {folderCount} 个文件夹中的 {fileCount} 个文件,总计大小 {totalDownloadSize}', + aria2DownloadProgress: '正在添加下载任务,还剩 {remainingFileCount} 个文件', + aria2DownloadSuccess: '已添加所有文件下载', + aria2DownloadFailed: '添加下载任务失败,原因:{failReason}', + aria2FetchFileFailed: '获取文件列表失败,原因:{failReason}', + aria2RPCSettings: 'Aria2 RPC 配置', + aria2RPCHost: '主机', + aria2RPCPort: '端口', + aria2RPCPath: '路径', + aria2RPCToken: '密码', + aria2RPCDownloadPath: '下载路径', + aria2TestConnection: '测试连接', + aria2Testing: '正在尝试连接', + aria2TestFailed: '连接失败,原因:{reason}', + aria2TestSucceed: '连接成功,Aria2 版本:{version}' } diff --git a/web/src/locales/zh-TW.js b/web/src/locales/zh-TW.js index 4fc73ee1..73cb4cea 100644 --- a/web/src/locales/zh-TW.js +++ b/web/src/locales/zh-TW.js @@ -6,6 +6,9 @@ export default { fileSize: '檔案大小', mainDrive: '主要硬碟', search: '搜尋', + save: '保存', + close: '關閉', + start: '開始', fileUpload: '檔案上傳', urlUpload: '從網址上傳', upload: '上傳', @@ -14,5 +17,25 @@ export default { serverProcessing: '伺服器正在處理檔案', bigFileUploadWarning: '由於 CloudFlare Workers 的限制,上傳大檔案可能會隨機失敗', - $vuetify + $vuetify, + aria2Download: '使用 Aria2 下載', + aria2DownloadRecursive: '包含子檔案夾', + aria2FetchingFiles: + '正在獲取檔案,還剩 {remainingFolderCount} 個檔案夾待獲取', + aria2DownloadStats: + '將會下載 {folderCount} 個檔案夾中的 {fileCount} 個檔案,總計大小 {totalDownloadSize}', + aria2DownloadProgress: '正在添加下載任務,還剩 {remainingFileCount} 個檔案', + aria2DownloadSuccess: '已添加所有檔案下載', + aria2DownloadFailed: '添加下載任務失敗,原因:{failReason}', + aria2FetchFileFailed: '獲取檔案列表失敗,原因:{failReason}', + aria2RPCSettings: 'Aria2 RPC 配置', + aria2RPCHost: '主機', + aria2RPCPort: '通訊埠', + aria2RPCPath: '路徑', + aria2RPCToken: '密碼', + aria2RPCDownloadPath: '下載路徑', + aria2TestConnection: '測試連接', + aria2Testing: '正在嘗試連接', + aria2TestFailed: '連接失敗,原因:{reason}', + aria2TestSucceed: '連接成功,Aria2 版本:{version}' } From 383d634385647496c490dcb565323446a76b5c6e Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 24 Nov 2019 21:04:32 +0800 Subject: [PATCH 05/10] Add documentation --- README.md | 16 ++++++++++++++++ README.zh.md | 16 ++++++++++++++++ README.zhtw.md | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/README.md b/README.md index fecf3d36..052354c0 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ - No directory-level password protection(.password) - Support Http Basic Auth - Support multiple drives(personal, team) without changing server's code +- Support Aria2 download ## Usage @@ -37,3 +38,18 @@ Go [https://gdindex-code-builder.glitch.me/](https://gdindex-code-builder.glitch 5. Copy the content of [worker/dist/worker.js](worker/dist/worker.js) to CloudFlare Workers. 6. Fill `refresh_token`, `root_folder_id` and other options on the top of the script. 7. Deploy! + +### Enabling download with Aria2 + +1. Add config `download_aria2: true` to your `worker.js`: + ``` + default_root_id: '...', + client_id: '...', + client_secret: '...', + refresh_token: '...', + ... + download_aria2: true + ``` +2. Redeploy, now you should see "Download with Aria2" and "Aria2 RPC Settings" beyond file list +3. Fill your aria2 connection info in "Aria2 RPC Settings" +4. Go to where you want to download and click "Download with aria2", which will add downloads for you! diff --git a/README.zh.md b/README.zh.md index 314e8da6..0fcd06ad 100644 --- a/README.zh.md +++ b/README.zh.md @@ -17,6 +17,7 @@ - 不支援目录加密(.password) - 支援 Http Basic Auth - 支援多云端硬盘(个人、团队),不需要额外改程序设定 +- 支持导出 Aria2 下载 ## 使用教学 @@ -33,3 +34,18 @@ 5. 复制 [worker/dist/worker.js](worker/dist/worker.js) 的内容到 CloudFlare Workers 6. 在脚本顶端填上 `refresh_token`, `root_folder_id` 以及其他的选项 7. 部署! + +### 启用 Aria2 下载 + +1. 在 `worker.js` 中添加配置 `download_aria2: true`: + ``` + default_root_id: '...', + client_id: '...', + client_secret: '...', + refresh_token: '...', + ... + download_aria2: true + ``` +2. 重新部署,此时你应该可以在文件列表上方看到“使用 Aria2 下载”以及“Aria2 RPC 配置”两个按钮 +3. 在“Aria2 RPC 配置”中填写 Aria2 RPC 连接信息 +4. 前往你要下载的文件夹,点击“使用 Aria2 下载”,开始添加下载任务 \ No newline at end of file diff --git a/README.zhtw.md b/README.zhtw.md index 4fa0325f..ec6844d6 100644 --- a/README.zhtw.md +++ b/README.zhtw.md @@ -17,6 +17,7 @@ - 不支援目錄加密(.password) - 支援 Http Basic Auth - 支援多雲端硬碟(個人、團隊),不需要額外改程式設定 +- 支援通過 Aria2 下載 ## 使用教學 @@ -33,3 +34,18 @@ 5. 複製 [worker/dist/worker.js](worker/dist/worker.js) 的內容到 CloudFlare Workers 6. 在腳本頂端填上 `refresh_token`, `root_folder_id` 以及其他的選項 7. 部署! + +### 啟用 Aria2 下載 + +1. 在 `worker.js` 中添加配置 `download_aria2: true`: + ``` + default_root_id: '...', + client_id: '...', + client_secret: '...', + refresh_token: '...', + ... + download_aria2: true + ``` +2. 重新部署,此時你應該可以在文件列表上方看到“使用 Aria2 下載”以及“Aria2 RPC 配置”兩個按鈕 +3. 在“Aria2 RPC 配置”中填寫 Aria2 RPC 連接信息 +4. 前往你要下載的文件夾,點擊“使用 Aria2 下載”,開始添加下載任務 \ No newline at end of file From dfa46659660491b1a863a9ba753d3665cbd4805e Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Mon, 25 Nov 2019 10:32:22 +0800 Subject: [PATCH 06/10] Bugfix --- web/src/aria2.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/aria2.js b/web/src/aria2.js index 6f88b18e..4e1fe524 100644 --- a/web/src/aria2.js +++ b/web/src/aria2.js @@ -17,7 +17,7 @@ function setStringToLocalStorage(key, value) { } const aria2Support = { - rawInstance: null, + aria2: null, getRpcHost: function() { return getStringFromLocalStorage(KEY_ARIA2_RPC_HOST) }, @@ -57,7 +57,7 @@ const aria2Support = { return setStringToLocalStorage(KEY_ARIA2_DOWNLOAD_PATH, path) }, prepare: function() { - if (this.rawInstance) { + if (this.aria2) { return } @@ -71,14 +71,14 @@ const aria2Support = { this.aria2 = new Aria2(options) }, test: async function() { - if (!this.rawInstance) { + if (!this.aria2) { this.prepare() } return await this.aria2.call('getVersion') }, addDownload: async function(url, downloadPath) { - if (!this.rawInstance) { + if (!this.aria2) { this.prepare() } const option = { From 4f04de0c4374a27cd35bd29dd993e52977f4974f Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 15 Dec 2019 10:49:59 +0800 Subject: [PATCH 07/10] Add missing .prettierrc and reformat index.js --- worker/.prettierrc | 8 ++++++++ worker/index.js | 14 +++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 worker/.prettierrc diff --git a/worker/.prettierrc b/worker/.prettierrc new file mode 100644 index 00000000..6e50ea95 --- /dev/null +++ b/worker/.prettierrc @@ -0,0 +1,8 @@ +{ + "useTabs": true, + "tabWidth": 4, + "endOfLine": "lf", + "singleQuote": true, + "semi": false, + "printWidth": 120 +} \ No newline at end of file diff --git a/worker/index.js b/worker/index.js index 29433ff4..3303c0d1 100644 --- a/worker/index.js +++ b/worker/index.js @@ -102,9 +102,14 @@ async function onPut(request) { const u = new URL(url) const Referer = u.href const Origin = u.protocol + '//' + u.host - fileBody = (await fetch(url, { - headers: { Referer, Origin } - })).body + fileBody = ( + await fetch(url, { + headers: { + Referer, + Origin + } + }) + ).body } else { fileBody = request.body } @@ -118,6 +123,7 @@ async function onPut(request) { } }) } + function unauthorized() { return new Response('Unauthorized', { headers: { @@ -127,6 +133,7 @@ function unauthorized() { status: 401 }) } + function parseBasicAuth(auth) { try { return atob(auth.split(' ').pop()).split(':') @@ -134,6 +141,7 @@ function parseBasicAuth(auth) { return [] } } + function doBasicAuth(request) { const auth = request.headers.get('Authorization') if (!auth || !/^Basic [A-Za-z0-9._~+/-]+=*$/i.test(auth)) { From 9994381c41f6416eda8033a0befd0f92e4d08f13 Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 15 Dec 2019 13:52:33 +0800 Subject: [PATCH 08/10] Add copy API --- worker/googleDrive.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/worker/googleDrive.js b/worker/googleDrive.js index deb5ddab..d6a0d8d8 100644 --- a/worker/googleDrive.js +++ b/worker/googleDrive.js @@ -167,5 +167,21 @@ class GoogleDrive { if (!id) return null return this.delete(id) } + async copy(fileId, parentId) { + this.initializeClient() + if (parentId) { + return this.client + .post(`files/${fileId}/copy`, { + json: { + parents: [parentId] + } + }).json() + } else { + return this.client + .post(`files/${fileId}/copy`, { + json: {} + }).json() + } + } } export default GoogleDrive From c0bec867cafd64a82937638c0477315ce09954b2 Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 15 Dec 2019 10:48:00 +0800 Subject: [PATCH 09/10] Introduce file copying on forbidden --- worker/index.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/worker/index.js b/worker/index.js index 3303c0d1..41cfbe5f 100644 --- a/worker/index.js +++ b/worker/index.js @@ -41,7 +41,27 @@ async function onGet(request) { } const isGoogleApps = result.mimeType.includes('vnd.google-apps') if (!isGoogleApps) { - const r = await gd.download(result.id, request.headers.get('Range')) + let r + try { + r = await gd.download(result.id, request.headers.get('Range')) + } catch (e) { + if (e.toString().indexOf('Forbidden') !== -1 && self.props.copy_on_forbidden) { + // try copy file + const copiedFile = await gd.copy(result.id, self.props.copy_parent_id) + r = await gd.download(copiedFile.id, request.headers.get('Range')) + } else { + // other error, return it + return new Response( + { + error: e + }, + { + status: r.status + } + ) + } + } + const h = new Headers(r.headers) h.set('Content-Disposition', `inline; filename*=UTF-8''${encodeURIComponent(result.name)}`) return new Response(r.body, { From b7217465b78be992f2832e8f60319210684338db Mon Sep 17 00:00:00 2001 From: CodeingBoy Date: Sun, 15 Dec 2019 13:39:35 +0800 Subject: [PATCH 10/10] Add documentations --- README.md | 19 +++++++++++++++++++ README.zh.md | 19 +++++++++++++++++++ README.zhtw.md | 19 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/README.md b/README.md index fecf3d36..842a682b 100644 --- a/README.md +++ b/README.md @@ -37,3 +37,22 @@ Go [https://gdindex-code-builder.glitch.me/](https://gdindex-code-builder.glitch 5. Copy the content of [worker/dist/worker.js](worker/dist/worker.js) to CloudFlare Workers. 6. Fill `refresh_token`, `root_folder_id` and other options on the top of the script. 7. Deploy! + +### Enabling file copy on forbidden + +Google Drive limited each users' file sharing bandwidth(about 750GB per day). If you try pulling a shared file from who exceed this limit, you will receive a `403 - forbidden` error. Copying file to your may solve this problem, but it hurts because you can only copy a file once a time. + +That's why "Copy on forbidden" comes in. + +1. Create a folder, which will be used to store your copied files, crawl its id from network requests(normally you can get it from Developer Tools) +2. Add following config to your `worker.js`: + +``` + ... + copy_on_forbidden: true, + copy_parent_id: 'YOUR_COPY_FOLDER_ID' // replace YOUR_COPY_FOLDER_ID to your copy folder's ID +``` + +3. Just do normal download, if this file exceed limits, worker will make a copy and return copied one to you. This process is transparent so you won't need to deal other things. + +Note: Be sure to delete all you copied files after a while, as more files get copied, it will consumer more space on you drive. Besides, this feature will NOT detect existing copies, multiple downloads will leads multiple copies. diff --git a/README.zh.md b/README.zh.md index 314e8da6..918447e9 100644 --- a/README.zh.md +++ b/README.zh.md @@ -33,3 +33,22 @@ 5. 复制 [worker/dist/worker.js](worker/dist/worker.js) 的内容到 CloudFlare Workers 6. 在脚本顶端填上 `refresh_token`, `root_folder_id` 以及其他的选项 7. 部署! + +### 启用按需复制 + +Google Drive 限制了每个用户分享文件的流量(一般是每天 750GB)。如果你试图从超出流量限制的用户处下载一个分享文件,会收到 `403 - forbidden` 错误。将文件复制一份可能可以解决此问题,但是在网页端上一次操作只能复制一个文件。 + +因此,我们引入了“按需复制”功能。 + +1. 新建一个用于存放所有复制文件的文件夹。打开“开发者工具”获得这个文件夹的 ID +2. 添加以下配置到你的 `worker.js`: + +``` + ... + copy_on_forbidden: true, + copy_parent_id: 'YOUR_COPY_FOLDER_ID' // 替换 YOUR_COPY_FOLDER_ID 为你的文件夹 ID +``` + +3. 正常开始下载即可,如果 worker 检测到文件分享流量超出限制,会自动复制一份到之前的文件夹并返回复制的文件给你。该过程是透明的,因此你无需进行额外处理 + +注意:请在下载完一段时间后删除复制的文件,否则,随着复制的文件越多,它们会占用更多的空间。另外,复制过程中不会检测是否已有复制的文件,因此多次下载会触发多次复制动作。 diff --git a/README.zhtw.md b/README.zhtw.md index 4fa0325f..2dec52b9 100644 --- a/README.zhtw.md +++ b/README.zhtw.md @@ -33,3 +33,22 @@ 5. 複製 [worker/dist/worker.js](worker/dist/worker.js) 的內容到 CloudFlare Workers 6. 在腳本頂端填上 `refresh_token`, `root_folder_id` 以及其他的選項 7. 部署! + +### 啟用按需複制 + +Google Drive 限制了每個用戶分享文件的流量(一般是每天 750GB)。如果你試圖從超出流量限制的用戶處下載一個分享文件,會收到 `403 - forbidden` 錯誤。將文件複製一份可能可以解決此問題,但是在網頁端上一次操作只能複制一個文件。 + +因此,我們引入了“按需複制”功能。 + +1. 新建一個用於存放所有復製文件的文件夾。打開“開發者工具”獲得這個文件夾的 ID +2. 添加以下配置到你的 `worker.js`: + +``` +  ... +  copy_on_forbidden: true, +  copy_parent_id: 'YOUR_COPY_FOLDER_ID' // 替換 YOUR_COPY_FOLDER_ID 為你的文件夾 ID +``` + +3. 正常開始下載即可,如果 worker 檢測到文件分享流量超出限制,會自動複製一份到之前的文件夾並返回複製的文件給你。該過程是透明的,因此你無需進行額外處理 + +注意:請在下載完一段時間後刪除複製的文件,否則,隨著複製的文件越多,它們會佔用更多的空間。另外,複製過程中不會檢測是否已有復制的文件,因此多次下載會觸發多次復制動作。