Skip to content

Instantly share code, notes, and snippets.

@Hevanafa
Last active February 5, 2023 03:06
Show Gist options
  • Save Hevanafa/d4807cfa2280647e4f62c956e753644c to your computer and use it in GitHub Desktop.
Save Hevanafa/d4807cfa2280647e4f62c956e753644c to your computer and use it in GitHub Desktop.
Deno YouTube Thumbnail Downloader
// deno run --allow-net --allow-write .\demo_script.ts
// YouTube Thumbnail Downloader
// By Hevanafa, 31-01-2023
// Edit 03-02-2023: trailing query string detection
// Edit 05-02-2023: hqdefault & maxresdefault_live detection
import { DOMParser } from "https://deno.land/x/deno_dom/deno-dom-wasm.ts";
import { copy, readerFromStreamReader } from "https://deno.land/std@0.175.0/streams/mod.ts";
if (Deno.args.length < 1) {
console.log("URL is required.");
Deno.exit(0);
}
// Obtain the download link
let href = "";
try {
const origin = Deno.args[0]; // "https://www.youtube.com/watch?v=kJGsWORSg-4";
const res = await fetch(origin);
const html = await res.text();
const document = new DOMParser().parseFromString(html, "text/html");
const link = document?.querySelector("link[itemprop=\"thumbnailUrl\"]");
href = link?.getAttribute("href") ?? "";
console.log("Got the link: %s", href);
} catch (e) {
console.error(e);
Deno.exit(1);
}
// Obtain the filename
// const chunks = href.split("/");
// const hash = chunks.at(-2) ?? "";
// const ext = (chunks.at(-1) ?? "").split(".")[1];
let match = href.match(/\/vi\/(.*?)\/maxresdefault\.(jpg|png)/);
// console.log(match);
// Deno.exit(0);
if (!match) {
console.error("Attempt 1 failed: Couldn't find maxresdefault.");
match = href.match(/\/vi\/(.*?)\/hqdefault\.(jpg|png)/);
if (!match) {
console.error("Attempt 2 failed: Couldn't find hqdefault.");
match = href.match(/\/vi\/(.*?)\/maxresdefault_live\.(jpg|png)/);
if (!match) {
console.error("Attempt 3 failed: Couldn't find maxresdefault_live.");
Deno.exit(1);
}
}
}
const hash = match[1];
const ext = match[2];
const filename = `${hash}.${ext}`;
console.log("%c%s", "color: #00ff00", filename);
// Create the "thumbs" folder
try {
await Deno.mkdir("thumbs");
} catch (e) {
// console.error(e);
}
// Download the thumbnail
try {
const origin = href;
const response = await fetch(origin);
const reader = response.body?.getReader();
if (reader) {
const r = readerFromStreamReader(reader);
const f = await Deno.open(`./thumbs/${filename}`, { create: true, write: true });
await copy(r, f);
f.close();
console.log("Thumbnail has been downloaded.");
}
} catch (e) {
console.error(e);
Deno.exit(1);
}
# .\run_deno [YouTube_url]
# .\run_deno https://www.youtube.com/watch?v=dQw4w9WgXcQ
deno run --allow-net --allow-write .\downloader.ts $args
# Refs:
# https://stackoverflow.com/questions/45760457/how-can-i-run-a-powershell-script-with-white-spaces-in-the-path-from-the-command
# https://lazyadmin.nl/powershell/run-a-powershell-script/
# powershell -noexit -file "{}"
# Ref: https://caiomsouza.medium.com/fix-for-powershell-script-not-digitally-signed-69f0ed518715
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
# Ref: https://superuser.com/questions/446827/configure-windows-powershell-to-display-only-the-current-folder-name-in-the-shel
function prompt { "$p> " }
write-output "This program requires Deno in order to work."
write-output "Enter .\run_deno to start."
write-output "Enter ""explorer .\thumbs"" to open downloaded thumbnails."
write-output ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment