diff --git a/data-adapters/adapter-mongodb/README.md b/data-adapters/adapter-mongodb/README.md index e5aee2b4e3..87253bd685 100644 --- a/data-adapters/adapter-mongodb/README.md +++ b/data-adapters/adapter-mongodb/README.md @@ -11,20 +11,24 @@ This includes some codecs, for commonly-used types - which you can use in your o To switch to the MongoDB data adapter follow these steps: -1. Set the `ADAPTER_MONGODB_URI` environmental variable to a MongoDB connection string. -2. Use the `mongoDB` function to set up the data adapter. +1. Add the MongoDB dependencies to your project. You can get the latest version number + [from Maven Central](https://mvnrepository.com/artifact/org.mongodb/mongodb-driver-kotlin-sync): + - `org.mongodb:mongodb-driver-kotlin-coroutine` + - `org.mongodb:bson-kotlinx` +2. Set the `ADAPTER_MONGODB_URI` environmental variable to a MongoDB connection string. +3. Use the `mongoDB` function to set up the data adapter. ```kotlin suspend fun main() { - val bot = ExtensibleBot(System.getenv("TOKEN")) { - mongoDB() - } + val bot = ExtensibleBot(System.getenv("TOKEN")) { + mongoDB() + } - bot.start() + bot.start() } ``` -3. If you use MongoDB elsewhere in your project, you can use the provided codecs to handle these types: +4. If you use MongoDB elsewhere in your project, you can use the provided codecs to handle these types: - `DateTimePeriod` (kotlinx Datetime) - `Instant` (Kotlinx Datetime) - `Snowflake` (Kord) diff --git a/data-adapters/adapter-mongodb/build.gradle.kts b/data-adapters/adapter-mongodb/build.gradle.kts index c69f749c56..f7381e2e4c 100644 --- a/data-adapters/adapter-mongodb/build.gradle.kts +++ b/data-adapters/adapter-mongodb/build.gradle.kts @@ -23,6 +23,7 @@ dependencies { implementation(libs.kx.coro) implementation(libs.bundles.logging) implementation(libs.mongodb) + implementation(libs.mongodb.bson.kotlinx) implementation(project(":kord-extensions")) } diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/Registry.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/Registry.kt index c1ad551de1..1920f3f636 100644 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/Registry.kt +++ b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/Registry.kt @@ -1,16 +1,19 @@ package com.kotlindiscord.kord.extensions.adapters.mongodb -import com.kotlindiscord.kord.extensions.adapters.mongodb.codecs.* +import com.kotlindiscord.kord.extensions.adapters.mongodb.db.Metadata +import com.kotlindiscord.kord.extensions.storage.StorageType +import dev.kord.common.entity.Snowflake +import kotlinx.datetime.DateTimePeriod +import kotlinx.datetime.Instant import org.bson.codecs.configuration.CodecRegistries import org.bson.codecs.configuration.CodecRegistry +import org.bson.codecs.kotlinx.KotlinSerializerCodec public val kordExCodecRegistry: CodecRegistry = CodecRegistries.fromCodecs( - DateTimePeriodCodec, - InstantCodec, - SnowflakeCodec, - StorageTypeCodec, + Metadata.codec, - // Required b/c the BSON codec library doesn't support standard polymorphism. - ConfigStorageTypeCodec, - DataStorageTypeCodec, + KotlinSerializerCodec.create(), + KotlinSerializerCodec.create(), + KotlinSerializerCodec.create(), + KotlinSerializerCodec.create(), ) diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/DateTimePeriodCodec.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/DateTimePeriodCodec.kt deleted file mode 100644 index 64a39d846f..0000000000 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/DateTimePeriodCodec.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package com.kotlindiscord.kord.extensions.adapters.mongodb.codecs - -import kotlinx.datetime.DateTimePeriod -import org.bson.BsonReader -import org.bson.BsonWriter -import org.bson.codecs.Codec -import org.bson.codecs.DecoderContext -import org.bson.codecs.EncoderContext - -public object DateTimePeriodCodec : Codec { - override fun decode(reader: BsonReader, decoderContext: DecoderContext): DateTimePeriod = - DateTimePeriod.parse(reader.readString()) - - override fun encode(writer: BsonWriter, value: DateTimePeriod, encoderContext: EncoderContext) { - writer.writeString(value.toString()) - } - - override fun getEncoderClass(): Class = - DateTimePeriod::class.java -} diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/InstantCodec.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/InstantCodec.kt deleted file mode 100644 index 2b080d6655..0000000000 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/InstantCodec.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package com.kotlindiscord.kord.extensions.adapters.mongodb.codecs - -import kotlinx.datetime.Instant -import org.bson.BsonReader -import org.bson.BsonWriter -import org.bson.codecs.Codec -import org.bson.codecs.DecoderContext -import org.bson.codecs.EncoderContext - -public object InstantCodec : Codec { - override fun decode(reader: BsonReader, decoderContext: DecoderContext): Instant = - Instant.parse(reader.readString()) - - override fun encode(writer: BsonWriter, value: Instant, encoderContext: EncoderContext) { - writer.writeString(value.toString()) - } - - override fun getEncoderClass(): Class = - Instant::class.java -} diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/SnowflakeCodec.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/SnowflakeCodec.kt deleted file mode 100644 index 7b0c82a824..0000000000 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/SnowflakeCodec.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package com.kotlindiscord.kord.extensions.adapters.mongodb.codecs - -import dev.kord.common.entity.Snowflake -import org.bson.BsonInvalidOperationException -import org.bson.BsonReader -import org.bson.BsonWriter -import org.bson.codecs.Codec -import org.bson.codecs.DecoderContext -import org.bson.codecs.EncoderContext - -public object SnowflakeCodec : Codec { - override fun decode(reader: BsonReader, decoderContext: DecoderContext): Snowflake = try { - Snowflake(reader.readString()) - } catch (e: BsonInvalidOperationException) { - Snowflake(reader.readInt64()) - } - - override fun encode(writer: BsonWriter, value: Snowflake, encoderContext: EncoderContext) { - writer.writeString(value.toString()) - } - - override fun getEncoderClass(): Class = - Snowflake::class.java -} diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/StorageTypeCodec.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/StorageTypeCodec.kt deleted file mode 100644 index e5eec71477..0000000000 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/codecs/StorageTypeCodec.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ - -package com.kotlindiscord.kord.extensions.adapters.mongodb.codecs - -import com.kotlindiscord.kord.extensions.storage.StorageType -import org.bson.BsonReader -import org.bson.BsonWriter -import org.bson.codecs.Codec -import org.bson.codecs.DecoderContext -import org.bson.codecs.EncoderContext - -public object StorageTypeCodec : Codec { - override fun decode(reader: BsonReader, decoderContext: DecoderContext): StorageType = - when (val string = reader.readString()) { - StorageType.Config.type -> StorageType.Config - StorageType.Data.type -> StorageType.Data - - else -> error("Unknown storage type: $string") - } - - override fun encode(writer: BsonWriter, value: StorageType, encoderContext: EncoderContext) { - writer.writeString(value.type) - } - - override fun getEncoderClass(): Class = - StorageType::class.java -} - -public object ConfigStorageTypeCodec : Codec { - override fun decode(reader: BsonReader, decoderContext: DecoderContext): StorageType.Config { - error("Do not use `StorageType.Config` as the type for a value - use `StorageType` instead.") - } - - override fun encode(writer: BsonWriter, value: StorageType.Config, encoderContext: EncoderContext) { - StorageTypeCodec.encode(writer, value, encoderContext) - } - - override fun getEncoderClass(): Class = - StorageType.Config::class.java -} - -public object DataStorageTypeCodec : Codec { - override fun decode(reader: BsonReader, decoderContext: DecoderContext): StorageType.Data { - error("Do not use `StorageType.Data` as the type for a value - use `StorageType` instead.") - } - - override fun encode(writer: BsonWriter, value: StorageType.Data, encoderContext: EncoderContext) { - StorageTypeCodec.encode(writer, value, encoderContext) - } - - override fun getEncoderClass(): Class = - StorageType.Data::class.java -} diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/AdaptedData.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/AdaptedData.kt index 248bbdd682..316b07f2f6 100644 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/AdaptedData.kt +++ b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/AdaptedData.kt @@ -14,17 +14,17 @@ import org.bson.codecs.pojo.annotations.BsonId @Serializable @Suppress("ConstructorParameterNaming", "DataClassShouldBeImmutable") internal data class AdaptedData( - @BsonId - override val _id: String, + @BsonId + override val _id: String, - val identifier: String, + val identifier: String, - val type: StorageType? = null, + val type: StorageType? = null, - val channel: Snowflake? = null, - val guild: Snowflake? = null, - val message: Snowflake? = null, - val user: Snowflake? = null, + val channel: Snowflake? = null, + val guild: Snowflake? = null, + val message: Snowflake? = null, + val user: Snowflake? = null, - var data: String, + var data: String, ) : Entity diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Entity.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Entity.kt index 4ec2eda1ac..3cd9322c58 100644 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Entity.kt +++ b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Entity.kt @@ -8,5 +8,5 @@ package com.kotlindiscord.kord.extensions.adapters.mongodb.db @Suppress("VariableNaming", "PropertyName") internal interface Entity { - val _id: ID + val _id: ID } diff --git a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Metadata.kt b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Metadata.kt index f7aca2a3ee..b78d456157 100644 --- a/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Metadata.kt +++ b/data-adapters/adapter-mongodb/src/main/kotlin/com/kotlindiscord/kord/extensions/adapters/mongodb/db/Metadata.kt @@ -10,21 +10,25 @@ import com.mongodb.client.model.Filters.eq import com.mongodb.client.model.ReplaceOptions import com.mongodb.client.result.UpdateResult import kotlinx.coroutines.flow.firstOrNull +import kotlinx.serialization.Contextual import kotlinx.serialization.Serializable -import org.bson.codecs.pojo.annotations.BsonId +import org.bson.codecs.kotlinx.KotlinSerializerCodec @Serializable @Suppress("DataClassContainsFunctions", "DataClassShouldBeImmutable") internal data class Metadata( - @BsonId + @Contextual override val _id: String, var version: Int, ) : Entity { + suspend inline fun save(): UpdateResult = Companion.save(this) companion object { + val codec = KotlinSerializerCodec.create() + const val COLLECTION_NAME: String = "metadata" private val Filters = object { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5c3e0dfb5c..7bc992a761 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -61,6 +61,7 @@ logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" } logback-groovy = { module = "io.github.virtualdogbert:logback-groovy-config", version.ref = "logback-groovy" } kotlin-logging = { module = "io.github.oshai:kotlin-logging", version.ref = "logging" } mongodb = { module = "org.mongodb:mongodb-driver-kotlin-coroutine", version.ref = "mongodb" } +mongodb-bson-kotlinx = { module = "org.mongodb:bson-kotlinx", version.ref = "mongodb" } pf4j = { module = "org.pf4j:pf4j", version.ref = "pf4j" } semver = { module = "io.github.z4kn4fein:semver", version.ref = "semver" } sentry = { module = "io.sentry:sentry", version.ref = "sentry" }