start of implementation

This commit is contained in:
InsanusMokrassar 2022-09-07 00:52:45 +06:00
parent 8fe93e20bc
commit 4a6e7e472b
7 changed files with 106 additions and 4 deletions

View File

@ -17,12 +17,19 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url "https://jitpack.io" }
} }
dependencies { dependencies {
implementation libs.kotlin implementation libs.kotlin
implementation libs.tgbotapi implementation libs.tgbotapi
implementation libs.microutils.repos.exposed
implementation libs.microutils.repos.cache
implementation libs.kslog
implementation libs.exposed
implementation libs.psql
implementation libs.imageboard
} }
application { application {

View File

@ -2,11 +2,27 @@
kotlin = "1.7.10" kotlin = "1.7.10"
tgbotapi = "3.2.0" tgbotapi = "3.2.0"
microutils = "0.12.7"
imageboard = "2.5.2"
krontab = "0.8.0"
kslog = "0.5.1"
exposed = "0.39.2"
psql = "42.5.0"
[libraries] [libraries]
kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" } tgbotapi = { module = "dev.inmo:tgbotapi", version.ref = "tgbotapi" }
microutils-repos-exposed = { module = "dev.inmo:micro_utils.repos.exposed", version.ref = "microutils" }
microutils-repos-cache = { module = "dev.inmo:micro_utils.repos.cache", version.ref = "microutils" }
krontab = { module = "dev.inmo:krontab", version.ref = "krontab" }
kslog = { module = "dev.inmo:kslog", version.ref = "kslog" }
exposed = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
psql = { module = "org.postgresql:postgresql", version.ref = "psql" }
imageboard = { module = "com.github.Kodehawa:imageboard-api", version.ref = "imageboard" }
# Libs for classpath # Libs for classpath
kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } kotlin-gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }

View File

@ -1,13 +1,18 @@
package telegram_bot import dev.inmo.micro_utils.repos.cache.cache.FullKVCache
import dev.inmo.micro_utils.repos.cache.cached
import dev.inmo.micro_utils.repos.exposed.keyvalue.ExposedKeyValueRepo
import dev.inmo.micro_utils.repos.mappers.withMapper
import dev.inmo.tgbotapi.bot.ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.types.ChatId
import java.io.File import java.io.File
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import models.Config
/** /**
* This method by default expects one argument in [args] field: telegram bot configuration * This method by default expects one argument in [args] field: telegram bot configuration
@ -23,6 +28,22 @@ suspend fun main(args: Array<String>) {
// that is kotlin coroutine scope which will be used in requests and parallel works under the hood // that is kotlin coroutine scope which will be used in requests and parallel works under the hood
val scope = CoroutineScope(Dispatchers.Default) val scope = CoroutineScope(Dispatchers.Default)
val repo = ExposedKeyValueRepo(
config.database.database,
{ long("chat_id") },
{ text("config") },
"configs"
).withMapper(
{ chatId },
{ json.encodeToString(ChatConfig.serializer(), this) },
{ ChatId(this) },
{ json.decodeFromString(ChatConfig.serializer(), this) },
).cached(FullKVCache(), scope = scope)
val chatsChangingMutex = Mutex()
val chatsSendingJobs = mutableMapOf<ChatId, Job>()
// here should be main logic of your bot // here should be main logic of your bot
bot.buildBehaviourWithLongPolling(scope) { bot.buildBehaviourWithLongPolling(scope) {
// in this lambda you will be able to call methods without "bot." prefix // in this lambda you will be able to call methods without "bot." prefix

View File

@ -0,0 +1,11 @@
import dev.inmo.krontab.*
import kotlinx.serialization.Serializable
@Serializable
data class ChatConfig(
val krontab: KrontabTemplate
) {
val scheduler by lazy {
krontab.toSchedule()
}
}

View File

@ -1,8 +1,9 @@
package telegram_bot package models
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class Config( data class Config(
val token: String val token: String,
val database: DatabaseConfig
) )

View File

@ -0,0 +1,9 @@
package models
import kotlinx.serialization.Serializable
@Serializable
data class DBConnectOptions(
val attempts: Int = 3,
val delay: Long = 1000L
)

View File

@ -0,0 +1,37 @@
package models
import dev.inmo.kslog.common.e
import dev.inmo.kslog.common.logger
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.transactions.transactionManager
import org.postgresql.Driver
import java.sql.Connection
@Serializable
data class DatabaseConfig(
val url: String = "jdbc:pgsql://localhost:12346/test",
val driver: String = Driver::class.qualifiedName!!,
val username: String = "",
val password: String = "",
val reconnectOptions: DBConnectOptions? = DBConnectOptions()
) {
@Transient
val database: Database = (0 until (reconnectOptions ?.attempts ?: 1)).firstNotNullOfOrNull {
runCatching {
Database.connect(
url,
driver,
username,
password
).also {
it.transactionManager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE // Or Connection.TRANSACTION_READ_UNCOMMITTED
it.connector().close()
}
}.onFailure {
logger.e(it)
Thread.sleep(reconnectOptions ?.delay ?: return@onFailure)
}.getOrNull()
} ?: error("Unable to create database")
}