From ac781c36f6b3d8e39b2e3e1fde3ed2b5e00ba0ea Mon Sep 17 00:00:00 2001 From: optionallychained <6907442+optionallychained@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:25:12 +0100 Subject: [PATCH 1/3] refactor js version for clarity + speed --- mkbsd.js | 169 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 113 insertions(+), 56 deletions(-) diff --git a/mkbsd.js b/mkbsd.js index d02593a..54dee5a 100644 --- a/mkbsd.js +++ b/mkbsd.js @@ -1,61 +1,32 @@ // Copyright 2024 Nadim Kobeissi // Licensed under the WTFPL License -const fs = require(`fs`); -const path = require(`path`); +const { existsSync, mkdirSync, rmSync, readdirSync, writeFileSync } = require(`fs`); +const { extname, join } = require(`path`); -async function main() { - const url = 'https://storage.googleapis.com/panels-api/data/20240916/media-1a-i-p~s'; - const delay = (ms) => { - return new Promise(resolve => setTimeout(resolve, ms)); - } - try { - const response = await fetch(url); - if (!response.ok) { - throw new Error(`ā›” Failed to fetch JSON file: ${response.statusText}`); - } - const jsonData = await response.json(); - const data = jsonData.data; - if (!data) { - throw new Error('ā›” JSON does not have a "data" property at its root.'); - } - const downloadDir = path.join(__dirname, 'downloads'); - if (!fs.existsSync(downloadDir)) { - fs.mkdirSync(downloadDir); - console.info(`šŸ“ Created directory: ${downloadDir}`); - } - let fileIndex = 1; - for (const key in data) { - const subproperty = data[key]; - if (subproperty && subproperty.dhd) { - const imageUrl = subproperty.dhd; - console.info(`šŸ” Found image URL!`); - await delay(100); - const ext = path.extname(new URL(imageUrl).pathname) || '.jpg'; - const filename = `${fileIndex}${ext}`; - const filePath = path.join(downloadDir, filename); - await downloadImage(imageUrl, filePath); - console.info(`šŸ–¼ļø Saved image to ${filePath}`); - fileIndex++; - await delay(250); - } - } - } catch (error) { - console.error(`Error: ${error.message}`); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// UTILITIES +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const printError = (message, { exit } = { exit: true }) => { + console.error(`\nā›” ${message}`) + + if (exit) { + process.exit(1) } } -async function downloadImage(url, filePath) { - const response = await fetch(url); - if (!response.ok) { - throw new Error(`Failed to download image: ${response.statusText}`); - } - const arrayBuffer = await response.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - await fs.promises.writeFile(filePath, buffer); +const printSuccess = (message) => { + console.info(`āœ… ${message}`) } -function asciiArt() { +const printLineBreak = () => { + console.log(`\n------------------------------------------\n`) +} + +const delayBy = async (ms, cb) => await new Promise((resolve) => setTimeout(() => resolve(cb()), ms)) + +const printAscii = () => { console.info(` /$$ /$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$$ | $$$ /$$$| $$ /$$/| $$__ $$ /$$__ $$| $$__ $$ @@ -64,12 +35,98 @@ function asciiArt() { | $$ $$$| $$| $$ $$ | $$__ $$ \\____ $$| $$ | $$ | $$\\ $ | $$| $$\\ $$ | $$ \\ $$ /$$ \\ $$| $$ | $$ | $$ \\/ | $$| $$ \\ $$| $$$$$$$/| $$$$$$/| $$$$$$$/ -|__/ |__/|__/ \\__/|_______/ \\______/ |_______/`); - console.info(``); - console.info(`šŸ¤‘ Starting downloads from your favorite sellout grifter's wallpaper app...`); +|__/ |__/|__/ \\__/|_______/ \\______/ |_______/ + +šŸ¤‘ Starting downloads from your favorite sellout grifter's wallpaper app...`) } -(() => { - asciiArt(); - setTimeout(main, 5000); -})(); +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// ACTIONS +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const fetchAssetData = async () => { + try { + const response = await fetch('https://storage.googleapis.com/panels-api/data/20240916/media-1a-i-p~s') + if (!response.ok) { + printError(`Failed to fetch asset data from Panels API: ${response.statusText}`) + } + + const { data } = await response.json() + if (!data) { + printError('Failed to fetch asset data from Panels API: data not found') + } + + printSuccess(`Successfully downloaded asset data from Panels API`) + + return data + } + catch (error) { + error(`Error downloading asset data from Panels API: ${error}`) + } +} + +const initializeDownloadDirectory = () => { + try { + const downloadDirectory = join(__dirname, 'downloads') + + if (existsSync(downloadDirectory)) { + rmSync(downloadDirectory, { recursive: true, force: true }) + } + mkdirSync(downloadDirectory) + + printSuccess(`Initialized download directory: ${downloadDirectory}`) + + return downloadDirectory + } + catch (error) { + exitWithError(`ā›” Error initializing download directory '${downloadDirectory}': ${error}`) + } +} + +const downloadImages = (data, downloadDirectory) => + Promise.all( + Object.values(data) + .filter((assetMap) => !!assetMap.dhd) + .map(({ dhd: url }, i) => { + // TODO extract actual image name past /content to first ? + const fileName = `${i + 1}${extname(new URL(url).pathname) || '.jpg'}` + const filePath = join(downloadDirectory, fileName) + + return fetch(url) + .then(async (response) => { + if (!response.ok) { + printError(`Failed to download image '${url}' with status text: '${response.statusText}'`, { exit: false }) + return + } + + writeFileSync(filePath, Buffer.from(await response.arrayBuffer())) + + printSuccess(`Downloaded image: ${url}`) + }) + .catch((error) => { + error(`Failed to download image '${url}' with error: ${error}`, { exit: false }) + }) + }) + ) + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// SCRIPT +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +const mkbsd = async () => { + printAscii() + printLineBreak() + + const data = await delayBy(500, fetchAssetData) + const downloadDirectory = await delayBy(500, initializeDownloadDirectory) + + printLineBreak() + console.log('Beginning image download...\n\n') + + await delayBy(500, downloadImages.bind(null, data, downloadDirectory)) + + printLineBreak() + printSuccess(`DONE! Downloaded ${readdirSync(downloadDirectory).length} images from Panels API`) +} + +mkbsd() \ No newline at end of file From 5ca589bd545a0ce83b73d86041fe81e370987412 Mon Sep 17 00:00:00 2001 From: optionallychained <6907442+optionallychained@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:05:10 +0100 Subject: [PATCH 2/3] extract image names from urls --- mkbsd.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mkbsd.js b/mkbsd.js index 54dee5a..0a5b696 100644 --- a/mkbsd.js +++ b/mkbsd.js @@ -40,6 +40,15 @@ const printAscii = () => { šŸ¤‘ Starting downloads from your favorite sellout grifter's wallpaper app...`) } +const extractImageName = (url) => + decodeURIComponent( + (new RegExp(/^https:\/\/.*\/content\/(.*.[a-zA-Z])\?/).exec(url)[1] || '') + .replace(`a~`, '') + .replace(/(_[a-z0-9]+)\//, ' - ') + .replace('/', ' - ') + .replace(/~+/g, ' ') + ) + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ACTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -88,8 +97,7 @@ const downloadImages = (data, downloadDirectory) => Object.values(data) .filter((assetMap) => !!assetMap.dhd) .map(({ dhd: url }, i) => { - // TODO extract actual image name past /content to first ? - const fileName = `${i + 1}${extname(new URL(url).pathname) || '.jpg'}` + const fileName = `[${i + 1}] - ${extractImageName(url)}` const filePath = join(downloadDirectory, fileName) return fetch(url) From ac2fedf2655cb353d3c73b180b474e4496d9bd66 Mon Sep 17 00:00:00 2001 From: optionallychained <6907442+optionallychained@users.noreply.github.com> Date: Thu, 26 Sep 2024 16:29:21 +0100 Subject: [PATCH 3/3] small fix --- mkbsd.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mkbsd.js b/mkbsd.js index 0a5b696..27ff39f 100644 --- a/mkbsd.js +++ b/mkbsd.js @@ -70,7 +70,7 @@ const fetchAssetData = async () => { return data } catch (error) { - error(`Error downloading asset data from Panels API: ${error}`) + printError(`Error downloading asset data from Panels API: ${error}`) } } @@ -88,7 +88,7 @@ const initializeDownloadDirectory = () => { return downloadDirectory } catch (error) { - exitWithError(`ā›” Error initializing download directory '${downloadDirectory}': ${error}`) + printError(`Error initializing download directory '${downloadDirectory}': ${error}`) } } @@ -112,7 +112,7 @@ const downloadImages = (data, downloadDirectory) => printSuccess(`Downloaded image: ${url}`) }) .catch((error) => { - error(`Failed to download image '${url}' with error: ${error}`, { exit: false }) + printError(`Failed to download image '${url}' with error: ${error}`, { exit: false }) }) }) )