add expression provider

This commit is contained in:
InsanusMokrassar 2021-03-30 21:05:26 +06:00
parent 8cc2503934
commit b3a9a9875f
2 changed files with 129 additions and 6 deletions

View File

@ -4,13 +4,13 @@ org.gradle.parallel=true
kotlin.js.generate.externals=true
kotlin.incremental=true
kotlin_version=1.4.31
kotlin_version=1.4.32
kotlin_coroutines_version=1.4.3
kotlin_serialisation_runtime_version=1.1.0
plagubot_version=0.1.5
plagubot_version=0.1.6
micro_utils_version=0.4.31-branch_0.4.31-build13
tgbotapi_libraries_version=0.0.2-branch_master-build12
micro_utils_version=0.4.31
tgbotapi_libraries_version=0.0.3-branch_master-build14
project_group=dev.inmo
project_version=0.1.6

View File

@ -16,8 +16,7 @@ import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitDataCallbackQuery
import dev.inmo.tgbotapi.extensions.utils.asSlotMachineReelImage
import dev.inmo.tgbotapi.extensions.utils.calculateSlotMachineResult
import dev.inmo.tgbotapi.extensions.utils.formatting.buildEntities
import dev.inmo.tgbotapi.extensions.utils.formatting.regular
import dev.inmo.tgbotapi.extensions.utils.formatting.*
import dev.inmo.tgbotapi.extensions.utils.shortcuts.executeUnsafe
import dev.inmo.tgbotapi.extensions.utils.types.buttons.InlineKeyboardMarkup
import dev.inmo.tgbotapi.requests.DeleteMessage
@ -34,6 +33,8 @@ import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.toList
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlin.math.abs
import kotlin.random.Random
@Serializable
sealed class CaptchaProvider {
@ -195,3 +196,125 @@ data class SimpleCaptchaProvider(
}
}
private object ExpressionBuilder {
sealed class ExpressionOperation {
object PlusExpressionOperation : ExpressionOperation() {
override fun asString(): String = "+"
override fun Int.perform(other: Int): Int = plus(other)
}
object MinusExpressionOperation : ExpressionOperation() {
override fun asString(): String = "-"
override fun Int.perform(other: Int): Int = minus(other)
}
abstract fun asString(): String
abstract fun Int.perform(other: Int): Int
}
private val experssions = listOf(ExpressionOperation.PlusExpressionOperation, ExpressionOperation.MinusExpressionOperation)
private fun createNumber(max: Int) = Random.nextInt(max + 1)
fun generateResult(max: Int, operationsNumber: Int = 1): Int {
val operations = (0 until operationsNumber).map { experssions.random() }
var current = createNumber(max)
operations.forEach {
val rightOne = createNumber(max)
current = it.run { current.perform(rightOne) }
}
return current
}
fun createExpression(max: Int, operationsNumber: Int = 1): Pair<Int, String> {
val operations = (0 until operationsNumber).map { experssions.random() }
var current = createNumber(max)
var numbersString = "$current"
operations.forEach {
val rightOne = createNumber(max)
current = it.run { current.perform(rightOne) }
numbersString = " ${it.asString()} $numbersString"
}
return current to numbersString
}
}
@Serializable
data class ExpressionCaptchaProvider(
val checkTimeSeconds: Seconds = 60,
val captchaText: String = "solve next captcha:",
val maxPerNumber: Int = 10,
val operations: Int = 2,
val answers: Int = 6,
val kick: Boolean = true
) : CaptchaProvider() {
@Transient
private val checkTimeSpan = checkTimeSeconds.seconds
override suspend fun BehaviourContext.doAction(
eventDateTime: DateTime,
chat: GroupChat,
newUsers: List<User>
) {
val userBanDateTime = eventDateTime + checkTimeSpan
newUsers.mapNotNull {
safelyWithoutExceptions {
launch {
doInSubContext {
val callbackData = ExpressionBuilder.createExpression(
maxPerNumber,
operations
)
val correctAnswer = callbackData.first.toString()
val answers = (0 until answers - 1).map {
ExpressionBuilder.generateResult(maxPerNumber, operations)
}.toMutableList().also { orderedAnswers ->
val correctAnswerPosition = Random.nextInt(orderedAnswers.size)
orderedAnswers.add(correctAnswerPosition, callbackData.first)
}.toList()
val sentMessage = sendTextMessage(
chat,
buildEntities {
+it.mention(it.firstName)
regular(", $captchaText ")
bold(callbackData.second)
},
replyMarkup = dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup(
answers.map {
CallbackDataInlineKeyboardButton(it.toString(), it.toString())
}.chunked(3)
)
)
suspend fun removeRedundantMessages() {
safelyWithoutExceptions {
deleteMessage(sentMessage)
}
}
val job = parallel {
waitDataCallbackQuery {
if (it.id == user.id && this.data == correctAnswer) {
this
} else {
null
}
}.first()
removeRedundantMessages()
safelyWithoutExceptions { restrictChatMember(chat, it, permissions = LeftRestrictionsChatPermissions) }
stop()
}
delay((userBanDateTime - eventDateTime).millisecondsLong)
if (job.isActive) {
job.cancel()
if (kick) {
safelyWithoutExceptions { kickChatMember(chat, it) }
}
}
}
}
}
}.joinAll()
}
}