mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-12-28 03:27:13 +00:00
improvements of commands expectations and triggers
This commit is contained in:
parent
0efa52fe00
commit
080db09d2c
@ -2,6 +2,12 @@
|
||||
|
||||
## 9.2.4
|
||||
|
||||
* `Utils`:
|
||||
* New extensions `*.parseCommandsWithNamedArgs`
|
||||
* `BehaviourBuilder`:
|
||||
* In expectaters and triggers of `commands` add `*WithNamedArgs` variants
|
||||
* In expectaters and triggers of `commands` add opportunity to use custom separator
|
||||
|
||||
## 9.2.3
|
||||
|
||||
* `Core`:
|
||||
|
@ -3,6 +3,10 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.expectations
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.BehaviourContext
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.handlers_registrar.doWithRegistration
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.TelegramBotCommandsDefaults
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgsSources
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithNamedArgs
|
||||
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||
import dev.inmo.tgbotapi.types.BotCommand
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage
|
||||
@ -82,32 +86,51 @@ fun Flow<CommonMessage<TextContent>>.requireCommandsWithoutParams() = filter {
|
||||
* Map the commands with their arguments and source messages
|
||||
*/
|
||||
fun Flow<CommonMessage<TextContent>>.commandsWithParams(): Flow<Pair<CommonMessage<TextContent>, List<Pair<BotCommandTextSource, Array<TextSource>>>>> = mapNotNull {
|
||||
var currentCommandTextSource: BotCommandTextSource? = null
|
||||
val currentArgs = mutableListOf<TextSource>()
|
||||
val result = mutableListOf<Pair<BotCommandTextSource, Array<TextSource>>>()
|
||||
|
||||
fun addCurrentCommandToResult() {
|
||||
currentCommandTextSource ?.let {
|
||||
result.add(it to currentArgs.toTypedArray())
|
||||
currentArgs.clear()
|
||||
}
|
||||
}
|
||||
|
||||
it.content.textSources.forEach {
|
||||
it.ifBotCommandTextSource {
|
||||
addCurrentCommandToResult()
|
||||
currentCommandTextSource = it
|
||||
return@forEach
|
||||
}
|
||||
currentArgs.add(it)
|
||||
}
|
||||
addCurrentCommandToResult()
|
||||
|
||||
result.toList().takeIf { it.isNotEmpty() } ?.let { result ->
|
||||
it to result
|
||||
}
|
||||
it to it.content.textSources.parseCommandsWithArgsSources().toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the commands with their arguments and source messages
|
||||
*/
|
||||
fun Flow<CommonMessage<TextContent>>.commandsWithArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
): Flow<Pair<CommonMessage<TextContent>, List<Pair<String, Array<String>>>>> = mapNotNull {
|
||||
val commandsWithArgs = it.content.textSources.parseCommandsWithArgs(argsSeparator).toList().ifEmpty {
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
it to commandsWithArgs
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the commands with their arguments and source messages
|
||||
*/
|
||||
fun Flow<CommonMessage<TextContent>>.commandsWithArgs(
|
||||
argsSeparator: String
|
||||
): Flow<Pair<CommonMessage<TextContent>, List<Pair<String, Array<String>>>>> = commandsWithArgs(Regex(argsSeparator))
|
||||
|
||||
/**
|
||||
* Map the commands with their arguments and source messages
|
||||
*/
|
||||
fun Flow<CommonMessage<TextContent>>.commandsWithNamedArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
): Flow<Pair<CommonMessage<TextContent>, List<Pair<String, List<Pair<String, String>>>>>> = mapNotNull {
|
||||
val commandsWithArgs = it.content.textSources.parseCommandsWithNamedArgs(argsSeparator, nameArgSeparator).toList().ifEmpty {
|
||||
return@mapNotNull null
|
||||
}
|
||||
|
||||
it to commandsWithArgs
|
||||
}
|
||||
|
||||
/**
|
||||
* Map the commands with their arguments and source messages
|
||||
*/
|
||||
fun Flow<CommonMessage<TextContent>>.commandsWithNamedArgs(
|
||||
argsSeparator: String,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
): Flow<Pair<CommonMessage<TextContent>, List<Pair<String, List<Pair<String, String>>>>>> = commandsWithNamedArgs(Regex(argsSeparator), nameArgSeparator)
|
||||
|
||||
/**
|
||||
* Flat [commandsWithParams]. Each [Pair] of [BotCommandTextSource] and its [Array] of arg text sources will
|
||||
* be associated with its source message
|
||||
|
@ -11,7 +11,9 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByC
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times
|
||||
import dev.inmo.tgbotapi.extensions.utils.botCommandTextSourceOrNull
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.TelegramBotCommandsDefaults
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithNamedArgs
|
||||
import dev.inmo.tgbotapi.types.BotCommand
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.content.TextMessage
|
||||
@ -124,6 +126,7 @@ suspend fun <BC : BehaviourContext> BC.commandWithArgs(
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, Array<String>>
|
||||
) = command(
|
||||
commandRegex,
|
||||
@ -132,7 +135,7 @@ suspend fun <BC : BehaviourContext> BC.commandWithArgs(
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory
|
||||
) {
|
||||
val args = it.parseCommandsWithParams().let { commandsWithArgs ->
|
||||
val args = it.parseCommandsWithArgs(argsSeparator = argsSeparator).let { commandsWithArgs ->
|
||||
val key = commandsWithArgs.keys.firstOrNull { it.matches(commandRegex) } ?: return@let null
|
||||
commandsWithArgs[key]
|
||||
} ?: emptyArray()
|
||||
@ -144,12 +147,14 @@ suspend fun <BC : BehaviourContext> BC.commandWithArgs(
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, Array<String>>
|
||||
) = commandWithArgs(
|
||||
command.toRegex(),
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
@ -158,12 +163,72 @@ suspend fun <BC : BehaviourContext> BC.commandWithArgs(
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, Array<String>>
|
||||
) = commandWithArgs(
|
||||
botCommand.command,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.commandWithNamedArgs(
|
||||
commandRegex: Regex,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, List<Pair<String, String>>>
|
||||
) = command(
|
||||
commandRegex,
|
||||
requireOnlyCommandInMessage = false,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory
|
||||
) {
|
||||
val args = it.parseCommandsWithNamedArgs(argsSeparator = argsSeparator, nameArgSeparator = nameArgSeparator).let { commandsWithArgs ->
|
||||
val key = commandsWithArgs.keys.firstOrNull { it.matches(commandRegex) } ?: return@let null
|
||||
commandsWithArgs[key]
|
||||
} ?: emptyList()
|
||||
scenarioReceiver(it, args)
|
||||
}
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.commandWithNamedArgs(
|
||||
command: String,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, List<Pair<String, String>>>
|
||||
) = commandWithNamedArgs(
|
||||
command.toRegex(),
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
nameArgSeparator = nameArgSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.commandWithNamedArgs(
|
||||
botCommand: BotCommand,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, List<Pair<String, String>>>
|
||||
) = commandWithNamedArgs(
|
||||
botCommand.command,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
nameArgSeparator = nameArgSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
@ -172,21 +237,99 @@ suspend fun <BC : BehaviourContext> BC.onCommandWithArgs(
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, Array<String>>
|
||||
): Job = commandWithArgs(commandRegex, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
|
||||
): Job = commandWithArgs(
|
||||
commandRegex = commandRegex,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.onCommandWithArgs(
|
||||
command: String,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, Array<String>>
|
||||
): Job = onCommandWithArgs(command.toRegex(), initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
|
||||
): Job = onCommandWithArgs(
|
||||
commandRegex = command.toRegex(),
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.onCommandWithArgs(
|
||||
botCommand: BotCommand,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, Array<String>>
|
||||
): Job = onCommandWithArgs(botCommand.command, initialFilter, subcontextUpdatesFilter, markerFactory, scenarioReceiver)
|
||||
): Job = onCommandWithArgs(
|
||||
command = botCommand.command,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.onCommandWithNamedArgs(
|
||||
commandRegex: Regex,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, List<Pair<String, String>>>
|
||||
) = commandWithNamedArgs(
|
||||
commandRegex,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
nameArgSeparator = nameArgSeparator,
|
||||
scenarioReceiver = scenarioReceiver,
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.onCommandWithNamedArgs(
|
||||
command: String,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, List<Pair<String, String>>>
|
||||
) = onCommandWithNamedArgs(
|
||||
command.toRegex(),
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
nameArgSeparator = nameArgSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
||||
suspend fun <BC : BehaviourContext> BC.onCommandWithNamedArgs(
|
||||
botCommand: BotCommand,
|
||||
initialFilter: CommonMessageFilter<TextContent>? = CommonMessageFilterExcludeMediaGroups,
|
||||
subcontextUpdatesFilter: CustomBehaviourContextAndTwoTypesReceiver<BC, Boolean, TextMessage, Update>? = MessageFilterByChat,
|
||||
markerFactory: MarkerFactory<in TextMessage, Any> = ByChatMessageMarkerFactory,
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
scenarioReceiver: CustomBehaviourContextAndTwoTypesReceiver<BC, Unit, TextMessage, List<Pair<String, String>>>
|
||||
) = onCommandWithNamedArgs(
|
||||
botCommand.command,
|
||||
initialFilter = initialFilter,
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory,
|
||||
argsSeparator = argsSeparator,
|
||||
nameArgSeparator = nameArgSeparator,
|
||||
scenarioReceiver = scenarioReceiver
|
||||
)
|
||||
|
@ -9,7 +9,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByC
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times
|
||||
import dev.inmo.tgbotapi.extensions.utils.botCommandTextSourceOrNull
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.content.TextMessage
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||
@ -65,7 +65,7 @@ suspend fun <BC : BehaviourContext> BC.unhandledCommandWithArgs(
|
||||
subcontextUpdatesFilter = subcontextUpdatesFilter,
|
||||
markerFactory = markerFactory
|
||||
) {
|
||||
val args = it.parseCommandsWithParams().let { commandsWithArgs ->
|
||||
val args = it.parseCommandsWithArgs().let { commandsWithArgs ->
|
||||
commandsWithArgs
|
||||
}
|
||||
scenarioReceiver(it, args)
|
||||
|
@ -4,22 +4,18 @@ package dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling
|
||||
|
||||
import dev.inmo.micro_utils.coroutines.*
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitDeepLinks
|
||||
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.utils.SimpleFilter
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.ByChatMessageMarkerFactory
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.marker_factories.MarkerFactory
|
||||
import dev.inmo.tgbotapi.extensions.behaviour_builder.utils.times
|
||||
import dev.inmo.tgbotapi.extensions.utils.*
|
||||
import dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithParams
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.content.TextMessage
|
||||
import dev.inmo.tgbotapi.types.message.textsources.RegularTextSource
|
||||
import dev.inmo.tgbotapi.types.update.abstracts.Update
|
||||
import io.ktor.http.decodeURLQueryComponent
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
||||
private val startRegex = Regex("start")
|
||||
suspend fun <BC : BehaviourContext> BC.onDeepLink(
|
||||
|
@ -0,0 +1,247 @@
|
||||
package dev.inmo.tgbotapi.extensions.utils.extensions
|
||||
|
||||
import dev.inmo.tgbotapi.abstracts.TextedWithTextSources
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
||||
import dev.inmo.tgbotapi.types.message.textsources.TextSource
|
||||
|
||||
object TelegramBotCommandsDefaults {
|
||||
const val defaultArgsSeparator = " "
|
||||
val defaultArgsSeparatorRegex = Regex(defaultArgsSeparator)
|
||||
const val defaultNamesArgsSeparator = "="
|
||||
val defaultNamesArgsSeparatorRegex = Regex(defaultNamesArgsSeparator)
|
||||
}
|
||||
|
||||
@Deprecated(message = "Replaced", replaceWith = ReplaceWith("TelegramBotCommandsDefaults.defaultArgsSeparatorRegex", "dev.inmo.tgbotapi.extensions.utils.extensions.TelegramBotCommandsDefaults"))
|
||||
val defaultArgsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun List<TextSource>.parseCommandsWithArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
): MutableMap<String, Array<String>> {
|
||||
val result = mutableMapOf<String, Array<String>>()
|
||||
var currentBotCommandSource: BotCommandTextSource? = null
|
||||
var currentArgs = ""
|
||||
|
||||
fun includeCurrent() = currentBotCommandSource?.let {
|
||||
currentArgs = currentArgs.trim()
|
||||
result[it.command] = if (currentArgs.isNotEmpty()) {
|
||||
currentArgs.split(argsSeparator).toTypedArray()
|
||||
} else {
|
||||
emptyArray()
|
||||
}
|
||||
currentArgs = ""
|
||||
currentBotCommandSource = null
|
||||
}
|
||||
|
||||
for (textSource in this) {
|
||||
if (textSource is BotCommandTextSource) {
|
||||
includeCurrent()
|
||||
currentBotCommandSource = textSource
|
||||
} else {
|
||||
currentArgs += textSource.source
|
||||
}
|
||||
}
|
||||
includeCurrent()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun TextedWithTextSources.parseCommandsWithArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
) = textSources?.parseCommandsWithArgs(argsSeparator) ?: emptyMap()
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun ContentMessage<TextContent>.parseCommandsWithArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
) = content.parseCommandsWithArgs(argsSeparator)
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun List<TextSource>.parseCommandsWithArgs(
|
||||
argsSeparator: String
|
||||
): MutableMap<String, Array<String>> = parseCommandsWithArgs(Regex(argsSeparator))
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun TextedWithTextSources.parseCommandsWithArgs(
|
||||
argsSeparator: String
|
||||
) = parseCommandsWithArgs(Regex(argsSeparator))
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun ContentMessage<TextContent>.parseCommandsWithArgs(
|
||||
argsSeparator: String
|
||||
) = parseCommandsWithArgs(Regex(argsSeparator))
|
||||
|
||||
/**
|
||||
* Uses [parseCommandsWithArgs] to create base [argsSeparator] split args for commands and map their as k-v pairs.
|
||||
* Sample:
|
||||
*
|
||||
* ```bash
|
||||
* /command args1=value1 arg2=value2 arg1=value3
|
||||
* ```
|
||||
*
|
||||
* Will produce [Map] with one key `command` and the list of three pairs:
|
||||
*
|
||||
* 1. `args1` to `value1`
|
||||
* 2. `args2` to `value2`
|
||||
* 3. `args1` to `value3`
|
||||
*
|
||||
* @return Array of named arguments
|
||||
*/
|
||||
fun List<TextSource>.parseCommandsWithNamedArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
): Map<String, List<Pair<String, String>>> {
|
||||
val withArgs = parseCommandsWithArgs(argsSeparator)
|
||||
|
||||
return withArgs.mapValues { (k, v) ->
|
||||
v.flatMap {
|
||||
it.split(nameArgSeparator, 2).map { v -> it to v }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses [parseCommandsWithArgs] to create base [argsSeparator] split args for commands and map their as k-v pairs.
|
||||
* Sample:
|
||||
*
|
||||
* ```bash
|
||||
* /command args1=value1 arg2=value2 arg1=value3
|
||||
* ```
|
||||
*
|
||||
* Will produce [Map] with one key `command` and the list of three pairs:
|
||||
*
|
||||
* 1. `args1` to `value1`
|
||||
* 2. `args2` to `value2`
|
||||
* 3. `args1` to `value3`
|
||||
*
|
||||
* @return Array of named arguments
|
||||
*/
|
||||
fun TextedWithTextSources.parseCommandsWithNamedArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
) = textSources?.parseCommandsWithNamedArgs(argsSeparator = argsSeparator, nameArgSeparator = nameArgSeparator) ?: emptyMap()
|
||||
|
||||
/**
|
||||
* Uses [parseCommandsWithArgs] to create base [argsSeparator] split args for commands and map their as k-v pairs.
|
||||
* Sample:
|
||||
*
|
||||
* ```bash
|
||||
* /command args1=value1 arg2=value2 arg1=value3
|
||||
* ```
|
||||
*
|
||||
* Will produce [Map] with one key `command` and the list of three pairs:
|
||||
*
|
||||
* 1. `args1` to `value1`
|
||||
* 2. `args2` to `value2`
|
||||
* 3. `args1` to `value3`
|
||||
*
|
||||
* @return Array of named arguments
|
||||
*/
|
||||
fun ContentMessage<TextContent>.parseCommandsWithNamedArgs(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
) = content.parseCommandsWithNamedArgs(argsSeparator = argsSeparator, nameArgSeparator = nameArgSeparator)
|
||||
|
||||
/**
|
||||
* Uses [parseCommandsWithArgs] to create base [argsSeparator] split args for commands and map their as k-v pairs.
|
||||
* Sample:
|
||||
*
|
||||
* ```bash
|
||||
* /command args1=value1 arg2=value2 arg1=value3
|
||||
* ```
|
||||
*
|
||||
* Will produce [Map] with one key `command` and the list of three pairs:
|
||||
*
|
||||
* 1. `args1` to `value1`
|
||||
* 2. `args2` to `value2`
|
||||
* 3. `args1` to `value3`
|
||||
*
|
||||
* @return Array of named arguments
|
||||
*/
|
||||
fun List<TextSource>.parseCommandsWithNamedArgs(
|
||||
argsSeparator: String,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
): Map<String, List<Pair<String, String>>> = parseCommandsWithNamedArgs(Regex(pattern = argsSeparator), nameArgSeparator)
|
||||
|
||||
/**
|
||||
* Uses [parseCommandsWithArgs] to create base [argsSeparator] split args for commands and map their as k-v pairs.
|
||||
* Sample:
|
||||
*
|
||||
* ```bash
|
||||
* /command args1=value1 arg2=value2 arg1=value3
|
||||
* ```
|
||||
*
|
||||
* Will produce [Map] with one key `command` and the list of three pairs:
|
||||
*
|
||||
* 1. `args1` to `value1`
|
||||
* 2. `args2` to `value2`
|
||||
* 3. `args1` to `value3`
|
||||
*
|
||||
* @return Array of named arguments
|
||||
*/
|
||||
fun TextedWithTextSources.parseCommandsWithNamedArgs(
|
||||
argsSeparator: String,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
) = parseCommandsWithNamedArgs(argsSeparator = Regex(pattern = argsSeparator), nameArgSeparator = nameArgSeparator)
|
||||
|
||||
/**
|
||||
* Uses [parseCommandsWithArgs] to create base [argsSeparator] split args for commands and map their as k-v pairs.
|
||||
* Sample:
|
||||
*
|
||||
* ```bash
|
||||
* /command args1=value1 arg2=value2 arg1=value3
|
||||
* ```
|
||||
*
|
||||
* Will produce [Map] with one key `command` and the list of three pairs:
|
||||
*
|
||||
* 1. `args1` to `value1`
|
||||
* 2. `args2` to `value2`
|
||||
* 3. `args1` to `value3`
|
||||
*
|
||||
* @return Array of named arguments
|
||||
*/
|
||||
fun ContentMessage<TextContent>.parseCommandsWithNamedArgs(
|
||||
argsSeparator: String,
|
||||
nameArgSeparator: Regex = TelegramBotCommandsDefaults.defaultNamesArgsSeparatorRegex,
|
||||
) = parseCommandsWithNamedArgs(argsSeparator = Regex(pattern = argsSeparator), nameArgSeparator = nameArgSeparator)
|
||||
|
||||
|
||||
// Deprecations
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
@Deprecated("Renamed", ReplaceWith("parseCommandsWithArgs(argsSeparator)", "dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs"))
|
||||
fun List<TextSource>.parseCommandsWithParams(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
): MutableMap<String, Array<String>> = parseCommandsWithArgs(argsSeparator)
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
@Deprecated("Renamed", ReplaceWith("parseCommandsWithArgs(argsSeparator)", "dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs"))
|
||||
fun TextedWithTextSources.parseCommandsWithParams(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
) = parseCommandsWithArgs(argsSeparator)
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
@Deprecated("Renamed", ReplaceWith("parseCommandsWithArgs(argsSeparator)", "dev.inmo.tgbotapi.extensions.utils.extensions.parseCommandsWithArgs"))
|
||||
fun ContentMessage<TextContent>.parseCommandsWithParams(
|
||||
argsSeparator: Regex = TelegramBotCommandsDefaults.defaultArgsSeparatorRegex
|
||||
) = parseCommandsWithArgs(argsSeparator)
|
@ -0,0 +1,53 @@
|
||||
package dev.inmo.tgbotapi.extensions.utils.extensions
|
||||
|
||||
import dev.inmo.tgbotapi.abstracts.TextedWithTextSources
|
||||
import dev.inmo.tgbotapi.extensions.utils.botCommandTextSourceOrNull
|
||||
import dev.inmo.tgbotapi.extensions.utils.ifBotCommandTextSource
|
||||
import dev.inmo.tgbotapi.extensions.utils.whenBotCommandTextSource
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
||||
import dev.inmo.tgbotapi.types.message.textsources.TextSource
|
||||
|
||||
// Sources
|
||||
|
||||
/**
|
||||
* Parse text sources to find commands with their arguments. This method will skip all the text sources __before__
|
||||
* first command and all following text sources until the next command will be guessed as an args of last found command
|
||||
*/
|
||||
fun List<TextSource>.parseCommandsWithArgsSources(): Map<BotCommandTextSource, Array<TextSource>> {
|
||||
var currentCommandTextSource: BotCommandTextSource? = null
|
||||
val currentArgs = mutableListOf<TextSource>()
|
||||
val result = mutableMapOf<BotCommandTextSource, Array<TextSource>>()
|
||||
|
||||
fun addCurrentCommandToResult() {
|
||||
currentCommandTextSource ?.let {
|
||||
result[it] = currentArgs.toTypedArray()
|
||||
currentArgs.clear()
|
||||
}
|
||||
}
|
||||
|
||||
forEach {
|
||||
it.whenBotCommandTextSource {
|
||||
addCurrentCommandToResult()
|
||||
currentCommandTextSource = it
|
||||
return@forEach
|
||||
}
|
||||
currentArgs.add(it)
|
||||
}
|
||||
addCurrentCommandToResult()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse text sources to find commands with their arguments. This method will skip all the text sources __before__
|
||||
* first command and all following text sources until the next command will be guessed as an args of last found command
|
||||
*/
|
||||
fun TextedWithTextSources.parseCommandsWithArgsSources() = textSources?.parseCommandsWithArgsSources() ?: emptyMap()
|
||||
|
||||
/**
|
||||
* Parse text sources to find commands with their arguments. This method will skip all the text sources __before__
|
||||
* first command and all following text sources until the next command will be guessed as an args of last found command
|
||||
*/
|
||||
fun ContentMessage<TextContent>.parseCommandsWithArgsSources() = content.parseCommandsWithArgsSources()
|
@ -1,54 +0,0 @@
|
||||
package dev.inmo.tgbotapi.extensions.utils.extensions
|
||||
|
||||
import dev.inmo.tgbotapi.abstracts.TextedWithTextSources
|
||||
import dev.inmo.tgbotapi.types.message.abstracts.ContentMessage
|
||||
import dev.inmo.tgbotapi.types.message.content.TextContent
|
||||
import dev.inmo.tgbotapi.types.message.textsources.BotCommandTextSource
|
||||
import dev.inmo.tgbotapi.types.message.textsources.TextSource
|
||||
|
||||
|
||||
val defaultArgsSeparator = Regex(" ")
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun List<TextSource>.parseCommandsWithParams(
|
||||
argsSeparator: Regex = defaultArgsSeparator
|
||||
): MutableMap<String, Array<String>> {
|
||||
val result = mutableMapOf<String, Array<String>>()
|
||||
var currentBotCommandSource: BotCommandTextSource? = null
|
||||
var currentArgs = ""
|
||||
fun includeCurrent() = currentBotCommandSource ?.let {
|
||||
currentArgs = currentArgs.trim()
|
||||
result[it.command] = if (currentArgs.isNotEmpty()) {
|
||||
currentArgs.split(argsSeparator).toTypedArray()
|
||||
} else {
|
||||
emptyArray()
|
||||
}
|
||||
currentArgs = ""
|
||||
currentBotCommandSource = null
|
||||
}
|
||||
for (textSource in this) {
|
||||
if (textSource is BotCommandTextSource) {
|
||||
includeCurrent()
|
||||
currentBotCommandSource = textSource
|
||||
} else {
|
||||
currentArgs += textSource.source
|
||||
}
|
||||
}
|
||||
includeCurrent()
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun TextedWithTextSources.parseCommandsWithParams(
|
||||
argsSeparator: Regex = defaultArgsSeparator
|
||||
) = textSources ?.parseCommandsWithParams(argsSeparator) ?: emptyMap()
|
||||
|
||||
/**
|
||||
* Parse commands and their args. Logic will find command, get all subsequent data as args until new command
|
||||
*/
|
||||
fun ContentMessage<TextContent>.parseCommandsWithParams(
|
||||
argsSeparator: Regex = defaultArgsSeparator
|
||||
) = content.parseCommandsWithParams(argsSeparator)
|
Loading…
Reference in New Issue
Block a user