mirror of
				https://github.com/InsanusMokrassar/TelegramBotAPI.git
				synced 2025-10-25 09:10:07 +00:00 
			
		
		
		
	add opportunity to use several bots in one to serve bots requests
This commit is contained in:
		| @@ -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) | ||||||
		Reference in New Issue
	
	Block a user