add first database revision
This commit is contained in:
parent
69a08ce6d4
commit
65e4a3d77c
@ -20,6 +20,7 @@ dependencies {
|
|||||||
implementation(libs.kx.ser)
|
implementation(libs.kx.ser)
|
||||||
implementation(libs.kx.coroutines)
|
implementation(libs.kx.coroutines)
|
||||||
implementation(libs.twitch4j)
|
implementation(libs.twitch4j)
|
||||||
|
implementation(libs.kmongo)
|
||||||
|
|
||||||
// Logging dependencies
|
// Logging dependencies
|
||||||
implementation(libs.groovy)
|
implementation(libs.groovy)
|
||||||
@ -32,6 +33,8 @@ dependencies {
|
|||||||
kordEx {
|
kordEx {
|
||||||
kordExVersion = "2.3.1-SNAPSHOT"
|
kordExVersion = "2.3.1-SNAPSHOT"
|
||||||
|
|
||||||
|
jvmTarget = 21
|
||||||
|
|
||||||
bot {
|
bot {
|
||||||
// See https://docs.kordex.dev/data-collection.html
|
// See https://docs.kordex.dev/data-collection.html
|
||||||
dataCollection(DataCollection.Standard)
|
dataCollection(DataCollection.Standard)
|
||||||
@ -79,3 +82,8 @@ docker {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.wrapper {
|
||||||
|
gradleVersion = "8.10.2"
|
||||||
|
distributionType = Wrapper.DistributionType.BIN
|
||||||
|
}
|
||||||
|
@ -10,6 +10,7 @@ logging = "7.0.0"
|
|||||||
twitch4j = "1.22.0"
|
twitch4j = "1.22.0"
|
||||||
events4j = "0.12.2"
|
events4j = "0.12.2"
|
||||||
kx-coroutines = "1.9.0"
|
kx-coroutines = "1.9.0"
|
||||||
|
kmongo = "4.9.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
|
groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
|
||||||
@ -22,3 +23,4 @@ logback-groovy = { module = "io.github.virtualdogbert:logback-groovy-config", ve
|
|||||||
logging = { module = "io.github.oshai:kotlin-logging", version.ref = "logging" }
|
logging = { module = "io.github.oshai:kotlin-logging", version.ref = "logging" }
|
||||||
twitch4j = { module = "com.github.twitch4j:twitch4j", version.ref = "twitch4j" }
|
twitch4j = { module = "com.github.twitch4j:twitch4j", version.ref = "twitch4j" }
|
||||||
events4j = { module = "com.github.philippheuer.events4j:events4j-handler-simple", version.ref = "events4j" }
|
events4j = { module = "com.github.philippheuer.events4j:events4j-handler-simple", version.ref = "events4j" }
|
||||||
|
kmongo = { module="org.litote.kmongo:kmongo-coroutine-serialization", version.ref = "kmongo"}
|
||||||
|
@ -3,20 +3,48 @@
|
|||||||
*/
|
*/
|
||||||
package dev.jansel.feixiao
|
package dev.jansel.feixiao
|
||||||
|
|
||||||
|
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.extensions.EventHooks
|
import dev.jansel.feixiao.extensions.EventHooks
|
||||||
import dev.jansel.feixiao.extensions.MessageEvents
|
import dev.jansel.feixiao.extensions.MessageEvents
|
||||||
import dev.jansel.feixiao.utils.*
|
import dev.jansel.feixiao.utils.*
|
||||||
import dev.kordex.core.DATA_COLLECTION
|
import dev.kord.core.behavior.getChannelOf
|
||||||
|
import dev.kord.core.entity.channel.GuildMessageChannel
|
||||||
import dev.kordex.core.ExtensibleBot
|
import dev.kordex.core.ExtensibleBot
|
||||||
import dev.kordex.data.api.DataCollection
|
import dev.kordex.data.api.DataCollection
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
suspend fun main() {
|
suspend fun main() {
|
||||||
val bot = ExtensibleBot(token) {
|
val bot = ExtensibleBot(token) {
|
||||||
|
database(true)
|
||||||
dataCollectionMode = DataCollection.None
|
dataCollectionMode = DataCollection.None
|
||||||
extensions {
|
extensions {
|
||||||
add(::MessageEvents)
|
add(::MessageEvents)
|
||||||
add(::EventHooks)
|
add(::EventHooks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val twitchClient = TwitchClientBuilder.builder()
|
||||||
|
.withEnableHelix(true)
|
||||||
|
.withClientId(twitchcid)
|
||||||
|
.withClientSecret(twitchcs)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
twitchClient.clientHelper.enableStreamEventListener("janselosu")
|
||||||
|
|
||||||
|
twitchClient.eventManager.onEvent(ChannelGoLiveEvent::class.java) {
|
||||||
|
println("${it.channel.name} went live!")
|
||||||
|
runBlocking {
|
||||||
|
launch {
|
||||||
|
val twitchpingschannel =
|
||||||
|
bot.kordRef.getGuildOrNull(tserverid)?.getChannelOf<GuildMessageChannel>(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}") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bot.start()
|
bot.start()
|
||||||
}
|
}
|
||||||
|
24
src/main/kotlin/dev/jansel/feixiao/database/Database.kt
Normal file
24
src/main/kotlin/dev/jansel/feixiao/database/Database.kt
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package dev.jansel.feixiao.database
|
||||||
|
|
||||||
|
import com.mongodb.ConnectionString
|
||||||
|
import com.mongodb.MongoClientSettings
|
||||||
|
import dev.jansel.feixiao.utils.mongoUri
|
||||||
|
import org.bson.UuidRepresentation
|
||||||
|
import org.litote.kmongo.coroutine.coroutine
|
||||||
|
import org.litote.kmongo.reactivestreams.KMongo
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
private val settings = MongoClientSettings
|
||||||
|
.builder()
|
||||||
|
.uuidRepresentation(UuidRepresentation.STANDARD)
|
||||||
|
.applyConnectionString(ConnectionString(mongoUri))
|
||||||
|
.build()
|
||||||
|
|
||||||
|
private val client = KMongo.createClient(settings).coroutine
|
||||||
|
|
||||||
|
val mongo get() = client.getDatabase("Feixiao")
|
||||||
|
|
||||||
|
suspend fun migrate() {
|
||||||
|
Migrator.migrate()
|
||||||
|
}
|
||||||
|
}
|
59
src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt
Normal file
59
src/main/kotlin/dev/jansel/feixiao/database/Migrator.kt
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package dev.jansel.feixiao.database
|
||||||
|
|
||||||
|
import dev.jansel.feixiao.database.collections.MetaCollection
|
||||||
|
import dev.jansel.feixiao.database.entities.MetaData
|
||||||
|
import dev.jansel.feixiao.database.migrations.v1
|
||||||
|
import dev.kordex.core.koin.KordExKoinComponent
|
||||||
|
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
|
||||||
|
object Migrator : KordExKoinComponent {
|
||||||
|
private val logger = KotlinLogging.logger("Migrator Logger")
|
||||||
|
|
||||||
|
private val db: Database by inject()
|
||||||
|
private val mainMetaCollection: MetaCollection by inject()
|
||||||
|
|
||||||
|
suspend fun migrate() {
|
||||||
|
logger.info { "Starting main database migration" }
|
||||||
|
|
||||||
|
var meta = mainMetaCollection.get()
|
||||||
|
|
||||||
|
if (meta == null) {
|
||||||
|
meta = MetaData(0)
|
||||||
|
|
||||||
|
mainMetaCollection.set(meta)
|
||||||
|
}
|
||||||
|
|
||||||
|
var currentVersion = meta.version
|
||||||
|
|
||||||
|
logger.info { "Current main database version: v$currentVersion" }
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
val nextVersion = currentVersion + 1
|
||||||
|
|
||||||
|
@Suppress("TooGenericExceptionCaught", "UseIfInsteadOfWhen")
|
||||||
|
try {
|
||||||
|
when (nextVersion) {
|
||||||
|
1 -> ::v1
|
||||||
|
else -> break
|
||||||
|
} (db.mongo)
|
||||||
|
|
||||||
|
logger.info { "Migrated database to version $nextVersion." }
|
||||||
|
} catch (t: Throwable) {
|
||||||
|
logger.error(t) { "Failed to migrate database to version $nextVersion." }
|
||||||
|
|
||||||
|
throw t
|
||||||
|
}
|
||||||
|
|
||||||
|
currentVersion = nextVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentVersion != meta.version) {
|
||||||
|
meta = meta.copy(version = currentVersion)
|
||||||
|
|
||||||
|
mainMetaCollection.update(meta)
|
||||||
|
|
||||||
|
logger.info { "Finished main database migrations." }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package dev.jansel.feixiao.database.collections
|
||||||
|
|
||||||
|
import dev.jansel.feixiao.database.Database
|
||||||
|
import dev.jansel.feixiao.database.entities.MetaData
|
||||||
|
import dev.kordex.core.koin.KordExKoinComponent
|
||||||
|
import org.koin.core.component.inject
|
||||||
|
import org.litote.kmongo.eq
|
||||||
|
|
||||||
|
class MetaCollection : KordExKoinComponent {
|
||||||
|
private val db: Database by inject()
|
||||||
|
|
||||||
|
@PublishedApi
|
||||||
|
internal val collection = db.mongo.getCollection<MetaData>()
|
||||||
|
|
||||||
|
suspend fun get(): MetaData? =
|
||||||
|
collection.findOne()
|
||||||
|
|
||||||
|
suspend fun set(meta: MetaData) =
|
||||||
|
collection.insertOne(meta)
|
||||||
|
|
||||||
|
suspend fun update(meta: MetaData) =
|
||||||
|
collection.findOneAndReplace(
|
||||||
|
MetaData::id eq "meta",
|
||||||
|
meta
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package dev.jansel.feixiao.database.entities
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MetaData(
|
||||||
|
val version: Int,
|
||||||
|
val id: String = "meta"
|
||||||
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
package dev.jansel.feixiao.database.migrations
|
||||||
|
|
||||||
|
import org.litote.kmongo.coroutine.CoroutineDatabase
|
||||||
|
|
||||||
|
suspend fun v1(db: CoroutineDatabase) {
|
||||||
|
db.createCollection("meta")
|
||||||
|
}
|
@ -1,20 +1,8 @@
|
|||||||
package dev.jansel.feixiao.extensions
|
package dev.jansel.feixiao.extensions
|
||||||
|
|
||||||
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.utils.tchannelid
|
|
||||||
import dev.jansel.feixiao.utils.tserverid
|
|
||||||
import dev.jansel.feixiao.utils.twitchcid
|
|
||||||
import dev.jansel.feixiao.utils.twitchcs
|
|
||||||
import dev.kord.core.behavior.getChannelOf
|
|
||||||
import dev.kord.core.entity.channel.GuildMessageChannel
|
|
||||||
import dev.kord.core.event.gateway.ReadyEvent
|
import dev.kord.core.event.gateway.ReadyEvent
|
||||||
import dev.kordex.core.extensions.Extension
|
import dev.kordex.core.extensions.Extension
|
||||||
import dev.kordex.core.extensions.event
|
import dev.kordex.core.extensions.event
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
|
|
||||||
class EventHooks : Extension() {
|
class EventHooks : Extension() {
|
||||||
override val name = "eventhooks"
|
override val name = "eventhooks"
|
||||||
@ -23,40 +11,7 @@ class EventHooks : Extension() {
|
|||||||
event<ReadyEvent> {
|
event<ReadyEvent> {
|
||||||
action {
|
action {
|
||||||
println("Bot is ready!")
|
println("Bot is ready!")
|
||||||
kord.editPresence { playing("osu!") }
|
kord.editPresence { "electing a president..." }
|
||||||
val twitchClient = TwitchClientBuilder.builder()
|
|
||||||
.withEnableHelix(true)
|
|
||||||
.withClientId(twitchcid)
|
|
||||||
.withClientSecret(twitchcs)
|
|
||||||
.build()
|
|
||||||
twitchClient.clientHelper.enableStreamEventListener("janselosu")
|
|
||||||
twitchClient.eventManager.onEvent(ChannelGoLiveEvent::class.java) {
|
|
||||||
println("${it.channel.name} went live!")
|
|
||||||
runBlocking {
|
|
||||||
launch {
|
|
||||||
val twitchpingschannel =
|
|
||||||
kord.getGuildOrNull(tserverid)?.getChannelOf<GuildMessageChannel>(tchannelid)
|
|
||||||
twitchpingschannel?.createMessage("<@&1130981452130037800> ${it.channel.name} is now live at https://twitch.tv/${it.channel.name} streaming ${it.stream.gameName}: ${it.stream.title}")
|
|
||||||
kord.editPresence { streaming(it.stream.title, "https://twitch.tv/${it.channel.name}") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
twitchClient.eventManager.onEvent(ChannelGoOfflineEvent::class.java) {
|
|
||||||
println("${it.channel.name} went offline.")
|
|
||||||
runBlocking {
|
|
||||||
launch {
|
|
||||||
kord.editPresence { playing("osu!") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
twitchClient.eventManager.onEvent(ChannelChangeTitleEvent::class.java) {
|
|
||||||
println("Title changed to ${it.title}")
|
|
||||||
runBlocking {
|
|
||||||
launch {
|
|
||||||
kord.editPresence { streaming(it.title, "https://twitch.tv/${it.channel.name}") }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,37 @@
|
|||||||
package dev.jansel.feixiao.utils
|
package dev.jansel.feixiao.utils
|
||||||
|
|
||||||
|
import dev.jansel.feixiao.database.Database
|
||||||
|
import dev.jansel.feixiao.database.collections.MetaCollection
|
||||||
import dev.kord.common.entity.Snowflake
|
import dev.kord.common.entity.Snowflake
|
||||||
|
import dev.kordex.core.builders.ExtensibleBotBuilder
|
||||||
import dev.kordex.core.utils.env
|
import dev.kordex.core.utils.env
|
||||||
|
import dev.kordex.core.utils.loadModule
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import org.koin.dsl.bind
|
||||||
|
|
||||||
val twitchcid = env("TWITCH_CLIENT_ID")
|
val twitchcid = env("TWITCH_CLIENT_ID")
|
||||||
val twitchcs = env("TWITCH_CLIENT_SECRET")
|
val twitchcs = env("TWITCH_CLIENT_SECRET")
|
||||||
val token = env("TOKEN")
|
val token = env("TOKEN")
|
||||||
val tserverid = Snowflake(env("TEST_SERVER").toLong())
|
val tserverid = Snowflake(env("TEST_SERVER").toLong())
|
||||||
val tchannelid = Snowflake(env("TEST_CHANNEL").toLong())
|
val tchannelid = Snowflake(env("TEST_CHANNEL").toLong())
|
||||||
|
val mongoUri = env("MONGO_URI")
|
||||||
|
|
||||||
|
suspend inline fun ExtensibleBotBuilder.database(migrate: Boolean) {
|
||||||
|
val db = Database()
|
||||||
|
|
||||||
|
hooks {
|
||||||
|
beforeKoinSetup {
|
||||||
|
loadModule {
|
||||||
|
single { db } bind Database::class
|
||||||
|
}
|
||||||
|
|
||||||
|
loadModule {
|
||||||
|
single { MetaCollection() } bind MetaCollection::class
|
||||||
|
}
|
||||||
|
|
||||||
|
if (migrate) {
|
||||||
|
runBlocking { db.migrate() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user