Compare commits

...

53 Commits

Author SHA1 Message Date
0652a95d11 Merge pull request #128 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v2.1.2
2022-06-29 18:41:36 +06:00
renovate[bot]
f6066c60c0 Update telegram_bot_api_version to v2.1.2 2022-06-29 12:41:23 +00:00
2fa340292c Merge pull request #127 from InsanusMokrassar/renovate/ktor_version
Update dependency io.ktor:ktor-server-cio to v2.0.3
2022-06-29 18:41:04 +06:00
7d94007905 Merge pull request #126 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.9
2022-06-29 18:40:53 +06:00
renovate[bot]
9638174d48 Update dependency dev.inmo:micro_utils.ktor.server to v0.11.9 2022-06-29 11:53:40 +00:00
renovate[bot]
18bacaea2e Update dependency io.ktor:ktor-server-cio to v2.0.3 2022-06-28 16:35:40 +00:00
0f2b3760dd Merge pull request #125 from InsanusMokrassar/2.1.1
2.1.1
2022-06-26 15:24:30 +06:00
730923f55c actualization 2022-06-26 13:25:26 +06:00
9cf8bd9f28 migration onto 2.1.1 2022-06-26 13:03:52 +06:00
370fa45dba Merge pull request #124 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.6
2022-06-24 08:27:13 +06:00
renovate[bot]
72e7a73e40 Update dependency dev.inmo:micro_utils.ktor.server to v0.11.6 2022-06-23 23:54:36 +00:00
10dd9bd851 Merge pull request #123 from InsanusMokrassar/2.1.0
2.1.0
2022-06-22 00:43:36 +06:00
0217f97014 checked 2.1.0 and Bot API 6.1 + update several examples 2022-06-21 19:45:24 +06:00
4ae700b58a Merge pull request #121 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.3
2022-06-17 17:44:48 +06:00
renovate[bot]
804fb1e5ee Update dependency dev.inmo:micro_utils.ktor.server to v0.11.3 2022-06-17 11:44:38 +00:00
d443c39813 Merge pull request #122 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v2.0.3
2022-06-17 17:43:10 +06:00
renovate[bot]
cd96547d15 Update telegram_bot_api_version to v2.0.3 2022-06-17 11:42:07 +00:00
f107b4144d Update gradle.properties 2022-06-05 21:25:59 +06:00
39f4196b76 Merge pull request #119 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.0
2022-06-05 21:25:40 +06:00
Renovate Bot
22b9776c26 Update dependency dev.inmo:micro_utils.ktor.server to v0.11.0 2022-06-05 05:10:25 +00:00
2f8f6f3169 Merge pull request #118 from Akkihi/master
fixing example webapp mobile view with html meta
2022-06-04 16:49:52 +06:00
f2b6a50cb5 fixing example webapp mobile view with html meta 2022-06-04 14:46:28 +04:00
acd602d6fa Merge pull request #116 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.10.8
2022-06-03 10:33:33 +06:00
fdb80bf471 Merge pull request #115 from InsanusMokrassar/renovate/ktor_version
Update dependency io.ktor:ktor-server-cio to v2.0.2
2022-06-03 08:57:38 +06:00
Renovate Bot
78c58db4b7 Update dependency dev.inmo:micro_utils.ktor.server to v0.10.8 2022-06-03 02:57:34 +00:00
edd6399bcc Merge pull request #117 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v2.0.1
2022-06-03 08:56:53 +06:00
Renovate Bot
9513e77ba3 Update telegram_bot_api_version to v2.0.1 2022-05-29 20:26:33 +00:00
Renovate Bot
ac75f6487e Update dependency io.ktor:ktor-server-cio to v2.0.2 2022-05-27 18:22:47 +00:00
07750a71c0 Merge pull request #114 from InsanusMokrassar/2.0.0
2.0.0
2022-05-22 14:55:10 +06:00
0bf7e33df3 migration onto 2.0.0 and several improvements 2022-05-22 12:57:53 +06:00
7fb308ea4b Merge pull request #113 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v1.1.3
2022-05-19 14:57:05 -04:00
Renovate Bot
75b403ac98 Update telegram_bot_api_version to v1.1.3 2022-05-19 18:56:32 +00:00
5976e37046 Merge pull request #112 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.10.5
2022-05-19 14:56:10 -04:00
Renovate Bot
c8a94496c7 Update dependency dev.inmo:micro_utils.ktor.server to v0.10.5 2022-05-19 17:40:28 +00:00
f6550bd401 Merge pull request #110 from InsanusMokrassar/1.1.2
1.1.2
2022-05-18 10:24:09 -04:00
389d96f323 fix of checkWebAppData method call 2022-05-18 17:46:50 +06:00
803c5fd664 add handling of errors in FSMBot and update up to tgbotapi 1.1.2 2022-05-18 17:46:04 +06:00
b6eb4fe134 Merge pull request #108 from InsanusMokrassar/1.1.1
1.1.1
2022-05-17 16:05:35 -04:00
9a4bd55ef6 update tgbotapi version 2022-05-17 19:55:42 +06:00
4dac411693 add support of data checking in webapp 2022-05-17 18:58:43 +06:00
d386d50f1c Merge pull request #107 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v1.1.0
2022-05-14 17:33:30 +06:00
Renovate Bot
1b846a6383 Update telegram_bot_api_version to v1.1.0 2022-05-14 11:33:22 +00:00
568b845890 Merge pull request #106 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.10.4
2022-05-14 17:32:48 +06:00
Renovate Bot
3ebca4a058 Update dependency dev.inmo:micro_utils.ktor.server to v0.10.4 2022-05-12 15:37:39 +00:00
2b9af2f667 Merge pull request #104 from InsanusMokrassar/1.0.0
1.0.0
2022-05-12 17:05:10 +06:00
16410debff decrease xmx 2022-05-12 17:00:22 +06:00
a18f22fe8f update xmx for builds 2022-05-12 16:47:46 +06:00
0489f217b3 update examples 2022-05-11 12:15:18 +06:00
e772cfda3b start migration onto 1.0.0 2022-05-11 02:47:37 +06:00
9d42385662 1.0.0 migration preview 2022-05-11 00:23:14 +06:00
b740203116 0.38.23 2022-05-08 00:41:13 +06:00
149717301d Update gradle.properties 2022-05-05 15:16:24 +06:00
60e72be844 Merge pull request #103 from InsanusMokrassar/0.38.21
0.38.21
2022-05-04 14:54:45 +06:00
19 changed files with 229 additions and 92 deletions

View File

@@ -8,9 +8,9 @@ jobs:
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up JDK 1.8 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 1.8 java-version: 11
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build run: ./gradlew build

View File

@@ -1,4 +1,6 @@
import dev.inmo.micro_utils.coroutines.AccumulatorFlow
import dev.inmo.micro_utils.fsm.common.State import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.api.send.sendMessage import dev.inmo.tgbotapi.extensions.api.send.sendMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.* import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.*
@@ -9,6 +11,7 @@ import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.message.content.TextContent
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.first
sealed interface BotState : State sealed interface BotState : State
data class ExpectContentOrStopState(override val context: ChatId, val sourceMessage: CommonMessage<TextContent>) : BotState data class ExpectContentOrStopState(override val context: ChatId, val sourceMessage: CommonMessage<TextContent>) : BotState
@@ -17,7 +20,22 @@ data class StopState(override val context: ChatId) : BotState
suspend fun main(args: Array<String>) { suspend fun main(args: Array<String>) {
val botToken = args.first() val botToken = args.first()
telegramBotWithBehaviourAndFSMAndStartLongPolling<BotState>(botToken, CoroutineScope(Dispatchers.IO)) { telegramBotWithBehaviourAndFSMAndStartLongPolling<BotState>(
botToken,
CoroutineScope(Dispatchers.IO),
onStateHandlingErrorHandler = { state, e ->
when (state) {
is ExpectContentOrStopState -> {
println("Thrown error on ExpectContentOrStopState")
}
is StopState -> {
println("Thrown error on StopState")
}
}
e.printStackTrace()
state
}
) {
strictlyOn<ExpectContentOrStopState> { strictlyOn<ExpectContentOrStopState> {
sendMessage( sendMessage(
it.context, it.context,
@@ -38,7 +56,7 @@ suspend fun main(args: Array<String>) {
} }
} }
strictlyOn<StopState> { strictlyOn<StopState> {
sendMessage(it.context, "You have stopped sending of content") send(it.context, "You have stopped sending of content")
null null
} }

View File

@@ -1,7 +1,6 @@
import dev.inmo.tgbotapi.extensions.api.files.downloadFile import dev.inmo.tgbotapi.extensions.api.files.downloadFile
import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo import dev.inmo.tgbotapi.extensions.api.get.getFileAdditionalInfo
import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviour
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMedia import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMedia
@@ -21,11 +20,9 @@ suspend fun main(args: Array<String>) {
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) { telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
onMedia(initialFilter = null) { onMedia(initialFilter = null) {
val pathedFile = bot.getFileAdditionalInfo(it.content.media) val pathedFile = bot.getFileAdditionalInfo(it.content.media)
val file = File(directoryOrFile, pathedFile.filePath.filenameFromUrl).apply { val outFile = File(directoryOrFile, pathedFile.filePath.filenameFromUrl)
createNewFile() bot.downloadFile(it.content.media, outFile)
writeBytes(bot.downloadFile(pathedFile)) reply(it, "Saved to ${outFile.absolutePath}")
}
reply(it, "Saved to ${file.absolutePath}")
} }
onContentMessage { println(it) } onContentMessage { println(it) }
}.second.join() }.second.join()

View File

@@ -2,7 +2,9 @@ import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.formatting.* import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.types.* import dev.inmo.tgbotapi.types.chat.CommonBot
import dev.inmo.tgbotapi.types.chat.CommonUser
import dev.inmo.tgbotapi.types.chat.ExtendedBot
import dev.inmo.tgbotapi.types.message.* import dev.inmo.tgbotapi.types.message.*
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -24,7 +26,13 @@ suspend fun main(vararg args: String) {
is UserForwardInfo -> { is UserForwardInfo -> {
val user = forwardInfo.from val user = forwardInfo.from
when (user) { when (user) {
is CommonUser -> regular("User ") is CommonUser -> {
if (user.isPremium) {
regular("Premium user ")
} else {
regular("User ")
}
}
is CommonBot, is CommonBot,
is ExtendedBot -> regular("Bot ") is ExtendedBot -> regular("Bot ")
} + code(user.id.chatId.toString()) + " (${user.firstName} ${user.lastName}: ${user.username ?.username ?: "Without username"})" } + code(user.id.chatId.toString()) + " (${user.firstName} ${user.lastName}: ${user.username ?.username ?: "Without username"})"
@@ -34,8 +42,6 @@ suspend fun main(vararg args: String) {
} }
} }
reply(it, toAnswer) reply(it, toAnswer)
coroutineContext.job.invokeOnCompletion { println("completance of onContentMessage") }
} }
coroutineContext.job.invokeOnCompletion { println("Completed :)") }
}.second.join() }.second.join()
} }

View File

@@ -1,4 +1,4 @@
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
/** /**
@@ -10,4 +10,4 @@ suspend fun main(vararg args: String) {
val bot = telegramBot(botToken) val bot = telegramBot(botToken)
println(bot.getMe()) println(bot.getMe())
} }

View File

@@ -1,20 +1,23 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.reply import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.send.sendTextMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2 import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2 import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2
import dev.inmo.tgbotapi.types.ParseMode.MarkdownV2 import dev.inmo.tgbotapi.types.chat.*
import dev.inmo.tgbotapi.types.User import dev.inmo.tgbotapi.types.chat.GroupChat
import dev.inmo.tgbotapi.types.chat.abstracts.* import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.chat.SupergroupChat
import dev.inmo.tgbotapi.types.message.MarkdownV2
import dev.inmo.tgbotapi.utils.PreviewFeature
import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common
import kotlinx.coroutines.* import kotlinx.coroutines.*
/** /**
* The main purpose of this bot is just to answer "Oh, hi, " and add user mention here * The main purpose of this bot is just to answer "Oh, hi, " and add user mention here
*/ */
@OptIn(PreviewFeature::class)
suspend fun main(vararg args: String) { suspend fun main(vararg args: String) {
val botToken = args.first() val botToken = args.first()
@@ -23,12 +26,12 @@ suspend fun main(vararg args: String) {
val chat = message.chat val chat = message.chat
if (chat is ChannelChat) { if (chat is ChannelChat) {
val answer = "Hi everybody in this channel \"${chat.title}\"" val answer = "Hi everybody in this channel \"${chat.title}\""
sendTextMessage(chat, answer, MarkdownV2) send(chat, answer, MarkdownV2)
return@onContentMessage return@onContentMessage
} }
val answerText = "Oh, hi, " + when (chat) { val answerText = "Oh, hi, " + when (chat) {
is PrivateChat -> "${chat.firstName} ${chat.lastName}".textMentionMarkdownV2(chat.id)
is User -> "${chat.firstName} ${chat.lastName}".textMentionMarkdownV2(chat.id) is User -> "${chat.firstName} ${chat.lastName}".textMentionMarkdownV2(chat.id)
is PrivateChat -> "${chat.firstName} ${chat.lastName}".textMentionMarkdownV2(chat.id)
is SupergroupChat -> (chat.username ?.username ?: getChat(chat).inviteLink) ?.let { is SupergroupChat -> (chat.username ?.username ?: getChat(chat).inviteLink) ?.let {
chat.title.linkMarkdownV2(it) chat.title.linkMarkdownV2(it)
} ?: chat.title } ?: chat.title

View File

@@ -9,7 +9,7 @@ buildscript {
} }
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version" id "org.jetbrains.kotlin.multiplatform"
} }

View File

@@ -1,17 +1,17 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.bot.Ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.answers.answer import dev.inmo.tgbotapi.extensions.api.answers.answer
import dev.inmo.tgbotapi.extensions.api.edit.text.editMessageText import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.edit.edit
import dev.inmo.tgbotapi.extensions.api.send.* import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.send.media.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilterExcludeMediaGroups
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.shortcuts.* import dev.inmo.tgbotapi.extensions.utils.formatting.botCommand
import dev.inmo.tgbotapi.extensions.utils.formatting.buildEntities
import dev.inmo.tgbotapi.extensions.utils.types.buttons.* import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.extensions.utils.withContent import dev.inmo.tgbotapi.extensions.utils.withContent
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.message.content.TextContent import dev.inmo.tgbotapi.types.message.content.TextContent
import kotlinx.coroutines.* import kotlinx.coroutines.*
@@ -86,12 +86,14 @@ suspend fun activateKeyboardsBot(
return@onMessageDataCallbackQuery return@onMessageDataCallbackQuery
} }
editMessageText( val text = "This is $page of $count"
edit(
it.message.withContent<TextContent>() ?: it.let { it.message.withContent<TextContent>() ?: it.let {
answer(it, "Unsupported message type :(") answer(it, "Unsupported message type :(")
return@onMessageDataCallbackQuery return@onMessageDataCallbackQuery
}, },
"This is $page of $count", text,
replyMarkup = inlineKeyboard { replyMarkup = inlineKeyboard {
row { row {
includePageButtons(page, count) includePageButtons(page, count)
@@ -100,6 +102,22 @@ suspend fun activateKeyboardsBot(
) )
} }
onUnhandledCommand {
reply(
it,
buildEntities {
+"Use " + botCommand("inline") + " to get pagination inline keyboard"
},
replyMarkup = replyKeyboard(resizeKeyboard = true, oneTimeKeyboard = true) {
row {
simpleButton("/inline")
}
}
)
}
setMyCommands(BotCommand("inline", "Creates message with pagination inline keyboard"))
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it) println(it)
} }

View File

@@ -1,23 +1,19 @@
import dev.inmo.tgbotapi.bot.Ktor.telegramBot import dev.inmo.micro_utils.common.filesize
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.bot.TelegramBot import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.send.media.sendDocument import dev.inmo.tgbotapi.extensions.api.send.media.sendDocument
import dev.inmo.tgbotapi.extensions.api.send.media.sendDocumentsGroup import dev.inmo.tgbotapi.extensions.api.send.media.sendDocumentsGroup
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.withUploadDocumentAction
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviour
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.onCommandWithArgs import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommandWithArgs
import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile
import dev.inmo.tgbotapi.requests.abstracts.toInputFile
import dev.inmo.tgbotapi.types.BotCommand import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.InputMedia.DocumentMediaGroupMemberInputMedia import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.InputMedia.InputMediaDocument import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.types.chat.abstracts.Chat import dev.inmo.tgbotapi.types.media.TelegramMediaDocument
import dev.inmo.tgbotapi.types.mediaCountInMediaGroup import dev.inmo.tgbotapi.types.mediaCountInMediaGroup
import kotlinx.coroutines.*
import java.io.File import java.io.File
private const val command = "send_file" private const val command = "send_file"
@@ -50,7 +46,7 @@ suspend fun main(args: Array<String>) {
) )
else -> sendDocumentsGroup( else -> sendDocumentsGroup(
chat, chat,
files.map { InputMediaDocument(it.asMultipartFile()) }, files.map { TelegramMediaDocument(it.asMultipartFile()) },
protectContent = true protectContent = true
) )
} }
@@ -69,9 +65,9 @@ suspend fun main(args: Array<String>) {
val chosen = mutableListOf<File>() val chosen = mutableListOf<File>()
while (left > 0) { while (left > 0) {
left-- val picked = pickFile() ?.takeIf { it.filesize > 0 } ?: continue
val picked = pickFile() ?: continue
chosen.add(picked) chosen.add(picked)
left--
if (chosen.size >= mediaCountInMediaGroup.last) { if (chosen.size >= mediaCountInMediaGroup.last) {
sendFiles(message.chat, chosen) sendFiles(message.chat, chosen)
chosen.clear() chosen.clear()
@@ -85,7 +81,7 @@ suspend fun main(args: Array<String>) {
} }
if (!sent) { if (!sent) {
bot.reply(message, "Nothing selected :(") reply(message, "Nothing selected :(")
} }
} }
} }

View File

@@ -9,7 +9,7 @@ buildscript {
} }
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version" id "org.jetbrains.kotlin.multiplatform"
} }

View File

@@ -1,6 +1,6 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.bot.Ktor.telegramBot import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.send.* import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.send.media.* import dev.inmo.tgbotapi.extensions.api.send.media.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
@@ -8,7 +8,6 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.CommonMessageFilte
import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat import dev.inmo.tgbotapi.extensions.behaviour_builder.filters.MessageFilterByChat
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.shortcuts.* import dev.inmo.tgbotapi.extensions.utils.shortcuts.*
import dev.inmo.tgbotapi.types.message.abstracts.Message
import kotlinx.coroutines.* import kotlinx.coroutines.*
suspend fun activateResenderBot( suspend fun activateResenderBot(
@@ -32,19 +31,19 @@ suspend fun activateResenderBot(
onVisualGallery { onVisualGallery {
val chat = it.chat ?: return@onVisualGallery val chat = it.chat ?: return@onVisualGallery
withUploadPhotoAction(chat) { withUploadPhotoAction(chat) {
sendVisualMediaGroup(chat, it.map { it.content.toMediaGroupMemberInputMedia() }) send(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
} }
} }
onPlaylist { onPlaylist {
val chat = it.chat ?: return@onPlaylist val chat = it.chat ?: return@onPlaylist
withUploadDocumentAction(chat) { withUploadDocumentAction(chat) {
sendPlaylist(chat, it.map { it.content.toMediaGroupMemberInputMedia() }) send(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
} }
} }
onDocumentsGroup { onDocumentsGroup {
val chat = it.chat ?: return@onDocumentsGroup val chat = it.chat ?: return@onDocumentsGroup
withUploadDocumentAction(chat) { withUploadDocumentAction(chat) {
sendDocumentsGroup(chat, it.map { it.content.toMediaGroupMemberInputMedia() }) send(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
} }
} }

View File

@@ -1,35 +1,26 @@
import dev.inmo.micro_utils.coroutines.safely import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.bot.Ktor.telegramBot
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.triggers_handling.onDice
import dev.inmo.tgbotapi.extensions.utils.* import dev.inmo.tgbotapi.extensions.utils.*
import dev.inmo.tgbotapi.extensions.utils.shortcuts.filterContentMessages
import dev.inmo.tgbotapi.extensions.utils.updates.retrieving.longPolling
import dev.inmo.tgbotapi.types.dice.SlotMachineDiceAnimationType import dev.inmo.tgbotapi.types.dice.SlotMachineDiceAnimationType
import dev.inmo.tgbotapi.types.message.content.DiceContent
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
suspend fun main(args: Array<String>) { suspend fun main(args: Array<String>) {
val bot = telegramBot(args.first()) val bot = telegramBot(args.first())
val scope = CoroutineScope(Dispatchers.Default) bot.buildBehaviourWithLongPolling(scope = CoroutineScope(Dispatchers.IO)) {
bot.longPolling(scope = scope) { onDice {
filterContentMessages<DiceContent>(scope).onEach {
val content = it.content val content = it.content
val dice = content.dice val dice = content.dice
val diceType = dice.animationType val diceType = dice.animationType
safely ({ it.printStackTrace() }) { if (diceType == SlotMachineDiceAnimationType) {
if (diceType == SlotMachineDiceAnimationType) { val result = dice.calculateSlotMachineResult() ?: return@onDice
val result = dice.calculateSlotMachineResult() ?: return@safely reply(it, "${result.leftReel}|${result.centerReel}|${result.rightReel}")
bot.reply(it, "${result.leftReel}|${result.centerReel}|${result.rightReel}") } else {
} else { reply(it, "There is no slot machine dice in message")
bot.reply(it, "There is no slot machine dice in message")
}
} }
}.launchIn(scope) }
} }.join()
}
scope.coroutineContext[Job]!!.join()
}

View File

@@ -9,7 +9,8 @@ buildscript {
} }
plugins { plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version" id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
} }
apply plugin: 'application' apply plugin: 'application'
@@ -25,6 +26,7 @@ kotlin {
commonMain { commonMain {
dependencies { dependencies {
implementation kotlin('stdlib') implementation kotlin('stdlib')
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:$serialization_version"
} }
} }

View File

@@ -0,0 +1,7 @@
import kotlinx.serialization.Serializable
@Serializable
data class WebAppDataWrapper(
val data: String,
val hash: String
)

View File

@@ -1,11 +1,11 @@
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.types.webAppQueryIdField import dev.inmo.tgbotapi.types.webAppQueryIdField
import dev.inmo.tgbotapi.webapps.* import dev.inmo.tgbotapi.webapps.*
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedbackStyle
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedbackType
import io.ktor.client.HttpClient import io.ktor.client.HttpClient
import io.ktor.client.call.receive
import io.ktor.client.request.* import io.ktor.client.request.*
import io.ktor.client.statement.HttpResponse import io.ktor.client.statement.bodyAsText
import io.ktor.client.statement.readText
import io.ktor.http.* import io.ktor.http.*
import io.ktor.http.content.TextContent import io.ktor.http.content.TextContent
import kotlinx.browser.document import kotlinx.browser.document
@@ -13,25 +13,54 @@ import kotlinx.browser.window
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.dom.appendElement import kotlinx.dom.appendElement
import kotlinx.dom.appendText import kotlinx.dom.appendText
import kotlinx.serialization.json.Json
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
fun HTMLElement.log(text: String) { fun HTMLElement.log(text: String) {
appendElement("p", {})
appendText(text) appendText(text)
appendElement("p", {})
} }
fun main() { fun main() {
console.log("Web app started") console.log("Web app started")
val client = HttpClient()
val baseUrl = window.location.origin.removeSuffix("/")
window.onload = { window.onload = {
val scope = CoroutineScope(Dispatchers.Default) val scope = CoroutineScope(Dispatchers.Default)
runCatching { runCatching {
scope.launchSafelyWithoutExceptions {
val response = client.post("$baseUrl/check") {
setBody(
Json { }.encodeToString(
WebAppDataWrapper.serializer(),
WebAppDataWrapper(webApp.initData, webApp.initDataUnsafe.hash)
)
)
}
val dataIsSafe = response.bodyAsText().toBoolean()
document.body ?.log(
if (dataIsSafe) {
"Data is safe"
} else {
"Data is unsafe"
}
)
document.body ?.log(
webApp.initDataUnsafe.chat.toString()
)
}
document.body ?.appendElement("button") { document.body ?.appendElement("button") {
addEventListener("click", { addEventListener("click", {
scope.launchSafelyWithoutExceptions { scope.launchSafelyWithoutExceptions {
handleResult({ "Clicked" }) { handleResult({ "Clicked" }) {
HttpClient().post<HttpResponse>("${window.location.origin.removeSuffix("/")}/inline") { client.post("${window.location.origin.removeSuffix("/")}/inline") {
parameter(webAppQueryIdField, it) parameter(webAppQueryIdField, it)
body = TextContent("Clicked", ContentType.Text.Plain) setBody(TextContent("Clicked", ContentType.Text.Plain))
document.body ?.log(url.build().toString()) document.body ?.log(url.build().toString())
}.coroutineContext.job.join() }.coroutineContext.job.join()
} }
@@ -46,6 +75,28 @@ fun main() {
onViewportChanged { onViewportChanged {
document.body ?.log("Viewport changed: ${it.isStateStable}") document.body ?.log("Viewport changed: ${it.isStateStable}")
} }
backButton.apply {
onClick {
document.body ?.log("Back button clicked")
hapticFeedback.impactOccurred(
HapticFeedbackStyle.Heavy
)
}
show()
}
mainButton.apply {
setText("Main button")
onClick {
document.body ?.log("Main button clicked")
hapticFeedback.notificationOccurred(
HapticFeedbackType.Success
)
}
show()
}
onSettingsButtonClicked {
document.body ?.log("Settings button clicked")
}
} }
webApp.ready() webApp.ready()
}.onFailure { }.onFailure {

View File

@@ -2,6 +2,11 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="format-detection" content="telephone=no"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="HandheldFriendly" content="True"/>
<meta name="robots" content="noindex,nofollow"/>
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>
<title>Web App Example</title> <title>Web App Example</title>
</head> </head>
<body> <body>

View File

@@ -1,4 +1,5 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.crypto.hmacSha256
import dev.inmo.micro_utils.ktor.server.createKtorServer import dev.inmo.micro_utils.ktor.server.createKtorServer
import dev.inmo.tgbotapi.extensions.api.answers.answer import dev.inmo.tgbotapi.extensions.api.answers.answer
import dev.inmo.tgbotapi.extensions.api.bot.getMe import dev.inmo.tgbotapi.extensions.api.bot.getMe
@@ -7,20 +8,27 @@ import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.telegramBot import dev.inmo.tgbotapi.extensions.api.telegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.* import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.* import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.formatting.botCommand
import dev.inmo.tgbotapi.extensions.utils.formatting.buildEntities
import dev.inmo.tgbotapi.extensions.utils.types.buttons.* import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.types.BotCommand import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent
import dev.inmo.tgbotapi.types.webAppQueryIdField import dev.inmo.tgbotapi.types.webAppQueryIdField
import dev.inmo.tgbotapi.types.webapps.WebAppInfo import dev.inmo.tgbotapi.types.webapps.WebAppInfo
import io.ktor.application.call import dev.inmo.tgbotapi.utils.PreviewFeature
import io.ktor.http.HttpStatusCode import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.http.content.* import io.ktor.http.*
import io.ktor.request.receiveText import io.ktor.server.application.call
import io.ktor.response.respond import io.ktor.server.http.content.*
import io.ktor.routing.* import io.ktor.server.request.receiveText
import io.ktor.server.response.respond
import io.ktor.server.routing.post
import io.ktor.server.routing.routing
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.serialization.json.Json
import java.io.File import java.io.File
import java.nio.charset.Charset
/** /**
* Accepts two parameters: * Accepts two parameters:
@@ -30,8 +38,13 @@ import java.io.File
* *
* Will start the server to share the static (index.html and WebApp.js) on 0.0.0.0:8080 * Will start the server to share the static (index.html and WebApp.js) on 0.0.0.0:8080
*/ */
@OptIn(PreviewFeature::class)
suspend fun main(vararg args: String) { suspend fun main(vararg args: String) {
val bot = telegramBot(args.first(), testServer = args.any { it == "testServer" }) val telegramBotAPIUrlsKeeper = TelegramAPIUrlsKeeper(
args.first(),
testServer = args.any { it == "testServer" }
)
val bot = telegramBot(telegramBotAPIUrlsKeeper)
createKtorServer( createKtorServer(
"0.0.0.0", "0.0.0.0",
8080, 8080,
@@ -51,6 +64,14 @@ suspend fun main(vararg args: String) {
bot.answer(queryId, InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody))) bot.answer(queryId, InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody)))
call.respond(HttpStatusCode.OK) call.respond(HttpStatusCode.OK)
} }
post("check") {
val requestBody = call.receiveText()
val webAppCheckData = Json { }.decodeFromString(WebAppDataWrapper.serializer(), requestBody)
val isSafe = telegramBotAPIUrlsKeeper.checkWebAppData(webAppCheckData.data, webAppCheckData.hash)
call.respond(HttpStatusCode.OK, isSafe.toString())
}
} }
}.start(false) }.start(false)
@@ -81,6 +102,15 @@ suspend fun main(vararg args: String) {
) )
} }
onUnhandledCommand {
reply(
it,
buildEntities {
+"Use " + botCommand("inline") + " to get inline web app button\n"
+"Use " + botCommand("reply_markup") + " to get reply markup web app button\n"
}
)
}
setMyCommands( setMyCommands(
BotCommand("reply_markup", "Use to get reply markup keyboard with web app trigger"), BotCommand("reply_markup", "Use to get reply markup keyboard with web app trigger"),
BotCommand("inline", "Use to get inline keyboard with web app trigger"), BotCommand("inline", "Use to get inline keyboard with web app trigger"),

View File

@@ -1,3 +1,14 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
}
}
allprojects { allprojects {
repositories { repositories {
mavenLocal() mavenLocal()

View File

@@ -1,8 +1,11 @@
kotlin.code.style=official kotlin.code.style=official
org.gradle.parallel=true org.gradle.parallel=true
# Due to parallel compilation project require next amount of memory on full build
org.gradle.jvmargs=-Xmx768m
kotlin_version=1.6.10 kotlin_version=1.6.21
telegram_bot_api_version=0.38.21 telegram_bot_api_version=2.1.2
micro_utils_version=0.9.24 micro_utils_version=0.11.9
ktor_version=1.6.8 serialization_version=1.3.3
ktor_version=2.0.3