import html from alphabet_detector import AlphabetDetector from telegram import ( Chat, ChatMemberAdministrator, ChatPermissions, MessageEntity, Update, ) from telegram.constants import ParseMode from telegram.error import BadRequest, TelegramError from telegram.ext import CommandHandler, ContextTypes, MessageHandler, filters from telegram.helpers import mention_html import Database.sql.locks_sql as sql from Database.sql.approve_sql import is_approved from Mikobot import DRAGONS, LOGGER, dispatcher, function from Mikobot.plugins.connection import connected from Mikobot.plugins.disable import DisableAbleCommandHandler from Mikobot.plugins.helper_funcs.alternate import send_message, typing_action from Mikobot.plugins.helper_funcs.chat_status import ( check_admin, is_bot_admin, user_not_admin, ) from Mikobot.plugins.log_channel import loggable ad = AlphabetDetector() LOCK_TYPES = { "audio": filters.AUDIO, "voice": filters.VOICE, "document": filters.Document.ALL, "video": filters.VIDEO, "contact": filters.CONTACT, "photo": filters.PHOTO, "url": filters.Entity(MessageEntity.URL) | filters.CaptionEntity(MessageEntity.URL), "bots": filters.StatusUpdate.NEW_CHAT_MEMBERS, "forward": filters.FORWARDED, "game": filters.GAME, "location": filters.LOCATION, "egame": filters.Dice.ALL, "rtl": "rtl", "button": "button", "inline": "inline", "phone": filters.Entity(MessageEntity.PHONE_NUMBER) | filters.CaptionEntity(MessageEntity.PHONE_NUMBER), "command": filters.COMMAND, "email": filters.Entity(MessageEntity.EMAIL) | filters.CaptionEntity(MessageEntity.EMAIL), "anonchannel": "anonchannel", "forwardchannel": "forwardchannel", "forwardbot": "forwardbot", # "invitelink": , "videonote": filters.VIDEO_NOTE, "emojicustom": filters.Entity(MessageEntity.CUSTOM_EMOJI) | filters.CaptionEntity(MessageEntity.CUSTOM_EMOJI), "stickerpremium": filters.Sticker.PREMIUM, "stickeranimated": filters.Sticker.ANIMATED, } LOCK_CHAT_RESTRICTION = { "all": { "can_send_messages": False, "can_send_media_messages": False, "can_send_polls": False, "can_send_other_messages": False, "can_add_web_page_previews": False, "can_change_info": False, "can_invite_users": False, "can_pin_messages": False, "can_manage_topics": False, }, "messages": {"can_send_messages": False}, "media": {"can_send_media_messages": False}, "sticker": {"can_send_other_messages": False}, "gif": {"can_send_other_messages": False}, "poll": {"can_send_polls": False}, "other": {"can_send_other_messages": False}, "previews": {"can_add_web_page_previews": False}, "info": {"can_change_info": False}, "invite": {"can_invite_users": False}, "pin": {"can_pin_messages": False}, "topics": {"can_manage_topics": False}, } UNLOCK_CHAT_RESTRICTION = { "all": { "can_send_messages": True, "can_send_media_messages": True, "can_send_polls": True, "can_send_other_messages": True, "can_add_web_page_previews": True, "can_invite_users": True, "can_manage_topics": True, }, "messages": {"can_send_messages": True}, "media": {"can_send_media_messages": True}, "sticker": {"can_send_other_messages": True}, "gif": {"can_send_other_messages": True}, "poll": {"can_send_polls": True}, "other": {"can_send_other_messages": True}, "previews": {"can_add_web_page_previews": True}, "info": {"can_change_info": True}, "invite": {"can_invite_users": True}, "pin": {"can_pin_messages": True}, "topics": {"can_manage_topics": True}, } PERM_GROUP = 1 REST_GROUP = 2 # NOT ASYNC async def restr_members( bot, chat_id, members, messages=False, media=False, other=False, previews=False, ): for mem in members: if mem.user in DRAGONS: pass elif mem.user == 777000 or mem.user == 1087968824: pass try: await bot.restrict_chat_member( chat_id, mem.user, permissions=ChatPermissions( can_send_messages=messages, can_send_media_messages=media, can_send_other_messages=other, can_add_web_page_previews=previews, ), ) except TelegramError: pass # NOT ASYNC async def unrestr_members( bot, chat_id, members, messages=True, media=True, other=True, previews=True, ): for mem in members: try: await bot.restrict_chat_member( chat_id, mem.user, permissions=ChatPermissions( can_send_messages=messages, can_send_media_messages=media, can_send_other_messages=other, can_add_web_page_previews=previews, ), ) except TelegramError: pass async def locktypes(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.effective_message.reply_text( "\n • ".join( ["Locks available: "] + sorted(list(LOCK_TYPES) + list(LOCK_CHAT_RESTRICTION)), ), ) @check_admin(permission="can_delete_messages", is_both=True) @loggable @typing_action async def lock(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: args = context.args chat = update.effective_chat user = update.effective_user if len(args) >= 1: ltype = args[0].lower() if ltype in LOCK_TYPES: # Connection check conn = await connected(context.bot, update, chat, user.id, need_admin=True) if conn: chat = await dispatcher.bot.getChat(conn) chat_id = conn chat_name = chat.title text = "Locked {} for non-admins in {}!".format(ltype, chat_name) else: if update.effective_message.chat.type == "private": await send_message( update.effective_message, "This command is meant to use in group not in PM", ) return "" chat = update.effective_chat chat_id = update.effective_chat.id chat_name = update.effective_message.chat.title text = "Locked {} for non-admins!".format(ltype) sql.update_lock(chat.id, ltype, locked=True) await send_message(update.effective_message, text, parse_mode="markdown") return ( "{}:" "\n#LOCK" "\nAdmin: {}" "\nLocked {}.".format( html.escape(chat.title), mention_html(user.id, user.first_name), ltype, ) ) elif ltype in LOCK_CHAT_RESTRICTION: # Connection check conn = await connected(context.bot, update, chat, user.id, need_admin=True) if conn: chat = await dispatcher.bot.getChat(conn) chat_id = conn chat_name = chat.title text = "Locked {} for all non-admins in {}!".format( ltype, chat_name, ) else: if update.effective_message.chat.type == "private": await send_message( update.effective_message, "This command is meant to use in group not in PM", ) return "" chat = update.effective_chat chat_id = update.effective_chat.id chat_name = update.effective_message.chat.title text = "Locked {} for all non-admins!".format(ltype) chat_obj = await context.bot.getChat(chat_id) current_permission = chat_obj.permissions await context.bot.set_chat_permissions( chat_id=chat_id, permissions=get_permission_list( current_permission.to_dict(), LOCK_CHAT_RESTRICTION[ltype.lower()], ), ) await context.bot.restrict_chat_member( chat.id, int(777000), permissions=ChatPermissions( can_send_messages=True, can_send_media_messages=True, can_send_other_messages=True, can_add_web_page_previews=True, ), ) await context.bot.restrict_chat_member( chat.id, int(1087968824), permissions=ChatPermissions( can_send_messages=True, can_send_media_messages=True, can_send_other_messages=True, can_add_web_page_previews=True, ), ) await send_message(update.effective_message, text, parse_mode="markdown") return ( "{}:" "\n#Permission_LOCK" "\nAdmin: {}" "\nLocked {}.".format( html.escape(chat.title), mention_html(user.id, user.first_name), ltype, ) ) else: await send_message( update.effective_message, "What are you trying to lock...? Try /locktypes for the list of lockables", ) else: await send_message(update.effective_message, "What are you trying to lock...?") return "" @check_admin(permission="can_delete_messages", is_both=True) @loggable @typing_action async def unlock(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str: args = context.args chat = update.effective_chat user = update.effective_user message = update.effective_message if len(args) >= 1: ltype = args[0].lower() if ltype in LOCK_TYPES: # Connection check conn = await connected(context.bot, update, chat, user.id, need_admin=True) if conn: chat = await dispatcher.bot.getChat(conn) chat_id = conn chat_name = chat.title text = "Unlocked {} for everyone in {}!".format(ltype, chat_name) else: if update.effective_message.chat.type == "private": await send_message( update.effective_message, "This command is meant to use in group not in PM", ) return "" chat = update.effective_chat chat_id = update.effective_chat.id chat_name = update.effective_message.chat.title text = "Unlocked {} for everyone!".format(ltype) sql.update_lock(chat.id, ltype, locked=False) await send_message(update.effective_message, text, parse_mode="markdown") return ( "{}:" "\n#UNLOCK" "\nAdmin: {}" "\nUnlocked {}.".format( html.escape(chat.title), mention_html(user.id, user.first_name), ltype, ) ) elif ltype in UNLOCK_CHAT_RESTRICTION: # Connection check conn = await connected(context.bot, update, chat, user.id, need_admin=True) if conn: chat = await dispatcher.bot.getChat(conn) chat_id = conn chat_name = chat.title text = "Unlocked {} for everyone in {}!".format(ltype, chat_name) else: if update.effective_message.chat.type == "private": await send_message( update.effective_message, "This command is meant to use in group not in PM", ) return "" chat = update.effective_chat chat_id = update.effective_chat.id chat_name = update.effective_message.chat.title text = "Unlocked {} for everyone!".format(ltype) member = await chat.get_member(context.bot.id) if isinstance(member, ChatMemberAdministrator): can_change_info = member.can_change_info else: can_change_info = True if not can_change_info: await send_message( update.effective_message, "I don't have permission to change group info.", parse_mode="markdown", ) return chat_obj = await context.bot.getChat(chat_id) current_permission = chat_obj.permissions await context.bot.set_chat_permissions( chat_id=chat_id, permissions=get_permission_list( current_permission.to_dict(), UNLOCK_CHAT_RESTRICTION[ltype.lower()], ), ) await send_message(update.effective_message, text, parse_mode="markdown") return ( "{}:" "\n#UNLOCK" "\nAdmin: {}" "\nUnlocked {}.".format( html.escape(chat.title), mention_html(user.id, user.first_name), ltype, ) ) else: await send_message( update.effective_message, "What are you trying to unlock...? Try /locktypes for the list of lockables.", ) else: await send_message( update.effective_message, "What are you trying to unlock...?" ) @user_not_admin @check_admin(permission="can_delete_messages", is_bot=True, no_reply=True) async def del_lockables(update: Update, context: ContextTypes.DEFAULT_TYPE): chat = update.effective_chat # type: Optional[Chat] message = update.effective_message # type: Optional[Message] user = update.effective_user if is_approved(chat.id, user.id): return for lockable, filter in LOCK_TYPES.items(): if lockable == "rtl": if sql.is_locked(chat.id, lockable): if message.caption: check = ad.detect_alphabet("{}".format(message.caption)) if "ARABIC" in check: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - rtl:caption") break if message.text: check = ad.detect_alphabet("{}".format(message.text)) if "ARABIC" in check: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - rtl:text") break continue if lockable == "button": if sql.is_locked(chat.id, lockable): if message.reply_markup and message.reply_markup.inline_keyboard: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - button") break continue if lockable == "inline": if sql.is_locked(chat.id, lockable): if message and message.via_bot: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - inline") break continue if lockable == "forwardchannel": if sql.is_locked(chat.id, lockable): if message.forward_from_chat: if message.forward_from_chat.type == "channel": try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - forwardchannel") break continue continue if lockable == "forwardbot": if sql.is_locked(chat.id, lockable): if message.forward_from: if message.forward_from.is_bot: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - forwardchannel") break continue continue if lockable == "anonchannel": if sql.is_locked(chat.id, lockable): if message.from_user: if message.from_user.id == 136817688: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables - anonchannel") break continue continue if filter.check_update(update) and sql.is_locked(chat.id, lockable): if lockable == "bots": new_members = update.effective_message.new_chat_members for new_mem in new_members: if new_mem.is_bot: if not await is_bot_admin(chat, context.bot.id): await send_message( update.effective_message, "I see a bot and I've been told to stop them from joining..." "but I'm not admin!", ) return await chat.ban_member(new_mem.id) await send_message( update.effective_message, "Only admins are allowed to add bots in this chat! Get outta here.", ) break else: try: await message.delete() except BadRequest as excp: if excp.message == "Message to delete not found": pass else: LOGGER.exception("ERROR in lockables") break async def build_lock_message(chat_id): locks = sql.get_locks(chat_id) res = "" locklist = [] permslist = [] if locks: res += "*" + "These are the current locks in this Chat:" + "*" if locks: locklist.append("sticker = `{}`".format(locks.sticker)) locklist.append("audio = `{}`".format(locks.audio)) locklist.append("voice = `{}`".format(locks.voice)) locklist.append("document = `{}`".format(locks.document)) locklist.append("video = `{}`".format(locks.video)) locklist.append("contact = `{}`".format(locks.contact)) locklist.append("photo = `{}`".format(locks.photo)) locklist.append("gif = `{}`".format(locks.gif)) locklist.append("url = `{}`".format(locks.url)) locklist.append("bots = `{}`".format(locks.bots)) locklist.append("forward = `{}`".format(locks.forward)) locklist.append("game = `{}`".format(locks.game)) locklist.append("location = `{}`".format(locks.location)) locklist.append("rtl = `{}`".format(locks.rtl)) locklist.append("button = `{}`".format(locks.button)) locklist.append("egame = `{}`".format(locks.egame)) locklist.append("phone = `{}`".format(locks.phone)) locklist.append("command = `{}`".format(locks.command)) locklist.append("email = `{}`".format(locks.email)) locklist.append("anonchannel = `{}`".format(locks.anonchannel)) locklist.append("forwardchannel = `{}`".format(locks.forwardchannel)) locklist.append("forwardbot = `{}`".format(locks.forwardbot)) locklist.append("videonote = `{}`".format(locks.videonote)) locklist.append("emojicustom = `{}`".format(locks.emojicustom)) locklist.append("stickerpremium = `{}`".format(locks.stickerpremium)) locklist.append("stickeranimated = `{}`".format(locks.stickeranimated)) permissions = await dispatcher.bot.get_chat(chat_id) if isinstance(permissions, Chat): permissions = permissions.permissions permslist.append("messages = `{}`".format(permissions.can_send_messages)) permslist.append("media = `{}`".format(permissions.can_send_media_messages)) permslist.append("poll = `{}`".format(permissions.can_send_polls)) permslist.append("other = `{}`".format(permissions.can_send_other_messages)) permslist.append( "previews = `{}`".format(permissions.can_add_web_page_previews) ) permslist.append("info = `{}`".format(permissions.can_change_info)) permslist.append("invite = `{}`".format(permissions.can_invite_users)) permslist.append("pin = `{}`".format(permissions.can_pin_messages)) permslist.append("topics = `{}`".format(permissions.can_manage_topics)) if locklist: # Ordering lock list locklist.sort() # Building lock list string for x in locklist: res += "\n • {}".format(x) res += "\n\n*" + "These are the current chat permissions:" + "*" for x in permslist: res += "\n • {}".format(x) return res @typing_action @check_admin(is_user=True) async def list_locks(update: Update, context: ContextTypes.DEFAULT_TYPE): chat = update.effective_chat # type: Optional[Chat] user = update.effective_user # Connection check conn = await connected(context.bot, update, chat, user.id, need_admin=True) if conn: chat = await dispatcher.bot.getChat(conn) chat_name = chat.title else: if update.effective_message.chat.type == "private": await send_message( update.effective_message, "This command is meant to use in group not in PM", ) return "" chat = update.effective_chat chat_name = update.effective_message.chat.title res = await build_lock_message(chat.id) if conn: res = res.replace("Locks in", "*{}*".format(chat_name)) await send_message(update.effective_message, res, parse_mode=ParseMode.MARKDOWN) def get_permission_list(current, new): permissions = { "can_send_messages": None, "can_send_media_messages": None, "can_send_polls": None, "can_send_other_messages": None, "can_add_web_page_previews": None, "can_change_info": None, "can_invite_users": None, "can_pin_messages": None, "can_manage_topics": None, } permissions.update(current) permissions.update(new) new_permissions = ChatPermissions(**permissions) return new_permissions async def __import_data__(chat_id, data, message): # set chat locks locks = data.get("locks", {}) for itemlock in locks: if itemlock in LOCK_TYPES: sql.update_lock(chat_id, itemlock, locked=True) elif itemlock in LOCK_CHAT_RESTRICTION: sql.update_restriction(chat_id, itemlock, locked=True) else: pass def __migrate__(old_chat_id, new_chat_id): sql.migrate_chat(old_chat_id, new_chat_id) async def __chat_settings__(chat_id, user_id): return await build_lock_message(chat_id) __help__ = """ ➠ Do stickers annoy you? or want to avoid people sharing links? or pictures? \ You're in the right place! The locks module allows you to lock away some common items in the \ telegram world; our bot will automatically delete them! » /locktypes: Lists all possible locktypes ➠ *Admins only:* » /lock : Lock items of a certain type (not available in private) » /unlock : Unlock items of a certain type (not available in private) » /locks: The current list of locks in this chat. ➠ Locks can be used to restrict a group's users. eg: Locking urls will auto-delete all messages with urls, locking stickers will restrict all \ non-admin users from sending stickers, etc. Locking bots will stop non-admins from adding bots to the chat. Locking anonchannel will stop anonymous channel from messaging in your group. ➠ *Note:* » Unlocking permission *info* will allow members (non-admins) to change the group information, such as the description or the group name » Unlocking permission *pin* will allow members (non-admins) to pin a message in a group """ __mod_name__ = "LOCKS" LOCKTYPES_HANDLER = DisableAbleCommandHandler("locktypes", locktypes, block=False) LOCK_HANDLER = CommandHandler( "lock", lock, block=False ) # , filters=filters.ChatType.GROUPS) UNLOCK_HANDLER = CommandHandler( "unlock", unlock, block=False ) # , filters=filters.ChatType.GROUPS) LOCKED_HANDLER = CommandHandler( "locks", list_locks, block=False ) # , filters=filters.ChatType.GROUPS) function(LOCK_HANDLER) function(UNLOCK_HANDLER) function(LOCKTYPES_HANDLER) function(LOCKED_HANDLER) function( MessageHandler(filters.ALL & filters.ChatType.GROUPS, del_lockables, block=False), PERM_GROUP, )