Compare commits

...

19 Commits
7.0.0 ... 7.1.0

Author SHA1 Message Date
0cfe60fd77 Update gradle.properties 2023-04-22 20:31:41 +06:00
6719b9e17c Update Bot.kt 2023-04-22 16:39:59 +06:00
8d33dc0ab2 Update README.md 2023-04-22 16:36:14 +06:00
3e2ccf9cf1 add answerInlineQuery with WebAppInfo 2023-04-22 11:06:03 +06:00
eccbe71e68 finish checking update 2023-04-22 00:17:39 +06:00
24c74f3b1a in keyboards bot add sample with sending of inline query 2023-04-22 00:11:56 +06:00
d7a7e7153e add inline queries sample 2023-04-21 23:21:15 +06:00
0b37acb7a9 Merge pull request #202 from InsanusMokrassar/7.0.2
7.0.2
2023-04-20 03:55:59 +06:00
3925ef9423 add opportunity to set port different with 8080 in WebAppServer sample 2023-04-19 21:46:35 +06:00
c6019b1862 complete sample with native 2023-04-19 20:20:11 +06:00
7b996fe1de rollback ktor version in native sample 2023-04-18 11:31:28 +06:00
4e3c186952 update dependencies 2023-04-18 03:27:56 +06:00
8fdf715419 Update build.yml 2023-04-04 09:57:28 +06:00
fca8704cec Update build.yml 2023-04-04 09:56:41 +06:00
bf499ee780 Update gradle.properties 2023-04-04 01:45:15 +06:00
9b10749411 update dependencies and other attributes 2023-04-04 01:02:18 +06:00
d3cb8a32ef add partially working native sample 2023-04-04 01:01:22 +06:00
0f0ad5a1af Update gradle.properties 2023-03-18 19:24:40 +06:00
c3bc55a15c Merge pull request #200 from InsanusMokrassar/7.0.0
7.0.0
2023-03-11 23:18:32 +06:00
23 changed files with 378 additions and 55 deletions

View File

@@ -8,6 +8,9 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: |
sudo apt install -y libcurl4-openssl-dev
- name: Set up JDK 11
uses: actions/setup-java@v1
with:

View File

@@ -1,16 +1,5 @@
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.chat.forum.closeForumTopic
import dev.inmo.tgbotapi.extensions.api.chat.forum.createForumTopic
import dev.inmo.tgbotapi.extensions.api.chat.forum.deleteForumTopic
import dev.inmo.tgbotapi.extensions.api.chat.forum.reopenForumTopic
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviour
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onForumTopicClosed
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.CustomEmojiId
import dev.inmo.tgbotapi.types.ForumTopic
import kotlinx.coroutines.delay
/**
* This is one of the most easiest bot - it will just print information about itself

View File

@@ -0,0 +1,9 @@
# InlineQueriesBot
This bot will form the inline queries for you. For that feature you should explicitly enable inline queries in bot settings
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

View File

@@ -0,0 +1,56 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.multiplatform"
}
apply plugin: 'application'
mainClassName="InlineQueriesBotKt"
kotlin {
def hostOs = System.getProperty("os.name")
def isMingwX64 = hostOs.startsWith("Windows")
def nativeTarget
if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries { executable() } }
else if (isMingwX64) nativeTarget = mingwX64("native") { binaries { executable() } }
else throw new GradleException("Host OS is not supported in Kotlin/Native.")
jvm()
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api "dev.inmo:tgbotapi:$telegram_bot_api_version"
}
}
nativeMain {
dependencies {
def engine
if (hostOs == "Linux") engine = "curl"
else if (isMingwX64) engine = "winhttp"
else throw new GradleException("Host OS is not supported in Kotlin/Native.")
api "io.ktor:ktor-client-$engine:$ktor_version"
}
}
}
}
dependencies {
implementation 'io.ktor:ktor-client-logging-jvm:2.3.0'
}

View File

@@ -0,0 +1,67 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.answers.answer
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.telegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onBaseInlineQuery
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onDeepLink
import dev.inmo.tgbotapi.requests.answers.InlineQueryResultsButton
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent
import dev.inmo.tgbotapi.types.inlineQueryAnswerResultsLimit
import dev.inmo.tgbotapi.utils.buildEntities
/**
* Thi bot will create inline query answers. You
* should enable inline queries in bot settings
*/
suspend fun doInlineQueriesBot(token: String) {
val bot = telegramBot(token)
bot.buildBehaviourWithLongPolling(
defaultExceptionsHandler = { it.printStackTrace() },
) {
onBaseInlineQuery {
val page = it.offset.toIntOrNull() ?: 0
val results = (0 until inlineQueryAnswerResultsLimit.last).map {
(page * inlineQueryAnswerResultsLimit.last) + it
}
answer(
it,
results = results.map { resultNumber ->
val resultAsString = resultNumber.toString()
InlineQueryResultArticle(
resultAsString,
"Title $resultNumber",
InputTextMessageContent(
buildEntities {
+"Result text of " + resultNumber.toString() + " result:\n"
+it.query
}
),
description = "Description of $resultNumber result"
)
},
cachedTime = 0,
isPersonal = true,
button = InlineQueryResultsButton.Start(
"Text of button with page $page",
"deep_link_for_page_$page"
),
nextOffset = (page + 1).toString()
)
}
onDeepLink { (message, deepLink) ->
reply(message, deepLink)
}
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
println(getMe())
}.join()
}

View File

@@ -0,0 +1,5 @@
import dev.inmo.micro_utils.common.MPPFile
suspend fun main(args: Array<String>) {
doInlineQueriesBot(args.first())
}

View File

@@ -0,0 +1,7 @@
import kotlinx.coroutines.runBlocking
fun main(args: Array<String>) {
runBlocking {
doInlineQueriesBot(args.first())
}
}

View File

@@ -4,12 +4,17 @@ 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.edit
import dev.inmo.tgbotapi.extensions.api.edit.editMessageText
import dev.inmo.tgbotapi.extensions.api.edit.reply_markup.editMessageReplyMarkup
import dev.inmo.tgbotapi.extensions.api.edit.text.editMessageText
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.types.buttons.*
import dev.inmo.tgbotapi.extensions.utils.withContent
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.utils.*
import kotlinx.coroutines.*
@@ -55,6 +60,16 @@ fun InlineKeyboardBuilder.includePageButtons(page: Int, count: Int) {
dataButton(">>", "$count $count")
}
}
row {
inlineQueryInChosenChatButton(
"Send somebody page",
query = "$page $count",
allowUsers = true,
allowBots = true,
allowGroups = true,
allowChannels = true,
)
}
}
suspend fun activateKeyboardsBot(
@@ -71,9 +86,7 @@ suspend fun activateKeyboardsBot(
reply(
message,
replyMarkup = inlineKeyboard {
row {
includePageButtons(1, numberOfPages)
}
includePageButtons(1, numberOfPages)
}
) {
regular("Your inline keyboard with $numberOfPages pages")
@@ -92,15 +105,48 @@ suspend fun activateKeyboardsBot(
return@onMessageDataCallbackQuery
},
replyMarkup = inlineKeyboard {
row {
includePageButtons(page, count)
}
includePageButtons(page, count)
}
) {
regular("This is $page of $count")
}
answer(it)
}
onInlineMessageIdDataCallbackQuery {
val (page, count) = it.data.parsePageAndCount() ?: it.let {
answer(it, "Unsupported data :(")
return@onInlineMessageIdDataCallbackQuery
}
editMessageText(
it.inlineMessageId,
replyMarkup = inlineKeyboard {
includePageButtons(page, count)
}
) {
regular("This is $page of $count")
}
answer(it)
}
onBaseInlineQuery {
val page = it.query.takeWhile { it.isDigit() }.toIntOrNull() ?: return@onBaseInlineQuery
val count = it.query.removePrefix(page.toString()).dropWhile { !it.isDigit() }.takeWhile { it.isDigit() }.toIntOrNull() ?: return@onBaseInlineQuery
answer(
it,
results = listOf(
InlineQueryResultArticle(
it.query,
"Send buttons",
InputTextMessageContent("It is sent via inline mode inline buttons"),
replyMarkup = inlineKeyboard {
includePageButtons(page, count)
}
)
)
)
}
onUnhandledCommand {
reply(

View File

@@ -4,6 +4,8 @@ This repository contains several examples of simple bots which are using Telegra
## How to use this repository
***TO RUN NATIVE TARGETS ON LINUX YOU SHOULD INSTALL CURL LIBRARY. FOR EXAMPLE: `sudo apt install libcurl4-gnutls-dev`***
This repository contains several important things:
* Example subprojects

View File

@@ -8,14 +8,45 @@ buildscript {
}
}
apply plugin: 'kotlin'
plugins {
id "org.jetbrains.kotlin.multiplatform"
}
apply plugin: 'application'
mainClassName="RandomFileSenderBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
kotlin {
def hostOs = System.getProperty("os.name")
def isMingwX64 = hostOs.startsWith("Windows")
def nativeTarget
if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries { executable() } }
else if (isMingwX64) nativeTarget = mingwX64("native") { binaries { executable() } }
else throw new GradleException("Host OS is not supported in Kotlin/Native.")
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
jvm()
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api "dev.inmo:tgbotapi:$telegram_bot_api_version"
}
}
nativeMain {
dependencies {
def engine
if (hostOs == "Linux") engine = "curl"
else if (isMingwX64) engine = "winhttp"
else throw new GradleException("Host OS is not supported in Kotlin/Native.")
api "io.ktor:ktor-client-$engine:$ktor_version"
}
}
}
}

View File

@@ -1,23 +1,25 @@
import dev.inmo.micro_utils.common.MPPFile
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.api.telegramBot
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
private const val command = "send_file"
expect fun pickFile(currentRoot: MPPFile): MPPFile?
/**
* This bot will send files inside of working directory OR from directory in the second argument.
* You may send /send_file command to this bot to get random file from the directory OR
@@ -25,19 +27,10 @@ private const val command = "send_file"
* /send_file and `/send_file 1` will have the same effect - bot will send one random file.
* But if you will send `/send_file 5` it will choose 5 random files and send them as group
*/
suspend fun main(args: Array<String>) {
val botToken = args.first()
val directoryOrFile = args.getOrNull(1) ?.let { File(it) } ?: File("")
suspend fun doRandomFileSenderBot(token: String, folder: MPPFile) {
val bot = telegramBot(token)
fun pickFile(currentRoot: File = directoryOrFile): File? {
if (currentRoot.isFile) {
return currentRoot
} else {
return pickFile(currentRoot.listFiles() ?.takeIf { it.isNotEmpty() } ?.random() ?: return null)
}
}
suspend fun TelegramBot.sendFiles(chat: Chat, files: List<File>) {
suspend fun TelegramBot.sendFiles(chat: Chat, files: List<MPPFile>) {
when (files.size) {
1 -> sendDocument(
chat.id,
@@ -52,8 +45,6 @@ suspend fun main(args: Array<String>) {
}
}
val bot = telegramBot(botToken)
bot.buildBehaviourWithLongPolling (defaultExceptionsHandler = { it.printStackTrace() }) {
onCommandWithArgs(command) { message, args ->
@@ -62,10 +53,10 @@ suspend fun main(args: Array<String>) {
var sent = false
var left = count
val chosen = mutableListOf<File>()
val chosen = mutableListOf<MPPFile>()
while (left > 0) {
val picked = pickFile() ?.takeIf { it.filesize > 0 } ?: continue
val picked = pickFile(folder) ?.takeIf { it.filesize > 0 } ?: continue
chosen.add(picked)
left--
if (chosen.size >= mediaCountInMediaGroup.last) {

View File

@@ -0,0 +1,10 @@
import dev.inmo.micro_utils.common.MPPFile
import java.io.File
actual fun pickFile(currentRoot: MPPFile): File? {
if (currentRoot.isFile) {
return currentRoot
} else {
return pickFile(currentRoot.listFiles() ?.takeIf { it.isNotEmpty() } ?.random() ?: return null)
}
}

View File

@@ -0,0 +1,5 @@
import dev.inmo.micro_utils.common.MPPFile
suspend fun main(args: Array<String>) {
doRandomFileSenderBot(args.first(), MPPFile(args.getOrNull(1) ?: ""))
}

View File

@@ -0,0 +1,10 @@
import dev.inmo.micro_utils.common.MPPFile
import okio.FileSystem
actual fun pickFile(currentRoot: MPPFile): MPPFile? {
if (FileSystem.SYSTEM.exists(currentRoot) && FileSystem.SYSTEM.listOrNull(currentRoot) == null) {
return currentRoot
} else {
return pickFile(FileSystem.SYSTEM.list(currentRoot).takeIf { it.isNotEmpty() } ?.random() ?: return null)
}
}

View File

@@ -0,0 +1,8 @@
import kotlinx.coroutines.runBlocking
import okio.Path.Companion.toPath
fun main(args: Array<String>) {
runBlocking {
doRandomFileSenderBot(args.first(), args.getOrNull(1) ?.toPath() ?: "".toPath())
}
}

View File

@@ -20,6 +20,8 @@ kotlin {
browser()
binaries.executable()
}
linuxX64()
mingwX64()
sourceSets {
commonMain {

View File

@@ -15,11 +15,7 @@ suspend fun activateResenderBot(
token: String,
print: (Any) -> Unit
) {
val bot = telegramBot(token)
print(bot.getMe())
bot.buildBehaviourWithLongPolling(CoroutineScope(currentCoroutineContext() + SupervisorJob())) {
telegramBotWithBehaviourAndLongPolling(token, scope = CoroutineScope(currentCoroutineContext() + SupervisorJob())) {
onContentMessage(
subcontextUpdatesFilter = MessageFilterByChat,
) {
@@ -43,5 +39,6 @@ suspend fun activateResenderBot(
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.join()
print(bot.getMe())
}.second.join()
}

View File

@@ -0,0 +1,46 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
plugins {
id "org.jetbrains.kotlin.multiplatform"
}
kotlin {
def hostOs = System.getProperty("os.name")
def isMingwX64 = hostOs.startsWith("Windows")
def nativeTarget
if (hostOs == "Linux") nativeTarget = linuxX64("native") { binaries { executable() } }
else if (isMingwX64) nativeTarget = mingwX64("native") { binaries { executable() } }
else throw new GradleException("Host OS is not supported in Kotlin/Native.")
sourceSets {
commonMain {
dependencies {
implementation kotlin('stdlib')
api project(":ResenderBot:ResenderBotLib")
}
}
nativeMain {
dependencies {
def engine
if (hostOs == "Linux") engine = "curl"
else if (isMingwX64) engine = "winhttp"
else throw new GradleException("Host OS is not supported in Kotlin/Native.")
api "io.ktor:ktor-client-$engine:$ktor_version"
}
}
}
}

View File

@@ -0,0 +1,9 @@
import kotlinx.coroutines.runBlocking
fun main(vararg args: String) {
runBlocking {
activateResenderBot(args.first()) {
println(it)
}
}
}

View File

@@ -1,13 +1,16 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.ktor.server.createKtorServer
import dev.inmo.tgbotapi.extensions.api.answers.answer
import dev.inmo.tgbotapi.extensions.api.answers.answerInlineQuery
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.telegramBot
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.formatting.makeTelegramStartattach
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.requests.answers.InlineQueryResultsButton
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.InlineQueries.InlineQueryResult.InlineQueryResultArticle
import dev.inmo.tgbotapi.types.InlineQueries.InputMessageContent.InputTextMessageContent
@@ -43,14 +46,13 @@ suspend fun main(vararg args: String) {
val bot = telegramBot(telegramBotAPIUrlsKeeper)
createKtorServer(
"0.0.0.0",
8080,
args.getOrNull(2) ?.toIntOrNull() ?: 8080,
additionalEngineEnvironmentConfigurator = {
parentCoroutineContext += Dispatchers.IO
}
) {
routing {
static {
files(File("WebApp/build/distributions"))
staticFiles("", File("WebApp/build/distributions")) {
default("WebApp/build/distributions/index.html")
}
post("inline") {
@@ -74,6 +76,7 @@ suspend fun main(vararg args: String) {
bot.buildBehaviourWithLongPolling(
defaultExceptionsHandler = { it.printStackTrace() }
) {
val me = getMe()
onCommand("reply_markup") {
reply(
it,
@@ -98,6 +101,27 @@ suspend fun main(vararg args: String) {
)
}
onCommand("attachment_menu") {
reply(
it,
"Button",
replyMarkup = inlineKeyboard {
row {
webAppButton("Open WebApp", WebAppInfo(args[1]))
}
}
)
}
onBaseInlineQuery {
answerInlineQuery(
it,
button = InlineQueryResultsButton.invoke(
"Open webApp",
WebAppInfo(args[1])
)
)
}
onUnhandledCommand {
reply(
it,
@@ -107,6 +131,9 @@ suspend fun main(vararg args: String) {
}
)
}
onWriteAccessAllowed(initialFilter = { it.chatEvent.webAppName != null }) {
send(it.chat, "Thanks for adding ${it.chatEvent.webAppName} to the attachment menu")
}
setMyCommands(
BotCommand("reply_markup", "Use to get reply markup keyboard with web app trigger"),
BotCommand("inline", "Use to get inline keyboard with web app trigger"),

View File

@@ -1,11 +1,11 @@
kotlin.code.style=official
org.gradle.parallel=true
# Due to parallel compilation project require next amount of memory on full build
org.gradle.jvmargs=-Xmx1g
org.gradle.jvmargs=-Xmx2g
kotlin_version=1.8.10
telegram_bot_api_version=7.0.0
micro_utils_version=0.17.5
kotlin_version=1.8.20
telegram_bot_api_version=7.1.0
micro_utils_version=0.17.8
serialization_version=1.5.0
ktor_version=2.2.4
ktor_version=2.3.0

View File

@@ -12,6 +12,7 @@ include ":FilesLoaderBot"
include ":ResenderBot:ResenderBotLib"
include ":ResenderBot:jvm_launcher"
include ":ResenderBot:native_launcher"
include ":KeyboardsBot:KeyboardsBotLib"
include ":KeyboardsBot:jvm_launcher"
@@ -36,3 +37,5 @@ include ":RightsChangerBot"
include ":LiveLocationsBot"
include ":StickerSetHandler"
include ":InlineQueriesBot"