music-very-player/src/playlists_manager.js

114 lines
3.8 KiB
JavaScript

const fs = require('fs').promises
const ytdl = require('ytdl-core')
const Discord = require('discord.js')
const { Manager } = require('./manager')
const { Playlist } = require('./playlist');
const { youtube_instance } = require('../src/youtube');
/**
* @extends Manager
*/
class PlaylistsManager extends Manager {
#playlists
#filepath
constructor(gmanager, guild_id, { filepath = "playlists_manager.db", data = null } = {}) {
return (async () => {
super(...arguments)
const playlists = data || await PlaylistsManager.readFile(filepath)
Object.entries(playlists).forEach(([title, tracks]) => {
playlists[title] = new Playlist({ tracks, name: title })
})
this.#playlists = playlists
this.#filepath = filepath
return this
})()
}
static async readFile(filename) {
try {
return JSON.parse(await fs.readFile(filename, 'utf-8'))
} catch (e) {
console.warn(`> Impossible to read file "${filename}"`)
return {}
}
}
static async writeFile(filename, playlists) {
return await fs.writeFile(filename, JSON.stringify(playlists, null, 2))
}
async register({ message, params }) {
const player = this.get_manager('player')
if (params[0] || player.get_playlist().is_named()) {
const playlist_title = params[0] || player.get_playlist().get_name()
this.#playlists[playlist_title] = player.get_playlist().clone()
await PlaylistsManager.writeFile(this.#filepath, this.#playlists)
message.channel.send(`:white_check_mark: Playlist \`${playlist_title}\` saved`)
player.get_playlist().untouch()
return true
} else {
message.channel.send(`:warning: Cannot save playlist without name`)
return false
}
}
async load({ message, params }) {
const player = this.get_manager('player')
const playlist_title = params[0] // TODO handle long names with spaces...
const named_playlist = { title: playlist_title, playlist: this.#playlists[playlist_title] }
// const playlist_id = params[0]
// const named_playlist = this.#playlists[playlist_id - 1]
if (named_playlist) {
player.set_playlist(named_playlist.playlist.clone())
message.channel.send(`:white_check_mark: Playlist \`${playlist_title}\` loaded`)
} else {
message.channel.send(`:warning: Cannot find playlist id \`${playlist_title}\``)
}
}
async fork({ message, params }) {
const [source, destination] = params
if (!this.#playlists[source]) {
message.channel.send(`:warning: Cannot find playlist source \`${source}\``)
} else {
this.#playlists[destination] = this.#playlists[source].clone()
await PlaylistsManager.writeFile(this.#filepath, this.#playlists)
message.channel.send(`:white_check_mark: Playlist \`${source}\` forked as \`${destination}\``)
}
}
async list({ message, params }) {
message.channel.send(
"Playlists:\n" +
"```json\n" +
Object.entries(this.#playlists).map(([title, p], idx) => `${idx+1}: ${title} (${p.get_duration_as_string()})`).join("\n") +
"```\n",
)
}
async import({ message, params }) {
const [playlist_title, query] = params
const playlist = await youtube_instance.get_playlist(query)
this.#playlists[playlist_title] = playlist
await PlaylistsManager.writeFile(this.#filepath, this.#playlists)
message.channel.send(`:white_check_mark: Playlist \`${playlist_title}\` imported`)
}
async export({ message, params }) {
if (params.length === 0) params = ["db"]
switch (params[0]) {
case "db":
const export_file = new Discord.MessageAttachment(this.#filepath);
message.channel.send(export_file)
break
default:
message.channel.send(`:warning: Cannot export this format.`)
}
}
}
module.exports = { PlaylistsManager }