Add config for song limit per playlist

This commit is contained in:
Thongrapee Panyapatiphan 2021-09-30 23:55:21 +07:00
parent 811c80d544
commit 296a0a8178
No known key found for this signature in database
GPG key ID: 4B08AEC7F50F1967
3 changed files with 31 additions and 11 deletions

View file

@ -10,6 +10,7 @@ import LoadingMessage from '../utils/loading-message.js';
import errorMsg from '../utils/error-msg.js'; import errorMsg from '../utils/error-msg.js';
import Command from '.'; import Command from '.';
import GetSongs from '../services/get-songs.js'; import GetSongs from '../services/get-songs.js';
import Config from '../services/config.js';
@injectable() @injectable()
export default class implements Command { export default class implements Command {
@ -31,10 +32,16 @@ export default class implements Command {
private readonly playerManager: PlayerManager; private readonly playerManager: PlayerManager;
private readonly getSongs: GetSongs; 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.playerManager = playerManager;
this.getSongs = getSongs; this.getSongs = getSongs;
this.playlistLimit = config.getPlaylistLimit();
} }
public async execute(msg: Message, args: string[]): Promise<void> { public async execute(msg: Message, args: string[]): Promise<void> {
@ -103,11 +110,11 @@ export default class implements Command {
} else if (url.protocol === 'spotify:' || url.host === 'open.spotify.com') { } else if (url.protocol === 'spotify:' || url.host === 'open.spotify.com') {
const [convertedSongs, nSongsNotFound, totalSongs] = await this.getSongs.spotifySource(args[0]); const [convertedSongs, nSongsNotFound, totalSongs] = await this.getSongs.spotifySource(args[0]);
if (totalSongs > 50) { if (totalSongs > this.playlistLimit) {
extraMsg = 'a random sample of 50 songs was taken'; extraMsg = `a random sample of ${this.playlistLimit} songs was taken`;
} }
if (totalSongs > 50 && nSongsNotFound !== 0) { if (totalSongs > this.playlistLimit && nSongsNotFound !== 0) {
extraMsg += ' and '; extraMsg += ' and ';
} }

View file

@ -4,6 +4,7 @@ import path from 'path';
dotenv.config(); dotenv.config();
export const DATA_DIR = path.resolve(process.env.DATA_DIR ? process.env.DATA_DIR : './data'); export const DATA_DIR = path.resolve(process.env.DATA_DIR ? process.env.DATA_DIR : './data');
const DEFAULT_PLAYLIST_LIMIT = 50;
const CONFIG_MAP = { const CONFIG_MAP = {
DISCORD_TOKEN: process.env.DISCORD_TOKEN, DISCORD_TOKEN: process.env.DISCORD_TOKEN,
@ -12,6 +13,7 @@ const CONFIG_MAP = {
SPOTIFY_CLIENT_SECRET: process.env.SPOTIFY_CLIENT_SECRET, SPOTIFY_CLIENT_SECRET: process.env.SPOTIFY_CLIENT_SECRET,
DATA_DIR, DATA_DIR,
CACHE_DIR: path.join(DATA_DIR, 'cache'), CACHE_DIR: path.join(DATA_DIR, 'cache'),
PLAYLIST_LIMIT: process.env.PLAYLIST_LIMIT,
} as const; } as const;
@injectable() @injectable()
@ -22,6 +24,7 @@ export default class Config {
readonly SPOTIFY_CLIENT_SECRET!: string; readonly SPOTIFY_CLIENT_SECRET!: string;
readonly DATA_DIR!: string; readonly DATA_DIR!: string;
readonly CACHE_DIR!: string; readonly CACHE_DIR!: string;
readonly PLAYLIST_LIMIT!: string;
constructor() { constructor() {
for (const [key, value] of Object.entries(CONFIG_MAP)) { 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; 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;
}
} }

View file

@ -27,6 +27,7 @@ export default class {
private readonly youtubeKey: string; private readonly youtubeKey: string;
private readonly spotify: Spotify; private readonly spotify: Spotify;
private readonly cache: CacheProvider; private readonly cache: CacheProvider;
private readonly playlistLimit: number;
private readonly ytsrQueue: PQueue; private readonly ytsrQueue: PQueue;
@ -38,6 +39,7 @@ export default class {
this.youtubeKey = config.YOUTUBE_API_KEY; this.youtubeKey = config.YOUTUBE_API_KEY;
this.spotify = thirdParty.spotify; this.spotify = thirdParty.spotify;
this.cache = cache; this.cache = cache;
this.playlistLimit = config.getPlaylistLimit();
this.ytsrQueue = new PQueue({concurrency: 4}); this.ytsrQueue = new PQueue({concurrency: 4});
} }
@ -126,7 +128,7 @@ export default class {
const {items, nextPageToken} = await this.cache.wrap( const {items, nextPageToken} = await this.cache.wrap(
this.youtube.playlists.items, this.youtube.playlists.items,
listId, listId,
{maxResults: '50', pageToken: nextToken}, {maxResults: `${this.playlistLimit}`, pageToken: nextToken},
{ {
expiresIn: ONE_MINUTE_IN_SECONDS, expiresIn: ONE_MINUTE_IN_SECONDS,
}, },
@ -199,7 +201,7 @@ export default class {
case 'album': { case 'album': {
const uri = parsed as spotifyURI.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); tracks.push(...items);
@ -210,7 +212,7 @@ export default class {
case 'playlist': { case 'playlist': {
const uri = parsed as spotifyURI.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}; playlist = {title: playlistResponse.name, source: playlistResponse.href};
@ -219,7 +221,7 @@ export default class {
while (tracksResponse.next) { while (tracksResponse.next) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
({body: tracksResponse} = await this.spotify.getPlaylistTracks(uri.id, { ({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), 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; const originalNSongs = tracks.length;
if (tracks.length > 50) { if (tracks.length > this.playlistLimit) {
const shuffled = shuffle(tracks); 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))); let songs = await Promise.all(tracks.map(async track => this.spotifyToYouTube(track, playlist)));