Skip to content

Commit fb0867f

Browse files
committed
Handle question for quizoji
1 parent 9c745d9 commit fb0867f

File tree

16 files changed

+384
-20
lines changed

16 files changed

+384
-20
lines changed

dialogs/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ plugins {
44
}
55

66
dependencies {
7+
api(libs.tgbotapi.core)
78
implementation(libs.kotlinx.serialization.core)
89
}

dialogs/dynamodb/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ dependencies {
66
api(project.projects.dialogs)
77
api(libs.dynamodb)
88
implementation(project.projects.utils.dynamodb)
9+
implementation(project.projects.utils.tgbotapiSerialization)
910
implementation(libs.kotlinx.coroutines.jdk8)
1011
implementation(libs.kotlinx.serialization.json)
1112

dialogs/dynamodb/src/main/kotlin/by/jprof/telegram/bot/dialogs/dynamodb/dao/DialogStateDAO.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@ import by.jprof.telegram.bot.dialogs.dao.DialogStateDAO
44
import by.jprof.telegram.bot.dialogs.model.DialogState
55
import by.jprof.telegram.bot.utils.dynamodb.toAttributeValue
66
import by.jprof.telegram.bot.utils.dynamodb.toString
7+
import by.jprof.telegram.bot.utils.tgbotapi_serialization.TgBotAPI
78
import kotlinx.coroutines.Dispatchers
89
import kotlinx.coroutines.future.await
910
import kotlinx.coroutines.withContext
1011
import kotlinx.serialization.decodeFromString
1112
import kotlinx.serialization.encodeToString
1213
import kotlinx.serialization.json.Json
14+
import kotlinx.serialization.modules.plus
1315
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient
1416
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
1517

@@ -55,7 +57,7 @@ class DialogStateDAO(
5557
}
5658
}
5759

58-
private val json = Json { serializersModule = DialogState.serializers }
60+
private val json = Json { serializersModule = DialogState.serializers + TgBotAPI.module }
5961

6062
fun Map<String, AttributeValue>.toDialogState(): DialogState = json.decodeFromString(this["value"].toString("value"))
6163

dialogs/dynamodb/src/test/kotlin/by/jprof/telegram/bot/dialogs/dynamodb/dao/DialogStateTest.kt

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package by.jprof.telegram.bot.dialogs.dynamodb.dao
22

3+
import by.jprof.telegram.bot.dialogs.model.quizoji.WaitingForOptions
34
import by.jprof.telegram.bot.dialogs.model.quizoji.WaitingForQuestion
5+
import dev.inmo.tgbotapi.types.message.content.TextContent
46
import org.junit.jupiter.api.Assertions
57
import org.junit.jupiter.api.Test
68
import software.amazon.awssdk.services.dynamodb.model.AttributeValue
79

810
internal class DialogStateTest {
911
@Test
10-
fun waitingForQuestionToAttributes() {
12+
fun quizojiWaitingForQuestionToAttributes() {
1113
Assertions.assertEquals(
1214
mapOf(
1315
"userId" to AttributeValue.builder().n("2").build(),
@@ -22,7 +24,7 @@ internal class DialogStateTest {
2224
}
2325

2426
@Test
25-
fun attributesToWaitingForQuestionTo() {
27+
fun quizojiAttributesToWaitingForQuestion() {
2628
Assertions.assertEquals(
2729
WaitingForQuestion(1, 2),
2830
mapOf(
@@ -35,4 +37,34 @@ internal class DialogStateTest {
3537
).toDialogState()
3638
)
3739
}
40+
41+
@Test
42+
fun quizojiWaitingForOptionsToAttributes() {
43+
Assertions.assertEquals(
44+
mapOf(
45+
"userId" to AttributeValue.builder().n("2").build(),
46+
"chatId" to AttributeValue.builder().n("1").build(),
47+
"value" to AttributeValue
48+
.builder()
49+
.s("{\"type\":\"WaitingForOptions\",\"chatId\":1,\"userId\":2,\"question\":{\"type\":\"TextContent\",\"text\":\"Question\"}}")
50+
.build(),
51+
),
52+
WaitingForOptions(1, 2, TextContent("Question")).toAttributes()
53+
)
54+
}
55+
56+
@Test
57+
fun quizojiAttributesToWaitingForOptions() {
58+
Assertions.assertEquals(
59+
WaitingForOptions(1, 2, TextContent("Question")),
60+
mapOf(
61+
"userId" to AttributeValue.builder().n("2").build(),
62+
"chatId" to AttributeValue.builder().n("1").build(),
63+
"value" to AttributeValue
64+
.builder()
65+
.s("{\"type\":\"WaitingForOptions\",\"chatId\":1,\"userId\":2,\"question\":{\"type\":\"TextContent\",\"text\":\"Question\"}}")
66+
.build(),
67+
).toDialogState()
68+
)
69+
}
3870
}

dialogs/src/main/kotlin/by/jprof/telegram/bot/dialogs/model/DialogState.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package by.jprof.telegram.bot.dialogs.model
22

3+
import by.jprof.telegram.bot.dialogs.model.quizoji.WaitingForOptions
34
import by.jprof.telegram.bot.dialogs.model.quizoji.WaitingForQuestion
45
import kotlinx.serialization.modules.SerializersModule
56
import kotlinx.serialization.modules.polymorphic
@@ -10,6 +11,7 @@ interface DialogState {
1011
val serializers = SerializersModule {
1112
polymorphic(DialogState::class) {
1213
subclass(WaitingForQuestion::class)
14+
subclass(WaitingForOptions::class)
1315
}
1416
}
1517
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package by.jprof.telegram.bot.dialogs.model.quizoji
2+
3+
import by.jprof.telegram.bot.dialogs.model.DialogState
4+
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
5+
import kotlinx.serialization.SerialName
6+
import kotlinx.serialization.Serializable
7+
8+
@Serializable
9+
@SerialName("WaitingForOptions")
10+
data class WaitingForOptions(
11+
override val chatId: Long,
12+
override val userId: Long,
13+
val question: MessageContent,
14+
) : DialogState

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ koin = "3.0.1"
1111
kotlinx-serialization = "1.2.1"
1212
jackson = "2.12.3"
1313

14-
tgbotapi = "0.33.3"
14+
tgbotapi = "0.35.0"
1515

1616
jsoup = "1.13.1"
1717

jep/src/main/kotlin/by/jprof/telegram/bot/jep/JEPUpdateProcessor.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import by.jprof.telegram.bot.votes.dao.VotesDAO
55
import by.jprof.telegram.bot.votes.model.Votes
66
import by.jprof.telegram.bot.votes.tgbotapi_extensions.toInlineKeyboardMarkup
77
import by.jprof.telegram.bot.votes.voting_processor.VotingProcessor
8-
import dev.inmo.tgbotapi.CommonAbstracts.justTextSources
98
import dev.inmo.tgbotapi.bot.RequestsExecutor
109
import dev.inmo.tgbotapi.extensions.api.send.reply
1110
import dev.inmo.tgbotapi.types.MessageEntity.textsources.TextLinkTextSource
@@ -65,8 +64,7 @@ class JEPUpdateProcessor(
6564
(message as? ContentMessage<*>)?.let { contentMessage ->
6665
(contentMessage.content as? TextContent)?.let { content ->
6766
content
68-
.textEntities
69-
.justTextSources()
67+
.textSources
7068
.mapNotNull {
7169
(it as? URLTextSource)?.source ?: (it as? TextLinkTextSource)?.url
7270
}

jep/src/test/kotlin/by/jprof/telegram/bot/jep/JEPUpdateProcessorTest.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package by.jprof.telegram.bot.jep
33
import by.jprof.telegram.bot.votes.dao.VotesDAO
44
import by.jprof.telegram.bot.votes.model.Votes
55
import by.jprof.telegram.bot.votes.tgbotapi_extensions.toInlineKeyboardMarkup
6-
import dev.inmo.tgbotapi.CommonAbstracts.TextPart
76
import dev.inmo.tgbotapi.bot.RequestsExecutor
87
import dev.inmo.tgbotapi.extensions.api.answers.answerCallbackQuery
98
import dev.inmo.tgbotapi.requests.send.SendTextMessage
@@ -92,8 +91,8 @@ internal class JEPUpdateProcessorTest {
9291
every { content } returns TextContent(
9392
"Hello, world!",
9493
listOf(
95-
TextPart(0..2, URLTextSource("https://google.com")),
96-
TextPart(0..2, TextLinkTextSource("google", "https://google.com")),
94+
URLTextSource("https://google.com"),
95+
TextLinkTextSource(" google", "https://google.com")
9796
)
9897
)
9998
}
@@ -110,8 +109,8 @@ internal class JEPUpdateProcessorTest {
110109
every { content } returns TextContent(
111110
"Hello, world!",
112111
listOf(
113-
TextPart(0..2, URLTextSource("https://openjdk.java.net/jeps/1")),
114-
TextPart(0..2, TextLinkTextSource("JEP 2", "https://openjdk.java.net/jeps/2")),
112+
URLTextSource("https://openjdk.java.net/jeps/1"),
113+
TextLinkTextSource("JEP 2", "https://openjdk.java.net/jeps/2"),
115114
)
116115
)
117116
every { chat } returns mockk {
@@ -155,8 +154,8 @@ internal class JEPUpdateProcessorTest {
155154
every { content } returns TextContent(
156155
"Hello, world!",
157156
listOf(
158-
TextPart(0..2, URLTextSource("https://openjdk.java.net/jeps/1")),
159-
TextPart(0..2, TextLinkTextSource("JEP 2", "https://openjdk.java.net/jeps/2")),
157+
URLTextSource("https://openjdk.java.net/jeps/1"),
158+
TextLinkTextSource("JEP 2", "https://openjdk.java.net/jeps/2"),
160159
)
161160
)
162161
every { chat } returns mockk {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package by.jprof.telegram.bot.quizoji
2+
3+
import by.jprof.telegram.bot.core.UpdateProcessor
4+
import by.jprof.telegram.bot.dialogs.dao.DialogStateDAO
5+
import by.jprof.telegram.bot.dialogs.model.quizoji.WaitingForOptions
6+
import by.jprof.telegram.bot.dialogs.model.quizoji.WaitingForQuestion
7+
import dev.inmo.tgbotapi.bot.RequestsExecutor
8+
import dev.inmo.tgbotapi.extensions.api.send.sendMessage
9+
import dev.inmo.tgbotapi.extensions.utils.asMessageUpdate
10+
import dev.inmo.tgbotapi.extensions.utils.asPrivateChat
11+
import dev.inmo.tgbotapi.extensions.utils.asPrivateContentMessage
12+
import dev.inmo.tgbotapi.types.MessageEntity.textsources.BotCommandTextSource
13+
import dev.inmo.tgbotapi.types.ParseMode.MarkdownV2
14+
import dev.inmo.tgbotapi.types.message.content.TextContent
15+
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
16+
import dev.inmo.tgbotapi.types.update.abstracts.Update
17+
import org.apache.logging.log4j.LogManager
18+
import kotlin.reflect.KClass
19+
20+
class QuizojiQuestionUpdateProcessor(
21+
private val dialogStateDAO: DialogStateDAO,
22+
private val bot: RequestsExecutor,
23+
) : UpdateProcessor {
24+
companion object {
25+
private val logger = LogManager.getLogger(QuizojiQuestionUpdateProcessor::class.java)!!
26+
private val supportedTypes = setOf<KClass<out MessageContent>>(
27+
TextContent::class
28+
)
29+
}
30+
31+
override suspend fun process(update: Update) {
32+
val message = update.asMessageUpdate()?.data?.asPrivateContentMessage() ?: return
33+
val chat = message.chat.asPrivateChat() ?: return
34+
val state = dialogStateDAO.get(chat.id.chatId, message.user.id.chatId)
35+
36+
if (state !is WaitingForQuestion) {
37+
return
38+
}
39+
40+
val content = message.content
41+
42+
if (content::class !in supportedTypes) {
43+
logger.warn("Unsupported message content: {}", content)
44+
45+
bot.sendMessage(
46+
chat = chat,
47+
text = "Unsupported question type: ${content::class.simpleName?.replace("Content", "")}"
48+
)
49+
50+
return
51+
}
52+
53+
if ((content as? TextContent)?.textSources?.any { it is BotCommandTextSource } == true) {
54+
logger.warn("Command sent as question: {}", content)
55+
56+
return
57+
}
58+
59+
logger.debug("{} provided a question ({}) for his Quizoji", chat.id.chatId, content)
60+
61+
dialogStateDAO.save(
62+
WaitingForOptions(
63+
chatId = chat.id.chatId,
64+
userId = message.user.id.chatId,
65+
question = content
66+
)
67+
)
68+
69+
bot.sendMessage(
70+
chat = chat,
71+
text = "Now send me the options, one per message\\. When done, send /done\\.\n\n_Up to 8 options are recommended, otherwise the buttons will be wrapped in multiple lines\\._",
72+
parseMode = MarkdownV2
73+
)
74+
}
75+
}

0 commit comments

Comments
 (0)