diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 65f648c..69d1cb8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -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: diff --git a/README.md b/README.md index 7256736..26ea126 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/RandomFileSenderBot/build.gradle b/RandomFileSenderBot/build.gradle index 946ccfc..70327df 100644 --- a/RandomFileSenderBot/build.gradle +++ b/RandomFileSenderBot/build.gradle @@ -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" + } + } + } } + diff --git a/RandomFileSenderBot/src/main/kotlin/RandomFileSenderBot.kt b/RandomFileSenderBot/src/commonMain/kotlin/Bot.kt similarity index 77% rename from RandomFileSenderBot/src/main/kotlin/RandomFileSenderBot.kt rename to RandomFileSenderBot/src/commonMain/kotlin/Bot.kt index 302200e..671d843 100644 --- a/RandomFileSenderBot/src/main/kotlin/RandomFileSenderBot.kt +++ b/RandomFileSenderBot/src/commonMain/kotlin/Bot.kt @@ -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) { - 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) { + suspend fun TelegramBot.sendFiles(chat: Chat, files: List) { when (files.size) { 1 -> sendDocument( chat.id, @@ -52,8 +45,6 @@ suspend fun main(args: Array) { } } - val bot = telegramBot(botToken) - bot.buildBehaviourWithLongPolling (defaultExceptionsHandler = { it.printStackTrace() }) { onCommandWithArgs(command) { message, args -> @@ -62,10 +53,10 @@ suspend fun main(args: Array) { var sent = false var left = count - val chosen = mutableListOf() + val chosen = mutableListOf() 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) { diff --git a/RandomFileSenderBot/src/commonMain/kotlin/PickFile.kt b/RandomFileSenderBot/src/commonMain/kotlin/PickFile.kt new file mode 100644 index 0000000..e69de29 diff --git a/RandomFileSenderBot/src/jvmMain/kotlin/ActualPickFile.kt b/RandomFileSenderBot/src/jvmMain/kotlin/ActualPickFile.kt new file mode 100644 index 0000000..f453694 --- /dev/null +++ b/RandomFileSenderBot/src/jvmMain/kotlin/ActualPickFile.kt @@ -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) + } +} diff --git a/RandomFileSenderBot/src/jvmMain/kotlin/RandomFileSenderBot.kt b/RandomFileSenderBot/src/jvmMain/kotlin/RandomFileSenderBot.kt new file mode 100644 index 0000000..52d0e06 --- /dev/null +++ b/RandomFileSenderBot/src/jvmMain/kotlin/RandomFileSenderBot.kt @@ -0,0 +1,5 @@ +import dev.inmo.micro_utils.common.MPPFile + +suspend fun main(args: Array) { + doRandomFileSenderBot(args.first(), MPPFile(args.getOrNull(1) ?: "")) +} diff --git a/RandomFileSenderBot/src/nativeMain/kotlin/ActualPickFile.kt b/RandomFileSenderBot/src/nativeMain/kotlin/ActualPickFile.kt new file mode 100644 index 0000000..1b6386d --- /dev/null +++ b/RandomFileSenderBot/src/nativeMain/kotlin/ActualPickFile.kt @@ -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) + } +} diff --git a/RandomFileSenderBot/src/nativeMain/kotlin/RandomFileSenderBot.kt b/RandomFileSenderBot/src/nativeMain/kotlin/RandomFileSenderBot.kt new file mode 100644 index 0000000..4ef7710 --- /dev/null +++ b/RandomFileSenderBot/src/nativeMain/kotlin/RandomFileSenderBot.kt @@ -0,0 +1,8 @@ +import kotlinx.coroutines.runBlocking +import okio.Path.Companion.toPath + +fun main(args: Array) { + runBlocking { + doRandomFileSenderBot(args.first(), args.getOrNull(1) ?.toPath() ?: "".toPath()) + } +} diff --git a/ResenderBot/ResenderBotLib/build.gradle b/ResenderBot/ResenderBotLib/build.gradle index 1d40c3e..0530296 100644 --- a/ResenderBot/ResenderBotLib/build.gradle +++ b/ResenderBot/ResenderBotLib/build.gradle @@ -20,6 +20,8 @@ kotlin { browser() binaries.executable() } + linuxX64() + mingwX64() sourceSets { commonMain { diff --git a/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt b/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt index cec4079..fe604d8 100644 --- a/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt +++ b/ResenderBot/ResenderBotLib/src/commonMain/kotlin/ResenderBot.kt @@ -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() } diff --git a/ResenderBot/native_launcher/build.gradle b/ResenderBot/native_launcher/build.gradle new file mode 100644 index 0000000..fa67557 --- /dev/null +++ b/ResenderBot/native_launcher/build.gradle @@ -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" + } + } + } +} + diff --git a/ResenderBot/native_launcher/src/nativeMain/kotlin/ResenderBot.kt b/ResenderBot/native_launcher/src/nativeMain/kotlin/ResenderBot.kt new file mode 100644 index 0000000..29e16b1 --- /dev/null +++ b/ResenderBot/native_launcher/src/nativeMain/kotlin/ResenderBot.kt @@ -0,0 +1,9 @@ +import kotlinx.coroutines.runBlocking + +fun main(vararg args: String) { + runBlocking { + activateResenderBot(args.first()) { + println(it) + } + } +} diff --git a/WebApp/src/jvmMain/kotlin/WebAppServer.kt b/WebApp/src/jvmMain/kotlin/WebAppServer.kt index 37acaef..0b800bf 100644 --- a/WebApp/src/jvmMain/kotlin/WebAppServer.kt +++ b/WebApp/src/jvmMain/kotlin/WebAppServer.kt @@ -43,14 +43,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") { diff --git a/gradle.properties b/gradle.properties index 699bec0..823884b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -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.1 -micro_utils_version=0.17.5 +kotlin_version=1.8.20 +telegram_bot_api_version=7.0.2 +micro_utils_version=0.17.8 serialization_version=1.5.0 -ktor_version=2.2.4 +ktor_version=2.3.0 diff --git a/settings.gradle b/settings.gradle index dde1eba..a665bb3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,6 +12,7 @@ include ":FilesLoaderBot" include ":ResenderBot:ResenderBotLib" include ":ResenderBot:jvm_launcher" +include ":ResenderBot:native_launcher" include ":KeyboardsBot:KeyboardsBotLib" include ":KeyboardsBot:jvm_launcher"