import { iter } from '@fuman/utils' import { z } from 'zod' import { minimist, question } from 'zx' import { downloadFile, ffetch } from '../../utils/fetch.ts' const args = minimist(process.argv.slice(2), { string: ['filename'], }) const query = args._[0] ?? await question('Search query: ') const data = await ffetch('https://itunes.apple.com/search', { query: { term: query, entity: 'musicArtist', limit: 15, }, }).parsedJson(z.object({ results: z.array(z.object({ wrapperType: z.literal('artist'), artistName: z.string(), artistLinkUrl: z.string(), primaryGenreName: z.string().default('Unknown'), }).passthrough()), })) for (const [i, result] of iter.enumerate(data.results)) { console.log(`${i + 1}. ${result.artistName} (${result.primaryGenreName})`) continue } console.log('Enter number to download artist art:') const number = Number.parseInt(await question('[1] > ') || '1') const pageUrl = data.results[number - 1].artistLinkUrl const $ = await ffetch(pageUrl).cheerio() const pageData = JSON.parse($('#serialized-server-data').html()!) const pageDataValidated = z.tuple([ z.object({ data: z.object({ seoData: z.object({ artworkUrl: z.string(), }), }), }), ]).parse(pageData) // {w}x{h}{c}.{f} const artworkUrl = pageDataValidated[0].data.seoData.artworkUrl .replace('{w}', '2500') .replace('{h}', '2500') .replace('{c}', 'cc') .replace('{f}', 'jpg') if (artworkUrl === '/assets/meta/apple-music.png') { console.log('No artwork available') process.exit(1) } await downloadFile(artworkUrl, args.filename ?? `assets/${query.replace(/\s/g, '_')}.jpg`)