mirror of
https://github.com/InsanusMokrassar/TelegramBotAPI.git
synced 2026-01-23 05:37:57 +00:00
migration
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class ProxySettings(
|
||||
val host: String = "localhost",
|
||||
val port: Int = 1080,
|
||||
val username: String? = null,
|
||||
val password: String? = null
|
||||
)
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||
|
||||
import com.soywiz.klock.DateTime
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
|
||||
private fun now(): Long = DateTime.nowUnixLong()
|
||||
|
||||
class CommonLimiter(
|
||||
private val lockCount: Int = 10,
|
||||
private val regenTime: Long = 20 * 1000L // 20 seconds for full regen of opportunity to send message
|
||||
) : RequestLimiter {
|
||||
private var doLimit: Boolean = false
|
||||
|
||||
private val counterChannel = Channel<Unit>(Channel.UNLIMITED)
|
||||
private val scope = CoroutineScope(Dispatchers.Default)
|
||||
private val counterJob = scope.launch {
|
||||
var wasLastSecond = 0
|
||||
var lastCountTime = now()
|
||||
var limitManagementJob: Job? = null
|
||||
var removeLimitTime: Long = lastCountTime
|
||||
for (counter in counterChannel) {
|
||||
val now = now()
|
||||
if (now - lastCountTime > 1000) {
|
||||
lastCountTime = now
|
||||
wasLastSecond = 1
|
||||
} else {
|
||||
wasLastSecond++
|
||||
}
|
||||
if (wasLastSecond >= lockCount) {
|
||||
removeLimitTime = now + regenTime
|
||||
if (limitManagementJob == null) {
|
||||
limitManagementJob = launch {
|
||||
doLimit = true
|
||||
var internalNow = now()
|
||||
while (internalNow < removeLimitTime) {
|
||||
delay(removeLimitTime - internalNow)
|
||||
internalNow = now()
|
||||
}
|
||||
doLimit = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (now > removeLimitTime) {
|
||||
limitManagementJob = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val quoterChannel = Channel<Unit>(Channel.CONFLATED)
|
||||
private val tickerJob = scope.launch {
|
||||
while (isActive) {
|
||||
quoterChannel.send(Unit)
|
||||
delay(1000L)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun <T> limit(block: suspend () -> T): T {
|
||||
counterChannel.send(Unit)
|
||||
return if (!doLimit) {
|
||||
block()
|
||||
} else {
|
||||
quoterChannel.receive()
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||
|
||||
object EmptyLimiter : RequestLimiter {
|
||||
override suspend fun <T> limit(block: suspend () -> T): T = block()
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.math.pow
|
||||
|
||||
private sealed class RequestEvent
|
||||
private class AddRequest(
|
||||
val continuation: Continuation<Long>
|
||||
) : RequestEvent()
|
||||
private object CompleteRequest : RequestEvent()
|
||||
|
||||
@Serializable
|
||||
data class PowLimiter(
|
||||
private val minAwaitTime: Long = 0L,
|
||||
private val maxAwaitTime: Long = 10000L,
|
||||
private val powValue: Double = 4.0,
|
||||
private val powK: Double = 0.0016
|
||||
) : RequestLimiter {
|
||||
@Transient
|
||||
private val scope = CoroutineScope(Dispatchers.Default)
|
||||
@Transient
|
||||
private val eventsChannel = Channel<RequestEvent>(Channel.UNLIMITED)
|
||||
@Transient
|
||||
private val awaitTimeRange = minAwaitTime .. maxAwaitTime
|
||||
|
||||
init {
|
||||
scope.launch {
|
||||
var requestsInWork: Double = 0.0
|
||||
for (event in eventsChannel) {
|
||||
when (event) {
|
||||
is AddRequest -> {
|
||||
val awaitTime = (((requestsInWork.pow(powValue) * powK) * 1000L).toLong())
|
||||
requestsInWork++
|
||||
|
||||
event.continuation.resume(
|
||||
if (awaitTime in awaitTimeRange) {
|
||||
awaitTime
|
||||
} else {
|
||||
if (awaitTime < minAwaitTime) {
|
||||
minAwaitTime
|
||||
} else {
|
||||
maxAwaitTime
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
is CompleteRequest -> requestsInWork--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun <T> limit(
|
||||
block: suspend () -> T
|
||||
): T {
|
||||
val delayMillis = suspendCoroutine<Long> {
|
||||
scope.launch { eventsChannel.send(AddRequest(it)) }
|
||||
}
|
||||
delay(delayMillis)
|
||||
return try {
|
||||
block()
|
||||
} finally {
|
||||
eventsChannel.send(CompleteRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.github.insanusmokrassar.TelegramBotAPI.bot.settings.limiters
|
||||
|
||||
interface RequestLimiter {
|
||||
/**
|
||||
* Use limit for working of block (like delay between or after, for example)
|
||||
*/
|
||||
suspend fun <T> limit(block: suspend () -> T): T
|
||||
}
|
||||
Reference in New Issue
Block a user