CaptchaPlaguBotPlugin/src/main/kotlin/dev/inmo/plagubot/plugins/captcha/Plugin.kt

133 lines
6.3 KiB
Kotlin
Raw Normal View History

2021-02-17 13:24:28 +00:00
package dev.inmo.plagubot.plugins.captcha
2021-02-17 18:27:18 +00:00
import dev.inmo.micro_utils.coroutines.*
2021-02-17 13:24:28 +00:00
import dev.inmo.micro_utils.repos.create
import dev.inmo.plagubot.Plugin
import dev.inmo.plagubot.plugins.captcha.db.CaptchaChatsSettingsRepo
import dev.inmo.plagubot.plugins.captcha.settings.ChatSettings
import dev.inmo.tgbotapi.bot.TelegramBot
import dev.inmo.tgbotapi.extensions.api.answers.answerCallbackQuery
import dev.inmo.tgbotapi.extensions.api.chat.members.*
2021-02-17 18:27:18 +00:00
import dev.inmo.tgbotapi.extensions.api.deleteMessage
import dev.inmo.tgbotapi.extensions.api.edit.ReplyMarkup.editMessageReplyMarkup
2021-02-17 13:24:28 +00:00
import dev.inmo.tgbotapi.extensions.api.send.media.reply
import dev.inmo.tgbotapi.extensions.api.send.sendDice
import dev.inmo.tgbotapi.extensions.api.send.sendTextMessage
import dev.inmo.tgbotapi.extensions.behaviour_builder.*
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitBaseInlineQuery
import dev.inmo.tgbotapi.extensions.behaviour_builder.expectations.waitDataCallbackQuery
import dev.inmo.tgbotapi.updateshandlers.FlowsUpdatesFilter
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onNewChatMembers
import dev.inmo.tgbotapi.extensions.utils.*
import dev.inmo.tgbotapi.extensions.utils.formatting.buildEntities
import dev.inmo.tgbotapi.extensions.utils.formatting.regular
2021-02-17 18:27:18 +00:00
import dev.inmo.tgbotapi.extensions.utils.shortcuts.executeUnsafe
import dev.inmo.tgbotapi.requests.DeleteMessage
2021-02-17 13:24:28 +00:00
import dev.inmo.tgbotapi.types.MessageEntity.textsources.mention
import dev.inmo.tgbotapi.types.User
import dev.inmo.tgbotapi.types.chat.ChatPermissions
2021-02-17 18:27:18 +00:00
import dev.inmo.tgbotapi.types.chat.LeftRestrictionsChatPermissions
2021-02-17 13:24:28 +00:00
import dev.inmo.tgbotapi.types.dice.SlotMachineDiceAnimationType
2021-02-17 18:27:18 +00:00
import dev.inmo.tgbotapi.types.message.abstracts.Message
2021-02-17 13:24:28 +00:00
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.toList
import kotlinx.serialization.Serializable
import org.jetbrains.exposed.sql.Database
@Serializable
class CaptchaBotPlugin : Plugin {
override suspend fun BehaviourContext.invoke(
database: Database,
params: Map<String, Any>
) {
val repo = CaptchaChatsSettingsRepo(database)
onNewChatMembers(
additionalFilter = {
it.chat.asPublicChat() != null
2021-02-17 18:27:18 +00:00
},
includeFilterByChatInBehaviourSubContext = false
2021-02-17 13:24:28 +00:00
) {
2021-02-17 18:27:18 +00:00
safelyWithoutExceptions { deleteMessage(it) }
2021-02-17 13:24:28 +00:00
val eventDateTime = it.date
val chat = it.chat.requirePublicChat()
val newUsers = it.chatEvent.members
newUsers.forEach { user ->
restrictChatMember(
chat,
user,
permissions = ChatPermissions()
)
}
val settings = repo.getById(it.chat.id) ?: repo.create(ChatSettings(it.chat.id)).firstOrNull() ?: return@onNewChatMembers
val userBanDateTime = eventDateTime + settings.checkTimeSpan
val authorized = Channel<User>(newUsers.size)
2021-02-17 18:27:18 +00:00
val messagesToDelete = Channel<Message>(Channel.UNLIMITED)
2021-02-17 13:24:28 +00:00
val subContexts = newUsers.map {
2021-02-17 18:27:18 +00:00
doInSubContext(stopOnCompletion = false) {
2021-02-17 13:24:28 +00:00
val sentMessage = sendTextMessage(
chat,
buildEntities {
+it.mention(it.firstName)
2021-02-17 18:27:18 +00:00
regular(", ${settings.captchaText}")
2021-02-17 13:24:28 +00:00
}
2021-02-17 18:27:18 +00:00
).also { messagesToDelete.send(it) }
2021-02-17 13:24:28 +00:00
val sentDice = sendDice(
sentMessage.chat,
SlotMachineDiceAnimationType,
replyToMessageId = sentMessage.messageId,
replyMarkup = slotMachineReplyMarkup()
2021-02-17 18:27:18 +00:00
).also { messagesToDelete.send(it) }
2021-02-17 13:24:28 +00:00
val reels = sentDice.content.dice.calculateSlotMachineResult()!!
val leftToClick = mutableListOf(
reels.left.asSlotMachineReelImage.text,
reels.center.asSlotMachineReelImage.text,
reels.right.asSlotMachineReelImage.text
)
launch {
2021-02-17 18:27:18 +00:00
val clicked = arrayOf<String?>(null, null, null)
2021-02-17 13:24:28 +00:00
while (leftToClick.isNotEmpty()) {
val userClicked = waitDataCallbackQuery { if (user.id == it.id) this else null }.first()
if (userClicked.data == leftToClick.first()) {
2021-02-17 18:27:18 +00:00
clicked[3 - leftToClick.size] = leftToClick.removeAt(0)
if (clicked.contains(null)) {
safelyWithoutExceptions { answerCallbackQuery(userClicked, "Ok, next one") }
editMessageReplyMarkup(sentDice, slotMachineReplyMarkup(clicked[0], clicked[1], clicked[2]))
} else {
safelyWithoutExceptions { answerCallbackQuery(userClicked, "Thank you and welcome", showAlert = true) }
safelyWithoutExceptions { deleteMessage(sentMessage) }
safelyWithoutExceptions { deleteMessage(sentDice) }
}
} else {
safelyWithoutExceptions { answerCallbackQuery(userClicked, "Nope") }
2021-02-17 13:24:28 +00:00
}
}
authorized.send(it)
2021-02-17 18:27:18 +00:00
safelyWithoutExceptions { restrictChatMember(chat, it, permissions = LeftRestrictionsChatPermissions) }
2021-02-17 13:24:28 +00:00
stop()
}
this to it
}
}
delay((userBanDateTime - eventDateTime).millisecondsLong)
authorized.close()
2021-02-17 18:27:18 +00:00
val authorizedUsers = authorized.toList()
2021-02-17 13:24:28 +00:00
subContexts.forEach { (context, user) ->
if (user !in authorizedUsers) {
context.stop()
safelyWithoutExceptions { kickChatMember(chat, user) }
}
}
2021-02-17 18:27:18 +00:00
messagesToDelete.close()
for (message in messagesToDelete) {
executeUnsafe(DeleteMessage(message.chat.id, message.messageId), retries = 0)
}
2021-02-17 13:24:28 +00:00
}
}
}