From 851bd2f75dab065d20ea4ecbd6a30ea2bea4ff29 Mon Sep 17 00:00:00 2001 From: derpystuff <3515180-derpystuff@users.noreply.gitlab.com> Date: Wed, 25 May 2022 22:55:38 +0200 Subject: [PATCH] [cmd] audio search --- commands/message/search/audio.js | 97 ++++++++++++++++++++++++++++++++ labscore/api/endpoints.js | 1 + labscore/api/index.js | 6 ++ labscore/utils/attachment.js | 36 +++++++++++- labscore/utils/buttons.js | 46 +++++++++++++++ 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 commands/message/search/audio.js create mode 100644 labscore/utils/buttons.js diff --git a/commands/message/search/audio.js b/commands/message/search/audio.js new file mode 100644 index 0000000..b66aa98 --- /dev/null +++ b/commands/message/search/audio.js @@ -0,0 +1,97 @@ +const { createEmbed, formatPaginationEmbeds } = require('../../../labscore/utils/embed') +const { link } = require('../../../labscore/utils/markdown') +const { editOrReply } = require('../../../labscore/utils/message') + +const { paginator } = require('../../../labscore/client'); +const { searchAudio } = require('../../../labscore/api'); +const { getRecentVideo } = require('../../../labscore/utils/attachment'); +const { renderMusicButtons } = require('../../../labscore/utils/buttons'); + +const superagent = require('superagent') + +const urlr = /(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})/g + +module.exports = { + name: 'audio', + aliases: ['aud'], + metadata: { + description: 'video audio detection', + examples: ['aud'], + category: 'search', + usage: 'audio ' + }, + run: async (context) => { + context.triggerTyping(); + try{ + + if(context.message.messageReference){ + let msg; + try{ + msg = await context.message.channel.fetchMessage(context.message.messageReference.messageId) + } catch(e){ + return editOrReply(context, {embeds:[createEmbed("error", context, "Unable to fetch message.")]}) + } + console.log(msg) + let urls = msg.content.match(urlr) + console.log(urls) + if(urls){ + try{ + let songlink = await superagent.get(`https://api.song.link/v1-alpha.1/links?url=${encodeURIComponent(urls[0])}`) + let song = songlink.body.entitiesByUniqueId[songlink.body.entityUniqueId] + + let btns = renderMusicButtons(songlink.body.linksByPlatform) + console.log(JSON.stringify(btns, null, 2)) + return editOrReply(context, {embeds:[ + createEmbed("default", context, { + author: { + name: `${song.title} by ${song.artistName}`.substr(0,1000), + iconUrl: song.thumbnailUrl, + url: url + }, + footer: {} + }) + ], components: btns}) + }catch(e){ + console.log(e) + } //ignore it and run the audio detection flow + } + } + + + let audios = await getRecentVideo(context, 50) + if(!audios.length) return editOrReply(context, {embeds:[createEmbed("warning", context, `Could not find supported video.`)]}) + let audioSearch = await searchAudio(context, audios[0].url) + search = audioSearch.response + console.log(audioSearch.response.body) + if(audioSearch.response.body.status == 0){ + // API lowkey sucks, fetch more metadata via songlink + let url = audioSearch.response.body.media[Object.keys(audioSearch.response.body.media)[0]] + if(audioSearch.response.body.media.deezer) url = audioSearch.response.body.media.deezer + if(audioSearch.response.body.media.spotify) url = audioSearch.response.body.media.spotify + let songlink = await superagent.get(`https://api.song.link/v1-alpha.1/links?url=${encodeURIComponent(url)}`) + //get song meta + let song = songlink.body.entitiesByUniqueId[songlink.body.entityUniqueId] + + let btns = renderMusicButtons(songlink.body.linksByPlatform) + console.log(JSON.stringify(btns, null, 2)) + return editOrReply(context, {embeds:[ + createEmbed("default", context, { + author: { + name: `${song.title} by ${song.artistName}`.substr(0,1000), + iconUrl: song.thumbnailUrl, + url: url + }, + footer: {} + }) + ], components: btns}) + } + + }catch(e){ + console.log(e) + if(e.response?.body?.status){ + return editOrReply(context, {embeds:[createEmbed("error", context, e.response.body.message)]}) + } + return editOrReply(context, {embeds:[createEmbed("error", context, `Unable to perform audio search.`)]}) + } + }, +}; \ No newline at end of file diff --git a/labscore/api/endpoints.js b/labscore/api/endpoints.js index 4cd448e..92ea77c 100644 --- a/labscore/api/endpoints.js +++ b/labscore/api/endpoints.js @@ -12,6 +12,7 @@ const Api = Object.freeze({ SEARCH_LYRICS: '/search/lyrics', + SEARCH_AUDIO: '/search/audio', SEARCH_GOOGLE: '/search/google', SEARCH_GOOGLE_IMAGES: '/search/google-images', SEARCH_BING: '/search/bing', diff --git a/labscore/api/index.js b/labscore/api/index.js index bb1b31e..954bc0c 100644 --- a/labscore/api/index.js +++ b/labscore/api/index.js @@ -47,6 +47,12 @@ module.exports.googleVisionOcr = async function(context, url){ }) } +module.exports.searchAudio = async function(context, url){ + return await request(Api.SEARCH_AUDIO, "GET", {}, { + url: url + }) +} + module.exports.lyrics = async function(context, query){ return await request(Api.SEARCH_LYRICS, "GET", {}, { q: query diff --git a/labscore/utils/attachment.js b/labscore/utils/attachment.js index b546643..c13e9e4 100644 --- a/labscore/utils/attachment.js +++ b/labscore/utils/attachment.js @@ -47,7 +47,38 @@ async function getRecentMedia(context, limit) { return attachments; } -// simple helpers + +async function getRecentVideo(context, limit) { + if (!context.message.channel) { + return undefined; + } + + // Handle Replies + if (context.message.messageReference) { + messages = [[context.message.messageReference.messageId, await context.message.channel.fetchMessage(context.message.messageReference.messageId)]] // somewhat hacky but it works lol + } else { + messages = await context.message.channel.fetchMessages({ + limit: limit, + before: context.message.id + }) + } + + if (!messages) { + return undefined; + } + + let attachments = []; + for (const m of messages) { + let message = m[1] + if ( // Then the embed image + message.embeds.length > 0 && + message.embeds.toArray()[0].video + ) { + attachments.push(message.embeds.toArray()[0].video) + } + } + return attachments; +} async function getRecentImage(context, limit) { let attachments = await getRecentMedia(context, limit) @@ -64,5 +95,6 @@ async function getRecentImage(context, limit) { } module.exports = { - getRecentImage + getRecentImage, + getRecentVideo } \ No newline at end of file diff --git a/labscore/utils/buttons.js b/labscore/utils/buttons.js new file mode 100644 index 0000000..0b25bc1 --- /dev/null +++ b/labscore/utils/buttons.js @@ -0,0 +1,46 @@ +const MUSIC_PLATFORMS = { + "amazon": "914614653479428177", + "amazonMusic": "914624582302982194", + "deezer": "914614652644761650", + "appleMusic": "914615427009744927", + "itunes": "914614654964211722", + "napster": "914614654595133481", + "pandora": "914614655115218986", + "soundcloud": "914614653076791306", + "spotify": "914614653122932817", + "tidal": "914614653479428176", + "youtube": "914614653563310130", + "youtubeMusic": "914614653663989781" +} + +module.exports.renderMusicButtons = function(platforms){ + let btns = []; + for(const k of Object.keys(platforms)){ + let s = platforms[k] + if(MUSIC_PLATFORMS[k]){ + btns.push( + { + custom_id: k.toLowerCase(), + style: 5, + url: s.url, + emoji: { id: MUSIC_PLATFORMS[k]}, + type: 2 + } + ) + } + } + let rows = [] + while(btns.length){ + rows.push(btns.splice(0, 5)) + } + let components = [] + for(const r of rows){ + components.push( + { + components: r, + type: 1, + } + ) + } + return components +} \ No newline at end of file