From 296a0a8178fb3c670c924b230a042cc1e6241719 Mon Sep 17 00:00:00 2001 From: Thongrapee Panyapatiphan Date: Thu, 30 Sep 2021 23:55:21 +0700 Subject: [PATCH] Add config for song limit per playlist --- src/commands/play.ts | 15 +++++++++++---- src/services/config.ts | 11 +++++++++++ src/services/get-songs.ts | 16 +++++++++------- 3 files changed, 31 insertions(+), 11 deletions(-) diff --git a/src/commands/play.ts b/src/commands/play.ts index a907a40..81a4ae1 100644 --- a/src/commands/play.ts +++ b/src/commands/play.ts @@ -10,6 +10,7 @@ import LoadingMessage from '../utils/loading-message.js'; import errorMsg from '../utils/error-msg.js'; import Command from '.'; import GetSongs from '../services/get-songs.js'; +import Config from '../services/config.js'; @injectable() export default class implements Command { @@ -31,10 +32,16 @@ export default class implements Command { private readonly playerManager: PlayerManager; private readonly getSongs: GetSongs; + private readonly playlistLimit: number; - constructor(@inject(TYPES.Managers.Player) playerManager: PlayerManager, @inject(TYPES.Services.GetSongs) getSongs: GetSongs) { + constructor( + @inject(TYPES.Managers.Player) playerManager: PlayerManager, + @inject(TYPES.Services.GetSongs) getSongs: GetSongs, + @inject(TYPES.Config) config: Config, + ) { this.playerManager = playerManager; this.getSongs = getSongs; + this.playlistLimit = config.getPlaylistLimit(); } public async execute(msg: Message, args: string[]): Promise { @@ -103,11 +110,11 @@ export default class implements Command { } else if (url.protocol === 'spotify:' || url.host === 'open.spotify.com') { const [convertedSongs, nSongsNotFound, totalSongs] = await this.getSongs.spotifySource(args[0]); - if (totalSongs > 50) { - extraMsg = 'a random sample of 50 songs was taken'; + if (totalSongs > this.playlistLimit) { + extraMsg = `a random sample of ${this.playlistLimit} songs was taken`; } - if (totalSongs > 50 && nSongsNotFound !== 0) { + if (totalSongs > this.playlistLimit && nSongsNotFound !== 0) { extraMsg += ' and '; } diff --git a/src/services/config.ts b/src/services/config.ts index 759a27a3..087ea0b 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -4,6 +4,7 @@ import path from 'path'; dotenv.config(); export const DATA_DIR = path.resolve(process.env.DATA_DIR ? process.env.DATA_DIR : './data'); +const DEFAULT_PLAYLIST_LIMIT = 50; const CONFIG_MAP = { DISCORD_TOKEN: process.env.DISCORD_TOKEN, @@ -12,6 +13,7 @@ const CONFIG_MAP = { SPOTIFY_CLIENT_SECRET: process.env.SPOTIFY_CLIENT_SECRET, DATA_DIR, CACHE_DIR: path.join(DATA_DIR, 'cache'), + PLAYLIST_LIMIT: process.env.PLAYLIST_LIMIT, } as const; @injectable() @@ -22,6 +24,7 @@ export default class Config { readonly SPOTIFY_CLIENT_SECRET!: string; readonly DATA_DIR!: string; readonly CACHE_DIR!: string; + readonly PLAYLIST_LIMIT!: string; constructor() { for (const [key, value] of Object.entries(CONFIG_MAP)) { @@ -33,4 +36,12 @@ export default class Config { this[key as keyof typeof CONFIG_MAP] = value; } } + + getPlaylistLimit() { + if (!this.PLAYLIST_LIMIT) { + return DEFAULT_PLAYLIST_LIMIT; + } + + return Number(this.PLAYLIST_LIMIT) || DEFAULT_PLAYLIST_LIMIT; + } } diff --git a/src/services/get-songs.ts b/src/services/get-songs.ts index ba4401c..dcf6823 100644 --- a/src/services/get-songs.ts +++ b/src/services/get-songs.ts @@ -27,6 +27,7 @@ export default class { private readonly youtubeKey: string; private readonly spotify: Spotify; private readonly cache: CacheProvider; + private readonly playlistLimit: number; private readonly ytsrQueue: PQueue; @@ -38,6 +39,7 @@ export default class { this.youtubeKey = config.YOUTUBE_API_KEY; this.spotify = thirdParty.spotify; this.cache = cache; + this.playlistLimit = config.getPlaylistLimit(); this.ytsrQueue = new PQueue({concurrency: 4}); } @@ -126,7 +128,7 @@ export default class { const {items, nextPageToken} = await this.cache.wrap( this.youtube.playlists.items, listId, - {maxResults: '50', pageToken: nextToken}, + {maxResults: `${this.playlistLimit}`, pageToken: nextToken}, { expiresIn: ONE_MINUTE_IN_SECONDS, }, @@ -199,7 +201,7 @@ export default class { case 'album': { const uri = parsed as spotifyURI.Album; - const [{body: album}, {body: {items}}] = await Promise.all([this.spotify.getAlbum(uri.id), this.spotify.getAlbumTracks(uri.id, {limit: 50})]); + const [{body: album}, {body: {items}}] = await Promise.all([this.spotify.getAlbum(uri.id), this.spotify.getAlbumTracks(uri.id, {limit: this.playlistLimit})]); tracks.push(...items); @@ -210,7 +212,7 @@ export default class { case 'playlist': { const uri = parsed as spotifyURI.Playlist; - let [{body: playlistResponse}, {body: tracksResponse}] = await Promise.all([this.spotify.getPlaylist(uri.id), this.spotify.getPlaylistTracks(uri.id, {limit: 50})]); + let [{body: playlistResponse}, {body: tracksResponse}] = await Promise.all([this.spotify.getPlaylist(uri.id), this.spotify.getPlaylistTracks(uri.id, {limit: this.playlistLimit})]); playlist = {title: playlistResponse.name, source: playlistResponse.href}; @@ -219,7 +221,7 @@ export default class { while (tracksResponse.next) { // eslint-disable-next-line no-await-in-loop ({body: tracksResponse} = await this.spotify.getPlaylistTracks(uri.id, { - limit: parseInt(new URL(tracksResponse.next).searchParams.get('limit') ?? '50', 10), + limit: parseInt(new URL(tracksResponse.next).searchParams.get('limit') ?? `${this.playlistLimit}`, 10), offset: parseInt(new URL(tracksResponse.next).searchParams.get('offset') ?? '0', 10), })); @@ -252,13 +254,13 @@ export default class { } } - // Get 50 random songs if many + // Get random songs if many then limit to playlistLimit (defaults to 50) const originalNSongs = tracks.length; - if (tracks.length > 50) { + if (tracks.length > this.playlistLimit) { const shuffled = shuffle(tracks); - tracks = shuffled.slice(0, 50); + tracks = shuffled.slice(0, this.playlistLimit); } let songs = await Promise.all(tracks.map(async track => this.spotifyToYouTube(track, playlist)));