diff --git a/src/main/kotlin/com/github/djaler/evilbot/handlers/ScamHandler.kt b/src/main/kotlin/com/github/djaler/evilbot/handlers/ScamHandler.kt new file mode 100644 index 00000000..75d81dd2 --- /dev/null +++ b/src/main/kotlin/com/github/djaler/evilbot/handlers/ScamHandler.kt @@ -0,0 +1,123 @@ +package com.github.djaler.evilbot.handlers + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.readValue +import com.github.djaler.evilbot.handlers.base.CallbackQueryHandler +import com.github.djaler.evilbot.handlers.base.CommonMessageHandler +import com.github.djaler.evilbot.service.ChatService +import com.github.djaler.evilbot.service.UserService +import com.github.djaler.evilbot.utils.createCallbackDataForHandler +import dev.inmo.tgbotapi.bot.RequestsExecutor +import dev.inmo.tgbotapi.extensions.api.answers.answerCallbackQuery +import dev.inmo.tgbotapi.extensions.api.chat.members.banChatMember +import dev.inmo.tgbotapi.extensions.api.deleteMessage +import dev.inmo.tgbotapi.extensions.api.send.reply +import dev.inmo.tgbotapi.extensions.utils.asFromUserMessage +import dev.inmo.tgbotapi.extensions.utils.asPossiblyReplyMessage +import dev.inmo.tgbotapi.extensions.utils.asPublicChat +import dev.inmo.tgbotapi.extensions.utils.asTextContent +import dev.inmo.tgbotapi.types.UserId +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardButtons.CallbackDataInlineKeyboardButton +import dev.inmo.tgbotapi.types.buttons.InlineKeyboardMarkup +import dev.inmo.tgbotapi.types.message.abstracts.CommonMessage +import dev.inmo.tgbotapi.types.queries.callback.MessageDataCallbackQuery +import dev.inmo.tgbotapi.utils.PreviewFeature +import org.springframework.core.io.support.PathMatchingResourcePatternResolver +import org.springframework.stereotype.Component +import javax.annotation.PostConstruct + + +@Component +class ScamHandler( + private val objectMapper: ObjectMapper, + private val chatService: ChatService, + private val userService: UserService, + private val requestsExecutor: RequestsExecutor +) : CommonMessageHandler() { + + private lateinit var triggers: List + + override val order = Int.MAX_VALUE + + @PostConstruct + fun init() { + val resources = PathMatchingResourcePatternResolver().getResources("classpath:spam/*.json") + + triggers = resources.flatMap { resource -> + val reactions: List = objectMapper.readValue(resource.inputStream) + reactions + } + } + + override suspend fun handleMessage(message: CommonMessage<*>): Boolean { + val content = message.content.asTextContent() ?: return false + + if (triggers.isNotEmpty() && + triggers.none { Regex(it, RegexOption.IGNORE_CASE).containsMatchIn(content.text) } + ){ + return false + } + + val chat = message.chat.asPublicChat() ?: return false + val user = message.asFromUserMessage()?.user ?: return false + + val (chatEntity, _) = chatService.getOrCreateChatFrom(chat) + val (userEntity, _) = userService.getOrCreateUserFrom(user) + + val statistic = userService.getStatistic(userEntity, chatEntity) + val buttonLabels = listOf("Пощадить", "Нет пощады") + + if (statistic == null || statistic.messagesCount < 10) { + val buttons = buttonLabels.map { label -> + CallbackDataInlineKeyboardButton( + label, + createCallbackDataForHandler( + ScamCallbackData(user.id).encode(), + ScamCallbackHandler::class.java + ) + ) + } + + requestsExecutor.reply( + message, + "Ты похож на скамера, что делать?", + replyMarkup = InlineKeyboardMarkup(listOf(buttons)) + ) + + return true + } + return false + } +} + +@Component +class ScamCallbackHandler( + private val requestsExecutor: RequestsExecutor +) : CallbackQueryHandler() { + @OptIn(PreviewFeature::class) + override suspend fun handleCallback(query: MessageDataCallbackQuery, data: String) { + val chat = query.message.chat + requestsExecutor.answerCallbackQuery(query, "Никакой пощады для скамеров") + requestsExecutor.banChatMember(chat.id, ScamCallbackData.decode(data).userId) + query.message.asPossiblyReplyMessage()?.replyTo?.let { + requestsExecutor.deleteMessage(chat.id, it.messageId) + } + requestsExecutor.deleteMessage(chat.id, query.message.messageId) + } +} + +data class ScamCallbackData( + val userId: UserId +) { + companion object { + fun decode(data: String): ScamCallbackData { + return ScamCallbackData( + UserId(data.toLong()) + ) + } + } + + fun encode(): String { + return userId.chatId.toString() + } +} \ No newline at end of file diff --git a/src/main/resources/spam/scam_trigger.json b/src/main/resources/spam/scam_trigger.json new file mode 100644 index 00000000..e3f38537 --- /dev/null +++ b/src/main/resources/spam/scam_trigger.json @@ -0,0 +1,8 @@ +[ + "\\bкрипта\\b", + "\\bкриптовалюта\\b", + "\\bдостойный доход\\b", + "\\bгибкий график\\b", + "\\bудаленная работа\\b", + "\\bпредлагаем сотрудничество\\b" +] \ No newline at end of file