Skip to content

Instantly share code, notes, and snippets.

@kutyel
Created July 17, 2026 10:25
Show Gist options
  • Select an option

  • Save kutyel/86e74fc9f667d4ec126956630ac43eb9 to your computer and use it in GitHub Desktop.

Select an option

Save kutyel/86e74fc9f667d4ec126956630ac43eb9 to your computer and use it in GitHub Desktop.
Download Original Songs from JW
const https = require('https');
const fs = require('fs');
// JW.org Public Media API for English (E) Original Songs (osg)
const API_URL = 'https://pubmedia.jw-api.org/GETPUBMEDIALINKS?output=json&pub=osg&fileformat=mp3&alllangs=0&langwritten=E&txtCMSLang=E';
https.get(API_URL, (res) => {
let body = '';
res.on('data', chunk => body += chunk);
res.on('end', () => {
try {
const data = JSON.parse(body);
const tracks = data.files.E.MP3;
const missingTracks = tracks.filter(t => {
const num = parseInt(t.track, 10);
// 1. Check if it's one of the missing track numbers
const isMissing = (num >= 54 && num <= 103) || num >= 107;
// 2. Explicitly filter out Audio Descriptions
// Checks the API flag, filename markers (_AD_), and title keywords
const isAudioDescription =
t.audioDescr === true ||
t.file.url.includes('_AD_') ||
t.file.url.includes('_AD.') ||
t.title.toLowerCase().includes('audio description');
// Only keep the track if it is missing AND is NOT an audio description
return isMissing && !isAudioDescription;
});
console.log(`Found ${missingTracks.length} missing standard songs. Starting download...`);
missingTracks.forEach(t => {
const numStr = String(t.track).padStart(3, '0');
// Sanitize the title so it's safe for your filesystem
const safeTitle = t.title.replace(/[<>:"/\\|?*]/g, '');
const filename = `${numStr} ${safeTitle}.mp3`;
const url = t.file.url;
console.log(`Downloading: ${filename}`);
const fileStream = fs.createWriteStream(filename);
https.get(url, (downloadRes) => {
downloadRes.pipe(fileStream);
fileStream.on('finish', () => {
fileStream.close();
console.log(`Finished: ${filename}`);
});
}).on('error', (err) => {
console.error(`Error downloading ${filename}:`, err.message);
fs.unlink(filename, () => {});
});
});
} catch (e) {
console.error('Error parsing the JW API response.', e.message);
}
});
}).on('error', (err) => {
console.error('Error fetching API data:', err.message);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment