aboutsummaryrefslogtreecommitdiff
path: root/src/services
diff options
context:
space:
mode:
Diffstat (limited to 'src/services')
-rw-r--r--src/services/config.ts36
-rw-r--r--src/services/get-songs.ts12
-rw-r--r--src/services/third-party.ts36
3 files changed, 79 insertions, 5 deletions
diff --git a/src/services/config.ts b/src/services/config.ts
new file mode 100644
index 0000000..80b4a81
--- /dev/null
+++ b/src/services/config.ts
@@ -0,0 +1,36 @@
+import dotenv from 'dotenv';
+import {injectable} from 'inversify';
+import path from 'path';
+dotenv.config();
+
+export const DATA_DIR = path.resolve(process.env.DATA_DIR ? process.env.DATA_DIR : './data');
+
+const CONFIG_MAP = {
+ DISCORD_TOKEN: process.env.DISCORD_TOKEN,
+ YOUTUBE_API_KEY: process.env.YOUTUBE_API_KEY,
+ SPOTIFY_CLIENT_ID: process.env.SPOTIFY_CLIENT_ID,
+ SPOTIFY_CLIENT_SECRET: process.env.SPOTIFY_CLIENT_SECRET,
+ DATA_DIR,
+ CACHE_DIR: path.join(DATA_DIR, 'cache')
+} as const;
+
+@injectable()
+export default class Config {
+ readonly DISCORD_TOKEN!: string;
+ readonly YOUTUBE_API_KEY!: string;
+ readonly SPOTIFY_CLIENT_ID!: string;
+ readonly SPOTIFY_CLIENT_SECRET!: string;
+ readonly DATA_DIR!: string;
+ readonly CACHE_DIR!: string;
+
+ constructor() {
+ for (const [key, value] of Object.entries(CONFIG_MAP)) {
+ if (typeof value === 'undefined') {
+ console.error(`Missing environment variable for ${key}`);
+ process.exit(1);
+ }
+
+ this[key as keyof typeof CONFIG_MAP] = value;
+ }
+ }
+}
diff --git a/src/services/get-songs.ts b/src/services/get-songs.ts
index d5ccdef..0a6524f 100644
--- a/src/services/get-songs.ts
+++ b/src/services/get-songs.ts
@@ -11,6 +11,8 @@ import {Except} from 'type-fest';
import {QueuedSong, QueuedPlaylist} from '../services/player';
import {TYPES} from '../types';
import {cleanUrl} from '../utils/url';
+import ThirdParty from './third-party';
+import Config from './config';
type QueuedSongWithoutChannel = Except<QueuedSong, 'addedInChannelId'>;
@@ -20,10 +22,10 @@ export default class {
private readonly youtubeKey: string;
private readonly spotify: Spotify;
- constructor(@inject(TYPES.Lib.YouTube) youtube: YouTube, @inject(TYPES.Config.YOUTUBE_API_KEY) youtubeKey: string, @inject(TYPES.Lib.Spotify) spotify: Spotify) {
- this.youtube = youtube;
- this.youtubeKey = youtubeKey;
- this.spotify = spotify;
+ constructor(@inject(TYPES.ThirdParty) thirdParty: ThirdParty, @inject(TYPES.Config) config: Config) {
+ this.youtube = thirdParty.youtube;
+ this.youtubeKey = config.YOUTUBE_API_KEY;
+ this.spotify = thirdParty.spotify;
}
async youtubeVideoSearch(query: string): Promise<QueuedSongWithoutChannel|null> {
@@ -214,7 +216,7 @@ export default class {
private async spotifyToYouTube(track: SpotifyApi.TrackObjectSimplified, _: QueuedPlaylist | null): Promise<QueuedSongWithoutChannel | null> {
try {
const {items} = await this.youtube.videos.search({q: `"${track.name}" "${track.artists[0].name}"`, maxResults: 10});
- const videoResult = items[0]; // Items.find(item => item.type === 'video');
+ const videoResult = items[0];
if (!videoResult) {
throw new Error('No video found for query.');
diff --git a/src/services/third-party.ts b/src/services/third-party.ts
new file mode 100644
index 0000000..00b9269
--- /dev/null
+++ b/src/services/third-party.ts
@@ -0,0 +1,36 @@
+import {inject, injectable} from 'inversify';
+import SpotifyWebApi from 'spotify-web-api-node';
+import Youtube from 'youtube.ts';
+import {TYPES} from '../types';
+import Config from './config';
+
+@injectable()
+export default class ThirdParty {
+ readonly youtube: Youtube;
+ readonly spotify: SpotifyWebApi;
+
+ private spotifyTokenTimerId?: NodeJS.Timeout;
+
+ constructor(@inject(TYPES.Config) config: Config) {
+ this.youtube = new Youtube(config.YOUTUBE_API_KEY);
+ this.spotify = new SpotifyWebApi({
+ clientId: config.SPOTIFY_CLIENT_ID,
+ clientSecret: config.SPOTIFY_CLIENT_SECRET
+ });
+
+ void this.refreshSpotifyToken();
+ }
+
+ cleanup() {
+ if (this.spotifyTokenTimerId) {
+ clearTimeout(this.spotifyTokenTimerId);
+ }
+ }
+
+ private async refreshSpotifyToken() {
+ const auth = await this.spotify.clientCredentialsGrant();
+ this.spotify.setAccessToken(auth.body.access_token);
+
+ this.spotifyTokenTimerId = setTimeout(this.refreshSpotifyToken, (auth.body.expires_in / 2) * 1000);
+ }
+}