# <============================================== IMPORTS =========================================================> import html import os import random import re import textwrap import time from contextlib import suppress from datetime import datetime from functools import partial import unidecode from PIL import Image, ImageChops, ImageDraw, ImageFont from pyrogram import filters as ft from pyrogram.types import ChatMemberUpdated, Message from telegram import ChatPermissions, InlineKeyboardButton, InlineKeyboardMarkup, Update from telegram.constants import ParseMode from telegram.error import BadRequest from telegram.ext import ( CallbackQueryHandler, CommandHandler, ContextTypes, MessageHandler, filters, ) from telegram.helpers import escape_markdown, mention_html, mention_markdown import Database.sql.welcome_sql as sql from Database.mongodb.toggle_mongo import dwelcome_off, dwelcome_on, is_dwelcome_on from Database.sql.global_bans_sql import is_user_gbanned from Infamous.temp import temp from Mikobot import DEV_USERS from Mikobot import DEV_USERS as SUDO from Mikobot import DRAGONS, EVENT_LOGS, LOGGER, OWNER_ID, app, dispatcher, function from Mikobot.plugins.helper_funcs.chat_status import check_admin, is_user_ban_protected from Mikobot.plugins.helper_funcs.misc import build_keyboard, revert_buttons from Mikobot.plugins.helper_funcs.msg_types import get_welcome_type from Mikobot.plugins.helper_funcs.string_handling import escape_invalid_curly_brackets from Mikobot.plugins.log_channel import loggable from Mikobot.utils.can_restrict import can_restrict # <=======================================================================================================> VALID_WELCOME_FORMATTERS = [ "first", "last", "fullname", "username", "id", "count", "chatname", "mention", ] ENUM_FUNC_MAP = { sql.Types.TEXT.value: dispatcher.bot.send_message, sql.Types.BUTTON_TEXT.value: dispatcher.bot.send_message, sql.Types.STICKER.value: dispatcher.bot.send_sticker, sql.Types.DOCUMENT.value: dispatcher.bot.send_document, sql.Types.PHOTO.value: dispatcher.bot.send_photo, sql.Types.AUDIO.value: dispatcher.bot.send_audio, sql.Types.VOICE.value: dispatcher.bot.send_voice, sql.Types.VIDEO.value: dispatcher.bot.send_video, } VERIFIED_USER_WAITLIST = {} # <================================================ TEMPLATE WELCOME FUNCTION =======================================================> async def circle(pfp, size=(259, 259)): pfp = pfp.resize(size, Image.ANTIALIAS).convert("RGBA") bigsize = (pfp.size[0] * 3, pfp.size[1] * 3) mask = Image.new("L", bigsize, 0) draw = ImageDraw.Draw(mask) draw.ellipse((0, 0) + bigsize, fill=255) mask = mask.resize(pfp.size, Image.ANTIALIAS) mask = ImageChops.darker(mask, pfp.split()[-1]) pfp.putalpha(mask) return pfp async def draw_multiple_line_text(image, text, font, text_start_height): draw = ImageDraw.Draw(image) image_width, image_height = image.size y_text = text_start_height lines = textwrap.wrap(text, width=50) for line in lines: line_width, line_height = font.getsize(line) draw.text( ((image_width - line_width) // 2, y_text), line, font=font, fill="black" ) y_text += line_height async def welcomepic(pic, user, chat, user_id): user = unidecode.unidecode(user) background = Image.open("Extra/bgg.jpg") background = background.resize( (background.size[0], background.size[1]), Image.ANTIALIAS ) pfp = Image.open(pic).convert("RGBA") pfp = await circle(pfp, size=(259, 259)) pfp_x = 55 pfp_y = (background.size[1] - pfp.size[1]) // 2 + 38 draw = ImageDraw.Draw(background) font = ImageFont.truetype("Extra/Calistoga-Regular.ttf", 42) text_width, text_height = draw.textsize(f"{user} [{user_id}]", font=font) text_x = 20 text_y = background.height - text_height - 20 - 25 draw.text((text_x, text_y), f"{user} [{user_id}]", font=font, fill="white") background.paste(pfp, (pfp_x, pfp_y), pfp) welcome_image_path = f"downloads/welcome_{user_id}.png" background.save(welcome_image_path) return welcome_image_path @app.on_chat_member_updated(ft.group) async def member_has_joined(client, member: ChatMemberUpdated): if ( not member.new_chat_member or member.new_chat_member.status in {"banned", "left", "restricted"} or member.old_chat_member ): return user = member.new_chat_member.user if member.new_chat_member else member.from_user if user.id in SUDO: await client.send_message(member.chat.id, "**Global Admins Joined The Chat!**") return elif user.is_bot: return else: chat_id = member.chat.id welcome_enabled = await is_dwelcome_on(chat_id) if not welcome_enabled: return if f"welcome-{chat_id}" in temp.MELCOW: try: await temp.MELCOW[f"welcome-{chat_id}"].delete() except: pass mention = f"{user.first_name}" joined_date = datetime.fromtimestamp(time.time()).strftime("%Y.%m. %d %H:%M:%S") first_name = ( f"{user.first_name} {user.last_name}" if user.last_name else user.first_name ) user_id = user.id dc = user.dc_id try: pic = await client.download_media( user.photo.big_file_id, file_name=f"pp{user_id}.png" ) except AttributeError: pic = "Extra/profilepic.png" try: welcomeimg = await welcomepic( pic, user.first_name, member.chat.title, user_id ) temp.MELCOW[f"welcome-{chat_id}"] = await client.send_photo( member.chat.id, photo=welcomeimg, caption=f"**π—›π—²π˜†β—οΈ{mention}, π—ͺ𝗲𝗹𝗰𝗼𝗺𝗲 𝗧𝗼 {member.chat.title} π—šπ—Ώπ—Όπ˜‚π—½.**\n\n**βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–βž–**\n**π—‘π—”π— π—˜ : {first_name}**\n**π—œπ—— : {user_id}**\n**π——π—”π—§π—˜ π—π—’π—œπ—‘π—˜π—— : {joined_date}**", ) except Exception as e: print(e) try: os.remove(f"downloads/welcome_{user_id}.png") os.remove(f"downloads/pp{user_id}.png") except Exception: pass @app.on_message(ft.command("dwelcome on")) @can_restrict async def enable_welcome(_, message: Message): chat_id = message.chat.id welcome_enabled = await is_dwelcome_on(chat_id) if welcome_enabled: await message.reply_text("Default welcome is already enabled") return await dwelcome_on(chat_id) await message.reply_text("New default welcome message enabled for this chat.") @app.on_message(ft.command("dwelcome off")) @can_restrict async def disable_welcome(_, message: Message): chat_id = message.chat.id welcome_enabled = await is_dwelcome_on(chat_id) if not welcome_enabled: await message.reply_text("Default welcome is already disabled") return await dwelcome_off(chat_id) await message.reply_text("New default welcome disabled for this chat.") # <=======================================================================================================> # <================================================ NORMAL WELCOME FUNCTION =======================================================> async def send(update: Update, message, keyboard, backup_message): chat = update.effective_chat cleanserv = sql.clean_service(chat.id) reply = update.effective_message.message_id if cleanserv: try: await dispatcher.bot.delete_message(chat.id, update.message.message_id) except BadRequest: pass reply = False try: try: msg = await dispatcher.bot.send_message( chat.id, message, parse_mode=ParseMode.HTML, reply_markup=keyboard, ) except: msg = await update.effective_message.reply_text( message, parse_mode=ParseMode.HTML, reply_markup=keyboard, reply_to_message_id=reply, ) except BadRequest as excp: if excp.message == "Reply message not found": msg = await update.effective_message.reply_text( message, parse_mode=ParseMode.MARKDOWN, reply_markup=keyboard, quote=False, ) elif excp.message == "Button_url_invalid": try: msg = await dispatcher.bot.send_message( chat.id, backup_message + "\nNote: The current message has an invalid URL in one of its buttons. Please update.", parse_mode=ParseMode.MARKDOWN, ) except: msg = await update.effective_message.reply_text( backup_message + "\nNote: The current message has an invalid URL in one of its buttons. Please update.", parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply, ) elif excp.message == "Unsupported URL protocol": try: msg = await dispatcher.bot.send_message( chat.id, backup_message + "\nNote: The current message has buttons which use URL protocols that are unsupported by Telegram. Please update.", parse_mode=ParseMode.MARKDOWN, ) except: msg = await update.effective_message.reply_text( backup_message + "\nNote: The current message has buttons which use URL protocols that are unsupported by Telegram. Please update.", parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply, ) elif excp.message == "Wrong URL host": try: msg = await dispatcher.bot.send_message( chat.id, backup_message + "\nNote: The current message has some bad URLs. Please update.", parse_mode=ParseMode.MARKDOWN, ) except: msg = await update.effective_message.reply_text( backup_message + "\nNote: The current message has some bad URLs. Please update.", parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply, ) LOGGER.warning(message) LOGGER.warning(keyboard) LOGGER.exception("Could not parse! Got invalid URL host errors") elif excp.message == "Have no rights to send a message": return else: try: msg = await dispatcher.bot.send_message( chat.id, backup_message + "\nNote: An error occurred when sending the custom message. Please update.", parse_mode=ParseMode.MARKDOWN, ) except: msg = await update.effective_message.reply_text( backup_message + "\nNote: An error occurred when sending the custom message. Please update.", parse_mode=ParseMode.MARKDOWN, reply_to_message_id=reply, ) LOGGER.exception() return msg @loggable async def new_member(update: Update, context: ContextTypes.DEFAULT_TYPE): bot, job_queue = context.bot, context.job_queue chat = update.effective_chat user = update.effective_user msg = update.effective_message should_welc, cust_welcome, cust_content, welc_type = sql.get_welc_pref(chat.id) welc_mutes = sql.welcome_mutes(chat.id) human_checks = sql.get_human_checks(user.id, chat.id) new_members = update.effective_message.new_chat_members for new_mem in new_members: if new_mem.id == bot.id and not Mikobot.ALLOW_CHATS: with suppress(BadRequest): await update.effective_message.reply_text( "Groups are disabled for {}, I'm outta here.".format(bot.first_name) ) await bot.leave_chat(update.effective_chat.id) return welcome_log = None res = None sent = None should_mute = True welcome_bool = True media_wel = False if is_user_gbanned(new_mem.id): return if should_welc: reply = update.message.message_id cleanserv = sql.clean_service(chat.id) if cleanserv: try: await dispatcher.bot.delete_message( chat.id, update.message.message_id ) except BadRequest: pass reply = False if new_mem.id == OWNER_ID: await update.effective_message.reply_text( "Oh, darling, I have searched for you everywhere.", reply_to_message_id=reply, ) welcome_log = ( "{}\n" "#USER_JOINED\n" "Bot owner just joined the group".format(html.escape(chat.title)) ) continue elif new_mem.id in DEV_USERS: await update.effective_message.reply_text( "Be cool! A member of the team just joined.", reply_to_message_id=reply, ) welcome_log = ( "{}\n" "#USER_JOINED\n" "Bot dev just joined the group".format(html.escape(chat.title)) ) continue elif new_mem.id in DRAGONS: await update.effective_message.reply_text( "Whoa! A dragon disaster just joined! Stay alert!", reply_to_message_id=reply, ) welcome_log = ( "{}\n" "#USER_JOINED\n" "Bot sudo just joined the group".format(html.escape(chat.title)) ) continue elif new_mem.id == bot.id: creator = None for x in await bot.get_chat_administrators(update.effective_chat.id): if x.status == "creator": creator = x.user break if creator: reply = """#NEWGROUP \ \nID: `{}` \ """.format( chat.id ) if chat.title: reply += "\nGroup name: **{}**".format( escape_markdown(chat.title) ) if chat.username: reply += "\nUsername: @{}".format( escape_markdown(chat.username) ) reply += "\nCreator ID: `{}`".format(creator.id) if creator.username: reply += "\nCreator Username: @{}".format(creator.username) await bot.send_message( EVENT_LOGS, reply, parse_mode="markdown", ) else: await bot.send_message( EVENT_LOGS, "#NEW_GROUP\nGroup name: {}\nID: {}".format( html.escape(chat.title), chat.id, ), parse_mode=ParseMode.HTML, ) await update.effective_message.reply_text( "I feel like I'm gonna suffocate in here.", reply_to_message_id=reply, ) continue else: buttons = sql.get_welc_buttons(chat.id) keyb = build_keyboard(buttons) if welc_type not in (sql.Types.TEXT, sql.Types.BUTTON_TEXT): media_wel = True first_name = new_mem.first_name or "PersonWithNoName" 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( "{} {}".format(first_name, new_mem.last_name) ) else: fullname = escape_markdown(first_name) count = await chat.get_member_count() mention = mention_markdown(new_mem.id, escape_markdown(first_name)) if new_mem.username: username = "@{}".format(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, ) else: res = random.choice(sql.DEFAULT_WELCOME_MESSAGES).format( first=escape_markdown(first_name), ) keyb = [] 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 if ( await is_user_ban_protected( chat, new_mem.id, await chat.get_member(new_mem.id) ) or human_checks ): should_mute = False if new_mem.is_bot: should_mute = False if user.id == new_mem.id: if should_mute: if welc_mutes == "soft": await 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, can_manage_topics=False, ), until_date=(int(time.time() + 24 * 60 * 60)), ) if welc_mutes == "strong": welcome_bool = False if not media_wel: VERIFIED_USER_WAITLIST.update( { 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( { 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 = '{}'.format( user.id, html.escape(new_mem.first_name) ) message = await msg.reply_text( "{}\nYou have 120 seconds to prove you're human.".format( new_join_mem ), reply_markup=InlineKeyboardMarkup( [ [ InlineKeyboardButton( text="YES, I'M HUMAN", callback_data="user_join_({})".format( new_mem.id ), ), ], ], ), parse_mode=ParseMode.HTML, reply_to_message_id=reply, ) await 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, can_manage_topics=False, ), ) job_queue.run_once( partial(check_not_bot, new_mem, chat.id, message.message_id), 120, name="welcomemute", ) if welcome_bool: if media_wel: sent = await ENUM_FUNC_MAP[welc_type]( chat.id, cust_content, caption=res, reply_markup=keyboard, reply_to_message_id=reply, parse_mode="markdown", ) else: sent = await send(update, res, keyboard, backup_message) prev_welc = sql.get_clean_pref(chat.id) if prev_welc: try: await bot.delete_message(chat.id, prev_welc) except BadRequest: pass if sent: sql.set_clean_welcome(chat.id, sent.message_id) if welcome_log: return welcome_log if user.id == new_mem.id: welcome_log = ( "{}\n" "#USER_JOINED\n" "User: {}\n" "ID: {}".format( html.escape(chat.title), mention_html(user.id, user.first_name), user.id, ) ) elif new_mem.is_bot and user.id != new_mem.id: welcome_log = ( "{}\n" "#BOT_ADDED\n" "Bot: {}\n" "ID: {}".format( html.escape(chat.title), mention_html(new_mem.id, new_mem.first_name), new_mem.id, ) ) else: welcome_log = ( "{}\n" "#USER_ADDED\n" "User: {}\n" "ID: {}".format( html.escape(chat.title), mention_html(new_mem.id, new_mem.first_name), new_mem.id, ) ) return welcome_log return "" async def check_not_bot(member, chat_id, message_id, context): bot = context.bot member_dict = VERIFIED_USER_WAITLIST.pop(member.id) member_status = member_dict.get("status") if not member_status: try: await bot.unban_chat_member(chat_id, member.id) except: pass try: await bot.edit_message_text( "Kicks user\nThey can always rejoin and try.", chat_id=chat_id, message_id=message_id, ) except: pass async def left_member(update, context: ContextTypes.DEFAULT_TYPE): bot = context.bot chat = update.effective_chat user = update.effective_user should_goodbye, cust_goodbye, goodbye_type = sql.get_gdbye_pref(chat.id) if user.id == bot.id: return if should_goodbye: reply = update.message.message_id cleanserv = sql.clean_service(chat.id) if cleanserv: try: await dispatcher.bot.delete_message(chat.id, update.message.message_id) except BadRequest: pass reply = False left_mem = update.effective_message.left_chat_member if left_mem: if is_user_gbanned(left_mem.id): return if left_mem.id == bot.id: return if left_mem.id == OWNER_ID: await update.effective_message.reply_text( "My master left..", reply_to_message_id=reply, ) return elif left_mem.id in DEV_USERS: await update.effective_message.reply_text( "see you later pro!", reply_to_message_id=reply, ) return if goodbye_type != sql.Types.TEXT and goodbye_type != sql.Types.BUTTON_TEXT: await ENUM_FUNC_MAP[goodbye_type](chat.id, cust_goodbye) return first_name = left_mem.first_name or "PersonWithNoName" if cust_goodbye: if cust_goodbye == sql.DEFAULT_GOODBYE: cust_goodbye = random.choice(sql.DEFAULT_GOODBYE_MESSAGES).format( first=first_name, ) if left_mem.last_name: fullname = "{} {}".format(first_name, left_mem.last_name) else: fullname = first_name count = await chat.get_member_count() mention = mention_markdown(left_mem.id, first_name) if left_mem.username: username = "@{}".format(left_mem.username) else: username = mention valid_format = escape_invalid_curly_brackets( cust_goodbye, VALID_WELCOME_FORMATTERS, ) res = valid_format.format( first=first_name, last=left_mem.last_name or first_name, fullname=fullname, username=username, mention=mention, count=count, chatname=chat.title, id=left_mem.id, ) buttons = sql.get_gdbye_buttons(chat.id) keyb = build_keyboard(buttons) else: res = random.choice(sql.DEFAULT_GOODBYE_MESSAGES).format( first=first_name, ) keyb = [] keyboard = InlineKeyboardMarkup(keyb) await send( update, res, keyboard, random.choice(sql.DEFAULT_GOODBYE_MESSAGES).format(first=first_name), ) @check_admin(is_user=True) async def welcome(update, context: ContextTypes.DEFAULT_TYPE): args = context.args chat = update.effective_chat if not args or args[0].lower() == "noformat": noformat = True pref, welcome_m, cust_content, welcome_type = sql.get_welc_pref(chat.id) await update.effective_message.reply_text( f"This chat has its welcome setting set to: `{pref}`.\n" f"The welcome message (not filling the {{}}) is:", parse_mode=ParseMode.MARKDOWN, ) if welcome_type == sql.Types.BUTTON_TEXT or welcome_type == sql.Types.TEXT: buttons = sql.get_welc_buttons(chat.id) if noformat: welcome_m += revert_buttons(buttons) await update.effective_message.reply_text(welcome_m) else: keyb = build_keyboard(buttons) keyboard = InlineKeyboardMarkup(keyb) await send(update, welcome_m, keyboard, sql.DEFAULT_WELCOME) else: buttons = sql.get_welc_buttons(chat.id) if noformat: welcome_m += revert_buttons(buttons) await ENUM_FUNC_MAP[welcome_type]( chat.id, cust_content, caption=welcome_m ) else: keyb = build_keyboard(buttons) keyboard = InlineKeyboardMarkup(keyb) ENUM_FUNC_MAP[welcome_type]( chat.id, cust_content, caption=welcome_m, reply_markup=keyboard, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True, ) elif len(args) >= 1: if args[0].lower() in ("on", "yes"): sql.set_welc_preference(str(chat.id), True) await update.effective_message.reply_text( "Okay! I'll greet members when they join.", ) elif args[0].lower() in ("off", "no"): sql.set_welc_preference(str(chat.id), False) await update.effective_message.reply_text( "I'll go loaf around and not welcome anyone then.", ) else: await update.effective_message.reply_text( "I understand 'on/yes' or 'off/no' only!", ) @check_admin(is_user=True) async def goodbye(update, context: ContextTypes.DEFAULT_TYPE): args = context.args chat = update.effective_chat if not args or args[0] == "noformat": noformat = True pref, goodbye_m, goodbye_type = sql.get_gdbye_pref(chat.id) await update.effective_message.reply_text( f"This chat has its goodbye setting set to: `{pref}`.\n" f"The goodbye message (not filling the {{}}) is:", parse_mode=ParseMode.MARKDOWN, ) if goodbye_type == sql.Types.BUTTON_TEXT: buttons = sql.get_gdbye_buttons(chat.id) if noformat: goodbye_m += revert_buttons(buttons) await update.effective_message.reply_text(goodbye_m) else: keyb = build_keyboard(buttons) keyboard = InlineKeyboardMarkup(keyb) await send(update, goodbye_m, keyboard, sql.DEFAULT_GOODBYE) else: if noformat: await ENUM_FUNC_MAP[goodbye_type](chat.id, goodbye_m) else: await ENUM_FUNC_MAP[goodbye_type]( chat.id, goodbye_m, parse_mode=ParseMode.MARKDOWN ) elif len(args) >= 1: if args[0].lower() in ("on", "yes"): sql.set_gdbye_preference(str(chat.id), True) await update.effective_message.reply_text("Okay its set to on!") elif args[0].lower() in ("off", "no"): sql.set_gdbye_preference(str(chat.id), False) await update.effective_message.reply_text("Okay its set to no!") else: await update.effective_message.reply_text( "I understand 'on/yes' or 'off/no' only!", ) @check_admin(is_user=True) @loggable async def set_welcome(update, context: ContextTypes.DEFAULT_TYPE): chat = update.effective_chat user = update.effective_user msg = update.effective_message text, data_type, content, buttons = get_welcome_type(msg) if data_type is None: await msg.reply_text("You didn't specify what to reply with!") return "" sql.set_custom_welcome(chat.id, content, text, data_type, buttons) await msg.reply_text("Successfully set custom welcome message!") return ( f"{html.escape(chat.title)}:\n" f"#SET_WELCOME\n" f"Admin: {mention_html(user.id, user.first_name)}\n" "Set the welcome message." ) @check_admin(is_user=True) @loggable async def reset_welcome(update, context: ContextTypes.DEFAULT_TYPE): chat = update.effective_chat user = update.effective_user sql.set_custom_welcome(chat.id, None, sql.DEFAULT_WELCOME, sql.Types.TEXT) await update.effective_message.reply_text( "Successfully reset welcome message to default!" ) return ( f"{html.escape(chat.title)}:\n" f"#RESET_WELCOME\n" f"Admin: {mention_html(user.id, user.first_name)}\n" "Reset the welcome message to default." ) @check_admin(is_user=True) @loggable async def set_goodbye(update, context: ContextTypes.DEFAULT_TYPE): chat = update.effective_chat user = update.effective_user msg = update.effective_message text, data_type, content, buttons = get_welcome_type(msg) if data_type is None: await msg.reply_text("You didn't specify what to reply with!") return "" sql.set_custom_gdbye(chat.id, content or text, data_type, buttons) await msg.reply_text("Successfully set custom goodbye message!") return ( f"{html.escape(chat.title)}:\n" f"#SET_GOODBYE\n" f"Admin: {mention_html(user.id, user.first_name)}\n" "Set the goodbye message." ) @check_admin(is_user=True) @loggable async def reset_goodbye(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: chat = update.effective_chat user = update.effective_user sql.set_custom_gdbye(chat.id, sql.DEFAULT_GOODBYE, sql.Types.TEXT) await update.effective_message.reply_text( "Successfully reset goodbye message to default!", ) return ( f"{html.escape(chat.title)}:\n" f"#RESET_GOODBYE\n" f"Admin: {mention_html(user.id, user.first_name)}\n" f"Reset the goodbye message." ) @check_admin(is_user=True) @loggable async def welcomemute(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: args = context.args chat = update.effective_chat user = update.effective_user msg = update.effective_message if len(args) >= 1: if args[0].lower() in ("off", "no"): sql.set_welcome_mutes(chat.id, False) await msg.reply_text("I will no longer mute people on joining!") return ( f"{html.escape(chat.title)}:\n" f"#WELCOME_MUTE\n" f"Admin: {mention_html(user.id, user.first_name)}\n" f"Has toggled welcome mute to off." ) elif args[0].lower() in ["soft"]: sql.set_welcome_mutes(chat.id, "soft") await msg.reply_text( "I will restrict users permission to send media for 24 hours.", ) return ( f"{html.escape(chat.title)}:\n" f"#π–π„π‹π‚πŽπŒπ„_πŒπ”π“π„\n" f"Admin: {mention_html(user.id, user.first_name)}\n" f"Has toggled welcome mute to soft." ) elif args[0].lower() in ["strong"]: sql.set_welcome_mutes(chat.id, "strong") await msg.reply_text( "I will now mute people when they join until they prove they're not a bot. They will have 120 seconds before they get kicked.", ) return ( f"{html.escape(chat.title)}:\n" f"#π–π„π‹π‚πŽπŒπ„_πŒπ”π“π„\n" f"Admin: {mention_html(user.id, user.first_name)}\n" f"Has toggled welcome mute to strong." ) else: await msg.reply_text( "Please enter off/no/soft/strong!", parse_mode=ParseMode.HTML, ) return "" else: curr_setting = sql.welcome_mutes(chat.id) reply = ( "Give me a setting!\nChoose one out of: off/no or soft or strong only! \n" f"Current setting: {curr_setting}" ) await msg.reply_text(reply, parse_mode=ParseMode.HTML) return "" @check_admin(is_user=True) @loggable async def clean_welcome(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: args = context.args chat = update.effective_chat user = update.effective_user if not args: clean_pref = sql.get_clean_pref(chat.id) if clean_pref: await update.effective_message.reply_text( "I should be deleting welcome messages up to two days old.", ) else: await update.effective_message.reply_text( "I'm currently not deleting old welcome messages!", ) return "" if args[0].lower() in ("on", "yes"): sql.set_clean_welcome(str(chat.id), True) await update.effective_message.reply_text( "I'll try to delete old welcome messages!" ) return ( f"{html.escape(chat.title)}:\n" f"#𝐂𝐋𝐄𝐀𝐍_π–π„π‹π‚πŽπŒπ„\n" f"Admin: {mention_html(user.id, user.first_name)}\n" "Has toggled clean welcomes to on." ) elif args[0].lower() in ("off", "no"): sql.set_clean_welcome(str(chat.id), False) await update.effective_message.reply_text( "I won't delete old welcome messages." ) return ( f"{html.escape(chat.title)}:\n" f"#𝐂𝐋𝐄𝐀𝐍_π–π„π‹π‚πŽπŒπ„\n" f"Admin: {mention_html(user.id, user.first_name)}\n" "Has toggled clean welcomes to off." ) else: await update.effective_message.reply_text( "I understand 'on/yes' or 'off/no' only!", ) return "" @check_admin(is_user=True) async def cleanservice(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: args = context.args chat = update.effective_chat # type: Optional[Chat] if chat.type != chat.PRIVATE: if len(args) >= 1: var = args[0] if var in ("no", "off"): sql.set_clean_service(chat.id, False) await update.effective_message.reply_text( "Welcome clean service is : off" ) elif var in ("yes", "on"): sql.set_clean_service(chat.id, True) await update.effective_message.reply_text( "Welcome clean service is : on" ) else: await update.effective_message.reply_text( "Invalid option", parse_mode=ParseMode.HTML, ) else: await update.effective_message.reply_text( "Usage is on/yes or off/no", parse_mode=ParseMode.HTML, ) else: curr = sql.clean_service(chat.id) if curr: await update.effective_message.reply_text( "Welcome clean service is : on", parse_mode=ParseMode.HTML, ) else: await update.effective_message.reply_text( "Welcome clean service is : off", parse_mode=ParseMode.HTML, ) async def user_button(update: Update, context: ContextTypes.DEFAULT_TYPE): chat = update.effective_chat user = update.effective_user query = update.callback_query bot = context.bot match = re.match(r"user_join_\((.+?)\)", query.data) message = update.effective_message join_user = int(match.group(1)) if join_user == user.id: sql.set_human_checks(user.id, chat.id) member_dict = VERIFIED_USER_WAITLIST.pop(user.id) member_dict["status"] = True VERIFIED_USER_WAITLIST.update({user.id: member_dict}) await query.answer(text="Yeet! You're a human, unmuted!") await bot.restrict_chat_member( chat.id, user.id, permissions=ChatPermissions( can_send_messages=True, can_invite_users=True, can_pin_messages=True, can_send_polls=True, can_change_info=True, can_send_media_messages=True, can_send_other_messages=True, can_add_web_page_previews=True, can_manage_topics=False, ), ) try: await bot.deleteMessage(chat.id, message.message_id) except: pass if member_dict["should_welc"]: if member_dict["media_wel"]: # topic_chat = get_action_topic(chat.id) sent = await ENUM_FUNC_MAP[member_dict["welc_type"]]( member_dict["chat_id"], member_dict["cust_content"], caption=member_dict["res"], reply_markup=member_dict["keyboard"], parse_mode="markdown", ) else: sent = await send( member_dict["update"], member_dict["res"], member_dict["keyboard"], member_dict["backup_message"], ) prev_welc = sql.get_clean_pref(chat.id) if prev_welc: try: await bot.delete_message(chat.id, prev_welc) except BadRequest: pass if sent: sql.set_clean_welcome(chat.id, sent.message_id) else: await query.answer(text="You're not allowed to do this!") WELC_MUTE_HELP_TXT = ( "You can get the bot to mute new people who join your group and hence prevent spambots from flooding your group. " "The following options are possible:\n" "β€’ `/welcomemute soft`: Restricts new members from sending media for 24 hours.\n" "β€’ `/welcomemute strong`: Mutes new members until they tap on a button, thereby verifying they're human.\n" "β€’ `/welcomemute off`: Turns off welcomemute.\n" "Note: Strong mode kicks a user from the chat if they don't verify in 120 seconds. They can always rejoin though." ) @check_admin(is_user=True) async def welcome_help(update: Update, context: ContextTypes.DEFAULT_TYPE): WELC_HELP_TXT = ( "Your group's welcome/goodbye messages can be personalized in multiple ways. If you want the messages" " to be individually generated, like the default welcome message is, you can use these variables:\n" " β€’ `{first}`: This represents the user's *first* name\n" " β€’ `{last}`: This represents the user's *last* name. Defaults to *first name* if the user has no last name.\n" " β€’ `{fullname}`: This represents the user's *full* name. Defaults to *first name* if the user has no last name.\n" " β€’ `{username}`: This represents the user's *username*. Defaults to a *mention* of the user's" " first name if they have no username.\n" " β€’ `{mention}`: This simply *mentions* a user - tagging them with their first name.\n" " β€’ `{id}`: This represents the user's *ID*\n" " β€’ `{count}`: This represents the user's *member number*.\n" " β€’ `{chatname}`: This represents the *current chat name*.\n" "\nEach variable must be surrounded by `{}` to be replaced.\n" "Welcome messages also support markdown, so you can make any elements bold/italic/code/links. " "Buttons are also supported, so you can make your welcomes look awesome with some nice intro buttons." "\nTo create a button linking to your rules, use this: `[rules](buttonurl://t.me/" f"{context.bot.username}?start=group_id)`. Simply replace `group_id` with your group's ID," " which can be obtained via /id, and you're good to go. Note that group IDs are usually preceded by a `-` sign, so please don't remove it." " You can even set images/gifs/videos/voice messages as the welcome message by replying to the desired media," " and calling `/setwelcome`." ) await update.effective_message.reply_text( WELC_HELP_TXT, parse_mode=ParseMode.MARKDOWN ) @check_admin(is_user=True) async def welcome_mute_help(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.effective_message.reply_text( WELC_MUTE_HELP_TXT, parse_mode=ParseMode.MARKDOWN, ) def __migrate__(old_chat_id, new_chat_id): sql.migrate_chat(old_chat_id, new_chat_id) def __chat_settings__(chat_id, user_id): welcome_pref = sql.get_welc_pref(chat_id)[0] goodbye_pref = sql.get_gdbye_pref(chat_id)[0] return ( f"This chat has its welcome preference set to `{welcome_pref}`.\n" f"Its goodbye preference is `{goodbye_pref}`." ) # <=================================================== HELP ====================================================> __help__ = """ ➠ *Admins Only:* ➠ *Default Welcome CMDS:* Β» /dwelcome on : Enables the default template welcome. Β» /dwelcome off : Disables the default template welcome. ➠ *Normal Welcome CMDS:* Β» /welcome : Enable/disable welcome messages. Β» /welcome: Shows current welcome settings. Β» /welcome noformat: Shows current welcome settings, without the formatting - useful to recycle your welcome messages! Β» /goodbye: Same usage and args as /welcome Β» /setwelcome : Set a custom welcome message. If used replying to media, uses that media. Β» /setgoodbye : Set a custom goodbye message. If used replying to media, uses that media. Β» /resetwelcome: Reset to the default welcome message. Β» /resetgoodbye: Reset to the default goodbye message. Β» /cleanwelcome : On new member, try to delete the previous welcome message to avoid spamming the chat. Β» /welcomemutehelp: Gives information about welcome mutes. Β» /cleanservice : Deletes Telegram's welcome/left service messages. ➠ *Example:* User joined chat, user left chat. ➠ *Welcome Markdown:* Β» /welcomehelp: View more formatting information for custom welcome/goodbye messages. """ # <================================================ HANDLER =======================================================> NEW_MEM_HANDLER = MessageHandler( filters.StatusUpdate.NEW_CHAT_MEMBERS, new_member, block=False ) LEFT_MEM_HANDLER = MessageHandler( filters.StatusUpdate.LEFT_CHAT_MEMBER, left_member, block=False ) WELC_PREF_HANDLER = CommandHandler( "welcome", welcome, filters=filters.ChatType.GROUPS, block=False ) GOODBYE_PREF_HANDLER = CommandHandler( "goodbye", goodbye, filters=filters.ChatType.GROUPS, block=False ) SET_WELCOME = CommandHandler( "setwelcome", set_welcome, filters=filters.ChatType.GROUPS, block=False ) SET_GOODBYE = CommandHandler( "setgoodbye", set_goodbye, filters=filters.ChatType.GROUPS, block=False ) RESET_WELCOME = CommandHandler( "resetwelcome", reset_welcome, filters=filters.ChatType.GROUPS, block=False ) RESET_GOODBYE = CommandHandler( "resetgoodbye", reset_goodbye, filters=filters.ChatType.GROUPS, block=False ) WELCOMEMUTE_HANDLER = CommandHandler( "welcomemute", welcomemute, filters=filters.ChatType.GROUPS, block=False ) CLEAN_SERVICE_HANDLER = CommandHandler( "cleanservice", cleanservice, filters=filters.ChatType.GROUPS, block=False ) CLEAN_WELCOME = CommandHandler( "cleanwelcome", clean_welcome, filters=filters.ChatType.GROUPS, block=False ) WELCOME_HELP = CommandHandler("welcomehelp", welcome_help, block=False) WELCOME_MUTE_HELP = CommandHandler("welcomemutehelp", welcome_mute_help, block=False) BUTTON_VERIFY_HANDLER = CallbackQueryHandler( user_button, pattern=r"user_join_", block=False ) function(NEW_MEM_HANDLER) function(LEFT_MEM_HANDLER) function(WELC_PREF_HANDLER) function(GOODBYE_PREF_HANDLER) function(SET_WELCOME) function(SET_GOODBYE) function(RESET_WELCOME) function(RESET_GOODBYE) function(CLEAN_WELCOME) function(WELCOME_HELP) function(WELCOMEMUTE_HANDLER) function(CLEAN_SERVICE_HANDLER) function(BUTTON_VERIFY_HANDLER) function(WELCOME_MUTE_HELP) __mod_name__ = "WELCOME" __command_list__ = [] __handlers__ = [ NEW_MEM_HANDLER, LEFT_MEM_HANDLER, WELC_PREF_HANDLER, GOODBYE_PREF_HANDLER, SET_WELCOME, SET_GOODBYE, RESET_WELCOME, RESET_GOODBYE, CLEAN_WELCOME, WELCOME_HELP, WELCOMEMUTE_HANDLER, CLEAN_SERVICE_HANDLER, BUTTON_VERIFY_HANDLER, WELCOME_MUTE_HELP, ] # <================================================ END =======================================================>