From 7bad8d2efad6e136b011480df4e0ffdb30b9402f Mon Sep 17 00:00:00 2001 From: "Rph :3" <11350302+rphsoftware@users.noreply.github.com> Date: Mon, 10 Feb 2025 22:48:08 +0100 Subject: [PATCH] hardcoded whatever idc for now --- 3p/appleMusicClient.ts | 27 +++++++++++++++++++ 3p/spotifyClient.ts | 20 ++++++++++++++ bun.lock | 38 ++++++++++++++++++++++++++ package.json | 4 +++ tools/isrcFiller.ts | 47 +++++++++++++++++++++++++++++++++ tools/views/isrcFiller/main.ejs | 0 6 files changed, 136 insertions(+) create mode 100644 tools/isrcFiller.ts create mode 100644 tools/views/isrcFiller/main.ejs diff --git a/3p/appleMusicClient.ts b/3p/appleMusicClient.ts index e69de29..ecb0770 100644 --- a/3p/appleMusicClient.ts +++ b/3p/appleMusicClient.ts @@ -0,0 +1,27 @@ +import { importPKCS8, SignJWT, GeneralSign } from "jose"; + +const TEAM_ID = process.env.TEAM_ID!; +const KEY_ID = process.env.KEY_ID!; +const privateKey = await Bun.file(process.env.AUTHKEY_PATH!).text(); +const realKey = await importPKCS8(privateKey, "ES256"); + +let currentTime = Date.now(); +const jwt = new SignJWT() + .setIssuer(TEAM_ID) + .setIssuedAt(Math.floor(currentTime / 1000)) + .setExpirationTime(Math.floor(currentTime / 1000) + 60 * 60 * 72) + +jwt.setProtectedHeader({ + alg: 'ES256', + kid: KEY_ID +}); + +const apmToken = await jwt.sign(realKey); + +export async function appleMusicFetch(url: string): Promise { + return fetch("https://api.music.apple.com/v1" + url, { + headers: { + "Authorization": `Bearer ${apmToken}` + } + }).then(res => res.json()); +} \ No newline at end of file diff --git a/3p/spotifyClient.ts b/3p/spotifyClient.ts index e69de29..a63b90e 100644 --- a/3p/spotifyClient.ts +++ b/3p/spotifyClient.ts @@ -0,0 +1,20 @@ +const s = new URLSearchParams(); +s.append("grant_type", "client_credentials"); +const spotify_response = await fetch("https://accounts.spotify.com/api/token", { + headers: { + "Authorization": `Basic ${Buffer.from(process.env.SPOTIFY_CLIENT + ":" + process.env.SPOTIFY_SECRET).toString('base64')}`, + "Content-Type": "application/x-www-form-urlencoded" + }, + body: s.toString(), + method: "POST" +}).then(res => res.json()); + +const sptToken = spotify_response.access_token; + +export async function spotifyFetch(url: string): Promise { + return fetch("https://api.spotify.com/v1" + url, { + headers: { + "Authorization": `Bearer ${sptToken}` + } + }).then(res => res.json()); +} \ No newline at end of file diff --git a/bun.lock b/bun.lock index bfac6bf..6e4ea3e 100644 --- a/bun.lock +++ b/bun.lock @@ -3,6 +3,10 @@ "workspaces": { "": { "name": "hellhound", + "dependencies": { + "ejs": "^3.1.10", + "jose": "^5.9.6", + }, "devDependencies": { "@types/bun": "latest", }, @@ -18,10 +22,44 @@ "@types/ws": ["@types/ws@8.5.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw=="], + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="], + "bun-types": ["bun-types@1.2.2", "", { "dependencies": { "@types/node": "*", "@types/ws": "~8.5.10" } }, "sha512-RCbMH5elr9gjgDGDhkTTugA21XtJAy/9jkKe/G3WR2q17VPGhcquf9Sir6uay9iW+7P/BV0CAHA1XlHXMAVKHg=="], + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "ejs": ["ejs@3.1.10", "", { "dependencies": { "jake": "^10.8.5" }, "bin": { "ejs": "bin/cli.js" } }, "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA=="], + + "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], + + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "jake": ["jake@10.9.2", "", { "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", "filelist": "^1.0.4", "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" } }, "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA=="], + + "jose": ["jose@5.9.6", "", {}, "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ=="], + + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + "typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], "undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], + + "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], + + "filelist/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], } } diff --git a/package.json b/package.json index dcbd0c2..b22b76b 100644 --- a/package.json +++ b/package.json @@ -7,5 +7,9 @@ }, "peerDependencies": { "typescript": "^5.0.0" + }, + "dependencies": { + "ejs": "^3.1.10", + "jose": "^5.9.6" } } \ No newline at end of file diff --git a/tools/isrcFiller.ts b/tools/isrcFiller.ts new file mode 100644 index 0000000..1d6d647 --- /dev/null +++ b/tools/isrcFiller.ts @@ -0,0 +1,47 @@ +import { appleMusicFetch } from "../3p/appleMusicClient"; +import { spotifyFetch } from "../3p/spotifyClient"; + +const APM_ID = "1552965331"; +const SPT_ID = "0kDiUhIznBbi6Y3slWiOBS"; + +const appleResult = await appleMusicFetch("/catalog/us/albums/" + APM_ID); +const spotiResult = await spotifyFetch("/albums/" + SPT_ID + "?market=US"); + +const appleAlbum = appleResult.data[0]; +const appleUpc = appleAlbum.attributes.upc; + +const spotifyUpc = spotiResult.external_ids.upc; + +if (appleUpc !== spotifyUpc) { + throw "UPC mismatch :/"; +} + +const appleISRCs = appleAlbum.relationships.tracks.data.map(a => a.attributes.isrc); +const spotifyISRCs = spotiResult.tracks.items.map(a => a.external_ids ? a.external_ids.isrc : null); + +if (appleISRCs.length !== spotifyISRCs.length) { + throw "ISRC or something mismatch :/"; +} + +const a = new URLSearchParams(); + +for (let i = 0; i < appleISRCs.length; i++) { + const cands = new Set([appleISRCs[i], spotifyISRCs[i]].filter(a => !!a)); + if (cands.size !== 1) throw "skill issue"; + const c = Array.from(cands); + + a.append(`isrc${i + 1}`, c[0]); +} + +a.append("edit-note", `Data obtained via authenticated APIs from: +- Apple Music: https://api.music.apple.com/v1/catalog/us/albums/${APM_ID} +- Spotify: https://api.spotify.com/v1/albums/${SPT_ID}?market=US`); + + +console.log("UPC: " + appleUpc); +console.log(`https://magicisrc.kepstin.ca/?${a.toString()}`); + +console.log("\n\n"); +console.log(`Data obtained via authenticated APIs from: +- Apple Music: https://api.music.apple.com/v1/catalog/us/albums/${APM_ID} +- Spotify: https://api.spotify.com/v1/albums/${SPT_ID}?market=US`) \ No newline at end of file diff --git a/tools/views/isrcFiller/main.ejs b/tools/views/isrcFiller/main.ejs new file mode 100644 index 0000000..e69de29