From 00e558b5cbe5678583643d6a8bb7372311628526 Mon Sep 17 00:00:00 2001 From: Yuzu Date: Tue, 5 Jul 2022 14:54:08 +0700 Subject: [PATCH] Implemented PlayMy feature --- locales/en.json | 3 + locales/jp.json | 3 + locales/th.json | 3 + src/discord/MusicPlayer/PlayMy.ts | 161 ++++++++++++++++++++++++++++++ src/providers/Discord.ts | 2 + 5 files changed, 172 insertions(+) create mode 100644 src/discord/MusicPlayer/PlayMy.ts diff --git a/locales/en.json b/locales/en.json index de0a33b..c2c24df 100644 --- a/locales/en.json +++ b/locales/en.json @@ -108,6 +108,9 @@ "queue_added_songs_description": "Added {{COUNT}} songs to the queue", "error": "Error while looking up the song" }, + "musicplayer_playmy": { + "not_detected": "You don't seem to be listening to any music currently according to your activity" + }, "musicplayer_queue": { "title": "Queue", "empty": "The queue is empty! (っ˘ω˘ς )", diff --git a/locales/jp.json b/locales/jp.json index 12ab5e5..9e30df3 100644 --- a/locales/jp.json +++ b/locales/jp.json @@ -108,6 +108,9 @@ "queue_added_songs_description": "キューに{{COUNT}}曲を追加", "error": "曲の検索中にエラーが発生" }, + "musicplayer_playmy": { + "not_detected": "あなたの活動状況を見ると、現在、音楽を聴いていないようですね" + }, "musicplayer_queue": { "title": "キュー", "empty": "キューは空です! (っ˘ω˘ς )", diff --git a/locales/th.json b/locales/th.json index 2fc9094..9d4da6e 100644 --- a/locales/th.json +++ b/locales/th.json @@ -108,6 +108,9 @@ "queue_added_songs_description": "เพิ่ม {{COUNT}} เพลงในคิว", "error": "เกิดข้อผิดพลาดขณะค้นหาเพลง" }, + "musicplayer_playmy": { + "not_detected": "เท่าที่ดูจากกิจกรรมของคุณ เหมือนว่าตอนนี้คุณไม่ได้เล่นเพลงอะไรอยู่นะ" + }, "musicplayer_queue": { "title": "คิวเพลง", "empty": "ตอนนี้คิวว่างนะ (っ˘ω˘ς )", diff --git a/src/discord/MusicPlayer/PlayMy.ts b/src/discord/MusicPlayer/PlayMy.ts new file mode 100644 index 0000000..c64089f --- /dev/null +++ b/src/discord/MusicPlayer/PlayMy.ts @@ -0,0 +1,161 @@ +import { I18n } from "i18n"; +import { Message, CommandInteraction, ActivityType, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; + +import DiscordMusicPlayer, { TrackUtils, ValidTracks } from "../../providers/DiscordMusicPlayer"; +import Locale from "../../services/Locale"; + +import { makeSuccessEmbed, makeErrorEmbed, sendHybridInteractionMessageResponse } from "../../utils/DiscordMessage"; +import DiscordModule, { HybridInteractionMessage } from "../../utils/DiscordModule"; +import { joinVoiceChannelProcedure } from "./Join"; + +const EMBEDS = { + NOT_DETECTED: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('musicplayer_playmy.not_detected'), + user: data.getUser() + }); + }, + USER_NOT_IN_VOICECHANNEL: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('musicplayer.not_in_voice'), + user: data.getUser() + }); + }, + USER_NOT_IN_SAME_VOICECHANNEL: (data: HybridInteractionMessage, locale: I18n) => { + return makeErrorEmbed({ + title: locale.__('musicplayer.different_voice_channel'), + user: data.getUser() + }); + }, + ADDED_QUEUE: async (data: HybridInteractionMessage, locale: I18n, track: ValidTracks) => { + + const title = TrackUtils.getTitle(track); + const thumbnails = await TrackUtils.getThumbnails(track); + + let embed = makeSuccessEmbed({ + title: locale.__('musicplayer_play.queue_added_song'), + description: title, + user: data.getUser() + }); + + if (TrackUtils.getHighestResolutionThumbnail(thumbnails)) + embed.setImage(TrackUtils.getHighestResolutionThumbnail(thumbnails).url); + + return embed; + } +} + +export default class PlayMy extends DiscordModule { + + public id = "Discord_MusicPlayer_PlayMy"; + public commands = ["playmy"]; + public commandInteractionName = "playmy"; + + async GuildOnModuleCommand(args: any, message: Message) { + await this.run(new HybridInteractionMessage(message), args); + } + + async GuildModuleCommandInteractionCreate(interaction: CommandInteraction) { + await this.run(new HybridInteractionMessage(interaction), interaction.options); + } + + async run(data: HybridInteractionMessage, args: any) { + + const guild = data.getGuild(); + const member = data.getMember(); + + if(!guild || !member) return; + + const locale = await Locale.getGuildLocale(guild.id); + + if (!member.voice.channel) + return await sendHybridInteractionMessageResponse(data, { + embeds: [EMBEDS.USER_NOT_IN_VOICECHANNEL(data, locale)] + }); + + const voiceChannel = member.voice.channel; + + if (!DiscordMusicPlayer.isGuildInstanceExists(guild.id)) { + await joinVoiceChannelProcedure(data, null, voiceChannel); + } + + let instance = DiscordMusicPlayer.getGuildInstance(guild.id); + if (!instance) return; + + if (instance!.voiceChannel.id !== member.voice.channel.id) + return await sendHybridInteractionMessageResponse( + data, + { embeds: [EMBEDS.USER_NOT_IN_SAME_VOICECHANNEL(data, locale)] }, + true + ); + + if (!instance!.isConnected()) { + await joinVoiceChannelProcedure(data, instance!, voiceChannel); + instance = DiscordMusicPlayer.getGuildInstance(guild.id); + } + + if(!instance) return; + if(!member.presence) return; + if(!member.presence.activities) return; + + let query; + let found = false; + for (const activity of member.presence.activities) { + if(activity.type === ActivityType.Listening) { + if(!activity.details) continue; + found = true; + + if(activity.name == "Spotify") + query = `${activity.state} - ${activity.details}` + else + query = `${activity.state} - ${activity.details}` // TODO: Find better query formula + + const result = await DiscordMusicPlayer.searchYouTubeByQuery(query); + if (!result) continue; + instance.addTrackToQueue(result[0]); + + let row; + if (result.length > 1) { + // TODO: Find a better logic than this + // If the first result title is exact match with the query or first title contains half the space of the query, it's probably a sentence + // then we don't need to show the search results + // if(result[0].title === query || result[0].title && (Math.ceil((result[0].title.split(" ").length - 1) / 2) === Math.ceil((query.split(" ").length - 1) / 2))) return; + + // The query length is too long to fit in json + if (query.length > 100 - 51) return; + + row = new ActionRowBuilder().addComponents( + new ButtonBuilder() + .setEmoji('🔎') + .setCustomId( + JSON.stringify({ + m: 'MP_S', + a: 'search', + d: { + q: query + } + }) + ) + .setLabel(' Not this? Search!') + .setStyle(ButtonStyle.Primary) + ); + } + + if(!row) + await sendHybridInteractionMessageResponse(data, { + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])] + }); + else + await sendHybridInteractionMessageResponse(data, { + embeds: [await EMBEDS.ADDED_QUEUE(data, locale, result[0])], + components: [row] + }); + } + } + + if(!found) + await sendHybridInteractionMessageResponse(data, { embeds:[EMBEDS.NOT_DETECTED(data, locale)] }); + + return; + } +} \ No newline at end of file diff --git a/src/providers/Discord.ts b/src/providers/Discord.ts index 24ad2d6..6e4b556 100644 --- a/src/providers/Discord.ts +++ b/src/providers/Discord.ts @@ -17,6 +17,7 @@ import Discord_Stats from '../discord/Stats'; import Discord_Support from '../discord/Support'; import Discord_MusicPlayer_Play from '../discord/MusicPlayer/Play'; +import Discord_MusicPlayer_PlayMy from '../discord/MusicPlayer/PlayMy'; import Discord_MusicPlayer_Skip from '../discord/MusicPlayer/Skip'; import Discord_MusicPlayer_Join from '../discord/MusicPlayer/Join'; import Discord_MusicPlayer_Leave from '../discord/MusicPlayer/Leave'; @@ -68,6 +69,7 @@ class Discord { new Discord_Support(), new Discord_MusicPlayer_Play(), + new Discord_MusicPlayer_PlayMy(), new Discord_MusicPlayer_NowPlaying(), new Discord_MusicPlayer_Skip(), new Discord_MusicPlayer_Join(),