From fdd5ad7ff09e657c7aee954af8e2be741d864b09 Mon Sep 17 00:00:00 2001 From: profitroll Date: Mon, 14 Aug 2023 12:11:53 +0200 Subject: [PATCH] This commit closes #13 --- classes/pyrogroup.py | 13 +++++++++ locale/de.json | 5 +++- locale/en.json | 9 ++++--- locale/uk.json | 5 +++- modules/kicker.py | 17 +++++++----- plugins/callbacks/emoji_button.py | 7 ++--- plugins/commands/ban_failed.py | 44 +++++++++++++++++++++++++++++++ plugins/handlers/user_join.py | 9 ++++--- 8 files changed, 91 insertions(+), 18 deletions(-) create mode 100644 plugins/commands/ban_failed.py diff --git a/classes/pyrogroup.py b/classes/pyrogroup.py index 73fc1bb..a3518e8 100644 --- a/classes/pyrogroup.py +++ b/classes/pyrogroup.py @@ -22,6 +22,7 @@ class PyroGroup: id: int locale: Union[str, None] locale_auto: bool + ban_failed: bool @classmethod async def create_if_not_exists( @@ -29,6 +30,7 @@ class PyroGroup: id: int, locale: Union[str, None] = sync.config_get("locale", "defaults", "group"), locale_auto: bool = sync.config_get("locale_auto", "defaults", "group"), + ban_failed: bool = sync.config_get("ban_failed", "defaults", "group"), ): db_entry = await col_groups.find_one( { @@ -42,6 +44,7 @@ class PyroGroup: "id": id, "locale": locale, "locale_auto": locale_auto, + "ban_failed": ban_failed, } ) db_entry = await col_groups.find_one({"_id": inserted.inserted_id}) @@ -65,6 +68,16 @@ class PyroGroup: {"_id": self._id}, {"$set": {"locale_auto": enabled}} ) + async def set_ban_failed(self, enabled: bool) -> None: + logger.debug( + "Banning users that failed the captcha in group %s has been set to %s", + self.id, + enabled, + ) + await col_groups.update_one( + {"_id": self._id}, {"$set": {"ban_failed": enabled}} + ) + # Group settings # User locale def select_locale( diff --git a/locale/de.json b/locale/de.json index 887910f..9250637 100644 --- a/locale/de.json +++ b/locale/de.json @@ -14,11 +14,14 @@ }, "commands": { "help": "Nützliche Informationen anzeigen", + "ban_failed": "Umschaltverbot bei fehlender Verifizierung", "language": "Sprache des Bots in dieser Gruppe einstellen", "language_auto": "Automatische Sprachwahl umschalten" }, "messages": { - "help": "Hallo! Dieser Bot kann Ihnen helfen, sich gegen nervige Bots zu schützen, indem er Emoji-Captchas beim Beitritt erzwingt.\n\nFügen Sie diesen Bot zu Ihrer gewünschten Gruppe hinzu und geben Sie ihm die Berechtigungen **Nachrichten löschen** und **Benutzer sperren**. Sie können auch die Sprache des Bots in der Gruppe mit /language ändern und die automatische Sprache pro Benutzer mit /language_auto umschalten.\n\nDieser Bot ist Open Source, also können Sie ihn selbst hosten oder nach Ihren Wünschen verändern: https://git.end-play.xyz/profitroll/EmojiCaptchaBot\n\nWenn Sie einen Fehler melden oder einen Vorschlag machen möchten – besuchen Sie die [Problemseite](https://git.end-play.xyz/profitroll/EmojiCaptchaBot/issues) des Bots auf git.\n\nEinen schönen Tag noch :)", + "help": "Hallo! Dieser Bot kann Ihnen helfen, sich gegen nervige Bots zu schützen, indem er Emoji-Captchas beim Beitritt erzwingt.\n\nFügen Sie diesen Bot zu Ihrer gewünschten Gruppe hinzu und geben Sie ihm die Berechtigungen **Nachrichten löschen** und **Benutzer sperren**.\n\nVerfügbare Kommandos:\n• /ban_failed - Bannen bei Zeitüberschreitung oder fehlgeschlagenem Captcha umschalten\n• /language - Sprache des Bots ändern\n• /language_auto - automatische Sprache pro Benutzer umschalten\n\nKommandos, die oben aufgelistet sind, müssen in der Gruppe von ihren Admins oder dem Besitzer ausgeführt werden.\n\nDieser Bot ist Open Source, also können Sie ihn selbst hosten oder nach Ihren Wünschen verändern: https://git.end-play.xyz/profitroll/EmojiCaptchaBot\n\nWenn Sie einen Fehler melden oder einen Vorschlag machen möchten – besuchen Sie die [Problemseite](https://git.end-play.xyz/profitroll/EmojiCaptchaBot/issues) des Bots auf git.\n\nEinen schönen Tag noch :)", + "ban_failed_disabled": "Bann bei Fehlschlag wurde **deaktiviert**. Wenn Benutzer die Überprüfung ignorieren oder sie nicht bestehen, bleiben sie in der Gruppe nur zum Lesen zugelassen.", + "ban_failed_enabled": "Bann bei Fehlschlag wurde **aktiviert**. Wenn Benutzer die Überprüfung ignorieren oder sie nicht bestehen, werden sie sofort aus der Gruppe geworfen und gesperrt.", "locale_auto_disabled": "Die automatische Sprachauswahl auf individueller Basis wurde **deaktiviert**. Bitte beachten Sie, dass jetzt die Sprache der Gruppe verwendet wird. Sie können sie mit /language ändern. Wenn \"Standard\" als Sprache eingestellt ist, wird die Standardsprache des Bots ({default_locale}) verwendet.", "locale_auto_enabled": "Die automatische Sprachauswahl auf individueller Basis wurde **aktiviert**. Bitte beachten Sie, dass die Standardsprache der Gruppe oder des Bots verwendet wird, wenn der Bot kein Sprachpaket für den Benutzer hat. Sie können die Sprache der Gruppe mit /language ändern. Wenn \"Standard\" als Sprache eingestellt ist, wird die Standardsprache des Bots ({default_locale}) verwendet.", "locale_choice": "Okay. Bitte wählen Sie die Sprache mit der Tastatur unten aus.\n\nBitte beachten Sie, dass Sie auch die automatische Sprachauswahl für jeden Benutzer mit dem Befehl /language_auto", diff --git a/locale/en.json b/locale/en.json index a05f5d3..de4d1e0 100644 --- a/locale/en.json +++ b/locale/en.json @@ -11,11 +11,14 @@ }, "commands": { "help": "Show some helpful info", - "language": "Set bot's language in this group", - "language_auto": "Toggle automatic language selection" + "ban_failed": "Toggle ban on verification fail", + "language_auto": "Toggle automatic language selection", + "language": "Set bot's language in this group" }, "messages": { - "help": "Hi! This bot can help you protect against annoying bots by enforcing emoji captcha on join.\n\nIn order to it, add this bot to your desired group and provide it with **Delete Messages** and **Ban Users** permissions. You can also change bot's language in the group using /language and toggle automatic per-user language using /language_auto.\n\nThis bot is open source, so feel free to host it yourself or modify to your liking: https://git.end-play.xyz/profitroll/EmojiCaptchaBot\n\nIf you want to file an issue or make a suggestion – visit bot's [issues page](https://git.end-play.xyz/profitroll/EmojiCaptchaBot/issues) on bot's git.\n\nHave a nice day :)", + "help": "Hi! This bot can help you protect against annoying bots by enforcing emoji captcha on join.\n\nIn order to it, add this bot to your desired group and provide it with **Delete Messages** and **Ban Users** permissions.\n\nAvailable commands:\n• /ban_failed - toggle banning on timeout or captcha fail\n• /language - change bot's language\n• /language_auto - toggle automatic per-user language\n\nCommands listed above must be executes in group by its admins or owner.\n\nThis bot is open source, so feel free to host it yourself or modify to your liking: https://git.end-play.xyz/profitroll/EmojiCaptchaBot\n\nIf you want to file an issue or make a suggestion – visit bot's [issues page](https://git.end-play.xyz/profitroll/EmojiCaptchaBot/issues) on bot's git.\n\nHave a nice day :)", + "ban_failed_disabled": "Ban on fail has been **disabled**. If users ignore verification or fail it, they will remain read-only in the group.", + "ban_failed_enabled": "Ban on fail has been **enabled**. If users ignore verification or fail it, they will be immediately kicked from the group and banned.", "locale_auto_disabled": "Automatic language selection on per-user basis has been **disabled**. Please note that group's language will now be used. You can change it using /language. If \"Default\" language is set – bot's default language ({default_locale}) will be used.", "locale_auto_enabled": "Automatic language selection on per-user basis has been **enabled**. Please note that if bot does not have a language pack for user – group's or bot's default language will be used. You can change group's language using /language. If \"Default\" language is set – bot's default language ({default_locale}) will be used.", "locale_choice": "Alright. Please choose the language using keyboard below.\n\nNote, that you can also enable automatic language selection on per-user basis using command /language_auto", diff --git a/locale/uk.json b/locale/uk.json index 892eeb6..4d31624 100644 --- a/locale/uk.json +++ b/locale/uk.json @@ -10,11 +10,14 @@ }, "commands": { "help": "Показати корисну інформацію", + "ban_failed": "Переключити бан при невдалій верифікації", "language": "Встановити мову бота в цій групі", "language_auto": "Переключити автоматичний вибір мови" }, "messages": { - "help": "Привіт! Цей бот допоможе вам захиститися від настирливих ботів, запровадивши емодзі-капчу при вході в групу.\n\nДля цього додайте цього бота в потрібну вам групу і надайте йому права **Видаляти повідомлення** та **Банити користувачів**. Ви також можете змінити мову бота в групі за допомогою /language та увімкнути автоматичну мову для кожного користувача за допомогою /language_auto.\n\nЦей бот має відкритий вихідний код, тому ви можете хостити його самостійно або модифікувати під себе: https://git.end-play.xyz/profitroll/EmojiCaptchaBot\n\nЯкщо ви хочете повідомити про проблему або внести пропозицію – відвідайте [сторінку підтримки бота](https://git.end-play.xyz/profitroll/EmojiCaptchaBot/issues) на гіті бота.\n\nГарного дня :)", + "help": "Привіт! Цей бот допоможе вам захиститися від настирливих ботів, запровадивши емодзі-капчу при вході в групу.\n\nДля цього додайте цього бота в потрібну вам групу і надайте йому права **Видаляти повідомлення** та **Банити користувачів**.\n\nДоступні команди:\n• /ban_failed - увімкнути заборону після таймауту або невдалого введення капчі\n• /language - змінити мову бота\n• /language_auto - перемкнути автоматичну мову для кожного користувача\n\nКоманди, перераховані вище, повинні виконуватися в групі її адміністраторами або власником.\n\nЦей бот має відкритий вихідний код, тому ви можете хостити його самостійно або модифікувати під себе: https://git.end-play.xyz/profitroll/EmojiCaptchaBot\n\nЯкщо ви хочете повідомити про проблему або внести пропозицію – відвідайте [сторінку підтримки бота](https://git.end-play.xyz/profitroll/EmojiCaptchaBot/issues) на гіті бота.\n\nГарного дня :)", + "ban_failed_disabled": "Блокування при невдалій верифікації було **вимкнено**. Якщо користувачі проігнорують верифікацію або не пройдуть її, вони залишаться в групі тільки для читання.", + "ban_failed_enabled": "Блокування при невдачі було **увімкнено**. Якщо користувач проігнорує верифікацію або не пройде її, його буде негайно вигнано з групи та забанено.", "locale_auto_disabled": "Автоматичний вибір мови для кожного користувача було **вимкнено**. Зверніть увагу, що тепер буде використовуватися мова групи. Ви можете змінити її за допомогою /language. Якщо встановлено мову \"За замовчуванням\" – буде використовуватися мова бота за замовчуванням ({default_locale}).", "locale_auto_enabled": "Автоматичний вибір мови для кожного користувача був **увімкнений**. Зверніть увагу, що якщо бот не має мовного пакета для користувача – буде використовуватися мова групи або бота за замовчуванням. Ви можете змінити мову групи за допомогою /language. Якщо встановлено мову \"За замовчуванням\" – буде використовуватися мова бота за замовчуванням ({default_locale}).", "locale_choice": "Гаразд. Будь ласка, оберіть мову за допомогою клавіатури нижче.\n\nЗауважте, що ви також можете увімкнути автоматичний вибір мови для кожного користувача за допомогою команди /language_auto", diff --git a/modules/kicker.py b/modules/kicker.py index 354d701..09239b6 100644 --- a/modules/kicker.py +++ b/modules/kicker.py @@ -1,18 +1,21 @@ from pyrogram.types import Message from classes.pyroclient import PyroClient +from classes.pyrogroup import PyroGroup async def kick_unstarted( app: PyroClient, user_id: int, group_id: int, message_id: int ) -> None: user = await app.find_user(user_id, group_id) + group = await PyroGroup.create_if_not_exists(group_id) if user.score == 0 and user.failed == 0: - banned = await app.ban_chat_member(group_id, user_id) + if group.ban_failed: + banned = await app.ban_chat_member(group_id, user_id) - if isinstance(banned, Message): - await banned.delete() + if isinstance(banned, Message): + await banned.delete() await app.delete_messages(group_id, message_id) @@ -21,11 +24,13 @@ async def kick_unverified( app: PyroClient, user_id: int, group_id: int, message_id: int ) -> None: user = await app.find_user(user_id, group_id) + group = await PyroGroup.create_if_not_exists(group_id) if user.score < 6 or user.failed: - banned = await app.ban_chat_member(group_id, user_id) + if group.ban_failed: + banned = await app.ban_chat_member(group_id, user_id) - if isinstance(banned, Message): - await banned.delete() + if isinstance(banned, Message): + await banned.delete() await app.delete_messages(group_id, message_id) diff --git a/plugins/callbacks/emoji_button.py b/plugins/callbacks/emoji_button.py index 7d52480..7d36bcc 100644 --- a/plugins/callbacks/emoji_button.py +++ b/plugins/callbacks/emoji_button.py @@ -82,10 +82,11 @@ async def callback_emoji_button(app: PyroClient, callback: CallbackQuery): app._("captcha_failed", "callbacks", locale=locale), show_alert=True ) - banned = await app.ban_chat_member(group.id, callback.from_user.id) + if group.ban_failed: + banned = await app.ban_chat_member(group.id, callback.from_user.id) - if isinstance(banned, Message): - await banned.delete() + if isinstance(banned, Message): + await banned.delete() await callback.message.delete() return diff --git a/plugins/commands/ban_failed.py b/plugins/commands/ban_failed.py new file mode 100644 index 0000000..46a0ac4 --- /dev/null +++ b/plugins/commands/ban_failed.py @@ -0,0 +1,44 @@ +import logging + +from pyrogram import filters +from pyrogram.enums.chat_member_status import ChatMemberStatus +from pyrogram.types import Message + +from classes.pyroclient import PyroClient +from classes.pyrogroup import PyroGroup + +logger = logging.getLogger(__name__) + + +@PyroClient.on_message( + ~filters.scheduled + & filters.group + & filters.command(["ban_failed"], prefixes=["/"]) # type: ignore +) +async def command_ban_failed(app: PyroClient, message: Message): + group = await PyroGroup.create_if_not_exists(message.chat.id, None, True) + locale = group.select_locale(app, message.from_user) + + if (await app.get_chat_member(group.id, message.from_user.id)).status not in [ + ChatMemberStatus.ADMINISTRATOR, + ChatMemberStatus.OWNER, + ]: + await message.reply_text( + app._("permission_denied", "messages", locale=locale), quote=True + ) + return + + if group.ban_failed: + await message.reply_text( + app._("ban_failed_disabled", "messages", locale=locale) + ) + else: + await message.reply_text(app._("ban_failed_enabled", "messages", locale=locale)) + + logger.info( + "Ban on fail in group %s has been set to %s", + group.id, + not group.ban_failed, + ) + + await group.set_ban_failed(not group.ban_failed) diff --git a/plugins/handlers/user_join.py b/plugins/handlers/user_join.py index 7f4e400..ec48c03 100644 --- a/plugins/handlers/user_join.py +++ b/plugins/handlers/user_join.py @@ -50,10 +50,11 @@ async def handler_user_join(app: PyroClient, message: Message): "User %s has previously failed the captcha, kicking and banning him", user.id, ) - banned = await app.ban_chat_member(group.id, user.id) + if group.ban_failed: + banned = await app.ban_chat_member(group.id, user.id) - if isinstance(banned, Message): - await banned.delete() + if isinstance(banned, Message): + await banned.delete() return @@ -101,7 +102,7 @@ async def handler_user_join(app: PyroClient, message: Message): kick_unstarted, "date", [app, user.id, verification_request.chat.id, verification_request.id], - run_date=datetime.now() + timedelta(seconds=app.config["timeouts"]["join"]), + run_date=datetime.now() + timedelta(seconds=group.timeout_join), ) await col_schedule.insert_one( {"user": user.id, "group": group.id, "job_id": job.id}