This commit is contained in:
retardgerman 2024-10-11 09:04:36 +02:00 committed by GitHub
commit 383ef1238b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 3756 additions and 89 deletions

View file

@ -18,15 +18,22 @@ MKBSD comes in two variants! Node.js and Python.
### Running in Node.js ### Running in Node.js
1. Ensure you have Node.js installed. 1. Ensure you have Node.js installed.
2. Run `node mkbsd.js` 2. Save the `images.json` file in the same directory as `mkbsd.js`.
3. Wait a little. 3. Run `node mkbsd.js`.
4. All wallpapers are now in a newly created `downloads` subfolder. 4. Wait a little.
5. All wallpapers are now in a newly created `downloads` subfolder.
### Changes Made in `mkbsd.js and mkbsd.py`
- **Local JSON Source**: The script was updated to read from a local `images.json` file instead of fetching data from a remote URL. This allows you to have full control over the data source.
- **File System Operations**: The script now uses Node.js's `fs` module to read and parse the JSON file directly.
- **Image Download Logic**: The image download logic was adapted to extract the artist's name and image URLs from the local JSON structure, ensuring the images are saved in artist-specific folders.
### Running in Python ### Running in Python
1. Ensure you have Python installed. 1. Ensure you have Python installed.
2. Ensure you have the `aiohttp` Python package installed (`pip install aiohttp`). 2. Save the `images.json` file in the same directory as `mkbsd.py`.
3. Run `python mkbsd.py` 3. Run `python mkbsd.py`.
4. Wait a little. 4. Wait a little.
5. All wallpapers are now in a newly created `downloads` subfolder. 5. All wallpapers are now in a newly created `downloads` subfolder.

3638
images.json Normal file

File diff suppressed because it is too large Load diff

128
mkbsd.js
View file

@ -1,62 +1,82 @@
// Copyright 2024 Nadim Kobeissi const fs = require('fs');
// Licensed under the WTFPL License const path = require('path');
const fs = require(`fs`); // Function to delay the downloads
const path = require(`path`); const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
async function main() { async function main() {
const url = 'https://storage.googleapis.com/panels-api/data/20240916/media-1a-i-p~s'; const jsonFilePath = path.join(__dirname, 'images.json');
const delay = (ms) => {
return new Promise(resolve => setTimeout(resolve, ms)); // Load local JSON file
} let jsonData;
try { try {
const response = await fetch(url); if (!fs.existsSync(jsonFilePath)) {
if (!response.ok) { throw new Error('⛔ JSON file not found.');
throw new Error(`⛔ Failed to fetch JSON file: ${response.statusText}`); }
}
const jsonData = await response.json(); const jsonFileContent = fs.readFileSync(jsonFilePath, 'utf-8');
const data = jsonData.data; jsonData = JSON.parse(jsonFileContent);
if (!data) { console.info('📂 JSON file loaded successfully!');
throw new Error('⛔ JSON does not have a "data" property at its root.'); } catch (error) {
} console.error(`⛔ Failed to load JSON file: ${error.message}`);
const downloadDir = path.join(__dirname, 'downloads'); return;
if (!fs.existsSync(downloadDir)) { }
fs.mkdirSync(downloadDir);
console.info(`📁 Created directory: ${downloadDir}`); const data = jsonData.data;
} if (!data) {
let fileIndex = 1; console.error('⛔ JSON does not have a "data" property at its root.');
for (const key in data) { return;
const subproperty = data[key]; }
if (subproperty && subproperty.dhd) {
const imageUrl = subproperty.dhd; // Loop through each item in the JSON
console.info(`🔍 Found image URL!`); for (const key in data) {
await delay(100); const subproperty = data[key];
const ext = path.extname(new URL(imageUrl).pathname) || '.jpg'; if (subproperty && subproperty.dhd) {
const filename = `${fileIndex}${ext}`; const imageUrl = subproperty.dhd;
const filePath = path.join(downloadDir, filename); console.info(`🔍 Found image URL!`);
await downloadImage(imageUrl, filePath);
console.info(`🖼️ Saved image to ${filePath}`); // Extract the artist name before the underscore
fileIndex++; const artistNameMatch = imageUrl.match(/a~([^_/]+)/);
await delay(250); const artistName = artistNameMatch ? artistNameMatch[1] : 'unknown_artist';
} const artistDir = path.join(__dirname, 'downloads', artistName);
}
} catch (error) { // Create artist directory if it doesn't exist
console.error(`Error: ${error.message}`); if (!fs.existsSync(artistDir)) {
} fs.mkdirSync(artistDir, { recursive: true });
console.info(`📁 Created directory: ${artistDir}`);
}
// Extract the filename and extension
const urlPath = new URL(imageUrl).pathname;
const fileName = path.basename(urlPath); // Filename including extension (e.g., .jpg or .png)
const filePath = path.join(artistDir, fileName);
// Download the image and save it to the specified path
try {
await downloadImage(imageUrl, filePath);
console.info(`🖼️ Saved image to ${filePath}`);
await delay(250); // Delay between downloads
} catch (err) {
console.error(`❌ Error downloading image: ${err.message}`);
}
}
}
} }
// Function to download the image from the provided URL
async function downloadImage(url, filePath) { async function downloadImage(url, filePath) {
const response = await fetch(url); const response = await fetch(url);
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to download image: ${response.statusText}`); throw new Error(`Failed to download image: ${response.statusText}`);
} }
const arrayBuffer = await response.arrayBuffer(); const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer); const buffer = Buffer.from(arrayBuffer);
await fs.promises.writeFile(filePath, buffer); await fs.promises.writeFile(filePath, buffer);
} }
// ASCII art function (optional)
function asciiArt() { function asciiArt() {
console.info(` console.info(`
/$$ /$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$$ /$$ /$$ /$$ /$$ /$$$$$$$ /$$$$$$ /$$$$$$$
| $$$ /$$$| $$ /$$/| $$__ $$ /$$__ $$| $$__ $$ | $$$ /$$$| $$ /$$/| $$__ $$ /$$__ $$| $$__ $$
| $$$$ /$$$$| $$ /$$/ | $$ \\ $$| $$ \\__/| $$ \\ $$ | $$$$ /$$$$| $$ /$$/ | $$ \\ $$| $$ \\__/| $$ \\ $$
@ -65,11 +85,11 @@ function asciiArt() {
| $$\\ $ | $$| $$\\ $$ | $$ \\ $$ /$$ \\ $$| $$ | $$ | $$\\ $ | $$| $$\\ $$ | $$ \\ $$ /$$ \\ $$| $$ | $$
| $$ \\/ | $$| $$ \\ $$| $$$$$$$/| $$$$$$/| $$$$$$$/ | $$ \\/ | $$| $$ \\ $$| $$$$$$$/| $$$$$$/| $$$$$$$/
|__/ |__/|__/ \\__/|_______/ \\______/ |_______/`); |__/ |__/|__/ \\__/|_______/ \\______/ |_______/`);
console.info(``); console.info(`🤑 Starting downloads from your favorite sellout grifter's wallpaper app...`);
console.info(`🤑 Starting downloads from your favorite sellout grifter's wallpaper app...`);
} }
// Start the program with ASCII art and delay
(() => { (() => {
asciiArt(); asciiArt();
setTimeout(main, 5000); setTimeout(main, 5000);
})(); })();

View file

@ -1,11 +1,12 @@
# Licensed under the WTFPL License
import os import os
import time import time
import aiohttp import aiohttp
import asyncio import asyncio
import json
from urllib.parse import urlparse from urllib.parse import urlparse
url = 'https://storage.googleapis.com/panels-api/data/20240916/media-1a-i-p~s'
# Load the local JSON file
json_file_path = 'images.json'
async def delay(ms): async def delay(ms):
await asyncio.sleep(ms / 1000) await asyncio.sleep(ms / 1000)
@ -23,36 +24,37 @@ async def download_image(session, image_url, file_path):
async def main(): async def main():
try: try:
# Load JSON data from the local file
with open(json_file_path, 'r') as json_file:
json_data = json.load(json_file)
data = json_data.get('data')
if not data:
raise Exception('⛔ JSON does not have a "data" property at its root.')
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.get(url) as response: for key, subproperty in data.items():
if response.status != 200: if subproperty and subproperty.get('dhd'):
raise Exception(f"⛔ Failed to fetch JSON file: {response.status}") image_url = subproperty['dhd']
json_data = await response.json() print(f"🔍 Found image URL!")
data = json_data.get('data')
# Extract artist name from the URL
if not data: artist_name = image_url.split('a~')[1].split('_')[0]
raise Exception('⛔ JSON does not have a "data" property at its root.') artist_dir = os.path.join(os.getcwd(), 'downloads', artist_name)
download_dir = os.path.join(os.getcwd(), 'downloads') if not os.path.exists(artist_dir):
if not os.path.exists(download_dir): os.makedirs(artist_dir)
os.makedirs(download_dir) print(f"📁 Created directory: {artist_dir}")
print(f"📁 Created directory: {download_dir}")
file_index = 1 # Extract filename from the URL
for key, subproperty in data.items(): filename = os.path.basename(urlparse(image_url).path) # Name including extension
if subproperty and subproperty.get('dhd'): file_path = os.path.join(artist_dir, filename)
image_url = subproperty['dhd']
print(f"🔍 Found image URL!")
parsed_url = urlparse(image_url)
ext = os.path.splitext(parsed_url.path)[-1] or '.jpg'
filename = f"{file_index}{ext}"
file_path = os.path.join(download_dir, filename)
await download_image(session, image_url, file_path) await download_image(session, image_url, file_path)
print(f"🖼️ Saved image to {file_path}") print(f"🖼️ Saved image to {file_path}")
file_index += 1 await delay(250)
await delay(250)
except Exception as e: except Exception as e:
print(f"Error: {str(e)}") print(f"Error: {str(e)}")
@ -73,4 +75,4 @@ def ascii_art():
if __name__ == "__main__": if __name__ == "__main__":
ascii_art() ascii_art()
time.sleep(5) time.sleep(5)
asyncio.run(main()) asyncio.run(main())