174 lines
4.6 KiB
JavaScript
Executable File
174 lines
4.6 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Script to download app icons from GitHub repositories
|
|
* Downloads icons for all dummy apps from Start9Labs/{app-id}-startos repos
|
|
*/
|
|
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import https from 'https'
|
|
import { fileURLToPath } from 'url'
|
|
|
|
const __filename = fileURLToPath(import.meta.url)
|
|
const __dirname = path.dirname(__filename)
|
|
|
|
const appIds = [
|
|
'bitcoin',
|
|
'btcpay-server',
|
|
'homeassistant',
|
|
'grafana',
|
|
'endurain',
|
|
'fedimint',
|
|
'morphos-server',
|
|
'lightning-stack',
|
|
'mempool',
|
|
'ollama',
|
|
'searxng',
|
|
'onlyoffice',
|
|
'penpot'
|
|
]
|
|
|
|
// Map app IDs to their Start9 repo names (some might differ)
|
|
const repoMap = {
|
|
'bitcoin': 'bitcoind-startos',
|
|
'btcpay-server': 'btcpayserver-startos',
|
|
'homeassistant': 'home-assistant-startos',
|
|
'grafana': 'grafana-startos',
|
|
'lightning-stack': 'lnd-startos',
|
|
'mempool': 'mempool-startos',
|
|
'searxng': 'searxng-startos',
|
|
'onlyoffice': 'onlyoffice-startos',
|
|
'penpot': 'penpot-startos',
|
|
}
|
|
|
|
// Custom icon URLs for apps without Start9 repos
|
|
const customIconUrls = {
|
|
'fedimint': [
|
|
'https://raw.githubusercontent.com/fedibtc/fedimint-ui/master/apps/router/public/favicon.svg',
|
|
],
|
|
}
|
|
|
|
const iconDir = path.join(__dirname, '../public/assets/img/app-icons')
|
|
|
|
// Ensure directory exists
|
|
if (!fs.existsSync(iconDir)) {
|
|
fs.mkdirSync(iconDir, { recursive: true })
|
|
}
|
|
|
|
function downloadFile(url, filepath) {
|
|
return new Promise((resolve, reject) => {
|
|
const file = fs.createWriteStream(filepath)
|
|
|
|
https.get(url, (response) => {
|
|
if (response.statusCode === 200) {
|
|
response.pipe(file)
|
|
file.on('finish', () => {
|
|
file.close()
|
|
console.log(`✅ Downloaded: ${path.basename(filepath)}`)
|
|
resolve()
|
|
})
|
|
} else if (response.statusCode === 404) {
|
|
file.close()
|
|
fs.unlinkSync(filepath) // Delete empty file
|
|
console.log(`⚠️ Not found: ${url}`)
|
|
reject(new Error(`404: ${url}`))
|
|
} else {
|
|
file.close()
|
|
fs.unlinkSync(filepath)
|
|
reject(new Error(`HTTP ${response.statusCode}: ${url}`))
|
|
}
|
|
}).on('error', (err) => {
|
|
file.close()
|
|
if (fs.existsSync(filepath)) {
|
|
fs.unlinkSync(filepath)
|
|
}
|
|
reject(err)
|
|
})
|
|
})
|
|
}
|
|
|
|
async function downloadIcon(appId) {
|
|
const targetExt = 'webp' // Prefer webp for consistency with mempool, etc.
|
|
const fallbackExts = ['webp', 'png', 'svg']
|
|
const filepath = path.join(iconDir, `${appId}.webp`)
|
|
|
|
// Skip if file already exists
|
|
if (appId === 'fedimint' && fs.existsSync(path.join(iconDir, 'fedimint.png'))) {
|
|
console.log(`⏭️ Skipping ${appId} (fedimint.png exists)`)
|
|
return true
|
|
}
|
|
for (const ext of fallbackExts) {
|
|
const fp = path.join(iconDir, `${appId}.${ext}`)
|
|
if (fs.existsSync(fp)) {
|
|
console.log(`⏭️ Skipping ${appId} (already exists)`)
|
|
return true
|
|
}
|
|
}
|
|
|
|
// Try custom URLs first (e.g. fedimint from fedimint-ui)
|
|
if (customIconUrls[appId]) {
|
|
for (const url of customIconUrls[appId]) {
|
|
try {
|
|
const ext = url.endsWith('.svg') ? 'svg' : (url.endsWith('.png') ? 'png' : 'webp')
|
|
const fp = path.join(iconDir, `${appId}.${ext}`)
|
|
await downloadFile(url, fp)
|
|
return true
|
|
} catch (err) {
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
|
|
const repoName = repoMap[appId] || `${appId}-startos`
|
|
const iconPaths = ['icon.png', 'icon.svg', 'assets/icon.png', 'assets/icon.svg']
|
|
|
|
for (const iconPath of iconPaths) {
|
|
const url = `https://raw.githubusercontent.com/Start9Labs/${repoName}/main/${iconPath}`
|
|
const extension = iconPath.endsWith('.svg') ? 'svg' : 'png'
|
|
const fp = path.join(iconDir, `${appId}.${extension}`)
|
|
try {
|
|
await downloadFile(url, fp)
|
|
return true
|
|
} catch (err) {
|
|
continue
|
|
}
|
|
}
|
|
|
|
console.log(`❌ Failed to download icon for ${appId}`)
|
|
return false
|
|
}
|
|
|
|
async function main() {
|
|
console.log('Downloading app icons from GitHub...\n')
|
|
|
|
const results = {
|
|
success: [],
|
|
failed: []
|
|
}
|
|
|
|
for (const appId of appIds) {
|
|
try {
|
|
const success = await downloadIcon(appId)
|
|
if (success) {
|
|
results.success.push(appId)
|
|
} else {
|
|
results.failed.push(appId)
|
|
}
|
|
// Small delay to avoid rate limiting
|
|
await new Promise(resolve => setTimeout(resolve, 500))
|
|
} catch (err) {
|
|
console.error(`Error downloading ${appId}:`, err.message)
|
|
results.failed.push(appId)
|
|
}
|
|
}
|
|
|
|
console.log(`\n✅ Successfully downloaded ${results.success.length} icons`)
|
|
if (results.failed.length > 0) {
|
|
console.log(`❌ Failed to download ${results.failed.length} icons:`, results.failed.join(', '))
|
|
}
|
|
}
|
|
|
|
main().catch(console.error)
|
|
|