configured prettier

This commit is contained in:
2025-10-11 00:57:35 -05:00
parent 7e842d5db6
commit 95c1a568db
2 changed files with 70 additions and 46 deletions

7
.prettierrc Normal file
View File

@@ -0,0 +1,7 @@
{
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"objectWrap": "collapse"
}

109
main.ts
View File

@@ -2,11 +2,13 @@ import { existsSync } from 'node:fs'
import { mkdir, writeFile } from 'node:fs/promises' import { mkdir, writeFile } from 'node:fs/promises'
import path from 'node:path' import path from 'node:path'
import { argv } from 'node:process' import { argv } from 'node:process'
import { Buffer } from "node:buffer" import { Buffer } from 'node:buffer'
import * as cheerio from "https://esm.sh/cheerio?target=esnext" import * as cheerio from 'https://esm.sh/cheerio?target=esnext'
const REGEX_PLAYLISTURL = /^https:\/\/downloads\.khinsider\.com\/game-soundtracks\/album\/[^\/]+\/?$/i const REGEX_PLAYLISTURL =
const REGEX_SONGURL = /^https:\/\/downloads\.khinsider\.com\/game-soundtracks\/album\/[^\/]+\/[^\/]+\/?$/i /^https:\/\/downloads\.khinsider\.com\/game-soundtracks\/album\/[^\/]+\/?$/i
const REGEX_SONGURL =
/^https:\/\/downloads\.khinsider\.com\/game-soundtracks\/album\/[^\/]+\/[^\/]+\/?$/i
const REGEX_ALBUMTITLE = /^(.*?) MP3 - Download/i const REGEX_ALBUMTITLE = /^(.*?) MP3 - Download/i
const REGEX_UNSAFEFORFILE = /[^a-z0-9\-_=+,.()\[\]{} ]/gi const REGEX_UNSAFEFORFILE = /[^a-z0-9\-_=+,.()\[\]{} ]/gi
@@ -22,7 +24,9 @@ async function main() {
await downloadSong(song, downloadPath || '.') await downloadSong(song, downloadPath || '.')
} }
} else { } else {
await Promise.all(playlist.map(song => downloadSong(song, downloadPath || '.'))) await Promise.all(
playlist.map((song) => downloadSong(song, downloadPath || '.'))
)
} }
} }
@@ -36,9 +40,10 @@ async function fetchPlaylist(url: string): Promise<PlaylistSongData[]> {
const $ = cheerio.load(text) const $ = cheerio.load(text)
const title = $.extract({ const title =
title: 'title' $.extract({
}).title ?? '' title: 'title',
}).title ?? ''
const titleMatch = REGEX_ALBUMTITLE.exec(title) const titleMatch = REGEX_ALBUMTITLE.exec(title)
if (titleMatch === null) { if (titleMatch === null) {
throw `unable to grab album name from ${title}` throw `unable to grab album name from ${title}`
@@ -49,7 +54,7 @@ async function fetchPlaylist(url: string): Promise<PlaylistSongData[]> {
const rows = getPlaylistRows($, columns, albumName) const rows = getPlaylistRows($, columns, albumName)
console.log(`downloading ${rows.length} songs`) console.log(`downloading ${rows.length} songs`)
return rows return rows
} }
@@ -58,6 +63,7 @@ interface PlaylistTableColumns {
track: number track: number
cd: number cd: number
} }
interface PlaylistSongData { interface PlaylistSongData {
url: string url: string
album: string album: string
@@ -69,26 +75,29 @@ interface PlaylistSongData {
function getPlaylistTableHeaders($: cheerio.CheerioAPI): PlaylistTableColumns { function getPlaylistTableHeaders($: cheerio.CheerioAPI): PlaylistTableColumns {
const header = $('#songlist tr#songlist_header') const header = $('#songlist tr#songlist_header')
const headerCells = header.extract({ const headerCells = header.extract({
cells: ['th'] cells: ['th'],
}) })
const indexes = headerCells.cells.reduce((p, c, i) => { const indexes = headerCells.cells.reduce(
switch (c.toLocaleLowerCase()) { (p, c, i) => {
case 'cd': switch (c.toLocaleLowerCase()) {
p.cd = i case 'cd':
break p.cd = i
case '#': break
p.track = i case '#':
break p.track = i
case 'song name': break
p.name = i case 'song name':
p.name = i
}
return p
},
{
name: -1,
track: -1,
cd: -1,
} }
return p )
}, {
name: -1,
track: -1,
cd: -1,
})
if (indexes.name == -1) { if (indexes.name == -1) {
throw 'unable to find song title column' throw 'unable to find song title column'
@@ -97,10 +106,14 @@ function getPlaylistTableHeaders($: cheerio.CheerioAPI): PlaylistTableColumns {
return indexes return indexes
} }
function getPlaylistRows($: cheerio.CheerioAPI, columns: PlaylistTableColumns, albumName: string): PlaylistSongData[] { function getPlaylistRows(
$: cheerio.CheerioAPI,
columns: PlaylistTableColumns,
albumName: string
): PlaylistSongData[] {
const rows = $('#songlist tr:not(#songlist_header):not(#songlist_footer)') const rows = $('#songlist tr:not(#songlist_header):not(#songlist_footer)')
const rowsData: PlaylistSongData[] = [] const rowsData: PlaylistSongData[] = []
rows.each((_, rowEl) => { rows.each((_, rowEl) => {
const row = cheerio.load(rowEl) const row = cheerio.load(rowEl)
const rowData: PlaylistSongData = { const rowData: PlaylistSongData = {
@@ -110,16 +123,17 @@ function getPlaylistRows($: cheerio.CheerioAPI, columns: PlaylistTableColumns, a
track: -1, track: -1,
cd: -1, cd: -1,
} }
rowData.url = row.extract({ rowData.url =
url: { row.extract({
selector: 'td.playlistDownloadSong a', url: {
value: 'href' selector: 'td.playlistDownloadSong a',
} value: 'href',
}).url ?? '' },
}).url ?? ''
const rowCells = row.extract({ const rowCells = row.extract({
cells: ['td'] cells: ['td'],
}).cells }).cells
rowData.name = rowCells[columns.name] rowData.name = rowCells[columns.name]
@@ -163,8 +177,8 @@ async function downloadSong(song: PlaylistSongData, location: string) {
const flacUrl = $.extract({ const flacUrl = $.extract({
url: { url: {
selector: '#pageContent a[href*="flac"]', selector: '#pageContent a[href*="flac"]',
value: 'href' value: 'href',
} },
}).url }).url
if (!flacUrl) { if (!flacUrl) {
@@ -172,7 +186,7 @@ async function downloadSong(song: PlaylistSongData, location: string) {
} }
const { pathname, fullpathname } = pathFor(location, song) const { pathname, fullpathname } = pathFor(location, song)
if (!existsSync(pathname)) { if (!existsSync(pathname)) {
await mkdir(pathname) await mkdir(pathname)
} }
@@ -198,24 +212,27 @@ function pathFor(location: string, song: PlaylistSongData): SongPath {
const albumname = song.album.replace(REGEX_UNSAFEFORFILE, '') const albumname = song.album.replace(REGEX_UNSAFEFORFILE, '')
const songname = song.name.replace(REGEX_UNSAFEFORFILE, '') const songname = song.name.replace(REGEX_UNSAFEFORFILE, '')
const filename = `${song.cd >= 0 ? song.cd+'.' : ''}${song.track >= 0 ? song.track+'.' : ''}${song.cd >= 0 || song.track >= 0 ? ' ' : ''}${songname}.flac` const cd = song.cd >= 0 ? song.cd + '.' : ''
const track = song.track >= 0 ? song.track + '.' : ''
const separator = song.cd >= 0 || song.track >= 0 ? ' ' : ''
const filename = `${cd}${track}${separator}${songname}.flac`
const pathname = path.resolve(location, albumname) const pathname = path.resolve(location, albumname)
const fullpathname = path.resolve(pathname, filename) const fullpathname = path.resolve(pathname, filename)
return { return {
pathname, pathname,
fullpathname fullpathname,
} }
} }
function toBuffer(arrayBuffer: ArrayBuffer) { function toBuffer(arrayBuffer: ArrayBuffer) {
const buffer = Buffer.alloc(arrayBuffer.byteLength); const buffer = Buffer.alloc(arrayBuffer.byteLength)
const view = new Uint8Array(arrayBuffer); const view = new Uint8Array(arrayBuffer)
for (let i = 0; i < buffer.length; ++i) { for (let i = 0; i < buffer.length; ++i) {
buffer[i] = view[i]; buffer[i] = view[i]
} }
return buffer; return buffer
} }
main().catch(e => console.error(e)) main().catch((e) => console.error(e))