diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d62294..fd5fef9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,4 +16,4 @@ jobs: with: java-version: 17 - name: Build with Gradle - run: ./gradlew build + run: ./gradlew build --no-daemon diff --git a/StarTransactionsBot/README.md b/StarTransactionsBot/README.md new file mode 100644 index 0000000..13b72ef --- /dev/null +++ b/StarTransactionsBot/README.md @@ -0,0 +1,9 @@ +# CustomBot + +This bot basically have no any useful behaviour, but you may customize it as a playground + +## Launch + +```bash +../gradlew run --args="BOT_TOKEN" +``` diff --git a/StarTransactionsBot/build.gradle b/StarTransactionsBot/build.gradle new file mode 100644 index 0000000..5f15acb --- /dev/null +++ b/StarTransactionsBot/build.gradle @@ -0,0 +1,21 @@ +buildscript { + repositories { + mavenCentral() + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +apply plugin: 'kotlin' +apply plugin: 'application' + +mainClassName="StarTransactionsBotKt" + + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" + + implementation "dev.inmo:tgbotapi:$telegram_bot_api_version" +} diff --git a/StarTransactionsBot/src/main/kotlin/StarTransactionsBot.kt b/StarTransactionsBot/src/main/kotlin/StarTransactionsBot.kt new file mode 100644 index 0000000..92707ca --- /dev/null +++ b/StarTransactionsBot/src/main/kotlin/StarTransactionsBot.kt @@ -0,0 +1,131 @@ +import dev.inmo.kslog.common.KSLog +import dev.inmo.kslog.common.LogLevel +import dev.inmo.kslog.common.defaultMessageFormatter +import dev.inmo.kslog.common.setDefaultKSLog +import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions +import dev.inmo.tgbotapi.extensions.api.answers.answer +import dev.inmo.tgbotapi.extensions.api.answers.payments.answerPreCheckoutQueryOk +import dev.inmo.tgbotapi.extensions.api.bot.getMe +import dev.inmo.tgbotapi.extensions.api.edit.edit +import dev.inmo.tgbotapi.extensions.api.get.getStarTransactions +import dev.inmo.tgbotapi.extensions.api.send.reply +import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.command +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onMessageDataCallbackQuery +import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onPreCheckoutQuery +import dev.inmo.tgbotapi.extensions.utils.extensions.sameChat +import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton +import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard +import dev.inmo.tgbotapi.extensions.utils.types.buttons.inlineKeyboard +import dev.inmo.tgbotapi.extensions.utils.types.buttons.payButton +import dev.inmo.tgbotapi.extensions.utils.withContentOrNull +import dev.inmo.tgbotapi.types.RawChatId +import dev.inmo.tgbotapi.types.UserId +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.types.message.content.TextContent +import dev.inmo.tgbotapi.types.message.textsources.TextSource +import dev.inmo.tgbotapi.types.message.textsources.TextSourcesList +import dev.inmo.tgbotapi.types.payments.LabeledPrice +import dev.inmo.tgbotapi.types.payments.stars.StarTransaction +import dev.inmo.tgbotapi.utils.* +import kotlinx.coroutines.* + +/** + * 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) { + val botToken = args.first() + val adminUserId = args.getOrNull(1) ?.toLongOrNull() ?.let(::RawChatId) ?.let(::UserId) ?: error("Pass user-admin for full access to the bot") + + val isDebug = args.any { it == "debug" } + val isTestServer = args.any { it == "testServer" } + + if (isDebug) { + setDefaultKSLog( + KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? -> + println(defaultMessageFormatter(level, tag, message, throwable)) + } + ) + } + + telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO), testServer = isTestServer) { + val me = getMe() + + val payload = "sample payload" + command("start") { + reply( + it, + price = LabeledPrice("1", 1L), + title = "Sample", + description = "Sample description", + payload = payload, + replyMarkup = flatInlineKeyboard { + payButton("Pay") + }, + ) + } + + onPreCheckoutQuery(initialFilter = { it.invoicePayload == payload }) { + answerPreCheckoutQueryOk(it) + } + + val transactionsDataPrefix = "getStarTransactions" + fun buildTransactionsData(offset: Int, limit: Int = 10) = "$transactionsDataPrefix $offset $limit" + fun parseTransactionsData(data: String): Pair = data.split(" ").drop(1).let { + it.first().toInt() to it.last().toInt() + } + suspend fun buildStarTransactionsPage(offset: Int, limit: Int = 10): Pair { + val transactions = getStarTransactions(offset, limit) + return buildEntities { + transactions.transactions.forEach { + regular("Transaction Id: ") + bold(it.id.string) + "\n" + regular("Date: ") + bold(it.date.asDate.toStringDefault()) + "\n" + regular("Amount: ") + bold(it.amount.toString()) + "\n" + when (it) { + is StarTransaction.Incoming -> { + regular("Type: ") + bold("incoming") + "\n" + regular("Partner: ") + bold(it.partner.type) + "\n" + } + is StarTransaction.Outgoing -> { + regular("Type: ") + bold("outgoing") + "\n" + regular("Partner: ") + bold(it.partner.type) + "\n" + } + is StarTransaction.Unknown -> { + regular("Type: ") + bold("unknown") + "\n" + regular("Partner: ") + bold(it.partner.type) + "\n" + } + } + } + } to inlineKeyboard { + row { + val prevOffset = (offset - limit).coerceAtLeast(0) + if (prevOffset < offset) { + dataButton("<", buildTransactionsData(prevOffset, limit)) + } + val nextOffset = (offset + limit) + dataButton(">", buildTransactionsData(nextOffset, limit)) + } + } + } + + onCommand("transactions", initialFilter = { it.sameChat(adminUserId) }) { + val (text, keyboard) = buildStarTransactionsPage(0) + + reply(it, text, replyMarkup = keyboard) + } + + onMessageDataCallbackQuery(Regex("$transactionsDataPrefix \\d+ \\d+")) { + val (offset, limit) = parseTransactionsData(it.data) + val (text, keyboard) = buildStarTransactionsPage(offset, limit) + edit( + it.message.withContentOrNull() ?: return@onMessageDataCallbackQuery, + text, + replyMarkup = keyboard, + ) + } + + allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) } + }.second.join() +} diff --git a/gradle.properties b/gradle.properties index 378fc01..cfd1d5e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,10 +2,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=-Xmx2344m +kotlin.daemon.jvmargs=-Xmx2g -Xms500m kotlin_version=1.9.23 -telegram_bot_api_version=14.1.0 +telegram_bot_api_version=15.0.0 micro_utils_version=0.21.0 serialization_version=1.6.3 ktor_version=2.3.11 diff --git a/settings.gradle b/settings.gradle index ba16eb9..637922f 100644 --- a/settings.gradle +++ b/settings.gradle @@ -50,4 +50,6 @@ include ":BoostsInfoBot" include ":BusinessConnectionsBot" +include ":StarTransactionsBot" + include ":CustomBot"