From 054b8beef16137072ac4058231caeec47e15d8b1 Mon Sep 17 00:00:00 2001 From: SebClem Date: Tue, 21 Jun 2022 17:25:34 +0200 Subject: [PATCH] :hammer: Add music status api enpoint --- .../Api/Controllers/MusicController.java | 28 ++++++++ .../Broken/Api/Data/Music/PlayBackInfo.java | 12 ++++ .../net/Broken/Api/Data/Music/Status.java | 14 ++++ .../net/Broken/Api/Data/Music/TrackInfo.java | 17 +++++ .../java/net/Broken/Api/Data/UserInfo.java | 8 +++ .../net/Broken/Api/Services/AudioService.java | 65 +++++++++++++++++++ 6 files changed, 144 insertions(+) create mode 100644 src/main/java/net/Broken/Api/Controllers/MusicController.java create mode 100644 src/main/java/net/Broken/Api/Data/Music/PlayBackInfo.java create mode 100644 src/main/java/net/Broken/Api/Data/Music/Status.java create mode 100644 src/main/java/net/Broken/Api/Data/Music/TrackInfo.java create mode 100644 src/main/java/net/Broken/Api/Data/UserInfo.java create mode 100644 src/main/java/net/Broken/Api/Services/AudioService.java diff --git a/src/main/java/net/Broken/Api/Controllers/MusicController.java b/src/main/java/net/Broken/Api/Controllers/MusicController.java new file mode 100644 index 0000000..578ce6e --- /dev/null +++ b/src/main/java/net/Broken/Api/Controllers/MusicController.java @@ -0,0 +1,28 @@ +package net.Broken.Api.Controllers; + +import net.Broken.Api.Data.Music.Status; +import net.Broken.Api.Security.Data.JwtPrincipal; +import net.Broken.Api.Services.AudioService; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/v2/music") +@CrossOrigin(origins = "*", maxAge = 3600) +public class MusicController { + + public final AudioService audioService; + + public MusicController(AudioService audioService) { + this.audioService = audioService; + } + + + @GetMapping("/{guildId}/status") + @PreAuthorize("isInGuild(#guildId)") + public Status getMusicStatus(@PathVariable String guildId, Authentication authentication){ + JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); + return audioService.getGuildAudioStatus(guildId, principal.user().getDiscordId()); + } +} diff --git a/src/main/java/net/Broken/Api/Data/Music/PlayBackInfo.java b/src/main/java/net/Broken/Api/Data/Music/PlayBackInfo.java new file mode 100644 index 0000000..67079a0 --- /dev/null +++ b/src/main/java/net/Broken/Api/Data/Music/PlayBackInfo.java @@ -0,0 +1,12 @@ +package net.Broken.Api.Data.Music; + +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public record PlayBackInfo( + Boolean paused, + Boolean stopped, + Long progress, + TrackInfo trackInfo +) { +} diff --git a/src/main/java/net/Broken/Api/Data/Music/Status.java b/src/main/java/net/Broken/Api/Data/Music/Status.java new file mode 100644 index 0000000..5f64836 --- /dev/null +++ b/src/main/java/net/Broken/Api/Data/Music/Status.java @@ -0,0 +1,14 @@ +package net.Broken.Api.Data.Music; + +import com.fasterxml.jackson.annotation.JsonInclude; +import net.Broken.Api.Data.Guild.Channel; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public record Status( + Boolean connected, + Channel channel, + Boolean canView, + Boolean canInteract, + PlayBackInfo playBackInfo +) { +} diff --git a/src/main/java/net/Broken/Api/Data/Music/TrackInfo.java b/src/main/java/net/Broken/Api/Data/Music/TrackInfo.java new file mode 100644 index 0000000..fcb8abf --- /dev/null +++ b/src/main/java/net/Broken/Api/Data/Music/TrackInfo.java @@ -0,0 +1,17 @@ +package net.Broken.Api.Data.Music; + +import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; +import net.Broken.Api.Data.UserInfo; +import net.Broken.audio.UserAudioTrack; + +public record TrackInfo(UserInfo submitter, AudioTrackInfo detail) { + public TrackInfo(UserInfo submitter, AudioTrackInfo detail) { + this.submitter = submitter; + this.detail = detail; + } + + public TrackInfo(UserAudioTrack userAudioTrack) { + this(new UserInfo(userAudioTrack.getSubmittedUser().getId(), userAudioTrack.getSubmittedUser().getName(), userAudioTrack.getSubmittedUser().getAvatarUrl()), + userAudioTrack.getAudioTrack().getInfo()); + } +} diff --git a/src/main/java/net/Broken/Api/Data/UserInfo.java b/src/main/java/net/Broken/Api/Data/UserInfo.java new file mode 100644 index 0000000..1de4cdf --- /dev/null +++ b/src/main/java/net/Broken/Api/Data/UserInfo.java @@ -0,0 +1,8 @@ +package net.Broken.Api.Data; + +public record UserInfo( + String id, + String username, + String avatar +) { +} diff --git a/src/main/java/net/Broken/Api/Services/AudioService.java b/src/main/java/net/Broken/Api/Services/AudioService.java new file mode 100644 index 0000000..8857e08 --- /dev/null +++ b/src/main/java/net/Broken/Api/Services/AudioService.java @@ -0,0 +1,65 @@ +package net.Broken.Api.Services; + +import net.Broken.Api.Data.Guild.Channel; +import net.Broken.Api.Data.Music.PlayBackInfo; +import net.Broken.Api.Data.Music.Status; +import net.Broken.Api.Data.Music.TrackInfo; +import net.Broken.MainBot; +import net.Broken.audio.AudioM; +import net.Broken.audio.UserAudioTrack; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.GuildVoiceState; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.VoiceChannel; +import org.springframework.stereotype.Service; + +@Service +public class AudioService { + public Status getGuildAudioStatus(String guildId, String userId) { + Guild guild = MainBot.jda.getGuildById(guildId); + Member member = guild.getMemberById(userId); + GuildVoiceState voiceState = guild.getSelfMember().getVoiceState(); + + if (voiceState != null) { + VoiceChannel channel = voiceState.getChannel(); + if (channel != null) { +// The user can view the audio status if: +// -> He can view the voice channel +// -> OR He can *not* view the voice channel, but he is connected to this voice channel + boolean canView = member.hasPermission(channel, Permission.VIEW_CHANNEL) + || (member.getVoiceState() != null && member.getVoiceState().getChannel() == channel); + if (canView) { +// The user can interact with the audio if: +// -> He can connect to this voice channel +// -> AND He can speak in this voice channel +// -> AND He is connected to this voice channel + boolean canInteract = member.hasPermission(channel, Permission.VOICE_CONNECT, Permission.VOICE_SPEAK) + && member.getVoiceState() != null + && member.getVoiceState().getChannel() == channel; + AudioM audioM = AudioM.getInstance(guild); + boolean stopped = audioM.getGuildAudioPlayer().player.getPlayingTrack() == null; + PlayBackInfo playBackInfo; + if (!stopped) { + boolean paused = audioM.getGuildAudioPlayer().player.isPaused(); + long position = audioM.getGuildAudioPlayer().player.getPlayingTrack().getPosition(); + UserAudioTrack userAudioTrack = audioM.getGuildAudioPlayer().scheduler.getCurrentPlayingTrack(); + + playBackInfo = new PlayBackInfo(paused, false, position, new TrackInfo(userAudioTrack)); + + } else { + playBackInfo = new PlayBackInfo(false, true, null, null); + } + Channel channelApi = new Channel(channel.getId(), channel.getName()); + return new Status(true, channelApi, true, canInteract, playBackInfo); + + } else { + return new Status(true, null, false, false, null); + } + + + } + } + return new Status(false, null, null, null, null); + } +}