#!/usr/bin/env node // Downloads stratagem icons from helldivers.wiki.gg // Saves as public/icons/.svg (same filenames as before) import { createWriteStream, mkdirSync } from 'fs'; import { join, dirname } from 'path'; import { fileURLToPath } from 'url'; import https from 'https'; const __dirname = dirname(fileURLToPath(import.meta.url)); const OUT_DIR = join(__dirname, '..', 'public', 'icons'); const BASE_URL = 'https://helldivers.wiki.gg/images/'; mkdirSync(OUT_DIR, { recursive: true }); // Maps our stratagem slug → wiki filename (without _Stratagem_Icon.svg suffix) const WIKI_MAP = { reinforce: 'Reinforce', resupply: 'Resupply', sos_beacon: 'SOS_Beacon', hellbomb: 'Hellbomb', seaf_artillery: 'SEAF_Artillery', upload_data: 'Start_Upload', eagle_rearm: 'Eagle_Rearm', prospecting_drill: 'Prospecting_Drill', orbital_gatling_barrage: 'Orbital_Gatling_Barrage', orbital_airburst_strike: 'Orbital_Airburst_Strike', orbital_120mm_he_barrage: 'Orbital_120mm_HE_Barrage', orbital_380mm_he_barrage: 'Orbital_380mm_HE_Barrage', orbital_walking_barrage: 'Orbital_Walking_Barrage', orbital_laser: 'Orbital_Laser', orbital_railcannon_strike: 'Orbital_Railcannon_Strike', orbital_precision_strike: 'Orbital_Precision_Strike', orbital_gas_strike: 'Orbital_Gas_Strike', orbital_ems_strike: 'Orbital_EMS_Strike', orbital_smoke_strike: 'Orbital_Smoke_Strike', orbital_illumination_flare: 'Orbital_Illumination_Flare', eagle_strafing_run: 'Eagle_Strafing_Run', eagle_airstrike: 'Eagle_Airstrike', eagle_cluster_bomb: 'Eagle_Cluster_Bomb', eagle_napalm_airstrike: 'Eagle_Napalm_Airstrike', lift_850_jump_pack: 'Jump_Pack', eagle_smoke_strike: 'Eagle_Smoke_Strike', eagle_110mm_rocket_pods: 'Eagle_110mm_Rocket_Pods', eagle_500kg_bomb: 'Eagle_500kg_Bomb', patriot_exosuit: 'Patriot_Exosuit', emancipator_exosuit: 'Emancipator_Exosuit', tesla_tower: 'Tesla_Tower', shield_generator_relay: 'Shield_Generator_Relay', machine_gun: 'Machine_Gun', anti_materiel_rifle: 'Anti-Materiel_Rifle', stalwart: 'Stalwart', expendable_anti_tank: 'Expendable_Anti-Tank', recoilless_rifle: 'Recoilless_Rifle', flamethrower: 'Flamethrower', autocannon: 'Autocannon', heavy_machine_gun: 'Heavy_Machine_Gun', airburst_rocket_launcher: 'Airburst_Rocket_Launcher', commando: 'Commando', railgun: 'Railgun', spear: 'Spear', quasar_cannon: 'Quasar_Cannon', arc_thrower: 'Arc_Thrower', laser_cannon: 'Laser_Cannon', grenade_launcher: 'Grenade_Launcher', supply_pack: 'Supply_Pack', guard_dog_rover: 'Rover', guard_dog: 'Guard_Dog', ballistic_shield_backpack: 'Ballistic_Shield_Backpack', shield_generator_pack: 'Shield_Generator_Pack', directional_shield: 'Directional_Shield', hmg_emplacement: 'HMG_Emplacement', anti_personnel_minefield: 'Anti-Personnel_Minefield', incendiary_mines: 'Incendiary_Mines', anti_tank_mines: 'Anti-Tank_Mines', machine_gun_sentry: 'Machine_Gun_Sentry', gatling_sentry: 'Gatling_Sentry', mortar_sentry: 'Mortar_Sentry', autocannon_sentry: 'Autocannon_Sentry', rocket_sentry: 'Rocket_Sentry', ems_mortar_sentry: 'EMS_Mortar_Sentry', anti_tank_emplacement: 'Anti-Tank_Emplacement', }; function download(url, dest) { return new Promise((resolve, reject) => { const file = createWriteStream(dest); const request = (targetUrl) => { https.get(targetUrl, { headers: { 'User-Agent': 'helldivers-trainer-bot/1.0' } }, (res) => { if (res.statusCode === 301 || res.statusCode === 302) { file.destroy(); return request(res.headers.location); } if (res.statusCode !== 200) { file.destroy(); return reject(new Error(`HTTP ${res.statusCode}`)); } res.pipe(file); file.on('finish', () => file.close(resolve)); }).on('error', reject); }; request(url); }); } async function main() { const entries = Object.entries(WIKI_MAP); let ok = 0, fail = 0; for (const [slug, wikiName] of entries) { const filename = wikiName + '_Stratagem_Icon.svg'; const url = BASE_URL + filename; const dest = join(OUT_DIR, slug + '.svg'); try { await download(url, dest); console.log(`✓ ${slug}`); ok++; } catch (err) { console.error(`✗ ${slug} (${err.message})`); fail++; } } console.log(`\nDone: ${ok} ok, ${fail} failed`); } main();