├── .gitignore ├── README.md ├── vercel ├── accounts │ └── .gitignore ├── app.js ├── config.example.js ├── genToken.js ├── now.json ├── package-lock.json └── package.json └── workers ├── app.js ├── config.example.js ├── package-lock.json ├── package.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | */config.js 2 | vercel/gdTokens.js 3 | vercel/.now 4 | vercel/.vercel 5 | vercel/.gitignore 6 | workers/dist 7 | */node_modules 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Workers 2 | 3 | Workers 和 Vercel 上的代理脚本 4 | 5 | ❗ | **因架构调整,本项目已不再维护并将存档。新项目将支持泛媒体文件管理,相关开发工作将迁移至 [@UsagiHouse](https://github.com/UsagiHouse) 进行,请知悉** 6 | :---: | :--- 7 | 8 | ## More info -> [core](https://github.com/JAVClub/core) 9 | 10 | 一开始是准备只使用 Workers 的, 但是奈何单账户很容易触发 ratelimit, 10ms 的 `CPU time` 又不足以计算 JWT 11 | 12 | ~~后面准备换用 Vercel, 但是发现 Payload 有 Max 5MB 的限制, 所以只好做成现在这样, Vercel 分发 `access token`, Workers 代理文件~~ 13 | 14 | 更新后的布局是: 所有链接指向 Vercel, Vercel 再生成 access token 并 302 跳转至 Workers 15 | 16 | ### 准备 17 | 18 | - [AutoRclone 创建的 Service Account 文件(们) (在 accounts 目录下](https://gsuitems.com/index.php/archives/13/) 19 | - Vercel 账户 20 | 21 | ### 使用 22 | 23 | ```bash 24 | git clone https://github.com/JAVClub/proxy JAVClub_proxy 25 | cd JAVClub_proxy 26 | cp workers/config.example.js workers/config.js 27 | cp vercel/config.example.js vercel/config.js 28 | cd workers 29 | npm i 30 | cd ../vercel 31 | npm i 32 | npm i -g now webpack webpack-cli 33 | ``` 34 | 35 | 然后部署 Workers, 进入 `./workers` 运行 `webpack app.js`, 将 `./workers/dist/main.js` 的内容部署至 Workers 即可 36 | 37 | 再然后将准备到的 `Service Account` 文件们复制到本项目的 `vercel/accounts` 目录下, 然后在 `./vercel` 目录下运行 `node genToken.js` 38 | 39 | 接下来更改 `./vercel/config.js` 中的 `password` 字段(对应 core 中表述的 `secret`)和其余的字段 40 | 41 | 最后在根目录执行 `now` 按提示部署至 Vercel 并记下 URL 即可 42 | 43 | ## 特殊使用 44 | 45 | 应要求加了个正常的使用方法 (即使用 refresh_token 获得 access_token) 46 | 47 | 若要使用这种方法,创建 `./worker/config.js` 并填写其中信息后, 将 `app.js` 的第三行的第一个注释(即 `//`)去掉即可 48 | 49 | ## 免责声明 50 | 51 | 本程序仅供学习了解, 请于下载后 24 小时内删除, 不得用作任何商业用途, 文字、数据及图片均有所属版权, 如转载须注明来源 52 | 53 | 使用本程序必循遵守部署服务器所在地、所在国家和用户所在国家的法律法规, 程序作者不对使用者任何不当行为负责 54 | -------------------------------------------------------------------------------- /vercel/accounts/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /vercel/app.js: -------------------------------------------------------------------------------- 1 | const CryptoJS = require('crypto-js') 2 | const Base64 = require('js-base64').Base64 3 | const express = require('express') 4 | const randomInt = require('random-int') 5 | const { 6 | GoogleToken 7 | } = require('gtoken') 8 | 9 | const app = express() 10 | const port = 48971 11 | 12 | const tokens = require('./gdTokens') 13 | const config = require('./config') 14 | const accessTokens = [] 15 | 16 | function genGdUrl(accessToken, fileId) { 17 | const uri = CryptoJS.AES.encrypt(accessToken + '||!||' + fileId, config.password).toString() 18 | return Base64.encode(uri) 19 | } 20 | 21 | app.get('/*', async (req, res) => { 22 | let str = `${req.path}`.substr(1) 23 | 24 | if (str.startsWith('https:/') || str.startsWith('http:/')) { 25 | const server = config.imgServer[randomInt(0, config.imgServer.length - 1)] 26 | return res.redirect(302, server + str.replace(':/', '://')) 27 | } 28 | 29 | let fileId 30 | try { 31 | str = Base64.decode(str) 32 | fileId = CryptoJS.AES.decrypt(str, config.password).toString(CryptoJS.enc.Utf8) 33 | } catch (error) { 34 | return res.status(403).json({ 35 | code: -2, 36 | msg: 'Access denied', 37 | data: {} 38 | }) 39 | } 40 | 41 | if (fileId || fileId.split('||!||').length === 2) { 42 | const server = config.gdServer[randomInt(0, config.gdServer.length - 1)] 43 | const result = fileId.split('||!||') 44 | 45 | const int = randomInt(0, tokens.length - 1) 46 | if (accessTokens[int] && accessTokens[int].expireTime > (new Date()).getTime()) { 47 | return res.redirect(server + genGdUrl(accessTokens[int].access_token, result[1]), 302) 48 | } 49 | 50 | const gtoken = new GoogleToken({ 51 | email: tokens[int].client_email, 52 | scope: ['https://www.googleapis.com/auth/drive.readonly'], 53 | key: tokens[int].private_key 54 | }) 55 | 56 | const obj = Object.assign({}, await gtoken.getToken()) 57 | obj.expireTime = (new Date()).getTime() + 3400 * 1000 58 | 59 | accessTokens[int] = obj 60 | 61 | return res.redirect(302, server + genGdUrl(accessTokens[int].access_token, result[1])) 62 | } else { 63 | return res.status(403).json({ 64 | code: -2, 65 | msg: 'Access denied', 66 | data: {} 67 | }) 68 | } 69 | }) 70 | 71 | app.listen(port, () => console.log(`App listening at :${port}`)) 72 | -------------------------------------------------------------------------------- /vercel/config.example.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | password: "yourPassword", 3 | imgServer: [ 4 | 'https://p.yourImgWorker.workers.dev/' 5 | ], 6 | gdServer: [ 7 | 'https://p.yourGdWorker.workers.dev/' 8 | ] 9 | } -------------------------------------------------------------------------------- /vercel/genToken.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | 3 | const accounts = fs.readdirSync('./accounts') 4 | const tokens = [] 5 | 6 | for (const i in accounts) { 7 | if (`${accounts[i]}`.length !== 45) continue 8 | let file = JSON.parse(fs.readFileSync('./accounts/' + accounts[i]).toString()) 9 | 10 | file = { 11 | client_email: file.client_email, 12 | private_key: file.private_key 13 | } 14 | 15 | tokens.push(file) 16 | } 17 | 18 | fs.writeFileSync('./gdTokens.js', 'module.exports='+JSON.stringify(tokens)) 19 | -------------------------------------------------------------------------------- /vercel/now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "builds": [{ "src": "app.js", "use": "@now/node-server" }], 4 | "routes": [ 5 | { 6 | "src": "/(.*)", 7 | "dest": "/app.js", 8 | "methods": ["GET"] 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /vercel/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vercel", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "abort-controller": { 8 | "version": "3.0.0", 9 | "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", 10 | "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", 11 | "requires": { 12 | "event-target-shim": "^5.0.0" 13 | } 14 | }, 15 | "accepts": { 16 | "version": "1.3.7", 17 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 18 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 19 | "requires": { 20 | "mime-types": "~2.1.24", 21 | "negotiator": "0.6.2" 22 | } 23 | }, 24 | "agent-base": { 25 | "version": "6.0.0", 26 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz", 27 | "integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==", 28 | "requires": { 29 | "debug": "4" 30 | }, 31 | "dependencies": { 32 | "debug": { 33 | "version": "4.1.1", 34 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 35 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 36 | "requires": { 37 | "ms": "^2.1.1" 38 | } 39 | }, 40 | "ms": { 41 | "version": "2.1.2", 42 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 43 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 44 | } 45 | } 46 | }, 47 | "array-flatten": { 48 | "version": "1.1.1", 49 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 50 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 51 | }, 52 | "body-parser": { 53 | "version": "1.19.0", 54 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 55 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 56 | "requires": { 57 | "bytes": "3.1.0", 58 | "content-type": "~1.0.4", 59 | "debug": "2.6.9", 60 | "depd": "~1.1.2", 61 | "http-errors": "1.7.2", 62 | "iconv-lite": "0.4.24", 63 | "on-finished": "~2.3.0", 64 | "qs": "6.7.0", 65 | "raw-body": "2.4.0", 66 | "type-is": "~1.6.17" 67 | } 68 | }, 69 | "buffer-equal-constant-time": { 70 | "version": "1.0.1", 71 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", 72 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" 73 | }, 74 | "bytes": { 75 | "version": "3.1.0", 76 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 77 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 78 | }, 79 | "content-disposition": { 80 | "version": "0.5.3", 81 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 82 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 83 | "requires": { 84 | "safe-buffer": "5.1.2" 85 | } 86 | }, 87 | "content-type": { 88 | "version": "1.0.4", 89 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 90 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 91 | }, 92 | "cookie": { 93 | "version": "0.4.0", 94 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 95 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 96 | }, 97 | "cookie-signature": { 98 | "version": "1.0.6", 99 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 100 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 101 | }, 102 | "crypto-js": { 103 | "version": "4.0.0", 104 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", 105 | "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" 106 | }, 107 | "debug": { 108 | "version": "2.6.9", 109 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 110 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 111 | "requires": { 112 | "ms": "2.0.0" 113 | } 114 | }, 115 | "depd": { 116 | "version": "1.1.2", 117 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 118 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 119 | }, 120 | "destroy": { 121 | "version": "1.0.4", 122 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 123 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 124 | }, 125 | "ecdsa-sig-formatter": { 126 | "version": "1.0.11", 127 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", 128 | "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", 129 | "requires": { 130 | "safe-buffer": "^5.0.1" 131 | } 132 | }, 133 | "ee-first": { 134 | "version": "1.1.1", 135 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 136 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 137 | }, 138 | "encodeurl": { 139 | "version": "1.0.2", 140 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 141 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 142 | }, 143 | "escape-html": { 144 | "version": "1.0.3", 145 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 146 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 147 | }, 148 | "etag": { 149 | "version": "1.8.1", 150 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 151 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 152 | }, 153 | "event-target-shim": { 154 | "version": "5.0.1", 155 | "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", 156 | "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" 157 | }, 158 | "express": { 159 | "version": "4.17.1", 160 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 161 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 162 | "requires": { 163 | "accepts": "~1.3.7", 164 | "array-flatten": "1.1.1", 165 | "body-parser": "1.19.0", 166 | "content-disposition": "0.5.3", 167 | "content-type": "~1.0.4", 168 | "cookie": "0.4.0", 169 | "cookie-signature": "1.0.6", 170 | "debug": "2.6.9", 171 | "depd": "~1.1.2", 172 | "encodeurl": "~1.0.2", 173 | "escape-html": "~1.0.3", 174 | "etag": "~1.8.1", 175 | "finalhandler": "~1.1.2", 176 | "fresh": "0.5.2", 177 | "merge-descriptors": "1.0.1", 178 | "methods": "~1.1.2", 179 | "on-finished": "~2.3.0", 180 | "parseurl": "~1.3.3", 181 | "path-to-regexp": "0.1.7", 182 | "proxy-addr": "~2.0.5", 183 | "qs": "6.7.0", 184 | "range-parser": "~1.2.1", 185 | "safe-buffer": "5.1.2", 186 | "send": "0.17.1", 187 | "serve-static": "1.14.1", 188 | "setprototypeof": "1.1.1", 189 | "statuses": "~1.5.0", 190 | "type-is": "~1.6.18", 191 | "utils-merge": "1.0.1", 192 | "vary": "~1.1.2" 193 | } 194 | }, 195 | "extend": { 196 | "version": "3.0.2", 197 | "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", 198 | "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" 199 | }, 200 | "finalhandler": { 201 | "version": "1.1.2", 202 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 203 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 204 | "requires": { 205 | "debug": "2.6.9", 206 | "encodeurl": "~1.0.2", 207 | "escape-html": "~1.0.3", 208 | "on-finished": "~2.3.0", 209 | "parseurl": "~1.3.3", 210 | "statuses": "~1.5.0", 211 | "unpipe": "~1.0.0" 212 | } 213 | }, 214 | "forwarded": { 215 | "version": "0.1.2", 216 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 217 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 218 | }, 219 | "fresh": { 220 | "version": "0.5.2", 221 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 222 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 223 | }, 224 | "gaxios": { 225 | "version": "3.0.3", 226 | "resolved": "https://registry.npmjs.org/gaxios/-/gaxios-3.0.3.tgz", 227 | "integrity": "sha512-PkzQludeIFhd535/yucALT/Wxyj/y2zLyrMwPcJmnLHDugmV49NvAi/vb+VUq/eWztATZCNcb8ue+ywPG+oLuw==", 228 | "requires": { 229 | "abort-controller": "^3.0.0", 230 | "extend": "^3.0.2", 231 | "https-proxy-agent": "^5.0.0", 232 | "is-stream": "^2.0.0", 233 | "node-fetch": "^2.3.0" 234 | } 235 | }, 236 | "google-p12-pem": { 237 | "version": "3.0.1", 238 | "resolved": "https://registry.npmjs.org/google-p12-pem/-/google-p12-pem-3.0.1.tgz", 239 | "integrity": "sha512-VlQgtozgNVVVcYTXS36eQz4PXPt9gIPqLOhHN0QiV6W6h4qSCNVKPtKC5INtJsaHHF2r7+nOIa26MJeJMTaZEQ==", 240 | "requires": { 241 | "node-forge": "^0.9.0" 242 | } 243 | }, 244 | "gtoken": { 245 | "version": "5.0.1", 246 | "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-5.0.1.tgz", 247 | "integrity": "sha512-33w4FNDkUcyIOq/TqyC+drnKdI4PdXmWp9lZzssyEQKuvu9ZFN3KttaSnDKo52U3E51oujVGop93mKxmqO8HHg==", 248 | "requires": { 249 | "gaxios": "^3.0.0", 250 | "google-p12-pem": "^3.0.0", 251 | "jws": "^4.0.0", 252 | "mime": "^2.2.0" 253 | }, 254 | "dependencies": { 255 | "mime": { 256 | "version": "2.4.5", 257 | "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.5.tgz", 258 | "integrity": "sha512-3hQhEUF027BuxZjQA3s7rIv/7VCQPa27hN9u9g87sEkWaKwQPuXOkVKtOeiyUrnWqTDiOs8Ed2rwg733mB0R5w==" 259 | } 260 | } 261 | }, 262 | "http-errors": { 263 | "version": "1.7.2", 264 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 265 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 266 | "requires": { 267 | "depd": "~1.1.2", 268 | "inherits": "2.0.3", 269 | "setprototypeof": "1.1.1", 270 | "statuses": ">= 1.5.0 < 2", 271 | "toidentifier": "1.0.0" 272 | } 273 | }, 274 | "https-proxy-agent": { 275 | "version": "5.0.0", 276 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 277 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 278 | "requires": { 279 | "agent-base": "6", 280 | "debug": "4" 281 | }, 282 | "dependencies": { 283 | "debug": { 284 | "version": "4.1.1", 285 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 286 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 287 | "requires": { 288 | "ms": "^2.1.1" 289 | } 290 | }, 291 | "ms": { 292 | "version": "2.1.2", 293 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 294 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 295 | } 296 | } 297 | }, 298 | "iconv-lite": { 299 | "version": "0.4.24", 300 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 301 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 302 | "requires": { 303 | "safer-buffer": ">= 2.1.2 < 3" 304 | } 305 | }, 306 | "inherits": { 307 | "version": "2.0.3", 308 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 309 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 310 | }, 311 | "ipaddr.js": { 312 | "version": "1.9.1", 313 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 314 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 315 | }, 316 | "is-stream": { 317 | "version": "2.0.0", 318 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", 319 | "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==" 320 | }, 321 | "js-base64": { 322 | "version": "3.2.4", 323 | "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.2.4.tgz", 324 | "integrity": "sha512-WFh/G3UxDU/3gWsJPtT1Ee8smRd9d6Z9k1/1aIg5ajGdYUeZg+ZRFTY6LxBqNArU3qjHKhrxu1pjr921DILu3w==" 325 | }, 326 | "jwa": { 327 | "version": "2.0.0", 328 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.0.tgz", 329 | "integrity": "sha512-jrZ2Qx916EA+fq9cEAeCROWPTfCwi1IVHqT2tapuqLEVVDKFDENFw1oL+MwrTvH6msKxsd1YTDVw6uKEcsrLEA==", 330 | "requires": { 331 | "buffer-equal-constant-time": "1.0.1", 332 | "ecdsa-sig-formatter": "1.0.11", 333 | "safe-buffer": "^5.0.1" 334 | } 335 | }, 336 | "jws": { 337 | "version": "4.0.0", 338 | "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.0.tgz", 339 | "integrity": "sha512-KDncfTmOZoOMTFG4mBlG0qUIOlc03fmzH+ru6RgYVZhPkyiy/92Owlt/8UEN+a4TXR1FQetfIpJE8ApdvdVxTg==", 340 | "requires": { 341 | "jwa": "^2.0.0", 342 | "safe-buffer": "^5.0.1" 343 | } 344 | }, 345 | "media-typer": { 346 | "version": "0.3.0", 347 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 348 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 349 | }, 350 | "merge-descriptors": { 351 | "version": "1.0.1", 352 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 353 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 354 | }, 355 | "methods": { 356 | "version": "1.1.2", 357 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 358 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 359 | }, 360 | "mime": { 361 | "version": "1.6.0", 362 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 363 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 364 | }, 365 | "mime-db": { 366 | "version": "1.44.0", 367 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 368 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 369 | }, 370 | "mime-types": { 371 | "version": "2.1.27", 372 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 373 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 374 | "requires": { 375 | "mime-db": "1.44.0" 376 | } 377 | }, 378 | "ms": { 379 | "version": "2.0.0", 380 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 381 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 382 | }, 383 | "negotiator": { 384 | "version": "0.6.2", 385 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 386 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 387 | }, 388 | "node-fetch": { 389 | "version": "2.6.0", 390 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", 391 | "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" 392 | }, 393 | "node-forge": { 394 | "version": "0.9.1", 395 | "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.1.tgz", 396 | "integrity": "sha512-G6RlQt5Sb4GMBzXvhfkeFmbqR6MzhtnT7VTHuLadjkii3rdYHNdw0m8zA4BTxVIh68FicCQ2NSUANpsqkr9jvQ==" 397 | }, 398 | "on-finished": { 399 | "version": "2.3.0", 400 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 401 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 402 | "requires": { 403 | "ee-first": "1.1.1" 404 | } 405 | }, 406 | "parseurl": { 407 | "version": "1.3.3", 408 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 409 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 410 | }, 411 | "path-to-regexp": { 412 | "version": "0.1.7", 413 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 414 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 415 | }, 416 | "proxy-addr": { 417 | "version": "2.0.6", 418 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 419 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 420 | "requires": { 421 | "forwarded": "~0.1.2", 422 | "ipaddr.js": "1.9.1" 423 | } 424 | }, 425 | "qs": { 426 | "version": "6.7.0", 427 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 428 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 429 | }, 430 | "random-int": { 431 | "version": "2.0.1", 432 | "resolved": "https://registry.npmjs.org/random-int/-/random-int-2.0.1.tgz", 433 | "integrity": "sha512-YALjWK2Rt9EMIv9BF/3mvlzFWQathsvb5UZmN1QmhfIOfcQYXc/UcLzg0ablqesSBpBVLt2Tlwv/eTuBh4LXUQ==" 434 | }, 435 | "range-parser": { 436 | "version": "1.2.1", 437 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 438 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 439 | }, 440 | "raw-body": { 441 | "version": "2.4.0", 442 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 443 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 444 | "requires": { 445 | "bytes": "3.1.0", 446 | "http-errors": "1.7.2", 447 | "iconv-lite": "0.4.24", 448 | "unpipe": "1.0.0" 449 | } 450 | }, 451 | "safe-buffer": { 452 | "version": "5.1.2", 453 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 454 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 455 | }, 456 | "safer-buffer": { 457 | "version": "2.1.2", 458 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 459 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 460 | }, 461 | "send": { 462 | "version": "0.17.1", 463 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 464 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 465 | "requires": { 466 | "debug": "2.6.9", 467 | "depd": "~1.1.2", 468 | "destroy": "~1.0.4", 469 | "encodeurl": "~1.0.2", 470 | "escape-html": "~1.0.3", 471 | "etag": "~1.8.1", 472 | "fresh": "0.5.2", 473 | "http-errors": "~1.7.2", 474 | "mime": "1.6.0", 475 | "ms": "2.1.1", 476 | "on-finished": "~2.3.0", 477 | "range-parser": "~1.2.1", 478 | "statuses": "~1.5.0" 479 | }, 480 | "dependencies": { 481 | "ms": { 482 | "version": "2.1.1", 483 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 484 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 485 | } 486 | } 487 | }, 488 | "serve-static": { 489 | "version": "1.14.1", 490 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 491 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 492 | "requires": { 493 | "encodeurl": "~1.0.2", 494 | "escape-html": "~1.0.3", 495 | "parseurl": "~1.3.3", 496 | "send": "0.17.1" 497 | } 498 | }, 499 | "setprototypeof": { 500 | "version": "1.1.1", 501 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 502 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 503 | }, 504 | "statuses": { 505 | "version": "1.5.0", 506 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 507 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 508 | }, 509 | "toidentifier": { 510 | "version": "1.0.0", 511 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 512 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 513 | }, 514 | "type-is": { 515 | "version": "1.6.18", 516 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 517 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 518 | "requires": { 519 | "media-typer": "0.3.0", 520 | "mime-types": "~2.1.24" 521 | } 522 | }, 523 | "unpipe": { 524 | "version": "1.0.0", 525 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 526 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 527 | }, 528 | "utils-merge": { 529 | "version": "1.0.1", 530 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 531 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 532 | }, 533 | "vary": { 534 | "version": "1.1.2", 535 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 536 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 537 | } 538 | } 539 | } 540 | -------------------------------------------------------------------------------- /vercel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vercel", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "crypto-js": "^4.0.0", 13 | "express": "^4.17.1", 14 | "gtoken": "^5.0.1", 15 | "js-base64": "^3.2.4", 16 | "random-int": "^2.0.1" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /workers/app.js: -------------------------------------------------------------------------------- 1 | const CryptoJS = require('crypto-js') 2 | const Base64 = require('js-base64').Base64 3 | const oAuth = null // || require('./config') // Needed if not using vercel 4 | const aesPassword = (oAuth && oAuth.aesPassword) || require('./../vercel/config').password 5 | 6 | let accessToken, oAuthToken = {} 7 | 8 | addEventListener('fetch', event => { 9 | event.respondWith(handleRequest(event)) 10 | }) 11 | 12 | async function handleRequest(event) { 13 | const request = event.request 14 | 15 | const gd = new googleDrive() 16 | 17 | const url = new URL(request.url) 18 | let str = url.pathname.substr(1) 19 | 20 | let fileId 21 | 22 | try { 23 | str = Base64.decode(str) 24 | fileId = CryptoJS.AES.decrypt(str, aesPassword).toString(CryptoJS.enc.Utf8) 25 | } catch (error) { 26 | return new Response(JSON.stringify({ 27 | code: -2, 28 | msg: 'Access denied', 29 | data: { 30 | msg: 'AES error' 31 | } 32 | }), { 33 | status: 403 34 | }) 35 | } 36 | 37 | if (fileId || fileId.split('||!||').length === 2) { 38 | const result = fileId.split('||!||') 39 | const range = request.headers.get('Range') 40 | 41 | accessToken = result[0] 42 | response = await gd.download(result[1], range) 43 | 44 | return response 45 | } else { 46 | return new Response(JSON.stringify({ 47 | code: -2, 48 | msg: 'Access denied', 49 | data: { 50 | msg: 'parse error' 51 | } 52 | }), { 53 | status: 403 54 | }) 55 | } 56 | } 57 | 58 | class googleDrive { 59 | async download(id, range) { 60 | const url = `https://www.googleapis.com/drive/v3/files/${id}?alt=media` 61 | 62 | const requestOption = await this.requestOption() 63 | 64 | requestOption.headers['Range'] = range 65 | 66 | let response = await fetch(url, requestOption) 67 | response = new Response(response.body, response) 68 | 69 | let cacheControl 70 | if (response.status < 299) cacheControl = 'public, max-age=2592000' 71 | else cacheControl = 'public, max-age=0' 72 | 73 | response.headers.set('Cache-Control', cacheControl) 74 | response.headers.set('X-Powered-By', 'JAVClub') 75 | response.headers.delete('x-guploader-uploadid') 76 | response.headers.delete('expires') 77 | response.headers.delete('date') 78 | response.headers.delete('content-disposition') 79 | 80 | return response 81 | } 82 | 83 | async requestOption(headers = {}, method = 'GET') { 84 | headers['authorization'] = 'Bearer ' + ((oAuth === null && accessToken) || await this.accessToken()) 85 | 86 | return { 87 | method, 88 | headers 89 | } 90 | } 91 | 92 | async accessToken() { 93 | if (oAuthToken.expires === undefined || oAuthToken.expires < Date.now()) { 94 | const obj = await this.fetchAccessToken(); 95 | if (obj.access_token != undefined) { 96 | oAuthToken.accessToken = obj.access_token; 97 | oAuthToken.expires = Date.now() + 3500 * 1000; 98 | } 99 | } 100 | return oAuthToken.accessToken; 101 | } 102 | 103 | async fetchAccessToken() { 104 | const url = "https://www.googleapis.com/oauth2/v4/token"; 105 | const headers = { 106 | 'Content-Type': 'application/x-www-form-urlencoded' 107 | }; 108 | const post_data = { 109 | client_id: oAuth.client_id, 110 | client_secret: oAuth.client_secret, 111 | refresh_token: oAuth.refresh_token, 112 | grant_type: 'refresh_token' 113 | } 114 | 115 | let requestOption = { 116 | 'method': 'POST', 117 | 'headers': headers, 118 | 'body': this.enQuery(post_data) 119 | }; 120 | 121 | const response = await fetch(url, requestOption); 122 | return await response.json(); 123 | } 124 | 125 | enQuery(data) { 126 | const ret = [] 127 | 128 | for (let d in data) { 129 | ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d])) 130 | } 131 | 132 | return ret.join('&') 133 | } 134 | } -------------------------------------------------------------------------------- /workers/config.example.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | client_id: '', 3 | client_secret: '', 4 | refresh_token: '', 5 | aesPassword: '' 6 | } -------------------------------------------------------------------------------- /workers/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "workers", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "crypto-js": { 8 | "version": "4.0.0", 9 | "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.0.0.tgz", 10 | "integrity": "sha512-bzHZN8Pn+gS7DQA6n+iUmBfl0hO5DJq++QP3U6uTucDtk/0iGpXd/Gg7CGR0p8tJhofJyaKoWBuJI4eAO00BBg==" 11 | }, 12 | "js-base64": { 13 | "version": "2.5.2", 14 | "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz", 15 | "integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /workers/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "workers", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "MIT", 11 | "dependencies": { 12 | "crypto-js": "^4.0.0", 13 | "js-base64": "^2.5.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /workers/webpack.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | target: 'webworker', 3 | mode: 'production' 4 | } 5 | --------------------------------------------------------------------------------