diff --git a/gradle.properties b/gradle.properties
index 1759e8f..31a7499 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -8,6 +8,6 @@ android.enableJetifier=true
# Project data
-group=project_group
+group=dev.inmo
version=0.0.1
android_code_version=1
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index de17777..44b7760 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -3,6 +3,10 @@
kotlin = "1.7.10"
kotlin-serialization = "1.4.0-RC"
+plagubot = "2.1.0"
+tgbotapi = "3.1.1"
+microutils = "0.12.1"
+
dexcount = "3.1.0"
junit_version = "4.12"
test_ext_junit_version = "1.1.3"
@@ -24,6 +28,11 @@ kotlin-test-js = { module = "org.jetbrains.kotlin:kotlin-test-js", version.ref =
android-test-junit = { module = "androidx.test.ext:junit", version.ref = "test_ext_junit_version" }
android-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "espresso_core" }
+tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" }
+plagubot-plugin = { module = "dev.inmo:plagubot.plugin", version.ref = "plagubot" }
+microutils-repos-common = { module = "dev.inmo:micro_utils.repos.common", version.ref = "microutils" }
+microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", version.ref = "microutils" }
+
# buildscript classpaths
android-tools-build = { module = "com.android.tools.build:gradle", version.ref = "android-gradle-plugin" }
diff --git a/lib/build.gradle b/lib/build.gradle
deleted file mode 100644
index 8a22926..0000000
--- a/lib/build.gradle
+++ /dev/null
@@ -1,8 +0,0 @@
-plugins {
- id "org.jetbrains.kotlin.multiplatform"
- id "org.jetbrains.kotlin.plugin.serialization"
- id "com.android.library"
-}
-
-apply from: "$mppProjectWithSerializationPresetPath"
-
diff --git a/lib/src/commonMain/kotlin/project_group/Library.kt b/lib/src/commonMain/kotlin/project_group/Library.kt
deleted file mode 100644
index 424d112..0000000
--- a/lib/src/commonMain/kotlin/project_group/Library.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package project_group
-
-class Library {
- fun someLibraryMethod(): Boolean {
- return true
- }
-}
diff --git a/lib/src/commonTest/kotlin/project_group/LibraryTest.kt b/lib/src/commonTest/kotlin/project_group/LibraryTest.kt
deleted file mode 100644
index 84b573a..0000000
--- a/lib/src/commonTest/kotlin/project_group/LibraryTest.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * This Kotlin source file was generated by the Gradle 'init' task.
- */
-package project_group
-
-import kotlin.test.Test
-import kotlin.test.assertTrue
-
-class LibraryTest {
- @Test fun testSomeLibraryMethod() {
- val classUnderTest = Library()
- assertTrue(classUnderTest.someLibraryMethod(), "someLibraryMethod should return 'true'")
- }
-}
diff --git a/lib/src/main/AndroidManifest.xml b/lib/src/main/AndroidManifest.xml
deleted file mode 100644
index 03c9554..0000000
--- a/lib/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/posts/build.gradle b/posts/build.gradle
new file mode 100644
index 0000000..1b0a1a6
--- /dev/null
+++ b/posts/build.gradle
@@ -0,0 +1,24 @@
+plugins {
+ id "org.jetbrains.kotlin.multiplatform"
+ id "org.jetbrains.kotlin.plugin.serialization"
+ id "com.android.library"
+}
+
+apply from: "$mppProjectWithSerializationPresetPath"
+
+kotlin {
+ sourceSets {
+ commonMain {
+ dependencies {
+ api libs.tgbotapi
+ api libs.microutils.repos.common
+ }
+ }
+ jvmMain {
+ dependencies {
+ api libs.microutils.repos.exposed
+ api libs.plagubot.plugin
+ }
+ }
+ }
+}
diff --git a/posts/src/commonMain/kotlin/PackageInfo.kt b/posts/src/commonMain/kotlin/PackageInfo.kt
new file mode 100644
index 0000000..51daf7a
--- /dev/null
+++ b/posts/src/commonMain/kotlin/PackageInfo.kt
@@ -0,0 +1 @@
+package dev.inmo.plaguposter.posts
diff --git a/posts/src/commonMain/kotlin/models/Post.kt b/posts/src/commonMain/kotlin/models/Post.kt
new file mode 100644
index 0000000..0e97632
--- /dev/null
+++ b/posts/src/commonMain/kotlin/models/Post.kt
@@ -0,0 +1,20 @@
+package dev.inmo.plaguposter.posts.models
+
+import dev.inmo.tgbotapi.types.ChatId
+import kotlinx.serialization.Serializable
+
+@Serializable
+sealed interface Post {
+ val content: List
+}
+
+@Serializable
+data class NewPost(
+ override val content: List
+) : Post
+
+@Serializable
+data class RegisteredPost(
+ val id: PostId,
+ override val content: List
+) : Post
diff --git a/posts/src/commonMain/kotlin/models/PostContentInfo.kt b/posts/src/commonMain/kotlin/models/PostContentInfo.kt
new file mode 100644
index 0000000..7a572d5
--- /dev/null
+++ b/posts/src/commonMain/kotlin/models/PostContentInfo.kt
@@ -0,0 +1,13 @@
+package dev.inmo.plaguposter.posts.models
+
+import dev.inmo.tgbotapi.types.ChatId
+import dev.inmo.tgbotapi.types.MessageIdentifier
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class PostContentInfo(
+ val chatId: ChatId,
+ val messageId: MessageIdentifier,
+ val group: String?,
+ val order: Int
+)
diff --git a/posts/src/commonMain/kotlin/models/PostId.kt b/posts/src/commonMain/kotlin/models/PostId.kt
new file mode 100644
index 0000000..806d412
--- /dev/null
+++ b/posts/src/commonMain/kotlin/models/PostId.kt
@@ -0,0 +1,10 @@
+package dev.inmo.plaguposter.posts.models
+
+import kotlinx.serialization.Serializable
+import kotlin.jvm.JvmInline
+
+@Serializable
+@JvmInline
+value class PostId(
+ val string: String
+)
diff --git a/posts/src/commonMain/kotlin/repo/PostsRepo.kt b/posts/src/commonMain/kotlin/repo/PostsRepo.kt
new file mode 100644
index 0000000..b22c7aa
--- /dev/null
+++ b/posts/src/commonMain/kotlin/repo/PostsRepo.kt
@@ -0,0 +1,7 @@
+package dev.inmo.plaguposter.posts.repo
+
+import dev.inmo.micro_utils.repos.CRUDRepo
+import dev.inmo.plaguposter.posts.models.*
+
+interface PostsRepo : CRUDRepo, ReadPostsRepo, WritePostsRepo {
+}
diff --git a/posts/src/commonMain/kotlin/repo/ReadPostsRepo.kt b/posts/src/commonMain/kotlin/repo/ReadPostsRepo.kt
new file mode 100644
index 0000000..83c9200
--- /dev/null
+++ b/posts/src/commonMain/kotlin/repo/ReadPostsRepo.kt
@@ -0,0 +1,6 @@
+package dev.inmo.plaguposter.posts.repo
+
+import dev.inmo.micro_utils.repos.ReadCRUDRepo
+import dev.inmo.plaguposter.posts.models.*
+
+interface ReadPostsRepo : ReadCRUDRepo
diff --git a/posts/src/commonMain/kotlin/repo/WritePostsRepo.kt b/posts/src/commonMain/kotlin/repo/WritePostsRepo.kt
new file mode 100644
index 0000000..c9f1be4
--- /dev/null
+++ b/posts/src/commonMain/kotlin/repo/WritePostsRepo.kt
@@ -0,0 +1,7 @@
+package dev.inmo.plaguposter.posts.repo
+
+import dev.inmo.micro_utils.repos.ReadCRUDRepo
+import dev.inmo.micro_utils.repos.WriteCRUDRepo
+import dev.inmo.plaguposter.posts.models.*
+
+interface WritePostsRepo : WriteCRUDRepo
diff --git a/posts/src/jvmMain/kotlin/Plugin.kt b/posts/src/jvmMain/kotlin/Plugin.kt
new file mode 100644
index 0000000..f420db5
--- /dev/null
+++ b/posts/src/jvmMain/kotlin/Plugin.kt
@@ -0,0 +1,12 @@
+package dev.inmo.plaguposter.posts
+
+import dev.inmo.plagubot.Plugin
+import kotlinx.serialization.json.JsonObject
+import org.jetbrains.exposed.sql.Database
+import org.koin.core.module.Module
+
+object Plugin : Plugin {
+ override fun Module.setupDI(database: Database, params: JsonObject) {
+ TODO("Not yet implemented")
+ }
+}
diff --git a/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt b/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt
new file mode 100644
index 0000000..7eaeed2
--- /dev/null
+++ b/posts/src/jvmMain/kotlin/exposed/ExposedContentInfoRepo.kt
@@ -0,0 +1,35 @@
+package dev.inmo.plaguposter.posts.exposed
+
+import com.benasher44.uuid.uuid4
+import dev.inmo.micro_utils.repos.KeyValuesRepo
+import dev.inmo.micro_utils.repos.exposed.*
+import dev.inmo.plaguposter.posts.models.*
+import dev.inmo.plaguposter.posts.repo.PostsRepo
+import dev.inmo.tgbotapi.types.ChatId
+import org.jetbrains.exposed.sql.*
+import org.jetbrains.exposed.sql.statements.InsertStatement
+import org.jetbrains.exposed.sql.statements.UpdateStatement
+import sun.security.pkcs.ContentInfo
+
+internal class ExposedContentInfoRepo(
+ override val database: Database,
+ postIdColumnReference: Column
+) : ExposedRepo, Table(name = "posts_content") {
+ val postIdColumn = (text("post_id") references postIdColumnReference).index()
+ val chatIdColumn = long("chat_id")
+ val messageIdColumn = long("message_id")
+ val groupColumn = text("group").nullable()
+ val orderColumn = integer("order")
+
+ val ResultRow.asObject
+ get() = PostContentInfo(
+ ChatId(get(chatIdColumn)),
+ get(messageIdColumn),
+ get(groupColumn),
+ get(orderColumn)
+ )
+
+ init {
+ initTable()
+ }
+}
diff --git a/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt b/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt
new file mode 100644
index 0000000..e733caa
--- /dev/null
+++ b/posts/src/jvmMain/kotlin/exposed/ExposedPostsRepo.kt
@@ -0,0 +1,86 @@
+package dev.inmo.plaguposter.posts.exposed
+
+import com.benasher44.uuid.uuid4
+import dev.inmo.micro_utils.repos.KeyValuesRepo
+import dev.inmo.micro_utils.repos.exposed.AbstractExposedCRUDRepo
+import dev.inmo.plaguposter.posts.models.*
+import dev.inmo.plaguposter.posts.repo.PostsRepo
+import kotlinx.serialization.json.Json
+import org.jetbrains.exposed.sql.*
+import org.jetbrains.exposed.sql.statements.InsertStatement
+import org.jetbrains.exposed.sql.statements.UpdateStatement
+
+class ExposedPostsRepo(
+ override val database: Database,
+ json: Json
+) : PostsRepo, AbstractExposedCRUDRepo(
+ tableName = "posts"
+) {
+ val idColumn = text("id").clientDefault { uuid4().toString() }
+
+ private val contentRepo by lazy {
+ ExposedContentInfoRepo(
+ database,
+ idColumn
+ )
+ }
+
+ override val primaryKey: PrimaryKey? = PrimaryKey(idColumn)
+
+ override val selectById: SqlExpressionBuilder.(PostId) -> Op = { idColumn.eq(it.string) }
+ override val selectByIds: SqlExpressionBuilder.(List) -> Op = { idColumn.inList(it.map { it.string }) }
+ override val ResultRow.asObject: RegisteredPost
+ get() {
+ val id = PostId(get(idColumn))
+ return RegisteredPost(
+ id,
+ with(contentRepo) {
+ select { postIdColumn.eq(id.string) }.map {
+ it.asObject
+ }
+ }
+ )
+ }
+
+ override fun InsertStatement.asObject(value: NewPost): RegisteredPost {
+ val id = PostId(get(idColumn))
+
+ with(contentRepo) {
+ value.content.forEach { contentInfo ->
+ insert {
+ it[postIdColumn] = id.string
+ it[chatIdColumn] = contentInfo.chatId.chatId
+ it[messageIdColumn] = contentInfo.messageId
+ it[groupColumn] = contentInfo.group
+ it[orderColumn] = contentInfo.order
+ }
+ }
+ }
+
+ return RegisteredPost(
+ id,
+ with(contentRepo) {
+ select { postIdColumn.eq(id.string) }.map {
+ it.asObject
+ }
+ }
+ )
+ }
+
+ override fun update(id: PostId, value: NewPost, it: UpdateStatement) {
+ with(contentRepo) {
+ deleteWhere { postIdColumn.eq(id.string) }
+ value.content.forEach { contentInfo ->
+ insert {
+ it[postIdColumn] = id.string
+ it[chatIdColumn] = contentInfo.chatId.chatId
+ it[messageIdColumn] = contentInfo.messageId
+ it[groupColumn] = contentInfo.group
+ it[orderColumn] = contentInfo.order
+ }
+ }
+ }
+ }
+
+ override fun insert(value: NewPost, it: InsertStatement) {}
+}
diff --git a/posts/src/main/AndroidManifest.xml b/posts/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..7bbd57b
--- /dev/null
+++ b/posts/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
diff --git a/settings.gradle b/settings.gradle
index 4e2023f..b8e2f35 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1,7 +1,7 @@
-rootProject.name = 'project_name'
+rootProject.name = 'plaguposter'
String[] includes = [
- ":lib"
+ ":posts"
]