Read playlist song limit from Settings

This commit is contained in:
Thongrapee Panyapatiphan 2021-10-01 21:11:43 +07:00
parent 96dcc4a536
commit c9cc9a17b1
No known key found for this signature in database
GPG key ID: 4B08AEC7F50F1967
3 changed files with 27 additions and 14 deletions

View file

@ -1,3 +1,4 @@
/* eslint-disable complexity */
import {TextChannel, Message} from 'discord.js'; import {TextChannel, Message} from 'discord.js';
import {URL} from 'url'; import {URL} from 'url';
import {Except} from 'type-fest'; import {Except} from 'type-fest';
@ -10,6 +11,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 Settings from '../models/settings.js';
@injectable() @injectable()
export default class implements Command { export default class implements Command {
@ -39,6 +41,7 @@ export default class implements Command {
public async execute(msg: Message, args: string[]): Promise<void> { public async execute(msg: Message, args: string[]): Promise<void> {
const [targetVoiceChannel] = getMemberVoiceChannel(msg.member!) ?? getMostPopularVoiceChannel(msg.guild!); const [targetVoiceChannel] = getMemberVoiceChannel(msg.member!) ?? getMostPopularVoiceChannel(msg.guild!);
const playlistLimit = await this.getPlaylistLimit(msg.guild!.id);
const res = new LoadingMessage(msg.channel as TextChannel); const res = new LoadingMessage(msg.channel as TextChannel);
await res.start(); await res.start();
@ -88,7 +91,8 @@ export default class implements Command {
// YouTube source // YouTube source
if (url.searchParams.get('list')) { if (url.searchParams.get('list')) {
// YouTube playlist // YouTube playlist
newSongs.push(...await this.getSongs.youtubePlaylist(url.searchParams.get('list')!)); const playlist = await this.getSongs.youtubePlaylist(url.searchParams.get('list')!, playlistLimit);
newSongs.push(...playlist);
} else { } else {
// Single video // Single video
const song = await this.getSongs.youtubeVideo(url.href); const song = await this.getSongs.youtubeVideo(url.href);
@ -101,13 +105,13 @@ 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], playlistLimit);
if (totalSongs > 50) { if (totalSongs > playlistLimit) {
extraMsg = 'a random sample of 50 songs was taken'; extraMsg = `a random sample of ${playlistLimit} songs was taken`;
} }
if (totalSongs > 50 && nSongsNotFound !== 0) { if (totalSongs > playlistLimit && nSongsNotFound !== 0) {
extraMsg += ' and '; extraMsg += ' and ';
} }
@ -166,4 +170,9 @@ export default class implements Command {
await player.play(); await player.play();
} }
} }
private async getPlaylistLimit(guildId: string) {
const settings = await Settings.findByPk(guildId);
return settings?.playlistLimit ?? 50;
}
} }

View file

@ -15,4 +15,8 @@ export default class Settings extends Model<Settings> {
@Default(false) @Default(false)
@Column @Column
finishedSetup!: boolean; finishedSetup!: boolean;
@Default(50)
@Column
playlistLimit!: number;
} }

View file

@ -97,7 +97,7 @@ export default class {
} }
} }
async youtubePlaylist(listId: string): Promise<QueuedSongWithoutChannel[]> { async youtubePlaylist(listId: string, limit: number): Promise<QueuedSongWithoutChannel[]> {
// YouTube playlist // YouTube playlist
const playlist = await this.cache.wrap( const playlist = await this.cache.wrap(
this.youtube.playlists.get, this.youtube.playlists.get,
@ -126,7 +126,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: `${limit}`, pageToken: nextToken},
{ {
expiresIn: ONE_MINUTE_IN_SECONDS, expiresIn: ONE_MINUTE_IN_SECONDS,
}, },
@ -188,7 +188,7 @@ export default class {
return songsToReturn; return songsToReturn;
} }
async spotifySource(url: string): Promise<[QueuedSongWithoutChannel[], number, number]> { async spotifySource(url: string, limit: number): Promise<[QueuedSongWithoutChannel[], number, number]> {
const parsed = spotifyURI.parse(url); const parsed = spotifyURI.parse(url);
let tracks: SpotifyApi.TrackObjectSimplified[] = []; let tracks: SpotifyApi.TrackObjectSimplified[] = [];
@ -199,7 +199,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})]);
tracks.push(...items); tracks.push(...items);
@ -210,7 +210,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})]);
playlist = {title: playlistResponse.name, source: playlistResponse.href}; playlist = {title: playlistResponse.name, source: playlistResponse.href};
@ -219,7 +219,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') ?? `${limit}`, 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 +252,13 @@ export default class {
} }
} }
// Get 50 random songs if many // Get random songs if the playlist is larger than limit
const originalNSongs = tracks.length; const originalNSongs = tracks.length;
if (tracks.length > 50) { if (tracks.length > limit) {
const shuffled = shuffle(tracks); const shuffled = shuffle(tracks);
tracks = shuffled.slice(0, 50); tracks = shuffled.slice(0, limit);
} }
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)));