From e61343f04fa4f1bb2f9c4ea2ff30b6b024d4d1e2 Mon Sep 17 00:00:00 2001 From: yourfriendoss Date: Sat, 20 Dec 2025 13:55:17 +0200 Subject: [PATCH] add sendgb downloader like a boss --- package.json | 4 +- src/sendgb.js | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 src/sendgb.js diff --git a/package.json b/package.json index 1fc25ad..3f7d2f0 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "deezify": "bun run src/deezify.js", "now-playing": "bun run src/now-playing.js", "request-bot": "bun run src/request-bot.js", - "pillow": "bun run src/pillow.js" - + "pillow": "bun run src/pillow.js", + "sendgb": "bun run src/sendgb.js" }, "engineStrict": true, "engines": { diff --git a/src/sendgb.js b/src/sendgb.js new file mode 100644 index 0000000..e474054 --- /dev/null +++ b/src/sendgb.js @@ -0,0 +1,103 @@ +import fs from "fs"; + +const C = { + info: msg => console.log("\x1b[36m[i]\x1b[0m " + msg), + ok: msg => console.log("\x1b[32m[✓]\x1b[0m " + msg), + warn: msg => console.log("\x1b[33m[!]\x1b[0m " + msg), + err: msg => console.log("\x1b[31m[✗]\x1b[0m " + msg), +}; + +const base = "https://sendgb.com/"; +const url = process.argv[2]; + +if (!url || !url.startsWith(base)) { + C.err("Usage: node sendgb.js "); + process.exit(1); +} + +C.info(`Fetching page: ${url}`); + +const page = await fetch(url); +const html = await page.text(); + +const sendgb_session = page.headers + .getSetCookie() + .find(c => c.startsWith("sendgb_ses=")) + ?.split(";")[0] + .split("=") + .at(-1); + +if (!sendgb_session) { + C.err("Failed to extract sendgb session cookie"); + process.exit(1); +} + +const get = (re) => [...html.matchAll(re)][0]?.[1]; + +const link = get(/
]*value="([^"]*)"/gm); +const total_files = get(/name="total_files"[^>]*value="(\d+)"/gm); + +if (!link || !secret || !total_files) { + C.err("Failed to parse download form"); + process.exit(1); +} + +C.info(`Files: ${total_files}`); +C.info("Requesting ZIP…"); + +const res = await fetch(link, { + method: "POST", + body: new URLSearchParams({ + action: "download", + secret_code: secret, + private_id: "", + download_id: url.replace(base, ""), + total_files + }), + headers: { + "User-Agent": "Mozilla/5.0" + } +}); + +if (!res.ok || !res.body) { + C.err(`Download failed (${res.status})`); + process.exit(1); +} + +C.info("Content-type: " + res.headers.get("content-type")) +const filename = + res.headers.get("content-disposition")?.match(/filename="?([^"]+)"?/)?.[1] + ?? "download.zip"; + +C.info(`Downloading ${filename}`); + +const file = fs.createWriteStream(filename); +const reader = res.body.getReader(); + +let downloaded = 0; +const total = Number(res.headers.get("content-length")) || 0; +const start = Date.now(); + +while (true) { + const { done, value } = await reader.read(); + if (done) break; + + file.write(value); + downloaded += value.length; + + if (total) { + const pct = ((downloaded / total) * 100).toFixed(1); + const mb = (downloaded / 1024 / 1024).toFixed(2); + const tmb = (total / 1024 / 1024).toFixed(2); + process.stdout.write(`\r${pct}% ${mb}/${tmb} MB`); + } else { + const mb = (downloaded / 1024 / 1024).toFixed(2); + process.stdout.write(`\r${mb} MB`); + } +} + +file.end(); + +process.stdout.write("\n"); +C.ok(`Saved as ${filename} in ${((Date.now() - start) / 1000).toFixed(1)}s`);