From 0ad78ba49401f9aaa942b1dd1b2b20a4fa3d1ffa Mon Sep 17 00:00:00 2001 From: Jannik Reimers Date: Wed, 6 Nov 2024 19:28:45 +0100 Subject: [PATCH] this database stuff should work, making the livestream announcements configurable. --- build.gradle.kts | 2 +- src/main/kotlin/dev/jansel/feixiao/App.kt | 29 +++++---- .../dev/jansel/feixiao/database/Migrator.kt | 2 +- .../collections/StreamerCollection.kt | 46 +++++++++++++++ .../feixiao/database/entities/StreamerData.kt | 17 ++++++ .../jansel/feixiao/extensions/EventHooks.kt | 2 +- .../feixiao/extensions/StreamerCommand.kt | 59 +++++++++++++++++++ 7 files changed, 143 insertions(+), 14 deletions(-) create mode 100644 src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt create mode 100644 src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt create mode 100644 src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt diff --git a/build.gradle.kts b/build.gradle.kts index 4746407..f3a0b17 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { } kordEx { - kordExVersion = "2.3.1-SNAPSHOT" + kordExVersion = "2.2.1-SNAPSHOT" jvmTarget = 21 diff --git a/src/main/kotlin/dev/jansel/feixiao/App.kt b/src/main/kotlin/dev/jansel/feixiao/App.kt index 27f8b05..40ba1d5 100644 --- a/src/main/kotlin/dev/jansel/feixiao/App.kt +++ b/src/main/kotlin/dev/jansel/feixiao/App.kt @@ -3,20 +3,22 @@ */ package dev.jansel.feixiao +import com.github.twitch4j.TwitchClient import com.github.twitch4j.TwitchClientBuilder -import com.github.twitch4j.events.ChannelChangeTitleEvent import com.github.twitch4j.events.ChannelGoLiveEvent -import com.github.twitch4j.events.ChannelGoOfflineEvent +import dev.jansel.feixiao.database.collections.StreamerCollection import dev.jansel.feixiao.extensions.EventHooks import dev.jansel.feixiao.extensions.MessageEvents +import dev.jansel.feixiao.extensions.StreamerCommand import dev.jansel.feixiao.utils.* -import dev.kord.core.behavior.getChannelOf import dev.kord.core.entity.channel.GuildMessageChannel import dev.kordex.core.ExtensibleBot import dev.kordex.data.api.DataCollection import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +var twitchClient: TwitchClient? = null + suspend fun main() { val bot = ExtensibleBot(token) { database(true) @@ -24,27 +26,32 @@ suspend fun main() { extensions { add(::MessageEvents) add(::EventHooks) + add(::StreamerCommand) } } - val twitchClient = TwitchClientBuilder.builder() + twitchClient = TwitchClientBuilder.builder() .withEnableHelix(true) .withClientId(twitchcid) .withClientSecret(twitchcs) .build() - twitchClient.clientHelper.enableStreamEventListener("janselosu") - - twitchClient.eventManager.onEvent(ChannelGoLiveEvent::class.java) { + twitchClient!!.eventManager.onEvent(ChannelGoLiveEvent::class.java) { println("${it.channel.name} went live!") runBlocking { launch { - val twitchpingschannel = - bot.kordRef.getGuildOrNull(tserverid)?.getChannelOf(tchannelid) - twitchpingschannel?.createMessage("<@&1130981452130037800> ${it.channel.name} is now live at https://twitch.tv/${it.channel.name} streaming ${it.stream.gameName}: ${it.stream.title}") - bot.kordRef.editPresence { streaming(it.stream.title, "https://twitch.tv/${it.channel.name}") } + val streamer = StreamerCollection().getData(it.channel.name) + val channel = bot.kordRef.getChannelOf(streamer!!.servers.first().channelId) + val role = streamer.servers.first().roleId + if (role != null) { + channel?.createMessage("<@&$role> ${it.channel.name} went live streaming ${it.stream.gameName}: ${it.stream.title}") + } else { + channel?.createMessage("${it.channel.name} went live: ${it.stream.title}") + } } } } bot.start() } + + diff --git a/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt b/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt index c93d585..2043779 100644 --- a/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt +++ b/src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt @@ -36,7 +36,7 @@ object Migrator : KordExKoinComponent { when (nextVersion) { 1 -> ::v1 else -> break - } (db.mongo) + }(db.mongo) logger.info { "Migrated database to version $nextVersion." } } catch (t: Throwable) { diff --git a/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt new file mode 100644 index 0000000..8df3691 --- /dev/null +++ b/src/main/kotlin/dev/jansel/feixiao/database/collections/StreamerCollection.kt @@ -0,0 +1,46 @@ +package dev.jansel.feixiao.database.collections + +import dev.jansel.feixiao.database.Database +import dev.jansel.feixiao.database.entities.Server +import dev.jansel.feixiao.database.entities.StreamerData +import dev.kord.common.entity.Snowflake +import dev.kordex.core.koin.KordExKoinComponent +import org.koin.core.component.inject +import org.litote.kmongo.eq +import org.litote.kmongo.setValue + +class StreamerCollection : KordExKoinComponent { + private val db: + Database by inject() + + @PublishedApi + internal val collection = + db.mongo.getCollection() + + suspend fun getData(channelName: String): StreamerData? = + collection.findOne(StreamerData::name eq channelName) + + suspend fun updateData(guildId: Snowflake, channelId: Snowflake, streamerName: String, roleId: Snowflake?) { + val coll = collection.findOne(StreamerData::name eq streamerName) + if (coll != null) { + collection.updateOne( + StreamerData::name eq streamerName, + setValue(StreamerData::servers, coll.servers + listOf(Server(guildId, channelId, roleId))) + ) + } else { + collection.insertOne( + StreamerData(streamerName, listOf(Server(guildId, channelId, roleId))) + ) + } + } + + suspend fun removeData(guildId: Snowflake, channelId: Snowflake, streamerName: String, roleId: Snowflake?) { + val coll = collection.findOne(StreamerData::name eq streamerName) + if (coll != null) { + collection.updateOne( + StreamerData::name eq streamerName, + setValue(StreamerData::servers, coll.servers - Server(guildId, channelId, roleId)) + ) + } + } +} diff --git a/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt b/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt new file mode 100644 index 0000000..66de7f2 --- /dev/null +++ b/src/main/kotlin/dev/jansel/feixiao/database/entities/StreamerData.kt @@ -0,0 +1,17 @@ +package dev.jansel.feixiao.database.entities + +import dev.kord.common.entity.Snowflake +import kotlinx.serialization.Serializable + +@Serializable +data class StreamerData( + val name: String, + val servers: List +) + +@Serializable +data class Server( + val guildId: Snowflake, + val channelId: Snowflake, + val roleId: Snowflake? +) diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt index 342e28e..38b457e 100644 --- a/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/EventHooks.kt @@ -11,7 +11,7 @@ class EventHooks : Extension() { event { action { println("Bot is ready!") - kord.editPresence { "electing a president..." } + kord.editPresence { listening("to the database") } } } } diff --git a/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt new file mode 100644 index 0000000..d68c9bf --- /dev/null +++ b/src/main/kotlin/dev/jansel/feixiao/extensions/StreamerCommand.kt @@ -0,0 +1,59 @@ +package dev.jansel.feixiao.extensions + +import dev.jansel.feixiao.database.collections.StreamerCollection +import dev.jansel.feixiao.twitchClient +import dev.kord.common.entity.Permission +import dev.kordex.core.checks.anyGuild +import dev.kordex.core.checks.hasPermission +import dev.kordex.core.commands.Arguments +import dev.kordex.core.commands.application.slash.publicSubCommand +import dev.kordex.core.commands.converters.impl.snowflake +import dev.kordex.core.commands.converters.impl.string +import dev.kordex.core.extensions.Extension +import dev.kordex.core.extensions.publicSlashCommand + +class StreamerCommand : Extension() { + override val name = "streamer" + override suspend fun setup() { + publicSlashCommand { + name = "streamer" + description = "Streamer commands" + + publicSubCommand(::StreamerArgs) { + name = "add" + description = "Add a streamer to the listener" + check { + anyGuild() + hasPermission(Permission.ManageGuild) + } + action { + val streamer = arguments.streamer + StreamerCollection().updateData(guild!!.id, channel.id, streamer, arguments.role) + twitchClient!!.clientHelper.enableStreamEventListener(streamer) + respond { + content = "Added streamer $streamer" + } + } + } + } + } + + inner class StreamerArgs : Arguments() { + val streamer by string { + name = "streamer" + description = "The streamer to add" + require(true) + } + val channel by snowflake { + name = "announceChannel" + description = "Channel where the bot will send a message when the streamer goes live" + require(true) + } + val role by snowflake { + name = "role" + description = "Role to ping when the streamer goes live" + require(false) + } + } + +}