Skip to content

Commit 73d9aec

Browse files
author
Simon Naumov
authored
⬆️ telegram bot v2.1.4 (#146)
* ⬆️ telegram bot v2.1.4 * 🚨 syfu barker
1 parent 9fe3fc4 commit 73d9aec

29 files changed

+432
-353
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## [1.2.8] - 02.06.2022
4+
5+
### Fixed
6+
7+
- Escaping markdown in messages
8+
- Developing
9+
- Moving to the telegram bot library v2.1.4
10+
- Using `DATABASE_URL` configuration option
11+
312
## [1.2.7] - 28.05.2022
413

514
### Fixed
@@ -148,6 +157,7 @@
148157
- Implicit party pulling
149158
- Rude mode
150159

160+
[1.2.8]: https://github.com/pool-party/pull-party-bot/compare/v1.2.7...v1.2.8
151161
[1.2.7]: https://github.com/pool-party/pull-party-bot/compare/v1.2.6...v1.2.7
152162
[1.2.6]: https://github.com/pool-party/pull-party-bot/compare/v1.2.5...v1.2.6
153163
[1.2.5]: https://github.com/pool-party/pull-party-bot/compare/v1.2.4...v1.2.5

Procfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
web: java -jar build/libs/pull-party-bot-1.2.7.jar
1+
web: java -jar build/libs/pull-party-bot-1.2.8.jar

build.gradle.kts

Lines changed: 26 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,43 @@
11
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
22

33
plugins {
4-
id("java")
5-
id("org.jetbrains.kotlin.jvm") version "1.6.20"
6-
kotlin("plugin.serialization") version "1.6.20"
7-
8-
id("org.flywaydb.flyway") version "8.5.8"
4+
alias(libs.plugins.jvm)
5+
alias(libs.plugins.serialization)
6+
alias(libs.plugins.ktlint)
7+
alias(libs.plugins.flyway)
98
}
109

1110
group = "org.pool-party"
12-
version = "1.2.7"
11+
version = "1.2.8"
1312

1413
repositories {
1514
maven("https://jitpack.io")
1615
mavenCentral()
1716
}
1817

19-
val exposedVersion = "0.38.1"
20-
val testContainersVersion = "1.17.1"
21-
val jupyterVersion = "5.8.2"
22-
val kotlinVersion = "1.6.20"
23-
2418
dependencies {
25-
implementation("org.jetbrains.kotlin", "kotlin-stdlib-jdk8", kotlinVersion)
26-
implementation("org.jetbrains.kotlin", "kotlin-reflect", kotlinVersion)
27-
implementation("org.jetbrains.kotlinx", "kotlinx-serialization-json", "1.3.2")
28-
implementation("com.github.elbekD", "kt-telegram-bot", "1.4.1")
29-
30-
implementation("org.jetbrains.exposed", "exposed-core", exposedVersion)
31-
implementation("org.jetbrains.exposed", "exposed-dao", exposedVersion)
32-
implementation("org.jetbrains.exposed", "exposed-jdbc", exposedVersion)
33-
implementation("org.jetbrains.exposed", "exposed-jodatime", exposedVersion)
34-
35-
implementation("org.flywaydb", "flyway-core", "8.5.8")
36-
37-
implementation("com.natpryce", "konfig", "1.6.10.0")
3819

39-
implementation("org.slf4j", "slf4j-simple", "2.0.0-alpha7")
40-
implementation("io.github.microutils", "kotlin-logging", "2.1.21")
41-
42-
implementation("info.debatty", "java-string-similarity", "2.0.0")
43-
44-
runtimeOnly("org.postgresql", "postgresql", "42.3.4")
45-
46-
testImplementation("org.jetbrains.kotlin", "kotlin-test-junit5", kotlinVersion)
47-
testImplementation("org.junit.jupiter", "junit-jupiter-api", jupyterVersion)
48-
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", jupyterVersion)
49-
50-
testImplementation("io.mockk", "mockk", "1.12.0")
51-
testImplementation("org.testcontainers", "postgresql", testContainersVersion)
52-
testImplementation("org.testcontainers", "junit-jupiter", testContainersVersion)
20+
implementation(libs.kotlin.std)
21+
implementation(libs.kotlin.reflect)
22+
implementation(libs.kotlin.serialization)
23+
implementation(libs.telegramBot)
24+
implementation(libs.exposed.core)
25+
implementation(libs.exposed.dao)
26+
implementation(libs.exposed.jdbc)
27+
implementation(libs.exposed.jodatime)
28+
implementation(libs.postgresql)
29+
implementation(libs.flyway)
30+
implementation(libs.konfig)
31+
implementation(libs.slf4j)
32+
implementation(libs.logging)
33+
implementation(libs.stringSimilarity)
34+
35+
testImplementation(libs.kotlin.test.junit5)
36+
testCompileOnly(libs.jupiter.api)
37+
testRuntimeOnly(libs.jupiter.engine)
38+
testImplementation(libs.mockk)
39+
testImplementation(libs.testContainers.jupiter)
40+
testImplementation(libs.testContainers.postgres)
5341
}
5442

5543
tasks.withType<Jar> {
@@ -75,6 +63,5 @@ tasks.withType<KotlinCompile>().configureEach {
7563
kotlinOptions.jvmTarget = "1.8"
7664
kotlinOptions.freeCompilerArgs += "-opt-in=kotlinx.coroutines.DelicateCoroutinesApi"
7765
kotlinOptions.freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
78-
kotlinOptions.freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
7966
kotlinOptions.freeCompilerArgs += "-Xcontext-receivers"
8067
}

gradle/libs.versions.toml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
[versions]
2+
kotlin = "1.7.0"
3+
testContainers = "1.17.1"
4+
jupiter = "5.8.2"
5+
exposed = "0.38.1"
6+
flyway = "8.5.8"
7+
8+
[plugins]
9+
jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
10+
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
11+
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version = "10.3.0" }
12+
flyway = { id = "org.flywaydb.flyway", version.ref = "flyway" }
13+
14+
[libraries]
15+
16+
# main
17+
18+
kotlin-std = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlin" }
19+
kotlin-reflect = { group = "org.jetbrains.kotlin", name = "kotlin-reflect", version.ref = "kotlin" }
20+
kotlin-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version = "1.3.3" }
21+
22+
exposed-core = { group = "org.jetbrains.exposed", name = "exposed-core", version.ref = "exposed" }
23+
exposed-dao = { group = "org.jetbrains.exposed", name = "exposed-dao", version.ref = "exposed" }
24+
exposed-jdbc = { group = "org.jetbrains.exposed", name = "exposed-jdbc", version.ref = "exposed" }
25+
exposed-jodatime = { group = "org.jetbrains.exposed", name = "exposed-jodatime", version.ref = "exposed" }
26+
postgresql = { group = "org.postgresql", name = "postgresql", version = "42.3.4" }
27+
28+
telegramBot = { group = "com.github.elbekD", name = "kt-telegram-bot", version = "2.1.4" }
29+
30+
flyway = { group = "org.flywaydb", name = "flyway-core", version.ref = "flyway" }
31+
32+
konfig = { group = "com.natpryce", name = "konfig", version = "1.6.10.0" }
33+
34+
slf4j = { group = "org.slf4j", name = "slf4j-simple", version = "2.0.0-alpha7" }
35+
logging = { group = "io.github.microutils", name = "kotlin-logging", version = "2.1.21" }
36+
37+
stringSimilarity = { group = "info.debatty", name = "java-string-similarity", version = "2.0.0" }
38+
39+
# test
40+
41+
kotlin-test-junit5 = { group = "org.jetbrains.kotlin", name = "kotlin-test-junit5", version.ref = "kotlin" }
42+
jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "jupiter" }
43+
jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "jupiter" }
44+
45+
mockk = { group = "io.mockk", name = "mockk", version = "1.12.4" }
46+
testContainers-jupiter = { group = "org.testcontainers", name = "junit-jupiter", version.ref = "testContainers" }
47+
testContainers-postgres = { group = "org.testcontainers", name = "postgresql", version.ref = "testContainers" }

src/main/kotlin/com/github/pool_party/pull_party_bot/Configuration.kt

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,43 +23,65 @@ object Configuration {
2323
else it
2424
}
2525

26-
val APP_URL by Configured(stringType)
27-
val USERNAME by Configured(stringType)
28-
val PORT by Configured(intType)
29-
val HOST by Configured(stringType)
26+
val APP_URL by string()
27+
val USERNAME by string()
28+
val PORT by int()
29+
val HOST by string()
3030

31-
val LONGPOLL by Configured(booleanType)
31+
val LONGPOLL by boolean()
3232

33-
val TELEGRAM_TOKEN by Configured(stringType)
33+
val TELEGRAM_TOKEN by string()
3434

35-
val JDBC_DATABASE_URL by Configured(stringType)
36-
val JDBC_DATABASE_USERNAME by Configured(stringType)
37-
val JDBC_DATABASE_PASSWORD by Configured(stringType)
35+
private val DATABASE_URL by string()
3836

39-
val DEVELOP_CHAT_ID by Configured(longType)
37+
val JDBC_DATABASE_URL by lazy {
38+
val (_, _, host, port, database) = getDatabaseUrl().destructured
39+
"jdbc:postgresql://$host:$port/$database"
40+
}
41+
val JDBC_DATABASE_USERNAME by lazy { getDatabaseUrl().groupValues[1] }
42+
val JDBC_DATABASE_PASSWORD by lazy { getDatabaseUrl().groupValues[2] }
43+
44+
val DEVELOP_CHAT_ID by long()
4045

4146
val PROHIBITED_SYMBOLS = "!,.?:;()".toList()
4247

43-
val STALE_PARTY_WEEKS by Configured(intType)
48+
val STALE_PARTY_WEEKS by int()
4449

45-
val STALE_PING_SECONDS by Configured(intType)
50+
val STALE_PING_SECONDS by int()
4651

47-
val PARTY_SIMILARITY_COEFFICIENT by Configured(doubleType)
52+
val PARTY_SIMILARITY_COEFFICIENT by double()
4853

4954
const val MESSAGE_LENGTH = 4096
5055

51-
val CACHE_CAPACITY_ALIAS by Configured(intType)
52-
val CACHE_CAPACITY_PARTY by Configured(intType)
53-
val CACHE_CAPACITY_PARTYALIASES by Configured(intType)
54-
val CACHE_CAPACITY_CHAT by Configured(intType)
56+
val CACHE_CAPACITY_ALIAS by int()
57+
val CACHE_CAPACITY_PARTY by int()
58+
val CACHE_CAPACITY_PARTYALIASES by int()
59+
val CACHE_CAPACITY_CHAT by int()
60+
61+
private fun boolean() = Configured(booleanType)
62+
63+
private fun string() = Configured(stringType)
64+
65+
private fun int() = Configured(intType)
66+
67+
private fun long() = Configured(longType)
68+
69+
private fun double() = Configured(doubleType)
70+
71+
private fun getDatabaseUrl(): MatchResult =
72+
"""postgres://(\w+):([\w\d]+)@([\w\d\-\.]+):(\d+)/([\w\d]+)""".toRegex().matchEntire(DATABASE_URL)
73+
?: throw RuntimeException("Bad DATABASE_URL format")
74+
75+
private val <T> KProperty<T>.configName
76+
get() = name.lowercase().replace('_', '.')
5577

56-
private open class Configured<T>(private val parse: (PropertyLocation, String) -> T) {
78+
private class Configured<T>(private val parse: (PropertyLocation, String) -> T) {
5779

5880
private var value: T? = null
5981

6082
operator fun getValue(thisRef: Configuration, property: KProperty<*>): T {
6183
if (value == null) {
62-
value = configuration[Key(property.name.lowercase().replace('_', '.'), parse)]
84+
value = configuration[Key(property.configName, parse)]
6385
}
6486
return value!!
6587
}

src/main/kotlin/com/github/pool_party/pull_party_bot/Main.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
package com.github.pool_party.pull_party_bot
22

3-
import com.elbekD.bot.Bot
4-
import com.elbekD.bot.server
3+
import com.elbekd.bot.Bot
4+
import com.elbekd.bot.server
55
import com.github.pool_party.pull_party_bot.commands.initHandlers
66
import com.github.pool_party.pull_party_bot.database.initDB
77

8-
fun main() {
8+
suspend fun main() {
99
val token = Configuration.TELEGRAM_TOKEN
1010
val userName = Configuration.USERNAME
1111

1212
val bot = if (Configuration.LONGPOLL) {
13-
Bot.createPolling(userName, token)
13+
Bot.createPolling(token, userName)
1414
} else {
15-
Bot.createWebhook(userName, token) {
15+
Bot.createWebhook(token, userName) {
1616
url = "${Configuration.APP_URL}/$token"
1717

1818
server {

src/main/kotlin/com/github/pool_party/pull_party_bot/commands/Callback.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.github.pool_party.pull_party_bot.commands
22

3-
import com.elbekD.bot.Bot
4-
import com.elbekD.bot.types.CallbackQuery
3+
import com.elbekd.bot.Bot
4+
import com.elbekd.bot.types.CallbackQuery
55
import kotlinx.serialization.Serializable
66
import kotlinx.serialization.decodeFromString
77
import kotlinx.serialization.json.Json

src/main/kotlin/com/github/pool_party/pull_party_bot/commands/Command.kt

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package com.github.pool_party.pull_party_bot.commands
22

3-
import com.elbekD.bot.Bot
4-
import com.elbekD.bot.types.BotCommand
5-
import com.elbekD.bot.types.Chat
6-
import com.elbekD.bot.types.Message
7-
import com.elbekD.bot.types.ReplyKeyboard
8-
import com.elbekD.bot.types.User
3+
import com.elbekd.bot.Bot
4+
import com.elbekd.bot.model.toChatId
5+
import com.elbekd.bot.types.BotCommand
6+
import com.elbekd.bot.types.Chat
7+
import com.elbekd.bot.types.Message
8+
import com.elbekd.bot.types.ReplyKeyboard
9+
import com.elbekd.bot.types.User
910
import com.github.pool_party.pull_party_bot.commands.messages.ON_ADMINS_PARTY_CHANGE
1011
import com.github.pool_party.pull_party_bot.commands.messages.ON_PERMISSION_DENY
1112
import com.github.pool_party.pull_party_bot.commands.messages.ON_SENDER_FAIL
@@ -50,7 +51,7 @@ abstract class AbstractCommand(
5051

5152
abstract suspend fun Bot.action(message: Message, args: String?)
5253

53-
override fun onMessage(bot: Bot) = bot.onCommand(command) { message, args ->
54+
override fun onMessage(bot: Bot) = bot.onCommand(command) { (message, args) ->
5455
logger.info {
5556
"${LocalDateTime.now()} $command <- ${message.from?.username}@${message.chat.title}: \"${message.text}\""
5657
}
@@ -64,8 +65,8 @@ abstract class AbstractCommand(
6465
}
6566
}
6667

67-
protected fun Bot.modifyCommandAssertion(chatId: Long, name: String): Boolean =
68-
(name == "admins").not().also { if (!it) sendMessage(chatId, ON_ADMINS_PARTY_CHANGE) }
68+
protected suspend fun Bot.modifyCommandAssertion(chatId: Long, name: String): Boolean =
69+
(name == "admins").not().also { if (!it) sendMessage(chatId.toChatId(), ON_ADMINS_PARTY_CHANGE) }
6970

7071
protected fun parseArgs(args: String?): List<String>? =
7172
args?.split(' ')?.map { it.trim().lowercase() }?.filter { it.isNotBlank() }
@@ -74,7 +75,7 @@ abstract class AbstractCommand(
7475
abstract class CaseCommand(command: String, description: String, helpMessage: String, protected val chatDao: ChatDao) :
7576
AbstractCommand(command, description, helpMessage) {
7677

77-
protected fun Bot.sendCaseMessage(
78+
protected suspend fun Bot.sendCaseMessage(
7879
chatId: Long,
7980
message: String,
8081
replyTo: Long? = null,
@@ -91,14 +92,14 @@ abstract class CaseCommand(command: String, description: String, helpMessage: St
9192
abstract class AdministratorCommand(command: String, description: String, helpMessage: String, chatDao: ChatDao) :
9293
CaseCommand(command, description, helpMessage, chatDao) {
9394

94-
abstract fun Bot.mainAction(message: Message, args: String?)
95+
abstract suspend fun Bot.mainAction(message: Message, args: String?)
9596

9697
override suspend fun Bot.action(message: Message, args: String?) {
9798
if (validateAdministrator(message.from, message.chat)) mainAction(message, args)
9899
}
99100
}
100101

101-
fun Bot.validateAdministrator(user: User?, chat: Chat, sendMessage: Boolean = true): Boolean {
102+
suspend fun Bot.validateAdministrator(user: User?, chat: Chat, sendMessage: Boolean = true): Boolean {
102103
val chatId = chat.id
103104

104105
if (user == null) {
@@ -108,7 +109,7 @@ fun Bot.validateAdministrator(user: User?, chat: Chat, sendMessage: Boolean = tr
108109

109110
val chatType = chat.type
110111
if ((chatType == "group" || chatType == "supergroup") &&
111-
getChatAdministrators(chatId).join().all { it.user != user }
112+
getChatAdministrators(chatId.toChatId()).all { it.user != user }
112113
) {
113114
if (sendMessage) sendMessageLogging(chatId, ON_PERMISSION_DENY)
114115
return false

src/main/kotlin/com/github/pool_party/pull_party_bot/commands/EveryMessageInteraction.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package com.github.pool_party.pull_party_bot.commands
22

3-
import com.elbekD.bot.Bot
4-
import com.elbekD.bot.types.Message
3+
import com.elbekd.bot.Bot
4+
import com.elbekd.bot.types.Message
55

66
interface EveryMessageInteraction {
77

src/main/kotlin/com/github/pool_party/pull_party_bot/commands/Handlers.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.github.pool_party.pull_party_bot.commands
22

3-
import com.elbekD.bot.Bot
3+
import com.elbekd.bot.Bot
4+
import com.elbekd.bot.model.toChatId
5+
import com.elbekd.bot.types.ParseMode
46
import com.github.pool_party.pull_party_bot.Configuration
57
import com.github.pool_party.pull_party_bot.commands.handlers.AddCommand
68
import com.github.pool_party.pull_party_bot.commands.handlers.AliasCommand
@@ -25,7 +27,7 @@ import com.github.pool_party.pull_party_bot.database.dao.ChatDaoImpl
2527
import com.github.pool_party.pull_party_bot.database.dao.PartyDaoImpl
2628
import mu.KotlinLogging
2729

28-
fun Bot.initHandlers() {
30+
suspend fun Bot.initHandlers() {
2931

3032
val partyDaoImpl = PartyDaoImpl()
3133

@@ -75,12 +77,12 @@ suspend fun <T> Bot.loggingError(action: suspend () -> T): T =
7577
processThrowable(throwable)
7678
}
7779

78-
private fun Bot.processThrowable(throwable: Throwable): Nothing {
80+
private suspend fun Bot.processThrowable(throwable: Throwable): Nothing {
7981
val (prefix, reason) =
8082
if (throwable is SendingMessageException) "${throwable.action}: " to throwable.reason else "" to throwable
8183

8284
logger.error { "$prefix${reason.message}:\n${reason.stackTraceToString()}" }
83-
sendMessage(Configuration.DEVELOP_CHAT_ID, onError(reason).escapeSpecial(), "MarkdownV2").join()
85+
sendMessage(Configuration.DEVELOP_CHAT_ID.toChatId(), onError(reason).escapeSpecial(), ParseMode.MarkdownV2)
8486

8587
throw reason
8688
}

0 commit comments

Comments
 (0)