I AM MUSIC

This commit is contained in:
nin0 2025-04-25 05:47:35 -04:00
parent 182f12f32c
commit 7c74f50c35
Signed by: nin0
SSH key fingerprint: SHA256:NOoDnFVvZNFvqfXCIhzr6oCTDImZAbTTuyAysZ8Ufk8
4 changed files with 102 additions and 27 deletions

View file

View file

@ -1,34 +1,11 @@
import Fastify from "fastify";
import { Yapper } from "./Yapper";
import path from "path";
import { readFileSync, stat, writeFileSync } from "fs";
const state = new Proxy(
JSON.parse(readFileSync(path.join(__dirname, "state.json"), "utf-8")),
{
get(target, prop) {
const data = readFileSync(
path.join(__dirname, "state.json"),
"utf-8"
);
return JSON.parse(data);
},
set(target, prop, value) {
const data = JSON.parse(
readFileSync(path.join(__dirname, "state.json"), "utf-8")
);
data[prop] = value;
writeFileSync(
path.join(__dirname, "state.json"),
JSON.stringify(data)
);
return true;
}
}
);
import { state } from "./utils";
import { reqSpotify, spotifyFilter } from "./spotify";
const fastify = Fastify({
loggerInstance: new Yapper()
loggerInstance: new Yapper(),
disableRequestLogging: true
});
fastify.get("/", (request, reply) => {
@ -72,12 +49,21 @@ fastify.get("/callback", async (request, reply) => {
})
).json();
if (tokenRes.error) return reply.code(400).send();
state.accessToken = tokenRes.access_token;
state.explodesAt = Date.now() + tokenRes.expires_in * 1000;
state.refreshToken = tokenRes.refresh_token;
return `Logged in as ${
(await reqSpotify("/me")).display_name
}. You're good to go!`;
});
try {
setInterval(spotifyFilter, 5000);
spotifyFilter();
fastify.listen({
port: 4929,
host: "0.0.0.0"

62
src/spotify.ts Normal file
View file

@ -0,0 +1,62 @@
import { state } from "./utils";
export async function reqSpotify(
endpoint: string,
method: string = "GET",
data?: object
) {
if (state.explodesAt >= Date.now()) {
const tokenRes = await (
await fetch("https://accounts.spotify.com/api/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: new URLSearchParams({
refresh_token: state.refreshToken,
client_id: process.env.CLIENT_ID!,
grant_type: "refresh_token"
})
})
).json();
if (!tokenRes.error) {
state.accessToken = tokenRes.access_token;
state.explodesAt = Date.now() + tokenRes.expires_in * 1000;
state.refreshToken = tokenRes.refresh_token;
}
}
try {
return await (
await fetch("https://api.spotify.com/v1" + endpoint, {
method,
headers: {
Authorization: `Bearer ${state.accessToken}`
},
body: JSON.stringify(data)
})
).json();
} catch {
return {};
}
}
export async function spotifyFilter() {
const likedSongs = (await reqSpotify("/me/tracks")).items.map((item) => {
return {
uri: item.track.uri
};
});
await reqSpotify("/playlists/0jWbMtGfptAzenepLTL4ED/tracks", "DELETE", {
tracks: likedSongs
});
await reqSpotify("/playlists/0jWbMtGfptAzenepLTL4ED/tracks", "POST", {
uris: likedSongs.map((lss) => lss.uri),
position: 0
});
await reqSpotify("/me/tracks", "DELETE", {
ids: likedSongs.map((lss) => lss.uri.replace("spotify:track:", ""))
});
}

27
src/utils.ts Normal file
View file

@ -0,0 +1,27 @@
import { readFileSync, writeFileSync } from "fs";
import path from "path";
export const state = new Proxy<{
explodesAt: number;
accessToken: string;
refreshToken: string;
}>(JSON.parse(readFileSync(path.join(__dirname, "../state.json"), "utf-8")), {
get(target, prop) {
const data = readFileSync(
path.join(__dirname, "../state.json"),
"utf-8"
);
return JSON.parse(data)[prop];
},
set(target, prop, value) {
const data = JSON.parse(
readFileSync(path.join(__dirname, "../state.json"), "utf-8")
);
data[prop] = value;
writeFileSync(
path.join(__dirname, "../state.json"),
JSON.stringify(data)
);
return true;
}
});