mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2024-11-15 21:03:48 +00:00
add opportunity to use several bots in one to serve bots requests
This commit is contained in:
parent
459414e7dd
commit
83fb7f7bcb
@ -0,0 +1,210 @@
|
|||||||
|
package dev.inmo.tgbotapi.bot.multiserver
|
||||||
|
|
||||||
|
import dev.inmo.tgbotapi.bot.Ktor.KtorRequestsExecutorBuilder
|
||||||
|
import dev.inmo.tgbotapi.bot.Ktor.telegramBot
|
||||||
|
import dev.inmo.tgbotapi.bot.RequestsExecutor
|
||||||
|
import dev.inmo.tgbotapi.bot.TelegramBot
|
||||||
|
import dev.inmo.tgbotapi.requests.abstracts.Request
|
||||||
|
import dev.inmo.tgbotapi.utils.TelegramAPIUrlsKeeper
|
||||||
|
import dev.inmo.tgbotapi.utils.telegramBotAPIDefaultUrl
|
||||||
|
import kotlinx.coroutines.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This type of [RequestsExecutor] (aka [TelegramBot]) has been created to aggregate several bots under the hood and make
|
||||||
|
* requests, for example, with changing of api url
|
||||||
|
*
|
||||||
|
* @param bots Bots which will be used to [execute] [Request]s
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one [execute]. By default, will select next
|
||||||
|
* [TelegramBot] when called (or first when current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [close] method. By default, will close all [bots]
|
||||||
|
*/
|
||||||
|
class SimpleMultiServerRequestsExecutor(
|
||||||
|
private val bots: List<TelegramBot>,
|
||||||
|
private val botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
private val onClose: () -> Unit = {
|
||||||
|
bots.forEach(TelegramBot::close)
|
||||||
|
}
|
||||||
|
) : RequestsExecutor {
|
||||||
|
override suspend fun <T : Any> execute(request: Request<T>): T {
|
||||||
|
var currentBot = bots.botSelector(-1, null)
|
||||||
|
while (currentCoroutineContext().isActive) {
|
||||||
|
val i = bots.indexOf(currentBot)
|
||||||
|
runCatching {
|
||||||
|
currentBot.execute(request)
|
||||||
|
}.onSuccess {
|
||||||
|
return it
|
||||||
|
}.onFailure {
|
||||||
|
currentBot = bots.botSelector(i, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
error("Coroutine has been terminated")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* @param keepers Will be used to create result [bots]
|
||||||
|
* @param builder Will be called with each item from [keepers] in process of bots creation
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one [execute]. By default, will select next
|
||||||
|
* [TelegramBot] when called (or first when current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [close] method. By default, will close all [bots]
|
||||||
|
*/
|
||||||
|
inline operator fun invoke(
|
||||||
|
keepers: Iterable<TelegramAPIUrlsKeeper>,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.(TelegramAPIUrlsKeeper) -> Unit = {},
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: ((List<TelegramBot>) -> Unit)? = null
|
||||||
|
): SimpleMultiServerRequestsExecutor {
|
||||||
|
val bots = keepers.map { telegramBot(it) { builder(it) } }
|
||||||
|
return if (onClose == null) {
|
||||||
|
SimpleMultiServerRequestsExecutor(bots, botSelector)
|
||||||
|
} else {
|
||||||
|
SimpleMultiServerRequestsExecutor(bots, botSelector) {
|
||||||
|
onClose(bots)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tokens Will be used to create result [bots]
|
||||||
|
* @param builder Will be called with each item from [tokens] in process of bots creation
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one [execute]. By default, will select next
|
||||||
|
* [TelegramBot] when called (or first when current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [close] method. By default, will close all [bots]
|
||||||
|
*/
|
||||||
|
inline operator fun invoke(
|
||||||
|
tokens: Iterable<String>,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.(String) -> Unit = {},
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: ((List<TelegramBot>) -> Unit)? = null
|
||||||
|
): SimpleMultiServerRequestsExecutor {
|
||||||
|
val bots = tokens.map { telegramBot(it) { builder(it) } }
|
||||||
|
return if (onClose == null) {
|
||||||
|
SimpleMultiServerRequestsExecutor(bots, botSelector)
|
||||||
|
} else {
|
||||||
|
SimpleMultiServerRequestsExecutor(bots, botSelector) {
|
||||||
|
onClose(bots)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tokens [Pair]s with first parameter as a token and second parameter api url. Will be used to create
|
||||||
|
* result [bots]
|
||||||
|
* @param builder Will be called with each item from [tokens] in process of bots creation
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one [execute]. By default, will select next
|
||||||
|
* [TelegramBot] when called (or first when current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [close] method. By default, will close all [bots]
|
||||||
|
*/
|
||||||
|
inline operator fun invoke(
|
||||||
|
tokens: Iterable<Pair<String, String>>,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.(Pair<String, String>) -> Unit = {},
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: ((List<TelegramBot>) -> Unit)? = null
|
||||||
|
): SimpleMultiServerRequestsExecutor {
|
||||||
|
val bots = tokens.map { telegramBot(it.first, it.second) { builder(it) } }
|
||||||
|
return if (onClose == null) {
|
||||||
|
SimpleMultiServerRequestsExecutor(bots, botSelector)
|
||||||
|
} else {
|
||||||
|
SimpleMultiServerRequestsExecutor(bots, botSelector) {
|
||||||
|
onClose(bots)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates [SimpleMultiServerRequestsExecutor]
|
||||||
|
*
|
||||||
|
* @param bots Bots which will be used to [SimpleMultiServerRequestsExecutor.execute] [Request]s
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one
|
||||||
|
* [SimpleMultiServerRequestsExecutor.execute]. By default, will select next [TelegramBot] when called (or first when
|
||||||
|
* current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [SimpleMultiServerRequestsExecutor.close] method. By default, will close all [bots]
|
||||||
|
*/
|
||||||
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
|
inline fun telegramBot(
|
||||||
|
bots: List<TelegramBot>,
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: () -> Unit = {
|
||||||
|
bots.forEach(TelegramBot::close)
|
||||||
|
}
|
||||||
|
): TelegramBot = SimpleMultiServerRequestsExecutor(bots, botSelector, onClose)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param keepers Will be used to create result [SimpleMultiServerRequestsExecutor.bots]
|
||||||
|
* @param builder Will be called with each item from [keepers] in process of bots creation
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one
|
||||||
|
* [SimpleMultiServerRequestsExecutor.execute]. By default, will select next [TelegramBot] when called (or first when
|
||||||
|
* current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [SimpleMultiServerRequestsExecutor.close] method. By default,
|
||||||
|
* will close all [SimpleMultiServerRequestsExecutor.bots]
|
||||||
|
*/
|
||||||
|
inline fun telegramBot(
|
||||||
|
keepers: Iterable<TelegramAPIUrlsKeeper>,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.(TelegramAPIUrlsKeeper) -> Unit = {},
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: ((List<TelegramBot>) -> Unit)? = null
|
||||||
|
): TelegramBot = SimpleMultiServerRequestsExecutor(keepers, builder, botSelector, onClose)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tokens Will be used to create result [SimpleMultiServerRequestsExecutor.bots]
|
||||||
|
* @param builder Will be called with each item from [tokens] in process of bots creation
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one
|
||||||
|
* [SimpleMultiServerRequestsExecutor.execute]. By default, will select next [TelegramBot] when called (or first when
|
||||||
|
* current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [SimpleMultiServerRequestsExecutor.close] method. By default,
|
||||||
|
* will close all [SimpleMultiServerRequestsExecutor.bots]
|
||||||
|
*/
|
||||||
|
inline fun telegramBot(
|
||||||
|
tokens: Iterable<String>,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.(String) -> Unit = {},
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: ((List<TelegramBot>) -> Unit)? = null
|
||||||
|
): TelegramBot = SimpleMultiServerRequestsExecutor(tokens, builder, botSelector, onClose)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param tokens [Pair]s with first parameter as a token and second parameter api url. Will be used to create
|
||||||
|
* result [SimpleMultiServerRequestsExecutor.bots]
|
||||||
|
* @param builder Will be called with each item from [tokens] in process of bots creation
|
||||||
|
* @param botSelector It is strategy by which the bot is selected for the execution. This lambda will receive **-1**
|
||||||
|
* when request execution just started and this call is first in context of one
|
||||||
|
* [SimpleMultiServerRequestsExecutor.execute]. By default, will select next
|
||||||
|
* [TelegramBot] when called (or first when current index is last or -1)
|
||||||
|
* @param onClose This method will be called inside of [SimpleMultiServerRequestsExecutor.close] method. By default,
|
||||||
|
* will close all [SimpleMultiServerRequestsExecutor.bots]
|
||||||
|
*/
|
||||||
|
inline fun telegramBot(
|
||||||
|
tokens: Iterable<Pair<String, String>>,
|
||||||
|
crossinline builder: KtorRequestsExecutorBuilder.(Pair<String, String>) -> Unit = {},
|
||||||
|
noinline botSelector: suspend List<TelegramBot>.(currentBotIndex: Int, t: Throwable?) -> TelegramBot = { i, _ ->
|
||||||
|
getOrElse(i + 1) { first() }
|
||||||
|
},
|
||||||
|
noinline onClose: ((List<TelegramBot>) -> Unit)? = null
|
||||||
|
): TelegramBot = SimpleMultiServerRequestsExecutor(tokens, builder, botSelector, onClose)
|
Loading…
Reference in New Issue
Block a user