diff --git a/music/build.gradle.kts b/music/build.gradle.kts index 4c0630e8..e6c128d1 100644 --- a/music/build.gradle.kts +++ b/music/build.gradle.kts @@ -1,3 +1,3 @@ subprojects { - version = "3.12.0-SNAPSHOT" + version = "3.12.1-SNAPSHOT" } diff --git a/music/player/src/main/kotlin/dev/schlaubi/mikmusic/core/MusicModule.kt b/music/player/src/main/kotlin/dev/schlaubi/mikmusic/core/MusicModule.kt index ad05ea5f..8e7b9c70 100644 --- a/music/player/src/main/kotlin/dev/schlaubi/mikmusic/core/MusicModule.kt +++ b/music/player/src/main/kotlin/dev/schlaubi/mikmusic/core/MusicModule.kt @@ -72,6 +72,8 @@ class MusicModule(context: PluginContext) : MikBotModule(context) { } } + internal fun unregister(guildId: Snowflake) = musicPlayers.remove(guildId) + override suspend fun setup() { registerSerializer(TrackListSerializer) registerSerializer(TrackLinkedListSerializer) diff --git a/music/player/src/main/kotlin/dev/schlaubi/mikmusic/musicchannel/MusicInteractionModule.kt b/music/player/src/main/kotlin/dev/schlaubi/mikmusic/musicchannel/MusicInteractionModule.kt index 6ffdfb9e..b9fe40c1 100644 --- a/music/player/src/main/kotlin/dev/schlaubi/mikmusic/musicchannel/MusicInteractionModule.kt +++ b/music/player/src/main/kotlin/dev/schlaubi/mikmusic/musicchannel/MusicInteractionModule.kt @@ -7,7 +7,7 @@ import dev.kord.core.behavior.channel.withTyping import dev.kord.core.behavior.interaction.response.EphemeralMessageInteractionResponseBehavior import dev.kord.core.behavior.interaction.response.createEphemeralFollowup import dev.kord.core.behavior.reply -import dev.kord.core.event.interaction.ComponentInteractionCreateEvent +import dev.kord.core.event.interaction.GuildComponentInteractionCreateEvent import dev.kord.core.event.message.MessageCreateEvent import dev.schlaubi.mikbot.plugin.api.PluginContext import dev.schlaubi.mikbot.plugin.api.module.MikBotModule @@ -30,7 +30,7 @@ class MusicInteractionModule(context: PluginContext) : MikBotModule(context) { val musicModule: MusicModule by extension() override suspend fun setup() { - event { + event { check { failIf { val interaction = this.event.interaction @@ -41,6 +41,11 @@ class MusicInteractionModule(context: PluginContext) : MikBotModule(context) { /* return */ interaction.message.id != guildSettings.musicChannelData?.musicChannelMessage } + failIf(translate("music.music_channel.disabled", "music")) { + val player = musicModule.getMusicPlayer(event.interaction.guild) + player.disableMusicChannel + } + musicControlCheck() respondIfFailed() } diff --git a/music/player/src/main/kotlin/dev/schlaubi/mikmusic/player/MusicPlayer.kt b/music/player/src/main/kotlin/dev/schlaubi/mikmusic/player/MusicPlayer.kt index 88e7a096..0742e336 100644 --- a/music/player/src/main/kotlin/dev/schlaubi/mikmusic/player/MusicPlayer.kt +++ b/music/player/src/main/kotlin/dev/schlaubi/mikmusic/player/MusicPlayer.kt @@ -27,15 +27,26 @@ import dev.schlaubi.lavakord.plugins.sponsorblock.rest.getSponsorblockCategories import dev.schlaubi.lavakord.plugins.sponsorblock.rest.putSponsorblockCategories import dev.schlaubi.lavakord.rest.getPlayer import dev.schlaubi.lavakord.rest.updatePlayer +import dev.schlaubi.mikmusic.core.MusicModule import dev.schlaubi.mikmusic.core.settings.MusicSettingsDatabase import dev.schlaubi.mikmusic.musicchannel.updateMessage import dev.schlaubi.mikmusic.player.queue.SchedulingOptions +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel +import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock +import org.koin.core.component.get import org.koin.core.component.inject +import kotlin.coroutines.CoroutineContext import kotlin.time.Duration import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds @@ -50,7 +61,7 @@ internal data class SavedTrack( val pause: Boolean, ) -class MusicPlayer(val link: Link, private val guild: GuildBehavior) : Link by link, KordExKoinComponent , KordObject { +class MusicPlayer(val link: Link, private val guild: GuildBehavior) : Link by link, KordExKoinComponent, CoroutineScope, KordObject { private val lock = Mutex() @@ -74,6 +85,9 @@ class MusicPlayer(val link: Link, private val guild: GuildBehavior) : Link by li get() = !autoPlay?.songs.isNullOrEmpty() val autoPlayTrackCount get() = autoPlay?.songs?.size ?: 0 + private val musicChannelUpdateFlow = MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST) + override val coroutineContext: CoroutineContext + get() = kord.coroutineContext + SupervisorJob() init { guild.kord.launch { @@ -88,6 +102,9 @@ class MusicPlayer(val link: Link, private val guild: GuildBehavior) : Link by li link.player.on(consumer = ::onTrackStart) link.player.on(consumer = ::onChaptersLoaded) link.player.on(consumer = ::onChapterStarted) + musicChannelUpdateFlow.debounce(5.seconds).onEach { + doMusicChannelMessageUpdate() + }.launchIn(this) } private fun updateSponsorBlock() = guild.kord.launch { @@ -111,11 +128,6 @@ class MusicPlayer(val link: Link, private val guild: GuildBehavior) : Link by li @Suppress("unused") // used by other plugins fun updateMusicChannelState(to: Boolean) { - if (to) { - queue.clear() - playingTrack = null - updateMusicChannelMessage() - } disableMusicChannel = to } @@ -367,9 +379,14 @@ class MusicPlayer(val link: Link, private val guild: GuildBehavior) : Link by li autoPlay = null playingTrack = null updateMusicChannelMessage() + cancel() + get().unregister(guild.id) } fun updateMusicChannelMessage() { + musicChannelUpdateFlow.tryEmit(Unit) + } + private fun doMusicChannelMessageUpdate() { if (!disableMusicChannel) { guild.kord.launch { updateMessage(