Compare commits

..

45 Commits

Author SHA1 Message Date
c7068182e3 make initialization of web app server more verbose 2024-06-01 20:31:51 +06:00
a5740e6315 change telegram bot api version to release one 2024-06-01 13:37:31 +06:00
3a35995bc7 several fixes and improvements 2024-06-01 13:19:05 +06:00
41fc5a9a4c Merge pull request #264 from InsanusMokrassar/13.0.0
13.0.0
2024-05-10 20:56:51 +06:00
79700f24e5 small updates 2024-05-10 19:53:21 +06:00
73c1af15b3 add CustomBot 2024-05-10 18:46:47 +06:00
aa9ca976f0 update polls to include showing of polls question and explanation text sources passing 2024-05-10 16:45:47 +06:00
238533a350 update polls sample 2024-05-10 16:35:07 +06:00
6f2a8bb0be Update gradle.properties 2024-04-26 10:45:55 +06:00
99232b53d7 Merge pull request #260 from InsanusMokrassar/12.0.0
12.0.0
2024-04-21 00:25:25 +06:00
30358f7d2f Merge pull request #258 from InsanusMokrassar/11.0.0
11.0.0
2024-04-21 00:24:07 +06:00
11a97c520a update 2024-04-19 19:34:48 +06:00
d6a6ad8d37 improvements in samples 2024-04-19 18:10:46 +06:00
c04a367375 fixes and improvements 2024-04-18 20:06:59 +06:00
b660bf5f42 upgrade to support new ktgbotapi 2024-04-18 17:03:53 +06:00
57dd2380cd fix up to 11.0.0 2024-03-18 13:46:15 +06:00
fbb41c7714 start update up to tgbotapi 11.0.0 2024-03-18 12:32:15 +06:00
9170d30b2f Update gradle-wrapper.properties 2024-03-02 00:08:22 +06:00
2f3fd2e53b Update gradle.properties 2024-03-02 00:05:34 +06:00
88697fb5a6 Merge pull request #253 from InsanusMokrassar/10.1.0
10.1.0
2024-02-17 13:38:13 +06:00
578d00cac6 Update gradle.properties 2024-02-17 13:37:50 +06:00
13ecb3f0df update dependencies 2024-02-17 01:51:32 +06:00
a008d861da Merge pull request #248 from InsanusMokrassar/10.0.0
10.0.0
2024-01-12 14:57:51 +06:00
6f3766dff6 fixes in samples and update up to 10.0.0 2024-01-12 14:23:27 +06:00
fda366d820 add boosts sample 2024-01-12 00:49:59 +06:00
578887ac63 update userChatShared bot 2024-01-12 00:29:48 +06:00
6a04b3980c improvements in users requests 2024-01-10 23:10:28 +06:00
984ffb8bae update dependencies 2024-01-10 16:47:31 +06:00
2bcec6487d fixes 2024-01-09 18:30:54 +06:00
a5e3bfc3fe update dependency of tgbotapi 2024-01-09 18:05:30 +06:00
941afd0902 update LinkPreviewsBot 2024-01-09 17:57:49 +06:00
94c014b308 add LinkPreviewsBot 2024-01-09 17:56:33 +06:00
538cc9d44f improvement of ReactionsInfoBot 2024-01-09 13:55:35 +06:00
cb29726487 add showing of reactions count in println 2024-01-09 13:06:18 +06:00
262ef26239 updates and fixes 2024-01-08 19:23:06 +06:00
41efe5e141 update tgbotapi version 2024-01-08 15:55:05 +06:00
05e289975a add reactions info bot 2024-01-08 15:46:23 +06:00
753d686fab build fixes 2024-01-08 13:21:41 +06:00
281243c7e5 update dependencies 2024-01-08 10:14:08 +06:00
3609ae6bc2 Merge pull request #240 from InsanusMokrassar/renovate/serialization_version
Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.6.2
2023-12-25 09:00:04 +06:00
4f128f3421 Merge pull request #239 from InsanusMokrassar/renovate/io.ktor-ktor-client-logging-jvm-2.x
Update dependency io.ktor:ktor-client-logging-jvm to v2.3.7
2023-12-25 08:59:47 +06:00
ada6cd61d7 Merge pull request #247 from InsanusMokrassar/renovate/kotlin-monorepo
Update kotlin monorepo to v1.9.22
2023-12-25 08:59:28 +06:00
renovate[bot]
051d647004 Update kotlin monorepo to v1.9.22 2023-12-21 14:11:32 +00:00
renovate[bot]
d21606860a Update dependency io.ktor:ktor-client-logging-jvm to v2.3.7 2023-12-07 12:54:06 +00:00
renovate[bot]
93c0fcb5bd Update dependency org.jetbrains.kotlinx:kotlinx-serialization-json to v1.6.2 2023-11-30 16:56:11 +00:00
37 changed files with 1112 additions and 390 deletions

9
BoostsInfoBot/README.md Normal file
View File

@@ -0,0 +1,9 @@
# UserChatShared
Showing info about boosts
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

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="BoostsInfoKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,65 @@
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.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.get.getUserChatBoosts
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatBoostUpdated
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.types.chat.member.ChatCommonAdministratorRights
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.utils.regular
import korlibs.time.DateFormat
import korlibs.time.format
suspend fun main(args: Array<String>) {
val isDebug = args.getOrNull(1) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val requestChatId = RequestId(1)
val bot = telegramBot(args.first())
bot.buildBehaviourWithLongPolling (defaultExceptionsHandler = { it.printStackTrace() }) {
onChatBoostUpdated {
println(it)
}
onCommand("start") {
reply(
it,
replyMarkup = flatReplyKeyboard {
requestChannelButton(
"Click me :)",
requestChatId,
botIsMember = true
)
}
) {
regular("Select chat to get know about your boosts")
}
}
onChatShared(initialFilter = { it.chatEvent.requestId == requestChatId }) {
val boosts = getUserChatBoosts(it.chatEvent.chatId, it.chat.id)
reply(
it
) {
boosts.boosts.forEach {
regular("Boost added: ${DateFormat.FORMAT1.format(it.addDate.asDate)}; Boost expire: ${DateFormat.FORMAT1.format(it.expirationDate.asDate)}; Unformatted: $it") + "\n"
}
}
}
}.join()
}

View File

@@ -0,0 +1,9 @@
# BusinessConnectionBotBot
When bot connected or disconnected to the business chat, it will notify this chat
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

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="BusinessConnectionsBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,85 @@
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.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.get.getBusinessConnection
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.ifBusinessContentMessage
import dev.inmo.tgbotapi.types.ChatId
import dev.inmo.tgbotapi.types.business_connection.BusinessConnectionId
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
suspend fun main(args: Array<String>) {
val botToken = args.first()
val isDebug = args.getOrNull(1) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val businessConnectionsChats = mutableMapOf<BusinessConnectionId, ChatId>()
val businessConnectionsChatsMutex = Mutex()
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
val me = getMe()
println(me)
onBusinessConnectionEnabled {
businessConnectionsChatsMutex.withLock {
businessConnectionsChats[it.id] = it.userChatId
}
send(it.userChatId, "Business connection ${it.businessConnectionId.string} has been enabled")
}
onBusinessConnectionDisabled {
businessConnectionsChatsMutex.withLock {
businessConnectionsChats.remove(it.id)
}
send(it.userChatId, "Business connection ${it.businessConnectionId.string} has been disabled")
}
onContentMessage {
it.ifBusinessContentMessage {
val sent = execute(it.content.createResend(it.from.id))
if (it.sentByBusinessConnectionOwner) {
reply(sent, "You have sent this message to the ${it.businessConnectionId.string} related chat")
} else {
reply(sent, "User have sent this message to you in the ${it.businessConnectionId.string} related chat")
}
}
}
onEditedContentMessage {
it.ifBusinessContentMessage {
val sent = execute(it.content.createResend(it.from.id))
if (it.sentByBusinessConnectionOwner) {
reply(sent, "You have edited this message in the ${it.businessConnectionId.string} related chat")
} else {
reply(sent, "User have edited this message to you in the ${it.businessConnectionId.string} related chat")
}
}
}
onBusinessMessagesDeleted {
var businessConnectionOwnerChat = businessConnectionsChatsMutex.withLock {
businessConnectionsChats[it.businessConnectionId]
}
if (businessConnectionOwnerChat == null) {
val businessConnection = getBusinessConnection(it.businessConnectionId)
businessConnectionsChatsMutex.withLock {
businessConnectionsChats[businessConnection.businessConnectionId] = businessConnection.userChatId
}
businessConnectionOwnerChat = businessConnection.userChatId
}
send(businessConnectionOwnerChat, "There are several removed messages in chat ${it.chat.id}: ${it.messageIds}")
}
}.second.join()
}

9
CustomBot/README.md Normal file
View File

@@ -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"
```

21
CustomBot/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="CustomBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,33 @@
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.bot.getMe
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.utils.PreviewFeature
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 isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
val me = getMe()
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) }
}.second.join()
}

View File

@@ -1,13 +1,16 @@
import dev.inmo.micro_utils.coroutines.AccumulatorFlow
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
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.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs
import dev.inmo.tgbotapi.extensions.utils.extensions.sameThread
import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.extensions.utils.textContentOrNull
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.IdChatIdentifier
import dev.inmo.tgbotapi.types.MessageThreadId
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
@@ -54,7 +57,8 @@ suspend fun main(args: Array<String>) {
val content = contentMessage.content
when {
content is TextContent && content.parseCommandsWithParams().keys.contains("stop") -> StopState(it.context)
content is TextContent && content.text == "/stop"
|| content is TextContent && content.parseCommandsWithArgs().keys.contains("stop") -> StopState(it.context)
else -> {
execute(content.createResend(it.context))
it
@@ -72,5 +76,17 @@ suspend fun main(args: Array<String>) {
) {
startChain(ExpectContentOrStopState(it.chat.id, it))
}
onContentMessage(
{
it.content.textContentOrNull() ?.text == "/start"
}
) {
startChain(ExpectContentOrStopState(it.chat.id, it.withContentOrNull() ?: return@onContentMessage))
}
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.second.join()
}

View File

@@ -5,6 +5,7 @@ import dev.inmo.kslog.common.filter.filtered
import dev.inmo.kslog.common.setDefaultKSLog
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
/**
@@ -12,13 +13,19 @@ import dev.inmo.tgbotapi.utils.DefaultKTgBotAPIKSLog
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.getOrNull(1) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
val bot = telegramBot(botToken)
println(bot.getMe())
val me = bot.getMe()
println(me)
println(bot.getChat(me))
}

View File

@@ -56,6 +56,10 @@ suspend fun main(vararg args: String) {
} ?: chat.title
}
}
is PreviewBusinessChat -> {
reply(message, "Hi, " + "${chat.original.firstName} ${chat.original.lastName} (as business chat :) )".textMentionMarkdownV2(chat.original.id), MarkdownV2)
return@onMentionWithAnyContent
}
is UnknownChatType -> "Unknown :(".escapeMarkdownV2Common()
}
reply(

View File

@@ -33,6 +33,6 @@ kotlin {
}
dependencies {
implementation 'io.ktor:ktor-client-logging-jvm:2.3.5'
implementation 'io.ktor:ktor-client-logging-jvm:2.3.7'
}

View File

@@ -9,6 +9,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onDeepLi
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.InlineQueryId
import dev.inmo.tgbotapi.types.inlineQueryAnswerResultsLimit
import dev.inmo.tgbotapi.utils.buildEntities
@@ -31,9 +32,9 @@ suspend fun doInlineQueriesBot(token: String) {
answer(
it,
results = results.map { resultNumber ->
val resultAsString = resultNumber.toString()
val inlineQueryId = InlineQueryId(resultNumber.toString())
InlineQueryResultArticle(
resultAsString,
inlineQueryId,
"Title $resultNumber",
InputTextMessageContent(
buildEntities {

View File

@@ -15,6 +15,7 @@ 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.InlineQueryId
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.utils.*
import kotlinx.coroutines.*
@@ -137,7 +138,7 @@ suspend fun activateKeyboardsBot(
it,
results = listOf(
InlineQueryResultArticle(
it.query,
InlineQueryId(it.query),
"Send buttons",
InputTextMessageContent("It is sent via inline mode inline buttons"),
replyMarkup = inlineKeyboard {

View File

@@ -0,0 +1,9 @@
# ReactionsInfoBot
This bot will resend messages with links with all variants of `LinkPreviewOptions`
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

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="LinkPreviewsBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,93 @@
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.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.copyMessage
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.send
import dev.inmo.tgbotapi.extensions.api.send.setMessageReaction
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionUpdatedByUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionsCountUpdated
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.textLinkTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.uRLTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.LinkPreviewOptions
import dev.inmo.tgbotapi.types.chat.ExtendedChat
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.message.content.TextedContent
import dev.inmo.tgbotapi.types.reactions.Reaction
import dev.inmo.tgbotapi.utils.customEmoji
import dev.inmo.tgbotapi.utils.regular
/**
* This bot will reply with the same
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.getOrNull(1) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val bot = telegramBot(botToken)
bot.buildBehaviourWithLongPolling {
onContentMessage {
val url = it.withContentOrNull<TextedContent>() ?.let {
it.content.textSources.firstNotNullOfOrNull {
it.textLinkTextSourceOrNull() ?.url ?: it.uRLTextSourceOrNull() ?.source
}
} ?: null.apply {
reply(it) {
regular("I am support only content with text contains url only")
}
} ?: return@onContentMessage
it.withContentOrNull<TextedContent>() ?.let {
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Disabled
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Large(url, showAboveText = true)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Large(url, showAboveText = false)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Small(url, showAboveText = true)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Small(url, showAboveText = false)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Default(url, showAboveText = true)
)
send(
it.chat,
it.content.textSources,
linkPreviewOptions = LinkPreviewOptions.Default(url, showAboveText = false)
)
}
}
}.join()
}

View File

@@ -1,33 +1,16 @@
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.EditLiveLocationInfo
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.edit.edit
import dev.inmo.tgbotapi.extensions.api.edit.location.live.stopLiveLocation
import dev.inmo.tgbotapi.extensions.api.handleLiveLocation
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitMessageDataCallbackQuery
import dev.inmo.tgbotapi.extensions.behaviour_builder.oneOf
import dev.inmo.tgbotapi.extensions.behaviour_builder.parallel
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onContentMessage
import dev.inmo.tgbotapi.extensions.utils.extensions.sameMessage
import dev.inmo.tgbotapi.extensions.utils.formatting.linkMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.formatting.textMentionMarkdownV2
import dev.inmo.tgbotapi.extensions.utils.ifFromChannelGroupContentMessage
import dev.inmo.tgbotapi.extensions.utils.types.buttons.dataButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.flatInlineKeyboard
import dev.inmo.tgbotapi.types.chat.*
import dev.inmo.tgbotapi.types.chat.GroupChat
import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.chat.SupergroupChat
import dev.inmo.tgbotapi.types.location.LiveLocation
import dev.inmo.tgbotapi.types.message.MarkdownV2
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
import dev.inmo.tgbotapi.types.message.content.LiveLocationContent
import dev.inmo.tgbotapi.types.message.content.LocationContent
import dev.inmo.tgbotapi.utils.PreviewFeature
import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
@@ -64,7 +47,7 @@ suspend fun main(vararg args: String) {
handleLiveLocation(
it.chat.id,
locationsFlow,
sentMessageFlow = FlowCollector { currentMessageState.emit(it) }
sentMessageFlow = FlowCollector { currentMessageState.emit(it) },
)
}

View File

@@ -1,33 +1,37 @@
import com.benasher44.uuid.uuid4
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.bot.getMe
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.*
import dev.inmo.tgbotapi.extensions.api.send.polls.sendQuizPoll
import dev.inmo.tgbotapi.extensions.api.send.polls.sendRegularPoll
import dev.inmo.tgbotapi.extensions.behaviour_builder.telegramBotWithBehaviourAndLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.extensions.utils.customEmojiTextSourceOrNull
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgsSources
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.ChatId
import dev.inmo.tgbotapi.types.IdChatIdentifier
import dev.inmo.tgbotapi.types.PollIdentifier
import dev.inmo.tgbotapi.types.*
import dev.inmo.tgbotapi.types.chat.*
import dev.inmo.tgbotapi.types.chat.GroupChat
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.types.polls.Poll
import dev.inmo.tgbotapi.types.polls.PollAnswer
import dev.inmo.tgbotapi.types.polls.PollOption
import dev.inmo.tgbotapi.types.polls.RegularPoll
import dev.inmo.tgbotapi.utils.PreviewFeature
import dev.inmo.tgbotapi.types.polls.*
import dev.inmo.tgbotapi.utils.*
import dev.inmo.tgbotapi.utils.extensions.escapeMarkdownV2Common
import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlin.random.Random
/**
* This bot will answer with anonymous or public poll and send message on
@@ -39,37 +43,114 @@ import kotlinx.coroutines.sync.withLock
@OptIn(PreviewFeature::class)
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
telegramBotWithBehaviourAndLongPolling(botToken, CoroutineScope(Dispatchers.IO)) {
val me = getMe()
val pollToChat = mutableMapOf<PollIdentifier, IdChatIdentifier>()
val pollToChat = mutableMapOf<PollId, IdChatIdentifier>()
val pollToChatMutex = Mutex()
onCommand("anonymous") {
onCommand("anonymous", requireOnlyCommandInMessage = false) {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "anonymous" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
val sentPoll = sendRegularPoll(
it.chat,
"Test regular anonymous poll",
it.chat.id,
buildEntities {
regular("Test regular anonymous poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
(1 .. 10).map {
it.toString()
InputPollOption {
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
},
isAnonymous = true,
replyToMessageId = it.messageId
replyParameters = ReplyParameters(it)
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
}
}
onCommand("public") {
onCommand("public", requireOnlyCommandInMessage = false) {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "public" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
val sentPoll = sendRegularPoll(
it.chat,
"Test regular anonymous poll",
it.chat.id,
buildEntities {
regular("Test regular non anonymous poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
(1 .. 10).map {
it.toString()
InputPollOption {
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
},
isAnonymous = false,
replyToMessageId = it.messageId
replyParameters = ReplyParameters(it)
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
}
}
onCommand("quiz", requireOnlyCommandInMessage = false) {
val customEmoji = it.content.parseCommandsWithArgsSources()
.toList()
.firstOrNull { it.first.command == "quiz" }
?.second
?.firstNotNullOfOrNull { it.customEmojiTextSourceOrNull() }
val correctAnswer = Random.nextInt(10)
val sentPoll = sendQuizPoll(
it.chat.id,
questionEntities = buildEntities {
regular("Test quiz poll")
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
},
(1 .. 10).map {
InputPollOption {
regular(it.toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
},
isAnonymous = false,
replyParameters = ReplyParameters(it),
correctOptionId = correctAnswer,
explanationTextSources = buildEntities {
regular("Random solved it to be ") + underline((correctAnswer + 1).toString()) + " "
if (customEmoji != null) {
customEmoji(customEmoji.customEmojiId, customEmoji.subsources)
}
}
)
pollToChatMutex.withLock {
pollToChat[sentPoll.content.poll.id] = sentPoll.chat.id
@@ -94,6 +175,12 @@ suspend fun main(vararg args: String) {
}
}
setMyCommands(
BotCommand("anonymous", "Create anonymous regular poll"),
BotCommand("public", "Create non anonymous regular poll"),
BotCommand("quiz", "Create quiz poll with random right answer"),
)
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) { println(it) }
}.second.join()
}

View File

@@ -0,0 +1,9 @@
# ReactionsInfoBot
This bot will send info about user reactions in his PM with reply to message user reacted to
## Launch
```bash
../gradlew run --args="BOT_TOKEN"
```

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="ReactionsInfoBotKt"
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
}

View File

@@ -0,0 +1,68 @@
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.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.chat.get.getChat
import dev.inmo.tgbotapi.extensions.api.send.reply
import dev.inmo.tgbotapi.extensions.api.send.setMessageReaction
import dev.inmo.tgbotapi.extensions.api.send.setMessageReactions
import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPolling
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionUpdatedByUser
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatMessageReactionsCountUpdated
import dev.inmo.tgbotapi.types.chat.ExtendedChat
import dev.inmo.tgbotapi.types.reactions.Reaction
import dev.inmo.tgbotapi.utils.customEmoji
import dev.inmo.tgbotapi.utils.regular
/**
* This bot will send info about user reactions in his PM with reply to message user reacted to
*/
suspend fun main(vararg args: String) {
val botToken = args.first()
val isDebug = args.getOrNull(1) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val bot = telegramBot(botToken)
bot.buildBehaviourWithLongPolling {
onChatMessageReactionUpdatedByUser {
setMessageReaction(
it.chat.id,
it.messageId,
""
)
val replyResult = reply(
it.chat.id,
it.messageId,
replyInChatId = it.reactedUser.id
) {
regular("Current reactions for message in reply:\n")
it.new.forEach {
when (it) {
is Reaction.CustomEmoji -> regular("") + customEmoji(it.customEmojiId) + regular("(customEmojiId: ${it.customEmojiId})")
is Reaction.Emoji -> regular("${it.emoji}")
is Reaction.Unknown -> regular("• Unknown emoji ($it)")
}
regular("\n")
}
}
setMessageReaction(
it.chat.id,
it.messageId,
)
}
onChatMessageReactionsCountUpdated {
val extendedChat: ExtendedChat = getChat(it.chat)
println(extendedChat)
println(it)
}
}.join()
}

View File

@@ -7,7 +7,13 @@ 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.utils.possiblyWithEffectMessageOrNull
import dev.inmo.tgbotapi.extensions.utils.shortcuts.*
import dev.inmo.tgbotapi.extensions.utils.withContentOrNull
import dev.inmo.tgbotapi.types.ReplyParameters
import dev.inmo.tgbotapi.types.message.abstracts.BusinessContentMessage
import dev.inmo.tgbotapi.types.message.content.TextContent
import dev.inmo.tgbotapi.types.quoteEntitiesField
import dev.inmo.tgbotapi.utils.extensions.threadIdOrNull
import kotlinx.coroutines.*
@@ -18,6 +24,7 @@ suspend fun activateResenderBot(
telegramBotWithBehaviourAndLongPolling(token, scope = CoroutineScope(currentCoroutineContext() + SupervisorJob())) {
onContentMessage(
subcontextUpdatesFilter = MessageFilterByChat,
initialFilter = { it !is BusinessContentMessage<*> || !it.sentByBusinessConnectionOwner }
) {
val chat = it.chat
@@ -26,7 +33,15 @@ suspend fun activateResenderBot(
it.content.createResend(
chat.id,
messageThreadId = it.threadIdOrNull,
replyToMessageId = it.messageId
replyParameters = it.replyInfo ?.messageMeta ?.let { meta ->
val quote = it.withContentOrNull<TextContent>() ?.content ?.quote
ReplyParameters(
meta,
entities = quote ?.textSources ?: emptyList(),
quotePosition = quote ?.position
)
},
effectId = it.possiblyWithEffectMessageOrNull() ?.effectId
)
) {
it.forEach(print)

View File

@@ -18,5 +18,5 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "dev.inmo:tgbotapi:$telegram_bot_api_version"
implementation 'io.ktor:ktor-client-logging-jvm:2.3.5'
implementation 'io.ktor:ktor-client-logging-jvm:2.3.7'
}

View File

@@ -1,4 +1,9 @@
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.firstOf
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.fsm.common.State
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
@@ -24,6 +29,7 @@ import dev.inmo.tgbotapi.types.chat.ChatPermissions
import dev.inmo.tgbotapi.types.chat.PublicChat
import dev.inmo.tgbotapi.types.chat.member.*
import dev.inmo.tgbotapi.types.commands.BotCommandScope
import dev.inmo.tgbotapi.types.message.abstracts.AccessibleMessage
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.utils.*
import dev.inmo.tgbotapi.utils.mention
@@ -49,9 +55,19 @@ sealed interface UserRetrievingStep : State {
suspend fun main(args: Array<String>) {
val botToken = args.first()
val isDebug = args.getOrNull(2) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val bot = telegramBot(botToken)
val allowedAdmin = ChatId(args[1].toLong())
val allowedAdmin = ChatId(RawChatId(args[1].toLong()))
fun Boolean?.allowedSymbol() = when (this) {
true -> ""
@@ -185,14 +201,21 @@ suspend fun main(args: Array<String>) {
) {
onCommand(
"simple",
initialFilter = { it.chat is PublicChat && it.fromUserMessageOrNull()?.user?.id == allowedAdmin }) {
initialFilter = { it.chat is PublicChat && it.fromUserMessageOrNull()?.user?.id == allowedAdmin }
) {
val replyMessage = it.replyTo
val userInReply = replyMessage?.fromUserMessageOrNull()?.user?.id ?: return@onCommand
reply(
replyMessage,
"Manage keyboard:",
replyMarkup = buildCommonKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
)
if (replyMessage is AccessibleMessage) {
reply(
replyMessage,
"Manage keyboard:",
replyMarkup = buildCommonKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
)
} else {
reply(it) {
regular("Reply to somebody's message to get hist/her rights keyboard")
}
}
}
onCommand(
"granular",
@@ -204,11 +227,17 @@ suspend fun main(args: Array<String>) {
val usernameInText = it.content.textSources.firstNotNullOfOrNull { it.mentionTextSourceOrNull() } ?.username
val userInReply = replyMessage?.fromUserMessageOrNull()?.user?.id ?: return@onCommand
reply(
replyMessage,
"Manage keyboard:",
replyMarkup = buildGranularKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
)
if (replyMessage is AccessibleMessage) {
reply(
replyMessage,
"Manage keyboard:",
replyMarkup = buildGranularKeyboard(it.chat.id.toChatId(), userInReply) ?: return@onCommand
)
} else {
reply(it) {
regular("Reply to somebody's message to get hist/her rights keyboard")
}
}
}
onMessageDataCallbackQuery(
@@ -348,8 +377,8 @@ suspend fun main(args: Array<String>) {
initialFilter = { it.user.id == allowedAdmin }
) {
val (channelIdString, userIdString) = it.data.split(" ").drop(1)
val channelId = ChatId(channelIdString.toLong())
val userId = ChatId(userIdString.toLong())
val channelId = ChatId(RawChatId(channelIdString.toLong()))
val userId = ChatId(RawChatId(userIdString.toLong()))
val chatMember = getChatMember(channelId, userId)
val asAdmin = chatMember.administratorChatMemberOrNull()
val asMember = chatMember.memberChatMemberOrNull()
@@ -503,5 +532,9 @@ suspend fun main(args: Array<String>) {
BotCommand("rights_in_channel", "Trigger granular keyboard. Use with reply to user"),
scope = BotCommandScope.AllGroupChats
)
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.join()
}

View File

@@ -9,16 +9,9 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.*
import dev.inmo.tgbotapi.types.StickerFormat
import dev.inmo.tgbotapi.types.StickerType
import dev.inmo.tgbotapi.types.message.textsources.*
import dev.inmo.tgbotapi.types.stickers.AnimatedStickerSet
import dev.inmo.tgbotapi.types.stickers.CustomEmojiSimpleStickerSet
import dev.inmo.tgbotapi.types.stickers.CustomEmojiStickerSet
import dev.inmo.tgbotapi.types.stickers.CustomEmojiVideoStickerSet
import dev.inmo.tgbotapi.types.stickers.MaskSimpleStickerSet
import dev.inmo.tgbotapi.types.stickers.MaskStickerSet
import dev.inmo.tgbotapi.types.stickers.MaskVideoStickerSet
import dev.inmo.tgbotapi.types.stickers.RegularSimpleStickerSet
import dev.inmo.tgbotapi.types.stickers.RegularStickerSet
import dev.inmo.tgbotapi.types.stickers.RegularVideoStickerSet
import dev.inmo.tgbotapi.types.stickers.StickerSet
import dev.inmo.tgbotapi.types.stickers.UnknownStickerSet
import dev.inmo.tgbotapi.utils.bold
@@ -31,12 +24,6 @@ fun StickerSet?.buildInfo() = buildEntities {
} else {
bold("StickerSet name: ") + "${name}\n"
bold("StickerSet title: ") + "${title}\n"
bold("Sticker format: ") + when (stickerFormat) {
StickerFormat.Animated -> "Animated"
StickerFormat.Static -> "Static"
is StickerFormat.Unknown -> stickerFormat.type
StickerFormat.Video -> "Video"
} + "\n"
bold(
when (stickerType) {
StickerType.CustomEmoji -> "Custom emoji"
@@ -44,7 +31,7 @@ fun StickerSet?.buildInfo() = buildEntities {
StickerType.Regular -> "Regular"
is StickerType.Unknown -> "Unknown type \"${stickerType.type}\""
}
) + " sticker set with title " + bold(title) + " and name " + bold(name)
) + " sticker set with title " + bold(title) + " and name " + bold(name.string)
}
}

View File

@@ -1,4 +1,5 @@
import dev.inmo.micro_utils.coroutines.runCatchingSafely
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.tgbotapi.extensions.api.bot.getMe
import dev.inmo.tgbotapi.extensions.api.files.downloadFile
import dev.inmo.tgbotapi.extensions.api.files.downloadFileToTemp
@@ -13,6 +14,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onSticke
import dev.inmo.tgbotapi.extensions.utils.extensions.raw.sticker
import dev.inmo.tgbotapi.requests.abstracts.asMultipartFile
import dev.inmo.tgbotapi.requests.stickers.InputSticker
import dev.inmo.tgbotapi.types.StickerSetName
import dev.inmo.tgbotapi.types.chat.Chat
import dev.inmo.tgbotapi.types.files.*
import dev.inmo.tgbotapi.types.toChatId
@@ -32,7 +34,7 @@ suspend fun main(args: Array<String>) {
}
) {
val me = getMe()
fun Chat.stickerSetName() = "s${id.chatId}_by_${me.username ?.usernameWithoutAt}"
fun Chat.stickerSetName() = StickerSetName("s${id.chatId}_by_${me.username ?.withoutAt}")
onCommand("start") {
reply(it) {
botCommand("delete") + " - to clear stickers"
@@ -55,16 +57,19 @@ suspend fun main(args: Array<String>) {
val newSticker = when (sticker) {
is CustomEmojiSticker -> InputSticker.WithKeywords.CustomEmoji(
downloadFileToTemp(sticker.fileId).asMultipartFile(),
sticker.stickerFormat,
listOf(sticker.emoji ?: "\uD83D\uDE0A"),
emptyList()
)
is MaskSticker -> InputSticker.Mask(
downloadFileToTemp(sticker.fileId).asMultipartFile(),
sticker.stickerFormat,
listOf(sticker.emoji ?: "\uD83D\uDE0A"),
sticker.maskPosition
)
is RegularSticker -> InputSticker.WithKeywords.Regular(
downloadFileToTemp(sticker.fileId).asMultipartFile(),
sticker.stickerFormat,
listOf(sticker.emoji ?: "\uD83D\uDE0A"),
emptyList()
)
@@ -73,18 +78,25 @@ suspend fun main(args: Array<String>) {
runCatchingSafely {
getStickerSet(stickerSetName)
}.onSuccess { stickerSet ->
addStickerToSet(it.chat.id.toChatId(), stickerSet.name, newSticker).also { _ ->
runCatching {
addStickerToSet(it.chat.id.toChatId(), stickerSet.name, newSticker).also { _ ->
reply(
it,
getStickerSet(stickerSetName).stickers.last()
)
}
}.onFailure { exception ->
exception.printStackTrace()
reply(
it,
getStickerSet(stickerSetName).stickers.last()
"Unable to add sticker in stickerset"
)
}
}.onFailure { _ ->
}.onFailure { exception ->
createNewStickerSet(
it.chat.id.toChatId(),
stickerSetName,
stickerSetName.string,
"Sticker set by ${me.firstName}",
it.content.media.stickerFormat,
listOf(
newSticker
),
@@ -97,5 +109,9 @@ suspend fun main(args: Array<String>) {
}
}
}
allUpdatesFlow.subscribeSafelyWithoutExceptions(this) {
println(it)
}
}.second.join()
}

View File

@@ -1,3 +1,7 @@
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.runCatchingSafely
import dev.inmo.tgbotapi.bot.ktor.telegramBot
import dev.inmo.tgbotapi.extensions.api.bot.setMyCommands
@@ -7,20 +11,26 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.buildBehaviourWithLongPoll
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onChatShared
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUserShared
import dev.inmo.tgbotapi.extensions.utils.types.buttons.replyKeyboard
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestBotButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestChatButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestGroupButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestUserButton
import dev.inmo.tgbotapi.extensions.utils.types.buttons.requestUserOrBotButton
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onUsersShared
import dev.inmo.tgbotapi.extensions.utils.types.buttons.*
import dev.inmo.tgbotapi.types.BotCommand
import dev.inmo.tgbotapi.types.chat.PrivateChat
import dev.inmo.tgbotapi.types.keyboardButtonRequestUserLimit
import dev.inmo.tgbotapi.types.message.textsources.mention
import dev.inmo.tgbotapi.types.request.RequestId
import dev.inmo.tgbotapi.utils.row
suspend fun main(args: Array<String>) {
val botToken = args.first()
val isDebug = args.getOrNull(1) == "debug"
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val bot = telegramBot(botToken)
@@ -30,127 +40,234 @@ suspend fun main(args: Array<String>) {
val requestIdUserPremium = RequestId(3)
val requestIdBot = RequestId(4)
val requestIdAnyChat = RequestId(5)
val requestIdChannel = RequestId(6)
val requestIdPublicChannel = RequestId(7)
val requestIdPrivateChannel = RequestId(8)
val requestIdChannelUserOwner = RequestId(9)
val requestIdUsersOrBots = RequestId(5)
val requestIdUsersNonPremium = RequestId(6)
val requestIdUsersAny = RequestId(7)
val requestIdUsersPremium = RequestId(8)
val requestIdBots = RequestId(9)
val requestIdGroup = RequestId(10)
val requestIdPublicGroup = RequestId(11)
val requestIdPrivateGroup = RequestId(12)
val requestIdGroupUserOwner = RequestId(13)
val requestIdAnyChat = RequestId(10)
val requestIdChannel = RequestId(11)
val requestIdPublicChannel = RequestId(12)
val requestIdPrivateChannel = RequestId(13)
val requestIdChannelUserOwner = RequestId(14)
val requestIdForum = RequestId(14)
val requestIdPublicForum = RequestId(15)
val requestIdPrivateForum = RequestId(16)
val requestIdForumUserOwner = RequestId(17)
val requestIdGroup = RequestId(15)
val requestIdPublicGroup = RequestId(16)
val requestIdPrivateGroup = RequestId(17)
val requestIdGroupUserOwner = RequestId(18)
val requestIdForum = RequestId(19)
val requestIdPublicForum = RequestId(20)
val requestIdPrivateForum = RequestId(21)
val requestIdForumUserOwner = RequestId(22)
val keyboard = replyKeyboard(
resizeKeyboard = true,
) {
row {
requestUserOrBotButton(
"\uD83D\uDC64/\uD83E\uDD16",
requestIdUserOrBot
"\uD83D\uDC64/\uD83E\uDD16 (1)",
requestIdUserOrBot,
requestName = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestUserButton(
"\uD83D\uDC64",
"\uD83D\uDC64 (1)",
requestIdUserNonPremium,
premiumUser = false
premiumUser = false,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestUserButton(
"\uD83D\uDC64",
"\uD83D\uDC64 (1)",
requestIdUserAny,
premiumUser = null
premiumUser = null,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestUserButton(
"\uD83D\uDC64",
"\uD83D\uDC64 (1)",
requestIdUserPremium,
premiumUser = true
premiumUser = true,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestBotButton(
"\uD83E\uDD16 (1)",
requestIdBot,
requestName = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestUsersOrBotsButton(
"\uD83D\uDC64/\uD83E\uDD16",
requestIdUsersOrBots,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersNonPremium,
premiumUser = false,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersAny,
premiumUser = null,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestUsersButton(
"\uD83D\uDC64",
requestIdUsersPremium,
premiumUser = true,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
requestBotsButton(
"\uD83E\uDD16",
requestIdBot
requestIdBots,
maxCount = keyboardButtonRequestUserLimit.last,
requestName = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestChatButton(
"\uD83D\uDDE3/\uD83D\uDC65",
requestIdAnyChat
requestIdAnyChat,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestChatButton(
"\uD83D\uDDE3",
requestIdChannel,
isChannel = true
isChannel = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestChatButton(
"\uD83D\uDDE3\uD83D\uDD17",
requestIdPublicChannel,
isChannel = true,
isPublic = true
isPublic = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestChatButton(
"\uD83D\uDDE3\uD83D\uDD17",
requestIdPrivateChannel,
isChannel = true,
isPublic = false
isPublic = false,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestChatButton(
"\uD83D\uDDE3\uD83D\uDC6E",
requestIdChannelUserOwner,
isChannel = true,
isOwnedBy = true
isOwnedBy = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestGroupButton(
"👥",
requestIdGroup
requestIdGroup,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestGroupButton(
"👥\uD83D\uDD17",
requestIdPublicGroup,
isPublic = true
isPublic = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestGroupButton(
"👥❌\uD83D\uDD17",
requestIdPrivateGroup,
isPublic = false
isPublic = false,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestGroupButton(
"👥\uD83D\uDC6E",
requestIdGroupUserOwner,
isOwnedBy = true
isOwnedBy = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
}
row {
requestGroupButton(
"🏛",
requestIdForum,
isForum = true
isForum = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestGroupButton(
"🏛\uD83D\uDD17",
requestIdPublicForum,
isPublic = true,
isForum = true
isForum = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestGroupButton(
"🏛❌\uD83D\uDD17",
requestIdPrivateForum,
isPublic = false,
isForum = true
isForum = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
requestGroupButton(
"🏛\uD83D\uDC6E",
requestIdForumUserOwner,
isOwnedBy = true,
isForum = true
isForum = true,
requestTitle = true,
requestUsername = true,
requestPhoto = true
)
}
}
@@ -164,25 +281,26 @@ suspend fun main(args: Array<String>) {
)
}
onUserShared {
val userId = it.chatEvent.userId
val userInfo = runCatchingSafely { getChat(userId) }.getOrNull()
reply(
it,
) {
+"You have shared "
+mention(
when (it.chatEvent.requestId) {
requestIdUserOrBot -> "user or bot"
requestIdUserNonPremium -> "non premium user"
requestIdUserAny -> "any user"
requestIdUserPremium -> "premium user"
requestIdBot -> "bot"
else -> "somebody O.o"
},
userId
)
+" (user info: $userInfo; user id: $userId)"
onUsersShared {
it.chatEvent.userIds.forEach { userId ->
val userInfo = runCatchingSafely { getChat(userId) }.getOrNull()
reply(
it,
) {
+"You have shared "
+mention(
when (it.chatEvent.requestId) {
requestIdUserOrBot -> "user or bot"
requestIdUserNonPremium -> "non premium user"
requestIdUserAny -> "any user"
requestIdUserPremium -> "premium user"
requestIdBot -> "bot"
else -> "somebody O.o"
},
userId
)
+" (user info: $userInfo; user id: $userId)"
}
}
}

View File

@@ -1,3 +1,4 @@
import dev.inmo.kslog.common.*
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.ktor.server.createKtorServer
import dev.inmo.tgbotapi.extensions.api.answers.answer
@@ -14,6 +15,8 @@ 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
import dev.inmo.tgbotapi.types.InlineQueryId
import dev.inmo.tgbotapi.types.LinkPreviewOptions
import dev.inmo.tgbotapi.types.webAppQueryIdField
import dev.inmo.tgbotapi.types.webapps.WebAppInfo
import dev.inmo.tgbotapi.utils.*
@@ -34,6 +37,7 @@ import java.nio.charset.Charset
*
* * Telegram Token
* * URL where will be placed
* * Port (default 8080)
*
* Will start the server to share the static (index.html and WebApp.js) on 0.0.0.0:8080
*/
@@ -43,6 +47,17 @@ suspend fun main(vararg args: String) {
args.first(),
testServer = args.any { it == "testServer" }
)
val isDebug = args.any { it == "debug" }
if (isDebug) {
setDefaultKSLog(
KSLog { level: LogLevel, tag: String?, message: Any, throwable: Throwable? ->
println(defaultMessageFormatter(level, tag, message, throwable))
}
)
}
val initiationLogger = KSLog("Initialization")
val bot = telegramBot(telegramBotAPIUrlsKeeper)
createKtorServer(
"0.0.0.0",
@@ -53,18 +68,34 @@ suspend fun main(vararg args: String) {
) {
routing {
val baseJsFolder = File("WebApp/build/dist/js/")
baseJsFolder.list() ?.forEach {
if (it == "productionExecutable" || it == "developmentExecutable") {
staticFiles("", File(baseJsFolder, it)) {
default("WebApp/build/dist/js/$it/index.html")
}
val prodSubFolder = File(baseJsFolder, "productionExecutable")
val devSubFolder = File(baseJsFolder, "developmentExecutable")
val staticFolder = when {
prodSubFolder.exists() -> {
initiationLogger.i("Folder for static is ${prodSubFolder.absolutePath}")
prodSubFolder
}
devSubFolder.exists() -> {
initiationLogger.i("Folder for static is ${devSubFolder.absolutePath}")
devSubFolder
}
else -> error("""
Unable to detect any folder with static. Current working directory: ${File("").absolutePath}.
Searched paths:
* ${prodSubFolder.absolutePath}
* ${devSubFolder.absolutePath}
""".trimIndent())
}
staticFiles("", staticFolder) {
default("${staticFolder.absolutePath}${File.separator}index.html")
}
post("inline") {
val requestBody = call.receiveText()
val queryId = call.parameters[webAppQueryIdField] ?: error("$webAppQueryIdField should be presented")
val queryId = call.parameters[webAppQueryIdField] ?.let(::InlineQueryId) ?: error("$webAppQueryIdField should be presented")
bot.answer(queryId, InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody)))
bot.answerInlineQuery(queryId, listOf(InlineQueryResultArticle(queryId, "Result", InputTextMessageContent(requestBody))))
call.respond(HttpStatusCode.OK)
}
post("check") {
@@ -102,8 +133,11 @@ suspend fun main(vararg args: String) {
row {
webAppButton("Open WebApp", WebAppInfo(args[1]))
}
}
},
linkPreviewOptions = LinkPreviewOptions.Small(
args[1],
showAboveText = false
)
)
}
onCommand("attachment_menu") {
@@ -114,8 +148,11 @@ suspend fun main(vararg args: String) {
row {
webAppButton("Open WebApp", WebAppInfo(args[1]))
}
}
},
linkPreviewOptions = LinkPreviewOptions.Large(
args[1],
showAboveText = true
)
)
}
onBaseInlineQuery {

View File

@@ -26,6 +26,6 @@ allprojects {
}
}
maven { url "https://git.inmo.dev/api/packages/InsanusMokrassar/maven" }
maven { url "https://nexus.inmo.dev/repository/maven-releases/" }
}
}

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=-Xmx2g
org.gradle.jvmargs=-Xmx2344m
kotlin_version=1.9.21
telegram_bot_api_version=9.4.1
micro_utils_version=0.20.15
serialization_version=1.6.1
ktor_version=2.3.6
kotlin_version=1.9.23
telegram_bot_api_version=14.0.0
micro_utils_version=0.20.45
serialization_version=1.6.3
ktor_version=2.3.10

Binary file not shown.

View File

@@ -1,7 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip

307
gradlew vendored
View File

@@ -1,127 +1,78 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#!/usr/bin/env sh
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
MAX_FD="maximum"
warn () {
echo "$*"
} >&2
}
die () {
echo
echo "$*"
echo
exit 1
} >&2
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD=$JAVA_HOME/bin/java
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -130,120 +81,92 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

56
gradlew.bat vendored
View File

@@ -1,20 +1,4 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%"=="" @echo off
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -25,23 +9,19 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -55,7 +35,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -65,26 +45,38 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View File

@@ -41,3 +41,13 @@ include ":LiveLocationsBot"
include ":StickerSetHandler"
include ":InlineQueriesBot"
include ":ReactionsInfoBot"
include ":LinkPreviewsBot"
include ":BoostsInfoBot"
include ":BusinessConnectionsBot"
include ":CustomBot"