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: