I AM MUSIC
This commit is contained in:
parent
182f12f32c
commit
7c74f50c35
4 changed files with 102 additions and 27 deletions
40
src/index.ts
40
src/index.ts
|
@ -1,34 +1,11 @@
|
||||||
import Fastify from "fastify";
|
import Fastify from "fastify";
|
||||||
import { Yapper } from "./Yapper";
|
import { Yapper } from "./Yapper";
|
||||||
import path from "path";
|
import { state } from "./utils";
|
||||||
import { readFileSync, stat, writeFileSync } from "fs";
|
import { reqSpotify, spotifyFilter } from "./spotify";
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
const fastify = Fastify({
|
const fastify = Fastify({
|
||||||
loggerInstance: new Yapper()
|
loggerInstance: new Yapper(),
|
||||||
|
disableRequestLogging: true
|
||||||
});
|
});
|
||||||
|
|
||||||
fastify.get("/", (request, reply) => {
|
fastify.get("/", (request, reply) => {
|
||||||
|
@ -72,12 +49,21 @@ fastify.get("/callback", async (request, reply) => {
|
||||||
})
|
})
|
||||||
).json();
|
).json();
|
||||||
|
|
||||||
|
if (tokenRes.error) return reply.code(400).send();
|
||||||
|
|
||||||
state.accessToken = tokenRes.access_token;
|
state.accessToken = tokenRes.access_token;
|
||||||
state.explodesAt = Date.now() + tokenRes.expires_in * 1000;
|
state.explodesAt = Date.now() + tokenRes.expires_in * 1000;
|
||||||
state.refreshToken = tokenRes.refresh_token;
|
state.refreshToken = tokenRes.refresh_token;
|
||||||
|
|
||||||
|
return `Logged in as ${
|
||||||
|
(await reqSpotify("/me")).display_name
|
||||||
|
}. You're good to go!`;
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
setInterval(spotifyFilter, 5000);
|
||||||
|
spotifyFilter();
|
||||||
|
|
||||||
fastify.listen({
|
fastify.listen({
|
||||||
port: 4929,
|
port: 4929,
|
||||||
host: "0.0.0.0"
|
host: "0.0.0.0"
|
||||||
|
|
62
src/spotify.ts
Normal file
62
src/spotify.ts
Normal 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
27
src/utils.ts
Normal 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;
|
||||||
|
}
|
||||||
|
});
|
Loading…
Add table
Add a link
Reference in a new issue