music-very-player/src/resource_manager.js

100 lines
3.2 KiB
JavaScript

const { Manager } = require('./manager')
const { GuildAction } = require('./guild_action')
const { Track } = require('./track')
const { youtube_instance } = require("./youtube")
/**
* The {@link Manager} that manage resources. Its main goal is to search resources and get their metadata.<br />
* Note that it only works for YouTube videos for now.
* @extends Manager
*/
class ResourceManager extends Manager {
#awaiting_answers
constructor() {
super(...arguments)
this.#awaiting_answers = []
}
/**
* Performs a research, depending on the search terms it's been asked for
* @param {string|string[]} query The search terms
* @returns {Track[]} An array of objects representing the search results.
*/
async get_search_results(query) {
if (query instanceof Array)
query = query.join(' ')
return await youtube_instance.search_track(query)
}
/**
* Do a research and send the search results back to the Discord channel it's been asked for
* @param {GuildAction}
*/
async search({ message, params }) {
const tracks = await this.get_search_results(params)
if (tracks.length === 0) {
message.channel.send(':warning: Something went wrong. Please try again')
} else {
const text_res = tracks
.slice(0, 10)
.map((track, i) => (i + 1) + ' ' + track)
.join('\n')
const input_manager = this.get_manager('input')
// TODO: 2000 chars limit
// TODO: find a better syntaxic coloration than js
const own_message = await message.channel.send('```js\n' + text_res + '```')
const trigger = {
pattern: /^\d+/,
target: 'resource',
action: 'search_confirm',
ttl: 300,
user_shared: false,
repeat: 1,
on_expire: function() {
own_message.react('🛑')
}
}
this.#awaiting_answers.push({
trigger: trigger,
search_results: tracks,
from: message.member.id
})
input_manager.add_trigger(trigger)
}
}
/**
* Choose a track given its id in a search result. Note that this only works right after a call to the {@link ResourceManager#search} action.
* @param {GuildAction}
*/
async search_confirm({ message, params }) {
// TODO: update this so that it can be more relient on the Trigger received
const id = parseInt(message.content)
const answer = this.#awaiting_answers
.filter(a => a.from === message.member.id)
.slice(-1)[0]
if (answer === undefined) {
message.channel.send(':warning: Something went wrong. That\'s not supposed to happen...')
} else if (answer.search_results[id - 1] === undefined) {
message.channel.send(':warning: Please choose a number between 1 and ' + answer.search_results.length)
} else {
// TODO: calling the add method is a bit ugly, we can probably do better...
const action = new GuildAction({ message, params: [answer.search_results[id - 1].get_url()] })
this.get_manager('player').add(action)
message.react('👌')
}
}
/**
* Given the url of a song, get its metadata.
* @param {string} url
* @returns {Track}
*/
async get_metadata(url) {
return youtube_instance.get_metadata(url)
}
}
module.exports = { ResourceManager }