Last active
September 16, 2024 11:23
-
-
Save chadrien/1b7a64edd8a60accf7c6ffe3e7800dc8 to your computer and use it in GitHub Desktop.
CardCastle to Moxfield CSV converter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Papa from 'papaparse'; | |
import commandLineArgs from 'command-line-args'; | |
import { readFileSync, writeFileSync } from 'fs'; | |
import { Sets } from "scryfall-sdk"; | |
const optionDefinitions = [ | |
{ name: 'file', alias: 'f', type: String }, | |
{ name: 'output', alias: 'o', type: String }, | |
]; | |
const options = commandLineArgs(optionDefinitions); | |
const condition = { | |
Mint: 'M', | |
'Near Mint': 'NM', | |
'Lightly Played': 'LP', | |
'Moderately Played': 'MP', | |
'Heavily Played': 'HP', | |
'Damaged': 'D', | |
} | |
const language = { | |
en: 'en', | |
sp: 'es', | |
fr: 'fr', | |
de: 'de', | |
it: 'it', | |
pt: 'pt', | |
jp: 'ja', | |
kr: 'ko', | |
ru: 'ru', | |
cs: 'zhs', | |
ct: 'zht', | |
ph: 'ph', | |
} | |
type CardCastleCsvRow = { | |
'Card Name': string; | |
'Set Name': string; | |
Condition: keyof typeof condition; | |
Foil: boolean; | |
Language: keyof typeof language; | |
} | |
type MoxfieldCsvRow = { | |
Count: number; | |
Name: string; | |
Edition: string; | |
Condition: (typeof condition)[keyof typeof condition]; | |
Language: (typeof language)[keyof typeof language]; | |
Foil: '' | 'foil'; | |
} | |
async function cardCastleCsvRowToMoxfieldCsvRow(input: CardCastleCsvRow): Promise<MoxfieldCsvRow> { | |
return { | |
Count: 1, | |
Name: input['Card Name'], | |
Edition: await setNameToSetCode(input['Set Name']), | |
Condition: condition[input.Condition], | |
Language: language[input.Language], | |
Foil: input.Foil ? 'foil' : '', | |
} | |
} | |
async function setNameToSetCode(setName: string): Promise<string> { | |
return (await Sets.byName(setName)).code | |
} | |
async function main() { | |
const input = readFileSync(options.file, { encoding: 'utf8', flag: 'r' }); | |
const result = Papa.parse(input, { | |
delimiter: ',', | |
header: true, | |
skipEmptyLines: true, | |
transform(value, field) { | |
if (field === 'Foil') { | |
return value === 'true' | |
} | |
return value | |
}, | |
}) | |
const mappedToMoxfield = (await Promise.all( | |
result.data | |
.map(async (row) => await cardCastleCsvRowToMoxfieldCsvRow(row as CardCastleCsvRow)) | |
)) | |
.reduce((acc, row) => { | |
const existingRow = acc.find((r) => r.Name === row.Name && r.Edition === row.Edition && r.Condition === row.Condition && r.Language === row.Language && r.Foil === row.Foil) | |
if (existingRow) { | |
existingRow.Count += 1 | |
} else { | |
acc.push(row) | |
} | |
return acc | |
}, [] as MoxfieldCsvRow[]) | |
const output = Papa.unparse(mappedToMoxfield, { | |
delimiter: ',', | |
header: true, | |
}) | |
writeFileSync(options.output, output, { encoding: 'utf8', flag: 'w' }); | |
process.exit(0) | |
} | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "cardcastle-to-moxfield", | |
"main": "index.ts", | |
"dependencies": { | |
"command-line-args": "^6.0.0", | |
"papaparse": "^5.4.1", | |
"scryfall-sdk": "^5.0.2" | |
}, | |
"devDependencies": { | |
"@types/command-line-args": "^5.2.3", | |
"@types/papaparse": "^5.3.14", | |
"ts-node": "^10.9.2", | |
"typescript": "^5.6.2" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Show hidden characters
{ | |
"compilerOptions": { | |
"target": "es2016", | |
"module": "NodeNext", | |
"moduleResolution": "NodeNext", | |
"esModuleInterop": true, | |
"forceConsistentCasingInFileNames": true, | |
"strict": true, | |
"skipLibCheck": true | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment