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

187 lines
8.2 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
2021-02-23 06:00:44 +00:00
import dev.inmo.tgbotapi.extensions.behaviour_builder.triggers_handling.onCommand
2021-02-17 13:24:28 +00:00
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
2021-02-23 07:29:17 +00:00
import dev.inmo.tgbotapi.libraries.cache.admins.*
2021-02-17 18:27:18 +00:00
import dev.inmo.tgbotapi.requests.DeleteMessage
2021-02-23 06:00:44 +00:00
import dev.inmo.tgbotapi.types.BotCommand
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-23 06:00:44 +00:00
import dev.inmo.tgbotapi.types.chat.abstracts.Chat
import dev.inmo.tgbotapi.types.chat.abstracts.PublicChat
2021-02-17 13:24:28 +00:00
import dev.inmo.tgbotapi.types.dice.SlotMachineDiceAnimationType
2021-02-23 06:00:44 +00:00
import dev.inmo.tgbotapi.types.message.abstracts.*
import dev.inmo.tgbotapi.types.message.content.abstracts.MessageContent
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
2021-02-23 06:00:44 +00:00
private const val enableAutoDeleteCommands = "captcha_auto_delete_commands_on"
private const val disableAutoDeleteCommands = "captcha_auto_delete_commands_off"
2021-02-17 13:24:28 +00:00
@Serializable
class CaptchaBotPlugin : Plugin {
2021-02-23 06:00:44 +00:00
override suspend fun getCommands(): List<BotCommand> = listOf(
BotCommand(
enableAutoDeleteCommands,
"Enable auto removing of commands addressed to captcha plugin"
),
BotCommand(
disableAutoDeleteCommands,
"Disable auto removing of commands addressed to captcha plugin"
)
)
2021-02-17 13:24:28 +00:00
override suspend fun BehaviourContext.invoke(
database: Database,
params: Map<String, Any>
) {
val repo = CaptchaChatsSettingsRepo(database)
2021-02-23 06:00:44 +00:00
val adminsAPI = params.adminsPlugin ?.adminsAPI(database)
suspend fun Chat.settings() = repo.getById(id) ?: repo.create(ChatSettings(id)).first()
2021-02-17 13:24:28 +00:00
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()
)
}
2021-02-23 06:00:44 +00:00
val settings = it.chat.settings() ?: return@onNewChatMembers
2021-02-17 13:24:28 +00:00
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
}
2021-02-23 06:00:44 +00:00
if (adminsAPI != null) {
onCommand(
enableAutoDeleteCommands,
requireOnlyCommandInMessage = false
) { message ->
2021-02-23 07:29:17 +00:00
message.doAfterVerification(adminsAPI) {
2021-02-23 06:00:44 +00:00
val settings = message.chat.settings()
repo.update(
message.chat.id,
settings.copy(autoRemoveCommands = true)
)
deleteMessage(message)
}
}
onCommand(
disableAutoDeleteCommands,
requireOnlyCommandInMessage = false
) { message ->
2021-02-23 07:29:17 +00:00
message.doAfterVerification(adminsAPI) {
2021-02-23 06:00:44 +00:00
val settings = message.chat.settings()
repo.update(
message.chat.id,
settings.copy(autoRemoveCommands = false)
)
}
}
}
2021-02-17 13:24:28 +00:00
}
}