Guest User

Untitled

a guest
Sep 25th, 2022
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 45.21 KB | None | 0 0
  1. 1. First things first; you need to make a free cloudflare account here: https://www.cloudflare.com/ Once that is done, login and click "Workers" in the left panel. From there, click "Create a Service" I named mine OtakuClub (I name a lot of things this. You can choose your own.) and then click "Create Service" at the bottom. We will now click "Quick Edit" which should bring you to a page that resembles an html editor. We're going to leave this open for now and come back to it.
  2.  
  3. So far your order of operations after logging into cloudflare is: Click Workers -> Click Create a Service -> Name it and click 'Create Service' -> Quick Edit
  4.  
  5. 2. Open up your googledrive and create the folder you want to hold your video files in. Then open that folder. We're going to be coming back to this as well.
  6.  
  7. 3. Open this in a third tab: https://bdi-generator.hashhackers.com/ and sign in with your google account. For site name, I once again just used the name of the gdrive folder. For share id/root however, we're going to take the random string of letters and numbers at the end of your gdrive folder url. https://drive.google.com/drive/folders/ (This information) / and click submit. You should then see a big ol block of code. We're going to come back to this.
  8.  
  9. 4. This part might be wholly unnecessary but it's what I did and what worked. So, attached to this post is a text file. You're going to download it, copy everything inside, and then go back to that editor we started in Step 1. Highlight everything in that editor and paste over it.
  10.  
  11. 5. Nearly done, just a few choice lines we need to change. Attached at the bottom of this post is an image that highlights the lines we're about to edit. Now we go back to the tab of code we made in Step 3 and take the respective information from that and paste it over the information in the cloudflare tab. My sitename that I picked is the same one I've used for the gdrive folder and so on. An important thing to note: "id": should be that bit of url from the gdrive folder you made.
  12.  
  13. 6. Click Deploy. You should receive a url that I highly recommend you bookmark. Go to it, and if there is no spinny wheel then you've successfully created a place to get cytube links that doesn't require the gdrive script or for the video to even render! You still need to handbrake and upload unfortunately, but no more waiting for renders and no more gdrive going kaput if more than 20 people watch at once.
  14.  
  15. /* ░██████╗░██████╗░██╗░░░░░░░░██╗░██████╗░░░░█████╗░██████╗░░██████╗░
  16. ██╔════╝░██╔══██╗██║░░░░░░░░██║██╔════╝░░░██╔══██╗██╔══██╗██╔════╝░
  17. ██║░░██╗░██║░░██║██║░░░░░░░░██║╚█████╗░░░░██║░░██║██████╔╝██║░░██╗░
  18. ██║░░╚██╗██║░░██║██║░░░██╗░░██║░╚═══██╗░░░██║░░██║██╔══██╗██║░░╚██╗
  19. ╚██████╔╝██████╔╝██║██╗╚█████╔╝██████╔╝██╗╚█████╔╝██║░░██║╚██████╔╝
  20. ░╚═════╝░╚═════╝░╚═╝╚═╝░╚════╝░╚═════╝░╚═╝░╚════╝░╚═╝░░╚═╝░╚═════╝░
  21. v 2.0.18
  22. A Script Redesigned by Parveen Bhadoo from GOIndex at https://github.com/ParveenBhadooOfficial/Google-Drive-Index */
  23.  
  24. // add multiple serviceaccounts as {}, {}, {}, random account will be selected by each time app is opened.
  25. const serviceaccounts = [
  26. {}
  27. ];
  28. const randomserviceaccount = serviceaccounts[Math.floor(Math.random()*serviceaccounts.length)];
  29.  
  30. const authConfig = {
  31. "siteName": "aethermovienight2", // Website name
  32. "client_id": "746239575955-oao9hkv614p8glrqpvuh5i8mqfoq145b.apps.googleusercontent.com", // Client id from Google Cloud Console
  33. "client_secret": "u5a1CSY5pNjdD2tGTU93TTnI", // Client Secret from Google Cloud Console
  34. "refresh_token": "1//0hch9KTh7mU_pCgYIARAAGBESNwF-L9IrymOgkIBJzbk6fNvO-3H-vnPnY5lsYRKtIYa_QEoxzWgK5SZVrFqrjc3dZDKFyihpNWc", // Authorize token
  35. "service_account": false, // true if you're using Service Account instead of user account
  36. "service_account_json": randomserviceaccount, // don't touch this one
  37. "files_list_page_size": 50,
  38. "search_result_list_page_size": 50,
  39. "enable_cors_file_down": false,
  40. "enable_password_file_verify": true, // support for .password file
  41. "roots":[
  42. {
  43. "id": "1BroFt_iWp50e6AYDbPlaqpsdETLibOMs",
  44. "name": "Drive One",
  45. "protect_file_link": false,
  46. // "auth": {"username":"password"} /* Remove double slash before "auth" to activate id password protection */
  47. },
  48. {
  49. "id": "root",
  50. "name": "Drive Two",
  51. "protect_file_link": false,
  52. // "auth": {"username":"password", "username1":"password1"} /* Remove double slash before "auth" to activate id password protection */
  53. },
  54. ]};
  55.  
  56.  
  57. /*
  58. ███████╗██████╗░██╗████████╗  ████████╗██╗░░██╗███████╗░██████╗███████╗
  59. ██╔════╝██╔══██╗██║╚══██╔══╝  ╚══██╔══╝██║░░██║██╔════╝██╔════╝██╔════╝
  60. █████╗░░██║░░██║██║░░░██║░░░  ░░░██║░░░███████║█████╗░░╚█████╗░█████╗░░
  61. ██╔══╝░░██║░░██║██║░░░██║░░░  ░░░██║░░░██╔══██║██╔══╝░░░╚═══██╗██╔══╝░░
  62. ███████╗██████╔╝██║░░░██║░░░  ░░░██║░░░██║░░██║███████╗██████╔╝███████╗
  63. ╚══════╝╚═════╝░╚═╝░░░╚═╝░░░  ░░░╚═╝░░░╚═╝░░╚═╝╚══════╝╚═════╝░╚══════╝
  64.  
  65. ██╗░░░██╗░█████╗░██╗░░░░░██╗░░░██╗███████╗░██████╗
  66. ██║░░░██║██╔══██╗██║░░░░░██║░░░██║██╔════╝██╔════╝
  67. ╚██╗░██╔╝███████║██║░░░░░██║░░░██║█████╗░░╚█████╗░
  68. ░╚████╔╝░██╔══██║██║░░░░░██║░░░██║██╔══╝░░░╚═══██╗
  69. ░░╚██╔╝░░██║░░██║███████╗╚██████╔╝███████╗██████╔╝
  70. ░░░╚═╝░░░╚═╝░░╚═╝╚══════╝░╚═════╝░╚══════╝╚═════╝░*/
  71.  
  72. const uiConfig = {
  73. "theme": "slate", // switch between themes, default set to vapor, select from https://github.com/ParveenBhadooOfficial/Google-Drive-Index#themes
  74. "version": "2.0.18", // don't touch this one. get latest code using generator at https://generator.driveindex.ga
  75. // If you're using Image then set to true, If you want text then set it to false
  76. "logo_image": true, // true if you're using image link in next option.
  77. "logo_height": "", // only if logo_image is true
  78. "logo_width": "100px", // only if logo_image is true
  79. "favicon": "https://cdn.jsdelivr.net/gh/ParveenBhadooOfficial/[email protected]/images/favicon.ico",
  80. // if logo is true then link otherwise just text for name
  81. "logo_link_name": "https://cdn.jsdelivr.net/gh/jscdn/[email protected]/bhadoo-cloud-logo-white.svg",
  82. "fixed_header": true, // If you want the footer to be flexible or fixed.
  83. "header_padding": "60", // Value 60 for fixed header, Value 20 for flexible header. Required to be changed accordingly in some themes.
  84. "fixed_footer": false, // If you want the footer to be flexible or fixed.
  85. "header_style_class": "navbar-dark bg-primary", // navbar-dark bg-primary || navbar-dark bg-dark || navbar-light bg-light
  86. "footer_style_class": "bg-primary", // bg-primary || bg-dark || bg-light
  87. "css_a_tag_color": "white", // Color Name or Hex Code eg. #ffffff
  88. "css_p_tag_color": "white", // Color Name or Hex Code eg. #ffffff
  89. "folder_text_color": "white", // Color Name or Hex Code eg. #ffffff
  90. "loading_spinner_class": "text-light", // https://getbootstrap.com/docs/5.0/components/spinners/#colors
  91. "search_button_class": "btn-outline-success", // https://getbootstrap.com/docs/5.0/components/buttons/#examples
  92. "path_nav_alert_class": "alert alert-primary", // https://getbootstrap.com/docs/4.0/components/alerts/#examples
  93. "file_view_alert_class": "alert alert-danger", // https://getbootstrap.com/docs/4.0/components/alerts/#examples
  94. "file_count_alert_class": "alert alert-secondary", // https://getbootstrap.com/docs/4.0/components/alerts/#examples
  95. "contact_link": "https://telegram.dog/Telegram", // Link to Contact Button on Menu
  96. "copyright_year": "2050", // year of copyright, can be anything like 2015 - 2020 or just 2020
  97. "company_name": "gdi.js.org", // Name next to copyright
  98. "company_link": "https://telegram.dog/Telegram", // link of copyright name
  99. "credit": true, // Set this to true to give us credit
  100. "display_size": true, // Set this to false to hide display file size
  101. "display_time": false, // Set this to false to hide display modified time for folder and files
  102. "display_download": true, // Set this to false to hide download icon for folder and files on main index
  103. "disable_player": false, // Set this to true to hide audio and video players
  104. "custom_srt_lang": "", // Subtitle Language Code for Custom .vtt language.
  105. "disable_video_download": false, // Remove Download, Copy Button on Videos
  106. "second_domain_for_dl": false, // If you want to display other URL for Downloading to protect your main domain.
  107. "downloaddomain": "https://testing.fetchgoogleapi.workers.dev", // If "second_domain_for_dl": true then enter downloaddomain otherwise keep empty. eg. https://workers.workersname.workers.dev No Trailing '/'
  108. "poster": "https://cdn.jsdelivr.net/gh/ParveenBhadooOfficial/[email protected]/images/poster.jpg", // Video poster URL or see Readme to how to load from Drive
  109. "audioposter": "https://cdn.jsdelivr.net/gh/ParveenBhadooOfficial/[email protected]/images/music.jpg", // Video poster URL or see Readme to how to load from Drive
  110. "jsdelivr_cdn_src": "https://cdn.jsdelivr.net/gh/ParveenBhadooOfficial/Google-Drive-Index", // If Project is Forked, then enter your Github repo
  111. "render_head_md": true, // Render Head.md
  112. "render_readme_md": true, // Render Readme.md
  113. "display_drive_link": false, // This will add a Link Button to Google Drive of that particular file.
  114. "plyr_io_version": "3.6.4", // Change plyr.io version in future when needed.
  115. "plyr_io_video_resolution": "16:9", // For reference, visit: https://github.com/sampotts/plyr#options
  116. "unauthorized_owner_link": "https://telegram.dog/Telegram", // Unauthorized Error Page Link to Owner
  117. "unauthorized_owner_email": "[email protected]", // Unauthorized Error Page Owner Email
  118. "arc_code": "jfoY2h19" // arc.io Integraion Code, get yours from https://portal.arc.io
  119. };
  120.  
  121.  
  122. /*
  123. ██████╗░░█████╗░  ███╗░░██╗░█████╗░████████╗  ███████╗██████╗░██╗████████╗
  124. ██╔══██╗██╔══██╗  ████╗░██║██╔══██╗╚══██╔══╝  ██╔════╝██╔══██╗██║╚══██╔══╝
  125. ██║░░██║██║░░██║  ██╔██╗██║██║░░██║░░░██║░░░  █████╗░░██║░░██║██║░░░██║░░░
  126. ██║░░██║██║░░██║  ██║╚████║██║░░██║░░░██║░░░  ██╔══╝░░██║░░██║██║░░░██║░░░
  127. ██████╔╝╚█████╔╝  ██║░╚███║╚█████╔╝░░░██║░░░  ███████╗██████╔╝██║░░░██║░░░
  128. ╚═════╝░░╚════╝░  ╚═╝░░╚══╝░╚════╝░░░░╚═╝░░░  ╚══════╝╚═════╝░╚═╝░░░╚═╝░░░
  129.  
  130. ██████╗░███████╗██╗░░░░░░█████╗░░██╗░░░░░░░██╗
  131. ██╔══██╗██╔════╝██║░░░░░██╔══██╗░██║░░██╗░░██║
  132. ██████╦╝█████╗░░██║░░░░░██║░░██║░╚██╗████╗██╔╝
  133. ██╔══██╗██╔══╝░░██║░░░░░██║░░██║░░████╔═████║░
  134. ██████╦╝███████╗███████╗╚█████╔╝░░╚██╔╝░╚██╔╝░
  135. ╚═════╝░╚══════╝╚══════╝░╚════╝░░░░╚═╝░░░╚═╝░░*/
  136.  
  137. // DON'T TOUCH BELOW THIS UNLESS YOU KNOW WHAT YOU'RE DOING
  138. var gds = [];
  139.  
  140. function html(current_drive_order = 0, model = {}) {
  141. return `<!DOCTYPE html>
  142. <html>
  143. <head>
  144. <meta charset="utf-8">
  145. <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no"/>
  146. <title>${authConfig.siteName}</title>
  147. <script async src="https://arc.io/widget.min.js#${uiConfig.arc_code}"></script>
  148. <meta name="robots" content="noindex" />
  149. <link rel="icon" href="${uiConfig.favicon}">
  150. <script>
  151. window.drive_names = JSON.parse('${JSON.stringify(authConfig.roots.map(it => it.name))}');
  152. window.MODEL = JSON.parse('${JSON.stringify(model)}');
  153. window.current_drive_order = ${current_drive_order};
  154. window.UI = JSON.parse('${JSON.stringify(uiConfig)}');
  155. </script>
  156. <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
  157. <link rel="stylesheet" href="https://cdn.plyr.io/${uiConfig.plyr_io_version}/plyr.css" />
  158. <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/${uiConfig.theme}/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
  159. <style>
  160. a {
  161. color: ${uiConfig.css_a_tag_color};
  162. }
  163. p {
  164. color: ${uiConfig.css_p_tag_color};
  165. }
  166. </style>
  167. <script src="${uiConfig.jsdelivr_cdn_src}@${uiConfig.version}/js/app.min.js"></script>
  168. <script src="https://cdn.jsdelivr.net/gh/ParveenBhadooOfficial/Google-Drive-Index@master/js/update.min.js"></script>
  169. <script src="https://cdn.jsdelivr.net/gh/mozilla/pdf.js@gh-pages/build/pdf.js"></script>
  170. <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
  171. </head>
  172. <body>
  173. </body>
  174. <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script>
  175. <script src="https://cdn.plyr.io/${uiConfig.plyr_io_version}/plyr.polyfilled.js"></script>
  176. </html>`;
  177. };
  178.  
  179. const unauthorized = `<html>
  180. <head><title>401 Unauthorized</title></head>
  181. <body>
  182. <center><h1>401 Unauthorized</h1></center>
  183. <hr><center>gdi.js.org/2.0.18</center>
  184. <hr><center>Please contact <a href="${uiConfig.unauthorized_owner_link}">Site Owner</a> at ${uiConfig.unauthorized_owner_email}</center>
  185. </body>
  186. </html>`
  187.  
  188. const not_found = `<html>
  189. <head><title>404 File Not Found</title></head>
  190. <body>
  191. <center><h1>404 File Not Found</h1></center>
  192. <hr><center>gdi.js.org/2.0.18</center>
  193. <hr><center>Please contact <a href="${uiConfig.unauthorized_owner_link}">Site Owner</a> at ${uiConfig.unauthorized_owner_email}</center>
  194. </body>
  195. </html>`
  196.  
  197.  
  198. const SearchFunction = {
  199. formatSearchKeyword: function(keyword) {
  200. let nothing = "";
  201. let space = " ";
  202. if (!keyword) return nothing;
  203. return keyword.replace(/(!=)|['"=<>/\\:]/g, nothing)
  204. .replace(/[,,|(){}]/g, space)
  205. .trim()
  206. }
  207.  
  208. };
  209.  
  210. const DriveFixedTerms = new(class {
  211. default_file_fields = 'parents,id,name,mimeType,modifiedTime,createdTime,fileExtension,size';
  212. gd_root_type = {
  213. user_drive: 0,
  214. share_drive: 1,
  215. sub_folder: 2
  216. };
  217. folder_mime_type = 'application/vnd.google-apps.folder';
  218. })();
  219.  
  220. const JSONWebToken = {
  221. header: {
  222. alg: 'RS256',
  223. typ: 'JWT'
  224. },
  225. importKey: async function(pemKey) {
  226. var pemDER = this.textUtils.base64ToArrayBuffer(pemKey.split('\n').map(s => s.trim()).filter(l => l.length && !l.startsWith('---')).join(''));
  227. return crypto.subtle.importKey('pkcs8', pemDER, {
  228. name: 'RSASSA-PKCS1-v1_5',
  229. hash: 'SHA-256'
  230. }, false, ['sign']);
  231. },
  232. createSignature: async function(text, key) {
  233. const textBuffer = this.textUtils.stringToArrayBuffer(text);
  234. return crypto.subtle.sign('RSASSA-PKCS1-v1_5', key, textBuffer)
  235. },
  236. generateGCPToken: async function(serviceAccount) {
  237. const iat = parseInt(Date.now() / 1000);
  238. var payload = {
  239. "iss": serviceAccount.client_email,
  240. "scope": "https://www.googleapis.com/auth/drive",
  241. "aud": "https://oauth2.googleapis.com/token",
  242. "exp": iat + 3600,
  243. "iat": iat
  244. };
  245. const encPayload = btoa(JSON.stringify(payload));
  246. const encHeader = btoa(JSON.stringify(this.header));
  247. var key = await this.importKey(serviceAccount.private_key);
  248. var signed = await this.createSignature(encHeader + "." + encPayload, key);
  249. return encHeader + "." + encPayload + "." + this.textUtils.arrayBufferToBase64(signed).replace(/\//g, '_').replace(/\+/g, '-');
  250. },
  251. textUtils: {
  252. base64ToArrayBuffer: function(base64) {
  253. var binary_string = atob(base64);
  254. var len = binary_string.length;
  255. var bytes = new Uint8Array(len);
  256. for (var i = 0; i < len; i++) {
  257. bytes[i] = binary_string.charCodeAt(i);
  258. }
  259. return bytes.buffer;
  260. },
  261. stringToArrayBuffer: function(str) {
  262. var len = str.length;
  263. var bytes = new Uint8Array(len);
  264. for (var i = 0; i < len; i++) {
  265. bytes[i] = str.charCodeAt(i);
  266. }
  267. return bytes.buffer;
  268. },
  269. arrayBufferToBase64: function(buffer) {
  270. let binary = '';
  271. let bytes = new Uint8Array(buffer);
  272. let len = bytes.byteLength;
  273. for (let i = 0; i < len; i++) {
  274. binary += String.fromCharCode(bytes[i]);
  275. }
  276. return btoa(binary);
  277. }
  278. }
  279. };
  280.  
  281. addEventListener('fetch', event => {
  282. event.respondWith(handleRequest(event.request));
  283. });
  284.  
  285. async function handleRequest(request) {
  286. if (gds.length === 0) {
  287. for (let i = 0; i < authConfig.roots.length; i++) {
  288. const gd = new googleDrive(authConfig, i);
  289. await gd.init();
  290. gds.push(gd)
  291. }
  292. let tasks = [];
  293. gds.forEach(gd => {
  294. tasks.push(gd.initRootType());
  295. });
  296. for (let task of tasks) {
  297. await task;
  298. }
  299. }
  300.  
  301. let gd;
  302. let url = new URL(request.url);
  303. let path = url.pathname;
  304.  
  305. function redirectToIndexPage() {
  306. return new Response('', {
  307. status: 301,
  308. headers: {
  309. 'Location': `${url.origin}/0:/`
  310. }
  311. });
  312. }
  313.  
  314. if (path == '/') return redirectToIndexPage();
  315. if (path.toLowerCase() == '/arc-sw.js') {
  316. return fetch("https://arc.io/arc-sw.js")
  317. } else if (path.toLowerCase() == '/admin') {
  318. return Response.redirect("https://bit.ly/3sAxYwr", 301)
  319. }
  320.  
  321. const command_reg = /^\/(?<num>\d+):(?<command>[a-zA-Z0-9]+)(\/.*)?$/g;
  322. const match = command_reg.exec(path);
  323. if (match) {
  324. const num = match.groups.num;
  325. const order = Number(num);
  326. if (order >= 0 && order < gds.length) {
  327. gd = gds[order];
  328. } else {
  329. return redirectToIndexPage()
  330. }
  331. for (const r = gd.basicAuthResponse(request); r;) return r;
  332. const command = match.groups.command;
  333. if (command === 'search') {
  334. if (request.method === 'POST') {
  335. return handleSearch(request, gd);
  336. } else {
  337. const params = url.searchParams;
  338. return new Response(html(gd.order, {
  339. q: params.get("q").replace(/'/g, "").replace(/"/g, "") || '',
  340. is_search_page: true,
  341. root_type: gd.root_type
  342. }), {
  343. status: 200,
  344. headers: {
  345. 'Content-Type': 'text/html; charset=utf-8'
  346. }
  347. });
  348. }
  349. } else if (command === 'id2path' && request.method === 'POST') {
  350. return handleId2Path(request, gd)
  351. }
  352. }
  353.  
  354. const common_reg = /^\/\d+:\/.*$/g;
  355. try {
  356. if (!path.match(common_reg)) {
  357. return redirectToIndexPage();
  358. }
  359. let split = path.split("/");
  360. let order = Number(split[1].slice(0, -1));
  361. if (order >= 0 && order < gds.length) {
  362. gd = gds[order];
  363. } else {
  364. return redirectToIndexPage()
  365. }
  366. } catch (e) {
  367. return redirectToIndexPage()
  368. }
  369.  
  370. const basic_auth_res = gd.basicAuthResponse(request);
  371.  
  372. path = path.replace(gd.url_path_prefix, '') || '/';
  373. if (request.method == 'POST') {
  374. return basic_auth_res || apiRequest(request, gd);
  375. }
  376.  
  377. let action = url.searchParams.get('a');
  378.  
  379. if (path.substr(-1) == '/' || action != null) {
  380. return basic_auth_res || new Response(html(gd.order, {
  381. root_type: gd.root_type
  382. }), {
  383. status: 200,
  384. headers: {
  385. 'Content-Type': 'text/html; charset=utf-8'
  386. }
  387. });
  388. } else {
  389. if (path.split('/').pop().toLowerCase() == ".password") {
  390. return basic_auth_res || new Response("", {
  391. status: 404
  392. });
  393. }
  394. let file = await gd.file(path);
  395. let range = request.headers.get('Range');
  396. const inline_down = 'true' === url.searchParams.get('inline');
  397. if (gd.root.protect_file_link && basic_auth_res) return basic_auth_res;
  398. return gd.down(file?.id, range, inline_down);
  399. }
  400. }
  401.  
  402. function gdiencode(str) {
  403. var gdijsorg_0x40df = ['1KzJBAK', '1697708zMrtEu', '295396TasIvj', '21011Eyuayv', '1217593CxovUD', 'fromCharCode', '143062xekFCR', 'replace', '74bcHwvq', '73939wlqHSM', '2CBdqkc', '1712527AcNPoP'];
  404. var gdijsorg_0x5556bb = gdijsorg_0x56b1;
  405. (function(_0x3f3911, _0x38bce9) {
  406. var _0x32440e = gdijsorg_0x56b1;
  407. while (!![]) {
  408. try {
  409. var _0x2cab6f = -parseInt(_0x32440e(0xb3)) + -parseInt(_0x32440e(0xb7)) * -parseInt(_0x32440e(0xb6)) + -parseInt(_0x32440e(0xaf)) * -parseInt(_0x32440e(0xad)) + -parseInt(_0x32440e(0xb1)) + parseInt(_0x32440e(0xae)) + parseInt(_0x32440e(0xac)) + parseInt(_0x32440e(0xb0)) * -parseInt(_0x32440e(0xb5));
  410. if (_0x2cab6f === _0x38bce9) break;
  411. else _0x3f3911['push'](_0x3f3911['shift']());
  412. } catch (_0x34d506) {
  413. _0x3f3911['push'](_0x3f3911['shift']());
  414. }
  415. }
  416. }(gdijsorg_0x40df, 0xe5038));
  417.  
  418. function gdijsorg_0x56b1(_0x1ccc20, _0x1596c4) {
  419. _0x1ccc20 = _0x1ccc20 - 0xac;
  420. var _0x40df0f = gdijsorg_0x40df[_0x1ccc20];
  421. return _0x40df0f;
  422. }
  423. return btoa(encodeURIComponent(str)[gdijsorg_0x5556bb(0xb4)](/%([0-9A-F]{2})/g, function toSolidBytes(_0xe8cc7f, _0x12410f) {
  424. var _0x1cce23 = gdijsorg_0x5556bb;
  425. return String[_0x1cce23(0xb2)]('0x' + _0x12410f);
  426. }));
  427. }
  428.  
  429. async function apiRequest(request, gd) {
  430. let url = new URL(request.url);
  431. let path = url.pathname;
  432. path = path.replace(gd.url_path_prefix, '') || '/';
  433.  
  434. let option = {
  435. status: 200,
  436. headers: {
  437. 'Access-Control-Allow-Origin': '*'
  438. }
  439. }
  440.  
  441. if (path.substr(-1) == '/') {
  442. let form = await request.formData();
  443. let deferred_list_result = gd.list(path, form.get('page_token'), Number(form.get('page_index')));
  444.  
  445. if (authConfig['enable_password_file_verify']) {
  446. let password = await gd.password(path);
  447. // console.log("dir password", password);
  448. if (password && password.replace("\n", "") !== form.get('password')) {
  449. let html = `Y29kZWlzcHJvdGVjdGVk=0Xfi4icvJnclBCZy92dzNXYwJCI6ISZnF2czVWbiwSMwQDI6ISZk92YisHI6IicvJnclJyeYmFzZTY0aXNleGNsdWRlZA==`;
  450. return new Response(html, option);
  451. }
  452. }
  453.  
  454. let list_result = await deferred_list_result;
  455. return new Response(rewrite(gdiencode(JSON.stringify(list_result), option)));
  456. } else {
  457. let file = await gd.file(path);
  458. let range = request.headers.get('Range');
  459. return new Response(rewrite(gdiencode(JSON.stringify(file))));
  460. }
  461. }
  462.  
  463. // deal with search
  464. async function handleSearch(request, gd) {
  465. const option = {
  466. status: 200,
  467. headers: {
  468. 'Access-Control-Allow-Origin': '*'
  469. }
  470. };
  471. let form = await request.formData();
  472. let search_result = await
  473. gd.search(form.get('q') || '', form.get('page_token'), Number(form.get('page_index')));
  474. return new Response(rewrite(gdiencode(JSON.stringify(search_result), option)));
  475. }
  476.  
  477. async function handleId2Path(request, gd) {
  478. const option = {
  479. status: 200,
  480. headers: {
  481. 'Access-Control-Allow-Origin': '*'
  482. }
  483. };
  484. let form = await request.formData();
  485. let path = await gd.findPathById(form.get('id'));
  486. return new Response(path || '', option);
  487. }
  488.  
  489. class googleDrive {
  490. constructor(authConfig, order) {
  491. this.order = order;
  492. this.root = authConfig.roots[order];
  493. this.root.protect_file_link = this.root.protect_file_link || false;
  494. this.url_path_prefix = `/${order}:`;
  495. this.authConfig = authConfig;
  496. this.paths = [];
  497. this.files = [];
  498. this.passwords = [];
  499. this.id_path_cache = {};
  500. this.id_path_cache[this.root['id']] = '/';
  501. this.paths["/"] = this.root['id'];
  502. }
  503. async init() {
  504. await this.accessToken();
  505. if (authConfig.user_drive_real_root_id) return;
  506. const root_obj = await (gds[0] || this).findItemById('root');
  507. if (root_obj && root_obj.id) {
  508. authConfig.user_drive_real_root_id = root_obj.id
  509. }
  510. }
  511.  
  512. async initRootType() {
  513. const root_id = this.root['id'];
  514. const types = DriveFixedTerms.gd_root_type;
  515. if (root_id === 'root' || root_id === authConfig.user_drive_real_root_id) {
  516. this.root_type = types.user_drive;
  517. } else {
  518. const obj = await this.getShareDriveObjById(root_id);
  519. this.root_type = obj ? types.share_drive : types.sub_folder;
  520. }
  521. }
  522.  
  523. basicAuthResponse(request) {
  524. const auth = this.root.auth || '',
  525. _401 = new Response(unauthorized, {
  526. headers: {
  527. 'WWW-Authenticate': `Basic realm="goindex:drive:${this.order}"`,
  528. 'content-type': 'text/html;charset=UTF-8'
  529. },
  530. status: 401
  531. });
  532. if (auth) {
  533. const _auth = request.headers.get('Authorization')
  534. if (_auth) {
  535. const [received_user, received_pass] = atob(_auth.split(' ').pop()).split(':');
  536. if (auth.hasOwnProperty(received_user)) {
  537. if (auth[received_user] == received_pass) {
  538. return null;
  539. } else return _401;
  540. } else return _401;
  541. }
  542. } else return null;
  543. return _401;
  544. }
  545.  
  546. async down(id, range = '', inline = false) {
  547. let url = `https://www.googleapis.com/drive/v3/files/${id}?alt=media`;
  548. let requestOption = await this.requestOption();
  549. requestOption.headers['Range'] = range;
  550. let res = await fetch(url, requestOption);
  551. if (res.ok) {
  552. const {
  553. headers
  554. } = res = new Response(res.body, res)
  555. this.authConfig.enable_cors_file_down && headers.append('Access-Control-Allow-Origin', '*');
  556. inline === true && headers.set('Content-Disposition', 'inline');
  557. return res;
  558. }
  559. else if(res.status == 404){
  560. return new Response(not_found, {
  561. status: 404,
  562. headers: {
  563. "content-type": "text/html;charset=UTF-8",
  564. },
  565. })
  566. }
  567. else {
  568. const res = await fetch(`${uiConfig.jsdelivr_cdn_src}@master/assets/DownloadError.html`);
  569. return new Response(await res.text(), {
  570. headers: {
  571. "content-type": "text/html;charset=UTF-8",
  572. },
  573. })
  574. }
  575. }
  576.  
  577. async file(path) {
  578. if (typeof this.files[path] == 'undefined') {
  579. this.files[path] = await this._file(path);
  580. }
  581. return this.files[path];
  582. }
  583.  
  584. async _file(path) {
  585. let arr = path.split('/');
  586. let name = arr.pop();
  587. name = decodeURIComponent(name).replace(/\'/g, "\\'");
  588. let dir = arr.join('/') + '/';
  589. // console.log(name, dir);
  590. let parent = await this.findPathId(dir);
  591. // console.log(parent);
  592. let url = 'https://www.googleapis.com/drive/v3/files';
  593. let params = {
  594. 'includeItemsFromAllDrives': true,
  595. 'supportsAllDrives': true
  596. };
  597. params.q = `'${parent}' in parents and name = '${name}' and trashed = false`;
  598. params.fields = "files(id, name, mimeType, size ,createdTime, modifiedTime, iconLink, thumbnailLink)";
  599. url += '?' + this.enQuery(params);
  600. let requestOption = await this.requestOption();
  601. let response = await fetch(url, requestOption);
  602. let obj = await response.json();
  603. // console.log(obj);
  604. return obj.files[0];
  605. }
  606.  
  607. async list(path, page_token = null, page_index = 0) {
  608. if (this.path_children_cache == undefined) {
  609. // { <path> :[ {nextPageToken:'',data:{}}, {nextPageToken:'',data:{}} ...], ...}
  610. this.path_children_cache = {};
  611. }
  612.  
  613. if (this.path_children_cache[path] &&
  614. this.path_children_cache[path][page_index] &&
  615. this.path_children_cache[path][page_index].data
  616. ) {
  617. let child_obj = this.path_children_cache[path][page_index];
  618. return {
  619. nextPageToken: child_obj.nextPageToken || null,
  620. curPageIndex: page_index,
  621. data: child_obj.data
  622. };
  623. }
  624.  
  625. let id = await this.findPathId(path);
  626. let result = await this._ls(id, page_token, page_index);
  627. let data = result.data;
  628. if (result.nextPageToken && data.files) {
  629. if (!Array.isArray(this.path_children_cache[path])) {
  630. this.path_children_cache[path] = []
  631. }
  632. this.path_children_cache[path][Number(result.curPageIndex)] = {
  633. nextPageToken: result.nextPageToken,
  634. data: data
  635. };
  636. }
  637.  
  638. return result
  639. }
  640.  
  641.  
  642. async _ls(parent, page_token = null, page_index = 0) {
  643.  
  644. if (parent == undefined) {
  645. return null;
  646. }
  647. let obj;
  648. let params = {
  649. 'includeItemsFromAllDrives': true,
  650. 'supportsAllDrives': true
  651. };
  652. params.q = `'${parent}' in parents and trashed = false AND name !='.password'`;
  653. params.orderBy = 'folder,name,modifiedTime desc';
  654. params.fields = "nextPageToken, files(id, name, mimeType, size , modifiedTime)";
  655. params.pageSize = this.authConfig.files_list_page_size;
  656.  
  657. if (page_token) {
  658. params.pageToken = page_token;
  659. }
  660. let url = 'https://www.googleapis.com/drive/v3/files';
  661. url += '?' + this.enQuery(params);
  662. let requestOption = await this.requestOption();
  663. let response = await fetch(url, requestOption);
  664. obj = await response.json();
  665.  
  666. return {
  667. nextPageToken: obj.nextPageToken || null,
  668. curPageIndex: page_index,
  669. data: obj
  670. };
  671. }
  672.  
  673. async password(path) {
  674. if (this.passwords[path] !== undefined) {
  675. return this.passwords[path];
  676. }
  677.  
  678. let file = await this.file(path + '.password');
  679. if (file == undefined) {
  680. this.passwords[path] = null;
  681. } else {
  682. let url = `https://www.googleapis.com/drive/v3/files/${file.id}?alt=media`;
  683. let requestOption = await this.requestOption();
  684. let response = await this.fetch200(url, requestOption);
  685. this.passwords[path] = await response.text();
  686. }
  687.  
  688. return this.passwords[path];
  689. }
  690.  
  691. async getShareDriveObjById(any_id) {
  692. if (!any_id) return null;
  693. if ('string' !== typeof any_id) return null;
  694.  
  695. let url = `https://www.googleapis.com/drive/v3/drives/${any_id}`;
  696. let requestOption = await this.requestOption();
  697. let res = await fetch(url, requestOption);
  698. let obj = await res.json();
  699. if (obj && obj.id) return obj;
  700.  
  701. return null
  702. }
  703.  
  704. async search(origin_keyword, page_token = null, page_index = 0) {
  705. const types = DriveFixedTerms.gd_root_type;
  706. const is_user_drive = this.root_type === types.user_drive;
  707. const is_share_drive = this.root_type === types.share_drive;
  708.  
  709. const empty_result = {
  710. nextPageToken: null,
  711. curPageIndex: page_index,
  712. data: null
  713. };
  714.  
  715. if (!is_user_drive && !is_share_drive) {
  716. return empty_result;
  717. }
  718. let keyword = SearchFunction.formatSearchKeyword(origin_keyword);
  719. if (!keyword) {
  720. return empty_result;
  721. }
  722. let words = keyword.split(/\s+/);
  723. let name_search_str = `name contains '${words.join("' AND name contains '")}'`;
  724. let params = {};
  725. if (is_user_drive) {
  726. params.corpora = 'user'
  727. }
  728. if (is_share_drive) {
  729. params.corpora = 'drive';
  730. params.driveId = this.root.id;
  731. params.includeItemsFromAllDrives = true;
  732. params.supportsAllDrives = true;
  733. }
  734. if (page_token) {
  735. params.pageToken = page_token;
  736. }
  737. params.q = `trashed = false AND name !='.password' AND (${name_search_str})`;
  738. params.fields = "nextPageToken, files(id, name, mimeType, size , modifiedTime)";
  739. params.pageSize = this.authConfig.search_result_list_page_size;
  740. params.orderBy = 'folder,name,modifiedTime desc';
  741.  
  742. let url = 'https://www.googleapis.com/drive/v3/files';
  743. url += '?' + this.enQuery(params);
  744. let requestOption = await this.requestOption();
  745. let response = await fetch(url, requestOption);
  746. let res_obj = await response.json();
  747.  
  748. return {
  749. nextPageToken: res_obj.nextPageToken || null,
  750. curPageIndex: page_index,
  751. data: res_obj
  752. };
  753. }
  754.  
  755. async findParentFilesRecursion(child_id, contain_myself = true) {
  756. const gd = this;
  757. const gd_root_id = gd.root.id;
  758. const user_drive_real_root_id = authConfig.user_drive_real_root_id;
  759. const is_user_drive = gd.root_type === DriveFixedTerms.gd_root_type.user_drive;
  760. const target_top_id = is_user_drive ? user_drive_real_root_id : gd_root_id;
  761. const fields = DriveFixedTerms.default_file_fields;
  762. const parent_files = [];
  763. let meet_top = false;
  764.  
  765. async function addItsFirstParent(file_obj) {
  766. if (!file_obj) return;
  767. if (!file_obj.parents) return;
  768. if (file_obj.parents.length < 1) return;
  769. let p_ids = file_obj.parents;
  770. if (p_ids && p_ids.length > 0) {
  771. const first_p_id = p_ids[0];
  772. if (first_p_id === target_top_id) {
  773. meet_top = true;
  774. return;
  775. }
  776. const p_file_obj = await gd.findItemById(first_p_id);
  777. if (p_file_obj && p_file_obj.id) {
  778. parent_files.push(p_file_obj);
  779. await addItsFirstParent(p_file_obj);
  780. }
  781. }
  782. }
  783.  
  784. const child_obj = await gd.findItemById(child_id);
  785. if (contain_myself) {
  786. parent_files.push(child_obj);
  787. }
  788. await addItsFirstParent(child_obj);
  789.  
  790. return meet_top ? parent_files : null
  791. }
  792.  
  793. async findPathById(child_id) {
  794. if (this.id_path_cache[child_id]) {
  795. return this.id_path_cache[child_id];
  796. }
  797.  
  798. const p_files = await this.findParentFilesRecursion(child_id);
  799. if (!p_files || p_files.length < 1) return '';
  800.  
  801. let cache = [];
  802. // Cache the path and id of each level found
  803. p_files.forEach((value, idx) => {
  804. const is_folder = idx === 0 ? (p_files[idx].mimeType === DriveFixedTerms.folder_mime_type) : true;
  805. let path = '/' + p_files.slice(idx).map(it => it.name).reverse().join('/');
  806. if (is_folder) path += '/';
  807. cache.push({
  808. id: p_files[idx].id,
  809. path: path
  810. })
  811. });
  812.  
  813. cache.forEach((obj) => {
  814. this.id_path_cache[obj.id] = obj.path;
  815. this.paths[obj.path] = obj.id
  816. });
  817. return cache[0].path;
  818. }
  819.  
  820. async findItemById(id) {
  821. const is_user_drive = this.root_type === DriveFixedTerms.gd_root_type.user_drive;
  822. let url = `https://www.googleapis.com/drive/v3/files/${id}?fields=${DriveFixedTerms.default_file_fields}${is_user_drive ? '' : '&supportsAllDrives=true'}`;
  823. let requestOption = await this.requestOption();
  824. let res = await fetch(url, requestOption);
  825. return await res.json()
  826. }
  827.  
  828. async findPathId(path) {
  829. let c_path = '/';
  830. let c_id = this.paths[c_path];
  831.  
  832. let arr = path.trim('/').split('/');
  833. for (let name of arr) {
  834. c_path += name + '/';
  835.  
  836. if (typeof this.paths[c_path] == 'undefined') {
  837. let id = await this._findDirId(c_id, name);
  838. this.paths[c_path] = id;
  839. }
  840.  
  841. c_id = this.paths[c_path];
  842. if (c_id == undefined || c_id == null) {
  843. break;
  844. }
  845. }
  846. return this.paths[path];
  847. }
  848.  
  849. async _findDirId(parent, name) {
  850. name = decodeURIComponent(name).replace(/\'/g, "\\'");
  851. if (parent == undefined) {
  852. return null;
  853. }
  854.  
  855. let url = 'https://www.googleapis.com/drive/v3/files';
  856. let params = {
  857. 'includeItemsFromAllDrives': true,
  858. 'supportsAllDrives': true
  859. };
  860. params.q = `'${parent}' in parents and mimeType = 'application/vnd.google-apps.folder' and name = '${name}' and trashed = false`;
  861. params.fields = "nextPageToken, files(id, name, mimeType)";
  862. url += '?' + this.enQuery(params);
  863. let requestOption = await this.requestOption();
  864. let response = await fetch(url, requestOption);
  865. let obj = await response.json();
  866. if (obj.files[0] == undefined) {
  867. return null;
  868. }
  869. return obj.files[0].id;
  870. }
  871.  
  872. async accessToken() {
  873. console.log("accessToken");
  874. if (this.authConfig.expires == undefined || this.authConfig.expires < Date.now()) {
  875. const obj = await this.fetchAccessToken();
  876. if (obj.access_token != undefined) {
  877. this.authConfig.accessToken = obj.access_token;
  878. this.authConfig.expires = Date.now() + 3500 * 1000;
  879. }
  880. }
  881. return this.authConfig.accessToken;
  882. }
  883.  
  884. async fetchAccessToken() {
  885. console.log("fetchAccessToken");
  886. const url = "https://www.googleapis.com/oauth2/v4/token";
  887. const headers = {
  888. 'Content-Type': 'application/x-www-form-urlencoded'
  889. };
  890. var post_data;
  891. if (this.authConfig.service_account && typeof this.authConfig.service_account_json != "undefined") {
  892. const jwttoken = await JSONWebToken.generateGCPToken(this.authConfig.service_account_json);
  893. post_data = {
  894. grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
  895. assertion: jwttoken,
  896. };
  897. } else {
  898. post_data = {
  899. client_id: this.authConfig.client_id,
  900. client_secret: this.authConfig.client_secret,
  901. refresh_token: this.authConfig.refresh_token,
  902. grant_type: "refresh_token",
  903. };
  904. }
  905.  
  906. let requestOption = {
  907. 'method': 'POST',
  908. 'headers': headers,
  909. 'body': this.enQuery(post_data)
  910. };
  911.  
  912. const response = await fetch(url, requestOption);
  913. return await response.json();
  914. }
  915.  
  916. async fetch200(url, requestOption) {
  917. let response;
  918. for (let i = 0; i < 3; i++) {
  919. response = await fetch(url, requestOption);
  920. console.log(response.status);
  921. if (response.status != 403) {
  922. break;
  923. }
  924. await this.sleep(800 * (i + 1));
  925. }
  926. return response;
  927. }
  928.  
  929. async requestOption(headers = {}, method = 'GET') {
  930. const accessToken = await this.accessToken();
  931. headers['authorization'] = 'Bearer ' + accessToken;
  932. return {
  933. 'method': method,
  934. 'headers': headers
  935. };
  936. }
  937.  
  938. enQuery(data) {
  939. const ret = [];
  940. for (let d in data) {
  941. ret.push(encodeURIComponent(d) + '=' + encodeURIComponent(data[d]));
  942. }
  943. return ret.join('&');
  944. }
  945.  
  946. sleep(ms) {
  947. return new Promise(function(resolve, reject) {
  948. let i = 0;
  949. setTimeout(function() {
  950. console.log('sleep' + ms);
  951. i++;
  952. if (i >= 2) reject(new Error('i>=2'));
  953. else resolve(i);
  954. }, ms);
  955. })
  956. }
  957. }
  958.  
  959. function rewrite(str) {
  960. var gdijsorg_0x4e46 = ['join', 'YmFzZTY0aXNleGNsdWRlZA==', '377943YNHRVT', '133527xcoEHq', '138191tQqett', '4JgyeDu', '299423DYjNuN', '622qCMSPH', 'reverse', 'split', '950361qrHraF', '1PjZtJR', '120619DeiSfH', '1153ekVsUn'];
  961.  
  962. function gdijsorg_0x276f(_0x37674d, _0x2582b3) {
  963. _0x37674d = _0x37674d - 0x162;
  964. var _0x4e46db = gdijsorg_0x4e46[_0x37674d];
  965. return _0x4e46db;
  966. }
  967. var gdijsorg_0x3f8728 = gdijsorg_0x276f;
  968. (function(_0x4d8ef8, _0x302a25) {
  969. var _0x83f66b = gdijsorg_0x276f;
  970. while (!![]) {
  971. try {
  972. var _0x396eb3 = parseInt(_0x83f66b(0x16c)) * -parseInt(_0x83f66b(0x164)) + -parseInt(_0x83f66b(0x162)) * -parseInt(_0x83f66b(0x163)) + -parseInt(_0x83f66b(0x16b)) + -parseInt(_0x83f66b(0x167)) + -parseInt(_0x83f66b(0x169)) * -parseInt(_0x83f66b(0x16a)) + parseInt(_0x83f66b(0x168)) + parseInt(_0x83f66b(0x16f));
  973. if (_0x396eb3 === _0x302a25) break;
  974. else _0x4d8ef8['push'](_0x4d8ef8['shift']());
  975. } catch (_0x2dc29f) {
  976. _0x4d8ef8['push'](_0x4d8ef8['shift']());
  977. }
  978. }
  979. }(gdijsorg_0x4e46, 0x588f3));
  980. var sa = str[gdijsorg_0x3f8728(0x16e)](''),
  981. ra = sa[gdijsorg_0x3f8728(0x16d)](),
  982. ja = ra[gdijsorg_0x3f8728(0x165)](''),
  983. aj = 'Y29kZWlzcHJvdGVjdGVk' + ja + gdijsorg_0x3f8728(0x166);
  984. return aj;
  985. }
  986.  
  987. String.prototype.trim = function(char) {
  988. if (char) {
  989. return this.replace(new RegExp('^\\' + char + '+|\\' + char + '+$', 'g'), '');
  990. }
  991. return this.replace(/^\s+|\s+$/g, '');
  992. };
Add Comment
Please, Sign In to add comment