Compare commits

..

70 Commits
1.0.0 ... 3.2.0

Author SHA1 Message Date
0ebfb3c44a small fixes 2022-08-26 16:35:36 +06:00
9fa3690db6 add DeepLinkBot 2022-08-26 12:21:24 +06:00
a8c5d403c6 Merge pull request #141 from InsanusMokrassar/3.1.1
3.1.1
2022-08-15 09:41:20 +06:00
0c5186a37d add toggle closing confirmation button 2022-08-15 01:28:59 +06:00
7e9968ced9 add work with alerts in webapp 2022-08-15 01:12:39 +06:00
f1e8ed88a8 Merge pull request #139 from InsanusMokrassar/3.1.0
3.1.0
2022-08-13 16:58:34 +06:00
068dc79ac8 migration onto 3.1.0 and including new example 2022-08-13 14:39:24 +06:00
36273adfd1 Merge pull request #136 from InsanusMokrassar/3.0.0
3.0.0
2022-08-06 08:33:15 +06:00
bca2ae905b Update gradle-wrapper.properties 2022-08-06 08:19:13 +06:00
19a713a3e3 Update gradle.properties 2022-08-06 08:18:55 +06:00
e039f90961 updates according to 3.0.0 2022-08-05 19:45:52 +06:00
21692d16ca fixes in forward chat info bot 2022-08-04 22:32:36 +06:00
d547dce2ab update dependencies 2022-08-04 21:41:55 +06:00
9bfe88a79c Merge pull request #134 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v2.2.2
2022-07-31 21:48:05 +06:00
renovate[bot]
bfa327acf3 Update telegram_bot_api_version to v2.2.2 2022-07-31 15:35:38 +00:00
88a031b05a Update gradle.properties 2022-07-22 20:26:06 +06:00
20e942b2ac Merge pull request #133 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.13
2022-07-22 20:14:02 +06:00
renovate[bot]
3e20cbd22c Update dependency dev.inmo:micro_utils.ktor.server to v0.11.13 2022-07-22 14:10:56 +00:00
bcd35de038 Merge pull request #131 from InsanusMokrassar/renovate/telegram_bot_api_version
Update telegram_bot_api_version to v2.2.0
2022-07-11 12:05:16 +06:00
renovate[bot]
2aec45d453 Update telegram_bot_api_version to v2.2.0 2022-07-11 06:03:16 +00:00
ee55378e7a Update gradle.properties 2022-07-10 00:34:53 +06:00
b402c7b6e7 Merge pull request #130 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.12
2022-07-02 12:07:54 +06:00
renovate[bot]
32b7c7b9a4 Update dependency dev.inmo:micro_utils.ktor.server to v0.11.12 2022-07-02 06:02:52 +00:00
0b2d6b20de Merge pull request #129 from InsanusMokrassar/renovate/micro_utils_version
Update dependency dev.inmo:micro_utils.ktor.server to v0.11.10
2022-06-30 13:50:34 +06:00
renovate[bot]
182ee7a865 Update dependency dev.inmo:micro_utils.ktor.server to v0.11.10 2022-06-30 05:26:51 +00:00
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
29 changed files with 523 additions and 59 deletions

9
DeepLinksBot/README.md Normal file
View File

@@ -0,0 +1,9 @@
# DeepLinksBot
This bot will send you deeplink to this bot when you send some text message and react on the `start` button
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

21
DeepLinksBot/build.gradle Normal file
View File

@@ -0,0 +1,21 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="DeepLinksBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,39 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelySkippingExceptions
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitDeepLinks
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.formatting.makeTelegramDeepLink
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
/**
* This bot will send you deeplink to this bot when you send some text message and react on the `start` button
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
telegramBotWithBehaviourAndLongPolling(botToken) {
val me = bot.getMe()
println(me)
onText(
initialFilter = { it.content.textSources.none { it is BotCommandTextSource } } // excluding messages with commands
) {
reply(it, makeTelegramDeepLink(me.username, it.content.text))
}
onCommand("start", requireOnlyCommandInMessage = true) { // handling of `start` without args
reply(it, "Hi :) Send me any text and I will try hard to create deeplink for you")
}
onDeepLink { (it, deepLink) ->
reply(it, "Ok, I got deep link \"${deepLink}\" in trigger")
}
waitDeepLinks().subscribeSafelyWithoutExceptions(this) { (it, deepLink) ->
reply(it, "Ok, I got deep link \"${deepLink}\" in waiter")
println(triggersHolder.handleableCommandsHolder.handleable)
}
}.second.join()
}

View File

@@ -1,5 +1,6 @@
import dev.inmo.micro_utils.coroutines.AccumulatorFlow
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.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.*
@@ -10,6 +11,7 @@ import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
import dev.inmo.tgbotapi.types.message.content.TextContent
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.first
sealed interface BotState : State
data class ExpectContentOrStopState(override val context: ChatId, val sourceMessage: CommonMessage<TextContent>) : BotState
@@ -18,7 +20,22 @@ data class StopState(override val context: ChatId) : BotState
suspend fun main(args: Array<String>) {
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> {
sendMessage(
it.context,
@@ -39,7 +56,7 @@ suspend fun main(args: Array<String>) {
}
}
strictlyOn<StopState> {
sendMessage(it.context, "You have stopped sending of content")
send(it.context, "You have stopped sending of content")
null
}

View File

@@ -14,17 +14,19 @@ import java.io.File
*/
suspend fun main(args: Array<String>) {
val botToken = args.first()
val directoryOrFile = args.getOrNull(1) ?.let { File(it) } ?: File("")
val directoryOrFile = args.getOrNull(1) ?.let { File(it) } ?: File("/tmp/")
directoryOrFile.mkdirs()
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
onMedia(initialFilter = null) {
val pathedFile = bot.getFileAdditionalInfo(it.content.media)
val file = File(directoryOrFile, pathedFile.filePath.filenameFromUrl).apply {
createNewFile()
writeBytes(bot.downloadFile(pathedFile))
val outFile = File(directoryOrFile, pathedFile.filePath.filenameFromUrl)
runCatching {
bot.downloadFile(it.content.media, outFile)
}.onFailure {
it.printStackTrace()
}
reply(it, "Saved to ${file.absolutePath}")
reply(it, "Saved to ${outFile.absolutePath}")
}
onContentMessage { println(it) }
}.second.join()

View File

@@ -16,23 +16,30 @@ suspend fun main(vararg args: String) {
val botToken = args.first()
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
onContentMessage(subcontextUpdatesFilter = { _, _ -> true }) {
onContentMessage {
val toAnswer = buildEntities {
when (val forwardInfo = it.forwardInfo) {
null -> +"There is no forward info"
is AnonymousForwardInfo -> {
is ForwardInfo.ByAnonymous -> {
regular("Anonymous user which signed as \"") + code(forwardInfo.senderName) + "\""
}
is UserForwardInfo -> {
is ForwardInfo.ByUser -> {
val user = forwardInfo.from
when (user) {
is CommonUser -> regular("User ")
is CommonUser -> {
if (user.isPremium) {
regular("Premium user ")
} else {
regular("User ")
}
}
is CommonBot,
is ExtendedBot -> regular("Bot ")
} + code(user.id.chatId.toString()) + " (${user.firstName} ${user.lastName}: ${user.username ?.username ?: "Without username"})"
}
is ForwardFromChannelInfo -> regular("Channel (") + code((forwardInfo.channelChat).title) + ")"
is ForwardFromSupergroupInfo -> regular("Supergroup (") + code((forwardInfo.group).title) + ")"
is ForwardInfo.PublicChat.FromChannel -> regular("Channel (") + code(forwardInfo.channelChat.title) + ")"
is ForwardInfo.PublicChat.FromSupergroup -> regular("Supergroup (") + code(forwardInfo.group.title) + ")"
is ForwardInfo.PublicChat.SentByChannel -> regular("Sent by channel (") + code(forwardInfo.channelChat.title) + ")"
}
}
reply(it, toAnswer)

View File

@@ -11,7 +11,7 @@ buildscript {
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="HelloBotKt"
mainClassName="GetMeBotKt"
dependencies {

View File

@@ -1,11 +1,13 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.sendTextMessage
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sender_chat
import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.ifChannelChat
import dev.inmo.tgbotapi.extensions.utils.ifFromChannelGroupContentMessage
import dev.inmo.tgbotapi.types.chat.*
import dev.inmo.tgbotapi.types.chat.GroupChat
import dev.inmo.tgbotapi.types.chat.PrivateChat
@@ -25,21 +27,35 @@ suspend fun main(vararg args: String) {
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
onContentMessage { message ->
val chat = message.chat
if (chat is ChannelChat) {
val answer = "Hi everybody in this channel \"${chat.title}\""
sendTextMessage(chat, answer, MarkdownV2)
return@onContentMessage
}
val answerText = "Oh, hi, " + when (chat) {
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 {
chat.title.linkMarkdownV2(it)
} ?: chat.title
is GroupChat -> bot.getChat(chat).inviteLink ?.let {
chat.title.linkMarkdownV2(it)
} ?: chat.title
else -> "Unknown :(".escapeMarkdownV2Common()
val answerText = when (val chat = message.chat) {
is ChannelChat -> {
val answer = "Hi everybody in this channel \"${chat.title}\""
reply(message, answer, MarkdownV2)
return@onContentMessage
}
is PrivateChat -> {
reply(message, "Hi, " + "${chat.firstName} ${chat.lastName}".textMentionMarkdownV2(chat.id), MarkdownV2)
return@onContentMessage
}
is GroupChat -> {
message.ifFromChannelGroupContentMessage {
val answer = "Hi, ${it.senderChat.title}"
reply(message, answer, MarkdownV2)
return@onContentMessage
}
"Oh, hi, " + when (chat) {
is SupergroupChat -> (chat.username ?.username ?: getChat(chat).inviteLink) ?.let {
chat.title.linkMarkdownV2(it)
} ?: chat.title
else -> bot.getChat(chat).inviteLink ?.let {
chat.title.linkMarkdownV2(it)
} ?: chat.title
}
}
is UnknownExtendedChat,
is UnknownChatType -> "Unknown :(".escapeMarkdownV2Common()
else -> error("Something went wrong: unknown type of chat $chat")
}
reply(
message,

View File

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

View File

@@ -3,7 +3,7 @@ import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.answers.answer
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.edit.text.editMessageText
import dev.inmo.tgbotapi.extensions.api.edit.edit
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
@@ -88,7 +88,7 @@ suspend fun activateKeyboardsBot(
val text = "This is $page of $count"
editMessageText(
edit(
it.message.withContent<TextContent>() ?: it.let {
answer(it, "Unsupported message type :(")
return@onMessageDataCallbackQuery
@@ -100,6 +100,7 @@ suspend fun activateKeyboardsBot(
}
}
)
answer(it)
}
onUnhandledCommand {

View File

@@ -1,16 +1,17 @@
import dev.inmo.micro_utils.common.filesize
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
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.sendDocumentsGroup
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.withUploadDocumentAction
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommandWithArgs
import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.files.DocumentFile
import dev.inmo.tgbotapi.types.media.TelegramMediaDocument
import dev.inmo.tgbotapi.types.mediaCountInMediaGroup
import java.io.File
@@ -64,9 +65,9 @@ suspend fun main(args: Array<String>) {
val chosen = mutableListOf<File>()
while (left > 0) {
left--
val picked = pickFile() ?: continue
val picked = pickFile() ?.takeIf { it.filesize > 0 } ?: continue
chosen.add(picked)
left--
if (chosen.size >= mediaCountInMediaGroup.last) {
sendFiles(message.chat, chosen)
chosen.clear()
@@ -80,7 +81,7 @@ suspend fun main(args: Array<String>) {
}
if (!sent) {
bot.reply(message, "Nothing selected :(")
reply(message, "Nothing selected :(")
}
}
}

View File

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

View File

@@ -25,25 +25,27 @@ suspend fun activateResenderBot(
) {
val chat = it.chat
withTypingAction(chat) {
executeUnsafe(it.content.createResend(chat.id, replyToMessageId = it.messageId))
executeUnsafe(it.content.createResend(chat.id, replyToMessageId = it.messageId)) {
it.forEach(print)
}
}
}
onVisualGallery {
val chat = it.chat ?: return@onVisualGallery
withUploadPhotoAction(chat) {
sendVisualMediaGroup(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
send(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
}
}
onPlaylist {
val chat = it.chat ?: return@onPlaylist
withUploadDocumentAction(chat) {
sendPlaylist(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
send(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
}
}
onDocumentsGroup {
val chat = it.chat ?: return@onDocumentsGroup
withUploadDocumentAction(chat) {
sendDocumentsGroup(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
send(chat, it.map { it.content.toMediaGroupMemberTelegramMedia() })
}
}

View File

@@ -17,9 +17,9 @@ suspend fun main(args: Array<String>) {
if (diceType == SlotMachineDiceAnimationType) {
val result = dice.calculateSlotMachineResult() ?: return@onDice
bot.reply(it, "${result.leftReel}|${result.centerReel}|${result.rightReel}")
reply(it, "${result.leftReel}|${result.centerReel}|${result.rightReel}")
} else {
bot.reply(it, "There is no slot machine dice in message")
reply(it, "There is no slot machine dice in message")
}
}
}.join()

View File

@@ -0,0 +1,33 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.multiplatform"
}
kotlin {
jvm()
// js(LEGACY) {
js(IR) {
browser()
binaries.executable()
}
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api "dev.inmo:tgbotapi:$telegram_bot_api_version"
}
}
}
}

View File

@@ -0,0 +1,71 @@
import dev.inmo.micro_utils.coroutines.defaultSafelyWithoutExceptionHandler
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.get.getCustomEmojiStickerOrNull
import dev.inmo.tgbotapi.extensions.api.get.getStickerSet
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.message.textsources.*
import dev.inmo.tgbotapi.types.stickers.StickerSet
import kotlinx.coroutines.*
fun StickerSet.buildInfo() = buildEntities {
bold("StickerSet name: ") + "${name}\n"
bold("StickerSet title: ") + "${title}\n"
bold(
when (stickerType) {
StickerType.CustomEmoji -> "Custom emoji"
StickerType.Mask -> "Mask"
StickerType.Regular -> "Regular"
is StickerType.Unknown -> "Unknown type \"${stickerType.type}\""
}
) + " sticker set with title " + bold(title) + " and name " + bold(name)
}
suspend fun activateStickerInfoBot(
token: String,
print: (Any) -> Unit
) {
val bot = telegramBot(token)
print(bot.getMe())
defaultSafelyWithoutExceptionHandler = {
it.printStackTrace()
}
bot.buildBehaviourWithLongPolling(CoroutineScope(currentCoroutineContext() + SupervisorJob())) {
onText {
withTypingAction(it.chat) {
it.content.textSources.mapNotNull {
if (it is CustomEmojiTextSource) {
getCustomEmojiStickerOrNull(it.customEmojiId) ?.stickerSetName
} else {
null
}
}.distinct().map {
getStickerSet(it)
}.distinct().flatMap {
it.buildInfo() + regular("\n")
}.separateForText().map { entities ->
reply(it, entities)
}
}
}
onSticker {
val stickerSetInfo = getStickerSet(it.content.media)
reply(
it,
stickerSetInfo.buildInfo()
)
}
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.join()
}

View File

@@ -0,0 +1,32 @@
import kotlinx.browser.document
import kotlinx.coroutines.*
import org.w3c.dom.*
private val scope = CoroutineScope(Dispatchers.Default)
fun main() {
document.addEventListener(
"DOMContentLoaded",
{
val botsContainer = document.getElementById("bots_container") ?: return@addEventListener
(document.getElementById("bot_token_form") as? HTMLFormElement) ?.onsubmit = {
(document.getElementById("bot_token") as? HTMLInputElement) ?.value ?.let { token ->
val botContainer = document.createElement("div") as HTMLDivElement
botsContainer.append(botContainer)
val infoDiv = document.createElement("div") as HTMLDivElement
botContainer.append(infoDiv)
scope.launch {
activateStickerInfoBot(token) {
infoDiv.innerHTML = it.toString()
}
}
}
false
}
}
)
}

View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Resender bot</title>
</head>
<body>
<form id="bot_token_form">
<input type="text" id="bot_token">
<input type="submit" value="Start bot">
</form>
<div id="start_offer">Type your bot token to the input above to start its work</div>
<script type="text/javascript" src="StickerInfoBotLib.js"></script>
<div id="bots_container"></div>
</body>
</html>

View File

@@ -0,0 +1,21 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
mainClassName="StickerInfoBotJvmKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation project(":StickerInfoBot:StickerInfoBotLib")
}

View File

@@ -0,0 +1,5 @@
suspend fun main(args: Array<String>) {
activateStickerInfoBot(args.first()) {
println(it)
}
}

View File

@@ -9,7 +9,8 @@ buildscript {
}
plugins {
id "org.jetbrains.kotlin.multiplatform" version "$kotlin_version"
id "org.jetbrains.kotlin.multiplatform"
id "org.jetbrains.kotlin.plugin.serialization"
}
apply plugin: 'application'
@@ -25,6 +26,7 @@ kotlin {
commonMain {
dependencies {
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,12 @@
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.tgbotapi.types.webAppQueryIdField
import dev.inmo.tgbotapi.webapps.*
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedbackStyle
import dev.inmo.tgbotapi.webapps.haptic.HapticFeedbackType
import dev.inmo.tgbotapi.webapps.popup.*
import io.ktor.client.HttpClient
import io.ktor.client.call.receive
import io.ktor.client.request.*
import io.ktor.client.statement.HttpResponse
import io.ktor.client.statement.readText
import io.ktor.client.statement.bodyAsText
import io.ktor.http.*
import io.ktor.http.content.TextContent
import kotlinx.browser.document
@@ -13,23 +14,52 @@ import kotlinx.browser.window
import kotlinx.coroutines.*
import kotlinx.dom.appendElement
import kotlinx.dom.appendText
import kotlinx.serialization.json.Json
import org.w3c.dom.HTMLElement
fun HTMLElement.log(text: String) {
appendElement("p", {})
appendText(text)
appendElement("p", {})
}
fun main() {
console.log("Web app started")
val client = HttpClient()
val baseUrl = window.location.origin.removeSuffix("/")
window.onload = {
val scope = CoroutineScope(Dispatchers.Default)
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") {
addEventListener("click", {
scope.launchSafelyWithoutExceptions {
handleResult({ "Clicked" }) {
HttpClient().post("${window.location.origin.removeSuffix("/")}/inline") {
client.post("${window.location.origin.removeSuffix("/")}/inline") {
parameter(webAppQueryIdField, it)
setBody(TextContent("Clicked", ContentType.Text.Plain))
document.body ?.log(url.build().toString())
@@ -39,6 +69,79 @@ fun main() {
})
appendText("Example button")
} ?: window.alert("Unable to load body")
document.body ?.appendElement("p", {})
document.body ?.appendText("Alerts:")
document.body ?.appendElement("button") {
addEventListener("click", {
webApp.showPopup(
PopupParams(
"It is sample title of default button",
"It is sample message of default button",
DefaultPopupButton("default", "Default button"),
OkPopupButton("ok"),
DestructivePopupButton("destructive", "Destructive button")
)
) {
document.body ?.log(
when (it) {
"default" -> "You have clicked default button in popup"
"ok" -> "You have clicked ok button in popup"
"destructive" -> "You have clicked destructive button in popup"
else -> "I can't imagine where you take button with id $it"
}
)
}
})
appendText("Popup")
} ?: window.alert("Unable to load body")
document.body ?.appendElement("button") {
addEventListener("click", {
webApp.showAlert(
"This is alert message"
) {
document.body ?.log(
"You have closed alert"
)
}
})
appendText("Alert")
} ?: window.alert("Unable to load body")
document.body ?.appendElement("button") {
addEventListener("click", {
webApp.showConfirm(
"This is confirm message"
) {
document.body ?.log(
"You have pressed \"${if (it) "Ok" else "Cancel"}\" in confirm"
)
}
})
appendText("Confirm")
} ?: window.alert("Unable to load body")
document.body ?.appendElement("p", {})
document.body ?.appendElement("button") {
fun updateText() {
textContent = if (webApp.isClosingConfirmationEnabled) {
"Disable closing confirmation"
} else {
"Enable closing confirmation"
}
}
addEventListener("click", {
webApp.toggleClosingConfirmation()
updateText()
})
updateText()
} ?: window.alert("Unable to load body")
document.body ?.appendElement("p", {})
webApp.apply {
onThemeChanged {
document.body ?.log("Theme changed: ${webApp.themeParams}")
@@ -46,6 +149,28 @@ fun main() {
onViewportChanged {
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()
}.onFailure {

View File

@@ -2,6 +2,11 @@
<html lang="en">
<head>
<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>
</head>
<body>

View File

@@ -16,7 +16,8 @@ import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessag
import dev.inmo.tgbotapi.types.webAppQueryIdField
import dev.inmo.tgbotapi.types.webapps.WebAppInfo
import dev.inmo.tgbotapi.utils.PreviewFeature
import io.ktor.http.HttpStatusCode
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
import io.ktor.http.*
import io.ktor.server.application.call
import io.ktor.server.http.content.*
import io.ktor.server.request.receiveText
@@ -24,7 +25,9 @@ import io.ktor.server.response.respond
import io.ktor.server.routing.post
import io.ktor.server.routing.routing
import kotlinx.coroutines.Dispatchers
import kotlinx.serialization.json.Json
import java.io.File
import java.nio.charset.Charset
/**
* Accepts two parameters:
@@ -36,7 +39,11 @@ import java.io.File
*/
@OptIn(PreviewFeature::class)
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(
"0.0.0.0",
8080,
@@ -56,6 +63,14 @@ suspend fun main(vararg args: String) {
bot.answer(queryId, InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody)))
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)

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 {
repositories {
mavenLocal()

View File

@@ -4,7 +4,8 @@ org.gradle.parallel=true
org.gradle.jvmargs=-Xmx768m
kotlin_version=1.6.21
telegram_bot_api_version=1.0.0
micro_utils_version=0.10.3
ktor_version=2.0.1
kotlin_version=1.7.10
telegram_bot_api_version=3.2.0
micro_utils_version=0.12.4
serialization_version=1.4.0
ktor_version=2.1.0

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip

View File

@@ -6,6 +6,8 @@ include ":HelloBot"
include ":GetMeBot"
include ":DeepLinksBot"
include ":FilesLoaderBot"
include ":ResenderBot:ResenderBotLib"
@@ -14,6 +16,9 @@ include ":ResenderBot:jvm_launcher"
include ":KeyboardsBot:KeyboardsBotLib"
include ":KeyboardsBot:jvm_launcher"
include ":StickerInfoBot:StickerInfoBotLib"
include ":StickerInfoBot:jvm_launcher"
include ":SlotMachineDetectorBot"
include ":WebApp"