Created
January 22, 2022 15:29
-
-
Save outloudvi/44602d8a2c5df5e273d6197d09fd6f28 to your computer and use it in GitHub Desktop.
Get songs of DENONBU from the official Spotify playlist.
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
/** | |
Usage: | |
1. Get a SPOTIFY_TOKEN (e.g. from kira.vercel.app) and run `deno run --allow-net ./denonbu-tpl.mjs` | |
2. Import `checkSongs()` from the file and call checkSongs(SPOTIFY_TOKEN). | |
**/ | |
import fetch from 'https://cdn.skypack.dev/node-fetch@3' | |
import { table } from 'https://cdn.skypack.dev/table@6.8.0' | |
// Change this | |
const SPOTIFY_TOKEN = '' | |
function simpleDedup(x) { | |
return [...new Set(x)] | |
} | |
function getSongs(token) { | |
// TODO: paginator | |
return fetch( | |
'https://api.spotify.com/v1/playlists/31s7OlRyx4YBvQpn57aF5c/tracks?limit=100&additional_types=track%2Cepisode&market=JP', | |
{ | |
headers: { | |
Accept: 'applicatoin/json', | |
Authorization: `Bearer ${token ?? SPOTIFY_TOKEN}`, | |
}, | |
} | |
) | |
.then((x) => x.json()) | |
.then((x) => x.items) | |
.then((x) => | |
x.map(({ track: { name, album, artists } }) => ({ | |
name, | |
date: album.release_date, | |
artists: artists.map(({ id, name }) => ({ id, name })), | |
})) | |
) | |
} | |
async function getArtists() { | |
const songs = await getSongs() | |
return songs | |
.map((x) => x.artists) | |
.reduce((a, b) => [...a, ...b]) | |
.reduce((a, b) => { | |
if (!a.map((x) => x.id).includes(b.id)) a.push(b) | |
return a | |
}, []) | |
} | |
const GROUPS = { | |
// Sotokanda Literature High School / ๅค็ฅ็ฐๆ่ธ้ซๆ ก | |
akiba: [ | |
'0h4HUlj0WCkc6Xn4F73XIt', // ๆฑ้ฒๅ้ณ (CV:ๅคฉ้ณใฟใป) | |
'66nXwB0bML5ETI8cGQxoNr', // ๆฑ้ฒๅ้ณ(CV:ๅคฉ้ณใฟใป) | |
'3U8W8KZ51Z96pSqPjkWNYz', // ๆฅ้ซ้ถๅฅ (CV: ่ ็ฅไฝณ) | |
'2T5vYihahEyo8aNKP2JXOz', // ๆฅ้ซ้ถๅฅ(CV:่ ็ฅไฝณ) | |
'5TuaJT25cXZwLgj8Z5znIz', // ่ ้ใตใใฐ(CV:ๅ ่ถใใช) | |
'n:ๆฑ้ฒๅ้ณ', | |
'n:ๆฅ้ซ้ถๅฅ', | |
'n:่ ้ใตใใฐ', | |
], | |
// Jingumae Sandou High School / ็ฅๅฎซๅๅ้ๅญฆๅญ | |
harajuku: [ | |
'6jCy1P04z78DNhIeHjzEC2', // ๆฐดไธ ้ (CV: ๅคงๆฃฎๆฅ้ ) | |
'2she8Gi8cVSwSM8aTWmurk', // ๆกไน็พใ ๅ (CV: ๅฐๅไบ็ฅ่็ตต) | |
'0JqX5C4CiNps3qRGvlMLcf', // ็ฌๅ ๅผ็ดซๆ (CV: ้ท่ฐทๅท็ฒๅฅ) | |
'n:ๆฐดไธ้', | |
'n:ๆกไน็พใ ๅ ', | |
'n:็ฌๅ ๅผ็ดซๆ', | |
], | |
// Minato Shirokane Girls' High School / ๆธฏ็ฝ้ๅฅณๅญฆ้ข | |
azabu: [ | |
'2xJeAewClnCHglceTI3gIw', // ็ฝ้ ็ (CV: ๅฐๅฎฎๆ็ด) | |
'0JQ292eFZdsbZbYUfNWpph', // ้ป้ใใพ (CV: ็งๅฅ) | |
'5B4sSyRcbTVegDTQlj8aX2', // ็ฐๅณถ้่ฏ (CV: ๆพ่ฐทๆขๅธ) | |
'n:็ฝ้็ ', | |
'n:้ป้ใใพ', | |
'n:็ฐๅณถ้่ฏ', | |
], | |
// Teion International High School / ๅธ้ณๅฝ้ ๅญฆ้ข / The "Nijisanji" group | |
shibuya: [ | |
'3fHDuekX2NfAhKC0f3Qde5', // ็ฌๆธๆตทๆ (CV: ใทในใฟใผใปใฏใฌใข) | |
'12WNAXEoWB8oNjlyuYU5hZ', // ้ณณๅฐ็ซๅ (CV: ๅฅๅฑ่ฑ้ฃ) | |
'3IFOQg0N8gQooK5duWNRq4', // ๅคง่ณใซใญใข (CV: ๆๅทใตใฉ) | |
'n:็ฌๆธๆตทๆ', | |
'n:้ณณๅฐ็ซๅ', | |
'n:ๅคง่ณใซใญใข', | |
], | |
} | |
function findArtist(item) { | |
// Find by Spotify ID (most accurate) | |
for (const [group, arr] of Object.entries(GROUPS)) { | |
for (const i of arr) { | |
if (!i.startsWith('n:')) { | |
if (item.id === i) return group | |
} | |
} | |
} | |
// Find by name (probably problematic) | |
for (const [group, arr] of Object.entries(GROUPS)) { | |
for (const i of arr) { | |
if (i.startsWith('n:')) { | |
if (item.name.replace(/ /g, '').includes(i.replace(/^n:/, ''))) { | |
console.warn( | |
`Fuzzy matching ${item.name} (id: ${item.id}) to ${i} (${group})` | |
) | |
return group | |
} | |
} | |
} | |
} | |
return null | |
} | |
export async function checkSongs(token) { | |
const songs = await getSongs(token) | |
const songGroups = {} | |
for (const i of songs) { | |
const groups = | |
simpleDedup(i.artists.map(findArtist).filter((x) => x)) | |
.sort() | |
.join(',') || 'none' | |
const obj = { | |
name: i.name, | |
date: i.date, | |
artists: i.artists.map((x) => x.name), | |
group: groups, | |
} | |
if (songGroups[groups]) { | |
songGroups[groups].push(obj) | |
} else { | |
songGroups[groups] = [obj] | |
} | |
} | |
for (const [key, arr] of Object.entries(songGroups)) { | |
console.log('-----------------') | |
console.log(`*** ${key} ***`) | |
const songsOrdered = arr.sort( | |
(a, b) => Number(new Date(a.date)) - Number(new Date(b.date)) | |
) | |
console.log( | |
table([ | |
['Name', 'Date', 'Artists'], | |
...songsOrdered.map((x) => [x.name, x.date, x.artists.join(', ')]), | |
]) | |
) | |
} | |
} | |
if (import.meta.main) { | |
checkSongs() | |
} |
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
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>denonbu-spotify.mjs</title> | |
</head> | |
<body> | |
Update the SPOTIFY_TOKEN and check the console! | |
<script type="module"> | |
import { checkSongs } from './denonbu-spotify.mjs' | |
checkSongs() | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sample output: