diff --git a/.idea/EnterpriseALRobot.iml b/.idea/EnterpriseALRobot.iml index d8e44bfe..9ee49e50 100644 --- a/.idea/EnterpriseALRobot.iml +++ b/.idea/EnterpriseALRobot.iml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 8fbba304..97bb910e 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ - + + + \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 210331f9..cadd4228 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,10 +5,9 @@ bleach cachetools configparser currencyconverter -emoji +emoji==1.7.0 feedparser future -git+https://github.com/python-telegram-bot/ptbcontrib.git gitpython gpytranslate markdown2 @@ -17,8 +16,8 @@ pillow>=4.2.0 psutil psycopg2-binary pyYAML>=5.1.2 -pyrate-limiter -python-telegram-bot==13.11 +pyrate-limiter==2.8.1 +python-telegram-bot==13.15 requests spamwatch speedtest-cli @@ -38,4 +37,3 @@ pytz gtts wikipedia - diff --git a/run.sh b/run.sh old mode 100644 new mode 100755 diff --git a/tg_bot/__init__.py b/tg_bot/__init__.py index b6535fb5..01d000b3 100644 --- a/tg_bot/__init__.py +++ b/tg_bot/__init__.py @@ -5,11 +5,10 @@ from typing import List import spamwatch import telegram.ext as tg -from telegram.ext import Dispatcher, Updater +from telegram.ext import Dispatcher, JobQueue, Updater from telethon import TelegramClient from telethon.sessions import MemorySession from configparser import ConfigParser -from ptbcontrib.postgres_persistence import PostgresPersistence from functools import wraps from SibylSystem import PsychoPass try: @@ -46,8 +45,6 @@ def get_user_list(key): logging.basicConfig(handlers = [file_handler, stream_handler, debug_handler], level = logging.DEBUG) log = logging.getLogger('[Enterprise]') -logging.getLogger('ptbcontrib.postgres_persistence.postgrespersistence').setLevel(logging.WARNING) - log.info("LOGGER is starting. | Project maintained by: github.com/itsLuuke (t.me/itsLuuke)") # if version < 3.6, stop bot. @@ -134,9 +131,6 @@ def __init__(self, parser: ConfigParser): self.SIBYL_ENDPOINT = self.parser.get("SIBYL_ENDPOINT", "https://psychopass.kaizoku.cyou") - - - def init_sw(self): if self.spamwatch_api is None: log.warning("SpamWatch API key is missing! Check your config.ini") @@ -234,15 +228,11 @@ def init_sw(self): from tg_bot.modules.sql import SESSION -if not KInit.DROP_UPDATES: - updater: Updater = tg.Updater(token=TOKEN, base_url=KInit.BOT_API_URL, base_file_url=KInit.BOT_API_FILE_URL, workers=min(32, os.cpu_count() + 4), request_kwargs={"read_timeout": 10, "connect_timeout": 10}, persistence=PostgresPersistence(session=SESSION)) - -else: - updater = tg.Updater(token=TOKEN, base_url=KInit.BOT_API_URL, base_file_url=KInit.BOT_API_FILE_URL, workers=min(32, os.cpu_count() + 4), request_kwargs={"read_timeout": 10, "connect_timeout": 10}) - +updater: Updater = tg.Updater(token=TOKEN, base_url=KInit.BOT_API_URL, base_file_url=KInit.BOT_API_FILE_URL, workers=min(32, os.cpu_count() + 4), request_kwargs={"read_timeout": 10, "connect_timeout": 10}) + telethn = TelegramClient(MemorySession(), APP_ID, API_HASH) dispatcher: Dispatcher = updater.dispatcher -j: Updater.job_queue = updater.job_queue +j: JobQueue = updater.job_queue diff --git a/tg_bot/__main__.py b/tg_bot/__main__.py index 62d9bd6e..619b7472 100644 --- a/tg_bot/__main__.py +++ b/tg_bot/__main__.py @@ -680,29 +680,24 @@ def migrate_chats(update: Update, _: CallbackContext): def main(): dispatcher.add_error_handler(error_callback) # dispatcher.add_error_handler(error_handler) + allowed_updates = ['message', 'edited_message', 'callback_query', 'callback_query', 'my_chat_member', + 'chat_member', 'chat_join_request', 'channel_post', 'edited_channel_post', 'inline_query'] if WEBHOOK: log.info("Using webhooks.") - updater.start_webhook(listen="127.0.0.1", port=PORT, url_path=TOKEN) + updater.start_webhook(listen="0.0.0.0", port=PORT, url_path=TOKEN, allowed_updates=allowed_updates, webhook_url=URL+TOKEN, drop_pending_updates=KInit.DROP_UPDATES, cert=CERT_PATH if CERT_PATH else None) - if CERT_PATH: - updater.bot.set_webhook(url=URL + TOKEN, certificate=open(CERT_PATH, "rb")) - else: - updater.bot.set_webhook(url=URL + TOKEN) + print(f"Updater started! Using webhooks. | BOT: [@{dispatcher.bot.username}]") else: - dispatcher.bot.sendMessage(OWNER_ID, "Master, I'm awake!") - # if SUPPORT_GROUP: - # dispatcher.bot.sendMessage(SUPPORT_GROUP, "I'm up!") KigyoINIT.bot_id = dispatcher.bot.id KigyoINIT.bot_username = dispatcher.bot.username KigyoINIT.bot_name = dispatcher.bot.first_name - allowed_updates = ['message', 'edited_message', 'callback_query', 'callback_query', 'my_chat_member', - 'chat_member', 'chat_join_request', 'channel_post', 'edited_channel_post', 'inline_query'] updater.start_polling( timeout=15, read_latency=4, allowed_updates=allowed_updates, drop_pending_updates=KInit.DROP_UPDATES) print(f"Updater started! Using long polling. | BOT: [@{dispatcher.bot.username}]") + dispatcher.bot.sendMessage(OWNER_ID, "Master, I'm awake!") telethn.run_until_disconnected() updater.idle() diff --git a/tg_bot/langs/en.yaml b/tg_bot/langs/en.yaml index 60727d5a..288db34e 100644 --- a/tg_bot/langs/en.yaml +++ b/tg_bot/langs/en.yaml @@ -130,6 +130,9 @@ bans_help: | - /tban x(m/h/d): bans a user for x time. (via handle, or reply). m = minutes, h = hours, d = days. - /unban : unbans a user. (via handle, or reply) - /kick : kick a user out of the group, (via handle, or reply) + - /dkick : kick a user out of the group, silently. + - /skick : kick a user out of the group, deleting the replied to message. + - /dskick : kick a user out of the group deleting the sent and replied to message. blacklist_help: | Blacklists are used to stop certain triggers from being said in a group. Any time the trigger is mentioned, the message will immediately be deleted. A good combo is sometimes to pair this up with warn filters! @@ -144,7 +147,7 @@ blacklist_help: | • `/unblacklist `*:* Remove triggers from the blacklist. Same newline logic applies here, so you can remove multiple triggers at once. • `/unblocklist `*:* Same as unblacklist • `/blacklistmode `*:* Action to perform when someone sends blacklisted words. - • `/blacklistmode `*:* Same as blacklistmode + • `/blocklistmode `*:* Same as blacklistmode Owner only: • `/removeallblacklists`*:* Removes all blacklists from the chat. @@ -452,6 +455,9 @@ misc_help: | muting_help: | *Admins only:* • `/mute `*:* silences a user. Can also be used as a reply, muting the replied to user. + • `/dmute `*:* silences a user. silently. + • `/smute `*:* silences a user. deleting the replied to message. + • `/dsmute `*:* silences a user. deleting the sent and replied to message. • `/tmute x(m/h/d)`*:* mutes a user for x time. (via handle, or reply). `m` = `minutes`, `h` = `hours`, `d` = `days`. • `/unmute `*:* unmutes a user. Can also be used as a reply, muting the replied to user. diff --git a/tg_bot/modules/admin.py b/tg_bot/modules/admin.py index c2c6a92b..d17c4509 100644 --- a/tg_bot/modules/admin.py +++ b/tg_bot/modules/admin.py @@ -1,11 +1,11 @@ import html +import time from telegram import ParseMode, Update from telegram.error import BadRequest from telegram.ext import CallbackContext from telegram.utils.helpers import mention_html -from telethon.tl.functions.channels import GetFullChannelRequest from telethon.tl.types import ChannelParticipantsAdmins from telethon.tl.types import ChannelParticipantCreator from tg_bot import telethn @@ -23,9 +23,7 @@ bot_admin_check, AdminPerms, get_bot_member, - bot_is_admin, - user_is_admin, - user_not_admin_check, + A_CACHE, B_CACHE ) from typing import Optional @@ -392,6 +390,35 @@ def invite(update: Update, context: CallbackContext) -> Optional[str]: ) +@kigcmd(command=["admincache"], can_disable=False) +@spamcheck +def admincache(update: Update, context: CallbackContext): + chat = update.effective_chat + msg = update.effective_message + user = update.effective_user + try: + last = _admincache[chat.id] + except KeyError: + last = None + now = time.time() + if last and last + 600 > now: + return msg.reply_text("this command can only be used once every 10 minutes") + + if chat.type in ["channel", "private"]: + return msg.reply_text("this command can only be used in groups") + + if chat.get_member(user.id).status not in ["administrator", "creator"] and user.id != 1087968824: + return msg.reply_text("this command can only be used by admins") + + A_CACHE[update.effective_chat.id] = update.effective_chat.get_administrators() + B_CACHE[update.effective_chat.id] = update.effective_chat.get_member(context.bot.id) + msg.reply_text("Admin cache updated") + _admincache[chat.id] = time.time() + + +_admincache = dict() + + @register(pattern="(admin|admins|staff|adminlist)", groups_only=True, no_args=True) async def adminList(event): try: diff --git a/tg_bot/modules/bans.py b/tg_bot/modules/bans.py index de438aac..ed7cada3 100644 --- a/tg_bot/modules/bans.py +++ b/tg_bot/modules/bans.py @@ -62,6 +62,7 @@ def cannot_ban(banner_id, user_id, message) -> bool: AdminPerms, bot_is_admin, user_is_admin, + u_na_errmsg, ) @@ -371,7 +372,7 @@ def temp_ban(update: Update, context: CallbackContext) -> str: return log_message -@kigcmd(command=['kick', 'punch'], pass_args=True) +@kigcmd(command=['kick', 'skick', 'dkick', 'dskick', 'punch'], pass_args=True) @spamcheck @connection_status @bot_admin_check(AdminPerms.CAN_RESTRICT_MEMBERS) @@ -383,8 +384,9 @@ def kick(update: Update, context: CallbackContext) -> str: message = update.effective_message log_message = "" bot, args = context.bot, context.args - - if message.reply_to_message.sender_chat: + silent = message.text[1] == 's' or message.text[2] == 's' + delete = message.text[1] == 'd' + if message.reply_to_message and message.reply_to_message.sender_chat: message.reply_text("This command doesn't work on channels, but I can ban them if u want.") return log_message @@ -412,24 +414,34 @@ def kick(update: Update, context: CallbackContext) -> str: message.reply_text("This user has immunity and cannot be banned.") return '' - if chat.unban_member(user_id): - bot.send_sticker(chat.id, BAN_STICKER) # banhammer marie sticker - - if reason: - - bot.sendMessage( - chat.id, - f"{mention_html(member.user.id, member.user.first_name)} was kicked by {mention_html(user.id, user.first_name)} in {message.chat.title}\nReason: {reason}", - parse_mode=ParseMode.HTML, - ) - + if delete and message.reply_to_message: + if user_is_admin(update, message.from_user.id, perm=AdminPerms.CAN_DELETE_MESSAGES): + if bot_is_admin(chat, AdminPerms.CAN_DELETE_MESSAGES): + message.reply_to_message.delete() + else: + update.effective_message.reply_text( + f"I can't perform this action due to missing permissions;\n" + f"Make sure i am an admin and {AdminPerms.CAN_DELETE_MESSAGES.name.lower().replace('is_', 'am ').replace('_', ' ')}!") + return else: + return u_na_errmsg(message, AdminPerms.CAN_DELETE_MESSAGES) - bot.sendMessage( - chat.id, - f"{mention_html(member.user.id, member.user.first_name)} was kicked by {mention_html(user.id, user.first_name)} in {message.chat.title}", - parse_mode=ParseMode.HTML, - ) + + if chat.unban_member(user_id): + if not silent: + bot.send_sticker(chat.id, BAN_STICKER) # banhammer marie sticker + if reason: + bot.sendMessage( + chat.id, + f"{mention_html(member.user.id, member.user.first_name)} was kicked by {mention_html(user.id, user.first_name)} in {message.chat.title}\nReason: {reason}", + parse_mode=ParseMode.HTML, + ) + else: + bot.sendMessage( + chat.id, + f"{mention_html(member.user.id, member.user.first_name)} was kicked by {mention_html(user.id, user.first_name)} in {message.chat.title}", + parse_mode=ParseMode.HTML, + ) log = ( f"{html.escape(chat.title)}:\n" diff --git a/tg_bot/modules/connection.py b/tg_bot/modules/connection.py index 9a326703..7315034b 100644 --- a/tg_bot/modules/connection.py +++ b/tg_bot/modules/connection.py @@ -387,7 +387,7 @@ def connect_button(update, context): def get_help(chat): return gs(chat, "connections_help") -CONNECT_CHAT_HANDLER = CommandHandler("connect", connect_chat, pass_args=True) +CONNECT_CHAT_HANDLER = CommandHandler("connect", connect_chat, pass_args=True, run_async=True) CONNECTION_CHAT_HANDLER = CommandHandler("connection", connection_chat, run_async=True) DISCONNECT_CHAT_HANDLER = CommandHandler("disconnect", disconnect_chat, run_async=True) ALLOW_CONNECTIONS_HANDLER = CommandHandler( diff --git a/tg_bot/modules/disable.py b/tg_bot/modules/disable.py index 2306f2ac..39bf3e3d 100644 --- a/tg_bot/modules/disable.py +++ b/tg_bot/modules/disable.py @@ -1,4 +1,4 @@ -from typing import Union +from typing import Union, Optional from future.utils import string_types from telegram import ParseMode, Update, Chat @@ -214,16 +214,30 @@ def enable(update, context): @user_admin_check(AdminPerms.CAN_CHANGE_INFO) @typing_action def list_cmds(update, context): - if DISABLE_CMDS + DISABLE_OTHER: + if DISABLE_CMDS: result = "".join( " - `{}`\n".format(escape_markdown(str(cmd))) - for cmd in set(DISABLE_CMDS + DISABLE_OTHER) + for cmd in set(DISABLE_CMDS) ) - update.effective_message.reply_text( - "The following commands are toggleable:\n{}".format(result), - parse_mode=ParseMode.MARKDOWN, - ) + text = "The following commands are toggleable:\n{}".format(result) + def paginate(text): + lines = text.split("\n") + previous_text = "" + for line in lines: + if len(previous_text) + 1 + len(line) > 4096: # char limit + yield previous_text + # stop before limit, if adding line makes msg too long + previous_text = line + else: + previous_text = (previous_text + "\n" + line).strip("\n") + yield previous_text + + for page in paginate(text): + update.effective_message.reply_text( + page, + parse_mode=ParseMode.MARKDOWN, + ) else: update.effective_message.reply_text("No commands can be disabled.") @@ -291,16 +305,16 @@ def __chat_settings__(chat_id, user_id): """ DISABLE_HANDLER = CommandHandler( - "disable", disable, pass_args=True + "disable", disable, pass_args=True, run_async=True ) # , filters=Filters.chat_type.groups) ENABLE_HANDLER = CommandHandler( - "enable", enable, pass_args=True + "enable", enable, pass_args=True, run_async=True ) # , filters=Filters.chat_type.groups) COMMANDS_HANDLER = CommandHandler( - ["cmds", "disabled"], commands + ["cmds", "disabled"], commands, run_async=True ) # , filters=Filters.chat_type.groups) TOGGLE_HANDLER = CommandHandler( - "listcmds", list_cmds + "listcmds", list_cmds, run_async=True ) # , filters=Filters.chat_type.groups) dispatcher.add_handler(DISABLE_HANDLER) diff --git a/tg_bot/modules/feds.py b/tg_bot/modules/feds.py index 4ed8ddfc..41f74e7e 100644 --- a/tg_bot/modules/feds.py +++ b/tg_bot/modules/feds.py @@ -842,7 +842,7 @@ def fed_ban(update, context): # sourcery no-metrics # Will send to current chat context.bot.send_message( chat.id, - "FedBan reason updated" + "New FederationBan" "\nFederation: {}" "\nFederation Admin: {}" "\nUser: {}" @@ -861,7 +861,7 @@ def fed_ban(update, context): # sourcery no-metrics if getfednotif: context.bot.send_message( info["owner"], - "FedBan reason updated" + "New FederationBan" "\nFederation: {}" "\nFederation Admin: {}" "\nUser: {}" @@ -884,7 +884,7 @@ def fed_ban(update, context): # sourcery no-metrics if int(get_fedlog) != int(chat.id): context.bot.send_message( get_fedlog, - "FedBan reason updated" + "New FederationBan" "\nFederation: {}" "\nFederation Admin: {}" "\nUser: {}" @@ -908,7 +908,7 @@ def fed_ban(update, context): # sourcery no-metrics try: # Do not spamming all fed chats """ - context.bot.send_message(chat, "FedBan reason updated" \ + context.bot.send_message(chat, "New FederationBan" \ "\nFederation: {}" \ "\nFederation Admin: {}" \ "\nUser: {}" \ @@ -931,7 +931,7 @@ def fed_ban(update, context): # sourcery no-metrics # Also do not spamming all fed admins """ send_to_list(bot, FEDADMIN, - "FedBan reason updated" \ + "New FederationBan" \ "\nFederation: {}" \ "\nFederation Admin: {}" \ "\nUser: {}" \ diff --git a/tg_bot/modules/helper_funcs/admin_status.py b/tg_bot/modules/helper_funcs/admin_status.py index c8ad1a17..4947afd9 100644 --- a/tg_bot/modules/helper_funcs/admin_status.py +++ b/tg_bot/modules/helper_funcs/admin_status.py @@ -107,7 +107,10 @@ def user_is_admin(update: Update, try: the_perm = perm.value except AttributeError: - return bxp(update) + if perm.upper() in AdminPerms.__members__: + the_perm = perm + else: + return bxp(update) return getattr(member, the_perm) or member.status == "creator" return member.status in ["administrator", "creator"] # check if user is admin diff --git a/tg_bot/modules/helper_funcs/parsing.py b/tg_bot/modules/helper_funcs/parsing.py index f3b6afd4..871483a8 100644 --- a/tg_bot/modules/helper_funcs/parsing.py +++ b/tg_bot/modules/helper_funcs/parsing.py @@ -13,7 +13,7 @@ BTN_LINK_REGEX = re.compile( - r"(? Optional[str]: return None -@kigcmd(command='mute') +@kigcmd(command=['mute', 'smute', 'dmute', 'dsmute']) @spamcheck @connection_status @bot_admin_check(AdminPerms.CAN_RESTRICT_MEMBERS) @@ -85,7 +86,8 @@ def mute(update: Update, context: CallbackContext) -> str: user = update.effective_user message = update.effective_message user = update.effective_user - + silent = message.text[1] == 's' or message.text[2] == 's' + delete = message.text[1] == 'd' user_id, reason = extract_user_and_text(message, args) reply = check_user(user_id, bot, update) @@ -93,6 +95,18 @@ def mute(update: Update, context: CallbackContext) -> str: message.reply_text(reply) return "" + if delete and message.reply_to_message: + if user_is_admin(update, message.from_user.id, perm=AdminPerms.CAN_DELETE_MESSAGES): + if bot_is_admin(chat, AdminPerms.CAN_DELETE_MESSAGES): + message.reply_to_message.delete() + else: + update.effective_message.reply_text( + f"I can't perform this action due to missing permissions;\n" + f"Make sure i am an admin and {AdminPerms.CAN_DELETE_MESSAGES.name.lower().replace('is_', 'am ').replace('_', ' ')}!") + return + else: + return u_na_errmsg(message, AdminPerms.CAN_DELETE_MESSAGES) + member = chat.get_member(user_id) log = ( @@ -124,8 +138,8 @@ def mute(update: Update, context: CallbackContext) -> str: ] ] ) - - context.bot.send_message( + if not silent: + context.bot.send_message( chat.id, mutemsg, parse_mode=ParseMode.HTML, @@ -149,10 +163,8 @@ def mute(update: Update, context: CallbackContext) -> str: def button(update: Update, context: CallbackContext) -> str: query: Optional[CallbackQuery] = update.callback_query user: Optional[User] = update.effective_user - chat = update.effective_chat - admeme = chat.get_member(user.id) match = re.match(r"cb_unmute\((.+?)\)", query.data) - if match and admeme.status == "administrator": + if match and user_is_admin(update, user.id, perm=AdminPerms.CAN_RESTRICT_MEMBERS): bot = context.bot user_id = match.group(1) @@ -171,7 +183,7 @@ def button(update: Update, context: CallbackContext) -> str: and user_member.can_send_other_messages and user_member.can_add_web_page_previews ): - update.effective_message.edit_tex("This user already has the right to speak.") + update.effective_message.edit_text("This user already has the right to speak.") else: chat_permissions = ChatPermissions( can_send_messages=True, @@ -188,7 +200,6 @@ def button(update: Update, context: CallbackContext) -> str: except BadRequest: pass - update.effective_message.edit_text( "{} was unmuted by {}.".format(mention_html(user_id, user_member.user.first_name), user.first_name), parse_mode=ParseMode.HTML, @@ -199,6 +210,8 @@ def button(update: Update, context: CallbackContext) -> str: f"Admin: {mention_html(user.id, user.first_name)}\n" f"User: {mention_html(user_member.user.id, user_member.user.first_name)}" ) + else: + query.answer("this is only for admins") @kigcmd(command='unmute') diff --git a/tg_bot/modules/purge.py b/tg_bot/modules/purge.py index e0438572..f8f16cb8 100644 --- a/tg_bot/modules/purge.py +++ b/tg_bot/modules/purge.py @@ -1,6 +1,6 @@ import time from asyncio import sleep -from telethon import events +from telethon.events import NewMessage from telethon.tl.types import ChannelParticipantsAdmins from .helper_funcs.decorators import register from .sql.clear_cmd_sql import get_clearcmd @@ -10,8 +10,8 @@ from telethon.errors.rpcerrorlist import MessageDeleteForbiddenError -@register(pattern='(purge|p)', groups_only=True, no_args=True) -async def purge_messages(event): +@register(pattern='(?:(s)?purge|p)', groups_only=True, no_args=True) +async def purge_messages(event: NewMessage.Event): start = time.perf_counter() if event.from_id is None: return @@ -53,15 +53,16 @@ async def purge_messages(event): await event.client.delete_messages(event.chat_id, messages) except: pass - time_ = time.perf_counter() - start - text = f"Purged Successfully in {time_:0.2f} Second(s)" - prmsg = await event.respond(text, parse_mode='markdown') + if not event.pattern_match.group(1): + time_ = time.perf_counter() - start + text = f"Purged Successfully in {time_:0.2f} Second(s)" + prmsg = await event.respond(text, parse_mode='markdown') - cleartime = get_clearcmd(event.chat_id, "purge") + cleartime = get_clearcmd(event.chat_id, "purge") - if cleartime: - await sleep(cleartime.time) - await prmsg.delete() + if cleartime: + await sleep(cleartime.time) + await prmsg.delete() @register(pattern='(del|d)', groups_only=True, no_args=True) diff --git a/tg_bot/modules/sticker_blacklist.py b/tg_bot/modules/sticker_blacklist.py index fac5f1e8..f6201420 100644 --- a/tg_bot/modules/sticker_blacklist.py +++ b/tg_bot/modules/sticker_blacklist.py @@ -80,7 +80,6 @@ def add_blackliststicker(update: Update, context: CallbackContext): added = 0 for trigger in to_blacklist: try: - get = bot.getStickerSet(trigger) sql.add_to_stickers(chat.id, trigger.lower()) added += 1 except BadRequest: @@ -116,7 +115,6 @@ def add_blackliststicker(update: Update, context: CallbackContext): send_message(update.effective_message, "Sticker is invalid!") return try: - get = bot.getStickerSet(trigger) sql.add_to_stickers(chat.id, trigger.lower()) added += 1 except BadRequest: @@ -482,17 +480,17 @@ def get_help(chat): BLACKLIST_STICKER_HANDLER = DisableAbleCommandHandler( - "blsticker", blackliststicker, admin_ok=True, + "blsticker", blackliststicker, admin_ok=True, run_async=True ) ADDBLACKLIST_STICKER_HANDLER = DisableAbleCommandHandler( - "addblsticker", add_blackliststicker, + "addblsticker", add_blackliststicker, run_async=True ) UNBLACKLIST_STICKER_HANDLER = CommandHandler( - ["unblsticker", "rmblsticker"], unblackliststicker, + ["unblsticker", "rmblsticker"], unblackliststicker, run_async=True ) -BLACKLISTMODE_HANDLER = CommandHandler("blstickermode", blacklist_mode) +BLACKLISTMODE_HANDLER = CommandHandler("blstickermode", blacklist_mode, run_async=True) BLACKLIST_STICKER_DEL_HANDLER = MessageHandler( - Filters.sticker & Filters.chat_type.groups, del_blackliststicker, + Filters.sticker & Filters.chat_type.groups, del_blackliststicker, run_async=True ) dispatcher.add_handler(BLACKLIST_STICKER_HANDLER) diff --git a/tg_bot/modules/stickers.py b/tg_bot/modules/stickers.py index 1a2f1fea..946663fb 100644 --- a/tg_bot/modules/stickers.py +++ b/tg_bot/modules/stickers.py @@ -6,13 +6,23 @@ from urllib.error import HTTPError from PIL import Image -from telegram import (InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, +from telegram import (Bot, InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, TelegramError, Update) from telegram.ext import CallbackContext from telegram.utils.helpers import mention_html from .helper_funcs.decorators import kigcmd +def get_sticker_count(bot: Bot, packname: str) -> int: + resp = bot._request.post( + f"{bot.base_url}/getStickerSet", + { + "name": packname, + }, + ) + return len(resp["stickers"]) + + @kigcmd(command='stickerid') @spamcheck def stickerid(update: Update, context: CallbackContext): @@ -38,24 +48,19 @@ def stickerid(update: Update, context: CallbackContext): @kigcmd(command='getsticker') @spamcheck def getsticker(update: Update, context: CallbackContext): - bot = context.bot msg = update.effective_message - chat_id = update.effective_chat.id if msg.reply_to_message and msg.reply_to_message.sticker: file_id = msg.reply_to_message.sticker.file_id # Check if it's an animated file is_animated = msg.reply_to_message.sticker.is_animated + bot = context.bot # Get the file and put it into a memory buffer new_file = bot.get_file(file_id) sticker_data = new_file.download(out=BytesIO()) # go back to the start of the buffer sticker_data.seek(0) - # Reply with the document. Telegram INSISTS on making anything - # that ends in .tgs become an animated sticker so we'll have to - # rename it to something the user should know how to handle. - filename = "sticker.png" - if is_animated: - filename = "animated_sticker.tgs.rename_me" + filename = "animated_sticker.tgs.rename_me" if is_animated else "sticker.png" + chat_id = update.effective_chat.id # Send the document bot.send_document(chat_id, document=sticker_data, @@ -101,8 +106,7 @@ def kang(update: Update, context: CallbackContext): # sourcery no-metrics while True: last_set = False try: - stickerset = context.bot.get_sticker_set(packname) - if len(stickerset.stickers) >= max_stickers: + if get_sticker_count(context.bot, packname) >= max_stickers: packnum += 1 if is_animated: packname = f"animated{packnum}_{user.id}_by_{context.bot.username}" @@ -233,8 +237,7 @@ def kang(update: Update, context: CallbackContext): # sourcery no-metrics # Find if the pack is full already while not packname_found: try: - stickerset = context.bot.get_sticker_set(packname) - if len(stickerset.stickers) >= max_stickers: + if get_sticker_count(context.bot, packname) >= max_stickers: packnum += 1 if is_animated: packname = f"animated{packnum}_{user.id}_by_{context.bot.username}" @@ -249,6 +252,8 @@ def kang(update: Update, context: CallbackContext): # sourcery no-metrics packname_found = True # we will need to create the sticker pack invalid = True + else: + raise # if the image isn't animated, ensure it's the right size/format with PIL if not is_animated and not is_video: @@ -401,6 +406,7 @@ def makepack_internal( "This media format isn't supported, I need it in a webm format, " "[see this guide](https://core.telegram.org/stickers/webm-vp9-encoding).", parse_mode=ParseMode.MARKDOWN, + disable_web_page_preview = True, ) return else: @@ -409,7 +415,6 @@ def makepack_internal( msg.reply_text( f"Sticker pack successfully created. Get it [here](t.me/addstickers/{packname})", parse_mode=ParseMode.MARKDOWN, - disable_web_page_preview = True, ) else: msg.reply_text("Failed to create sticker pack. Possibly due to blek mejik.") diff --git a/tg_bot/modules/warns.py b/tg_bot/modules/warns.py index 734039c4..db626e7a 100644 --- a/tg_bot/modules/warns.py +++ b/tg_bot/modules/warns.py @@ -423,7 +423,7 @@ def warn_user(update: Update, context: CallbackContext) -> str: user_id, reason = extract_user_and_text(message, args) - if (message.reply_to_message and message.reply_to_message.sender_chat) or user_id < 0: + if (message.reply_to_message and message.reply_to_message.sender_chat) or (user_id and user_id < 0): message.reply_text("This command can't be used on channels, however you can ban them instead.") return "" diff --git a/tg_bot/modules/welcome.py b/tg_bot/modules/welcome.py index ffe7e045..827d3570 100644 --- a/tg_bot/modules/welcome.py +++ b/tg_bot/modules/welcome.py @@ -37,7 +37,7 @@ from telegram.error import BadRequest, TelegramError from telegram.ext import ( CallbackContext, - Filters, + Filters, ChatMemberHandler, MessageHandler, ) from telegram.utils.helpers import escape_markdown, mention_html, mention_markdown from .helper_funcs.decorators import kigcmd, kigmsg, kigcallback @@ -86,26 +86,16 @@ # do not async def send(update, message, keyboard, backup_message): chat = update.effective_chat - cleanserv = sql.clean_service(chat.id) - reply = update.message.message_id - # Clean service welcome - if cleanserv: - try: - dispatcher.bot.delete_message(chat.id, update.message.message_id) - except BadRequest: - pass - reply = False try: - msg = update.effective_message.reply_text( + msg = dispatcher.bot.send_message(chat.id, message, parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard, - reply_to_message_id=reply, allow_sending_without_reply=True, ) except BadRequest as excp: if excp.message == 'Button_url_invalid': - msg = update.effective_message.reply_text( + msg = dispatcher.bot.send_message(chat.id, markdown_parser( ( backup_message @@ -113,13 +103,12 @@ def send(update, message, keyboard, backup_message): ) ), parse_mode=ParseMode.MARKDOWN, - reply_to_message_id=reply, ) elif excp.message == 'Have no rights to send a message': return elif excp.message == 'Reply message not found': - msg = update.effective_message.reply_text( + msg = dispatcher.bot.send_message(chat.id, message, parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard, @@ -127,7 +116,7 @@ def send(update, message, keyboard, backup_message): ) elif excp.message == 'Unsupported url protocol': - msg = update.effective_message.reply_text( + msg = dispatcher.bot.send_message(chat.id, markdown_parser( ( backup_message @@ -136,11 +125,10 @@ def send(update, message, keyboard, backup_message): ) ), parse_mode=ParseMode.MARKDOWN, - reply_to_message_id=reply, ) elif excp.message == 'Wrong url host': - msg = update.effective_message.reply_text( + msg = dispatcher.bot.send_message(chat.id, markdown_parser( ( backup_message @@ -148,14 +136,13 @@ def send(update, message, keyboard, backup_message): ) ), parse_mode=ParseMode.MARKDOWN, - reply_to_message_id=reply, ) log.warning(message) log.warning(keyboard) log.exception('Could not parse! got invalid url host errors') else: - msg = update.effective_message.reply_text( + msg = dispatcher.bot.send_message(chat.id, markdown_parser( ( backup_message @@ -163,20 +150,31 @@ def send(update, message, keyboard, backup_message): ) ), parse_mode=ParseMode.MARKDOWN, - reply_to_message_id=reply, ) log.exception() return msg -@kigmsg((Filters.status_update.new_chat_members), group=WELCOME_GROUP) -#@loggable +def welcomeFilter(update: Update, context: CallbackContext): + if update.effective_chat.type != "group" and update.effective_chat.type != "supergroup": + return + if nm := update.chat_member.new_chat_member: + om = update.chat_member.old_chat_member + if nm.status == nm.MEMBER and (om.status == nm.KICKED or om.status == nm.LEFT): + return new_member(update, context) + if (nm.status == nm.KICKED or nm.status == nm.LEFT) and \ + (om.status == nm.MEMBER or om.status == nm.ADMINISTRATOR or om.status == nm.CREATOR): + return left_member(update, context) + + +dispatcher.add_handler(ChatMemberHandler(welcomeFilter, ChatMemberHandler.CHAT_MEMBER, run_async=True), group=WELCOME_GROUP) + + def new_member(update: Update, context: CallbackContext): # sourcery no-metrics bot, job_queue = context.bot, context.job_queue chat = update.effective_chat user = update.effective_user - msg = update.effective_message log_setting = logsql.get_chat_setting(chat.id) if not log_setting: logsql.set_chat_setting(logsql.LogChannelSettings(chat.id, True, True, True, True, True)) @@ -186,405 +184,401 @@ def new_member(update: Update, context: CallbackContext): # sourcery no-metrics human_checks = sql.get_human_checks(user.id, chat.id) raid, _, deftime = sql.getRaidStatus(str(chat.id)) - new_members = update.effective_message.new_chat_members + new_mem = update.chat_member.new_chat_member.user - for new_mem in new_members: + welcome_log = None + res = None + sent = None + should_mute = True + welcome_bool = True + media_wel = False - welcome_log = None - res = None - sent = None - should_mute = True - welcome_bool = True - media_wel = False + if raid and new_mem.id not in WHITELISTED: + bantime = deftime + try: + chat.ban_member(new_mem.id, until_date=bantime) + return + except: + pass + if sw is not None: + sw_ban = sw.get_ban(new_mem.id) + if sw_ban: + return - if raid and new_mem.id not in WHITELISTED: - bantime = deftime - try: - chat.ban_member(new_mem.id, until_date=bantime) - return - except: - pass - if sw is not None: - sw_ban = sw.get_ban(new_mem.id) - if sw_ban: - return + data = None + if sibylClient and does_chat_sibylban(chat.id): + try: + data = sibylClient.get_info(user.id) + except GeneralException: + pass + except BaseException as e: + log.error(e) + pass + if data and data.banned: + return # all modes handle it in different ways - data = None - if sibylClient and does_chat_sibylban(chat.id): - try: - data = sibylClient.get_info(user.id) - except GeneralException: - pass - except BaseException as e: - log.error(e) - pass - if data and data.banned: - return # all modes handle it in different ways + if should_welc: - reply = update.message.message_id - cleanserv = sql.clean_service(chat.id) - # Clean service welcome - if cleanserv: - try: - dispatcher.bot.delete_message(chat.id, update.message.message_id) - except BadRequest: - pass - reply = False + # Give the owner a special welcome + if new_mem.id == OWNER_ID: + bot.send_message(chat.id, + "Hey master, May The Force Be With You!", + ) + welcome_log = ( + f"{html.escape(chat.title)}\n" + f"#USER_JOINED\n" + f"Bot Owner just joined the chat" + ) + return - if should_welc: + # Welcome Devs + elif new_mem.id in DEV_USERS: + bot.send_message(chat.id, + "Whoa! A developer user just joined!", + ) + return - # Give the owner a special welcome - if new_mem.id == OWNER_ID: - update.effective_message.reply_text( - "Hey master, May The Force Be With You!", reply_to_message_id=reply - ) - welcome_log = ( - f"{html.escape(chat.title)}\n" - f"#USER_JOINED\n" - f"Bot Owner just joined the chat" - ) - continue + # Welcome Sudos + elif new_mem.id in SUDO_USERS: + bot.send_message(chat.id, + "Huh! A Sudo user just joined! Stay Alert!", + ) + return - # Welcome Devs - elif new_mem.id in DEV_USERS: - update.effective_message.reply_text( - "Whoa! A developer user just joined!", - reply_to_message_id=reply, - ) - continue + # Welcome Support + elif new_mem.id in SUPPORT_USERS: + bot.send_message(chat.id, + "Huh! a Support user just joined!", + ) + return - # Welcome Sudos - elif new_mem.id in SUDO_USERS: - update.effective_message.reply_text( - "Huh! A Sudo user just joined! Stay Alert!", - reply_to_message_id=reply, - ) - continue + # Welcome WHITELIST_USERS + elif new_mem.id in WHITELIST_USERS: + bot.send_message(chat.id, + "Oof! A Whitelist user just joined!", + ) + return - # Welcome Support - elif new_mem.id in SUPPORT_USERS: - update.effective_message.reply_text( - "Huh! a Support user just joined!", - reply_to_message_id=reply, - ) - continue + # Welcome MOD_USERS + elif new_mem.id in MOD_USERS: + bot.send_message(chat.id, + "Ah! A Moderator just joined!", + ) + return - # Welcome WHITELIST_USERS - elif new_mem.id in WHITELIST_USERS: - update.effective_message.reply_text( - "Oof! A Whitelist user just joined!", reply_to_message_id=reply - ) - continue + # Welcome yourself + elif new_mem.id == bot.id: + bot.send_message(chat.id, + "Heyy, thanks for adding me!", + ) + return - # Welcome MOD_USERS - elif new_mem.id in MOD_USERS: - update.effective_message.reply_text( - "Ah! A Moderator just joined!", reply_to_message_id=reply - ) - continue + else: + buttons = sql.get_welc_buttons(chat.id) + keyb = build_keyboard(buttons) - # Welcome yourself - elif new_mem.id == bot.id: - update.effective_message.reply_text( - "Heyy, thanks for adding me!", - reply_to_message_id=reply, - ) - continue + if welc_type not in (sql.Types.TEXT, sql.Types.BUTTON_TEXT): + media_wel = True - else: - buttons = sql.get_welc_buttons(chat.id) - keyb = build_keyboard(buttons) + first_name = ( + new_mem.first_name or "PersonWithNoName" + ) # edge case of empty name - occurs for some bugs. - if welc_type not in (sql.Types.TEXT, sql.Types.BUTTON_TEXT): - media_wel = True - - first_name = ( - new_mem.first_name or "PersonWithNoName" - ) # edge case of empty name - occurs for some bugs. - - if cust_welcome: - if cust_welcome == sql.DEFAULT_WELCOME: - cust_welcome = random.choice( - sql.DEFAULT_WELCOME_MESSAGES - ).format(first=escape_markdown(first_name)) - - if new_mem.last_name: - fullname = escape_markdown(f"{first_name} {new_mem.last_name}") - else: - fullname = escape_markdown(first_name) - count = chat.get_member_count() - mention = mention_markdown(new_mem.id, escape_markdown(first_name)) - if new_mem.username: - username = "@" + escape_markdown(new_mem.username) - else: - username = mention - - valid_format = escape_invalid_curly_brackets( - cust_welcome, VALID_WELCOME_FORMATTERS - ) - res = valid_format.format( - first=escape_markdown(first_name), - last=escape_markdown(new_mem.last_name or first_name), - fullname=escape_markdown(fullname), - username=username, - mention=mention, - count=count, - chatname=escape_markdown(chat.title), - id=new_mem.id, - ) + if cust_welcome: + if cust_welcome == sql.DEFAULT_WELCOME: + cust_welcome = random.choice( + sql.DEFAULT_WELCOME_MESSAGES + ).format(first=escape_markdown(first_name)) + if new_mem.last_name: + fullname = escape_markdown(f"{first_name} {new_mem.last_name}") else: - res = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format( - first=escape_markdown(first_name) - ) - keyb = [] + fullname = escape_markdown(first_name) + count = chat.get_member_count() + mention = mention_markdown(new_mem.id, escape_markdown(first_name)) + if new_mem.username: + username = "@" + escape_markdown(new_mem.username) + else: + username = mention - backup_message = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format( + valid_format = escape_invalid_curly_brackets( + cust_welcome, VALID_WELCOME_FORMATTERS + ) + res = valid_format.format( + first=escape_markdown(first_name), + last=escape_markdown(new_mem.last_name or first_name), + fullname=escape_markdown(fullname), + username=username, + mention=mention, + count=count, + chatname=escape_markdown(chat.title), + id=new_mem.id, + ) + + else: + res = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format( first=escape_markdown(first_name) ) - keyboard = InlineKeyboardMarkup(keyb) + keyb = [] - else: + backup_message = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format( + first=escape_markdown(first_name) + ) + keyboard = InlineKeyboardMarkup(keyb) + + else: + welcome_bool = False + res = None + keyboard = None + backup_message = None + reply = None + + # User exceptions from welcomemutes + if ( + chat.get_member(new_mem.id).status in ["creator", "administrator"] + or human_checks + ): + should_mute = False + # Join welcome: soft mute + if new_mem.is_bot: + should_mute = False + + if user.id == new_mem.id and should_mute: + if welc_mutes == "soft": + bot.restrict_chat_member( + chat.id, + new_mem.id, + permissions=ChatPermissions( + can_send_messages=True, + can_send_media_messages=False, + can_send_other_messages=False, + can_invite_users=False, + can_pin_messages=False, + can_send_polls=False, + can_change_info=False, + can_add_web_page_previews=False, + ), + until_date=(int(time.time() + 24 * 60 * 60)), + ) + sql.set_human_checks(user.id, chat.id) + if welc_mutes == "strong": welcome_bool = False - res = None - keyboard = None - backup_message = None - reply = None - - # User exceptions from welcomemutes - if ( - chat.get_member(new_mem.id).status in ["creator", "administrator"] - or human_checks - ): - should_mute = False - # Join welcome: soft mute - if new_mem.is_bot: - should_mute = False - - if user.id == new_mem.id and should_mute: - if welc_mutes == "soft": - bot.restrict_chat_member( - chat.id, - new_mem.id, - permissions=ChatPermissions( - can_send_messages=True, - can_send_media_messages=False, - can_send_other_messages=False, - can_invite_users=False, - can_pin_messages=False, - can_send_polls=False, - can_change_info=False, - can_add_web_page_previews=False, - ), - until_date=(int(time.time() + 24 * 60 * 60)), - ) - sql.set_human_checks(user.id, chat.id) - if welc_mutes == "strong": - welcome_bool = False - if not media_wel: - VERIFIED_USER_WAITLIST.update( - { - (chat.id, new_mem.id): { - "should_welc": should_welc, - "media_wel": False, - "status": False, - "update": update, - "res": res, - "keyboard": keyboard, - "backup_message": backup_message, - } + if not media_wel: + VERIFIED_USER_WAITLIST.update( + { + (chat.id, new_mem.id): { + "should_welc": should_welc, + "media_wel": False, + "status": False, + "update": update, + "res": res, + "keyboard": keyboard, + "backup_message": backup_message, } - ) - else: - VERIFIED_USER_WAITLIST.update( - { - (chat.id, new_mem.id): { - "should_welc": should_welc, - "chat_id": chat.id, - "status": False, - "media_wel": True, - "cust_content": cust_content, - "welc_type": welc_type, - "res": res, - "keyboard": keyboard, - } + } + ) + else: + VERIFIED_USER_WAITLIST.update( + { + (chat.id, new_mem.id): { + "should_welc": should_welc, + "chat_id": chat.id, + "status": False, + "media_wel": True, + "cust_content": cust_content, + "welc_type": welc_type, + "res": res, + "keyboard": keyboard, } - ) - new_join_mem = f"[{escape_markdown(new_mem.first_name)}](tg://user?id={user.id})" - message = msg.reply_text( - f"{new_join_mem}, click the button below to prove you're human.\nYou have 120 seconds.", - reply_markup=InlineKeyboardMarkup( + } + ) + new_join_mem = f"[{escape_markdown(new_mem.first_name)}](tg://user?id={user.id})" + message = bot.send_message(chat.id, + f"{new_join_mem}, click the button below to prove you're human.\nYou have 120 seconds.", + reply_markup=InlineKeyboardMarkup( + [ [ - [ - InlineKeyboardButton( - text="Yes, I'm human.", - callback_data=f"user_join_({new_mem.id})", - ) - ] + InlineKeyboardButton( + text="Yes, I'm human.", + callback_data=f"user_join_({new_mem.id})", + ) ] - ), - parse_mode=ParseMode.MARKDOWN, - reply_to_message_id=reply, - allow_sending_without_reply=True, - ) - bot.restrict_chat_member( - chat.id, - new_mem.id, - permissions=ChatPermissions( - can_send_messages=False, - can_invite_users=False, - can_pin_messages=False, - can_send_polls=False, - can_change_info=False, - can_send_media_messages=False, - can_send_other_messages=False, - can_add_web_page_previews=False, - ), - ) - job_queue.run_once( - partial(check_not_bot, new_mem, chat.id, message.message_id), - 120, - name="welcomemute", - ) - if welc_mutes == "captcha": - btn = [] - # Captcha image size number (2 -> 640x360) - CAPCTHA_SIZE_NUM = 2 - # Create Captcha Generator object of specified size - generator = CaptchaGenerator(CAPCTHA_SIZE_NUM) - - # Generate a captcha image - captcha = generator.gen_captcha_image(difficult_level=3) - # Get information - image = captcha["image"] - characters = captcha["characters"] - # print(characters) - fileobj = BytesIO() - fileobj.name = f'captcha_{new_mem.id}.png' - image.save(fp=fileobj) - fileobj.seek(0) - CAPTCHA_ANS_DICT[(chat.id, new_mem.id)] = int(characters) - welcome_bool = False - if not media_wel: - VERIFIED_USER_WAITLIST.update( - { - (chat.id, new_mem.id): { - "should_welc": should_welc, - "media_wel": False, - "status": False, - "update": update, - "res": res, - "keyboard": keyboard, - "backup_message": backup_message, - "captcha_correct": characters, - } + ] + ), + parse_mode=ParseMode.MARKDOWN, + allow_sending_without_reply=True, + ) + bot.restrict_chat_member( + chat.id, + new_mem.id, + permissions=ChatPermissions( + can_send_messages=False, + can_invite_users=False, + can_pin_messages=False, + can_send_polls=False, + can_change_info=False, + can_send_media_messages=False, + can_send_other_messages=False, + can_add_web_page_previews=False, + ), + ) + job_queue.run_once( + partial(check_not_bot, new_mem, chat.id, message.message_id), + 120, + name="welcomemute", + ) + if welc_mutes == "captcha": + btn = [] + # Captcha image size number (2 -> 640x360) + CAPCTHA_SIZE_NUM = 2 + # Create Captcha Generator object of specified size + generator = CaptchaGenerator(CAPCTHA_SIZE_NUM) + + # Generate a captcha image + captcha = generator.gen_captcha_image(difficult_level=3) + # Get information + image = captcha["image"] + characters = captcha["characters"] + # print(characters) + fileobj = BytesIO() + fileobj.name = f'captcha_{new_mem.id}.png' + image.save(fp=fileobj) + fileobj.seek(0) + CAPTCHA_ANS_DICT[(chat.id, new_mem.id)] = int(characters) + welcome_bool = False + if not media_wel: + VERIFIED_USER_WAITLIST.update( + { + (chat.id, new_mem.id): { + "should_welc": should_welc, + "media_wel": False, + "status": False, + "update": update, + "res": res, + "keyboard": keyboard, + "backup_message": backup_message, + "captcha_correct": characters, } - ) - else: - VERIFIED_USER_WAITLIST.update( - { - (chat.id, new_mem.id): { - "should_welc": should_welc, - "chat_id": chat.id, - "status": False, - "media_wel": True, - "cust_content": cust_content, - "welc_type": welc_type, - "res": res, - "keyboard": keyboard, - "captcha_correct": characters, - } + } + ) + else: + VERIFIED_USER_WAITLIST.update( + { + (chat.id, new_mem.id): { + "should_welc": should_welc, + "chat_id": chat.id, + "status": False, + "media_wel": True, + "cust_content": cust_content, + "welc_type": welc_type, + "res": res, + "keyboard": keyboard, + "captcha_correct": characters, } - ) + } + ) - nums = [random.randint(1000, 9999) for _ in range(7)] - nums.append(characters) - random.shuffle(nums) - to_append = [] - # print(nums) - for a in nums: - to_append.append(InlineKeyboardButton(text=str(a), - callback_data=f"user_captchajoin_({chat.id},{new_mem.id})_({a})")) - if len(to_append) > 2: - btn.append(to_append) - to_append = [] - if to_append: + nums = [random.randint(1000, 9999) for _ in range(7)] + nums.append(characters) + random.shuffle(nums) + to_append = [] + # print(nums) + for a in nums: + to_append.append(InlineKeyboardButton(text=str(a), + callback_data=f"user_captchajoin_({chat.id},{new_mem.id})_({a})")) + if len(to_append) > 2: btn.append(to_append) + to_append = [] + if to_append: + btn.append(to_append) + + message = bot.send_photo(chat.id, fileobj, + caption=f'Welcome [{escape_markdown(new_mem.first_name)}](tg://user?id={user.id}). Click the correct button to get unmuted!\n' + f'You got 120 seconds for this.', + reply_markup=InlineKeyboardMarkup(btn), + parse_mode=ParseMode.MARKDOWN, + allow_sending_without_reply=True, + ) + bot.restrict_chat_member( + chat.id, + new_mem.id, + permissions=ChatPermissions( + can_send_messages=False, + can_invite_users=False, + can_pin_messages=False, + can_send_polls=False, + can_change_info=False, + can_send_media_messages=False, + can_send_other_messages=False, + can_add_web_page_previews=False, + ), + ) + job_queue.run_once( + partial(check_not_bot, new_mem, chat.id, message.message_id), + 120, + name="welcomemute", + ) - message = msg.reply_photo(fileobj, - caption=f'Welcome [{escape_markdown(new_mem.first_name)}](tg://user?id={user.id}). Click the correct button to get unmuted!\n' - f'You got 120 seconds for this.', - reply_markup=InlineKeyboardMarkup(btn), - parse_mode=ParseMode.MARKDOWN, - reply_to_message_id=reply, - allow_sending_without_reply=True, - ) - bot.restrict_chat_member( + if welcome_bool: + if media_wel: + if ENUM_FUNC_MAP[welc_type] == dispatcher.bot.send_sticker: + sent = ENUM_FUNC_MAP[welc_type]( chat.id, - new_mem.id, - permissions=ChatPermissions( - can_send_messages=False, - can_invite_users=False, - can_pin_messages=False, - can_send_polls=False, - can_change_info=False, - can_send_media_messages=False, - can_send_other_messages=False, - can_add_web_page_previews=False, - ), - ) - job_queue.run_once( - partial(check_not_bot, new_mem, chat.id, message.message_id), - 120, - name="welcomemute", + cust_content, + reply_markup=keyboard, ) - - if welcome_bool: - if media_wel: - if ENUM_FUNC_MAP[welc_type] == dispatcher.bot.send_sticker: - sent = ENUM_FUNC_MAP[welc_type]( - chat.id, - cust_content, - reply_markup=keyboard, - reply_to_message_id=reply, - ) - else: - sent = ENUM_FUNC_MAP[welc_type]( - chat.id, - cust_content, - caption=res, - reply_markup=keyboard, - reply_to_message_id=reply, - parse_mode="markdown", - ) else: - sent = send(update, res, keyboard, backup_message) - prev_welc = sql.get_clean_pref(chat.id) - if prev_welc: - try: - bot.delete_message(chat.id, prev_welc) - except BadRequest: - pass + sent = ENUM_FUNC_MAP[welc_type]( + chat.id, + cust_content, + caption=res, + reply_markup=keyboard, + parse_mode="markdown", + ) + else: + sent = send(update, res, keyboard, backup_message) + prev_welc = sql.get_clean_pref(chat.id) + if prev_welc: + try: + bot.delete_message(chat.id, prev_welc) + except BadRequest: + pass - if sent: - sql.set_clean_welcome(chat.id, sent.message_id) + if sent: + sql.set_clean_welcome(chat.id, sent.message_id) - def clean_welc(_): - try: - bot.delete_message(chat.id, sent.message_id) - except: - pass + def clean_welc(_): + try: + bot.delete_message(chat.id, sent.message_id) + except: + pass - j.run_once(clean_welc, 300) + j.run_once(clean_welc, 300) - if not log_setting.log_joins: - return "" - if welcome_log: - return welcome_log + if not log_setting.log_joins: + return "" + if welcome_log: + return welcome_log return "" +def cleanServiceFilter(u: Update, _): + if u.effective_message.left_chat_member or u.effective_message.new_chat_members: + return handleCleanService(u) + + +def handleCleanService(update: Update): + if sql.clean_service(update.effective_chat.id): + try: + dispatcher.bot.delete_message(update.effective_chat.id, update.message.message_id) + except BadRequest: + pass + + +dispatcher.add_handler(MessageHandler(Filters.chat_type.groups, cleanServiceFilter)) + + def check_not_bot(member: User, chat_id: int, message_id: int, context: CallbackContext): bot = context.bot member_dict = VERIFIED_USER_WAITLIST.pop((chat_id, member.id)) @@ -607,7 +601,8 @@ def check_not_bot(member: User, chat_id: int, message_id: int, context: Callback member.first_name)), chat_id=chat_id, parse_mode=ParseMode.HTML) -@kigmsg((Filters.status_update.left_chat_member), group=WELCOME_GROUP) + +# @kigmsg((Filters.status_update.left_chat_member), group=WELCOME_GROUP) #@loggable def left_member(update: Update, context: CallbackContext): # sourcery no-metrics bot = context.bot @@ -618,20 +613,8 @@ def left_member(update: Update, context: CallbackContext): # sourcery no-metric if user.id == bot.id: return - reply = update.message.message_id - cleanserv = sql.clean_service(chat.id) - # Clean service welcome - if cleanserv: - try: - dispatcher.bot.delete_message(chat.id, update.message.message_id) - except BadRequest: - pass - reply = False - if should_goodbye: - - - left_mem = update.effective_message.left_chat_member + left_mem = update.chat_member.new_chat_member.user if left_mem: # Thingy for spamwatched users @@ -650,23 +633,22 @@ def left_member(update: Update, context: CallbackContext): # sourcery no-metric # Give the owner a special goodbye if left_mem.id == OWNER_ID: - update.effective_message.reply_text( - "Sorry to see you leave :(", reply_to_message_id=reply + bot.send_message(chat.id, + "Sorry to see you leave :(", ) return # Give the other bot a special goodbye if left_mem.id == 1826542418: - update.effective_message.reply_text( - "You can rest now...", reply_to_message_id=reply, parse_mode=ParseMode.HTML + bot.send_message(chat.id, + "You can rest now...", parse_mode=ParseMode.HTML ) return # Give the devs a special goodbye elif left_mem.id in DEV_USERS: - update.effective_message.reply_text( + bot.send_message(chat.id, "See you later Dev!", - reply_to_message_id=reply, ) return