diff --git a/.deepsource.toml b/.deepsource.toml index 774d5152..d45d60ac 100644 --- a/.deepsource.toml +++ b/.deepsource.toml @@ -8,15 +8,3 @@ name = "python" [[transformers]] name = "black" - -[[transformers]] -name = "autopep8" - -[[transformers]] -name = "isort" - -[[transformers]] -name = "yapf" - -[[transformers]] -name = "ruff" \ No newline at end of file diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS deleted file mode 100644 index 3efc216d..00000000 --- a/.github/CODEOWNERS +++ /dev/null @@ -1 +0,0 @@ -* @AshokShau diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index dd84ea78..00000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Desktop (please complete the following information):** - - OS: [e.g. iOS] - - Browser [e.g. chrome, safari] - - Version [e.g. 22] - -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md deleted file mode 100644 index 48d5f81f..00000000 --- a/.github/ISSUE_TEMPLATE/custom.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -name: Custom issue template -about: Describe this issue template's purpose here. -title: '' -labels: '' -assignees: '' - ---- - - diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d..00000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/README.md b/.github/README.md deleted file mode 100644 index e6d551a5..00000000 --- a/.github/README.md +++ /dev/null @@ -1,163 +0,0 @@ -━━━━━━━━━━━━━━━━━━━━ -
-𝗗𝗘𝗣𝗟𝗢𝗬𝗠𝗘𝗡𝗧 𝗠𝗘𝗧𝗛𝗢𝗗𝗦 -
- -{args[1].lower()}
is not a module",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_help(chat.id, (gs(chat.id, "pm_help_text")))
-
-
-def send_settings(chat_id: int, user_id: int, user=False):
- """#TODO
-
- Params:
- chat_id -
- user_id -
- user -
- """
-
- if user:
- if USER_SETTINGS:
- settings = "\n\n".join(
- f"*{mod.__mod_name__}*:\n{mod.__user_settings__(user_id)}"
- for mod in USER_SETTINGS.values()
- )
- dispatcher.bot.send_message(
- user_id,
- "ᴛʜᴇsᴇ ᴀʀᴇ ʏᴏᴜʀ ᴄᴜʀʀᴇɴᴛ sᴇᴛᴛɪɴɢs:" + "\n\n" + settings,
- parse_mode=ParseMode.MARKDOWN,
- )
-
- else:
- dispatcher.bot.send_message(
- user_id,
- "sᴇᴇᴍs ʟɪᴋᴇ ᴛʜᴇʀᴇ ᴀʀᴇɴ'ᴛ ᴀɴʏ ᴜsᴇʀ sᴘᴇᴄɪғɪᴄ sᴇᴛᴛɪɴɢs ᴀᴠᴀɪʟᴀʙʟᴇ :'(",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- elif CHAT_SETTINGS:
- chat_name = dispatcher.bot.getChat(chat_id).title
- dispatcher.bot.send_message(
- user_id,
- text=f"ᴡʜɪᴄʜ ᴍᴏᴅᴜʟᴇ ᴡᴏᴜʟᴅ ʏᴏᴜ ʟɪᴋᴇ ᴛᴏ ᴄʜᴇᴄᴋ {chat_name}'s sᴇᴛᴛɪɴɢs ғᴏʀ?",
- reply_markup=InlineKeyboardMarkup(
- paginate_modules(0, CHAT_SETTINGS, "stngs", chat=chat_id)
- ),
- )
- else:
- dispatcher.bot.send_message(
- user_id,
- "sᴇᴇᴍs ʟɪᴋᴇ ᴛʜᴇʀᴇ ᴀʀᴇɴ'ᴛ ᴀɴʏ ᴄʜᴀᴛ sᴇᴛᴛɪɴɢs ᴀᴠᴀɪʟᴀʙʟᴇ :'(\nsᴇɴᴅ ᴛʜɪs "
- "ɪɴ ᴀ ɢʀᴏᴜᴘ ᴄʜᴀᴛ ʏᴏᴜ'ʀᴇ ᴀᴅᴍɪɴ ɪɴ ᴛᴏ ғɪɴᴅ ɪᴛs ᴄᴜʀʀᴇɴᴛ sᴇᴛᴛɪɴɢs!",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-@Exoncallback(pattern=r"stngs_")
-def settings_button(update: Update, context: CallbackContext):
- """#TODO
-
- Params:
- update: Update -
- context: CallbackContext -
- """
-
- query = update.callback_query
- user = update.effective_user
- bot = context.bot
- mod_match = re.match(r"stngs_module\((.+?),(.+?)\)", query.data)
- prev_match = re.match(r"stngs_prev\((.+?),(.+?)\)", query.data)
- next_match = re.match(r"stngs_next\((.+?),(.+?)\)", query.data)
- back_match = re.match(r"stngs_back\((.+?)\)", query.data)
- try:
- if mod_match:
- chat_id = mod_match[1]
- module = mod_match[2]
- chat = bot.get_chat(chat_id)
- text = f"*{escape_markdown(chat.title)}* ʜᴀs ᴛʜᴇ ғᴏʟʟᴏᴡɪɴɢ sᴇᴛᴛɪɴɢs ғᴏʀ ᴛʜᴇ *{CHAT_SETTINGS[module].__mod_name__}* ᴍᴏᴅᴜʟᴇ:\n\n{CHAT_SETTINGS[module].__chat_settings__(chat_id, user.id)}"
- query.message.reply_text(
- text=text,
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ʙᴀᴄᴋ",
- callback_data=f"stngs_back({chat_id})",
- )
- ]
- ]
- ),
- )
-
- elif prev_match:
- chat_id = prev_match[1]
- curr_page = int(prev_match[2])
- chat = bot.get_chat(chat_id)
- query.message.reply_text(
- f"ʜɪ ᴛʜᴇʀᴇ! ᴛʜᴇʀᴇ ᴀʀᴇ ǫᴜɪᴛᴇ ᴀ ғᴇᴡ sᴇᴛᴛɪɴɢs ғᴏʀ {chat.title} - ɢᴏ ᴀʜᴇᴀᴅ ᴀɴᴅ ᴘɪᴄᴋ ᴡʜᴀᴛ ʏᴏᴜ'ʀᴇ ɪɴᴛᴇʀᴇsᴛᴇᴅ ɪɴ.",
- reply_markup=InlineKeyboardMarkup(
- paginate_modules(
- curr_page - 1, CHAT_SETTINGS, "stngs", chat=chat_id
- )
- ),
- )
-
- elif next_match:
- chat_id = next_match[1]
- next_page = int(next_match[2])
- chat = bot.get_chat(chat_id)
- query.message.reply_text(
- f"ʜɪ ᴛʜᴇʀᴇ! ᴛʜᴇʀᴇ ᴀʀᴇ ǫᴜɪᴛᴇ ᴀ ғᴇᴡ sᴇᴛᴛɪɴɢs ғᴏʀ {chat.title} - ɢᴏ ᴀʜᴇᴀᴅ ᴀɴᴅ ᴘɪᴄᴋ ᴡʜᴀᴛ ʏᴏᴜ'ʀᴇ ɪɴᴛᴇʀᴇsᴛᴇᴅ ɪɴ.",
- reply_markup=InlineKeyboardMarkup(
- paginate_modules(
- next_page + 1, CHAT_SETTINGS, "stngs", chat=chat_id
- )
- ),
- )
-
- elif back_match:
- chat_id = back_match[1]
- chat = bot.get_chat(chat_id)
- query.message.reply_text(
- text=f"ʜɪ ᴛʜᴇʀᴇ! ᴛʜᴇʀᴇ ᴀʀᴇ ǫᴜɪᴛᴇ ᴀ ғᴇᴡ sᴇᴛᴛɪɴɢs ғᴏʀ {escape_markdown(chat.title)} - ɢᴏ ᴀʜᴇᴀᴅ ᴀɴᴅ ᴘɪᴄᴋ ᴡʜᴀᴛ ʏᴏᴜ'ʀᴇ ɪɴᴛᴇʀᴇsᴛᴇᴅ ɪɴ.",
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=InlineKeyboardMarkup(
- paginate_modules(0, CHAT_SETTINGS, "stngs", chat=chat_id)
- ),
- )
-
- # ensure no spinny white circle
- bot.answer_callback_query(query.id)
- query.message.delete()
- except BadRequest as excp:
- if excp.message not in [
- "ᴍᴇssᴀɢᴇ ɪs ɴᴏᴛ ᴍᴏᴅɪғɪᴇᴅ",
- "Query_id_invalid",
- "ᴍᴇssᴀɢᴇ ᴄᴀɴ'ᴛ ʙᴇ ᴅᴇʟᴇᴛᴇᴅ",
- ]:
- log.exception("ᴇxᴄᴇᴘᴛɪᴏɴ ɪɴ sᴇᴛᴛɪɴɢs ʙᴜᴛᴛᴏɴs. %s", str(query.data))
-
-
-@Exoncmd(command="settings")
-def get_settings(update: Update, context: CallbackContext):
- """#TODO
-
- Params:
- update: Update -
- context: CallbackContext -
- """
-
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- msg = update.effective_message # type: Optional[Message]
-
- # ONLY send settings in PM
- if chat.type == chat.PRIVATE:
- send_settings(chat.id, user.id, True)
-
- elif is_user_admin(update, user.id):
- text = "ᴄʟɪᴄᴋ ʜᴇʀᴇ ᴛᴏ ɢᴇᴛ ᴛʜɪs ᴄʜᴀᴛ sᴇᴛᴛɪɴɢs, ᴀs ᴡᴇʟʟ ᴀs ʏᴏᴜʀs."
- msg.reply_text(
- text,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="sᴇᴛᴛɪɴɢs",
- url=f"t.me/{context.bot.username}?start=stngs_{chat.id}",
- )
- ]
- ]
- ),
- )
- else:
- text = "ᴄʟɪᴄᴋ ʜᴇʀᴇ ᴛᴏ ᴄʜᴇᴄᴋ ʏᴏᴜʀ sᴇᴛᴛɪɴɢs."
-
-
-@Exonmsg(Filters.status_update.migrate)
-def migrate_chats(update: Update, context: CallbackContext):
- """#TODO
-
- Params:
- update: Update -
- context: CallbackContext -
- """
-
- msg = update.effective_message # type: Optional[Message]
- if msg.migrate_to_chat_id:
- old_chat = update.effective_chat.id
- new_chat = msg.migrate_to_chat_id
- elif msg.migrate_from_chat_id:
- old_chat = msg.migrate_from_chat_id
- new_chat = update.effective_chat.id
- else:
- return
-
- log.info("ᴍɪɢʀᴀᴛɪɴɢ ғʀᴏᴍ %s, ᴛᴏ %s", str(old_chat), str(new_chat))
- for mod in MIGRATEABLE:
- mod.__migrate__(old_chat, new_chat)
-
- log.info("sᴜᴄᴄᴇssғᴜʟʟʏ ᴍɪɢʀᴀᴛᴇᴅ!")
- raise DispatcherHandlerStop
-
-
-def main():
- if SUPPORT_CHAT is not None and isinstance(SUPPORT_CHAT, str):
- try:
- dispatcher.bot.sendAnimation(
- f"@{SUPPORT_CHAT}",
- animation="https://te.legra.ph/file/8dea393ddf4fc2e339179.gif",
- caption=f"""
-ㅤ🥀 {dispatcher.bot.first_name} ɪs ᴀʟɪᴠᴇ ʙᴀʙʏ ✨ .....
-
-━━━━━━━━━━━━━
-⍟ ᴍʏ [ᴏᴡɴᴇʀ](https://t.me/{OWNER_USERNAME})
-⍟ **ʟɪʙʀᴀʀʏ ᴠᴇʀsɪᴏɴ :** `{lver}`
-⍟ **ᴛᴇʟᴇᴛʜᴏɴ ᴠᴇʀsɪᴏɴ :** `{tver}`
-⍟ **ᴘʏʀᴏɢʀᴀᴍ ᴠᴇʀsɪᴏɴ :** `{pver}`
-⍟ **ᴘʏᴛʜᴏɴ ᴠᴇʀsɪᴏɴ :** `{version_info[0]}.{version_info[1]}.{version_info[2]}`
-⍟ **ʙᴏᴛ ᴠᴇʀsɪᴏɴ :** `2.69``
-━━━━━━━━━━━━━
-""",
- parse_mode=ParseMode.MARKDOWN,
- )
- except Unauthorized:
- log.warning("ʙᴏᴛ ɪsɴᴛ ᴀʙʟᴇ ᴛᴏ sᴇɴᴅ ᴍᴇssᴀɢᴇ ᴛᴏ sᴜᴘᴘᴏʀᴛ_ᴄʜᴀᴛ, ɢᴏ ᴀɴᴅ ᴄʜᴇᴄᴋ !")
- except BadRequest as e:
- log.warning(e.message)
-
- log.info(
- f"ᴜsɪɴɢ ʟᴏɴɢ ᴘᴏʟʟɪɴɢ. ........... ᴇɴᴊᴏʏ ʏᴏᴜʀ ʙᴏᴛ sᴛᴀʀᴛᴇᴅ ᴀs → {dispatcher.bot.first_name} "
- )
- updater.start_polling(timeout=15, read_latency=4, drop_pending_updates=True)
-
- if len(argv) in {1, 3, 4}:
- telethn.run_until_disconnected()
-
- else:
- telethn.disconnect()
- updater.idle()
-
-
-if __name__ == "__main__":
- log.info(f"[ᴇxᴏɴ] → sᴜᴄᴄᴇssғᴜʟʟʏ ʟᴏᴀᴅᴇᴅ ᴍᴏᴅᴜʟᴇs: {str(ALL_MODULES)}")
- telethn.start(bot_token=TOKEN)
- pbot.start()
- main()
diff --git a/Exon/antispam.py b/Exon/antispam.py
deleted file mode 100644
index 8a50d7db..00000000
--- a/Exon/antispam.py
+++ /dev/null
@@ -1,189 +0,0 @@
-from . import OWNER_ID, dispatcher
-
-Owner = [OWNER_ID]
-NoResUser = [OWNER_ID]
-AntiSpamValue = 6
-
-GLOBAL_USER_DATA = {}
-
-
-def antispam_restrict_user(user_id, time):
- # print(GLOBAL_USER_DATA)
- if user_id in NoResUser:
- return True
- if GLOBAL_USER_DATA.get(user_id) and GLOBAL_USER_DATA.get(user_id).get("AntiSpamHard") and GLOBAL_USER_DATA.get(
- user_id).get("AntiSpamHard").get("restrict"):
- return True
- try:
- number = GLOBAL_USER_DATA["AntiSpam"][user_id]["value"]
- status = GLOBAL_USER_DATA["AntiSpam"][user_id]["status"]
- restime = GLOBAL_USER_DATA["AntiSpam"][user_id]["restrict"]
- level = GLOBAL_USER_DATA["AntiSpam"][user_id]["level"]
- except Exception:
- number = 0
- status = False
- restime = None
- level = 1
- if restime and int(time) <= int(restime):
- if status:
- return False
- number += 1
- if number >= int(AntiSpamValue * level):
- status = True
- restrict_time = int(time) + (60 * (number / AntiSpamValue))
- else:
- status = False
- restrict_time = int(time) + AntiSpamValue
- GLOBAL_USER_DATA["AntiSpam"] = {
- user_id: {
- "status": status,
- "user": user_id,
- "value": number,
- "restrict": restrict_time,
- "level": level,
- }
- }
-
-
-def antispam_cek_user(user_id, time):
- # print(GLOBAL_USER_DATA)
- try:
- value = GLOBAL_USER_DATA["AntiSpam"]
- if not value.get(user_id):
- return {
- "status": False,
- "user": user_id,
- "value": 0,
- "restrict": None,
- "level": 1,
- }
- value = GLOBAL_USER_DATA["AntiSpam"][user_id]
- if value["restrict"]:
- if int(time) >= int(value["restrict"]):
- if value["status"]:
- # value['value'] = 0
- value["status"] = False
- value["level"] += 1
- value["restrict"] = 0
- else:
- value["value"] = 2 * int(value["level"])
- elif value["status"]:
- try:
- number = GLOBAL_USER_DATA["AntiSpamHard"][user_id]["value"]
- status = GLOBAL_USER_DATA["AntiSpamHard"][user_id]["status"]
- restime = GLOBAL_USER_DATA["AntiSpamHard"][user_id][
- "restrict"
- ]
- level = GLOBAL_USER_DATA["AntiSpamHard"][user_id]["level"]
- except Exception:
- number = 0
- status = False
- restime = None
- level = 1
- if status:
- dispatcher.bot.sendMessage(
- Owner,
- f"⚠ ᴡᴀʀɴɪɴɢ: ᴜsᴇʀ `{user_id}` ᴡᴀs ᴅᴇᴛᴇᴄᴛᴇᴅ sᴘᴀᴍ.",
- parse_mode="markdown",
- )
- GLOBAL_USER_DATA["AntiSpamHard"] = {
- user_id: {
- "status": False,
- "user": user_id,
- "value": 0,
- "restrict": restime,
- "level": level,
- }
- }
- # print(GLOBAL_USER_DATA["AntiSpamHard"])
- return value
- else:
- if number >= 5:
- restrict_time = int(time) + 3600
- status = True
- GLOBAL_USER_DATA["AntiSpam"] = {
- user_id: {
- "status": status,
- "user": user_id,
- "value": GLOBAL_USER_DATA["AntiSpam"][user_id][
- "value"
- ],
- "restrict": restrict_time,
- "level": GLOBAL_USER_DATA["AntiSpam"][user_id][
- "level"
- ],
- }
- }
- else:
- restrict_time = None
- number += 1
- GLOBAL_USER_DATA["AntiSpamHard"] = {
- user_id: {
- "status": status,
- "user": user_id,
- "value": number,
- "restrict": restrict_time,
- "level": level,
- }
- }
- # print(GLOBAL_USER_DATA["AntiSpamHard"])
- return value
- except KeyError:
- return {
- "status": False,
- "user": user_id,
- "value": 0,
- "restrict": None,
- "level": 1,
- }
-
-
-def check_user_spam(user_id):
- if GLOBAL_USER_DATA.get("AntiSpam"):
- if GLOBAL_USER_DATA["AntiSpam"].get(user_id):
- status = GLOBAL_USER_DATA["AntiSpam"].get(user_id).get("status")
- else:
- status = False
- else:
- status = False
- if GLOBAL_USER_DATA.get("AntiSpamHard"):
- if GLOBAL_USER_DATA["AntiSpamHard"].get(user_id):
- status_hard = GLOBAL_USER_DATA["AntiSpamHard"].get(user_id).get("status")
- else:
- status_hard = False
- else:
- status_hard = False
- return {"status": status, "status_hard": status_hard}
-
-
-# This is will detect user
-def detect_user(user_id, chat_id, message, parsing_date):
- check_spam = antispam_cek_user(user_id, parsing_date)
- check_user = check_user_spam(user_id)
- if check_spam["status"]:
- if check_user["status_hard"]:
- getbotinfo = dispatcher.bot.getChatMember(chat_id, dispatcher.bot.id)
- try:
- if getbotinfo.status in ("administrator", "creator"):
- dispatcher.bot.kickChatMember(chat_id, user_id)
- dispatcher.bot.sendMessage(
- chat_id,
- "I'ᴠᴇ ʙᴀɴɴᴇᴅ ᴛʜᴇᴍ!",
- reply_to_message_id=message.message_id,
- )
- return True
- except Exception:
- pass
- if message.chat.type != "private":
- dispatcher.bot.sendMessage(
- chat_id,
- "ғʟᴏᴏᴅ ᴍᴇssᴀɢᴇ ᴡᴀs ᴅᴇᴛᴇᴄᴛᴇᴅ!\nI'ᴍ ᴏᴜᴛ, ɪɴᴠɪᴛᴇ ᴍᴇ ᴀɢᴀɪɴ ɪғ ᴛʜᴇ ғʟᴏᴏᴅ ʜᴀs sᴛᴏᴘᴘᴇᴅ 🙂\n\nᴛʜᴀɴᴋs",
- )
- dispatcher.bot.leaveChat(chat_id)
- return True
- dispatcher.bot.sendMessage(
- chat_id,
- "ʜᴇɪ! sᴍᴀʀᴛ ᴀɴᴛɪғʟᴏᴏᴅ ᴡᴀs ᴅᴇᴛᴇᴄᴛᴇᴅ ғᴏʀ ᴛʜɪs ᴜsᴇʀ!\n\nʏᴏᴜ ᴡɪʟʟ ʙᴇ ʀᴇsᴛʀɪᴄᴛᴇᴅ ғᴏʀ ᴀ ᴡʜɪʟᴇ.\n\nɪғ ʏᴏᴜ sᴛɪʟʟ ᴄᴏɴᴛɪɴᴜᴇs ɪ ᴡɪʟʟ ʙᴀɴ ᴀɴᴅ ᴄʀᴇᴀᴛᴇ ᴀ sᴘᴀᴍ ʀᴇᴘᴏʀᴛ ғᴏʀ ᴛʜɪs ᴜsᴇʀ!",
- reply_to_message_id=message.message_id,
- )
- return True
diff --git a/Exon/conf.py b/Exon/conf.py
deleted file mode 100644
index d9874184..00000000
--- a/Exon/conf.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from envparse import env
-
-from Exon import LOGGER
-
-DEFAULTS = {
- "LOAD_MODULES": True,
-}
-
-
-def get_str_key(name, required=False):
- default = DEFAULTS.get(name)
- if not (data := env.str(name, default=default)) and not required:
- LOGGER.warn(f"No str key: {name}")
- return None
- if data:
- return data
- LOGGER.critical(f"No str key: {name}")
- sys.exit(2)
-
-
-def get_int_key(name, required=False):
- default = DEFAULTS.get(name)
- if not (data := env.int(name, default=default)) and not required:
- LOGGER.warn(f"No int key: {name}")
- return None
- if data:
- return data
- LOGGER.critical(f"No int key: {name}")
- sys.exit(2)
diff --git a/Exon/elevated_users.json b/Exon/elevated_users.json
deleted file mode 100644
index 91ef1026..00000000
--- a/Exon/elevated_users.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "devs": [
- 5938660179
- ],
- "supports": [
- 5938660179
- ],
- "whitelists": [
- 5938660179
- ],
- "spammers": [
- 5938660179
- ],
- "dragons": [
- 5938660179
- ],
- "demons": [
- 5938660179
- ],
- "wolfes": [
- 5938660179
- ],
- "heroes": [
- 5938660179
- ],
- "tigers": [
- 5938660179
- ],
- "sudos": [
- 5938660179
- ]
-}
diff --git a/Exon/events.py b/Exon/events.py
deleted file mode 100644
index f6e093f8..00000000
--- a/Exon/events.py
+++ /dev/null
@@ -1,29 +0,0 @@
-from telethon import events
-
-from Exon import telethn
-
-
-def register(**args):
- """ʀᴇɢɪsᴛᴇʀs ᴀ ɴᴇᴡ ᴍᴇssᴀɢᴇ."""
- pattern = args.get("pattern")
-
- r_pattern = r"^[/!]"
-
- if pattern is not None and not pattern.startswith("(?i)"):
- args["pattern"] = f"(?i){pattern}"
-
- args["pattern"] = pattern.replace("^/", r_pattern, 1)
-
- def decorator(func):
- telethn.add_event_handler(func, events.NewMessage(**args))
- return func
-
- return decorator
-
-
-def Asuinline(**args):
- def decorator(func):
- telethn.add_event_handler(func, events.CallbackQuery(**args))
- return func
-
- return decorator
diff --git a/Exon/langs/__init__.py b/Exon/langs/__init__.py
deleted file mode 100644
index e5277391..00000000
--- a/Exon/langs/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from Exon.langs.language import langs
-
-get_string = langs.get_string
-reload_strings = langs.reload_strings
-get_languages = langs.get_languages
-get_language = langs.get_language
diff --git a/Exon/langs/en.yaml b/Exon/langs/en.yaml
deleted file mode 100644
index 85c1b802..00000000
--- a/Exon/langs/en.yaml
+++ /dev/null
@@ -1,628 +0,0 @@
-# ʟᴀɴɢᴜᴀɢᴇ ɴᴀᴍᴇ ɪɴ ᴛʜᴇɪʀ ɴᴀᴛɪᴠᴇ
-language: "𝐄ɴɢʟɪsʜ "
-
-
-# ɴᴀᴍᴇ ᴏғ ᴘᴇᴏᴘʟᴇ(s) ᴡʜᴏ ᴡᴏʀᴋᴇᴅ ᴏɴ ᴛʜɪs ᴛʀᴀɴsʟᴀᴛɪᴏɴ
-authors: "@AshokShau"
-
-# ʟᴀɴɢᴜᴀɢᴇs
-curr_chat_lang: "ʜᴇʏ. ʏᴏᴜʀ ᴄᴜʀʀᴇɴᴛ ʟᴀɴɢᴜᴀɢᴇ ɪs {}, sᴇʟᴇᴄᴛ ᴛʜᴇ ᴏɴᴇ ʏᴏᴜ ᴡᴀɴᴛ ғʀᴏᴍ ᴛʜᴇ ʙᴜᴛᴛᴏɴs ʙᴇʟᴏᴡ :)"
-set_chat_lang: "ɢʀᴇᴀᴛ, {} ɪᴛ ɪs ( ғʀᴏᴍ ɴᴏᴡ ᴏɴ!"
-
-
-
-pm_start_text: |
- ʜɪ {},
- {} ɪs ᴛʜᴇ *ᴍᴏsᴛ ᴄᴏᴍᴘʟᴇᴛᴇ* ʙᴏᴛ ᴛᴏ ʜᴇʟᴘ
- ʏᴏᴜ ᴍᴀɴᴀɢᴇ ʏᴏᴜʀ *ɢʀᴏᴜᴘs* ᴇᴀsɪʟʏ ᴀɴᴅ *sᴀғᴇʟʏ*.
- ➣ *ᴜᴘᴛɪᴍᴇ :* {}
- ➣ *ᴜsᴇʀs :* 0{}
- ➢ *ᴄʜᴀᴛs :* 0{}
-
-
-grp_start_text: "ʜɪ, ɪ'ᴍ ᴀʟɪᴠᴇ ʙᴀʙʏ."
-
-
-pm_help_text: |
- ━━━━━━━ *ʜᴇʟᴘ* ━━━━━━━
- ᴄʜᴏᴏsᴇ ᴏɴᴇ ᴏғ ᴛʜᴇ ᴄᴀᴛᴇɢᴏʀʏ ʙᴇʟᴏᴡ
- ᴛᴏ sᴇᴇ ᴛʜᴇ ᴀᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs.
- ➼ ᴜsᴇᴀʙʟᴇ ʜᴀɴᴅʟᴇʀ *:* (/ , !)
- ━━━━━━━ *ʜᴇʟᴘ* ━━━━━━━
-
-
-add_bot: "➕ ᴀᴅᴅ ᴍᴇ ᴛᴏ ʏᴏᴜʀ ᴄʜᴀᴛ"
-help_menu: "📚 ʜᴇʟᴘ"
-about: "🏡 ᴀʙᴏᴜᴛ"
-owner: "🥀 ᴅᴇᴠᴇʟᴏᴘᴇʀ"
-
-
-abishnoi_help: |
- *ᴏɴʟʏ ᴀᴅᴍɪɴs ʜᴇʟᴘ ᴍᴇɴᴜ*
-
-
-kingAbishnoi_help: |
- *ᴇxᴛʀᴀ ʜᴇʟᴘ ᴍᴇɴᴜ*
-
-
-akboss_help: |
- *ᴀɴᴛɪ sᴇʀᴠɪᴄᴇ ʜᴇʟᴘ ᴍᴇɴᴜ*
-
-
-achannel_help: |
- *ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ*
- ᴛɪʀᴇᴅ ᴏғ ᴛᴇʟᴇɢʀᴀᴍ's sᴛᴜᴘɪᴅɪᴛʏ? ᴡᴇʟʟ ʜᴇʀᴇ ʏᴏᴜ ɢᴏ
- *ᴀᴠᴀɪʟᴀʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs:*
- •➥ /antichannel `code words`
: Backticks are used for monospace fonts. Shows as: code words
.
- - _italic words_
: Underscores are used for italic fonts. Shows as: italic words.
- - *bold words*
: Asterisks are used for bold fonts. Shows as: bold words.
- - ~strikethrough~
: Tildes are used for strikethrough. Shows as: [hyperlink](example.com)
: This is the formatting used for hyperlinks. Shows as: hyperlink.
- - [My Button](buttonurl://example.com)
: This is the formatting used for creating buttons. This example will create a button named "My button" which opens example.com
when clicked.
- If you would like to send buttons on the same row, use the :same
formatting.
- Example:
- [button 1](buttonurl://example.com)
- [button 2](buttonurl://example.com:same)
- [button 3](buttonurl://example.com)
- This will show button 1 and 2 on the same line, with 3 underneath.
-filling_help: |
- Fillings
- You can also customise the contents of your message with contextual data. For example, you could mention a user by name in the welcome message, or mention them in a filter!
- You can use these to mention a user in notes too!
- Supported fillings:
- - {first}
: The user's first name.
- - {last}
: The user's last name.
- - {fullname}
: The user's full name.
- - {username}
: The user's username. If they don't have one, mentions the user instead.
- - {mention}
: Mentions the user with their firstname.
- - {id}
: The user's ID.
- - {chatname}
: The chat's name.
-
-
-gcast_help: |
- •➥ /broadcastall: ʙʀᴏᴀᴅᴄᴀsᴛs ᴇᴠᴇʀʏᴡʜᴇʀᴇ.
- •➥ /broadcastusers: ʙʀᴏᴀᴅᴄᴀsᴛs ᴛᴏᴏ ᴀʟʟ ᴜsᴇʀs.
- •➥ /broadcastgroups: ʙʀᴏᴀᴅᴄᴀsᴛs ᴛᴏᴏ ᴀʟʟ ɢʀᴏᴜᴘs.
-
-
-gtranslate_help: |
- •➥ *ᴜsᴇ ᴛʜɪs ᴍᴏᴅᴜʟᴇ ᴛᴏ ᴛʀᴀɴsʟᴀᴛᴇ sᴛᴜғғ!*
- •➥ /tl (or /tr): ᴀs ᴀ ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ, ᴛʀᴀɴsʟᴀᴛᴇs ɪᴛ ᴛᴏ ᴇɴɢʟɪsʜ.
- •➥ /tl `code words`
: Backticks are used for monospace fonts. Shows as: code words
.
- - _italic words_
: Underscores are used for italic fonts. Shows as: italic words.
- - *bold words*
: Asterisks are used for bold fonts. Shows as: bold words.
- - ~strikethrough~
: Tildes are used for strikethrough. Shows as: [hyperlink](example.com)
: This is the formatting used for hyperlinks. Shows as: hyperlink.
- - [My Button](buttonurl://example.com)
: This is the formatting used for creating buttons. This example will create a button named "My button" which opens example.com
when clicked.
- If you would like to send buttons on the same row, use the :same
formatting.
- Example:
- [button 1](buttonurl://example.com)
- [button 2](buttonurl://example.com:same)
- [button 3](buttonurl://example.com)
- This will show button 1 and 2 on the same line, with 3 underneath.
-filling_help: |
- Fillings
- You can also customise the contents of your message with contextual data. For example, you could mention a user by name in the welcome message, or mention them in a filter!
- You can use these to mention a user in notes too!
- Supported fillings:
- - {first}
: The user's first name.
- - {last}
: The user's last name.
- - {fullname}
: The user's full name.
- - {username}
: The user's username. If they don't have one, mentions the user instead.
- - {mention}
: Mentions the user with their firstname.
- - {id}
: The user's ID.
- - {chatname}
: The chat's name.
-
-
-gcast_help: |
- •➥ /broadcastall: ʙʀᴏᴀᴅᴄᴀsᴛs ᴇᴠᴇʀʏᴡʜᴇʀᴇ.
- •➥ /broadcastusers: ʙʀᴏᴀᴅᴄᴀsᴛs ᴛᴏᴏ ᴀʟʟ ᴜsᴇʀs.
- •➥ /broadcastgroups: ʙʀᴏᴀᴅᴄᴀsᴛs ᴛᴏᴏ ᴀʟʟ ɢʀᴏᴜᴘs.
-
-
-gtranslate_help: |
- •➥ *ᴜsᴇ ᴛʜɪs ᴍᴏᴅᴜʟᴇ ᴛᴏ ᴛʀᴀɴsʟᴀᴛᴇ sᴛᴜғғ!*
- •➥ /tl (or /tr): ᴀs ᴀ ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ, ᴛʀᴀɴsʟᴀᴛᴇs ɪᴛ ᴛᴏ ᴇɴɢʟɪsʜ.
- •➥ /tl {user_member.user.first_name or user_id}
"
- f"ᴛᴏ {html.escape(title[:16])}
!",
- parse_mode=ParseMode.HTML,
- )
-
-
-@bot_admin
-@can_pin
-@user_admin
-@loggable
-def pin(update: Update, context: CallbackContext) -> str:
- bot, args = context.bot, context.args
- user = update.effective_user
- chat = update.effective_chat
- msg = update.effective_message
- msg_id = msg.reply_to_message.message_id if msg.reply_to_message else msg.message_id
-
- if msg.chat.username:
- # If chat has a username, use this format
- link_chat_id = msg.chat.username
- message_link = f"https://t.me/{link_chat_id}/{msg_id}"
- elif (str(msg.chat.id)).startswith("-100"):
- # If chat does not have a username, use this
- link_chat_id = (str(msg.chat.id)).replace("-100", "")
- message_link = f"https://t.me/c/{link_chat_id}/{msg_id}"
-
- is_group = chat.type not in ("private", "channel")
- prev_message = update.effective_message.reply_to_message
-
- if prev_message is None:
- msg.reply_text("ʀᴇᴘʟʏ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ ᴘɪɴ ɪᴛ!")
- return
-
- if prev_message and is_group:
- is_silent = (
- (
- args[0].lower() != "notify"
- or args[0].lower() == "loud"
- or args[0].lower() == "violent"
- )
- if len(args) >= 1
- else True
- )
- try:
- bot.pinChatMessage(
- chat.id, prev_message.message_id, disable_notification=is_silent
- )
- msg.reply_text(
- "sᴜᴄᴄᴇss! ᴘɪɴɴᴇᴅ ᴛʜɪs ᴍᴇssᴀɢᴇ ᴏɴ ᴛʜɪs ɢʀᴏᴜᴘ",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="📝 ᴠɪᴇᴡ ᴍᴇssᴀɢᴇs", url=f"{message_link}"
- ),
- InlineKeyboardButton(
- text="❌ ᴅᴇʟᴇᴛᴇ", callback_data="close2"
- ),
- ]
- ]
- ),
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
- except BadRequest as excp:
- if excp.message != "Chat_not_modified":
- raise
-
- return f"{html.escape(chat.title)}:\nᴘɪɴɴᴇᴅ\nᴀᴅᴍɪɴ: {mention_html(user.id, html.escape(user.first_name))}"
-
-
-close_keyboard = InlineKeyboardMarkup(
- [[InlineKeyboardButton("❌ ᴅᴇʟᴇᴛᴇ", callback_data="close2")]]
-)
-
-
-@bot_admin
-@can_pin
-@user_admin
-@loggable
-def unpin(update: Update, context: CallbackContext):
- chat = update.effective_chat
- user = update.effective_user
- msg = update.effective_message
- msg_id = msg.reply_to_message.message_id if msg.reply_to_message else msg.message_id
- unpinner = chat.get_member(user.id)
-
- if (
- not unpinner.can_pin_messages
- and unpinner.status != "creator"
- and user.id not in DRAGONS
- ):
- message.reply_text("ʏᴏᴜ ᴅᴏɴ ʜᴀᴠᴇ ᴛʜᴇ ɴᴇᴄᴇssᴀʀʏ ʀɪɢʜᴛs ᴛᴏ ᴅᴏ ᴛʜᴀᴛ!")
- return
-
- if msg.chat.username:
- # If chat has a username, use this format
- link_chat_id = msg.chat.username
- message_link = f"https://t.me/{link_chat_id}/{msg_id}"
- elif (str(msg.chat.id)).startswith("-100"):
- # If chat does not have a username, use this
- link_chat_id = (str(msg.chat.id)).replace("-100", "")
- message_link = f"https://t.me/c/{link_chat_id}/{msg_id}"
-
- is_group = chat.type not in ("private", "channel")
- prev_message = update.effective_message.reply_to_message
-
- if prev_message and is_group:
- try:
- context.bot.unpinChatMessage(chat.id, prev_message.message_id)
- msg.reply_text(
- f"ᴜɴᴘɪɴɴᴇᴅ this message.",
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
- except BadRequest as excp:
- if excp.message != "Chat_not_modified":
- raise
-
- if not prev_message and is_group:
- try:
- context.bot.unpinChatMessage(chat.id)
- msg.reply_text("🔽 ᴜɴᴘɪɴɴᴇᴅ ᴛʜᴇ ʟᴀsᴛ ᴍᴇssᴀɢᴇ ᴏɴ ᴛʜɪs ɢʀᴏᴜᴘ.")
- except BadRequest as excp:
- if excp.message == "ᴍᴇssᴀɢᴇ ᴛᴏ ᴜɴᴘɪɴ ɴᴏᴛ ғᴏᴜɴᴅ":
- msg.reply_text(
- "I ᴄᴀɴ'ᴛ sᴇᴇ ᴘɪɴɴᴇᴅ ᴍᴇssᴀɢᴇ, ᴍᴀʏʙᴇ ᴀʟʀᴇᴀᴅʏ ᴜɴᴘɪɴᴇᴅ, ᴏʀ ᴘɪɴ ᴍᴇssᴀɢᴇ ᴛᴏ ᴏʟᴅ 🙂"
- )
- else:
- raise
-
- return f"{html.escape(chat.title)}:\nᴍᴇssᴀɢᴇ-ᴜɴᴘɪɴɴᴇᴅ-sᴜᴄᴄᴇssғᴜʟʟʏ\nᴀᴅᴍɪɴ: {mention_html(user.id, html.escape(user.first_name))}"
-
-
-@bot_admin
-def pinned(update: Update, context: CallbackContext) -> str:
- bot = context.bot
- msg = update.effective_message
- msg_id = (
- update.effective_message.reply_to_message.message_id
- if update.effective_message.reply_to_message
- else update.effective_message.message_id
- )
-
- chat = bot.getChat(chat_id=msg.chat.id)
- if chat.pinned_message:
- pinned_id = chat.pinned_message.message_id
- if msg.chat.username:
- link_chat_id = msg.chat.username
- message_link = f"https://t.me/{link_chat_id}/{pinned_id}"
- elif (str(msg.chat.id)).startswith("-100"):
- link_chat_id = (str(msg.chat.id)).replace("-100", "")
- message_link = f"https://t.me/c/{link_chat_id}/{pinned_id}"
-
- msg.reply_text(
- f"📌 ᴘɪɴɴᴇᴅ ᴛʜᴇ ᴍᴇssᴀɢᴇ ᴏɴ {html.escape(chat.title)}.",
- reply_to_message_id=msg_id,
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ᴘɪɴɴᴇᴅ ᴍᴇssᴀɢᴇs",
- url=f"https://t.me/{link_chat_id}/{pinned_id}",
- )
- ]
- ]
- ),
- )
-
- else:
- msg.reply_text(
- f"ᴛʜᴇʀᴇ ɪs ɴᴏ ᴘɪɴɴᴇᴅ ᴍᴇssᴀɢᴇ ᴏɴ {html.escape(chat.title)}!",
- parse_mode=ParseMode.HTML,
- )
-
-
-@bot_admin
-@user_admin
-@typing_action
-def invite(update, context):
- bot = context.bot
- user = update.effective_user
- msg = update.effective_message
- chat = update.effective_chat
-
- if conn := connected(bot, update, chat, user.id, need_admin=True):
- chat = dispatcher.bot.getChat(conn)
- else:
- if msg.chat.type == "private":
- msg.reply_text("ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪs ᴍᴇᴀɴᴛ ᴛᴏ ᴜsᴇ ɪɴ ᴄʜᴀᴛ ɴᴏᴛ ɪɴ PM")
- return ""
- chat = update.effective_chat
-
- if chat.username:
- msg.reply_text(chat.username)
- elif chat.type in [chat.SUPERGROUP, chat.CHANNEL]:
- bot_member = chat.get_member(bot.id)
- if bot_member.can_invite_users:
- invitelink = context.bot.exportChatInviteLink(chat.id)
- msg.reply_text(invitelink)
- else:
- msg.reply_text(
- "I ᴅᴏɴ'ᴛ ʜᴀᴠᴇ ᴀᴄᴄᴇss ᴛᴏ ᴛʜᴇ ɪɴᴠɪᴛᴇ ʟɪɴᴋ, ᴛʀʏ ᴄʜᴀɴɢɪɴɢ ᴍʏ ᴘᴇʀᴍɪssɪᴏɴs!"
- )
- else:
- msg.reply_text(
- "I ᴄᴀɴ ᴏɴʟʏ ɢɪᴠᴇ ʏᴏᴜ ɪɴᴠɪᴛᴇ ʟɪɴᴋs ғᴏʀ sᴜᴘᴇʀɢʀᴏᴜᴘs ᴀɴᴅ ᴄʜᴀɴɴᴇʟs, sᴏʀʀʏ!"
- )
-
-
-"""
-@Abishnoi.on_message(filters.command(["staff", "admins", "adminlist"]) & filters.group)
- uname = f"ᴀᴅᴍɪɴs ɪɴ {message.chat.title} :\n\n"
- async for gey in app.iter_chat_members(message.chat.id, filter="administrators"):
- try:
- uname += f"@{(await app.get_users(int(gey.user.id))).username}\n"
- except:
- uname += ""
- await message.reply_text(uname)
-"""
-
-
-@Abishnoi.on_message(filters.command(["adminlist", "staff", "admins"]))
-async def admins(client, message):
- try:
- adminList = []
- ownerList = []
- async for admin in Abishnoi.get_chat_members(
- message.chat.id, filter=enums.ChatMembersFilter.ADMINISTRATORS
- ):
- if admin.privileges.is_anonymous == False:
- if admin.user.is_bot == True:
- pass
- elif admin.status == ChatMemberStatus.OWNER:
- ownerList.append(admin.user)
- else:
- adminList.append(admin.user)
- lenAdminList = len(ownerList) + len(adminList)
- text2 = f"**ɢʀᴏᴜᴘ sᴛᴀғғ - {message.chat.title}**\n\n"
- try:
- owner = ownerList[0]
- if owner.username is None:
- text2 += f"👑 ᴏᴡɴᴇʀ\n└ {owner.mention}\n\n👮🏻 ᴀᴅᴍɪɴs\n"
- else:
- text2 += f"👑 ᴏᴡɴᴇʀ\n└ @{owner.username}\n\n👮🏻 ᴀᴅᴍɪɴs\n"
- except Exception:
- text2 += f"👑 ᴏᴡɴᴇʀ\n└ Hidden\n\n👮🏻 ᴀᴅᴍɪɴs\n"
- if not adminList:
- text2 += "└ ᴀᴅᴍɪɴs ᴀʀᴇ ʜɪᴅᴅᴇɴ"
- else:
- while len(adminList) > 1:
- admin = adminList.pop(0)
- if admin.username is None:
- text2 += f"├ {admin.mention}\n"
- else:
- text2 += f"├ @{admin.username}\n"
- admin = adminList.pop(0)
- if admin.username is None:
- text2 += f"└ {admin.mention}\n\n"
- else:
- text2 += f"└ @{admin.username}\n\n"
- text2 += f"✅ | **ᴛᴏᴛᴀʟ ɴᴜᴍʙᴇʀ ᴏғ ᴀᴅᴍɪɴs**: {lenAdminList}\n❌ | ʙᴏᴛs ᴀɴᴅ ᴀɴᴏɴʏᴍᴏᴜs ᴀᴅᴍɪɴs ᴡᴇʀᴇ ʀᴇᴊᴇᴄᴛᴇᴅ."
- await Abishnoi.send_message(message.chat.id, text2)
- except FloodWait as e:
- await asyncio.sleep(e.value)
-
-
-@Abishnoi.on_message(filters.command("bots"))
-async def bots(client, message):
- try:
- botList = []
- async for bot in Abishnoi.get_chat_members(
- message.chat.id, filter=enums.ChatMembersFilter.BOTS
- ):
- botList.append(bot.user)
- lenBotList = len(botList)
- text3 = f"**ʙᴏᴛ ʟɪsᴛ - {message.chat.title}**\n\n🤖 Bots\n"
- while len(botList) > 1:
- bot = botList.pop(0)
- text3 += f"├ @{bot.username}\n"
- bot = botList.pop(0)
- text3 += f"└ @{bot.username}\n\n"
- text3 += f"✅ | **ᴛᴏᴛᴀʟ ɴᴜᴍʙᴇʀ ᴏғ ʙᴏᴛs**: {lenBotList}"
- await Abishnoi.send_message(message.chat.id, text3)
- except FloodWait as e:
- await asyncio.sleep(e.value)
-
-
-@bot_admin
-@can_promote
-@user_admin
-@loggable
-def button(update: Update, context: CallbackContext) -> str:
- query: Optional[CallbackQuery] = update.callback_query
- user: Optional[User] = update.effective_user
- bot: Optional[Bot] = context.bot
- if match := re.match(r"demote_\((.+?)\)", query.data):
- user_id = match.group(1)
- chat: Optional[Chat] = update.effective_chat
- member = chat.get_member(user_id)
- bot_member = chat.get_member(bot.id)
- bot_permissions = promoteChatMember(
- chat.id,
- user_id,
- can_change_info=bot_member.can_change_info,
- can_post_messages=bot_member.can_post_messages,
- can_edit_messages=bot_member.can_edit_messages,
- can_delete_messages=bot_member.can_delete_messages,
- can_invite_users=bot_member.can_invite_users,
- can_promote_members=bot_member.can_promote_members,
- can_restrict_members=bot_member.can_restrict_members,
- can_pin_messages=bot_member.can_pin_messages,
- can_manage_voice_chats=bot_member.can_manage_voice_chats,
- )
- if demoted := bot.promoteChatMember(
- chat.id,
- user_id,
- can_change_info=False,
- can_post_messages=False,
- can_edit_messages=False,
- can_delete_messages=False,
- can_invite_users=False,
- can_restrict_members=False,
- can_pin_messages=False,
- can_promote_members=False,
- can_manage_voice_chats=False,
- ):
- update.effective_message.edit_text(
- f"ʏᴇᴘ! {mention_html(user_member.user.id, user_member.user.first_name)} has been demoted in {chat.title}!"
- f"ʙʏ {mention_html(user.id, user.first_name)}",
- parse_mode=ParseMode.HTML,
- )
- query.answer("ᴅᴇᴍᴏᴛᴇᴅ!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#ᴅᴇᴍᴏᴛᴇ\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ᴜsᴇʀ: {mention_html(member.user.id, member.user.first_name)}"
- )
- else:
- update.effective_message.edit_text(
- "ᴛʜɪs ᴜsᴇʀ ɪs ɴᴏᴛ ᴘʀᴏᴍᴏᴛᴇᴅ ᴏʀ ʜᴀs ʟᴇғᴛ ᴛʜᴇ ɢʀᴏᴜᴘ!"
- )
- return ""
-
-
-SET_DESC_HANDLER = CommandHandler(
- "setdesc", set_desc, filters=Filters.chat_type.groups, run_async=True
-)
-SET_STICKER_HANDLER = CommandHandler(
- "setsticker", set_sticker, filters=Filters.chat_type.groups, run_async=True
-)
-SETCHATPIC_HANDLER = CommandHandler(
- "setgpic", setchatpic, filters=Filters.chat_type.groups, run_async=True
-)
-RMCHATPIC_HANDLER = CommandHandler(
- "delgpic", rmchatpic, filters=Filters.chat_type.groups, run_async=True
-)
-SETCHAT_TITLE_HANDLER = CommandHandler(
- "setgtitle", setchat_title, filters=Filters.chat_type.groups, run_async=True
-)
-
-PIN_HANDLER = CommandHandler(
- "pin", pin, filters=Filters.chat_type.groups, run_async=True
-)
-UNPIN_HANDLER = CommandHandler(
- "unpin", unpin, filters=Filters.chat_type.groups, run_async=True
-)
-PINNED_HANDLER = CommandHandler(
- "pinned", pinned, filters=Filters.chat_type.groups, run_async=True
-)
-
-INVITE_HANDLER = DisableAbleCommandHandler("invitelink", invite, run_async=True)
-
-PROMOTE_HANDLER = DisableAbleCommandHandler("promote", promote, run_async=True)
-FULLPROMOTE_HANDLER = DisableAbleCommandHandler(
- "fullpromote", fullpromote, run_async=True
-)
-DEMOTE_HANDLER = DisableAbleCommandHandler("demote", demote, run_async=True)
-
-SET_TITLE_HANDLER = CommandHandler("title", set_title, run_async=True)
-ADMIN_REFRESH_HANDLER = CommandHandler(
- "admincache", refresh_admin, filters=Filters.chat_type.groups, run_async=True
-)
-
-dispatcher.add_handler(SET_DESC_HANDLER)
-dispatcher.add_handler(SET_STICKER_HANDLER)
-dispatcher.add_handler(SETCHATPIC_HANDLER)
-dispatcher.add_handler(RMCHATPIC_HANDLER)
-dispatcher.add_handler(SETCHAT_TITLE_HANDLER)
-dispatcher.add_handler(PIN_HANDLER)
-dispatcher.add_handler(UNPIN_HANDLER)
-dispatcher.add_handler(PINNED_HANDLER)
-dispatcher.add_handler(INVITE_HANDLER)
-dispatcher.add_handler(PROMOTE_HANDLER)
-dispatcher.add_handler(FULLPROMOTE_HANDLER)
-dispatcher.add_handler(DEMOTE_HANDLER)
-dispatcher.add_handler(SET_TITLE_HANDLER)
-dispatcher.add_handler(ADMIN_REFRESH_HANDLER)
-
-__mod_name__ = "𝐀ᴅᴍɪɴ"
-__command_list__ = [
- "setdesc" "setsticker" "setgpic" "delgpic" "setgtitle",
- "admins",
- "invitelink",
- "promote",
- "fullpromote",
- "demote",
- "admincache",
-]
-__handlers__ = [
- SET_DESC_HANDLER,
- SET_STICKER_HANDLER,
- SETCHATPIC_HANDLER,
- RMCHATPIC_HANDLER,
- SETCHAT_TITLE_HANDLER,
- PIN_HANDLER,
- UNPIN_HANDLER,
- PINNED_HANDLER,
- INVITE_HANDLER,
- PROMOTE_HANDLER,
- FULLPROMOTE_HANDLER,
- DEMOTE_HANDLER,
- SET_TITLE_HANDLER,
- ADMIN_REFRESH_HANDLER,
-]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "admin_help")
-
-# """
diff --git a/Exon/modules/afk.py b/Exon/modules/afk.py
deleted file mode 100644
index db34632f..00000000
--- a/Exon/modules/afk.py
+++ /dev/null
@@ -1,210 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import time
-
-from Abg.helpers.human_read import get_readable_time
-from pyrogram.types import Message
-
-from Exon import Abishnoi
-from Exon.modules.no_sql.afk_db import add_afk, is_afk, remove_afk
-
-
-@Abishnoi.on_cmd(["afk", "brb"])
-async def active_afk(_, message: Message):
- if message.sender_chat:
- return
- user_id = message.from_user.id
- verifier, reasondb = await is_afk(user_id)
- if verifier:
- await remove_afk(user_id)
- try:
- afktype = reasondb["type"]
- timeafk = reasondb["time"]
- data = reasondb["data"]
- reasonafk = reasondb["reason"]
- seenago = get_readable_time((int(time.time() - timeafk)))
- if afktype == "animation":
- send = (
- await message.reply_animation(
- data,
- caption=f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}",
- )
- if str(reasonafk) == "None"
- else await message.reply_animation(
- data,
- caption=f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`",
- )
- )
- elif afktype == "photo":
- send = (
- await message.reply_photo(
- photo=f"downloads/{user_id}.jpg",
- caption=f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}",
- )
- if str(reasonafk) == "None"
- else await message.reply_photo(
- photo=f"downloads/{user_id}.jpg",
- caption=f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`",
- )
- )
- elif afktype == "text":
- send = await message.reply_text(
- f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}",
- disable_web_page_preview=True,
- )
- elif afktype == "text_reason":
- send = await message.reply_text(
- f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`",
- disable_web_page_preview=True,
- )
- except Exception:
- send = await message.reply_text(
- f"**{message.from_user.first_name}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ",
- disable_web_page_preview=True,
- )
-
- if len(message.command) == 1 and not message.reply_to_message:
- details = {
- "type": "text",
- "time": time.time(),
- "data": None,
- "reason": None,
- }
- elif len(message.command) > 1 and not message.reply_to_message:
- _reason = (message.text.split(None, 1)[1].strip())[:100]
- details = {
- "type": "text_reason",
- "time": time.time(),
- "data": None,
- "reason": _reason,
- }
- elif len(message.command) == 1 and message.reply_to_message.animation:
- _data = message.reply_to_message.animation.file_id
- details = {
- "type": "animation",
- "time": time.time(),
- "data": _data,
- "reason": None,
- }
- elif len(message.command) > 1 and message.reply_to_message.animation:
- _data = message.reply_to_message.animation.file_id
- _reason = (message.text.split(None, 1)[1].strip())[:100]
- details = {
- "type": "animation",
- "time": time.time(),
- "data": _data,
- "reason": _reason,
- }
- elif len(message.command) == 1 and message.reply_to_message.photo:
- await Abishnoi.download_media(
- message.reply_to_message, file_name=f"{user_id}.jpg"
- )
- details = {
- "type": "photo",
- "time": time.time(),
- "data": None,
- "reason": None,
- }
- elif len(message.command) > 1 and message.reply_to_message.photo:
- await Abishnoi.download_media(
- message.reply_to_message, file_name=f"{user_id}.jpg"
- )
- _reason = message.text.split(None, 1)[1].strip()
- details = {
- "type": "photo",
- "time": time.time(),
- "data": None,
- "reason": _reason,
- }
- elif len(message.command) == 1 and message.reply_to_message.sticker:
- if message.reply_to_message.sticker.is_animated:
- details = {
- "type": "text",
- "time": time.time(),
- "data": None,
- "reason": None,
- }
- else:
- await Abishnoi.download_media(
- message.reply_to_message, file_name=f"{user_id}.jpg"
- )
- details = {
- "type": "photo",
- "time": time.time(),
- "data": None,
- "reason": None,
- }
- elif len(message.command) > 1 and message.reply_to_message.sticker:
- _reason = (message.text.split(None, 1)[1].strip())[:100]
- if message.reply_to_message.sticker.is_animated:
- details = {
- "type": "text_reason",
- "time": time.time(),
- "data": None,
- "reason": _reason,
- }
- else:
- await Abishnoi.download_media(
- message.reply_to_message, file_name=f"{user_id}.jpg"
- )
- details = {
- "type": "photo",
- "time": time.time(),
- "data": None,
- "reason": _reason,
- }
- else:
- details = {
- "type": "text",
- "time": time.time(),
- "data": None,
- "reason": None,
- }
-
- await add_afk(user_id, details)
- await message.reply_sticker(
- "CAACAgUAAx0CUgguZAABAdegY2N5paaiPapUxRm0RYy9Xf6dPEYAAisIAAJ2PRlXxkn7UgOIdewqBA"
- )
- await message.reply_text(f"{message.from_user.first_name} ɪs ɴᴏᴡ ᴀғᴋ!")
-
-
-__mod_name__ = "𝐀ғᴋ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "afk_help")
-
-# """
diff --git a/Exon/modules/antichannel.py b/Exon/modules/antichannel.py
deleted file mode 100644
index 60bbfde7..00000000
--- a/Exon/modules/antichannel.py
+++ /dev/null
@@ -1,240 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import html
-
-import requests
-from telegram import ParseMode, TelegramError, Update
-from telegram.ext import CallbackContext, CommandHandler, MessageHandler
-from telegram.ext.filters import Filters
-
-import Exon.modules.sql.antilinkedchannel_sql as sql
-from Exon import SUPPORT_CHAT, TOKEN, dispatcher
-from Exon.modules.helper_funcs.anonymous import AdminPerms, user_admin
-from Exon.modules.helper_funcs.chat_status import bot_admin, bot_can_delete
-from Exon.modules.helper_funcs.chat_status import user_admin as u_admin
-from Exon.modules.helper_funcs.decorators import Exoncmd, Exonmsg
-from Exon.modules.sql import acm_sql
-
-
-@Exoncmd(command="antilinkedchan", group=112)
-@bot_can_delete
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-def set_antilinkedchannel(update: Update, context: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
- args = context.args
- if len(args) > 0:
- s = args[0].lower()
- if s in ["yes", "on"]:
- if sql.status_pin(chat.id):
- sql.disable_pin(chat.id)
- sql.enable_pin(chat.id)
- message.reply_html(
- f"ᴇɴᴀʙʟᴇᴅ ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴅᴇʟᴇᴛɪᴏɴ ᴀɴᴅ ᴅɪsᴀʙʟᴇᴅ ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ ᴘɪɴ ɪɴ {html.escape(chat.title)}"
- )
- else:
- sql.enable_linked(chat.id)
- message.reply_html(f"ᴇɴᴀʙʟᴇᴅ ᴀɴᴛɪ ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ɪɴ {html.escape(chat.title)}")
- elif s in ["off", "no"]:
- sql.disable_linked(chat.id)
- message.reply_html(
- f"ᴅɪsᴀʙʟᴇᴅ ᴀɴᴛɪ ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ɪɴ {html.escape(chat.title)}"
- )
- else:
- message.reply_text(f"ᴜɴʀᴇᴄᴏɢɴɪᴢᴇᴅ ᴀʀɢᴜᴍᴇɴᴛs {s}")
- return
- message.reply_html(
- f"ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴅᴇʟᴇᴛɪᴏɴ ɪs ᴄᴜʀʀᴇɴᴛʟʏ {sql.status_linked(chat.id)} ɪɴ {html.escape(chat.title)}"
- )
-
-
-@Exonmsg(Filters.is_automatic_forward, group=111)
-def eliminate_linked_channel_msg(update: Update, _: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
- if not sql.status_linked(chat.id):
- return
- try:
- message.delete()
- except TelegramError:
- return
-
-
-@bot_admin
-@u_admin
-def antichannelmode(update: Update, context: CallbackContext):
- chat = update.effective_chat
- msg = update.effective_message
- if args := context.args:
- if len(args) != 1:
- msg.reply_text("Invalid arguments!")
- return
- param = args[0]
- if param in ("on", "true", "yes", "On", "Yes", "True"):
- acm_sql.setCleanLinked(chat.id, True)
- msg.reply_text(
- f"*ᴇɴᴀʙʟᴇᴅ* ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ ɪɴ {chat.title}. ᴍᴇssᴀɢᴇs sᴇɴᴛ ʙʏ ᴄʜᴀɴɴᴇʟ ᴡɪʟʟ ʙᴇ ᴅᴇʟᴇᴛᴇᴅ.",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- if param in ("off", "false", "no", "No", "Off", "False"):
- acm_sql.setCleanLinked(chat.id, False)
- msg.reply_text(
- f"*ᴅɪsᴀʙʟᴇᴅ* ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ ɪɴ {chat.title}.",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- msg.reply_text(
- "Your input was not recognised as one of: yes/no/on/off"
- ) # on or off ffs
- else:
- if stat := acm_sql.getCleanLinked(str(chat.id)):
- msg.reply_text(
- f"ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴘᴏsᴛ ᴅᴇʟᴇᴛɪᴏɴ ɪs ᴄᴜʀʀᴇɴᴛʟʏ *ᴇɴᴀʙʟᴇᴅ* ɪɴ {chat.title}. ᴍᴇssᴀɢᴇs sᴇɴᴛ ғʀᴏᴍ ᴛʜᴇ ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴡɪʟʟ ʙᴇ ᴅᴇʟᴇᴛᴇᴅ.",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- msg.reply_text(
- f"ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴘᴏsᴛ ᴅᴇʟᴇᴛɪᴏɴ ɪs ᴄᴜʀʀᴇɴᴛʟʏ *ᴅɪsᴀʙʟᴇᴅ* ɪɴ {chat.title}.",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
-
-
-def sfachat(update: Update, context: CallbackContext):
- user = update.effective_user
- if user and user.id == 136817688:
- msg = update.effective_message
- chat = update.effective_chat
- bot = context.bot
- if cleanlinked := acm_sql.getCleanLinked(str(chat.id)):
- linked_group_channel = bot.get_chat(chat.id)
- lgc_id = linked_group_channel.linked_chat_id
- if str(update.message.sender_chat.id) == str(lgc_id):
- return ""
- BAN_CHAT_CHANNEL = f"https://api.telegram.org/bot{TOKEN}/banChatSenderChat?chat_id={update.message.chat.id}&sender_chat_id={update.message.sender_chat.id}"
- respond = requests.post(BAN_CHAT_CHANNEL)
- if respond.status_code == 200:
- BANNED_CHANNEL_LINK = (
- f"t.me/c/{update.message.sender_chat.id}/1".replace("-100", "")
- )
- update.message.reply_text(
- f"""
-• AUTO-BAN CHANNEL EVENT ‼️
-🚫 ʙᴀɴɴᴇᴅ ᴛʜɪs ᴄʜᴀɴɴᴇʟ: ʜᴇʀᴇ's ᴛʜᴇ ʟɪɴᴋ
- """,
- parse_mode=ParseMode.HTML,
- )
- else:
- update.message.reply_text(
- f"""
-ᴛʜᴇʀᴇ ᴡᴀs ᴀɴ ᴇʀʀᴏʀ ᴏᴄᴄᴜʀᴇᴅ ᴅᴜʀɪɴɢ ᴀᴜᴛᴏ ʙᴀɴ ᴀɴᴅ ᴅᴇʟᴇᴛᴇ ᴍᴇssᴀɢᴇ. ᴘʟᴇᴀsᴇ ʀᴇᴘᴏʀᴛ ᴛʜɪs ᴛᴏ {SUPPORT_CHAT} !
-• ᴇʀʀᴏʀ: `{respond}`
- """
- )
- msg.delete()
- return ""
-
-
-@Exoncmd(command="antichannelpin", group=114)
-@bot_admin
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-def set_antipinchannel(update: Update, context: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
- args = context.args
- if len(args) > 0:
- s = args[0].lower()
- if s in ["yes", "on"]:
- if sql.status_linked(chat.id):
- sql.disable_linked(chat.id)
- sql.enable_pin(chat.id)
- message.reply_html(
- f"ᴅɪsᴀʙʟᴇᴅ ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴅᴇʟᴇᴛɪᴏɴ ᴀɴᴅ ᴇɴᴀʙʟᴇᴅ ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ ᴘɪɴ ɪɴ {html.escape(chat.title)}"
- )
- else:
- sql.enable_pin(chat.id)
- message.reply_html(f"ᴇɴᴀʙʟᴇᴅ ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ ᴘɪɴ ɪɴ {html.escape(chat.title)}")
- elif s in ["off", "no"]:
- sql.disable_pin(chat.id)
- message.reply_html(f"ᴅɪsᴀʙʟᴇᴅ ᴀɴᴛɪ ᴄʜᴀɴɴᴇʟ ᴘɪɴ ɪɴ {html.escape(chat.title)}")
- else:
- message.reply_text(f"ᴜɴʀᴇᴄᴏɢɴɪᴢᴇᴅ ᴀʀɢᴜᴍᴇɴᴛs {s}")
- return
- message.reply_html(
- f"ʟɪɴᴋᴇᴅ ᴄʜᴀɴɴᴇʟ ᴍᴇssᴀɢᴇ ᴜɴᴘɪɴ ɪs ᴄᴜʀʀᴇɴᴛʟʏ {sql.status_pin(chat.id)} ɪɴ {html.escape(chat.title)}"
- )
-
-
-@Exonmsg(Filters.is_automatic_forward | Filters.status_update.pinned_message, group=113)
-def eliminate_linked_channel_msg(update: Update, _: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
- if not sql.status_pin(chat.id):
- return
- try:
- message.unpin()
- except TelegramError:
- return
-
-
-__mod_name__ = "𝐀-ᴄʜᴀɴɴᴇʟ"
-
-CLEANLINKED_HANDLER = CommandHandler(
- ["acm", "antichannel", "antichannelmode"],
- antichannelmode,
- filters=Filters.chat_type.groups,
- run_async=True,
-)
-SFA_HANDLER = MessageHandler(Filters.all, sfachat, allow_edit=True, run_async=True)
-
-dispatcher.add_handler(SFA_HANDLER, group=69)
-dispatcher.add_handler(CLEANLINKED_HANDLER)
-
-__command_list__ = [
- "antichannel",
-]
-
-__handlers__ = [
- CLEANLINKED_HANDLER,
- SFA_HANDLER,
-]
-
-__mod_name__ = "𝐀-ᴄʜᴀɴɴᴇʟ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "achannel_help")
-
-# """
diff --git a/Exon/modules/antiflood.py b/Exon/modules/antiflood.py
deleted file mode 100644
index c9728866..00000000
--- a/Exon/modules/antiflood.py
+++ /dev/null
@@ -1,363 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import html
-from typing import Optional
-
-from telegram import ChatPermissions, ParseMode
-from telegram.error import BadRequest
-from telegram.ext import CommandHandler, Filters, MessageHandler
-from telegram.utils.helpers import mention_html
-
-from Exon import dispatcher
-from Exon.modules.connection import connected
-from Exon.modules.helper_funcs.alternate import send_message, typing_action
-from Exon.modules.helper_funcs.chat_status import is_user_admin
-from Exon.modules.helper_funcs.string_handling import extract_time
-from Exon.modules.log_channel import loggable
-from Exon.modules.sql import antiflood_sql as sql
-from Exon.modules.sql.approve_sql import is_approved
-from ..modules.helper_funcs.anonymous import AdminPerms, user_admin
-
-FLOOD_GROUP = 3
-
-
-@loggable
-def check_flood(update, context) -> Optional[str]:
- user = update.effective_user # type: Optional[User]
- chat = update.effective_chat # type: Optional[Chat]
- msg = update.effective_message # type: Optional[Message]
-
- if is_approved(chat.id, user.id):
- sql.update_flood(chat.id, None)
- return
-
- if not user: # ignore channels
- return ""
-
- # ignore admins
- if is_user_admin(update, user.id):
- sql.update_flood(chat.id, None)
- return ""
-
- should_ban = sql.update_flood(chat.id, user.id)
- if not should_ban:
- return ""
-
- try:
- getmode, getvalue = sql.get_flood_setting(chat.id)
- if getmode == 1:
- chat.ban_member(user.id)
- execstrings = "ʙᴀɴɴᴇᴅ"
- tag = "BANNED"
- elif getmode == 2:
- chat.ban_member(user.id)
- chat.unban_member(user.id)
- execstrings = "ᴋɪᴄᴋᴇᴅ"
- tag = "KICKED"
- elif getmode == 3:
- context.bot.restrict_chat_member(
- chat.id, user.id, permissions=ChatPermissions(can_send_messages=False)
- )
- execstrings = "ᴍᴜᴛᴇᴅ"
- tag = "MUTED"
- elif getmode == 4:
- bantime = extract_time(msg, getvalue)
- chat.ban_member(user.id, until_date=bantime)
- execstrings = f"ʙᴀɴɴᴇᴅ ғᴏʀ {getvalue}"
- tag = "TBAN"
- elif getmode == 5:
- mutetime = extract_time(msg, getvalue)
- context.bot.restrict_chat_member(
- chat.id,
- user.id,
- until_date=mutetime,
- permissions=ChatPermissions(can_send_messages=False),
- )
- execstrings = f"ᴍᴜᴛᴇᴅ ғᴏʀ {getvalue}"
- tag = "TMUTE"
- send_message(
- update.effective_message,
- f"ᴡᴀɴɴᴀ sᴘᴀᴍ?! sᴏʀʀʏ ɪᴛ's ɴᴏᴛ ʏᴏᴜʀ ʜᴏᴜsᴇ ᴍᴀɴ!\n{execstrings}!",
- )
-
- return f"{html.escape(chat.title)}:\n#{tag}\nᴜsᴇʀ: {mention_html(user.id, user.first_name)}\ɴғʟᴏᴏᴅᴇᴅ ᴛʜᴇ ɢʀᴏᴜᴘ."
-
- except BadRequest:
- msg.reply_text(
- "I ᴄᴀɴ'ᴛ ʀᴇsᴛʀɪᴄᴛ (ʙᴀɴ) ᴘᴇᴏᴘʟᴇ ʜᴇʀᴇ, ɢɪᴠᴇ ᴍᴇ ᴘᴇʀᴍɪssɪᴏɴs ғɪʀsᴛ! ᴜɴᴛɪʟ ᴛʜᴇɴ, I'ʟʟ ᴅɪsᴀʙʟᴇ ᴀɴᴛɪ-ғʟᴏᴏᴅ."
- )
- sql.set_flood(chat.id, 0)
- return f"{chat.title}:\n#𝐀𝐋𝐄𝐑𝐓 !\nᴅᴏɴ'ᴛ ʜᴀᴠᴇ ᴇɴᴏᴜɢʜ ᴘᴇʀᴍɪssɪᴏɴ ᴛᴏ ʀᴇsᴛʀɪᴄᴛ ᴜsᴇʀs sᴏ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ᴅɪsᴀʙʟᴇᴅ ᴀɴᴛɪ-ғʟᴏᴏᴅ "
-
-
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-@typing_action
-def set_flood(update, context) -> str:
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- message = update.effective_message # type: Optional[Message]
- args = context.args
-
- conn = connected(context.bot, update, chat, user.id, need_admin=True)
- if conn:
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type == "private":
- send_message(
- update.effective_message,
- "ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪs ᴍᴇᴀɴᴛ ᴛᴏ ᴜsᴇ ɪɴ ɢʀᴏᴜᴘ ɴᴏᴛ ɪɴ ᴘᴍ",
- )
- return ""
- chat_id = update.effective_chat.id
- chat_name = update.effective_message.chat.title
-
- if len(args) >= 1:
- val = args[0].lower()
- if val in ("off", "no", "0"):
- sql.set_flood(chat_id, 0)
- if conn:
- text = message.reply_text(f"ᴀɴᴛɪғʟᴏᴏᴅ ʜᴀs ʙᴇᴇɴ ᴅɪsᴀʙʟᴇᴅ ɪɴ {chat_name}.")
- else:
- text = message.reply_text("ᴀɴᴛɪғʟᴏᴏᴅ ʜᴀs ʙᴇᴇɴ ᴅɪsᴀʙʟᴇᴅ.")
- send_message(update.effective_message, text, parse_mode="markdown")
-
- elif val.isdigit():
- amount = int(val)
- if amount <= 0:
- sql.set_flood(chat_id, 0)
- if conn:
- text = message.reply_text(f"ᴀɴᴛɪғʟᴏᴏᴅ ʜᴀs ʙᴇᴇɴ ᴅɪsᴀʙʟᴇᴅ ɪɴ {chat_name}.")
- else:
- text = message.reply_text("ᴀɴᴛɪғʟᴏᴏᴅ ʜᴀs ʙᴇᴇɴ ᴅɪsᴀʙʟᴇᴅ.")
- return f"{html.escape(chat_name)}:\n#𝐒𝐄𝐓𝐅𝐋𝐎𝐎𝐃\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\nᴅɪsᴀʙʟᴇ ᴀɴᴛɪғʟᴏᴏᴅ."
-
- if amount < 3:
- send_message(
- update.effective_message,
- "ᴀɴᴛɪғʟᴏᴏᴅ ᴍᴜsᴛ ʙᴇ ᴇɪᴛʜᴇʀ 0 (disabled) ᴏʀ ɴᴜᴍʙᴇʀ ɢʀᴇᴀᴛᴇʀ ᴛʜᴀɴ 3!",
- )
- return ""
- sql.set_flood(chat_id, amount)
- if conn:
- text = message.reply_text(
- f"ᴀɴᴛɪ-ғʟᴏᴏᴅ ʜᴀs ʙᴇᴇɴ sᴇᴛ ᴛᴏ {amount} ɪɴ ᴄʜᴀᴛ: {chat_name}"
- )
- else:
- text = message.reply_text(
- f"sᴜᴄᴄᴇssғᴜʟʟʏ ᴜᴘᴅᴀᴛᴇᴅ ᴀɴᴛɪ-ғʟᴏᴏᴅ ʟɪᴍɪᴛ ᴛᴏ {amount}!"
- )
- send_message(update.effective_message, text, parse_mode="markdown")
- return f"{html.escape(chat_name)}:\n#𝐒𝐄𝐓𝐅𝐋𝐎𝐎𝐃\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\nsᴇᴛ ᴀɴᴛɪғʟᴏᴏᴅ ᴛᴏ {amount}
."
-
- else:
- message.reply_text("ɪɴᴠᴀʟɪᴅ ᴀʀɢᴜᴍᴇɴᴛ ᴘʟᴇᴀsᴇ ᴜsᴇ ᴀ ɴᴜᴍʙᴇʀ, 'off' ᴏʀ 'no'")
- else:
- message.reply_text(
- (
- "ᴜsᴇ `/setflood ɴᴜᴍʙᴇʀ` ᴛᴏ ᴇɴᴀʙʟᴇ ᴀɴᴛɪ-ғʟᴏᴏᴅ.\nᴏʀ ᴜsᴇ `/setflood off` ᴛᴏ ᴅɪsᴀʙʟᴇ ᴀɴᴛɪ-ғʟᴏᴏᴅ!."
- ),
- parse_mode="markdown",
- )
- return ""
-
-
-@typing_action
-def flood(update, context):
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- msg = update.effective_message
-
- conn = connected(context.bot, update, chat, user.id, need_admin=False)
- if conn:
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type == "private":
- send_message(
- update.effective_message,
- "ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪs ᴍᴇᴀɴᴛ ᴛᴏ ᴜsᴇ ɪɴ ɢʀᴏᴜᴘ ɴᴏᴛ ɪɴ ᴘᴍ",
- )
- return
- chat_id = update.effective_chat.id
- chat_name = update.effective_message.chat.title
-
- limit = sql.get_flood_limit(chat_id)
- if limit == 0:
- if conn:
- text = msg.reply_text(f"I'ᴍ ɴᴏᴛ ᴇɴғᴏʀᴄɪɴɢ ᴀɴʏ ғʟᴏᴏᴅ ᴄᴏɴᴛʀᴏʟ ɪɴ {chat_name}!")
- else:
- text = msg.reply_text("I'ᴍ ɴᴏᴛ ᴇɴғᴏʀᴄɪɴɢ ᴀɴʏ ғʟᴏᴏᴅ ᴄᴏɴᴛʀᴏʟ ʜᴇʀᴇ!")
- elif conn:
- text = msg.reply_text(
- f"I'ᴍ ᴄᴜʀʀᴇɴᴛʟʏ ʀᴇsᴛʀɪᴄᴛɪɴɢ ᴍᴇᴍʙᴇʀs ᴀғᴛᴇʀ {limit} ᴄᴏɴsᴇᴄᴜᴛɪᴠᴇ ᴍᴇssᴀɢᴇs ɪɴ {chat_name}."
- )
- else:
- text = msg.reply_text(
- f"I'm currently restricting members after {limit} consecutive messages."
- )
- send_message(update.effective_message, text, parse_mode="markdown")
-
-
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-@typing_action
-def set_flood_mode(update, context):
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- msg = update.effective_message # type: Optional[Message]
- args = context.args
-
- conn = connected(context.bot, update, chat, user.id, need_admin=True)
- if conn:
- chat = dispatcher.bot.getChat(conn)
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type == "private":
- send_message(
- update.effective_message,
- "ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪs ᴍᴇᴀɴᴛ ᴛᴏ ᴜsᴇ ɪɴ ɢʀᴏᴜᴘ ɴᴏᴛ ɪɴ PM",
- )
- return ""
- chat = update.effective_chat
- chat_id = update.effective_chat.id
- chat_name = update.effective_message.chat.title
-
- if args:
- if args[0].lower() == "ban":
- settypeflood = "ʙᴀɴ"
- sql.set_flood_strength(chat_id, 1, "0")
- elif args[0].lower() == "kick":
- settypeflood = "ᴋɪᴄᴋ"
- sql.set_flood_strength(chat_id, 2, "0")
- elif args[0].lower() == "mute":
- settypeflood = "ᴍᴜᴛᴇ"
- sql.set_flood_strength(chat_id, 3, "0")
- elif args[0].lower() == "tban":
- if len(args) == 1:
- teks = """ɪᴛ ʟᴏᴏᴋs ʟɪᴋᴇ ʏᴏᴜ ᴛʀɪᴇᴅ ᴛᴏ sᴇᴛ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ ғᴏʀ ᴀɴᴛɪғʟᴏᴏᴅ ʙᴜᴛ ʏᴏᴜ ᴅɪᴅɴ'ᴛ sᴘᴇᴄɪғɪᴇᴅ ᴛɪᴍᴇ; ᴛʀʏ, `/setfloodmode tban <ᴛɪᴍᴇᴠᴀʟᴜᴇ>`.
- ᴇxᴀᴍᴘʟᴇs ᴏғ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ: 4ᴍ = 4 ᴍɪɴᴜᴛᴇs, 3ʜ = 3 ʜᴏᴜʀs, 6ᴅ = 6 ᴅᴀʏs, 5ᴡ = 5 ᴡᴇᴇᴋs."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return
- settypeflood = f"ᴛʙᴀɴ ғᴏʀ {args[1]}"
- sql.set_flood_strength(chat_id, 4, str(args[1]))
- elif args[0].lower() == "tmute":
- if len(args) == 1:
- teks = """ɪᴛ ʟᴏᴏᴋs ʟɪᴋᴇ ʏᴏᴜ ᴛʀɪᴇᴅ ᴛᴏ sᴇᴛ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ ғᴏʀ ᴀɴᴛɪғʟᴏᴏᴅ ʙᴜᴛ ʏᴏᴜ ᴅɪᴅɴ'ᴛ sᴘᴇᴄɪғɪᴇᴅ ᴛɪᴍᴇ; ᴛʀʏ, `/setfloodmode tmute <ᴛɪᴍᴇᴠᴀʟᴜᴇ>`.
- ᴇxᴀᴍᴘʟᴇs ᴏғ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ: 4ᴍ = 4 ᴍɪɴᴜᴛᴇs, 3ʜ = 3 ʜᴏᴜʀs, 6d = 6 ᴅᴀʏs, 5ᴡ = 5 ᴡᴇᴇᴋs."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return
- settypeflood = f"ᴛᴍᴜᴛᴇ ғᴏʀ {args[1]}"
- sql.set_flood_strength(chat_id, 5, str(args[1]))
- else:
- send_message(
- update.effective_message, "I ᴏɴʟʏ ᴜɴᴅᴇʀsᴛᴀɴᴅ ʙᴀɴ/ᴋɪᴄᴋ/ᴍᴜᴛᴇ/ᴛʙᴀɴ/ᴛᴍᴜᴛᴇ!"
- )
- return
- if conn:
- text = msg.reply_text(
- f"ᴇxᴄᴇᴇᴅɪɴɢ ᴄᴏɴsᴇᴄᴜᴛɪᴠᴇ ғʟᴏᴏᴅ ʟɪᴍɪᴛ ᴡɪʟʟ ʀᴇsᴜʟᴛ ɪɴ {settypeflood} ɪɴ {chat_name}!"
- )
- else:
- text = msg.reply_text(
- f"ᴇxᴄᴇᴇᴅɪɴɢ ᴄᴏɴsᴇᴄᴜᴛɪᴠᴇ ғʟᴏᴏᴅ ʟɪᴍɪᴛ ᴡɪʟʟ ʀᴇsᴜʟᴛ ɪɴ {settypeflood}!"
- )
- send_message(update.effective_message, text, parse_mode="markdown")
- return f"{settypeflood}:\nᴀᴅᴍɪɴ: {html.escape(chat.title)}\nʜᴀs ᴄʜᴀɴɢᴇᴅ ᴀɴᴛɪғʟᴏᴏᴅ ᴍᴏᴅᴇ. ᴜsᴇʀ ᴡɪʟʟ {mention_html(user.id, user.first_name)}."
- getmode, getvalue = sql.get_flood_setting(chat.id)
- if getmode == 1:
- settypeflood = "ʙᴀɴ"
- elif getmode == 2:
- settypeflood = "ᴋɪᴄᴋ"
- elif getmode == 3:
- settypeflood = "ᴍᴜᴛᴇ"
- elif getmode == 4:
- settypeflood = f"ᴛʙᴀɴ ғᴏʀ {getvalue}"
- elif getmode == 5:
- settypeflood = f"ᴛᴍᴜᴛᴇ ғᴏʀ {getvalue}"
- if conn:
- text = msg.reply_text(
- f"sᴇɴᴅɪɴɢ ᴍᴏʀᴇ ᴍᴇssᴀɢᴇs ᴛʜᴀɴ ғʟᴏᴏᴅ ʟɪᴍɪᴛ ᴡɪʟʟ ʀᴇsᴜʟᴛ ɪɴ {settypeflood} ɪɴ {chat_name}."
- )
- else:
- text = msg.reply_text(
- f"sᴇɴᴅɪɴɢ ᴍᴏʀᴇ ᴍᴇssᴀɢᴇ ᴛʜᴀɴ ғʟᴏᴏᴅ ʟɪᴍɪᴛ ᴡɪʟʟ ʀᴇsᴜʟᴛ ɪɴ {settypeflood}."
- )
- send_message(update.effective_message, text, parse_mode=ParseMode.MARKDOWN)
- return ""
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- limit = sql.get_flood_limit(chat_id)
- if limit == 0:
- return "ɴᴏᴛ ᴇɴғᴏʀᴄɪɴɢ ᴛᴏ ғʟᴏᴏᴅ ᴄᴏɴᴛʀᴏʟ."
- return f"ᴀɴᴛɪғʟᴏᴏᴅ ʜᴀs ʙᴇᴇɴ sᴇᴛ ᴛᴏ`{limit}`."
-
-
-__mod_name__ = "𝐀-ғʟᴏᴏᴅ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "antiflood_help")
-
-
-# """
-
-
-FLOOD_BAN_HANDLER = MessageHandler(
- Filters.all & ~Filters.status_update & Filters.chat_type.groups,
- check_flood,
- run_async=True,
-)
-SET_FLOOD_HANDLER = CommandHandler(
- "setflood", set_flood, pass_args=True, run_async=True
-) # , filters=Filters.chat_type.groups)
-SET_FLOOD_MODE_HANDLER = CommandHandler(
- "setfloodmode", set_flood_mode, pass_args=True, run_async=True
-) # , filters=Filters.chat_type.groups)
-FLOOD_HANDLER = CommandHandler(
- "flood", flood, run_async=True
-) # , filters=Filters.chat_type.groups)
-
-dispatcher.add_handler(FLOOD_BAN_HANDLER, FLOOD_GROUP)
-dispatcher.add_handler(SET_FLOOD_HANDLER)
-dispatcher.add_handler(SET_FLOOD_MODE_HANDLER)
-dispatcher.add_handler(FLOOD_HANDLER)
diff --git a/Exon/modules/antiraid.py b/Exon/modules/antiraid.py
deleted file mode 100644
index 79342354..00000000
--- a/Exon/modules/antiraid.py
+++ /dev/null
@@ -1,303 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import html
-from datetime import timedelta
-from typing import Optional
-
-from pytimeparse.timeparse import timeparse
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.ext import CallbackContext
-from telegram.utils.helpers import mention_html
-
-import Exon.modules.sql.welcome_sql as sql
-from Exon import LOGGER as log
-from Exon.modules.cron_jobs import j
-from Exon.modules.helper_funcs.anonymous import AdminPerms
-from Exon.modules.helper_funcs.anonymous import resolve_user as res_user
-from Exon.modules.helper_funcs.anonymous import user_admin as u_admin
-from Exon.modules.helper_funcs.chat_status import connection_status, user_admin_no_reply
-from Exon.modules.helper_funcs.decorators import Exoncallback, Exoncmd
-from Exon.modules.log_channel import loggable
-
-
-def get_time(time: str) -> int:
- try:
- return timeparse(time)
- except Exception:
- return 0
-
-
-def get_readable_time(time: int) -> str:
- t = f"{timedelta(seconds=time)}".split(":")
- if time == 86400:
- return "1 day"
- return f"{t[0]} ʜᴏᴜʀ(s)" if time >= 3600 else f"{t[1]} ᴍɪɴᴜᴛᴇs"
-
-
-@Exoncmd(command="raid", pass_args=True)
-@connection_status
-@loggable
-@u_admin(AdminPerms.CAN_CHANGE_INFO)
-def setRaid(update: Update, context: CallbackContext) -> Optional[str]:
- args = context.args
- chat = update.effective_chat
- msg = update.effective_message
- u = update.effective_user
- user = res_user(u, msg.message_id, chat)
- if chat.type == "private":
- context.bot.sendMessage(chat.id, "ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪs ɴᴏᴛ ᴀᴠᴀɪʟᴀʙʟᴇ ɪɴ ᴘᴍs.")
- return
- stat, time, acttime = sql.getDefenseStatus(chat.id)
- readable_time = get_readable_time(time)
- if len(args) == 0:
- if stat:
- text = "ʀᴀɪᴅ ᴍᴏᴅᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ ᴇɴᴀʙʟᴇᴅ
\nᴡᴏᴜʟᴅ ʏᴏᴜ ʟɪᴋᴇ ᴛᴏ ᴅɪsᴀʙʟᴇ
ʀᴀɪᴅ?"
- keyboard = [
- [
- InlineKeyboardButton(
- "ᴅɪsᴀʙʟᴇ ʀᴀɪᴅ",
- callback_data=f"disable_raid={chat.id}={time}",
- ),
- InlineKeyboardButton(
- "ᴄᴀɴᴄᴇʟ", callback_data="cancel_raid=1"
- ),
- ]
- ]
- else:
- text = f"ʀᴀɪᴅ ᴍᴏᴅᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ ᴅɪsᴀʙʟᴇᴅ
\nᴡᴏᴜʟᴅ ʏᴏᴜ ʟɪᴋᴇ ᴛᴏ ᴇɴᴀʙʟᴇ
ʀᴀɪᴅ ғᴏʀ {readable_time}?"
- keyboard = [
- [
- InlineKeyboardButton(
- "ᴇɴᴀʙʟᴇ ʀᴀɪᴅ",
- callback_data=f"enable_raid={chat.id}={time}",
- ),
- InlineKeyboardButton(
- "ᴄᴀɴᴄᴇʟ", callback_data="cancel_raid=0"
- ),
- ]
- ]
- reply_markup = InlineKeyboardMarkup(keyboard)
- msg.reply_text(text, parse_mode=ParseMode.HTML, reply_markup=reply_markup)
-
- elif args[0] == "off":
- if stat:
- sql.setDefenseStatus(chat.id, False, time, acttime)
- text = "ʀᴀɪᴅ ᴍᴏᴅᴇ ʜᴀs ʙᴇᴇɴ ᴅɪsᴀʙʟᴇᴅ
, ᴍᴇᴍʙᴇʀs ᴛʜᴀᴛ ᴊᴏɪɴ ᴡɪʟʟ ɴᴏ ʟᴏɴɢᴇʀ ʙᴇ ᴋɪᴄᴋᴇᴅ."
- msg.reply_text(text, parse_mode=ParseMode.HTML)
- return f"{html.escape(chat.title)}:\n#𝐑𝐀𝐈𝐃\nᴅɪsᴀʙʟᴇᴅ\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- else:
- args_time = args[0].lower()
- if time := get_time(args_time):
- readable_time = get_readable_time(time)
- if time >= 300 and time < 86400:
- text = f"ʀᴀɪᴅ ᴍᴏᴅᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ ᴅɪsᴀʙʟᴇᴅ
\nᴡᴏᴜʟᴅ ʏᴏᴜ ʟɪᴋᴇ ᴛᴏ ᴇɴᴀʙʟᴇ
ʀᴀɪᴅ ғᴏʀ {readable_time}?"
- keyboard = [
- [
- InlineKeyboardButton(
- "ᴇɴᴀʙʟᴇ ʀᴀɪᴅ",
- callback_data=f"enable_raid={chat.id}={time}",
- ),
- InlineKeyboardButton(
- "ᴄᴀɴᴄᴇʟ", callback_data="cancel_raid=0"
- ),
- ]
- ]
- reply_markup = InlineKeyboardMarkup(keyboard)
- msg.reply_text(
- text, parse_mode=ParseMode.HTML, reply_markup=reply_markup
- )
- else:
- msg.reply_text(
- "ʏᴏᴜ ᴄᴀɴ ᴏɴʟʏ sᴇᴛ ᴛɪᴍᴇ ʙᴇᴛᴡᴇᴇɴ 5 ᴍɪɴᴜᴛᴇs ᴀɴᴅ 1 ᴅᴀʏ",
- parse_mode=ParseMode.HTML,
- )
-
- else:
- msg.reply_text(
- "ᴜɴᴋɴᴏᴡɴ ᴛɪᴍᴇ ɢɪᴠᴇɴ, ɢɪᴠᴇ ᴍᴇ sᴏᴍᴇᴛʜɪɴɢ ʟɪᴋᴇ 5m ᴏʀ 1h",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncallback(pattern="enable_raid=")
-@connection_status
-@user_admin_no_reply
-@loggable
-def enable_raid_cb(update: Update, _: CallbackContext) -> Optional[str]:
- args = update.callback_query.data.replace("enable_raid=", "").split("=")
- chat = update.effective_chat
- user = update.effective_user
- chat_id = args[0]
- time = int(args[1])
- readable_time = get_readable_time(time)
- _, t, acttime = sql.getDefenseStatus(chat_id)
- sql.setDefenseStatus(chat_id, True, time, acttime)
- update.effective_message.edit_text(
- f"ʀᴀɪᴅ ᴍᴏᴅᴇ ʜᴀs ʙᴇᴇɴ ᴇɴᴀʙʟᴇᴅ
ғᴏʀ {readable_time}.",
- parse_mode=ParseMode.HTML,
- )
- log.info("ᴇɴᴀʙʟᴇᴅ ʀᴀɪᴅ ᴍᴏᴅᴇ ɪɴ {} ғᴏʀ {}".format(chat_id, readable_time))
-
- def disable_raid(_):
- sql.setDefenseStatus(chat_id, False, t, acttime)
- log.info("ᴅɪsʙʟᴇᴅ ʀᴀɪᴅ ᴍᴏᴅᴇ ɪɴ {}".format(chat_id))
- logmsg = (
- f"{html.escape(chat.title)}:\n"
- f"#𝐑𝐀𝐈𝐃\n"
- f"ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ᴅɪsᴀʙʟᴇᴅ\n"
- )
- return logmsg
-
- j.run_once(disable_raid, time)
- logmsg = (
- f"{html.escape(chat.title)}:\n"
- f"#𝐑𝐀𝐈𝐃\n"
- f"ᴇɴᴀʙʟʙᴇᴅ ғᴏʀ {readable_time}\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- )
- return logmsg
-
-
-@Exoncallback(pattern="disable_raid=")
-@connection_status
-@user_admin_no_reply
-@loggable
-def disable_raid_cb(update: Update, _: CallbackContext) -> Optional[str]:
- args = update.callback_query.data.replace("disable_raid=", "").split("=")
- chat = update.effective_chat
- user = update.effective_user
- chat_id = args[0]
- time = args[1]
- _, t, acttime = sql.getDefenseStatus(chat_id)
- sql.setDefenseStatus(chat_id, False, time, acttime)
- update.effective_message.edit_text(
- "ʀᴀɪᴅ ᴍᴏᴅᴇ ʜᴀs ʙᴇᴇɴ Disabled
, ᴊᴏɪɴɪɢ ᴍᴇᴍʙᴇʀs ᴡɪʟʟ ɴᴏ ʟᴏɴɢᴇʀ ʙᴇ ᴋɪᴄᴋᴇᴅ.",
- parse_mode=ParseMode.HTML,
- )
- return f"{html.escape(chat.title)}:\n#𝐑𝐀𝐈𝐃\nᴅɪsᴀʙʟᴇᴅ\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
-
-
-@Exoncallback(pattern="cancel_raid=")
-@connection_status
-@user_admin_no_reply
-def disable_raid_cb(update: Update, context: CallbackContext):
- args = update.callback_query.data.split("=")
- what = args[0]
- update.effective_message.edit_text(
- f"ᴀᴄᴛɪᴏɴ ᴄᴀɴᴄᴇʟʟᴇᴅ, ʀᴀɪᴅ ᴍᴏᴅᴇ ᴡɪʟʟ sᴛᴀʏ {'Enabled' if what == 1 else 'Disabled'}
.",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncmd(command="raidtime")
-@connection_status
-@loggable
-@u_admin(AdminPerms.CAN_CHANGE_INFO)
-def raidtime(update: Update, context: CallbackContext) -> Optional[str]:
- what, time, acttime = sql.getDefenseStatus(update.effective_chat.id)
- args = context.args
- msg = update.effective_message
- u = update.effective_user
- chat = update.effective_chat
- user = res_user(u, msg.message_id, chat)
- if not args:
- msg.reply_text(
- f"ʀᴀɪᴅ ᴍᴏᴅᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ sᴇᴛ ᴛᴏ {get_readable_time(time)}\nᴡʜᴇɴ ᴛᴏɢɢʟᴇᴅ, ᴛʜᴇ ʀᴀɪᴅ ᴍᴏᴅᴇ ᴡɪʟʟ ʟᴀsᴛ ғᴏʀ {get_readable_time(time)} ᴛʜᴇɴ ᴛᴜʀɴ ᴏғғ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ",
- parse_mode=ParseMode.HTML,
- )
- return
- args_time = args[0].lower()
- if time := get_time(args_time):
- readable_time = get_readable_time(time)
- if time >= 300 and time < 86400:
- text = f"ʀᴀɪᴅ ᴍᴏᴅᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ sᴇᴛ ᴛᴏ {readable_time}\nᴡʜᴇɴ ᴛᴏɢɢʟᴇᴅ, ᴛʜᴇ ʀᴀɪᴅ ᴍᴏᴅᴇ ᴡɪʟʟ ʟᴀsᴛ ғᴏʀ {readable_time} ᴛʜᴇɴ ᴛᴜʀɴ ᴏғғ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ"
- msg.reply_text(text, parse_mode=ParseMode.HTML)
- sql.setDefenseStatus(chat.id, what, time, acttime)
- return f"{html.escape(chat.title)}:\n#𝐑𝐀𝐈𝐃\nsᴇᴛ ʀᴀɪᴅ ᴍᴏᴅᴇ ᴛɪᴍᴇ ᴛᴏ {readable_time}\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- else:
- msg.reply_text(
- "ʏᴏᴜ ᴄᴀɴ ᴏɴʟʏ sᴇᴛ ᴛɪᴍᴇ ʙᴇᴛᴡᴇᴇɴ 5 ᴍɪɴᴜᴛᴇs ᴀɴᴅ 1 ᴅᴀʏ",
- parse_mode=ParseMode.HTML,
- )
- else:
- msg.reply_text(
- "ᴜɴᴋɴᴏᴡɴ ᴛɪᴍᴇ ɢɪᴠᴇɴ, give ᴍᴇ sᴏᴍᴇᴛʜɪɴɢ ʟɪᴋᴇ 5ᴍ ᴏʀ 1ʜ",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncmd(command="raidactiontime", pass_args=True)
-@connection_status
-@u_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def raidtime(update: Update, context: CallbackContext) -> Optional[str]:
- what, t, time = sql.getDefenseStatus(update.effective_chat.id)
- args = context.args
- msg = update.effective_message
- u = update.effective_user
- chat = update.effective_chat
- user = res_user(u, msg.message_id, chat)
- if not args:
- msg.reply_text(
- f"ʀᴀɪᴅ ᴀᴄᴛᴏɪɴ ᴛɪᴍᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ sᴇᴛ ᴛᴏ {get_readable_time(time)}\nᴡʜᴇɴ ᴛᴏɢɢʟᴇᴅ, ᴛʜᴇ ᴍᴇᴍʙᴇʀs ᴛʜᴀᴛ ᴊᴏɪɴ ᴡɪʟʟ ʙᴇ ᴛᴇᴍᴘ ʙᴀɴɴᴇᴅ ғᴏʀ {get_readable_time(time)}",
- parse_mode=ParseMode.HTML,
- )
- return
- args_time = args[0].lower()
- if time := get_time(args_time):
- readable_time = get_readable_time(time)
- if time >= 300 and time < 86400:
- text = f"ʀᴀɪᴅ ᴀᴄᴛᴏɪɴ ᴛɪᴍᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ sᴇᴛ ᴛᴏ {get_readable_time(time)}\nᴡʜᴇɴ ᴛᴏɢɢʟᴇᴅ, ᴛʜᴇ ᴍᴇᴍʙᴇʀs ᴛʜᴀᴛ ᴊᴏɪɴ ᴡɪʟʟ ʙᴇ ᴛᴇᴍᴘ ʙᴀɴɴᴇᴅ ғᴏʀ {readable_time}"
- msg.reply_text(text, parse_mode=ParseMode.HTML)
- sql.setDefenseStatus(chat.id, what, t, time)
- return f"{html.escape(chat.title)}:\n#𝐑𝐀𝐈𝐃\nsᴇᴛ ʀᴀɪᴅ ᴍᴏᴅᴇ ᴀᴄᴛɪᴏɴ ᴛɪᴍᴇ ᴛᴏ {readable_time}\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- else:
- msg.reply_text(
- "ʏᴏᴜ ᴄᴀɴ ᴏɴʟʏ sᴇᴛ ᴛɪᴍᴇ ʙᴇᴛᴡᴇᴇɴ 5 ᴍɪɴᴜᴛᴇs ᴀɴᴅ 1 ᴅᴀʏ",
- parse_mode=ParseMode.HTML,
- )
- else:
- msg.reply_text(
- "ᴜɴᴋɴᴏᴡɴ ᴛɪᴍᴇ ɢɪᴠᴇɴ, ɢɪᴠᴇ ᴍᴇ sᴏᴍᴇᴛʜɪɴɢ ʟɪᴋᴇ 5m ᴏʀ 1h",
- parse_mode=ParseMode.HTML,
- )
-
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "raid_help")
-
-
-# """
-
-__mod_name__ = "𝐀-ʀᴀɪᴅ"
diff --git a/Exon/modules/approval.py b/Exon/modules/approval.py
deleted file mode 100644
index 98a939c7..00000000
--- a/Exon/modules/approval.py
+++ /dev/null
@@ -1,243 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import html
-
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, CallbackQueryHandler
-from telegram.utils.helpers import mention_html
-
-import Exon.modules.sql.approve_sql as sql
-from Exon import DRAGONS, dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.chat_status import user_admin
-from Exon.modules.helper_funcs.extraction import extract_user
-from Exon.modules.log_channel import loggable
-
-
-@loggable
-@user_admin
-def approve(update, context):
- message = update.effective_message
- chat_title = message.chat.title
- chat = update.effective_chat
- args = context.args
- user = update.effective_user
- user_id = extract_user(message, args)
- if not user_id:
- message.reply_text(
- "I ᴅᴏɴ'ᴛ ᴋɴᴏᴡ ᴡʜᴏ ʏᴏᴜ'ʀᴇ ᴛᴀʟᴋɪɴɢ ᴀʙᴏᴜᴛ, ʏᴏᴜ'ʀᴇ ɢᴏɪɴɢ ᴛᴏ ɴᴇᴇᴅ ᴛᴏ sᴘᴇᴄɪғʏ ᴀ ᴜsᴇʀ!",
- )
- return ""
- try:
- member = chat.get_member(user_id)
- except BadRequest:
- return ""
- if member.status in ("administrator", "creator"):
- message.reply_text(
- "ᴜsᴇʀ ɪs ᴀʟʀᴇᴀᴅʏ ᴀᴅᴍɪɴ - ʟᴏᴄᴋs, ʙʟᴏᴄᴋʟɪsᴛs, ᴀɴᴅ ᴀɴᴛɪғʟᴏᴏᴅ ᴀʟʀᴇᴀᴅʏ ᴅᴏɴ'ᴛ ᴀᴘᴘʟʏ ᴛᴏ ᴛʜᴇᴍ.",
- )
- return ""
- if sql.is_approved(message.chat_id, user_id):
- message.reply_text(
- f"[{member.user['first_name']}](tg://user?id={member.user['id']}) ɪs ᴀʟʀᴇᴀᴅʏ ᴀᴘᴘʀᴏᴠᴇᴅ ɪɴ {chat_title}",
- parse_mode=ParseMode.MARKDOWN,
- )
- return ""
- sql.approve(message.chat_id, user_id)
- message.reply_text(
- f"[{member.user['first_name']}](tg://user?id={member.user['id']}) ʜᴀs ʙᴇᴇɴ ᴀᴘᴘʀᴏᴠᴇᴅ ɪɴ {chat_title}! ᴛʜᴇʏ ᴡɪʟʟ ɴᴏᴡ ʙᴇ ɪɢɴᴏʀᴇᴅ ʙʏ ᴀᴜᴛᴏᴍᴀᴛᴇᴅ ᴀᴅᴍɪɴ ᴀᴄᴛɪᴏɴs ʟɪᴋᴇ ʟᴏᴄᴋs, ʙʟᴏᴄᴋʟɪsᴛs, ᴀɴᴅ ᴀɴᴛɪғʟᴏᴏᴅ.",
- parse_mode=ParseMode.MARKDOWN,
- )
- return f"{html.escape(chat.title)}:\n#𝐀𝐏𝐏𝐑𝐎𝐕𝐄𝐃\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\nᴜsᴇʀ: {mention_html(member.user.id, member.user.first_name)}"
-
-
-@loggable
-@user_admin
-def disapprove(update, context):
- message = update.effective_message
- chat_title = message.chat.title
- chat = update.effective_chat
- args = context.args
- user = update.effective_user
- user_id = extract_user(message, args)
- if not user_id:
- message.reply_text(
- "I ᴅᴏɴ'ᴛ ᴋɴᴏᴡ ᴡʜᴏ ʏᴏᴜ'ʀᴇ ᴛᴀʟᴋɪɴɢ ᴀʙᴏᴜᴛ, ʏᴏᴜ'ʀᴇ ɢᴏɪɴɢ ᴛᴏ ɴᴇᴇᴅ ᴛᴏ sᴘᴇᴄɪғʏ ᴀ ᴜsᴇʀ!",
- )
- return ""
- try:
- member = chat.get_member(user_id)
- except BadRequest:
- return ""
- if member.status in ("administrator", "creator"):
- message.reply_text("ᴛʜɪs ᴜsᴇʀ ɪs ᴀɴ ᴀᴅᴍɪɴ, ᴛʜᴇʏ ᴄᴀɴ'ᴛ ʙᴇ ᴜɴᴀᴘᴘʀᴏᴠᴇᴅ.")
- return ""
- if not sql.is_approved(message.chat_id, user_id):
- message.reply_text(f"{member.user['first_name']} ɪsɴ'ᴛ ᴀᴘᴘʀᴏᴠᴇᴅ ʏᴇᴛ!")
- return ""
- sql.disapprove(message.chat_id, user_id)
- message.reply_text(
- f"{member.user['first_name']} ɪs ɴᴏ ʟᴏɴɢᴇʀ ᴀᴘᴘʀᴏᴠᴇᴅ ɪɴ {chat_title}.",
- )
- return f"{html.escape(chat.title)}:\n#𝐔𝐍𝐀𝐏𝐏𝐑𝐎𝐕𝐄𝐃\nᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\nᴜsᴇʀ: {mention_html(member.user.id, member.user.first_name)}"
-
-
-@user_admin
-def approved(update, context):
- message = update.effective_message
- chat_title = message.chat.title
- chat = update.effective_chat
- msg = "ᴛʜᴇ ғᴏʟʟᴏᴡɪɴɢ ᴜsᴇʀ's ᴀʀᴇ ᴀᴘᴘʀᴏᴠᴇᴅ.\n"
- approved_users = sql.list_approved(message.chat_id)
- for i in approved_users:
- member = chat.get_member(int(i.user_id))
- msg += f"× `{i.user_id}`: {member.user['first_name']}\n"
- if msg.endswith("ᴀᴘᴘʀᴏᴠᴇᴅ.\n"):
- message.reply_text(f"ɴᴏ ᴜsᴇʀs ᴀʀᴇ ᴀᴘᴘʀᴏᴠᴇᴅ ɪɴ {chat_title}.")
- return ""
- message.reply_text(msg, parse_mode=ParseMode.MARKDOWN)
-
-
-@user_admin
-def approval(update, context):
- message = update.effective_message
- chat = update.effective_chat
- args = context.args
- user_id = extract_user(message, args)
- member = chat.get_member(int(user_id))
- if not user_id:
- message.reply_text(
- "I ᴅᴏɴ'ᴛ ᴋɴᴏᴡ ᴡʜᴏ ʏᴏᴜ'ʀᴇ ᴛᴀʟᴋɪɴɢ ᴀʙᴏᴜᴛ, ʏᴏᴜ'ʀᴇ ɢᴏɪɴɢ ᴛᴏ ɴᴇᴇᴅ ᴛᴏ sᴘᴇᴄɪғʏ ᴀ ᴜsᴇʀ!",
- )
- return ""
- if sql.is_approved(message.chat_id, user_id):
- message.reply_text(
- f"{member.user['first_name']} ɪs ᴀɴ ᴀᴘᴘʀᴏᴠᴇᴅ ᴜsᴇʀ. ʟᴏᴄᴋs, ᴀɴᴛɪғʟᴏᴏᴅ, ᴀɴᴅ ʙʟᴏᴄᴋʟɪsᴛs ᴡᴏɴ'ᴛ ᴀᴘᴘʟʏ ᴛᴏ ᴛʜᴇᴍ.",
- )
- else:
- message.reply_text(
- f"{member.user['first_name']} ɪs ɴᴏᴛ ᴀɴ ᴀᴘᴘʀᴏᴠᴇᴅ ᴜsᴇʀ. ᴛʜᴇʏ ᴀʀᴇ ᴀғғᴇᴄᴛᴇᴅ ʙʏ ɴᴏʀᴍᴀʟ ᴄᴏᴍᴍᴀɴᴅs.",
- )
-
-
-def unapproveall(update: Update, context: CallbackContext):
- chat = update.effective_chat
- user = update.effective_user
- member = chat.get_member(user.id)
- if member.status != "creator" and user.id not in DRAGONS:
- update.effective_message.reply_text(
- "ᴏɴʟʏ ᴛʜᴇ ᴄʜᴀᴛ ᴏᴡɴᴇʀ ᴄᴀɴ ᴜɴᴀᴘᴘʀᴏᴠᴇ ᴀʟʟ ᴜsᴇʀs ᴀᴛ ᴏɴᴄᴇ.",
- )
- else:
- buttons = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ᴜɴᴀᴘᴘʀᴏᴠᴇ ᴀʟʟ ᴜsᴇʀs",
- callback_data="unapproveall_user",
- ),
- ],
- [
- InlineKeyboardButton(
- text="ᴄᴀɴᴄᴇʟ",
- callback_data="unapproveall_cancel",
- ),
- ],
- ],
- )
- update.effective_message.reply_text(
- f"ᴀʀᴇ ʏᴏᴜ sᴜʀᴇ ʏᴏᴜ ᴡᴏᴜʟᴅ ʟɪᴋᴇ ᴛᴏ ᴜɴᴀᴘᴘʀᴏᴠᴇ 𝐀𝐋𝐋 ᴜsᴇʀs ɪɴ {chat.title}? ᴛʜɪs ᴀᴄᴛɪᴏɴ ᴄᴀɴɴᴏᴛ ʙᴇ ᴜɴᴅᴏɴᴇ.",
- reply_markup=buttons,
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def unapproveall_btn(update: Update, context: CallbackContext):
- query = update.callback_query
- chat = update.effective_chat
- message = update.effective_message
- member = chat.get_member(query.from_user.id)
- if query.data == "unapproveall_user":
- if member.status == "creator" or query.from_user.id in DRAGONS:
- approved_users = sql.list_approved(chat.id)
- users = [int(i.user_id) for i in approved_users]
- for user_id in users:
- sql.disapprove(chat.id, user_id)
- message.edit_text("sᴜᴄᴄᴇssғᴜʟʟʏ ᴜɴᴀᴘᴘʀᴏᴠᴇᴅ ᴀʟʟ ᴜsᴇʀ ɪɴ ᴛʜɪs ᴄʜᴀᴛ.")
- return
-
- if member.status == "administrator":
- query.answer("ᴏɴʟʏ ᴏᴡɴᴇʀ ᴏғ ᴛʜᴇ ᴄʜᴀᴛ ᴄᴀɴ ᴅᴏ ᴛʜɪs.")
-
- if member.status == "member":
- query.answer("ʏᴏᴜ ɴᴇᴇᴅ ᴛᴏ ʙᴇ ᴀᴅᴍɪɴ ᴛᴏ ᴅᴏ ᴛʜɪs.")
- elif query.data == "unapproveall_cancel":
- if member.status == "creator" or query.from_user.id in DRAGONS:
- message.edit_text("ʀᴇᴍᴏᴠɪɴɢ ᴏғ ᴀʟʟ ᴀᴘᴘʀᴏᴠᴇᴅ ᴜsᴇʀs ʜᴀs ʙᴇᴇɴ ᴄᴀɴᴄᴇʟʟᴇᴅ.")
- return ""
- if member.status == "administrator":
- query.answer("ᴏɴʟʏ ᴏᴡɴᴇʀ ᴏғ ᴛʜᴇ ᴄʜᴀᴛ ᴄᴀɴ ᴅᴏ ᴛʜɪs.")
- if member.status == "member":
- query.answer("ʏᴏᴜ ɴᴇᴇᴅ ᴛᴏ ʙᴇ ᴀᴅᴍɪɴ ᴛᴏ ᴅᴏ ᴛʜɪs.")
-
-
-APPROVE = DisableAbleCommandHandler(["approve", "free"], approve, run_async=True)
-DISAPPROVE = DisableAbleCommandHandler("unapprove", disapprove, run_async=True)
-APPROVED = DisableAbleCommandHandler("approved", approved, run_async=True)
-APPROVAL = DisableAbleCommandHandler("approval", approval, run_async=True)
-UNAPPROVEALL = DisableAbleCommandHandler("unapproveall", unapproveall, run_async=True)
-UNAPPROVEALL_BTN = CallbackQueryHandler(
- unapproveall_btn, pattern=r"unapproveall_.*", run_async=True
-)
-
-dispatcher.add_handler(APPROVE)
-dispatcher.add_handler(DISAPPROVE)
-dispatcher.add_handler(APPROVED)
-dispatcher.add_handler(APPROVAL)
-dispatcher.add_handler(UNAPPROVEALL)
-dispatcher.add_handler(UNAPPROVEALL_BTN)
-
-__mod_name__ = "𝐀ᴘᴘʀᴏᴠᴀʟ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "approve_help")
-
-
-# """
-
-
-__command_list__ = ["approve", "unapprove", "approved", "approval"]
-__handlers__ = [APPROVE, DISAPPROVE, APPROVED, APPROVAL]
diff --git a/Exon/modules/backups.py b/Exon/modules/backups.py
deleted file mode 100644
index 2c3448e3..00000000
--- a/Exon/modules/backups.py
+++ /dev/null
@@ -1,373 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import json
-import os
-import time
-from io import BytesIO
-
-from telegram import ParseMode
-from telegram.error import BadRequest
-from telegram.ext import CommandHandler
-
-# from Exon.modules.sql import warns_sql as warnssql
-import Exon.modules.sql.blacklist_sql as blacklistsql
-# from Exon.modules.sql import cust_filters_sql as filtersql
-# import Exon.modules.sql.welcome_sql as welcsql
-import Exon.modules.sql.locks_sql as locksql
-import Exon.modules.sql.notes_sql as sql
-# from Exon.modules.rules import get_rules
-import Exon.modules.sql.rules_sql as rulessql
-from Exon import JOIN_LOGGER, LOGGER, OWNER_ID, SUPPORT_CHAT, dispatcher
-from Exon.__main__ import DATA_IMPORT
-from Exon.modules.connection import connected
-from Exon.modules.helper_funcs.alternate import typing_action
-from Exon.modules.helper_funcs.chat_status import user_admin
-from Exon.modules.sql import disable_sql as disabledsql
-
-
-@user_admin
-@typing_action
-def import_data(update, context):
- msg = update.effective_message
- chat = update.effective_chat
- user = update.effective_user
- # TODO: allow uploading doc with command, not just as reply
- # only work with a doc
-
- conn = connected(context.bot, update, chat, user.id, need_admin=True)
- if conn:
- chat = dispatcher.bot.getChat(conn)
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type == "private":
- update.effective_message.reply_text("ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ғᴏʀ ɢʀᴏᴜᴘ !")
- return ""
-
- chat = update.effective_chat
- chat_name = update.effective_message.chat.title
-
- if msg.reply_to_message and msg.reply_to_message.document:
- try:
- file_info = context.bot.get_file(msg.reply_to_message.document.file_id)
- except BadRequest:
- msg.reply_text(
- "ᴛʀʏ ᴅᴏᴡɴʟᴏᴀᴅɪɴɢ ᴀɴᴅ ᴜᴘʟᴏᴀᴅɪɴɢ ᴛʜᴇ ғɪʟᴇ ʏᴏᴜʀsᴇʟғ ᴀɢᴀɪɴ, ᴛʜɪs ᴏɴᴇ sᴇᴇᴍ ʙʀᴏᴋᴇɴ ᴛᴏ ᴍᴇ!",
- )
- return
-
- with BytesIO() as file:
- file_info.download(out=file)
- file.seek(0)
- data = json.load(file)
-
- # only import one group
- if len(data) > 1 and str(chat.id) not in data:
- msg.reply_text(
- "ᴛʜᴇʀᴇ ᴀʀᴇ ᴍᴏʀᴇ ᴛʜᴀɴ ᴏɴᴇ ɢʀᴏᴜᴘ ɪɴ ᴛʜɪs ғɪʟᴇ ᴀɴᴅ ᴛʜᴇ chat.id ɪs ɴᴏᴛ sᴀᴍᴇ! ʜᴏᴡ ᴀᴍ ɪ sᴜᴘᴘᴏsᴇᴅ ᴛᴏ ɪᴍᴘᴏʀᴛ ɪᴛ?",
- )
- return
-
- # Check if backup is this chat
- try:
- if data.get(str(chat.id)) is None:
- if conn:
- text = f"ʙᴀᴄᴋᴜᴘ ᴄᴏᴍᴇs ғʀᴏᴍ ᴀɴᴏᴛʜᴇʀ ᴄʜᴀᴛ, ɪ ᴄᴀɴ'ᴛ ʀᴇᴛᴜʀɴ ᴀɴᴏᴛʜᴇʀ ᴄʜᴀᴛ ᴛᴏ ᴄʜᴀᴛ *{chat_name}*"
- else:
- text = "ʙᴀᴄᴋᴜᴘ ᴄᴏᴍᴇs ғʀᴏᴍ ᴀɴᴏᴛʜᴇʀ ᴄʜᴀᴛ, I ᴄᴀɴ'ᴛ ʀᴇᴛᴜʀɴ another ᴄʜᴀᴛ ᴛᴏ ᴛʜɪs ᴄʜᴀᴛ"
- return msg.reply_text(text, parse_mode="markdown")
- except Exception:
- return msg.reply_text("ᴛʜᴇʀᴇ ᴡᴀs ᴀ ᴘʀᴏʙʟᴇᴍ ᴡʜɪʟᴇ ɪᴍᴘᴏʀᴛɪɴɢ ᴛʜᴇ ᴅᴀᴛᴀ!")
- # Check if backup is from self
- try:
- if str(context.bot.id) != str(data[str(chat.id)]["bot"]):
- return msg.reply_text(
- "ʙᴀᴄᴋᴜᴘ ғʀᴏᴍ ᴀɴᴏᴛʜᴇʀ ʙᴏᴛ ᴛʜᴀᴛ ɪs ɴᴏᴛ sᴜɢɢᴇsᴛᴇᴅ ᴍɪɢʜᴛ ᴄᴀᴜsᴇ ᴛʜᴇ ᴘʀᴏʙʟᴇᴍ, ᴅᴏᴄᴜᴍᴇɴᴛs, ᴘʜᴏᴛᴏs, ᴠɪᴅᴇᴏs, ᴀᴜᴅɪᴏs, ʀᴇᴄᴏʀᴅs ᴍɪɢʜᴛ ɴᴏᴛ ᴡᴏʀᴋ ᴀs ɪᴛ sʜᴏᴜʟᴅ ʙᴇ.",
- )
- except Exception:
- pass
- # Select data source
- if str(chat.id) in data:
- data = data[str(chat.id)]["hashes"]
- else:
- data = data[list(data.keys())[0]]["hashes"]
-
- try:
- for mod in DATA_IMPORT:
- mod.__import_data__(str(chat.id), data)
- except Exception:
- msg.reply_text(
- f"ᴀɴ ᴇʀʀᴏʀ ᴏᴄᴄᴜʀʀᴇᴅ ᴡʜɪʟᴇ ʀᴇᴄᴏᴠᴇʀɪɴɢ ʏᴏᴜʀ ᴅᴀᴛᴀ. ᴛʜᴇ ᴘʀᴏᴄᴇss ғᴀɪʟᴇᴅ. ɪғ ʏᴏᴜ ᴇxᴘᴇʀɪᴇɴᴄᴇ ᴀ ᴘʀᴏʙʟᴇᴍ ᴡɪᴛʜ ᴛʜɪs, ᴘʟᴇᴀsᴇ ᴛᴀᴋᴇ ɪᴛ ᴛᴏ @{SUPPORT_CHAT}",
- )
-
- LOGGER.exception(
- "ɪᴍᴘᴏʀᴛ ғᴏʀ ᴛʜᴇ ᴄʜᴀᴛ %s ᴡɪᴛʜ ᴛʜᴇ ɴᴀᴍᴇ %s ғᴀɪʟᴇᴅ.",
- str(chat.id),
- str(chat.title),
- )
- return
-
- # TODO: some of that link logic
- # NOTE: consider default permissions stuff?
- if conn:
- text = f"ʙᴀᴄᴋᴜᴘ ғᴜʟʟʏ ʀᴇsᴛᴏʀᴇᴅ ᴏɴ *{chat_name}*."
- else:
- text = "ʙᴀᴄᴋᴜᴘ ғᴜʟʟʏ ʀᴇsᴛᴏʀᴇᴅ"
- msg.reply_text(text, parse_mode="markdown")
-
-
-@user_admin
-def export_data(update, context):
- chat_data = context.chat_data
- msg = update.effective_message # type: Optional[Message]
- user = update.effective_user # type: Optional[User]
- chat_id = update.effective_chat.id
- chat = update.effective_chat
- current_chat_id = update.effective_chat.id
- if conn := connected(context.bot, update, chat, user.id, need_admin=True):
- chat = dispatcher.bot.getChat(conn)
- chat_id = conn
- else:
- if update.effective_message.chat.type == "private":
- update.effective_message.reply_text("ᴛʜɪs ɪs ᴀ ɢʀᴏᴜᴘ ᴄᴏᴍᴍᴀɴᴅ!")
- return ""
- chat = update.effective_chat
- chat_id = update.effective_chat.id
- jam = time.time()
- new_jam = jam + 10800
- checkchat = get_chat(chat_id, chat_data)
- if checkchat.get("status") and jam <= int(checkchat.get("value")):
- timeformatt = time.strftime(
- "%H:%M:%S %d/%m/%Y",
- time.localtime(checkchat.get("value")),
- )
- update.effective_message.reply_text(
- f"ʏᴏᴜ ᴄᴀɴ ᴏɴʟʏ ʙᴀᴄᴋᴜᴘ ᴏɴᴄᴇ ᴀ ᴅᴀʏ!\nʏᴏᴜ ᴄᴀɴ ʙᴀᴄᴋᴜᴘ ᴀɢᴀɪɴ ɪɴ ᴀʙᴏᴜᴛ `{timeformatt}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- if user.id != OWNER_ID:
- put_chat(chat_id, new_jam, chat_data)
- note_list = sql.get_all_chat_notes(chat_id)
- # button = ""
- buttonlist = []
- namacat = ""
- isicat = ""
- rules = ""
- count = 0
- countbtn = 0
- # Notes
- for note in note_list:
- count += 1
- # getnote = sql.get_note(chat_id, note.name)
- namacat += f"{note.name}<###splitter###>"
- if note.msgtype == 1:
- tombol = sql.get_buttons(chat_id, note.name)
- # keyb = []
- for btn in tombol:
- countbtn += 1
- if btn.same_line:
- buttonlist.append((f"{btn.name}", f"{btn.url}", True))
- else:
- buttonlist.append((f"{btn.name}", f"{btn.url}", False))
- isicat += f"###button###: {note.value}<###button###>{buttonlist}<###splitter###>"
- buttonlist.clear()
- elif note.msgtype == 2:
- isicat += f"###sticker###:{note.file}<###splitter###>"
- elif note.msgtype == 3:
- isicat += f"###file###:{note.file}<###TYPESPLIT###>{note.value}<###splitter###>"
- elif note.msgtype == 4:
- isicat += f"###photo###:{note.file}<###TYPESPLIT###>{note.value}<###splitter###>"
- elif note.msgtype == 5:
- isicat += f"###audio###:{note.file}<###TYPESPLIT###>{note.value}<###splitter###>"
- elif note.msgtype == 6:
- isicat += f"###voice###:{note.file}<###TYPESPLIT###>{note.value}<###splitter###>"
- elif note.msgtype == 7:
- isicat += f"###video###:{note.file}<###TYPESPLIT###>{note.value}<###splitter###>"
- elif note.msgtype == 8:
- isicat += f"###video_note###:{note.file}<###TYPESPLIT###>{note.value}<###splitter###>"
- else:
- isicat += f"{note.value}<###splitter###>"
- notes = {
- f'#{namacat.split("<###splitter###>")[x]}': f'{isicat.split("<###splitter###>")[x]}'
- for x in range(count)
- }
- # Rules
- rules = rulessql.get_rules(chat_id)
- # Blacklist
- bl = list(blacklistsql.get_chat_blacklist(chat_id))
- # Disabled command
- disabledcmd = list(disabledsql.get_all_disabled(chat_id))
- # Filters (TODO)
- """
- all_filters = list(filtersql.get_chat_triggers(chat_id))
- export_filters = {}
- for filters in all_filters:
- filt = filtersql.get_filter(chat_id, filters)
- # print(vars(filt))
- if filt.is_sticker:
- tipefilt = "sticker"
- elif filt.is_document:
- tipefilt = "doc"
- elif filt.is_image:
- tipefilt = "img"
- elif filt.is_audio:
- tipefilt = "audio"
- elif filt.is_voice:
- tipefilt = "voice"
- elif filt.is_video:
- tipefilt = "video"
- elif filt.has_buttons:
- tipefilt = "button"
- buttons = filtersql.get_buttons(chat.id, filt.keyword)
- print(vars(buttons))
- elif filt.has_markdown:
- tipefilt = "text"
- if tipefilt == "button":
- content = "{}#=#{}|btn|{}".format(tipefilt, filt.reply, buttons)
- else:
- content = "{}#=#{}".format(tipefilt, filt.reply)
- print(content)
- export_filters[filters] = content
- print(export_filters)
- """
- # Welcome (TODO)
- # welc = welcsql.get_welc_pref(chat_id)
- # Locked
- curr_locks = locksql.get_locks(chat_id)
- curr_restr = locksql.get_restr(chat_id)
-
- if curr_locks:
- locked_lock = {
- "sticker": curr_locks.sticker,
- "audio": curr_locks.audio,
- "voice": curr_locks.voice,
- "document": curr_locks.document,
- "video": curr_locks.video,
- "contact": curr_locks.contact,
- "photo": curr_locks.photo,
- "gif": curr_locks.gif,
- "url": curr_locks.url,
- "bots": curr_locks.bots,
- "forward": curr_locks.forward,
- "game": curr_locks.game,
- "location": curr_locks.location,
- "rtl": curr_locks.rtl,
- }
- else:
- locked_lock = {}
-
- if curr_restr:
- locked_restr = {
- "messages": curr_restr.messages,
- "media": curr_restr.media,
- "other": curr_restr.other,
- "previews": curr_restr.preview,
- "all": all(
- [
- curr_restr.messages,
- curr_restr.media,
- curr_restr.other,
- curr_restr.preview,
- ],
- ),
- }
- else:
- locked_restr = {}
-
- locks = {"locks": locked_lock, "restrict": locked_restr}
- backup = {
- chat_id: {
- "bot": context.bot.id,
- "hashes": {
- "info": {"rules": rules},
- "extra": notes,
- "blacklist": bl,
- "disabled": disabledcmd,
- "locks": locks,
- },
- }
- }
- baccinfo = json.dumps(backup, indent=4)
- with open(f"Exon-Exon{chat_id}.backup", "w") as f:
- f.write(baccinfo)
- context.bot.sendChatAction(current_chat_id, "upload_document")
- tgl = time.strftime("%H:%M:%S - %d/%m/%Y", time.localtime(time.time()))
- try:
- context.bot.sendMessage(
- JOIN_LOGGER,
- f"*sᴜᴄᴄᴇssғᴜʟʟʏ ɪᴍᴘᴏʀᴛᴇᴅ ʙᴀᴄᴋᴜᴘ:*\nᴄʜᴀᴛ: `{chat.title}`\nᴄʜᴀᴛ ɪᴅ: `{chat_id}`\nᴏɴ: `{tgl}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- except BadRequest:
- pass
- context.bot.sendDocument(
- current_chat_id,
- document=open(f"Exon-Exon{chat_id}.backup", "rb"),
- caption=f"*sᴜᴄᴄᴇssғᴜʟʟʏ ᴇxᴘᴏʀᴛᴇᴅ ʙᴀᴄᴋᴜᴘ:*\nᴄʜᴀᴛ: `{chat.title}`\nᴄʜᴀᴛ ɪᴅ: `{chat_id}`\nᴏɴ: `{tgl}`\n\nɴᴏᴛᴇ: ᴛʜɪs `Exon-Exon-Backup` ᴡᴀs sᴘᴇᴄɪᴀʟʟʏ ᴍᴀᴅᴇ ғᴏʀ ɴᴏᴛᴇs.",
- timeout=360,
- reply_to_message_id=msg.message_id,
- parse_mode=ParseMode.MARKDOWN,
- )
- os.remove(f"Exon-Exon{chat_id}.backup")
-
-
-# Temporary data
-def put_chat(chat_id, value, chat_data):
- # print(chat_data)
- status = value is not False
- chat_data[chat_id] = {"backups": {"status": status, "value": value}}
-
-
-def get_chat(chat_id, chat_data):
- # print(chat_data)
- try:
- return chat_data[chat_id]["backups"]
- except KeyError:
- return {"status": False, "value": False}
-
-
-__mod_name__ = "𝐁ᴀᴄᴋᴜᴘ"
-
-IMPORT_HANDLER = CommandHandler(["import", "backup"], import_data, run_async=True)
-EXPORT_HANDLER = CommandHandler(
- "export", export_data, pass_chat_data=True, run_async=True
-)
-
-dispatcher.add_handler(IMPORT_HANDLER)
-dispatcher.add_handler(EXPORT_HANDLER)
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "backup_help")
-
-# """
diff --git a/Exon/modules/bans.py b/Exon/modules/bans.py
deleted file mode 100644
index 7961253b..00000000
--- a/Exon/modules/bans.py
+++ /dev/null
@@ -1,639 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import html
-from typing import Optional
-
-from telegram import (
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- TelegramError,
- Update,
-)
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler, Filters
-from telegram.utils.helpers import mention_html
-
-from Exon import (
- DEMONS,
- DEV_USERS,
- DRAGONS,
- LOGGER,
- OWNER_ID,
- TIGERS,
- WOLVES,
- dispatcher,
-)
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.anonymous import AdminPerms, user_admin
-from Exon.modules.helper_funcs.chat_status import (
- bot_admin,
- can_delete,
- can_restrict,
- connection_status,
- dev_plus,
- is_user_admin,
- is_user_ban_protected,
- is_user_in_chat,
-)
-from Exon.modules.helper_funcs.chat_status import user_admin as u_admin
-from Exon.modules.helper_funcs.chat_status import user_admin_no_reply, user_can_ban
-from Exon.modules.helper_funcs.extraction import extract_user_and_text
-from Exon.modules.helper_funcs.filters import CustomFilters
-from Exon.modules.helper_funcs.string_handling import extract_time
-from Exon.modules.log_channel import gloggable, loggable
-
-
-# @Exoncmd(command=["ban", "sban", "dban"], pass_args=True)
-@connection_status
-@bot_admin
-@can_restrict
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-@loggable
-def ban(
- update: Update, context: CallbackContext
-) -> Optional[str]: # sourcery no-metrics
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- message = update.effective_message # type: Optional[Message]
- args = context.args
- bot = context.bot
- log_message = ""
- reason = ""
- if message.reply_to_message and message.reply_to_message.sender_chat:
- if r := bot.ban_chat_sender_chat(
- chat_id=chat.id,
- sender_chat_id=message.reply_to_message.sender_chat.id,
- ):
- message.reply_text(
- f"Finally! Channel {html.escape(message.reply_to_message.sender_chat.title)} was banned successfully from {html.escape(chat.title)}\n\n💡 He can only write with his profile but not through other channels.",
- parse_mode="html",
- )
- return (
- f"{html.escape(chat.title)}:\n"
- f"#BANNED\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"Channel: {html.escape(message.reply_to_message.sender_chat.title)} ({message.reply_to_message.sender_chat.id})"
- )
- message.reply_text("Failed to ban channel")
- return
-
- user_id, reason = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text("I doubt that's a user.")
- return log_message
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message != "User not found":
- raise
-
- message.reply_text("Can't seem to find this person.")
- return log_message
- if user_id == context.bot.id:
- message.reply_text("Oh yeah, ban myself, noob!")
- return log_message
-
- if is_user_ban_protected(update, user_id, member) and user not in DEV_USERS:
- if user_id == OWNER_ID:
- message.reply_text("Fighting with my Master will put user lives at risk")
- elif user_id in DEV_USERS:
- message.reply_text("I can't act against our own.")
- elif user_id in DRAGONS:
- message.reply_text(
- "Fighting this Shadow Slayer here will put user lives at risk."
- )
- elif user_id in DEMONS:
- message.reply_text("Bring an order from Master Servant to fight a Guardian")
- elif user_id in TIGERS:
- message.reply_text(
- "Bring an order from Master Servant to fight a Light Shooters"
- )
- elif user_id in WOLVES:
- message.reply_text("Villain abilities make them ban immune!")
- else:
- message.reply_text("This user has immunity and cannot be banned.")
- return log_message
-
- if message.text.startswith("/d") and message.reply_to_message:
- message.reply_to_message.delete()
-
- if message.text.startswith("/s"):
- silent = True
- if not can_delete(chat, context.bot.id):
- return ""
- else:
- silent = False
-
- log = (
- f"{html.escape(chat.title)}:\n"
- f"#{'S' if silent else ''}BANNED\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"User: {mention_html(member.user.id, member.user.first_name)}"
- )
- if reason:
- log += f"\nReason: {reason}"
-
- try:
- chat.ban_member(user_id)
-
- if silent:
- if message.reply_to_message:
- message.reply_to_message.delete()
- message.delete()
- return log
-
- # context.bot.send_sticker(chat.id, BAN_STICKER) # banhammer marie sticker
- reply = (
- f"Yep! Banned {mention_html(member.user.id, html.escape(member.user.first_name))} from {chat.title}\n"
- f"By {mention_html(user.id, html.escape(user.first_name))}"
- )
- if reason:
- reply += f"\nReason: {html.escape(reason)}"
-
- bot.sendMessage(
- chat.id,
- reply,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⚠️ Unban", callback_data=f"unbanb_unban={user_id}"
- ),
- InlineKeyboardButton(
- text="❌ Delete", callback_data="unbanb_del"
- ),
- ]
- ]
- ),
- parse_mode=ParseMode.HTML,
- )
- return log
-
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- if silent:
- return log
- message.reply_text("Banned!", quote=False)
- return log
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR banning user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't ban that user.")
-
- return ""
-
-
-@connection_status
-@bot_admin
-@can_restrict
-@u_admin
-@user_can_ban
-@loggable
-def temp_ban(update: Update, context: CallbackContext) -> str:
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
- log_message = ""
- bot, args = context.bot, context.args
-
- user_id, reason = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text("Dude! at least refer some user to ban...")
- return log_message
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message != "User not found":
- raise
- message.reply_text("I can't seem to find this user.")
- return log_message
- if user_id == bot.id:
- message.reply_text("I'm not gonna BAN myself, are you crazy?")
- return log_message
-
- if is_user_ban_protected(chat, user_id, member):
- message.reply_text("I don't feel like it.")
- return log_message
-
- if not reason:
- message.reply_text("You haven't specified a time to ban this user for!")
- return log_message
-
- split_reason = reason.split(None, 1)
-
- time_val = split_reason[0].lower()
- reason = split_reason[1] if len(split_reason) > 1 else ""
- bantime = extract_time(message, time_val)
-
- if not bantime:
- return log_message
-
- log = (
- f"{html.escape(chat.title)}:\n"
- "#TEMP BANNED\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(member.user.id, html.escape(member.user.first_name))}\n"
- f"Time: {time_val}"
- )
- if reason:
- log += f"\nReason: {reason}"
-
- try:
- chat.ban_member(user_id, until_date=bantime)
- # bot.send_sticker(chat.id, BAN_STICKER) # banhammer marie sticker
-
- reply_msg = (
- f"Yep! Temporary Banned {mention_html(member.user.id, html.escape(member.user.first_name))} from {chat.title}\n"
- f"By {mention_html(user.id, html.escape(user.first_name))}"
- )
- if reason:
- reply_msg += f"\nReason: {html.escape(reason)}"
-
- bot.sendMessage(
- chat.id,
- reply_msg,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⚠️ Unban", callback_data=f"unbanb_unban={user_id}"
- ),
- InlineKeyboardButton(
- text="❌ Delete", callback_data="unbanb_del"
- ),
- ]
- ]
- ),
- parse_mode=ParseMode.HTML,
- )
- return log
-
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text(
- f"Banned! User will be banned for {time_val}.", quote=False
- )
- return log
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR banning user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't ban that user.")
-
- return log_message
-
-
-@connection_status
-@bot_admin
-@can_restrict
-@user_admin_no_reply
-@user_can_ban
-@loggable
-def unbanb_btn(update: Update, context: CallbackContext) -> str:
- bot = context.bot
- query = update.callback_query
- user = update.effective_user
- if query.data != "unbanb_del":
- splitter = query.data.split("=")
- query_match = splitter[0]
- if query_match == "unbanb_unban":
- user_id = splitter[1]
- if not is_user_admin(update, int(user.id)):
- bot.answer_callback_query(
- query.id,
- text="You don't have enough rights to unmute people",
- show_alert=True,
- )
- return ""
-
- chat = update.effective_chat
- try:
- member = chat.get_member(user_id)
- except BadRequest:
- pass
-
- dick = (
- f"Yep! Unbanned {mention_html(member.user.id, html.escape(member.user.first_name))} from {chat.title}\n"
- f"Unbanned By: {mention_html(user.id, html.escape(user.first_name))}"
- )
- chat.unban_member(user_id)
- query.message.edit_text(
- dick,
- parse_mode=ParseMode.HTML,
- )
- bot.answer_callback_query(query.id, text="Unbanned!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#UNBANNED\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"User: {mention_html(member.user.id, member.user.first_name)}"
- )
-
- else:
- if not is_user_admin(update, int(user.id)):
- bot.answer_callback_query(
- query.id,
- text="You don't have enough rights to delete this message.",
- show_alert=True,
- )
- return ""
- query.message.delete()
- bot.answer_callback_query(query.id, text="Deleted!")
- return ""
-
-
-@connection_status
-@bot_admin
-@can_restrict
-@u_admin
-@user_can_ban
-@loggable
-def punch(update: Update, context: CallbackContext) -> str:
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
- log_message = ""
- bot, args = context.bot, context.args
-
- user_id, reason = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text("I doubt that's a user.")
- return log_message
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message != "User not found":
- raise
-
- message.reply_text("I can't seem to find this user.")
- return log_message
- if user_id == bot.id:
- message.reply_text("Yeahhh I'm not gonna do that.")
- return log_message
-
- if is_user_ban_protected(update, user_id):
- message.reply_text("I really wish I could punch this user....")
- return log_message
-
- if res := chat.unban_member(user_id):
- # bot.send_sticker(chat.id, BAN_STICKER) # banhammer marie sticker
- bot.sendMessage(
- chat.id,
- f"One kicked! {mention_html(member.user.id, html.escape(member.user.first_name))}.",
- parse_mode=ParseMode.HTML,
- )
- log = (
- f"{html.escape(chat.title)}:\n"
- f"#KICKED\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(member.user.id, html.escape(member.user.first_name))}"
- )
- if reason:
- log += f"\nReason: {reason}"
-
- return log
- message.reply_text("Well damn, I can't punch that user.")
-
- return log_message
-
-
-@bot_admin
-@can_restrict
-def punchme(update: Update, context: CallbackContext):
- user_id = update.effective_message.from_user.id
- if is_user_admin(update, user_id):
- update.effective_message.reply_text("I wish I could... but you're an admin.")
- return
-
- if res := update.effective_chat.unban_member(user_id):
- update.effective_message.reply_text("*punches you out of the group*")
- else:
- update.effective_message.reply_text("Huh? I can't :/")
-
-
-@connection_status
-@bot_admin
-@can_restrict
-@u_admin
-@user_can_ban
-@loggable
-def unban(update: Update, context: CallbackContext) -> Optional[str]:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- log_message = ""
- bot, args = context.bot, context.args
- if message.reply_to_message and message.reply_to_message.sender_chat:
- if r := bot.unban_chat_sender_chat(
- chat_id=chat.id,
- sender_chat_id=message.reply_to_message.sender_chat.id,
- ):
- message.reply_text(
- f"Finally! Channel {html.escape(message.reply_to_message.sender_chat.title)} was unbanned successfully from {html.escape(chat.title)}\n\n💡 Now this users can send the messages with they channel again",
- parse_mode="html",
- )
- else:
- message.reply_text("Failed to unban channel")
- return
-
- user_id, reason = extract_user_and_text(message, args)
- if not user_id:
- message.reply_text("I doubt that's a user.")
- return log_message
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message != "User not found":
- raise
- message.reply_text("I can't seem to find this user.")
- return log_message
- if user_id == bot.id:
- message.reply_text("How would I unban myself if I wasn't here...?")
- return log_message
-
- if is_user_in_chat(chat, user_id):
- message.reply_text("Isn't this person already here??")
- return log_message
-
- chat.unban_member(user_id)
- message.reply_text(
- f"Yep! Unbanned {mention_html(member.user.id, html.escape(member.user.first_name))} from {chat.title}\n"
- f"Unbanned By: {mention_html(user.id, html.escape(user.first_name))}!",
- parse_mode=ParseMode.HTML,
- )
-
- log = (
- f"{html.escape(chat.title)}:\n"
- f"#UNBANNED\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(member.user.id, html.escape(member.user.first_name))}"
- )
- if reason:
- log += f"\nReason: {reason}"
-
- return log
-
-
-@connection_status
-@bot_admin
-@can_restrict
-@gloggable
-def selfunban(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- bot, args = context.bot, context.args
- if user.id not in DRAGONS or user.id not in TIGERS:
- return
-
- try:
- chat_id = int(args[0])
- except Exception:
- message.reply_text("Give a valid chat ID.")
- return
-
- chat = bot.getChat(chat_id)
-
- try:
- member = chat.get_member(user.id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user.")
- return
- raise
-
- if is_user_in_chat(chat, user.id):
- message.reply_text("Aren't you already in the chat??")
- return
-
- chat.unban_member(user.id)
- message.reply_text(
- f"Yep! I Have Unbanned You {mention_html(member.user.id, html.escape(member.user.first_name))} from {chat.title}\n"
- f"Unbanned By: {mention_html(user.id, html.escape(user.first_name))}.",
- parse_mode=ParseMode.HTML,
- )
-
- return f"{html.escape(chat.title)}:\n#UNBANNED\nUser: {mention_html(member.user.id, html.escape(member.user.first_name))}"
-
-
-@bot_admin
-@can_restrict
-@loggable
-def banme(update: Update, context: CallbackContext):
- user_id = update.effective_message.from_user.id
- chat = update.effective_chat
- user = update.effective_user
- if is_user_admin(update, user_id):
- update.effective_message.reply_text("Yeahhh.. not gonna ban an admin.")
- return
-
- if res := update.effective_chat.ban_member(user_id):
- update.effective_message.reply_text("Yes, you're right! GTFO..")
- return f"{html.escape(chat.title)}:\n#BANME\nUser: {mention_html(user.id, user.first_name)}\nID: {user_id}
"
- update.effective_message.reply_text("Huh? I can't :/")
-
-
-@dev_plus
-def snipe(update: Update, context: CallbackContext):
- args = context.args
- bot = context.bot
- try:
- chat_id = str(args[0])
- del args[0]
- except TypeError:
- update.effective_message.reply_text("Please give me a chat to echo to!")
- to_send = " ".join(args)
- if len(to_send) >= 2:
- try:
- bot.sendMessage(int(chat_id), to_send)
- except TelegramError:
- LOGGER.warning("Couldn't send to group %s", chat_id)
- update.effective_message.reply_text(
- "Couldn't send the message. Perhaps I'm not part of that group?"
- )
-
-
-__mod_name__ = "𝐁ᴀɴs"
-
-BAN_HANDLER = CommandHandler(["ban", "sban", "dban"], ban, run_async=True)
-TEMPBAN_HANDLER = CommandHandler(["tban"], temp_ban, run_async=True)
-KICK_HANDLER = CommandHandler(["kick", "punch"], punch, run_async=True)
-UNBAN_HANDLER = CommandHandler("unban", unban, run_async=True)
-ROAR_HANDLER = CommandHandler("roar", selfunban, run_async=True)
-UNBAN_BUTTON_HANDLER = CallbackQueryHandler(
- unbanb_btn, pattern=r"unbanb_", run_async=True
-)
-KICKME_HANDLER = DisableAbleCommandHandler(
- ["kickme", "punchme"], punchme, filters=Filters.chat_type.groups, run_async=True
-)
-SNIPE_HANDLER = CommandHandler(
- "snipe", snipe, pass_args=True, filters=CustomFilters.dev_filter, run_async=True
-)
-BANME_HANDLER = CommandHandler("banme", banme, run_async=True)
-
-dispatcher.add_handler(BAN_HANDLER)
-dispatcher.add_handler(TEMPBAN_HANDLER)
-dispatcher.add_handler(KICK_HANDLER)
-dispatcher.add_handler(UNBAN_HANDLER)
-dispatcher.add_handler(ROAR_HANDLER)
-dispatcher.add_handler(KICKME_HANDLER)
-dispatcher.add_handler(UNBAN_BUTTON_HANDLER)
-dispatcher.add_handler(SNIPE_HANDLER)
-dispatcher.add_handler(BANME_HANDLER)
-
-__handlers__ = [
- BAN_HANDLER,
- TEMPBAN_HANDLER,
- KICK_HANDLER,
- UNBAN_HANDLER,
- ROAR_HANDLER,
- KICKME_HANDLER,
- UNBAN_BUTTON_HANDLER,
- SNIPE_HANDLER,
- BANME_HANDLER,
-]
diff --git a/Exon/modules/blacklist.py b/Exon/modules/blacklist.py
deleted file mode 100644
index ba237976..00000000
--- a/Exon/modules/blacklist.py
+++ /dev/null
@@ -1,547 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import html
-import re
-
-from telegram import (
- ChatPermissions,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- Update,
-)
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, CommandHandler, Filters, MessageHandler
-from telegram.utils.helpers import mention_html
-
-import Exon.modules.sql.blacklist_sql as sql
-from Exon import LOGGER, dispatcher
-from Exon.modules.connection import connected
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.alternate import send_message, typing_action
-from Exon.modules.helper_funcs.chat_status import user_admin, user_not_admin
-from Exon.modules.helper_funcs.decorators import Exoncallback as akboss
-from Exon.modules.helper_funcs.extraction import extract_text
-from Exon.modules.helper_funcs.misc import split_message
-from Exon.modules.helper_funcs.string_handling import extract_time
-from Exon.modules.log_channel import loggable
-from Exon.modules.sql.approve_sql import is_approved
-from Exon.modules.warns import warn
-
-BLACKLIST_GROUP = 11
-
-
-@user_admin
-@typing_action
-def blacklist(update, context):
- chat = update.effective_chat
- user = update.effective_user
- args = context.args
-
- if conn := connected(context.bot, update, chat, user.id, need_admin=False):
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if chat.type == "private":
- return
- chat_id = update.effective_chat.id
- chat_name = chat.title
-
- filter_list = f"ᴄᴜʀʀᴇɴᴛ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅs ɪɴ {chat_name}:\n"
-
- all_blacklisted = sql.get_chat_blacklist(chat_id)
-
- if len(args) > 0 and args[0].lower() == "copy":
- for trigger in all_blacklisted:
- filter_list += f"{html.escape(trigger)}
\n"
- else:
- for trigger in all_blacklisted:
- filter_list += f" - {html.escape(trigger)}
\n"
-
- # for trigger in all_blacklisted:
- # filter_list += " - {}
\n".format(html.escape(trigger))
-
- split_text = split_message(filter_list)
- for text in split_text:
- if (
- filter_list
- == f"ᴄᴜʀʀᴇɴᴛ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅs ɪɴ {html.escape(chat_name)}:\n"
- ):
- send_message(
- update.effective_message,
- f"ɴᴏ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅs ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- return
- send_message(update.effective_message, text, parse_mode=ParseMode.HTML)
-
-
-@user_admin
-@typing_action
-def add_blacklist(update, context):
- msg = update.effective_message
- chat = update.effective_chat
- user = update.effective_user
- words = msg.text.split(None, 1)
-
- if conn := connected(context.bot, update, chat, user.id):
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- chat_id = update.effective_chat.id
- if chat.type == "private":
- return
- chat_name = chat.title
-
- if len(words) > 1:
- text = words[1]
- to_blacklist = list(
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()}
- )
- for trigger in to_blacklist:
- sql.add_to_blacklist(chat_id, trigger.lower())
-
- if len(to_blacklist) == 1:
- send_message(
- update.effective_message,
- f"ᴀᴅᴅᴇᴅ ʙʟᴀᴄᴋʟɪsᴛ {html.escape(to_blacklist[0])}
ɪɴ ᴄʜᴀᴛ: {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
-
- else:
- send_message(
- update.effective_message,
- f"ᴀᴅᴅᴇᴅ ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀ: {len(to_blacklist)}
in {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
-
- else:
- send_message(
- update.effective_message,
- "ᴛᴇʟʟ ᴍᴇ ᴡʜɪᴄʜ ᴡᴏʀᴅs ʏᴏᴜ ᴡᴏᴜʟᴅ ʟɪᴋᴇ ᴛᴏ ᴀᴅᴅ ɪɴ ʙʟᴀᴄᴋʟɪsᴛ.",
- )
-
-
-@user_admin
-@typing_action
-def unblacklist(update, context):
- msg = update.effective_message
- chat = update.effective_chat
- user = update.effective_user
- words = msg.text.split(None, 1)
-
- if conn := connected(context.bot, update, chat, user.id):
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- chat_id = update.effective_chat.id
- if chat.type == "private":
- return
- chat_name = chat.title
-
- if len(words) > 1:
- text = words[1]
- to_unblacklist = list(
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()}
- )
- successful = 0
- for trigger in to_unblacklist:
- success = sql.rm_from_blacklist(chat_id, trigger.lower())
- if success:
- successful += 1
-
- if len(to_unblacklist) == 1:
- if successful:
- send_message(
- update.effective_message,
- f"ʀᴇᴍᴏᴠᴇᴅ {html.escape(to_unblacklist[0])}
ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_message(
- update.effective_message, "ᴛʜɪs ɪs ɴᴏᴛ ᴀ ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀ!"
- )
-
- elif successful == len(to_unblacklist):
- send_message(
- update.effective_message,
- f"Removed {successful}
ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
-
- elif not successful:
- send_message(
- update.effective_message,
- "ɴᴏɴᴇ ᴏғ ᴛʜᴇsᴇ ᴛʀɪɢɢᴇʀs ᴇxɪsᴛ sᴏ ɪᴛ ᴄᴀɴ'ᴛ ʙᴇ ʀᴇᴍᴏᴠᴇᴅ.".format(
- successful, len(to_unblacklist) - successful
- ),
- parse_mode=ParseMode.HTML,
- )
-
- else:
- send_message(
- update.effective_message,
- f"ʀᴇᴍᴏᴠᴇᴅ {successful}
ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ. {len(to_unblacklist) - successful} ᴅɪᴅ ɴᴏᴛ ᴇxɪsᴛ, so were not removed.",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_message(
- update.effective_message,
- "ᴛᴇʟʟ ᴍᴇ ᴡʜɪᴄʜ ᴡᴏʀᴅs ʏᴏᴜ ᴡᴏᴜʟᴅ ʟɪᴋᴇ ᴛᴏ ʀᴇᴍᴏᴠᴇ ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ!",
- )
-
-
-@loggable
-@user_admin
-@typing_action
-def blacklist_mode(update, context):
- chat = update.effective_chat
- user = update.effective_user
- msg = update.effective_message
- args = context.args
-
- conn = connected(context.bot, update, chat, user.id, need_admin=True)
- if conn:
- chat = dispatcher.bot.getChat(conn)
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type == "private":
- send_message(
- update.effective_message,
- "ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴄᴀɴ ʙᴇ ᴏɴʟʏ ᴜsᴇᴅ ɪɴ ɢʀᴏᴜᴘ ɴᴏᴛ ɪɴ PM",
- )
- return ""
- chat = update.effective_chat
- chat_id = update.effective_chat.id
- chat_name = update.effective_message.chat.title
-
- if args:
- if args[0].lower() in ("off", "nothing", "no"):
- settypeblacklist = "ᴅᴏ ɴᴏᴛʜɪɴɢ"
- sql.set_blacklist_strength(chat_id, 0, "0")
- elif args[0].lower() in ("del", "delete"):
- settypeblacklist = "ᴡɪʟʟ ᴅᴇʟᴇᴛᴇ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴍᴇssᴀɢᴇ"
- sql.set_blacklist_strength(chat_id, 1, "0")
- elif args[0].lower() == "warn":
- settypeblacklist = "ᴡᴀʀɴ ᴛʜᴇ sᴇɴᴅᴇʀ"
- sql.set_blacklist_strength(chat_id, 2, "0")
- elif args[0].lower() == "mute":
- settypeblacklist = "ᴍᴜᴛᴇ ᴛʜᴇ sᴇɴᴅᴇʀ"
- sql.set_blacklist_strength(chat_id, 3, "0")
- elif args[0].lower() == "kick":
- settypeblacklist = "ᴋɪᴄᴋ ᴛʜᴇ sᴇɴᴅᴇʀ"
- sql.set_blacklist_strength(chat_id, 4, "0")
- elif args[0].lower() == "ban":
- settypeblacklist = "ʙᴀɴ ᴛʜᴇ sᴇɴᴅᴇʀ"
- sql.set_blacklist_strength(chat_id, 5, "0")
- elif args[0].lower() == "tban":
- if len(args) == 1:
- teks = """ɪᴛ ʟᴏᴏᴋs ʟɪᴋᴇ ʏᴏᴜ ᴛʀɪᴇᴅ ᴛᴏ sᴇᴛ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ ғᴏʀ ʙʟᴀᴄᴋʟɪsᴛ ʙᴜᴛ ʏᴏᴜ ᴅɪᴅɴ'ᴛ sᴘᴇᴄɪғɪᴇᴅ ᴛɪᴍᴇ; 𝐓𝐫𝐲, `/blacklistmode tban <ᴛɪᴍᴇᴠᴀʟᴜᴇ>`.
- ᴇxᴀᴍᴘʟᴇs ᴏғ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ: 4ᴍ = 4 ᴍɪɴᴜᴛᴇs, 3ʜ = 3 ʜᴏᴜʀs, 6d = 6 ᴅᴀʏs, 5ᴡ = 5 ᴡᴇᴇᴋs."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return ""
- restime = extract_time(msg, args[1])
- if not restime:
- teks = """ɪɴᴠᴀʟɪᴅ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ!
- Example of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return ""
- settypeblacklist = f"ᴛᴇᴍᴘᴏʀᴀʀɪʟʏ ʙᴀɴ ғᴏʀ {args[1]}"
- sql.set_blacklist_strength(chat_id, 6, str(args[1]))
- elif args[0].lower() == "tmute":
- if len(args) == 1:
- teks = """ɪᴛ ʟᴏᴏᴋs ʟɪᴋᴇ ʏᴏᴜ ᴛʀɪᴇᴅ ᴛᴏ sᴇᴛ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ ғᴏʀ ʙʟᴀᴄᴋʟɪsᴛ ʙᴜᴛ ʏᴏᴜ ᴅɪᴅɴ'ᴛ sᴘᴇᴄɪғɪᴇᴅ ᴛɪᴍᴇ; ᴛʀʏ, `/blacklistmode tmute <ᴛɪᴍᴇᴠᴀʟᴜᴇ>`.
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return ""
- restime = extract_time(msg, args[1])
- if not restime:
- teks = """ɪɴᴠᴀʟɪᴅ ᴛɪᴍᴇ ᴠᴀʟᴜᴇ!
- Examples of time value: 4m = 4 minutes, 3h = 3 hours, 6d = 6 days, 5w = 5 weeks."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return ""
- settypeblacklist = f"ᴛᴇᴍᴘᴏʀᴀʀɪʟʏ ᴍᴜᴛᴇ ғᴏʀ {args[1]}"
- sql.set_blacklist_strength(chat_id, 7, str(args[1]))
- else:
- send_message(
- update.effective_message,
- "I ᴏɴʟʏ ᴜɴᴅᴇʀsᴛᴀɴᴅ: off/del/warn/ban/kick/mute/tban/tmute!",
- )
- return ""
- if conn:
- text = f"ᴄʜᴀɴɢᴇᴅ ʙʟᴀᴄᴋʟɪsᴛ ᴍᴏᴅᴇ: `{settypeblacklist}` in *{chat_name}*!"
- else:
- text = f"ᴄʜᴀɴɢᴇᴅ ʙʟᴀᴄᴋʟɪsᴛ ᴍᴏᴅᴇ: `{settypeblacklist}`!"
- send_message(update.effective_message, text, parse_mode="markdown")
- return f"{html.escape(chat.title)}:\nᴀᴅᴍɪɴ: {mention_html(user.id, html.escape(user.first_name))}\nᴄʜᴀɴɢᴇᴅ ᴛʜᴇ ʙʟᴀᴄᴋʟɪsᴛ ᴍᴏᴅᴇ. ᴡɪʟʟ {settypeblacklist}."
- getmode, getvalue = sql.get_blacklist_setting(chat.id)
- if getmode == 0:
- settypeblacklist = "ᴅᴏ ɴᴏᴛʜɪɴɢ"
- elif getmode == 1:
- settypeblacklist = "ᴅᴇʟᴇᴛᴇ"
- elif getmode == 2:
- settypeblacklist = "warn"
- elif getmode == 3:
- settypeblacklist = "ᴍᴜᴛᴇ"
- elif getmode == 4:
- settypeblacklist = "ᴋɪᴄᴋ"
- elif getmode == 5:
- settypeblacklist = "ʙᴀɴ"
- elif getmode == 6:
- settypeblacklist = f"ᴛᴇᴍᴘᴏʀᴀʀɪʟʏ ʙᴀɴ ғᴏʀ {getvalue}"
- elif getmode == 7:
- settypeblacklist = f"ᴛᴇᴍᴘᴏʀᴀʀɪʟʏ ᴍᴜᴛᴇ ғᴏʀ {getvalue}"
- if conn:
- text = f"ᴄᴜʀʀᴇɴᴛ ʙʟᴀᴄᴋʟɪsᴛᴍᴏᴅᴇ: *{settypeblacklist}* ɪɴ *{chat_name}*."
- else:
- text = f"ᴄᴜʀʀᴇɴᴛ ʙʟᴀᴄᴋʟɪsᴛᴍᴏᴅᴇ: *{settypeblacklist}*."
- send_message(update.effective_message, text, parse_mode=ParseMode.MARKDOWN)
- return ""
-
-
-def findall(p, s):
- i = s.find(p)
- while i != -1:
- yield i
- i = s.find(p, i + 1)
-
-
-@user_not_admin
-def del_blacklist(update, context):
- chat = update.effective_chat
- message = update.effective_message
- user = update.effective_user
- bot = context.bot
- to_match = extract_text(message)
-
- if not to_match:
- return
-
- if is_approved(chat.id, user.id):
- return
-
- getmode, value = sql.get_blacklist_setting(chat.id)
-
- chat_filters = sql.get_chat_blacklist(chat.id)
- for trigger in chat_filters:
- pattern = r"( |^|[^\w])" + re.escape(trigger) + r"( |$|[^\w])"
- if re.search(pattern, to_match, flags=re.IGNORECASE):
- try:
- if getmode == 0:
- return
- if getmode == 1:
- message.delete()
- elif getmode == 2:
- message.delete()
- warn(
- update.effective_user,
- update,
- f"ᴜsɪɴɢ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴛʀɪɢɢᴇʀ: {trigger}",
- message,
- update.effective_user,
- )
- return
- elif getmode == 3:
- message.delete()
- bot.restrict_chat_member(
- chat.id,
- update.effective_user.id,
- permissions=ChatPermissions(can_send_messages=False),
- )
- bot.sendMessage(
- chat.id,
- f"ᴍᴜᴛᴇᴅ {user.first_name} ғᴏʀ ᴜsɪɴɢ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅ: {trigger}!",
- )
- return
- elif getmode == 4:
- message.delete()
- if res := chat.unban_member(update.effective_user.id):
- bot.sendMessage(
- chat.id,
- f"ᴋɪᴄᴋᴇᴅ {user.first_name} ғᴏʀ ᴜsɪɴɢ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅ: {trigger}!",
- )
- return
- elif getmode == 5:
- message.delete()
- chat.ban_member(user.id)
- bot.sendMessage(
- chat.id,
- f"ʙᴀɴɴᴇᴅ {user.first_name} ғᴏʀ ᴜsɪɴɢ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅ: {trigger}",
- )
- return
- elif getmode == 6:
- message.delete()
- bantime = extract_time(message, value)
- chat.ban_member(user.id, until_date=bantime)
- bot.sendMessage(
- chat.id,
- f"ʙᴀɴɴᴇᴅ {user.first_name} ᴜɴᴛɪʟ '{value}' ғᴏʀ ᴜsɪɴɢ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅ: {trigger}!",
- )
- return
- elif getmode == 7:
- message.delete()
- mutetime = extract_time(message, value)
- bot.restrict_chat_member(
- chat.id,
- user.id,
- until_date=mutetime,
- permissions=ChatPermissions(can_send_messages=False),
- )
- bot.sendMessage(
- chat.id,
- f"ᴍᴜᴛᴇᴅ {user.first_name} ᴜɴᴛɪʟ '{value}' ғᴏʀ ᴜsɪɴɢ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅ: {trigger}!",
- )
- return
- except BadRequest as excp:
- if excp.message != "ᴍᴇssᴀɢᴇ ᴛᴏ ᴅᴇʟᴇᴛᴇ ɴᴏᴛ ғᴏᴜɴᴅ":
- LOGGER.exception("ᴇʀʀᴏʀ ᴡʜɪʟᴇ ᴅᴇʟᴇᴛɪɴɢ ʙʟᴀᴄᴋʟɪsᴛ ᴍᴇssᴀɢᴇ.")
- break
-
-
-def __import_data__(chat_id, data):
- # set chat blacklist
- blacklist = data.get("blacklist", {})
- for trigger in blacklist:
- sql.add_to_blacklist(chat_id, trigger)
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- blacklisted = sql.num_blacklist_chat_filters(chat_id)
- return f"ᴛʜᴇʀᴇ ᴀʀᴇ {blacklisted} ʙʟᴀᴄᴋʟɪsᴛᴇᴅ ᴡᴏʀᴅs."
-
-
-def __stats__():
- return f"≛≛ {sql.num_blacklist_filters()} ʙʟᴀᴄᴋʟɪsᴛ ᴛʀɪɢɢᴇʀs, ᴀᴄʀᴏss {sql.num_blacklist_filter_chats()} ᴄʜᴀᴛs."
-
-
-BLACKLIST_HANDLER = DisableAbleCommandHandler(
- ["blacklist", "blocklist"], blacklist, pass_args=True, admin_ok=True, run_async=True
-)
-
-ADD_BLACKLIST_HANDLER = CommandHandler(
- ["addblacklist", "addblocklist"], add_blacklist, run_async=True
-)
-UNBLACKLIST_HANDLER = CommandHandler(
- ["unblacklist", "rmblocklist", "rmblacklist"], unblacklist, run_async=True
-)
-BLACKLISTMODE_HANDLER = CommandHandler(
- ["blacklistmode", "blocklistmode"], blacklist_mode, pass_args=True, run_async=True
-)
-BLACKLIST_DEL_HANDLER = MessageHandler(
- (Filters.text | Filters.command | Filters.sticker | Filters.photo)
- & Filters.chat_type.groups,
- del_blacklist,
- allow_edit=True,
- run_async=True,
-)
-
-dispatcher.add_handler(BLACKLIST_HANDLER)
-dispatcher.add_handler(ADD_BLACKLIST_HANDLER)
-dispatcher.add_handler(UNBLACKLIST_HANDLER)
-dispatcher.add_handler(BLACKLISTMODE_HANDLER)
-dispatcher.add_handler(BLACKLIST_DEL_HANDLER, group=BLACKLIST_GROUP)
-
-__handlers__ = [
- BLACKLIST_HANDLER,
- ADD_BLACKLIST_HANDLER,
- UNBLACKLIST_HANDLER,
- BLACKLISTMODE_HANDLER,
- (BLACKLIST_DEL_HANDLER, BLACKLIST_GROUP),
-]
-
-# """
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-from Exon.modules.language import gs
-
-
-def blacklist_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "blacklist_help"),
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def sticker_blacklist_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "sticker_blacklist_help"),
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-@akboss(pattern=r"asusau_help_")
-def blacklist_help_bse(update: Update, context: CallbackContext):
- query = update.callback_query
- bot = context.bot
- help_info = query.data.split("asusau_help_")[1]
- if help_info == "wblack":
- help_text = gs(update.effective_chat.id, "blacklist_help")
- elif help_info == "sblack":
- help_text = gs(update.effective_chat.id, "sticker_blacklist_help")
- query.message.edit_text(
- text=help_text,
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ʙᴀᴄᴋ",
- callback_data=f"help_module({__mod_name__.lower()})",
- )
- ]
- ]
- ),
- )
- bot.answer_callback_query(query.id)
-
-
-__mod_name__ = "𝐁-ʟɪsᴛ️"
-
-
-def get_help(chat):
- return [
- gs(chat, "blacklist_help_bse"),
- [
- InlineKeyboardButton(
- text="ʙʟᴀᴄᴋʟɪsᴛ 👽", callback_data="asusau_help_wblack"
- ),
- InlineKeyboardButton(
- text="ʙ-sᴛɪᴄᴋᴇʀ 🦍", callback_data="asusau_help_sblack"
- ),
- ],
- ]
-
-# """
diff --git a/Exon/modules/blacklist_stickers.py b/Exon/modules/blacklist_stickers.py
deleted file mode 100644
index db1cd04e..00000000
--- a/Exon/modules/blacklist_stickers.py
+++ /dev/null
@@ -1,500 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import html
-
-from telegram import ChatPermissions, ParseMode, Update
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, CommandHandler, Filters, MessageHandler
-from telegram.utils.helpers import mention_html, mention_markdown
-
-import Exon.modules.sql.blsticker_sql as sql
-from Exon import LOGGER, dispatcher
-from Exon.modules.connection import connected
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.alternate import send_message
-from Exon.modules.helper_funcs.chat_status import user_admin, user_not_admin
-from Exon.modules.helper_funcs.misc import split_message
-from Exon.modules.helper_funcs.string_handling import extract_time
-from Exon.modules.log_channel import loggable
-from Exon.modules.sql.approve_sql import is_approved
-from Exon.modules.warns import warn
-
-
-def blackliststicker(update: Update, context: CallbackContext):
- msg = update.effective_message # type: Optional[Message]
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- bot, args = context.bot, context.args
- if conn := connected(bot, update, chat, user.id, need_admin=False):
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if chat.type == "private":
- return
- chat_id = update.effective_chat.id
- chat_name = chat.title
-
- sticker_list = f"ʟɪsᴛ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ sᴛɪᴄᴋᴇʀs ᴄᴜʀʀᴇɴᴛʟʏ ɪɴ {chat_name}:\n"
-
- all_stickerlist = sql.get_chat_stickers(chat_id)
-
- if len(args) > 0 and args[0].lower() == "copy":
- for trigger in all_stickerlist:
- sticker_list += f"{html.escape(trigger)}
\n"
- elif len(args) == 0:
- for trigger in all_stickerlist:
- sticker_list += f" - {html.escape(trigger)}
\n"
-
- split_text = split_message(sticker_list)
- for text in split_text:
- if (
- sticker_list
- == f"ʟɪsᴛ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ sᴛɪᴄᴋᴇʀs ᴄᴜʀʀᴇɴᴛʟʏ ɪɴ {chat_name}:\n".format(
- html.escape(chat_name)
- )
- ):
- send_message(
- update.effective_message,
- f"ᴛʜᴇʀᴇ ᴀʀᴇ ɴᴏ ʙʟᴀᴄᴋʟɪsᴛ sᴛɪᴄᴋᴇʀs ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- return
- send_message(update.effective_message, text, parse_mode=ParseMode.HTML)
-
-
-@user_admin
-def add_blackliststicker(update: Update, context: CallbackContext):
- bot = context.bot
- msg = update.effective_message # type: Optional[Message]
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- words = msg.text.split(None, 1)
- bot = context.bot
- if conn := connected(bot, update, chat, user.id):
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- chat_id = update.effective_chat.id
- if chat.type == "private":
- return
- chat_name = chat.title
-
- if len(words) > 1:
- text = words[1].replace("https://t.me/addstickers/", "")
- to_blacklist = list(
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()},
- )
-
- added = 0
- for trigger in to_blacklist:
- try:
- bot.getStickerSet(trigger)
- sql.add_to_stickers(chat_id, trigger.lower())
- added += 1
- except BadRequest:
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ `{trigger}` ᴄᴀɴ ɴᴏᴛ ʙᴇ ғᴏᴜɴᴅ!",
- parse_mode="markdown",
- )
-
- if added == 0:
- return
-
- if len(to_blacklist) == 1:
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ {html.escape(to_blacklist[0])}
ᴀᴅᴅᴇᴅ ᴛᴏ ʙʟᴀᴄᴋʟɪsᴛ sᴛɪᴄᴋᴇʀs ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_message(
- update.effective_message,
- f"{added}
sᴛɪᴄᴋᴇʀs ᴀᴅᴅᴇᴅ ᴛᴏ ʙʟᴀᴄᴋʟɪsᴛ sᴛɪᴄᴋᴇʀ ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- elif msg.reply_to_message:
- added = 0
- trigger = msg.reply_to_message.sticker.set_name
- if trigger is None:
- send_message(update.effective_message, "sᴛɪᴄᴋᴇʀ ɪs ɪɴᴠᴀʟɪᴅ!")
- return
- try:
- bot.getStickerSet(trigger)
- sql.add_to_stickers(chat_id, trigger.lower())
- added += 1
- except BadRequest:
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ `{trigger}` ᴄᴀɴ ɴᴏᴛ ʙᴇ ғᴏᴜɴᴅ!",
- parse_mode="markdown",
- )
-
- if added == 0:
- return
-
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ {trigger}
ᴀᴅᴅᴇᴅ ᴛᴏ ʙʟᴀᴄᴋʟɪsᴛ sᴛɪᴄᴋᴇʀs ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_message(
- update.effective_message,
- "ᴛᴇʟʟ ᴍᴇ ᴡʜᴀᴛ sᴛɪᴄᴋᴇʀs ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ᴀᴅᴅ ᴛᴏ ᴛʜᴇ ʙʟᴀᴄᴋʟɪsᴛ.",
- )
-
-
-@user_admin
-def unblackliststicker(update: Update, context: CallbackContext):
- bot = context.bot
- msg = update.effective_message # type: Optional[Message]
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- words = msg.text.split(None, 1)
- bot = context.bot
- if conn := connected(bot, update, chat, user.id):
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- chat_id = update.effective_chat.id
- if chat.type == "private":
- return
- chat_name = chat.title
-
- if len(words) > 1:
- text = words[1].replace("https://t.me/addstickers/", "")
- to_unblacklist = list(
- {trigger.strip() for trigger in text.split("\n") if trigger.strip()},
- )
-
- successful = 0
- for trigger in to_unblacklist:
- success = sql.rm_from_stickers(chat_id, trigger.lower())
- if success:
- successful += 1
-
- if len(to_unblacklist) == 1:
- if successful:
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ {html.escape(to_unblacklist[0])}
ᴅᴇʟᴇᴛᴇᴅ ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_message(
- update.effective_message,
- "ᴛʜɪs sᴛɪᴄᴋᴇʀ ɪs ɴᴏᴛ ᴏɴ ᴛʜᴇ ʙʟᴀᴄᴋʟɪsᴛ...!",
- )
-
- elif successful == len(to_unblacklist):
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ {successful}
ᴅᴇʟᴇᴛᴇᴅ ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ ɪɴ {html.escape(chat_name)}!",
- parse_mode=ParseMode.HTML,
- )
-
- elif not successful:
- send_message(
- update.effective_message,
- "ɴᴏɴᴇ ᴏғ ᴛʜᴇsᴇ sᴛɪᴄᴋᴇʀs ᴇxɪsᴛ, sᴏ ᴛʜᴇʏ ᴄᴀɴɴᴏᴛ ʙᴇ ʀᴇᴍᴏᴠᴇᴅ.",
- parse_mode=ParseMode.HTML,
- )
-
- else:
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ {successful}
ᴅᴇʟᴇᴛᴇᴅ ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ. {len(to_unblacklist) - successful} ᴅɪᴅ ɴᴏᴛ ᴇxɪsᴛ, sᴏ it's ɴᴏᴛ ᴅᴇʟᴇᴛᴇᴅ.",
- parse_mode=ParseMode.HTML,
- )
- elif msg.reply_to_message:
- trigger = msg.reply_to_message.sticker.set_name
- if trigger is None:
- send_message(update.effective_message, "sᴛɪᴄᴋᴇʀ ɪs ɪɴᴠᴀʟɪᴅ!")
- return
- if success := sql.rm_from_stickers(chat_id, trigger.lower()):
- send_message(
- update.effective_message,
- f"sᴛɪᴄᴋᴇʀ {trigger}
ᴅᴇʟᴇᴛᴇᴅ ғʀᴏᴍ ʙʟᴀᴄᴋʟɪsᴛ ɪɴ {chat_name}!",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_message(
- update.effective_message,
- f"{trigger} ɴᴏᴛ ғᴏᴜɴᴅ ᴏɴ ʙʟᴀᴄᴋʟɪsᴛᴇᴅ sᴛɪᴄᴋᴇʀs...!",
- )
- else:
- send_message(
- update.effective_message,
- "ᴛᴇʟʟ ᴍᴇ ᴡʜᴀᴛ sᴛɪᴄᴋᴇʀs ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ʀᴇᴍᴏᴠᴇ ғʀᴏᴍ ᴛʜᴇ ʙʟᴀᴄᴋʟɪsᴛ.",
- )
-
-
-@loggable
-@user_admin
-def blacklist_mode(update: Update, context: CallbackContext):
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user # type: Optional[User]
- msg = update.effective_message # type: Optional[Message]
- bot, args = context.bot, context.args
- conn = connected(bot, update, chat, user.id, need_admin=True)
- if conn:
- chat = dispatcher.bot.getChat(conn)
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type == "private":
- send_message(
- update.effective_message,
- "ʏᴏᴜ ᴄᴀɴ ᴅᴏ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ɪɴ ɢʀᴏᴜᴘs, ɴᴏᴛ PM",
- )
- return ""
- chat = update.effective_chat
- chat_id = update.effective_chat.id
- chat_name = update.effective_message.chat.title
-
- if args:
- if args[0].lower() in ["off", "nothing", "no"]:
- settypeblacklist = "ᴛᴜʀɴ ᴏғғ"
- sql.set_blacklist_strength(chat_id, 0, "0")
- elif args[0].lower() in ["del", "delete"]:
- settypeblacklist = "ʟᴇғᴛ, ᴛʜᴇ ᴍᴇssᴀɢᴇ ᴡɪʟʟ ʙᴇ ᴅᴇʟᴇᴛᴇᴅ"
- sql.set_blacklist_strength(chat_id, 1, "0")
- elif args[0].lower() == "warn":
- settypeblacklist = "ᴡᴀʀɴᴇᴅ"
- sql.set_blacklist_strength(chat_id, 2, "0")
- elif args[0].lower() == "mute":
- settypeblacklist = "ᴍᴜᴛᴇᴅ"
- sql.set_blacklist_strength(chat_id, 3, "0")
- elif args[0].lower() == "kick":
- settypeblacklist = "ᴋɪᴄᴋᴇᴅ"
- sql.set_blacklist_strength(chat_id, 4, "0")
- elif args[0].lower() == "ban":
- settypeblacklist = "ʙᴀɴɴᴇᴅ"
- sql.set_blacklist_strength(chat_id, 5, "0")
- elif args[0].lower() == "tban":
- if len(args) == 1:
- teks = """It ʟᴏᴏᴋs ʟɪᴋᴇ you ᴀʀᴇ trying ᴛᴏ sᴇᴛ ᴀ ᴛᴇᴍᴘᴏʀᴀʀʏ ᴠᴀʟᴜᴇ ᴛᴏ ʙʟᴀᴄᴋʟɪsᴛ, ʙᴜᴛ ʜᴀs ɴᴏᴛ ᴅᴇᴛᴇʀᴍɪɴᴇᴅ ᴛʜᴇ ᴛɪᴍᴇ; ᴜsᴇ `/blstickermode tban <ᴛɪᴍᴇᴠᴀʟᴜᴇ>`.
- ᴇxᴀᴍᴘʟᴇs of time values: 4m = 4 ᴍɪɴᴜᴛᴇ, 3h = 3 ʜᴏᴜʀs, 6d = 6 ᴅᴀʏs, 5w = 5 ᴡᴇᴇᴋs."""
- send_message(update.effective_message, teks, parse_mode="markdown")
- return
- settypeblacklist = f"ᴛᴇᴍᴘᴏʀᴀʀʏ ʙᴀɴɴᴇᴅ ғᴏʀ {args[1]}"
- sql.set_blacklist_strength(chat_id, 6, str(args[1]))
- elif args[0].lower() == "tmute":
- if len(args) == 1:
- teks = """It ʟᴏᴏᴋs ʟɪᴋᴇ ʏᴏᴜ ᴀʀᴇ ᴛʀʏɪɴɢ ᴛᴏ sᴇᴛ ᴀ ᴛᴇᴍᴘᴏʀᴀʀʏ ᴠᴀʟᴜᴇ ᴛᴏ ʙʟᴀᴄᴋʟɪsᴛ, ʙᴜᴛ ʜᴀs ʜᴀs ᴅᴇᴛᴇʀᴍɪɴᴇᴅ the ᴛɪᴍᴇ; ᴜsᴇ `/blstickermode tmute {reason}
"
- else:
- text = text.format("No")
-
- return text
-
-
-BL_HANDLER = CommandHandler("ignore", bl_user, run_async=True)
-UNBL_HANDLER = CommandHandler("notice", unbl_user, run_async=True)
-BLUSERS_HANDLER = CommandHandler("ignoredlist", bl_users, run_async=True)
-
-dispatcher.add_handler(BL_HANDLER)
-dispatcher.add_handler(UNBL_HANDLER)
-dispatcher.add_handler(BLUSERS_HANDLER)
-
-__mod_name__ = "𝐁-ᴜsᴇʀs"
-__handlers__ = [BL_HANDLER, UNBL_HANDLER, BLUSERS_HANDLER]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "buser_help")
-
-# """
diff --git a/Exon/modules/cleaner.py b/Exon/modules/cleaner.py
deleted file mode 100644
index 5ba2dd5d..00000000
--- a/Exon/modules/cleaner.py
+++ /dev/null
@@ -1,275 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import html
-
-from telegram import ParseMode, Update
-from telegram.ext import CallbackContext, CommandHandler, Filters, MessageHandler
-
-from Exon import ALLOW_EXCL, CustomCommandHandler, dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.chat_status import (
- bot_can_delete,
- connection_status,
- dev_plus,
- user_admin,
-)
-from Exon.modules.sql import cleaner_sql as sql
-
-CMD_STARTERS = ("/", "!") if ALLOW_EXCL else "/"
-BLUE_TEXT_CLEAN_GROUP = 13
-CommandHandlerList = (CommandHandler, CustomCommandHandler, DisableAbleCommandHandler)
-command_list = [
- "cleanblue",
- "ignoreblue",
- "unignoreblue",
- "listblue",
- "ungignoreblue",
- "gignoreblue",
- "start",
- "help",
- "settings",
- "donate",
- "stalk",
- "aka",
- "leaderboard",
-]
-
-for handler_list in dispatcher.handlers:
- for handler in dispatcher.handlers[handler_list]:
- if any(isinstance(handler, cmd_handler) for cmd_handler in CommandHandlerList):
- command_list += handler.command
-
-
-def clean_blue_text_must_click(update: Update, context: CallbackContext):
- bot = context.bot
- chat = update.effective_chat
- message = update.effective_message
- if chat.get_member(bot.id).can_delete_messages and sql.is_enabled(chat.id):
- fst_word = message.text.strip().split(None, 1)[0]
-
- if len(fst_word) > 1 and any(
- fst_word.startswith(start) for start in CMD_STARTERS
- ):
- command = fst_word[1:].split("@")
- chat = update.effective_chat
-
- if ignored := sql.is_command_ignored(chat.id, command[0]):
- return
-
- if command[0] not in command_list:
- message.delete()
-
-
-@connection_status
-@bot_can_delete
-@user_admin
-def set_blue_text_must_click(update: Update, context: CallbackContext):
- chat = update.effective_chat
- message = update.effective_message
- bot, args = context.bot, context.args
- if len(args) >= 1:
- val = args[0].lower()
- if val in ("off", "no"):
- sql.set_cleanbt(chat.id, False)
- reply = f"Bluetext cleaning has been disabled for {html.escape(chat.title)}"
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
- elif val in ("yes", "on"):
- sql.set_cleanbt(chat.id, True)
- reply = f"Bluetext cleaning has been enabled for {html.escape(chat.title)}"
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
- else:
- reply = "Invalid argument.Accepted values are 'yes', 'on', 'no', 'off'"
- message.reply_text(reply)
- else:
- clean_status = sql.is_enabled(chat.id)
- clean_status = "Enabled" if clean_status else "Disabled"
- reply = f"Bluetext cleaning for {html.escape(chat.title)} : {clean_status}"
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
-
-@user_admin
-def add_bluetext_ignore(update: Update, context: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
- args = context.args
- if len(args) >= 1:
- val = args[0].lower()
- if added := sql.chat_ignore_command(chat.id, val):
- reply = f"{args[0]} has been added to bluetext cleaner ignore list."
- else:
- reply = "Command is already ignored."
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
- else:
- reply = "No command supplied to be ignored."
- message.reply_text(reply)
-
-
-@user_admin
-def remove_bluetext_ignore(update: Update, context: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
- args = context.args
- if len(args) >= 1:
- val = args[0].lower()
- if removed := sql.chat_unignore_command(chat.id, val):
- reply = f"{args[0]} has been removed from bluetext cleaner ignore list."
- else:
- reply = "Command isn't ignored currently."
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
- else:
- reply = "No command supplied to be unignored."
- message.reply_text(reply)
-
-
-@user_admin
-def add_bluetext_ignore_global(update: Update, context: CallbackContext):
- message = update.effective_message
- args = context.args
- if len(args) >= 1:
- val = args[0].lower()
- if added := sql.global_ignore_command(val):
- reply = f"{args[0]} has been added to global bluetext cleaner ignore list."
- else:
- reply = "Command is already ignored."
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
- else:
- reply = "No command supplied to be ignored."
- message.reply_text(reply)
-
-
-@dev_plus
-def remove_bluetext_ignore_global(update: Update, context: CallbackContext):
- message = update.effective_message
- args = context.args
- if len(args) >= 1:
- val = args[0].lower()
- if removed := sql.global_unignore_command(val):
- reply = f"{args[0]} has been removed from global bluetext cleaner ignore list."
- else:
- reply = "Command isn't ignored currently."
- message.reply_text(reply, parse_mode=ParseMode.HTML)
-
- else:
- reply = "No command supplied to be unignored."
- message.reply_text(reply)
-
-
-@dev_plus
-def bluetext_ignore_list(update: Update, context: CallbackContext):
- message = update.effective_message
- chat = update.effective_chat
-
- global_ignored_list, local_ignore_list = sql.get_all_ignored(chat.id)
- text = ""
-
- if global_ignored_list:
- text = "The following commands are currently ignored globally from bluetext cleaning :\n"
-
- for x in global_ignored_list:
- text += f" - {x}
\n"
-
- if local_ignore_list:
- text += "\nThe following commands are currently ignored locally from bluetext cleaning :\n"
-
- for x in local_ignore_list:
- text += f" - {x}
\n"
-
- if text == "":
- text = "No commands are currently ignored from bluetext cleaning."
- message.reply_text(text)
- return
-
- message.reply_text(text, parse_mode=ParseMode.HTML)
- return
-
-
-SET_CLEAN_BLUE_TEXT_HANDLER = CommandHandler(
- "cleanblue", set_blue_text_must_click, run_async=True
-)
-ADD_CLEAN_BLUE_TEXT_HANDLER = CommandHandler(
- "ignoreblue", add_bluetext_ignore, run_async=True
-)
-REMOVE_CLEAN_BLUE_TEXT_HANDLER = CommandHandler(
- "unignoreblue", remove_bluetext_ignore, run_async=True
-)
-ADD_CLEAN_BLUE_TEXT_GLOBAL_HANDLER = CommandHandler(
- "gignoreblue",
- add_bluetext_ignore_global,
- run_async=True,
-)
-REMOVE_CLEAN_BLUE_TEXT_GLOBAL_HANDLER = CommandHandler(
- "ungignoreblue",
- remove_bluetext_ignore_global,
- run_async=True,
-)
-LIST_CLEAN_BLUE_TEXT_HANDLER = CommandHandler(
- "listblue", bluetext_ignore_list, run_async=True
-)
-CLEAN_BLUE_TEXT_HANDLER = MessageHandler(
- Filters.command & Filters.chat_type.groups,
- clean_blue_text_must_click,
- run_async=True,
-)
-
-dispatcher.add_handler(SET_CLEAN_BLUE_TEXT_HANDLER)
-dispatcher.add_handler(ADD_CLEAN_BLUE_TEXT_HANDLER)
-dispatcher.add_handler(REMOVE_CLEAN_BLUE_TEXT_HANDLER)
-dispatcher.add_handler(ADD_CLEAN_BLUE_TEXT_GLOBAL_HANDLER)
-dispatcher.add_handler(REMOVE_CLEAN_BLUE_TEXT_GLOBAL_HANDLER)
-dispatcher.add_handler(LIST_CLEAN_BLUE_TEXT_HANDLER)
-dispatcher.add_handler(CLEAN_BLUE_TEXT_HANDLER, BLUE_TEXT_CLEAN_GROUP)
-
-__mod_name__ = "𝐂ʟᴇᴀɴ"
-__handlers__ = [
- SET_CLEAN_BLUE_TEXT_HANDLER,
- ADD_CLEAN_BLUE_TEXT_HANDLER,
- REMOVE_CLEAN_BLUE_TEXT_HANDLER,
- ADD_CLEAN_BLUE_TEXT_GLOBAL_HANDLER,
- REMOVE_CLEAN_BLUE_TEXT_GLOBAL_HANDLER,
- LIST_CLEAN_BLUE_TEXT_HANDLER,
- (CLEAN_BLUE_TEXT_HANDLER, BLUE_TEXT_CLEAN_GROUP),
-]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "cleaner_help")
-
-# """
diff --git a/Exon/modules/connection.py b/Exon/modules/connection.py
deleted file mode 100644
index f9e6ba95..00000000
--- a/Exon/modules/connection.py
+++ /dev/null
@@ -1,444 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import re
-import time
-
-from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.error import BadRequest, Unauthorized
-from telegram.ext import CallbackQueryHandler, CommandHandler
-
-import Exon.modules.sql.connection_sql as sql
-from Exon import DEV_USERS, DRAGONS, dispatcher
-from Exon.modules.helper_funcs import chat_status
-from Exon.modules.helper_funcs.alternate import send_message, typing_action
-
-user_admin = chat_status.user_admin
-
-
-@user_admin
-@typing_action
-def allow_connections(update, context) -> str:
- chat = update.effective_chat
- args = context.args
-
- if chat.type == chat.PRIVATE:
- send_message(
- update.effective_message,
- "This command is for group only. Not in PM!",
- )
-
- elif len(args) >= 1:
- var = args[0]
- if var == "no":
- sql.set_allow_connect_to_chat(chat.id, False)
- send_message(
- update.effective_message,
- "Connection has been disabled for this chat",
- )
- elif var == "yes":
- sql.set_allow_connect_to_chat(chat.id, True)
- send_message(
- update.effective_message,
- "Connection has been enabled for this chat",
- )
- else:
- send_message(
- update.effective_message,
- "Please enter `yes` or `no`!",
- parse_mode=ParseMode.MARKDOWN,
- )
- elif get_settings := sql.allow_connect_to_chat(chat.id):
- send_message(
- update.effective_message,
- "Connections to this group are *Allowed* for members!",
- parse_mode=ParseMode.MARKDOWN,
- )
- else:
- send_message(
- update.effective_message,
- "Connection to this group are *Not Allowed* for members!",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-@typing_action
-def connection_chat(update, context):
- chat = update.effective_chat
- user = update.effective_user
-
- conn = connected(context.bot, update, chat, user.id, need_admin=True)
-
- if conn:
- chat = dispatcher.bot.getChat(conn)
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- if update.effective_message.chat.type != "private":
- return
- chat = update.effective_chat
- chat_name = update.effective_message.chat.title
-
- if conn:
- message = f"You are currently connected to {chat_name}.\n"
- else:
- message = "You are currently not connected in any group.\n"
- send_message(update.effective_message, message, parse_mode="markdown")
-
-
-@typing_action
-def connect_chat(update, context):
- chat = update.effective_chat
- user = update.effective_user
- if update.effective_chat.type == "private":
- args = context.args
-
- if args and len(args) >= 1:
- try:
- connect_chat = int(args[0])
- getstatusadmin = context.bot.get_chat_member(
- connect_chat,
- update.effective_message.from_user.id,
- )
- except ValueError:
- try:
- connect_chat = str(args[0])
- get_chat = context.bot.getChat(connect_chat)
- connect_chat = get_chat.id
- getstatusadmin = context.bot.get_chat_member(
- connect_chat,
- update.effective_message.from_user.id,
- )
- except BadRequest:
- send_message(update.effective_message, "Invalid Chat ID!")
- return
- except BadRequest:
- send_message(update.effective_message, "Invalid Chat ID!")
- return
-
- isadmin = getstatusadmin.status in ("administrator", "creator")
- ismember = getstatusadmin.status in ("member")
- isallow = sql.allow_connect_to_chat(connect_chat)
-
- if (isadmin) or (isallow and ismember) or (user.id in DRAGONS):
- if connection_status := sql.connect(
- update.effective_message.from_user.id,
- connect_chat,
- ):
- conn_chat = dispatcher.bot.getChat(
- connected(context.bot, update, chat, user.id, need_admin=False),
- )
- chat_name = conn_chat.title
- send_message(
- update.effective_message,
- f"Successfully connected to *{chat_name}*. \nUse /helpconnect to check available commands.",
- parse_mode=ParseMode.MARKDOWN,
- )
- sql.add_history_conn(user.id, str(conn_chat.id), chat_name)
- else:
- send_message(update.effective_message, "Connection failed!")
- else:
- send_message(
- update.effective_message,
- "Connection to this chat is not allowed!",
- )
- else:
- gethistory = sql.get_history_conn(user.id)
- if gethistory:
- buttons = [
- InlineKeyboardButton(
- text="❎ Close button",
- callback_data="connect_close",
- ),
- InlineKeyboardButton(
- text="🧹 Clear history",
- callback_data="connect_clear",
- ),
- ]
- else:
- buttons = []
- if conn := connected(
- context.bot, update, chat, user.id, need_admin=False
- ):
- connectedchat = dispatcher.bot.getChat(conn)
- text = f"You are currently connected to *{connectedchat.title}* (`{conn}`)"
- buttons.append(
- InlineKeyboardButton(
- text="🔌 Disconnect",
- callback_data="connect_disconnect",
- ),
- )
- else:
- text = "Write the chat ID or tag to connect!"
- if gethistory:
- text += "\n\n*Connection history:*\n"
- text += "╒═══「 *Info* 」\n"
- text += "│ Sorted: `Newest`\n"
- text += "│\n"
- buttons = [buttons]
- for x in sorted(gethistory.keys(), reverse=True):
- htime = time.strftime("%d/%m/%Y", time.localtime(x))
- text += f'╞═「 *{gethistory[x]["chat_name"]}* 」\n│ `{gethistory[x]["chat_id"]}`\n│ `{htime}`\n'
- text += "│\n"
- buttons.append(
- [
- InlineKeyboardButton(
- text=gethistory[x]["chat_name"],
- callback_data=f'connect({gethistory[x]["chat_id"]})',
- )
- ]
- )
- text += f'╘══「 Total {f"{len(gethistory)} (max)" if len(gethistory) == 5 else str(len(gethistory))} Chats 」'
- conn_hist = InlineKeyboardMarkup(buttons)
- elif buttons:
- conn_hist = InlineKeyboardMarkup([buttons])
- else:
- conn_hist = None
- send_message(
- update.effective_message,
- text,
- parse_mode="markdown",
- reply_markup=conn_hist,
- )
-
- else:
- getstatusadmin = context.bot.get_chat_member(
- chat.id,
- update.effective_message.from_user.id,
- )
- isadmin = getstatusadmin.status in ("administrator", "creator")
- ismember = getstatusadmin.status in ("member")
- isallow = sql.allow_connect_to_chat(chat.id)
- if (isadmin) or (isallow and ismember) or (user.id in DRAGONS):
- if connection_status := sql.connect(
- update.effective_message.from_user.id,
- chat.id,
- ):
- chat_name = dispatcher.bot.getChat(chat.id).title
- send_message(
- update.effective_message,
- f"Successfully connected to *{chat_name}*.",
- parse_mode=ParseMode.MARKDOWN,
- )
- try:
- sql.add_history_conn(user.id, str(chat.id), chat_name)
- context.bot.send_message(
- update.effective_message.from_user.id,
- f"You are connected to *{chat_name}*. \nUse `/helpconnect` to check available commands.",
- parse_mode="markdown",
- )
- except (BadRequest, Unauthorized):
- pass
- else:
- send_message(update.effective_message, "Connection failed!")
- else:
- send_message(
- update.effective_message,
- "Connection to this chat is not allowed!",
- )
-
-
-def disconnect_chat(update, context):
- if update.effective_chat.type == "private":
- if disconnection_status := sql.disconnect(
- update.effective_message.from_user.id
- ):
- sql.disconnected_chat = send_message(
- update.effective_message,
- "Disconnected from chat!",
- )
- else:
- send_message(update.effective_message, "You're not connected!")
- else:
- send_message(update.effective_message, "This command is only available in PM.")
-
-
-def connected(bot: Bot, update: Update, chat, user_id, need_admin=True):
- user = update.effective_user
-
- if chat.type == chat.PRIVATE and sql.get_connected_chat(user_id):
- conn_id = sql.get_connected_chat(user_id).chat_id
- getstatusadmin = bot.get_chat_member(
- conn_id,
- update.effective_message.from_user.id,
- )
- isadmin = getstatusadmin.status in ("administrator", "creator")
- ismember = getstatusadmin.status in ("member")
- isallow = sql.allow_connect_to_chat(conn_id)
-
- if (
- (isadmin)
- or (isallow and ismember)
- or (user.id in DRAGONS)
- or (user.id in DEV_USERS)
- ):
- if need_admin is not True:
- return conn_id
- if (
- getstatusadmin.status in ("administrator", "creator")
- or user_id in DRAGONS
- or user.id in DEV_USERS
- ):
- return conn_id
- send_message(
- update.effective_message,
- "You must be an admin in the connected group!",
- )
- else:
- send_message(
- update.effective_message,
- "The group changed the connection rights or you are no longer an admin.\nI've disconnected you.",
- )
- disconnect_chat(update, bot)
- else:
- return False
-
-
-CONN_HELP = """
-Actions which are available with connected groups:-
-*User Actions:*
-• View Notes
-• View Filters
-• View Blacklist
-• View AntiFlood settings
-• View Disabled Commands
-• Many More in future!
-*Admin Actions:*
- • View and edit Notes
- • View and edit Filters.
- • Get invite link of chat.
- • Set and control AntiFlood settings.
- • Set and control Blacklist settings.
- • Set Locks and Unlocks in chat.
- • Enable and Disable commands in chat.
- • Export and Imports of chat backup.
-
-"""
-
-
-def help_connect_chat(update, context):
- context.args
-
- if update.effective_message.chat.type != "private":
- send_message(update.effective_message, "PM me with that command to get help.")
- return
- send_message(update.effective_message, CONN_HELP, parse_mode="markdown")
-
-
-def connect_button(update, context):
- query = update.callback_query
- chat = update.effective_chat
- user = update.effective_user
-
- connect_match = re.match(r"connect\((.+?)\)", query.data)
- disconnect_match = query.data == "connect_disconnect"
- clear_match = query.data == "connect_clear"
- connect_close = query.data == "connect_close"
-
- if connect_match:
- target_chat = connect_match[1]
- getstatusadmin = context.bot.get_chat_member(target_chat, query.from_user.id)
- isadmin = getstatusadmin.status in ("administrator", "creator")
- ismember = getstatusadmin.status in ("member")
- isallow = sql.allow_connect_to_chat(target_chat)
-
- if (isadmin) or (isallow and ismember) or (user.id in DRAGONS):
- if connection_status := sql.connect(
- query.from_user.id, target_chat
- ):
- conn_chat = dispatcher.bot.getChat(
- connected(context.bot, update, chat, user.id, need_admin=False),
- )
- chat_name = conn_chat.title
- query.message.edit_text(
- f"Successfully connected to *{chat_name}*. \nUse `/helpconnect` to check available commands.",
- parse_mode=ParseMode.MARKDOWN,
- )
- sql.add_history_conn(user.id, str(conn_chat.id), chat_name)
- else:
- query.message.edit_text("Connection failed!")
- else:
- context.bot.answer_callback_query(
- query.id,
- "Connection to this chat is not allowed!",
- show_alert=True,
- )
- elif disconnect_match:
- if disconnection_status := sql.disconnect(query.from_user.id):
- sql.disconnected_chat = query.message.edit_text("Disconnected from chat!")
- else:
- context.bot.answer_callback_query(
- query.id,
- "You're not connected!",
- show_alert=True,
- )
- elif clear_match:
- sql.clear_history_conn(query.from_user.id)
- query.message.edit_text("History connected has been cleared!")
- elif connect_close:
- query.message.edit_text("Closed.\nTo open again, type /connect")
- else:
- connect_chat(update, context)
-
-
-__mod_name__ = "𝐂ᴏɴɴᴇᴄᴛ"
-
-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(
- "allowconnect", allow_connections, pass_args=True, run_async=True
-)
-HELP_CONNECT_CHAT_HANDLER = CommandHandler(
- "helpconnect", help_connect_chat, run_async=True
-)
-CONNECT_BTN_HANDLER = CallbackQueryHandler(
- connect_button, pattern=r"connect", run_async=True
-)
-
-dispatcher.add_handler(CONNECT_CHAT_HANDLER)
-dispatcher.add_handler(CONNECTION_CHAT_HANDLER)
-dispatcher.add_handler(DISCONNECT_CHAT_HANDLER)
-dispatcher.add_handler(ALLOW_CONNECTIONS_HANDLER)
-dispatcher.add_handler(HELP_CONNECT_CHAT_HANDLER)
-dispatcher.add_handler(CONNECT_BTN_HANDLER)
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "connections_help")
-
-# """
diff --git a/Exon/modules/cron_jobs.py b/Exon/modules/cron_jobs.py
deleted file mode 100644
index 0f48a4ab..00000000
--- a/Exon/modules/cron_jobs.py
+++ /dev/null
@@ -1,138 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-import datetime
-import os
-import shutil
-import subprocess
-from time import sleep
-
-from telegram.ext.callbackcontext import CallbackContext
-from telegram.ext.filters import Filters
-from telegram.update import Update
-
-from Exon import BACKUP_PASS, DB_URL, DEV_USERS, LOGGER, OWNER_ID, dispatcher
-from Exon.modules.helper_funcs.decorators import Exoncmd
-
-
-@Exoncmd(command="backupdb", filters=Filters.user(DEV_USERS) | Filters.user(OWNER_ID))
-def backup_now(_: Update, ctx: CallbackContext):
- cronjob.run(dispatcher=dispatcher)
-
-
-@Exoncmd(command="stopjobs", filters=Filters.user(DEV_USERS) | Filters.user(OWNER_ID))
-def stop_jobs(update: Update, _: CallbackContext):
- print(j.stop())
- update.effective_message.reply_text("Scheduler has been shut down")
-
-
-@Exoncmd(command="startjobs", filters=Filters.user(DEV_USERS) | Filters.user(OWNER_ID))
-def start_jobs(update: Update, _: CallbackContext):
- print(j.start())
- update.effective_message.reply_text("Scheduler started")
-
-
-zip_pass = BACKUP_PASS
-
-
-def backup_db(_: CallbackContext):
- bot = dispatcher.bot
- tmpmsg = "Performing backup, Please wait..."
- tmp = bot.send_message(OWNER_ID, tmpmsg)
- datenow = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
- dbbkpname = f"db_{bot.username}_{datenow}.tar"
- bkplocation = f"backups/{datenow}"
- bkpcmd = f"pg_dump {DB_URL} --format=tar > {bkplocation}/{dbbkpname}"
-
- if not os.path.exists(bkplocation):
- os.makedirs(bkplocation)
- LOGGER.info("Performing db backup")
- loginfo = "db backup"
- term(bkpcmd, loginfo)
- if not os.path.exists(f"{bkplocation}/{dbbkpname}"):
- bot.send_message(OWNER_ID, "An error occurred during the db backup")
- tmp.edit_text("Backup Failed!")
- sleep(8)
- tmp.delete()
- return
- else:
- LOGGER.info("Copying config, and logs to backup location")
- if os.path.exists("logs.txt"):
- print("Logs copied")
- shutil.copyfile("logs.txt", f"{bkplocation}/logs.txt")
- if os.path.exists("config.ini"):
- print("Config copied")
- shutil.copyfile("config.ini", f"{bkplocation}/config.ini")
- LOGGER.info("Zipping the backup")
- zipcmd = f"zip --password '{zip_pass}' {bkplocation} {bkplocation}/*"
- zipinfo = "zipping db backup"
- LOGGER.info("Zip initiated")
- term(zipcmd, zipinfo)
- LOGGER.info("Zip done")
- sleep(1)
- with open(f"backups/{datenow}.zip", "rb") as bkp:
- nm = f"{bot.username} backup \n{datenow}"
- bot.send_document(OWNER_ID, document=bkp, caption=nm, timeout=20)
- LOGGER.info("Removing zipped files")
- shutil.rmtree(f"backups/{datenow}")
- LOGGER.info("Backup done")
- tmp.edit_text("Backup complete!")
- sleep(5)
- tmp.delete()
-
-
-@Exoncmd(
- command="purgebackups", filters=Filters.user(DEV_USERS) | Filters.user(OWNER_ID)
-)
-def del_bkp_fldr(update: Update, _: CallbackContext):
- shutil.rmtree("backups")
- update.effective_message.reply_text("'Backups' directory has been purged!")
-
-
-def term(cmd, info):
- process = subprocess.Popen(
- cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
- )
- stdout, stderr = process.communicate()
- stderr = stderr.decode()
- if stdout := stdout.decode():
- LOGGER.info(f"{info} successful!")
- LOGGER.info(f"{stdout}")
- if stderr:
- LOGGER.error(f"error while running {info}")
- LOGGER.info(f"{stderr}")
-
-
-from Exon import updater as u
-
-# run the backup daily at 1:00
-twhen = datetime.datetime.strptime("01:00", "%H:%M").time()
-j = u.job_queue
-cronjob = j.run_daily(callback=backup_db, name="database backups", time=twhen)
diff --git a/Exon/modules/cust_filters.py b/Exon/modules/cust_filters.py
deleted file mode 100644
index e443f1b9..00000000
--- a/Exon/modules/cust_filters.py
+++ /dev/null
@@ -1,654 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import random
-import re
-from html import escape
-
-import telegram
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
-from telegram.error import BadRequest
-from telegram.ext import (
- CallbackQueryHandler,
- DispatcherHandlerStop,
- Filters,
- MessageHandler,
-)
-from telegram.utils.helpers import escape_markdown, mention_html
-
-from Exon import DRAGONS, LOGGER, dispatcher
-from Exon.modules.connection import connected
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.alternate import send_message, typing_action
-from Exon.modules.helper_funcs.chat_status import user_admin
-from Exon.modules.helper_funcs.extraction import extract_text
-from Exon.modules.helper_funcs.filters import CustomFilters
-from Exon.modules.helper_funcs.handlers import MessageHandlerChecker
-from Exon.modules.helper_funcs.misc import build_keyboard_parser
-from Exon.modules.helper_funcs.msg_types import get_filter_type
-from Exon.modules.helper_funcs.string_handling import (
- button_markdown_parser,
- escape_invalid_curly_brackets,
- markdown_to_html,
- split_quotes,
-)
-from Exon.modules.sql import cust_filters_sql as sql
-
-HANDLER_GROUP = 10
-
-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,
- # sql.Types.VIDEO_NOTE.value: dispatcher.bot.send_video_note
-}
-
-
-@typing_action
-def list_handlers(update, context):
- chat = update.effective_chat
- user = update.effective_user
-
- conn = connected(context.bot, update, chat, user.id, need_admin=False)
- if conn is not False:
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- filter_list = "*Filter in {}:*\n"
- else:
- chat_id = update.effective_chat.id
- if chat.type == "private":
- chat_name = "Local filters"
- filter_list = "*local filters:*\n"
- else:
- chat_name = chat.title
- filter_list = "*Filters in {}*:\n"
-
- all_handlers = sql.get_chat_triggers(chat_id)
-
- if not all_handlers:
- send_message(update.effective_message, f"No filters saved in {chat_name}!")
- return
-
- for keyword in all_handlers:
- entry = f" × `{escape_markdown(keyword)}`\n"
- if len(entry) + len(filter_list) > telegram.MAX_MESSAGE_LENGTH:
- send_message(
- update.effective_message,
- filter_list.format(chat_name),
- parse_mode=telegram.ParseMode.MARKDOWN,
- )
- filter_list = entry
- else:
- filter_list += entry
-
- send_message(
- update.effective_message,
- filter_list.format(chat_name),
- parse_mode=telegram.ParseMode.MARKDOWN,
- )
-
-
-# NOT ASYNC BECAUSE DISPATCHER HANDLER RAISED
-@user_admin
-@typing_action
-def filters(update, context):
- chat = update.effective_chat
- user = update.effective_user
- msg = update.effective_message
- args = msg.text.split(
- None, 1
- ) # use python's maxsplit to separate Cmd, keyword, and reply_text
-
- conn = connected(context.bot, update, chat, user.id)
- if conn is not False:
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- chat_id = update.effective_chat.id
- chat_name = "local filters" if chat.type == "private" else chat.title
- if not msg.reply_to_message and len(args) < 2:
- send_message(
- update.effective_message,
- "Please provide keyboard keyword for this filter to reply with!",
- )
- return
-
- if msg.reply_to_message:
- if len(args) < 2:
- send_message(
- update.effective_message,
- "Please provide keyword for this filter to reply with!",
- )
- return
- keyword = args[1]
- else:
- extracted = split_quotes(args[1])
- if len(extracted) < 1:
- return
- # set trigger -> lower, so as to avoid adding duplicate filters with different cases
- keyword = extracted[0].lower()
-
- # Add the filter
- # Note: perhaps handlers can be removed somehow using sql.get_chat_filters
- for handler in dispatcher.handlers.get(HANDLER_GROUP, []):
- if handler.filters == (keyword, chat_id):
- dispatcher.remove_handler(handler, HANDLER_GROUP)
-
- text, file_type, file_id = get_filter_type(msg)
- if not msg.reply_to_message and len(extracted) >= 2:
- offset = len(extracted[1]) - len(
- msg.text
- ) # set correct offset relative to command + notename
- text, buttons = button_markdown_parser(
- extracted[1], entities=msg.parse_entities(), offset=offset
- )
- text = text.strip()
- if not text:
- send_message(
- update.effective_message,
- "There is no note message - You can't JUST have buttons, you need a message to go with it!",
- )
- return
-
- elif msg.reply_to_message and len(args) >= 2:
- if msg.reply_to_message.text:
- text_to_parsing = msg.reply_to_message.text
- elif msg.reply_to_message.caption:
- text_to_parsing = msg.reply_to_message.caption
- else:
- text_to_parsing = ""
- offset = len(
- text_to_parsing
- ) # set correct offset relative to command + notename
- text, buttons = button_markdown_parser(
- text_to_parsing, entities=msg.parse_entities(), offset=offset
- )
- text = text.strip()
-
- elif not text and not file_type:
- send_message(
- update.effective_message,
- "Please provide keyword for this filter reply with!",
- )
- return
-
- elif msg.reply_to_message:
- if msg.reply_to_message.text:
- text_to_parsing = msg.reply_to_message.text
- elif msg.reply_to_message.caption:
- text_to_parsing = msg.reply_to_message.caption
- else:
- text_to_parsing = ""
- offset = len(
- text_to_parsing
- ) # set correct offset relative to command + notename
- text, buttons = button_markdown_parser(
- text_to_parsing, entities=msg.parse_entities(), offset=offset
- )
- text = text.strip()
- if (msg.reply_to_message.text or msg.reply_to_message.caption) and not text:
- send_message(
- update.effective_message,
- "There is no note message - You can't JUST have buttons, you need a message to go with it!",
- )
- return
-
- else:
- send_message(update.effective_message, "Invalid filter!")
- return
-
- add = addnew_filter(update, chat_id, keyword, text, file_type, file_id, buttons)
- # This is an old method
- # sql.add_filter(chat_id, keyword, content, is_sticker, is_document, is_image, is_audio, is_voice, is_video, buttons)
-
- if add is True:
- send_message(
- update.effective_message,
- f"Saved filter '{keyword}' in *{chat_name}*!",
- parse_mode=telegram.ParseMode.MARKDOWN,
- )
- raise DispatcherHandlerStop
-
-
-# NOT ASYNC BECAUSE DISPATCHER HANDLER RAISED
-@user_admin
-@typing_action
-def stop_filter(update, context):
- chat = update.effective_chat
- user = update.effective_user
- args = update.effective_message.text.split(None, 1)
-
- conn = connected(context.bot, update, chat, user.id)
- if conn is not False:
- chat_id = conn
- chat_name = dispatcher.bot.getChat(conn).title
- else:
- chat_id = update.effective_chat.id
- chat_name = "Local filters" if chat.type == "private" else chat.title
- if len(args) < 2:
- send_message(update.effective_message, "What should i stop?")
- return
-
- chat_filters = sql.get_chat_triggers(chat_id)
-
- if not chat_filters:
- send_message(update.effective_message, "No filters active here!")
- return
-
- for keyword in chat_filters:
- if keyword == args[1]:
- sql.remove_filter(chat_id, args[1])
- send_message(
- update.effective_message,
- f"Okay, I'll stop replying to that filter in *{chat_name}*.",
- parse_mode=telegram.ParseMode.MARKDOWN,
- )
- raise DispatcherHandlerStop
-
- send_message(
- update.effective_message,
- "That's not a filter - Click: /filters to get currently active filters.",
- )
-
-
-def reply_filter(update, context):
- chat = update.effective_chat # type: Optional[Chat]
- message = update.effective_message # type: Optional[Message]
-
- if not update.effective_user or update.effective_user.id == 777000:
- return
- to_match = extract_text(message)
- if not to_match:
- return
-
- chat_filters = sql.get_chat_triggers(chat.id)
- for keyword in chat_filters:
- pattern = r"( |^|[^\w])" + re.escape(keyword) + r"( |$|[^\w])"
- if re.search(pattern, to_match, flags=re.IGNORECASE):
- if MessageHandlerChecker.check_user(update.effective_user.id):
- return
- filt = sql.get_filter(chat.id, keyword)
- if filt.reply == "there is should be a new reply":
- buttons = sql.get_buttons(chat.id, filt.keyword)
- keyb = build_keyboard_parser(context.bot, chat.id, buttons)
- keyboard = InlineKeyboardMarkup(keyb)
-
- VALID_WELCOME_FORMATTERS = [
- "first",
- "last",
- "fullname",
- "username",
- "id",
- "chatname",
- "mention",
- ]
- if filt.reply_text:
- if "%%%" in filt.reply_text:
- split = filt.reply_text.split("%%%")
- text = random.choice(split) if all(split) else filt.reply_text
- else:
- text = filt.reply_text
- if text.startswith("~!") and text.endswith("!~"):
- sticker_id = text.replace("~!", "").replace("!~", "")
- try:
- context.bot.send_sticker(
- chat.id,
- sticker_id,
- reply_to_message_id=message.message_id,
- )
- return
- except BadRequest as excp:
- if (
- excp.message
- == "Wrong remote file identifier specified: wrong padding in the string"
- ):
- context.bot.send_message(
- chat.id,
- "Message couldn't be sent, Is the sticker id valid?",
- )
- return
- LOGGER.exception(f"Error in filters: {excp.message}")
- return
- if valid_format := escape_invalid_curly_brackets(
- text, VALID_WELCOME_FORMATTERS
- ):
- filtext = valid_format.format(
- first=escape(message.from_user.first_name),
- last=escape(
- message.from_user.last_name
- or message.from_user.first_name
- ),
- fullname=" ".join(
- [
- escape(message.from_user.first_name),
- escape(message.from_user.last_name),
- ]
- if message.from_user.last_name
- else [escape(message.from_user.first_name)]
- ),
- username=f"@{escape(message.from_user.username)}"
- if message.from_user.username
- else mention_html(
- message.from_user.id,
- message.from_user.first_name,
- ),
- mention=mention_html(
- message.from_user.id,
- message.from_user.first_name,
- ),
- chatname=escape(message.chat.title)
- if message.chat.type != "private"
- else escape(message.from_user.first_name),
- id=message.from_user.id,
- )
- else:
- filtext = ""
- else:
- filtext = ""
-
- if filt.file_type in (sql.Types.BUTTON_TEXT, sql.Types.TEXT):
- try:
- context.bot.send_message(
- chat.id,
- markdown_to_html(filtext),
- reply_to_message_id=message.message_id,
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- reply_markup=keyboard,
- )
- except BadRequest as excp:
- error_catch = get_exception(excp, filt, chat)
- if error_catch == "noreply":
- try:
- context.bot.send_message(
- chat.id,
- markdown_to_html(filtext),
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- reply_markup=keyboard,
- )
- except BadRequest as excp:
- LOGGER.exception(f"Error in filters: {excp.message}")
- send_message(
- update.effective_message,
- get_exception(excp, filt, chat),
- )
- else:
- try:
- send_message(
- update.effective_message,
- get_exception(excp, filt, chat),
- )
- except BadRequest as excp:
- LOGGER.exception(f"Failed to send message: {excp.message}")
- elif ENUM_FUNC_MAP[filt.file_type] == dispatcher.bot.send_sticker:
- ENUM_FUNC_MAP[filt.file_type](
- chat.id,
- filt.file_id,
- reply_to_message_id=message.message_id,
- reply_markup=keyboard,
- )
- else:
- ENUM_FUNC_MAP[filt.file_type](
- chat.id,
- filt.file_id,
- caption=markdown_to_html(filtext),
- reply_to_message_id=message.message_id,
- parse_mode=ParseMode.HTML,
- reply_markup=keyboard,
- )
- break
- if filt.is_sticker:
- message.reply_sticker(filt.reply)
- elif filt.is_document:
- message.reply_document(filt.reply)
- elif filt.is_image:
- message.reply_photo(filt.reply)
- elif filt.is_audio:
- message.reply_audio(filt.reply)
- elif filt.is_voice:
- message.reply_voice(filt.reply)
- elif filt.is_video:
- message.reply_video(filt.reply)
- elif filt.has_markdown:
- buttons = sql.get_buttons(chat.id, filt.keyword)
- keyb = build_keyboard_parser(context.bot, chat.id, buttons)
- keyboard = InlineKeyboardMarkup(keyb)
-
- try:
- send_message(
- update.effective_message,
- filt.reply,
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- reply_markup=keyboard,
- )
- except BadRequest as excp:
- if excp.message == "Unsupported url protocol":
- try:
- send_message(
- update.effective_message,
- "You seem to be trying to use an url protocol"
- "Telegram doesn't support buttons such as tg://, Please try again",
- )
- except BadRequest as excp:
- LOGGER.exception(f"Error in filters: {excp.message}")
- elif excp.message == "Reply message not found":
- try:
- context.bot.send_message(
- chat.id,
- filt.reply,
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- reply_markup=keyboard,
- )
- except BadRequest as excp:
- LOGGER.exception(f"Error in filters: {excp.message}")
- else:
- try:
- send_message(
- update.effective_message,
- "This message couldn't be sent because incorrectly formatted.",
- )
- except BadRequest as excp:
- LOGGER.exception(f"Error in filters: {excp.message}")
- LOGGER.warning(
- "Message %s could not be parsed", str(filt.reply)
- )
- LOGGER.exception(
- "Could not parse filter %s in chat %s",
- str(filt.keyword),
- str(chat.id),
- )
-
- else:
- # LEGACY - all new filters will have has_markdown set to True.
- try:
- send_message(update.effective_message, filt.reply)
- except BadRequest as excp:
- LOGGER.exception(f"Error in filters: {excp.message}")
- break
-
-
-def rmall_filters(update, context):
- chat = update.effective_chat
- user = update.effective_user
- member = chat.get_member(user.id)
- if member.status != "creator" and user.id not in DRAGONS:
- update.effective_message.reply_text(
- "Only the chat owner can clear all notes at once."
- )
- else:
- buttons = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="Stop all filters", callback_data="filters_rmall"
- )
- ],
- [InlineKeyboardButton(text="Cancel", callback_data="filters_cancel")],
- ]
- )
- update.effective_message.reply_text(
- f"Are you sure you would like to stop ALL filters in {chat.title}? This action cannot be undone.",
- reply_markup=buttons,
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def rmall_callback(update, context):
- query = update.callback_query
- chat = update.effective_chat
- msg = update.effective_message
- member = chat.get_member(query.from_user.id)
- if query.data == "filters_rmall":
- if member.status == "creator" or query.from_user.id in DRAGONS:
- allfilters = sql.get_chat_triggers(chat.id)
- if not allfilters:
- msg.edit_text("No filters in this chat, nothing to stop!")
- return
-
- count = 0
- filterlist = []
- for x in allfilters:
- count += 1
- filterlist.append(x)
-
- for i in filterlist:
- sql.remove_filter(chat.id, i)
-
- msg.edit_text(f"Cleaned {count} filters in {chat.title}")
-
- if member.status == "administrator":
- query.answer("Only owner of the chat can do this.")
-
- if member.status == "member":
- query.answer("You need to be admin to do this.")
- elif query.data == "filters_cancel":
- if member.status == "creator" or query.from_user.id in DRAGONS:
- msg.edit_text("Clearing of all filters has been cancelled.")
- return
- if member.status == "administrator":
- query.answer("Only owner of the chat can do this.")
- if member.status == "member":
- query.answer("You need to be admin to do this.")
-
-
-# NOT ASYNC NOT A HANDLER
-def get_exception(excp, filt, chat):
- if excp.message == "Unsupported url protocol":
- return "You seem to be trying to use URL protocol which not supported.\nTelegram does not support key protocols, such as tg: //. Please try again!"
- if excp.message == "Reply message not found":
- return "noreply"
- LOGGER.warning("Message %s could not be parsed", str(filt.reply))
- LOGGER.exception(
- "Could not parse filter %s in chat %s", str(filt.keyword), str(chat.id)
- )
- return "This data could not be sent because it is incorrectly formatted."
-
-
-# NOT ASYNC NOT A HANDLER
-def addnew_filter(update, chat_id, keyword, text, file_type, file_id, buttons):
- msg = update.effective_message
- totalfilt = sql.get_chat_triggers(chat_id)
- if len(totalfilt) >= 150: # Idk why i made this like function....
- msg.reply_text("This group has reached its max filters limit of 150.")
- return False
- sql.new_add_filter(chat_id, keyword, text, file_type, file_id, buttons)
- return True
-
-
-def __stats__():
- return f"× {sql.num_filters()} filters, across {sql.num_chats()} chats."
-
-
-def __import_data__(chat_id, data):
- # set chat filters
- filters = data.get("filters", {})
- for trigger in filters:
- sql.add_to_blacklist(chat_id, trigger)
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- cust_filters = sql.get_chat_triggers(chat_id)
- return f"There are `{len(cust_filters)}` custom filters here."
-
-
-__mod_name__ = "𝐅ɪʟᴛᴇʀs"
-
-FILTER_HANDLER = DisableAbleCommandHandler("filter", filters, run_async=True)
-STOP_HANDLER = DisableAbleCommandHandler("stop", stop_filter, run_async=True)
-RMALLFILTER_HANDLER = DisableAbleCommandHandler(
- "removeallfilters", rmall_filters, filters=Filters.chat_type.groups, run_async=True
-)
-RMALLFILTER_CALLBACK = CallbackQueryHandler(
- rmall_callback, pattern=r"filters_.*", run_async=True
-)
-LIST_HANDLER = DisableAbleCommandHandler(
- "filters", list_handlers, admin_ok=True, run_async=True
-)
-CUST_FILTER_HANDLER = MessageHandler(
- CustomFilters.has_text & ~Filters.update.edited_message,
- reply_filter,
- run_async=True,
-)
-
-dispatcher.add_handler(FILTER_HANDLER)
-dispatcher.add_handler(STOP_HANDLER)
-dispatcher.add_handler(LIST_HANDLER)
-dispatcher.add_handler(CUST_FILTER_HANDLER, HANDLER_GROUP)
-dispatcher.add_handler(RMALLFILTER_HANDLER)
-dispatcher.add_handler(RMALLFILTER_CALLBACK)
-
-__handlers__ = [
- FILTER_HANDLER,
- STOP_HANDLER,
- LIST_HANDLER,
- (CUST_FILTER_HANDLER, HANDLER_GROUP, RMALLFILTER_HANDLER),
-]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "cust_filters_help")
-
-# """
diff --git a/Exon/modules/dbcleanup.py b/Exon/modules/dbcleanup.py
deleted file mode 100644
index c69062a4..00000000
--- a/Exon/modules/dbcleanup.py
+++ /dev/null
@@ -1,247 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-from time import sleep
-
-from telegram import Bot, InlineKeyboardButton, InlineKeyboardMarkup, Update
-from telegram.error import BadRequest, Unauthorized
-from telegram.ext import CallbackQueryHandler, CommandHandler
-
-from Exon import DEV_USERS, dispatcher
-from Exon.modules.helper_funcs.filters import CustomFilters
-from Exon.modules.no_sql import global_bans_db as gban_db
-from Exon.modules.no_sql import users_db as user_db
-
-
-def get_invalid_chats(bot: Bot, update: Update, remove: bool = False):
- chat_id = update.effective_chat.id
- chats = user_db.get_all_chats()
- kicked_chats, progress = 0, 0
- chat_list = []
- progress_message = None
-
- for chat in chats:
- if ((100 * chats.index(chat)) / len(chats)) > progress:
- progress_bar = f"{progress}% completed in getting invalid chats."
- if progress_message:
- try:
- bot.editMessageText(
- progress_bar, chat_id, progress_message.message_id
- )
- except BaseException:
- pass
- else:
- progress_message = bot.sendMessage(chat_id, progress_bar)
- progress += 5
-
- cid = chat["chat_id"]
- sleep(0.5)
- try:
- bot.get_chat(cid, timeout=120)
- except (BadRequest, Unauthorized):
- kicked_chats += 1
- chat_list.append(cid)
- except BaseException:
- pass
-
- try:
- progress_message.delete()
- except BaseException:
- pass
-
- if not remove:
- return kicked_chats
- for muted_chat in chat_list:
- sleep(0.5)
- user_db.rem_chat(muted_chat)
- return kicked_chats
-
-
-def get_invalid_gban(bot: Bot, update: Update, remove: bool = False):
- banned = gban_db.get_gban_list()
- ungbanned_users = 0
- ungban_list = []
-
- for user in banned:
- user_id = user["_id"]
- sleep(0.5)
- try:
- bot.get_chat(user_id)
- except BadRequest:
- ungbanned_users += 1
- ungban_list.append(user_id)
- except BaseException:
- pass
-
- if not remove:
- return ungbanned_users
- for user_id in ungban_list:
- sleep(0.5)
- gban_db.ungban_user(user_id)
- return ungbanned_users
-
-
-def dbcleanup(update, context):
- msg = update.effective_message
-
- msg.reply_text("Getting invalid chat count ...")
- invalid_chat_count = get_invalid_chats(context.bot, update)
-
- msg.reply_text("Getting invalid gbanned count ...")
- invalid_gban_count = get_invalid_gban(context.bot, update)
-
- reply = f"Total invalid chats - {invalid_chat_count}\n"
- reply += f"Total invalid gbanned users - {invalid_gban_count}"
-
- buttons = [[InlineKeyboardButton("Cleanup DB", callback_data="db_cleanup")]]
-
- update.effective_message.reply_text(
- reply, reply_markup=InlineKeyboardMarkup(buttons)
- )
-
-
-def get_muted_chats(bot: Bot, update: Update, leave: bool = False):
- chat_id = update.effective_chat.id
- chats = user_db.get_all_chats()
- muted_chats, progress = 0, 0
- chat_list = []
- progress_message = None
-
- for chat in chats:
- if ((100 * chats.index(chat)) / len(chats)) > progress:
- progress_bar = f"{progress}% completed in getting muted chats."
- if progress_message:
- try:
- bot.editMessageText(
- progress_bar, chat_id, progress_message.message_id
- )
- except BaseException:
- pass
- else:
- progress_message = bot.sendMessage(chat_id, progress_bar)
- progress += 5
-
- cid = chat["chat_id"]
- sleep(0.5)
-
- try:
- bot.send_chat_action(cid, "TYPING", timeout=120)
- except (BadRequest, Unauthorized):
- muted_chats += +1
- chat_list.append(cid)
- except BaseException:
- pass
-
- try:
- progress_message.delete()
- except BaseException:
- pass
-
- if not leave:
- return muted_chats
- for muted_chat in chat_list:
- sleep(0.5)
- try:
- bot.leaveChat(muted_chat, timeout=120)
- except BaseException:
- pass
- users_db.rem_chat(muted_chat)
- return muted_chats
-
-
-def leave_muted_chats(update, context):
- message = update.effective_message
- progress_message = message.reply_text("Getting chat count ...")
- muted_chats = get_muted_chats(context.bot, update)
-
- buttons = [[InlineKeyboardButton("Leave chats", callback_data="db_leave_chat")]]
-
- update.effective_message.reply_text(
- f"I am muted in {muted_chats} chats.",
- reply_markup=InlineKeyboardMarkup(buttons),
- )
- progress_message.delete()
-
-
-def callback_button(update, context):
- bot = context.bot
- query = update.callback_query
- message = query.message
- chat_id = update.effective_chat.id
- query_type = query.data
-
- bot.answer_callback_query(query.id)
-
- if query_type == "db_cleanup" and query.from_user.id in DEV_USERS:
- bot.editMessageText("Cleaning up DB ...", chat_id, message.message_id)
- invalid_chat_count = get_invalid_chats(bot, update, True)
- invalid_gban_count = get_invalid_gban(bot, update, True)
- reply = f"Cleaned up {invalid_chat_count} chats and {invalid_gban_count} gbanned users from db."
- bot.sendMessage(chat_id, reply)
- elif (
- query_type == "db_cleanup"
- or query_type == "db_leave_chat"
- and query.from_user.id not in DEV_USERS
- ):
- query.answer("You are not allowed to use this.")
-
- elif query_type == "db_leave_chat":
- bot.editMessageText("Leaving chats ...", chat_id, message.message_id)
- chat_count = get_muted_chats(bot, update, True)
- bot.sendMessage(chat_id, f"Left {chat_count} chats.")
-
-
-DB_CLEANUP_HANDLER = CommandHandler(
- "dbcleanup", dbcleanup, filters=CustomFilters.dev_filter, run_async=True
-)
-LEAVE_MUTED_CHATS_HANDLER = CommandHandler(
- "leavemutedchats",
- leave_muted_chats,
- filters=CustomFilters.dev_filter,
- run_async=True,
-)
-BUTTON_HANDLER = CallbackQueryHandler(callback_button, pattern="db_.*", run_async=True)
-
-dispatcher.add_handler(DB_CLEANUP_HANDLER)
-dispatcher.add_handler(LEAVE_MUTED_CHATS_HANDLER)
-dispatcher.add_handler(BUTTON_HANDLER)
-
-__mod_name__ = "𝐃ʙ-ᴄʟᴇᴀɴ"
-__handlers__ = [DB_CLEANUP_HANDLER, LEAVE_MUTED_CHATS_HANDLER, BUTTON_HANDLER]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "dbclean_help")
-
-# """
diff --git a/Exon/modules/debug.py b/Exon/modules/debug.py
deleted file mode 100644
index ef43745f..00000000
--- a/Exon/modules/debug.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import datetime
-import os
-
-from telegram import Update
-from telegram.ext import CallbackContext, CommandHandler
-from telethon import events
-
-from Exon import dispatcher, telethn
-from Exon.modules.helper_funcs.chat_status import dev_plus
-
-DEBUG_MODE = False
-
-
-@dev_plus
-def debug(update: Update, context: CallbackContext):
- global DEBUG_MODE
- args = update.effective_message.text.split(None, 1)
- message = update.effective_message
- print(DEBUG_MODE)
- if len(args) > 1:
- if args[1] in ("yes", "on"):
- DEBUG_MODE = True
- message.reply_text("Debug mode is now on.")
- elif args[1] in ("no", "off"):
- DEBUG_MODE = False
- message.reply_text("Debug mode is now off.")
- elif DEBUG_MODE:
- message.reply_text("Debug mode is currently on.")
- else:
- message.reply_text("Debug mode is currently off.")
-
-
-@telethn.on(events.NewMessage(pattern="[/!].*"))
-async def i_do_nothing_yes(event):
- if DEBUG_MODE:
- print(f"-{event.from_id} ({event.chat_id}) : {event.text}")
- if os.path.exists("updates.txt"):
- with open("updates.txt", "r") as f:
- text = f.read()
- with open("updates.txt", "w+") as f:
- f.write(f"{text}\n-{event.from_id} ({event.chat_id}) : {event.text}")
- else:
- with open("updates.txt", "w+") as f:
- f.write(
- f"- {event.from_id} ({event.chat_id}) : {event.text} | {datetime.datetime.now()}",
- )
-
-
-support_chat = os.getenv("SUPPORT_CHAT")
-
-
-@dev_plus
-def logs(update: Update, context: CallbackContext):
- user = update.effective_user
- with open("log.txt", "rb") as f:
- context.bot.send_document(document=f, filename=f.name, chat_id=user.id)
-
-
-LOG_HANDLER = CommandHandler("logs", logs, run_async=True)
-DEBUG_HANDLER = CommandHandler("debug", debug, run_async=True)
-
-dispatcher.add_handler(LOG_HANDLER)
-dispatcher.add_handler(DEBUG_HANDLER)
-
-__mod_name__ = "𝐃ᴇʙᴜɢ"
-
-__command_list__ = ["debug"]
-
-__handlers__ = [DEBUG_HANDLER]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "debug_help")
-
-# """
diff --git a/Exon/modules/dev.py b/Exon/modules/dev.py
deleted file mode 100644
index 8205a90a..00000000
--- a/Exon/modules/dev.py
+++ /dev/null
@@ -1,260 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import asyncio
-import os
-import re
-import subprocess
-import sys
-import time
-from statistics import mean
-from threading import Thread
-from time import monotonic as time
-
-from telegram import (
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- TelegramError,
- Update,
-)
-from telegram.ext import CallbackContext, CommandHandler
-from telegram.ext.callbackqueryhandler import CallbackQueryHandler
-from telethon import events
-
-from Exon import DEV_USERS, OWNER_ID, dispatcher, telethn, updater
-from Exon.modules.helper_funcs.alternate import typing_action
-from Exon.modules.helper_funcs.chat_status import dev_plus
-from Exon.modules.helper_funcs.filters import CustomFilters
-
-
-def leave_cb(update: Update, context: CallbackContext):
- bot = context.bot
- callback = update.callback_query
- if callback.from_user.id != DEV_USERS:
- callback.answer(text="This isn't for you", show_alert=True)
- return
-
- match = re.match(r"leavechat_cb_\((.+?)\)", callback.data)
- chat = int(match[1])
- bot.leave_chat(chat_id=chat)
- callback.answer(text="Left the chat from this group.")
-
-
-@dev_plus
-def allow_groups(update: Update, context: CallbackContext):
- args = context.args
- if not args:
- state = "off" if Exon.ALLOW_CHATS else "Lockdown is " + "on"
- update.effective_message.reply_text(f"Current state: {state}")
- return
- if args[0].lower() in ["off", "no"]:
- Exon.ALLOW_CHATS = True
- elif args[0].lower() in ["yes", "on"]:
- Exon.ALLOW_CHATS = False
- else:
- update.effective_message.reply_text("Format: /lockdown Yes/No or Off/On")
- return
- update.effective_message.reply_text("Done! Lockdown value toggled.")
-
-
-class Store:
- def __init__(self, func):
- self.func = func
- self.calls = []
- self.time = time()
- self.lock = asyncio.Lock()
-
- def average(self):
- return round(mean(self.calls), 2) if self.calls else 0
-
- def __repr__(self):
- return f"{messages.average()}/s\n"
- f"» Average Callback Queries: {callback_queries.average()}/s\n"
- f"» Average Inline Queries: {inline_queries.average()}/s",
- parse_mode=ParseMode.HTML,
- )
-
-
-@dev_plus
-def pip_install(update: Update, context: CallbackContext):
- message = update.effective_message
- args = context.args
- if not args:
- message.reply_text("Enter a package name.")
- return
- if len(args) >= 1:
- cmd = f'py -m pip install {" ".join(args)}'
- process = subprocess.Popen(
- cmd.split(" "),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- )
- stdout, stderr = process.communicate()
- reply = ""
- stderr = stderr.decode()
- if stdout := stdout.decode():
- reply += f"*Stdout*\n`{stdout}`\n"
- if stderr:
- reply += f"*Stderr*\n`{stderr}`\n"
-
- message.reply_text(text=reply, parse_mode=ParseMode.MARKDOWN)
-
-
-@dev_plus
-def leave(update: Update, context: CallbackContext):
- if args := context.args:
- chat_id = str(args[0])
- leave_msg = " ".join(args[1:])
- bot = context.bot
- try:
- context.bot.send_message(chat_id, leave_msg)
- bot.leave_chat(int(chat_id))
- update.effective_message.reply_text("Left chat.")
- except TelegramError:
- update.effective_message.reply_text("Failed to leave chat for some reason.")
- else:
- chat = update.effective_chat
- # user = update.effective_user
- Exon_leave_bt = [
- [
- InlineKeyboardButton(
- text="Yes", callback_data=f"leavechat_cb_({chat.id})"
- ),
- InlineKeyboardButton(text="No", callback_data="close2"),
- ]
- ]
- update.effective_message.reply_text(
- f"I'm going to leave {chat.title}, press the button below to confirm",
- reply_markup=InlineKeyboardMarkup(Exon_leave_bt),
- )
-
-
-close_keyboard = InlineKeyboardMarkup(
- [[InlineKeyboardButton("No", callback_data="close2")]]
-)
-
-
-@typing_action
-def gitpull(update, context):
- sent_msg = update.effective_message.reply_text("Pulling all changes from remote...")
- subprocess.Popen(
- "git reset --hard origin/master && git clean -fd && git pull",
- stdout=subprocess.PIPE,
- shell=True,
- )
-
- sent_msg_text = (
- sent_msg.text
- + "\n\nChanges pulled... I guess..\nContinue to restart with /reboot "
- )
- sent_msg.edit_text(sent_msg_text)
-
-
-def stop_and_restart():
- """Kill old instance, replace the new one"""
- updater.stop()
- os.execl(sys.executable, sys.executable, *sys.argv)
-
-
-@dev_plus
-def restart(update, context):
- update.message.reply_text("Exiting all Processes and starting a new Instance!")
- Thread(target=stop_and_restart).start()
-
-
-PIP_INSTALL_HANDLER = CommandHandler("install", pip_install, run_async=True)
-LEAVE_HANDLER = CommandHandler("leave", leave, run_async=True)
-RESTART_HANDLER = CommandHandler("reboot", restart, run_async=True)
-ALLOWGROUPS_HANDLER = CommandHandler("lockdown", allow_groups, run_async=True)
-LEAVE_CALLBACK_HANDLER = CallbackQueryHandler(
- leave_cb, pattern=r"leavechat_cb_", run_async=True
-)
-GITPULL_HANDLER = CommandHandler(
- "gitpull", gitpull, filters=CustomFilters.dev_filter, run_async=True
-)
-
-dispatcher.add_handler(PIP_INSTALL_HANDLER)
-dispatcher.add_handler(ALLOWGROUPS_HANDLER)
-dispatcher.add_handler(LEAVE_HANDLER)
-dispatcher.add_handler(RESTART_HANDLER)
-dispatcher.add_handler(LEAVE_CALLBACK_HANDLER)
-dispatcher.add_handler(GITPULL_HANDLER)
-
-__mod_name__ = "𝐃ᴇᴠs"
-__handlers__ = [
- LEAVE_HANDLER,
- RESTART_HANDLER,
- ALLOWGROUPS_HANDLER,
- LEAVE_CALLBACK_HANDLER,
- PIP_INSTALL_HANDLER,
- GITPULL_HANDLER,
-]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "devs_help")
-
-# """
diff --git a/Exon/modules/disable.py b/Exon/modules/disable.py
deleted file mode 100644
index 811d058d..00000000
--- a/Exon/modules/disable.py
+++ /dev/null
@@ -1,372 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import importlib
-from typing import Union
-
-from future.utils import string_types
-from telegram import ParseMode, Update
-from telegram.ext import (
- CallbackContext,
- CommandHandler,
- Filters,
- MessageHandler,
- RegexHandler,
-)
-from telegram.utils.helpers import escape_markdown
-
-from Exon import dispatcher
-from Exon.modules.helper_funcs.handlers import CMD_STARTERS, SpamChecker
-from Exon.modules.helper_funcs.misc import is_module_loaded
-
-FILENAME = __name__.rsplit(".", 1)[-1]
-
-# If module is due to be loaded, then setup all the magical handlers
-if is_module_loaded(FILENAME):
- from Exon.modules.helper_funcs.chat_status import (
- connection_status,
- is_user_admin,
- user_admin,
- )
- from Exon.modules.sql import disable_sql as sql
-
- DISABLE_CMDS = []
- DISABLE_OTHER = []
- ADMIN_CMDS = []
-
-
- class DisableAbleCommandHandler(CommandHandler):
- def __init__(self, command, callback, admin_ok=False, **kwargs):
- super().__init__(command, callback, **kwargs)
- self.admin_ok = admin_ok
- if isinstance(command, string_types):
- DISABLE_CMDS.append(command)
- if admin_ok:
- ADMIN_CMDS.append(command)
- else:
- DISABLE_CMDS.extend(command)
- if admin_ok:
- ADMIN_CMDS.extend(command)
-
- def check_update(self, update):
- if not isinstance(update, Update) or not update.effective_message:
- return
- message = update.effective_message
-
- if message.text and len(message.text) > 1:
- fst_word = message.text.split(None, 1)[0]
- if len(fst_word) > 1 and any(
- fst_word.startswith(start) for start in CMD_STARTERS
- ):
- args = message.text.split()[1:]
- command = fst_word[1:].split("@")
- command.append(message.bot.username)
-
- if (
- command[0].lower() not in self.command
- or command[1].lower() != message.bot.username.lower()
- ):
- return None
- chat = update.effective_chat
- user = update.effective_user
- user_id = chat.id if user.id == 1087968824 else user.id
- if SpamChecker.check_user(user_id):
- return None
- if filter_result := self.filters(update):
- # disabled, admincmd, user admin
- if sql.is_command_disabled(chat.id, command[0].lower()):
- # check if command was disabled
- is_disabled = command[0] in ADMIN_CMDS and is_user_admin(
- chat, user.id
- )
- return (args, filter_result) if is_disabled else None
- return args, filter_result
- return False
-
-
- class DisableAbleMessageHandler(MessageHandler):
- def __init__(self, filters, callback, friendly, **kwargs):
- super().__init__(filters, callback, **kwargs)
- DISABLE_OTHER.append(friendly)
- self.friendly = friendly
- if filters:
- self.filters = Filters.update.messages & filters
- else:
- self.filters = Filters.update.messages
-
- def check_update(self, update):
- chat = update.effective_chat
- message = update.effective_message
- filter_result = self.filters(update)
-
- try:
- args = message.text.split()[1:]
- except Exception:
- args = []
-
- if super().check_update(update):
- if sql.is_command_disabled(chat.id, self.friendly):
- return False
- return args, filter_result
-
-
- class DisableAbleRegexHandler(RegexHandler):
- def __init__(self, pattern, callback, friendly="", filters=None, **kwargs):
- super().__init__(pattern, callback, filters, **kwargs)
- DISABLE_OTHER.append(friendly)
- self.friendly = friendly
-
- def check_update(self, update):
- chat = update.effective_chat
- if super().check_update(update):
- return not sql.is_command_disabled(chat.id, self.friendly)
-
-
- @connection_status
- @user_admin
- def disable(update: Update, context: CallbackContext):
- args = context.args
- if len(args) >= 1:
- disable_cmd = args[0]
- if disable_cmd.startswith(CMD_STARTERS):
- disable_cmd = disable_cmd[1:]
-
- if disable_cmd in set(DISABLE_CMDS + DISABLE_OTHER):
- chat = update.effective_chat
- sql.disable_command(chat.id, str(disable_cmd).lower())
- update.effective_message.reply_text(
- f"Disabled the use of `{disable_cmd}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- else:
- update.effective_message.reply_text("That command can't be disabled")
-
- else:
- update.effective_message.reply_text("What should I disable?")
-
-
- @connection_status
- @user_admin
- def disable_module(update: Update, context: CallbackContext):
- args = context.args
- if len(args) >= 1:
- disable_module = "Exon.modules." + args[0].rsplit(".", 1)[0]
-
- try:
- module = importlib.import_module(disable_module)
- except Exception:
- update.effective_message.reply_text("Does that module even exist?")
- return
-
- try:
- command_list = module.__command_list__
- except Exception:
- update.effective_message.reply_text(
- "Module does not contain command list!",
- )
- return
-
- disabled_cmds = []
- failed_disabled_cmds = []
-
- chat = update.effective_chat
- for disable_cmd in command_list:
- if disable_cmd.startswith(CMD_STARTERS):
- disable_cmd = disable_cmd[1:]
-
- if disable_cmd in set(DISABLE_CMDS + DISABLE_OTHER):
- sql.disable_command(chat.id, str(disable_cmd).lower())
- disabled_cmds.append(disable_cmd)
- else:
- failed_disabled_cmds.append(disable_cmd)
-
- if disabled_cmds:
- disabled_cmds_string = ", ".join(disabled_cmds)
- update.effective_message.reply_text(
- f"Disabled the uses of `{disabled_cmds_string}`",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- if failed_disabled_cmds:
- failed_disabled_cmds_string = ", ".join(failed_disabled_cmds)
- update.effective_message.reply_text(
- f"Commands `{failed_disabled_cmds_string}` can't be disabled",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- else:
- update.effective_message.reply_text("What should I disable?")
-
-
- @connection_status
- @user_admin
- def enable(update: Update, context: CallbackContext):
- args = context.args
- if len(args) >= 1:
- enable_cmd = args[0]
- if enable_cmd.startswith(CMD_STARTERS):
- enable_cmd = enable_cmd[1:]
-
- chat = update.effective_chat
- if sql.enable_command(chat.id, enable_cmd):
- update.effective_message.reply_text(
- f"Enabled the use of `{enable_cmd}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- else:
- update.effective_message.reply_text("Is that even disabled?")
-
- else:
- update.effective_message.reply_text("What should I enable?")
-
-
- @connection_status
- @user_admin
- def enable_module(update: Update, context: CallbackContext):
- args = context.args
- if len(args) >= 1:
- enable_module = "Exon.modules." + args[0].rsplit(".", 1)[0]
-
- try:
- module = importlib.import_module(enable_module)
- except Exception:
- update.effective_message.reply_text("Does that module even exist?")
- return
-
- try:
- command_list = module.__command_list__
- except Exception:
- update.effective_message.reply_text(
- "Module does not contain command list!",
- )
- return
-
- enabled_cmds = []
- failed_enabled_cmds = []
-
- chat = update.effective_chat
-
- for enable_cmd in command_list:
- if enable_cmd.startswith(CMD_STARTERS):
- enable_cmd = enable_cmd[1:]
-
- if sql.enable_command(chat.id, enable_cmd):
- enabled_cmds.append(enable_cmd)
- else:
- failed_enabled_cmds.append(enable_cmd)
-
- if enabled_cmds:
- enabled_cmds_string = ", ".join(enabled_cmds)
- update.effective_message.reply_text(
- f"Enabled the uses of `{enabled_cmds_string}`",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- if failed_enabled_cmds:
- failed_enabled_cmds_string = ", ".join(failed_enabled_cmds)
- update.effective_message.reply_text(
- f"Are the commands `{failed_enabled_cmds_string}` even disabled?",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- else:
- update.effective_message.reply_text("What should I enable?")
-
-
- @connection_status
- @user_admin
- def list_cmds(update: Update, context: CallbackContext):
- if DISABLE_CMDS + DISABLE_OTHER:
- result = "".join(
- f" - `{escape_markdown(cmd)}`\n"
- for cmd in set(DISABLE_CMDS + DISABLE_OTHER)
- )
-
- update.effective_message.reply_text(
- f"The following commands are toggleable:\n{result}",
- parse_mode=ParseMode.MARKDOWN,
- )
- else:
- update.effective_message.reply_text("No commands can be disabled.")
-
-
- # do not async
- def build_curr_disabled(chat_id: Union[str, int]) -> str:
- disabled = sql.get_all_disabled(chat_id)
- if not disabled:
- return "No commands are disabled!"
-
- result = "".join(f" - `{escape_markdown(cmd)}`\n" for cmd in disabled)
- return f"The following commands are currently restricted:\n{result}"
-
-
- @connection_status
- def commands(update: Update, context: CallbackContext):
- chat = update.effective_chat
- update.effective_message.reply_text(
- build_curr_disabled(chat.id),
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
- def __stats__():
- return f"× {sql.num_disabled()} ᴅɪsᴀʙʟᴇᴅ ɪᴛᴇᴍs, ᴀᴄʀᴏss {sql.num_chats()} ᴄʜᴀᴛs."
-
-
- def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
- def __chat_settings__(chat_id, user_id):
- return build_curr_disabled(chat_id)
-
-
- DISABLE_HANDLER = CommandHandler("disable", disable, run_async=True)
- DISABLE_MODULE_HANDLER = CommandHandler(
- "disablemodule", disable_module, run_async=True
- )
- ENABLE_HANDLER = CommandHandler("enable", enable, run_async=True)
- ENABLE_MODULE_HANDLER = CommandHandler(
- "enablemodule", enable_module, run_async=True
- )
- COMMANDS_HANDLER = CommandHandler(["cmds", "disabled"], commands, run_async=True)
- TOGGLE_HANDLER = CommandHandler("listcmds", list_cmds, run_async=True)
-
- dispatcher.add_handler(DISABLE_HANDLER)
- dispatcher.add_handler(DISABLE_MODULE_HANDLER)
- dispatcher.add_handler(ENABLE_HANDLER)
- dispatcher.add_handler(ENABLE_MODULE_HANDLER)
- dispatcher.add_handler(COMMANDS_HANDLER)
- dispatcher.add_handler(TOGGLE_HANDLER)
-
-
-else:
- DisableAbleCommandHandler = CommandHandler
- DisableAbleRegexHandler = RegexHandler
- DisableAbleMessageHandler = MessageHandler
diff --git a/Exon/modules/disable_help.py b/Exon/modules/disable_help.py
deleted file mode 100644
index 8c1376c1..00000000
--- a/Exon/modules/disable_help.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "disable_help")
-
-
-__mod_name__ = "𝐃ɪsᴀʙʟᴇ"
diff --git a/Exon/modules/disasters.py b/Exon/modules/disasters.py
deleted file mode 100644
index 6962d584..00000000
--- a/Exon/modules/disasters.py
+++ /dev/null
@@ -1,599 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import html
-import json
-import os
-from typing import Optional
-
-from telegram import ParseMode, TelegramError, Update
-from telegram.ext import CallbackContext, CommandHandler
-from telegram.utils.helpers import mention_html
-
-from Exon import DEMONS, DEV_USERS, DRAGONS, OWNER_ID, TIGERS, WOLVES, dispatcher
-from Exon.modules.helper_funcs.chat_status import dev_plus, sudo_plus, whitelist_plus
-from Exon.modules.helper_funcs.extraction import extract_user
-from Exon.modules.log_channel import gloggable
-
-ELEVATED_USERS_FILE = os.path.join(os.getcwd(), "Exon/elevated_users.json")
-
-
-def check_user_id(user_id: int, context: CallbackContext) -> Optional[str]:
- bot = context.bot
- if not user_id:
- return "That...is a chat! baka ka omae?"
-
- return "This does not work that way." if user_id == bot.id else None
-
-
-@dev_plus
-@gloggable
-def addsudo(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
- rt = ""
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in DRAGONS:
- message.reply_text("This member is already a Shadow Slayer")
- return ""
-
- if user_id in DEMONS:
- rt += "Requested the Sakura Union to promote a Guardian to Shadow Slayer."
- data["supports"].remove(user_id)
- DEMONS.remove(user_id)
-
- if user_id in WOLVES:
- rt += "Requested the Sakura Union to promote a Villain to Shadow Slayer."
- data["whitelists"].remove(user_id)
- WOLVES.remove(user_id)
-
- data["sudos"].append(user_id)
- DRAGONS.append(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- update.effective_message.reply_text(
- f"{rt}\nSuccessfully set Disaster level of {user_member.first_name} to Shadow Slayer!"
- )
-
- log_message = (
- f"#ADDSUDO\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
-
-
-@sudo_plus
-@gloggable
-def addsupport(
- update: Update,
- context: CallbackContext,
-) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
- rt = ""
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in DRAGONS:
- rt += "Requested the Sakura Union to demote this Shadow Slayer to Guardian"
- data["sudos"].remove(user_id)
- DRAGONS.remove(user_id)
-
- if user_id in DEMONS:
- message.reply_text("This user is already a Guardian.")
- return ""
-
- if user_id in WOLVES:
- rt += "Requested the Sakura Union to promote this Villain to Guardian"
- data["whitelists"].remove(user_id)
- WOLVES.remove(user_id)
-
- data["supports"].append(user_id)
- DEMONS.append(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- update.effective_message.reply_text(
- f"{rt}\n{user_member.first_name} was added as a Guardian!"
- )
-
- log_message = (
- f"#ADDSUPPORT\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
-
-
-@sudo_plus
-@gloggable
-def addwhitelist(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
- rt = ""
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in DRAGONS:
- rt += "This member is a Light Shooters, Demoting to Villain."
- data["sudos"].remove(user_id)
- DRAGONS.remove(user_id)
-
- if user_id in DEMONS:
- rt += "This user is already a Guardian, Demoting to Villain."
- data["supports"].remove(user_id)
- DEMONS.remove(user_id)
-
- if user_id in WOLVES:
- message.reply_text("This user is already a Villain.")
- return ""
-
- data["whitelists"].append(user_id)
- WOLVES.append(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- update.effective_message.reply_text(
- f"{rt}\nSuccessfully promoted {user_member.first_name} to a Villain!"
- )
-
- log_message = (
- f"#ADDWHITELIST\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))} \n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
-
-
-@sudo_plus
-@gloggable
-def addtiger(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
- rt = ""
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in DRAGONS:
- rt += "This member is a Shadow Slayer, Demoting to Light Shooters."
- data["sudos"].remove(user_id)
- DRAGONS.remove(user_id)
-
- if user_id in DEMONS:
- rt += "This user is already a Guardian, Demoting to Light Shooters."
- data["supports"].remove(user_id)
- DEMONS.remove(user_id)
-
- if user_id in WOLVES:
- rt += "This user is already a Villain, Demoting to No Access.."
- data["whitelists"].remove(user_id)
- WOLVES.remove(user_id)
-
- if user_id in TIGERS:
- message.reply_text("This user is already a Light Shooters.")
- return ""
-
- data["tigers"].append(user_id)
- TIGERS.append(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- update.effective_message.reply_text(
- f"{rt}\nSuccessfully promoted {user_member.first_name} to a Light Shooters!"
- )
-
- log_message = (
- f"#LIGHTSHOOTERS\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))} \n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
-
-
-@dev_plus
-@gloggable
-def removesudo(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in DRAGONS:
- message.reply_text("Requested the Sakura Union to demote this user to Civilian")
- DRAGONS.remove(user_id)
- data["sudos"].remove(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- log_message = (
- f"#UNSUDO\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
- message.reply_text("This user is not a Shadow Slayer!")
- return ""
-
-
-@sudo_plus
-@gloggable
-def removesupport(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in DEMONS:
- message.reply_text("Requested the Sakura Union to demote this user to Civilian")
- DEMONS.remove(user_id)
- data["supports"].remove(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- log_message = (
- f"#UNSUPPORT\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
- message.reply_text("This user is not a Guardian!")
- return ""
-
-
-@sudo_plus
-@gloggable
-def removewhitelist(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in WOLVES:
- message.reply_text("Requested the Sakura Union to demote this user to Civilian")
- WOLVES.remove(user_id)
- data["whitelists"].remove(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- log_message = (
- f"#UNWHITELIST\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
- message.reply_text("This user is not a Villain!")
- return ""
-
-
-@sudo_plus
-@gloggable
-def removetiger(update: Update, context: CallbackContext) -> str:
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- bot, args = context.bot, context.args
- user_id = extract_user(message, args)
- user_member = bot.getChat(user_id)
-
- if reply := check_user_id(user_id, bot):
- message.reply_text(reply)
- return ""
-
- with open(ELEVATED_USERS_FILE, "r") as infile:
- data = json.load(infile)
-
- if user_id in TIGERS:
- message.reply_text("Requested the Sakura Union to demote this user to Civilian")
- TIGERS.remove(user_id)
- data["tigers"].remove(user_id)
-
- with open(ELEVATED_USERS_FILE, "w") as outfile:
- json.dump(data, outfile, indent=4)
-
- log_message = (
- f"#UNLIGHTSHOOTERS\n"
- f"Admin: {mention_html(user.id, html.escape(user.first_name))}\n"
- f"User: {mention_html(user_member.id, html.escape(user_member.first_name))}"
- )
-
- if chat.type != "private":
- log_message = f"{html.escape(chat.title)}:\n{log_message}"
-
- return log_message
- message.reply_text("This user is not a Light Shooters!")
- return ""
-
-
-@whitelist_plus
-def whitelistlist(update: Update, context: CallbackContext):
- reply = "ᴛᴇᴍᴀ ᴀʙɪsʜᴏɪɴ ᴍᴇᴍʙᴇʀs:\n"
- m = update.effective_message.reply_text(
- "Gathering intel..
",
- parse_mode=ParseMode.HTML,
- )
- bot = context.bot
- for each_user in WOLVES:
- user_id = int(each_user)
- try:
- user = bot.get_chat(user_id)
-
- reply += f"× {mention_html(user_id, html.escape(user.first_name))}\n"
- except TelegramError:
- pass
- m.edit_text(reply, parse_mode=ParseMode.HTML)
-
-
-@whitelist_plus
-def tigerlist(update: Update, context: CallbackContext):
- reply = "ᴋɴᴏᴡɴ ʟɪɢʜᴛ sʜᴏᴏᴛᴇʀs ᴍᴇᴍʙᴇʀs:\n"
- m = update.effective_message.reply_text(
- "Gathering intel..
",
- parse_mode=ParseMode.HTML,
- )
- bot = context.bot
- for each_user in TIGERS:
- user_id = int(each_user)
- try:
- user = bot.get_chat(user_id)
- reply += f"× {mention_html(user_id, html.escape(user.first_name))}\n"
- except TelegramError:
- pass
- m.edit_text(reply, parse_mode=ParseMode.HTML)
-
-
-@whitelist_plus
-def supportlist(update: Update, context: CallbackContext):
- bot = context.bot
- m = update.effective_message.reply_text(
- "Gathering intel..
",
- parse_mode=ParseMode.HTML,
- )
- reply = "Known Guardians Members:\n"
- for each_user in DEMONS:
- user_id = int(each_user)
- try:
- user = bot.get_chat(user_id)
- reply += f"× {mention_html(user_id, html.escape(user.first_name))}\n"
- except TelegramError:
- pass
- m.edit_text(reply, parse_mode=ParseMode.HTML)
-
-
-@whitelist_plus
-def sudolist(update: Update, context: CallbackContext):
- bot = context.bot
- m = update.effective_message.reply_text(
- "Gathering intel..
",
- parse_mode=ParseMode.HTML,
- )
- true_sudo = list(set(DRAGONS) - set(DEV_USERS))
- reply = "Known Shadow Slayers Members:\n"
- for each_user in true_sudo:
- user_id = int(each_user)
- try:
- user = bot.get_chat(user_id)
- reply += f"× {mention_html(user_id, html.escape(user.first_name))}\n"
- except TelegramError:
- pass
- m.edit_text(reply, parse_mode=ParseMode.HTML)
-
-
-@whitelist_plus
-def devlist(update: Update, context: CallbackContext):
- bot = context.bot
- m = update.effective_message.reply_text(
- "Gathering intel..
",
- parse_mode=ParseMode.HTML,
- )
- true_dev = list(set(DEV_USERS) - {OWNER_ID})
- reply = "Tantei wa mou, Shindeiru Members:\n"
- for each_user in true_dev:
- user_id = int(each_user)
- try:
- user = bot.get_chat(user_id)
- reply += f"× {mention_html(user_id, html.escape(user.first_name))}\n"
- except TelegramError:
- pass
- m.edit_text(reply, parse_mode=ParseMode.HTML)
-
-
-SUDO_HANDLER = CommandHandler(("addsudo", "addshadowslayers"), addsudo, run_async=True)
-SUPPORT_HANDLER = CommandHandler(
- ("addsupport", "addguardian"), addsupport, run_async=True
-)
-TIGER_HANDLER = CommandHandler(("addlightshooters"), addtiger)
-WHITELIST_HANDLER = CommandHandler(
- ("addvillain", "addwhitelist"), addwhitelist, run_async=True
-)
-UNSUDO_HANDLER = CommandHandler(
- ("rmsudo", "rmshadowslayers"), removesudo, run_async=True
-)
-UNSUPPORT_HANDLER = CommandHandler(
- ("rmsupport", "rmguardian"), removesupport, run_async=True
-)
-UNTIGER_HANDLER = CommandHandler(("rmlightshooters"), removetiger)
-UNWHITELIST_HANDLER = CommandHandler(
- ("rmwhitelist", "rmvillain"), removewhitelist, run_async=True
-)
-WHITELISTLIST_HANDLER = CommandHandler(
- ["whitelistlist", "villain"], whitelistlist, run_async=True
-)
-TIGERLIST_HANDLER = CommandHandler(["lightshooters"], tigerlist, run_async=True)
-SUPPORTLIST_HANDLER = CommandHandler(
- ["supportlist", "guardians"], supportlist, run_async=True
-)
-SUDOLIST_HANDLER = CommandHandler(
- ["sudolist", "shadowslayers"], sudolist, run_async=True
-)
-DEVLIST_HANDLER = CommandHandler(["devlist", "sakuraunion"], devlist, run_async=True)
-
-dispatcher.add_handler(SUDO_HANDLER)
-dispatcher.add_handler(SUPPORT_HANDLER)
-dispatcher.add_handler(TIGER_HANDLER)
-dispatcher.add_handler(WHITELIST_HANDLER)
-dispatcher.add_handler(UNSUDO_HANDLER)
-dispatcher.add_handler(UNSUPPORT_HANDLER)
-dispatcher.add_handler(UNTIGER_HANDLER)
-dispatcher.add_handler(UNWHITELIST_HANDLER)
-dispatcher.add_handler(WHITELISTLIST_HANDLER)
-dispatcher.add_handler(TIGERLIST_HANDLER)
-dispatcher.add_handler(SUPPORTLIST_HANDLER)
-dispatcher.add_handler(SUDOLIST_HANDLER)
-dispatcher.add_handler(DEVLIST_HANDLER)
-
-__mod_name__ = "𝐎ᴡɴᴇʀ"
-
-__handlers__ = [
- SUDO_HANDLER,
- SUPPORT_HANDLER,
- TIGER_HANDLER,
- WHITELIST_HANDLER,
- UNSUDO_HANDLER,
- UNSUPPORT_HANDLER,
- UNTIGER_HANDLER,
- UNWHITELIST_HANDLER,
- WHITELISTLIST_HANDLER,
- TIGERLIST_HANDLER,
- SUPPORTLIST_HANDLER,
- SUDOLIST_HANDLER,
- DEVLIST_HANDLER,
-]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "owner_help")
-
-# """
diff --git a/Exon/modules/error_handling.py b/Exon/modules/error_handling.py
deleted file mode 100644
index 47d2b10a..00000000
--- a/Exon/modules/error_handling.py
+++ /dev/null
@@ -1,152 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import html
-import io
-import random
-import sys
-import traceback
-
-import pretty_errors
-import requests
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.ext import CallbackContext
-
-from Exon import DEV_USERS
-from Exon import LOG_GROUP_ID as ERROR_LOGS
-from Exon import dispatcher
-from Exon.modules.helper_funcs.decorators import Exoncmd
-
-pretty_errors.mono()
-
-
-class ErrorsDict(dict):
- """A custom dict to store errors and their count"""
-
- def __init__(self, *args, **kwargs):
- self.raw = []
- super().__init__(*args, **kwargs)
-
- def __contains__(self, error):
- self.raw.append(error)
- error.identifier = "".join(random.choices("ABCDEFGHIJKLMNOPQRSTUVWXYZ", k=5))
- for e in self:
- if type(e) is type(error) and e.args == error.args:
- self[e] += 1
- return True
- self[error] = 0
- return False
-
- def __len__(self):
- return len(self.raw)
-
-
-errors = ErrorsDict()
-
-
-def error_callback(update: Update, context: CallbackContext):
- if not update:
- return
- if context.error not in errors:
- try:
- stringio = io.StringIO()
- pretty_errors.output_stderr = stringio
- output = pretty_errors.excepthook(
- type(context.error),
- context.error,
- context.error.__traceback__,
- )
- pretty_errors.output_stderr = sys.stderr
- pretty_error = stringio.getvalue()
- stringio.close()
- except Exception:
- pretty_error = "Failed to create pretty error."
- tb_list = traceback.format_exception(
- None,
- context.error,
- context.error.__traceback__,
- )
- tb = "".join(tb_list)
- pretty_message = f'{pretty_error}\n-------------------------------------------------------------------------------\nAn exception was raised while handling an update\nUser: {update.effective_user.id}\nChat: {update.effective_chat.title if update.effective_chat else ""} {update.effective_chat.id if update.effective_chat else ""}\nCallback data: {update.callback_query.data if update.callback_query else "None"}\nMessage: {update.effective_message.text if update.effective_message else "No message"}\n\nFull Traceback: {tb}'
- extension = "txt"
- url = "https://spaceb.in/api/v1/documents/"
- try:
- response = requests.post(
- url, data={"content": pretty_message, "extension": extension}
- )
- except Exception as e:
- return {"error": str(e)}
- response = response.json()
- e = html.escape(f"{context.error}")
- if not response:
- with open("error.txt", "w+") as f:
- f.write(pretty_message)
- context.bot.send_document(
- ERROR_LOGS,
- open("error.txt", "rb"),
- caption=f"#{context.error.identifier}\nʏᴏᴜʀ ᴄᴜᴛᴇ ᴇxᴏɴ ʜᴀᴠᴇ ᴀɴ ᴇʀʀᴏʀ ғᴏʀ ʏᴏᴜ:"
- f"\n{e}
",
- parse_mode="html",
- )
- return
-
- url = f"https://spaceb.in/{response['payload']['id']}"
- context.bot.send_message(
- ERROR_LOGS,
- text=f"#{context.error.identifier}\nYour Cute Exon Nagisa Have An Error For You:"
- f"\n{e}
",
- reply_markup=InlineKeyboardMarkup(
- [[InlineKeyboardButton("sᴇxʏ ᴇxᴏɴ ᴇʀʀᴏʀ ʟᴏɢs", url=url)]],
- ),
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncmd(command="errors")
-def list_errors(update: Update, context: CallbackContext):
- if update.effective_user.id not in DEV_USERS:
- return
- e = dict(sorted(errors.items(), key=lambda item: item[1], reverse=True))
- msg = "Errors List:\n"
- for x, value in e.items():
- msg += f"× {x}:
{value} #{x.identifier}\n"
- msg += f"{len(errors)} have occurred since startup."
- if len(msg) > 4096:
- with open("errors_msg.txt", "w+") as f:
- f.write(msg)
- context.bot.send_document(
- update.effective_chat.id,
- open("errors_msg.txt", "rb"),
- caption="Too many errors have occured..",
- parse_mode="html",
- )
- return
- update.effective_message.reply_text(msg, parse_mode="html")
-
-
-dispatcher.add_error_handler(error_callback)
diff --git a/Exon/modules/eval.py b/Exon/modules/eval.py
deleted file mode 100644
index bf05b381..00000000
--- a/Exon/modules/eval.py
+++ /dev/null
@@ -1,251 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-import ast
-import io
-import os
-import sys
-import textwrap
-import traceback
-from contextlib import redirect_stdout
-from inspect import getfullargspec
-from io import StringIO
-from time import time
-
-from pyrogram import filters
-from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
-from telegram import ParseMode, Update
-from telegram.ext import CallbackContext, CommandHandler
-
-from Exon import Abishnoi as app
-from Exon import DEV_USERS, LOGGER
-from Exon import dispatcher
-from Exon.modules.helper_funcs.chat_status import dev_plus
-
-namespaces = {}
-
-
-def namespace_of(chat, update, bot):
- if chat not in namespaces:
- namespaces[chat] = {
- "__builtins__": globals()["__builtins__"],
- "bot": bot,
- "effective_message": update.effective_message,
- "effective_user": update.effective_user,
- "effective_chat": update.effective_chat,
- "update": update,
- }
- return namespaces[chat]
-
-
-def log_input(update):
- user = update.effective_user.id
- chat = update.effective_chat.id
- LOGGER.info(f"IN: {update.effective_message.text} (user={user}, chat={chat})")
-
-
-def send(msg, bot, update):
- if len(str(msg)) > 2000:
- with io.BytesIO(str.encode(msg)) as out_file:
- out_file.name = "output.txt"
- bot.send_document(chat_id=update.effective_chat.id, document=out_file)
- else:
- LOGGER.info(f"OUT: '{msg}'")
- bot.send_message(
- chat_id=update.effective_chat.id,
- text=f"Result:\n{msg}
",
- parse_mode=ParseMode.HTML,
- )
-
-
-async def aexec(code, client, message):
- exec(
- "async def __aexec(client, message): "
- + "".join(f"\n {a}" for a in code.split("\n"))
- )
- return await locals()["__aexec"](client, message)
-
-
-async def edit_or_reply(msg: Message, **kwargs):
- func = msg.edit_text if msg.from_user.is_self else msg.reply
- spec = getfullargspec(func.__wrapped__).args
- await func(**{k: v for k, v in kwargs.items() if k in spec})
-
-
-@dev_plus
-def execute(update: Update, context: CallbackContext):
- bot = context.bot
- send(do(exec, bot, update), bot, update)
-
-
-def cleanup_code(code):
- if code.startswith("```") and code.endswith("```"):
- return "\n".join(code.split("\n")[1:-1])
- return code.strip("` \n")
-
-
-def do(func, bot, update):
- log_input(update)
- content = update.message.text.split(" ", 1)[-1]
- body = cleanup_code(content)
- env = namespace_of(update.message.chat_id, update, bot)
- os.chdir(os.getcwd())
- with open(
- os.path.join(os.getcwd(), "Exon/modules/helper_funcs/temp.txt"),
- "w",
- ) as temp:
- temp.write(body)
- stdout = io.StringIO()
- to_compile = f'def func():\n{textwrap.indent(body, " ")}'
- try:
- exec(to_compile, env)
- except Exception as e:
- return f"{e.__class__.__name__}: {e}"
- func = env["func"]
- try:
- with redirect_stdout(stdout):
- func_return = func()
- except Exception:
- value = stdout.getvalue()
- return f"{value}{traceback.format_exc()}"
- else:
- value = stdout.getvalue()
- result = None
- if func_return is None:
- if value:
- result = f"{value}"
- else:
- try:
- result = f"{repr(ast.literal_eval(body, env))}"
- except Exception:
- pass
- else:
- result = f"{value}{func_return}"
- if result:
- return result
-
-
-@app.on_message(
- filters.user(DEV_USERS)
- & ~filters.forwarded
- & ~filters.via_bot
- & filters.command(["eval", "e"])
-)
-async def executor(client, message):
- try:
- cmd = message.text.split(" ", maxsplit=1)[1]
- except IndexError:
- return await message.delete()
- t1 = time()
- old_stderr = sys.stderr
- old_stdout = sys.stdout
- redirected_output = sys.stdout = StringIO()
- redirected_error = sys.stderr = StringIO()
- stdout, stderr, exc = None, None, None
- try:
- await aexec(cmd, client, message)
- except Exception:
- exc = traceback.format_exc()
- stdout = redirected_output.getvalue()
- stderr = redirected_error.getvalue()
- sys.stdout = old_stdout
- sys.stderr = old_stderr
- evaluation = ""
- if exc:
- evaluation = exc
- elif stderr:
- evaluation = stderr
- elif stdout:
- evaluation = stdout
- else:
- evaluation = "Success"
- final_output = f"**OUTPUT**:\n```{evaluation.strip()}```"
- if len(final_output) > 4096:
- filename = "output.txt"
- with open(filename, "w+", encoding="utf8") as out_file:
- out_file.write(str(evaluation.strip()))
- t2 = time()
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⏳",
- callback_data=f"runtime {t2 - t1} Seconds",
- )
- ]
- ]
- )
- await message.reply_document(
- document=filename,
- caption=f"**INPUT:**\n`{cmd[:980]}`\n\n**OUTPUT:**\n`Attached Document`",
- quote=False,
- reply_markup=keyboard,
- )
- await message.delete()
- os.remove(filename)
- else:
- t2 = time()
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⏳",
- callback_data=f"runtime {round(t2 - t1, 3)} Seconds",
- )
- ]
- ]
- )
- await edit_or_reply(message, text=final_output, reply_markup=keyboard)
-
-
-@app.on_callback_query(filters.regex(r"runtime"))
-async def runtime_func_cq(_, cq):
- runtime = cq.data.split(None, 1)[1]
- await cq.answer(runtime, show_alert=True)
-
-
-@dev_plus
-def clear(update: Update, context: CallbackContext):
- bot = context.bot
- log_input(update)
- if update.message.chat_id in namespaces:
- del namespaces[update.message.chat_id]
- send("Cleared locals.", bot, update)
-
-
-EXEC_HANDLER = CommandHandler(
- ("x", "ex", "exe", "py"),
- execute,
- run_async=True,
-)
-CLEAR_HANDLER = CommandHandler("clearlocals", clear, run_async=True)
-
-dispatcher.add_handler(EXEC_HANDLER)
-dispatcher.add_handler(CLEAR_HANDLER)
diff --git a/Exon/modules/feds.py b/Exon/modules/feds.py
deleted file mode 100644
index a278ba29..00000000
--- a/Exon/modules/feds.py
+++ /dev/null
@@ -1,2262 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import ast
-import csv
-import json
-import os
-import re
-import time
-import uuid
-from io import BytesIO
-
-from telegram import (
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- MessageEntity,
- ParseMode,
- Update,
-)
-from telegram.error import BadRequest, TelegramError, Unauthorized
-from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler
-from telegram.utils.helpers import mention_html, mention_markdown
-
-import Exon.modules.sql.feds_sql as sql
-from Exon import (
- DRAGONS,
- EVENT_LOGS,
- LOGGER,
- OWNER_ID,
- SUPPORT_CHAT,
- TIGERS,
- WOLVES,
- dispatcher,
-)
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.alternate import send_message
-from Exon.modules.helper_funcs.chat_status import is_user_admin
-from Exon.modules.helper_funcs.decorators import Exoncallback
-from Exon.modules.helper_funcs.extraction import (
- extract_unt_fedban,
- extract_user,
- extract_user_fban,
-)
-from Exon.modules.helper_funcs.string_handling import markdown_parser
-
-# Hello bot owner, I spended for feds many hours of my life, Please don't remove this if you still respect MrYacha and peaktogoo and AyraHikari too
-# Federation by MrYacha 2018-2019
-# Federation rework by Mizukito Akito 2019
-# Federation update v2 by Ayra Hikari 2019
-# Time spended on feds = 10h by #MrYacha
-# Time spended on reworking on the whole feds = 22+ hours by @peaktogoo
-# Time spended on updating version to v2 = 26+ hours by @AyraHikari
-# Total spended for making this features is 68+ hours
-# LOGGER.info("Original federation module by MrYacha, reworked by Mizukito Akito (@peaktogoo) on Telegram.")
-
-FBAN_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to kick it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can kick group administrators",
- "Channel_private",
- "Not in the chat",
- "Have no rights to send a message",
-}
-
-UNFBAN_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Method is available for supergroup and channel chats only",
- "Not in the chat",
- "Channel_private",
- "Chat_admin_required",
- "Have no rights to send a message",
-}
-
-
-def new_fed(update: Update, context: CallbackContext):
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
- if chat.type != "private":
- update.effective_message.reply_text(
- "Federations can only be created by privately messaging me.",
- )
- return
- if len(message.text) == 1:
- send_message(
- update.effective_message,
- "Please write the name of the federation!",
- )
- return
- fednam = message.text.split(None, 1)[1]
- if fednam != "":
- fed_id = str(uuid.uuid4())
- fed_name = fednam
- LOGGER.info(fed_id)
-
- # Currently only for creator
- # if fednam == 'Team Nusantara Disciplinary Circle':
- # fed_id = "TeamNusantaraDevs"
-
- x = sql.new_fed(user.id, fed_name, fed_id)
- if not x:
- update.effective_message.reply_text(
- f"Can't federate! Please contact @{SUPPORT_CHAT} if the problem persist.",
- )
- return
-
- update.effective_message.reply_text(
- f"*You have succeeded in creating a new federation!*\nName: `{fed_name}`\nID: `{fed_id}`\n\nUse the command below to join the federation:\n`/joinfed {fed_id}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- try:
- bot.send_message(
- EVENT_LOGS,
- f"New Federation: {fed_name}\nID: {fed_id}
",
- parse_mode=ParseMode.HTML,
- )
- except Exception:
- LOGGER.warning("Cannot send a message to EVENT_LOGS")
- else:
- update.effective_message.reply_text(
- "Please write down the name of the federation",
- )
-
-
-def del_fed(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- if chat.type != "private":
- update.effective_message.reply_text(
- "Federations can only be deleted by privately messaging me.",
- )
- return
- if args:
- is_fed_id = args[0]
- getinfo = sql.get_fed_info(is_fed_id)
- if getinfo is False:
- update.effective_message.reply_text("This federation does not exist.")
- return
- if int(getinfo["owner"]) == int(user.id) or int(user.id) == OWNER_ID:
- fed_id = is_fed_id
- else:
- update.effective_message.reply_text("Only federation owners can do this!")
- return
- else:
- update.effective_message.reply_text("What should I delete?")
- return
-
- if is_user_fed_owner(fed_id, user.id) is False:
- update.effective_message.reply_text("Only federation owners can do this!")
- return
-
- update.effective_message.reply_text(
- f"""You sure you want to delete your federation? This cannot be reverted, you will lose your entire ban list, and '{getinfo["fname"]}' will be permanently lost.""",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⚠️ Delete Federation ⚠️",
- callback_data=f"rmfed_{fed_id}",
- )
- ],
- [
- InlineKeyboardButton(
- text="Cancel", callback_data="rmfed_cancel"
- )
- ],
- ]
- ),
- )
-
-
-def rename_fed(update, context):
- user = update.effective_user
- msg = update.effective_message
- args = msg.text.split(None, 2)
-
- if len(args) < 3:
- return msg.reply_text("usage: /renamefed ")
-
- fed_id, newname = args[1], args[2]
- verify_fed = sql.get_fed_info(fed_id)
-
- if not verify_fed:
- return msg.reply_text("This fed not exist in my database!")
-
- if is_user_fed_owner(fed_id, user.id):
- sql.rename_fed(fed_id, user.id, newname)
- msg.reply_text(f"Successfully renamed your fed name to {newname}!")
- else:
- msg.reply_text("Only federation owner can do this!")
-
-
-def fed_chat(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- update.effective_user
- fed_id = sql.get_fed_id(chat.id)
-
- user_id = update.effective_message.from_user.id
- if not is_user_admin(update.effective_chat, user_id):
- update.effective_message.reply_text(
- "You must be an admin to execute this command",
- )
- return
-
- if not fed_id:
- update.effective_message.reply_text("This group is not in any federation!")
- return
-
- update.effective_user
- chat = update.effective_chat
- info = sql.get_fed_info(fed_id)
-
- text = f'This group is part of the following federation:\n{info["fname"]} (ID: {fed_id}
)'
- update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
-
-
-def join_fed(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- message = update.effective_message
- administrators = chat.get_administrators()
- fed_id = sql.get_fed_id(chat.id)
-
- if user.id not in DRAGONS:
- for admin in administrators:
- if str(admin.user.id) != str(user.id):
- status = admin.status
- if status == "creator":
- update.effective_message.reply_text(
- "Only group creators can use this command!",
- )
- return
- if fed_id:
- message.reply_text("You cannot join two federations from one chat")
- return
-
- if len(args) >= 1:
- getfed = sql.search_fed_by_id(args[0])
- if getfed is False:
- message.reply_text("Please enter a valid federation ID")
- return
-
- x = sql.chat_join_fed(args[0], chat.title, chat.id)
- if not x:
- message.reply_text(
- f"Failed to join federation! Please contact @{SUPPORT_CHAT} should this problem persist!",
- )
- return
-
- get_fedlog = sql.get_fed_log(args[0])
- if get_fedlog and ast.literal_eval(get_fedlog):
- bot.send_message(
- get_fedlog,
- f'Chat *{chat.title}* has joined the federation *{getfed["fname"]}*',
- parse_mode="markdown",
- )
-
-
-def leave_fed(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our PM!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- fed_info = sql.get_fed_info(fed_id)
-
- # administrators = chat.get_administrators().status
- getuser = bot.get_chat_member(chat.id, user.id).status
- if getuser in "creator" or user.id in DRAGONS:
- if sql.chat_leave_fed(chat.id) is True:
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and ast.literal_eval(get_fedlog):
- bot.send_message(
- get_fedlog,
- f'Chat *{chat.title}* has left the federation *{fed_info["fname"]}*',
- parse_mode="markdown",
- )
- send_message(
- update.effective_message,
- f'This group has left the federation {fed_info["fname"]}!',
- )
- else:
- update.effective_message.reply_text(
- "How can you leave a federation that you never joined?!",
- )
- else:
- update.effective_message.reply_text("Only group creators can use this command!")
-
-
-def user_join_fed(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- msg = update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
-
- if is_user_fed_owner(fed_id, user.id) or user.id in DRAGONS:
- user_id = extract_user(msg, args)
- if user_id:
- user = bot.get_chat(user_id)
- elif not msg.reply_to_message and not args:
- user = msg.from_user
- elif not msg.reply_to_message and (
- not args
- or (
- len(args) >= 1
- and not args[0].startswith("@")
- and not args[0].isdigit()
- and not msg.parse_entities([MessageEntity.TEXT_MENTION])
- )
- ):
- msg.reply_text("I cannot extract user from this message")
- return
- else:
- LOGGER.warning("error")
- getuser = sql.search_user_in_fed(fed_id, user_id)
- fed_id = sql.get_fed_id(chat.id)
- info = sql.get_fed_info(fed_id)
- get_owner = ast.literal_eval(info["fusers"])["owner"]
- get_owner = bot.get_chat(get_owner).id
- if user_id == get_owner:
- update.effective_message.reply_text(
- "You do know that the user is the federation owner, right? RIGHT?",
- )
- return
- if getuser:
- update.effective_message.reply_text(
- "I cannot promote users who are already federation admins! Can remove them if you want!",
- )
- return
- if user_id == bot.id:
- update.effective_message.reply_text(
- "I already am a federation admin in all federations!",
- )
- return
- if res := sql.user_join_fed(fed_id, user_id):
- update.effective_message.reply_text("Successfully Promoted!")
- else:
- update.effective_message.reply_text("Failed to promote!")
- else:
- update.effective_message.reply_text("Only federation owners can do this!")
-
-
-def user_demote_fed(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
-
- if is_user_fed_owner(fed_id, user.id):
- msg = update.effective_message
- user_id = extract_user(msg, args)
- if user_id:
- user = bot.get_chat(user_id)
-
- elif not msg.reply_to_message and not args:
- user = msg.from_user
-
- elif not msg.reply_to_message and (
- not args
- or (
- len(args) >= 1
- and not args[0].startswith("@")
- and not args[0].isdigit()
- and not msg.parse_entities([MessageEntity.TEXT_MENTION])
- )
- ):
- msg.reply_text("I cannot extract user from this message")
- return
- else:
- LOGGER.warning("error")
-
- if user_id == bot.id:
- update.effective_message.reply_text(
- "The thing you are trying to demote me from will fail to work without me! Just saying.",
- )
- return
-
- if sql.search_user_in_fed(fed_id, user_id) is False:
- update.effective_message.reply_text(
- "I cannot demote people who are not federation admins!",
- )
- return
-
- res = sql.user_demote_fed(fed_id, user_id)
- if res is True:
- update.effective_message.reply_text("Demoted from a Fed Admin!")
- else:
- update.effective_message.reply_text("Demotion failed!")
- else:
- update.effective_message.reply_text("Only federation owners can do this!")
- return
-
-
-def fed_info(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- if args:
- fed_id = args[0]
- else:
- if chat.type == "private":
- send_message(
- update.effective_message,
- "You need to provide me a fedid to check fedinfo in my pm.",
- )
- return
- fed_id = sql.get_fed_id(chat.id)
- if not fed_id:
- send_message(
- update.effective_message,
- "This group is not in any federation!",
- )
- return
- info = sql.get_fed_info(fed_id)
- if is_user_fed_admin(fed_id, user.id) is False:
- update.effective_message.reply_text("Only a federation admin can do this!")
- return
-
- owner = bot.get_chat(info["owner"])
- try:
- owner_name = f"{owner.first_name} {owner.last_name}"
- except Exception:
- owner_name = owner.first_name
- FEDADMIN = sql.all_fed_users(fed_id)
- TotalAdminFed = len(FEDADMIN)
-
- user = update.effective_user
- chat = update.effective_chat
- info = sql.get_fed_info(fed_id)
-
- text = f"ℹ️ Federation Information:\nFedID: {fed_id}
"
- text += f'\nName: {info["fname"]}'
- text += f"\nCreator: {mention_html(owner.id, owner_name)}"
- text += f"\nAll Admins: {TotalAdminFed}
"
- getfban = sql.get_all_fban_users(fed_id)
- text += f"\nTotal banned users: {len(getfban)}
"
- getfchat = sql.all_fed_chats(fed_id)
- text += f"\nNumber of groups in this federation: {len(getfchat)}
"
-
- update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
-
-
-def fed_admin(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
-
- if not fed_id:
- update.effective_message.reply_text("This group is not in any federation!")
- return
-
- if is_user_fed_admin(fed_id, user.id) is False:
- update.effective_message.reply_text("Only federation admins can do this!")
- return
-
- user = update.effective_user
- chat = update.effective_chat
- info = sql.get_fed_info(fed_id)
-
- text = f'Federation Admin {info["fname"]}:\n\n' + "👑 Owner:\n"
- owner = bot.get_chat(info["owner"])
- try:
- owner_name = f"{owner.first_name} {owner.last_name}"
- except Exception:
- owner_name = owner.first_name
- text += f" • {mention_html(owner.id, owner_name)}\n"
-
- members = sql.all_fed_members(fed_id)
- if len(members) == 0:
- text += "\n🔱 There are no admins in this federation"
- else:
- text += "\n🔱 Admin:\n"
- for x in members:
- user = bot.get_chat(x)
- text += f" • {mention_html(user.id, user.first_name)}\n"
-
- update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
-
-
-def fed_ban(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
-
- if not fed_id:
- update.effective_message.reply_text(
- "This group is not a part of any federation!",
- )
- return
-
- info = sql.get_fed_info(fed_id)
- getfednotif = sql.user_feds_report(info["owner"])
-
- if is_user_fed_admin(fed_id, user.id) is False:
- update.effective_message.reply_text("Only federation admins can do this!")
- return
-
- message = update.effective_message
-
- user_id, reason = extract_unt_fedban(message, args)
-
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, user_id)
-
- if not user_id:
- message.reply_text("You don't seem to be referring to a user")
- return
-
- if user_id == bot.id:
- message.reply_text(
- "What is funnier than kicking the group creator? Self sacrifice.",
- )
- return
-
- if is_user_fed_owner(fed_id, user_id) is True:
- message.reply_text("Why did you try the federation fban?")
- return
-
- if is_user_fed_admin(fed_id, user_id) is True:
- message.reply_text("He is a federation admin, I can't fban him.")
- return
-
- if user_id == OWNER_ID:
- message.reply_text("Disaster level God cannot be fed banned!")
- return
-
- if int(user_id) in DRAGONS:
- message.reply_text("Dragons cannot be fed banned!")
- return
-
- if int(user_id) in TIGERS:
- message.reply_text("Tigers cannot be fed banned!")
- return
-
- if int(user_id) in WOLVES:
- message.reply_text("Wolves cannot be fed banned!")
- return
-
- if user_id in [777000, 1087968824]:
- message.reply_text("Fool! You can't attack Telegram's native tech!")
- return
-
- try:
- user_chat = bot.get_chat(user_id)
- isvalid = True
- fban_user_id = user_chat.id
- fban_user_name = user_chat.first_name
- fban_user_lname = user_chat.last_name
- fban_user_uname = user_chat.username
- except BadRequest as excp:
- if not str(user_id).isdigit():
- send_message(update.effective_message, excp.message)
- return
- if len(str(user_id)) != 9:
- send_message(update.effective_message, "That's so not a user!")
- return
- isvalid = False
- fban_user_id = int(user_id)
- fban_user_name = f"user({user_id})"
- fban_user_lname = None
- fban_user_uname = None
-
- if isvalid and user_chat.type != "private":
- send_message(update.effective_message, "That's so not a user!")
- return
-
- if isvalid:
- user_target = mention_html(fban_user_id, fban_user_name)
- else:
- user_target = fban_user_name
-
- if fban:
- fed_name = info["fname"]
- # https://t.me/OnePunchSupport/41606 // https://t.me/OnePunchSupport/41619
- # starting = "The reason fban is replaced for {} in the Federation {}.".format(user_target, fed_name)
- # send_message(update.effective_message, starting, parse_mode=ParseMode.HTML)
-
- # if reason == "":
- # reason = "No reason given."
-
- temp = sql.un_fban_user(fed_id, fban_user_id)
- if not temp:
- message.reply_text("Failed to update the reason for fedban!")
- return
- x = sql.fban_user(
- fed_id,
- fban_user_id,
- fban_user_name,
- fban_user_lname,
- fban_user_uname,
- reason,
- int(time.time()),
- )
- if not x:
- message.reply_text(
- f"Failed to ban from the federation! If this problem continues, contact @{SUPPORT_CHAT}.",
- )
- return
-
- fed_chats = sql.all_fed_chats(fed_id)
- # Will send to current chat
- bot.send_message(
- chat.id,
- f"FedBan reason updated\nFederation: {fed_name}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
\nReason: {reason}",
- parse_mode="HTML",
- )
- # Send message to owner if fednotif is enabled
- if getfednotif:
- bot.send_message(
- info["owner"],
- f"FedBan reason updated\nFederation: {fed_name}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
\nReason: {reason}",
- parse_mode="HTML",
- )
- # If fedlog is set, then send message, except fedlog is current chat
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and int(get_fedlog) != int(chat.id):
- bot.send_message(
- get_fedlog,
- f"FedBan reason updated\nFederation: {fed_name}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
\nReason: {reason}",
- parse_mode="HTML",
- )
- for fedschat in fed_chats:
- try:
- # Do not spam all fed chats
- """
- bot.send_message(chat, "FedBan reason updated" \
- "\nFederation: {}" \
- "\nFederation Admin: {}" \
- "\nUser: {}" \
- "\nUser ID: {}
" \
- "\nReason: {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason), parse_mode="HTML")
- """
- bot.ban_chat_member(fedschat, fban_user_id)
- except BadRequest as excp:
- if excp.message in FBAN_ERRORS:
- try:
- dispatcher.bot.getChat(fedschat)
- except Unauthorized:
- sql.chat_leave_fed(fedschat)
- LOGGER.info(
- f'Chat {fedschat} has leave fed {info["fname"]} because I was kicked'
- )
- continue
- elif excp.message == "User_id_invalid":
- break
- else:
- LOGGER.warning(f"Could not fban on {chat} because: {excp.message}")
- except TelegramError:
- pass
- # Also do not spam all fed admins
- """
- send_to_list(bot, FEDADMIN,
- "FedBan reason updated" \
- "\nFederation: {}" \
- "\nFederation Admin: {}" \
- "\nUser: {}" \
- "\nUser ID: {}
" \
- "\nReason: {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason),
- html=True)
- """
-
- if subscriber := list(sql.get_subscriber(fed_id)):
- for fedsid in subscriber:
- all_fedschat = sql.all_fed_chats(fedsid)
- for fedschat in all_fedschat:
- try:
- bot.ban_chat_member(fedschat, fban_user_id)
- except BadRequest as excp:
- if excp.message in FBAN_ERRORS:
- try:
- dispatcher.bot.getChat(fedschat)
- except Unauthorized:
- targetfed_id = sql.get_fed_id(fedschat)
- sql.unsubs_fed(fed_id, targetfed_id)
- LOGGER.info(
- f'Chat {fedschat} has unsub fed {info["fname"]} because I was kicked'
- )
- continue
- elif excp.message == "User_id_invalid":
- break
- else:
- LOGGER.warning(f"Unable to fban on {fedschat} because: {excp.message}")
- except TelegramError:
- pass
- # send_message(update.effective_message, "Fedban Reason has been updated.")
- return
-
- fed_name = info["fname"]
-
- # starting = "Starting a federation ban for {} in the Federation {}.".format(
- # user_target, fed_name)
- # update.effective_message.reply_text(starting, parse_mode=ParseMode.HTML)
-
- # if reason == "":
- # reason = "No reason given."
-
- x = sql.fban_user(
- fed_id,
- fban_user_id,
- fban_user_name,
- fban_user_lname,
- fban_user_uname,
- reason,
- int(time.time()),
- )
- if not x:
- message.reply_text(
- f"Failed to ban from the federation! If this problem continues, contact @{SUPPORT_CHAT}.",
- )
- return
-
- fed_chats = sql.all_fed_chats(fed_id)
- # Will send to current chat
- bot.send_message(
- chat.id,
- f"New FedBan\nFederation: {fed_name}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
\nReason: {reason}",
- parse_mode="HTML",
- )
- # Send message to owner if fednotif is enabled
- if getfednotif:
- bot.send_message(
- info["owner"],
- f"New FedBan\nFederation: {fed_name}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
\nReason: {reason}",
- parse_mode="HTML",
- )
- # If fedlog is set, then send message, except fedlog is current chat
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and int(get_fedlog) != int(chat.id):
- bot.send_message(
- get_fedlog,
- f"New FedBan\nFederation: {fed_name}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
\nReason: {reason}",
- parse_mode="HTML",
- )
- chats_in_fed = 0
- for fedschat in fed_chats:
- chats_in_fed += 1
- try:
- # Do not spamming all fed chats
- """
- bot.send_message(chat, "FedBan reason updated" \
- "\nFederation: {}" \
- "\nFederation Admin: {}" \
- "\nUser: {}" \
- "\nUser ID: {}
" \
- "\nReason: {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason), parse_mode="HTML")
- """
- bot.ban_chat_member(fedschat, fban_user_id)
- except BadRequest as excp:
- if excp.message in FBAN_ERRORS:
- pass
- elif excp.message == "User_id_invalid":
- break
- else:
- LOGGER.warning(f"Could not fban on {chat} because: {excp.message}")
- except TelegramError:
- pass
-
- # Also do not spamming all fed admins
- """
- send_to_list(bot, FEDADMIN,
- "FedBan reason updated" \
- "\nFederation: {}" \
- "\nFederation Admin: {}" \
- "\nUser: {}" \
- "\nUser ID: {}
" \
- "\nReason: {}".format(fed_name, mention_html(user.id, user.first_name), user_target, fban_user_id, reason),
- html=True)
- """
-
- if subscriber := list(sql.get_subscriber(fed_id)):
- for fedsid in subscriber:
- all_fedschat = sql.all_fed_chats(fedsid)
- for fedschat in all_fedschat:
- try:
- bot.ban_chat_member(fedschat, fban_user_id)
- except BadRequest as excp:
- if excp.message in FBAN_ERRORS:
- try:
- dispatcher.bot.getChat(fedschat)
- except Unauthorized:
- targetfed_id = sql.get_fed_id(fedschat)
- sql.unsubs_fed(fed_id, targetfed_id)
- LOGGER.info(
- f'Chat {fedschat} has unsub fed {info["fname"]} because I was kicked'
- )
- continue
- elif excp.message == "User_id_invalid":
- break
- else:
- LOGGER.warning(f"Unable to fban on {fedschat} because: {excp.message}")
- except TelegramError:
- pass
- # if chats_in_fed == 0:
- # send_message(update.effective_message, "Fedban affected 0 chats. ")
- # elif chats_in_fed > 0:
- # send_message(update.effective_message,
- # "Fedban affected {} chats. ".format(chats_in_fed))
-
-
-def unfban(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
-
- if not fed_id:
- update.effective_message.reply_text(
- "This group is not a part of any federation!",
- )
- return
-
- info = sql.get_fed_info(fed_id)
- getfednotif = sql.user_feds_report(info["owner"])
-
- if is_user_fed_admin(fed_id, user.id) is False:
- update.effective_message.reply_text("Only federation admins can do this!")
- return
-
- user_id = extract_user_fban(message, args)
- if not user_id:
- message.reply_text("You do not seem to be referring to a user.")
- return
-
- try:
- user_chat = bot.get_chat(user_id)
- isvalid = True
- fban_user_id = user_chat.id
- fban_user_name = user_chat.first_name
- user_chat.last_name
- user_chat.username
- except BadRequest as excp:
- if not str(user_id).isdigit():
- send_message(update.effective_message, excp.message)
- return
- if len(str(user_id)) != 9:
- send_message(update.effective_message, "That's so not a user!")
- return
- isvalid = False
- fban_user_id = int(user_id)
- fban_user_name = f"user({user_id})"
-
- if isvalid and user_chat.type != "private":
- message.reply_text("That's so not a user!")
- return
-
- if isvalid:
- user_target = mention_html(fban_user_id, fban_user_name)
- else:
- user_target = fban_user_name
-
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, fban_user_id)
- if fban is False:
- message.reply_text("This user is not fbanned!")
- return
-
- update.effective_user
-
- # message.reply_text("I'll give {} another chance in this federation".format(user_chat.first_name))
-
- chat_list = sql.all_fed_chats(fed_id)
- # Will send to current chat
- bot.send_message(
- chat.id,
- f'Un-FedBan\nFederation: {info["fname"]}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
',
- parse_mode="HTML",
- )
- # Send message to owner if fednotif is enabled
- if getfednotif:
- bot.send_message(
- info["owner"],
- f'Un-FedBan\nFederation: {info["fname"]}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
',
- parse_mode="HTML",
- )
- # If fedlog is set, then send message, except fedlog is current chat
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and int(get_fedlog) != int(chat.id):
- bot.send_message(
- get_fedlog,
- f'Un-FedBan\nFederation: {info["fname"]}\nFederation Admin: {mention_html(user.id, user.first_name)}\nUser: {user_target}\nUser ID: {fban_user_id}
',
- parse_mode="HTML",
- )
- unfbanned_in_chats = 0
- for fedchats in chat_list:
- unfbanned_in_chats += 1
- try:
- member = bot.get_chat_member(fedchats, user_id)
- if member.status == "kicked":
- bot.unban_chat_member(fedchats, user_id)
- # Do not spamming all fed chats
- """
- bot.send_message(chat, "Un-FedBan" \
- "\nFederation: {}" \
- "\nFederation Admin: {}" \
- "\nUser: {}" \
- "\nUser ID: {}
".format(info['fname'], mention_html(user.id, user.first_name), user_target, fban_user_id), parse_mode="HTML")
- """
- except BadRequest as excp:
- if excp.message in UNFBAN_ERRORS:
- pass
- elif excp.message == "User_id_invalid":
- break
- else:
- LOGGER.warning(f"Could not fban on {chat} because: {excp.message}")
- except TelegramError:
- pass
-
- try:
- x = sql.un_fban_user(fed_id, user_id)
- if not x:
- send_message(
- update.effective_message,
- "Un-fban failed, this user may already be un-fedbanned!",
- )
- return
- except Exception:
- pass
-
- if subscriber := list(sql.get_subscriber(fed_id)):
- for fedsid in subscriber:
- all_fedschat = sql.all_fed_chats(fedsid)
- for fedschat in all_fedschat:
- try:
- bot.unban_chat_member(fedchats, user_id)
- except BadRequest as excp:
- if excp.message in FBAN_ERRORS:
- try:
- dispatcher.bot.getChat(fedschat)
- except Unauthorized:
- targetfed_id = sql.get_fed_id(fedschat)
- sql.unsubs_fed(fed_id, targetfed_id)
- LOGGER.info(
- f'Chat {fedschat} has unsub fed {info["fname"]} because I was kicked'
- )
- continue
- elif excp.message == "User_id_invalid":
- break
- else:
- LOGGER.warning(f"Unable to fban on {fedschat} because: {excp.message}")
- except TelegramError:
- pass
-
- if unfbanned_in_chats == 0:
- send_message(
- update.effective_message,
- "This person has been un-fbanned in 0 chats.",
- )
- if unfbanned_in_chats > 0:
- send_message(
- update.effective_message,
- f"This person has been un-fbanned in {unfbanned_in_chats} chats.",
- )
- # Also do not spamming all fed admins
- """
- FEDADMIN = sql.all_fed_users(fed_id)
- for x in FEDADMIN:
- getreport = sql.user_feds_report(x)
- if getreport is False:
- FEDADMIN.remove(x)
- send_to_list(bot, FEDADMIN,
- "Un-FedBan" \
- "\nFederation: {}" \
- "\nFederation Admin: {}" \
- "\nUser: {}" \
- "\nUser ID: {}
".format(info['fname'], mention_html(user.id, user.first_name),
- mention_html(user_chat.id, user_chat.first_name),
- user_chat.id),
- html=True)
- """
-
-
-def set_frules(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
-
- if not fed_id:
- update.effective_message.reply_text("This group is not in any federation!")
- return
-
- if is_user_fed_admin(fed_id, user.id) is False:
- update.effective_message.reply_text("Only fed admins can do this!")
- return
-
- if len(args) >= 1:
- msg = update.effective_message
- raw_text = msg.text
- args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args
- if len(args) == 2:
- txt = args[1]
- offset = len(txt) - len(raw_text) # set correct offset relative to command
- markdown_rules = markdown_parser(
- txt,
- entities=msg.parse_entities(),
- offset=offset,
- )
- x = sql.set_frules(fed_id, markdown_rules)
- if not x:
- update.effective_message.reply_text(
- f"Whoa! There was an error while setting federation rules! If you wondered why please ask it in @{SUPPORT_CHAT}!",
- )
- return
-
- rules = sql.get_fed_info(fed_id)["frules"]
- getfed = sql.get_fed_info(fed_id)
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and ast.literal_eval(get_fedlog):
- bot.send_message(
- get_fedlog,
- f'*{user.first_name}* has updated federation rules for fed *{getfed["fname"]}*',
- parse_mode="markdown",
- )
- update.effective_message.reply_text(f"Rules have been changed to :\n{rules}!")
- else:
- update.effective_message.reply_text("Please write rules to set this up!")
-
-
-def get_frules(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- if not fed_id:
- update.effective_message.reply_text("This group is not in any federation!")
- return
-
- rules = sql.get_frules(fed_id)
- text = "*Rules in this fed:*\n"
- text += rules
- update.effective_message.reply_text(text, parse_mode=ParseMode.MARKDOWN)
-
-
-def fed_broadcast(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- msg = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- if args:
- chat = update.effective_chat
- fed_id = sql.get_fed_id(chat.id)
- fedinfo = sql.get_fed_info(fed_id)
- if is_user_fed_owner(fed_id, user.id) is False:
- update.effective_message.reply_text("Only federation owners can do this!")
- return
- # Parsing md
- raw_text = msg.text
- args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args
- txt = args[1]
- offset = len(txt) - len(raw_text) # set correct offset relative to command
- text_parser = markdown_parser(txt, entities=msg.parse_entities(), offset=offset)
- text = text_parser
- try:
- broadcaster = user.first_name
- except Exception:
- broadcaster = f"{user.first_name} {user.last_name}"
- text += f"\n\n- {mention_markdown(user.id, broadcaster)}"
- chat_list = sql.all_fed_chats(fed_id)
- failed = 0
- for chat in chat_list:
- title = f'*New broadcast from Fed {fedinfo["fname"]}*\n'
- try:
- bot.sendMessage(chat, title + text, parse_mode="markdown")
- except TelegramError:
- try:
- dispatcher.bot.getChat(chat)
- except Unauthorized:
- failed += 1
- sql.chat_leave_fed(chat)
- LOGGER.info(
- f'Chat {chat} has left fed {fedinfo["fname"]} because I was punched'
- )
- continue
- failed += 1
- LOGGER.warning(f"Couldn't send broadcast to {str(chat)}")
-
- send_text = "The federation broadcast is complete"
- if failed >= 1:
- send_text += f"{failed} the group failed to receive the message, probably because it left the Federation."
- update.effective_message.reply_text(send_text)
-
-
-def fed_ban_list(update: Update, context: CallbackContext):
- bot, args, chat_data = context.bot, context.args, context.chat_data
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- info = sql.get_fed_info(fed_id)
-
- if not fed_id:
- update.effective_message.reply_text(
- "This group is not a part of any federation!",
- )
- return
-
- if is_user_fed_owner(fed_id, user.id) is False:
- update.effective_message.reply_text("Only Federation owners can do this!")
- return
-
- user = update.effective_user
- chat = update.effective_chat
- getfban = sql.get_all_fban_users(fed_id)
- if len(getfban) == 0:
- update.effective_message.reply_text(
- f'The federation ban list of {info["fname"]} is empty',
- parse_mode=ParseMode.HTML,
- )
- return
-
- if args:
- if args[0] == "json":
- jam = time.time()
- new_jam = jam + 1800
- cek = get_chat(chat.id, chat_data)
- if cek.get("status") and jam <= int(cek.get("value")):
- waktu = time.strftime(
- "%H:%M:%S %d/%m/%Y",
- time.localtime(cek.get("value")),
- )
- update.effective_message.reply_text(
- f"You can backup your data once every 30 minutes!\nYou can back up data again at `{waktu}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- if user.id not in DRAGONS:
- put_chat(chat.id, new_jam, chat_data)
- backups = ""
- for users in getfban:
- getuserinfo = sql.get_all_fban_users_target(fed_id, users)
- json_parser = {
- "user_id": users,
- "first_name": getuserinfo["first_name"],
- "last_name": getuserinfo["last_name"],
- "user_name": getuserinfo["user_name"],
- "reason": getuserinfo["reason"],
- }
- backups += json.dumps(json_parser)
- backups += "\n"
- with BytesIO(str.encode(backups)) as output:
- output.name = "Exon_fbanned_users.json"
- update.effective_message.reply_document(
- document=output,
- filename="Exon_fbanned_users.json",
- caption=f'Total {len(getfban)} User are blocked by the Federation {info["fname"]}.',
- )
- return
- if args[0] == "csv":
- jam = time.time()
- new_jam = jam + 1800
- cek = get_chat(chat.id, chat_data)
- if cek.get("status") and jam <= int(cek.get("value")):
- waktu = time.strftime(
- "%H:%M:%S %d/%m/%Y",
- time.localtime(cek.get("value")),
- )
- update.effective_message.reply_text(
- f"You can back up data once every 30 minutes!\nYou can back up data again at `{waktu}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- if user.id not in DRAGONS:
- put_chat(chat.id, new_jam, chat_data)
- backups = "id,firstname,lastname,username,reason\n"
- for users in getfban:
- getuserinfo = sql.get_all_fban_users_target(fed_id, users)
- backups += (
- "{user_id},{first_name},{last_name},{user_name},{reason}".format(
- user_id=users,
- first_name=getuserinfo["first_name"],
- last_name=getuserinfo["last_name"],
- user_name=getuserinfo["user_name"],
- reason=getuserinfo["reason"],
- )
- )
- backups += "\n"
- with BytesIO(str.encode(backups)) as output:
- output.name = "Exon_fbanned_users.csv"
- update.effective_message.reply_document(
- document=output,
- filename="Exon_fbanned_users.csv",
- caption=f'Total {len(getfban)} User are blocked by Federation {info["fname"]}.',
- )
- return
-
- text = f'{len(getfban)} users have been banned from the federation {info["fname"]}:\n'
- for users in getfban:
- getuserinfo = sql.get_all_fban_users_target(fed_id, users)
- if getuserinfo is False:
- text = f'There are no users banned from the federation {info["fname"]}'
- break
- user_name = getuserinfo["first_name"]
- if getuserinfo["last_name"]:
- user_name += " " + getuserinfo["last_name"]
- text += f" • {mention_html(users, user_name)} ({users}
)\n"
-
- try:
- update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
- except Exception:
- jam = time.time()
- new_jam = jam + 1800
- cek = get_chat(chat.id, chat_data)
- if cek.get("status") and jam <= int(cek.get("value")):
- waktu = time.strftime(
- "%H:%M:%S %d/%m/%Y",
- time.localtime(cek.get("value")),
- )
- update.effective_message.reply_text(
- f"You can back up data once every 30 minutes!\nYou can back up data again at `{waktu}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- if user.id not in DRAGONS:
- put_chat(chat.id, new_jam, chat_data)
- cleanr = re.compile("<.*?>")
- cleantext = re.sub(cleanr, "", text)
- with BytesIO(str.encode(cleantext)) as output:
- output.name = "fbanlist.txt"
- update.effective_message.reply_document(
- document=output,
- filename="fbanlist.txt",
- caption=f'The following is a list of users who are currently fbanned in the Federation {info["fname"]}.',
- )
-
-
-def fed_notif(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- msg = update.effective_message
- fed_id = sql.get_fed_id(chat.id)
-
- if not fed_id:
- update.effective_message.reply_text(
- "This group is not a part of any federation!",
- )
- return
-
- if args:
- if args[0] in ("yes", "on"):
- sql.set_feds_setting(user.id, True)
- msg.reply_text(
- "Reporting Federation back up! Every user who is fban / unfban you will be notified via PM.",
- )
- elif args[0] in ("no", "off"):
- sql.set_feds_setting(user.id, False)
- msg.reply_text(
- "Reporting Federation has stopped! Every user who is fban / unfban you will not be notified via PM.",
- )
- else:
- msg.reply_text("Please enter `on`/`off`", parse_mode="markdown")
- else:
- getreport = sql.user_feds_report(user.id)
- msg.reply_text(
- f"Your current Federation report preferences: `{getreport}`",
- parse_mode="markdown",
- )
-
-
-def fed_chats(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- info = sql.get_fed_info(fed_id)
-
- if not fed_id:
- update.effective_message.reply_text(
- "This group is not a part of any federation!",
- )
- return
-
- if is_user_fed_admin(fed_id, user.id) is False:
- update.effective_message.reply_text("Only federation admins can do this!")
- return
-
- getlist = sql.all_fed_chats(fed_id)
- if len(getlist) == 0:
- update.effective_message.reply_text(
- f'No users are fbanned from the federation {info["fname"]}',
- parse_mode=ParseMode.HTML,
- )
- return
-
- text = f'New chat joined the federation {info["fname"]}:\n'
- for chats in getlist:
- try:
- chat_name = dispatcher.bot.getChat(chats).title
- except Unauthorized:
- sql.chat_leave_fed(chats)
- LOGGER.info(f'Chat {chats} has leave fed {info["fname"]} because I was kicked')
- continue
- text += f" • {chat_name} ({chats}
)\n"
-
- try:
- update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
- except Exception:
- cleanr = re.compile("<.*?>")
- cleantext = re.sub(cleanr, "", text)
- with BytesIO(str.encode(cleantext)) as output:
- output.name = "fedchats.txt"
- update.effective_message.reply_document(
- document=output,
- filename="fedchats.txt",
- caption=f'Here is a list of all the chats that joined the federation {info["fname"]}.',
- )
-
-
-def fed_import_bans(update: Update, context: CallbackContext):
- bot, chat_data = context.bot, context.chat_data
- chat = update.effective_chat
- user = update.effective_user
- msg = update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- sql.get_fed_info(fed_id)
- getfed = sql.get_fed_info(fed_id)
-
- if not fed_id:
- update.effective_message.reply_text(
- "This group is not a part of any federation!",
- )
- return
-
- if is_user_fed_owner(fed_id, user.id) is False:
- update.effective_message.reply_text("Only Federation owners can do this!")
- return
-
- if msg.reply_to_message and msg.reply_to_message.document:
- jam = time.time()
- new_jam = jam + 1800
- cek = get_chat(chat.id, chat_data)
- if cek.get("status") and jam <= int(cek.get("value")):
- waktu = time.strftime(
- "%H:%M:%S %d/%m/%Y",
- time.localtime(cek.get("value")),
- )
- update.effective_message.reply_text(
- f"You can get your data once every 30 minutes!\nYou can get data again at `{waktu}`",
- parse_mode=ParseMode.MARKDOWN,
- )
- return
- if user.id not in DRAGONS:
- put_chat(chat.id, new_jam, chat_data)
- # if int(int(msg.reply_to_message.document.file_size)/1024) >= 200:
- # msg.reply_text("This file is too big!")
- # return
- success = 0
- failed = 0
- try:
- file_info = bot.get_file(msg.reply_to_message.document.file_id)
- except BadRequest:
- msg.reply_text(
- "Try downloading and re-uploading the file, this one seems broken!",
- )
- return
- fileformat = msg.reply_to_message.document.file_name.split(".")[-1]
- if fileformat == "json":
- multi_fed_id = []
- multi_import_userid = []
- multi_import_firstname = []
- multi_import_lastname = []
- multi_import_username = []
- multi_import_reason = []
- with BytesIO() as file:
- file_info.download(out=file)
- file.seek(0)
- reading = file.read().decode("UTF-8")
- splitting = reading.split("\n")
- for x in splitting:
- if x == "":
- continue
- try:
- data = json.loads(x)
- except json.decoder.JSONDecodeError as err:
- failed += 1
- continue
- try:
- import_userid = int(data["user_id"]) # Make sure it int
- import_firstname = str(data["first_name"])
- import_lastname = str(data["last_name"])
- import_username = str(data["user_name"])
- import_reason = str(data["reason"])
- except ValueError:
- failed += 1
- continue
- # Checking user
- if import_userid == bot.id:
- failed += 1
- continue
- if is_user_fed_owner(fed_id, import_userid) is True:
- failed += 1
- continue
- if is_user_fed_admin(fed_id, import_userid) is True:
- failed += 1
- continue
- if str(import_userid) == str(OWNER_ID):
- failed += 1
- continue
- if import_userid in DRAGONS:
- failed += 1
- continue
- if import_userid in TIGERS:
- failed += 1
- continue
- if import_userid in WOLVES:
- failed += 1
- continue
- multi_fed_id.append(fed_id)
- multi_import_userid.append(str(import_userid))
- multi_import_firstname.append(import_firstname)
- multi_import_lastname.append(import_lastname)
- multi_import_username.append(import_username)
- multi_import_reason.append(import_reason)
- success += 1
- sql.multi_fban_user(
- multi_fed_id,
- multi_import_userid,
- multi_import_firstname,
- multi_import_lastname,
- multi_import_username,
- multi_import_reason,
- )
- text = f"Blocks were successfully imported. {success} people are blocked."
- if failed >= 1:
- text += f" {failed} Failed to import."
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and ast.literal_eval(get_fedlog):
- teks = f'Fed *{getfed["fname"]}* has successfully imported data. {success} banned.'
- if failed >= 1:
- teks += f" {failed} Failed to import."
- bot.send_message(get_fedlog, teks, parse_mode="markdown")
- elif fileformat == "csv":
- multi_fed_id = []
- multi_import_userid = []
- multi_import_firstname = []
- multi_import_lastname = []
- multi_import_username = []
- multi_import_reason = []
- file_info.download(f"fban_{msg.reply_to_message.document.file_id}.csv")
- with open(f"fban_{msg.reply_to_message.document.file_id}.csv", "r", encoding="utf8") as csvFile:
- reader = csv.reader(csvFile)
- for data in reader:
- try:
- import_userid = int(data[0]) # Make sure it int
- import_firstname = str(data[1])
- import_lastname = str(data[2])
- import_username = str(data[3])
- import_reason = str(data[4])
- except ValueError:
- failed += 1
- continue
- # Checking user
- if import_userid == bot.id:
- failed += 1
- continue
- if is_user_fed_owner(fed_id, import_userid) is True:
- failed += 1
- continue
- if is_user_fed_admin(fed_id, import_userid) is True:
- failed += 1
- continue
- if str(import_userid) == str(OWNER_ID):
- failed += 1
- continue
- if import_userid in DRAGONS:
- failed += 1
- continue
- if import_userid in TIGERS:
- failed += 1
- continue
- if import_userid in WOLVES:
- failed += 1
- continue
- multi_fed_id.append(fed_id)
- multi_import_userid.append(str(import_userid))
- multi_import_firstname.append(import_firstname)
- multi_import_lastname.append(import_lastname)
- multi_import_username.append(import_username)
- multi_import_reason.append(import_reason)
- success += 1
- # t = ThreadWithReturnValue(target=sql.fban_user, args=(fed_id, str(import_userid), import_firstname, import_lastname, import_username, import_reason,))
- # t.start()
- sql.multi_fban_user(
- multi_fed_id,
- multi_import_userid,
- multi_import_firstname,
- multi_import_lastname,
- multi_import_username,
- multi_import_reason,
- )
- csvFile.close()
- os.remove(f"fban_{msg.reply_to_message.document.file_id}.csv")
- text = f"Files were imported successfully. {success} people banned."
- if failed >= 1:
- text += f" {failed} Failed to import."
- get_fedlog = sql.get_fed_log(fed_id)
- if get_fedlog and ast.literal_eval(get_fedlog):
- teks = f'Fed *{getfed["fname"]}* has successfully imported data. {success} banned.'
- if failed >= 1:
- teks += f" {failed} Failed to import."
- bot.send_message(get_fedlog, teks, parse_mode="markdown")
- else:
- send_message(update.effective_message, "This file is not supported.")
- return
- send_message(update.effective_message, text)
-
-
-def del_fed_button(update: Update, context: CallbackContext):
- query = update.callback_query
- query.message.chat.id
- fed_id = query.data.split("_")[1]
-
- if fed_id == "cancel":
- query.message.edit_text("Federation deletion cancelled")
- return
-
- if getfed := sql.get_fed_info(fed_id):
- if delete := sql.del_fed(fed_id):
- query.message.edit_text(
- f'You have removed your Federation! Now all the Groups that are connected with `{getfed["fname"]}` do not have a Federation.',
- parse_mode="markdown",
- )
-
-
-def fed_stat_user(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- update.effective_chat
- update.effective_user
- msg = update.effective_message
-
- user_id = args[0] if args and args[0].isdigit() else extract_user(msg, args)
- if user_id:
- if len(args) == 2 and args[0].isdigit():
- fed_id = args[1]
- user_name, reason, fbantime = sql.get_user_fban(fed_id, str(user_id))
- if fbantime:
- fbantime = time.strftime("%d/%m/%Y", time.localtime(fbantime))
- else:
- fbantime = "Unavaiable"
- if user_name is False:
- send_message(
- update.effective_message,
- f"Fed {fed_id} not found!",
- parse_mode="markdown",
- )
- return
- if user_name == "" or user_name is None:
- user_name = "He/she"
- if not reason:
- send_message(
- update.effective_message,
- f"{user_name} is not banned in this federation!",
- )
- else:
- teks = f"{user_name} banned in this federation because:\n`{reason}`\n*Banned at:* `{fbantime}`"
- send_message(update.effective_message, teks, parse_mode="markdown")
- return
- user_name, fbanlist = sql.get_user_fbanlist(str(user_id))
- if user_name == "":
- try:
- user_name = bot.get_chat(user_id).first_name
- except BadRequest:
- user_name = "He/she"
- if not user_name or user_name is None:
- user_name = "He/she"
- if len(fbanlist) == 0:
- send_message(
- update.effective_message,
- f"{user_name} is not banned in any federation!",
- )
- return
- teks = f"{user_name} has been banned in this federation:\n"
- for x in fbanlist:
- teks += f"- `{x[0]}`: {x[1][:20]}\n"
- teks += "\nIf you want to find out more about the reasons for Fedban specifically, use /fbanstat "
- send_message(update.effective_message, teks, parse_mode="markdown")
-
- elif not msg.reply_to_message and not args:
- user_id = msg.from_user.id
- user_name, fbanlist = sql.get_user_fbanlist(user_id)
- if user_name == "":
- user_name = msg.from_user.first_name
- if len(fbanlist) == 0:
- send_message(
- update.effective_message,
- f"{user_name} is not banned in any federation!",
- )
- else:
- teks = f"{user_name} has been banned in this federation:\n"
- for x in fbanlist:
- teks += f"- `{x[0]}`: {x[1][:20]}\n"
- teks += "\nIf you want to find out more about the reasons for Fedban specifically, use /fbanstat "
- send_message(update.effective_message, teks, parse_mode="markdown")
-
- else:
- fed_id = args[0]
- fedinfo = sql.get_fed_info(fed_id)
- if not fedinfo:
- send_message(update.effective_message, f"Fed {fed_id} not found!")
- return
- name, reason, fbantime = sql.get_user_fban(fed_id, msg.from_user.id)
- if fbantime:
- fbantime = time.strftime("%d/%m/%Y", time.localtime(fbantime))
- else:
- fbantime = "Unavaiable"
- if not name:
- name = msg.from_user.first_name
- if not reason:
- send_message(
- update.effective_message,
- f"{name} is not banned in this federation",
- )
- return
- send_message(
- update.effective_message,
- f"{name} banned in this federation because:\n`{reason}`\n*Banned at:* `{fbantime}`",
- parse_mode="markdown",
- )
-
-
-def set_fed_log(update: Update, context: CallbackContext):
- args = context.args
- chat = update.effective_chat
- user = update.effective_user
- update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- if args:
- fedinfo = sql.get_fed_info(args[0])
- if not fedinfo:
- send_message(update.effective_message, "This Federation does not exist!")
- return
- isowner = is_user_fed_owner(args[0], user.id)
- if not isowner:
- send_message(
- update.effective_message,
- "Only federation creator can set federation logs.",
- )
- return
- if setlog := sql.set_fed_log(args[0], chat.id):
- send_message(
- update.effective_message,
- f'Federation log `{fedinfo["fname"]}` has been set to {chat.title}',
- parse_mode="markdown",
- )
- else:
- send_message(
- update.effective_message,
- "You have not provided your federated ID!",
- )
-
-
-def unset_fed_log(update: Update, context: CallbackContext):
- args = context.args
- chat = update.effective_chat
- user = update.effective_user
- update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- if args:
- fedinfo = sql.get_fed_info(args[0])
- if not fedinfo:
- send_message(update.effective_message, "This Federation does not exist!")
- return
- isowner = is_user_fed_owner(args[0], user.id)
- if not isowner:
- send_message(
- update.effective_message,
- "Only federation creator can set federation logs.",
- )
- return
- if setlog := sql.set_fed_log(args[0], None):
- send_message(
- update.effective_message,
- f'Federation log `{fedinfo["fname"]}` has been revoked on {chat.title}',
- parse_mode="markdown",
- )
- else:
- send_message(
- update.effective_message,
- "You have not provided your federated ID!",
- )
-
-
-def subs_feds(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- fedinfo = sql.get_fed_info(fed_id)
-
- if not fed_id:
- send_message(update.effective_message, "This group is not in any federation!")
- return
-
- if is_user_fed_owner(fed_id, user.id) is False:
- send_message(update.effective_message, "Only fed owner can do this!")
- return
-
- if args:
- getfed = sql.search_fed_by_id(args[0])
- if getfed is False:
- send_message(
- update.effective_message,
- "Please enter a valid federation id.",
- )
- return
- if subfed := sql.subs_fed(args[0], fed_id):
- send_message(
- update.effective_message,
- f'Federation `{fedinfo["fname"]}` has subscribe the federation `{getfed["fname"]}`. Every time there is a Fedban from that federation, this federation will also banned that user.',
- parse_mode="markdown",
- )
- get_fedlog = sql.get_fed_log(args[0])
- if get_fedlog and int(get_fedlog) != int(chat.id):
- bot.send_message(
- get_fedlog,
- f'Federation `{fedinfo["fname"]}` has subscribe the federation `{getfed["fname"]}`',
- parse_mode="markdown",
- )
- else:
- send_message(
- update.effective_message,
- f'Federation `{fedinfo["fname"]}` already subscribe the federation `{getfed["fname"]}`.',
- parse_mode="markdown",
- )
- else:
- send_message(
- update.effective_message,
- "You have not provided your federated ID!",
- )
-
-
-def unsubs_feds(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- fedinfo = sql.get_fed_info(fed_id)
-
- if not fed_id:
- send_message(update.effective_message, "This group is not in any federation!")
- return
-
- if is_user_fed_owner(fed_id, user.id) is False:
- send_message(update.effective_message, "Only fed owner can do this!")
- return
-
- if args:
- getfed = sql.search_fed_by_id(args[0])
- if getfed is False:
- send_message(
- update.effective_message,
- "Please enter a valid federation id.",
- )
- return
- if subfed := sql.unsubs_fed(args[0], fed_id):
- send_message(
- update.effective_message,
- f'Federation `{fedinfo["fname"]}` now unsubscribe fed `{getfed["fname"]}`.',
- parse_mode="markdown",
- )
- get_fedlog = sql.get_fed_log(args[0])
- if get_fedlog and int(get_fedlog) != int(chat.id):
- bot.send_message(
- get_fedlog,
- f'Federation `{fedinfo["fname"]}` has unsubscribe fed `{getfed["fname"]}`.',
- parse_mode="markdown",
- )
- else:
- send_message(
- update.effective_message,
- f'Federation `{fedinfo["fname"]}` is not subscribing `{getfed["fname"]}`.',
- parse_mode="markdown",
- )
- else:
- send_message(
- update.effective_message,
- "You have not provided your federated ID!",
- )
-
-
-def get_myfedsubs(update: Update, context: CallbackContext):
- context.args
- chat = update.effective_chat
- user = update.effective_user
- update.effective_message
-
- if chat.type == "private":
- send_message(
- update.effective_message,
- "This command is specific to the group, not to our pm!",
- )
- return
-
- fed_id = sql.get_fed_id(chat.id)
- fedinfo = sql.get_fed_info(fed_id)
-
- if not fed_id:
- send_message(update.effective_message, "This group is not in any federation!")
- return
-
- if is_user_fed_owner(fed_id, user.id) is False:
- send_message(update.effective_message, "Only fed owner can do this!")
- return
-
- try:
- getmy = sql.get_mysubs(fed_id)
- except Exception:
- getmy = []
-
- if not getmy:
- send_message(
- update.effective_message,
- f'Federation `{fedinfo["fname"]}` is not subscribing any federation.',
- parse_mode="markdown",
- )
- return
- listfed = f'Federation `{fedinfo["fname"]}` is subscribing federation:\n'
- for x in getmy:
- listfed += f"- `{x}`\n"
- listfed += (
- "\nTo get fed info `/fedinfo `. To unsubscribe `/unsubfed `."
- )
- send_message(update.effective_message, listfed, parse_mode="markdown")
-
-
-def get_myfeds_list(update: Update, context: CallbackContext):
- update.effective_chat
- user = update.effective_user
- update.effective_message
-
- if fedowner := sql.get_user_owner_fed_full(user.id):
- text = "*You are owner of feds:\n*"
- for f in fedowner:
- text += f'- `{f["fed_id"]}`: *{f["fed"]["fname"]}*\n'
- else:
- text = "*You are not have any feds!*"
- send_message(update.effective_message, text, parse_mode="markdown")
-
-
-def is_user_fed_admin(fed_id, user_id):
- fed_admins = sql.all_fed_users(fed_id)
- if fed_admins is False:
- return False
- return int(user_id) in fed_admins or int(user_id) == OWNER_ID
-
-
-def is_user_fed_owner(fed_id, user_id):
- getsql = sql.get_fed_info(fed_id)
- if getsql is False:
- return False
- getfedowner = ast.literal_eval(getsql["fusers"])
- if getfedowner is None or getfedowner is False:
- return False
- getfedowner = getfedowner["owner"]
- return str(user_id) == getfedowner or int(user_id) == OWNER_ID
-
-
-# There's no handler for this yet, but updating for v12 in case its used
-def welcome_fed(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- fed_id = sql.get_fed_id(chat.id)
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, user.id)
- if fban:
- update.effective_message.reply_text(
- "This user is banned in current federation! I will remove him.",
- )
- bot.ban_chat_member(chat.id, user.id)
- return True
- return False
-
-
-def __stats__():
- all_fbanned = sql.get_all_fban_users_global()
- all_feds = sql.get_all_feds_users_global()
- return f"× {len(all_fbanned)} banned users across {len(all_feds)} Federations"
-
-
-def __user_info__(user_id, chat_id):
- if fed_id := sql.get_fed_id(chat_id):
- fban, fbanreason, fbantime = sql.get_fban_user(fed_id, user_id)
- info = sql.get_fed_info(fed_id)
- infoname = info["fname"]
-
- if int(info["owner"]) == user_id:
- text = f"Federation owner of: {infoname}."
- elif is_user_fed_admin(fed_id, user_id):
- text = f"Federation admin of: {infoname}."
-
- elif fban:
- text = f"Federation banned: Yes\nReason: {fbanreason}"
- else:
- text = "Federation banned: No"
- else:
- text = ""
- return text
-
-
-# Temporary data
-def put_chat(chat_id, value, chat_data):
- # print(chat_data)
- status = value is not False
- chat_data[chat_id] = {"federation": {"status": status, "value": value}}
-
-
-def get_chat(chat_id, chat_data):
- # print(chat_data)
- try:
- return chat_data[chat_id]["federation"]
- except KeyError:
- return {"status": False, "value": False}
-
-
-def fed_owner_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- """*👑 Fed Owner Only:*
- ❂ `/newfed `*:* Creates a Federation, One allowed per user
- ❂ `/renamefed `*:* Renames the fed id to a new name
- ❂ `/delfed `*:* Delete a Federation, and any information related to it. Will not cancel blocked users
- ❂ `/fpromote `*:* Assigns the user as a federation admin. Enables all commands for the user under `Fed Admins`
- ❂ `/fdemote `*:* Drops the User from the admin Federation to a normal User
- ❂ `/subfed `*:* Subscribes to a given fed ID, bans from that subscribed fed will also happen in your fed
- ❂ `/unsubfed `*:* Unsubscribes to a given fed ID
- ❂ `/setfedlog `*:* Sets the group as a fed log report base for the federation
- ❂ `/unsetfedlog `*:* Removed the group as a fed log report base for the federation
- ❂ `/fbroadcast `*:* Broadcasts a messages to all groups that have joined your fed
- ❂ `/fedsubs`*:* Shows the feds your group is subscribed to `(broken rn)`""",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def fed_admin_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- """*🔱 Fed Admins:*
- ❂ `/fban `*:* Fed bans a user
- ❂ `/unfban `*:* Removes a user from a fed ban
- ❂ `/fedinfo `*:* Information about the specified Federation
- ❂ `/joinfed `*:* Join the current chat to the Federation. Only chat owners can do this. Every chat can only be in one Federation
- ❂ `/leavefed `*:* Leave the Federation given. Only chat owners can do this
- ❂ `/setfrules `*:* Arrange Federation rules
- ❂ `/fedadmins`*:* Show Federation admin
- ❂ `/fbanlist`*:* Displays all users who are victimized at the Federation at this time
- ❂ `/fedchats`*:* Get all the chats that are connected in the Federation
- ❂ `/chatfed `*:* See the Federation in the current chat\n""",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def fed_user_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- """*🎩 Any user:*
-
-❂ /fbanstat*:* Shows if you/or the user you are replying to or their username is fbanned somewhere or not
-❂ /fednotif *:* Federation settings not in PM when there are users who are fbaned/unfbanned
-❂ /frules*:* See Federation regulations\n""",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-__mod_name__ = "𝐅ᴇᴅs "
-
-from Exon.modules.language import gs
-
-
-def fed_owner_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "FED_OWNER_HELP"),
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def fed_admin_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "FED_ADMIN_HELP"),
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def fed_user_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "FED_USER_HELP"),
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-@Exoncallback(pattern=r"fed_help_")
-def fed_help(update: Update, context: CallbackContext):
- query = update.callback_query
- bot = context.bot
- help_info = query.data.split("fed_help_")[1]
- if help_info == "owner":
- help_text = gs(update.effective_chat.id, "FED_OWNER_HELP")
- elif help_info == "admin":
- help_text = gs(update.effective_chat.id, "FED_ADMIN_HELP")
- elif help_info == "user":
- help_text = gs(update.effective_chat.id, "FED_USER_HELP")
- query.message.edit_text(
- text=help_text,
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ʙᴀᴄᴋ",
- callback_data=f"help_module({__mod_name__.lower()})",
- )
- ]
- ]
- ),
- )
- bot.answer_callback_query(query.id)
-
-
-def get_help(chat):
- return [
- gs(chat, "feds_help"),
- [
- InlineKeyboardButton(text="ғᴇᴅᴀᴅᴍɪɴ", callback_data="fed_help_admin"),
- InlineKeyboardButton(text="ғᴇᴅᴏᴡɴᴇʀ", callback_data="fed_help_owner"),
- ],
- [InlineKeyboardButton(text="ᴜsᴇʀs", callback_data="fed_help_user")],
- ]
-
-
-NEW_FED_HANDLER = CommandHandler("newfed", new_fed, run_async=True)
-DEL_FED_HANDLER = CommandHandler("delfed", del_fed, run_async=True)
-RENAME_FED = CommandHandler("renamefed", rename_fed, run_async=True)
-JOIN_FED_HANDLER = CommandHandler("joinfed", join_fed, run_async=True)
-LEAVE_FED_HANDLER = CommandHandler("leavefed", leave_fed, run_async=True)
-PROMOTE_FED_HANDLER = CommandHandler("fpromote", user_join_fed, run_async=True)
-DEMOTE_FED_HANDLER = CommandHandler("fdemote", user_demote_fed, run_async=True)
-INFO_FED_HANDLER = CommandHandler("fedinfo", fed_info, run_async=True)
-BAN_FED_HANDLER = DisableAbleCommandHandler("fban", fed_ban, run_async=True)
-UN_BAN_FED_HANDLER = CommandHandler("unfban", unfban, run_async=True)
-FED_BROADCAST_HANDLER = CommandHandler("fbroadcast", fed_broadcast, run_async=True)
-FED_SET_RULES_HANDLER = CommandHandler("setfrules", set_frules, run_async=True)
-FED_GET_RULES_HANDLER = CommandHandler("frules", get_frules, run_async=True)
-FED_CHAT_HANDLER = CommandHandler("chatfed", fed_chat, run_async=True)
-FED_ADMIN_HANDLER = CommandHandler("fedadmins", fed_admin, run_async=True)
-FED_USERBAN_HANDLER = CommandHandler("fbanlist", fed_ban_list, run_async=True)
-FED_NOTIF_HANDLER = CommandHandler("fednotif", fed_notif, run_async=True)
-FED_CHATLIST_HANDLER = CommandHandler("fedchats", fed_chats, run_async=True)
-FED_IMPORTBAN_HANDLER = CommandHandler("importfbans", fed_import_bans, run_async=True)
-FEDSTAT_USER = DisableAbleCommandHandler(
- ["fedstat", "fbanstat"], fed_stat_user, run_async=True
-)
-SET_FED_LOG = CommandHandler("setfedlog", set_fed_log, run_async=True)
-UNSET_FED_LOG = CommandHandler("unsetfedlog", unset_fed_log, run_async=True)
-SUBS_FED = CommandHandler("subfed", subs_feds, run_async=True)
-UNSUBS_FED = CommandHandler("unsubfed", unsubs_feds, run_async=True)
-MY_SUB_FED = CommandHandler("fedsubs", get_myfedsubs, run_async=True)
-MY_FEDS_LIST = CommandHandler("myfeds", get_myfeds_list, run_async=True)
-DELETEBTN_FED_HANDLER = CallbackQueryHandler(
- del_fed_button, pattern=r"rmfed_", run_async=True
-)
-FED_OWNER_HELP_HANDLER = CommandHandler("fedownerhelp", fed_owner_help, run_async=True)
-FED_ADMIN_HELP_HANDLER = CommandHandler("fedadminhelp", fed_admin_help, run_async=True)
-FED_USER_HELP_HANDLER = CommandHandler("feduserhelp", fed_user_help, run_async=True)
-
-dispatcher.add_handler(NEW_FED_HANDLER)
-dispatcher.add_handler(DEL_FED_HANDLER)
-dispatcher.add_handler(RENAME_FED)
-dispatcher.add_handler(JOIN_FED_HANDLER)
-dispatcher.add_handler(LEAVE_FED_HANDLER)
-dispatcher.add_handler(PROMOTE_FED_HANDLER)
-dispatcher.add_handler(DEMOTE_FED_HANDLER)
-dispatcher.add_handler(INFO_FED_HANDLER)
-dispatcher.add_handler(BAN_FED_HANDLER)
-dispatcher.add_handler(UN_BAN_FED_HANDLER)
-dispatcher.add_handler(FED_BROADCAST_HANDLER)
-dispatcher.add_handler(FED_SET_RULES_HANDLER)
-dispatcher.add_handler(FED_GET_RULES_HANDLER)
-dispatcher.add_handler(FED_CHAT_HANDLER)
-dispatcher.add_handler(FED_ADMIN_HANDLER)
-dispatcher.add_handler(FED_USERBAN_HANDLER)
-dispatcher.add_handler(FED_NOTIF_HANDLER)
-dispatcher.add_handler(FED_CHATLIST_HANDLER)
-dispatcher.add_handler(FEDSTAT_USER)
-dispatcher.add_handler(SET_FED_LOG)
-dispatcher.add_handler(UNSET_FED_LOG)
-dispatcher.add_handler(SUBS_FED)
-dispatcher.add_handler(UNSUBS_FED)
-dispatcher.add_handler(MY_SUB_FED)
-dispatcher.add_handler(MY_FEDS_LIST)
-dispatcher.add_handler(DELETEBTN_FED_HANDLER)
-dispatcher.add_handler(FED_OWNER_HELP_HANDLER)
-dispatcher.add_handler(FED_ADMIN_HELP_HANDLER)
-dispatcher.add_handler(FED_USER_HELP_HANDLER)
diff --git a/Exon/modules/feedback.py b/Exon/modules/feedback.py
deleted file mode 100644
index 4ecaac5c..00000000
--- a/Exon/modules/feedback.py
+++ /dev/null
@@ -1,88 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import random
-
-from telegram import ParseMode
-from telethon import Button
-
-from Exon import OWNER_ID, SUPPORT_CHAT
-from Exon import telethn as tbot
-from ..events import register
-
-
-@register(pattern="/feedback ?(.*)")
-async def feedback(e):
- quew = e.pattern_match.group(1)
- user_id = e.sender.id
- user_name = e.sender.first_name
- mention = f"[{user_name}](tg://user?id={str(user_id)})"
- Exon = (
- "https://telegra.ph/file/753bfe51f0e0314f1f3ff.jpg",
- "https://telegra.ph/file/20bab4a499d6dccd823f1.jpg",
- "https://telegra.ph/file/2ef1c255ac51d9febb3f4.jpg",
- "https://telegra.ph/file/bc3a10df7c66e6333bba6.jpg",
- "https://telegra.ph/file/bf283996f928a6ab5b625.jpg",
- "https://telegra.ph/file/bf283996f928a6ab5b625.jpg",
- "https://telegra.ph/file/43b4f5a5645ab1cd1dd7c.jpg",
- "https://telegra.ph/file/0f5240ad4d50d5dac57fe.jpg",
- "https://telegra.ph/file/f6128a7a197cf088ba5e0.jpg",
- "https://telegra.ph/file/53d0320dcaa0d21da19c0.jpg",
- "https://telegra.ph/file/fc988e9441acfb5fe71a7.jpg",
- "https://telegra.ph/file/731387573fd96e3cfc2f5.jpg",
- "https://telegra.ph/file/6c9951e14cece66f2fc3a.jpg",
- )
- NATFEED = ("https://telegra.ph/file/2dd04f407b16bc2cfdf76.jpg",)
- BUTTON = [[Button.url("Go To Support Group", f"https://t.me/{SUPPORT_CHAT}")]]
- TEXT = "ᴛʜᴀɴᴋꜱ ꜰᴏʀ ʏᴏᴜʀ ꜰᴇᴇᴅʙᴀᴄᴋ, ɪ ʜᴏᴘᴇ ʏᴏᴜ ʜᴀᴘᴘʏ ᴡɪᴛʜ ᴏᴜʀ ꜱᴇʀᴠɪᴄᴇ."
- logger_text = f"""
-**ɴᴇᴡ ꜰᴇᴇᴅʙᴀᴄᴋ**
-
-**ꜰʀᴏᴍ ᴜꜱᴇʀ:** {mention}
-**ᴜꜱᴇʀɴᴀᴍᴇ:** @{e.sender.username}
-**ᴜꜱᴇʀ ɪᴅ:** `{e.sender.id}`
-**ꜰᴇᴇᴅʙᴀᴄᴋ:** `{e.text}`
-"""
- if e.sender_id != OWNER_ID and not quew:
- GIVE = "ɢɪᴠᴇ ꜱᴏᴍᴇ ᴛᴇxᴛ ꜰᴏʀ ꜰᴇᴇᴅʙᴄᴋ ✨"
- await e.reply(
- GIVE,
- parse_mode=ParseMode.MARKDOWN,
- buttons=BUTTON,
- file=random.choice(NATFEED),
- ),
- return
-
- await tbot.send_message(
- SUPPORT_CHAT,
- f"{logger_text}",
- file=random.choice(Exon),
- link_preview=False,
- )
- await e.reply(TEXT, file=random.choice(Exon), buttons=BUTTON)
diff --git a/Exon/modules/fonts.py b/Exon/modules/fonts.py
deleted file mode 100644
index 7e602b6c..00000000
--- a/Exon/modules/fonts.py
+++ /dev/null
@@ -1,226 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishno1Mi
-# TG :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
-
-from Exon import Abishnoi as abishnoi
-from Exon.modules.resources.fonts import Fonts
-
-
-@abishnoi.on_cmd(["font", "fonts"])
-async def style_buttons(c, m, cb=False):
- buttons = [
- [
- InlineKeyboardButton("𝚃𝚢𝚙𝚎𝚠𝚛𝚒𝚝𝚎𝚛", callback_data="style+typewriter"),
- InlineKeyboardButton("𝕆𝕦𝕥𝕝𝕚𝕟𝕖", callback_data="style+outline"),
- InlineKeyboardButton("𝐒𝐞𝐫𝐢𝐟", callback_data="style+serif"),
- ],
- [
- InlineKeyboardButton("𝑺𝒆𝒓𝒊𝒇", callback_data="style+bold_cool"),
- InlineKeyboardButton("𝑆𝑒𝑟𝑖𝑓", callback_data="style+cool"),
- InlineKeyboardButton("Sᴍᴀʟʟ Cᴀᴘs", callback_data="style+small_cap"),
- ],
- [
- InlineKeyboardButton("𝓈𝒸𝓇𝒾𝓅𝓉", callback_data="style+script"),
- InlineKeyboardButton("𝓼𝓬𝓻𝓲𝓹𝓽", callback_data="style+script_bolt"),
- InlineKeyboardButton("ᵗⁱⁿʸ", callback_data="style+tiny"),
- ],
- [
- InlineKeyboardButton("ᑕOᗰIᑕ", callback_data="style+comic"),
- InlineKeyboardButton("𝗦𝗮𝗻𝘀", callback_data="style+sans"),
- InlineKeyboardButton("𝙎𝙖𝙣𝙨", callback_data="style+slant_sans"),
- ],
- [
- InlineKeyboardButton("𝘚𝘢𝘯𝘴", callback_data="style+slant"),
- InlineKeyboardButton("𝖲𝖺𝗇𝗌", callback_data="style+sim"),
- InlineKeyboardButton("Ⓒ︎Ⓘ︎Ⓡ︎Ⓒ︎Ⓛ︎Ⓔ︎Ⓢ︎", callback_data="style+circles"),
- ],
- [
- InlineKeyboardButton("🅒︎🅘︎🅡︎🅒︎🅛︎🅔︎🅢︎", callback_data="style+circle_dark"),
- InlineKeyboardButton("𝔊𝔬𝔱𝔥𝔦𝔠", callback_data="style+gothic"),
- InlineKeyboardButton("𝕲𝖔𝖙𝖍𝖎𝖈", callback_data="style+gothic_bolt"),
- ],
- [
- InlineKeyboardButton("C͜͡l͜͡o͜͡u͜͡d͜͡s͜͡", callback_data="style+cloud"),
- InlineKeyboardButton("H̆̈ă̈p̆̈p̆̈y̆̈", callback_data="style+happy"),
- InlineKeyboardButton("S̑̈ȃ̈d̑̈", callback_data="style+sad"),
- ],
- [InlineKeyboardButton("ɴᴇxᴛ ➻", callback_data="nxt")],
- ]
- if not cb:
- await m.reply_text(
- m.text, reply_markup=InlineKeyboardMarkup(buttons), quote=True
- )
- else:
- await m.answer()
- await m.message.edit_reply_markup(InlineKeyboardMarkup(buttons))
-
-
-@abishnoi.on_cb("nxt")
-async def nxt(c, m):
- if m.data == "nxt":
- buttons = [
- [
- InlineKeyboardButton("🇸 🇵 🇪 🇨 🇮 🇦 🇱 ", callback_data="style+special"),
- InlineKeyboardButton("🅂🅀🅄🄰🅁🄴🅂", callback_data="style+squares"),
- InlineKeyboardButton(
- "🆂︎🆀︎🆄︎🅰︎🆁︎🅴︎🆂︎", callback_data="style+squares_bold"
- ),
- ],
- [
- InlineKeyboardButton("ꪖꪀᦔꪖꪶꪊᥴ𝓲ꪖ", callback_data="style+andalucia"),
- InlineKeyboardButton("爪卂几ᘜ卂", callback_data="style+manga"),
- InlineKeyboardButton("S̾t̾i̾n̾k̾y̾", callback_data="style+stinky"),
- ],
- [
- InlineKeyboardButton(
- "B̥ͦu̥ͦb̥ͦb̥ͦl̥ͦe̥ͦs̥ͦ", callback_data="style+bubbles"
- ),
- InlineKeyboardButton(
- "U͟n͟d͟e͟r͟l͟i͟n͟e͟", callback_data="style+underline"
- ),
- InlineKeyboardButton("꒒ꍏꀷꌩꌃꀎꁅ", callback_data="style+ladybug"),
- ],
- [
- InlineKeyboardButton("R҉a҉y҉s҉", callback_data="style+rays"),
- InlineKeyboardButton("B҈i҈r҈d҈s҈", callback_data="style+birds"),
- InlineKeyboardButton("S̸l̸a̸s̸h̸", callback_data="style+slash"),
- ],
- [
- InlineKeyboardButton("s⃠t⃠o⃠p⃠", callback_data="style+stop"),
- InlineKeyboardButton(
- "S̺͆k̺͆y̺͆l̺͆i̺͆n̺͆e̺͆", callback_data="style+skyline"
- ),
- InlineKeyboardButton("A͎r͎r͎o͎w͎s͎", callback_data="style+arrows"),
- ],
- [
- InlineKeyboardButton("ዪሀክቿነ", callback_data="style+qvnes"),
- InlineKeyboardButton("S̶t̶r̶i̶k̶e̶", callback_data="style+strike"),
- InlineKeyboardButton("F༙r༙o༙z༙e༙n༙", callback_data="style+frozen"),
- ],
- [InlineKeyboardButton("ʙᴀᴄᴋ", callback_data="nxt+0")],
- ]
- await m.answer()
- await m.message.edit_reply_markup(InlineKeyboardMarkup(buttons))
- else:
- await style_buttons(c, m, cb=True)
-
-
-@abishnoi.on_cb("style")
-async def style(c, m):
- await m.answer()
- cmd, style = m.data.split("+")
-
- if style == "andalucia":
- cls = Fonts.andalucia
- elif style == "arrows":
- cls = Fonts.arrows
- elif style == "birds":
- cls = Fonts.birds
- elif style == "bold_cool":
- cls = Fonts.bold_cool
- elif style == "bubbles":
- cls = Fonts.bubbles
- elif style == "circle_dark":
- cls = Fonts.dark_circle
- elif style == "circles":
- cls = Fonts.circles
- elif style == "cloud":
- cls = Fonts.cloud
- elif style == "comic":
- cls = Fonts.comic
- elif style == "cool":
- cls = Fonts.cool
- elif style == "frozen":
- cls = Fonts.frozen
- elif style == "gothic":
- cls = Fonts.gothic
- elif style == "gothic_bolt":
- cls = Fonts.bold_gothic
- elif style == "happy":
- cls = Fonts.happy
- elif style == "ladybug":
- cls = Fonts.ladybug
- elif style == "manga":
- cls = Fonts.manga
- elif style == "outline":
- cls = Fonts.outline
- elif style == "qvnes":
- cls = Fonts.rvnes
- elif style == "rays":
- cls = Fonts.rays
- elif style == "sad":
- cls = Fonts.sad
- elif style == "sans":
- cls = Fonts.san
- elif style == "script":
- cls = Fonts.script
- elif style == "script_bolt":
- cls = Fonts.bold_script
- elif style == "serif":
- cls = Fonts.serief
- elif style == "sim":
- cls = Fonts.sim
- elif style == "skyline":
- cls = Fonts.skyline
- elif style == "slant":
- cls = Fonts.slant
- elif style == "slant_sans":
- cls = Fonts.slant_san
- elif style == "slash":
- cls = Fonts.slash
- elif style == "small_cap":
- cls = Fonts.smallcap
- elif style == "special":
- cls = Fonts.special
- elif style == "squares":
- cls = Fonts.square
- elif style == "squares_bold":
- cls = Fonts.dark_square
- elif style == "stinky":
- cls = Fonts.stinky
- elif style == "stop":
- cls = Fonts.stop
- elif style == "strike":
- cls = Fonts.strike
- elif style == "tiny":
- cls = Fonts.tiny
- elif style == "typewriter":
- cls = Fonts.typewriter
- elif style == "underline":
- cls = Fonts.underline
- new_text = cls(m.message.reply_to_message.text)
- try:
- await m.message.edit_text(new_text, reply_markup=m.message.reply_markup)
- except Exception:
- pass
-
-
-__mod_name__ = "𝐅ᴏɴᴛs"
diff --git a/Exon/modules/forcesub.py b/Exon/modules/forcesub.py
deleted file mode 100644
index a181a1fb..00000000
--- a/Exon/modules/forcesub.py
+++ /dev/null
@@ -1,184 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from telethon import Button, events, types
-from telethon.errors import ChatAdminRequiredError
-from telethon.errors.rpcerrorlist import UserNotParticipantError
-from telethon.tl.functions.channels import GetParticipantRequest
-
-from Exon import BOT_ID
-from Exon import DRAGONS as DEVS
-from Exon import OWNER_ID
-from Exon import telethn as Rani
-from Exon.events import Asuinline
-from Exon.events import register as Asubot
-from Exon.modules.no_sql import fsub_db as db
-
-
-async def is_admin(chat_id, user_id):
- try:
- p = await Rani(GetParticipantRequest(chat_id, user_id))
- except UserNotParticipantError:
- return False
- return isinstance(
- p.participant,
- (types.ChannelParticipantAdmin, types.ChannelParticipantCreator),
- )
-
-
-async def participant_check(channel, user_id):
- try:
- await Rani(GetParticipantRequest(channel, int(user_id)))
- return True
- except UserNotParticipantError:
- return False
- except Exception:
- return False
-
-
-@Asubot(pattern="^/(fsub|Fsub|forcesubscribe|Forcesub|forcesub|Forcesubscribe) ?(.*)")
-async def fsub(event):
- if event.is_private:
- return
- if event.is_group:
- perm = await event.client.get_permissions(event.chat_id, event.sender_id)
- if not perm.is_admin:
- return await event.reply("ʏᴏᴜ ɴᴇᴇᴅ ᴛᴏ ʙᴇ ᴀɴ ᴀᴅᴍɪɴ ᴛᴏ ᴅᴏ ᴛʜɪs.")
- if not perm.is_creator:
- return await event.reply(
- "❗ ɢʀᴏᴜᴘ ᴄʀᴇᴀᴛᴏʀ ʀᴇǫᴜɪʀᴇᴅ \nʏᴏᴜ ʜᴀᴠᴇ ᴛᴏ ʙᴇ ᴛʜᴇ ɢʀᴏᴜᴘ ᴄʀᴇᴀᴛᴏʀ ᴛᴏ ᴅᴏ ᴛʜᴀᴛ.",
- parse_mode="html",
- )
- try:
- channel = event.text.split(None, 1)[1]
- except IndexError:
- channel = None
- if not channel:
- if chat_db := db.fs_settings(event.chat_id):
- await event.reply(
- f"ғᴏʀᴄᴇsᴜʙsᴄʀɪʙᴇ ɪs ᴄᴜʀʀᴇɴᴛʟʏ ᴇɴᴀʙʟᴇᴅ. ᴜsᴇʀs ᴀʀᴇ ғᴏʀᴄᴇᴅ ᴛᴏ ᴊᴏɪɴ @{chat_db.channel} ᴛᴏ sᴘᴇᴀᴋ ʜᴇʀᴇ.",
- parse_mode="html",
- )
- else:
- await event.reply(
- "❌ ғᴏʀᴄᴇ sᴜʙsᴄʀɪʙᴇ ɪs ᴅɪsᴀʙʟᴇᴅ ɪɴ ᴛʜɪs ᴄʜᴀᴛ.", parse_mode="HTML"
- )
- elif channel in ["on", "yes", "y"]:
- await event.reply("❗ᴘʟᴇᴀsᴇ sᴘᴇᴄɪғʏ ᴛʜᴇ ᴄʜᴀɴɴᴇʟ ᴜsᴇʀɴᴀᴍᴇ.")
- elif channel in ["off", "no", "n"]:
- await event.reply("**❌ ғᴏʀᴄᴇ sᴜʙsᴄʀɪʙᴇ ɪs ᴅɪsᴀʙʟᴇᴅ sᴜᴄᴄᴇssғᴜʟʟʏ.**")
- db.disapprove(event.chat_id)
- else:
- try:
- channel_entity = await event.client.get_entity(channel)
- except Exception:
- return await event.reply(
- "❗ɪɴᴠᴀʟɪᴅ ᴄʜᴀɴɴᴇʟ ᴜsᴇʀɴᴀᴍᴇ ᴘʀᴏᴠɪᴅᴇᴅ.", parse_mode="html"
- )
- channel = channel_entity.username
- try:
- if not channel_entity.broadcast:
- return await event.reply("ᴛʜᴀᴛ's ɴᴏᴛ ᴀ ᴠᴀʟɪᴅ ᴄʜᴀɴɴᴇʟ.")
- except Exception:
- return await event.reply("ᴛʜᴀᴛ's ɴᴏᴛ ᴀ ᴠᴀʟɪᴅ ᴄʜᴀɴɴᴇʟ.")
- if not await participant_check(channel, BOT_ID):
- return await event.reply(
- f"❗**ɴᴏᴛ ᴀɴ ᴀᴅᴍɪɴ ɪɴ ᴛʜᴇ ᴄʜᴀɴɴᴇʟ**\nI ᴀᴍ ɴᴏᴛ ᴀɴ ᴀᴅᴍɪɴ ɪɴ ᴛʜᴇ [ᴄʜᴀɴɴᴇʟ](https://t.me/{channel}). ᴀᴅᴅ ᴍᴇ ᴀs ᴀ ᴀᴅᴍɪɴ ɪɴ ᴏʀᴅᴇʀ ᴛᴏ ᴇɴᴀʙʟᴇ ғᴏʀᴄᴇsᴜʙsᴄʀɪʙᴇ.",
- link_preview=False,
- )
- db.add_channel(event.chat_id, str(channel))
- await event.reply(f"✅ **ғᴏʀᴄᴇ sᴜʙsᴄʀɪʙᴇ ɪs ᴇɴᴀʙʟᴇᴅ** to @{channel}.")
-
-
-@Rani.on(events.NewMessage())
-async def fsub_n(e):
- if not db.fs_settings(e.chat_id):
- return
- if e.is_private:
- return
- if not e.chat.admin_rights:
- return
- if not e.chat.admin_rights.ban_users:
- return
- if not e.from_id:
- return
- if (
- await is_admin(e.chat_id, e.sender_id)
- or e.sender_id in DEVS
- or e.sender_id == OWNER_ID
- ):
- return
- channel = (db.fs_settings(e.chat_id)).get("channel")
- try:
- check = await participant_check(channel, e.sender_id)
- except ChatAdminRequiredError:
- return
- if not check:
- buttons = [Button.url("ᴊᴏɪɴ ᴄʜᴀɴɴᴇʟ", f"t.me/{channel}")], [
- Button.inline("ᴜɴᴍᴜᴛᴇ ᴍᴇ", data=f"fs_{str(e.sender_id)}")
- ]
- txt = f'{e.sender.first_name}, ʏᴏᴜ ʜᴀᴠᴇ ɴᴏᴛ sᴜʙsᴄʀɪʙᴇᴅ ᴛᴏ ᴏᴜʀ ᴄʜᴀɴɴᴇʟ ʏᴇᴛ❗.ᴘʟᴇᴀsᴇ ᴊᴏɪɴ ᴀɴᴅ ᴘʀᴇss ᴛʜᴇ ʙᴜᴛᴛᴏɴ ʙᴇʟᴏᴡ ᴛᴏ ᴜɴᴍᴜᴛᴇ ʏᴏᴜʀsᴇʟғ.'
- await e.reply(txt, buttons=buttons, parse_mode="html", link_preview=False)
- await e.client.edit_permissions(e.chat_id, e.sender_id, send_messages=False)
-
-
-@Asuinline(pattern=r"fs(\_(.*))")
-async def unmute_fsub(event):
- user_id = int(((event.pattern_match.group(1)).decode()).split("_", 1)[1])
- if event.sender_id != user_id:
- return await event.answer("ᴛʜɪs ɪs ɴᴏᴛ ᴍᴇᴀɴᴛ ғᴏʀ ʏᴏᴜ.", alert=True)
- channel = (db.fs_settings(event.chat_id)).get("channel")
- try:
- check = await participant_check(channel, user_id)
- except ChatAdminRequiredError:
- check = False
- return
- if not check:
- return await event.answer(
- "ʏᴏᴜ ʜᴀᴠᴇ ᴛᴏ ᴊᴏɪɴ ᴛʜᴇ ᴄʜᴀɴɴᴇʟ ғɪʀsᴛ, ᴛᴏ ɢᴇᴛ ᴜɴᴍᴜᴛᴇᴅ!", alert=True
- )
- try:
- await event.client.edit_permissions(event.chat_id, user_id, send_messages=True)
- except ChatAdminRequiredError:
- pass
- await event.delete()
-
-
-__mod_name__ = "𝐅-sᴜʙ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "fsub_help")
-
-# """
diff --git a/Exon/modules/global_bans.py b/Exon/modules/global_bans.py
deleted file mode 100644
index 92034e4b..00000000
--- a/Exon/modules/global_bans.py
+++ /dev/null
@@ -1,635 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import html
-import time
-from datetime import datetime
-from io import BytesIO
-
-from telegram import Bot, ParseMode, Update
-from telegram.error import BadRequest, TelegramError, Unauthorized
-from telegram.ext import CallbackContext, CommandHandler, Filters, MessageHandler
-from telegram.utils.helpers import mention_html
-
-import Exon.modules.no_sql.global_bans_db as gban_db
-from Exon import (
- DEMONS,
- DEV_USERS,
- DRAGONS,
- EVENT_LOGS,
- OWNER_ID,
- SPAMWATCH_SUPPORT_CHAT,
- STRICT_GBAN,
- SUPPORT_CHAT,
- TIGERS,
- WOLVES,
- dispatcher,
- sw,
-)
-from Exon.modules.helper_funcs.chat_status import (
- is_user_admin,
- support_plus,
- user_admin,
-)
-from Exon.modules.helper_funcs.decorators import Exonmsg
-from Exon.modules.helper_funcs.extraction import extract_user, extract_user_and_text
-from Exon.modules.helper_funcs.misc import send_to_list
-from Exon.modules.no_sql.users_db import get_user_com_chats
-
-GBAN_ENFORCE_GROUP = 6
-
-GBAN_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to kick it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can kick group administrators",
- "Channel_private",
- "Not in the chat",
- "Can't remove chat owner",
-}
-
-UNGBAN_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Method is available for supergroup and channel chats only",
- "Not in the chat",
- "Channel_private",
- "Chat_admin_required",
- "Peer_id_invalid",
- "User not found",
-}
-
-
-@support_plus
-def gban(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- log_message = ""
-
- user_id, reason = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
-
- if int(user_id) in DEV_USERS:
- message.reply_text(
- "That user is a Destroyers",
- )
- return
-
- if int(user_id) in DRAGONS:
- message.reply_text(
- "I spy, with my little eye... a Shadow Slayer! Why are you guys turning on each other?",
- )
- return
-
- if int(user_id) in DEMONS:
- message.reply_text(
- "OOOH someone's trying to gban a Guardian! *Grabs Popcorn*",
- )
- return
-
- if int(user_id) in TIGERS:
- message.reply_text("That's a Light Shooters! They cannot be banned!")
- return
-
- if int(user_id) in WOLVES:
- message.reply_text("That's a Villain! They have a immune for ban and gban!")
- return
-
- if user_id == bot.id:
- message.reply_text("You uhh...want me to punch myself?")
- return
-
- if user_id in [777000, 1087968824]:
- message.reply_text("Fool! You can't attack Telegram's native tech!")
- return
-
- try:
- user_chat = bot.get_chat(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user.")
- return ""
- return
-
- if user_chat.type != "private":
- message.reply_text("That's not a user!")
- return
-
- if gban_db.is_user_gbanned(user_id):
- if not reason:
- message.reply_text(
- "This user is already gbanned; I'd change the reason, but you haven't given me one...",
- )
- return
-
- if old_reason := gban_db.update_gban_reason(
- user_id,
- user_chat.username or user_chat.first_name,
- reason,
- ):
- message.reply_text(
- f"This user is already gbanned, for the following reason:\n{html.escape(old_reason)}
\nI've gone and updated it with your new reason!",
- parse_mode=ParseMode.HTML,
- )
-
- else:
- message.reply_text(
- "This user is already gbanned, but had no reason set; I've gone and updated it!",
- )
-
- return
-
- message.reply_text("On it!")
-
- start_time = time.time()
- datetime_fmt = "%Y-%m-%dT%H:%M"
- current_time = datetime.utcnow().strftime(datetime_fmt)
-
- if chat.type != "private":
- chat_origin = f"{html.escape(chat.title)} ({chat.id})\n"
- else:
- chat_origin = f"{chat.id}\n"
-
- log_message = (
- f"#GBANNED\n"
- f"Originated from: {chat_origin}
\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"Banned User: {mention_html(user_chat.id, user_chat.first_name)}\n"
- f"Banned User ID: {user_chat.id}
\n"
- f"Event Stamp: {current_time}
"
- )
-
- if reason:
- if chat.type == chat.SUPERGROUP and chat.username:
- log_message += f'\nReason: {reason}'
- else:
- log_message += f"\nReason: {reason}
"
-
- if EVENT_LOGS:
- try:
- log = bot.send_message(EVENT_LOGS, log_message, parse_mode=ParseMode.HTML)
- except BadRequest:
- log = bot.send_message(
- EVENT_LOGS,
- log_message
- + "\n\nFormatting has been disabled due to an unexpected error.",
- )
-
- else:
- send_to_list(bot, DRAGONS + DEMONS, log_message, html=True)
-
- gban_db.gban_user(user_id, user_chat.username or user_chat.first_name, reason)
-
- chats = get_user_com_chats(user_id)
- gbanned_chats = 0
-
- for chat in chats:
- chat_id = chat["chat_id"]
-
- # Check if this group has disabled gbans
- if not gban_db.does_chat_gban(chat_id):
- continue
-
- try:
- bot.ban_chat_member(chat_id, user_id)
- gbanned_chats += 1
-
- except BadRequest as excp:
- if excp.message not in GBAN_ERRORS:
- message.reply_text(f"Could not gban due to: {excp.message}")
- if EVENT_LOGS:
- bot.send_message(
- EVENT_LOGS,
- f"Could not gban due to {excp.message}",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_to_list(
- bot,
- DRAGONS + DEMONS,
- f"Could not gban due to: {excp.message}",
- )
- gban_db.ungban_user(user_id)
- return
- except TelegramError:
- pass
-
- if EVENT_LOGS:
- log.edit_text(
- f"{log_message}\nChats affected: {gbanned_chats}
",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_to_list(
- bot,
- DRAGONS + DEMONS,
- f"Gban complete! (User banned in {gbanned_chats}
chats)",
- html=True,
- )
-
- end_time = time.time()
- gban_time = round((end_time - start_time), 2)
-
- if gban_time > 60:
- gban_time = round((gban_time / 60), 2)
- message.reply_text("Done! Gbanned.", parse_mode=ParseMode.HTML)
- try:
- bot.send_message(
- user_id,
- "#EVENT"
- "You have been marked as Malicious and as such have been banned from any future groups we manage."
- f"\nReason: {html.escape(user['reason'])}
"
- f"Appeal Chat: @{SUPPORT_CHAT}",
- parse_mode=ParseMode.HTML,
- )
- except Exception:
- pass # bot probably blocked by user
-
-
-@support_plus
-def ungban(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
- user = update.effective_user
- chat = update.effective_chat
- log_message = ""
-
- user_id = extract_user(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
-
- user_chat = bot.get_chat(user_id)
- if user_chat.type != "private":
- message.reply_text("That's not a user!")
- return
-
- if not gban_db.is_user_gbanned(user_id):
- message.reply_text("This user is not gbanned!")
- return
-
- message.reply_text(f"I'll give {user_chat.first_name} a second chance, globally.")
-
- start_time = time.time()
- datetime_fmt = "%Y-%m-%dT%H:%M"
- current_time = datetime.utcnow().strftime(datetime_fmt)
-
- if chat.type != "private":
- chat_origin = f"{html.escape(chat.title)} ({chat.id})\n"
- else:
- chat_origin = f"{chat.id}\n"
-
- log_message = (
- f"#UNGBANNED\n"
- f"Originated from: {chat_origin}
\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"Unbanned User: {mention_html(user_chat.id, user_chat.first_name)}\n"
- f"Unbanned User ID: {user_chat.id}
\n"
- f"Event Stamp: {current_time}
"
- )
-
- if EVENT_LOGS:
- try:
- log = bot.send_message(EVENT_LOGS, log_message, parse_mode=ParseMode.HTML)
- except BadRequest:
- log = bot.send_message(
- EVENT_LOGS,
- log_message
- + "\n\nFormatting has been disabled due to an unexpected error.",
- )
- else:
- send_to_list(bot, DRAGONS + DEMONS, log_message, html=True)
-
- chats = get_user_com_chats(user_id)
- ungbanned_chats = 0
-
- for chat in chats:
- chat_id = chat["chat_id"]
-
- # Check if this group has disabled gbans
- if not gban_db.does_chat_gban(chat_id):
- continue
-
- try:
- member = bot.get_chat_member(chat_id, user_id)
- if member.status == "kicked":
- bot.unban_chat_member(chat_id, user_id)
- ungbanned_chats += 1
-
- except BadRequest as excp:
- if excp.message not in UNGBAN_ERRORS:
- message.reply_text(f"Could not un-gban due to: {excp.message}")
- if EVENT_LOGS:
- bot.send_message(
- EVENT_LOGS,
- f"Could not un-gban due to: {excp.message}",
- parse_mode=ParseMode.HTML,
- )
- else:
- bot.send_message(
- OWNER_ID,
- f"Could not un-gban due to: {excp.message}",
- )
- return
- except TelegramError:
- pass
-
- gban_db.ungban_user(user_id)
-
- if EVENT_LOGS:
- log.edit_text(
- f"{log_message}\nChats affected: {ungbanned_chats}",
- parse_mode=ParseMode.HTML,
- )
- else:
- send_to_list(bot, DRAGONS + DEMONS, "un-gban complete!")
-
- end_time = time.time()
- ungban_time = round((end_time - start_time), 2)
-
- if ungban_time > 60:
- ungban_time = round((ungban_time / 60), 2)
- message.reply_text(f"Person has been un-gbanned. Took {ungban_time} min")
- else:
- message.reply_text(f"Person has been un-gbanned. Took {ungban_time} sec")
-
-
-@support_plus
-def gbanlist(update: Update, context: CallbackContext):
- banned_users = gban_db.get_gban_list()
-
- if not banned_users:
- update.effective_message.reply_text(
- "There aren't any gbanned users! You're kinder than I expected...",
- )
- return
-
- banfile = "Screw these guys.\n"
- for user in banned_users:
- banfile += f"[x] {user['name']} - {user['_id']}\n"
- if user["reason"]:
- banfile += f"Reason: {user['reason']}\n"
-
- with BytesIO(str.encode(banfile)) as output:
- output.name = "gbanlist.txt"
- update.effective_message.reply_document(
- document=output,
- filename="gbanlist.txt",
- caption="Here is the list of currently gbanned users.",
- )
-
-
-def check_and_ban(update, user_id, should_message=True):
- if user_id in TIGERS or user_id in WOLVES:
- sw_ban = None
- else:
- try:
- sw_ban = sw.get_ban(int(user_id))
- except Exception:
- sw_ban = None
-
- if sw_ban:
- update.effective_chat.ban_member(user_id)
- if should_message:
- update.effective_message.reply_text(
- f"Alert: this user is globally banned.\n"
- f"*bans them from here*
.\n"
- f"Appeal chat: {SPAMWATCH_SUPPORT_CHAT}\n"
- f"User ID: {sw_ban.id}
\n"
- f"Ban Reason: {html.escape(sw_ban.reason)}
",
- parse_mode=ParseMode.HTML,
- )
- return
-
- if gban_db.is_user_gbanned(user_id):
- update.effective_chat.ban_member(user_id)
- if should_message:
- text = (
- f"Alert: this user is globally banned.\n"
- f"*bans them from here*
.\n"
- f"Appeal chat: @{SUPPORT_CHAT}\n"
- f"User ID: {user_id}
"
- )
- user = gban_db.get_gbanned_user(user_id)
- if user["reason"]:
- text += (
- f"\nBan Reason: {html.escape(user['reason'])}
"
- )
- update.effective_message.reply_text(text, parse_mode=ParseMode.HTML)
-
-
-@Exonmsg(
- (Filters.all & Filters.chat_type.groups),
- can_disable=False,
- group=GBAN_ENFORCE_GROUP,
-)
-def enforce_gban(update: Update, context: CallbackContext):
- # Not using @restrict handler to avoid spamming - just ignore if cant gban.
- bot = context.bot
- try:
- restrict_permission = update.effective_chat.get_member(
- bot.id,
- ).can_restrict_members
- except Unauthorized:
- return
- if gban_db.does_chat_gban(update.effective_chat.id) and restrict_permission:
- user = update.effective_user
- update.effective_chat
- msg = update.effective_message
-
- if user and not is_user_admin(update, user.id):
- check_and_ban(update, user.id)
- return
-
- if msg.new_chat_members:
- new_members = update.effective_message.new_chat_members
- for mem in new_members:
- check_and_ban(update, mem.id)
-
- if msg.reply_to_message:
- user = msg.reply_to_message.from_user
- if user and not is_user_admin(update, user.id):
- check_and_ban(update, user.id, should_message=False)
-
-
-@user_admin
-def gbanstat(update: Update, context: CallbackContext):
- args = context.args
- if len(args) > 0:
- if args[0].lower() in ["on", "yes"]:
- gban_db.enable_gbans(update.effective_chat.id)
- update.effective_message.reply_text(
- "» Antispam is now enabled\n"
- "» Spamwatch is now enabled\n\n"
- "I am now protecting your group from potential remote threats!",
- )
- elif args[0].lower() in ["off", "no"]:
- gban_db.disable_gbans(update.effective_chat.id)
- update.effective_message.reply_text(
- "» Antispan is now disabled\n" "» Spamwatch is now disabled\n"
- )
- else:
- update.effective_message.reply_text(
- f"Give me some arguments to choose a setting! on/off, yes/no!\n\nYour current setting is: {gban_db.does_chat_gban(update.effective_chat.id)}\nWhen True, any gbans that happen will also happen in your group. When False, they won't, leaving you at the possible mercy of spammers."
- )
-
-
-def clear_gbans(bot: Bot, update: Update):
- banned = gban_db.get_gban_list()
- deleted = 0
- for user in banned:
- id = user["user_id"]
- time.sleep(0.1) # Reduce floodwait
- try:
- acc = bot.get_chat(id)
- if not acc.first_name:
- deleted += 1
- gban_db.ungban_user(id)
- except BadRequest:
- deleted += 1
- gban_db.ungban_user(id)
- update.message.reply_text(
- f"Done! `{deleted}` deleted accounts were removed from the gbanlist.",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def check_gbans(bot: Bot, update: Update):
- banned = gban_db.get_gban_list()
- deleted = 0
- for user in banned:
- id = user["user_id"]
- time.sleep(0.1) # Reduce floodwait
- try:
- acc = bot.get_chat(id)
- if not acc.first_name:
- deleted += 1
- except BadRequest:
- deleted += 1
- if deleted:
- update.message.reply_text(
- f"`{deleted}` deleted accounts found in the gbanlist! Run /cleangb to remove them from the database!",
- parse_mode=ParseMode.MARKDOWN,
- )
- else:
- update.message.reply_text("No deleted accounts in the gbanlist!")
-
-
-def __stats__():
- return f"× {gban_db.num_gbanned_users()} gbanned users."
-
-
-def __user_info__(user_id):
- is_gbanned = gban_db.is_user_gbanned(user_id)
- text = "Gbanned: {}"
- if user_id in [777000, 1087968824]:
- return ""
- if user_id == dispatcher.bot.id:
- return ""
- if int(user_id) in DRAGONS + TIGERS + WOLVES:
- return ""
- if is_gbanned:
- text = text.format("Yes")
- user = gban_db.get_gbanned_user(user_id)
- if user["reason"]:
- text += f"\nReason: {html.escape(user['reason'])}
"
- text += f"\nAppeal Chat: @{SUPPORT_CHAT}"
- else:
- text = text.format("???")
- return text
-
-
-def __migrate__(old_chat_id, new_chat_id):
- gban_db.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- return f"This chat is enforcing *gbans*: `{gban_db.does_chat_gban(chat_id)}`."
-
-
-GBAN_HANDLER = CommandHandler("gban", gban, run_async=True)
-UNGBAN_HANDLER = CommandHandler("ungban", ungban, run_async=True)
-GBAN_LIST = CommandHandler("gbanlist", gbanlist, run_async=True)
-
-GBAN_STATUS = CommandHandler(
- "antispam", gbanstat, filters=Filters.chat_type.groups, run_async=True
-)
-CHECK_GBAN_HANDLER = CommandHandler(
- "checkgb", check_gbans, filters=Filters.user(OWNER_ID), run_async=True
-)
-CLEAN_GBAN_HANDLER = CommandHandler(
- "cleangb", clear_gbans, filters=Filters.user(OWNER_ID), run_async=True
-)
-
-GBAN_ENFORCER = MessageHandler(
- Filters.all & Filters.chat_type.groups, enforce_gban, run_async=True
-)
-
-dispatcher.add_handler(GBAN_HANDLER)
-dispatcher.add_handler(UNGBAN_HANDLER)
-dispatcher.add_handler(GBAN_LIST)
-dispatcher.add_handler(GBAN_STATUS)
-
-__mod_name__ = "𝐀-sᴘᴀᴍ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "antispam_help")
-
-
-# """
-
-
-__handlers__ = [GBAN_HANDLER, UNGBAN_HANDLER, GBAN_LIST, GBAN_STATUS]
-
-if STRICT_GBAN: # enforce GBANS if this is set
- dispatcher.add_handler(GBAN_ENFORCER, GBAN_ENFORCE_GROUP)
- __handlers__.append((GBAN_ENFORCER, GBAN_ENFORCE_GROUP))
diff --git a/Exon/modules/gtranslator.py b/Exon/modules/gtranslator.py
deleted file mode 100644
index 20ca2e3f..00000000
--- a/Exon/modules/gtranslator.py
+++ /dev/null
@@ -1,178 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import os
-
-from gpytranslate import SyncTranslator
-from gtts import gTTS
-from telegram import (
- ChatAction,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- Update,
-)
-from telegram.ext import CallbackContext
-
-from Exon import dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.alternate import send_action, typing_action
-
-trans = SyncTranslator()
-
-
-def translate(update: Update, context: CallbackContext) -> None:
- bot = context.bot
- message = update.effective_message
- reply_msg = message.reply_to_message
- if not reply_msg:
- message.reply_text("Reply to a message to translate it!")
- return
- to_translate = reply_msg.caption or reply_msg.text
- try:
- args = message.text.split()[1].lower()
- if "//" in args:
- source = args.split("//")[0]
- dest = args.split("//")[1]
- else:
- source = trans.detect(to_translate)
- dest = args
- except IndexError:
- source = trans.detect(to_translate)
- dest = "en"
- translation = trans(to_translate, sourcelang=source, targetlang=dest)
- reply = (
- f"Language: {source} -> {dest}:\n\n"
- f"Translation: {translation.text}
"
- )
-
- bot.send_message(text=reply, chat_id=message.chat.id, parse_mode=ParseMode.HTML)
-
-
-def languages(update: Update, context: CallbackContext) -> None:
- update.effective_message.reply_text(
- "Click on the button below to see the list of supported language codes.",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="Language codes",
- url="https://telegra.ph/Lang-Codes-03-19-3",
- ),
- ],
- ],
- disable_web_page_preview=True,
- ),
- )
-
-
-@send_action(ChatAction.RECORD_AUDIO)
-def gtts(update, context):
- msg = update.effective_message
- reply = " ".join(context.args)
- if not reply:
- if msg.reply_to_message:
- reply = msg.reply_to_message.text
- else:
- return msg.reply_text(
- "Reply to some message or enter some text to convert it into audio format!"
- )
- for x in "\n":
- reply = reply.replace(x, "")
- try:
- tts = gTTS(reply)
- tts.save("Exon.mp3")
- with open("Exon.mp3", "rb") as speech:
- msg.reply_audio(speech)
- finally:
- if os.path.isfile("Exon.mp3"):
- os.remove("Exon.mp3")
-
-
-# Open API key
-API_KEY = "6ae0c3a0-afdc-4532-a810-82ded0054236"
-URL = "http://services.gingersoftware.com/Ginger/correct/json/GingerTheText"
-
-
-@typing_action
-def spellcheck(update, _):
- if update.effective_message.reply_to_message:
- msg = update.effective_message.reply_to_message
-
- params = dict(lang="US", clientVersion="2.0", apiKey=API_KEY, text=msg.text)
-
- res = requests.get(URL, params=params)
- changes = json.loads(res.text).get("LightGingerTheTextResult")
- curr_string = ""
- prev_end = 0
-
- for change in changes:
- start = change.get("From")
- end = change.get("To") + 1
- if suggestions := change.get("Suggestions"):
- sugg_str = suggestions[0].get("Text") # should look at this list more
- curr_string += msg.text[prev_end:start] + sugg_str
- prev_end = end
-
- curr_string += msg.text[prev_end:]
- update.effective_message.reply_text(curr_string)
- else:
- update.effective_message.reply_text(
- "Reply to some message to get grammar corrected text!"
- )
-
-
-dispatcher.add_handler(
- DisableAbleCommandHandler(["tr", "tl"], translate, pass_args=True, run_async=True)
-)
-dispatcher.add_handler(
- DisableAbleCommandHandler(["langs", "lang"], languages, run_async=True)
-)
-dispatcher.add_handler(
- DisableAbleCommandHandler("tts", gtts, pass_args=True, run_async=True)
-)
-dispatcher.add_handler(
- DisableAbleCommandHandler("splcheck", spellcheck, run_async=True)
-)
-
-__command_list__ = ["tr", "tl", "lang", "languages", "splcheck", "tts"]
-
-__mod_name__ = "𝐓ʀᴀɴsʟᴀᴛᴏʀ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "gtranslate_help")
-
-# """
diff --git "a/Exon/modules/helper_funcs/ABISHNOI COPYRIGHT \302\251" "b/Exon/modules/helper_funcs/ABISHNOI COPYRIGHT \302\251"
deleted file mode 100644
index 2896b7d1..00000000
--- "a/Exon/modules/helper_funcs/ABISHNOI COPYRIGHT \302\251"
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# MY ALL BOTS :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
\ No newline at end of file
diff --git a/Exon/modules/helper_funcs/__init__.py b/Exon/modules/helper_funcs/__init__.py
deleted file mode 100644
index d51256a0..00000000
--- a/Exon/modules/helper_funcs/__init__.py
+++ /dev/null
@@ -1,24 +0,0 @@
-""" @Abishnoi1M"""
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
diff --git a/Exon/modules/helper_funcs/alternate.py b/Exon/modules/helper_funcs/alternate.py
deleted file mode 100644
index 9179d8fa..00000000
--- a/Exon/modules/helper_funcs/alternate.py
+++ /dev/null
@@ -1,66 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from functools import wraps
-
-from telegram import ChatAction
-from telegram.error import BadRequest
-
-
-def send_message(message, text, *args, **kwargs):
- try:
- return message.reply_text(text, *args, **kwargs)
- except BadRequest as err:
- if str(err) == "Reply message not found":
- return message.reply_text(text, quote=False, *args, **kwargs)
-
-
-def typing_action(func):
- """Sends typing action while processing func command."""
-
- @wraps(func)
- def command_func(update, context, *args, **kwargs):
- context.bot.send_chat_action(
- chat_id=update.effective_chat.id,
- action=ChatAction.TYPING,
- )
- return func(update, context, *args, **kwargs)
-
- return command_func
-
-
-def send_action(action):
- """Sends `action` while processing func command."""
-
- def decorator(func):
- @wraps(func)
- def command_func(update, context, *args, **kwargs):
- context.bot.send_chat_action(
- chat_id=update.effective_chat.id, action=action
- )
- return func(update, context, *args, **kwargs)
-
- return command_func
-
- return decorator
diff --git a/Exon/modules/helper_funcs/anonymous.py b/Exon/modules/helper_funcs/anonymous.py
deleted file mode 100644
index 725efa4b..00000000
--- a/Exon/modules/helper_funcs/anonymous.py
+++ /dev/null
@@ -1,157 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import functools
-from enum import Enum
-
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.ext import CallbackContext
-
-from Exon import DEV_USERS, DRAGONS, dispatcher
-from Exon.modules.helper_funcs.decorators import Exoncallback
-
-
-class AdminPerms(Enum):
- CAN_RESTRICT_MEMBERS = "can_restrict_members"
- CAN_PROMOTE_MEMBERS = "can_promote_members"
- CAN_INVITE_USERS = "can_invite_users"
- CAN_DELETE_MESSAGES = "can_delete_messages"
- CAN_CHANGE_INFO = "can_change_info"
- CAN_PIN_MESSAGES = "can_pin_messages"
-
-
-class ChatStatus(Enum):
- CREATOR = "creator"
- ADMIN = "administrator"
-
-
-anon_callbacks = {}
-anon_callback_messages = {}
-anon_users = {}
-
-
-def user_admin(permission: AdminPerms):
- def wrapper(func):
- @functools.wraps(func)
- def awrapper(update: Update, context: CallbackContext, *args, **kwargs):
- nonlocal permission
- if update.effective_chat.type == "private":
- return func(update, context, *args, **kwargs)
- message = update.effective_message
- is_anon = update.effective_message.sender_chat
-
- if is_anon:
- callback_id = (
- f"anoncb/{message.chat.id}/{message.message_id}/{permission.value}"
- )
- anon_callbacks[(message.chat.id, message.message_id)] = (
- (update, context),
- func,
- )
- anon_callback_messages[(message.chat.id, message.message_id)] = (
- message.reply_text(
- "Seems like you're anonymous, click the button below to prove your identity",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="Prove identity", callback_data=callback_id
- )
- ]
- ]
- ),
- )
- ).message_id
- # send message with callback f'anoncb{callback_id}'
- else:
- user_id = message.from_user.id
- chat_id = message.chat.id
- mem = context.bot.get_chat_member(chat_id=chat_id, user_id=user_id)
- if (
- getattr(mem, permission.value) is True
- or mem.status == "creator"
- or user_id in DRAGONS
- ):
- return func(update, context, *args, **kwargs)
- else:
- return message.reply_text(
- f"You lack the permission: `{permission.name}`",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- return awrapper
-
- return wrapper
-
-
-@Exoncallback(pattern="anoncb")
-def anon_callback_handler1(upd: Update, _: CallbackContext):
- callback = upd.callback_query
- perm = callback.data.split("/")[3]
- chat_id = int(callback.data.split("/")[1])
- message_id = int(callback.data.split("/")[2])
- try:
- mem = upd.effective_chat.get_member(user_id=callback.from_user.id)
- except BaseException as e:
- callback.answer(f"Error: {e}", show_alert=True)
- return
- if mem.status not in [ChatStatus.ADMIN.value, ChatStatus.CREATOR.value]:
- callback.answer("You're aren't admin.")
- dispatcher.bot.delete_message(
- chat_id, anon_callback_messages.pop((chat_id, message_id), None)
- )
- dispatcher.bot.send_message(
- chat_id, "You lack the permissions required for this command"
- )
- elif (
- getattr(mem, perm) is True
- or mem.status == "creator"
- or mem.user.id in DEV_USERS
- ):
- if cb := anon_callbacks.pop((chat_id, message_id), None):
- message_id = anon_callback_messages.pop((chat_id, message_id), None)
- if message_id is not None:
- dispatcher.bot.delete_message(chat_id, message_id)
- return cb[1](cb[0][0], cb[0][1])
- else:
- callback.answer("This isn't for ya")
-
-
-def resolve_user(user, message_id, chat):
- if user.id == 1087968824:
- try:
- uid = anon_users.pop((chat.id, message_id))
- user = chat.get_member(uid).user
- except KeyError:
- return dispatcher.bot.edit_message_text(
- chat.id,
- message_id,
- f"You're now identified as: {user.first_name}",
- )
- except BaseException as e:
- return dispatcher.bot.edit_message_text(chat.id, message_id, f"Error: {e}")
-
- else:
- user = user
- return user
diff --git a/Exon/modules/helper_funcs/chat_status.py b/Exon/modules/helper_funcs/chat_status.py
deleted file mode 100644
index f3b038d7..00000000
--- a/Exon/modules/helper_funcs/chat_status.py
+++ /dev/null
@@ -1,620 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from functools import wraps
-from threading import RLock
-from time import perf_counter
-
-from cachetools import TTLCache
-from pyrogram import filters
-from telegram import Chat, ChatMember, ParseMode, TelegramError, Update, User
-from telegram.ext import CallbackContext
-
-from Exon import (
- DEL_CMDS,
- DEMONS,
- DEV_USERS,
- DRAGONS,
- SUPPORT_CHAT,
- TIGERS,
- WOLVES,
- dispatcher,
-)
-
-ADMIN_CACHE = TTLCache(maxsize=512, ttl=60 * 10, timer=perf_counter)
-THREAD_LOCK = RLock()
-
-
-def is_whitelist_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
- return any(user_id in user for user in [WOLVES, TIGERS, DEMONS, DRAGONS, DEV_USERS])
-
-
-def is_support_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
- return user_id in DEMONS or user_id in DRAGONS or user_id in DEV_USERS
-
-
-def is_sudo_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
- return user_id in DRAGONS or user_id in DEV_USERS
-
-
-def is_stats_plus(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
- return user_id in DEV_USERS
-
-
-def user_can_changeinfo(chat: Chat, user: User, bot_id: int) -> bool:
- return chat.get_member(user.id).can_change_info
-
-
-def user_can_promote(chat: Chat, user: User, bot_id: int) -> bool:
- return chat.get_member(user.id).can_promote_members
-
-
-def user_can_pin(chat: Chat, user: User, bot_id: int) -> bool:
- return chat.get_member(user.id).can_pin_messages
-
-
-def is_user_admin(update: Update, user_id: int, member: ChatMember = None) -> bool:
- chat = update.effective_chat
- msg = update.effective_message
- if (
- chat.type == "private"
- or user_id in DEMONS
- or user_id in DEV_USERS
- or chat.all_members_are_administrators
- or (
- msg.reply_to_message
- and msg.reply_to_message.sender_chat is not None
- and msg.reply_to_message.sender_chat.type != "channel"
- )
- ):
- return True
-
- if not member:
- # try to fetch from cache first.
- try:
- return user_id in ADMIN_CACHE[chat.id]
- except KeyError:
- # KeyError happened means cache is deleted,
- # so query bot api again and return user status
- # while saving it in cache for future usage...
- chat_admins = dispatcher.bot.getChatAdministrators(chat.id)
- admin_list = [x.user.id for x in chat_admins]
- ADMIN_CACHE[chat.id] = admin_list
-
- return user_id in admin_list
-
-
-def is_user_mod(update: Update, user_id: int, member: ChatMember = None) -> bool:
- chat = update.effective_chat
- msg = update.effective_message
- if (
- chat.type == "private"
- or user_id in MOD_USERS
- or user_id in DEMONS
- or user_id in DEV_USERS
- or chat.all_members_are_administrators
- or (msg.sender_chat is not None and msg.sender_chat.type != "channel")
- ): # Count telegram and Group Anonymous as admin
- return True
-
- if not member:
- # try to fetch from cache first.
- try:
- return user_id in ADMIN_CACHE[chat.id]
- except KeyError:
- # keyerror happend means cache is deleted,
- # so query bot api again and return user status
- # while saving it in cache for future useage...
- chat_admins = dispatcher.bot.getChatAdministrators(chat.id)
- admin_list = [x.user.id for x in chat_admins]
- ADMIN_CACHE[chat.id] = admin_list
-
- return user_id in admin_list
-
-
-def is_bot_admin(chat: Chat, bot_id: int, bot_member: ChatMember = None) -> bool:
- if chat.type == "private" or chat.all_members_are_administrators:
- return True
-
- if not bot_member:
- bot_member = chat.get_member(bot_id)
-
- return bot_member.status in ("administrator", "creator")
-
-
-def can_delete(chat: Chat, bot_id: int) -> bool:
- return chat.get_member(bot_id).can_delete_messages
-
-
-def is_user_ban_protected(
- update: Update, user_id: int, member: ChatMember = None
-) -> bool:
- chat = update.effective_chat
- msg = update.effective_message
- if (
- chat.type == "private"
- or user_id in DEMONS
- or user_id in DEV_USERS
- or user_id in DRAGONS
- or user_id in TIGERS
- or chat.all_members_are_administrators
- or (
- msg.reply_to_message
- and msg.reply_to_message.sender_chat is not None
- and msg.reply_to_message.sender_chat.type != "channel"
- )
- ):
- return True
-
- if not member:
- member = chat.get_member(user_id)
-
- return member.status in ("administrator", "creator")
-
-
-def is_user_ban_protectedd(chat: Chat, user_id: int, member: ChatMember = None) -> bool:
- if (
- chat.type == "private"
- or user_id in DRAGONS
- or user_id in DEV_USERS
- or user_id in WOLVES
- or user_id in TIGERS
- or chat.all_members_are_administrators
- or user_id in {777000, 1087968824}
- ): # Count telegram and Group Anonymous as admin
- return True
-
- if not member:
- member = chat.get_member(user_id)
-
- return member.status in ("administrator", "creator")
-
-
-def is_user_in_chat(chat: Chat, user_id: int) -> bool:
- member = chat.get_member(user_id)
- return member.status not in ("left", "kicked")
-
-
-def dev_plus(func):
- @wraps(func)
- def is_dev_plus_func(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user
-
- if user.id in DEV_USERS:
- return func(update, context, *args, **kwargs)
- if not user:
- pass
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
- else:
- update.effective_message.reply_text(
- "This is a developer restricted command."
- " You do not have permissions to run this."
- )
-
- return is_dev_plus_func
-
-
-def sudo_plus(func):
- @wraps(func)
- def is_sudo_plus_func(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user
- chat = update.effective_chat
-
- if user and is_sudo_plus(chat, user.id):
- return func(update, context, *args, **kwargs)
- if not user:
- pass
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
- else:
- update.effective_message.reply_text(
- "Who dis non-admin telling me what to do?"
- )
-
- return is_sudo_plus_func
-
-
-def stats_plus(func):
- @wraps(func)
- def is_stats_plus_func(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user
- chat = update.effective_chat
-
- if user and is_stats_plus(chat, user.id):
- return func(update, context, *args, **kwargs)
- if not user:
- pass
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
- else:
- update.effective_message.reply_text(
- "Yuzuki stats is just for Dev User",
- )
-
- return is_sudo_plus_func
-
-
-def support_plus(func):
- @wraps(func)
- def is_support_plus_func(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user
- chat = update.effective_chat
-
- if user and is_support_plus(chat, user.id):
- return func(update, context, *args, **kwargs)
- if DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
-
- return is_support_plus_func
-
-
-def whitelist_plus(func):
- @wraps(func)
- def is_whitelist_plus_func(
- update: Update, context: CallbackContext, *args, **kwargs
- ):
- context.bot
- user = update.effective_user
- chat = update.effective_chat
-
- if user and is_whitelist_plus(chat, user.id):
- return func(update, context, *args, **kwargs)
- update.effective_message.reply_text(
- f"You don't have access to use this.\nVisit @{SUPPORT_CHAT}"
- )
-
- return is_whitelist_plus_func
-
-
-def user_admin(func):
- @wraps(func)
- def is_admin(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user
- update.effective_chat
-
- if user and is_user_admin(update, user.id):
- return func(update, context, *args, **kwargs)
- if not user:
- pass
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
- else:
- update.effective_message.reply_text(
- "Who dis non-admin telling me what to do?"
- )
-
- return is_admin
-
-
-def user_admin_no_reply(func):
- @wraps(func)
- def is_not_admin_no_reply(
- update: Update, context: CallbackContext, *args, **kwargs
- ):
- context.bot
- user = update.effective_user
- update.effective_chat
-
- if user and is_user_admin(update, user.id):
- return func(update, context, *args, **kwargs)
- if not user:
- pass
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
-
- return is_not_admin_no_reply
-
-
-def user_not_admin(func):
- @wraps(func)
- def is_not_admin(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user
- update.effective_chat
-
- if user and not is_user_admin(update, user.id):
- return func(update, context, *args, **kwargs)
- if not user:
- pass
-
- return is_not_admin
-
-
-def bot_admin(func):
- @wraps(func)
- def is_admin(update: Update, context: CallbackContext, *args, **kwargs):
- bot = context.bot
- chat = update.effective_chat
- update_chat_title = chat.title
- message_chat_title = update.effective_message.chat.title
-
- if update_chat_title == message_chat_title:
- not_admin = "I'm not admin! - REEEEEE"
- else:
- not_admin = f"I'm not admin in {update_chat_title}! - REEEEEE"
-
- if is_bot_admin(chat, bot.id):
- return func(update, context, *args, **kwargs)
- update.effective_message.reply_text(not_admin, parse_mode=ParseMode.HTML)
-
- return is_admin
-
-
-def bot_can_delete(func):
- @wraps(func)
- def delete_rights(update: Update, context: CallbackContext, *args, **kwargs):
- bot = context.bot
- chat = update.effective_chat
- update_chat_title = chat.title
- message_chat_title = update.effective_message.chat.title
-
- if update_chat_title == message_chat_title:
- cant_delete = "I can't delete messages here!\nMake sure I'm admin and can delete other user's messages."
- else:
- cant_delete = f"I can't delete messages in {update_chat_title}!\nMake sure I'm admin and can delete other user's messages there."
-
- if can_delete(chat, bot.id):
- return func(update, context, *args, **kwargs)
- update.effective_message.reply_text(cant_delete, parse_mode=ParseMode.HTML)
-
- return delete_rights
-
-
-def can_pin(func):
- @wraps(func)
- def pin_rights(update: Update, context: CallbackContext, *args, **kwargs):
- bot = context.bot
- chat = update.effective_chat
- update_chat_title = chat.title
- message_chat_title = update.effective_message.chat.title
-
- if update_chat_title == message_chat_title:
- cant_pin = (
- "I can't pin messages here!\nMake sure I'm admin and can pin messages."
- )
- else:
- cant_pin = f"I can't pin messages in {update_chat_title}!\nMake sure I'm admin and can pin messages there."
-
- if chat.get_member(bot.id).can_pin_messages:
- return func(update, context, *args, **kwargs)
- update.effective_message.reply_text(cant_pin, parse_mode=ParseMode.HTML)
-
- return pin_rights
-
-
-def can_promote(func):
- @wraps(func)
- def promote_rights(update: Update, context: CallbackContext, *args, **kwargs):
- bot = context.bot
- chat = update.effective_chat
- update_chat_title = chat.title
- message_chat_title = update.effective_message.chat.title
-
- if update_chat_title == message_chat_title:
- cant_promote = "I can't promote/demote people here!\nMake sure I'm admin and can appoint new admins."
- else:
- cant_promote = (
- f"I can't promote/demote people in {update_chat_title}!\n"
- f"Make sure I'm admin there and can appoint new admins."
- )
-
- if chat.get_member(bot.id).can_promote_members:
- return func(update, context, *args, **kwargs)
- update.effective_message.reply_text(cant_promote, parse_mode=ParseMode.HTML)
-
- return promote_rights
-
-
-def can_restrict(func):
- @wraps(func)
- def restrict_rights(update: Update, context: CallbackContext, *args, **kwargs):
- bot = context.bot
- chat = update.effective_chat
- update_chat_title = chat.title
- message_chat_title = update.effective_message.chat.title
-
- if update_chat_title == message_chat_title:
- cant_restrict = "I can't restrict people here!\nMake sure I'm admin and can restrict users."
- else:
- cant_restrict = f"I can't restrict people in {update_chat_title}!\nMake sure I'm admin there and can restrict users."
-
- if chat.get_member(bot.id).can_restrict_members:
- return func(update, context, *args, **kwargs)
- update.effective_message.reply_text(cant_restrict, parse_mode=ParseMode.HTML)
-
- return restrict_rights
-
-
-def user_can_ban(func):
- @wraps(func)
- def user_is_banhammer(update: Update, context: CallbackContext, *args, **kwargs):
- context.bot
- user = update.effective_user.id
- member = update.effective_chat.get_member(user)
-
- if (
- not member.can_restrict_members
- and member.status != "creator"
- and user not in DEV_USERS
- ):
- update.effective_message.reply_text(
- "Sorry son, but you're not worthy to wield the banhammer."
- )
- return ""
-
- return func(update, context, *args, **kwargs)
-
- return user_is_banhammer
-
-
-def callbacks_in_filters(data):
- return filters.create(lambda flt, _, query: flt.data in query.data, data=data)
-
-
-def connection_status(func):
- @wraps(func)
- def connected_status(update: Update, context: CallbackContext, *args, **kwargs):
- conn = connected(
- context.bot,
- update,
- update.effective_chat,
- update.effective_user.id,
- need_admin=False,
- )
-
- if conn:
- chat = dispatcher.bot.getChat(conn)
- update.__setattr__("_effective_chat", chat)
- return func(update, context, *args, **kwargs)
- if update.effective_message.chat.type == "private":
- update.effective_message.reply_text(
- "Send /connect in a group that you and I have in common first."
- )
- return connected_status
-
- return func(update, context, *args, **kwargs)
-
- return connected_status
-
-
-def user_admin_no_reply(func):
- @wraps(func)
- def is_not_admin_no_reply(
- update: Update, context: CallbackContext, *args, **kwargs
- ):
- # bot = context.bot
- user = update.effective_user
- # chat = update.effective_chat
- query = update.callback_query
-
- if user:
- if is_user_admin(update, user.id):
- return func(update, context, *args, **kwargs)
- else:
- query.answer("this is not for you")
- elif not user:
- query.answer("this is not for you")
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except TelegramError:
- pass
-
- return is_not_admin_no_reply
-
-
-def user_can_restrict_no_reply(func):
- @wraps(func)
- def u_can_restrict_noreply(
- update: Update, context: CallbackContext, *args, **kwargs
- ):
- context.bot
- user = update.effective_user
- chat = update.effective_chat
- query = update.callback_query
- member = chat.get_member(user.id)
-
- if user:
- if (
- member.can_restrict_members
- or member.status == "creator"
- or user.id in DRAGONS
- ):
- return func(update, context, *args, **kwargs)
- elif member.status == "administrator":
- query.answer("You're missing the `can_restrict_members` permission.")
- else:
- query.answer(
- "You need to be admin with `can_restrict_users` permission to do this."
- )
- elif DEL_CMDS and " " not in update.effective_message.text:
- try:
- update.effective_message.delete()
- except Exception:
- pass
-
- return u_can_restrict_noreply
-
-
-ADMIN_PERMS = [
- "can_delete_messages",
- "can_restrict_members",
- "can_pin_messages",
- "can_promote_members",
-]
-
-MESSAGES = [
- "You don't have sufficient permissions to delete messages!",
- "You don't have sufficient permissions to restrict users!",
- "You don't have sufficient permissions to pin messages!",
- "You don't have sufficient permissions to promote users!",
-]
-
-
-def check_perms(update: Update, type: str):
- chat = update.effective_chat
- user = update.effective_user
-
- admin = chat.get_member(int(user.id))
- admin_perms = (
- admin[ADMIN_PERMS[type]]
- if admin["status"] != "creator" and user.id not in DRAGONS
- else True
- )
-
- if not admin_perms:
- update.effective_message.reply_text(MESSAGES[type])
- return False
-
- return True
-
-
-# Workaround for circular import with connection.py
-from Exon.modules import connection
-
-connected = connection.connected
diff --git a/Exon/modules/helper_funcs/decorators.py b/Exon/modules/helper_funcs/decorators.py
deleted file mode 100644
index 5e3f2af1..00000000
--- a/Exon/modules/helper_funcs/decorators.py
+++ /dev/null
@@ -1,203 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from typing import List, Optional, Union
-
-from telegram.ext import (
- CallbackQueryHandler,
- CommandHandler,
- InlineQueryHandler,
- MessageHandler,
-)
-from telegram.ext.filters import MessageFilter
-
-from Exon import LOGGER
-from Exon import dispatcher as n
-from Exon.modules.disable import DisableAbleCommandHandler, DisableAbleMessageHandler
-
-
-class ExonTelegramHandler:
- def __init__(self, n):
- self._dispatcher = n
-
- def command(
- self,
- command: str,
- filters: Optional[MessageFilter] = None,
- admin_ok: bool = False,
- pass_args: bool = False,
- pass_chat_data: bool = False,
- run_async: bool = True,
- can_disable: bool = True,
- group: Optional[Union[int, str]] = 40,
- ):
- def _command(func):
- try:
- if can_disable:
- self._dispatcher.add_handler(
- DisableAbleCommandHandler(
- command,
- func,
- filters=filters,
- run_async=run_async,
- pass_args=pass_args,
- admin_ok=admin_ok,
- ),
- group,
- )
- else:
- self._dispatcher.add_handler(
- CommandHandler(
- command,
- func,
- filters=filters,
- run_async=run_async,
- pass_args=pass_args,
- ),
- group,
- )
- LOGGER.debug(
- f"[ExonCMD] Loaded handler {command} for function {func.__name__} in group {group}"
- )
- except TypeError:
- if can_disable:
- self._dispatcher.add_handler(
- DisableAbleCommandHandler(
- command,
- func,
- filters=filters,
- run_async=run_async,
- pass_args=pass_args,
- admin_ok=admin_ok,
- pass_chat_data=pass_chat_data,
- )
- )
- else:
- self._dispatcher.add_handler(
- CommandHandler(
- command,
- func,
- filters=filters,
- run_async=run_async,
- pass_args=pass_args,
- pass_chat_data=pass_chat_data,
- )
- )
- LOGGER.debug(
- f"[ExonCMD] Loaded handler {command} for function {func.__name__}"
- )
-
- return func
-
- return _command
-
- def message(
- self,
- pattern: Optional[str] = None,
- can_disable: bool = True,
- run_async: bool = True,
- group: Optional[Union[int, str]] = 60,
- friendly=None,
- ):
- def _message(func):
- try:
- if can_disable:
- self._dispatcher.add_handler(
- DisableAbleMessageHandler(
- pattern, func, friendly=friendly, run_async=run_async
- ),
- group,
- )
- else:
- self._dispatcher.add_handler(
- MessageHandler(pattern, func, run_async=run_async), group
- )
- LOGGER.debug(
- f"[ExonMSG] Loaded filter pattern {pattern} for function {func.__name__} in group {group}"
- )
- except TypeError:
- if can_disable:
- self._dispatcher.add_handler(
- DisableAbleMessageHandler(
- pattern, func, friendly=friendly, run_async=run_async
- )
- )
- else:
- self._dispatcher.add_handler(
- MessageHandler(pattern, func, run_async=run_async)
- )
- LOGGER.debug(
- f"[ExonMSG] Loaded filter pattern {pattern} for function {func.__name__}"
- )
-
- return func
-
- return _message
-
- def callbackquery(self, pattern: str = None, run_async: bool = True):
- def _callbackquery(func):
- self._dispatcher.add_handler(
- CallbackQueryHandler(
- pattern=pattern, callback=func, run_async=run_async
- )
- )
- LOGGER.debug(
- f"[ExonCALLBACK] Loaded callbackquery handler with pattern {pattern} for function {func.__name__}"
- )
- return func
-
- return _callbackquery
-
- def inlinequery(
- self,
- pattern: Optional[str] = None,
- run_async: bool = True,
- pass_user_data: bool = True,
- pass_chat_data: bool = True,
- chat_types: List[str] = None,
- ):
- def _inlinequery(func):
- self._dispatcher.add_handler(
- InlineQueryHandler(
- pattern=pattern,
- callback=func,
- run_async=run_async,
- pass_user_data=pass_user_data,
- pass_chat_data=pass_chat_data,
- chat_types=chat_types,
- )
- )
- LOGGER.debug(
- f"[ExonINLINE] Loaded inlinequery handler with pattern {pattern} for function {func.__name__} | PASSES "
- f"USER DATA: {pass_user_data} | PASSES CHAT DATA: {pass_chat_data} | CHAT TYPES: {chat_types}"
- )
- return func
-
- return _inlinequery
-
-
-Exoncmd = ExonTelegramHandler(n).command
-Exonmsg = ExonTelegramHandler(n).message
-Exoncallback = ExonTelegramHandler(n).callbackquery
-Exoninline = ExonTelegramHandler(n).inlinequery
diff --git a/Exon/modules/helper_funcs/extraction.py b/Exon/modules/helper_funcs/extraction.py
deleted file mode 100644
index 64a3aa17..00000000
--- a/Exon/modules/helper_funcs/extraction.py
+++ /dev/null
@@ -1,187 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from typing import List, Optional, Tuple
-
-from telegram import Message, MessageEntity
-from telegram.error import BadRequest
-
-from Exon import LOGGER
-from Exon.modules.users import get_user_id
-
-
-def id_from_reply(message):
- prev_message = message.reply_to_message
- if not prev_message:
- return None, None
- user_id = prev_message.from_user.id
- res = message.text.split(None, 1)
- return (user_id, "") if len(res) < 2 else (user_id, res[1])
-
-
-def extract_user(message: Message, args: List[str]) -> Optional[int]:
- return extract_user_and_text(message, args)[0]
-
-
-def extract_user_and_text(
- message: Message, args: List[str]
-) -> Tuple[Optional[int], Optional[str]]:
- prev_message = message.reply_to_message
- split_text = message.text.split(None, 1)
-
- if len(split_text) < 2:
- return id_from_reply(message) # only option possible
-
- text_to_parse = split_text[1]
-
- text = ""
-
- entities = list(message.parse_entities([MessageEntity.TEXT_MENTION]))
- ent = entities[0] if entities else None
- # if entity offset matches (command end/text start) then all good
- if entities and ent and ent.offset == len(message.text) - len(text_to_parse):
- ent = entities[0]
- user_id = ent.user.id
- text = message.text[ent.offset + ent.length:]
-
- elif len(args) >= 1 and args[0][0] == "@":
- user = args[0]
- user_id = get_user_id(user)
- if not user_id:
- message.reply_text(
- "I don't have that user in my db. You'll be able to interact with them if "
- "you reply to that person's message instead, or forward one of that user's messages."
- )
- return None, None
- res = message.text.split(None, 2)
- if len(res) >= 3:
- text = res[2]
-
- elif len(args) >= 1 and args[0].isdigit():
- user_id = int(args[0])
- res = message.text.split(None, 2)
- if len(res) >= 3:
- text = res[2]
-
- elif prev_message:
- user_id, text = id_from_reply(message)
-
- else:
- return None, None
-
- try:
- message.bot.get_chat(user_id)
- except BadRequest as excp:
- if excp.message in ("User_id_invalid", "Chat not found"):
- message.reply_text(
- "I don't seem to have interacted with this user before - please forward a message from "
- "them to give me control! (like a voodoo doll, I need a piece of them to be able "
- "to execute certain commands...)"
- )
- else:
- LOGGER.exception("Exception %s on user %s", excp.message, user_id)
-
- return None, None
-
- return user_id, text
-
-
-def extract_text(message) -> str:
- return (
- message.text
- or message.caption
- or (message.sticker.emoji if message.sticker else None)
- )
-
-
-def extract_unt_fedban(
- message: Message, args: List[str]
-) -> Tuple[Optional[int], Optional[str]]:
- prev_message = message.reply_to_message
- split_text = message.text.split(None, 1)
-
- if len(split_text) < 2:
- return id_from_reply(message) # only option possible
-
- text_to_parse = split_text[1]
-
- text = ""
-
- entities = list(message.parse_entities([MessageEntity.TEXT_MENTION]))
- ent = entities[0] if entities else None
- # if entity offset matches (command end/text start) then all good
- if entities and ent and ent.offset == len(message.text) - len(text_to_parse):
- ent = entities[0]
- user_id = ent.user.id
- text = message.text[ent.offset + ent.length:]
-
- elif len(args) >= 1 and args[0][0] == "@":
- user = args[0]
- user_id = get_user_id(user)
- if not user_id and not str(user_id).isdigit():
- message.reply_text(
- "I don't have this user's information in my database so, you'll not be able to interact with them"
- "Try replying to that person's msg or forward their message so i can act upon them"
- )
- return None, None
- res = message.text.split(None, 2)
- if len(res) >= 3:
- text = res[2]
-
- elif len(args) >= 1 and args[0].isdigit():
- user_id = int(args[0])
- res = message.text.split(None, 2)
- if len(res) >= 3:
- text = res[2]
-
- elif prev_message:
- user_id, text = id_from_reply(message)
-
- else:
- return None, None
-
- try:
- message.bot.get_chat(user_id)
- except BadRequest as excp:
- if (
- excp.message in ("User_id_invalid", "Chat not found")
- and not str(user_id).isdigit()
- ):
- message.reply_text(
- "I don't seem to have interacted with this user before - please forward a message from "
- "them to give me control! (like a voodoo doll, I need a piece of them to be able "
- "to execute certain commands...)"
- )
- return None, None
- if excp.message != "Chat not found":
- LOGGER.exception("Exception %s on user %s", excp.message, user_id)
- return None, None
- if not str(user_id).isdigit():
- return None, None
-
- return user_id, text
-
-
-def extract_user_fban(message: Message, args: List[str]) -> Optional[int]:
- return extract_unt_fedban(message, args)[0]
diff --git a/Exon/modules/helper_funcs/filters.py b/Exon/modules/helper_funcs/filters.py
deleted file mode 100644
index 40ee8d62..00000000
--- a/Exon/modules/helper_funcs/filters.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from emoji import UNICODE_EMOJI
-from telegram import Message
-from telegram.ext import MessageFilter
-
-from Exon import DEMONS, DEV_USERS
-
-
-class CustomFilters:
- class _Supporters(MessageFilter):
- def filter(self, message: Message):
- return bool(message.from_user and message.from_user.id in DEMONS)
-
- support_filter = _Supporters()
-
- class _Sudoers(MessageFilter):
- def filter(self, message: Message):
- return bool(message.from_user and message.from_user.id in DEV_USERS)
-
- dev_filter = _Sudoers()
-
- class _MimeType(MessageFilter):
- def __init__(self, mimetype):
- self.mime_type = mimetype
- self.name = f"CustomFilters.mime_type({self.mime_type})"
-
- def filter(self, message: Message):
- return bool(
- message.document and message.document.mime_type == self.mime_type
- )
-
- mime_type = _MimeType
-
- class _HasText(MessageFilter):
- def filter(self, message: Message):
- return bool(
- message.text
- or message.sticker
- or message.photo
- or message.document
- or message.video
- )
-
- has_text = _HasText()
-
- class _HasEmoji(MessageFilter):
- def filter(self, message: Message):
- text = message.text or ""
- for emoji in UNICODE_EMOJI:
- for letter in text:
- if letter == emoji:
- return True
- return False
-
- has_emoji = _HasEmoji()
-
- class _IsEmoji(MessageFilter):
- def filter(self, message: Message):
- if message.text and len(message.text) == 1:
- for emoji in UNICODE_EMOJI:
- for letter in message.text:
- if letter == emoji:
- return True
- return False
-
- is_emoji = _IsEmoji()
-
- class _IsAnonChannel(MessageFilter):
- def filter(self, message: Message):
- return bool(message.from_user and message.from_user.id == 136817688)
-
- is_anon_channel = _IsAnonChannel()
diff --git a/Exon/modules/helper_funcs/formatter.py b/Exon/modules/helper_funcs/formatter.py
deleted file mode 100644
index 87eb4b0d..00000000
--- a/Exon/modules/helper_funcs/formatter.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-
-def get_readable_time(seconds: int) -> str:
- count = 0
- ping_time = ""
- time_list = []
- time_suffix_list = ["s", "m", "h", "days"]
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
- for i in range(len(time_list)):
- time_list[i] = str(time_list[i]) + time_suffix_list[i]
- if len(time_list) == 4:
- ping_time += f"{time_list.pop()}, "
- time_list.reverse()
- ping_time += ":".join(time_list)
- return ping_time
-
-
-# Convert seconds to mm:ss
-async def convert_seconds_to_minutes(seconds: int):
- seconds = seconds
- seconds %= 24 * 3600
- seconds %= 3600
- minutes = seconds // 60
- seconds %= 60
- return "%02d:%02d" % (minutes, seconds)
diff --git a/Exon/modules/helper_funcs/git_api.py b/Exon/modules/helper_funcs/git_api.py
deleted file mode 100644
index 331e6346..00000000
--- a/Exon/modules/helper_funcs/git_api.py
+++ /dev/null
@@ -1,98 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import json
-import urllib.request as url
-
-VERSION = "1.1.0"
-APIURL = "http://api.github.com/repos/"
-
-
-def vercheck() -> str:
- return str(VERSION)
-
-
-# Repo-wise stuff
-
-
-def getData(repoURL):
- try:
- with url.urlopen(APIURL + repoURL + "/releases") as data_raw:
- return json.loads(data_raw.read().decode())
- except Exception:
- return None
-
-
-def getReleaseData(repoData, index):
- return repoData[index] if index < len(repoData) else None
-
-
-# Release-wise stuff
-
-
-def getAuthor(releaseData):
- return None if releaseData is None else releaseData["author"]["login"]
-
-
-def getAuthorUrl(releaseData):
- return None if releaseData is None else releaseData["author"]["html_url"]
-
-
-def getReleaseName(releaseData):
- return None if releaseData is None else releaseData["name"]
-
-
-def getReleaseDate(releaseData):
- return None if releaseData is None else releaseData["published_at"]
-
-
-def getAssetsSize(releaseData):
- return None if releaseData is None else len(releaseData["assets"])
-
-
-def getAssets(releaseData):
- return None if releaseData is None else releaseData["assets"]
-
-
-def getBody(releaseData): # changelog stuff
- return None if releaseData is None else releaseData["body"]
-
-
-# Asset-wise stuff
-
-
-def getReleaseFileName(asset):
- return asset["name"]
-
-
-def getReleaseFileURL(asset):
- return asset["browser_download_url"]
-
-
-def getDownloadCount(asset):
- return asset["download_count"]
-
-
-def getSize(asset):
- return asset["size"]
diff --git a/Exon/modules/helper_funcs/handlers.py b/Exon/modules/helper_funcs/handlers.py
deleted file mode 100644
index 501cf6b8..00000000
--- a/Exon/modules/helper_funcs/handlers.py
+++ /dev/null
@@ -1,155 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from pyrate_limiter import (
- BucketFullException,
- Duration,
- Limiter,
- MemoryListBucket,
- RequestRate,
-)
-from telegram import Update
-from telegram.ext import CommandHandler, Filters, MessageHandler, RegexHandler
-
-import Exon.modules.sql.blacklistusers_sql as sql
-from Exon import DEMONS, DEV_USERS, DRAGONS, TIGERS, WOLVES
-
-CMD_STARTERS = ("/", "!", "-", "?")
-
-
-class AntiSpam:
- def __init__(self):
- self.whitelist = (
- (DEV_USERS or [])
- + (DRAGONS or [])
- + (WOLVES or [])
- + (DEMONS or [])
- + (TIGERS or [])
- )
- # Values are HIGHLY experimental, its recommended you pay attention to our commits as we will be adjusting the values over time with what suits best.
- Duration.CUSTOM = 15 # Custom duration, 15 seconds
- self.sec_limit = RequestRate(6, Duration.CUSTOM) # 6 / Per 15 Seconds
- self.min_limit = RequestRate(20, Duration.MINUTE) # 20 / Per minute
- self.hour_limit = RequestRate(100, Duration.HOUR) # 100 / Per hour
- self.daily_limit = RequestRate(1000, Duration.DAY) # 1000 / Per day
- self.limiter = Limiter(
- self.sec_limit,
- self.min_limit,
- self.hour_limit,
- self.daily_limit,
- bucket_class=MemoryListBucket,
- )
-
- def check_user(self, user):
- """
- Return True if user is to be ignored else False
- """
- if user in self.whitelist:
- return False
- try:
- self.limiter.try_acquire(user)
- return False
- except BucketFullException:
- return True
-
-
-SpamChecker = AntiSpam()
-MessageHandlerChecker = AntiSpam()
-
-
-class CustomCommandHandler(CommandHandler):
- def __init__(self, command, callback, admin_ok=False, allow_edit=False, **kwargs):
- super().__init__(command, callback, **kwargs)
-
- if allow_edit is False:
- self.filters &= ~(
- Filters.update.edited_message | Filters.update.edited_channel_post
- )
-
- def check_update(self, update):
- if not isinstance(update, Update) or not update.effective_message:
- return
- message = update.effective_message
-
- try:
- user_id = update.effective_user.id
- except Exception:
- user_id = None
-
- if user_id and sql.is_user_blacklisted(user_id):
- return False
-
- if message.text and len(message.text) > 1:
- fst_word = message.text.split(None, 1)[0]
- if len(fst_word) > 1 and any(
- fst_word.startswith(start) for start in CMD_STARTERS
- ):
- args = message.text.split()[1:]
- command = fst_word[1:].split("@")
- command.append(message.bot.username)
- if user_id == 1087968824:
- user_id = update.effective_chat.id
- if (
- command[0].lower() not in self.command
- or command[1].lower() != message.bot.username.lower()
- ):
- return None
- if SpamChecker.check_user(user_id):
- return None
- if filter_result := self.filters(update):
- return args, filter_result
- return False
-
- def handle_update(self, update, dispatcher, check_result, context=None):
- if context:
- self.collect_additional_context(context, update, dispatcher, check_result)
- return self.callback(update, context)
- optional_args = self.collect_optional_args(dispatcher, update, check_result)
- return self.callback(dispatcher.bot, update, **optional_args)
-
- def collect_additional_context(self, context, update, dispatcher, check_result):
- if isinstance(check_result, bool):
- context.args = update.effective_message.text.split()[1:]
- else:
- context.args = check_result[0]
- if isinstance(check_result[1], dict):
- context.update(check_result[1])
-
-
-class CustomRegexHandler(RegexHandler):
- def __init__(self, pattern, callback, friendly="", **kwargs):
- super().__init__(pattern, callback, **kwargs)
-
-
-class CustomMessageHandler(MessageHandler):
- def __init__(self, filters, callback, friendly="", allow_edit=False, **kwargs):
- super().__init__(filters, callback, **kwargs)
- if allow_edit is False:
- self.filters &= ~(
- Filters.update.edited_message | Filters.update.edited_channel_post
- )
-
- def check_update(self, update):
- if isinstance(update, Update) and update.effective_message:
- return self.filters(update)
diff --git a/Exon/modules/helper_funcs/misc.py b/Exon/modules/helper_funcs/misc.py
deleted file mode 100644
index c07a5c7b..00000000
--- a/Exon/modules/helper_funcs/misc.py
+++ /dev/null
@@ -1,274 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import base64
-import json
-import typing
-import zlib
-from math import ceil
-from typing import Dict, List
-from urllib.parse import urljoin, urlparse, urlunparse
-from uuid import uuid4
-
-import base58
-import requests
-from Crypto import Hash, Protocol, Random
-from Crypto.Cipher import AES
-from telegram import (
- MAX_MESSAGE_LENGTH,
- Bot,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- InlineQueryResultArticle,
- InputTextMessageContent,
- ParseMode,
-)
-from telegram.error import TelegramError
-
-from Exon import NO_LOAD
-
-
-class EqInlineKeyboardButton(InlineKeyboardButton):
- def __eq__(self, other):
- return self.text == other.text
-
- def __lt__(self, other):
- return self.text < other.text
-
- def __gt__(self, other):
- return self.text > other.text
-
-
-def split_message(msg: str) -> List[str]:
- if len(msg) < MAX_MESSAGE_LENGTH:
- return [msg]
-
- lines = msg.splitlines(True)
- small_msg = ""
- result = []
- for line in lines:
- if len(small_msg) + len(line) < MAX_MESSAGE_LENGTH:
- small_msg += line
- else:
- result.append(small_msg)
- small_msg = line
- # Else statement at the end of the for loop, so append the leftover string.
- result.append(small_msg)
-
- return result
-
-
-def paginate_modules(page_n: int, module_dict: Dict, prefix, chat=None) -> List:
- if not chat:
- modules = sorted(
- [
- EqInlineKeyboardButton(
- x.__mod_name__,
- callback_data=f'{prefix}_module({x.__mod_name__.replace(" ", "_").lower()})',
- )
- for x in module_dict.values()
- ]
- )
- else:
- modules = sorted(
- [
- EqInlineKeyboardButton(
- x.__mod_name__,
- callback_data=f'{prefix}_module({chat},{x.__mod_name__.replace(" ", "_").lower()})',
- )
- for x in module_dict.values()
- ]
- )
-
- pairs = list(zip(modules[::3], modules[1::3], modules[2::3]))
- i = 0
- for m in pairs:
- for _ in m:
- i += 1
- if len(modules) - i == 1:
- pairs.append((modules[-1],))
- elif len(modules) - i == 2:
- pairs.append(
- (
- modules[-2],
- modules[-1],
- )
- )
-
- COLUMN_SIZE = 6
-
- max_num_pages = ceil(len(pairs) / COLUMN_SIZE)
- modulo_page = page_n % max_num_pages
-
- # can only have a certain amount of buttons side by side
- if len(pairs) > COLUMN_SIZE:
- pairs = pairs[
- modulo_page * COLUMN_SIZE: COLUMN_SIZE * (modulo_page + 1)
- ] + [
- (
- EqInlineKeyboardButton(
- "☜", callback_data=f"{prefix}_prev({modulo_page})"
- ),
- EqInlineKeyboardButton(
- "ɢᴏ ʜᴏᴍᴇ",
- callback_data="start_back",
- ),
- EqInlineKeyboardButton(
- "☞", callback_data=f"{prefix}_next({modulo_page})"
- ),
- )
- ]
-
- return pairs
-
-
-def article(
- title: str = "",
- description: str = "",
- message_text: str = "",
- thumb_url: str = None,
- reply_markup: InlineKeyboardMarkup = None,
- disable_web_page_preview: bool = False,
-) -> InlineQueryResultArticle:
- return InlineQueryResultArticle(
- id=uuid4(),
- title=title,
- description=description,
- thumb_url=thumb_url,
- input_message_content=InputTextMessageContent(
- message_text=message_text,
- disable_web_page_preview=disable_web_page_preview,
- ),
- reply_markup=reply_markup,
- )
-
-
-def send_to_list(
- bot: Bot, send_to: list, message: str, markdown=False, html=False
-) -> None:
- if html and markdown:
- raise Exception("Can only send with either markdown or HTML!")
- for user_id in set(send_to):
- try:
- if markdown:
- bot.send_message(user_id, message, parse_mode=ParseMode.MARKDOWN)
- elif html:
- bot.send_message(user_id, message, parse_mode=ParseMode.HTML)
- else:
- bot.send_message(user_id, message)
- except TelegramError:
- pass # ignore users who fail
-
-
-def build_keyboard(buttons):
- keyb = []
- for btn in buttons:
- if btn.same_line and keyb:
- keyb[-1].append(InlineKeyboardButton(btn.name, url=btn.url))
- else:
- keyb.append([InlineKeyboardButton(btn.name, url=btn.url)])
-
- return keyb
-
-
-def revert_buttons(buttons):
- return "".join(
- f"\n[{btn.name}](buttonurl://{btn.url}:same)"
- if btn.same_line
- else f"\n[{btn.name}](buttonurl://{btn.url})"
- for btn in buttons
- )
-
-
-def build_keyboard_parser(bot, chat_id, buttons):
- keyb = []
- for btn in buttons:
- if btn.url == "{rules}":
- btn.url = f"http://t.me/{bot.username}?start={chat_id}"
- if btn.same_line and keyb:
- keyb[-1].append(InlineKeyboardButton(btn.name, url=btn.url))
- else:
- keyb.append([InlineKeyboardButton(btn.name, url=btn.url)])
-
- return keyb
-
-
-def is_module_loaded(name):
- return name not in NO_LOAD
-
-
-def delete(delmsg, timer):
- sleep(timer)
- try:
- delmsg.delete()
- except Exception:
- return
-
-
-def upload_text(data: str) -> typing.Optional[str]:
- passphrase = Random.get_random_bytes(32)
- salt = Random.get_random_bytes(8)
- key = Protocol.KDF.PBKDF2(
- passphrase, salt, 32, 100000, hmac_hash_module=Hash.SHA256
- )
- compress = zlib.compressobj(wbits=-15)
- paste_blob = (
- compress.compress(json.dumps({"paste": data}, separators=(",", ":")).encode())
- + compress.flush()
- )
- cipher = AES.new(key, AES.MODE_GCM)
- paste_meta = [
- [
- base64.b64encode(cipher.nonce).decode(),
- base64.b64encode(salt).decode(),
- 100000,
- 256,
- 128,
- "aes",
- "gcm",
- "zlib",
- ],
- "syntaxhighlighting",
- 0,
- 0,
- ]
- cipher.update(json.dumps(paste_meta, separators=(",", ":")).encode())
- ct, tag = cipher.encrypt_and_digest(paste_blob)
- resp = requests.post(
- "https://bin.nixnet.services",
- headers={"X-Requested-With": "JSONHttpRequest"},
- data=json.dumps(
- {
- "v": 2,
- "adata": paste_meta,
- "ct": base64.b64encode(ct + tag).decode(),
- "meta": {"expire": "1week"},
- },
- separators=(",", ":"),
- ),
- )
- data = resp.json()
- url = list(urlparse(urljoin("https://bin.nixnet.services", data["url"])))
- url[5] = base58.b58encode(passphrase).decode()
- return urlunparse(url)
diff --git a/Exon/modules/helper_funcs/msg_types.py b/Exon/modules/helper_funcs/msg_types.py
deleted file mode 100644
index ef3bd24a..00000000
--- a/Exon/modules/helper_funcs/msg_types.py
+++ /dev/null
@@ -1,233 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-from enum import IntEnum, unique
-
-from telegram import Message
-
-from Exon.modules.helper_funcs.string_handling import button_markdown_parser
-
-
-@unique
-class Types(IntEnum):
- TEXT = 0
- BUTTON_TEXT = 1
- STICKER = 2
- DOCUMENT = 3
- PHOTO = 4
- AUDIO = 5
- VOICE = 6
- VIDEO = 7
-
-
-def get_note_type(msg: Message):
- data_type = None
- content = None
- text = ""
- raw_text = msg.text or msg.caption
- args = raw_text.split(None, 2) # use python's maxsplit to separate cmd and args
- note_name = args[1]
-
- buttons = []
- # determine what the contents of the filter are - text, image, sticker, etc
- if len(args) >= 3:
- offset = len(args[2]) - len(
- raw_text,
- ) # set correct offset relative to command + notename
- text, buttons = button_markdown_parser(
- args[2],
- entities=msg.parse_entities() or msg.parse_caption_entities(),
- offset=offset,
- )
- data_type = Types.BUTTON_TEXT if buttons else Types.TEXT
- elif msg.reply_to_message:
- entities = msg.reply_to_message.parse_entities()
- msgtext = msg.reply_to_message.text or msg.reply_to_message.caption
- if len(args) >= 2 and msg.reply_to_message.text: # not caption, text
- text, buttons = button_markdown_parser(msgtext, entities=entities)
- data_type = Types.BUTTON_TEXT if buttons else Types.TEXT
- elif msg.reply_to_message.sticker:
- content = msg.reply_to_message.sticker.file_id
- data_type = Types.STICKER
-
- elif msg.reply_to_message.document:
- content = msg.reply_to_message.document.file_id
- text, buttons = button_markdown_parser(msgtext, entities=entities)
- data_type = Types.DOCUMENT
-
- elif msg.reply_to_message.photo:
- content = msg.reply_to_message.photo[-1].file_id # last elem = best quality
- text, buttons = button_markdown_parser(msgtext, entities=entities)
- data_type = Types.PHOTO
-
- elif msg.reply_to_message.audio:
- content = msg.reply_to_message.audio.file_id
- text, buttons = button_markdown_parser(msgtext, entities=entities)
- data_type = Types.AUDIO
-
- elif msg.reply_to_message.voice:
- content = msg.reply_to_message.voice.file_id
- text, buttons = button_markdown_parser(msgtext, entities=entities)
- data_type = Types.VOICE
-
- elif msg.reply_to_message.video:
- content = msg.reply_to_message.video.file_id
- text, buttons = button_markdown_parser(msgtext, entities=entities)
- data_type = Types.VIDEO
-
- return note_name, text, data_type, content, buttons
-
-
-# note: add own args?
-def get_welcome_type(msg: Message):
- data_type = None
- content = None
- text = ""
-
- try:
- if msg.reply_to_message:
- args = msg.reply_to_message.text or msg.reply_to_message.caption
- else:
- args = msg.text.split(
- None,
- 1,
- ) # use python's maxsplit to separate cmd and args
- except AttributeError:
- args = False
-
- if msg.reply_to_message:
- if msg.reply_to_message.sticker:
- content = msg.reply_to_message.sticker.file_id
- text = None
- data_type = Types.STICKER
-
- elif msg.reply_to_message.document:
- content = msg.reply_to_message.document.file_id
- text = msg.reply_to_message.caption
- data_type = Types.DOCUMENT
-
- elif msg.reply_to_message.photo:
- content = msg.reply_to_message.photo[-1].file_id # last elem = best quality
- text = msg.reply_to_message.caption
- data_type = Types.PHOTO
-
- elif msg.reply_to_message.audio:
- content = msg.reply_to_message.audio.file_id
- text = msg.reply_to_message.caption
- data_type = Types.AUDIO
-
- elif msg.reply_to_message.voice:
- content = msg.reply_to_message.voice.file_id
- text = msg.reply_to_message.caption
- data_type = Types.VOICE
-
- elif msg.reply_to_message.video:
- content = msg.reply_to_message.video.file_id
- text = msg.reply_to_message.caption
- data_type = Types.VIDEO
-
- elif msg.reply_to_message.video_note:
- content = msg.reply_to_message.video_note.file_id
- text = None
- data_type = Types.VIDEO_NOTE
-
- buttons = []
- # determine what the contents of the filter are - text, image, sticker, etc
- if args:
- if msg.reply_to_message:
- argumen = msg.reply_to_message.caption or ""
- offset = 0 # offset is no need since target was in reply
- entities = msg.reply_to_message.parse_entities()
- else:
- argumen = args[1]
- offset = len(argumen) - len(
- msg.text,
- ) # set correct offset relative to command + notename
- entities = msg.parse_entities()
- text, buttons = button_markdown_parser(
- argumen,
- entities=entities,
- offset=offset,
- )
-
- if not data_type and text:
- data_type = Types.BUTTON_TEXT if buttons else Types.TEXT
- return text, data_type, content, buttons
-
-
-def get_filter_type(msg: Message):
- if not msg.reply_to_message and msg.text and len(msg.text.split()) >= 3:
- content = None
- text = msg.text.split(None, 2)[2]
- data_type = Types.TEXT
-
- elif (
- msg.reply_to_message
- and msg.reply_to_message.text
- and len(msg.text.split()) >= 2
- ):
- content = None
- text = msg.reply_to_message.text
- data_type = Types.TEXT
-
- elif msg.reply_to_message and msg.reply_to_message.sticker:
- content = msg.reply_to_message.sticker.file_id
- text = None
- data_type = Types.STICKER
-
- elif msg.reply_to_message and msg.reply_to_message.document:
- content = msg.reply_to_message.document.file_id
- text = msg.reply_to_message.caption
- data_type = Types.DOCUMENT
-
- elif msg.reply_to_message and msg.reply_to_message.photo:
- content = msg.reply_to_message.photo[-1].file_id # last elem = best quality
- text = msg.reply_to_message.caption
- data_type = Types.PHOTO
-
- elif msg.reply_to_message and msg.reply_to_message.audio:
- content = msg.reply_to_message.audio.file_id
- text = msg.reply_to_message.caption
- data_type = Types.AUDIO
-
- elif msg.reply_to_message and msg.reply_to_message.voice:
- content = msg.reply_to_message.voice.file_id
- text = msg.reply_to_message.caption
- data_type = Types.VOICE
-
- elif msg.reply_to_message and msg.reply_to_message.video:
- content = msg.reply_to_message.video.file_id
- text = msg.reply_to_message.caption
- data_type = Types.VIDEO
-
- elif msg.reply_to_message and msg.reply_to_message.video_note:
- content = msg.reply_to_message.video_note.file_id
- text = None
- data_type = Types.VIDEO_NOTE
-
- else:
- text = None
- data_type = None
- content = None
-
- return text, data_type, content
diff --git a/Exon/modules/helper_funcs/readable_time.py b/Exon/modules/helper_funcs/readable_time.py
deleted file mode 100644
index 2de32a11..00000000
--- a/Exon/modules/helper_funcs/readable_time.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-
-def get_readable_time(seconds: int) -> str:
- count = 0
- readable_time = ""
- time_list = []
- time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"]
-
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
-
- for x in range(len(time_list)):
- time_list[x] = str(time_list[x]) + time_suffix_list[x]
- if len(time_list) == 4:
- readable_time += f"{time_list.pop()}, "
-
- time_list.reverse()
- readable_time += ":".join(time_list)
-
- return readable_time
diff --git a/Exon/modules/helper_funcs/regex_helper.py b/Exon/modules/helper_funcs/regex_helper.py
deleted file mode 100644
index f4fed42d..00000000
--- a/Exon/modules/helper_funcs/regex_helper.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-import regex
-
-
-def regex_searcher(regex_string, string):
- try:
- search = regex.search(regex_string, string, timeout=6)
- except (TimeoutError, Exception):
- return False
- return search
-
-
-def infinite_loop_check(regex_string):
- loop_matches = [
- r"\((.{1,}[\+\*]){1,}\)[\+\*].",
- r"[\(\[].{1,}\{\d(,)?\}[\)\]]\{\d(,)?\}",
- r"\(.{1,}\)\{.{1,}(,)?\}\(.*\)(\+|\* |\{.*\})",
- ]
- for match in loop_matches:
- if match_1 := regex.search(match, regex_string):
- return True
- return False
diff --git a/Exon/modules/helper_funcs/string_handling.py b/Exon/modules/helper_funcs/string_handling.py
deleted file mode 100644
index 742e3a98..00000000
--- a/Exon/modules/helper_funcs/string_handling.py
+++ /dev/null
@@ -1,309 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import re
-import time
-from typing import Dict, List
-
-import bleach
-import emoji
-import markdown2
-# from emoji import unicode_codes
-from telegram import MessageEntity
-from telegram.utils.helpers import escape_markdown
-
-# NOTE: the url \ escape may cause double escapes
-# match * (bold) (don't escape if in url)
-# match _ (italics) (don't escape if in url)
-# match ` (code)
-# match []() (markdown link)
-# else, escape *, _, `, and [
-MATCH_MD = re.compile(
- r"\*(.*?)\*|"
- r"_(.*?)_|"
- r"`(.*?)`|"
- r"(?[*_`\[])",
-)
-
-# regex to find []() links -> hyperlinks/buttons
-LINK_REGEX = re.compile(r"(? str:
- """
- Escape all invalid markdown
- :param to_parse: text to escape
- :return: valid markdown string
- """
- offset = 0 # offset to be used as adding a \ character causes the string to shift
- for match in MATCH_MD.finditer(to_parse):
- if match.group("esc"):
- ent_start = match.start()
- to_parse = (
- to_parse[: ent_start + offset] + "\\" + to_parse[ent_start + offset:]
- )
- offset += 1
- return to_parse
-
-
-# This is a fun one.
-def _calc_emoji_offset(to_calc) -> int:
- # Get all emoji in text.
- emoticons = emoji.get_emoji_regexp().finditer(to_calc)
- # Check the utf16 length of the emoji to determine the offset it caused.
- # Normal, 1 character emoji don't affect; hence sub 1.
- # special, eg with two emoji characters (eg face, and skin col) will have length 2, so by subbing one we
- # know we'll get one extra offset,
- return sum(len(e.group(0).encode("utf-16-le")) // 2 - 1 for e in emoticons)
-
-
-def markdown_parser(
- txt: str, entities: Dict[MessageEntity, str] = None, offset: int = 0
-) -> str:
- """
- Parse a string, escaping all invalid markdown entities.
- Escapes URL's so as to avoid URL mangling.
- Re-adds any telegram code entities obtained from the entities object.
- :param txt: text to parse
- :param entities: dict of message entities in text
- :param offset: message offset - command and notename length
- :return: valid markdown string
- """
- if not entities:
- entities = {}
- if not txt:
- return ""
-
- prev = 0
- res = ""
- # Loop over all message entities, and:
- # reinsert code
- # escape free-standing urls
- for ent, ent_text in entities.items():
- if ent.offset < -offset:
- continue
-
- start = ent.offset + offset # start of entity
- end = ent.offset + offset + ent.length - 1 # end of entity
-
- if ent.type not in ("code", "url", "text_link"):
- continue
-
- # count emoji to switch counter
- count = _calc_emoji_offset(txt[:start])
- start -= count
- end -= count
-
- # URL handling -> do not escape if in [](), escape otherwise.
- if ent.type == "url":
- if any(
- match.start(1) <= start and end <= match.end(1)
- for match in LINK_REGEX.finditer(txt)
- ):
- continue
- # TODO: investigate possible offset bug when lots of emoji are present
- res += _selective_escape(txt[prev:start] or "") + escape_markdown(
- ent_text
- )
-
- elif ent.type == "code":
- res += f"{_selective_escape(txt[prev:start])}`{ent_text}`"
-
- elif ent.type == "text_link":
- res += f"{_selective_escape(txt[prev:start])}[{ent_text}]({ent.url})"
-
- end += 1
-
- prev = end
-
- res += _selective_escape(txt[prev:]) # add the rest of the text
- return res
-
-
-def button_markdown_parser(
- txt: str,
- entities: Dict[MessageEntity, str] = None,
- offset: int = 0,
-) -> (str, List):
- markdown_note = markdown_parser(txt, entities, offset)
- prev = 0
- note_data = ""
- buttons = []
- for match in BTN_URL_REGEX.finditer(markdown_note):
- # Check if btnurl is escaped
- n_escapes = 0
- to_check = match.start(1) - 1
- while to_check > 0 and markdown_note[to_check] == "\\":
- n_escapes += 1
- to_check -= 1
-
- # if even, not escaped -> create button
- if n_escapes % 2 == 0:
- # create a thruple with button label, url, and newline status
- buttons.append((match.group(2), match.group(3), bool(match.group(4))))
- note_data += markdown_note[prev: match.start(1)]
- prev = match.end(1)
- # if odd, escaped -> move along
- else:
- note_data += markdown_note[prev:to_check]
- prev = match.start(1) - 1
-
- note_data += markdown_note[prev:]
-
- return note_data, buttons
-
-
-def escape_invalid_curly_brackets(text: str, valids: List[str]) -> str:
- new_text = ""
- idx = 0
- while idx < len(text):
- if text[idx] == "{":
- if idx + 1 < len(text) and text[idx + 1] == "{":
- idx += 2
- new_text += "{{{{"
- continue
- success = False
- for v in valids:
- if text[idx:].startswith("{" + v + "}"):
- success = True
- break
- if success:
- new_text += text[idx: idx + len(v) + 2]
- idx += len(v) + 2
- continue
- new_text += "{{"
-
- elif text[idx] == "}":
- if idx + 1 < len(text) and text[idx + 1] == "}":
- idx += 2
- new_text += "}}}}"
- continue
- new_text += "}}"
-
- else:
- new_text += text[idx]
- idx += 1
-
- return new_text
-
-
-SMART_OPEN = "“"
-SMART_CLOSE = "”"
-START_CHAR = ("'", '"', SMART_OPEN)
-
-
-def split_quotes(text: str) -> List:
- if not any(text.startswith(char) for char in START_CHAR):
- return text.split(None, 1)
- counter = 1 # ignore first char -> is some kind of quote
- while counter < len(text):
- if text[counter] == "\\":
- counter += 1
- elif text[counter] == text[0] or (
- text[0] == SMART_OPEN and text[counter] == SMART_CLOSE
- ):
- break
- counter += 1
- else:
- return text.split(None, 1)
-
- # 1 to avoid starting quote, and counter is exclusive so avoids ending
- key = remove_escapes(text[1:counter].strip())
- # index will be in range, or `else` would have been executed and returned
- rest = text[counter + 1:].strip()
- if not key:
- key = text[0] + text[0]
- return list(filter(None, [key, rest]))
-
-
-def remove_escapes(text: str) -> str:
- res = ""
- is_escaped = False
- for counter in range(len(text)):
- if is_escaped:
- res += text[counter]
- is_escaped = False
- elif text[counter] == "\\":
- is_escaped = True
- else:
- res += text[counter]
- return res
-
-
-def escape_chars(text: str, to_escape: List[str]) -> str:
- to_escape.append("\\")
- new_text = ""
- for x in text:
- if x in to_escape:
- new_text += "\\"
- new_text += x
- return new_text
-
-
-def extract_time(message, time_val):
- if any(time_val.endswith(unit) for unit in ("m", "h", "d")):
- unit = time_val[-1]
- time_num = time_val[:-1] # type: str
- if not time_num.isdigit():
- message.reply_text("Invalid time amount specified.")
- return ""
-
- if unit == "d":
- bantime = int(time.time() + int(time_num) * 24 * 60 * 60)
- elif unit == "h":
- bantime = int(time.time() + int(time_num) * 60 * 60)
- elif unit == "m":
- bantime = int(time.time() + int(time_num) * 60)
- else:
- # how even...?
- return ""
- return bantime
- message.reply_text(
- f"Invalid time type specified. Expected m,h, or d, got: {time_val[-1]}"
- )
- return ""
-
-
-def markdown_to_html(text):
- text = text.replace("*", "**")
- text = text.replace("`", "```")
- text = text.replace("~", "~~")
- _html = markdown2.markdown(text, extras=["strike", "underline"])
- return bleach.clean(
- _html,
- tags=["strong", "em", "a", "code", "pre", "strike", "u"],
- strip=True,
- )[:-1]
diff --git "a/Exon/modules/helper_funcs/telethn/ABISHNOI \302\251" "b/Exon/modules/helper_funcs/telethn/ABISHNOI \302\251"
deleted file mode 100644
index bec02f49..00000000
--- "a/Exon/modules/helper_funcs/telethn/ABISHNOI \302\251"
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# """DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# MY ALL BOTS :- Abishnoi_bots
-# GITHUB :- Abishnoi69 """
diff --git a/Exon/modules/helper_funcs/telethn/__init__.py b/Exon/modules/helper_funcs/telethn/__init__.py
deleted file mode 100644
index 3e7af513..00000000
--- a/Exon/modules/helper_funcs/telethn/__init__.py
+++ /dev/null
@@ -1,31 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from Exon import DEMONS, DEV_USERS, DRAGONS, TIGERS, WOLVES
-
-IMMUNE_USERS = DRAGONS + WOLVES + DEMONS + TIGERS + DEV_USERS
-
-IMMUNE_USERS = (
- list(DRAGONS) + list(WOLVES) + list(DEMONS) + list(TIGERS) + list(DEV_USERS)
-)
diff --git a/Exon/modules/helper_funcs/telethn/chatstatus.py b/Exon/modules/helper_funcs/telethn/chatstatus.py
deleted file mode 100644
index 488aa1e3..00000000
--- a/Exon/modules/helper_funcs/telethn/chatstatus.py
+++ /dev/null
@@ -1,124 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from telethon.tl.types import ChannelParticipantsAdmins
-
-from Exon import DRAGONS
-from Exon.modules.helper_funcs.telethn import IMMUNE_USERS, telethn
-
-
-async def user_is_ban_protected(user_id: int, message):
- status = False
- if message.is_private or user_id in (IMMUNE_USERS):
- return True
-
- async for user in telethn.iter_participants(
- message.chat_id,
- filter=ChannelParticipantsAdmins,
- ):
- if user_id == user.id:
- status = True
- break
- return status
-
-
-async def user_is_admin(user_id: int, message):
- status = False
- if message.is_private:
- return True
-
- async for user in telethn.iter_participants(
- message.chat_id,
- filter=ChannelParticipantsAdmins,
- ):
- if user_id == user.id or user_id in DRAGONS:
- status = True
- break
- return status
-
-
-async def is_user_admin(user_id: int, chat_id):
- status = False
- async for user in telethn.iter_participants(
- chat_id,
- filter=ChannelParticipantsAdmins,
- ):
- if user_id == user.id or user_id in DRAGONS:
- status = True
- break
- return status
-
-
-async def natsunagi_is_admin(chat_id: int):
- status = False
- natsunagi = await telethn.get_me()
- async for user in telethn.iter_participants(
- chat_id,
- filter=ChannelParticipantsAdmins,
- ):
- if natsunagi.id == user.id:
- status = True
- break
- return status
-
-
-async def is_user_in_chat(chat_id: int, user_id: int):
- status = False
- async for user in telethn.iter_participants(chat_id):
- if user_id == user.id:
- status = True
- break
- return status
-
-
-async def can_change_info(message):
- return message.chat.admin_rights.change_info if message.chat.admin_rights else False
-
-
-async def can_ban_users(message):
- return message.chat.admin_rights.ban_users if message.chat.admin_rights else False
-
-
-async def can_pin_messages(message):
- return (
- message.chat.admin_rights.pin_messages if message.chat.admin_rights else False
- )
-
-
-async def can_invite_users(message):
- return (
- message.chat.admin_rights.invite_users if message.chat.admin_rights else False
- )
-
-
-async def can_add_admins(message):
- return message.chat.admin_rights.add_admins if message.chat.admin_rights else False
-
-
-async def can_delete_messages(message):
- if message.is_private:
- return True
- if message.chat.admin_rights:
- return message.chat.admin_rights.delete_messages
- return False
diff --git a/Exon/modules/info.py b/Exon/modules/info.py
deleted file mode 100644
index 97f2bb9d..00000000
--- a/Exon/modules/info.py
+++ /dev/null
@@ -1,155 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from pyrogram import filters
-from pyrogram.types import Message
-
-from Exon import Abishnoi as app
-from Exon import DEV_USERS
-from Exon.utils.sections import section
-
-
-async def get_user_info(user, already=False):
- if not already:
- user = await app.get_users(user)
- if not user.first_name:
- return ["Deleted account", None]
- user_id = user.id
- username = user.username
- first_name = user.first_name
- mention = user.mention("Link")
- dc_id = user.dc_id
- photo_id = user.photo.big_file_id if user.photo else None
- is_sudo = user_id in DEV_USERS
- body = {
- "ID": user_id,
- "DC": dc_id,
- "Name": [first_name],
- "Username": [f"@{username}" if username else None],
- "Mention": [mention],
- "Sudo": is_sudo,
- }
- caption = section("User info", body)
- return [caption, photo_id]
-
-
-async def get_chat_info(chat, already=False):
- if not already:
- chat = await app.get_chat(chat)
- chat_id = chat.id
- username = chat.username
- title = chat.title
- type_ = chat.type
- is_scam = chat.is_scam
- description = chat.description
- members = chat.members_count
- is_restricted = chat.is_restricted
- link = f"[Link](t.me/{username})" if username else None
- dc_id = chat.dc_id
- photo_id = chat.photo.big_file_id if chat.photo else None
- body = {
- "ID": chat_id,
- "DC": dc_id,
- "Type": type_,
- "Name": [title],
- "Username": [f"@{username}" if username else None],
- "Mention": [link],
- "Members": members,
- "Scam": is_scam,
- "Restricted": is_restricted,
- "Description": [description],
- }
- caption = section("Chat info", body)
- return [caption, photo_id]
-
-
-@app.on_message(filters.command("uinfo"))
-async def info_func(_, message: Message):
- if message.reply_to_message:
- user = message.reply_to_message.from_user.id
- elif len(message.command) == 1:
- user = message.from_user.id
- else:
- user = message.text.split(None, 1)[1]
-
- m = await message.reply_text("Processing...")
-
- try:
- info_caption, photo_id = await get_user_info(user)
- except Exception as e:
- return await m.edit(str(e))
-
- if not photo_id:
- return await m.edit(info_caption, disable_web_page_preview=True)
- photo = await app.download_media(photo_id)
-
- await message.reply_photo(photo, caption=info_caption, quote=False)
- await m.delete()
- os.remove(photo)
-
-
-@app.on_message(filters.command("cinfo"))
-async def chat_info_func(_, message: Message):
- try:
- if len(message.command) > 2:
- return await message.reply_text("**Usage:**cinfo ")
-
- if len(message.command) == 1:
- chat = message.chat.id
- elif len(message.command) == 2:
- chat = message.text.split(None, 1)[1]
-
- m = await message.reply_text("Processing...")
-
- info_caption, photo_id = await get_chat_info(chat)
- if not photo_id:
- return await m.edit(info_caption, disable_web_page_preview=True)
-
- photo = await app.download_media(photo_id)
- await message.reply_photo(photo, caption=info_caption, quote=False)
-
- await m.delete()
- os.remove(photo)
- except Exception as e:
- await m.edit(e)
-
-
-__mod_name__ = "𝐂ɪɴғᴏ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "cinfo_help")
-
-# """
diff --git a/Exon/modules/invitelinks.py b/Exon/modules/invitelinks.py
deleted file mode 100644
index 24c0b61d..00000000
--- a/Exon/modules/invitelinks.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import html
-import re
-
-from telegram import ParseMode
-from telegram.ext import ChatJoinRequestHandler
-from telegram.ext.callbackcontext import CallbackContext
-from telegram.inline.inlinekeyboardbutton import InlineKeyboardButton
-from telegram.inline.inlinekeyboardmarkup import InlineKeyboardMarkup
-from telegram.update import Update
-from telegram.utils.helpers import mention_html
-
-from Exon import dispatcher
-from Exon.modules.helper_funcs.chat_status import bot_admin, user_can_restrict_no_reply
-from Exon.modules.helper_funcs.decorators import Exoncallback
-from Exon.modules.log_channel import loggable
-
-
-def chat_join_req(upd: Update, ctx: CallbackContext):
- bot = ctx.bot
- user = upd.chat_join_request.from_user
- chat = upd.chat_join_request.chat
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- "ᴀᴘᴘʀᴏᴠᴇ", callback_data=f"cb_approve={user.id}"
- ),
- InlineKeyboardButton(
- "ᴅᴇᴄʟɪɴᴇ", callback_data=f"cb_decline={user.id}"
- ),
- ]
- ]
- )
- bot.send_message(
- chat.id,
- f'{mention_html(user.id, user.first_name)} ᴡᴀɴᴛs ᴛᴏ ᴊᴏɪɴ {chat.title or "this chat"}',
- reply_markup=keyboard,
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncallback(pattern=r"cb_approve=")
-@user_can_restrict_no_reply
-@bot_admin
-@loggable
-def approve_joinreq(update: Update, context: CallbackContext) -> str:
- bot = context.bot
- query = update.callback_query
- user = update.effective_user
- chat = update.effective_chat
- match = re.match(r"cb_approve=(.+)", query.data)
-
- user_id = match[1]
- try:
- bot.approve_chat_join_request(chat.id, user_id)
- update.effective_message.edit_text(
- f"ᴊᴏɪɴ ʀᴇǫᴜᴇsᴛ ᴀᴘᴘʀᴏᴠᴇᴅ ʙʏ {mention_html(user.id, user.first_name)}.",
- parse_mode="HTML",
- )
- return f"{html.escape(chat.title)}:\n#𝐉𝐎𝐈𝐍_𝐑𝐄𝐐𝐔𝐄𝐒𝐓\nᴀᴘᴘʀᴏᴠᴇᴅ\nᴀᴅᴍɪɴ: {mention_html(user.id, html.escape(user.first_name))}\nᴜsᴇʀ: {mention_html(user_id, html.escape(user.first_name))}\n"
- except Exception as e:
- update.effective_message.edit_text(str(e))
-
-
-@Exoncallback(pattern=r"cb_decline=")
-@user_can_restrict_no_reply
-@bot_admin
-@loggable
-def decline_joinreq(update: Update, context: CallbackContext) -> str:
- bot = context.bot
- query = update.callback_query
- user = update.effective_user
- chat = update.effective_chat
- match = re.match(r"cb_decline=(.+)", query.data)
-
- user_id = match[1]
- try:
- bot.decline_chat_join_request(chat.id, user_id)
- update.effective_message.edit_text(
- f"ᴊᴏɪɴ ʀᴇǫᴜᴇsᴛ ᴅᴇᴄʟɪɴᴇᴅ ʙʏ {mention_html(user.id, user.first_name)}.",
- parse_mode="HTML",
- )
- return f"{html.escape(chat.title)}:\n#𝐉𝐎𝐈𝐍_𝐑𝐄𝐐𝐔𝐄𝐒𝐓\nᴅᴇᴄʟɪɴᴇᴅ\nᴀᴅᴍɪɴ: {mention_html(user.id, html.escape(user.first_name))}\nᴜsᴇʀ: {mention_html(user_id, html.escape(user.first_name))}\n"
- except Exception as e:
- update.effective_message.edit_text(str(e))
-
-
-dispatcher.add_handler(ChatJoinRequestHandler(callback=chat_join_req, run_async=True))
diff --git a/Exon/modules/karmas.py b/Exon/modules/karmas.py
deleted file mode 100644
index 83833013..00000000
--- a/Exon/modules/karmas.py
+++ /dev/null
@@ -1,194 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-
-import asyncio
-
-from pyrogram import filters
-
-from Exon import Abishnoi as abishnoi
-from Exon import OWNER_ID
-from Exon.modules.no_sql.karma_db import (
- alpha_to_int,
- get_karma,
- get_karmas,
- int_to_alpha,
- is_karma_on,
- karma_off,
- karma_on,
- update_karma,
-)
-
-regex_upvote = r"^(\+|\+\+|\+1|\++|\+69|thx|thanx|thanks|🖤|❣️|💝|💖|💕|❤|💘|cool|good|👍|baby|thankyou|love|pro)$"
-regex_downvote = r"^(\-|\-\-|\-1|👎|💔|noob|weak|fuck off|nub|gey|kid|shit|mf)$"
-
-karma_positive_group = 3
-karma_negative_group = 4
-
-
-@abishnoi.on_message(
- filters.text
- & filters.group
- & filters.incoming
- & filters.reply
- & filters.regex(regex_upvote)
- & ~filters.via_bot
- & ~filters.bot,
- group=karma_positive_group,
-)
-async def upvote(_, message):
- if not await is_karma_on(message.chat.id):
- return
- if not message.reply_to_message.from_user:
- return
- if not message.from_user:
- return
- if message.reply_to_message.from_user.id == OWNER_ID:
- await message.reply_text("ʜᴏᴡ sᴏ ᴘʀᴏ ?")
- return
- if message.reply_to_message.from_user.id == message.from_user.id:
- return
- chat_id = message.chat.id
- user_id = message.reply_to_message.from_user.id
- user_mention = message.reply_to_message.from_user.mention
- current_karma = await get_karma(chat_id, await int_to_alpha(user_id))
- if current_karma:
- current_karma = current_karma["karma"]
- karma = current_karma + 1
- else:
- karma = 1
- new_karma = {"karma": karma}
- await update_karma(chat_id, await int_to_alpha(user_id), new_karma)
- await message.reply_text(
- f"ɪɴᴄʀᴇᴍᴇɴᴛᴇᴅ ᴋᴀʀᴍᴀ ᴏғ {user_mention} ʙʏ 1.\n**ᴛᴏᴛᴀʟ ᴩᴏɪɴᴛs :** {karma}"
- )
-
-
-@abishnoi.on_message(
- filters.text
- & filters.group
- & filters.incoming
- & filters.reply
- & filters.regex(regex_downvote)
- & ~filters.via_bot
- & ~filters.bot,
- group=karma_negative_group,
-)
-async def downvote(_, message):
- if not await is_karma_on(message.chat.id):
- return
- if not message.reply_to_message.from_user:
- return
- if not message.from_user:
- return
- if message.reply_to_message.from_user.id == OWNER_ID:
- await message.reply_text("ɪ ᴋɴᴏᴡ ʜɪᴍ, sᴏ ɪ'ᴍ ɴᴏᴛ ɢᴏɴɴᴀ ᴅᴏ ᴛʜᴀᴛ ʙᴀʙʏ.")
- return
- if message.reply_to_message.from_user.id == message.from_user.id:
- return
- user_id = message.reply_to_message.from_user.id
- user_mention = message.reply_to_message.from_user.mention
- current_karma = await get_karma(message.chat.id, await int_to_alpha(user_id))
- if current_karma:
- current_karma = current_karma["karma"]
- karma = current_karma - 1
- else:
- karma = 0
- new_karma = {"karma": karma}
- await update_karma(message.chat.id, await int_to_alpha(user_id), new_karma)
- await message.reply_text(
- f"ᴅᴇᴄʀᴇᴍᴇɴᴛᴇᴅ ᴋᴀʀᴍᴀ ᴏғ {user_mention} ʙʏ 1.\n**ᴛᴏᴛᴀʟ ᴩᴏɪɴᴛs :** {karma}"
- )
-
-
-@abishnoi.on_cmd("karmastat", group_only=True)
-@abishnoi.adminsOnly(permissions="can_change_info", is_both=True)
-async def command_karma(_, message):
- chat_id = message.chat.id
- if not message.reply_to_message:
- m = await message.reply_text("ɢᴇᴛᴛɪɴɢ ᴋᴀʀᴍᴀ ʟɪsᴛ ᴏғ ᴛᴏᴘ 10 ᴜsᴇʀs ᴡᴀɪᴛ...")
- karma = await get_karmas(chat_id)
- if not karma:
- await m.edit("ɴᴏ ᴋᴀʀᴍᴀ ɪɴ ᴅʙ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ.")
- return
- msg = f"🏆 **ᴋᴀʀᴍᴀ ʟɪsᴛ ᴏғ {message.chat.title}**\n"
- limit = 0
- karma_dicc = {}
- for i in karma:
- user_id = await alpha_to_int(i)
- user_karma = karma[i]["karma"]
- karma_dicc[str(user_id)] = user_karma
- karma_arranged = dict(
- sorted(
- karma_dicc.items(),
- key=lambda item: item[1],
- reverse=True,
- )
- )
- if not karma_dicc:
- await m.edit("ɴᴏ ᴋᴀʀᴍᴀ ɪɴ ᴅʙ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ.")
- return
- for user_idd, karma_count in karma_arranged.items():
- if limit > 9:
- break
- try:
- user = await app.get_users(int(user_idd))
- await asyncio.sleep(0.8)
- except Exception:
- continue
- first_name = user.first_name
- if not first_name:
- continue
- username = user.username
- msg += f"\n≛ [{first_name}](https://t.me/{username}) : {karma_count}"
- limit += 1
- await m.edit(msg, disable_web_page_preview=True)
- else:
- user_id = message.reply_to_message.from_user.id
- karma = await get_karma(chat_id, await int_to_alpha(user_id))
- karma = karma["karma"] if karma else 0
- await message.reply_text(f"**ᴛᴏᴛᴀʟ ᴘᴏɪɴᴛs**: __{karma}__")
-
-
-@abishnoi.on_cmd("karma", group_only=True)
-@abishnoi.adminsOnly(permissions="can_change_info", is_both=True)
-async def captcha_state(_, message):
- usage = "**ᴜsᴀɢᴇ:**\n/karma [ON|OFF]"
- if len(message.command) != 2:
- return await message.reply_text(usage)
- state = message.text.split(None, 1)[1].strip()
- state = state.lower()
- if state == "on":
- await karma_on(message.chat.id)
- await message.reply_text("ᴇɴᴀʙʟᴇᴅ ᴋᴀʀᴍᴀ sʏsᴛᴇᴍ.")
- elif state == "off":
- await karma_off(message.chat.id)
- await message.reply_text("ᴅɪsᴀʙʟᴇᴅ ᴋᴀʀᴍᴀ sʏsᴛᴇᴍ.")
- else:
- await message.reply_text(usage)
diff --git a/Exon/modules/language.py b/Exon/modules/language.py
deleted file mode 100644
index 28044815..00000000
--- a/Exon/modules/language.py
+++ /dev/null
@@ -1,102 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import itertools
-from collections.abc import Iterable
-from typing import Generator, List, Union
-
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
-
-import Exon.modules.sql.language_sql as sql
-from Exon.langs import get_language, get_languages, get_string
-from Exon.modules.helper_funcs.chat_status import user_admin, user_admin_no_reply
-from Exon.modules.helper_funcs.decorators import Exoncallback, Exoncmd
-
-
-def paginate(iterable: Iterable, page_size: int) -> Generator[List, None, None]:
- while True:
- i1, i2 = itertools.tee(iterable)
- iterable, page = (
- itertools.islice(i1, page_size, None),
- list(itertools.islice(i2, page_size)),
- )
- if not page:
- break
- yield page
-
-
-def gs(chat_id: Union[int, str], string: str) -> str:
- try:
- lang = sql.get_chat_lang(chat_id)
- return get_string(lang, string)
- except Exception:
- return "ᴍᴇ ɴᴏᴡ ʙᴜsʏ ᴡʜᴇɴ ғʀᴇᴇ ᴀᴅᴅ ᴛʜɪs "
-
-
-@Exoncmd(command="language")
-@user_admin
-def set_lang(update: Update, _) -> None:
- chat = update.effective_chat
- msg = update.effective_message
-
- msg_text = gs(chat.id, "curr_chat_lang").format(
- get_language(sql.get_chat_lang(chat.id))[:-3]
- )
-
- keyb = [
- InlineKeyboardButton(
- text=name,
- callback_data=f"setLang_{code}",
- )
- for code, name in get_languages().items()
- ]
- keyb = list(paginate(keyb, 2))
- keyb.append(
- [
- InlineKeyboardButton(
- text="ʜᴇʟᴘ ᴜs ɪɴ ᴛʀᴀɴsʟᴀᴛɪᴏɴs",
- url="https://github.com/Abishnoi69/ExonRobot", # plz. Don't edit and change
- )
- ]
- )
- msg.reply_text(msg_text, reply_markup=InlineKeyboardMarkup(keyb))
-
-
-@Exoncallback(pattern=r"setLang_")
-@user_admin_no_reply
-def lang_button(update: Update, _) -> None:
- query = update.callback_query
- chat = update.effective_chat
-
- query.answer()
- lang = query.data.split("_")[1]
- sql.set_lang(chat.id, lang)
-
- query.message.edit_text(
- gs(chat.id, "set_chat_lang").format(get_language(lang)[:-3])
- )
diff --git a/Exon/modules/locks.py b/Exon/modules/locks.py
deleted file mode 100644
index 8417db1d..00000000
--- a/Exon/modules/locks.py
+++ /dev/null
@@ -1,578 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import ast
-import html
-
-from alphabet_detector import AlphabetDetector
-from telegram import ChatPermissions, MessageEntity, ParseMode, TelegramError, Update
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, Filters
-from telegram.utils.helpers import mention_html
-
-import Exon.modules.sql.locks_sql as sql
-from Exon import LOGGER as log
-from Exon import dispatcher
-from Exon.modules.connection import connected
-from Exon.modules.helper_funcs.alternate import send_message, typing_action
-from Exon.modules.helper_funcs.anonymous import AdminPerms, user_admin
-from Exon.modules.helper_funcs.chat_status import can_delete, is_bot_admin
-from Exon.modules.helper_funcs.chat_status import user_admin as u_admin
-from Exon.modules.helper_funcs.chat_status import user_not_admin
-from Exon.modules.helper_funcs.decorators import Exoncmd as natsunagicmd
-from Exon.modules.helper_funcs.decorators import Exonmsg as natsunagimsg
-from Exon.modules.log_channel import loggable
-from Exon.modules.sql.approve_sql import is_approved
-
-ad = AlphabetDetector()
-
-LOCK_TYPES = {
- "audio": Filters.audio,
- "voice": Filters.voice,
- "document": Filters.document,
- "video": Filters.video,
- "contact": Filters.contact,
- "photo": Filters.photo,
- "url": Filters.entity(MessageEntity.URL)
- | Filters.caption_entity(MessageEntity.URL),
- "bots": Filters.status_update.new_chat_members,
- "forward": Filters.forwarded & ~Filters.is_automatic_forward,
- "game": Filters.game,
- "location": Filters.location,
- "egame": Filters.dice,
- "rtl": "rtl",
- "button": "button",
- "inline": "inline",
- "apk": Filters.document.mime_type("application/vnd.android.package-archive"),
- "doc": Filters.document.mime_type("application/msword"),
- "exe": Filters.document.mime_type("application/x-ms-dos-executable"),
- "gif": Filters.document.mime_type("video/mp4"),
- "jpg": Filters.document.mime_type("image/jpeg"),
- "mp3": Filters.document.mime_type("audio/mpeg"),
- "pdf": Filters.document.mime_type("application/pdf"),
- "txt": Filters.document.mime_type("text/plain"),
- "xml": Filters.document.mime_type("application/xml"),
- "zip": Filters.document.mime_type("application/zip"),
- "docx": Filters.document.mime_type(
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
- ),
- "py": Filters.document.mime_type("text/x-python"),
- "svg": Filters.document.mime_type("image/svg+xml"),
- "targz": Filters.document.mime_type("application/x-compressed-tar"),
- "wav": Filters.document.mime_type("audio/x-wav"),
-}
-
-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,
- },
- "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},
-}
-
-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,
- },
- "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},
-}
-
-PERM_GROUP = -8
-REST_GROUP = -12
-
-
-# NOT ASYNC
-def restr_members(
- bot, chat_id, members, messages=False, media=False, other=False, previews=False
-):
- for mem in members:
- try:
- bot.restrict_chat_member(
- chat_id,
- mem.user,
- 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
-def unrestr_members(
- bot, chat_id, members, messages=True, media=True, other=True, previews=True
-):
- for mem in members:
- try:
- bot.restrict_chat_member(
- chat_id,
- mem.user,
- can_send_messages=messages,
- can_send_media_messages=media,
- can_send_other_messages=other,
- can_add_web_page_previews=previews,
- )
- except TelegramError:
- pass
-
-
-@natsunagicmd(command="locktypes")
-def locktypes(update, _):
- update.effective_message.reply_text(
- "\n × ".join(
- ["Locks available: "]
- + sorted(list(LOCK_TYPES) + list(LOCK_CHAT_RESTRICTION))
- )
- )
-
-
-@natsunagicmd(command="lock", pass_args=True)
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-@typing_action
-def lock(update: Update, context: CallbackContext) -> str: # sourcery no-metrics
- args = context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if (
- can_delete(chat, context.bot.id)
- or update.effective_message.chat.type == "private"
- ):
- if len(args) >= 1:
- ltype = args[0].lower()
- if ltype in LOCK_TYPES:
- if conn := connected(
- context.bot, update, chat, user.id, need_admin=True
- ):
- chat = dispatcher.bot.getChat(conn)
- # chat_id = conn
- chat_name = chat.title
- text = f"Locked {ltype} for non-admins in {chat_name}!"
- else:
- if update.effective_message.chat.type == "private":
- 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 = f"Locked {ltype} for non-admins!"
- sql.update_lock(chat.id, ltype, locked=True)
- send_message(update.effective_message, text, parse_mode="markdown")
-
- return f"{html.escape(chat.title)}:\n#LOCK\nAdmin: {mention_html(user.id, user.first_name)}\nLocked {ltype}
."
-
- if ltype in LOCK_CHAT_RESTRICTION:
- if conn := connected(
- context.bot, update, chat, user.id, need_admin=True
- ):
- chat = dispatcher.bot.getChat(conn)
- chat_id = conn
- chat_name = chat.title
- text = f"Locked {ltype} for all non-admins in {chat_name}!"
- else:
- if update.effective_message.chat.type == "private":
- 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 = f"Locked {ltype} for all non-admins!"
-
- current_permission = context.bot.getChat(chat_id).permissions
- context.bot.set_chat_permissions(
- chat_id=chat_id,
- permissions=get_permission_list(
- ast.literal_eval(str(current_permission)),
- LOCK_CHAT_RESTRICTION[ltype.lower()],
- ),
- )
-
- send_message(update.effective_message, text, parse_mode="markdown")
- return f"{html.escape(chat.title)}:\n#Permission_LOCK\nAdmin: {mention_html(user.id, user.first_name)}\nLocked {ltype}
."
-
- send_message(
- update.effective_message,
- "What are you trying to lock...? Try /locktypes for the list of lockables",
- )
- else:
- send_message(update.effective_message, "What are you trying to lock...?")
-
- else:
- send_message(
- update.effective_message,
- "I am not administrator or haven't got enough rights.",
- )
-
- return ""
-
-
-@natsunagicmd(command="unlock", pass_args=True)
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-@typing_action
-def unlock(update: Update, context: CallbackContext) -> str: # sourcery no-metrics
- 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:
- if conn := connected(
- context.bot, update, chat, user.id, need_admin=True
- ):
- chat = context.bot.getChat(conn)
- # chat_id = conn
- chat_name = chat.title
- text = f"Unlocked {ltype} for everyone in {chat_name}!"
- else:
- if update.effective_message.chat.type == "private":
- 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 = f"Unlocked {ltype} for everyone!"
- sql.update_lock(chat.id, ltype, locked=False)
- send_message(update.effective_message, text, parse_mode="markdown")
- return f"{html.escape(chat.title)}:\n#UNLOCK\nAdmin: {mention_html(user.id, user.first_name)}\nUnlocked {ltype}
."
-
- if ltype in UNLOCK_CHAT_RESTRICTION:
- if conn := connected(
- context.bot, update, chat, user.id, need_admin=True
- ):
- chat = dispatcher.bot.getChat(conn)
- chat_id = conn
- chat_name = chat.title
- text = f"Unlocked {ltype} for everyone in {chat_name}!"
- else:
- if update.effective_message.chat.type == "private":
- 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 = f"Unlocked {ltype} for everyone!"
-
- current_permission = context.bot.getChat(chat_id).permissions
- context.bot.set_chat_permissions(
- chat_id=chat_id,
- permissions=get_permission_list(
- ast.literal_eval(str(current_permission)),
- UNLOCK_CHAT_RESTRICTION[ltype.lower()],
- ),
- )
-
- send_message(update.effective_message, text, parse_mode="markdown")
-
- return f"{html.escape(chat.title)}:\n#UNLOCK\nAdmin: {mention_html(user.id, user.first_name)}\nUnlocked {ltype}
."
- send_message(
- update.effective_message,
- "What are you trying to unlock...? Try /locktypes for the list of lockables.",
- )
-
- else:
- send_message(update.effective_message, "What are you trying to unlock...?")
-
- return ""
-
-
-@natsunagimsg((Filters.all & Filters.chat_type.groups), group=PERM_GROUP)
-@user_not_admin
-def del_lockables(update, context): # sourcery no-metrics
- 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) and can_delete(chat, context.bot.id):
- if message.caption:
- check = ad.detect_alphabet(f"{message.caption}")
- if "ARABIC" in check:
- try:
- message.delete()
- except BadRequest as excp:
- if excp.message != "Message to delete not found":
- log.exception("ERROR in lockables")
- break
- if message.text:
- check = ad.detect_alphabet(f"{message.text}")
- if "ARABIC" in check:
- try:
- message.delete()
- except BadRequest as excp:
- if excp.message != "Message to delete not found":
- log.exception("ERROR in lockables")
- break
- continue
- if lockable == "button":
- if (
- sql.is_locked(chat.id, lockable)
- and can_delete(chat, context.bot.id)
- and message.reply_markup
- and message.reply_markup.inline_keyboard
- ):
- try:
- message.delete()
- except BadRequest as excp:
- if excp.message != "Message to delete not found":
- log.exception("ERROR in lockables")
- break
- continue
- if lockable == "inline":
- if (
- sql.is_locked(chat.id, lockable)
- and can_delete(chat, context.bot.id)
- and message
- and message.via_bot
- ):
- try:
- message.delete()
- except BadRequest as excp:
- if excp.message != "Message to delete not found":
- log.exception("ERROR in lockables")
- break
- continue
- if (
- filter(update)
- and sql.is_locked(chat.id, lockable)
- and can_delete(chat, context.bot.id)
- ):
- if lockable == "bots":
- new_members = update.effective_message.new_chat_members
- for new_mem in new_members:
- if new_mem.is_bot:
- if not is_bot_admin(chat, context.bot.id):
- 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
-
- chat.ban_member(new_mem.id)
- send_message(
- update.effective_message,
- "Only admins are allowed to add bots in this chat! Get outta here.",
- )
- break
- else:
- try:
- message.delete()
- except BadRequest as excp:
- if excp.message != "Message to delete not found":
- log.exception("ERROR in lockables")
-
- break
-
-
-def build_lock_message(chat_id):
- locks = sql.get_locks(chat_id)
- res = ""
- locklist = []
- if locks:
- res += "*" + "These are the current locks in this Chat:" + "*"
- locklist.extend(
- (
- f"sticker = `{locks.sticker}`",
- f"audio = `{locks.audio}`",
- f"voice = `{locks.voice}`",
- f"document = `{locks.document}`",
- f"video = `{locks.video}`",
- f"contact = `{locks.contact}`",
- f"photo = `{locks.photo}`",
- f"gif = `{locks.gif}`",
- f"url = `{locks.url}`",
- f"bots = `{locks.bots}`",
- f"forward = `{locks.forward}`",
- f"game = `{locks.game}`",
- f"location = `{locks.location}`",
- f"rtl = `{locks.rtl}`",
- f"button = `{locks.button}`",
- f"egame = `{locks.egame}`",
- f"inline = `{locks.inline}`",
- f"apk = `{locks.apk}`",
- f"doc = `{locks.doc}`",
- f"exe = `{locks.exe}`",
- f"jpg = `{locks.jpg}`",
- f"mp3 = `{locks.mp3}`",
- f"pdf = `{locks.pdf}`",
- f"txt = `{locks.txt}`",
- f"xml = `{locks.xml}`",
- f"zip = `{locks.zip}`",
- f"docx = `{locks.docx}`",
- f"py = `{locks.py}`",
- f"svg = `{locks.svg}`",
- f"targz = `{locks.targz}`",
- f"wav = `{locks.wav}`",
- )
- )
- permissions = dispatcher.bot.get_chat(chat_id).permissions
- permslist = [
- f"messages = `{permissions.can_send_messages}`",
- f"media = `{permissions.can_send_media_messages}`",
- f"poll = `{permissions.can_send_polls}`",
- f"other = `{permissions.can_send_other_messages}`",
- f"previews = `{permissions.can_add_web_page_previews}`",
- f"info = `{permissions.can_change_info}`",
- f"invite = `{permissions.can_invite_users}`",
- f"pin = `{permissions.can_pin_messages}`",
- ]
- if locklist:
- # Ordering lock list
- locklist.sort()
- # Building lock list string
- for x in locklist:
- res += f"\n × {x}"
- res += "\n\n*" + "These are the current chat permissions:" + "*"
- for x in permslist:
- res += f"\n × {x}"
- return res
-
-
-@natsunagicmd(command="locks")
-@u_admin
-@typing_action
-def list_locks(update, context):
- chat = update.effective_chat # type: Optional[Chat]
- user = update.effective_user
-
- # Connection check
- conn = connected(context.bot, update, chat, user.id, need_admin=True)
- if conn:
- chat = dispatcher.bot.getChat(conn)
- chat_name = chat.title
- else:
- if update.effective_message.chat.type == "private":
- 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 = build_lock_message(chat.id)
- if conn:
- res = res.replace("Locks in", f"*{chat_name}*")
-
- 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,
- }
- permissions |= current
- permissions.update(new)
- return ChatPermissions(**permissions)
-
-
-def __import_data__(chat_id, data):
- # 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)
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- return build_lock_message(chat_id)
-
-
-__mod_name__ = "𝐋ᴏᴄᴋs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "locks_help")
-
-# """
diff --git a/Exon/modules/log_channel.py b/Exon/modules/log_channel.py
deleted file mode 100644
index cab2beb2..00000000
--- a/Exon/modules/log_channel.py
+++ /dev/null
@@ -1,330 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from datetime import datetime
-from functools import wraps
-
-from telegram.ext import CallbackContext
-
-from Exon.modules.helper_funcs.decorators import Exoncallback, Exoncmd
-from Exon.modules.helper_funcs.misc import is_module_loaded
-from ..modules.helper_funcs.anonymous import AdminPerms, user_admin
-
-FILENAME = __name__.rsplit(".", 1)[-1]
-
-if is_module_loaded(FILENAME):
- from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
- from telegram.error import BadRequest, Unauthorized
- from telegram.ext import JobQueue
- from telegram.utils.helpers import escape_markdown
-
- from Exon import EVENT_LOGS, LOGGER, dispatcher
- from Exon.modules.helper_funcs.chat_status import is_user_admin
- from Exon.modules.helper_funcs.chat_status import user_admin as u_admin
- from Exon.modules.sql import log_channel_sql as sql
-
-
- def loggable(func):
- @wraps(func)
- def log_action(
- update: Update,
- context: CallbackContext,
- job_queue: JobQueue = None,
- *args,
- **kwargs,
- ):
- if not job_queue:
- result = func(update, context, *args, **kwargs)
- else:
- result = func(update, context, job_queue, *args, **kwargs)
-
- chat = update.effective_chat
- message = update.effective_message
-
- if result:
- datetime_fmt = "%H:%M - %d-%m-%Y"
- result += f"\nEvent Stamp: {datetime.utcnow().strftime(datetime_fmt)}
"
-
- try:
- if message.chat.type == chat.SUPERGROUP:
- if message.chat.username:
- result += f'\nLink: click here'
- else:
- cid = str(chat.id).replace("-100", "")
- result += f'\nLink: click here'
- except AttributeError:
- result += "\nLink: No link for manual actions." # or just without the whole line
- log_chat = sql.get_chat_log_channel(chat.id)
- if log_chat:
- send_log(context, log_chat, chat.id, result)
-
- return result
-
- return log_action
-
-
- def gloggable(func):
- @wraps(func)
- def glog_action(update: Update, context: CallbackContext, *args, **kwargs):
- result = func(update, context, *args, **kwargs)
- chat = update.effective_chat
- message = update.effective_message
-
- if result:
- datetime_fmt = "%H:%M - %d-%m-%Y"
- result += "\nEvent Stamp: {}
".format(
- datetime.utcnow().strftime(datetime_fmt),
- )
-
- if message.chat.type == chat.SUPERGROUP and message.chat.username:
- result += f'\nLink: click here'
- log_chat = str(EVENT_LOGS)
- if log_chat:
- send_log(context, log_chat, chat.id, result)
-
- return result
-
- return glog_action
-
-
- def send_log(
- context: CallbackContext, log_chat_id: str, orig_chat_id: str, result: str
- ):
- bot = context.bot
- try:
- bot.send_message(
- log_chat_id,
- result,
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
- except BadRequest as excp:
- if excp.message == "Chat not found":
- bot.send_message(
- orig_chat_id,
- "This log channel has been deleted - unsetting.",
- )
- sql.stop_chat_logging(orig_chat_id)
- else:
- LOGGER.warning(excp.message)
- LOGGER.warning(result)
- LOGGER.exception("Could not parse")
-
- bot.send_message(
- log_chat_id,
- result
- + "\n\nFormatting has been disabled due to an unexpected error.",
- )
-
-
- @Exoncmd(command="logchannel")
- @u_admin
- def logging(update: Update, context: CallbackContext):
- bot = context.bot
- message = update.effective_message
- chat = update.effective_chat
-
- if log_channel := sql.get_chat_log_channel(chat.id):
- log_channel_info = bot.get_chat(log_channel)
- message.reply_text(
- f"This group has all it's logs sent to:"
- f" {escape_markdown(log_channel_info.title)} (`{log_channel}`)",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- else:
- message.reply_text("No log channel has been set for this group!")
-
-
- @Exoncmd(command="setlog")
- @user_admin(AdminPerms.CAN_CHANGE_INFO)
- def setlog(update: Update, context: CallbackContext):
- bot = context.bot
- message = update.effective_message
- chat = update.effective_chat
- if chat.type == chat.CHANNEL:
- message.reply_text(
- "Now, forward the /setlog to the group you want to tie this channel to!",
- )
-
- elif message.forward_from_chat:
- sql.set_chat_log_channel(chat.id, message.forward_from_chat.id)
- try:
- message.delete()
- except BadRequest as excp:
- if excp.message != "Message to delete not found":
- LOGGER.exception(
- "Error deleting message in log channel. Should work anyway though.",
- )
-
- try:
- bot.send_message(
- message.forward_from_chat.id,
- f"This channel has been set as the log channel for {chat.title or chat.first_name}.",
- )
- except Unauthorized as excp:
- if excp.message == "Forbidden: bot is not a member of the channel chat":
- bot.send_message(chat.id, "Successfully set log channel!")
- else:
- LOGGER.exception("ERROR in setting the log channel.")
-
- bot.send_message(chat.id, "Successfully set log channel!")
-
- else:
- message.reply_text(
- "The steps to set a log channel are:\n"
- " - add bot to the desired channel\n"
- " - send /setlog to the channel\n"
- " - forward the /setlog to the group\n",
- )
-
-
- @Exoncmd(command="unsetlog")
- @user_admin(AdminPerms.CAN_CHANGE_INFO)
- def unsetlog(update: Update, context: CallbackContext):
- bot = context.bot
- message = update.effective_message
- chat = update.effective_chat
-
- if log_channel := sql.stop_chat_logging(chat.id):
- bot.send_message(
- log_channel,
- f"Channel has been unlinked from {chat.title}",
- )
- message.reply_text("Log channel has been un-set.")
-
- else:
- message.reply_text("No log channel has been set yet!")
-
-
- def __stats__():
- return f"× {sql.num_logchannels()} log channels set."
-
-
- def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
- def __chat_settings__(chat_id, user_id):
- if log_channel := sql.get_chat_log_channel(chat_id):
- log_channel_info = dispatcher.bot.get_chat(log_channel)
- return f"This group has all it's logs sent to: {escape_markdown(log_channel_info.title)} (`{log_channel}`)"
- return "No log channel is set for this group!"
-
-
- __mod_name__ = "𝐋ᴏɢɢᴇʀ"
-
-else:
- # run anyway if module not loaded
- def loggable(func):
- return func
-
-
- def gloggable(func):
- return func
-
-
-@Exoncmd("logsettings")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-def log_settings(update: Update, _: CallbackContext):
- chat = update.effective_chat
- chat_set = sql.get_chat_setting(chat_id=chat.id)
- if not chat_set:
- sql.set_chat_setting(
- setting=sql.LogChannelSettings(chat.id, True, True, True, True, True)
- )
- btn = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(text="Warn", callback_data="log_tog_warn"),
- InlineKeyboardButton(text="Action", callback_data="log_tog_act"),
- ],
- [
- InlineKeyboardButton(text="Join", callback_data="log_tog_join"),
- InlineKeyboardButton(text="Leave", callback_data="log_tog_leave"),
- ],
- [InlineKeyboardButton(text="Report", callback_data="log_tog_rep")],
- ]
- )
- msg = update.effective_message
- msg.reply_text("Toggle channel log settings", reply_markup=btn)
-
-
-from Exon.modules.sql import log_channel_sql as sql
-
-
-@Exoncallback(pattern=r"log_tog_.*")
-def log_setting_callback(update: Update, context: CallbackContext):
- cb = update.callback_query
- user = cb.from_user
- chat = cb.message.chat
- if not is_user_admin(update, user.id):
- cb.answer("You aren't admin", show_alert=True)
- return
- setting = cb.data.replace("log_tog_", "")
- chat_set = sql.get_chat_setting(chat_id=chat.id)
- if not chat_set:
- sql.set_chat_setting(
- setting=sql.LogChannelSettings(chat.id, True, True, True, True, True)
- )
-
- t = sql.get_chat_setting(chat.id)
- if setting == "warn":
- r = t.toggle_warn()
- cb.answer(f"Warning log set to {r}")
- return
- if setting == "act":
- r = t.toggle_action()
- cb.answer(f"Action log set to {r}")
- return
- if setting == "join":
- r = t.toggle_joins()
- cb.answer(f"Join log set to {r}")
- return
- if setting == "leave":
- r = t.toggle_leave()
- cb.answer(f"Leave log set to {r}")
- return
- if setting == "rep":
- r = t.toggle_report()
- cb.answer(f"Report log set to {r}")
- return
-
- cb.answer("Now, What i need to do")
-
-
-__mod_name__ = "𝐋ᴏɢs "
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "log_help")
diff --git a/Exon/modules/misc.py b/Exon/modules/misc.py
deleted file mode 100644
index 1b7da5c8..00000000
--- a/Exon/modules/misc.py
+++ /dev/null
@@ -1,353 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import datetime
-import os
-import platform
-import random
-import re
-from platform import python_version
-
-import requests as r
-import wikipedia
-from psutil import boot_time, cpu_percent, disk_usage, virtual_memory
-from requests import get
-from spamwatch import __version__ as __sw__
-from telegram import (
- ChatAction,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- Update,
- __version__,
-)
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, CommandHandler, Filters
-from telegraph import Telegraph
-
-from Exon import OWNER_ID, dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.alternate import send_action, typing_action
-from Exon.modules.helper_funcs.chat_status import user_admin
-from Exon.modules.helper_funcs.decorators import Exoncmd
-from Exon.modules.helper_funcs.filters import CustomFilters
-
-MARKDOWN_HELP = f"""
-Markdown is a very powerful formatting tool supported by telegram. {dispatcher.bot.first_name} has some enhancements, to make sure that \
-saved messages are correctly parsed, and to allow you to create buttons.
- × _italic_
: wrapping text with '_' will produce italic text
- × *bold*
: wrapping text with '*' will produce bold text
- × `code`
: wrapping text with '`' will produce monospaced text, also known as 'code'
- × [sometext](someURL)
: this will create a link - the message will just show sometext
, \
-and tapping on it will open the page at someURL
.
-Example:[test](example.com)
-× [buttontext](buttonurl:someURL)
: this is a special enhancement to allow users to have telegram \
-buttons in their markdown. buttontext
will be what is displayed on the button, and someurl
\
-will be the url which is opened.
-Example: [This is a button](buttonurl:example.com)
-If you want multiple buttons on the same line, use :same, as such:
-[one](buttonurl://example.com)
-[two](buttonurl://google.com:same)
-This will create two buttons on a single line, instead of one button per line.
-Keep in mind that your message MUST contain some text other than just a button!
-"""
-
-wibu = "Exon"
-telegraph = Telegraph()
-data = telegraph.create_account(short_name=wibu)
-auth_url = data["auth_url"]
-TMP_DOWNLOAD_DIRECTORY = "./"
-
-
-@user_admin
-def echo(update, _):
- args = update.effective_message.text.split(None, 1)
- message = update.effective_message
-
- if message.reply_to_message:
- message.reply_to_message.reply_text(
- args[1], parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True
- )
- else:
- message.reply_text(
- args[1],
- quote=False,
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- )
- message.delete()
-
-
-def markdown_help_sender(update: Update):
- update.effective_message.reply_text(MARKDOWN_HELP, parse_mode=ParseMode.HTML)
- update.effective_message.reply_text(
- "Try forwarding the following message to me, and you'll see, and Use #test!",
- )
- update.effective_message.reply_text(
- "/save test This is a markdown test. _italics_, *bold*, code, "
- "[URL](example.com) [button](buttonurl:github.com) "
- "[button2](buttonurl://google.com:same)",
- )
-
-
-@typing_action
-def src(update, _):
- update.effective_message.reply_text(
- "Hey there! You can find what makes me click [here](https://github.com/Abishnoi69/ExonRobot).",
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- )
-
-
-@send_action(ChatAction.UPLOAD_PHOTO)
-def rmemes(update, context):
- msg = update.effective_message
- chat = update.effective_chat
-
- SUBREDS = [
- "meirl",
- "dankmemes",
- "AdviceAnimals",
- "memes",
- "meme",
- "memes_of_the_dank",
- "PornhubComments",
- "teenagers",
- "memesIRL",
- "insanepeoplefacebook",
- "terriblefacebookmemes",
- ]
-
- subreddit = random.choice(SUBREDS)
- res = r.get(f"https://meme-api.herokuapp.com/gimme/{subreddit}")
-
- if res.status_code != 200: # Like if api is down?
- msg.reply_text("Sorry some error occurred :(")
- return
- res = res.json()
-
- rpage = res.get("subreddit")
- title = res.get("title")
- memeu = res.get("url")
- plink = res.get("postLink")
-
- caps = f"× Title: {title}\n"
- caps += f"× Subreddit: r/{rpage}
"
-
- keyb = [[InlineKeyboardButton(text="Subreddit Postlink 🔗", url=plink)]]
- try:
- context.bot.send_photo(
- chat.id,
- photo=memeu,
- caption=caps,
- reply_markup=InlineKeyboardMarkup(keyb),
- timeout=60,
- parse_mode=ParseMode.HTML,
- )
-
- except BadRequest as excp:
- return msg.reply_text(f"Error! {excp.message}")
-
-
-def markdown_help(update: Update, context: CallbackContext):
- if update.effective_chat.type != "private":
- update.effective_message.reply_text(
- "Contact me in pm",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- "Markdown help",
- url=f"t.me/{context.bot.username}?start=markdownhelp",
- ),
- ],
- ],
- ),
- )
- return
- markdown_help_sender(update)
-
-
-@typing_action
-def get_bot_ip(update, context):
- """Sends the bot's IP address, so as to be able to ssh in if necessary.
- OWNER ONLY.
- """
- res = requests.get("http://ipinfo.io/ip")
- update.message.reply_text(res.text)
-
-
-@typing_action
-def system_status(update, context):
- uptime = datetime.datetime.fromtimestamp(boot_time()).strftime("%Y-%m-%d %H:%M:%S")
- status = "======[ SYSTEM INFO ]======\n\n"
- status += f"System uptime: {str(uptime)}" + "
\n"
-
- uname = platform.uname()
- status += f"System: {str(uname.system)}" + "
\n"
- status += f"Node name: {str(uname.node)}" + "
\n"
- status += f"Release: {str(uname.release)}" + "
\n"
- status += f"Version: {str(uname.version)}" + "
\n"
- status += f"Machine: {str(uname.machine)}" + "
\n"
- status += f"Processor: {str(uname.processor)}" + "
\n\n"
-
- mem = virtual_memory()
- cpu = cpu_percent()
- disk = disk_usage("/")
- status += f"CPU usage: {str(cpu)}" + " %
\n"
- status += f"Ram usage: {str(mem[2])}" + " %
\n"
- status += f"Storage used: {str(disk[3])}" + " %
\n\n"
- status += f"Python version: {python_version()}" + "
\n"
- status += f"Library version: {str(__version__)}" + "
\n"
- status += f"Spamwatch API: {str(__sw__)}" + "
\n"
- context.bot.sendMessage(update.effective_chat.id, status, parse_mode=ParseMode.HTML)
-
-
-@Exoncmd(command="wiki")
-@typing_action
-def wiki(update, context):
- Shinano = re.split(pattern="wiki", string=update.effective_message.text)
- wikipedia.set_lang("en")
- if not str(Shinano[1]):
- update.effective_message.reply_text(
- "Enter the keywords for searching to wikipedia!"
- )
- else:
- try:
- Exon = update.effective_message.reply_text(
- "Searching the keywords from wikipedia..."
- )
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="More Information",
- url=wikipedia.page(Shinano).url,
- )
- ]
- ]
- )
- context.bot.editMessageText(
- chat_id=update.effective_chat.id,
- message_id=Exon.message_id,
- text=wikipedia.summary(Shinano, sentences=10),
- reply_markup=keyboard,
- )
- except wikipedia.PageError as e:
- update.effective_message.reply_text(f"⚠ Error Detected: {e}")
- except BadRequest as et:
- update.effective_message.reply_text(f"⚠ Error Detected: {et}")
- except wikipedia.exceptions.DisambiguationError as eet:
- update.effective_message.reply_text(
- f"⚠ Error Detected\n\nThere are too many query! Express it more!\n\nPossible query result:\n\n{eet}"
- )
-
-
-@Exoncmd(command="ud")
-@typing_action
-def ud(update, context):
- msg = update.effective_message
- args = context.args
- text = " ".join(args).lower()
- if not text:
- msg.reply_text("Please enter keywords to search on ud!")
- return
- if text == "Arya":
- msg.reply_text(
- "Arya is my owner so if you search him on urban dictionary you can't find the meaning because he is my husband and only me who know what's the meaning of Arya!"
- )
- return
- try:
- results = get(f"http://api.urbandictionary.com/v0/define?term={text}").json()
- reply_text = f'Word: {text}\n\nDefinition: \n{results["list"][0]["definition"]}'
- reply_text += f'\n\nExample: \n{results["list"][0]["example"]}'
- except IndexError:
- reply_text = (
- f"Word: {text}\n\nResults: Sorry could not find any matching results!"
- )
- ignore_chars = "[]"
- reply = reply_text
- for chars in ignore_chars:
- reply = reply.replace(chars, "")
- if len(reply) >= 4096:
- reply = reply[:4096] # max msg lenth of tg.
- try:
- msg.reply_text(reply)
- except BadRequest as err:
- msg.reply_text(f"Error! {err.message}")
-
-
-file_help = os.path.basename(__file__)
-file_help = file_help.replace(".py", "")
-file_helpo = file_help.replace("_", " ")
-
-ECHO_HANDLER = DisableAbleCommandHandler(
- "echo", echo, filters=Filters.chat_type.groups, run_async=True
-)
-MD_HELP_HANDLER = CommandHandler("markdownhelp", markdown_help, run_async=True)
-SRC_HANDLER = CommandHandler(
- "source", src, filters=Filters.chat_type.private, run_async=True
-)
-REDDIT_MEMES_HANDLER = DisableAbleCommandHandler("rmeme", rmemes, run_async=True)
-IP_HANDLER = CommandHandler(
- "ip", get_bot_ip, filters=Filters.chat(OWNER_ID), run_async=True
-)
-SYS_STATUS_HANDLER = CommandHandler(
- "sysinfo", system_status, filters=CustomFilters.dev_filter, run_async=True
-)
-
-dispatcher.add_handler(ECHO_HANDLER)
-dispatcher.add_handler(MD_HELP_HANDLER)
-dispatcher.add_handler(SRC_HANDLER)
-dispatcher.add_handler(REDDIT_MEMES_HANDLER)
-dispatcher.add_handler(SYS_STATUS_HANDLER)
-dispatcher.add_handler(IP_HANDLER)
-
-__mod_name__ = "𝐄xᴛʀᴀs"
-__command_list__ = ["id", "echo", "source", "rmeme", "ip", "sysinfo"]
-__handlers__ = [
- ECHO_HANDLER,
- MD_HELP_HANDLER,
- SRC_HANDLER,
- REDDIT_MEMES_HANDLER,
- IP_HANDLER,
- SYS_STATUS_HANDLER,
-]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "misc_help")
-
-# """
diff --git a/Exon/modules/modules.py b/Exon/modules/modules.py
deleted file mode 100644
index 318fb4e2..00000000
--- a/Exon/modules/modules.py
+++ /dev/null
@@ -1,223 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import collections
-import importlib
-
-from telegram import ParseMode, Update
-from telegram.ext import CallbackContext
-
-from Exon import dispatcher, telethn
-from Exon.__main__ import (
- CHAT_SETTINGS,
- DATA_EXPORT,
- DATA_IMPORT,
- HELPABLE,
- IMPORTED,
- MIGRATEABLE,
- STATS,
- USER_INFO,
- USER_SETTINGS,
-)
-from Exon.modules.helper_funcs.chat_status import dev_plus, sudo_plus
-from Exon.modules.helper_funcs.decorators import Exoncmd
-
-
-@Exoncmd(command="load")
-@dev_plus
-def load(update: Update, context: CallbackContext):
- message = update.effective_message
- text = message.text.split(" ", 1)[1]
- load_messasge = message.reply_text(
- f"Attempting to load module : {text}",
- parse_mode=ParseMode.HTML,
- )
-
- try:
- imported_module = importlib.import_module(f"Exon.modules.{text}")
- except Exception:
- load_messasge.edit_text("Does that module even exist?")
- return
-
- if not hasattr(imported_module, "__mod_name__"):
- imported_module.__mod_name__ = imported_module.__name__
-
- if imported_module.__mod_name__.lower() not in IMPORTED:
- IMPORTED[imported_module.__mod_name__.lower()] = imported_module
- else:
- load_messasge.edit_text("Module already loaded.")
- return
- if "__handlers__" in dir(imported_module):
- handlers = imported_module.__handlers__
- for handler in handlers:
- if not isinstance(handler, tuple):
- dispatcher.add_handler(handler)
- elif isinstance(handler[0], collections.Callable):
- callback, telethon_event = handler
- telethn.add_event_handler(callback, telethon_event)
- else:
- handler_name, priority = handler
- dispatcher.add_handler(handler_name, priority)
- else:
- IMPORTED.pop(imported_module.__mod_name__.lower())
- load_messasge.edit_text("The module cannot be loaded.")
- return
-
- if hasattr(imported_module, "__help__") and imported_module.__help__:
- HELPABLE[imported_module.__mod_name__.lower()] = imported_module
-
- # Chats to migrate on chat_migrated events
- if hasattr(imported_module, "__migrate__"):
- MIGRATEABLE.append(imported_module)
-
- if hasattr(imported_module, "__stats__"):
- STATS.append(imported_module)
-
- if hasattr(imported_module, "__user_info__"):
- USER_INFO.append(imported_module)
-
- if hasattr(imported_module, "__import_data__"):
- DATA_IMPORT.append(imported_module)
-
- if hasattr(imported_module, "__export_data__"):
- DATA_EXPORT.append(imported_module)
-
- if hasattr(imported_module, "__chat_settings__"):
- CHAT_SETTINGS[imported_module.__mod_name__.lower()] = imported_module
-
- if hasattr(imported_module, "__user_settings__"):
- USER_SETTINGS[imported_module.__mod_name__.lower()] = imported_module
-
- load_messasge.edit_text(
- f"Successfully loaded module : {text}",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncmd(command="unload")
-@dev_plus
-def unload(update: Update, context: CallbackContext):
- message = update.effective_message
- text = message.text.split(" ", 1)[1]
- unload_messasge = message.reply_text(
- f"Attempting to unload module : {text}",
- parse_mode=ParseMode.HTML,
- )
-
- try:
- imported_module = importlib.import_module(f"Exon.modules.{text}")
- except Exception:
- unload_messasge.edit_text("Does that module even exist?")
- return
-
- if not hasattr(imported_module, "__mod_name__"):
- imported_module.__mod_name__ = imported_module.__name__
- if imported_module.__mod_name__.lower() in IMPORTED:
- IMPORTED.pop(imported_module.__mod_name__.lower())
- else:
- unload_messasge.edit_text("Can't unload something that isn't loaded.")
- return
- if "__handlers__" in dir(imported_module):
- handlers = imported_module.__handlers__
- for handler in handlers:
- if isinstance(handler, bool):
- unload_messasge.edit_text("This module can't be unloaded!")
- return
- if not isinstance(handler, tuple):
- dispatcher.remove_handler(handler)
- elif isinstance(handler[0], collections.Callable):
- callback, telethon_event = handler
- telethn.remove_event_handler(callback, telethon_event)
- else:
- handler_name, priority = handler
- dispatcher.remove_handler(handler_name, priority)
- else:
- unload_messasge.edit_text("The module cannot be unloaded.")
- return
-
- if hasattr(imported_module, "__help__") and imported_module.__help__:
- HELPABLE.pop(imported_module.__mod_name__.lower())
-
- # Chats to migrate on chat_migrated events
- if hasattr(imported_module, "__migrate__"):
- MIGRATEABLE.remove(imported_module)
-
- if hasattr(imported_module, "__stats__"):
- STATS.remove(imported_module)
-
- if hasattr(imported_module, "__user_info__"):
- USER_INFO.remove(imported_module)
-
- if hasattr(imported_module, "__import_data__"):
- DATA_IMPORT.remove(imported_module)
-
- if hasattr(imported_module, "__export_data__"):
- DATA_EXPORT.remove(imported_module)
-
- if hasattr(imported_module, "__chat_settings__"):
- CHAT_SETTINGS.pop(imported_module.__mod_name__.lower())
-
- if hasattr(imported_module, "__user_settings__"):
- USER_SETTINGS.pop(imported_module.__mod_name__.lower())
-
- unload_messasge.edit_text(
- f"Successfully unloaded module : {text}",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncmd(command="listmodules")
-@sudo_plus
-def listmodules(update: Update, context: CallbackContext):
- message = update.effective_message
- module_list = []
-
- for helpable_module in HELPABLE:
- helpable_module_info = IMPORTED[helpable_module]
- file_info = IMPORTED[helpable_module_info.__mod_name__.lower()]
- file_name = file_info.__name__.rsplit("Exon.modules.", 1)[1]
- mod_name = file_info.__mod_name__
- module_list.append(f"- {mod_name} ({file_name})
\n")
- module_list = "Following modules are loaded : \n\n" + "".join(module_list)
- message.reply_text(module_list, parse_mode=ParseMode.HTML)
-
-
-__mod_name__ = "𝐌ᴏᴅᴜʟᴇs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "modules_help")
-
-# """
diff --git a/Exon/modules/muting.py b/Exon/modules/muting.py
deleted file mode 100644
index 6e468953..00000000
--- a/Exon/modules/muting.py
+++ /dev/null
@@ -1,379 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import html
-import re
-from typing import Optional
-
-from telegram import (
- Bot,
- CallbackQuery,
- Chat,
- ChatPermissions,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- Update,
- User,
-)
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler
-from telegram.utils.helpers import mention_html
-
-from Exon import LOGGER, TIGERS, dispatcher
-from Exon.modules.helper_funcs.chat_status import (
- bot_admin,
- can_restrict,
- connection_status,
- is_user_admin,
- user_admin,
- user_admin_no_reply,
-)
-from Exon.modules.helper_funcs.extraction import extract_user_and_text
-from Exon.modules.helper_funcs.string_handling import extract_time
-from Exon.modules.log_channel import loggable
-
-
-def check_user(user_id: int, bot: Bot, update: Update) -> Optional[str]:
- if not user_id:
- return "You don't seem to be referring to a user or the ID specified is incorrect.."
-
- try:
- member = update.effective_chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- return "I can't seem to find this user"
- raise
- if user_id == bot.id:
- return "I'm not gonna MUTE myself, How high are you?"
-
- if is_user_admin(update, user_id, member) or user_id in TIGERS:
- return "Can't. Find someone else to mute but not this one."
-
- return None
-
-
-@connection_status
-@bot_admin
-@user_admin
-@loggable
-def mute(update: Update, context: CallbackContext) -> str:
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
-
- user_id, reason = extract_user_and_text(message, args)
- if reply := check_user(user_id, bot, update):
- message.reply_text(reply)
- return ""
-
- member = chat.get_member(user_id)
-
- log = (
- f"{html.escape(chat.title)}:\n"
- f"#MUTE\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"User: {mention_html(member.user.id, member.user.first_name)}"
- )
-
- if reason:
- log += f"\nReason: {reason}"
-
- if member.can_send_messages is None or member.can_send_messages:
- chat_permissions = ChatPermissions(can_send_messages=False)
- bot.restrict_chat_member(chat.id, user_id, chat_permissions)
- msg = (
- f"Yep! Muted {mention_html(member.user.id, member.user.first_name)} for talking in {chat.title}\n"
- f"by {mention_html(user.id, html.escape(user.first_name))}"
- )
- if reason:
- msg += f"\nReason: {html.escape(reason)}"
-
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⚠️ Unmute",
- callback_data=f"unmute_({member.user.id})",
- ),
- InlineKeyboardButton(
- text="❌ Delete", callback_data="close2"
- ),
- ]
- ]
- )
- bot.sendMessage(
- chat.id,
- msg,
- reply_markup=keyboard,
- parse_mode=ParseMode.HTML,
- )
- return log
- message.reply_text("This user is already muted!")
-
- return ""
-
-
-close_keyboard = InlineKeyboardMarkup(
- [[InlineKeyboardButton("❌ Delete", callback_data="close2")]]
-)
-
-
-@connection_status
-@bot_admin
-@user_admin
-@loggable
-def unmute(update: Update, context: CallbackContext) -> str:
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
-
- user_id, reason = extract_user_and_text(message, args)
- if not user_id:
- message.reply_text(
- "You'll need to either give me a username to unmute, or reply to someone to be unmuted."
- )
- return ""
-
- member = chat.get_member(int(user_id))
-
- if member.status in ("kicked", "left"):
- message.reply_text(
- "This user isn't even in the chat, unmuting them won't make them talk more than they "
- "already do!",
- )
-
- elif (
- member.can_send_messages
- and member.can_send_media_messages
- and member.can_send_other_messages
- and member.can_add_web_page_previews
- ):
- message.reply_text("This user already has the right to speak.")
- else:
- chat_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,
- )
- try:
- bot.restrict_chat_member(chat.id, int(user_id), chat_permissions)
- except BadRequest:
- pass
- reply = (
- f"Yep! Unmuted {mention_html(member.user.id, member.user.first_name)} "
- f"by {mention_html(user.id, user.first_name)} in {message.chat.title}"
- )
- if reason:
- reply += f"Reason: {reason}"
- bot.sendMessage(
- chat.id,
- reply,
- parse_mode=ParseMode.HTML,
- )
- return (
- f"{html.escape(chat.title)}:\n"
- f"#UNMUTE\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"User: {mention_html(member.user.id, member.user.first_name)}"
- )
- return ""
-
-
-@connection_status
-@bot_admin
-@can_restrict
-@user_admin
-@loggable
-def temp_mute(update: Update, context: CallbackContext) -> str:
- bot, args = context.bot, context.args
- chat = update.effective_chat
- user = update.effective_user
- message = update.effective_message
-
- user_id, reason = extract_user_and_text(message, args)
- if reply := check_user(user_id, bot, update):
- message.reply_text(reply)
- return ""
-
- member = chat.get_member(user_id)
-
- if not reason:
- message.reply_text("You haven't specified a time to mute this user for!")
- return ""
-
- split_reason = reason.split(None, 1)
-
- time_val = split_reason[0].lower()
- reason = split_reason[1] if len(split_reason) > 1 else ""
- mutetime = extract_time(message, time_val)
-
- if not mutetime:
- return ""
-
- log = (
- f"{html.escape(chat.title)}:\n"
- f"#TEMP MUTED\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"User: {mention_html(member.user.id, member.user.first_name)}\n"
- f"Time: {time_val}"
- )
- if reason:
- log += f"\nReason: {reason}"
-
- try:
- if member.can_send_messages is None or member.can_send_messages:
- chat_permissions = ChatPermissions(can_send_messages=False)
- bot.restrict_chat_member(
- chat.id,
- user_id,
- chat_permissions,
- until_date=mutetime,
- )
- msg = (
- f"Yep! Temporary Muted {mention_html(member.user.id, member.user.first_name)} from talking for {time_val}
in {chat.title}\n"
- f"by {mention_html(user.id, html.escape(user.first_name))}",
- )
-
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⚠️ Unmute",
- callback_data=f"unmute_({member.user.id})",
- ),
- InlineKeyboardButton(
- text="❌ Delete", callback_data="close2"
- ),
- ]
- ]
- )
- bot.sendMessage(
- chat.id, msg, reply_markup=keyboard, parse_mode=ParseMode.HTML
- )
-
- return log
- message.reply_text("This user is already muted.")
-
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text(f"Muted for {time_val}!", quote=False)
- return log
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR muting user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't mute that user.")
-
- return ""
-
-
-close_keyboard = InlineKeyboardMarkup(
- [[InlineKeyboardButton("❌ Delete", callback_data="close2")]]
-)
-
-
-@user_admin_no_reply
-@bot_admin
-@loggable
-def button(update: Update, context: CallbackContext) -> str:
- query: Optional[CallbackQuery] = update.callback_query
- user: Optional[User] = update.effective_user
- bot: Optional[Bot] = context.bot
- if match := re.match(r"unmute_\((.+?)\)", query.data):
- user_id = match[1]
- chat: Optional[Chat] = update.effective_chat
- member = chat.get_member(user_id)
- chat_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,
- )
- if unmuted := bot.restrict_chat_member(
- chat.id, int(user_id), chat_permissions
- ):
- update.effective_message.edit_text(
- f"Yep! User {mention_html(member.user.id, member.user.first_name)} can start talking again in {chat.title}!",
- parse_mode=ParseMode.HTML,
- )
- query.answer("Unmuted!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#UNMUTE\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"User: {mention_html(member.user.id, member.user.first_name)}"
- )
- else:
- update.effective_message.edit_text(
- "This user is not muted or has left the group!"
- )
- return ""
-
-
-MUTE_HANDLER = CommandHandler("mute", mute, run_async=True)
-UNMUTE_HANDLER = CommandHandler("unmute", unmute, run_async=True)
-TEMPMUTE_HANDLER = CommandHandler(["tmute", "tempmute"], temp_mute, run_async=True)
-UNMUTE_BUTTON_HANDLER = CallbackQueryHandler(button, pattern=r"unmute_", run_async=True)
-
-dispatcher.add_handler(MUTE_HANDLER)
-dispatcher.add_handler(UNMUTE_HANDLER)
-dispatcher.add_handler(TEMPMUTE_HANDLER)
-dispatcher.add_handler(UNMUTE_BUTTON_HANDLER)
-
-__mod_name__ = "𝐌ᴜᴛɪɴɢ"
-__handlers__ = [MUTE_HANDLER, UNMUTE_HANDLER, TEMPMUTE_HANDLER]
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "muting_help")
-
-# """
diff --git a/Exon/modules/nightmode.py b/Exon/modules/nightmode.py
deleted file mode 100644
index b37579d9..00000000
--- a/Exon/modules/nightmode.py
+++ /dev/null
@@ -1,199 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-from apscheduler.schedulers.asyncio import AsyncIOScheduler
-from telegram import ParseMode
-from telethon import *
-from telethon.tl.types import ChatBannedRights
-
-from Exon import LOGGER, OWNER_ID, telethn
-from Exon.events import register
-from Exon.modules.sql.night_mode_sql import (
- add_nightmode,
- get_all_chat_id,
- is_nightmode_indb,
- rmnightmode,
-)
-
-hehes = ChatBannedRights(
- until_date=None,
- send_messages=True,
- send_media=True,
- send_stickers=True,
- send_gifs=True,
- send_games=True,
- send_inline=True,
- send_polls=True,
- invite_users=True,
- pin_messages=True,
- change_info=True,
-)
-
-openhehe = ChatBannedRights(
- until_date=None,
- send_messages=False,
- send_media=False,
- send_stickers=False,
- send_gifs=False,
- send_games=False,
- send_inline=False,
- send_polls=False,
- invite_users=True,
- pin_messages=True,
- change_info=True,
-)
-
-
-async def is_register_admin(chat, user):
- if isinstance(chat, (types.InputPeerChannel, types.InputChannel)):
- return isinstance(
- (
- await telethn(functions.channels.GetParticipantRequest(chat, user))
- ).participant,
- (types.ChannelParticipantAdmin, types.ChannelParticipantCreator),
- )
- if isinstance(chat, types.InputPeerUser):
- return True
-
-
-async def can_change_info(message):
- result = await telethn(
- functions.channels.GetParticipantRequest(
- channel=message.chat_id,
- user_id=message.sender_id,
- )
- )
- p = result.participant
- return isinstance(p, types.ChannelParticipantCreator) or (
- isinstance(p, types.ChannelParticipantAdmin) and p.admin_rights.change_info
- )
-
-
-@register(pattern="^/(nightmode|Nightmode|NightMode|Nmode|night|closechat) ?(.*)")
-async def profanity(event):
- if event.fwd_from:
- return
- if event.is_private:
- return
- input = event.pattern_match.group(2)
- if event.sender_id != OWNER_ID:
- if not await is_register_admin(event.input_chat, event.sender_id):
- await event.reply("ᴏɴʟʏ ᴀᴅᴍɪɴs ᴄᴀɴ ᴇxᴇᴄᴜᴛᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ!")
- return
- if not await can_change_info(message=event):
- await event.reply(
- "ʏᴏᴜ ᴀʀᴇ ᴍɪssɪɴɢ ᴛʜᴇ ғᴏʟʟᴏᴡɪɴɢ ʀɪɢʜᴛs ᴛᴏ ᴜsᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ : CanChangeinfo"
- )
- return
- if not input:
- if is_nightmode_indb(str(event.chat_id)):
- await event.reply("ᴄᴜʀʀᴇɴᴛʟʏ ɴɪɢʜᴛᴍᴏᴅᴇ ɪs ᴇɴᴀʙʟᴇᴅ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ")
- return
- await event.reply("ᴄᴜʀʀᴇɴᴛʟʏ ɴɪɢʜᴛᴍᴏᴅᴇ ɪs ᴅɪsᴀʙʟᴇᴅ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ")
- return
- if "on" in input and event.is_group:
- if is_nightmode_indb(str(event.chat_id)):
- await event.reply("ɴɪɢʜᴛ ᴍᴏᴅᴇ ɪs ᴀʟʀᴇᴀᴅʏ ᴛᴜʀɴᴇᴅ ᴏɴ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ")
- return
- add_nightmode(str(event.chat_id))
- await event.reply("ɴɪɢʜᴛᴍᴏᴅᴇ ᴛᴜʀɴᴇᴅ ᴏɴ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ.")
- if "off" in input:
- if event.is_group and not is_nightmode_indb(str(event.chat_id)):
- await event.reply("ɴɪɢʜᴛ ᴍᴏᴅᴇ ɪs ᴀʟʀᴇᴀᴅʏ ᴏғғ ғᴏʀ ᴛʜɪs ᴄʜᴀᴛ")
- return
- rmnightmode(str(event.chat_id))
- await event.reply("ɴɪɢʜᴛᴍᴏᴅᴇ ᴅɪsᴀʙʟᴇᴅ!")
- if "off" not in input and "on" not in input:
- await event.reply("ᴘʟᴇᴀsᴇ sᴘᴇᴄɪғʏ ᴏɴ ᴏʀ ᴏғғ!")
- return
-
-
-async def job_close():
- chats = get_all_chat_id()
- if len(chats) == 0:
- return
- for pro in chats:
- try:
- await telethn.send_message(
- int(pro.chat_id),
- "🌗 ɴɪɢʜᴛ ᴍᴏᴅᴇ sᴛᴀʀᴛɪɴɢ: ᴄʟᴏsɪɴɢ sᴛɪᴄᴋᴇʀs ᴀɴᴅ ᴍᴇᴅɪᴀ sᴇɴᴅ ᴘᴇʀᴍɪssɪᴏɴs ᴜɴᴛɪʟ 06:00ᴀᴍ
\n\n",
- parse_mode=ParseMode.HTML,
- )
- await telethn(
- functions.messages.EditChatDefaultBannedRightsRequest(
- peer=int(pro.chat_id), banned_rights=hehes
- )
- )
- except Exception as e:
- LOGGER.info(f"ᴜɴᴀʙʟᴇ ᴛᴏ ᴄʟᴏsᴇ ɢʀᴏᴜᴘ {chat} - {e}")
-
-
-# Run everyday at 12am
-scheduler = AsyncIOScheduler(timezone="Asia/Kolkata")
-scheduler.add_job(job_close, trigger="cron", hour=23, minute=59)
-scheduler.start()
-
-
-async def job_open():
- chats = get_all_chat_id()
- if len(chats) == 0:
- return
- for pro in chats:
- try:
- await telethn.send_message(
- int(pro.chat_id),
- "🌗 ɴɪɢʜᴛ ᴍᴏᴅᴇ ᴇɴᴅᴇᴅ: ᴄʜᴀᴛ ᴏᴘᴇɴɪɴɢ
\n\nᴇᴠᴇʀʏᴏɴᴇ sʜᴏᴜʟᴅ ʙᴇ ᴀʙʟᴇ ᴛᴏ sᴇɴᴅ ᴍᴇssᴀɢᴇs",
- parse_mode=ParseMode.HTML,
- )
- await telethn(
- functions.messages.EditChatDefaultBannedRightsRequest(
- peer=int(pro.chat_id), banned_rights=openhehe
- )
- )
- except Exception as e:
- logger.info(f"ᴜɴᴀʙʟᴇ ᴛᴏ ᴏᴘᴇɴ ɢʀᴏᴜᴘ {pro.chat_id} - {e}")
-
-
-# Run everyday at 06
-scheduler = AsyncIOScheduler(timezone="Asia/Kolkata")
-scheduler.add_job(job_open, trigger="cron", hour=5, minute=59)
-scheduler.start()
-
-__mod_name__ = "𝐍-ᴍᴏᴅᴇ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "nmode_help")
-
-# """
diff --git "a/Exon/modules/no_sql/ABISHNOI COPYRIGHT \302\251" "b/Exon/modules/no_sql/ABISHNOI COPYRIGHT \302\251"
deleted file mode 100644
index bdb308d1..00000000
--- "a/Exon/modules/no_sql/ABISHNOI COPYRIGHT \302\251"
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
\ No newline at end of file
diff --git a/Exon/modules/no_sql/__init__.py b/Exon/modules/no_sql/__init__.py
deleted file mode 100644
index 53921dfa..00000000
--- a/Exon/modules/no_sql/__init__.py
+++ /dev/null
@@ -1,109 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-
-from motor.motor_asyncio import AsyncIOMotorClient as MongoCli
-from pymongo import MongoClient, collection
-
-from Exon import DB_NAME
-from Exon import MONGO_URI as MONGO_DB_URI
-
-mongo = MongoCli(MONGO_DB_URI)
-Asudb = mongo.ExonRobot_
-
-try:
- client = MongoClient(MONGO_DB_URI)
-except PyMongoError:
- exiter(1)
-main_db = client[DB_NAME]
-
-AsuXdb = main_db
-
-
-def get_collection(name: str) -> collection:
- """ɢᴇᴛ ᴛʜᴇ ᴄᴏʟʟᴇᴄᴛɪᴏɴ ғʀᴏᴍ ᴅᴀᴛᴀʙᴀsᴇ."""
- return AsuXdb[name]
-
-
-class MongoDB:
- """Class for interacting with Bot database."""
-
- def __init__(self, collection) -> None:
- self.collection = AsuXdb[collection]
-
- # Insert one entry into collection
- def insert_one(self, document):
- result = self.collection.insert_one(document)
- return repr(result.inserted_id)
-
- # Find one entry from collection
- def find_one(self, query):
- return result if (result := self.collection.find_one(query)) else False
-
- # Find entries from collection
- def find_all(self, query=None):
- if query is None:
- query = {}
- return list(self.collection.find(query))
-
- # Count entries from collection
- def count(self, query=None):
- if query is None:
- query = {}
- return self.collection.count_documents(query)
-
- # Delete entry/entries from collection
- def delete_one(self, query):
- self.collection.delete_many(query)
- return self.collection.count_documents({})
-
- # Replace one entry in collection
- def replace(self, query, new_data):
- old = self.collection.find_one(query)
- _id = old["_id"]
- self.collection.replace_one({"_id": _id}, new_data)
- new = self.collection.find_one({"_id": _id})
- return old, new
-
- # Update one entry from collection
- def update(self, query, update):
- result = self.collection.update_one(query, {"$set": update})
- new_document = self.collection.find_one(query)
- return result.modified_count, new_document
-
- @staticmethod
- def close():
- return client.close()
-
-
-def __connect_first():
- _ = MongoDB("test")
-
-
-__connect_first()
diff --git a/Exon/modules/no_sql/afk_db.py b/Exon/modules/no_sql/afk_db.py
deleted file mode 100644
index 9b69fc93..00000000
--- a/Exon/modules/no_sql/afk_db.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-from Exon.modules.no_sql import Asudb
-
-afkdb = Asudb.afk
-
-
-async def is_afk(user_id: int) -> bool:
- user = await afkdb.find_one({"user_id": user_id})
- return (True, user["reason"]) if user else (False, {})
-
-
-async def add_afk(user_id: int, mode):
- await afkdb.update_one(
- {"user_id": user_id}, {"$set": {"reason": mode}}, upsert=True
- )
-
-
-async def remove_afk(user_id: int):
- user = await afkdb.find_one({"user_id": user_id})
- if user:
- return await afkdb.delete_one({"user_id": user_id})
-
-
-async def get_afk_users() -> list:
- users = afkdb.find({"user_id": {"$gt": 0}})
- return list(await users.to_list(length=1000000000)) if users else []
diff --git a/Exon/modules/no_sql/blacklist_db.py b/Exon/modules/no_sql/blacklist_db.py
deleted file mode 100644
index 3c49a04d..00000000
--- a/Exon/modules/no_sql/blacklist_db.py
+++ /dev/null
@@ -1,132 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-from Exon.modules.no_sql import get_collection
-
-BL = get_collection("BLACKLIST")
-BL_SETTING = get_collection("BLACKLIST_SETTINGS")
-
-CHAT_BLACKLISTS = {}
-CHAT_SETTINGS_BLACKLISTS = {}
-
-
-def add_to_blacklist(chat_id, trigger):
- BL.find_one_and_update(
- {"chat_id": chat_id, "trigger": trigger},
- {"$set": {"chat_id": chat_id, "trigger": trigger}},
- upsert=True,
- )
- if CHAT_BLACKLISTS.get(str(chat_id), set()) == set():
- CHAT_BLACKLISTS[str(chat_id)] = {trigger}
- else:
- CHAT_BLACKLISTS.get(str(chat_id), set()).add(trigger)
-
-
-def rm_from_blacklist(chat_id, trigger) -> bool:
- if data := BL.find_one_and_delete(
- {"chat_id": chat_id, "trigger": trigger}
- ):
- if trigger in CHAT_BLACKLISTS.get(str(chat_id), set()):
- CHAT_BLACKLISTS.get(str(chat_id), set()).remove(trigger)
- return True
- return False
-
-
-def get_chat_blacklist(chat_id) -> set:
- return CHAT_BLACKLISTS.get(str(chat_id), set())
-
-
-def num_blacklist_filters() -> int:
- return BL.count_documents({})
-
-
-def num_blacklist_chat_filters(chat_id) -> int:
- return BL.count_documents({"chat_id": chat_id})
-
-
-def num_blacklist_filter_chats() -> int:
- data = BL.distinct("chat_id")
- return len(data)
-
-
-def set_blacklist_strength(chat_id, blacklist_type, value):
- """For blacklist type settings
- `blacklist_type` (int):
- - 0 = nothing
- - 1 = delete
- - 2 = warn
- - 3 = mute
- - 4 = kick
- - 5 = ban
- - 6 = tban
- - 7 = tmute.
- """
- BL_SETTING.update_one(
- {"chat_id": chat_id},
- {"$set": {"blacklist_type": int(blacklist_type), "value": str(value)}},
- upsert=True,
- )
- CHAT_SETTINGS_BLACKLISTS[str(chat_id)] = {
- "blacklist_type": int(blacklist_type),
- "value": value,
- }
-
-
-def get_blacklist_setting(chat_id) -> [int, str]:
- if setting := CHAT_SETTINGS_BLACKLISTS.get(str(chat_id)):
- return setting["blacklist_type"], setting["value"]
- return 1, "0"
-
-
-def __load_chat_blacklists():
- for chat in BL.find():
- CHAT_BLACKLISTS[chat["chat_id"]] = []
-
- for x in BL.find():
- CHAT_BLACKLISTS[x["chat_id"]] += [x["trigger"]]
-
- CHAT_BLACKLISTS = {str(x): set(y) for x, y in CHAT_BLACKLISTS.items()}
-
-
-def __load_chat_settings_blacklists():
- for x in BL_SETTING.find():
- CHAT_SETTINGS_BLACKLISTS[x["chat_id"]] = {
- "blacklist_type": x["blacklist_type"],
- "value": x["value"],
- }
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- BL.update_many({"chat_id": old_chat_id}, {"$set": {"chat_id": new_chat_id}})
- __load_chat_blacklists()
- __load_chat_settings_blacklists()
-
-
-__load_chat_blacklists()
-__load_chat_settings_blacklists()
diff --git a/Exon/modules/no_sql/disable_db.py b/Exon/modules/no_sql/disable_db.py
deleted file mode 100644
index be68dd95..00000000
--- a/Exon/modules/no_sql/disable_db.py
+++ /dev/null
@@ -1,92 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-
-from Exon.modules.no_sql import get_collection
-
-DISABLED_COMMANDS = get_collection("DISABLED_COMMANDS")
-
-DISABLED = {}
-
-
-def disable_command(chat_id, disable) -> bool:
- data = DISABLED_COMMANDS.find_one({"chat_id": chat_id, "command": disable})
- if not data:
- DISABLED.setdefault(str(chat_id), set()).add(disable)
-
- DISABLED_COMMANDS.insert_one({"chat_id": chat_id, "command": disable})
- return True
- return False
-
-
-def enable_command(chat_id, enable) -> bool:
- if data := DISABLED_COMMANDS.find_one(
- {"chat_id": chat_id, "command": enable}
- ):
- if enable in DISABLED.get(str(chat_id)): # sanity check
- DISABLED.setdefault(str(chat_id), set()).remove(enable)
-
- DISABLED_COMMANDS.delete_one({"chat_id": chat_id, "command": enable})
- return True
- return False
-
-
-def is_command_disabled(chat_id, cmd) -> bool:
- return cmd in DISABLED.get(str(chat_id), set())
-
-
-def get_all_disabled(chat_id) -> dict:
- return DISABLED.get(str(chat_id), set())
-
-
-def num_chats() -> int:
- chats = DISABLED_COMMANDS.distinct("chat_id")
- return len(chats)
-
-
-def num_disabled() -> int:
- return DISABLED_COMMANDS.count_documents({})
-
-
-def migrate_chat(old_chat_id, new_chat_id) -> None:
- DISABLED_COMMANDS.update_many(
- {"chat_id": old_chat_id}, {"$set": {"chat_id": new_chat_id}}
- )
-
- if str(old_chat_id) in DISABLED:
- DISABLED[str(old_chat_id)] = DISABLED.get(str(old_chat_id), set())
-
-
-def __load_disabled_commands() -> None:
- all_chats = DISABLED_COMMANDS.find()
- for chat in all_chats:
- DISABLED.setdefault(chat["chat_id"], set()).add(chat["command"])
-
-
-__load_disabled_commands()
diff --git a/Exon/modules/no_sql/fsub_db.py b/Exon/modules/no_sql/fsub_db.py
deleted file mode 100644
index b8891196..00000000
--- a/Exon/modules/no_sql/fsub_db.py
+++ /dev/null
@@ -1,44 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-from . import AsuXdb as db
-
-fsub = db.force_sub
-
-
-def fs_settings(chat_id: int):
- return _x if (_x := fsub.find_one({"chat_id": chat_id})) else None
-
-
-def add_channel(chat_id: int, channel):
- fsub.update_one({"chat_id": chat_id}, {"$set": {"channel": channel}}, upsert=True)
-
-
-def disapprove(chat_id: int):
- fsub.delete_one({"chat_id": chat_id})
diff --git a/Exon/modules/no_sql/global_bans_db.py b/Exon/modules/no_sql/global_bans_db.py
deleted file mode 100644
index ef5742bf..00000000
--- a/Exon/modules/no_sql/global_bans_db.py
+++ /dev/null
@@ -1,125 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-"""ɢʟᴏʙᴀʟ ʙᴀɴs ᴅᴀᴛᴀʙᴀsᴇ"""
-
-from Exon.modules.no_sql import get_collection
-
-GBAN_USER = get_collection("GBANS")
-GBAN_SETTINGS = get_collection("GBAN_SETTINGS")
-GBANNED_LIST = set()
-GBANSTAT_LIST = set()
-
-
-def gban_user(user_id, name, reason=None) -> None:
- GBAN_USER.insert_one(
- {
- "_id": user_id,
- "name": name,
- "reason": reason,
- }
- )
- __load_gbanned_userid_list()
-
-
-def update_gban_reason(user_id, name, reason) -> str:
- data = GBAN_USER.find_one_and_update(
- {"_id": user_id}, {"$set": {"name": name, "reason": reason}}, upsert=False
- )
- return data["reason"]
-
-
-def ungban_user(user_id) -> None:
- GBAN_USER.delete_one({"_id": user_id})
- __load_gbanned_userid_list()
-
-
-def is_user_gbanned(user_id):
- return user_id in GBANNED_LIST
-
-
-def get_gbanned_user(user_id):
- return GBAN_USER.find_one({"_id": user_id})
-
-
-def get_gban_list() -> dict:
- return list(GBAN_USER.find())
-
-
-def enable_gbans(chat_id) -> None:
- __gban_setting(chat_id, True)
- if str(chat_id) in GBANSTAT_LIST:
- GBANSTAT_LIST.remove(str(chat_id))
-
-
-def disable_gbans(chat_id) -> None:
- __gban_setting(chat_id, False)
- GBANSTAT_LIST.add(str(chat_id))
-
-
-def __gban_setting(chat_id, setting: bool = True) -> None:
- if GBAN_SETTINGS.find_one({"_id": chat_id}):
- GBAN_SETTINGS.update_one({"_id": chat_id}, {"$set": {"setting": setting}})
- else:
- GBAN_SETTINGS.insert_one({"_id": chat_id, "setting": setting})
-
-
-def does_chat_gban(chat_id) -> bool:
- return str(chat_id) not in GBANSTAT_LIST
-
-
-def num_gbanned_users() -> int:
- return len(GBANNED_LIST)
-
-
-def __load_gbanned_userid_list() -> None:
- global GBANNED_LIST
- GBANNED_LIST = {i["_id"] for i in GBAN_USER.find()}
-
-
-def __load_gban_stat_list() -> None:
- global GBANSTAT_LIST
- GBANSTAT_LIST = {str(i["_id"]) for i in GBAN_SETTINGS.find() if not i["setting"]}
-
-
-def migrate_chat(old_chat_id, new_chat_id) -> None:
- if old := GBAN_SETTINGS.find_one_and_delete({"_id": old_chat_id}):
- setting = old["setting"]
- else:
- setting = True
- GBAN_SETTINGS.update_one(
- {"_id": new_chat_id},
- {"$set": {"setting": setting}},
- upsert=True,
- )
-
-
-# Create in memory userid to avoid disk access
-__load_gbanned_userid_list()
-__load_gban_stat_list()
diff --git a/Exon/modules/no_sql/karma_db.py b/Exon/modules/no_sql/karma_db.py
deleted file mode 100644
index 1cdd03f0..00000000
--- a/Exon/modules/no_sql/karma_db.py
+++ /dev/null
@@ -1,135 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-
-from typing import Dict, Union
-
-from . import AsuXdb as db
-
-couplesdb = db.couple
-karmadb = db.karma
-
-
-async def _get_lovers(chat_id: int):
- lovers = couplesdb.find_one({"chat_id": chat_id})
- lovers = lovers["couple"] if lovers else {}
- return lovers
-
-
-async def get_couple(chat_id: int, date: str):
- lovers = await _get_lovers(chat_id)
- return lovers[date] if date in lovers else False
-
-
-async def save_couple(chat_id: int, date: str, couple: dict):
- lovers = await _get_lovers(chat_id)
- lovers[date] = couple
- couplesdb.update_one(
- {"chat_id": chat_id}, {"$set": {"couple": lovers}}, upsert=True
- )
-
-
-async def get_karmas_count() -> dict:
- chats = karmadb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return {}
- chats_count = 0
- karmas_count = 0
- for chat in await chats.to_list(length=1000000):
- for i in chat["karma"]:
- karma_ = chat["karma"][i]["karma"]
- if karma_ > 0:
- karmas_count += karma_
- chats_count += 1
- return {"chats_count": chats_count, "karmas_count": karmas_count}
-
-
-async def user_global_karma(user_id) -> int:
- chats = karmadb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return 0
- total_karma = 0
- for chat in await chats.to_list(length=1000000):
- karma = await get_karma(chat["chat_id"], await int_to_alpha(user_id))
- if karma and (int(karma["karma"]) > 0):
- total_karma += int(karma["karma"])
- return total_karma
-
-
-async def get_karmas(chat_id: int) -> Dict[str, int]:
- karma = karmadb.find_one({"chat_id": chat_id})
- return karma["karma"] if karma else {}
-
-
-async def get_karma(chat_id: int, name: str) -> Union[bool, dict]:
- name = name.lower().strip()
- karmas = await get_karmas(chat_id)
- if name in karmas:
- return karmas[name]
-
-
-async def update_karma(chat_id: int, name: str, karma: dict):
- name = name.lower().strip()
- karmas = await get_karmas(chat_id)
- karmas[name] = karma
- karmadb.update_one({"chat_id": chat_id}, {"$set": {"karma": karmas}}, upsert=True)
-
-
-async def is_karma_on(chat_id: int) -> bool:
- chat = karmadb.find_one({"chat_id_toggle": chat_id})
- return not chat
-
-
-async def karma_on(chat_id: int):
- is_karma = await is_karma_on(chat_id)
- if is_karma:
- return
- return karmadb.delete_one({"chat_id_toggle": chat_id})
-
-
-async def karma_off(chat_id: int):
- is_karma = await is_karma_on(chat_id)
- if not is_karma:
- return
- return karmadb.insert_one({"chat_id_toggle": chat_id})
-
-
-async def int_to_alpha(user_id: int) -> str:
- alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
- user_id = str(user_id)
- return "".join(alphabet[int(i)] for i in user_id)
-
-
-async def alpha_to_int(user_id_alphabet: str) -> int:
- alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
- user_id = ""
- for i in user_id_alphabet:
- index = alphabet.index(i)
- user_id += str(index)
- return int(user_id)
diff --git a/Exon/modules/no_sql/log_channel_db.py b/Exon/modules/no_sql/log_channel_db.py
deleted file mode 100644
index bae29409..00000000
--- a/Exon/modules/no_sql/log_channel_db.py
+++ /dev/null
@@ -1,72 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-from Exon.modules.no_sql import get_collection
-
-LOG_DATA = get_collection("log_channels")
-
-CHANNELS = {}
-
-
-def set_chat_log_channel(chat_id, log_channel):
- LOG_DATA.update_one(
- {"chat_id": chat_id}, {"$set": {"log_channel": log_channel}}, upsert=True
- )
- CHANNELS[str(chat_id)] = log_channel
-
-
-def get_chat_log_channel(chat_id) -> int:
- return CHANNELS.get(str(chat_id))
-
-
-def stop_chat_logging(chat_id) -> int:
- res = LOG_DATA.find_one_and_delete({"chat_id": chat_id})
- if str(chat_id) in CHANNELS:
- del CHANNELS[str(chat_id)]
- return res["log_channel"]
-
-
-def num_logchannels() -> int:
- return LOG_DATA.count_documents({})
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- LOG_DATA.update_one({"chat_id": old_chat_id}, {"$set": {"chat_id": new_chat_id}})
- if str(old_chat_id) in CHANNELS:
- CHANNELS[str(new_chat_id)] = CHANNELS.get(str(old_chat_id))
-
-
-def __load_log_channels():
- global CHANNELS
- CHANNELS = {
- str(chat["chat_id"]): str(chat["log_channel"]) for chat in LOG_DATA.find()
- }
-
-
-__load_log_channels()
diff --git a/Exon/modules/no_sql/users_db.py b/Exon/modules/no_sql/users_db.py
deleted file mode 100644
index 02688d52..00000000
--- a/Exon/modules/no_sql/users_db.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-"""Users Database."""
-
-from Exon import dispatcher
-from Exon.modules.no_sql import get_collection
-
-USERS_DB = get_collection("users")
-CHATS_DB = get_collection("chats")
-CHAT_MEMBERS_DB = get_collection("chat_mamber")
-
-
-def ensure_bot_in_db():
- USERS_DB.update_one(
- {"_id": dispatcher.bot.id},
- {"$set": {"username": dispatcher.bot.username}},
- upsert=True,
- )
-
-
-def update_user(user_id, username, chat_id=None, chat_name=None):
- USERS_DB.update_one({"_id": user_id}, {"$set": {"username": username}}, upsert=True)
-
- if not (chat_id or chat_name):
- return
-
- CHATS_DB.update_one(
- {"chat_id": chat_id}, {"$set": {"chat_name": chat_name}}, upsert=True
- )
-
- member = CHAT_MEMBERS_DB.find_one({"chat_id": chat_id, "user_id": user_id})
- if member is None:
- CHAT_MEMBERS_DB.insert_one({"chat_id": chat_id, "user_id": user_id})
-
-
-def get_userid_by_name(username) -> dict:
- return list(USERS_DB.find({"username": username}))
-
-
-def get_name_by_userid(user_id) -> dict:
- return list(USERS_DB.find_one({"_id": user_id}))
-
-
-def get_chat_members(chat_id) -> list:
- return list(CHAT_MEMBERS_DB.find({"chat_id": chat_id}))
-
-
-def get_all_chats() -> list:
- return list(CHATS_DB.find())
-
-
-def get_all_users() -> list:
- return list(USERS_DB.find())
-
-
-def get_user_num_chats(user_id) -> int:
- return CHAT_MEMBERS_DB.count_documents({"user_id": user_id})
-
-
-def get_user_com_chats(user_id) -> int:
- return list(CHAT_MEMBERS_DB.find({"user_id": user_id}))
-
-
-def num_chats() -> int:
- return CHATS_DB.count_documents({})
-
-
-def num_chat_users() -> int:
- return CHAT_MEMBERS_DB.count_documents({})
-
-
-def num_users() -> int:
- return USERS_DB.count_documents({})
-
-
-def rem_chat(chat_id) -> None:
- CHATS_DB.delete_one({"chat_id": chat_id})
-
-
-def migrate_chat(old_chat_id, new_chat_id) -> None:
- CHATS_DB.update_one({"chat_id": old_chat_id}, {"$set": {"chat_id": new_chat_id}})
-
- chat_members = CHAT_MEMBERS_DB.find({"chat_id": old_chat_id})
- for member in chat_members:
- CHAT_MEMBERS_DB.update_one(
- {"chat_id": member["chat_id"]}, {"$set": {"chat_id": new_chat_id}}
- )
-
-
-ensure_bot_in_db()
diff --git a/Exon/modules/notes.py b/Exon/modules/notes.py
deleted file mode 100644
index e219a6eb..00000000
--- a/Exon/modules/notes.py
+++ /dev/null
@@ -1,605 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import ast
-import random
-import re
-from io import BytesIO
-
-from telegram import (
- MAX_MESSAGE_LENGTH,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- Update,
-)
-from telegram.error import BadRequest
-from telegram.ext import (
- CallbackContext,
- CallbackQueryHandler,
- CommandHandler,
- Filters,
- MessageHandler,
-)
-from telegram.utils.helpers import escape_markdown, mention_markdown
-
-import Exon.modules.sql.notes_sql as sql
-from Exon import DRAGONS, JOIN_LOGGER, LOGGER, SUPPORT_CHAT, dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.chat_status import connection_status, user_admin
-from Exon.modules.helper_funcs.handlers import MessageHandlerChecker
-from Exon.modules.helper_funcs.misc import build_keyboard, revert_buttons
-from Exon.modules.helper_funcs.msg_types import get_note_type
-from Exon.modules.helper_funcs.string_handling import escape_invalid_curly_brackets
-
-FILE_MATCHER = re.compile(r"^###file_id(!photo)?###:(.*?)(?:\s|$)")
-STICKER_MATCHER = re.compile(r"^###sticker(!photo)?###:")
-BUTTON_MATCHER = re.compile(r"^###button(!photo)?###:(.*?)(?:\s|$)")
-MYFILE_MATCHER = re.compile(r"^###file(!photo)?###:")
-MYPHOTO_MATCHER = re.compile(r"^###photo(!photo)?###:")
-MYAUDIO_MATCHER = re.compile(r"^###audio(!photo)?###:")
-MYVOICE_MATCHER = re.compile(r"^###voice(!photo)?###:")
-MYVIDEO_MATCHER = re.compile(r"^###video(!photo)?###:")
-MYVIDEONOTE_MATCHER = re.compile(r"^###video_note(!photo)?###:")
-
-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,
-}
-
-
-# Do not async
-def get(update, context, notename, show_none=True, no_format=False):
- bot = context.bot
- chat_id = update.effective_message.chat.id
- note_chat_id = update.effective_chat.id
- note = sql.get_note(note_chat_id, notename)
- message = update.effective_message # type: Optional[Message]
-
- if note:
- if MessageHandlerChecker.check_user(update.effective_user.id):
- return
- # If we're replying to a message, reply to that message (unless it's an error)
- if message.reply_to_message:
- reply_id = message.reply_to_message.message_id
- else:
- reply_id = message.message_id
- if note.is_reply:
- if JOIN_LOGGER:
- try:
- bot.forward_message(
- chat_id=chat_id,
- from_chat_id=JOIN_LOGGER,
- message_id=note.value,
- )
- except BadRequest as excp:
- if excp.message != "Message to forward not found":
- raise
- message.reply_text(
- "This message seems to have been lost - I'll remove it "
- "from your notes list.",
- )
- sql.rm_note(note_chat_id, notename)
- else:
- try:
- bot.forward_message(
- chat_id=chat_id,
- from_chat_id=chat_id,
- message_id=note.value,
- )
- except BadRequest as excp:
- if excp.message != "Message to forward not found":
- raise
- message.reply_text(
- "Looks like the original sender of this note has deleted "
- "their message - sorry! Get your bot admin to start using a "
- "message dump to avoid this. I'll remove this note from "
- "your saved notes.",
- )
- sql.rm_note(note_chat_id, notename)
- else:
- VALID_NOTE_FORMATTERS = [
- "first",
- "last",
- "fullname",
- "username",
- "id",
- "chatname",
- "mention",
- ]
- if valid_format := escape_invalid_curly_brackets(
- note.value,
- VALID_NOTE_FORMATTERS,
- ):
- if not no_format and "%%%" in valid_format:
- split = valid_format.split("%%%")
- text = random.choice(split) if all(split) else valid_format
- else:
- text = valid_format
- text = text.format(
- first=escape_markdown(message.from_user.first_name),
- last=escape_markdown(
- message.from_user.last_name
- or message.from_user.first_name,
- ),
- fullname=escape_markdown(
- " ".join(
- [
- message.from_user.first_name,
- message.from_user.last_name,
- ]
- if message.from_user.last_name
- else [message.from_user.first_name],
- ),
- ),
- username=f"@{message.from_user.username}"
- if message.from_user.username
- else mention_markdown(
- message.from_user.id,
- message.from_user.first_name,
- ),
- mention=mention_markdown(
- message.from_user.id,
- message.from_user.first_name,
- ),
- chatname=escape_markdown(
- message.chat.title
- if message.chat.type != "private"
- else message.from_user.first_name,
- ),
- id=message.from_user.id,
- )
- else:
- text = ""
-
- keyb = []
- parseMode = ParseMode.MARKDOWN
- buttons = sql.get_buttons(note_chat_id, notename)
- if no_format:
- parseMode = None
- text += revert_buttons(buttons)
- else:
- keyb = build_keyboard(buttons)
-
- keyboard = InlineKeyboardMarkup(keyb)
-
- try:
- if note.msgtype in (sql.Types.BUTTON_TEXT, sql.Types.TEXT):
- bot.send_message(
- chat_id,
- text,
- reply_to_message_id=reply_id,
- parse_mode=parseMode,
- disable_web_page_preview=True,
- reply_markup=keyboard,
- )
- elif ENUM_FUNC_MAP[note.msgtype] == dispatcher.bot.send_sticker:
- ENUM_FUNC_MAP[note.msgtype](
- chat_id,
- note.file,
- reply_to_message_id=reply_id,
- reply_markup=keyboard,
- )
- else:
- ENUM_FUNC_MAP[note.msgtype](
- chat_id,
- note.file,
- caption=text,
- reply_to_message_id=reply_id,
- parse_mode=parseMode,
- reply_markup=keyboard,
- )
-
- except BadRequest as excp:
- if excp.message == "Entity_mention_user_invalid":
- message.reply_text(
- "Looks like you tried to mention someone I've never seen before. If you really "
- "want to mention them, forward one of their messages to me, and I'll be able "
- "to tag them!",
- )
- elif FILE_MATCHER.match(note.value):
- message.reply_text(
- "This note was an incorrectly imported file from another bot - I can't use "
- "it. If you really need it, you'll have to save it again. In "
- "the meantime, I'll remove it from your notes list.",
- )
- sql.rm_note(note_chat_id, notename)
- else:
- message.reply_text(
- "This note could not be sent, as it is incorrectly formatted. Ask in "
- f"@{SUPPORT_CHAT} if you can't figure out why!",
- )
- LOGGER.exception(
- "Could not parse message #%s in chat %s",
- notename,
- str(note_chat_id),
- )
- LOGGER.warning("Message was: %s", str(note.value))
- return
- if show_none:
- message.reply_text("This note doesn't exist")
-
-
-@connection_status
-def cmd_get(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- if len(args) >= 2 and args[1].lower() == "noformat":
- get(update, context, args[0].lower(), show_none=True, no_format=True)
- elif len(args) >= 1:
- get(update, context, args[0].lower(), show_none=True)
- else:
- update.effective_message.reply_text("Get rekt")
-
-
-@connection_status
-def hash_get(update: Update, context: CallbackContext):
- message = update.effective_message.text
- fst_word = message.split()[0]
- no_hash = fst_word[1:].lower()
- get(update, context, no_hash, show_none=False)
-
-
-@connection_status
-def slash_get(update: Update, context: CallbackContext):
- message, chat_id = update.effective_message.text, update.effective_chat.id
- no_slash = message[1:]
- note_list = sql.get_all_chat_notes(chat_id)
-
- try:
- noteid = note_list[int(no_slash) - 1]
- note_name = str(noteid).strip(">").split()[1]
- get(update, context, note_name, show_none=False)
- except IndexError:
- update.effective_message.reply_text("Wrong Note ID 😾")
-
-
-@user_admin
-@connection_status
-def save(update: Update, context: CallbackContext):
- chat_id = update.effective_chat.id
- msg = update.effective_message # type: Optional[Message]
-
- note_name, text, data_type, content, buttons = get_note_type(msg)
- note_name = note_name.lower()
- if data_type is None:
- msg.reply_text("Dude, there's no note")
- return
-
- sql.add_note_to_db(
- chat_id,
- note_name,
- text,
- data_type,
- buttons=buttons,
- file=content,
- )
-
- msg.reply_text(
- f"Yas! Added `{note_name}`.\nGet it with /get `{note_name}`, or `#{note_name}`",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- if msg.reply_to_message and msg.reply_to_message.from_user.is_bot:
- if text:
- msg.reply_text(
- "Seems like you're trying to save a message from a bot. Unfortunately, "
- "bots can't forward bot messages, so I can't save the exact message. "
- "\nI'll save all the text I can, but if you want more, you'll have to "
- "forward the message yourself, and then save it.",
- )
- else:
- msg.reply_text(
- "Bots are kinda handicapped by telegram, making it hard for bots to "
- "interact with other bots, so I can't save this message "
- "like I usually would - do you mind forwarding it and "
- "then saving that new message? Thanks!",
- )
- return
-
-
-@user_admin
-@connection_status
-def clear(update: Update, context: CallbackContext):
- args = context.args
- if len(args) >= 1:
- chat_id = update.effective_chat.id
- notename = args[0].lower()
-
- if sql.rm_note(chat_id, notename):
- update.effective_message.reply_text("Successfully removed note.")
- else:
- update.effective_message.reply_text("That's not a note in my database!")
-
-
-def clearall(update: Update, context: CallbackContext):
- chat = update.effective_chat
- user = update.effective_user
- member = chat.get_member(user.id)
- if member.status != "creator" and user.id not in DRAGONS:
- update.effective_message.reply_text(
- "Only the chat owner can clear all notes at once.",
- )
- else:
- buttons = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="Delete all notes",
- callback_data="notes_rmall",
- ),
- ],
- [InlineKeyboardButton(text="Cancel", callback_data="notes_cancel")],
- ],
- )
- update.effective_message.reply_text(
- f"Are you sure you would like to clear ALL notes in {chat.title}? This action cannot be undone.",
- reply_markup=buttons,
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-def clearall_btn(update: Update, context: CallbackContext):
- query = update.callback_query
- chat = update.effective_chat
- message = update.effective_message
- member = chat.get_member(query.from_user.id)
- if query.data == "notes_rmall":
- if member.status == "creator" or query.from_user.id in DRAGONS:
- note_list = sql.get_all_chat_notes(chat.id)
- try:
- for notename in note_list:
- note = notename.name.lower()
- sql.rm_note(chat.id, note)
- message.edit_text("Deleted all notes.")
- except BadRequest:
- return
-
- if member.status == "administrator":
- query.answer("Only owner of the chat can do this.")
-
- if member.status == "member":
- query.answer("You need to be admin to do this.")
- elif query.data == "notes_cancel":
- if member.status == "creator" or query.from_user.id in DRAGONS:
- message.edit_text("Clearing of all notes has been cancelled.")
- return
- if member.status == "administrator":
- query.answer("Only owner of the chat can do this.")
- if member.status == "member":
- query.answer("You need to be admin to do this.")
-
-
-@connection_status
-def list_notes(update: Update, context: CallbackContext):
- chat_id = update.effective_chat.id
- note_list = sql.get_all_chat_notes(chat_id)
- notes = len(note_list) + 1
- msg = "Get note by `/notenumber` or `#notename` \n\n *ID* *Note* \n"
- for note_id, note in zip(range(1, notes), note_list):
- if note_id < 10:
- note_name = f"`{note_id:2}.` `#{(note.name.lower())}`\n"
- else:
- note_name = f"`{note_id}.` `#{(note.name.lower())}`\n"
- if len(msg) + len(note_name) > MAX_MESSAGE_LENGTH:
- update.effective_message.reply_text(msg, parse_mode=ParseMode.MARKDOWN)
- msg = ""
- msg += note_name
-
- if not note_list:
- try:
- update.effective_message.reply_text("No notes in this chat!")
- except BadRequest:
- update.effective_message.reply_text("No notes in this chat!", quote=False)
-
- elif len(msg) != 0:
- update.effective_message.reply_text(msg, parse_mode=ParseMode.MARKDOWN)
-
-
-def __import_data__(chat_id, data):
- failures = []
- for notename, notedata in data.get("extra", {}).items():
- match = FILE_MATCHER.match(notedata)
- matchsticker = STICKER_MATCHER.match(notedata)
- matchbtn = BUTTON_MATCHER.match(notedata)
- matchfile = MYFILE_MATCHER.match(notedata)
- matchphoto = MYPHOTO_MATCHER.match(notedata)
- matchaudio = MYAUDIO_MATCHER.match(notedata)
- matchvoice = MYVOICE_MATCHER.match(notedata)
- matchvideo = MYVIDEO_MATCHER.match(notedata)
- matchvn = MYVIDEONOTE_MATCHER.match(notedata)
-
- if match:
- failures.append(notename)
- if notedata := notedata[match.end():].strip():
- sql.add_note_to_db(chat_id, notename[1:], notedata, sql.Types.TEXT)
- elif matchsticker:
- if content := notedata[matchsticker.end():].strip():
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.STICKER,
- file=content,
- )
- elif matchbtn:
- parse = notedata[matchbtn.end():].strip()
- notedata = parse.split("<###button###>")[0]
- buttons = parse.split("<###button###>")[1]
- if buttons := ast.literal_eval(buttons):
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.BUTTON_TEXT,
- buttons=buttons,
- )
- elif matchfile:
- file = notedata[matchfile.end():].strip()
- file = file.split("<###TYPESPLIT###>")
- notedata = file[1]
- if content := file[0]:
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.DOCUMENT,
- file=content,
- )
- elif matchphoto:
- photo = notedata[matchphoto.end():].strip()
- photo = photo.split("<###TYPESPLIT###>")
- notedata = photo[1]
- if content := photo[0]:
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.PHOTO,
- file=content,
- )
- elif matchaudio:
- audio = notedata[matchaudio.end():].strip()
- audio = audio.split("<###TYPESPLIT###>")
- notedata = audio[1]
- if content := audio[0]:
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.AUDIO,
- file=content,
- )
- elif matchvoice:
- voice = notedata[matchvoice.end():].strip()
- voice = voice.split("<###TYPESPLIT###>")
- notedata = voice[1]
- if content := voice[0]:
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.VOICE,
- file=content,
- )
- elif matchvideo:
- video = notedata[matchvideo.end():].strip()
- video = video.split("<###TYPESPLIT###>")
- notedata = video[1]
- if content := video[0]:
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.VIDEO,
- file=content,
- )
- elif matchvn:
- video_note = notedata[matchvn.end():].strip()
- video_note = video_note.split("<###TYPESPLIT###>")
- notedata = video_note[1]
- if content := video_note[0]:
- sql.add_note_to_db(
- chat_id,
- notename[1:],
- notedata,
- sql.Types.VIDEO_NOTE,
- file=content,
- )
- else:
- sql.add_note_to_db(chat_id, notename[1:], notedata, sql.Types.TEXT)
-
- if failures:
- with BytesIO(str.encode("\n".join(failures))) as output:
- output.name = "failed_imports.txt"
- dispatcher.bot.send_document(
- chat_id,
- document=output,
- filename="failed_imports.txt",
- caption="These files/photos failed to import due to originating "
- "from another bot. This is a telegram API restriction, and can't "
- "be avoided. Sorry for the inconvenience!",
- )
-
-
-def __stats__():
- return f"× {sql.num_notes()} notes, across {sql.num_chats()} chats."
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- notes = sql.get_all_chat_notes(chat_id)
- return f"There are `{len(notes)}` notes in this chat."
-
-
-__mod_name__ = "𝐍ᴏᴛᴇs "
-
-GET_HANDLER = CommandHandler("get", cmd_get, run_async=True)
-HASH_GET_HANDLER = MessageHandler(
- Filters.regex(r"^#[\w\-]+(?!\n)$"), hash_get, run_async=True
-)
-SLASH_GET_HANDLER = MessageHandler(Filters.regex(r"^/\d+$"), slash_get, run_async=True)
-SAVE_HANDLER = CommandHandler("save", save, run_async=True)
-DELETE_HANDLER = CommandHandler("clear", clear, run_async=True)
-
-LIST_HANDLER = DisableAbleCommandHandler(
- ["notes", "saved"], list_notes, admin_ok=True, run_async=True
-)
-
-CLEARALL = DisableAbleCommandHandler("removeallnotes", clearall, run_async=True)
-CLEARALL_BTN = CallbackQueryHandler(clearall_btn, pattern=r"notes_.*", run_async=True)
-
-dispatcher.add_handler(GET_HANDLER)
-dispatcher.add_handler(SAVE_HANDLER)
-dispatcher.add_handler(LIST_HANDLER)
-dispatcher.add_handler(DELETE_HANDLER)
-dispatcher.add_handler(HASH_GET_HANDLER)
-dispatcher.add_handler(SLASH_GET_HANDLER)
-dispatcher.add_handler(CLEARALL)
-dispatcher.add_handler(CLEARALL_BTN)
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "notes_help")
-
-# """
diff --git a/Exon/modules/pin.py b/Exon/modules/pin.py
deleted file mode 100644
index b557f7dd..00000000
--- a/Exon/modules/pin.py
+++ /dev/null
@@ -1,402 +0,0 @@
-from re import compile
-
-from pyrogram import filters
-from pyrogram.errors import ChatAdminRequired, RightForbidden, RPCError
-from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
-
-from Exon import Abishnoi
-from Exon.modules.no_sql import AsuXdb as db
-from Exon.utils.pluginhelp import member_permissions
-
-BTN_URL_REGEX = compile(r"(\[([^\[]+?)\]\(buttonurl:(?:/{0,2})(.+?)(:same)?\))")
-
-
-async def parse_button(text: str):
- """Parse button from text."""
- markdown_note = text
- prev = 0
- note_data = ""
- buttons = []
- for match in BTN_URL_REGEX.finditer(markdown_note):
- # Check if btnurl is escaped
- n_escapes = 0
- to_check = match.start(1) - 1
- while to_check > 0 and markdown_note[to_check] == "\\":
- n_escapes += 1
- to_check -= 1
-
- # if even, not escaped -> create button
- if n_escapes % 2 == 0:
- # create a thruple with button label, url, and newline status
- buttons.pgramend((match.group(2), match.group(3), bool(match.group(4))))
- note_data += markdown_note[prev: match.start(1)]
- prev = match.end(1)
- # if odd, escaped -> move along
- else:
- note_data += markdown_note[prev:to_check]
- prev = match.start(1) - 1
-
- note_data += markdown_note[prev:]
-
- return note_data, buttons
-
-
-async def build_keyboard(buttons):
- """Build keyboards from provided buttons."""
- keyb = []
- for btn in buttons:
- if btn[-1] and keyb:
- keyb[-1].pgramend(InlineKeyboardButton(btn[0], url=btn[1]))
- else:
- keyb.pgramend([InlineKeyboardButton(btn[0], url=btn[1])])
-
- return keyb
-
-
-class MongoDB:
- """Class for interacting with Bot database."""
-
- def __init__(self, collection) -> None:
- self.collection = db[collection]
-
- # Insert one entry into collection
- def insert_one(self, document):
- result = self.collection.insert_one(document)
- return repr(result.inserted_id)
-
- # Find one entry from collection
- def find_one(self, query):
- return result if (result := self.collection.find_one(query)) else False
-
- # Find entries from collection
- def find_all(self, query=None):
- if query is None:
- query = {}
- lst = []
- for document in self.collection.find(query):
- lst.pgramend(document)
- return lst
-
- # Count entries from collection
- def count(self, query=None):
- if query is None:
- query = {}
- return self.collection.count_documents(query)
-
- # Delete entry/entries from collection
- def delete_one(self, query):
- self.collection.delete_many(query)
- return self.collection.count_documents({})
-
- # Replace one entry in collection
- def replace(self, query, new_data):
- old = self.collection.find_one(query)
- _id = old["_id"]
- self.collection.replace_one({"_id": _id}, new_data)
- new = self.collection.find_one({"_id": _id})
- return old, new
-
- # Update one entry from collection
- def update(self, query, update):
- result = self.collection.update_one(query, {"$set": update})
- new_document = self.collection.find_one(query)
- return result.modified_count, new_document
-
- # Close connection
- @staticmethod
- def close():
- return mongodb_client.close()
-
-
-def __connect_first():
- _ = MongoDB("test")
-
-
-__connect_first()
-
-
-@Abishnoi.on_message(filters.command("unpinall") & ~filters.private)
-async def unpinall_message(_, m: Message):
- try:
- chat_id = m.chat.id
- user_id = m.from_user.id
- permissions = await member_permissions(chat_id, user_id)
- if "can_change_info" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_pin_messages" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_restrict_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_promote_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- try:
- await _.unpin_all_chat_messages(m.chat.id)
- await m.reply("I have unpinned all messages")
- except ChatAdminRequired:
- await m.reply("I'm not admin here")
- except RightForbidden:
- await m.reply("I don't have enough rights to unpin here")
- except RPCError as ef:
- await m.reply_text(ef)
- return
-
- except Exception as e:
- print(e)
- await m.reply_text(e)
- return
-
-
-from threading import RLock
-
-INSERTION_LOCK = RLock()
-
-
-class Pins:
- """Class for managing antichannelpins in chats."""
-
- # Database name to connect to to preform operations
- db_name = "antichannelpin"
-
- def __init__(self, chat_id: int) -> None:
- self.collection = MongoDB(self.db_name)
- self.chat_id = chat_id
- self.chat_info = self.__ensure_in_db()
-
- def get_settings(self):
- with INSERTION_LOCK:
- return self.chat_info
-
- def antichannelpin_on(self):
- with INSERTION_LOCK:
- return self.set_on("antichannelpin")
-
- def cleanlinked_on(self):
- with INSERTION_LOCK:
- return self.set_on("cleanlinked")
-
- def antichannelpin_off(self):
- with INSERTION_LOCK:
- return self.set_off("antichannelpin")
-
- def cleanlinked_off(self):
- with INSERTION_LOCK:
- return self.set_off("cleanlinked")
-
- def set_on(self, atype: str):
- with INSERTION_LOCK:
- otype = "cleanlinked" if atype == "antichannelpin" else "antichannelpin"
- return self.collection.update(
- {"_id": self.chat_id},
- {atype: True, otype: False},
- )
-
- def set_off(self, atype: str):
- with INSERTION_LOCK:
- otype = "cleanlinked" if atype == "antichannelpin" else "antichannelpin"
- return self.collection.update(
- {"_id": self.chat_id},
- {atype: False, otype: False},
- )
-
- def __ensure_in_db(self):
- chat_data = self.collection.find_one({"_id": self.chat_id})
- if not chat_data:
- new_data = {
- "_id": self.chat_id,
- "antichannelpin": False,
- "cleanlinked": False,
- }
- self.collection.insert_one(new_data)
- return new_data
- return chat_data
-
- # Migrate if chat id changes!
- def migrate_chat(self, new_chat_id: int):
- old_chat_db = self.collection.find_one({"_id": self.chat_id})
- new_data = old_chat_db.update({"_id": new_chat_id})
- self.collection.insert_one(new_data)
- self.collection.delete_one({"_id": self.chat_id})
-
- # ----- sᴛᴀᴛɪᴄ ᴍᴇᴛʜᴏᴅs -----
- @staticmethod
- def count_chats(atype: str):
- with INSERTION_LOCK:
- collection = MongoDB(Pins.db_name)
- return collection.count({atype: True})
-
- @staticmethod
- def list_chats(query: str):
- with INSERTION_LOCK:
- collection = MongoDB(Pins.db_name)
- return collection.find_all({query: True})
-
- @staticmethod
- def load_from_db():
- with INSERTION_LOCK:
- collection = MongoDB(Pins.db_name)
- return collection.findall()
-
- @staticmethod
- def repair_db(collection):
- all_data = collection.find_all()
- keys = {"antichannelpin": False, "cleanlinked": False}
- for data in all_data:
- for key, val in keys.items():
- try:
- _ = data[key]
- except KeyError:
- collection.update({"_id": data["_id"]}, {key: val})
-
-
-def __pre_req_pins_chats():
- collection = MongoDB(Pins.db_name)
- Pins.repair_db(collection)
-
-
-@Abishnoi.on_message(filters.command("antichannelpin") & ~filters.private)
-async def anti_channel_pin(_, m: Message):
- chat_id = m.chat.id
- user_id = m.from_user.id
- permissions = await member_permissions(chat_id, user_id)
- if "can_change_info" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_pin_messages" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_restrict_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_promote_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- pinsdb = Pins(m.chat.id)
- if len(m.text.split()) == 1:
- status = pinsdb.get_settings()["antichannelpin"]
- await m.reply_text(f"Antichannelpin currently: {status}")
- return
-
- if len(m.text.split()) == 2:
- if m.command[1] in ("yes", "on", "true"):
- pinsdb.antichannelpin_on()
- msg = "Antichannelpin turned on for this chat"
- elif m.command[1] in ("no", "off", "false"):
- pinsdb.antichannelpin_off()
- msg = "Antichannelpin turned off for this chat"
- else:
- await m.reply_text("Invalid syntax")
- return
-
- await m.reply_text(msg)
- return
-
-
-@Abishnoi.on_message(filters.command("cleanlinked") & ~filters.private)
-async def clean_linked(_, m: Message):
- chat_id = m.chat.id
- user_id = m.from_user.id
- permissions = await member_permissions(chat_id, user_id)
- if "can_change_info" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_pin_messages" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_restrict_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_promote_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- pinsdb = Pins(m.chat.id)
-
- if len(m.text.split()) == 1:
- status = pinsdb.get_settings()["cleanlinked"]
- await m.reply_text(f"Cleanlinked pins currently: {status}")
- return
-
- if len(m.text.split()) == 2:
- if m.command[1] in ("yes", "on", "true"):
- pinsdb.cleanlinked_on()
- msg = "Turned on CleanLinked! Now all the messages from linked channel will be deleted!"
- elif m.command[1] in ("no", "off", "false"):
- pinsdb.cleanlinked_off()
- msg = "Turned off CleanLinked! Messages from linked channel will not be deleted!"
- else:
- await m.reply("Invalid syntax")
- return
-
- await m.reply(msg)
- return
-
-
-@Abishnoi.on_message(filters.command("permapin") & ~filters.private)
-async def perma_pin(_, m: Message):
- chat_id = m.chat.id
- user_id = m.from_user.id
- permissions = await member_permissions(chat_id, user_id)
- if "can_change_info" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_pin_messages" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_restrict_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if "can_promote_members" not in permissions:
- await m.reply_text("You Don't Have Enough Permissions.")
- return
- if m.reply_to_message or len(m.text.split()) > 1:
- if m.reply_to_message:
- text = m.reply_to_message.text
- elif len(m.text.split()) > 1:
- text = m.text.split(None, 1)[1]
- teks, button = await parse_button(text)
- button = await build_keyboard(button)
- button = InlineKeyboardMarkup(button) if button else None
- z = await m.reply_text(teks, reply_markup=button)
- await z.pin()
- else:
- await m.reply_text("Reply to a message or enter text to pin it.")
- await m.delete()
- return
-
-
-@Abishnoi.on_message(filters.linked_channel)
-async def antichanpin_cleanlinked(c, m: Message):
- try:
- msg_id = m.message_id
- pins_db = Pins(m.chat.id)
- curr = pins_db.get_settings()
- if curr["antichannelpin"]:
- await c.unpin_chat_message(chat_id=m.chat.id, message_id=msg_id)
- if curr["cleanlinked"]:
- await c.delete_messages(m.chat.id, msg_id)
- except ChatAdminRequired:
- await m.reply_text(
- "Disabled antichannelpin as I don't have enough admin rights!",
- )
- pins_db.antichannelpin_off()
- except Exception:
- return
- return
-
-
-__mod_name__ = "𝐏ɪɴs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "pins_help")
-
-# """
diff --git a/Exon/modules/ping.py b/Exon/modules/ping.py
deleted file mode 100644
index 1c77470e..00000000
--- a/Exon/modules/ping.py
+++ /dev/null
@@ -1,169 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import time
-from typing import List
-
-import requests
-from pyrogram import filters
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.ext import CallbackContext
-
-from Exon import Abishnoi as Exon
-from Exon import StartTime, dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.chat_status import sudo_plus
-from Exon.modules.stats import bot_sys_stats as nagisa
-
-sites_list = {
- "Telegram": "https://api.telegram.org",
- "Kaizoku": "https://animekaizoku.com",
- "Kayo": "https://animekayo.com",
- "Jikan": "https://api.jikan.moe/v3",
- "Kuki Chatbot": "https://kuki-yukicloud.up.railway.app/",
- "liones API": "https://liones-api.herokuapp.com/",
-}
-
-
-def get_readable_time(seconds: int) -> str:
- count = 0
- ping_time = ""
- time_list = []
- time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"]
-
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
-
- for x in range(len(time_list)):
- time_list[x] = str(time_list[x]) + time_suffix_list[x]
- if len(time_list) == 4:
- ping_time += f"{time_list.pop()}, "
-
- time_list.reverse()
- ping_time += ":".join(time_list)
-
- return ping_time
-
-
-def ping_func(to_ping: List[str]) -> List[str]:
- ping_result = []
-
- for each_ping in to_ping:
- start_time = time.time()
- site_to_ping = sites_list[each_ping]
- r = requests.get(site_to_ping)
- end_time = time.time()
- ping_time = f"{str(round(end_time - start_time, 2))}s"
-
- pinged_site = f"{each_ping}"
-
- if each_ping in ("Kaizoku", "Kayo"):
- pinged_site = f'{each_ping}'
- ping_time = f"{ping_time} (Status: {r.status_code})
"
-
- ping_text = f"{pinged_site}: {ping_time}
"
- ping_result.append(ping_text)
-
- return ping_result
-
-
-# @sudo_plus # ᴘᴜʙʟɪᴄ ᴘɪɴɢ ᴄᴏᴍᴍᴀɴᴅ
-def ping(update: Update, context: CallbackContext):
- msg = update.effective_message
-
- start_time = time.time()
- message = msg.reply_text("Pinging...")
- end_time = time.time()
- telegram_ping = f"{str(round((end_time - start_time) * 1000, 3))} ms"
- uptime = get_readable_time((time.time() - StartTime))
-
- message.edit_text(
- f"PONG!!\nᴛɪᴍᴇ ᴛᴀᴋᴇɴ: {telegram_ping}
\nsᴇʀᴠɪᴄᴇ ᴜᴘᴛɪᴍᴇ: {uptime}
",
- parse_mode=ParseMode.HTML,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="sʏsᴛᴇᴍ sᴛᴀᴛs", callback_data="stats_callback"
- )
- ]
- ]
- ),
- )
-
-
-@Exon.on_callback_query(filters.regex("stats_callback"))
-async def stats_callback(_, CallbackQuery):
- text = await nagisa()
- await Exon.answer_callback_query(CallbackQuery.id, text, show_alert=True)
-
-
-@sudo_plus
-def pingall(update: Update, context: CallbackContext):
- to_ping = ["Kaizoku", "Kayo", "Telegram", "Jikan", "Kuki Chatbot", "liones API"]
- pinged_list = ping_func(to_ping)
- pinged_list.insert(2, "")
- uptime = get_readable_time((time.time() - StartTime))
-
- reply_msg = "⏱ Ping results are:\n" + "\n".join(pinged_list)
- reply_msg += f"\nService uptime: {uptime}
"
-
- update.effective_message.reply_text(
- reply_msg,
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
-
-
-PING_HANDLER = DisableAbleCommandHandler("ping", ping, run_async=True)
-PINGALL_HANDLER = DisableAbleCommandHandler("pingall", pingall, run_async=True)
-
-dispatcher.add_handler(PING_HANDLER)
-dispatcher.add_handler(PINGALL_HANDLER)
-
-__command_list__ = ["ping", "pingall"]
-__handlers__ = [PING_HANDLER, PINGALL_HANDLER]
-
-__mod_name__ = "𝐏ɪɴɢ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "ping_help")
-
-# """
diff --git a/Exon/modules/purge.py b/Exon/modules/purge.py
deleted file mode 100644
index 57230856..00000000
--- a/Exon/modules/purge.py
+++ /dev/null
@@ -1,152 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-from pyrogram.enums import ChatType
-from pyrogram.errors import MessageDeleteForbidden, RPCError
-from pyrogram.types import Message
-
-from Exon import LOGGER, Abishnoi
-
-
-@Abishnoi.on_cmd("purge")
-@Abishnoi.adminsOnly(permissions="can_delete_messages", is_both=True)
-async def purge(c: Abishnoi, m: Message):
- if m.chat.type != ChatType.SUPERGROUP:
- await m.reply_text(text="ᴄᴀɴɴᴏᴛ ᴘᴜʀɢᴇ ᴍᴇssᴀɢᴇs ɪɴ ᴀ ʙᴀsɪᴄ ɢʀᴏᴜᴘ")
- return
-
- if m.reply_to_message:
- message_ids = list(range(m.reply_to_message.id, m.id))
-
- def divide_chunks(l: list, n: int = 100):
- for i in range(0, len(l), n):
- yield l[i: i + n]
-
- # Dielete messages in chunks of 100 messages
- m_list = list(divide_chunks(message_ids))
-
- try:
- for plist in m_list:
- await c.delete_messages(
- chat_id=m.chat.id,
- message_ids=plist,
- revoke=True,
- )
- await m.delete()
- except MessageDeleteForbidden:
- await m.reply_text(
- text="ᴄᴀɴɴᴏᴛ ᴅᴇʟᴇᴛᴇ ᴀʟʟ ᴍᴇssᴀɢᴇs. ᴛʜᴇ ᴍᴇssᴀɢᴇs ᴍᴀʏ ʙᴇ ᴛᴏᴏ ᴏʟᴅ, I ᴍɪɢʜᴛ ɴᴏᴛ ʜᴀᴠᴇ ᴅᴇʟᴇᴛᴇ ʀɪɢʜᴛs, ᴏʀ ᴛʜɪs ᴍɪɢʜᴛ ɴᴏᴛ ʙᴇ ᴀ sᴜᴘᴇʀɢʀᴏᴜᴘ."
- )
- return
- except RPCError as ef:
- LOGGER.info(f"ERROR on purge {ef}")
-
- count_del_msg = len(message_ids)
-
- z = await m.reply_text(text=f"ᴅᴇʟᴇᴛᴇᴅ {count_del_msg} messages")
- return
- await m.reply_text("ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ sᴛᴀʀᴛ ᴘᴜʀɢᴇ !")
- return
-
-
-@Abishnoi.on_cmd("spurge")
-@Abishnoi.adminsOnly(permissions="can_delete_messages", is_both=True)
-async def spurge(c: Abishnoi, m: Message):
- if m.chat.type != ChatType.SUPERGROUP:
- await m.reply_text(text="ᴄᴀɴɴᴏᴛ ᴘᴜʀɢᴇ ᴍᴇssᴀɢᴇs ɪɴ ᴀ ʙᴀsɪᴄ ɢʀᴏᴜᴘ")
- return
-
- if m.reply_to_message:
- message_ids = list(range(m.reply_to_message.id, m.id))
-
- def divide_chunks(l: list, n: int = 100):
- for i in range(0, len(l), n):
- yield l[i: i + n]
-
- # Dielete messages in chunks of 100 messages
- m_list = list(divide_chunks(message_ids))
-
- try:
- for plist in m_list:
- await c.delete_messages(
- chat_id=m.chat.id,
- message_ids=plist,
- revoke=True,
- )
- await m.delete()
- except MessageDeleteForbidden:
- await m.reply_text(
- text="ᴄᴀɴɴᴏᴛ ᴅᴇʟᴇᴛᴇ ᴀʟʟ ᴍᴇssᴀɢᴇs. ᴛʜᴇ ᴍᴇssᴀɢᴇs ᴍᴀʏ ʙᴇ ᴛᴏᴏ ᴏʟᴅ, I ᴍɪɢʜᴛ ɴᴏᴛ ʜᴀᴠᴇ ᴅᴇʟᴇᴛᴇ ʀɪɢʜᴛs, ᴏʀ ᴛʜɪs ᴍɪɢʜᴛ ɴᴏᴛ ʙᴇ ᴀ sᴜᴘᴇʀɢʀᴏᴜᴘ."
- )
- return
- except RPCError as ef:
- LOGGER.info(f"ERROR on purge {ef}")
- return
- await m.reply_text("ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴛᴏ sᴛᴀʀᴛ sᴘᴜʀɢᴇ !")
- return
-
-
-@Abishnoi.on_cmd("del")
-@Abishnoi.adminsOnly(permissions="can_delete_messages", is_both=True)
-async def del_msg(c: Abishnoi, m: Message):
- if m.reply_to_message:
- await m.delete()
- await c.delete_messages(
- chat_id=m.chat.id,
- message_ids=m.reply_to_message.id,
- )
- else:
- await m.reply_text(text="ᴡʜᴀᴛ ᴅᴏ ʏᴏᴜ ᴡᴀɴɴᴀ ᴅᴇʟᴇᴛᴇ?")
- return
-
-
-__PLUGIN__ = "Pᴜʀɢᴇ"
-
-__alt_name__ = ["purge", "del", "spurge"]
-
-__HELP__ = """
-• /purge: ᴅᴇʟᴇᴛᴇs ᴍᴇssᴀɢᴇs ᴜᴘᴛᴏ ʀᴇᴘʟɪᴇᴅ ᴍᴇssᴀɢᴇ.
-• /spurge: ᴅᴇʟᴇᴛᴇs ᴍᴇssᴀɢᴇs ᴜᴘᴛᴏ ʀᴇᴘʟɪᴇᴅ ᴍᴇssᴀɢᴇ ᴡɪᴛʜᴏᴜᴛ ᴀ sᴜᴄᴄᴇss ᴍᴇssᴀɢᴇ.
-• /del: ᴅᴇʟᴇᴛᴇs ᴀ sɪɴɢʟᴇ ᴍᴇssᴀɢᴇ, ᴜsᴇᴅ ᴀs ᴀ ʀᴇᴘʟʏ ᴛᴏ ᴍᴇssᴀɢᴇ.
-"""
-
-__mod_name__ = "𝐏ᴜʀɢᴇ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "purge_help")
-
-# """
diff --git a/Exon/modules/quote.py b/Exon/modules/quote.py
deleted file mode 100644
index f7bc30b6..00000000
--- a/Exon/modules/quote.py
+++ /dev/null
@@ -1,419 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import base64
-import json
-import os
-from asyncio import sleep
-from json.decoder import JSONDecodeError
-from random import choice
-
-from telethon.errors import MessageDeleteForbiddenError, MessageNotModifiedError
-from telethon.tl import types
-from telethon.tl.custom import Message
-from telethon.tl.types import MessageService
-from telethon.utils import get_display_name, get_peer_id
-
-from Exon.events import register
-
-##api
-
-try:
- from aiohttp import ContentTypeError
-except ImportError:
- ContentTypeError = None
-
-try:
- from PIL import Image
-except ImportError:
- Image = None
-
-try:
- import cv2
-except ImportError:
- cv2 = None
-try:
- import numpy as np
-except ImportError:
- np = None
-
-try:
- from bs4 import BeautifulSoup
-except ImportError:
- BeautifulSoup = None
-
-
-class Quotly:
- _API = "https://bot.lyo.su/quote/generate"
- _entities = {
- types.MessageEntityPhone: "phone_number",
- types.MessageEntityMention: "mention",
- types.MessageEntityBold: "bold",
- types.MessageEntityCashtag: "cashtag",
- types.MessageEntityStrike: "strikethrough",
- types.MessageEntityHashtag: "hashtag",
- types.MessageEntityEmail: "email",
- types.MessageEntityMentionName: "text_mention",
- types.MessageEntityUnderline: "underline",
- types.MessageEntityUrl: "url",
- types.MessageEntityTextUrl: "text_link",
- types.MessageEntityBotCommand: "bot_command",
- types.MessageEntityCode: "code",
- types.MessageEntityPre: "pre",
- }
-
- async def _format_quote(self, event, reply=None, sender=None, type_="private"):
- async def telegraph(file_):
- file = f"{file_}.png"
- Image.open(file_).save(file, "PNG")
- files = {"file": open(file, "rb").read()}
- uri = (
- "https://telegra.ph"
- + (
- await async_searcher(
- "https://telegra.ph/upload", post=True, data=files, re_json=True
- )
- )[0]["src"]
- )
- os.remove(file)
- os.remove(file_)
- return uri
-
- if reply:
- reply = {
- "name": get_display_name(reply.sender) or "Deleted Account",
- "text": reply.raw_text,
- "chatId": reply.chat_id,
- }
- else:
- reply = {}
- is_fwd = event.fwd_from
- name = None
- last_name = None
- if sender and sender.id not in DEVLIST:
- id_ = get_peer_id(sender)
- name = get_display_name(sender)
- elif not is_fwd:
- id_ = event.sender_id
- sender = await event.get_sender()
- name = get_display_name(sender)
- else:
- id_, sender = None, None
- name = is_fwd.from_name
- if is_fwd.from_id:
- id_ = get_peer_id(is_fwd.from_id)
- try:
- sender = await event.client.get_entity(id_)
- name = get_display_name(sender)
- except ValueError:
- pass
- if sender and hasattr(sender, "last_name"):
- last_name = sender.last_name
- entities = []
- if event.entities:
- for entity in event.entities:
- if type(entity) in self._entities:
- enti_ = entity.to_dict()
- del enti_["_"]
- enti_["type"] = self._entities[type(entity)]
- entities.append(enti_)
- message = {
- "entities": entities,
- "chatId": id_,
- "avatar": True,
- "from": {
- "id": id_,
- "first_name": (name or (sender.first_name if sender else None))
- or "Deleted Account",
- "last_name": last_name,
- "username": sender.username if sender else None,
- "language_code": "en",
- "title": name,
- "name": name or "Unknown",
- "type": type_,
- },
- "text": event.raw_text,
- "replyMessage": reply,
- }
- if event.document and event.document.thumbs:
- file_ = await event.download_media(thumb=-1)
- uri = await telegraph(file_)
- message["media"] = {"url": uri}
-
- return message
-
- async def create_quotly(self, event, url="https://qoute-api-akashpattnaik.koyeb.app/generate", reply=None, bg=None,
- sender=None, OQAPI=True, file_name="quote.webp"):
- """Create quotely's quote."""
- if reply is None:
- reply = {}
- if not isinstance(event, list):
- event = [event]
- if OQAPI:
- url = Quotly._API
- if not bg:
- bg = "#1b1429"
- content = {
- "type": "quote",
- "format": "webp",
- "backgroundColor": bg,
- "width": 512,
- "height": 768,
- "scale": 2,
- "messages": [
- await self._format_quote(message, reply=reply, sender=sender)
- for message in event
- ],
- }
- try:
- request = await async_searcher(url, post=True, json=content, re_json=True)
- except ContentTypeError as er:
- if url != self._API:
- return await self.create_quotly(
- self._API, post=True, json=content, re_json=True
- )
- raise er
- if request.get("ok"):
- with open(file_name, "wb") as file:
- image = base64.decodebytes(request["result"]["image"].encode("utf-8"))
- file.write(image)
- return file_name
- raise Exception(str(request))
-
-
-quotly = Quotly()
-
-try:
- import certifi
-except ImportError:
- certifi = None
-
-try:
- import numpy as np
-except ImportError:
- np = None
-
-
-async def async_searcher(
- url: str,
- post: bool = None,
- headers: dict = None,
- params: dict = None,
- json: dict = None,
- data: dict = None,
- ssl=None,
- re_json: bool = False,
- re_content: bool = False,
- real: bool = False,
- *args,
- **kwargs,
-):
- try:
- import aiohttp
- except ImportError as e:
- raise DependencyMissingError(
- "'aiohttp' is not installed!\nthis function requires aiohttp to be installed."
- ) from e
- async with aiohttp.ClientSession(headers=headers) as client:
- if post:
- data = await client.post(
- url, json=json, data=data, ssl=ssl, *args, **kwargs
- )
- else:
- data = await client.get(url, params=params, ssl=ssl, *args, **kwargs)
- if re_json:
- return await data.json()
- if re_content:
- return await data.read()
- return data if real else await data.text()
-
-
-def _unquote_text(text):
- return text.replace("'", "'").replace('"', '"')
-
-
-def json_parser(data, indent=None, ascii=False):
- parsed = {}
- try:
- if isinstance(data, str):
- parsed = json.loads(str(data))
- if indent:
- parsed = json.dumps(
- json.loads(str(data)), indent=indent, ensure_ascii=ascii
- )
- elif isinstance(data, dict):
- parsed = data
- if indent:
- parsed = json.dumps(data, indent=indent, ensure_ascii=ascii)
- except JSONDecodeError:
- parsed = eval(data)
- return parsed
-
-
-def check_filename(filroid):
- if os.path.exists(filroid):
- no = 1
- while True:
- ult = "{0}_{2}{1}".format(*os.path.splitext(filroid) + (no,))
- if os.path.exists(ult):
- no += 1
- else:
- return ult
- return filroid
-
-
-# edit or reply for telethon
-async def eor(event, text=None, **args):
- time = args.get("time", None)
- edit_time = args.get("edit_time", None)
- if "edit_time" in args:
- del args["edit_time"]
- if "time" in args:
- del args["time"]
- if "link_preview" not in args:
- args["link_preview"] = False
- args["reply_to"] = event.reply_to_msg_id or event
- if event.out and not isinstance(event, MessageService):
- if edit_time:
- await sleep(edit_time)
- if "file" in args and args["file"] and not event.media:
- await event.delete()
- try:
- ok = await event.client.send_message(event.chat_id, text, **args)
- except MessageNotModifiedError:
- pass
- else:
- try:
- try:
- del args["reply_to"]
- except KeyError:
- pass
- ok = await event.edit(text, **args)
- except MessageNotModifiedError:
- pass
- else:
- ok = await event.client.send_message(event.chat_id, text, **args)
-
- if time:
- await sleep(time)
- return await ok.delete()
- return ok
-
-
-async def eod(event, text=None, **kwargs):
- kwargs["time"] = kwargs.get("time", 8)
- return await eor(event, text, **kwargs)
-
-
-async def _try_delete(event):
- try:
- return await event.delete()
- except MessageDeleteForbiddenError:
- pass
- except BaseException as er:
- from . import LOGS
-
- LOGS.error("Error while Deleting Message..")
- LOGS.exception(er)
-
-
-setattr(Message, "eor", eor)
-setattr(Message, "try_delete", _try_delete)
-
-
-@register(pattern="^/q(?: |$)(.*)")
-async def quott_(event):
- match = event.pattern_match.group(1).strip()
- if not event.is_reply:
- return await event.eor("ᴘʟᴇᴀsᴇ ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ")
- msg = await event.reply("⚡️")
- reply = await event.get_reply_message()
- replied_to, reply_ = None, None
- if match:
- spli_ = match.split(maxsplit=1)
- if (spli_[0] in ["r", "reply"]) or (
- spli_[0].isdigit() and int(spli_[0]) in range(1, 21)
- ):
- if spli_[0].isdigit():
- if not event.client._bot:
- reply_ = await event.client.get_messages(
- event.chat_id,
- min_id=event.reply_to_msg_id - 1,
- reverse=True,
- limit=int(spli_[0]),
- )
- else:
- id_ = reply.id
- reply_ = []
- for msg_ in range(id_, id_ + int(spli_[0])):
- msh = await event.client.get_messages(event.chat_id, ids=msg_)
- if msh:
- reply_.append(msh)
- else:
- replied_to = await reply.get_reply_message()
- try:
- match = spli_[1]
- except IndexError:
- match = None
- user = None
- if not reply_:
- reply_ = reply
- if match:
- match = match.split(maxsplit=1)
- if match:
- if match[0].startswith("@") or match[0].isdigit():
- try:
- match_ = await event.client.parse_id(match[0])
- user = await event.client.get_entity(match_)
- except ValueError:
- pass
- match = match[1] if len(match) == 2 else None
- else:
- match = match[0]
- if match == "random":
- match = choice(all_col)
- try:
- file = await quotly.create_quotly(
- reply_, bg=match, reply=replied_to, sender=user
- )
- except Exception as er:
- return await msg.edit(str(er))
- message = await reply.reply("", file=file)
- os.remove(file)
- await msg.delete()
- return message
-
-
-__mod_name__ = "𝐐ᴜᴏᴛʟʏ"
-
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "quotly_help")
diff --git a/Exon/modules/remote_cmds.py b/Exon/modules/remote_cmds.py
deleted file mode 100644
index 2cec76dc..00000000
--- a/Exon/modules/remote_cmds.py
+++ /dev/null
@@ -1,574 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from telegram import ChatPermissions, Update
-from telegram.error import BadRequest, TelegramError
-from telegram.ext import CallbackContext
-
-from Exon import LOGGER
-from Exon.modules.helper_funcs.chat_status import (
- bot_admin,
- dev_plus,
- is_bot_admin,
- is_user_ban_protected,
- is_user_in_chat,
-)
-from Exon.modules.helper_funcs.decorators import Exoncmd
-from Exon.modules.helper_funcs.extraction import extract_user_and_text
-
-RBAN_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to punch it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can punch group administrators",
- "Channel_private",
- "Not in the chat",
-}
-
-RUNBAN_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to punch it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can punch group administrators",
- "Channel_private",
- "Not in the chat",
-}
-
-RKICK_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to punch it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can punch group administrators",
- "Channel_private",
- "Not in the chat",
-}
-
-RMUTE_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to punch it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can punch group administrators",
- "Channel_private",
- "Not in the chat",
-}
-
-RUNMUTE_ERRORS = {
- "User is an administrator of the chat",
- "Chat not found",
- "Not enough rights to restrict/unrestrict chat member",
- "User_not_participant",
- "Peer_id_invalid",
- "Group chat was deactivated",
- "Need to be inviter of a user to punch it from a basic group",
- "Chat_admin_required",
- "Only the creator of a basic group can punch group administrators",
- "Channel_private",
- "Not in the chat",
-}
-
-
-@Exoncmd(command="rban")
-@bot_admin
-def rban(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
-
- if not args:
- message.reply_text("You don't seem to be referring to a chat/user.")
- return
-
- user_id, chat_id = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
- if not chat_id:
- message.reply_text("You don't seem to be referring to a chat.")
- return
-
- try:
- chat = bot.get_chat(chat_id.split()[0])
- except BadRequest as excp:
- if excp.message == "Chat not found":
- message.reply_text(
- "Chat not found! Make sure you entered a valid chat ID and I'm part of that chat.",
- )
- return
- raise
-
- if chat.type == "private":
- message.reply_text("I'm sorry, but that's a private chat!")
- return
-
- if (
- not is_bot_admin(chat, bot.id)
- or not chat.get_member(bot.id).can_restrict_members
- ):
- message.reply_text(
- "I can't restrict people there! Make sure I'm admin and can ban users.",
- )
- return
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user")
- return
- raise
-
- if is_user_ban_protected(chat, user_id, member):
- message.reply_text("I really wish I could ban admins...")
- return
-
- if user_id == bot.id:
- message.reply_text("I'm not gonna BAN myself, are you crazy?")
- return
-
- try:
- chat.ban_member(user_id)
- message.reply_text("Banned from chat!")
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text("Banned!", quote=False)
- elif excp.message in RBAN_ERRORS:
- message.reply_text(excp.message)
- else:
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR banning user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't ban that user.")
-
-
-@Exoncmd(command="runban")
-@bot_admin
-def runban(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
-
- if not args:
- message.reply_text("You don't seem to be referring to a chat/user.")
- return
-
- user_id, chat_id = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
- if not chat_id:
- message.reply_text("You don't seem to be referring to a chat.")
- return
-
- try:
- chat = bot.get_chat(chat_id.split()[0])
- except BadRequest as excp:
- if excp.message == "Chat not found":
- message.reply_text(
- "Chat not found! Make sure you entered a valid chat ID and I'm part of that chat.",
- )
- return
- raise
-
- if chat.type == "private":
- message.reply_text("I'm sorry, but that's a private chat!")
- return
-
- if (
- not is_bot_admin(chat, bot.id)
- or not chat.get_member(bot.id).can_restrict_members
- ):
- message.reply_text(
- "I can't unrestrict people there! Make sure I'm admin and can unban users.",
- )
- return
-
- try:
- chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user there")
- return
- raise
-
- if is_user_in_chat(chat, user_id):
- message.reply_text(
- "Why are you trying to remotely unban someone that's already in that chat?",
- )
- return
-
- if user_id == bot.id:
- message.reply_text("I'm not gonna UNBAN myself, I'm an admin there!")
- return
-
- try:
- chat.unban_member(user_id)
- message.reply_text("Yep, this user can join that chat!")
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text("Unbanned!", quote=False)
- elif excp.message in RUNBAN_ERRORS:
- message.reply_text(excp.message)
- else:
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR unbanning user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't unban that user.")
-
-
-@Exoncmd(command="rkick")
-@bot_admin
-def rkick(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
-
- if not args:
- message.reply_text("You don't seem to be referring to a chat/user.")
- return
-
- user_id, chat_id = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
- if not chat_id:
- message.reply_text("You don't seem to be referring to a chat.")
- return
-
- try:
- chat = bot.get_chat(chat_id.split()[0])
- except BadRequest as excp:
- if excp.message == "Chat not found":
- message.reply_text(
- "Chat not found! Make sure you entered a valid chat ID and I'm part of that chat.",
- )
- return
- raise
-
- if chat.type == "private":
- message.reply_text("I'm sorry, but that's a private chat!")
- return
-
- if (
- not is_bot_admin(chat, bot.id)
- or not chat.get_member(bot.id).can_restrict_members
- ):
- message.reply_text(
- "I can't restrict people there! Make sure I'm admin and can punch users.",
- )
- return
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user")
- return
- raise
-
- if is_user_ban_protected(chat, user_id, member):
- message.reply_text("I really wish I could punch admins...")
- return
-
- if user_id == bot.id:
- message.reply_text("I'm not gonna punch myself, are you crazy?")
- return
-
- try:
- chat.unban_member(user_id)
- message.reply_text("Punched from chat!")
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text("Punched!", quote=False)
- elif excp.message in RKICK_ERRORS:
- message.reply_text(excp.message)
- else:
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR punching user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't punch that user.")
-
-
-@Exoncmd(command="rmute")
-@bot_admin
-def rmute(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
-
- if not args:
- message.reply_text("You don't seem to be referring to a chat/user.")
- return
-
- user_id, chat_id = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
- if not chat_id:
- message.reply_text("You don't seem to be referring to a chat.")
- return
-
- try:
- chat = bot.get_chat(chat_id.split()[0])
- except BadRequest as excp:
- if excp.message == "Chat not found":
- message.reply_text(
- "Chat not found! Make sure you entered a valid chat ID and I'm part of that chat.",
- )
- return
- raise
-
- if chat.type == "private":
- message.reply_text("I'm sorry, but that's a private chat!")
- return
-
- if (
- not is_bot_admin(chat, bot.id)
- or not chat.get_member(bot.id).can_restrict_members
- ):
- message.reply_text(
- "I can't restrict people there! Make sure I'm admin and can mute users.",
- )
- return
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user")
- return
- raise
-
- if is_user_ban_protected(chat, user_id, member):
- message.reply_text("I really wish I could mute admins...")
- return
-
- if user_id == bot.id:
- message.reply_text("I'm not gonna MUTE myself, are you crazy?")
- return
-
- try:
- bot.restrict_chat_member(
- chat.id,
- user_id,
- permissions=ChatPermissions(can_send_messages=False),
- )
- message.reply_text("Muted from the chat!")
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text("Muted!", quote=False)
- elif excp.message in RMUTE_ERRORS:
- message.reply_text(excp.message)
- else:
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR mute user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't mute that user.")
-
-
-@Exoncmd(command="runmute")
-@bot_admin
-def runmute(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
-
- if not args:
- message.reply_text("You don't seem to be referring to a chat/user.")
- return
-
- user_id, chat_id = extract_user_and_text(message, args)
-
- if not user_id:
- message.reply_text(
- "You don't seem to be referring to a user or the ID specified is incorrect..",
- )
- return
- if not chat_id:
- message.reply_text("You don't seem to be referring to a chat.")
- return
-
- try:
- chat = bot.get_chat(chat_id.split()[0])
- except BadRequest as excp:
- if excp.message == "Chat not found":
- message.reply_text(
- "Chat not found! Make sure you entered a valid chat ID and I'm part of that chat.",
- )
- return
- raise
-
- if chat.type == "private":
- message.reply_text("I'm sorry, but that's a private chat!")
- return
-
- if (
- not is_bot_admin(chat, bot.id)
- or not chat.get_member(bot.id).can_restrict_members
- ):
- message.reply_text(
- "I can't unrestrict people there! Make sure I'm admin and can unban users.",
- )
- return
-
- try:
- member = chat.get_member(user_id)
- except BadRequest as excp:
- if excp.message == "User not found":
- message.reply_text("I can't seem to find this user there")
- return
- raise
-
- if is_user_in_chat(chat, user_id) and (
- member.can_send_messages
- and member.can_send_media_messages
- and member.can_send_other_messages
- and member.can_add_web_page_previews
- ):
- message.reply_text("This user already has the right to speak in that chat.")
- return
-
- if user_id == bot.id:
- message.reply_text("I'm not gonna UNMUTE myself, I'm an admin there!")
- return
-
- try:
- bot.restrict_chat_member(
- chat.id,
- int(user_id),
- permissions=ChatPermissions(
- can_send_messages=True,
- can_send_media_messages=True,
- can_send_other_messages=True,
- can_add_web_page_previews=True,
- ),
- )
- message.reply_text("Yep, this user can talk in that chat!")
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text("Unmuted!", quote=False)
- elif excp.message in RUNMUTE_ERRORS:
- message.reply_text(excp.message)
- else:
- LOGGER.warning(update)
- LOGGER.exception(
- "ERROR unmnuting user %s in chat %s (%s) due to %s",
- user_id,
- chat.title,
- chat.id,
- excp.message,
- )
- message.reply_text("Well damn, I can't unmute that user.")
-
-
-@Exoncmd(command="recho")
-@dev_plus
-def recho(update: Update, context: CallbackContext):
- bot = context.bot
- args = context.args
- message = update.effective_message
- try:
- chat_id = str(args[0])
- del args[0]
- except TypeError:
- message.reply_text("Please give me a chat ID.")
- to_send = " ".join(args)
- if len(to_send) >= 2:
- try:
- bot.sendMessage(int(chat_id), to_send)
- except TelegramError:
- message.reply_text(
- "Couldn't send the message. Perhaps I'm not part of that group?"
- )
-
-
-__mod_name__ = "𝐑-ᴄᴍᴅs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "rcmds_help")
-
-# """
diff --git a/Exon/modules/repo.py b/Exon/modules/repo.py
deleted file mode 100644
index 696e3ee3..00000000
--- a/Exon/modules/repo.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# MY ALL BOTS :- Abishnoi_bots
-# GITHUB :- KingAbishnoi ""
-
-from platform import python_version as y
-
-from pyrogram import __version__ as z
-from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
-from telegram import __version__ as o
-from telethon import __version__ as s
-
-from Exon import Abishnoi as pbot
-
-ABISHNOIX = "https://te.legra.ph/file/abfc49a1cc4b5629dc8cd.jpg"
-
-
-@pbot.on_cmd("repo")
-async def repo(_, message):
- await message.reply_photo(
- photo=ABISHNOIX,
- caption=f"""✨ **ʜᴇʏ {message.from_user.mention},**
-
-**ᴏᴡɴᴇʀ : [𝐀ʙɪꜱʜɴᴏɪ](https://t.me/AshokShau)**
-**ᴘʏᴛʜᴏɴ ᴠᴇʀꜱɪᴏɴ :** `{y()}`
-**ʟɪʙʀᴀʀʏ ᴠᴇʀꜱɪᴏɴ :** `{o}`
-**ᴛᴇʟᴇᴛʜᴏɴ ᴠᴇʀꜱɪᴏɴ :** `{s}`
-**ᴘʏʀᴏɢʀᴀᴍ ᴠᴇʀꜱɪᴏɴ :** `{z}`
-""",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- "•ᴍᴜꜱɪᴄ•", url="https://github.com/AshokShau/AsuXMusic"
- ),
- InlineKeyboardButton(
- "•ʀᴏʙᴏᴠ1•", url="https://github.com/AshokShau/ExonRobot"
- ),
- ]
- ]
- ),
- )
diff --git a/Exon/modules/reporting.py b/Exon/modules/reporting.py
deleted file mode 100644
index 5c13f10c..00000000
--- a/Exon/modules/reporting.py
+++ /dev/null
@@ -1,292 +0,0 @@
-import html
-
-from telegram import Chat, InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.error import BadRequest, Unauthorized
-from telegram.ext import CallbackContext, Filters
-from telegram.utils.helpers import mention_html
-
-import Exon.modules.sql.log_channel_sql as logsql
-from Exon import DRAGONS, LOGGER, TIGERS, WOLVES
-from Exon.modules.helper_funcs.chat_status import user_not_admin
-from Exon.modules.helper_funcs.decorators import Exoncallback, Exoncmd, Exonmsg
-from Exon.modules.log_channel import loggable
-from Exon.modules.sql import reporting_sql as sql
-from ..modules.helper_funcs.anonymous import AdminPerms, user_admin
-
-REPORT_GROUP = 12
-REPORT_IMMUNE_USERS = DRAGONS + TIGERS + WOLVES
-
-
-@Exoncmd(command="reports")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-def report_setting(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- chat = update.effective_chat
- msg = update.effective_message
-
- if chat.type == chat.PRIVATE:
- if len(args) >= 1:
- if args[0] in ("yes", "on"):
- sql.set_user_setting(chat.id, True)
- msg.reply_text(
- "ᴛᴜʀɴᴇᴅ ᴏɴ ʀᴇᴘᴏʀᴛɪɴɢ! ʏᴏᴜ'ʟʟ ʙᴇ ɴᴏᴛɪꜰɪᴇᴅ ᴡʜᴇɴᴇᴠᴇʀ ᴀɴʏᴏɴᴇ ʀᴇᴘᴏʀᴛꜱ ꜱᴏᴍᴇᴛʜɪɴɢ.",
- )
-
- elif args[0] in ("no", "off"):
- sql.set_user_setting(chat.id, False)
- msg.reply_text("ᴛᴜʀɴᴇᴅ ᴏꜰꜰ ʀᴇᴘᴏʀᴛɪɴɢ! ʏᴏᴜ ᴡᴏɴᴛ ɢᴇᴛ ᴀɴʏ ʀᴇᴘᴏʀᴛꜱ.")
- else:
- msg.reply_text(
- f"Your current report preference is: `{sql.user_should_report(chat.id)}`",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- elif len(args) >= 1:
- if args[0] in ("yes", "on"):
- sql.set_chat_setting(chat.id, True)
- msg.reply_text(
- "ᴛᴜʀɴᴇᴅ ᴏɴ ʀᴇᴘᴏʀᴛɪɴɢ! ᴀᴅᴍɪɴꜱ ᴡʜᴏ ʜᴀᴠᴇ ᴛᴜʀɴᴇᴅ ᴏɴ ʀᴇᴘᴏʀᴛꜱ ᴡɪʟʟ ʙᴇ ɴᴏᴛɪꜰɪᴇᴅ ᴡʜᴇɴ /report "
- "ᴏʀ @admin ɪꜱ ᴄᴀʟʟᴇᴅ.",
- )
-
- elif args[0] in ("no", "off"):
- sql.set_chat_setting(chat.id, False)
- msg.reply_text(
- "ᴛᴜʀɴᴇᴅ ᴏꜰꜰ ʀᴇᴘᴏʀᴛɪɴɢ! ɴᴏ ᴀᴅᴍɪɴꜱ ᴡɪʟʟʟ ʙᴇ ɴᴏᴛɪꜰɪᴇᴅ ᴏɴ /report ᴏʀ @admin.",
- )
- else:
- msg.reply_text(
- f"ᴛʜɪꜱ ɢʀᴏᴜᴘ'ꜱ ᴄᴜʀʀᴇɴᴛ ꜱᴇᴛᴛɪɴɢ ɪꜱ : `{sql.chat_should_report(chat.id)}`",
- parse_mode=ParseMode.MARKDOWN,
- )
-
-
-@Exoncmd(command="report", filters=Filters.chat_type.groups, group=REPORT_GROUP)
-@Exonmsg((Filters.regex(r"(?i)@admin(s)?")), group=REPORT_GROUP)
-@user_not_admin
-@loggable
-def report(update: Update, context: CallbackContext) -> str:
- # sourcery no-metrics
- global reply_markup
- bot = context.bot
- args = context.args
- message = update.effective_message
- chat = update.effective_chat
- user = update.effective_user
-
- if message.sender_chat:
- admin_list = bot.getChatAdministrators(chat.id)
- reported = "ʀᴇᴘᴏʀᴛᴇᴅ ᴛᴏ ᴀᴅᴍɪɴs."
- for admin in admin_list:
- if admin.user.is_bot: # AI didnt take over yet
- continue
- try:
- reported += f'\u2063'
- except BadRequest:
- log.exception("ᴇxᴄᴇᴘᴛɪᴏɴ ᴡʜɪʟᴇ ʀᴇᴘᴏʀᴛɪɴɢ ᴜsᴇʀ")
- message.reply_text(reported, parse_mode=ParseMode.HTML)
-
- if chat and message.reply_to_message and sql.chat_should_report(chat.id):
- reported_user = message.reply_to_message.from_user
- chat_name = chat.title or chat.username
- admin_list = chat.get_administrators()
- message = update.effective_message
-
- if not args:
- message.reply_text("ᴀᴅᴅ ᴀ ʀᴇᴀꜱᴏɴ ꜰᴏʀ ʀᴇᴘᴏʀᴛɪɴɢ.")
- return ""
-
- if user.id == reported_user.id:
- message.reply_text("ᴜʜ ʏᴇᴀʜ, ꜱᴜʀᴇ ꜱᴜʀᴇ...ᴍᴀꜱᴏ ᴍᴜᴄʜ?")
- return ""
-
- if user.id == bot.id:
- message.reply_text("ɴɪᴄᴇ ᴛʀʏ.")
- return ""
-
- if reported_user.id in REPORT_IMMUNE_USERS:
- message.reply_text("ᴜʜ? ʏᴏᴜ ʀᴇᴘᴏʀᴛɪɴɢ ᴀ ᴅɪꜱᴀꜱᴛᴇʀ?")
- return ""
-
- if chat.username and chat.type == Chat.SUPERGROUP:
- reported = f"{mention_html(user.id, user.first_name)} reported {mention_html(reported_user.id, reported_user.first_name)} to the admins!"
-
- msg = (
- f"⚠️ ʀᴇᴘᴏʀᴛ: {html.escape(chat.title)}\n"
- f" • ʀᴇᴘᴏʀᴛ ʙʏ: {mention_html(user.id, user.first_name)}({user.id}
)\n"
- f" • ʀᴇᴘᴏʀᴛ ᴜꜱᴇʀ: {mention_html(reported_user.id, reported_user.first_name)} ({reported_user.id}
)\n"
- )
- link = f' • ʀᴇᴘᴏʀᴛᴇᴅ ᴍᴇꜱꜱᴀɢᴇ: click here'
- should_forward = False
- keyboard = [
- [
- InlineKeyboardButton(
- "➡ ᴍᴇꜱꜱᴀɢᴇ",
- url=f"https://t.me/{chat.username}/{message.reply_to_message.message_id}",
- ),
- ],
- [
- InlineKeyboardButton(
- "⚠ ᴋɪᴄᴋ",
- callback_data=f"report_{chat.id}=kick={reported_user.id}={reported_user.first_name}",
- ),
- InlineKeyboardButton(
- "⛔️ ʙᴀɴ",
- callback_data=f"report_{chat.id}=banned={reported_user.id}={reported_user.first_name}",
- ),
- ],
- [
- InlineKeyboardButton(
- "❎ ᴅᴇʟᴇᴛᴇ ᴍᴇꜱꜱᴀɢᴇ",
- callback_data=f"report_{chat.id}=delete={reported_user.id}={message.reply_to_message.message_id}",
- ),
- ],
- ]
- reply_markup = InlineKeyboardMarkup(keyboard)
- else:
- reported = (
- f"{mention_html(user.id, user.first_name)} ʀᴇᴘᴏʀᴛᴇᴅ "
- f"{mention_html(reported_user.id, reported_user.first_name)} ᴛᴏ ᴛʜᴇ ᴀᴅᴍɪɴꜱ!"
- )
-
- msg = f'{mention_html(user.id, user.first_name)} ɪꜱ ᴄᴀʟʟɪɴɢ ꜰᴏʀ ᴀᴅᴍɪɴꜱ ɪɴ "{html.escape(chat_name)}"!'
- link = ""
- should_forward = True
-
- for admin in admin_list:
- if admin.user.is_bot: # can't message bots
- continue
-
- if sql.user_should_report(admin.user.id):
- try:
- if chat.type != Chat.SUPERGROUP:
- bot.send_message(
- admin.user.id,
- msg + link,
- parse_mode=ParseMode.HTML,
- )
-
- if should_forward:
- message.reply_to_message.forward(admin.user.id)
-
- if (
- len(message.text.split()) > 1
- ): # If user is giving a reason, send his message too
- message.forward(admin.user.id)
- if not chat.username:
- bot.send_message(
- admin.user.id,
- msg + link,
- parse_mode=ParseMode.HTML,
- )
-
- if should_forward:
- message.reply_to_message.forward(admin.user.id)
-
- if (
- len(message.text.split()) > 1
- ): # If user is giving a reason, send his message too
- message.forward(admin.user.id)
-
- if chat.username and chat.type == Chat.SUPERGROUP:
- bot.send_message(
- admin.user.id,
- msg + link,
- parse_mode=ParseMode.HTML,
- reply_markup=reply_markup,
- )
-
- if should_forward:
- message.reply_to_message.forward(admin.user.id)
-
- if (
- len(message.text.split()) > 1
- ): # If user is giving a reason, send his message too
- message.forward(admin.user.id)
-
- except Unauthorized:
- pass
- except BadRequest as excp: # TODO: cleanup exceptions
- LOGGER.exception(f"ᴇxᴄᴇᴘᴛɪᴏɴ ᴡʜɪʟᴇ ʀᴇᴘᴏʀᴛɪɴɢ ᴜꜱᴇʀ\n{excp}")
-
- message.reply_to_message.reply_text(
- f"{mention_html(user.id, user.first_name)} ʀᴇᴘᴏʀᴛᴇᴅ ᴛʜᴇ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴛʜᴇ ᴀᴅᴍɪɴꜱ.",
- parse_mode=ParseMode.HTML,
- )
- return msg if logsql.get_chat_setting(chat.id).log_report else ""
- return ""
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, _):
- return f"ᴛʜɪs ᴄʜᴀᴛ ɪs sᴇᴛᴜᴘ ᴛᴏ sᴇɴᴅ ᴜsᴇʀ ʀᴇᴘᴏʀᴛs ᴛᴏ ᴀᴅᴍɪɴs, ᴠɪᴀ /report ᴀɴᴅ @admin: `{sql.chat_should_report(chat_id)}`"
-
-
-def __user_settings__(user_id):
- return (
- "ʏᴏᴜ ᴡɪʟʟ ʀᴇᴄᴇɪᴠᴇ ʀᴇᴘᴏʀᴛᴀ ꜰʀᴏᴍ ᴄʜᴀᴛꜱ ʏᴏᴜ'ʀᴇ ᴀᴅᴍɪɴ."
- if sql.user_should_report(user_id) is True
- else "ʏᴏᴜ ᴡɪʟʟ *ɴᴏᴛ* ʀᴇᴄᴇɪᴠᴇ ʀᴇᴘᴏʀᴛꜱ ꜰʀᴏᴍ ᴄʜᴀᴛꜱ ʏᴏᴜ'ʀᴇ ᴀᴅᴍɪɴ."
- )
-
-
-@Exoncallback(pattern=r"report_")
-def buttons(update: Update, context: CallbackContext):
- bot = context.bot
- query = update.callback_query
- splitter = query.data.replace("report_", "").split("=")
- if splitter[1] == "kick":
- try:
- bot.kickChatMember(splitter[0], splitter[2])
- bot.unbanChatMember(splitter[0], splitter[2])
- query.answer("✅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ᴋɪᴄᴋᴇᴅ")
- return ""
- except Exception as err:
- query.answer("🛑 ꜰᴀɪʟᴇᴅ ᴛᴏ ᴋɪᴄᴋ")
- bot.sendMessage(
- text=f"Error: {err}",
- chat_id=query.message.chat_id,
- parse_mode=ParseMode.HTML,
- )
- elif splitter[1] == "banned":
- try:
- bot.kickChatMember(splitter[0], splitter[2])
- query.answer("✅ ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ʙᴀɴᴇᴅ")
- return ""
- except Exception as err:
- bot.sendMessage(
- text=f"Error: {err}",
- chat_id=query.message.chat_id,
- parse_mode=ParseMode.HTML,
- )
- query.answer("🛑 ꜰᴀɪʟᴇᴅ ᴛᴏ ʙᴀɴ")
- elif splitter[1] == "delete":
- try:
- bot.deleteMessage(splitter[0], splitter[3])
- query.answer("✅ ᴍᴇꜱꜱᴀɢᴇ ᴅᴇʟᴇᴛᴇᴅ")
- return ""
- except Exception as err:
- bot.sendMessage(
- text=f"Error: {err}",
- chat_id=query.message.chat_id,
- parse_mode=ParseMode.HTML,
- )
- query.answer("🛑 ꜰᴀɪʟᴇᴅ ᴛᴏ ᴅᴇʟᴇᴛᴇ ᴍᴇꜱꜱᴀɢᴇ!")
-
-
-__mod_name__ = "𝐑ᴇᴘᴏʀᴛ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "reports_help")
-
-# """
diff --git a/Exon/modules/resources/asu.ttf b/Exon/modules/resources/asu.ttf
deleted file mode 100644
index 4746c268..00000000
Binary files a/Exon/modules/resources/asu.ttf and /dev/null differ
diff --git a/Exon/modules/resources/fonts.py b/Exon/modules/resources/fonts.py
deleted file mode 100644
index f025b963..00000000
--- a/Exon/modules/resources/fonts.py
+++ /dev/null
@@ -1,2392 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# TG :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-
-class Fonts:
- def typewriter(self):
- style = {
- "a": "𝚊",
- "b": "𝚋",
- "c": "𝚌",
- "d": "𝚍",
- "e": "𝚎",
- "f": "𝚏",
- "g": "𝚐",
- "h": "𝚑",
- "i": "𝚒",
- "j": "𝚓",
- "k": "𝚔",
- "l": "𝚕",
- "m": "𝚖",
- "n": "𝚗",
- "o": "𝚘",
- "p": "𝚙",
- "q": "𝚚",
- "r": "𝚛",
- "s": "𝚜",
- "t": "𝚝",
- "u": "𝚞",
- "v": "𝚟",
- "w": "𝚠",
- "x": "𝚡",
- "y": "𝚢",
- "z": "𝚣",
- "A": "𝙰",
- "B": "𝙱",
- "C": "𝙲",
- "D": "𝙳",
- "E": "𝙴",
- "F": "𝙵",
- "G": "𝙶",
- "H": "𝙷",
- "I": "𝙸",
- "J": "𝙹",
- "K": "𝙺",
- "L": "𝙻",
- "M": "𝙼",
- "N": "𝙽",
- "O": "𝙾",
- "P": "𝙿",
- "Q": "𝚀",
- "R": "𝚁",
- "S": "𝚂",
- "T": "𝚃",
- "U": "𝚄",
- "V": "𝚅",
- "W": "𝚆",
- "X": "𝚇",
- "Y": "𝚈",
- "Z": "𝚉",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def outline(self):
- style = {
- "a": "𝕒",
- "b": "𝕓",
- "c": "𝕔",
- "d": "𝕕",
- "e": "𝕖",
- "f": "𝕗",
- "g": "𝕘",
- "h": "𝕙",
- "i": "𝕚",
- "j": "𝕛",
- "k": "𝕜",
- "l": "𝕝",
- "m": "𝕞",
- "n": "𝕟",
- "o": "𝕠",
- "p": "𝕡",
- "q": "𝕢",
- "r": "𝕣",
- "s": "𝕤",
- "t": "𝕥",
- "u": "𝕦",
- "v": "𝕧",
- "w": "𝕨",
- "x": "𝕩",
- "y": "𝕪",
- "z": "𝕫",
- "A": "𝔸",
- "B": "𝔹",
- "C": "ℂ",
- "D": "𝔻",
- "E": "𝔼",
- "F": "𝔽",
- "G": "𝔾",
- "H": "ℍ",
- "I": "𝕀",
- "J": "𝕁",
- "K": "𝕂",
- "L": "𝕃",
- "M": "𝕄",
- "N": "ℕ",
- "O": "𝕆",
- "P": "ℙ",
- "Q": "ℚ",
- "R": "ℝ",
- "S": "𝕊",
- "T": "𝕋",
- "U": "𝕌",
- "V": "𝕍",
- "W": "𝕎",
- "X": "𝕏",
- "Y": "𝕐",
- "Z": "ℤ",
- "0": "𝟘",
- "1": "𝟙",
- "2": "𝟚",
- "3": "𝟛",
- "4": "𝟜",
- "5": "𝟝",
- "6": "𝟞",
- "7": "𝟟",
- "8": "𝟠",
- "9": "𝟡",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def serief(self):
- style = {
- "a": "𝐚",
- "b": "𝐛",
- "c": "𝐜",
- "d": "𝐝",
- "e": "𝐞",
- "f": "𝐟",
- "g": "𝐠",
- "h": "𝐡",
- "i": "𝐢",
- "j": "𝐣",
- "k": "𝐤",
- "l": "𝐥",
- "m": "𝐦",
- "n": "𝐧",
- "o": "𝐨",
- "p": "𝐩",
- "q": "𝐪",
- "r": "𝐫",
- "s": "𝐬",
- "t": "𝐭",
- "u": "𝐮",
- "v": "𝐯",
- "w": "𝐰",
- "x": "𝐱",
- "y": "𝐲",
- "z": "𝐳",
- "A": "𝐀",
- "B": "𝐁",
- "C": "𝐂",
- "D": "𝐃",
- "E": "𝐄",
- "F": "𝐅",
- "G": "𝐆",
- "H": "𝐇",
- "I": "𝐈",
- "J": "𝐉",
- "K": "𝐊",
- "L": "𝐋",
- "M": "𝐌",
- "N": "𝐍",
- "O": "𝐎",
- "P": "𝐏",
- "Q": "𝐐",
- "R": "𝐑",
- "S": "𝐒",
- "T": "𝐓",
- "U": "𝐔",
- "V": "𝐕",
- "W": "𝐖",
- "X": "𝐗",
- "Y": "𝐘",
- "Z": "𝐙",
- "0": "𝟎",
- "1": "𝟏",
- "2": "𝟐",
- "3": "𝟑",
- "4": "𝟒",
- "5": "𝟓",
- "6": "𝟔",
- "7": "𝟕",
- "8": "𝟖",
- "9": "𝟗",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def bold_cool(self):
- style = {
- "a": "𝒂",
- "b": "𝒃",
- "c": "𝒄",
- "d": "𝒅",
- "e": "𝒆",
- "f": "𝒇",
- "g": "𝒈",
- "h": "𝒉",
- "i": "𝒊",
- "j": "𝒋",
- "k": "𝒌",
- "l": "𝒍",
- "m": "𝒎",
- "n": "𝒏",
- "o": "𝒐",
- "p": "𝒑",
- "q": "𝒒",
- "r": "𝒓",
- "s": "𝒔",
- "t": "𝒕",
- "u": "𝒖",
- "v": "𝒗",
- "w": "𝒘",
- "x": "𝒙",
- "y": "𝒚",
- "z": "𝒛",
- "A": "𝑨",
- "B": "𝑩",
- "C": "𝑪",
- "D": "𝑫",
- "E": "𝑬",
- "F": "𝑭",
- "G": "𝑮",
- "H": "𝑯",
- "I": "𝑰",
- "J": "𝑱",
- "K": "𝑲",
- "L": "𝑳",
- "M": "𝑴",
- "N": "𝑵",
- "O": "𝑶",
- "P": "𝑷",
- "Q": "𝑸",
- "R": "𝑹",
- "S": "𝑺",
- "T": "𝑻",
- "U": "𝑼",
- "V": "𝑽",
- "W": "𝑾",
- "X": "𝑿",
- "Y": "𝒀",
- "Z": "𝒁",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def cool(self):
- style = {
- "a": "𝑎",
- "b": "𝑏",
- "c": "𝑐",
- "d": "𝑑",
- "e": "𝑒",
- "f": "𝑓",
- "g": "𝑔",
- "h": "ℎ",
- "i": "𝑖",
- "j": "𝑗",
- "k": "𝑘",
- "l": "𝑙",
- "m": "𝑚",
- "n": "𝑛",
- "o": "𝑜",
- "p": "𝑝",
- "q": "𝑞",
- "r": "𝑟",
- "s": "𝑠",
- "t": "𝑡",
- "u": "𝑢",
- "v": "𝑣",
- "w": "𝑤",
- "x": "𝑥",
- "y": "𝑦",
- "z": "𝑧",
- "A": "𝐴",
- "B": "𝐵",
- "C": "𝐶",
- "D": "𝐷",
- "E": "𝐸",
- "F": "𝐹",
- "G": "𝐺",
- "H": "𝐻",
- "I": "𝐼",
- "J": "𝐽",
- "K": "𝐾",
- "L": "𝐿",
- "M": "𝑀",
- "N": "𝑁",
- "O": "𝑂",
- "P": "𝑃",
- "Q": "𝑄",
- "R": "𝑅",
- "S": "𝑆",
- "T": "𝑇",
- "U": "𝑈",
- "V": "𝑉",
- "W": "𝑊",
- "X": "𝑋",
- "Y": "𝑌",
- "Z": "𝑍",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def smallcap(self):
- style = {
- "a": "ᴀ",
- "b": "ʙ",
- "c": "ᴄ",
- "d": "ᴅ",
- "e": "ᴇ",
- "f": "ғ",
- "g": "ɢ",
- "h": "ʜ",
- "i": "ɪ",
- "j": "J",
- "k": "ᴋ",
- "l": "ʟ",
- "m": "ᴍ",
- "n": "ɴ",
- "o": "ᴏ",
- "p": "ᴘ",
- "q": "ǫ",
- "r": "ʀ",
- "s": "s",
- "t": "ᴛ",
- "u": "ᴜ",
- "v": "ᴠ",
- "w": "ᴡ",
- "x": "x",
- "y": "ʏ",
- "z": "ᴢ",
- "A": "A",
- "B": "B",
- "C": "C",
- "D": "D",
- "E": "E",
- "F": "F",
- "G": "G",
- "H": "H",
- "I": "I",
- "J": "J",
- "K": "K",
- "L": "L",
- "M": "M",
- "N": "N",
- "O": "O",
- "P": "P",
- "Q": "Q",
- "R": "R",
- "S": "S",
- "T": "T",
- "U": "U",
- "V": "V",
- "W": "W",
- "X": "X",
- "Y": "Y",
- "Z": "Z",
- "0": "𝟶",
- "1": "𝟷",
- "2": "𝟸",
- "3": "𝟹",
- "4": "𝟺",
- "5": "𝟻",
- "6": "𝟼",
- "7": "𝟽",
- "8": "𝟾",
- "9": "𝟿",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def script(self):
- style = {
- "a": "𝒶",
- "b": "𝒷",
- "c": "𝒸",
- "d": "𝒹",
- "e": "ℯ",
- "f": "𝒻",
- "g": "ℊ",
- "h": "𝒽",
- "i": "𝒾",
- "j": "𝒿",
- "k": "𝓀",
- "l": "𝓁",
- "m": "𝓂",
- "n": "𝓃",
- "o": "ℴ",
- "p": "𝓅",
- "q": "𝓆",
- "r": "𝓇",
- "s": "𝓈",
- "t": "𝓉",
- "u": "𝓊",
- "v": "𝓋",
- "w": "𝓌",
- "x": "𝓍",
- "y": "𝓎",
- "z": "𝓏",
- "A": "𝒜",
- "B": "ℬ",
- "C": "𝒞",
- "D": "𝒟",
- "E": "ℰ",
- "F": "ℱ",
- "G": "𝒢",
- "H": "ℋ",
- "I": "ℐ",
- "J": "𝒥",
- "K": "𝒦",
- "L": "ℒ",
- "M": "ℳ",
- "N": "𝒩",
- "O": "𝒪",
- "P": "𝒫",
- "Q": "𝒬",
- "R": "ℛ",
- "S": "𝒮",
- "T": "𝒯",
- "U": "𝒰",
- "V": "𝒱",
- "W": "𝒲",
- "X": "𝒳",
- "Y": "𝒴",
- "Z": "𝒵",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def bold_script(self):
- style = {
- "a": "𝓪",
- "b": "𝓫",
- "c": "𝓬",
- "d": "𝓭",
- "e": "𝓮",
- "f": "𝓯",
- "g": "𝓰",
- "h": "𝓱",
- "i": "𝓲",
- "j": "𝓳",
- "k": "𝓴",
- "l": "𝓵",
- "m": "𝓶",
- "n": "𝓷",
- "o": "𝓸",
- "p": "𝓹",
- "q": "𝓺",
- "r": "𝓻",
- "s": "𝓼",
- "t": "𝓽",
- "u": "𝓾",
- "v": "𝓿",
- "w": "𝔀",
- "x": "𝔁",
- "y": "𝔂",
- "z": "𝔃",
- "A": "𝓐",
- "B": "𝓑",
- "C": "𝓒",
- "D": "𝓓",
- "E": "𝓔",
- "F": "𝓕",
- "G": "𝓖",
- "H": "𝓗",
- "I": "𝓘",
- "J": "𝓙",
- "K": "𝓚",
- "L": "𝓛",
- "M": "𝓜",
- "N": "𝓝",
- "O": "𝓞",
- "P": "𝓟",
- "Q": "𝓠",
- "R": "𝓡",
- "S": "𝓢",
- "T": "𝓣",
- "U": "𝓤",
- "V": "𝓥",
- "W": "𝓦",
- "X": "𝓧",
- "Y": "𝓨",
- "Z": "𝓩",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def tiny(self):
- style = {
- "a": "ᵃ",
- "b": "ᵇ",
- "c": "ᶜ",
- "d": "ᵈ",
- "e": "ᵉ",
- "f": "ᶠ",
- "g": "ᵍ",
- "h": "ʰ",
- "i": "ⁱ",
- "j": "ʲ",
- "k": "ᵏ",
- "l": "ˡ",
- "m": "ᵐ",
- "n": "ⁿ",
- "o": "ᵒ",
- "p": "ᵖ",
- "q": "ᵠ",
- "r": "ʳ",
- "s": "ˢ",
- "t": "ᵗ",
- "u": "ᵘ",
- "v": "ᵛ",
- "w": "ʷ",
- "x": "ˣ",
- "y": "ʸ",
- "z": "ᶻ",
- "A": "ᵃ",
- "B": "ᵇ",
- "C": "ᶜ",
- "D": "ᵈ",
- "E": "ᵉ",
- "F": "ᶠ",
- "G": "ᵍ",
- "H": "ʰ",
- "I": "ⁱ",
- "J": "ʲ",
- "K": "ᵏ",
- "L": "ˡ",
- "M": "ᵐ",
- "N": "ⁿ",
- "O": "ᵒ",
- "P": "ᵖ",
- "Q": "ᵠ",
- "R": "ʳ",
- "S": "ˢ",
- "T": "ᵗ",
- "U": "ᵘ",
- "V": "ᵛ",
- "W": "ʷ",
- "X": "ˣ",
- "Y": "ʸ",
- "Z": "ᶻ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def comic(self):
- style = {
- "a": "ᗩ",
- "b": "ᗷ",
- "c": "ᑕ",
- "d": "ᗪ",
- "e": "ᗴ",
- "f": "ᖴ",
- "g": "ᘜ",
- "h": "ᕼ",
- "i": "I",
- "j": "ᒍ",
- "k": "K",
- "l": "ᒪ",
- "m": "ᗰ",
- "n": "ᑎ",
- "o": "O",
- "p": "ᑭ",
- "q": "ᑫ",
- "r": "ᖇ",
- "s": "Տ",
- "t": "T",
- "u": "ᑌ",
- "v": "ᐯ",
- "w": "ᗯ",
- "x": "᙭",
- "y": "Y",
- "z": "ᘔ",
- "A": "ᗩ",
- "B": "ᗷ",
- "C": "ᑕ",
- "D": "ᗪ",
- "E": "ᗴ",
- "F": "ᖴ",
- "G": "ᘜ",
- "H": "ᕼ",
- "I": "I",
- "J": "ᒍ",
- "K": "K",
- "L": "ᒪ",
- "M": "ᗰ",
- "N": "ᑎ",
- "O": "O",
- "P": "ᑭ",
- "Q": "ᑫ",
- "R": "ᖇ",
- "S": "Տ",
- "T": "T",
- "U": "ᑌ",
- "V": "ᐯ",
- "W": "ᗯ",
- "X": "᙭",
- "Y": "Y",
- "Z": "ᘔ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def san(self):
- style = {
- "a": "𝗮",
- "b": "𝗯",
- "c": "𝗰",
- "d": "𝗱",
- "e": "𝗲",
- "f": "𝗳",
- "g": "𝗴",
- "h": "𝗵",
- "i": "𝗶",
- "j": "𝗷",
- "k": "𝗸",
- "l": "𝗹",
- "m": "𝗺",
- "n": "𝗻",
- "o": "𝗼",
- "p": "𝗽",
- "q": "𝗾",
- "r": "𝗿",
- "s": "𝘀",
- "t": "𝘁",
- "u": "𝘂",
- "v": "𝘃",
- "w": "𝘄",
- "x": "𝘅",
- "y": "𝘆",
- "z": "𝘇",
- "A": "𝗔",
- "B": "𝗕",
- "C": "𝗖",
- "D": "𝗗",
- "E": "𝗘",
- "F": "𝗙",
- "G": "𝗚",
- "H": "𝗛",
- "I": "𝗜",
- "J": "𝗝",
- "K": "𝗞",
- "L": "𝗟",
- "M": "𝗠",
- "N": "𝗡",
- "O": "𝗢",
- "P": "𝗣",
- "Q": "𝗤",
- "R": "𝗥",
- "S": "𝗦",
- "T": "𝗧",
- "U": "𝗨",
- "V": "𝗩",
- "W": "𝗪",
- "X": "𝗫",
- "Y": "𝗬",
- "Z": "𝗭",
- "0": "𝟬",
- "1": "𝟭",
- "2": "𝟮",
- "3": "𝟯",
- "4": "𝟰",
- "5": "𝟱",
- "6": "𝟲",
- "7": "𝟳",
- "8": "𝟴",
- "9": "𝟵",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def slant_san(self):
- style = {
- "a": "𝙖",
- "b": "𝙗",
- "c": "𝙘",
- "d": "𝙙",
- "e": "𝙚",
- "f": "𝙛",
- "g": "𝙜",
- "h": "𝙝",
- "i": "𝙞",
- "j": "𝙟",
- "k": "𝙠",
- "l": "𝙡",
- "m": "𝙢",
- "n": "𝙣",
- "o": "𝙤",
- "p": "𝙥",
- "q": "𝙦",
- "r": "𝙧",
- "s": "𝙨",
- "t": "𝙩",
- "u": "𝙪",
- "v": "𝙫",
- "w": "𝙬",
- "x": "𝙭",
- "y": "𝙮",
- "z": "𝙯",
- "A": "𝘼",
- "B": "𝘽",
- "C": "𝘾",
- "D": "𝘿",
- "E": "𝙀",
- "F": "𝙁",
- "G": "𝙂",
- "H": "𝙃",
- "I": "𝙄",
- "J": "𝙅",
- "K": "𝙆",
- "L": "𝙇",
- "M": "𝙈",
- "N": "𝙉",
- "O": "𝙊",
- "P": "𝙋",
- "Q": "𝙌",
- "R": "𝙍",
- "S": "𝙎",
- "T": "𝙏",
- "U": "𝙐",
- "V": "𝙑",
- "W": "𝙒",
- "X": "𝙓",
- "Y": "𝙔",
- "Z": "𝙕",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def slant(self):
- style = {
- "a": "𝘢",
- "b": "𝘣",
- "c": "𝘤",
- "d": "𝘥",
- "e": "𝘦",
- "f": "𝘧",
- "g": "𝘨",
- "h": "𝘩",
- "i": "𝘪",
- "j": "𝘫",
- "k": "𝘬",
- "l": "𝘭",
- "m": "𝘮",
- "n": "𝘯",
- "o": "𝘰",
- "p": "𝘱",
- "q": "𝘲",
- "r": "𝘳",
- "s": "𝘴",
- "t": "𝘵",
- "u": "𝘶",
- "v": "𝘷",
- "w": "𝘸",
- "x": "𝘹",
- "y": "𝘺",
- "z": "𝘻",
- "A": "𝘈",
- "B": "𝘉",
- "C": "𝘊",
- "D": "𝘋",
- "E": "𝘌",
- "F": "𝘍",
- "G": "𝘎",
- "H": "𝘏",
- "I": "𝘐",
- "J": "𝘑",
- "K": "𝘒",
- "L": "𝘓",
- "M": "𝘔",
- "N": "𝘕",
- "O": "𝘖",
- "P": "𝘗",
- "Q": "𝘘",
- "R": "𝘙",
- "S": "𝘚",
- "T": "𝘛",
- "U": "𝘜",
- "V": "𝘝",
- "W": "𝘞",
- "X": "𝘟",
- "Y": "𝘠",
- "Z": "𝘡",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def sim(self):
- style = {
- "a": "𝖺",
- "b": "𝖻",
- "c": "𝖼",
- "d": "𝖽",
- "e": "𝖾",
- "f": "𝖿",
- "g": "𝗀",
- "h": "𝗁",
- "i": "𝗂",
- "j": "𝗃",
- "k": "𝗄",
- "l": "𝗅",
- "m": "𝗆",
- "n": "𝗇",
- "o": "𝗈",
- "p": "𝗉",
- "q": "𝗊",
- "r": "𝗋",
- "s": "𝗌",
- "t": "𝗍",
- "u": "𝗎",
- "v": "𝗏",
- "w": "𝗐",
- "x": "𝗑",
- "y": "𝗒",
- "z": "𝗓",
- "A": "𝖠",
- "B": "𝖡",
- "C": "𝖢",
- "D": "𝖣",
- "E": "𝖤",
- "F": "𝖥",
- "G": "𝖦",
- "H": "𝖧",
- "I": "𝖨",
- "J": "𝖩",
- "K": "𝖪",
- "L": "𝖫",
- "M": "𝖬",
- "N": "𝖭",
- "O": "𝖮",
- "P": "𝖯",
- "Q": "𝖰",
- "R": "𝖱",
- "S": "𝖲",
- "T": "𝖳",
- "U": "𝖴",
- "V": "𝖵",
- "W": "𝖶",
- "X": "𝖷",
- "Y": "𝖸",
- "Z": "𝖹",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def circles(self):
- style = {
- "a": "Ⓐ︎",
- "b": "Ⓑ︎",
- "c": "Ⓒ︎",
- "d": "Ⓓ︎",
- "e": "Ⓔ︎",
- "f": "Ⓕ︎",
- "g": "Ⓖ︎",
- "h": "Ⓗ︎",
- "i": "Ⓘ︎",
- "j": "Ⓙ︎",
- "k": "Ⓚ︎",
- "l": "Ⓛ︎",
- "m": "Ⓜ︎",
- "n": "Ⓝ︎",
- "o": "Ⓞ︎",
- "p": "Ⓟ︎",
- "q": "Ⓠ︎",
- "r": "Ⓡ︎",
- "s": "Ⓢ︎",
- "t": "Ⓣ︎",
- "u": "Ⓤ︎",
- "v": "Ⓥ︎",
- "w": "Ⓦ︎",
- "x": "Ⓧ︎",
- "y": "Ⓨ︎",
- "z": "Ⓩ︎",
- "A": "Ⓐ︎",
- "B": "Ⓑ︎",
- "C": "Ⓒ︎",
- "D": "Ⓓ︎",
- "E": "Ⓔ︎",
- "F": "Ⓕ︎",
- "G": "Ⓖ︎",
- "H": "Ⓗ︎",
- "I": "Ⓘ︎",
- "J": "Ⓙ︎",
- "K": "Ⓚ︎",
- "L": "Ⓛ︎",
- "M": "Ⓜ︎",
- "N": "Ⓝ︎",
- "O": "Ⓞ︎",
- "P": "Ⓟ︎",
- "Q": "Ⓠ︎",
- "R": "Ⓡ︎",
- "S": "Ⓢ︎",
- "T": "Ⓣ︎",
- "U": "Ⓤ︎",
- "V": "Ⓥ︎",
- "W": "Ⓦ︎",
- "X": "Ⓧ︎",
- "Y": "Ⓨ︎",
- "Z": "Ⓩ︎",
- "0": "⓪",
- "1": "①",
- "2": "②",
- "3": "③",
- "4": "④",
- "5": "⑤",
- "6": "⑥",
- "7": "⑦",
- "8": "⑧",
- "9": "⑨",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def dark_circle(self):
- style = {
- "a": "🅐︎",
- "b": "🅑︎",
- "c": "🅒︎",
- "d": "🅓︎",
- "e": "🅔︎",
- "f": "🅕︎",
- "g": "🅖︎",
- "h": "🅗︎",
- "i": "🅘︎",
- "j": "🅙︎",
- "k": "🅚︎",
- "l": "🅛︎",
- "m": "🅜︎",
- "n": "🅝︎",
- "o": "🅞︎",
- "p": "🅟︎",
- "q": "🅠︎",
- "r": "🅡︎",
- "s": "🅢︎",
- "t": "🅣︎",
- "u": "🅤︎",
- "v": "🅥︎",
- "w": "🅦︎",
- "x": "🅧︎",
- "y": "🅨︎",
- "z": "🅩︎",
- "A": "🅐︎",
- "B": "🅑︎",
- "C": "🅒︎",
- "D": "🅓︎",
- "E": "🅔︎",
- "F": "🅕︎",
- "G": "🅖︎",
- "H": "🅗︎",
- "I": "🅘︎",
- "J": "🅙︎",
- "K": "🅚︎",
- "L": "🅛︎",
- "M": "🅜︎",
- "N": "🅝︎",
- "O": "🅞︎",
- "P": "🅟︎",
- "Q": "🅠︎",
- "R": "🅡︎",
- "S": "🅢︎",
- "T": "🅣︎",
- "U": "🅤︎",
- "V": "🅥︎",
- "W": "🅦︎",
- "X": "🅧︎",
- "Y": "🅨︎",
- "Z": "🅩",
- "0": "⓿",
- "1": "➊",
- "2": "➋",
- "3": "➌",
- "4": "➍",
- "5": "➎",
- "6": "➏",
- "7": "➐",
- "8": "➑",
- "9": "➒",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def gothic(self):
- style = {
- "a": "𝔞",
- "b": "𝔟",
- "c": "𝔠",
- "d": "𝔡",
- "e": "𝔢",
- "f": "𝔣",
- "g": "𝔤",
- "h": "𝔥",
- "i": "𝔦",
- "j": "𝔧",
- "k": "𝔨",
- "l": "𝔩",
- "m": "𝔪",
- "n": "𝔫",
- "o": "𝔬",
- "p": "𝔭",
- "q": "𝔮",
- "r": "𝔯",
- "s": "𝔰",
- "t": "𝔱",
- "u": "𝔲",
- "v": "𝔳",
- "w": "𝔴",
- "x": "𝔵",
- "y": "𝔶",
- "z": "𝔷",
- "A": "𝔄",
- "B": "𝔅",
- "C": "ℭ",
- "D": "𝔇",
- "E": "𝔈",
- "F": "𝔉",
- "G": "𝔊",
- "H": "ℌ",
- "I": "ℑ",
- "J": "𝔍",
- "K": "𝔎",
- "L": "𝔏",
- "M": "𝔐",
- "N": "𝔑",
- "O": "𝔒",
- "P": "𝔓",
- "Q": "𝔔",
- "R": "ℜ",
- "S": "𝔖",
- "T": "𝔗",
- "U": "𝔘",
- "V": "𝔙",
- "W": "𝔚",
- "X": "𝔛",
- "Y": "𝔜",
- "Z": "ℨ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def bold_gothic(self):
- style = {
- "a": "𝖆",
- "b": "𝖇",
- "c": "𝖈",
- "d": "𝖉",
- "e": "𝖊",
- "f": "𝖋",
- "g": "𝖌",
- "h": "𝖍",
- "i": "𝖎",
- "j": "𝖏",
- "k": "𝖐",
- "l": "𝖑",
- "m": "𝖒",
- "n": "𝖓",
- "o": "𝖔",
- "p": "𝖕",
- "q": "𝖖",
- "r": "𝖗",
- "s": "𝖘",
- "t": "𝖙",
- "u": "𝖚",
- "v": "𝖛",
- "w": "𝖜",
- "x": "𝖝",
- "y": "𝖞",
- "z": "𝖟",
- "A": "𝕬",
- "B": "𝕭",
- "C": "𝕮",
- "D": "𝕺",
- "E": "𝕰",
- "F": "𝕱",
- "G": "𝕲",
- "H": "𝕳",
- "I": "𝕴",
- "J": "𝕵",
- "K": "𝕶",
- "L": "𝕷",
- "M": "𝕸",
- "N": "𝕹",
- "O": "𝕺",
- "P": "𝕻",
- "Q": "𝕼",
- "R": "𝕽",
- "S": "𝕾",
- "T": "𝕿",
- "U": "𝖀",
- "V": "𝖁",
- "W": "𝖂",
- "X": "𝖃",
- "Y": "𝖄",
- "Z": "𝖅",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def cloud(self):
- style = {
- "a": "a͜͡",
- "b": "b͜͡",
- "c": "c͜͡",
- "d": "d͜͡",
- "e": "e͜͡",
- "f": "f͜͡",
- "g": "g͜͡",
- "h": "h͜͡",
- "i": "i͜͡",
- "j": "j͜͡",
- "k": "k͜͡",
- "l": "l͜͡",
- "m": "m͜͡",
- "n": "n͜͡",
- "o": "o͜͡",
- "p": "p͜͡",
- "q": "q͜͡",
- "r": "r͜͡",
- "s": "s͜͡",
- "t": "t͜͡",
- "u": "u͜͡",
- "v": "v͜͡",
- "w": "w͜͡",
- "x": "x͜͡",
- "y": "y͜͡",
- "z": "z͜͡",
- "A": "A͜͡",
- "B": "B͜͡",
- "C": "C͜͡",
- "D": "D͜͡",
- "E": "E͜͡",
- "F": "F͜͡",
- "G": "G͜͡",
- "H": "H͜͡",
- "I": "I͜͡",
- "J": "J͜͡",
- "K": "K͜͡",
- "L": "L͜͡",
- "M": "M͜͡",
- "N": "N͜͡",
- "O": "O͜͡",
- "P": "P͜͡",
- "Q": "Q͜͡",
- "R": "R͜͡",
- "S": "S͜͡",
- "T": "T͜͡",
- "U": "U͜͡",
- "V": "V͜͡",
- "W": "W͜͡",
- "X": "X͜͡",
- "Y": "Y͜͡",
- "Z": "Z͜͡",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def happy(self):
- style = {
- "a": "ă̈",
- "b": "b̆̈",
- "c": "c̆̈",
- "d": "d̆̈",
- "e": "ĕ̈",
- "f": "f̆̈",
- "g": "ğ̈",
- "h": "h̆̈",
- "i": "ĭ̈",
- "j": "j̆̈",
- "k": "k̆̈",
- "l": "l̆̈",
- "m": "m̆̈",
- "n": "n̆̈",
- "o": "ŏ̈",
- "p": "p̆̈",
- "q": "q̆̈",
- "r": "r̆̈",
- "s": "s̆̈",
- "t": "t̆̈",
- "u": "ŭ̈",
- "v": "v̆̈",
- "w": "w̆̈",
- "x": "x̆̈",
- "y": "y̆̈",
- "z": "z̆̈",
- "A": "Ă̈",
- "B": "B̆̈",
- "C": "C̆̈",
- "D": "D̆̈",
- "E": "Ĕ̈",
- "F": "F̆̈",
- "G": "Ğ̈",
- "H": "H̆̈",
- "I": "Ĭ̈",
- "J": "J̆̈",
- "K": "K̆̈",
- "L": "L̆̈",
- "M": "M̆̈",
- "N": "N̆̈",
- "O": "Ŏ̈",
- "P": "P̆̈",
- "Q": "Q̆̈",
- "R": "R̆̈",
- "S": "S̆̈",
- "T": "T̆̈",
- "U": "Ŭ̈",
- "V": "V̆̈",
- "W": "W̆̈",
- "X": "X̆̈",
- "Y": "Y̆̈",
- "Z": "Z̆̈",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def sad(self):
- style = {
- "a": "ȃ̈",
- "b": "b̑̈",
- "c": "c̑̈",
- "d": "d̑̈",
- "e": "ȇ̈",
- "f": "f̑̈",
- "g": "g̑̈",
- "h": "h̑̈",
- "i": "ȋ̈",
- "j": "j̑̈",
- "k": "k̑̈",
- "l": "l̑̈",
- "m": "m̑̈",
- "n": "n̑̈",
- "o": "ȏ̈",
- "p": "p̑̈",
- "q": "q̑̈",
- "r": "ȓ̈",
- "s": "s̑̈",
- "t": "t̑̈",
- "u": "ȗ̈",
- "v": "v̑̈",
- "w": "w̑̈",
- "x": "x̑̈",
- "y": "y̑̈",
- "z": "z̑̈",
- "A": "Ȃ̈",
- "B": "B̑̈",
- "C": "C̑̈",
- "D": "D̑̈",
- "E": "Ȇ̈",
- "F": "F̑̈",
- "G": "G̑̈",
- "H": "H̑̈",
- "I": "Ȋ̈",
- "J": "J̑̈",
- "K": "K̑̈",
- "L": "L̑̈",
- "M": "M̑̈",
- "N": "N̑̈",
- "O": "Ȏ̈",
- "P": "P̑̈",
- "Q": "Q̑̈",
- "R": "Ȓ̈",
- "S": "S̑̈",
- "T": "T̑̈",
- "U": "Ȗ̈",
- "V": "V̑̈",
- "W": "W̑̈",
- "X": "X̑̈",
- "Y": "Y̑̈",
- "Z": "Z̑̈",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def special(self):
- style = {
- "a": "🇦 ",
- "b": "🇧 ",
- "c": "🇨 ",
- "d": "🇩 ",
- "e": "🇪 ",
- "f": "🇫 ",
- "g": "🇬 ",
- "h": "🇭 ",
- "i": "🇮 ",
- "j": "🇯 ",
- "k": "🇰 ",
- "l": "🇱 ",
- "m": "🇲 ",
- "n": "🇳 ",
- "o": "🇴 ",
- "p": "🇵 ",
- "q": "🇶 ",
- "r": "🇷 ",
- "s": "🇸 ",
- "t": "🇹 ",
- "u": "🇺 ",
- "v": "🇻 ",
- "w": "🇼 ",
- "x": "🇽 ",
- "y": "🇾 ",
- "z": "🇿 ",
- "A": "🇦 ",
- "B": "🇧 ",
- "C": "🇨 ",
- "D": "🇩 ",
- "E": "🇪 ",
- "F": "🇫 ",
- "G": "🇬 ",
- "H": "🇭 ",
- "I": "🇮 ",
- "J": "🇯 ",
- "K": "🇰 ",
- "L": "🇱 ",
- "M": "🇲 ",
- "N": "🇳 ",
- "O": "🇴 ",
- "P": "🇵 ",
- "Q": "🇶 ",
- "R": "🇷 ",
- "S": "🇸 ",
- "T": "🇹 ",
- "U": "🇺 ",
- "V": "🇻 ",
- "W": "🇼 ",
- "X": "🇽 ",
- "Y": "🇾 ",
- "Z": "🇿 ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def square(self):
- style = {
- "a": "🄰",
- "b": "🄱",
- "c": "🄲",
- "d": "🄳",
- "e": "🄴",
- "f": "🄵",
- "g": "🄶",
- "h": "🄷",
- "i": "🄸",
- "j": "🄹",
- "k": "🄺",
- "l": "🄻",
- "m": "🄼",
- "n": "🄽",
- "o": "🄾",
- "p": "🄿",
- "q": "🅀",
- "r": "🅁",
- "s": "🅂",
- "t": "🅃",
- "u": "🅄",
- "v": "🅅",
- "w": "🅆",
- "x": "🅇",
- "y": "🅈",
- "z": "🅉",
- "A": "🄰",
- "B": "🄱",
- "C": "🄲",
- "D": "🄳",
- "E": "🄴",
- "F": "🄵",
- "G": "🄶",
- "H": "🄷",
- "I": "🄸",
- "J": "🄹",
- "K": "🄺",
- "L": "🄻",
- "M": "🄼",
- "N": "🄽",
- "O": "🄾",
- "P": "🄿",
- "Q": "🅀",
- "R": "🅁",
- "S": "🅂",
- "T": "🅃",
- "U": "🅄",
- "V": "🅅",
- "W": "🅆",
- "X": "🅇",
- "Y": "🅈",
- "Z": "🅉",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def dark_square(self):
- style = {
- "a": "🅰︎",
- "b": "🅱︎",
- "c": "🅲︎",
- "d": "🅳︎",
- "e": "🅴︎",
- "f": "🅵︎",
- "g": "🅶︎",
- "h": "🅷︎",
- "i": "🅸︎",
- "j": "🅹︎",
- "k": "🅺︎",
- "l": "🅻︎",
- "m": "🅼︎",
- "n": "🅽︎",
- "o": "🅾︎",
- "p": "🅿︎",
- "q": "🆀︎",
- "r": "🆁︎",
- "s": "🆂︎",
- "t": "🆃︎",
- "u": "🆄︎",
- "v": "🆅︎",
- "w": "🆆︎",
- "x": "🆇︎",
- "y": "🆈︎",
- "z": "🆉︎",
- "A": "🅰︎",
- "B": "🅱︎",
- "C": "🅲︎",
- "D": "🅳︎",
- "E": "🅴︎",
- "F": "🅵︎",
- "G": "🅶︎",
- "H": "🅷︎",
- "I": "🅸︎",
- "J": "🅹︎",
- "K": "🅺︎",
- "L": "🅻︎",
- "M": "🅼︎",
- "N": "🅽︎",
- "O": "🅾︎",
- "P": "🅿︎",
- "Q": "🆀︎",
- "R": "🆁︎",
- "S": "🆂︎",
- "T": "🆃︎",
- "U": "🆄︎",
- "V": "🆅︎",
- "W": "🆆︎",
- "X": "🆇︎",
- "Y": "🆈︎",
- "Z": "🆉︎",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def andalucia(self):
- style = {
- "a": "ꪖ",
- "b": "᥇",
- "c": "ᥴ",
- "d": "ᦔ",
- "e": "ꫀ",
- "f": "ᠻ",
- "g": "ᧁ",
- "h": "ꫝ",
- "i": "𝓲",
- "j": "𝓳",
- "k": "𝘬",
- "l": "ꪶ",
- "m": "ꪑ",
- "n": "ꪀ",
- "o": "ꪮ",
- "p": "ρ",
- "q": "𝘲",
- "r": "𝘳",
- "s": "𝘴",
- "t": "𝓽",
- "u": "ꪊ",
- "v": "ꪜ",
- "w": "᭙",
- "x": "᥊",
- "y": "ꪗ",
- "z": "ɀ",
- "A": "ꪖ",
- "B": "᥇",
- "C": "ᥴ",
- "D": "ᦔ",
- "E": "ꫀ",
- "F": "ᠻ",
- "G": "ᧁ",
- "H": "ꫝ",
- "I": "𝓲",
- "J": "𝓳",
- "K": "𝘬",
- "L": "ꪶ",
- "M": "ꪑ",
- "N": "ꪀ",
- "O": "ꪮ",
- "P": "ρ",
- "Q": "𝘲",
- "R": "𝘳",
- "S": "𝘴",
- "T": "𝓽",
- "U": "ꪊ",
- "V": "ꪜ",
- "W": "᭙",
- "X": "᥊",
- "Y": "ꪗ",
- "Z": "ɀ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def manga(self):
- style = {
- "a": "卂",
- "b": "乃",
- "c": "匚",
- "d": "ᗪ",
- "e": "乇",
- "f": "千",
- "g": "ᘜ",
- "h": "卄",
- "i": "|",
- "j": "フ",
- "k": "Ҝ",
- "l": "ㄥ",
- "m": "爪",
- "n": "几",
- "o": "ㄖ",
- "p": "卩",
- "q": "Ҩ",
- "r": "尺",
- "s": "丂",
- "t": "ㄒ",
- "u": "ㄩ",
- "v": "ᐯ",
- "w": "山",
- "x": "乂",
- "y": "ㄚ",
- "z": "乙",
- "A": "卂",
- "B": "乃",
- "C": "匚",
- "D": "ᗪ",
- "E": "乇",
- "F": "千",
- "G": "ᘜ",
- "H": "卄",
- "I": "|",
- "J": "フ",
- "K": "Ҝ",
- "L": "ㄥ",
- "M": "爪",
- "N": "几",
- "O": "ㄖ",
- "P": "卩",
- "Q": "Ҩ",
- "R": "尺",
- "S": "丂",
- "T": "ㄒ",
- "U": "ㄩ",
- "V": "ᐯ",
- "W": "山",
- "X": "乂",
- "Y": "ㄚ",
- "Z": "乙",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def stinky(self):
- style = {
- "a": "a̾",
- "b": "b̾",
- "c": "c̾",
- "d": "d̾",
- "e": "e̾",
- "f": "f̾",
- "g": "g̾",
- "h": "h̾",
- "i": "i̾",
- "j": "j̾",
- "k": "k̾",
- "l": "l̾",
- "m": "m̾",
- "n": "n̾",
- "o": "o̾",
- "p": "p̾",
- "q": "q̾",
- "r": "r̾",
- "s": "s̾",
- "t": "t̾",
- "u": "u̾",
- "v": "v̾",
- "w": "w̾",
- "x": "x̾",
- "y": "y̾",
- "z": "z̾",
- "A": "A̾",
- "B": "B̾",
- "C": "C̾",
- "D": "D̾",
- "E": "E̾",
- "F": "F̾",
- "G": "G̾",
- "H": "H̾",
- "I": "I̾",
- "J": "J̾",
- "K": "K̾",
- "L": "L̾",
- "M": "M̾",
- "N": "N̾",
- "O": "O̾",
- "P": "P̾",
- "Q": "Q̾",
- "R": "R̾",
- "S": "S̾",
- "T": "T̾",
- "U": "U̾",
- "V": "V̾",
- "W": "W̾",
- "X": "X̾",
- "Y": "Y̾",
- "Z": "Z̾",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def bubbles(self):
- style = {
- "a": "ḁͦ",
- "b": "b̥ͦ",
- "c": "c̥ͦ",
- "d": "d̥ͦ",
- "e": "e̥ͦ",
- "f": "f̥ͦ",
- "g": "g̥ͦ",
- "h": "h̥ͦ",
- "i": "i̥ͦ",
- "j": "j̥ͦ",
- "k": "k̥ͦ",
- "l": "l̥ͦ",
- "m": "m̥ͦ",
- "n": "n̥ͦ",
- "o": "o̥ͦ",
- "p": "p̥ͦ",
- "q": "q̥ͦ",
- "r": "r̥ͦ",
- "s": "s̥ͦ",
- "t": "t̥ͦ",
- "u": "u̥ͦ",
- "v": "v̥ͦ",
- "w": "w̥ͦ",
- "x": "x̥ͦ",
- "y": "y̥ͦ",
- "z": "z̥ͦ",
- "A": "Ḁͦ",
- "B": "B̥ͦ",
- "C": "C̥ͦ",
- "D": "D̥ͦ",
- "E": "E̥ͦ",
- "F": "F̥ͦ",
- "G": "G̥ͦ",
- "H": "H̥ͦ",
- "I": "I̥ͦ",
- "J": "J̥ͦ",
- "K": "K̥ͦ",
- "L": "L̥ͦ",
- "M": "M̥ͦ",
- "N": "N̥ͦ",
- "O": "O̥ͦ",
- "P": "P̥ͦ",
- "Q": "Q̥ͦ",
- "R": "R̥ͦ",
- "S": "S̥ͦ",
- "T": "T̥ͦ",
- "U": "U̥ͦ",
- "V": "V̥ͦ",
- "W": "W̥ͦ",
- "X": "X̥ͦ",
- "Y": "Y̥ͦ",
- "Z": "Z̥ͦ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def underline(self):
- style = {
- "a": "a͟",
- "b": "b͟",
- "c": "c͟",
- "d": "d͟",
- "e": "e͟",
- "f": "f͟",
- "g": "g͟",
- "h": "h͟",
- "i": "i͟",
- "j": "j͟",
- "k": "k͟",
- "l": "l͟",
- "m": "m͟",
- "n": "n͟",
- "o": "o͟",
- "p": "p͟",
- "q": "q͟",
- "r": "r͟",
- "s": "s͟",
- "t": "t͟",
- "u": "u͟",
- "v": "v͟",
- "w": "w͟",
- "x": "x͟",
- "y": "y͟",
- "z": "z͟",
- "A": "A͟",
- "B": "B͟",
- "C": "C͟",
- "D": "D͟",
- "E": "E͟",
- "F": "F͟",
- "G": "G͟",
- "H": "H͟",
- "I": "I͟",
- "J": "J͟",
- "K": "K͟",
- "L": "L͟",
- "M": "M͟",
- "N": "N͟",
- "O": "O͟",
- "P": "P͟",
- "Q": "Q͟",
- "R": "R͟",
- "S": "S͟",
- "T": "T͟",
- "U": "U͟",
- "V": "V͟",
- "W": "W͟",
- "X": "X͟",
- "Y": "Y͟",
- "Z": "Z͟",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def ladybug(self):
- style = {
- "a": "ꍏ",
- "b": "ꌃ",
- "c": "ꏳ",
- "d": "ꀷ",
- "e": "ꏂ",
- "f": "ꎇ",
- "g": "ꁅ",
- "h": "ꀍ",
- "i": "ꀤ",
- "j": "꒻",
- "k": "ꀘ",
- "l": "꒒",
- "m": "ꎭ",
- "n": "ꈤ",
- "o": "ꂦ",
- "p": "ᖘ",
- "q": "ꆰ",
- "r": "ꋪ",
- "s": "ꌚ",
- "t": "꓄",
- "u": "ꀎ",
- "v": "꒦",
- "w": "ꅐ",
- "x": "ꉧ",
- "y": "ꌩ",
- "z": "ꁴ",
- "A": "ꍏ",
- "B": "ꌃ",
- "C": "ꏳ",
- "D": "ꀷ",
- "E": "ꏂ",
- "F": "ꎇ",
- "G": "ꁅ",
- "H": "ꀍ",
- "I": "ꀤ",
- "J": "꒻",
- "K": "ꀘ",
- "L": "꒒",
- "M": "ꎭ",
- "N": "ꈤ",
- "O": "ꂦ",
- "P": "ᖘ",
- "Q": "ꆰ",
- "R": "ꋪ",
- "S": "ꌚ",
- "T": "꓄",
- "U": "ꀎ",
- "V": "꒦",
- "W": "ꅐ",
- "X": "ꉧ",
- "Y": "ꌩ",
- "Z": "ꁴ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def rays(self):
- style = {
- "a": "a҉",
- "b": "b҉",
- "c": "c҉",
- "d": "d҉",
- "e": "e҉",
- "f": "f҉",
- "g": "g҉",
- "h": "h҉",
- "i": "i҉",
- "j": "j҉",
- "k": "k҉",
- "l": "l҉",
- "m": "m҉",
- "n": "n҉",
- "o": "o҉",
- "p": "p҉",
- "q": "q҉",
- "r": "r҉",
- "s": "s҉",
- "t": "t҉",
- "u": "u҉",
- "v": "v҉",
- "w": "w҉",
- "x": "x҉",
- "y": "y҉",
- "z": "z҉",
- "A": "A҉",
- "B": "B҉",
- "C": "C҉",
- "D": "D҉",
- "E": "E҉",
- "F": "F҉",
- "G": "G҉",
- "H": "H҉",
- "I": "I҉",
- "J": "J҉",
- "K": "K҉",
- "L": "L҉",
- "M": "M҉",
- "N": "N҉",
- "O": "O҉",
- "P": "P҉",
- "Q": "Q҉",
- "R": "R҉",
- "S": "S҉",
- "T": "T҉",
- "U": "U҉",
- "V": "V҉",
- "W": "W҉",
- "X": "X҉",
- "Y": "Y҉",
- "Z": "Z҉",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def birds(self):
- style = {
- "a": "a҈",
- "b": "b҈",
- "c": "c҈",
- "d": "d҈",
- "e": "e҈",
- "f": "f҈",
- "g": "g҈",
- "h": "h҈",
- "i": "i҈",
- "j": "j҈",
- "k": "k҈",
- "l": "l҈",
- "m": "m҈",
- "n": "n҈",
- "o": "o҈",
- "p": "p҈",
- "q": "q҈",
- "r": "r҈",
- "s": "s҈",
- "t": "t҈",
- "u": "u҈",
- "v": "v҈",
- "w": "w҈",
- "x": "x҈",
- "y": "y҈",
- "z": "z҈",
- "A": "A҈",
- "B": "B҈",
- "C": "C҈",
- "D": "D҈",
- "E": "E҈",
- "F": "F҈",
- "G": "G҈",
- "H": "H҈",
- "I": "I҈",
- "J": "J҈",
- "K": "K҈",
- "L": "L҈",
- "M": "M҈",
- "N": "N҈",
- "O": "O҈",
- "P": "P҈",
- "Q": "Q҈",
- "R": "R҈",
- "S": "S҈",
- "T": "T҈",
- "U": "U҈",
- "V": "V҈",
- "W": "W҈",
- "X": "X҈",
- "Y": "Y҈",
- "Z": "Z҈",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def slash(self):
- style = {
- "a": "a̸",
- "b": "b̸",
- "c": "c̸",
- "d": "d̸",
- "e": "e̸",
- "f": "f̸",
- "g": "g̸",
- "h": "h̸",
- "i": "i̸",
- "j": "j̸",
- "k": "k̸",
- "l": "l̸",
- "m": "m̸",
- "n": "n̸",
- "o": "o̸",
- "p": "p̸",
- "q": "q̸",
- "r": "r̸",
- "s": "s̸",
- "t": "t̸",
- "u": "u̸",
- "v": "v̸",
- "w": "w̸",
- "x": "x̸",
- "y": "y̸",
- "z": "z̸",
- "A": "A̸",
- "B": "B̸",
- "C": "C̸",
- "D": "D̸",
- "E": "E̸",
- "F": "F̸",
- "G": "G̸",
- "H": "H̸",
- "I": "I̸",
- "J": "J̸",
- "K": "K̸",
- "L": "L̸",
- "M": "M̸",
- "N": "N̸",
- "O": "O̸",
- "P": "P̸",
- "Q": "Q̸",
- "R": "R̸",
- "S": "S̸",
- "T": "T̸",
- "U": "U̸",
- "V": "V̸",
- "W": "W̸",
- "X": "X̸",
- "Y": "Y̸",
- "Z": "Z̸",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def stop(self):
- style = {
- "a": "a⃠",
- "b": "b⃠",
- "c": "c⃠",
- "d": "d⃠",
- "e": "e⃠",
- "f": "f⃠",
- "g": "g⃠",
- "h": "h⃠",
- "i": "i⃠",
- "j": "j⃠",
- "k": "k⃠",
- "l": "l⃠",
- "m": "m⃠",
- "n": "n⃠",
- "o": "o⃠",
- "p": "p⃠",
- "q": "q⃠",
- "r": "r⃠",
- "s": "s⃠",
- "t": "t⃠",
- "u": "u⃠",
- "v": "v⃠",
- "w": "w⃠",
- "x": "x⃠",
- "y": "y⃠",
- "z": "z⃠",
- "A": "A⃠",
- "B": "B⃠",
- "C": "C⃠",
- "D": "D⃠",
- "E": "E⃠",
- "F": "F⃠",
- "G": "G⃠",
- "H": "H⃠",
- "I": "I⃠",
- "J": "J⃠",
- "K": "K⃠",
- "L": "L⃠",
- "M": "M⃠",
- "N": "N⃠",
- "O": "O⃠",
- "P": "P⃠",
- "Q": "Q⃠",
- "R": "R⃠",
- "S": "S⃠",
- "T": "T⃠",
- "U": "U⃠",
- "V": "V⃠",
- "W": "W⃠",
- "X": "X⃠",
- "Y": "Y⃠",
- "Z": "Z⃠",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def skyline(self):
- style = {
- "a": "a̺͆",
- "b": "b̺͆",
- "c": "c̺͆",
- "d": "d̺͆",
- "e": "e̺͆",
- "f": "f̺͆",
- "g": "g̺͆",
- "h": "h̺͆",
- "i": "i̺͆",
- "j": "j̺͆",
- "k": "k̺͆",
- "l": "l̺͆",
- "m": "m̺͆",
- "n": "n̺͆",
- "o": "o̺͆",
- "p": "p̺͆",
- "q": "q̺͆",
- "r": "r̺͆",
- "s": "s̺͆",
- "t": "t̺͆",
- "u": "u̺͆",
- "v": "v̺͆",
- "w": "w̺͆",
- "x": "x̺͆",
- "y": "y̺͆",
- "z": "z̺͆",
- "A": "A̺͆",
- "B": "B̺͆",
- "C": "C̺͆",
- "D": "D̺͆",
- "E": "E̺͆",
- "F": "F̺͆",
- "G": "G̺͆",
- "H": "H̺͆",
- "I": "I̺͆",
- "J": "J̺͆",
- "K": "K̺͆",
- "L": "L̺͆",
- "M": "M̺͆",
- "N": "N̺͆",
- "O": "O̺͆",
- "P": "P̺͆",
- "Q": "Q̺͆",
- "R": "R̺͆",
- "S": "S̺͆",
- "T": "T̺͆",
- "U": "U̺͆",
- "V": "V̺͆",
- "W": "W̺͆",
- "X": "X̺͆",
- "Y": "Y̺͆",
- "Z": "Z̺͆",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def arrows(self):
- style = {
- "a": "a͎",
- "b": "b͎",
- "c": "c͎",
- "d": "d͎",
- "e": "e͎",
- "f": "f͎",
- "g": "g͎",
- "h": "h͎",
- "i": "i͎",
- "j": "j͎",
- "k": "k͎",
- "l": "l͎",
- "m": "m͎",
- "n": "n͎",
- "o": "o͎",
- "p": "p͎",
- "q": "q͎",
- "r": "r͎",
- "s": "s͎",
- "t": "t͎",
- "u": "u͎",
- "v": "v͎",
- "w": "w͎",
- "x": "x͎",
- "y": "y͎",
- "z": "z͎",
- "A": "A͎",
- "B": "B͎",
- "C": "C͎",
- "D": "D͎",
- "E": "E͎",
- "F": "F͎",
- "G": "G͎",
- "H": "H͎",
- "I": "I͎",
- "J": "J͎",
- "K": "K͎",
- "L": "L͎",
- "M": "M͎",
- "N": "N͎",
- "O": "O͎",
- "P": "P͎",
- "Q": "Q͎",
- "R": "R͎",
- "S": "S͎",
- "T": "T͎",
- "U": "U͎",
- "V": "V͎",
- "W": "W͎",
- "X": "X͎",
- "Y": "Y͎",
- "Z": "Z͎",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def rvnes(self):
- style = {
- "a": "ል",
- "b": "ጌ",
- "c": "ር",
- "d": "ዕ",
- "e": "ቿ",
- "f": "ቻ",
- "g": "ኗ",
- "h": "ዘ",
- "i": "ጎ",
- "j": "ጋ",
- "k": "ጕ",
- "l": "ረ",
- "m": "ጠ",
- "n": "ክ",
- "o": "ዐ",
- "p": "የ",
- "q": "ዒ",
- "r": "ዪ",
- "s": "ነ",
- "t": "ፕ",
- "u": "ሁ",
- "v": "ሀ",
- "w": "ሠ",
- "x": "ሸ",
- "y": "ሃ",
- "z": "ጊ",
- "A": "ል",
- "B": "ጌ",
- "C": "ር",
- "D": "ዕ",
- "E": "ቿ",
- "F": "ቻ",
- "G": "ኗ",
- "H": "ዘ",
- "I": "ጎ",
- "J": "ጋ",
- "K": "ጕ",
- "L": "ረ",
- "M": "ጠ",
- "N": "ክ",
- "O": "ዐ",
- "P": "የ",
- "Q": "ዒ",
- "R": "ዪ",
- "S": "ነ",
- "T": "ፕ",
- "U": "ሁ",
- "V": "ሀ",
- "W": "ሠ",
- "X": "ሸ",
- "Y": "ሃ",
- "Z": "ጊ",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def strike(self):
- style = {
- "a": "a̶",
- "b": "b̶",
- "c": "c̶",
- "d": "d̶",
- "e": "e̶",
- "f": "f̶",
- "g": "g̶",
- "h": "h̶",
- "i": "i̶",
- "j": "j̶",
- "k": "k̶",
- "l": "l̶",
- "m": "m̶",
- "n": "n̶",
- "o": "o̶",
- "p": "p̶",
- "q": "q̶",
- "r": "r̶",
- "s": "s̶",
- "t": "t̶",
- "u": "u̶",
- "v": "v̶",
- "w": "w̶",
- "x": "x̶",
- "y": "y̶",
- "z": "z̶",
- "A": "A̶",
- "B": "B̶",
- "C": "C̶",
- "D": "D̶",
- "E": "E̶",
- "F": "F̶",
- "G": "G̶",
- "H": "H̶",
- "I": "I̶",
- "J": "J̶",
- "K": "K̶",
- "L": "L̶",
- "M": "M̶",
- "N": "N̶",
- "O": "O̶",
- "P": "P̶",
- "Q": "Q̶",
- "R": "R̶",
- "S": "S̶",
- "T": "T̶",
- "U": "U̶",
- "V": "V̶",
- "W": "W̶",
- "X": "X̶",
- "Y": "Y̶",
- "Z": "Z̶",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
-
- def frozen(self):
- style = {
- "a": "a༙",
- "b": "b༙",
- "c": "c༙",
- "d": "d༙",
- "e": "e༙",
- "f": "f༙",
- "g": "g༙",
- "h": "h༙",
- "i": "i༙",
- "j": "j༙",
- "k": "k༙",
- "l": "l༙",
- "m": "m༙",
- "n": "n༙",
- "o": "o༙",
- "p": "p༙",
- "q": "q༙",
- "r": "r༙",
- "s": "s༙",
- "t": "t༙",
- "u": "u༙",
- "v": "v༙",
- "w": "w༙",
- "x": "x༙",
- "y": "y༙",
- "z": "z༙",
- "A": "A༙",
- "B": "B༙",
- "C": "C༙",
- "D": "D༙",
- "E": "E༙",
- "F": "F༙",
- "G": "G༙",
- "H": "H༙",
- "I": "I༙",
- "J": "J༙",
- "K": "K༙",
- "L": "L༙",
- "M": "M༙",
- "N": "N༙",
- "O": "O༙",
- "P": "P༙",
- "Q": "Q༙",
- "R": "R༙",
- "S": "S༙",
- "T": "T༙",
- "U": "U༙",
- "V": "V༙",
- "W": "W༙",
- "X": "X༙",
- "Y": "Y༙",
- "Z": "Z༙",
- }
- for i, j in style.items():
- self = self.replace(i, j)
- return self
diff --git a/Exon/modules/rules.py b/Exon/modules/rules.py
deleted file mode 100644
index 74be7b01..00000000
--- a/Exon/modules/rules.py
+++ /dev/null
@@ -1,185 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode, Update
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext, Filters
-from telegram.utils.helpers import escape_markdown
-
-import Exon.modules.sql.rules_sql as sql
-from Exon import dispatcher
-from Exon.modules.helper_funcs.anonymous import AdminPerms, user_admin
-from Exon.modules.helper_funcs.decorators import Exoncmd
-from Exon.modules.helper_funcs.string_handling import markdown_parser
-
-
-@Exoncmd(command="rules", filters=Filters.chat_type.groups)
-def get_rules(update: Update, _: CallbackContext):
- chat_id = update.effective_chat.id
- send_rules(update, chat_id)
-
-
-# Do not async - not from a handler
-def send_rules(update, chat_id, from_pm=False):
- bot = dispatcher.bot
- user = update.effective_user # type: Optional[User]
- message = update.effective_message
- reply_msg = update.message.reply_to_message
- try:
- chat = bot.get_chat(chat_id)
- except BadRequest as excp:
- if excp.message == "Chat not found" and from_pm:
- bot.send_message(
- user.id,
- "ᴛʜᴇ ʀᴜʟᴇꜱ ꜱʜᴏʀᴛᴄᴜᴛ ꜰᴏʀ ᴛʜɪꜱ ᴄʜᴀᴛ ʜᴀꜱɴ'ᴛ ʙᴇᴇɴ ꜱᴇᴛ ᴘʀᴏᴘᴇʀʟʏ! ᴀꜱᴋ ᴀᴅᴍɪɴꜱ ᴛᴏ "
- "ꜰɪx ᴛʜɪꜱ.\nᴍᴀʏ ʙᴇ ᴛʜᴇʏ ꜰᴏʀɢᴏᴛ ᴛʜᴇ ʜʏᴘʜᴇɴ ɪɴ ɪᴅ",
- )
- return
- raise
-
- rules = sql.get_rules(chat_id)
- text = f"ᴛʜᴇ ʀᴜʟᴇꜱ ꜰᴏʀ *{escape_markdown(chat.title)}* ᴀʀᴇ:\n\n{rules}"
-
- if from_pm and rules:
- bot.send_message(
- user.id,
- text,
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- )
- elif from_pm:
- bot.send_message(
- user.id,
- "ᴛʜᴇ ɢʀᴏᴜᴘ ᴀᴅᴍɪɴꜱ ʜᴀᴠᴇɴ'ᴛ ꜱᴇᴛ ᴀɴʏ ʀᴜʟᴇꜱ ꜰᴏʀ ᴛʜɪꜱ ᴄʜᴀᴛ ʏᴇᴛ. "
- "ᴛʜɪꜱ ᴘʀᴏʙᴇʙʟʏ ᴅᴏᴇꜱ'ᴛ ᴍᴇᴀɴ ɪᴛ'ꜱ ʟᴀᴡʟᴇꜱꜱ ᴛʜᴏᴜɢʜ...!",
- )
- elif rules and reply_msg:
- reply_msg.reply_text(
- "ᴘʟᴇᴀꜱᴇ ᴄʟɪᴄᴋ ᴛʜᴇ ʙᴜᴛᴛᴏɴ ʙᴇʟᴏᴡ ᴛᴏ ꜱᴇᴇ ᴛʜᴇ ʀᴜʟᴇꜱ.",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="📝 ʀᴇᴀᴅ ʀᴜʟᴇꜱ",
- url=f"t.me/{bot.username}?start={chat_id}",
- ),
- InlineKeyboardButton(text="❌ ᴅᴇʟᴇᴛᴇ", callback_data="close2"),
- ]
- ]
- ),
- )
- elif rules:
- btn = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="📝 ʀᴇᴀᴅ ʀᴜʟᴇꜱ",
- url=f"t.me/{bot.username}?start={chat_id}",
- ),
- InlineKeyboardButton(text="❌ ᴅᴇʟᴇᴛᴇ", callback_data="close2"),
- ]
- ]
- )
- txt = "Please click the button below to see the rules."
- if not message.reply_to_message:
- message.reply_text(txt, reply_markup=btn)
-
- if message.reply_to_message:
- message.reply_to_message.reply_text(txt, reply_markup=btn)
- else:
- update.effective_message.reply_text(
- "ᴛʜᴇ ɢʀᴏᴜᴘ ᴀᴅᴍɪɴꜱ ʜᴀᴠᴇɴ'ᴛ ꜱᴇᴛ ᴀɴʏ ʀᴜʟᴇꜱ ꜰᴏʀ ᴛʜɪꜱ ᴄʜᴀᴛ ʏᴇᴛ. "
- "ᴛʜɪꜱ ᴘʀᴏʙᴀʙʟʏ ᴅᴏᴇꜱ'ᴛ ᴍᴇᴀɴ ɪᴛꜱ ʟᴀᴡʟᴇꜱꜱ ᴛʜᴏᴜɢʜ...!",
- )
-
-
-close_keyboard = InlineKeyboardMarkup(
- [[InlineKeyboardButton("❌ ᴅᴇʟᴇᴛᴇ", callback_data="close2")]]
-)
-
-
-@Exoncmd(command="setrules", filters=Filters.chat_type.groups)
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-def set_rules(update: Update, context: CallbackContext):
- chat_id = update.effective_chat.id
- msg = update.effective_message # type: Optional[Message]
- raw_text = msg.text
- args = raw_text.split(None, 1) # use python's maxsplit to separate cmd and args
- if len(args) == 2:
- txt = args[1]
- offset = len(txt) - len(raw_text) # set correct offset relative to command
- markdown_rules = markdown_parser(
- txt,
- entities=msg.parse_entities(),
- offset=offset,
- )
-
- sql.set_rules(chat_id, markdown_rules)
- update.effective_message.reply_text("ꜱᴜᴄᴇꜱꜱꜰᴜʟʟʏ ꜱᴇᴛ ʀᴜʟᴇꜱ ꜰᴏʀ ᴛʜɪꜱ ɢʀᴏᴜᴘ.")
-
-
-@Exoncmd(command="clearrules", filters=Filters.chat_type.groups)
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-def clear_rules(update: Update, context: CallbackContext):
- chat_id = update.effective_chat.id
- sql.set_rules(chat_id, "")
- update.effective_message.reply_text("ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ᴄʟᴇᴀʀᴇᴅ ʀᴜʟᴇꜱ!")
-
-
-def __stats__():
- return f"× {sql.num_chats()} chats have rules set."
-
-
-def __import_data__(chat_id, data):
- # set chat rules
- rules = data.get("info", {}).get("rules", "")
- sql.set_rules(chat_id, rules)
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- return f"This chat has had it's rules set: `{bool(sql.get_rules(chat_id))}`"
-
-
-__mod_name__ = "𝐑ᴜʟᴇs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "rules_help")
-
-# """
diff --git a/Exon/modules/shell.py b/Exon/modules/shell.py
deleted file mode 100644
index 0d4d1eb7..00000000
--- a/Exon/modules/shell.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import subprocess
-
-from telegram import ParseMode, Update
-from telegram.ext import CallbackContext, CommandHandler
-
-from Exon import LOGGER, dispatcher
-from Exon.modules.helper_funcs.chat_status import dev_plus
-
-
-@dev_plus
-def shell(update: Update, context: CallbackContext):
- message = update.effective_message
- cmd = message.text.split(" ", 1)
- if len(cmd) == 1:
- message.reply_text("ɴᴏ ᴄᴏᴍᴍᴀɴᴅ ᴛᴏ ᴇxᴄᴜᴛᴇ ᴡᴀꜱ ɢɪᴠᴇɴ ʙᴀʙʏ.")
- return
- cmd = cmd[1]
- process = subprocess.Popen(
- cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=True,
- )
- stdout, stderr = process.communicate()
- reply = ""
- stderr = stderr.decode()
- if stdout := stdout.decode():
- reply += f"*ꜱᴛᴅᴏᴜᴛ*\n`{stdout}`\n"
- LOGGER.info(f"Shell - {cmd} - {stdout}")
- if stderr:
- reply += f"*Stderr*\n`{stderr}`\n"
- LOGGER.error(f"Shell - {cmd} - {stderr}")
- if len(reply) > 3000:
- with open("shell_output.txt", "w") as file:
- file.write(reply)
- with open("shell_output.txt", "rb") as doc:
- context.bot.send_document(
- document=doc,
- filename=doc.name,
- reply_to_message_id=message.message_id,
- chat_id=message.chat_id,
- )
- else:
- message.reply_text(reply, parse_mode=ParseMode.MARKDOWN)
-
-
-SHELL_HANDLER = CommandHandler(["sh"], shell, run_async=True)
-dispatcher.add_handler(SHELL_HANDLER)
-__mod_name__ = "Shell"
-__command_list__ = ["sh"]
-__handlers__ = [SHELL_HANDLER]
diff --git "a/Exon/modules/sql/ABISHNOI COPYRIGHT \302\251" "b/Exon/modules/sql/ABISHNOI COPYRIGHT \302\251"
deleted file mode 100644
index f6afaf5a..00000000
--- "a/Exon/modules/sql/ABISHNOI COPYRIGHT \302\251"
+++ /dev/null
@@ -1,28 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi
-# MY ALL BOTS :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
\ No newline at end of file
diff --git a/Exon/modules/sql/__init__.py b/Exon/modules/sql/__init__.py
deleted file mode 100644
index 88c525a7..00000000
--- a/Exon/modules/sql/__init__.py
+++ /dev/null
@@ -1,56 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-from sqlalchemy import create_engine
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import scoped_session, sessionmaker
-
-from Exon import DB_URL as DB_URI
-from Exon import LOGGER as log
-
-if DB_URI and DB_URI.startswith("postgres://"):
- DB_URI = DB_URI.replace("postgres://", "postgresql://", 1)
-
-
-def start() -> scoped_session:
- engine = create_engine(DB_URI, client_encoding="utf8")
- log.info("[PostgreSQL] Connecting to database......")
- BASE.metadata.bind = engine
- BASE.metadata.create_all(engine)
- return scoped_session(sessionmaker(bind=engine, autoflush=False))
-
-
-BASE = declarative_base()
-try:
- SESSION: scoped_session = start()
-except Exception as e:
- log.exception(f"[PostgreSQL] Failed to connect due to {e}")
- exit()
-
-log.info("[PostgreSQL] Connection successful, session started.")
diff --git a/Exon/modules/sql/acm_sql.py b/Exon/modules/sql/acm_sql.py
deleted file mode 100644
index 395fb32c..00000000
--- a/Exon/modules/sql/acm_sql.py
+++ /dev/null
@@ -1,68 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import threading
-
-from sqlalchemy import Boolean, Column, String
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class CleanLinked(BASE):
- __tablename__ = "clean_linked"
- chat_id = Column(String(14), primary_key=True)
- status = Column(Boolean, default=False)
-
- def __init__(self, chat_id, status):
- self.chat_id = str(chat_id)
- self.status = status
-
-
-CleanLinked.__table__.create(checkfirst=True)
-
-CLEANLINKED_LOCK = threading.RLock()
-
-
-def getCleanLinked(chat_id):
- try:
- if resultObj := SESSION.query(CleanLinked).get(str(chat_id)):
- return resultObj.status
- return False # default
- finally:
- SESSION.close()
-
-
-def setCleanLinked(chat_id, status):
- with CLEANLINKED_LOCK:
- if prevObj := SESSION.query(CleanLinked).get(str(chat_id)):
- SESSION.delete(prevObj)
- newObj = CleanLinked(str(chat_id), status)
- SESSION.add(newObj)
- SESSION.commit()
diff --git a/Exon/modules/sql/antiflood_sql.py b/Exon/modules/sql/antiflood_sql.py
deleted file mode 100644
index bab73ce2..00000000
--- a/Exon/modules/sql/antiflood_sql.py
+++ /dev/null
@@ -1,171 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import threading
-
-from sqlalchemy import Column, Integer, String, UnicodeText
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.sql import BASE, SESSION
-
-DEF_COUNT = 1
-DEF_LIMIT = 0
-DEF_OBJ = (None, DEF_COUNT, DEF_LIMIT)
-
-
-class FloodControl(BASE):
- __tablename__ = "antiflood"
- chat_id = Column(String(14), primary_key=True)
- user_id = Column(BigInteger)
- count = Column(Integer, default=DEF_COUNT)
- limit = Column(Integer, default=DEF_LIMIT)
-
- def __init__(self, chat_id):
- self.chat_id = str(chat_id) # ensure string
-
- def __repr__(self):
- return f""
-
-
-class FloodSettings(BASE):
- __tablename__ = "antiflood_settings"
- chat_id = Column(String(14), primary_key=True)
- flood_type = Column(Integer, default=1)
- value = Column(UnicodeText, default="0")
-
- def __init__(self, chat_id, flood_type=1, value="0"):
- self.chat_id = str(chat_id)
- self.flood_type = flood_type
- self.value = value
-
- def __repr__(self):
- return f"<{self.chat_id} will executing {self.flood_type} for flood.>"
-
-
-FloodControl.__table__.create(checkfirst=True)
-FloodSettings.__table__.create(checkfirst=True)
-
-INSERTION_FLOOD_LOCK = threading.RLock()
-INSERTION_FLOOD_SETTINGS_LOCK = threading.RLock()
-
-CHAT_FLOOD = {}
-
-
-def set_flood(chat_id, amount):
- with INSERTION_FLOOD_LOCK:
- flood = SESSION.query(FloodControl).get(str(chat_id)) or FloodControl(str(chat_id))
-
- flood.user_id = None
- flood.limit = amount
-
- CHAT_FLOOD[str(chat_id)] = (None, DEF_COUNT, amount)
-
- SESSION.add(flood)
- SESSION.commit()
-
-
-def update_flood(chat_id: str, user_id) -> bool:
- if chat_id not in CHAT_FLOOD:
- return
-
- curr_user_id, count, limit = CHAT_FLOOD.get(chat_id, DEF_OBJ)
-
- if limit == 0: # no antiflood
- return False
-
- if user_id != curr_user_id or user_id is None: # other user
- CHAT_FLOOD[chat_id] = (user_id, DEF_COUNT, limit)
- return False
-
- count += 1
- if count > limit: # too many msgs, kick
- CHAT_FLOOD[chat_id] = (None, DEF_COUNT, limit)
- return True
-
- # default -> update
- CHAT_FLOOD[chat_id] = (user_id, count, limit)
- return False
-
-
-def get_flood_limit(chat_id):
- return CHAT_FLOOD.get(str(chat_id), DEF_OBJ)[2]
-
-
-def set_flood_strength(chat_id, flood_type, value):
- # for flood_type
- # 1 = ban
- # 2 = kick
- # 3 = mute
- # 4 = tban
- # 5 = tmute
- with INSERTION_FLOOD_SETTINGS_LOCK:
- curr_setting = SESSION.query(FloodSettings).get(str(chat_id)) or FloodSettings(
- chat_id,
- flood_type=int(flood_type),
- value=value,
- )
-
- curr_setting.flood_type = int(flood_type)
- curr_setting.value = str(value)
-
- SESSION.add(curr_setting)
- SESSION.commit()
-
-
-def get_flood_setting(chat_id):
- try:
- if setting := SESSION.query(FloodSettings).get(str(chat_id)):
- return setting.flood_type, setting.value
- return 1, "0"
-
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with INSERTION_FLOOD_LOCK:
- if flood := SESSION.query(FloodControl).get(str(old_chat_id)):
- CHAT_FLOOD[str(new_chat_id)] = CHAT_FLOOD.get(str(old_chat_id), DEF_OBJ)
- flood.chat_id = str(new_chat_id)
- SESSION.commit()
-
- SESSION.close()
-
-
-def __load_flood_settings():
- global CHAT_FLOOD
- try:
- all_chats = SESSION.query(FloodControl).all()
- CHAT_FLOOD = {chat.chat_id: (None, DEF_COUNT, chat.limit) for chat in all_chats}
- finally:
- SESSION.close()
-
-
-__load_flood_settings()
diff --git a/Exon/modules/sql/antilinkedchannel_sql.py b/Exon/modules/sql/antilinkedchannel_sql.py
deleted file mode 100644
index be3f8ee1..00000000
--- a/Exon/modules/sql/antilinkedchannel_sql.py
+++ /dev/null
@@ -1,135 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Boolean, Column
-from sqlalchemy.sql.sqltypes import String
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class AntiLinkedChannelSettings(BASE):
- __tablename__ = "anti_linked_channel_settings"
-
- chat_id = Column(String(14), primary_key=True)
- setting = Column(Boolean, default=False, nullable=False)
-
- def __init__(self, chat_id: int, disabled: bool):
- self.chat_id = str(chat_id)
- self.setting = disabled
-
- def __repr__(self):
- return f""
-
-
-class AntiPinChannelSettings(BASE):
- __tablename__ = "anti_pin_channel_settings"
-
- chat_id = Column(String(14), primary_key=True)
- setting = Column(Boolean, default=False, nullable=False)
-
- def __init__(self, chat_id: int, disabled: bool):
- self.chat_id = str(chat_id)
- self.setting = disabled
-
- def __repr__(self):
- return f""
-
-
-AntiLinkedChannelSettings.__table__.create(checkfirst=True)
-ANTI_LINKED_CHANNEL_SETTING_LOCK = threading.RLock()
-
-AntiPinChannelSettings.__table__.create(checkfirst=True)
-ANTI_PIN_CHANNEL_SETTING_LOCK = threading.RLock()
-
-
-def enable(chat_id: int):
- with ANTI_LINKED_CHANNEL_SETTING_LOCK:
- chat = SESSION.query(AntiLinkedChannelSettings).get(str(chat_id)) or AntiLinkedChannelSettings(chat_id, True)
-
- chat.setting = True
- SESSION.add(chat)
- SESSION.commit()
-
-
-def enable_pin(chat_id: int):
- with ANTI_PIN_CHANNEL_SETTING_LOCK:
- chat = SESSION.query(AntiPinChannelSettings).get(str(chat_id)) or AntiPinChannelSettings(chat_id, True)
-
- chat.setting = True
- SESSION.add(chat)
- SESSION.commit()
-
-
-def disable_linked(chat_id: int):
- with ANTI_LINKED_CHANNEL_SETTING_LOCK:
- chat = SESSION.query(AntiLinkedChannelSettings).get(str(chat_id)) or AntiLinkedChannelSettings(chat_id, False)
-
- chat.setting = False
- SESSION.add(chat)
- SESSION.commit()
-
-
-def disable_pin(chat_id: int):
- with ANTI_PIN_CHANNEL_SETTING_LOCK:
- chat = SESSION.query(AntiPinChannelSettings).get(str(chat_id)) or AntiPinChannelSettings(chat_id, False)
-
- chat.setting = False
- SESSION.add(chat)
- SESSION.commit()
-
-
-def status_linked(chat_id: int) -> bool:
- with ANTI_LINKED_CHANNEL_SETTING_LOCK:
- d = SESSION.query(AntiLinkedChannelSettings).get(str(chat_id))
- return d.setting if d else False
-
-
-def status_pin(chat_id: int) -> bool:
- with ANTI_PIN_CHANNEL_SETTING_LOCK:
- d = SESSION.query(AntiPinChannelSettings).get(str(chat_id))
- return d.setting if d else False
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with ANTI_LINKED_CHANNEL_SETTING_LOCK:
- if chat := SESSION.query(AntiLinkedChannelSettings).get(
- str(old_chat_id)
- ):
- chat.chat_id = new_chat_id
- SESSION.add(chat)
-
- SESSION.commit()
- with ANTI_PIN_CHANNEL_SETTING_LOCK:
- if chat := SESSION.query(AntiPinChannelSettings).get(str(old_chat_id)):
- chat.chat_id = new_chat_id
- SESSION.add(chat)
-
- SESSION.commit()
diff --git a/Exon/modules/sql/approve_sql.py b/Exon/modules/sql/approve_sql.py
deleted file mode 100644
index e871b2bd..00000000
--- a/Exon/modules/sql/approve_sql.py
+++ /dev/null
@@ -1,90 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @Abishnoi1m
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import threading
-
-from sqlalchemy import Column, String
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class Approvals(BASE):
- __tablename__ = "approval"
- chat_id = Column(String(14), primary_key=True)
- user_id = Column(BigInteger, primary_key=True)
-
- def __init__(self, chat_id, user_id):
- self.chat_id = str(chat_id) # ensure string
- self.user_id = user_id
-
- def __repr__(self):
- return f""
-
-
-Approvals.__table__.create(checkfirst=True)
-
-APPROVE_INSERTION_LOCK = threading.RLock()
-
-
-def approve(chat_id, user_id):
- with APPROVE_INSERTION_LOCK:
- approve_user = Approvals(str(chat_id), user_id)
- SESSION.add(approve_user)
- SESSION.commit()
-
-
-def is_approved(chat_id, user_id):
- try:
- return SESSION.query(Approvals).get((str(chat_id), user_id))
- finally:
- SESSION.close()
-
-
-def disapprove(chat_id, user_id):
- with APPROVE_INSERTION_LOCK:
- if disapprove_user := SESSION.query(Approvals).get(
- (str(chat_id), user_id)
- ):
- SESSION.delete(disapprove_user)
- SESSION.commit()
- return True
- SESSION.close()
- return False
-
-
-def list_approved(chat_id):
- try:
- return (
- SESSION.query(Approvals)
- .filter(Approvals.chat_id == str(chat_id))
- .order_by(Approvals.user_id.asc())
- .all()
- )
- finally:
- SESSION.close()
diff --git a/Exon/modules/sql/blacklist_sql.py b/Exon/modules/sql/blacklist_sql.py
deleted file mode 100644
index 62279759..00000000
--- a/Exon/modules/sql/blacklist_sql.py
+++ /dev/null
@@ -1,221 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import threading
-
-from sqlalchemy import Column, Integer, String, UnicodeText, distinct, func
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class BlackListFilters(BASE):
- __tablename__ = "blacklist"
- chat_id = Column(String(14), primary_key=True)
- trigger = Column(UnicodeText, primary_key=True, nullable=False)
-
- def __init__(self, chat_id, trigger):
- self.chat_id = str(chat_id) # ensure string
- self.trigger = trigger
-
- def __repr__(self):
- return f""
-
- def __eq__(self, other):
- return (
- isinstance(other, BlackListFilters)
- and self.chat_id == other.chat_id
- and self.trigger == other.trigger
- )
-
-
-class BlacklistSettings(BASE):
- __tablename__ = "blacklist_settings"
- chat_id = Column(String(14), primary_key=True)
- blacklist_type = Column(Integer, default=1)
- value = Column(UnicodeText, default="0")
-
- def __init__(self, chat_id, blacklist_type=1, value="0"):
- self.chat_id = str(chat_id)
- self.blacklist_type = blacklist_type
- self.value = value
-
- def __repr__(self):
- return f"<{self.chat_id} will executing {self.blacklist_type} for blacklist trigger.>"
-
-
-BlackListFilters.__table__.create(checkfirst=True)
-BlacklistSettings.__table__.create(checkfirst=True)
-
-BLACKLIST_FILTER_INSERTION_LOCK = threading.RLock()
-BLACKLIST_SETTINGS_INSERTION_LOCK = threading.RLock()
-
-CHAT_BLACKLISTS = {}
-CHAT_SETTINGS_BLACKLISTS = {}
-
-
-def add_to_blacklist(chat_id, trigger):
- with BLACKLIST_FILTER_INSERTION_LOCK:
- blacklist_filt = BlackListFilters(str(chat_id), trigger)
-
- SESSION.merge(blacklist_filt) # merge to avoid duplicate key issues
- SESSION.commit()
- if CHAT_BLACKLISTS.get(str(chat_id), set()) == set():
- CHAT_BLACKLISTS[str(chat_id)] = {trigger}
- else:
- CHAT_BLACKLISTS.get(str(chat_id), set()).add(trigger)
-
-
-def rm_from_blacklist(chat_id, trigger):
- with BLACKLIST_FILTER_INSERTION_LOCK:
- if blacklist_filt := SESSION.query(BlackListFilters).get(
- (str(chat_id), trigger)
- ):
- if trigger in CHAT_BLACKLISTS.get(str(chat_id), set()): # sanity check
- CHAT_BLACKLISTS.get(str(chat_id), set()).remove(trigger)
-
- SESSION.delete(blacklist_filt)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def get_chat_blacklist(chat_id):
- return CHAT_BLACKLISTS.get(str(chat_id), set())
-
-
-def num_blacklist_filters():
- try:
- return SESSION.query(BlackListFilters).count()
- finally:
- SESSION.close()
-
-
-def num_blacklist_chat_filters(chat_id):
- try:
- return (
- SESSION.query(BlackListFilters.chat_id)
- .filter(BlackListFilters.chat_id == str(chat_id))
- .count()
- )
- finally:
- SESSION.close()
-
-
-def num_blacklist_filter_chats():
- try:
- return SESSION.query(func.count(distinct(BlackListFilters.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def set_blacklist_strength(chat_id, blacklist_type, value):
- # for blacklist_type
- # 0 = nothing
- # 1 = delete
- # 2 = warn
- # 3 = mute
- # 4 = kick
- # 5 = ban
- # 6 = tban
- # 7 = tmute
- with BLACKLIST_SETTINGS_INSERTION_LOCK:
- curr_setting = SESSION.query(BlacklistSettings).get(str(chat_id)) or BlacklistSettings(
- chat_id,
- blacklist_type=int(blacklist_type),
- value=value,
- )
-
- curr_setting.blacklist_type = int(blacklist_type)
- curr_setting.value = str(value)
- CHAT_SETTINGS_BLACKLISTS[str(chat_id)] = {
- "blacklist_type": int(blacklist_type),
- "value": value,
- }
-
- SESSION.add(curr_setting)
- SESSION.commit()
-
-
-def get_blacklist_setting(chat_id):
- try:
- if setting := CHAT_SETTINGS_BLACKLISTS.get(str(chat_id)):
- return setting["blacklist_type"], setting["value"]
- return 1, "0"
-
- finally:
- SESSION.close()
-
-
-def __load_chat_blacklists():
- global CHAT_BLACKLISTS
- try:
- chats = SESSION.query(BlackListFilters.chat_id).distinct().all()
- for (chat_id,) in chats: # remove tuple by ( ,)
- CHAT_BLACKLISTS[chat_id] = []
-
- all_filters = SESSION.query(BlackListFilters).all()
- for x in all_filters:
- CHAT_BLACKLISTS[x.chat_id] += [x.trigger]
-
- CHAT_BLACKLISTS = {x: set(y) for x, y in CHAT_BLACKLISTS.items()}
-
- finally:
- SESSION.close()
-
-
-def __load_chat_settings_blacklists():
- try:
- chats_settings = SESSION.query(BlacklistSettings).all()
- for x in chats_settings: # remove tuple by ( ,)
- CHAT_SETTINGS_BLACKLISTS[x.chat_id] = {
- "blacklist_type": x.blacklist_type,
- "value": x.value,
- }
-
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with BLACKLIST_FILTER_INSERTION_LOCK:
- chat_filters = (
- SESSION.query(BlackListFilters)
- .filter(BlackListFilters.chat_id == str(old_chat_id))
- .all()
- )
- for filt in chat_filters:
- filt.chat_id = str(new_chat_id)
- SESSION.commit()
-
-
-__load_chat_blacklists()
-__load_chat_settings_blacklists()
diff --git a/Exon/modules/sql/blacklistusers_sql.py b/Exon/modules/sql/blacklistusers_sql.py
deleted file mode 100644
index 391b70d5..00000000
--- a/Exon/modules/sql/blacklistusers_sql.py
+++ /dev/null
@@ -1,93 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import threading
-
-from sqlalchemy import Column, String, UnicodeText
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class BlacklistUsers(BASE):
- __tablename__ = "blacklistusers"
- user_id = Column(String(14), primary_key=True)
- reason = Column(UnicodeText)
-
- def __init__(self, user_id, reason=None):
- self.user_id = user_id
- self.reason = reason
-
-
-BlacklistUsers.__table__.create(checkfirst=True)
-
-BLACKLIST_LOCK = threading.RLock()
-BLACKLIST_USERS = set()
-
-
-def blacklist_user(user_id, reason=None):
- with BLACKLIST_LOCK:
- user = SESSION.query(BlacklistUsers).get(str(user_id))
- if not user:
- user = BlacklistUsers(str(user_id), reason)
- else:
- user.reason = reason
-
- SESSION.add(user)
- SESSION.commit()
- __load_blacklist_userid_list()
-
-
-def unblacklist_user(user_id):
- with BLACKLIST_LOCK:
- if user := SESSION.query(BlacklistUsers).get(str(user_id)):
- SESSION.delete(user)
-
- SESSION.commit()
- __load_blacklist_userid_list()
-
-
-def get_reason(user_id):
- user = SESSION.query(BlacklistUsers).get(str(user_id))
- rep = user.reason if user else ""
- SESSION.close()
- return rep
-
-
-def is_user_blacklisted(user_id):
- return user_id in BLACKLIST_USERS
-
-
-def __load_blacklist_userid_list():
- global BLACKLIST_USERS
- try:
- BLACKLIST_USERS = {int(x.user_id) for x in SESSION.query(BlacklistUsers).all()}
- finally:
- SESSION.close()
-
-
-__load_blacklist_userid_list()
diff --git a/Exon/modules/sql/blsticker_sql.py b/Exon/modules/sql/blsticker_sql.py
deleted file mode 100644
index b8703048..00000000
--- a/Exon/modules/sql/blsticker_sql.py
+++ /dev/null
@@ -1,220 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Column, Integer, String, UnicodeText, distinct, func
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class StickersFilters(BASE):
- __tablename__ = "blacklist_stickers"
- chat_id = Column(String(14), primary_key=True)
- trigger = Column(UnicodeText, primary_key=True, nullable=False)
-
- def __init__(self, chat_id, trigger):
- self.chat_id = str(chat_id) # ensure string
- self.trigger = trigger
-
- def __repr__(self):
- return f""
-
- def __eq__(self, other):
- return (
- isinstance(other, StickersFilters)
- and self.chat_id == other.chat_id
- and self.trigger == other.trigger
- )
-
-
-class StickerSettings(BASE):
- __tablename__ = "blsticker_settings"
- chat_id = Column(String(14), primary_key=True)
- blacklist_type = Column(Integer, default=1)
- value = Column(UnicodeText, default="0")
-
- def __init__(self, chat_id, blacklist_type=1, value="0"):
- self.chat_id = str(chat_id)
- self.blacklist_type = blacklist_type
- self.value = value
-
- def __repr__(self):
- return f"<{self.chat_id} will executing {self.blacklist_type} for blacklist trigger.>"
-
-
-StickersFilters.__table__.create(checkfirst=True)
-StickerSettings.__table__.create(checkfirst=True)
-
-STICKERS_FILTER_INSERTION_LOCK = threading.RLock()
-STICKSET_FILTER_INSERTION_LOCK = threading.RLock()
-
-CHAT_STICKERS = {}
-CHAT_BLSTICK_BLACKLISTS = {}
-
-
-def add_to_stickers(chat_id, trigger):
- with STICKERS_FILTER_INSERTION_LOCK:
- stickers_filt = StickersFilters(str(chat_id), trigger)
-
- SESSION.merge(stickers_filt) # merge to avoid duplicate key issues
- SESSION.commit()
- if CHAT_STICKERS.get(str(chat_id), set()) == set():
- CHAT_STICKERS[str(chat_id)] = {trigger}
- else:
- CHAT_STICKERS.get(str(chat_id), set()).add(trigger)
-
-
-def rm_from_stickers(chat_id, trigger):
- with STICKERS_FILTER_INSERTION_LOCK:
- if stickers_filt := SESSION.query(StickersFilters).get(
- (str(chat_id), trigger)
- ):
- if trigger in CHAT_STICKERS.get(str(chat_id), set()): # sanity check
- CHAT_STICKERS.get(str(chat_id), set()).remove(trigger)
-
- SESSION.delete(stickers_filt)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def get_chat_stickers(chat_id):
- return CHAT_STICKERS.get(str(chat_id), set())
-
-
-def num_stickers_filters():
- try:
- return SESSION.query(StickersFilters).count()
- finally:
- SESSION.close()
-
-
-def num_stickers_chat_filters(chat_id):
- try:
- return (
- SESSION.query(StickersFilters.chat_id)
- .filter(StickersFilters.chat_id == str(chat_id))
- .count()
- )
- finally:
- SESSION.close()
-
-
-def num_stickers_filter_chats():
- try:
- return SESSION.query(func.count(distinct(StickersFilters.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def set_blacklist_strength(chat_id, blacklist_type, value):
- # for blacklist_type
- # 0 = nothing
- # 1 = delete
- # 2 = warn
- # 3 = mute
- # 4 = kick
- # 5 = ban
- # 6 = tban
- # 7 = tmute
- with STICKSET_FILTER_INSERTION_LOCK:
- curr_setting = SESSION.query(StickerSettings).get(str(chat_id)) or StickerSettings(
- chat_id,
- blacklist_type=int(blacklist_type),
- value=value,
- )
-
- curr_setting.blacklist_type = int(blacklist_type)
- curr_setting.value = str(value)
- CHAT_BLSTICK_BLACKLISTS[str(chat_id)] = {
- "blacklist_type": int(blacklist_type),
- "value": value,
- }
-
- SESSION.add(curr_setting)
- SESSION.commit()
-
-
-def get_blacklist_setting(chat_id):
- try:
- if setting := CHAT_BLSTICK_BLACKLISTS.get(str(chat_id)):
- return setting["blacklist_type"], setting["value"]
- return 1, "0"
-
- finally:
- SESSION.close()
-
-
-def __load_CHAT_STICKERS():
- global CHAT_STICKERS
- try:
- chats = SESSION.query(StickersFilters.chat_id).distinct().all()
- for (chat_id,) in chats: # remove tuple by ( ,)
- CHAT_STICKERS[chat_id] = []
-
- all_filters = SESSION.query(StickersFilters).all()
- for x in all_filters:
- CHAT_STICKERS[x.chat_id] += [x.trigger]
-
- CHAT_STICKERS = {x: set(y) for x, y in CHAT_STICKERS.items()}
-
- finally:
- SESSION.close()
-
-
-def __load_chat_stickerset_blacklists():
- try:
- chats_settings = SESSION.query(StickerSettings).all()
- for x in chats_settings: # remove tuple by ( ,)
- CHAT_BLSTICK_BLACKLISTS[x.chat_id] = {
- "blacklist_type": x.blacklist_type,
- "value": x.value,
- }
-
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with STICKERS_FILTER_INSERTION_LOCK:
- chat_filters = (
- SESSION.query(StickersFilters)
- .filter(StickersFilters.chat_id == str(old_chat_id))
- .all()
- )
- for filt in chat_filters:
- filt.chat_id = str(new_chat_id)
- SESSION.commit()
-
-
-__load_CHAT_STICKERS()
-__load_chat_stickerset_blacklists()
diff --git a/Exon/modules/sql/cleaner_sql.py b/Exon/modules/sql/cleaner_sql.py
deleted file mode 100644
index c425cbfd..00000000
--- a/Exon/modules/sql/cleaner_sql.py
+++ /dev/null
@@ -1,225 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Boolean, Column, UnicodeText
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class CleanerBlueTextChatSettings(BASE):
- __tablename__ = "cleaner_bluetext_chat_setting"
- chat_id = Column(UnicodeText, primary_key=True)
- is_enable = Column(Boolean, default=False)
-
- def __init__(self, chat_id, is_enable):
- self.chat_id = chat_id
- self.is_enable = is_enable
-
- def __repr__(self):
- return f"clean blue text for {self.chat_id}"
-
-
-class CleanerBlueTextChat(BASE):
- __tablename__ = "cleaner_bluetext_chat_ignore_commands"
- chat_id = Column(UnicodeText, primary_key=True)
- command = Column(UnicodeText, primary_key=True)
-
- def __init__(self, chat_id, command):
- self.chat_id = chat_id
- self.command = command
-
-
-class CleanerBlueTextGlobal(BASE):
- __tablename__ = "cleaner_bluetext_global_ignore_commands"
- command = Column(UnicodeText, primary_key=True)
-
- def __init__(self, command):
- self.command = command
-
-
-CleanerBlueTextChatSettings.__table__.create(checkfirst=True)
-CleanerBlueTextChat.__table__.create(checkfirst=True)
-CleanerBlueTextGlobal.__table__.create(checkfirst=True)
-
-CLEANER_CHAT_SETTINGS = threading.RLock()
-CLEANER_CHAT_LOCK = threading.RLock()
-CLEANER_GLOBAL_LOCK = threading.RLock()
-
-CLEANER_CHATS = {}
-GLOBAL_IGNORE_COMMANDS = set()
-
-
-def set_cleanbt(chat_id, is_enable):
- with CLEANER_CHAT_SETTINGS:
- if curr := SESSION.query(CleanerBlueTextChatSettings).get(
- str(chat_id)
- ):
- SESSION.delete(curr)
-
- newcurr = CleanerBlueTextChatSettings(str(chat_id), is_enable)
-
- SESSION.add(newcurr)
- SESSION.commit()
-
-
-def chat_ignore_command(chat_id, ignore):
- ignore = ignore.lower()
- with CLEANER_CHAT_LOCK:
- ignored = SESSION.query(CleanerBlueTextChat).get((str(chat_id), ignore))
-
- if not ignored:
- if str(chat_id) not in CLEANER_CHATS:
- CLEANER_CHATS.setdefault(
- str(chat_id), {"setting": False, "commands": set()}
- )
-
- CLEANER_CHATS[str(chat_id)]["commands"].add(ignore)
-
- ignored = CleanerBlueTextChat(str(chat_id), ignore)
- SESSION.add(ignored)
- SESSION.commit()
- return True
- SESSION.close()
- return False
-
-
-def chat_unignore_command(chat_id, unignore):
- unignore = unignore.lower()
- with CLEANER_CHAT_LOCK:
- if unignored := SESSION.query(CleanerBlueTextChat).get(
- (str(chat_id), unignore)
- ):
- if str(chat_id) not in CLEANER_CHATS:
- CLEANER_CHATS.setdefault(
- str(chat_id), {"setting": False, "commands": set()}
- )
- if unignore in CLEANER_CHATS.get(str(chat_id)).get("commands"):
- CLEANER_CHATS[str(chat_id)]["commands"].remove(unignore)
-
- SESSION.delete(unignored)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def global_ignore_command(command):
- command = command.lower()
- with CLEANER_GLOBAL_LOCK:
- ignored = SESSION.query(CleanerBlueTextGlobal).get(str(command))
-
- if not ignored:
- GLOBAL_IGNORE_COMMANDS.add(command)
-
- ignored = CleanerBlueTextGlobal(str(command))
- SESSION.add(ignored)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def global_unignore_command(command):
- command = command.lower()
- with CLEANER_GLOBAL_LOCK:
- if unignored := SESSION.query(CleanerBlueTextGlobal).get(str(command)):
- if command in GLOBAL_IGNORE_COMMANDS:
- GLOBAL_IGNORE_COMMANDS.remove(command)
-
- SESSION.delete(command)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def is_command_ignored(chat_id, command):
- if command.lower() in GLOBAL_IGNORE_COMMANDS:
- return True
-
- return str(
- chat_id
- ) in CLEANER_CHATS and command.lower() in CLEANER_CHATS.get(
- str(chat_id)
- ).get(
- "commands"
- )
-
-
-def is_enabled(chat_id):
- try:
- if resultcurr := SESSION.query(CleanerBlueTextChatSettings).get(
- str(chat_id)
- ):
- return resultcurr.is_enable
- return False # default
- finally:
- SESSION.close()
-
-
-def get_all_ignored(chat_id):
- if str(chat_id) in CLEANER_CHATS:
- LOCAL_IGNORE_COMMANDS = CLEANER_CHATS.get(str(chat_id)).get("commands")
- else:
- LOCAL_IGNORE_COMMANDS = set()
-
- return GLOBAL_IGNORE_COMMANDS, LOCAL_IGNORE_COMMANDS
-
-
-def __load_cleaner_list():
- global GLOBAL_IGNORE_COMMANDS
-
- try:
- GLOBAL_IGNORE_COMMANDS = {
- x.command for x in SESSION.query(CleanerBlueTextGlobal).all()
- }
- finally:
- SESSION.close()
-
- try:
- for x in SESSION.query(CleanerBlueTextChatSettings).all():
- CLEANER_CHATS.setdefault(x.chat_id, {"setting": False, "commands": set()})
- CLEANER_CHATS[x.chat_id]["setting"] = x.is_enable
- finally:
- SESSION.close()
-
- try:
- for x in SESSION.query(CleanerBlueTextChat).all():
- CLEANER_CHATS.setdefault(x.chat_id, {"setting": False, "commands": set()})
- CLEANER_CHATS[x.chat_id]["commands"].add(x.command)
- finally:
- SESSION.close()
-
-
-__load_cleaner_list()
diff --git a/Exon/modules/sql/clear_cmd_sql.py b/Exon/modules/sql/clear_cmd_sql.py
deleted file mode 100644
index 71cc6732..00000000
--- a/Exon/modules/sql/clear_cmd_sql.py
+++ /dev/null
@@ -1,113 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Column, Integer, String, UnicodeText
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class ClearCmd(BASE):
- __tablename__ = "clear_cmd"
- chat_id = Column(String(14), primary_key=True)
- cmd = Column(UnicodeText, primary_key=True, nullable=False)
- time = Column(Integer)
-
- def __init__(self, chat_id, cmd, time):
- self.chat_id = chat_id
- self.cmd = cmd
- self.time = time
-
-
-ClearCmd.__table__.create(checkfirst=True)
-
-CLEAR_CMD_LOCK = threading.RLock()
-
-
-def get_allclearcmd(chat_id):
- try:
- return SESSION.query(ClearCmd).filter(ClearCmd.chat_id == str(chat_id)).all()
- finally:
- SESSION.close()
-
-
-def get_clearcmd(chat_id, cmd):
- try:
- if clear_cmd := SESSION.query(ClearCmd).get((str(chat_id), cmd)):
- return clear_cmd
- return False
- finally:
- SESSION.close()
-
-
-def set_clearcmd(chat_id, cmd, time):
- with CLEAR_CMD_LOCK:
- clear_cmd = SESSION.query(ClearCmd).get((str(chat_id), cmd)) or ClearCmd(str(chat_id), cmd, time)
-
- clear_cmd.time = time
- SESSION.add(clear_cmd)
- SESSION.commit()
-
-
-def del_clearcmd(chat_id, cmd):
- with CLEAR_CMD_LOCK:
- if del_cmd := SESSION.query(ClearCmd).get((str(chat_id), cmd)):
- SESSION.delete(del_cmd)
- SESSION.commit()
- return True
- else:
- SESSION.close()
- return False
-
-
-def del_allclearcmd(chat_id):
- with CLEAR_CMD_LOCK:
- if (
- del_cmd := SESSION.query(ClearCmd)
- .filter(ClearCmd.chat_id == str(chat_id))
- .all()
- ):
- for cmd in del_cmd:
- SESSION.delete(cmd)
- SESSION.commit()
- return True
- else:
- SESSION.close()
- return False
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with CLEAR_CMD_LOCK:
- chat_filters = (
- SESSION.query(ClearCmd).filter(ClearCmd.chat_id == str(old_chat_id)).all()
- )
- for filt in chat_filters:
- filt.chat_id = str(new_chat_id)
- SESSION.commit()
diff --git a/Exon/modules/sql/connection_sql.py b/Exon/modules/sql/connection_sql.py
deleted file mode 100644
index b6f4d006..00000000
--- a/Exon/modules/sql/connection_sql.py
+++ /dev/null
@@ -1,230 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import threading
-import time
-from typing import Union
-
-from sqlalchemy import Boolean, Column, Integer, String, UnicodeText
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class ChatAccessConnectionSettings(BASE):
- __tablename__ = "access_connection"
- chat_id = Column(String(14), primary_key=True)
- allow_connect_to_chat = Column(Boolean, default=True)
-
- def __init__(self, chat_id, allow_connect_to_chat):
- self.chat_id = str(chat_id)
- self.allow_connect_to_chat = str(allow_connect_to_chat)
-
- def __repr__(self):
- return f""
-
-
-class Connection(BASE):
- __tablename__ = "connection"
- user_id = Column(BigInteger, primary_key=True)
- chat_id = Column(String(14))
-
- def __init__(self, user_id, chat_id):
- self.user_id = user_id
- self.chat_id = str(chat_id) # Ensure String
-
-
-class ConnectionHistory(BASE):
- __tablename__ = "connection_history"
- user_id = Column(BigInteger, primary_key=True)
- chat_id = Column(String(14), primary_key=True)
- chat_name = Column(UnicodeText)
- conn_time = Column(Integer)
-
- def __init__(self, user_id, chat_id, chat_name, conn_time):
- self.user_id = user_id
- self.chat_id = str(chat_id)
- self.chat_name = str(chat_name)
- self.conn_time = int(conn_time)
-
- def __repr__(self):
- return f""
-
-
-ChatAccessConnectionSettings.__table__.create(checkfirst=True)
-Connection.__table__.create(checkfirst=True)
-ConnectionHistory.__table__.create(checkfirst=True)
-
-CHAT_ACCESS_LOCK = threading.RLock()
-CONNECTION_INSERTION_LOCK = threading.RLock()
-CONNECTION_HISTORY_LOCK = threading.RLock()
-
-HISTORY_CONNECT = {}
-
-
-def allow_connect_to_chat(chat_id: Union[str, int]) -> bool:
- try:
- if chat_setting := SESSION.query(ChatAccessConnectionSettings).get(
- str(chat_id)
- ):
- return chat_setting.allow_connect_to_chat
- return False
- finally:
- SESSION.close()
-
-
-def set_allow_connect_to_chat(chat_id: Union[int, str], setting: bool):
- with CHAT_ACCESS_LOCK:
- chat_setting = SESSION.query(ChatAccessConnectionSettings).get(str(chat_id)) or ChatAccessConnectionSettings(
- chat_id, setting)
-
- chat_setting.allow_connect_to_chat = setting
- SESSION.add(chat_setting)
- SESSION.commit()
-
-
-def connect(user_id, chat_id):
- with CONNECTION_INSERTION_LOCK:
- if prev := SESSION.query(Connection).get((int(user_id))):
- SESSION.delete(prev)
- connect_to_chat = Connection(int(user_id), chat_id)
- SESSION.add(connect_to_chat)
- SESSION.commit()
- return True
-
-
-def get_connected_chat(user_id):
- try:
- return SESSION.query(Connection).get((int(user_id)))
- finally:
- SESSION.close()
-
-
-def curr_connection(chat_id):
- try:
- return SESSION.query(Connection).get((str(chat_id)))
- finally:
- SESSION.close()
-
-
-def disconnect(user_id):
- with CONNECTION_INSERTION_LOCK:
- if disconnect := SESSION.query(Connection).get((int(user_id))):
- SESSION.delete(disconnect)
- SESSION.commit()
- return True
- SESSION.close()
- return False
-
-
-def add_history_conn(user_id, chat_id, chat_name):
- with CONNECTION_HISTORY_LOCK:
- conn_time = int(time.time())
- if HISTORY_CONNECT.get(int(user_id)):
- counting = (
- SESSION.query(ConnectionHistory.user_id)
- .filter(ConnectionHistory.user_id == str(user_id))
- .count()
- )
- getchat_id = {
- HISTORY_CONNECT[int(user_id)][x]["chat_id"]: x
- for x in HISTORY_CONNECT[int(user_id)]
- }
-
- if chat_id in getchat_id:
- todeltime = getchat_id[str(chat_id)]
- if delold := SESSION.query(ConnectionHistory).get(
- (int(user_id), str(chat_id)),
- ):
- SESSION.delete(delold)
- HISTORY_CONNECT[int(user_id)].pop(todeltime)
- elif counting >= 5:
- todel = list(HISTORY_CONNECT[int(user_id)])
- todel.reverse()
- todel = todel[4:]
- for x in todel:
- chat_old = HISTORY_CONNECT[int(user_id)][x]["chat_id"]
- if delold := SESSION.query(ConnectionHistory).get(
- (int(user_id), str(chat_old)),
- ):
- SESSION.delete(delold)
- HISTORY_CONNECT[int(user_id)].pop(x)
- else:
- HISTORY_CONNECT[int(user_id)] = {}
- if delold := SESSION.query(ConnectionHistory).get(
- (int(user_id), str(chat_id))
- ):
- SESSION.delete(delold)
- history = ConnectionHistory(int(user_id), str(chat_id), chat_name, conn_time)
- SESSION.add(history)
- SESSION.commit()
- HISTORY_CONNECT[int(user_id)][conn_time] = {
- "chat_name": chat_name,
- "chat_id": str(chat_id),
- }
-
-
-def get_history_conn(user_id):
- if not HISTORY_CONNECT.get(int(user_id)):
- HISTORY_CONNECT[int(user_id)] = {}
- return HISTORY_CONNECT[int(user_id)]
-
-
-def clear_history_conn(user_id):
- todel = list(HISTORY_CONNECT[int(user_id)])
- for x in todel:
- chat_old = HISTORY_CONNECT[int(user_id)][x]["chat_id"]
- if delold := SESSION.query(ConnectionHistory).get(
- (int(user_id), str(chat_old))
- ):
- SESSION.delete(delold)
- HISTORY_CONNECT[int(user_id)].pop(x)
- SESSION.commit()
- return True
-
-
-def __load_user_history():
- global HISTORY_CONNECT
- try:
- qall = SESSION.query(ConnectionHistory).all()
- HISTORY_CONNECT = {}
- for x in qall:
- check = HISTORY_CONNECT.get(x.user_id)
- if check is None:
- HISTORY_CONNECT[x.user_id] = {}
- HISTORY_CONNECT[x.user_id][x.conn_time] = {
- "chat_name": x.chat_name,
- "chat_id": x.chat_id,
- }
- finally:
- SESSION.close()
-
-
-__load_user_history()
diff --git a/Exon/modules/sql/cust_filters_sql.py b/Exon/modules/sql/cust_filters_sql.py
deleted file mode 100644
index c8aac78d..00000000
--- a/Exon/modules/sql/cust_filters_sql.py
+++ /dev/null
@@ -1,430 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import threading
-
-from sqlalchemy import Boolean, Column, Integer, String, UnicodeText, distinct, func
-
-from Exon.modules.helper_funcs.msg_types import Types
-from Exon.modules.sql import BASE, SESSION
-
-
-class CustomFilters(BASE):
- __tablename__ = "cust_filters"
- chat_id = Column(String(14), primary_key=True)
- keyword = Column(UnicodeText, primary_key=True, nullable=False)
- reply = Column(UnicodeText, nullable=False)
- is_sticker = Column(Boolean, nullable=False, default=False)
- is_document = Column(Boolean, nullable=False, default=False)
- is_image = Column(Boolean, nullable=False, default=False)
- is_audio = Column(Boolean, nullable=False, default=False)
- is_voice = Column(Boolean, nullable=False, default=False)
- is_video = Column(Boolean, nullable=False, default=False)
-
- has_buttons = Column(Boolean, nullable=False, default=False)
- # NOTE: Here for legacy purposes, to ensure older filters don't mess up.
- has_markdown = Column(Boolean, nullable=False, default=False)
-
- # NEW FILTER
- # alter table cust_filters add column reply_text text;
- # alter table cust_filters add column file_type integer default 1;
- # alter table cust_filters add column file_id text;
- reply_text = Column(UnicodeText)
- file_type = Column(Integer, nullable=False, default=1)
- file_id = Column(UnicodeText, default=None)
-
- def __init__(
- self,
- chat_id,
- keyword,
- reply,
- is_sticker=False,
- is_document=False,
- is_image=False,
- is_audio=False,
- is_voice=False,
- is_video=False,
- has_buttons=False,
- reply_text=None,
- file_type=1,
- file_id=None,
- ):
- self.chat_id = str(chat_id) # ensure string
- self.keyword = keyword
- self.reply = reply
- self.is_sticker = is_sticker
- self.is_document = is_document
- self.is_image = is_image
- self.is_audio = is_audio
- self.is_voice = is_voice
- self.is_video = is_video
- self.has_buttons = has_buttons
- self.has_markdown = True
-
- self.reply_text = reply_text
- self.file_type = file_type
- self.file_id = file_id
-
- def __repr__(self):
- return f""
-
- def __eq__(self, other):
- return (
- isinstance(other, CustomFilters)
- and self.chat_id == other.chat_id
- and self.keyword == other.keyword
- )
-
-
-class NewCustomFilters(BASE):
- __tablename__ = "cust_filters_new"
- chat_id = Column(String(14), primary_key=True)
- keyword = Column(UnicodeText, primary_key=True, nullable=False)
- text = Column(UnicodeText)
- file_type = Column(Integer, nullable=False, default=1)
- file_id = Column(UnicodeText, default=None)
-
- def __init__(self, chat_id, keyword, text, file_type, file_id):
- self.chat_id = str(chat_id) # ensure string
- self.keyword = keyword
- self.text = text
- self.file_type = file_type
- self.file_id = file_id
-
- def __repr__(self):
- return f""
-
- def __eq__(self, other):
- return (
- isinstance(other, CustomFilters)
- and self.chat_id == other.chat_id
- and self.keyword == other.keyword
- )
-
-
-class Buttons(BASE):
- __tablename__ = "cust_filter_urls"
- id = Column(Integer, primary_key=True, autoincrement=True)
- chat_id = Column(String(14), primary_key=True)
- keyword = Column(UnicodeText, primary_key=True)
- name = Column(UnicodeText, nullable=False)
- url = Column(UnicodeText, nullable=False)
- same_line = Column(Boolean, default=False)
-
- def __init__(self, chat_id, keyword, name, url, same_line=False):
- self.chat_id = str(chat_id)
- self.keyword = keyword
- self.name = name
- self.url = url
- self.same_line = same_line
-
-
-CustomFilters.__table__.create(checkfirst=True)
-Buttons.__table__.create(checkfirst=True)
-
-CUST_FILT_LOCK = threading.RLock()
-BUTTON_LOCK = threading.RLock()
-CHAT_FILTERS = {}
-
-
-def get_all_filters():
- try:
- return SESSION.query(CustomFilters).all()
- finally:
- SESSION.close()
-
-
-def add_filter(
- chat_id,
- keyword,
- reply,
- is_sticker=False,
- is_document=False,
- is_image=False,
- is_audio=False,
- is_voice=False,
- is_video=False,
- buttons=None,
-):
- if buttons is None:
- buttons = []
-
- with CUST_FILT_LOCK:
- if prev := SESSION.query(CustomFilters).get((str(chat_id), keyword)):
- with BUTTON_LOCK:
- prev_buttons = (
- SESSION.query(Buttons)
- .filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
- .all()
- )
- for btn in prev_buttons:
- SESSION.delete(btn)
- SESSION.delete(prev)
-
- filt = CustomFilters(
- str(chat_id),
- keyword,
- reply,
- is_sticker,
- is_document,
- is_image,
- is_audio,
- is_voice,
- is_video,
- bool(buttons),
- )
-
- if keyword not in CHAT_FILTERS.get(str(chat_id), []):
- CHAT_FILTERS[str(chat_id)] = sorted(
- CHAT_FILTERS.get(str(chat_id), []) + [keyword],
- key=lambda x: (-len(x), x),
- )
-
- SESSION.add(filt)
- SESSION.commit()
-
- for b_name, url, same_line in buttons:
- add_note_button_to_db(chat_id, keyword, b_name, url, same_line)
-
-
-def new_add_filter(chat_id, keyword, reply_text, file_type, file_id, buttons):
- if buttons is None:
- buttons = []
-
- with CUST_FILT_LOCK:
- if prev := SESSION.query(CustomFilters).get((str(chat_id), keyword)):
- with BUTTON_LOCK:
- prev_buttons = (
- SESSION.query(Buttons)
- .filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
- .all()
- )
- for btn in prev_buttons:
- SESSION.delete(btn)
- SESSION.delete(prev)
-
- filt = CustomFilters(
- str(chat_id),
- keyword,
- reply="there is should be a new reply",
- is_sticker=False,
- is_document=False,
- is_image=False,
- is_audio=False,
- is_voice=False,
- is_video=False,
- has_buttons=bool(buttons),
- reply_text=reply_text,
- file_type=file_type.value,
- file_id=file_id,
- )
-
- if keyword not in CHAT_FILTERS.get(str(chat_id), []):
- CHAT_FILTERS[str(chat_id)] = sorted(
- CHAT_FILTERS.get(str(chat_id), []) + [keyword],
- key=lambda x: (-len(x), x),
- )
-
- SESSION.add(filt)
- SESSION.commit()
-
- for b_name, url, same_line in buttons:
- add_note_button_to_db(chat_id, keyword, b_name, url, same_line)
-
-
-def remove_filter(chat_id, keyword):
- with CUST_FILT_LOCK:
- if filt := SESSION.query(CustomFilters).get((str(chat_id), keyword)):
- if keyword in CHAT_FILTERS.get(str(chat_id), []): # Sanity check
- CHAT_FILTERS.get(str(chat_id), []).remove(keyword)
-
- with BUTTON_LOCK:
- prev_buttons = (
- SESSION.query(Buttons)
- .filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
- .all()
- )
- for btn in prev_buttons:
- SESSION.delete(btn)
-
- SESSION.delete(filt)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def get_chat_triggers(chat_id):
- return CHAT_FILTERS.get(str(chat_id), set())
-
-
-def get_chat_filters(chat_id):
- try:
- return (
- SESSION.query(CustomFilters)
- .filter(CustomFilters.chat_id == str(chat_id))
- .order_by(func.length(CustomFilters.keyword).desc())
- .order_by(CustomFilters.keyword.asc())
- .all()
- )
- finally:
- SESSION.close()
-
-
-def get_filter(chat_id, keyword):
- try:
- return SESSION.query(CustomFilters).get((str(chat_id), keyword))
- finally:
- SESSION.close()
-
-
-def add_note_button_to_db(chat_id, keyword, b_name, url, same_line):
- with BUTTON_LOCK:
- button = Buttons(chat_id, keyword, b_name, url, same_line)
- SESSION.add(button)
- SESSION.commit()
-
-
-def get_buttons(chat_id, keyword):
- try:
- return (
- SESSION.query(Buttons)
- .filter(Buttons.chat_id == str(chat_id), Buttons.keyword == keyword)
- .order_by(Buttons.id)
- .all()
- )
- finally:
- SESSION.close()
-
-
-def num_filters():
- try:
- return SESSION.query(CustomFilters).count()
- finally:
- SESSION.close()
-
-
-def num_chats():
- try:
- return SESSION.query(func.count(distinct(CustomFilters.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def __load_chat_filters():
- global CHAT_FILTERS
- try:
- chats = SESSION.query(CustomFilters.chat_id).distinct().all()
- for (chat_id,) in chats: # remove tuple by ( ,)
- CHAT_FILTERS[chat_id] = []
-
- all_filters = SESSION.query(CustomFilters).all()
- for x in all_filters:
- CHAT_FILTERS[x.chat_id] += [x.keyword]
-
- CHAT_FILTERS = {
- x: sorted(set(y), key=lambda i: (-len(i), i))
- for x, y in CHAT_FILTERS.items()
- }
-
- finally:
- SESSION.close()
-
-
-# ONLY USE FOR MIGRATE OLD FILTERS TO NEW FILTERS
-def __migrate_filters():
- try:
- all_filters = SESSION.query(CustomFilters).distinct().all()
- for x in all_filters:
- if x.is_document:
- file_type = Types.DOCUMENT
- elif x.is_image:
- file_type = Types.PHOTO
- elif x.is_video:
- file_type = Types.VIDEO
- elif x.is_sticker:
- file_type = Types.STICKER
- elif x.is_audio:
- file_type = Types.AUDIO
- elif x.is_voice:
- file_type = Types.VOICE
- else:
- file_type = Types.TEXT
-
- print(x.chat_id, x.keyword, x.reply, file_type.value)
- if file_type == Types.TEXT:
- filt = CustomFilters(
- str(x.chat_id),
- x.keyword,
- x.reply,
- file_type.value,
- None,
- )
- else:
- filt = CustomFilters(
- str(x.chat_id),
- x.keyword,
- None,
- file_type.value,
- x.reply,
- )
-
- SESSION.add(filt)
- SESSION.commit()
-
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with CUST_FILT_LOCK:
- chat_filters = (
- SESSION.query(CustomFilters)
- .filter(CustomFilters.chat_id == str(old_chat_id))
- .all()
- )
- for filt in chat_filters:
- filt.chat_id = str(new_chat_id)
- SESSION.commit()
- if old_filt := CHAT_FILTERS.get(str(old_chat_id)):
- CHAT_FILTERS[str(new_chat_id)] = old_filt
- del CHAT_FILTERS[str(old_chat_id)]
-
- with BUTTON_LOCK:
- chat_buttons = (
- SESSION.query(Buttons).filter(Buttons.chat_id == str(old_chat_id)).all()
- )
- for btn in chat_buttons:
- btn.chat_id = str(new_chat_id)
- SESSION.commit()
-
-
-__load_chat_filters()
diff --git a/Exon/modules/sql/disable_sql.py b/Exon/modules/sql/disable_sql.py
deleted file mode 100644
index 4585d440..00000000
--- a/Exon/modules/sql/disable_sql.py
+++ /dev/null
@@ -1,131 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Column, String, UnicodeText, distinct, func
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class Disable(BASE):
- __tablename__ = "disabled_commands"
- chat_id = Column(String(14), primary_key=True)
- command = Column(UnicodeText, primary_key=True)
-
- def __init__(self, chat_id, command):
- self.chat_id = chat_id
- self.command = command
-
- def __repr__(self):
- return f"Disabled cmd {self.command} in {self.chat_id}"
-
-
-Disable.__table__.create(checkfirst=True)
-DISABLE_INSERTION_LOCK = threading.RLock()
-
-DISABLED = {}
-
-
-def disable_command(chat_id, disable):
- with DISABLE_INSERTION_LOCK:
- disabled = SESSION.query(Disable).get((str(chat_id), disable))
-
- if not disabled:
- DISABLED.setdefault(str(chat_id), set()).add(disable)
-
- disabled = Disable(str(chat_id), disable)
- SESSION.add(disabled)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def enable_command(chat_id, enable):
- with DISABLE_INSERTION_LOCK:
- if disabled := SESSION.query(Disable).get((str(chat_id), enable)):
- if enable in DISABLED.get(str(chat_id)): # sanity check
- DISABLED.setdefault(str(chat_id), set()).remove(enable)
-
- SESSION.delete(disabled)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def is_command_disabled(chat_id, cmd):
- return str(cmd).lower() in DISABLED.get(str(chat_id), set())
-
-
-def get_all_disabled(chat_id):
- return DISABLED.get(str(chat_id), set())
-
-
-def num_chats():
- try:
- return SESSION.query(func.count(distinct(Disable.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def num_disabled():
- try:
- return SESSION.query(Disable).count()
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with DISABLE_INSERTION_LOCK:
- chats = SESSION.query(Disable).filter(Disable.chat_id == str(old_chat_id)).all()
- for chat in chats:
- chat.chat_id = str(new_chat_id)
- SESSION.add(chat)
-
- if str(old_chat_id) in DISABLED:
- DISABLED[str(new_chat_id)] = DISABLED.get(str(old_chat_id), set())
-
- SESSION.commit()
-
-
-def __load_disabled_commands():
- try:
- all_chats = SESSION.query(Disable).all()
- for chat in all_chats:
- DISABLED.setdefault(chat.chat_id, set()).add(chat.command)
-
- finally:
- SESSION.close()
-
-
-__load_disabled_commands()
diff --git a/Exon/modules/sql/feds_sql.py b/Exon/modules/sql/feds_sql.py
deleted file mode 100644
index 0fcf06c7..00000000
--- a/Exon/modules/sql/feds_sql.py
+++ /dev/null
@@ -1,885 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import ast
-import threading
-
-from sqlalchemy import Boolean, Column, Integer, String, UnicodeText
-from sqlalchemy.sql.sqltypes import BigInteger
-from telegram.error import BadRequest, Unauthorized
-
-from Exon import dispatcher
-from Exon.modules.sql import BASE, SESSION
-
-
-class Federations(BASE):
- __tablename__ = "feds"
- owner_id = Column(String(14))
- fed_name = Column(UnicodeText)
- fed_id = Column(UnicodeText, primary_key=True)
- fed_rules = Column(UnicodeText)
- fed_log = Column(UnicodeText)
- fed_users = Column(UnicodeText)
-
- def __init__(self, owner_id, fed_name, fed_id, fed_rules, fed_log, fed_users):
- self.owner_id = owner_id
- self.fed_name = fed_name
- self.fed_id = fed_id
- self.fed_rules = fed_rules
- self.fed_log = fed_log
- self.fed_users = fed_users
-
-
-class ChatF(BASE):
- __tablename__ = "chat_feds"
- chat_id = Column(String(14), primary_key=True)
- chat_name = Column(UnicodeText)
- fed_id = Column(UnicodeText)
-
- def __init__(self, chat_id, chat_name, fed_id):
- self.chat_id = chat_id
- self.chat_name = chat_name
- self.fed_id = fed_id
-
-
-class BansF(BASE):
- __tablename__ = "bans_feds"
- fed_id = Column(UnicodeText, primary_key=True)
- user_id = Column(String(14), primary_key=True)
- first_name = Column(UnicodeText, nullable=False)
- last_name = Column(UnicodeText)
- user_name = Column(UnicodeText)
- reason = Column(UnicodeText, default="")
- time = Column(Integer, default=0)
-
- def __init__(self, fed_id, user_id, first_name, last_name, user_name, reason, time):
- self.fed_id = fed_id
- self.user_id = user_id
- self.first_name = first_name
- self.last_name = last_name
- self.user_name = user_name
- self.reason = reason
- self.time = time
-
-
-class FedsUserSettings(BASE):
- __tablename__ = "feds_settings"
- user_id = Column(BigInteger, primary_key=True)
- should_report = Column(Boolean, default=True)
-
- def __init__(self, user_id):
- self.user_id = user_id
-
- def __repr__(self):
- return f""
-
-
-class FedSubs(BASE):
- __tablename__ = "feds_subs"
- fed_id = Column(UnicodeText, primary_key=True)
- fed_subs = Column(UnicodeText, primary_key=True, nullable=False)
-
- def __init__(self, fed_id, fed_subs):
- self.fed_id = fed_id
- self.fed_subs = fed_subs
-
- def __repr__(self):
- return f""
-
-
-# Dropping db
-# Federations.__table__.drop()
-# ChatF.__table__.drop()
-# BansF.__table__.drop()
-# FedSubs.__table__.drop()
-
-Federations.__table__.create(checkfirst=True)
-ChatF.__table__.create(checkfirst=True)
-BansF.__table__.create(checkfirst=True)
-FedsUserSettings.__table__.create(checkfirst=True)
-FedSubs.__table__.create(checkfirst=True)
-
-FEDS_LOCK = threading.RLock()
-CHAT_FEDS_LOCK = threading.RLock()
-FEDS_SETTINGS_LOCK = threading.RLock()
-FEDS_SUBSCRIBER_LOCK = threading.RLock()
-
-FEDERATION_BYNAME = {}
-FEDERATION_BYOWNER = {}
-FEDERATION_BYFEDID = {}
-
-FEDERATION_CHATS = {}
-FEDERATION_CHATS_BYID = {}
-
-FEDERATION_BANNED_FULL = {}
-FEDERATION_BANNED_USERID = {}
-
-FEDERATION_NOTIFICATION = {}
-FEDS_SUBSCRIBER = {}
-MYFEDS_SUBSCRIBER = {}
-
-
-def get_fed_info(fed_id):
- get = FEDERATION_BYFEDID.get(str(fed_id))
- return False if get is None else get
-
-
-def get_fed_id(chat_id):
- get = FEDERATION_CHATS.get(str(chat_id))
- return False if get is None else get["fid"]
-
-
-def get_fed_name(chat_id):
- get = FEDERATION_CHATS.get(str(chat_id))
- return False if get is None else get["chat_name"]
-
-
-def get_user_fban(fed_id, user_id):
- if not FEDERATION_BANNED_FULL.get(fed_id):
- return False, False, False
- if user_info := FEDERATION_BANNED_FULL[fed_id].get(user_id):
- return user_info["first_name"], user_info["reason"], user_info["time"]
- else:
- return None, None, None
-
-
-def get_user_admin_fed_name(user_id):
- return [
- FEDERATION_BYFEDID[f]["fname"]
- for f in FEDERATION_BYFEDID
- if int(user_id)
- in ast.literal_eval(
- ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["members"]
- )
- ]
-
-
-def get_user_owner_fed_name(user_id):
- return [
- FEDERATION_BYFEDID[f]["fname"]
- for f in FEDERATION_BYFEDID
- if int(user_id)
- == int(ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["owner"])
- ]
-
-
-def get_user_admin_fed_full(user_id):
- return [
- {"fed_id": f, "fed": FEDERATION_BYFEDID[f]}
- for f in FEDERATION_BYFEDID
- if int(user_id)
- in ast.literal_eval(
- ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["members"]
- )
- ]
-
-
-def get_user_owner_fed_full(user_id):
- return [
- {"fed_id": f, "fed": FEDERATION_BYFEDID[f]}
- for f in FEDERATION_BYFEDID
- if int(user_id)
- == int(ast.literal_eval(FEDERATION_BYFEDID[f]["fusers"])["owner"])
- ]
-
-
-def get_user_fbanlist(user_id):
- banlist = FEDERATION_BANNED_FULL
- user_name = ""
- fedname = []
- for x in banlist:
- if banlist[x].get(user_id):
- if user_name == "":
- user_name = banlist[x][user_id].get("first_name")
- fedname.append([x, banlist[x][user_id].get("reason")])
- return user_name, fedname
-
-
-def new_fed(owner_id, fed_name, fed_id):
- with FEDS_LOCK:
- fed = Federations(
- str(owner_id),
- fed_name,
- str(fed_id),
- "Rules is not set in this federation.",
- None,
- str({"owner": str(owner_id), "members": "[]"}),
- )
- SESSION.add(fed)
- SESSION.commit()
- FEDERATION_BYOWNER[str(owner_id)] = {
- "fid": str(fed_id),
- "fname": fed_name,
- "frules": "Rules is not set in this federation.",
- "flog": None,
- "fusers": str({"owner": str(owner_id), "members": "[]"}),
- }
- FEDERATION_BYFEDID[str(fed_id)] = {
- "owner": str(owner_id),
- "fname": fed_name,
- "frules": "Rules is not set in this federation.",
- "flog": None,
- "fusers": str({"owner": str(owner_id), "members": "[]"}),
- }
- FEDERATION_BYNAME[fed_name] = {
- "fid": str(fed_id),
- "owner": str(owner_id),
- "frules": "Rules is not set in this federation.",
- "flog": None,
- "fusers": str({"owner": str(owner_id), "members": "[]"}),
- }
- return fed
-
-
-def del_fed(fed_id):
- with FEDS_LOCK:
- getcache = FEDERATION_BYFEDID.get(fed_id)
- if getcache is None:
- return False
- # Variables
- getfed = FEDERATION_BYFEDID.get(fed_id)
- owner_id = getfed["owner"]
- fed_name = getfed["fname"]
- # Delete from cache
- FEDERATION_BYOWNER.pop(owner_id)
- FEDERATION_BYFEDID.pop(fed_id)
- FEDERATION_BYNAME.pop(fed_name)
- if FEDERATION_CHATS_BYID.get(fed_id):
- for x in FEDERATION_CHATS_BYID[fed_id]:
- if delchats := SESSION.query(ChatF).get(str(x)):
- SESSION.delete(delchats)
- SESSION.commit()
- FEDERATION_CHATS.pop(x)
- FEDERATION_CHATS_BYID.pop(fed_id)
- if getall := FEDERATION_BANNED_USERID.get(fed_id):
- for x in getall:
- if banlist := SESSION.query(BansF).get((fed_id, str(x))):
- SESSION.delete(banlist)
- SESSION.commit()
- if FEDERATION_BANNED_USERID.get(fed_id):
- FEDERATION_BANNED_USERID.pop(fed_id)
- if FEDERATION_BANNED_FULL.get(fed_id):
- FEDERATION_BANNED_FULL.pop(fed_id)
- if getall := MYFEDS_SUBSCRIBER.get(fed_id):
- for x in getall:
- if getsubs := SESSION.query(FedSubs).get((fed_id, str(x))):
- SESSION.delete(getsubs)
- SESSION.commit()
- if FEDS_SUBSCRIBER.get(fed_id):
- FEDS_SUBSCRIBER.pop(fed_id)
- if MYFEDS_SUBSCRIBER.get(fed_id):
- MYFEDS_SUBSCRIBER.pop(fed_id)
- if curr := SESSION.query(Federations).get(fed_id):
- SESSION.delete(curr)
- SESSION.commit()
- return True
-
-
-def rename_fed(fed_id, owner_id, newname):
- with FEDS_LOCK:
- fed = SESSION.query(Federations).get(fed_id)
- if not fed:
- return False
- fed.fed_name = newname
- SESSION.commit()
-
- # Update the dicts
- oldname = FEDERATION_BYFEDID[str(fed_id)]["fname"]
- tempdata = FEDERATION_BYNAME[oldname]
- FEDERATION_BYNAME.pop(oldname)
-
- FEDERATION_BYOWNER[str(owner_id)]["fname"] = newname
- FEDERATION_BYFEDID[str(fed_id)]["fname"] = newname
- FEDERATION_BYNAME[newname] = tempdata
- return True
-
-
-def chat_join_fed(fed_id, chat_name, chat_id):
- with FEDS_LOCK:
- r = ChatF(chat_id, chat_name, fed_id)
- SESSION.add(r)
- FEDERATION_CHATS[str(chat_id)] = {"chat_name": chat_name, "fid": fed_id}
- checkid = FEDERATION_CHATS_BYID.get(fed_id)
- if checkid is None:
- FEDERATION_CHATS_BYID[fed_id] = []
- FEDERATION_CHATS_BYID[fed_id].append(str(chat_id))
- SESSION.commit()
- return r
-
-
-def search_fed_by_name(fed_name):
- allfed = FEDERATION_BYNAME.get(fed_name)
- return False if allfed is None else allfed
-
-
-def search_user_in_fed(fed_id, user_id):
- getfed = FEDERATION_BYFEDID.get(fed_id)
- if getfed is None:
- return False
- getfed = ast.literal_eval(getfed["fusers"])["members"]
- return user_id in ast.literal_eval(getfed)
-
-
-def user_demote_fed(fed_id, user_id):
- with FEDS_LOCK:
- # Variables
- getfed = FEDERATION_BYFEDID.get(str(fed_id))
- owner_id = getfed["owner"]
- fed_name = getfed["fname"]
- fed_rules = getfed["frules"]
- fed_log = getfed["flog"]
- # Temp set
- try:
- members = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
- except ValueError:
- return False
- members.remove(user_id)
- # Set user
- FEDERATION_BYOWNER[str(owner_id)]["fusers"] = str(
- {"owner": str(owner_id), "members": str(members)},
- )
- FEDERATION_BYFEDID[str(fed_id)]["fusers"] = str(
- {"owner": str(owner_id), "members": str(members)},
- )
- FEDERATION_BYNAME[fed_name]["fusers"] = str(
- {"owner": str(owner_id), "members": str(members)},
- )
- # Set on database
- fed = Federations(
- str(owner_id),
- fed_name,
- str(fed_id),
- fed_rules,
- fed_log,
- str({"owner": str(owner_id), "members": str(members)}),
- )
- SESSION.merge(fed)
- SESSION.commit()
- return True
-
-
-def user_join_fed(fed_id, user_id):
- with FEDS_LOCK:
- # Variables
- getfed = FEDERATION_BYFEDID.get(str(fed_id))
- owner_id = getfed["owner"]
- fed_name = getfed["fname"]
- fed_rules = getfed["frules"]
- fed_log = getfed["flog"]
- # Temp set
- members = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
- members.append(user_id)
- # Set user
- FEDERATION_BYOWNER[str(owner_id)]["fusers"] = str(
- {"owner": str(owner_id), "members": str(members)},
- )
- FEDERATION_BYFEDID[str(fed_id)]["fusers"] = str(
- {"owner": str(owner_id), "members": str(members)},
- )
- FEDERATION_BYNAME[fed_name]["fusers"] = str(
- {"owner": str(owner_id), "members": str(members)},
- )
- # Set on database
- fed = Federations(
- str(owner_id),
- fed_name,
- str(fed_id),
- fed_rules,
- fed_log,
- str({"owner": str(owner_id), "members": str(members)}),
- )
- SESSION.merge(fed)
- SESSION.commit()
- __load_all_feds_chats()
- return True
-
-
-def chat_leave_fed(chat_id):
- with FEDS_LOCK:
- # Set variables
- fed_info = FEDERATION_CHATS.get(str(chat_id))
- if fed_info is None:
- return False
- fed_id = fed_info["fid"]
- # Delete from cache
- FEDERATION_CHATS.pop(str(chat_id))
- FEDERATION_CHATS_BYID[str(fed_id)].remove(str(chat_id))
- # Delete from db
- curr = SESSION.query(ChatF).all()
- for U in curr:
- if int(U.chat_id) == int(chat_id):
- SESSION.delete(U)
- SESSION.commit()
- return True
-
-
-def all_fed_chats(fed_id):
- with FEDS_LOCK:
- getfed = FEDERATION_CHATS_BYID.get(fed_id)
- return [] if getfed is None else getfed
-
-
-def all_fed_users(fed_id):
- with FEDS_LOCK:
- getfed = FEDERATION_BYFEDID.get(str(fed_id))
- if getfed is None:
- return False
- fed_owner = ast.literal_eval(ast.literal_eval(getfed["fusers"])["owner"])
- fed_admins = ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
- fed_admins.append(fed_owner)
- return fed_admins
-
-
-def all_fed_members(fed_id):
- with FEDS_LOCK:
- getfed = FEDERATION_BYFEDID.get(str(fed_id))
- return ast.literal_eval(ast.literal_eval(getfed["fusers"])["members"])
-
-
-def set_frules(fed_id, rules):
- with FEDS_LOCK:
- # Variables
- getfed = FEDERATION_BYFEDID.get(str(fed_id))
- owner_id = getfed["owner"]
- fed_name = getfed["fname"]
- fed_members = getfed["fusers"]
- fed_rules = str(rules)
- fed_log = getfed["flog"]
- # Set user
- FEDERATION_BYOWNER[str(owner_id)]["frules"] = fed_rules
- FEDERATION_BYFEDID[str(fed_id)]["frules"] = fed_rules
- FEDERATION_BYNAME[fed_name]["frules"] = fed_rules
- # Set on database
- fed = Federations(
- str(owner_id),
- fed_name,
- str(fed_id),
- fed_rules,
- fed_log,
- str(fed_members),
- )
- SESSION.merge(fed)
- SESSION.commit()
- return True
-
-
-def get_frules(fed_id):
- with FEDS_LOCK:
- return FEDERATION_BYFEDID[str(fed_id)]["frules"]
-
-
-def fban_user(fed_id, user_id, first_name, last_name, user_name, reason, time):
- with FEDS_LOCK:
- r = SESSION.query(BansF).all()
- for I in r:
- if I.fed_id == fed_id and int(I.user_id) == int(user_id):
- SESSION.delete(I)
-
- r = BansF(
- str(fed_id),
- str(user_id),
- first_name,
- last_name,
- user_name,
- reason,
- time,
- )
-
- SESSION.add(r)
- try:
- SESSION.commit()
- except Exception:
- SESSION.rollback()
- return False
- finally:
- SESSION.commit()
- __load_all_feds_banned()
- return r
-
-
-def multi_fban_user(
- multi_fed_id,
- multi_user_id,
- multi_first_name,
- multi_last_name,
- multi_user_name,
- multi_reason,
-):
- counter = 0
- time = 0
- for x in enumerate(multi_fed_id):
- fed_id = multi_fed_id[x]
- user_id = multi_user_id[x]
- first_name = multi_first_name[x]
- last_name = multi_last_name[x]
- user_name = multi_user_name[x]
- reason = multi_reason[x]
- r = SESSION.query(BansF).all()
- for I in r:
- if I.fed_id == fed_id and int(I.user_id) == int(user_id):
- SESSION.delete(I)
-
- r = BansF(
- str(fed_id),
- str(user_id),
- first_name,
- last_name,
- user_name,
- reason,
- time,
- )
-
- SESSION.add(r)
- counter += 1
- if str(str(counter)[-2:]) == "00":
- print(user_id)
- print(first_name)
- print(reason)
- print(counter)
- try:
- SESSION.commit()
- except Exception:
- SESSION.rollback()
- return False
- finally:
- SESSION.commit()
- __load_all_feds_banned()
- print("Done")
- return counter
-
-
-def un_fban_user(fed_id, user_id):
- with FEDS_LOCK:
- r = SESSION.query(BansF).all()
- for I in r:
- if I.fed_id == fed_id and int(I.user_id) == int(user_id):
- SESSION.delete(I)
- try:
- SESSION.commit()
- except Exception:
- SESSION.rollback()
- return False
- finally:
- SESSION.commit()
- __load_all_feds_banned()
- return I
-
-
-def get_fban_user(fed_id, user_id):
- list_fbanned = FEDERATION_BANNED_USERID.get(fed_id)
- if list_fbanned is None:
- FEDERATION_BANNED_USERID[fed_id] = []
- if user_id in FEDERATION_BANNED_USERID[fed_id]:
- r = SESSION.query(BansF).all()
- reason = None
- for I in r:
- if I.fed_id == fed_id and int(I.user_id) == int(user_id):
- reason = I.reason
- time = I.time
- return True, reason, time
- return False, None, None
-
-
-def get_all_fban_users(fed_id):
- list_fbanned = FEDERATION_BANNED_USERID.get(fed_id)
- if list_fbanned is None:
- FEDERATION_BANNED_USERID[fed_id] = []
- return FEDERATION_BANNED_USERID[fed_id]
-
-
-def get_all_fban_users_target(fed_id, user_id):
- list_fbanned = FEDERATION_BANNED_FULL.get(fed_id)
- if list_fbanned is None:
- FEDERATION_BANNED_FULL[fed_id] = []
- return False
- return list_fbanned[str(user_id)]
-
-
-def get_all_fban_users_global():
- total = []
- for x in list(FEDERATION_BANNED_USERID):
- total.extend(iter(FEDERATION_BANNED_USERID[x]))
- return total
-
-
-def get_all_feds_users_global():
- return [FEDERATION_BYFEDID[x] for x in list(FEDERATION_BYFEDID)]
-
-
-def search_fed_by_id(fed_id):
- get = FEDERATION_BYFEDID.get(fed_id)
- return False if get is None else get
-
-
-def user_feds_report(user_id: int) -> bool:
- user_setting = FEDERATION_NOTIFICATION.get(str(user_id))
- if user_setting is None:
- user_setting = True
- return user_setting
-
-
-def set_feds_setting(user_id: int, setting: bool):
- with FEDS_SETTINGS_LOCK:
- user_setting = SESSION.query(FedsUserSettings).get(user_id) or FedsUserSettings(user_id)
-
- user_setting.should_report = setting
- FEDERATION_NOTIFICATION[str(user_id)] = setting
- SESSION.add(user_setting)
- SESSION.commit()
-
-
-def get_fed_log(fed_id):
- fed_setting = FEDERATION_BYFEDID.get(str(fed_id))
- if fed_setting is None:
- fed_setting = False
- return fed_setting
- if fed_setting.get("flog") is None:
- return False
- if fed_setting.get("flog"):
- try:
- dispatcher.bot.get_chat(fed_setting.get("flog"))
- except (BadRequest, Unauthorized):
- set_fed_log(fed_id, None)
- return False
- return fed_setting.get("flog")
- return False
-
-
-def set_fed_log(fed_id, chat_id):
- with FEDS_LOCK:
- # Variables
- getfed = FEDERATION_BYFEDID.get(str(fed_id))
- owner_id = getfed["owner"]
- fed_name = getfed["fname"]
- fed_members = getfed["fusers"]
- fed_rules = getfed["frules"]
- fed_log = str(chat_id)
- # Set user
- FEDERATION_BYOWNER[str(owner_id)]["flog"] = fed_log
- FEDERATION_BYFEDID[str(fed_id)]["flog"] = fed_log
- FEDERATION_BYNAME[fed_name]["flog"] = fed_log
- # Set on database
- fed = Federations(
- str(owner_id),
- fed_name,
- str(fed_id),
- fed_rules,
- fed_log,
- str(fed_members),
- )
- SESSION.merge(fed)
- SESSION.commit()
- print(fed_log)
- return True
-
-
-def subs_fed(fed_id, my_fed):
- if check := get_spec_subs(fed_id, my_fed):
- return False
- with FEDS_SUBSCRIBER_LOCK:
- subsfed = FedSubs(fed_id, my_fed)
-
- SESSION.merge(subsfed) # merge to avoid duplicate key issues
- SESSION.commit()
- # Temporary Data For Subbed Feds
- if FEDS_SUBSCRIBER.get(fed_id, set()) == set():
- FEDS_SUBSCRIBER[fed_id] = {my_fed}
- else:
- FEDS_SUBSCRIBER.get(fed_id, set()).add(my_fed)
- # Temporary data for Fed Subs
- if MYFEDS_SUBSCRIBER.get(my_fed, set()) == set():
- MYFEDS_SUBSCRIBER[my_fed] = {fed_id}
- else:
- MYFEDS_SUBSCRIBER.get(my_fed, set()).add(fed_id)
- return True
-
-
-def unsubs_fed(fed_id, my_fed):
- with FEDS_SUBSCRIBER_LOCK:
- if getsubs := SESSION.query(FedSubs).get((fed_id, my_fed)):
- if my_fed in FEDS_SUBSCRIBER.get(fed_id, set()): # sanity check
- FEDS_SUBSCRIBER.get(fed_id, set()).remove(my_fed)
- if fed_id in MYFEDS_SUBSCRIBER.get(my_fed, set()): # sanity check
- MYFEDS_SUBSCRIBER.get(my_fed, set()).remove(fed_id)
-
- SESSION.delete(getsubs)
- SESSION.commit()
- return True
-
- SESSION.close()
- return False
-
-
-def get_all_subs(fed_id):
- return FEDS_SUBSCRIBER.get(fed_id, set())
-
-
-def get_spec_subs(fed_id, fed_target):
- if FEDS_SUBSCRIBER.get(fed_id, set()) == set():
- return {}
- return FEDS_SUBSCRIBER.get(fed_id, fed_target)
-
-
-def get_mysubs(my_fed):
- return list(MYFEDS_SUBSCRIBER.get(my_fed))
-
-
-def get_subscriber(fed_id):
- return FEDS_SUBSCRIBER.get(fed_id, set())
-
-
-def __load_all_feds():
- try:
- feds = SESSION.query(Federations).all()
- for x in feds: # remove tuple by ( ,)
- # Fed by Owner
- check = FEDERATION_BYOWNER.get(x.owner_id)
- if check is None:
- FEDERATION_BYOWNER[x.owner_id] = []
- FEDERATION_BYOWNER[str(x.owner_id)] = {
- "fid": str(x.fed_id),
- "fname": x.fed_name,
- "frules": x.fed_rules,
- "flog": x.fed_log,
- "fusers": str(x.fed_users),
- }
- # Fed By FedId
- check = FEDERATION_BYFEDID.get(x.fed_id)
- if check is None:
- FEDERATION_BYFEDID[x.fed_id] = []
- FEDERATION_BYFEDID[str(x.fed_id)] = {
- "owner": str(x.owner_id),
- "fname": x.fed_name,
- "frules": x.fed_rules,
- "flog": x.fed_log,
- "fusers": str(x.fed_users),
- }
- # Fed By Name
- check = FEDERATION_BYNAME.get(x.fed_name)
- if check is None:
- FEDERATION_BYNAME[x.fed_name] = []
- FEDERATION_BYNAME[x.fed_name] = {
- "fid": str(x.fed_id),
- "owner": str(x.owner_id),
- "frules": x.fed_rules,
- "flog": x.fed_log,
- "fusers": str(x.fed_users),
- }
- finally:
- SESSION.close()
-
-
-def __load_all_feds_chats():
- global FEDERATION_CHATS, FEDERATION_CHATS_BYID
- try:
- qall = SESSION.query(ChatF).all()
- FEDERATION_CHATS = {}
- FEDERATION_CHATS_BYID = {}
- for x in qall:
- # Federation Chats
- check = FEDERATION_CHATS.get(x.chat_id)
- if check is None:
- FEDERATION_CHATS[x.chat_id] = {}
- FEDERATION_CHATS[x.chat_id] = {"chat_name": x.chat_name, "fid": x.fed_id}
- # Federation Chats By ID
- check = FEDERATION_CHATS_BYID.get(x.fed_id)
- if check is None:
- FEDERATION_CHATS_BYID[x.fed_id] = []
- FEDERATION_CHATS_BYID[x.fed_id].append(x.chat_id)
- finally:
- SESSION.close()
-
-
-def __load_all_feds_banned():
- global FEDERATION_BANNED_USERID, FEDERATION_BANNED_FULL
- try:
- FEDERATION_BANNED_USERID = {}
- FEDERATION_BANNED_FULL = {}
- qall = SESSION.query(BansF).all()
- for x in qall:
- check = FEDERATION_BANNED_USERID.get(x.fed_id)
- if check is None:
- FEDERATION_BANNED_USERID[x.fed_id] = []
- if int(x.user_id) not in FEDERATION_BANNED_USERID[x.fed_id]:
- FEDERATION_BANNED_USERID[x.fed_id].append(int(x.user_id))
- check = FEDERATION_BANNED_FULL.get(x.fed_id)
- if check is None:
- FEDERATION_BANNED_FULL[x.fed_id] = {}
- FEDERATION_BANNED_FULL[x.fed_id][x.user_id] = {
- "first_name": x.first_name,
- "last_name": x.last_name,
- "user_name": x.user_name,
- "reason": x.reason,
- "time": x.time,
- }
- finally:
- SESSION.close()
-
-
-def __load_all_feds_settings():
- try:
- getuser = SESSION.query(FedsUserSettings).all()
- for x in getuser:
- FEDERATION_NOTIFICATION[str(x.user_id)] = x.should_report
- finally:
- SESSION.close()
-
-
-def __load_feds_subscriber():
- global FEDS_SUBSCRIBER
- global MYFEDS_SUBSCRIBER
- try:
- feds = SESSION.query(FedSubs.fed_id).distinct().all()
- for (fed_id,) in feds: # remove tuple by ( ,)
- FEDS_SUBSCRIBER[fed_id] = []
- MYFEDS_SUBSCRIBER[fed_id] = []
-
- all_fedsubs = SESSION.query(FedSubs).all()
- for x in all_fedsubs:
- FEDS_SUBSCRIBER[x.fed_id] += [x.fed_subs]
- try:
- MYFEDS_SUBSCRIBER[x.fed_subs] += [x.fed_id]
- except KeyError:
- if getsubs := SESSION.query(FedSubs).get(
- (x.fed_id, x.fed_subs)
- ):
- SESSION.delete(getsubs)
- SESSION.commit()
-
- FEDS_SUBSCRIBER = {x: set(y) for x, y in FEDS_SUBSCRIBER.items()}
- MYFEDS_SUBSCRIBER = {x: set(y) for x, y in MYFEDS_SUBSCRIBER.items()}
-
- finally:
- SESSION.close()
-
-
-__load_all_feds()
-__load_all_feds_chats()
-__load_all_feds_banned()
-__load_all_feds_settings()
-__load_feds_subscriber()
diff --git a/Exon/modules/sql/fsub_sql.py b/Exon/modules/sql/fsub_sql.py
deleted file mode 100644
index de01c771..00000000
--- a/Exon/modules/sql/fsub_sql.py
+++ /dev/null
@@ -1,73 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-from sqlalchemy import Column, Numeric, String
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class forceSubscribe(BASE):
- __tablename__ = "forceSubscribe"
- chat_id = Column(Numeric, primary_key=True)
- channel = Column(String)
-
- def __init__(self, chat_id, channel):
- self.chat_id = chat_id
- self.channel = channel
-
-
-forceSubscribe.__table__.create(checkfirst=True)
-
-
-def fs_settings(chat_id):
- try:
- return (
- SESSION.query(forceSubscribe)
- .filter(forceSubscribe.chat_id == chat_id)
- .one()
- )
- except Exception:
- return None
- finally:
- SESSION.close()
-
-
-def add_channel(chat_id, channel):
- adder = SESSION.query(forceSubscribe).get(chat_id)
- if adder:
- adder.channel = channel
- else:
- adder = forceSubscribe(chat_id, channel)
- SESSION.add(adder)
- SESSION.commit()
-
-
-def disapprove(chat_id):
- if rem := SESSION.query(forceSubscribe).get(chat_id):
- SESSION.delete(rem)
- SESSION.commit()
diff --git a/Exon/modules/sql/language_sql.py b/Exon/modules/sql/language_sql.py
deleted file mode 100644
index d6f6d8ca..00000000
--- a/Exon/modules/sql/language_sql.py
+++ /dev/null
@@ -1,83 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import threading
-
-from sqlalchemy import Column, String, UnicodeText
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class ChatLangs(BASE):
- __tablename__ = "chatlangs"
- chat_id = Column(String(14), primary_key=True)
- language = Column(UnicodeText)
-
- def __init__(self, chat_id, language):
- self.chat_id = str(chat_id) # ensure string
- self.language = language
-
- def __repr__(self):
- return f"Language {self.language} chat {self.chat_id}"
-
-
-CHAT_LANG = {}
-LANG_LOCK = threading.RLock()
-ChatLangs.__table__.create(checkfirst=True)
-
-
-def set_lang(chat_id: str, lang: str) -> None:
- with LANG_LOCK:
- if curr := SESSION.query(ChatLangs).get(chat_id):
- curr.language = lang
-
- else:
- curr = ChatLangs(chat_id, lang)
- SESSION.add(curr)
- SESSION.flush()
- CHAT_LANG[chat_id] = lang
- SESSION.commit()
-
-
-def get_chat_lang(chat_id: str) -> str:
- lang = CHAT_LANG.get(chat_id)
- if lang is None:
- lang = "en"
- return lang
-
-
-def __load_chat_language() -> None:
- global CHAT_LANG
- try:
- allchats = SESSION.query(ChatLangs).all()
- CHAT_LANG = {x.chat_id: x.language for x in allchats}
- finally:
- SESSION.close()
-
-
-__load_chat_language()
diff --git a/Exon/modules/sql/locks_sql.py b/Exon/modules/sql/locks_sql.py
deleted file mode 100644
index 483388a5..00000000
--- a/Exon/modules/sql/locks_sql.py
+++ /dev/null
@@ -1,372 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Boolean, Column, String
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class Permissions(BASE):
- __tablename__ = "permissions"
- chat_id = Column(String(14), primary_key=True)
- # Booleans are for "is this locked", _NOT_ "is this allowed"
- audio = Column(Boolean, default=False)
- voice = Column(Boolean, default=False)
- contact = Column(Boolean, default=False)
- video = Column(Boolean, default=False)
- document = Column(Boolean, default=False)
- photo = Column(Boolean, default=False)
- sticker = Column(Boolean, default=False)
- gif = Column(Boolean, default=False)
- url = Column(Boolean, default=False)
- bots = Column(Boolean, default=False)
- forward = Column(Boolean, default=False)
- game = Column(Boolean, default=False)
- location = Column(Boolean, default=False)
- rtl = Column(Boolean, default=False)
- button = Column(Boolean, default=False)
- egame = Column(Boolean, default=False)
- inline = Column(Boolean, default=False)
- apk = Column(Boolean, default=False)
- doc = Column(Boolean, default=False)
- exe = Column(Boolean, default=False)
- jpg = Column(Boolean, default=False)
- mp3 = Column(Boolean, default=False)
- pdf = Column(Boolean, default=False)
- txt = Column(Boolean, default=False)
- xml = Column(Boolean, default=False)
- zip = Column(Boolean, default=False)
- docx = Column(Boolean, default=False)
- py = Column(Boolean, default=False)
- svg = Column(Boolean, default=False)
- targz = Column(Boolean, default=False)
- wav = Column(Boolean, default=False)
-
- def __init__(self, chat_id):
- self.chat_id = str(chat_id) # ensure string
- self.audio = False
- self.voice = False
- self.contact = False
- self.video = False
- self.document = False
- self.photo = False
- self.sticker = False
- self.gif = False
- self.url = False
- self.bots = False
- self.forward = False
- self.game = False
- self.location = False
- self.rtl = False
- self.button = False
- self.egame = False
- self.inline = False
- self.apk = False
- self.doc = False
- self.exe = False
- self.jpg = False
- self.mp3 = False
- self.pdf = False
- self.txt = False
- self.xml = False
- self.zip = False
- self.docx = False
- self.py = False
- self.svg = False
- self.targz = False
- self.wav = False
-
- def __repr__(self):
- return f""
-
-
-class Restrictions(BASE):
- __tablename__ = "restrictions"
- chat_id = Column(String(14), primary_key=True)
- # Booleans are for "is this restricted", _NOT_ "is this allowed"
- messages = Column(Boolean, default=False)
- media = Column(Boolean, default=False)
- other = Column(Boolean, default=False)
- preview = Column(Boolean, default=False)
-
- def __init__(self, chat_id):
- self.chat_id = str(chat_id) # ensure string
- self.messages = False
- self.media = False
- self.other = False
- self.preview = False
-
- def __repr__(self):
- return f""
-
-
-# For those who faced database error, Just uncomment the
-# line below and run bot for 1 time & remove that line!
-
-Permissions.__table__.create(checkfirst=True)
-# Permissions.__table__.drop()
-Restrictions.__table__.create(checkfirst=True)
-
-PERM_LOCK = threading.RLock()
-RESTR_LOCK = threading.RLock()
-
-
-def init_permissions(chat_id, reset=False):
- curr_perm = SESSION.query(Permissions).get(str(chat_id))
- if reset:
- SESSION.delete(curr_perm)
- SESSION.flush()
- perm = Permissions(str(chat_id))
- SESSION.add(perm)
- SESSION.commit()
- return perm
-
-
-def init_restrictions(chat_id, reset=False):
- curr_restr = SESSION.query(Restrictions).get(str(chat_id))
- if reset:
- SESSION.delete(curr_restr)
- SESSION.flush()
- restr = Restrictions(str(chat_id))
- SESSION.add(restr)
- SESSION.commit()
- return restr
-
-
-def update_lock(chat_id, lock_type, locked):
- with PERM_LOCK:
- curr_perm = SESSION.query(Permissions).get(str(chat_id)) or init_permissions(chat_id)
-
- if lock_type == "apk":
- curr_perm.apk = locked
- elif lock_type == "audio":
- curr_perm.audio = locked
- elif lock_type == "bots":
- curr_perm.bots = locked
- elif lock_type == "button":
- curr_perm.button = locked
- elif lock_type == "contact":
- curr_perm.contact = locked
- elif lock_type in ["doc", "docx"]:
- curr_perm.doc = locked
- elif lock_type == "document":
- curr_perm.document = locked
- elif lock_type == "egame":
- curr_perm.egame = locked
- elif lock_type == "exe":
- curr_perm.exe = locked
- elif lock_type == "forward":
- curr_perm.forward = locked
- elif lock_type == "game":
- curr_perm.game = locked
- elif lock_type == "gif":
- curr_perm.gif = locked
- elif lock_type == "inline":
- curr_perm.inline = locked
- elif lock_type == "jpg":
- curr_perm.jpg = locked
- elif lock_type == "location":
- curr_perm.location = locked
- elif lock_type == "mp3":
- curr_perm.mp3 = locked
- elif lock_type == "pdf":
- curr_perm.pdf = locked
- elif lock_type == "photo":
- curr_perm.photo = locked
- elif lock_type == "py":
- curr_perm.py = locked
- elif lock_type == "rtl":
- curr_perm.rtl = locked
- elif lock_type == "sticker":
- curr_perm.sticker = locked
- elif lock_type == "svg":
- curr_perm.svg = locked
- elif lock_type == "targz":
- curr_perm.tar = locked
- elif lock_type == "txt":
- curr_perm.txt = locked
- elif lock_type == "url":
- curr_perm.url = locked
- elif lock_type == "video":
- curr_perm.video = locked
- elif lock_type == "voice":
- curr_perm.voice = locked
- elif lock_type == "wav":
- curr_perm.wav = locked
-
- elif lock_type == "xml":
- curr_perm.xml = locked
- elif lock_type == "zip":
- curr_perm.zip = locked
- SESSION.add(curr_perm)
- SESSION.commit()
-
-
-def update_restriction(chat_id, restr_type, locked):
- with RESTR_LOCK:
- curr_restr = SESSION.query(Restrictions).get(str(chat_id)) or init_restrictions(chat_id)
-
- if restr_type == "messages":
- curr_restr.messages = locked
- elif restr_type == "media":
- curr_restr.media = locked
- elif restr_type == "other":
- curr_restr.other = locked
- elif restr_type == "previews":
- curr_restr.preview = locked
- elif restr_type == "all":
- curr_restr.messages = locked
- curr_restr.media = locked
- curr_restr.other = locked
- curr_restr.preview = locked
- SESSION.add(curr_restr)
- SESSION.commit()
-
-
-def is_locked(chat_id, lock_type):
- curr_perm = SESSION.query(Permissions).get(str(chat_id))
- SESSION.close()
-
- if not curr_perm:
- return False
-
- if lock_type == "sticker":
- return curr_perm.sticker
- if lock_type == "photo":
- return curr_perm.photo
- if lock_type == "audio":
- return curr_perm.audio
- if lock_type == "voice":
- return curr_perm.voice
- if lock_type == "contact":
- return curr_perm.contact
- if lock_type == "video":
- return curr_perm.video
- if lock_type == "document":
- return curr_perm.document
- if lock_type == "gif":
- return curr_perm.gif
- if lock_type == "url":
- return curr_perm.url
- if lock_type == "bots":
- return curr_perm.bots
- if lock_type == "forward":
- return curr_perm.forward
- if lock_type == "game":
- return curr_perm.game
- if lock_type == "location":
- return curr_perm.location
- if lock_type == "rtl":
- return curr_perm.rtl
- if lock_type == "button":
- return curr_perm.button
- if lock_type == "egame":
- return curr_perm.egame
- if lock_type == "inline":
- return curr_perm.inline
- if lock_type == "apk":
- return curr_perm.apk
- if lock_type == "doc":
- return curr_perm.doc
- if lock_type == "exe":
- return curr_perm.exe
- if lock_type == "jpg":
- return curr_perm.jpg
- if lock_type == "mp3":
- return curr_perm.mp3
- if lock_type == "pdf":
- return curr_perm.pdf
- if lock_type == "txt":
- return curr_perm.txt
- if lock_type == "xml":
- return curr_perm.xml
- if lock_type == "zip":
- return curr_perm.zip
- if lock_type == "docx":
- return curr_perm.docx
- if lock_type == "py":
- return curr_perm.py
- if lock_type == "svg":
- return curr_perm.svg
- if lock_type == "targz":
- return curr_perm.targz
- if lock_type == "wav":
- return curr_perm.wav
-
-
-def is_restr_locked(chat_id, lock_type):
- curr_restr = SESSION.query(Restrictions).get(str(chat_id))
- SESSION.close()
-
- if not curr_restr:
- return False
-
- if lock_type == "messages":
- return curr_restr.messages
- if lock_type == "media":
- return curr_restr.media
- if lock_type == "other":
- return curr_restr.other
- if lock_type == "previews":
- return curr_restr.preview
- if lock_type == "all":
- return (
- curr_restr.messages
- and curr_restr.media
- and curr_restr.other
- and curr_restr.preview
- )
-
-
-def get_locks(chat_id):
- try:
- return SESSION.query(Permissions).get(str(chat_id))
- finally:
- SESSION.close()
-
-
-def get_restr(chat_id):
- try:
- return SESSION.query(Restrictions).get(str(chat_id))
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with PERM_LOCK:
- if perms := SESSION.query(Permissions).get(str(old_chat_id)):
- perms.chat_id = str(new_chat_id)
- SESSION.commit()
-
- with RESTR_LOCK:
- if rest := SESSION.query(Restrictions).get(str(old_chat_id)):
- rest.chat_id = str(new_chat_id)
- SESSION.commit()
diff --git a/Exon/modules/sql/log_channel_sql.py b/Exon/modules/sql/log_channel_sql.py
deleted file mode 100644
index 3bf02b02..00000000
--- a/Exon/modules/sql/log_channel_sql.py
+++ /dev/null
@@ -1,182 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import threading
-import typing
-
-from sqlalchemy import BigInteger, Boolean, Column, String, distinct, func
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class GroupLogs(BASE):
- __tablename__ = "log_channels"
- chat_id = Column(String(14), primary_key=True)
- log_channel = Column(String(14), nullable=False)
-
- def __init__(self, chat_id, log_channel):
- self.chat_id = str(chat_id)
- self.log_channel = str(log_channel)
-
-
-class LogChannelSettings(BASE):
- __tablename__ = "log_channel_setting"
- chat_id = Column(BigInteger, primary_key=True)
- log_joins = Column(Boolean, default=True)
- log_leave = Column(Boolean, default=True)
- log_warn = Column(Boolean, default=True)
- log_action = Column(Boolean, default=True)
- # log_media = Column(Boolean)
- log_report = Column(Boolean, default=True)
-
- def __init__(
- self,
- chat_id: int,
- log_join: bool,
- log_leave: bool,
- log_warn: bool,
- log_action: bool,
- log_report: bool,
- ):
- self.chat_id = chat_id
- self.log_warn = log_warn
- self.log_joins = log_join
- self.log_leave = log_leave
- self.log_report = log_report
- self.log_action = log_action
-
- def toggle_warn(self) -> bool:
- self.log_warn = not self.log_warn
- SESSION.commit()
- return self.log_warn
-
- def toggle_joins(self) -> bool:
- self.log_joins = not self.log_joins
- SESSION.commit()
- return self.log_joins
-
- def toggle_leave(self) -> bool:
- self.log_leave = not self.log_leave
- SESSION.commit()
- return self.log_leave
-
- def toggle_report(self) -> bool:
- self.log_report = not self.log_report
- SESSION.commit()
- return self.log_report
-
- def toggle_action(self) -> bool:
- self.log_action = not self.log_action
- SESSION.commit()
- return self.log_action
-
-
-GroupLogs.__table__.create(checkfirst=True)
-LogChannelSettings.__table__.create(checkfirst=True)
-
-LOGS_INSERTION_LOCK = threading.RLock()
-LOG_SETTING_LOCK = threading.RLock()
-CHANNELS = {}
-
-
-def get_chat_setting(chat_id: int) -> typing.Optional[LogChannelSettings]:
- with LOG_SETTING_LOCK:
- return SESSION.query(LogChannelSettings).get(chat_id)
-
-
-def set_chat_setting(setting: LogChannelSettings):
- with LOGS_INSERTION_LOCK:
- if res := SESSION.query(LogChannelSettings).get(setting.chat_id):
- res.log_warn = setting.log_warn
- res.log_action = setting.log_action
- res.log_report = setting.log_report
- res.log_joins = setting.log_joins
- res.log_leave = setting.log_leave
- else:
- SESSION.add(setting)
- SESSION.commit()
-
-
-def set_chat_log_channel(chat_id, log_channel):
- with LOGS_INSERTION_LOCK:
- if res := SESSION.query(GroupLogs).get(str(chat_id)):
- res.log_channel = log_channel
- else:
- res = GroupLogs(chat_id, log_channel)
- SESSION.add(res)
-
- CHANNELS[str(chat_id)] = log_channel
- SESSION.commit()
-
-
-def get_chat_log_channel(chat_id):
- return CHANNELS.get(str(chat_id))
-
-
-def stop_chat_logging(chat_id):
- with LOGS_INSERTION_LOCK:
- if res := SESSION.query(GroupLogs).get(str(chat_id)):
- if str(chat_id) in CHANNELS:
- del CHANNELS[str(chat_id)]
-
- log_channel = res.log_channel
- SESSION.delete(res)
- SESSION.commit()
- return log_channel
-
-
-def num_logchannels():
- try:
- return SESSION.query(func.count(distinct(GroupLogs.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with LOGS_INSERTION_LOCK:
- if chat := SESSION.query(GroupLogs).get(str(old_chat_id)):
- chat.chat_id = str(new_chat_id)
- SESSION.add(chat)
- if str(old_chat_id) in CHANNELS:
- CHANNELS[str(new_chat_id)] = CHANNELS.get(str(old_chat_id))
-
- SESSION.commit()
-
-
-def __load_log_channels():
- global CHANNELS
- try:
- all_chats = SESSION.query(GroupLogs).all()
- CHANNELS = {chat.chat_id: chat.log_channel for chat in all_chats}
- finally:
- SESSION.close()
-
-
-__load_log_channels()
diff --git a/Exon/modules/sql/logger_sql.py b/Exon/modules/sql/logger_sql.py
deleted file mode 100644
index 9feffc4c..00000000
--- a/Exon/modules/sql/logger_sql.py
+++ /dev/null
@@ -1,84 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Boolean, Column, String
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class LoggerSettings(BASE):
- __tablename__ = "chat_log_settings"
- chat_id = Column(String(14), primary_key=True)
- setting = Column(Boolean, default=False, nullable=False)
-
- def __init__(self, chat_id, disabled):
- self.chat_id = str(chat_id)
- self.setting = disabled
-
- def __repr__(self):
- return f""
-
-
-LoggerSettings.__table__.create(checkfirst=True)
-
-LOG_SETTING_LOCK = threading.RLock()
-
-
-def enable_chat_log(chat_id):
- with LOG_SETTING_LOCK:
- chat = SESSION.query(LoggerSettings).get(str(chat_id)) or LoggerSettings(chat_id, True)
- chat.setting = True
- SESSION.add(chat)
- SESSION.commit()
-
-
-def disable_chat_log(chat_id):
- with LOG_SETTING_LOCK:
- chat = SESSION.query(LoggerSettings).get(str(chat_id)) or LoggerSettings(chat_id, False)
-
- chat.setting = False
- SESSION.add(chat)
- SESSION.commit()
-
-
-def does_chat_log(chat_id):
- with LOG_SETTING_LOCK:
- d = SESSION.query(LoggerSettings).get(str(chat_id))
- return d.setting if d else False
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with LOG_SETTING_LOCK:
- if chat := SESSION.query(LoggerSettings).get(str(old_chat_id)):
- chat.chat_id = new_chat_id
- SESSION.add(chat)
-
- SESSION.commit()
diff --git a/Exon/modules/sql/night_mode_sql.py b/Exon/modules/sql/night_mode_sql.py
deleted file mode 100644
index bd939cf2..00000000
--- a/Exon/modules/sql/night_mode_sql.py
+++ /dev/null
@@ -1,69 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-from sqlalchemy import Column, String
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class Nightmode(BASE):
- __tablename__ = "nightmode"
- chat_id = Column(String(14), primary_key=True)
-
- def __init__(self, chat_id):
- self.chat_id = chat_id
-
-
-Nightmode.__table__.create(checkfirst=True)
-
-
-def add_nightmode(chat_id: str):
- nightmoddy = Nightmode(chat_id)
- SESSION.add(nightmoddy)
- SESSION.commit()
-
-
-def rmnightmode(chat_id: str):
- if rmnightmoddy := SESSION.query(Nightmode).get(chat_id):
- SESSION.delete(rmnightmoddy)
- SESSION.commit()
-
-
-def get_all_chat_id():
- stark = SESSION.query(Nightmode).all()
- SESSION.close()
- return stark
-
-
-def is_nightmode_indb(chat_id: str):
- try:
- if s__ := SESSION.query(Nightmode).get(chat_id):
- return str(s__.chat_id)
- finally:
- SESSION.close()
diff --git a/Exon/modules/sql/notes_sql.py b/Exon/modules/sql/notes_sql.py
deleted file mode 100644
index 078201e6..00000000
--- a/Exon/modules/sql/notes_sql.py
+++ /dev/null
@@ -1,214 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import threading
-
-from sqlalchemy import Boolean, Column, Integer, String, UnicodeText, distinct, func
-
-from Exon.modules.helper_funcs.msg_types import Types
-from Exon.modules.sql import BASE, SESSION
-
-
-class Notes(BASE):
- __tablename__ = "notes"
- chat_id = Column(String(14), primary_key=True)
- name = Column(UnicodeText, primary_key=True)
- value = Column(UnicodeText, nullable=False)
- file = Column(UnicodeText)
- is_reply = Column(Boolean, default=False)
- has_buttons = Column(Boolean, default=False)
- msgtype = Column(Integer, default=Types.BUTTON_TEXT.value)
-
- def __init__(self, chat_id, name, value, msgtype, file=None):
- self.chat_id = str(chat_id) # ensure string
- self.name = name
- self.value = value
- self.msgtype = msgtype
- self.file = file
-
- def __repr__(self):
- return f""
-
-
-class Buttons(BASE):
- __tablename__ = "note_urls"
- id = Column(Integer, primary_key=True, autoincrement=True)
- chat_id = Column(String(14), primary_key=True)
- note_name = Column(UnicodeText, primary_key=True)
- name = Column(UnicodeText, nullable=False)
- url = Column(UnicodeText, nullable=False)
- same_line = Column(Boolean, default=False)
-
- def __init__(self, chat_id, note_name, name, url, same_line=False):
- self.chat_id = str(chat_id)
- self.note_name = note_name
- self.name = name
- self.url = url
- self.same_line = same_line
-
-
-Notes.__table__.create(checkfirst=True)
-Buttons.__table__.create(checkfirst=True)
-
-NOTES_INSERTION_LOCK = threading.RLock()
-BUTTONS_INSERTION_LOCK = threading.RLock()
-
-
-def add_note_to_db(chat_id, note_name, note_data, msgtype, buttons=None, file=None):
- if not buttons:
- buttons = []
-
- with NOTES_INSERTION_LOCK:
- if prev := SESSION.query(Notes).get((str(chat_id), note_name)):
- with BUTTONS_INSERTION_LOCK:
- prev_buttons = (
- SESSION.query(Buttons)
- .filter(
- Buttons.chat_id == str(chat_id),
- Buttons.note_name == note_name,
- )
- .all()
- )
- for btn in prev_buttons:
- SESSION.delete(btn)
- SESSION.delete(prev)
- note = Notes(
- str(chat_id),
- note_name,
- note_data or "",
- msgtype=msgtype.value,
- file=file,
- )
- SESSION.add(note)
- SESSION.commit()
-
- for b_name, url, same_line in buttons:
- add_note_button_to_db(chat_id, note_name, b_name, url, same_line)
-
-
-def get_note(chat_id, note_name):
- try:
- return (
- SESSION.query(Notes)
- .filter(func.lower(Notes.name) == note_name, Notes.chat_id == str(chat_id))
- .first()
- )
- finally:
- SESSION.close()
-
-
-def rm_note(chat_id, note_name):
- with NOTES_INSERTION_LOCK:
- if note := (
- SESSION.query(Notes)
- .filter(
- func.lower(Notes.name) == note_name,
- Notes.chat_id == str(chat_id),
- )
- .first()
- ):
- with BUTTONS_INSERTION_LOCK:
- buttons = (
- SESSION.query(Buttons)
- .filter(
- Buttons.chat_id == str(chat_id),
- Buttons.note_name == note_name,
- )
- .all()
- )
- for btn in buttons:
- SESSION.delete(btn)
-
- SESSION.delete(note)
- SESSION.commit()
- return True
- SESSION.close()
- return False
-
-
-def get_all_chat_notes(chat_id):
- try:
- return (
- SESSION.query(Notes)
- .filter(Notes.chat_id == str(chat_id))
- .order_by(Notes.name.asc())
- .all()
- )
- finally:
- SESSION.close()
-
-
-def add_note_button_to_db(chat_id, note_name, b_name, url, same_line):
- with BUTTONS_INSERTION_LOCK:
- button = Buttons(chat_id, note_name, b_name, url, same_line)
- SESSION.add(button)
- SESSION.commit()
-
-
-def get_buttons(chat_id, note_name):
- try:
- return (
- SESSION.query(Buttons)
- .filter(Buttons.chat_id == str(chat_id), Buttons.note_name == note_name)
- .order_by(Buttons.id)
- .all()
- )
- finally:
- SESSION.close()
-
-
-def num_notes():
- try:
- return SESSION.query(Notes).count()
- finally:
- SESSION.close()
-
-
-def num_chats():
- try:
- return SESSION.query(func.count(distinct(Notes.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with NOTES_INSERTION_LOCK:
- chat_notes = (
- SESSION.query(Notes).filter(Notes.chat_id == str(old_chat_id)).all()
- )
- for note in chat_notes:
- note.chat_id = str(new_chat_id)
-
- with BUTTONS_INSERTION_LOCK:
- chat_buttons = (
- SESSION.query(Buttons).filter(Buttons.chat_id == str(old_chat_id)).all()
- )
- for btn in chat_buttons:
- btn.chat_id = str(new_chat_id)
-
- SESSION.commit()
diff --git a/Exon/modules/sql/reporting_sql.py b/Exon/modules/sql/reporting_sql.py
deleted file mode 100644
index 7ae2fc32..00000000
--- a/Exon/modules/sql/reporting_sql.py
+++ /dev/null
@@ -1,117 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-from typing import Union
-
-from sqlalchemy import Boolean, Column, String
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class ReportingUserSettings(BASE):
- __tablename__ = "user_report_settings"
- user_id = Column(BigInteger, primary_key=True)
- should_report = Column(Boolean, default=True)
-
- def __init__(self, user_id):
- self.user_id = user_id
-
- def __repr__(self):
- return f""
-
-
-class ReportingChatSettings(BASE):
- __tablename__ = "chat_report_settings"
- chat_id = Column(String(14), primary_key=True)
- should_report = Column(Boolean, default=True)
-
- def __init__(self, chat_id):
- self.chat_id = str(chat_id)
-
- def __repr__(self):
- return f""
-
-
-ReportingUserSettings.__table__.create(checkfirst=True)
-ReportingChatSettings.__table__.create(checkfirst=True)
-
-CHAT_LOCK = threading.RLock()
-USER_LOCK = threading.RLock()
-
-
-def chat_should_report(chat_id: Union[str, int]) -> bool:
- try:
- if chat_setting := SESSION.query(ReportingChatSettings).get(
- str(chat_id)
- ):
- return chat_setting.should_report
- return False
- finally:
- SESSION.close()
-
-
-def user_should_report(user_id: int) -> bool:
- try:
- if user_setting := SESSION.query(ReportingUserSettings).get(user_id):
- return user_setting.should_report
- return True
- finally:
- SESSION.close()
-
-
-def set_chat_setting(chat_id: Union[int, str], setting: bool):
- with CHAT_LOCK:
- chat_setting = SESSION.query(ReportingChatSettings).get(str(chat_id)) or ReportingChatSettings(chat_id)
-
- chat_setting.should_report = setting
- SESSION.add(chat_setting)
- SESSION.commit()
-
-
-def set_user_setting(user_id: int, setting: bool):
- with USER_LOCK:
- user_setting = SESSION.query(ReportingUserSettings).get(user_id) or ReportingUserSettings(user_id)
-
- user_setting.should_report = setting
- SESSION.add(user_setting)
- SESSION.commit()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with CHAT_LOCK:
- chat_notes = (
- SESSION.query(ReportingChatSettings)
- .filter(ReportingChatSettings.chat_id == str(old_chat_id))
- .all()
- )
- for note in chat_notes:
- note.chat_id = str(new_chat_id)
- SESSION.commit()
diff --git a/Exon/modules/sql/rules_sql.py b/Exon/modules/sql/rules_sql.py
deleted file mode 100644
index ff4ac3ab..00000000
--- a/Exon/modules/sql/rules_sql.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import threading
-
-from sqlalchemy import Column, String, UnicodeText, distinct, func
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class Rules(BASE):
- __tablename__ = "rules"
- chat_id = Column(String(14), primary_key=True)
- rules = Column(UnicodeText, default="")
-
- def __init__(self, chat_id):
- self.chat_id = chat_id
-
- def __repr__(self):
- return f""
-
-
-Rules.__table__.create(checkfirst=True)
-
-INSERTION_LOCK = threading.RLock()
-
-
-def set_rules(chat_id, rules_text):
- with INSERTION_LOCK:
- rules = SESSION.query(Rules).get(str(chat_id)) or Rules(str(chat_id))
- rules.rules = rules_text
-
- SESSION.add(rules)
- SESSION.commit()
-
-
-def get_rules(chat_id):
- rules = SESSION.query(Rules).get(str(chat_id))
- ret = rules.rules if rules else ""
- SESSION.close()
- return ret
-
-
-def num_chats():
- try:
- return SESSION.query(func.count(distinct(Rules.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with INSERTION_LOCK:
- if chat := SESSION.query(Rules).get(str(old_chat_id)):
- chat.chat_id = str(new_chat_id)
- SESSION.commit()
diff --git a/Exon/modules/sql/userinfo_sql.py b/Exon/modules/sql/userinfo_sql.py
deleted file mode 100644
index 3598e4a5..00000000
--- a/Exon/modules/sql/userinfo_sql.py
+++ /dev/null
@@ -1,101 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import threading
-
-from sqlalchemy import Column, UnicodeText
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class UserInfo(BASE):
- __tablename__ = "userinfo"
- user_id = Column(BigInteger, primary_key=True)
- info = Column(UnicodeText)
-
- def __init__(self, user_id, info):
- self.user_id = user_id
- self.info = info
-
- def __repr__(self):
- return "" % self.user_id
-
-
-class UserBio(BASE):
- __tablename__ = "userbio"
- user_id = Column(BigInteger, primary_key=True)
- bio = Column(UnicodeText)
-
- def __init__(self, user_id, bio):
- self.user_id = user_id
- self.bio = bio
-
- def __repr__(self):
- return "" % self.user_id
-
-
-UserInfo.__table__.create(checkfirst=True)
-UserBio.__table__.create(checkfirst=True)
-
-INSERTION_LOCK = threading.RLock()
-
-
-def get_user_me_info(user_id):
- userinfo = SESSION.query(UserInfo).get(user_id)
- SESSION.close()
- return userinfo.info if userinfo else None
-
-
-def set_user_me_info(user_id, info):
- with INSERTION_LOCK:
- userinfo = SESSION.query(UserInfo).get(user_id)
- if userinfo:
- userinfo.info = info
- else:
- userinfo = UserInfo(user_id, info)
- SESSION.add(userinfo)
- SESSION.commit()
-
-
-def get_user_bio(user_id):
- userbio = SESSION.query(UserBio).get(user_id)
- SESSION.close()
- return userbio.bio if userbio else None
-
-
-def set_user_bio(user_id, bio):
- with INSERTION_LOCK:
- userbio = SESSION.query(UserBio).get(user_id)
- if userbio:
- userbio.bio = bio
- else:
- userbio = UserBio(user_id, bio)
-
- SESSION.add(userbio)
- SESSION.commit()
diff --git a/Exon/modules/sql/warns_sql.py b/Exon/modules/sql/warns_sql.py
deleted file mode 100644
index f2581086..00000000
--- a/Exon/modules/sql/warns_sql.py
+++ /dev/null
@@ -1,331 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import threading
-
-from sqlalchemy import Boolean, Column, Integer, String, UnicodeText, distinct, func
-from sqlalchemy.dialects import postgresql
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.sql import BASE, SESSION
-
-
-class Warns(BASE):
- __tablename__ = "warns"
-
- user_id = Column(BigInteger, primary_key=True)
- chat_id = Column(String(14), primary_key=True)
- num_warns = Column(Integer, default=0)
- reasons = Column(postgresql.ARRAY(UnicodeText))
-
- def __init__(self, user_id, chat_id):
- self.user_id = user_id
- self.chat_id = str(chat_id)
- self.num_warns = 0
- self.reasons = []
-
- def __repr__(self):
- return f"<{self.num_warns} warns for {self.user_id} in {self.chat_id} for reasons {self.reasons}>"
-
-
-class WarnFilters(BASE):
- __tablename__ = "warn_filters"
- chat_id = Column(String(14), primary_key=True)
- keyword = Column(UnicodeText, primary_key=True, nullable=False)
- reply = Column(UnicodeText, nullable=False)
-
- def __init__(self, chat_id, keyword, reply):
- self.chat_id = str(chat_id) # ensure string
- self.keyword = keyword
- self.reply = reply
-
- def __repr__(self):
- return f""
-
- def __eq__(self, other):
- return (
- isinstance(other, WarnFilters)
- and self.chat_id == other.chat_id
- and self.keyword == other.keyword
- )
-
-
-class WarnSettings(BASE):
- __tablename__ = "warn_settings"
- chat_id = Column(String(14), primary_key=True)
- warn_limit = Column(Integer, default=3)
- soft_warn = Column(Boolean, default=False)
-
- def __init__(self, chat_id, warn_limit=3, soft_warn=False):
- self.chat_id = str(chat_id)
- self.warn_limit = warn_limit
- self.soft_warn = soft_warn
-
- def __repr__(self):
- return f"<{self.chat_id} has {self.warn_limit} possible warns.>"
-
-
-Warns.__table__.create(checkfirst=True)
-WarnFilters.__table__.create(checkfirst=True)
-WarnSettings.__table__.create(checkfirst=True)
-
-WARN_INSERTION_LOCK = threading.RLock()
-WARN_FILTER_INSERTION_LOCK = threading.RLock()
-WARN_SETTINGS_LOCK = threading.RLock()
-
-WARN_FILTERS = {}
-
-
-def warn_user(user_id, chat_id, reason=None):
- with WARN_INSERTION_LOCK:
- warned_user = SESSION.query(Warns).get((user_id, str(chat_id))) or Warns(user_id, str(chat_id))
-
- warned_user.num_warns += 1
- if reason:
- warned_user.reasons = warned_user.reasons + [
- reason,
- ] # TODO:: double check this wizardry
-
- reasons = warned_user.reasons
- num = warned_user.num_warns
-
- SESSION.add(warned_user)
- SESSION.commit()
-
- return num, reasons
-
-
-def remove_warn(user_id, chat_id):
- with WARN_INSERTION_LOCK:
- removed = False
- warned_user = SESSION.query(Warns).get((user_id, str(chat_id)))
-
- if warned_user and warned_user.num_warns > 0:
- warned_user.num_warns -= 1
- warned_user.reasons = warned_user.reasons[:-1]
- SESSION.add(warned_user)
- SESSION.commit()
- removed = True
-
- SESSION.close()
- return removed
-
-
-def reset_warns(user_id, chat_id):
- with WARN_INSERTION_LOCK:
- if warned_user := SESSION.query(Warns).get((user_id, str(chat_id))):
- warned_user.num_warns = 0
- warned_user.reasons = []
-
- SESSION.add(warned_user)
- SESSION.commit()
- SESSION.close()
-
-
-def get_warns(user_id, chat_id):
- try:
- user = SESSION.query(Warns).get((user_id, str(chat_id)))
- return (user.num_warns, user.reasons) if user else None
- finally:
- SESSION.close()
-
-
-def add_warn_filter(chat_id, keyword, reply):
- with WARN_FILTER_INSERTION_LOCK:
- warn_filt = WarnFilters(str(chat_id), keyword, reply)
-
- if keyword not in WARN_FILTERS.get(str(chat_id), []):
- WARN_FILTERS[str(chat_id)] = sorted(
- WARN_FILTERS.get(str(chat_id), []) + [keyword],
- key=lambda x: (-len(x), x),
- )
-
- SESSION.merge(warn_filt) # merge to avoid duplicate key issues
- SESSION.commit()
-
-
-def remove_warn_filter(chat_id, keyword):
- with WARN_FILTER_INSERTION_LOCK:
- if warn_filt := SESSION.query(WarnFilters).get(
- (str(chat_id), keyword)
- ):
- if keyword in WARN_FILTERS.get(str(chat_id), []): # sanity check
- WARN_FILTERS.get(str(chat_id), []).remove(keyword)
-
- SESSION.delete(warn_filt)
- SESSION.commit()
- return True
- SESSION.close()
- return False
-
-
-def get_chat_warn_triggers(chat_id):
- return WARN_FILTERS.get(str(chat_id), set())
-
-
-def get_chat_warn_filters(chat_id):
- try:
- return (
- SESSION.query(WarnFilters).filter(WarnFilters.chat_id == str(chat_id)).all()
- )
- finally:
- SESSION.close()
-
-
-def get_warn_filter(chat_id, keyword):
- try:
- return SESSION.query(WarnFilters).get((str(chat_id), keyword))
- finally:
- SESSION.close()
-
-
-def set_warn_limit(chat_id, warn_limit):
- with WARN_SETTINGS_LOCK:
- curr_setting = SESSION.query(WarnSettings).get(str(chat_id)) or WarnSettings(chat_id, warn_limit=warn_limit)
-
- curr_setting.warn_limit = warn_limit
-
- SESSION.add(curr_setting)
- SESSION.commit()
-
-
-def set_warn_strength(chat_id, soft_warn):
- with WARN_SETTINGS_LOCK:
- curr_setting = SESSION.query(WarnSettings).get(str(chat_id)) or WarnSettings(chat_id, soft_warn=soft_warn)
-
- curr_setting.soft_warn = soft_warn
-
- SESSION.add(curr_setting)
- SESSION.commit()
-
-
-def get_warn_setting(chat_id):
- try:
- if setting := SESSION.query(WarnSettings).get(str(chat_id)):
- return setting.warn_limit, setting.soft_warn
- return 3, False
-
- finally:
- SESSION.close()
-
-
-def num_warns():
- try:
- return SESSION.query(func.sum(Warns.num_warns)).scalar() or 0
- finally:
- SESSION.close()
-
-
-def num_warn_chats():
- try:
- return SESSION.query(func.count(distinct(Warns.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def num_warn_filters():
- try:
- return SESSION.query(WarnFilters).count()
- finally:
- SESSION.close()
-
-
-def num_warn_chat_filters(chat_id):
- try:
- return (
- SESSION.query(WarnFilters.chat_id)
- .filter(WarnFilters.chat_id == str(chat_id))
- .count()
- )
- finally:
- SESSION.close()
-
-
-def num_warn_filter_chats():
- try:
- return SESSION.query(func.count(distinct(WarnFilters.chat_id))).scalar()
- finally:
- SESSION.close()
-
-
-def __load_chat_warn_filters():
- global WARN_FILTERS
- try:
- chats = SESSION.query(WarnFilters.chat_id).distinct().all()
- for (chat_id,) in chats: # remove tuple by ( ,)
- WARN_FILTERS[chat_id] = []
-
- all_filters = SESSION.query(WarnFilters).all()
- for x in all_filters:
- WARN_FILTERS[x.chat_id] += [x.keyword]
-
- WARN_FILTERS = {
- x: sorted(set(y), key=lambda i: (-len(i), i))
- for x, y in WARN_FILTERS.items()
- }
-
- finally:
- SESSION.close()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with WARN_INSERTION_LOCK:
- chat_notes = (
- SESSION.query(Warns).filter(Warns.chat_id == str(old_chat_id)).all()
- )
- for note in chat_notes:
- note.chat_id = str(new_chat_id)
- SESSION.commit()
-
- with WARN_FILTER_INSERTION_LOCK:
- chat_filters = (
- SESSION.query(WarnFilters)
- .filter(WarnFilters.chat_id == str(old_chat_id))
- .all()
- )
- for filt in chat_filters:
- filt.chat_id = str(new_chat_id)
- SESSION.commit()
- old_warn_filt = WARN_FILTERS.get(str(old_chat_id))
- if old_warn_filt is not None:
- WARN_FILTERS[str(new_chat_id)] = old_warn_filt
- del WARN_FILTERS[str(old_chat_id)]
-
- with WARN_SETTINGS_LOCK:
- chat_settings = (
- SESSION.query(WarnSettings)
- .filter(WarnSettings.chat_id == str(old_chat_id))
- .all()
- )
- for setting in chat_settings:
- setting.chat_id = str(new_chat_id)
- SESSION.commit()
-
-
-__load_chat_warn_filters()
diff --git a/Exon/modules/sql/welcome_sql.py b/Exon/modules/sql/welcome_sql.py
deleted file mode 100644
index cc91f673..00000000
--- a/Exon/modules/sql/welcome_sql.py
+++ /dev/null
@@ -1,698 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import random
-import threading
-from typing import Union
-
-from sqlalchemy import Boolean, Column, Integer, String, UnicodeText
-from sqlalchemy.sql.sqltypes import BigInteger
-
-from Exon.modules.helper_funcs.msg_types import Types
-from Exon.modules.sql import BASE, SESSION
-
-DEFAULT_WELCOME = "Hey {first}, how are you?"
-DEFAULT_GOODBYE = "Nice knowing ya!"
-
-DEFAULT_WELCOME_MESSAGES = [
- "{first} is here!", # Discord welcome messages copied
- "Ready player {first}",
- "Genos, {first} is here.",
- "A wild {first} appeared.",
- "{first} came in like a Lion!",
- "{first} has joined your party.",
- "{first} just joined. Can I get a heal?",
- "{first} just joined the chat - asdgfhak!",
- "{first} just joined. Everyone, look busy!",
- "Welcome, {first}. Stay awhile and listen.",
- "Welcome, {first}. We were expecting you ( ͡° ͜ʖ ͡°)",
- "Welcome, {first}. We hope you brought pizza.",
- "Welcome, {first}. Leave your weapons by the door.",
- "Swoooosh. {first} just landed.",
- "Brace yourselves. {first} just joined the chat.",
- "{first} just joined. Hide your bananas.",
- "{first} just arrived. Seems OP - please nerf.",
- "{first} just slid into the chat.",
- "A {first} has spawned in the chat.",
- "Big {first} showed up!",
- "Where’s {first}? In the chat!",
- "{first} hopped into the chat. Kangaroo!!",
- "{first} just showed up. Hold my beer.",
- "Challenger approaching! {first} has appeared!",
- "It's a bird! It's a plane! Nevermind, it's just {first}.",
- r"It's {first}! Praise the sun! \o/",
- "Never gonna give {first} up. Never gonna let {first} down.",
- "Ha! {first} has joined! You activated my trap card!",
- "Hey! Listen! {first} has joined!",
- "We've been expecting you {first}",
- "It's dangerous to go alone, take {first}!",
- "{first} has joined the chat! It's super effective!",
- "Cheers, love! {first} is here!",
- "{first} is here, as the prophecy foretold.",
- "{first} has arrived. Party's over.",
- "{first} is here to kick butt and chew bubblegum. And {first} is all out of gum.",
- "Hello. Is it {first} you're looking for?",
- "{first} has joined. Stay awhile and listen!",
- "Roses are red, violets are blue, {first} joined this chat with you",
- "Welcome {first}, Avoid Punches if you can!",
- "It's a bird! It's a plane! - Nope, its {first}!",
- "{first} Joined! - Ok.", # Discord welcome messages end.
- "All Hail {first}!",
- "Hi, {first}. Don't lurk, only Villans do that.",
- "{first} has joined the battle bus.",
- "A new Challenger enters!", # Tekken
- "Ok!",
- "{first} just fell into the chat!",
- "Something just fell from the sky! - oh, its {first}.",
- "{first} Just teleported into the chat!",
- "Hi, {first}, show me your Hunter License!", # Hunter Hunter
- "I'm looking for Garo, oh wait nvm it's {first}.", # One Punch man s2
- "Welcome {first}, leaving is not an option!",
- "Run Forest! ..I mean...{first}.",
- "{first} do 100 push-ups, 100 sit-ups, 100 squats, and 10km running EVERY SINGLE DAY!!!", # One Punch ma
- "Huh?\nDid someone with a disaster level just join?\nOh wait, it's just {first}.", # One Punch ma
- "Hey, {first}, ever heard the King Engine?", # One Punch ma
- "Hey, {first}, empty your pockets.",
- "Hey, {first}!, are you strong?",
- "Call the Avengers! - {first} just joined the chat.",
- "{first} joined. You must construct additional pylons.",
- "Ermagherd. {first} is here.",
- "Come for the Snail Racing, Stay for the Chimichangas!",
- "Who needs Google? You're everything we were searching for.",
- "This place must have free WiFi, cause I'm feeling a connection.",
- "Speak friend and enter.",
- "Welcome you are",
- "Welcome {first}, your princess is in another castle.",
- "Hi {first}, welcome to the dark side.",
- "Hola {first}, beware of people with disaster levels",
- "Hey {first}, we have the droids you are looking for.",
- "Hi {first}\nThis isn't a strange place, this is my home, it's the people who are strange.",
- "Oh, hey {first} what's the password?",
- "Hey {first}, I know what we're gonna do today",
- "{first} just joined, be at alert they could be a spy.",
- "{first} joined the group, read by Mark Zuckerberg, CIA and 35 others.",
- "Welcome {first}, watch out for falling monkeys.",
- "Everyone stop what you’re doing, We are now in the presence of {first}.",
- "Hey {first}, do you wanna know how I got these scars?",
- "Welcome {first}, drop your weapons and proceed to the spy scanner.",
- "Stay safe {first}, Keep 3 meters social distances between your messages.", # Corona memes lmao
- "Hey {first}, Do you know I once One-punched a meteorite?",
- "You’re here now {first}, Resistance is futile",
- "{first} just arrived, the force is strong with this one.",
- "{first} just joined on president’s orders.",
- "Hi {first}, is the glass half full or half empty?",
- "Yipee Kayaye {first} arrived.",
- "Welcome {first}, if you’re a secret agent press 1, otherwise start a conversation",
- "{first}, I have a feeling we’re not in Kansas anymore.",
- "They may take our lives, but they’ll never take our {first}.",
- "Coast is clear! You can come out guys, it’s just {first}.",
- "Welcome {first}, pay no attention to that guy lurking.",
- "Welcome {first}, may the force be with you.",
- "May the {first} be with you.",
- "{first} just joined. Hey, where's Perry?",
- "{first} just joined. Oh, there you are, Perry.",
- "Ladies and gentlemen, I give you ... {first}.",
- "Behold my new evil scheme, the {first}-Inator.",
- "Ah, {first} the Platypus, you're just in time... to be trapped.",
- "{first} just arrived. Diable Jamble!", # One Piece Sanji
- "{first} just arrived. Aschente!", # No Game No Life
- "{first} say Aschente to swear by the pledges.", # No Game No Life
- "{first} just joined. El Psy congroo!", # Steins Gate
- "Irasshaimase {first}!", # weeabo shit
- "Hi {first}, what is 1000-7?", # tokyo ghoul
- "Come. I don't want to destroy this place", # hunter x hunter
- "I... am... Whitebeard!...wait..wrong anime.", # one Piece
- "Hey {first}...have you ever heard these words?", # BNHA
- "Can't a guy get a little sleep around here?", # Kamina Falls – Gurren Lagann
- "It's time someone put you in your place, {first}.", # Hellsing
- "Unit-01's reactivated..", # Neon Genesis: Evangelion
- "Prepare for trouble...And make it double", # Pokemon
- "Hey {first}, are You Challenging Me?", # Shaggy
- "Oh? You're Approaching Me?", # jojo
- "Ho… mukatta kuruno ka?", # jojo jap ver
- "I can't beat the shit out of you without getting closer", # jojo
- "Ho ho! Then come as close as you'd like.", # jojo
- "Hoho! Dewa juubun chikazukanai youi", # jojo jap ver
- "Guess who survived his time in Hell, {first}.", # jojo
- "How many loaves of bread have you eaten in your lifetime?", # jojo
- "What did you say? Depending on your answer, I may have to kick your ass!", # jojo
- "Oh? You're approaching me? Instead of running away, you come right to me? Even though your grandfather, Joseph, told you the secret of The World, like an exam student scrambling to finish the problems on an exam until the last moments before the chime?",
- # jojo
- "Rerorerorerorerorero.", # jojo
- "{first} just warped into the group!",
- "I..it's..it's just {first}.",
- "Sugoi, Dekai. {first} Joined!",
- "{first}, do you know gods of death love apples?", # Death Note owo
- "I'll take a potato chip.... and eat it", # Death Note owo
- "Oshiete oshiete yo sono shikumi wo!", # Tokyo Ghoul
- "Kaizoku ou ni...nvm wrong anime.", # op
- "{first} just joined! Gear.....second!", # Op
- "Omae wa mou....shindeiru",
- "Hey {first}, the leaf village lotus blooms twice!", # Naruto stuff begins from here
- "{first} Joined! Omote renge!",
- "{first}! I, Madara! declare you the strongest",
- "{first}, this time I'll lend you my power. ", # Kyuubi to naruto
- "{first}, welcome to the hidden leaf village!", # Naruto thingies end here
- "In the jungle, you must wait...until the dice read five or eight.", # Jumanji stuff
- "Dr.{first} Famed archeologist and international explorer,\nWelcome to Jumanji!\nJumanji's Fate is up to you now.",
- "{first}, this will not be an easy mission - monkeys slow the expedition.", # End of Jumanji stuff
- "Remember, remember, the Fifth of November, the Gunpowder Treason and Plot. I know of no reason why the Gunpowder Treason should ever be forgot.",
- # V for Vendetta
- "The only verdict is vengeance; a vendetta, held as a votive not in vain, for the value and veracity of such shall one day vindicate the vigilant and the virtuous.",
- # V for Vendetta
- "Behind {first} there is more than just flesh. Beneath this user there is an idea... and ideas are bulletproof.",
- # V for Vendetta
- "Love your rage, not your cage.", # V for Vendetta
- "Get your stinking paws off me, you damned dirty ape!", # Planet of the apes
- "Elementary, my dear {first}.",
- "I'm back - {first}.",
- "Bond. {first} Bond.",
- "Come with me if you want to live",
-]
-DEFAULT_GOODBYE_MESSAGES = [
- "{first} will be missed.",
- "{first} just went offline.",
- "{first} has left the lobby.",
- "{first} has left the clan.",
- "{first} has left the game.",
- "{first} has fled the area.",
- "{first} is out of the running.",
- "Nice knowing ya, {first}!",
- "It was a fun time {first}.",
- "We hope to see you again soon, {first}.",
- "I donut want to say goodbye, {first}.",
- "Goodbye {first}! Guess who's gonna miss you :')",
- "Goodbye {first}! It's gonna be lonely without ya.",
- "Please don't leave me alone in this place, {first}!",
- "Good luck finding better shit-posters than us, {first}!",
- "You know we're gonna miss you {first}. Right? Right? Right?",
- "Congratulations, {first}! You're officially free of this mess.",
- "{first}. You were an opponent worth fighting.",
- "You're leaving, {first}? Yare Yare Daze.",
- "Bring him the photo",
- "Go outside!",
- "Ask again later",
- "Think for yourself",
- "Question authority",
- "You are worshiping a sun god",
- "Don't leave the house today",
- "Give up!",
- "Marry and reproduce",
- "Stay asleep",
- "Wake up",
- "Look to la luna",
- "Steven lives",
- "Meet strangers without prejudice",
- "A hanged man will bring you no luck today",
- "What do you want to do today?",
- "You are dark inside",
- "Have you seen the exit?",
- "Get a baby pet it will cheer you up.",
- "Your princess is in another castle.",
- "You are playing it wrong give me the controller",
- "Trust good people",
- "Live to die.",
- "When life gives you lemons reroll!",
- "Well, that was worthless",
- "I fell asleep!",
- "May your troubles be many",
- "Your old life lies in ruin",
- "Always look on the bright side",
- "It is dangerous to go alone",
- "You will never be forgiven",
- "You have nobody to blame but yourself",
- "Only a sinner",
- "Use bombs wisely",
- "Nobody knows the troubles you have seen",
- "You look fat you should exercise more",
- "Follow the zebra",
- "Why so blue?",
- "The devil in disguise",
- "Go outside",
- "Always your head in the clouds",
-]
-
-
-# Line 111 to 152 are references from https://bindingofisaac.fandom.com/wiki/Fortune_Telling_Machine
-
-
-class Welcome(BASE):
- __tablename__ = "welcome_pref"
- chat_id = Column(String(14), primary_key=True)
- should_welcome = Column(Boolean, default=True)
- should_goodbye = Column(Boolean, default=True)
- custom_content = Column(UnicodeText, default=None)
-
- custom_welcome = Column(
- UnicodeText,
- default=random.choice(DEFAULT_WELCOME_MESSAGES),
- )
- welcome_type = Column(Integer, default=Types.TEXT.value)
-
- custom_leave = Column(UnicodeText, default=random.choice(DEFAULT_GOODBYE_MESSAGES))
- leave_type = Column(Integer, default=Types.TEXT.value)
-
- clean_welcome = Column(Integer)
-
- def __init__(self, chat_id, should_welcome=True, should_goodbye=True):
- self.chat_id = chat_id
- self.should_welcome = should_welcome
- self.should_goodbye = should_goodbye
-
- def __repr__(self):
- return f""
-
-
-class WelcomeButtons(BASE):
- __tablename__ = "welcome_urls"
- id = Column(Integer, primary_key=True, autoincrement=True)
- chat_id = Column(String(14), primary_key=True)
- name = Column(UnicodeText, nullable=False)
- url = Column(UnicodeText, nullable=False)
- same_line = Column(Boolean, default=False)
-
- def __init__(self, chat_id, name, url, same_line=False):
- self.chat_id = str(chat_id)
- self.name = name
- self.url = url
- self.same_line = same_line
-
-
-class GoodbyeButtons(BASE):
- __tablename__ = "leave_urls"
- id = Column(Integer, primary_key=True, autoincrement=True)
- chat_id = Column(String(14), primary_key=True)
- name = Column(UnicodeText, nullable=False)
- url = Column(UnicodeText, nullable=False)
- same_line = Column(Boolean, default=False)
-
- def __init__(self, chat_id, name, url, same_line=False):
- self.chat_id = str(chat_id)
- self.name = name
- self.url = url
- self.same_line = same_line
-
-
-class WelcomeMute(BASE):
- __tablename__ = "welcome_mutes"
- chat_id = Column(String(14), primary_key=True)
- welcomemutes = Column(UnicodeText, default=False)
-
- def __init__(self, chat_id, welcomemutes):
- self.chat_id = str(chat_id) # ensure string
- self.welcomemutes = welcomemutes
-
-
-class WelcomeMuteUsers(BASE):
- __tablename__ = "human_checks"
- user_id = Column(BigInteger, primary_key=True)
- chat_id = Column(String(14), primary_key=True)
- human_check = Column(Boolean)
-
- def __init__(self, user_id, chat_id, human_check):
- self.user_id = user_id # ensure string
- self.chat_id = str(chat_id)
- self.human_check = human_check
-
-
-class CleanServiceSetting(BASE):
- __tablename__ = "clean_service"
- chat_id = Column(String(14), primary_key=True)
- clean_service = Column(Boolean, default=True)
-
- def __init__(self, chat_id):
- self.chat_id = str(chat_id)
-
- def __repr__(self):
- return f""
-
-
-class DefenseMode(BASE):
- __tablename__ = "defense_mode"
- chat_id = Column(String(14), primary_key=True)
- status = Column(Boolean, default=False)
- time = Column(Integer, default=21600)
- acttime = Column(Integer, default=3600)
- permanent = Column(Boolean, default=False)
-
- def __init__(self, chat_id, status, time, acttime, permanent):
- self.chat_id = str(chat_id)
- self.status = status
- self.time = time
- self.acttime = acttime
- self.permanent = permanent
-
-
-Welcome.__table__.create(checkfirst=True)
-WelcomeButtons.__table__.create(checkfirst=True)
-GoodbyeButtons.__table__.create(checkfirst=True)
-WelcomeMute.__table__.create(checkfirst=True)
-WelcomeMuteUsers.__table__.create(checkfirst=True)
-CleanServiceSetting.__table__.create(checkfirst=True)
-DefenseMode.__table__.create(checkfirst=True)
-
-INSERTION_LOCK = threading.RLock()
-WELC_BTN_LOCK = threading.RLock()
-LEAVE_BTN_LOCK = threading.RLock()
-WM_LOCK = threading.RLock()
-CS_LOCK = threading.RLock()
-DEFENSE_LOCK = threading.RLock()
-
-
-def welcome_mutes(chat_id):
- try:
- if welcomemutes := SESSION.query(WelcomeMute).get(str(chat_id)):
- return welcomemutes.welcomemutes
- return False
- finally:
- SESSION.close()
-
-
-def set_welcome_mutes(chat_id, welcomemutes):
- with WM_LOCK:
- if prev := SESSION.query(WelcomeMute).get((str(chat_id))):
- SESSION.delete(prev)
- welcome_m = WelcomeMute(str(chat_id), welcomemutes)
- SESSION.add(welcome_m)
- SESSION.commit()
-
-
-def set_human_checks(user_id, chat_id):
- with INSERTION_LOCK:
- human_check = SESSION.query(WelcomeMuteUsers).get((user_id, str(chat_id)))
- if not human_check:
- human_check = WelcomeMuteUsers(user_id, str(chat_id), True)
-
- else:
- human_check.human_check = True
-
- SESSION.add(human_check)
- SESSION.commit()
-
- return human_check
-
-
-def get_human_checks(user_id, chat_id):
- try:
- human_check = SESSION.query(WelcomeMuteUsers).get((user_id, str(chat_id)))
- return human_check.human_check if human_check else None
- finally:
- SESSION.close()
-
-
-def get_welc_mutes_pref(chat_id):
- welcomemutes = SESSION.query(WelcomeMute).get(str(chat_id))
- SESSION.close()
-
- return welcomemutes.welcomemutes if welcomemutes else False
-
-
-def get_welc_pref(chat_id):
- welc = SESSION.query(Welcome).get(str(chat_id))
- SESSION.close()
- if welc:
- return (
- welc.should_welcome,
- welc.custom_welcome,
- welc.custom_content,
- welc.welcome_type,
- )
- # Welcome by default.
- return True, DEFAULT_WELCOME, None, Types.TEXT
-
-
-def get_gdbye_pref(chat_id):
- welc = SESSION.query(Welcome).get(str(chat_id))
- SESSION.close()
- if welc:
- return welc.should_goodbye, welc.custom_leave, welc.leave_type
- # Welcome by default.
- return True, DEFAULT_GOODBYE, Types.TEXT
-
-
-def set_clean_welcome(chat_id, clean_welcome):
- with INSERTION_LOCK:
- curr = SESSION.query(Welcome).get(str(chat_id)) or Welcome(str(chat_id))
-
- curr.clean_welcome = int(clean_welcome)
-
- SESSION.add(curr)
- SESSION.commit()
-
-
-def get_clean_pref(chat_id):
- welc = SESSION.query(Welcome).get(str(chat_id))
- SESSION.close()
-
- return welc.clean_welcome if welc else False
-
-
-def set_welc_preference(chat_id, should_welcome):
- with INSERTION_LOCK:
- curr = SESSION.query(Welcome).get(str(chat_id))
- if not curr:
- curr = Welcome(str(chat_id), should_welcome=should_welcome)
- else:
- curr.should_welcome = should_welcome
-
- SESSION.add(curr)
- SESSION.commit()
-
-
-def set_gdbye_preference(chat_id, should_goodbye):
- with INSERTION_LOCK:
- curr = SESSION.query(Welcome).get(str(chat_id))
- if not curr:
- curr = Welcome(str(chat_id), should_goodbye=should_goodbye)
- else:
- curr.should_goodbye = should_goodbye
-
- SESSION.add(curr)
- SESSION.commit()
-
-
-def set_custom_welcome(
- chat_id,
- custom_content,
- custom_welcome,
- welcome_type,
- buttons=None,
-):
- if buttons is None:
- buttons = []
-
- with INSERTION_LOCK:
- welcome_settings = SESSION.query(Welcome).get(str(chat_id)) or Welcome(str(chat_id), True)
-
- if custom_welcome or custom_content:
- welcome_settings.custom_content = custom_content
- welcome_settings.custom_welcome = custom_welcome
- welcome_settings.welcome_type = welcome_type.value
-
- else:
- welcome_settings.custom_welcome = DEFAULT_WELCOME
- welcome_settings.welcome_type = Types.TEXT.value
-
- SESSION.add(welcome_settings)
-
- with WELC_BTN_LOCK:
- prev_buttons = (
- SESSION.query(WelcomeButtons)
- .filter(WelcomeButtons.chat_id == str(chat_id))
- .all()
- )
- for btn in prev_buttons:
- SESSION.delete(btn)
-
- for b_name, url, same_line in buttons:
- button = WelcomeButtons(chat_id, b_name, url, same_line)
- SESSION.add(button)
-
- SESSION.commit()
-
-
-def get_custom_welcome(chat_id):
- welcome_settings = SESSION.query(Welcome).get(str(chat_id))
- ret = DEFAULT_WELCOME
- if welcome_settings and welcome_settings.custom_welcome:
- ret = welcome_settings.custom_welcome
-
- SESSION.close()
- return ret
-
-
-def set_custom_gdbye(chat_id, custom_goodbye, goodbye_type, buttons=None):
- if buttons is None:
- buttons = []
-
- with INSERTION_LOCK:
- welcome_settings = SESSION.query(Welcome).get(str(chat_id)) or Welcome(str(chat_id), True)
-
- if custom_goodbye:
- welcome_settings.custom_leave = custom_goodbye
- welcome_settings.leave_type = goodbye_type.value
-
- else:
- welcome_settings.custom_leave = DEFAULT_GOODBYE
- welcome_settings.leave_type = Types.TEXT.value
-
- SESSION.add(welcome_settings)
-
- with LEAVE_BTN_LOCK:
- prev_buttons = (
- SESSION.query(GoodbyeButtons)
- .filter(GoodbyeButtons.chat_id == str(chat_id))
- .all()
- )
- for btn in prev_buttons:
- SESSION.delete(btn)
-
- for b_name, url, same_line in buttons:
- button = GoodbyeButtons(chat_id, b_name, url, same_line)
- SESSION.add(button)
-
- SESSION.commit()
-
-
-def get_custom_gdbye(chat_id):
- welcome_settings = SESSION.query(Welcome).get(str(chat_id))
- ret = DEFAULT_GOODBYE
- if welcome_settings and welcome_settings.custom_leave:
- ret = welcome_settings.custom_leave
-
- SESSION.close()
- return ret
-
-
-def get_welc_buttons(chat_id):
- try:
- return (
- SESSION.query(WelcomeButtons)
- .filter(WelcomeButtons.chat_id == str(chat_id))
- .order_by(WelcomeButtons.id)
- .all()
- )
- finally:
- SESSION.close()
-
-
-def get_gdbye_buttons(chat_id):
- try:
- return (
- SESSION.query(GoodbyeButtons)
- .filter(GoodbyeButtons.chat_id == str(chat_id))
- .order_by(GoodbyeButtons.id)
- .all()
- )
- finally:
- SESSION.close()
-
-
-def clean_service(chat_id: Union[str, int]) -> bool:
- try:
- if chat_setting := SESSION.query(CleanServiceSetting).get(
- str(chat_id)
- ):
- return chat_setting.clean_service
- return False
- finally:
- SESSION.close()
-
-
-def set_clean_service(chat_id: Union[int, str], setting: bool):
- with CS_LOCK:
- chat_setting = SESSION.query(CleanServiceSetting).get(str(chat_id)) or CleanServiceSetting(chat_id)
-
- chat_setting.clean_service = setting
- SESSION.add(chat_setting)
- SESSION.commit()
-
-
-def migrate_chat(old_chat_id, new_chat_id):
- with INSERTION_LOCK:
- if chat := SESSION.query(Welcome).get(str(old_chat_id)):
- chat.chat_id = str(new_chat_id)
-
- with WELC_BTN_LOCK:
- chat_buttons = (
- SESSION.query(WelcomeButtons)
- .filter(WelcomeButtons.chat_id == str(old_chat_id))
- .all()
- )
- for btn in chat_buttons:
- btn.chat_id = str(new_chat_id)
-
- with LEAVE_BTN_LOCK:
- chat_buttons = (
- SESSION.query(GoodbyeButtons)
- .filter(GoodbyeButtons.chat_id == str(old_chat_id))
- .all()
- )
- for btn in chat_buttons:
- btn.chat_id = str(new_chat_id)
-
- SESSION.commit()
-
-
-def getDefenseStatus(chat_id):
- try:
- if stat := SESSION.query(DefenseMode).get(str(chat_id)):
- return stat.status, stat.time, stat.acttime
- return False, 21600, 3600 # default
- finally:
- SESSION.close()
-
-
-def setDefenseStatus(chat_id, status, time=21600, acttime=3600):
- with DEFENSE_LOCK:
- prevObj = SESSION.query(DefenseMode).get(str(chat_id))
- perma = False
- if prevObj:
- perma = prevObj.permanent
- SESSION.delete(prevObj)
- newObj = DefenseMode(str(chat_id), status, time, acttime, perma or False)
- SESSION.add(newObj)
- SESSION.commit()
-
-
-def toggleDefenseStatus(chat_id):
- newObj = True
- with DEFENSE_LOCK:
- prevObj = SESSION.query(DefenseMode).get(str(chat_id))
- if prevObj:
- newObj = not prevObj.status
- stat = DefenseMode(
- str(chat_id),
- newObj,
- prevObj.time or 21600,
- prevObj.acttime or 3600,
- prevObj.permanent or False,
- )
- SESSION.add(stat)
- SESSION.commit()
- return newObj
diff --git a/Exon/modules/stats.py b/Exon/modules/stats.py
deleted file mode 100644
index 89e18271..00000000
--- a/Exon/modules/stats.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import os
-import time
-
-import psutil
-
-import Exon.modules.no_sql.users_db as users_db
-from Exon import BOT_NAME, StartTime
-from Exon.modules.helper_funcs import formatter
-
-
-# sᴛᴀᴛs ᴍᴏᴅᴜʟᴇ
-
-
-async def bot_sys_stats():
- bot_uptime = int(time.time() - StartTime)
- cpu = psutil.cpu_percent()
- mem = psutil.virtual_memory().percent
- disk = psutil.disk_usage("/").percent
- process = psutil.Process(os.getpid())
- return f"""
-------------------
-⛖ {BOT_NAME} ᴜᴘᴛɪᴍᴇ : {formatter.get_readable_time(bot_uptime)}
-⛖ ʙᴏᴛ ᴄᴀᴘᴀᴄɪᴛʏ : {round(process.memory_info()[0] / 1024 ** 2)} ᴍʙ
-⛖ ᴄᴘᴜ ᴜsᴀɢᴇ : {cpu}%
-⛖ ʀᴀᴍ ᴜsᴀɢᴇ : {mem}%
-⛖ ᴅɪsᴋ ᴜsᴀɢᴇ : {disk}%
-⛖ ᴜsᴇʀs : 0{users_db.num_users()} ᴜsᴇʀs.
-⛖ ɢʀᴏᴜᴘs : 0{users_db.num_chats()} ɢʀᴏᴜᴘs.
-"""
diff --git a/Exon/modules/stickers.py b/Exon/modules/stickers.py
deleted file mode 100644
index 8e39f212..00000000
--- a/Exon/modules/stickers.py
+++ /dev/null
@@ -1,1037 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import math
-import os
-import textwrap
-import urllib.request as urllib
-from html import escape
-from io import BytesIO
-from urllib.parse import quote as urlquote
-
-import cv2
-import ffmpeg
-from PIL import Image, ImageDraw, ImageFont
-from bs4 import BeautifulSoup
-from cloudscraper import CloudScraper
-from telegram import (
- Bot,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- TelegramError,
- Update,
-)
-from telegram.ext import CallbackContext, CallbackQueryHandler, CommandHandler
-from telegram.utils.helpers import mention_html
-
-from Exon import dispatcher
-from Exon import telethn as bot
-from Exon.events import register as asux
-
-combot_stickers_url = "https://combot.org/telegram/stickers?q="
-
-
-def sticker_count(bot: Bot, pname: str) -> int:
- resp = bot._request.post(
- f"{bot.base_url}/getStickerSet",
- {
- "name": pname,
- },
- )
- return len(resp["stickers"])
-
-
-def convert_gif(input):
- """ғᴜɴᴄᴛɪᴏɴ ᴛᴏ ᴄᴏɴᴠᴇʀᴛ ᴍᴘ4 ᴛᴏ ᴡᴇʙᴍ(ᴠᴘ9)!(ᴀʙɪsʜɴᴏɪ)"""
-
- vid = cv2.VideoCapture(input)
- height = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)
- width = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
-
- # check height and width to scale
- if width > height:
- width = 512
- height = -1
- elif height > width:
- height = 512
- width = -1
- elif width == height:
- width = 512
- height = 512
-
- converted_name = "kangsticker.webm"
-
- (
- ffmpeg.input(input)
- .filter("fps", fps=30, round="up")
- .filter("scale", width=width, height=height)
- .trim(start="00:00:00", end="00:00:03", duration="3")
- .output(
- converted_name,
- vcodec="libvpx-vp9",
- **{
- # 'vf': 'scale=512:-1',
- "crf": "30"
- },
- )
- .overwrite_output()
- .run()
- )
-
- return converted_name
-
-
-def stickerid(update: Update, context: CallbackContext):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.sticker:
- update.effective_message.reply_text(
- "ʜᴇʟʟᴏ "
- + f"{mention_html(msg.from_user.id, msg.from_user.first_name)}"
- + ", ᴛʜᴇ sᴛɪᴄᴋᴇʀ ɪᴅ ʏᴏᴜ ᴀʀᴇ ʀᴇᴘʟʏɪɴɢ ɪs:\n"
- + escape(msg.reply_to_message.sticker.file_id)
- + "
",
- parse_mode=ParseMode.HTML,
- )
- else:
- update.effective_message.reply_text(
- "ʜᴇʟʟᴏ "
- + f"{mention_html(msg.from_user.id, msg.from_user.first_name)}"
- + ", ᴘʟᴇᴀsᴇ ʀᴇᴘʟʏ ᴛᴏ sᴛɪᴄᴋᴇʀ ᴍᴇssᴀɢᴇ ᴛᴏ ɢᴇᴛ ɪᴅ sᴛɪᴄᴋᴇʀ",
- parse_mode=ParseMode.HTML,
- )
-
-
-scraper = CloudScraper()
-
-
-def get_cbs_data(query, page, user_id):
- # returns (text, buttons)
- text = scraper.get(f"{combot_stickers_url}{urlquote(query)}&page={page}").text
- soup = BeautifulSoup(text, "lxml")
- div = soup.find("div", class_="page__container")
- packs = div.find_all("a", class_="sticker-pack__btn")
- titles = div.find_all("div", "sticker-pack__title")
- has_prev_page = has_next_page = None
- highlighted_page = div.find("a", class_="pagination__link is-active")
- if highlighted_page is not None and user_id is not None:
- highlighted_page = highlighted_page.parent
- has_prev_page = highlighted_page.previous_sibling.previous_sibling is not None
- has_next_page = highlighted_page.next_sibling.next_sibling is not None
- buttons = []
- if has_prev_page:
- buttons.append(
- InlineKeyboardButton(text="⟨", callback_data=f"cbs_{page - 1}_{user_id}")
- )
- if has_next_page:
- buttons.append(
- InlineKeyboardButton(text="⟩", callback_data=f"cbs_{page + 1}_{user_id}")
- )
- buttons = InlineKeyboardMarkup([buttons]) if buttons else None
- text = f"sᴛɪᴄᴋᴇʀs ғᴏʀ {escape(query)}
:\nᴘᴀɢᴇ: {page}"
- if packs and titles:
- for pack, title in zip(packs, titles):
- link = pack["href"]
- text += f"\n• {escape(title.get_text())}"
- elif page == 1:
- text = "ɴᴏ ʀᴇsᴜʟᴛs ғᴏᴜɴᴅ, ᴛʀʏ ᴀ ᴅɪғғᴇʀᴇɴᴛ ᴛᴇʀᴍ"
- else:
- text += "\n\nɪɴᴛᴇʀᴇsᴛɪɴɢʟʏ, ᴛʜᴇʀᴇ's ɴᴏᴛʜɪɴɢ ʜᴇʀᴇ."
- return text, buttons
-
-
-def cb_sticker(update: Update, context: CallbackContext):
- msg = update.effective_message
- query = " ".join(msg.text.split()[1:])
- if not query:
- msg.reply_text("ᴘʀᴏᴠɪᴅᴇ sᴏᴍᴇ ᴛᴇʀᴍ ᴛᴏ sᴇᴀʀᴄʜ ғᴏʀ ᴀ sᴛɪᴄᴋᴇʀ ᴘᴀᴄᴋ.")
- return
- if len(query) > 50:
- msg.reply_text("ᴘʀᴏᴠɪᴅᴇ ᴀ sᴇᴀʀᴄʜ ǫᴜᴇʀʏ ᴜɴᴅᴇʀ 50 ᴄʜᴀʀᴀᴄᴛᴇʀs")
- return
- user_id = msg.from_user.id if msg.from_user else None
- text, buttons = get_cbs_data(query, 1, user_id)
- msg.reply_text(text, parse_mode=ParseMode.HTML, reply_markup=buttons)
-
-
-def cbs_callback(update: Update, context: CallbackContext):
- query = update.callback_query
- _, page, user_id = query.data.split("_", 2)
- if int(user_id) != query.from_user.id:
- query.answer("ɴᴏᴛ ғᴏʀ ʏᴏᴜ", cache_time=60 * 60)
- return
- search_query = query.message.text.split("\n", 1)[0].split(maxsplit=2)[2][:-1]
- text, buttons = get_cbs_data(search_query, int(page), query.from_user.id)
- query.edit_message_text(text, parse_mode=ParseMode.HTML, reply_markup=buttons)
- query.answer()
-
-
-def getsticker(update: Update, context: CallbackContext):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.sticker:
- file_id = msg.reply_to_message.sticker.file_id
- bot = context.bot
- is_anim = msg.reply_to_message.sticker.is_animated
- sticker_data = bot.get_file(file_id).download(out=BytesIO())
- sticker_data.seek(0)
- filename = "animated_sticker.tgs.hmm_" if is_anim else "sticker.png"
-
- bot.send_document(
- update.effective_chat.id,
- document=sticker_data,
- filename=filename,
- )
-
- else:
- update.effective_message.reply_text(
- "ᴘʟᴇᴀsᴇ ʀᴇᴘʟʏ ᴛᴏ ᴀ sᴛɪᴄᴋᴇʀ ғᴏʀ ᴍᴇ ᴛᴏ ᴜᴘʟᴏᴀᴅ ɪᴛs PNG.",
- )
-
-
-def kang(update, context):
- msg = update.effective_message
- args = context.args
- packnum = 0
- user = update.effective_user
- packname = f"a{str(user.id)}_by_{context.bot.username}"
- packname_found = 0
- max_stickers = 120
-
- while packname_found == 0:
- try:
- if sticker_count(context.bot, packname) >= max_stickers:
- packnum += 1
- packname = f"a{str(packnum)}_{str(user.id)}_by_{context.bot.username}"
- else:
- packname_found = 1
- except TelegramError as e:
- if e.message == "Stickerset_invalid":
- packname_found = 1
-
- kangsticker = "kangsticker.png"
- is_animated = False
- is_video = False
- # convert gif method
- is_gif = False
- file_id = ""
-
- if msg.reply_to_message:
- if msg.reply_to_message.sticker:
- if msg.reply_to_message.sticker.is_animated:
- is_animated = True
- elif msg.reply_to_message.sticker.is_video:
- is_video = True
- file_id = msg.reply_to_message.sticker.file_id
- elif msg.reply_to_message.photo:
- file_id = msg.reply_to_message.photo[-1].file_id
- elif (
- msg.reply_to_message.document
- and msg.reply_to_message.document.mime_type != "video/mp4"
- ):
- file_id = msg.reply_to_message.document.file_id
- elif msg.reply_to_message.animation:
- file_id = msg.reply_to_message.animation.file_id
- is_gif = True
- else:
- msg.reply_text("ʏᴇᴀ, ɪ ᴄᴀɴ'ᴛ ᴋᴀɴɢ ᴛʜᴀᴛ.")
- kang_file = context.bot.get_file(file_id)
- if not is_animated and not is_video and not is_gif:
- kang_file.download("kangsticker.png")
- elif is_animated:
- kang_file.download("kangsticker.tgs")
- elif is_video and not is_gif:
- kang_file.download("kangsticker.webm")
- else:
- kang_file.download("kang.mp4")
- convert_gif("kang.mp4")
-
- if args:
- sticker_emoji = str(args[0])
- elif msg.reply_to_message.sticker and msg.reply_to_message.sticker.emoji:
- sticker_emoji = msg.reply_to_message.sticker.emoji
- else:
- sticker_emoji = "🙂"
-
- adding_process = msg.reply_text(
- "ᴘʟᴇᴀsᴇ ᴡᴀɪᴛ...ғᴏʀ ᴀ ᴍᴏᴍᴇɴᴛ",
- parse_mode=ParseMode.HTML,
- )
-
- if not is_animated and not is_video and not is_gif:
- try:
- im = Image.open(kangsticker)
- maxsize = (512, 512)
- if (im.width and im.height) < 512:
- size1 = im.width
- size2 = im.height
- if im.width > im.height:
- scale = 512 / size1
- size1new = 512
- size2new = size2 * scale
- else:
- scale = 512 / size2
- size1new = size1 * scale
- size2new = 512
- size1new = math.floor(size1new)
- size2new = math.floor(size2new)
- sizenew = (size1new, size2new)
- im = im.resize(sizenew)
- else:
- im.thumbnail(maxsize)
- if not msg.reply_to_message.sticker:
- im.save(kangsticker, "PNG")
- context.bot.add_sticker_to_set(
- user_id=user.id,
- name=packname,
- png_sticker=open("kangsticker.png", "rb"),
- emojis=sticker_emoji,
- )
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
-
- except OSError as e:
- print(e)
- return
-
- except TelegramError as e:
- if (
- e.message
- == "Internal Server Error: sticker set not found (500)"
- ):
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- msg.reply_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- elif e.message == "Invalid sticker emojis":
- msg.reply_text("Invalid emoji(s).")
- elif e.message == "Sticker_png_dimensions":
- im.save(kangsticker, "PNG")
- adding_process = msg.reply_text(
- "ᴡᴀɪᴛ.... ғᴏʀ ᴀ ᴍᴏᴍᴇɴᴛ ..",
- parse_mode=ParseMode.HTML,
- )
- context.bot.add_sticker_to_set(
- user_id=user.id,
- name=packname,
- png_sticker=open("kangsticker.png", "rb"),
- emojis=sticker_emoji,
- )
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- elif e.message == "Stickers_too_much":
- msg.reply_text("Max packsize reached. Press F to pay respecc.")
- elif e.message == "Stickerset_invalid":
- makepack_internal(
- update,
- context,
- msg,
- user,
- sticker_emoji,
- packname,
- packnum,
- png_sticker=open("kangsticker.png", "rb"),
- )
- adding_process.delete()
- print(e)
-
- elif is_animated:
- packname = f"animated{str(user.id)}_by_{context.bot.username}"
- packname_found = 0
- max_stickers = 50
- while packname_found == 0:
- try:
- if sticker_count(context.bot, packname) >= max_stickers:
- packnum += 1
- packname = f"animated{str(packnum)}_{str(user.id)}_by_{context.bot.username}"
- else:
- packname_found = 1
- except TelegramError as e:
- if e.message == "Stickerset_invalid":
- packname_found = 1
- try:
- context.bot.add_sticker_to_set(
- user_id=user.id,
- name=packname,
- tgs_sticker=open("kangsticker.tgs", "rb"),
- emojis=sticker_emoji,
- )
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- except TelegramError as e:
- if (
- e.message
- == "Internal Server Error: sticker set not found (500)"
- ):
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- elif e.message == "Invalid sticker emojis":
- msg.reply_text("Invalid emoji(s).")
- elif e.message == "Stickerset_invalid":
- makepack_internal(
- update,
- context,
- msg,
- user,
- sticker_emoji,
- packname,
- packnum,
- tgs_sticker=open("kangsticker.tgs", "rb"),
- )
- adding_process.delete()
- print(e)
-
- else:
- packname = f"video{str(user.id)}_by_{context.bot.username}"
- packname_found = 0
- max_stickers = 50
- while packname_found == 0:
- try:
- if sticker_count(context.bot, packname) >= max_stickers:
- packnum += 1
- packname = (
- "video"
- + str(packnum)
- + "_"
- + str(user.id)
- + "_by_"
- + context.bot.username
- )
- else:
- packname_found = 1
- except TelegramError as e:
- if e.message == "Stickerset_invalid":
- packname_found = 1
- try:
- context.bot.add_sticker_to_set(
- user_id=user.id,
- name=packname,
- webm_sticker=open("kangsticker.webm", "rb"),
- emojis=sticker_emoji,
- )
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- except TelegramError as e:
- if (
- e.message
- == "Internal Server Error: sticker set not found (500)"
- ):
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- elif e.message == "Invalid sticker emojis":
- msg.reply_text("Invalid emoji(s).")
- elif e.message == "Stickerset_invalid":
- makepack_internal(
- update,
- context,
- msg,
- user,
- sticker_emoji,
- packname,
- packnum,
- webm_sticker=open("kangsticker.webm", "rb"),
- )
- adding_process.delete()
- print(e)
-
- elif args:
- try:
- try:
- urlemoji = msg.text.split(" ")
- png_sticker = urlemoji[1]
- sticker_emoji = urlemoji[2]
- except IndexError:
- sticker_emoji = "🙃"
- urllib.urlretrieve(png_sticker, kangsticker)
- im = Image.open(kangsticker)
- maxsize = (512, 512)
- if (im.width and im.height) < 512:
- size1 = im.width
- size2 = im.height
- if im.width > im.height:
- scale = 512 / size1
- size1new = 512
- size2new = size2 * scale
- else:
- scale = 512 / size2
- size1new = size1 * scale
- size2new = 512
- size1new = math.floor(size1new)
- size2new = math.floor(size2new)
- sizenew = (size1new, size2new)
- im = im.resize(sizenew)
- else:
- im.thumbnail(maxsize)
- im.save(kangsticker, "PNG")
- msg.reply_photo(photo=open("kangsticker.png", "rb"))
- context.bot.add_sticker_to_set(
- user_id=user.id,
- name=packname,
- png_sticker=open("kangsticker.png", "rb"),
- emojis=sticker_emoji,
- )
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- except OSError as e:
- msg.reply_text(" sᴏʀʀʏ ɪ ᴄᴀɴ'ᴛ ᴋᴀɴɢ ᴛʜᴀᴛ.")
- print(e)
- return
- except TelegramError as e:
- if (
- e.message
- == "Internal Server Error: sticker set not found (500)"
- ):
- msg.reply_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- elif e.message == "Invalid sticker emojis":
- msg.reply_text("Invalid emoji(s).")
- elif e.message == "Sticker_png_dimensions":
- im.save(kangsticker, "png")
- context.bot.add_sticker_to_set(
- user_id=user.id,
- name=packname,
- png_sticker=open("kangsticker.png", "rb"),
- emojis=sticker_emoji,
- )
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}"
- )
- ]
- ]
- )
- adding_process.edit_text(
- f"ʏᴏᴜʀ sᴛɪᴄᴋᴇʀ ʜᴀs ʙᴇᴇɴ ᴀᴅᴅᴇᴅ!"
- f"\nᴇᴍᴏᴊɪ ɪs ➼ : {sticker_emoji}",
- reply_markup=edited_keyboard,
- parse_mode=ParseMode.HTML,
- )
- elif e.message == "Stickers_too_much":
- msg.reply_text("Max packsize reached. Press F to pay respect.")
- elif e.message == "Stickerset_invalid":
- makepack_internal(
- update,
- context,
- msg,
- user,
- sticker_emoji,
- packname,
- packnum,
- png_sticker=open("kangsticker.png", "rb"),
- )
- adding_process.delete()
- print(e)
- else:
- packs_text = "*ᴘʟᴇᴀsᴇ ʀᴇᴘʟʏ ᴛᴏ ᴀ sᴛɪᴄᴋᴇʀ, ᴏʀ ɪᴍᴀɢᴇ ᴛᴏ ᴋᴀɴɢ ɪᴛ!*\n"
- if packnum > 0:
- firstpackname = f"a{str(user.id)}_by_{context.bot.username}"
- for i in range(packnum + 1):
- if i == 0:
- packs = f"t.me/addstickers/{firstpackname}"
- else:
- packs = f"t.me/addstickers/{packname}"
- else:
- packs = f"t.me/addstickers/{packname}"
-
- edited_keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(text="sᴛɪᴄᴋᴇʀ ᴘᴀᴄᴋ", url=f"{packs}"),
- ],
- ]
- )
- msg.reply_text(
- packs_text, reply_markup=edited_keyboard, parse_mode=ParseMode.MARKDOWN
- )
- try:
- if os.path.isfile("kangsticker.png"):
- os.remove("kangsticker.png")
- elif os.path.isfile("kangsticker.tgs"):
- os.remove("kangsticker.tgs")
- elif os.path.isfile("kangsticker.webm"):
- os.remove("kangsticker.webm")
- elif os.path.isfile("kang.mp4"):
- os.remove("kang.mp4")
- except Exception:
- pass
-
-
-def makepack_internal(
- update,
- context,
- msg,
- user,
- emoji,
- packname,
- packnum,
- png_sticker=None,
- tgs_sticker=None,
- webm_sticker=None,
-):
- name = user.first_name
- name = name[:50]
- keyboard = InlineKeyboardMarkup(
- [[InlineKeyboardButton(text="⎋ ᴘᴀᴄᴋ ⎋", url=f"t.me/addstickers/{packname}")]]
- )
- try:
- extra_version = f" {str(packnum)}" if packnum > 0 else ""
- if png_sticker:
- sticker_pack_name = f"{name}'s sticker pack (@{context.bot.username}){extra_version}"
- success = context.bot.create_new_sticker_set(
- user.id,
- packname,
- sticker_pack_name,
- png_sticker=png_sticker,
- emojis=emoji,
- )
- if tgs_sticker:
- sticker_pack_name = f"{name}'s animated pack (@{context.bot.username}){extra_version}"
- success = context.bot.create_new_sticker_set(
- user.id,
- packname,
- sticker_pack_name,
- tgs_sticker=tgs_sticker,
- emojis=emoji,
- )
- if webm_sticker:
- sticker_pack_name = (
- f"{name}'s video pack (@{context.bot.username}){extra_version}"
- )
- success = context.bot.create_new_sticker_set(
- user.id,
- packname,
- sticker_pack_name,
- webm_sticker=webm_sticker,
- emojis=emoji,
- )
-
- except TelegramError as e:
- print(e)
- if e.message == "Sticker set name is already occupied":
- msg.reply_text(
- "Your Sticker Pack is already created!"
- "\n\nYou can now reply to images, stickers and animated sticker with /steal to add them to your pack"
- "\n\nSend /stickers to find any sticker pack.",
- reply_markup=keyboard,
- parse_mode=ParseMode.HTML,
- )
- else:
- msg.reply_text(
- f"{context.bot.first_name} was blocked by you.",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ᴜɴʙʟᴏᴄᴋ", url=f"t.me/{context.bot.username}"
- )
- ]
- ]
- ),
- )
- return
-
- if success:
- msg.reply_text(
- "Your Sticker Pack has been created!"
- "\n\nYou can now reply to images, stickers and animated sticker with /steal to add them to your pack"
- "\n\nSend /stickers to find sticker pack.",
- reply_markup=keyboard,
- parse_mode=ParseMode.HTML,
- )
- else:
- msg.reply_text("Failed to create sticker pack. Possibly due to blek mejik.")
-
-
-def getsticker(update: Update, context: CallbackContext):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.sticker:
- file_id = msg.reply_to_message.sticker.file_id
- bot = context.bot
- new_file = bot.get_file(file_id)
- new_file.download("sticker.png")
- chat_id = update.effective_chat.id
- bot.send_document(chat_id, document=open("sticker.png", "rb"))
- os.remove("sticker.png")
- else:
- update.effective_message.reply_text(
- "Please reply to a sticker for me to upload its PNG."
- )
-
-
-def getvidsticker(update: Update, context: CallbackContext):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.sticker:
- file_id = msg.reply_to_message.sticker.file_id
- bot = context.bot
- new_file = bot.get_file(file_id)
- new_file.download("sticker.mp4")
- chat_id = update.effective_chat.id
- bot.send_video(chat_id, video=open("sticker.mp4", "rb"))
- os.remove("sticker.mp4")
- else:
- update.effective_message.reply_text(
- "Please reply to a video sticker to upload its MP4."
- )
-
-
-def delsticker(update, context):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.sticker:
- file_id = msg.reply_to_message.sticker.file_id
- context.bot.delete_sticker_from_set(file_id)
- msg.reply_text("ᴅᴇʟᴇᴛᴇᴅ!")
- else:
- update.effective_message.reply_text(
- "Please reply to sticker message to del sticker"
- )
-
-
-def video(update: Update, context: CallbackContext):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.animation:
- file_id = msg.reply_to_message.animation.file_id
- bot = context.bot
- new_file = bot.get_file(file_id)
- new_file.download("video.mp4")
- chat_id = update.effective_chat.id
- bot.send_video(chat_id, video=open("video.mp4", "rb"))
- os.remove("video.mp4")
- else:
- update.effective_message.reply_text(
- "Please reply to a gif for me to get it's video."
- )
-
-
-Credit = "Abishnoi69"
-
-
-@asux(pattern="^/mmf ?(.*)")
-async def handler(event):
- if event.fwd_from:
- return
-
- if not event.reply_to_msg_id:
- await event.reply("Provide Some Text To Draw!")
-
- return
-
- reply_message = await event.get_reply_message()
-
- if not reply_message.media:
- await event.reply("```ʀᴇᴘʟʏ ᴛᴏ ᴀ ɪᴍᴀɢᴇ/sᴛɪᴄᴋᴇʀ.```")
-
- return
-
- file = await bot.download_media(reply_message)
-
- msg = await event.reply("```ᴍᴇᴍɪғʏɪɴɢ ᴛʜɪs ɪᴍᴀɢᴇ! 😉 ```")
-
- if "Abishnoi69" not in Credit:
- await event.reply("ᴛʜɪs ɴɪɢɢᴀ ʀᴇᴍᴏᴠᴇᴅ ᴄʀᴇᴅɪᴛ ʟɪɴᴇ ғʀᴏᴍ ᴄᴏᴅᴇ 😶")
-
- text = str(event.pattern_match.group(1)).strip()
-
- if not text:
- return await msg.reply("ʏᴏᴜ ᴍɪɢʜᴛ ᴡᴀɴᴛ ᴛᴏ ᴛʀʏ `/mmf text`")
-
- meme = await drawText(file, text)
-
- await bot.send_file(event.chat_id, file=meme, force_document=False)
-
- await msg.delete()
-
- os.remove(meme)
-
-
-async def drawText(image_path, text):
- img = Image.open(image_path)
-
- os.remove(image_path)
-
- i_width, i_height = img.size
-
- fnt = "ariel.ttf" if os.name == "nt" else "./Exon/modules/resources/asu.ttf"
- m_font = ImageFont.truetype(fnt, int((70 / 640) * i_width))
-
- if ";" in text:
- upper_text, lower_text = text.split(";")
-
- else:
- upper_text = text
-
- lower_text = ""
-
- draw = ImageDraw.Draw(img)
-
- current_h, pad = 10, 5
-
- if upper_text:
- for u_text in textwrap.wrap(upper_text, width=15):
- u_width, u_height = draw.textsize(u_text, font=m_font)
-
- draw.text(
- xy=(((i_width - u_width) / 2) - 2, int((current_h / 640) * i_width)),
- text=u_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=(((i_width - u_width) / 2) + 2, int((current_h / 640) * i_width)),
- text=u_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=((i_width - u_width) / 2, int(((current_h / 640) * i_width)) - 2),
- text=u_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=(((i_width - u_width) / 2), int(((current_h / 640) * i_width)) + 2),
- text=u_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=((i_width - u_width) / 2, int((current_h / 640) * i_width)),
- text=u_text,
- font=m_font,
- fill=(255, 255, 255),
- )
-
- current_h += u_height + pad
-
- if lower_text:
- for l_text in textwrap.wrap(lower_text, width=15):
- u_width, u_height = draw.textsize(l_text, font=m_font)
-
- draw.text(
- xy=(
- ((i_width - u_width) / 2) - 2,
- i_height - u_height - int((20 / 640) * i_width),
- ),
- text=l_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=(
- ((i_width - u_width) / 2) + 2,
- i_height - u_height - int((20 / 640) * i_width),
- ),
- text=l_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=(
- (i_width - u_width) / 2,
- (i_height - u_height - int((20 / 640) * i_width)) - 2,
- ),
- text=l_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=(
- (i_width - u_width) / 2,
- (i_height - u_height - int((20 / 640) * i_width)) + 2,
- ),
- text=l_text,
- font=m_font,
- fill=(0, 0, 0),
- )
-
- draw.text(
- xy=(
- (i_width - u_width) / 2,
- i_height - u_height - int((20 / 640) * i_width),
- ),
- text=l_text,
- font=m_font,
- fill=(255, 255, 255),
- )
-
- current_h += u_height + pad
-
- image_name = "memify.webp"
-
- webp_file = os.path.join(image_name)
-
- img.save(webp_file, "webp")
-
- return webp_file
-
-
-__mod_name__ = "𝐒ᴛɪᴄᴋᴇʀ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "sticker_help")
-
-
-# """
-
-STICKERID_HANDLER = CommandHandler("stickerid", stickerid, run_async=True)
-GETSTICKER_HANDLER = CommandHandler("getsticker", getsticker, run_async=True)
-GETVIDSTICKER_HANDLER = CommandHandler("getvidsticker", getvidsticker, run_async=True)
-KANG_HANDLER = CommandHandler("kang", kang, pass_args=True, run_async=True)
-DEL_HANDLER = CommandHandler("delsticker", delsticker, run_async=True)
-STICKERS_HANDLER = CommandHandler("stickers", cb_sticker, run_async=True)
-VIDEO_HANDLER = CommandHandler("getvideo", video, run_async=True)
-CBSCALLBACK_HANDLER = CallbackQueryHandler(cbs_callback, pattern="cbs_", run_async=True)
-
-dispatcher.add_handler(VIDEO_HANDLER)
-dispatcher.add_handler(CBSCALLBACK_HANDLER)
-dispatcher.add_handler(STICKERS_HANDLER)
-dispatcher.add_handler(STICKERID_HANDLER)
-dispatcher.add_handler(GETSTICKER_HANDLER)
-dispatcher.add_handler(GETVIDSTICKER_HANDLER)
-dispatcher.add_handler(KANG_HANDLER)
-dispatcher.add_handler(DEL_HANDLER)
diff --git a/Exon/modules/tags.py b/Exon/modules/tags.py
deleted file mode 100644
index dae4cfea..00000000
--- a/Exon/modules/tags.py
+++ /dev/null
@@ -1,426 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-from telethon import events
-from telethon.errors import UserNotParticipantError
-from telethon.tl.functions.channels import GetParticipantRequest
-from telethon.tl.types import ChannelParticipantAdmin, ChannelParticipantCreator
-
-from Exon import telethn as abishnoi
-
-spam_chats = []
-
-import asyncio
-from datetime import timedelta
-
-import dateparser
-from pyrogram import filters
-from pyrogram.types import ChatPermissions, InlineKeyboardButton, InlineKeyboardMarkup
-
-from Exon import Abishnoi as AsuX
-from Exon.modules.no_sql import AsuXdb as db
-
-approved_users = db.approve
-tagdb = db.tagdb1
-alarms = db.alarm
-shedule = db.shedule
-nightmod = db.nightmode4
-
-
-def get_info(id):
- return nightmod.find_one({"id": id})
-
-
-@AsuX.on_message(filters.command(["tagalert"]))
-async def locks_dfunc(_, message):
- lol = await message.reply("ᴘʀᴏᴄᴇꜱꜱɪɴɢ..")
- if len(message.command) != 2:
- return await lol.edit("ᴇxᴘᴇᴄᴛᴇᴅ ᴏɴ ᴏʀ ᴏғғ 👀")
- parameter = message.text.strip().split(None, 1)[1].lower()
-
- if parameter in ["on", "ON"]:
- if not message.from_user:
- return
- if not message.from_user.username:
- return await lol.edit(
- "ᴏɴʟʏ ᴜꜱᴇʀꜱ ᴡɪᴛʜ ᴜꜱᴇʀɴᴀᴍᴇꜱ ᴀʀᴇ ᴇʟɪɢɪʙʟᴇ ғᴏʀ ᴛᴀɢ ᴀʟᴇʀᴛ ꜱᴇʀᴠɪᴄᴇ"
- )
- uname = str(message.from_user.username)
- uname = uname.lower()
- if isittrue := tagdb.find_one({"teg": uname}):
- return await lol.edit("ᴛᴀɢ ᴀʟᴇʀᴛꜱ ᴀʟʀᴇᴀᴅʏ ᴇɴᴀʙʟᴇᴅ ғᴏʀ ʏᴏᴜ")
- tagdb.insert_one({"teg": uname})
- return await lol.edit(
- f"ᴛᴀɢ ᴀʟᴇʀᴛꜱ ᴇɴᴀʙʟᴇᴅ.\nWhen ꜱᴏᴍᴇᴏɴᴇ ᴛᴀɢꜱ ʏᴏᴜ ᴀꜱ @{uname} ʏᴏᴜ ᴡɪʟʟ ʙᴇ ɴᴏᴛɪғɪᴇᴅ"
- )
- if parameter in ["off", "OFF"]:
- if not message.from_user:
- return
- if not message.from_user.username:
- return await lol.edit(
- "ᴏɴʟʏ ᴜꜱᴇʀꜱ ᴡɪᴛʜ ᴜꜱᴇʀɴᴀᴍᴇꜱ ᴀʀᴇ ᴇʟɪɢɪʙʟᴇ ғᴏʀ ᴛᴀɢ ᴀʟᴇʀᴛ ꜱᴇʀᴠɪᴄᴇ"
- )
- uname = message.from_user.username
- uname = uname.lower()
- if not (isittrue := tagdb.find_one({"teg": uname})):
- return await lol.edit("ᴛᴀɢ ᴀʟᴇʀᴛꜱ ᴀʟʀᴇᴀᴅʏ ᴅɪꜱᴀʙʟᴇᴅ ғᴏʀ ʏᴏᴜ")
- tagdb.delete_one({"teg": uname})
- return await lol.edit("ᴛᴀɢ ᴀʟᴇʀᴛꜱ ʀᴇᴍᴏᴠᴇᴅ")
- else:
- await lol.edit("ᴇxᴘᴇᴄᴛᴇᴅ ᴏɴ ᴏʀ ᴏғғ 👀")
-
-
-@AsuX.on_message(filters.incoming)
-async def mentioned_alert(client, message):
- try:
- if not message:
- message.continue_propagation()
- return
- if not message.from_user:
- message.continue_propagation()
- return
- input_str = message.text
- input_str = input_str.lower()
- if "@" in input_str:
- input_str = input_str.replace("@", " |")
- inuka = input_str.split("|")[1]
- text = inuka.split()[0]
- else:
- chats = alarms.find({})
- for c in chats:
- # print(c)
- chat = c["chat"]
- user = c["user"]
- time = c["time"]
- zone = c["zone"]
- reason = c["reason"]
- present = dateparser.parse(
- "now",
- settings={"TIMEZONE": f"{zone}", "DATE_ORDER": "YMD"},
- )
- ttime = dateparser.parse(f"{time}", settings={"TIMEZONE": f"{zone}"})
- # print(ttime)
- # print(present)
- # print (zone)
- # print(present>=ttime)
- if present > ttime:
- try:
- alarms.delete_one(
- {
- "chat": chat,
- "user": user,
- "time": time,
- "zone": zone,
- "reason": reason,
- }
- )
- await client.send_message(
- chat,
- f"**🚨 ʀᴇᴍɪɴᴅᴇʀ 🚨**\n\n__ᴛʜɪꜱ ɪꜱ ᴀ ʀᴇᴍɪɴᴅᴇʀ ꜱᴇᴛ ʙʏ__ {user}\n__ʀᴇᴀꜱᴏɴ__: {reason} \n\n`ʀᴇᴍɪɴᴅᴇᴅ ᴀᴛ: {ttime}`",
- )
-
- message.continue_propagation()
- except Exception:
- alarms.delete_one(
- {
- "chat": chat,
- "user": user,
- "time": time,
- "zone": zone,
- "reason": reason,
- }
- )
- return message.continue_propagation()
- break
- continue
- chats = shedule.find({})
- for c in chats:
- # print(c)
- chat = c["chat"]
- user = c["user"]
- time = c["time"]
- zone = c["zone"]
- reason = c["reason"]
- present = dateparser.parse(
- "now",
- settings={"TIMEZONE": f"{zone}", "DATE_ORDER": "YMD"},
- )
- ttime = dateparser.parse(f"{time}", settings={"TIMEZONE": f"{zone}"})
- # print(ttime)alarms
- # print(present)
- # print (zone)
- # print(present>=ttime)
- if present > ttime:
- try:
- shedule.delete_one(
- {
- "chat": chat,
- "user": user,
- "time": time,
- "zone": zone,
- "reason": reason,
- }
- )
- await client.send_message(chat, f"{reason}")
- message.continue_propagation()
- except Exception:
- shedule.delete_one(
- {
- "chat": chat,
- "user": user,
- "time": time,
- "zone": zone,
- "reason": reason,
- }
- )
- return message.continue_propagation()
- break
- continue
- chats = nightmod.find({})
-
- for c in chats:
- # print(c)
- id = c["id"]
- valid = c["valid"]
- zone = c["zone"]
- c["ctime"]
- otime = c["otime"]
- present = dateparser.parse(
- "now", settings={"TIMEZONE": f"{zone}", "DATE_ORDER": "YMD"}
- )
- try:
- if present > otime and valid:
- newtime = otime + timedelta(days=1)
- to_check = get_info(id=id)
- if not to_check:
- return message.continue_propagation()
- if not newtime:
- return message.continue_propagation()
- # print(newtime)
- # print(to_check)
- nightmod.update_one(
- {
- "_id": to_check["_id"],
- "id": to_check["id"],
- "valid": to_check["valid"],
- "zone": to_check["zone"],
- "ctime": to_check["ctime"],
- "otime": to_check["otime"],
- },
- {"$set": {"otime": newtime}},
- )
- await client.set_chat_permissions(
- id,
- ChatPermissions(
- can_send_messages=True,
- can_send_media_messages=True,
- can_send_stickers=True,
- can_send_animations=True,
- ),
- )
-
- await client.send_message(
- id,
- "**🌗 ɴɪɢʜᴛ ᴍᴏᴅᴇ ᴇɴᴅᴇᴅ: `ᴄʜᴀᴛ ᴏᴘᴇɴɪɴɢ` \n\n ᴇᴠᴇʀʏᴏɴᴇ ꜱʜᴏᴜʟᴅ ʙᴇ ᴀʙʟᴇ ᴛᴏ ꜱᴇɴᴅ ᴍᴇꜱꜱᴀɢᴇꜱ.**",
- )
- message.continue_propagation()
- break
- except Exception:
- print("Chat open error in nightbot")
- return message.continue_propagation()
- continue
- chats = nightmod.find({})
- for c in chats:
- # print(c)
- id = c["id"]
- valid = c["valid"]
- zone = c["zone"]
- ctime = c["ctime"]
- c["otime"]
- c["otime"]
- present = dateparser.parse(
- "now", settings={"TIMEZONE": f"{zone}", "DATE_ORDER": "YMD"}
- )
- try:
- if present > ctime and valid:
- newtime = ctime + timedelta(days=1)
- to_check = get_info(id=id)
- if not to_check:
- return message.continue_propagation()
- if not newtime:
- return message.continue_propagation()
- # print(newtime)
- # print(to_check)
- nightmod.update_one(
- {
- "_id": to_check["_id"],
- "id": to_check["id"],
- "valid": to_check["valid"],
- "zone": to_check["zone"],
- "ctime": to_check["ctime"],
- "otime": to_check["otime"],
- },
- {"$set": {"ctime": newtime}},
- )
- await client.set_chat_permissions(id, ChatPermissions())
- await client.send_message(
- id,
- "**🌗ɴɪɢʜᴛ ᴍᴏᴅᴇ ꜱᴛᴀʀᴛɪɴɢ: `ᴄʜᴀᴛ ᴄʟᴏꜱᴇ ɪɴɪᴛɪᴀᴛᴇᴅ`\n\nᴏɴʟʏ ᴀᴅᴍɪɴꜱ ꜱʜᴏᴜʟᴅ ʙᴇ ᴀʙʟᴇ ᴛᴏ ꜱᴇɴᴅ ᴍᴇꜱꜱᴀɢᴇꜱ**",
- )
- message.continue_propagation()
- break
- except Exception:
- print("Chat close err")
- return message.continue_propagation()
- continue
- return message.continue_propagation()
- # print(text)
- if not tagdb.find_one({"teg": text}):
- return message.continue_propagation()
- # print("Im inn")
- try:
- chat_name = message.chat.title
- message.chat.id
- tagged_msg_link = message.link
- except Exception:
- return message.continue_propagation()
- user_ = message.from_user.mention or f"@{message.from_user.username}"
-
- final_tagged_msg = f"**🔔 ʏᴏᴜ ʜᴀᴠᴇ ʙᴇᴇɴ** [ᴛᴀɢɢᴇᴅ]({tagged_msg_link}) **ɪɴ** {chat_name} **ʙʏ** {user_}"
- button_s = InlineKeyboardMarkup(
- [[InlineKeyboardButton("🔔 ᴠɪᴇᴡ ᴍᴇꜱꜱᴀɢᴇ 🔔", url=tagged_msg_link)]]
- )
- # print(final_tagged_msg)
- try:
- await client.send_message(
- chat_id=f"{text}",
- text=final_tagged_msg,
- reply_markup=button_s,
- disable_web_page_preview=True,
- )
-
- except Exception:
- return message.continue_propagation()
- message.continue_propagation()
- except Exception:
- return message.continue_propagation()
-
-
-@abishnoi.on(events.NewMessage(pattern="^/tagall ?(.*)"))
-@abishnoi.on(events.NewMessage(pattern="^@all ?(.*)"))
-async def mentionall(event):
- chat_id = event.chat_id
- if event.is_private:
- return await event.respond("__ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴄᴀɴ ʙᴇ ᴜsᴇ ɪɴ ɢʀᴏᴜᴘs !__")
-
- is_admin = False
- try:
- partici_ = await abishnoi(GetParticipantRequest(event.chat_id, event.sender_id))
- except UserNotParticipantError:
- is_admin = False
- else:
- if isinstance(
- partici_.participant, (ChannelParticipantAdmin, ChannelParticipantCreator)
- ):
- is_admin = True
- if not is_admin:
- return await event.respond("__ᴏɴʟʏ ᴀᴅᴍɪɴs ᴄᴀɴ ᴍᴇɴᴛɪᴏɴ ᴀʟʟ !__")
-
- if event.pattern_match.group(1) and event.is_reply:
- return await event.respond("__ɢɪᴠᴇ ᴍᴇ ᴏɴᴇ ᴀʀɢᴜᴍᴇɴᴛ ʙᴀʙʏ!__")
- elif event.pattern_match.group(1):
- mode = "text_on_cmd"
- msg = event.pattern_match.group(1)
- elif event.is_reply:
- mode = "text_on_reply"
- msg = await event.get_reply_message()
- if msg is None:
- return await event.respond(
- "__I ᴄᴀɴ'ᴛ ᴍᴇɴᴛɪᴏɴ ᴍᴇᴍʙᴇʀs ғᴏʀ ᴏʟᴅᴇʀ ᴍᴇssᴀɢᴇs! (ᴍᴇssᴀɢᴇs ᴡʜɪᴄʜ ᴀʀᴇ sᴇɴᴛ ʙᴇғᴏʀᴇ I'ᴍ ᴀᴅᴅᴇᴅ ᴛᴏ ɢʀᴏᴜᴘ)__"
- )
- else:
- return await event.respond(
- "__ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇssᴀɢᴇ ᴏʀ ɢɪᴠᴇ ᴍᴇ sᴏᴍᴇ ᴛᴇxᴛ ᴛᴏ ᴍᴇɴᴛɪᴏɴ ᴏᴛʜᴇʀs!__"
- )
-
- spam_chats.append(chat_id)
- usrnum = 0
- usrtxt = ""
- async for usr in abishnoi.iter_participants(chat_id):
- if chat_id not in spam_chats:
- break
- usrnum += 1
- usrtxt += f"[{usr.first_name}](tg://user?id={usr.id}), "
- if usrnum == 5:
- if mode == "text_on_cmd":
- txt = f"{msg}\n{usrtxt}"
- await abishnoi.send_message(chat_id, txt)
- elif mode == "text_on_reply":
- await msg.reply(usrtxt)
- await asyncio.sleep(3)
- usrnum = 0
- usrtxt = ""
- try:
- spam_chats.remove(chat_id)
- except Exception:
- pass
-
-
-@abishnoi.on(events.NewMessage(pattern="^/cancel$"))
-async def cancel_spam(event):
- if event.chat_id not in spam_chats:
- return await event.respond("__ᴛʜᴇʀᴇ ɪs ɴᴏ ᴘʀᴏᴄᴄᴇss ᴏɴ ɢᴏɪɴɢ...__")
- is_admin = False
- try:
- partici_ = await abishnoi(GetParticipantRequest(event.chat_id, event.sender_id))
- except UserNotParticipantError:
- is_admin = False
- else:
- if isinstance(
- partici_.participant, (ChannelParticipantAdmin, ChannelParticipantCreator)
- ):
- is_admin = True
- if not is_admin:
- return await event.respond("__ᴏɴʟʏ ᴀᴅᴍɪɴs ᴄᴀɴ ᴇxᴇᴄᴜᴛᴇ ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ!__")
-
- try:
- spam_chats.remove(event.chat_id)
- except Exception:
- pass
- return await event.respond("__sᴛᴏᴘᴘᴇᴅ ᴍᴇɴᴛɪᴏɴ.__")
-
-
-__mod_name__ = "𝐓ᴀɢ-Aʟʟ"
-
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "tags_help")
diff --git a/Exon/modules/tools.py b/Exon/modules/tools.py
deleted file mode 100644
index 04867d8b..00000000
--- a/Exon/modules/tools.py
+++ /dev/null
@@ -1,159 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import asyncio
-import os
-
-from telethon import types
-
-from Exon import Abishnoi as asau
-from Exon import telethn as Client
-from Exon.events import register
-
-TMP_DOWNLOAD_DIRECTORY = "./"
-
-from datetime import datetime
-
-from PIL import Image
-from telegraph import Telegraph, exceptions, upload_file
-
-wibu = "Exon_Robot"
-telegraph = Telegraph()
-data = telegraph.create_account(short_name=wibu)
-auth_url = data["auth_url"]
-
-
-@register(pattern="^/tm$")
-async def _(event):
- loda = "use\n➥ `/tgm` (reply to media)\n➥ `/tgt` (reply to text)"
- lund = await event.reply(loda)
- await asyncio.sleep(10)
- await event.delete()
- await lund.delete()
-
-
-@register(pattern="^/t(gm|gt) ?(.*)")
-async def telegrap(event):
- optional_title = event.pattern_match.group(2)
- if event.reply_to_msg_id:
- start = datetime.now()
- reply_msg = await event.get_reply_message()
- input_str = event.pattern_match.group(1)
- if input_str == "gm":
- downloaded_file_name = await Client.download_media(
- reply_msg, TMP_DOWNLOAD_DIRECTORY
- )
- a = await asau.get_me()
- end = datetime.now()
- ms = (end - start).seconds
- if not downloaded_file_name:
- await Client.send_message(event.chat_id, "ɴᴏᴛ ꜱᴜᴘᴘᴏʀᴛᴇᴅ ғᴏʀᴍᴀᴛ ᴍᴇᴅɪᴀ!")
- return
- else:
- if downloaded_file_name.endswith((".webp")):
- resize_image(downloaded_file_name)
- try:
- start = datetime.now()
- media_urls = upload_file(downloaded_file_name)
-
- except exceptions.TelegraphException as exc:
- await event.reply(f"ERROR: {str(exc)}")
- os.remove(downloaded_file_name)
- else:
- end = datetime.now()
- ms_two = (end - start).seconds
- os.remove(downloaded_file_name)
- await Client.send_message(
- event.chat_id,
- f"`ᴅᴏɴᴇ`!\n**•ʀᴇϙᴜᴇꜱᴛᴇᴅ ʙʏ:**- [{event.sender.first_name}](tg://user?id={event.sender.id})\n**•ᴜᴘʟᴏᴀᴅ ʙʏ:** [{a.first_name}](tg://user?id={a.id})\n**•ʟɪɴᴋ: **`https://telegra.ph{media_urls[0]}` ",
- buttons=[
- [
- types.KeyboardButtonUrl(
- "➡ ʙʀᴏᴡsᴇʀ ᴠɪᴇᴡ",
- f"https://telegra.ph{media_urls[0]}",
- )
- ]
- ],
- )
- elif input_str == "gt":
- user_object = await Client.get_entity(reply_msg.sender_id)
- title_of_page = user_object.first_name # + " " + user_object.last_name
- # apparently, all Users do not have last_name field
- if optional_title:
- title_of_page = optional_title
- page_content = reply_msg.message
- if reply_msg.media:
- if page_content != "":
- title_of_page = page_content
- else:
- await Client.send_message(
- event.chat_id, "ɴᴏᴛ ꜱᴜᴘᴘᴏʀᴛᴇᴅ ғᴏʀᴍᴀᴛ ᴛᴇxᴛ!"
- )
- downloaded_file_name = await Client.download_media(
- reply_msg, TMP_DOWNLOAD_DIRECTORY
- )
- m_list = None
- with open(downloaded_file_name, "rb") as fd:
- m_list = fd.readlines()
- for m in m_list:
- page_content += m.decode("UTF-8") + "\n"
- os.remove(downloaded_file_name)
- page_content = page_content.replace("\n", "
")
- response = telegraph.create_page(title_of_page, html_content=page_content)
- a = await asau.get_me()
- end = datetime.now()
- ms = (end - start).seconds
- url = f'https://telegra.ph/{response["path"]}'
- await Client.send_message(
- event.chat_id,
- f"ᴅᴏɴᴇ!\n**•ʀᴇϙᴜᴇꜱᴛᴇᴅ ʙʏ:-** [{event.sender.first_name}](tg://user?id={event.sender.id})\n**•ᴜᴘʟᴏᴀᴅ ʙʏ:-** [{a.first_name}](tg://user?id={a.id})\n**•ʟɪɴᴋ:** `{url}`",
- buttons=[
- [
- types.KeyboardButtonUrl(
- "➡ ʙʀᴏᴡsᴇʀ ᴠɪᴇᴡ ",
- f'https://telegra.ph/{response["path"]}',
- )
- ]
- ],
- )
- else:
- await event.reply("`ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ɢᴇᴛ ᴀ ᴘᴇʀᴍᴀɴᴇɴᴛ telegra.ph link`")
-
-
-def resize_image(image):
- im = Image.open(image)
- im.save(image, "PNG")
-
-
-file_help = os.path.basename(__file__)
-file_help = file_help.replace(".py", "")
-file_helpo = file_help.replace("_", " ")
-
-__mod_name__ = "𝐓-ɢᴀᴘʜ"
diff --git a/Exon/modules/truth_and_dare.py b/Exon/modules/truth_and_dare.py
deleted file mode 100644
index 528f61ca..00000000
--- a/Exon/modules/truth_and_dare.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-import requests
-
-from Exon import SUPPORT_CHAT
-from Exon.events import register as abishnoi
-
-
-@abishnoi(pattern="[/!]dare")
-async def _(asux):
- try:
- ak = requests.get("https://api.truthordarebot.xyz/v1/dare").json()
- results = f"{ak['question']}"
- return await asux.reply(results)
- except Exception:
- await asux.reply(f"ᴇʀʀᴏʀ ʀᴇᴘᴏʀᴛ @{SUPPORT_CHAT}")
-
-
-@abishnoi(pattern="[/!]truth")
-async def _(asux):
- try:
- ak = requests.get("https://api.truthordarebot.xyz/v1/truth").json()
- results = f"{ak['question']}"
- return await asux.reply(results)
- except Exception:
- await asux.reply(f"ᴇʀʀᴏʀ ʀᴇᴘᴏʀᴛ @{SUPPORT_CHAT}")
-
-
-__mod_name__ = "𝐓ʀᴜᴛʜ-Dᴀʀᴇ"
-
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "td_help")
diff --git a/Exon/modules/uall.py b/Exon/modules/uall.py
deleted file mode 100644
index 9fd2267c..00000000
--- a/Exon/modules/uall.py
+++ /dev/null
@@ -1,225 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-
-from time import sleep
-
-from telethon import *
-from telethon.errors import *
-from telethon.errors import FloodWaitError, UserNotParticipantError
-from telethon.tl import *
-from telethon.tl import functions, types
-from telethon.tl.functions.channels import GetParticipantRequest
-from telethon.tl.types import *
-from telethon.tl.types import (
- ChannelParticipantAdmin,
- ChannelParticipantCreator,
- ChatBannedRights,
-)
-
-from Exon import *
-from Exon import LOGGER
-from Exon.events import register
-
-CMD_HELP = "/ !"
-
-
-# ================================================
-
-
-async def is_register_admin(chat, user):
- if isinstance(chat, (types.InputPeerChannel, types.InputChannel)):
- return isinstance(
- (
- await telethn(functions.channels.GetParticipantRequest(chat, user))
- ).participant,
- (types.ChannelParticipantAdmin, types.ChannelParticipantCreator),
- )
- if isinstance(chat, types.InputPeerUser):
- return True
-
-
-@register(pattern="^/unbanall$")
-@register(pattern="^/unbanall@Exon_Robot$")
-async def _(event):
- chat = await event.get_chat()
- admin = chat.admin_rights.ban_users
- creator = chat.creator
- if event.is_private:
- return await event.respond(
- "__ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴄᴀɴ ʙᴇ ᴜsᴇ ɪɴ ɢʀᴏᴜᴘs ᴀɴᴅ ᴄʜᴀɴɴᴇʟs!__"
- )
-
- is_admin = False
- try:
- cutiepii = await telethn(GetParticipantRequest(event.chat_id, event.sender_id))
- except UserNotParticipantError:
- is_admin = False
- else:
- if isinstance(
- cutiepii.participant,
- (
- ChannelParticipantAdmin,
- ChannelParticipantCreator,
- ),
- ):
- is_admin = True
- if not is_admin:
- return await event.respond("__ᴏɴʟʏ ᴀᴅᴍɪɴs ᴄᴀɴ ᴜɴᴍᴜᴛᴇᴀʟʟ!__")
-
- if not admin and not creator:
- await event.reply("`I ᴅᴏɴ'ᴛ ʜᴀᴠᴇ ᴇɴᴏᴜɢʜ ᴘᴇʀᴍɪssɪᴏɴs!`")
- return
-
- done = await event.reply("sᴇᴀʀᴄʜɪɴɢ ᴘᴀʀᴛɪᴄɪᴘᴀɴᴛ ʟɪsᴛs.")
- p = 0
- async for i in telethn.iter_participants(
- event.chat_id, filter=ChannelParticipantsKicked, aggressive=True
- ):
- rights = ChatBannedRights(until_date=0, view_messages=False)
- try:
- await telethn(
- functions.channels.EditBannedRequest(event.chat_id, i, rights)
- )
- except FloodWaitError as ex:
- LOGGER.warn(f"sʟᴇᴇᴘɪɴɢ ғᴏʀ {ex.seconds} sᴇᴄᴏɴᴅs")
- sleep(ex.seconds)
- except Exception as ex:
- await event.reply(str(ex))
- else:
- p += 1
-
- if p == 0:
- await done.edit("ɴᴏ ᴏɴᴇ ɪs ʙᴀɴɴᴇᴅ ɪɴ ᴛʜɪs ᴄʜᴀᴛ")
- return
- required_string = "sᴜᴄᴄᴇssғᴜʟʟʏ ᴜɴʙᴀɴɴᴇᴅ **{}** ᴜsᴇʀs"
- await event.reply(required_string.format(p))
-
-
-@register(pattern="^/unmuteall@Exon_Robot$")
-@register(pattern="^/unmuteall$")
-async def _(event):
- if event.is_private:
- return await event.respond(
- "__ᴛʜɪs ᴄᴏᴍᴍᴀɴᴅ ᴄᴀɴ ʙᴇ ᴜsᴇ ɪɴ ɢʀᴏᴜᴘꜱ ᴀɴᴅ ᴄʜᴀɴɴᴇʟꜱ!__"
- )
-
- is_admin = False
- try:
- cutiepii = await telethn(GetParticipantRequest(event.chat_id, event.sender_id))
- except UserNotParticipantError:
- is_admin = False
- else:
- if isinstance(
- cutiepii.participant,
- (
- ChannelParticipantAdmin,
- ChannelParticipantCreator,
- ),
- ):
- is_admin = True
- if not is_admin:
- return await event.respond("__ᴏɴʟʏ ᴀᴅᴍɪɴꜱ ᴄᴀɴ ᴜɴᴍᴜᴛᴇᴀʟʟ!__")
- chat = await event.get_chat()
- admin = chat.admin_rights.ban_users
- creator = chat.creator
-
- # Well
- if not admin and not creator:
- await event.reply("`I ᴅᴏɴ'ᴛ ʜᴀᴠᴇ ᴇɴᴏᴜɢʜ ᴘᴇʀᴍɪꜱꜱɪᴏɴꜱ!`")
- return
-
- done = await event.reply("ᴡᴏʀᴋɪɴɢ ...")
- p = 0
- async for i in telethn.iter_participants(
- event.chat_id, filter=ChannelParticipantsBanned, aggressive=True
- ):
- rights = ChatBannedRights(
- until_date=0,
- send_messages=False,
- )
- try:
- await telethn(
- functions.channels.EditBannedRequest(event.chat_id, i, rights)
- )
- except FloodWaitError as ex:
- LOGGER.warn(f"ꜱʟᴇᴇᴘɪɴɢ ғᴏʀ {ex.seconds} ꜱᴇᴄᴏɴᴅꜱ")
- sleep(ex.seconds)
- except Exception as ex:
- await event.reply(str(ex))
- else:
- p += 1
-
- if p == 0:
- await done.edit("ɴᴏ ᴏɴᴇ ɪꜱ ᴍᴜᴛᴇᴅ ɪɴ ᴛʜɪꜱ ᴄʜᴀᴛ")
- return
- required_string = "ꜱᴜᴄᴄᴇꜱꜱғᴜʟʟʏ ᴜɴᴍᴜᴛᴇᴅ **{}** ᴜꜱᴇʀꜱ"
- await event.reply(required_string.format(p))
-
-
-@register(pattern="^/gusers$")
-async def get_users(show):
- if not show.is_group:
- return
- if not await is_register_admin(show.input_chat, show.sender_id):
- return
- info = await telethn.get_entity(show.chat_id)
- title = info.title or "this chat"
- mentions = f"ᴜꜱᴇʀꜱ ɪɴ {title}: \n"
- async for user in telethn.iter_participants(show.chat_id):
- mentions += (
- f"\n ᴅᴇʟᴇᴛᴇᴅ ᴀᴄᴄᴏᴜɴᴛ {user.id}"
- if user.deleted
- else f"\n[{user.first_name}](tg://user?id={user.id}) {user.id}"
- )
-
- with open("userslist.txt", "w+") as file:
- file.write(mentions)
- await telethn.send_file(
- show.chat_id,
- "userslist.txt",
- caption=f"Users in {title}",
- reply_to=show.id,
- )
-
- os.remove("userslist.txt")
-
-
-__mod_name__ = "𝐔ᴀʟʟ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "uall_help")
-
-# """
diff --git a/Exon/modules/ubot.py b/Exon/modules/ubot.py
deleted file mode 100644
index 3b3bee65..00000000
--- a/Exon/modules/ubot.py
+++ /dev/null
@@ -1,87 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from asyncio.exceptions import TimeoutError
-
-from telethon.errors.rpcerrorlist import YouBlockedUserError
-
-from Exon import ubot
-from Exon.events import register
-
-
-@register(pattern="^/sg ?(.*)")
-@register(pattern="^/check_name ?(.*)")
-async def lastname(steal):
- steal.pattern_match.group(1)
- puki = await steal.reply("```Retrieving Such User Information..```")
- if steal.fwd_from:
- return
- if not steal.reply_to_msg_id:
- await puki.edit("```Please Reply To User Message.```")
- return
- message = await steal.get_reply_message()
- chat = "@SangMataInfo_bot"
- user_id = message.sender.id
- id = f"/search_id {user_id}"
- if message.sender.bot:
- await puki.edit("```Reply To Real User's Message.```")
- return
- await puki.edit("```Please wait...```")
- try:
- async with ubot.conversation(chat) as conv:
- try:
- msg = await conv.send_message(id)
- r = await conv.get_response()
- response = await conv.get_response()
- except YouBlockedUserError:
- await steal.reply("```Error, report to @AbishnoiMF```")
- return
- if r.text.startswith("Name"):
- respond = await conv.get_response()
- await puki.edit(f"`{r.message}`")
- await ubot.delete_messages(
- conv.chat_id, [msg.id, r.id, response.id, respond.id]
- )
- return
- if response.text.startswith("No records") or r.text.startswith(
- "No records"
- ):
- await puki.edit(
- "```I Can't Find This User's Information, This User Has Never Changed His Name Before.```"
- )
- await ubot.delete_messages(conv.chat_id, [msg.id, r.id, response.id])
- return
- else:
- respond = await conv.get_response()
- await puki.edit(f"```{response.message}```")
- await ubot.delete_messages(
- conv.chat_id, [msg.id, r.id, response.id, respond.id]
- )
- except TimeoutError:
- return await puki.edit("`I'm Sick Sorry...`")
diff --git a/Exon/modules/userinfo.py b/Exon/modules/userinfo.py
deleted file mode 100644
index a56c3094..00000000
--- a/Exon/modules/userinfo.py
+++ /dev/null
@@ -1,670 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-
-import datetime
-import html
-import platform
-import time
-from platform import python_version
-
-import requests
-from psutil import boot_time, cpu_percent, disk_usage, virtual_memory
-from telegram import (
- MAX_MESSAGE_LENGTH,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- MessageEntity,
- ParseMode,
- Update,
-)
-from telegram import __version__ as ptbver
-from telegram.error import BadRequest
-from telegram.ext import CallbackContext
-from telegram.utils.helpers import escape_markdown, mention_html
-from telethon import events
-from telethon.tl.functions.channels import GetFullChannelRequest
-from telethon.tl.types import ChannelParticipantsAdmins
-
-import Exon.modules.sql.userinfo_sql as sql
-from Exon import (
- DEMONS,
- DEV_USERS,
- DRAGONS,
- INFOPIC,
- OWNER_ID,
- TIGERS,
- WOLVES,
- StartTime,
- dispatcher,
- sw,
-)
-from Exon import telethn as Exon
-from Exon.__main__ import STATS, TOKEN, USER_INFO
-from Exon.modules.helper_funcs.chat_status import sudo_plus
-from Exon.modules.helper_funcs.decorators import Exoncallback, Exoncmd
-from Exon.modules.helper_funcs.extraction import extract_user
-from Exon.modules.no_sql.global_bans_db import is_user_gbanned
-from Exon.modules.no_sql.users_db import get_user_num_chats
-from Exon.modules.sql import SESSION
-
-
-def no_by_per(totalhp, percentage):
- """
- rtype: num of `percentage` from total
- eg: 1000, 10 -> 10% of 1000 (100)
- """
- return totalhp * percentage / 100
-
-
-def get_percentage(totalhp, earnedhp):
- """
- rtype: percentage of `totalhp` num
- eg: (1000, 100) will return 10%
- """
- matched_less = totalhp - earnedhp
- per_of_totalhp = 100 - matched_less * 100.0 / totalhp
- per_of_totalhp = str(int(per_of_totalhp))
- return per_of_totalhp
-
-
-def get_readable_time(seconds: int) -> str:
- count = 0
- ping_time = ""
- time_list = []
- time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"]
-
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
-
- for x in range(len(time_list)):
- time_list[x] = str(time_list[x]) + time_suffix_list[x]
- if len(time_list) == 4:
- ping_time += f"{time_list.pop()}, "
-
- time_list.reverse()
- ping_time += ":".join(time_list)
-
- return ping_time
-
-
-def hpmanager(user):
- total_hp = (get_user_num_chats(user.id) + 10) * 10
-
- if not is_user_gbanned(user.id):
- # Assign new var `new_hp` since we need `total_hp` in
- # end to calculate percentage.
- new_hp = total_hp
-
- # if no username decrease 25% of hp.
- if not user.username:
- new_hp -= no_by_per(total_hp, 25)
- try:
- dispatcher.bot.get_user_profile_photos(user.id).photos[0][-1]
- except IndexError:
- # no profile photo ==> -25% of hp
- new_hp -= no_by_per(total_hp, 25)
- # if no /setme exist ==> -20% of hp
- if not sql.get_user_me_info(user.id):
- new_hp -= no_by_per(total_hp, 20)
- # if no bio exsit ==> -10% of hp
- if not sql.get_user_bio(user.id):
- new_hp -= no_by_per(total_hp, 10)
-
- # new_hp = no_by_per(total_hp, 5)
-
- return {
- "earnedhp": int(new_hp),
- "totalhp": int(total_hp),
- "percentage": get_percentage(total_hp, new_hp),
- }
-
-
-def make_bar(per):
- done = min(round(per / 10), 10)
- return "⬢" * done + "⬡" * (10 - done)
-
-
-@Exoncmd(command="id")
-def get_id(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
- chat = update.effective_chat
- msg = update.effective_message
- if user_id := extract_user(msg, args):
- if msg.reply_to_message and msg.reply_to_message.forward_from:
- user1 = message.reply_to_message.from_user
- user2 = message.reply_to_message.forward_from
-
- msg.reply_text(
- f"× ꜱᴇɴᴅᴇʀ: {mention_html(user2.id, user2.first_name)} - {user2.id}
.\n"
- f"× ꜰᴏʀᴡᴀʀᴅᴇʀ: {mention_html(user1.id, user1.first_name)} - {user1.id}
.",
- parse_mode=ParseMode.HTML,
- )
-
- else:
- user = bot.get_chat(user_id)
- msg.reply_text(
- f"× ʀᴇᴘʟɪᴇᴅ ᴛᴏ: {mention_html(user.id, user.first_name)}\n× ID of the user: {user.id}
",
- parse_mode=ParseMode.HTML,
- )
-
- elif chat.type == "private":
- msg.reply_text(
- f"⟃ ʏᴏᴜʀ ɪᴅ ɪꜱ {chat.id}
.", parse_mode=ParseMode.HTML
- )
-
- else:
- msg.reply_text(
- f"⟃ ᴜꜱᴇʀ: {mention_html(msg.from_user.id, msg.from_user.first_name)}\n⟃ ꜰʀᴏᴍ ᴜꜱᴇʀ ɪᴅ: {update.effective_message.from_user.id}
\n⟃ ᴛʜɪꜱ ɢʀᴏᴜᴘ ɪᴅ: {chat.id}
",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exon.on(
- events.NewMessage(
- pattern="/ginfo ",
- from_users=(TIGERS or []) + (DRAGONS or []) + (DEMONS or []),
- ),
-)
-async def group_info(event) -> None:
- chat = event.text.split(" ", 1)[1]
- try:
- entity = await event.client.get_entity(chat)
- totallist = await event.client.get_participants(
- entity,
- filter=ChannelParticipantsAdmins,
- )
- ch_full = await event.client(GetFullChannelRequest(channel=entity))
- except Exception:
- await event.reply(
- "Can't for some reason, maybe it is a private one or that I am banned there.",
- )
- return
- msg = f"**ɪᴅ**: `{entity.id}`"
- msg += f"\n**ᴛɪᴛʟᴇ**: `{entity.title}`"
- msg += f"\n**ᴅᴀᴛᴀᴄᴇɴᴛᴇʀ**: `{entity.photo.dc_id}`"
- msg += f"\n**ᴠɪᴅᴇᴏ ᴘꜰᴘ**: `{entity.photo.has_video}`"
- msg += f"\n**ꜱᴜᴘᴇʀɢʀᴏᴜᴘ**: `{entity.megagroup}`"
- msg += f"\n**ʀᴇꜱᴛʀɪᴄᴛᴇᴅ**: `{entity.restricted}`"
- msg += f"\n**ꜱᴄᴀᴍ**: `{entity.scam}`"
- msg += f"\n**ꜱʟᴏᴡᴍᴏᴅᴇ**: `{entity.slowmode_enabled}`"
- if entity.username:
- msg += f"\n**ᴜꜱᴇʀɴᴀᴍᴇ**: {entity.username}"
- msg += "\n\n**ᴍᴇᴍʙᴇʀ ꜱᴛᴀᴛꜱ:**"
- msg += f"\n`ᴀᴅᴍɪɴꜱ:` `{len(totallist)}`"
- msg += f"\n`ᴜꜱᴇʀꜱ`: `{totallist.total}`"
- msg += "\n\n**ᴀᴅᴍɪɴꜱ ʟɪꜱᴛ:**"
- for x in totallist:
- msg += f"\n• [{x.id}](tg://user?id={x.id})"
- msg += f"\n\n**ᴅᴇꜱᴄʀɪᴘᴛɪᴏɴ**:\n`{ch_full.full_chat.about}`"
- await event.reply(msg)
-
-
-@Exoncmd(command="gifid")
-def gifid(update: Update, context: CallbackContext):
- msg = update.effective_message
- if msg.reply_to_message and msg.reply_to_message.animation:
- update.effective_message.reply_text(
- f"ɢɪꜰ ɪᴅ:\n{msg.reply_to_message.animation.file_id}
",
- parse_mode=ParseMode.HTML,
- )
- else:
- update.effective_message.reply_text("Please reply to a gif to get its ID.")
-
-
-@Exoncmd(command=["info", "book"])
-def info(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
- chat = update.effective_chat
- user_id = extract_user(update.effective_message, args)
-
- if user_id:
- user = bot.get_chat(user_id)
-
- elif not message.reply_to_message and not args:
- user = message.from_user
-
- elif not message.reply_to_message and (
- not args
- or (
- len(args) >= 1
- and not args[0].startswith("@")
- and not args[0].isdigit()
- and not message.parse_entities([MessageEntity.TEXT_MENTION])
- )
- ):
- message.reply_text("ɪ ᴄᴀɴ'ᴛ ᴇxᴛʀᴀᴄᴛ ᴀ ᴜꜱᴇʀ ꜰʀᴏᴍ ᴛʜɪꜱ.")
- return
-
- else:
- return
-
- rep = message.reply_text("ᴀᴘᴘʀᴀɪꜱɪɴɢ...
", parse_mode=ParseMode.HTML)
-
- text = (
- f"╔━⊰✦✪「 Appraisal Results: 」✪✦⊱━╗\n"
- f"➻ ɪᴅ: {user.id}
\n"
- f"➻ ꜰɪʀꜱᴛ ɴᴀᴍᴇ: {html.escape(user.first_name)}"
- )
-
- if user.last_name:
- text += f"\n➻ ʟᴀꜱᴛ ɴᴀᴍᴇ: {html.escape(user.last_name)}"
-
- if user.username:
- text += f"\n➻ ᴜꜱᴇʀɴᴀᴍᴇ: @{html.escape(user.username)}"
-
- text += f"\n➻ ᴜꜱᴇʀʟɪɴᴋ: {mention_html(user.id, 'link')}"
-
- if chat.type != "private" and user_id != bot.id:
- _stext = "\n➻ ᴩʀᴇsᴇɴᴄᴇ: {}
"
-
- # afk_st = is_afk(user.id)
- # if afk_st:
- # text += _stext.format("AFK")
- # else:
- status = status = bot.get_chat_member(chat.id, user.id).status
- if status:
- if status in {"left", "kicked"}:
- text += _stext.format("ɴᴏᴛ ʜᴇʀᴇ")
- elif status == "member":
- text += _stext.format("ᴅᴇᴛᴇᴄᴛᴇᴅ")
- elif status in {"administrator", "creator"}:
- text += _stext.format("ᴀᴅᴍɪɴ")
- if user_id not in [bot.id, 777000, 1087968824]:
- userhp = hpmanager(user)
- text += f"\n\nʜᴇᴀʟᴛʜ: {userhp['earnedhp']}/{userhp['totalhp']}
\n[{make_bar(int(userhp['percentage']))} {userhp['percentage']}%]"
-
- try:
- if spamwtc := sw.get_ban(int(user.id)):
- text += "\n\nᴛʜɪs ᴘᴇʀsᴏɴ ɪs sᴘᴀᴍᴡᴀᴛᴄʜᴇᴅ!"
- text += f"\nʀᴇᴀꜱᴏɴ: {spamwtc.reason}
"
- text += "\nᴀᴘᴘᴇᴀʟ ᴀᴛ @AbishnoiMF"
- except Exception:
- pass # don't crash if api is down somehow...
-
- disaster_level_present = False
-
- if user.id == OWNER_ID:
- text += "\n\nᴛʜᴇ ʟᴇᴠᴇʟ ғᴏʀ ᴍʏ ᴍᴀsᴛᴇʀ "
- disaster_level_present = True
- elif user.id in DEV_USERS:
- text += "\n\nThe level for this user is Destroyers"
- disaster_level_present = True
- elif user.id in DRAGONS:
- text += "\n\nThe level for this user is Shadow Slayer"
- disaster_level_present = True
- elif user.id in DEMONS:
- text += "\n\nThe level for this user is Guardian"
- disaster_level_present = True
- elif user.id in TIGERS:
- text += "\n\nThe level for this user is Light Shooters"
- disaster_level_present = True
- elif user.id in WOLVES:
- text += "\n\nThe level for this user is Villain"
- disaster_level_present = True
- elif user.id == 5938660179:
- text += "\n\nᴄᴏ-ᴏᴡᴇʀɴ ᴏғ ᴀ ʙᴏᴛ."
- disaster_level_present = True
-
- if disaster_level_present:
- text += ' [ʟᴇᴠᴇʟʟɪɴɢ]'.format(
- bot.username,
- )
-
- try:
- user_member = chat.get_member(user.id)
- if user_member.status == "administrator":
- result = requests.post(
- f"https://api.telegram.org/bot{TOKEN}/getChatMember?chat_id={chat.id}&user_id={user.id}",
- )
- result = result.json()["result"]
- if "custom_title" in result.keys():
- custom_title = result["custom_title"]
- text += f"\n\nᴛɪᴛʟᴇ:\n{custom_title}"
- except BadRequest:
- pass
-
- for mod in USER_INFO:
- try:
- mod_info = mod.__user_info__(user.id).strip()
- except TypeError:
- mod_info = mod.__user_info__(user.id, chat.id).strip()
- if mod_info:
- text += "\n\n" + mod_info
-
- if INFOPIC:
- try:
- profile = context.bot.get_user_profile_photos(user.id).photos[0][-1]
- context.bot.sendChatAction(chat.id, "upload_photo")
- context.bot.send_photo(
- chat.id,
- photo=profile,
- caption=(text),
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- "ʜᴇᴀʟᴛʜ", url="https://t.me/Abishnoi_bots/60"
- ),
- InlineKeyboardButton(
- "ᴅɪsᴀsᴛᴇʀ", url="https://t.me/Abishnoi_bots/60"
- ),
- ],
- ]
- ),
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
-
- # Incase user don't have profile pic, send normal text
- except IndexError:
- message.reply_text(
- text,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- "ʜᴇᴀʟᴛʜ", url="https://t.me/Abishnoi_bots/60"
- ),
- InlineKeyboardButton(
- "ʟᴇᴠᴇʟʟɪɴɢ", url="https://t.me/Abishnoi_bots/60"
- ),
- ],
- ]
- ),
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
-
- else:
- message.reply_text(
- text,
- parse_mode=ParseMode.HTML,
- disable_web_page_preview=True,
- )
-
- rep.delete()
-
-
-@Exoncmd(command="me")
-def about_me(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
- user_id = extract_user(message, args)
-
- user = bot.get_chat(user_id) if user_id else message.from_user
- if info := sql.get_user_me_info(user.id):
- update.effective_message.reply_text(
- f"*{user.first_name}*:\n{escape_markdown(info)}",
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- )
- elif message.reply_to_message:
- username = message.reply_to_message.from_user.first_name
- update.effective_message.reply_text(
- f"{username} ʜᴀꜱɴ'ᴛ ꜱᴇᴛ ᴀɴ ɪɴꜰᴏ ᴍᴇꜱꜱᴀɢᴇ ᴀʙᴏᴜᴛ ᴛʜᴇᴍꜱᴇʟᴠᴇꜱ ʏᴇ !",
- )
- else:
- update.effective_message.reply_text(
- "ᴛʜᴇʀᴇ ɪꜱ ɴᴏᴛ ᴀɴʏ ʙɪᴏ, use /setme ᴛᴏ ꜱᴇᴛ ᴏɴᴇ."
- )
-
-
-@Exoncmd(command="setme")
-def set_about_me(update: Update, context: CallbackContext):
- message = update.effective_message
- user_id = message.from_user.id
- if user_id in [777000, 1087968824]:
- message.reply_text("Error! Unauthorized")
- ᴛ
- bot = context.bot
- if message.reply_to_message:
- repl_message = message.reply_to_message
- repl_user_id = repl_message.from_user.id
- if repl_user_id in [bot.id, 777000, 1087968824] and (user_id in DEV_USERS):
- user_id = repl_user_id
- text = message.text
- info = text.split(None, 1)
- if len(info) == 2:
- if len(info[1]) < MAX_MESSAGE_LENGTH // 4:
- sql.set_user_me_info(user_id, info[1])
- if user_id in [777000, 1087968824]:
- message.reply_text("Authorized...Information updated!")
- elif user_id == bot.id:
- message.reply_text("I have updated my info with the one you provided!")
- else:
- message.reply_text("Information updated!")
- else:
- message.reply_text(
- f"The info needs to be under {MAX_MESSAGE_LENGTH // 4} characters! You have {len(info[1])}."
- )
-
-
-@Exoncmd(command="stats", can_disable=True)
-@sudo_plus
-def stats(update, context):
- db_size = SESSION.execute(
- "SELECT pg_size_pretty(pg_database_size(current_database()))"
- ).scalar_one_or_none()
- uptime = datetime.datetime.fromtimestamp(boot_time()).strftime("%Y-%m-%d %H:%M:%S")
- botuptime = get_readable_time((time.time() - StartTime))
- status = "*╒═══「 ꜱʏꜱᴛᴇᴍ ꜱᴛᴀᴛɪᴄꜱ: 」*\n\n"
- status += f"*× ꜱʏꜱᴛᴇᴍ ꜱᴛᴀʀᴛ ᴛɪᴍᴇ:* {str(uptime)}" + "\n"
- uname = platform.uname()
- status += f"*× ꜱʏꜱᴛᴇᴍ:* {str(uname.system)}" + "\n"
- status += f"*× ɴᴏᴅᴇ ɴᴀᴍᴇ:* {escape_markdown(str(uname.node))}" + "\n"
- status += f"*× ʀᴇʟᴇᴀꜱᴇ:* {escape_markdown(str(uname.release))}" + "\n"
- status += f"*× ᴍᴀᴄʜɪɴᴇ:* {escape_markdown(str(uname.machine))}" + "\n"
-
- mem = virtual_memory()
- cpu = cpu_percent()
- disk = disk_usage("/")
- status += f"*× ᴄᴘᴜ:* {str(cpu)}" + " %\n"
- status += f"*× ʀᴀᴍ:* {str(mem[2])}" + " %\n"
- status += f"*× ꜱᴛᴏʀᴀɢᴇ:* {str(disk[3])}" + " %\n\n"
- status += f"*× ᴘʏᴛʜᴏɴ ᴠᴇʀꜱɪᴏɴ:* {python_version()}" + "\n"
- status += f"*× ᴘʏᴛʜᴏɴ-ᴛᴇʟᴇɢʀᴀᴍ-ʙᴏᴛ:* {str(ptbver)}" + "\n"
- status += f"*× ᴜᴘᴛɪᴍᴇ:* {str(botuptime)}" + "\n"
- status += f"*× ᴅʙ ꜱɪᴢᴇ:* {str(db_size)}" + "\n"
- kb = [[InlineKeyboardButton("Ping", callback_data="pingCB")]]
- # repo = git.Repo(search_parent_directories=True)
- # sha = repo.head.object.hexsha
- # status += f"*× ᴄᴏᴍᴍɪᴛ*: {sha[0:9]}\n"
- try:
- update.effective_message.reply_text(
- status
- + "\n*Bot statistics*:\n"
- + "\n".join([mod.__stats__() for mod in STATS])
- + "\n\n[⍙ ɢɪᴛʜᴜʙ](https://github.com/Abishnoi69/ExonRobot) | ⍚\n\n "
- + "╘══「 by [ᴀʙɪsʜɴᴏɪ](github.com/Abishnoi69) 」\n",
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=InlineKeyboardMarkup(kb),
- disable_web_page_preview=True,
- )
- except BaseException:
- update.effective_message.reply_text(
- (
- (
- (
- "\n*Bot statistics*:\n"
- + "\n".join(mod.__stats__() for mod in STATS)
- )
- + "\n\n⍙ [ɢɪᴛʜᴜʙ](https://github.com/Abishnoi69/ExonRobot) | ⍚ \n\n"
- )
- + "╘══「 by [ᴅʏɴᴀᴍɪᴄ](github.com/Abishnoi69) 」\n"
- ),
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=InlineKeyboardMarkup(kb),
- disable_web_page_preview=True,
- )
-
-
-@Exoncallback(pattern=r"^pingCB")
-def pingCallback(update: Update, context: CallbackContext):
- query = update.callback_query
- start_time = time.time()
- requests.get("https://api.telegram.org")
- end_time = time.time()
- ping_time = round((end_time - start_time) * 1000, 3)
- query.answer(f"ᴘᴏɴɢ 🌺! {ping_time}ms")
-
-
-@Exoncmd(command="bio")
-def about_bio(update: Update, context: CallbackContext):
- bot, args = context.bot, context.args
- message = update.effective_message
-
- user_id = extract_user(message, args)
- user = bot.get_chat(user_id) if user_id else message.from_user
- if info := sql.get_user_bio(user.id):
- update.effective_message.reply_text(
- f"*{user.first_name}*:\n{escape_markdown(info)}",
- parse_mode=ParseMode.MARKDOWN,
- disable_web_page_preview=True,
- )
- elif message.reply_to_message:
- username = user.first_name
- update.effective_message.reply_text(
- f"{username} ʜᴀꜱɴ'ᴛ ʜᴀᴅ ᴀ ᴍᴇꜱꜱᴀɢᴇ ꜱᴇᴛ ᴀʙᴏᴜᴛ ᴛʜᴇᴍꜱᴇʟᴠᴇꜱ ʏᴇᴛ!\nꜱᴇᴛ ᴏɴᴇ ᴜꜱɪɴɢ /setbio",
- )
- else:
- update.effective_message.reply_text(
- "ʏᴏᴜ ʜᴀꜱɴ' ʜᴀᴅ ᴀ ʙɪᴏ ꜱᴇᴛ ᴀʙᴏᴜᴛ ʏᴏᴜʀꜱᴇʟꜰ ʏᴇᴛ!",
- )
- message = update.effective_message
- if message.reply_to_message:
- repl_message = message.reply_to_message
- user_id = repl_message.from_user.id
- if user_id == message.from_user.id:
- message.reply_text(
- "ʜᴀ, ʏᴏᴜ ᴄᴀɴ'ᴛ ꜱᴇᴛ ʏᴏᴜʀ ᴏᴡɴ ʙɪᴏ ! ʏᴏᴜ'ʀᴇ ᴀᴛ ᴛʜᴇ ᴍᴇʀᴄʏ ᴏʀ ᴏᴛʜᴇʀꜱ ʜᴇʀᴇ..."
- )
- return
- sender_id = update.effective_user.id
-
- if (
- user_id == bot.id
- and sender_id not in SUDO_USERS
- and sender_id not in DEV_USERS
- ):
- message.reply_text(
- "Erm... yeah, I only trust sudo users or developers to set my bio."
- )
- return
- text = message.text
- # use python's maxsplit to only remove the cmd, hence keeping newlines.
- bio = text.split(None, 1)
- if len(bio) == 2:
- if len(bio[1]) < MAX_MESSAGE_LENGTH // 4:
- sql.set_user_bio(user_id, bio[1])
- message.reply_text(f"ᴜᴘᴅᴀᴛᴇᴅ {repl_message.from_user.first_name}'ꜱ ʙɪᴏ!")
- else:
- message.reply_text(
- f"ᴀ ʙɪᴏ ɴᴇᴇᴅꜱ ᴛᴏ ʙᴇ ᴜɴᴅᴇʀ {MAX_MESSAGE_LENGTH // 4} ᴄʜᴀʀᴇᴄᴛᴇʀ! ʏᴏᴜ ᴛʀɪᴇᴅ ᴛᴏ ꜱᴇᴛ {len(bio[1])}."
- )
- else:
- message.reply_text("ʀᴇᴘʟʏ ᴛᴏ ꜱᴏᴍᴇᴏɴᴇ'ꜱ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ꜱᴇᴛ ᴛʜᴇɪʀ ʙɪᴏ!")
-
-
-@Exoncmd(command="setbio")
-def set_about_bio(update: Update, context: CallbackContext):
- message = update.effective_message
- sender_id = update.effective_user.id
- bot = context.bot
-
- if message.reply_to_message:
- repl_message = message.reply_to_message
- user_id = repl_message.from_user.id
-
- if user_id == message.from_user.id:
- message.reply_text(
- "ʜᴀ, ʏᴏᴜ ᴄᴀɴ'ᴛ ꜱᴇᴛ ʏᴏᴜʀ ᴏᴡɴ ʙɪᴏ! ʏᴏᴜ'ʀᴇ ᴀᴛ ᴛʜᴇ ᴍᴇʀᴄʏ ᴏꜰ ᴏᴛʜᴇʀꜱ ʜᴇʀᴇ...",
- )
- return
-
- if user_id in [777000, 1087968824] and sender_id not in DEV_USERS:
- message.reply_text("You are not authorised")
- return
-
- if user_id == bot.id and sender_id not in DEV_USERS:
- message.reply_text(
- "ᴇʀᴍ... ʏᴇᴀʜ, ɪ ᴏɴʟʏ ᴛʀᴜꜱᴛ ᴛʜᴇ ᴀᴄᴋᴇʀᴍᴀɴꜱ ᴛᴏ ꜱᴇᴛ ᴍʏ ʙɪᴏ.",
- )
- return
-
- text = message.text
- bio = text.split(
- None,
- 1,
- ) # use python's maxsplit to only remove the cmd, hence keeping newlines.
-
- if len(bio) == 2:
- if len(bio[1]) < MAX_MESSAGE_LENGTH // 4:
- sql.set_user_bio(user_id, bio[1])
- message.reply_text(f"Updated {repl_message.from_user.first_name}'s bio!")
- else:
- message.reply_text(
- f"ʙɪᴏ ɴᴇᴇᴅꜱ ᴛᴏ ᴜɴᴅᴇʀ {MAX_MESSAGE_LENGTH // 4} ᴄʜᴀʀᴇᴄᴛᴇʀ! ʏᴏᴜ ᴛʀɪᴇᴅ ᴛᴏ ꜱᴇᴛ {len(bio[1])}."
- )
- else:
- message.reply_text("ʀᴇᴘʟʏ ᴛᴏ ꜱᴏᴍᴇᴏɴᴇ ᴛᴏ ꜱᴇᴛ ᴛʜᴇɪʀ ʙɪᴏ!")
-
-
-def __user_info__(user_id):
- bio = html.escape(sql.get_user_bio(user_id) or "")
- me = html.escape(sql.get_user_me_info(user_id) or "")
- result = ""
- if me:
- result += f"ᴀʙᴏᴜᴛ ᴜꜱᴇʀ:\n{me}\n"
- if bio:
- result += f"ᴡʜᴀᴛ ᴏᴛʜᴇʀ ꜱᴀʏꜱ:\n{bio}\n"
- result = result.strip("\n")
- return result
-
-
-__mod_name__ = "𝐈ɴғᴏ "
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "userinfo_help")
-
-# """
diff --git a/Exon/modules/users.py b/Exon/modules/users.py
deleted file mode 100644
index c92e96ff..00000000
--- a/Exon/modules/users.py
+++ /dev/null
@@ -1,208 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-from io import BytesIO
-from time import sleep
-
-from telegram import ParseMode, TelegramError, Update
-from telegram.error import BadRequest, Unauthorized
-from telegram.ext import CallbackContext, Filters
-
-import Exon.modules.no_sql.users_db as user_db
-from Exon import DEV_USERS, LOGGER, OWNER_ID, dispatcher
-from Exon.modules.helper_funcs.chat_status import dev_plus, sudo_plus
-from Exon.modules.helper_funcs.decorators import Exoncmd, Exonmsg
-from Exon.modules.no_sql.users_db import get_all_users
-
-USERS_GROUP = 4
-CHAT_GROUP = 5
-DEV_AND_MORE = DEV_USERS.append(int(OWNER_ID))
-
-
-def get_user_id(username):
- # ensure valid userid
- if len(username) <= 5:
- return None
-
- if username.startswith("@"):
- username = username[1:]
-
- users = user_db.get_userid_by_name(username)
-
- if not users:
- return None
-
- if len(users) == 1:
- return users[0]["_id"]
-
- for user_obj in users:
- try:
- userdat = dispatcher.bot.get_chat(user_obj["_id"])
- if userdat.username == username:
- return userdat.id
-
- except BadRequest as excp:
- if excp.message != "Chat not found":
- LOGGER.exception("Error extracting user ID")
-
- return None
-
-
-@Exoncmd(command=["broadcastall", "broadcastusers", "broadcastgroups"])
-@dev_plus
-def broadcast(update: Update, context: CallbackContext):
- to_send = update.effective_message.text.split(None, 1)
-
- if len(to_send) >= 2:
- to_group = False
- to_user = False
- if to_send[0] == "/broadcastgroups":
- to_group = True
- if to_send[0] == "/broadcastusers":
- to_user = True
- else:
- to_group = to_user = True
- chats = user_db.get_all_chats() or []
- users = get_all_users()
- failed = 0
- failed_user = 0
- if to_group:
- for chat in chats:
- try:
- context.bot.sendMessage(
- int(chat["chat_id"]),
- to_send[1],
- parse_mode="MARKDOWN",
- disable_web_page_preview=True,
- )
- sleep(0.1)
- except TelegramError:
- failed += 1
- if to_user:
- for user in users:
- try:
- context.bot.sendMessage(
- int(user["_id"]),
- to_send[1],
- parse_mode="MARKDOWN",
- disable_web_page_preview=True,
- )
- sleep(0.1)
- except TelegramError:
- failed_user += 1
- update.effective_message.reply_text(
- f"Broadcast complete.\nGroups failed: {failed}
.\nUsers failed: {failed_user}
.",
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exonmsg((Filters.all & Filters.chat_type.groups), group=USERS_GROUP)
-def log_user(update: Update, context: CallbackContext):
- chat = update.effective_chat
- msg = update.effective_message
-
- user_db.update_user(msg.from_user.id, msg.from_user.username, chat.id, chat.title)
-
- if msg.reply_to_message:
- user_db.update_user(
- msg.reply_to_message.from_user.id,
- msg.reply_to_message.from_user.username,
- chat.id,
- chat.title,
- )
-
- if msg.forward_from:
- user_db.update_user(msg.forward_from.id, msg.forward_from.username)
-
-
-@Exoncmd(command="groups")
-@sudo_plus
-def chats(update: Update, context: CallbackContext):
- all_chats = user_db.get_all_chats() or []
- chatfile = "List of chats.\n0. Chat name | Chat ID | Members count\n"
- P = 1
- for chat in all_chats:
- try:
- curr_chat = context.bot.getChat(chat.chat_id)
- curr_chat.get_member(context.bot.id)
- chat_members = curr_chat.get_member_count(context.bot.id)
- chatfile += f"{P}. {chat.chat_name} | {chat.chat_id} | {chat_members}\n"
- P += 1
- except Exception:
- pass
-
- with BytesIO(str.encode(chatfile)) as output:
- output.name = "groups_list.txt"
- update.effective_message.reply_document(
- document=output,
- filename="groups_list.txt",
- caption="ʜᴇʀᴇ ʙᴇ ᴛʜᴇ ʟɪꜱᴛ ᴏꜰ ɢʀᴏᴜᴘꜱ ɪɴ ᴍʏ ᴅᴀᴛᴀʙᴀꜱᴇ.",
- )
-
-
-@Exonmsg((Filters.all & Filters.chat_type.groups), group=CHAT_GROUP)
-def chat_checker(update: Update, context: CallbackContext):
- bot = context.bot
- try:
- if update.effective_message.chat.get_member(bot.id).can_send_messages is False:
- bot.leaveChat(update.effective_message.chat.id)
- except Unauthorized:
- pass
-
-
-def __user_info__(user_id):
- if user_id in [777000, 1087968824]:
- return """╘══「 ɢʀᴏᴜᴘꜱ ᴄᴏᴜɴᴛ: ???
」"""
- if user_id == dispatcher.bot.id:
- return """╘══「 ɢʀᴏᴜᴘꜱ ᴄᴏᴜɴᴛ: ???
」"""
- num_chats = user_db.get_user_num_chats(user_id)
- return f"""╘══「 ɢʀᴏᴜᴘꜱ ᴄᴏᴜɴᴛ: {num_chats}
」"""
-
-
-def __stats__():
- return f"× 0{user_db.num_users()} ᴜsᴇʀs, ᴀᴄʀᴏss 0{user_db.num_chats()} ᴄʜᴀᴛs"
-
-
-def __migrate__(old_chat_id, new_chat_id):
- user_db.migrate_chat(old_chat_id, new_chat_id)
-
-
-__mod_name__ = "𝐆-ᴄᴀsᴛ"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "gcast_help")
-
-# """
diff --git a/Exon/modules/wallpaper.py b/Exon/modules/wallpaper.py
deleted file mode 100644
index 7ec821f5..00000000
--- a/Exon/modules/wallpaper.py
+++ /dev/null
@@ -1,82 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-
-import random
-from random import randint
-
-import requests
-from pyrogram import enums
-from pyrogram.types import Message
-
-from Exon import Abishnoi, arq
-
-
-@Abishnoi.on_cmd(["wallpaper"])
-async def wallpaper(_, msg):
- if len(msg.command) < 2:
- await msg.reply_text("ʜᴇʏ ʙᴀʙʏ ɢɪᴠᴇ sᴏᴍᴇᴛʜɪɴɢ ᴛᴏ sᴇᴀʀᴄʜ.")
- return
- query = (
- msg.text.split(None, 1)[1]
- if len(msg.command) < 3
- else msg.text.split(None, 1)[1].replace(" ", "%20")
- )
-
- if not query:
- await msg.reply_text("ʜᴇʏ ʙᴀʙʏ ɢɪᴠᴇ sᴏᴍᴇᴛʜɪɴɢ ᴛᴏ sᴇᴀʀᴄʜ.")
- url = f"https://api.safone.me/wall?query={query}"
- re = requests.get(url).json()
- walls = re.get("results")
- if not walls:
- await msg.reply_text("ɴᴏ ʀᴇsᴜʟᴛs ғᴏᴜɴᴅ! ")
- return
- wall_index = randint(0, len(walls) - 1)
- wallpaper = walls[wall_index]
- wallpaper.get("imageUrl")
- preview = wallpaper.get("thumbUrl")
- title = wallpaper.get("title")
- try:
- await Abishnoi.send_chat_action(msg.chat.id, enums.ChatAction.UPLOAD_PHOTO)
- await msg.reply_photo(
- preview, caption=f"🔎 ᴛɪᴛʟᴇ - {title}\nᴊᴏɪɴ [@ᴀʙɪsʜɴᴏɪᴍғ](t.me/AbishnoiMF)"
- )
- # await msg.reply_document(pic, caption=f"🔎 ᴛɪᴛʟᴇ - {title} \n🥀 **ʀᴇǫᴜᴇsᴛᴇᴅ ʙʏ :** {msg.from_user.mention}")
- except Exception as error:
- await msg.reply_text(f"ᴀɴ ᴇʀʀᴏʀ ᴏᴄᴄᴜʀᴇᴅ.\n {error}")
-
-
-@Abishnoi.on_cmd("wall")
-async def wall(_, m: Message):
- if len(m.command) < 2:
- return await m.reply_text("ɢɪᴠᴇ ᴍᴇ ᴀ ᴛᴇxᴛ !")
- search = m.text.split(None, 1)[1]
- x = await arq.wall(search)
- y = x.result
- await m.reply_photo(random.choice(y).url_image)
- # await m.reply_document(random.choice(y).url_image)
diff --git a/Exon/modules/warns.py b/Exon/modules/warns.py
deleted file mode 100644
index bd15b680..00000000
--- a/Exon/modules/warns.py
+++ /dev/null
@@ -1,580 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- ABISHNOI69 ""
-import html
-import re
-from typing import Optional
-
-import telegram
-from telegram import (
- CallbackQuery,
- Chat,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- Message,
- ParseMode,
- Update,
- User,
-)
-from telegram.error import BadRequest
-from telegram.ext import (
- CallbackContext,
- CallbackQueryHandler,
- CommandHandler,
- DispatcherHandlerStop,
- Filters,
- MessageHandler,
-)
-from telegram.utils.helpers import mention_html
-
-from Exon import TIGERS, WOLVES, dispatcher
-from Exon.modules.disable import DisableAbleCommandHandler
-from Exon.modules.helper_funcs.chat_status import (
- bot_admin,
- can_restrict,
- is_user_admin,
- user_admin_no_reply,
-)
-from Exon.modules.helper_funcs.extraction import (
- extract_text,
- extract_user,
- extract_user_and_text,
-)
-from Exon.modules.helper_funcs.filters import CustomFilters
-from Exon.modules.helper_funcs.misc import split_message
-from Exon.modules.helper_funcs.string_handling import split_quotes
-from Exon.modules.log_channel import loggable
-from Exon.modules.sql import warns_sql as sql
-from Exon.modules.sql.approve_sql import is_approved
-from ..modules.helper_funcs.anonymous import AdminPerms, user_admin
-
-WARN_HANDLER_GROUP = 9
-CURRENT_WARNING_FILTER_STRING = "ᴄᴜʀʀᴇɴᴛ ᴡᴀʀɴɪɴɢ ꜰɪʟᴛᴇʀꜱ ɪɴ ᴛʜɪꜱ ᴄʜᴀᴛ:\n"
-
-
-# Not async
-def warn(
- user: User, update: Update, reason: str, message: Message, warner: User = None
-) -> Optional[str]: # sourcery no-metrics
- chat = update.effective_chat
- if is_user_admin(update, user.id):
- # message.reply_text("ᴅᴀᴍɴ ᴀᴅᴍɪɴꜱ, ᴛʜᴇʏ ᴀʀᴇ ᴛᴏᴏ ꜰᴀʀ ᴛᴏ ʙᴇ ᴋɪᴄᴋᴇᴅ!")
- return
-
- if user.id in TIGERS:
- if warner:
- message.reply_text("ʟɪɢʜᴛ ꜱʜᴏᴏᴛᴇʀꜱ ᴄᴀɴᴛ ʙᴇ ᴡᴀʀɴᴇᴅ.")
- else:
- message.reply_text(
- "ʟɪɢʜᴛ ꜱʜᴏᴏᴛᴇʀꜱ ᴛʀɪɢɢʀᴇᴅ ᴀɴ ᴀᴜᴛᴏ ᴡᴀʀɴ ꜰɪʟᴛᴇʀꜱ!\n ɪ ᴄᴀɴ'ᴛ ᴡᴀʀɴ ᴛʜᴇ ʟɪɢʜᴛ ꜱʜᴏᴏᴛᴇʀꜱ ʙᴜᴛ ᴛʜᴇʏ ꜱʜᴏᴜʟᴅ ᴀᴠᴏɪᴅ ᴀʙᴜꜱɪɴɢ ᴛʜɪꜱ."
- )
- return
-
- if user.id in WOLVES:
- if warner:
- message.reply_text("ᴠɪʟʟᴀɪɴ ᴅɪꜱᴀꜱᴛᴇʀꜱ ᴀʀᴇ ᴡᴀʀɴ ɪᴍᴍᴜɴᴇ.")
- else:
- message.reply_text(
- "ᴠɪʟʟᴀɪɴꜱ ᴅɪꜱᴀꜱᴛᴇʀ ᴛʀɪɢɢᴇʀᴇᴅ ᴀɴ ᴀᴜᴛᴏ ᴡᴀʀɴ ꜰɪʟᴛᴇʀꜱ!\nɪ ᴄᴀɴ'ᴛ ᴡᴀʀɴ ᴛʜᴇ ᴠɪʟʟᴀɪɴꜱ ʙᴜᴛ ᴛʜᴇʏ ꜱʜᴏᴜʟᴅ ᴀᴠᴏɪᴅ ᴀʙᴜꜱɪɴɢ ᴛʜɪꜱ."
- )
- return
-
- if warner:
- warner_tag = mention_html(warner.id, warner.first_name)
- else:
- warner_tag = "Automated warn filter."
-
- limit, soft_warn = sql.get_warn_setting(chat.id)
- num_warns, reasons = sql.warn_user(user.id, chat.id, reason)
- if num_warns >= limit:
- sql.reset_warns(user.id, chat.id)
- if soft_warn: # kick
- chat.unban_member(user.id)
- reply = (
- f"❕ ᴋɪᴄᴋ ᴇᴠᴇɴᴛ\n"
- f"➻ ᴜꜱᴇʀ: {mention_html(user.id, user.first_name)}\n"
- f"➻ ᴄᴏᴜɴᴛ: {limit}"
- )
-
- else: # ban
- chat.ban_member(user.id)
- reply = (
- f"❕ ʙᴀɴ ᴇᴠᴇɴᴛ\n"
- f"➻ ᴜꜱᴇʀ: {mention_html(user.id, user.first_name)}\n"
- f"➻ ᴄᴏᴜɴᴛ: {limit}"
- )
-
- for warn_reason in reasons:
- reply += f"\n - {html.escape(warn_reason)}"
-
- # message.bot.send_sticker(chat.id, BAN_STICKER) # Saitama's sticker
- keyboard = None
- log_reason = (
- f"{html.escape(chat.title)}:\n"
- f"#WARN_BAN\n"
- f"ᴀᴅᴅ ᴜꜱᴇʀ: {warner_tag}\n"
- f"ᴜꜱᴇʀ: {mention_html(user.id, user.first_name)}\n"
- f"ᴜꜱᴇʀ ɪᴅ: {user.id}
\n"
- f"ʀᴇᴀꜱᴏɴ: {reason}\n"
- f"ᴄᴏᴜɴᴛꜱ: {num_warns}/{limit}
"
- )
-
- else:
- keyboard = InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- "⟳ ʀᴇᴍᴏᴠᴇ ᴡᴀʀɴ ⟲", callback_data=f"rm_warn({user.id})"
- )
- ]
- ]
- )
-
- reply = (
- f"❕ ᴡᴀʀɴ ᴇᴠᴇɴᴛ\n"
- f"⟃ ᴜꜱᴇʀ: {mention_html(user.id, user.first_name)}\n"
- f"⟃ ᴄᴏᴜɴᴛ: {num_warns}/{limit}"
- )
- if reason:
- reply += f"\n⟃ ʀᴇᴀꜱᴏɴ: {html.escape(reason)}"
-
- log_reason = (
- f"{html.escape(chat.title)}:\n"
- f"#WARN\n"
- f"ᴀᴅᴍɪɴ: {warner_tag}\n"
- f"ᴜꜱᴇʀ: {mention_html(user.id, user.first_name)}\n"
- f"ᴜꜱᴇʀ ɪᴅ: {user.id}
\n"
- f"ʀᴇᴀꜱᴏɴ: {reason}\n"
- f"ᴄᴏᴜɴᴛꜱ: {num_warns}/{limit}
"
- )
-
- try:
- message.reply_text(reply, reply_markup=keyboard, parse_mode=ParseMode.HTML)
- except BadRequest as excp:
- if excp.message == "Reply message not found":
- # Do not reply
- message.reply_text(
- reply, reply_markup=keyboard, parse_mode=ParseMode.HTML, quote=False
- )
- else:
- raise
- return log_reason
-
-
-@user_admin_no_reply
-@bot_admin
-@loggable
-def button(update: Update, context: CallbackContext) -> str:
- query: Optional[CallbackQuery] = update.callback_query
- user: Optional[User] = update.effective_user
- if match := re.match(r"rm_warn\((.+?)\)", query.data):
- user_id = match[1]
- chat: Optional[Chat] = update.effective_chat
- if res := sql.remove_warn(user_id, chat.id):
- update.effective_message.edit_text(
- f"Warn removed by {mention_html(user.id, user.first_name)}.",
- parse_mode=ParseMode.HTML,
- )
- user_member = chat.get_member(user_id)
- return (
- f"{html.escape(chat.title)}:\n"
- f"#UNWARN\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ᴜꜱᴇʀ: {mention_html(user_member.user.id, user_member.user.first_name)}\n"
- f"ᴜꜱᴇʀ ɪᴅ: {user_member.user.id}
"
- )
- update.effective_message.edit_text(
- "ᴜꜱᴇʀ ᴀʟʀᴇᴀᴅʏ ʜᴀꜱʜ ɴᴏ ᴡᴀʀɴꜱ.", parse_mode=ParseMode.HTML
- )
-
- return ""
-
-
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-@can_restrict
-@loggable
-def warn_user(update: Update, context: CallbackContext) -> str:
- args = context.args
- message: Optional[Message] = update.effective_message
- chat: Optional[Chat] = update.effective_chat
- warner: Optional[User] = update.effective_user
-
- user_id, reason = extract_user_and_text(message, args)
-
- if user_id:
- if (
- message.reply_to_message
- and message.reply_to_message.from_user.id == user_id
- ):
- return warn(
- message.reply_to_message.from_user,
- update,
- reason,
- message.reply_to_message,
- warner,
- )
- return warn(chat.get_member(user_id).user, update, reason, message, warner)
- else:
- message.reply_text("➻ ᴛʜᴀᴛ ʟᴏᴏᴋꜱ ʟɪᴋᴇ ᴀɴ ɪɴᴠᴀʟɪᴅ ᴜꜱᴇʀ ɪᴅ ᴛᴏ ᴍᴇ.")
- return ""
-
-
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-@bot_admin
-@loggable
-def reset_warns(update: Update, context: CallbackContext) -> str:
- args = context.args
- message: Optional[Message] = update.effective_message
- chat: Optional[Chat] = update.effective_chat
- user: Optional[User] = update.effective_user
-
- if user_id := extract_user(message, args):
- sql.reset_warns(user_id, chat.id)
- message.reply_text("Warns have been reset!")
- warned = chat.get_member(user_id).user
- return (
- f"{html.escape(chat.title)}:\n"
- f"#RESETWARNS\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ᴜꜱᴇʀ: {mention_html(warned.id, warned.first_name)}\n"
- f"ᴜꜱᴇʀ ɪᴅ: {warned.id}
"
- )
- message.reply_text("⟃ ɴᴏ ᴜꜱᴇʀ ʜᴀꜱ ʙᴇᴇɴ ᴅᴇꜱɪɢɴᴀᴛᴇᴅ!")
- return ""
-
-
-def warns(update: Update, context: CallbackContext):
- args = context.args
- message: Optional[Message] = update.effective_message
- chat: Optional[Chat] = update.effective_chat
- user_id = extract_user(message, args) or update.effective_user.id
- result = sql.get_warns(user_id, chat.id)
-
- if result and result[0] != 0:
- num_warns, reasons = result
- limit, soft_warn = sql.get_warn_setting(chat.id)
-
- if reasons:
- text = (
- f"➻ ᴛʜɪꜱ ᴜꜱᴇʀ ʜᴀꜱ {num_warns}/{limit} ᴡᴀʀɴꜱ, ꜰᴏʀ ᴛʜᴇ ꜰᴏʟʟᴏᴡɪɴɢ ʀᴇᴀꜱᴏɴ:"
- )
- for reason in reason:
- text += f"\n • {reason}"
-
- msgs = split_message(text)
- for msg in msgs:
- update.effective_message.reply_text(msg)
- else:
- update.effective_message.reply_text(
- f"ᴛʜɪꜱ ᴜꜱᴇʀ ʜᴀꜱ {num_warns}/{limit} ᴡᴀʀɴꜱ, ʙᴜᴛ ɴᴏ ʀᴇᴀꜱᴏɴꜱ ꜰᴏʀ ᴀɴʏ ᴏꜰ ᴛʜᴇᴍ."
- )
- else:
- update.effective_message.reply_text("ᴛʜɪꜱ ᴜꜱᴇʀ ᴅᴏᴇꜱɴ'ᴛ ʜᴀᴠᴇ ᴀɴʏ ᴡᴀʀɴꜱ!")
-
-
-# Dispatcher handler stop - do not async
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-def add_warn_filter(update: Update, context: CallbackContext):
- chat: Optional[Chat] = update.effective_chat
- msg: Optional[Message] = update.effective_message
-
- args = msg.text.split(
- None, 1
- ) # use python's maxsplit to separate Cmd, keyword, and reply_text
-
- if len(args) < 2:
- return
-
- extracted = split_quotes(args[1])
-
- if len(extracted) < 2:
- return
-
- # set trigger -> lower, so as to avoid adding duplicate filters with different cases
- keyword = extracted[0].lower()
- content = extracted[1]
-
- # Note: perhaps handlers can be removed somehow using sql.get_chat_filters
- for handler in dispatcher.handlers.get(WARN_HANDLER_GROUP, []):
- if handler.filters == (keyword, chat.id):
- dispatcher.remove_handler(handler, WARN_HANDLER_GROUP)
-
- sql.add_warn_filter(chat.id, keyword, content)
-
- update.effective_message.reply_text(f"Warn handler added for '{keyword}'!")
- raise DispatcherHandlerStop
-
-
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-def remove_warn_filter(update: Update, context: CallbackContext):
- chat: Optional[Chat] = update.effective_chat
- msg: Optional[Message] = update.effective_message
-
- args = msg.text.split(
- None, 1
- ) # use python's maxsplit to separate Cmd, keyword, and reply_text
-
- if len(args) < 2:
- return
-
- extracted = split_quotes(args[1])
-
- if len(extracted) < 1:
- return
-
- to_remove = extracted[0]
-
- chat_filters = sql.get_chat_warn_triggers(chat.id)
-
- if not chat_filters:
- msg.reply_text("ɴᴏ ᴡᴀʀɴɪɴɢ ꜰɪʟᴛᴇʀꜱ ᴀʀᴇ ᴀᴄᴛɪᴠᴇ ʜᴇʀᴇ!")
- return
-
- for filt in chat_filters:
- if filt == to_remove:
- sql.remove_warn_filter(chat.id, to_remove)
- msg.reply_text("ᴏᴋᴀʏ, ɪ'ʟʟ ꜱᴛᴏᴘ ᴡᴀʀɴɪɴɢ ᴘᴇᴏᴘʟᴇ ꜰᴏʀ ᴛʜᴀᴛ.")
- raise DispatcherHandlerStop
-
- msg.reply_text(
- "ᴛʜᴀᴛ'ꜱ ɴᴏᴛ ᴀ ᴄᴜʀʀᴇɴᴛ ᴡᴀʀɴɪɴɢ ꜰɪʟᴛᴇʀ - ʀᴜɴ /warnlist ꜰᴏʀ ᴀʟʟ ᴀᴄᴛɪᴠᴇ ᴡᴀʀɴɪɴɢ ꜰɪʟᴛᴇʀꜱ."
- )
-
-
-def list_warn_filters(update: Update, context: CallbackContext):
- chat: Optional[Chat] = update.effective_chat
- all_handlers = sql.get_chat_warn_triggers(chat.id)
-
- if not all_handlers:
- update.effective_message.reply_text("ɴᴏ ᴡᴀʀɴɪɴɢ ꜰɪʟᴛᴇʀꜱ ᴀʀᴇ ᴀᴄᴛɪᴠᴇ ʜᴇʀᴇ !")
- return
-
- filter_list = CURRENT_WARNING_FILTER_STRING
- for keyword in all_handlers:
- entry = f" - {html.escape(keyword)}\n"
- if len(entry) + len(filter_list) > telegram.MAX_MESSAGE_LENGTH:
- update.effective_message.reply_text(filter_list, parse_mode=ParseMode.HTML)
- filter_list = entry
- else:
- filter_list += entry
-
- if filter_list != CURRENT_WARNING_FILTER_STRING:
- update.effective_message.reply_text(filter_list, parse_mode=ParseMode.HTML)
-
-
-@loggable
-def reply_filter(update: Update, context: CallbackContext) -> Optional[str]:
- chat: Optional[Chat] = update.effective_chat
- message: Optional[Message] = update.effective_message
- user: Optional[User] = update.effective_user
-
- if not user: # Ignore channel
- return
-
- if user.id == 777000:
- return
- if is_approved(chat.id, user.id):
- return
-
- chat_warn_filters = sql.get_chat_warn_triggers(chat.id)
- to_match = extract_text(message)
- if not to_match:
- return ""
-
- for keyword in chat_warn_filters:
- pattern = r"( |^|[^\w])" + re.escape(keyword) + r"( |$|[^\w])"
- if re.search(pattern, to_match, flags=re.IGNORECASE):
- user: Optional[User] = update.effective_user
- warn_filter = sql.get_warn_filter(chat.id, keyword)
- return warn(user, update, warn_filter.reply, message)
- return ""
-
-
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-@loggable
-def set_warn_limit(update: Update, context: CallbackContext) -> str:
- chat: Optional[Chat] = update.effective_chat
- msg: Optional[Message] = update.effective_message
-
- if args := context.args:
- user: Optional[User] = update.effective_user
- if args[0].isdigit():
- if int(args[0]) < 3:
- msg.reply_text("The minimum warn limit is 3!")
- else:
- sql.set_warn_limit(chat.id, int(args[0]))
- msg.reply_text(f"Updated the warn limit to {args[0]}")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#SET_WARN_LIMIT\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ꜱᴇᴛ ᴛʜᴇ ᴡᴀʀɴ ʟɪᴍɪᴛ ᴛᴏ {args[0]}
"
- )
- else:
- msg.reply_text("ɢɪᴠᴇ ᴍᴇ ᴀ ɴᴜᴍʙᴇʀ ᴀꜱ ᴀɴ ᴀʀɢ!")
- else:
- limit, soft_warn = sql.get_warn_setting(chat.id)
-
- msg.reply_text(f"ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴡᴀʀɴ ʟɪᴍɪᴛ ɪꜱ {limit}")
- return ""
-
-
-@user_admin(AdminPerms.CAN_RESTRICT_MEMBERS)
-def set_warn_strength(update: Update, context: CallbackContext):
- chat: Optional[Chat] = update.effective_chat
- msg: Optional[Message] = update.effective_message
-
- if args := context.args:
- user: Optional[User] = update.effective_user
- if args[0].lower() in ("on", "yes"):
- sql.set_warn_strength(chat.id, False)
- msg.reply_text("Too many warns will now result in a Ban!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ʜᴀꜱ ᴇɴᴀʙʟᴇᴅ ꜱᴛʀᴏɴɢ ᴡᴀʀɴꜱ. ᴜꜱᴇʀꜱ ᴡɪʟʟ ʙᴀɴɴᴇᴅ"
- )
-
- if args[0].lower() in ("off", "no"):
- sql.set_warn_strength(chat.id, True)
- msg.reply_text(
- "Too many warns will now result in a kick! Users will be able to join again after."
- )
- return (
- f"{html.escape(chat.title)}:\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ʜᴀꜱ ᴅɪꜱᴀʙʟᴇᴅ ʙᴀɴꜱ. ɪ ᴡɪʟʟ ᴊᴜꜱᴛ ᴋɪᴄᴋ ᴜꜱᴇʀꜱ."
- )
-
- msg.reply_text("ɪ ᴏɴʟʏ ᴜɴᴅᴇʀꜱᴛᴀɴᴅꜱ on/yes/no/off!")
- else:
- limit, soft_warn = sql.get_warn_setting(chat.id)
- if soft_warn:
- msg.reply_text(
- "ᴡᴀʀɴꜱ ᴀʀᴇ ᴄᴜʀʀᴇɴᴛʟʏ ꜱᴇᴛ ᴛᴏ *ᴋɪᴄᴋ* ᴜꜱᴇʀꜱ ᴡʜᴇɴ ᴛʜᴇʏ ᴇxᴄᴇᴇᴅ ᴛʜᴇ ʟɪᴍɪᴛ.",
- parse_mode=ParseMode.MARKDOWN,
- )
- else:
- msg.reply_text(
- "ᴡᴀʀɴꜱ ᴀʀᴇ ᴄᴜʀʀᴇɴᴛʟʏ ꜱᴇᴛ ᴛᴏ *ʙᴀɴ* ᴜꜱᴇʀꜱ ᴡʜᴇɴ ᴛʜᴇʏ ᴇxᴄᴇᴇᴅ ᴛʜᴇ ʟɪᴍɪᴛꜱ.",
- parse_mode=ParseMode.MARKDOWN,
- )
- return ""
-
-
-def __stats__():
- return (
- f"× {sql.num_warns()} ᴏᴠᴇʀᴀʟʟ ᴡᴀʀɴꜱ, ᴀᴄʀᴏꜱꜱ {sql.num_warn_chats()} ᴄʜᴀᴛꜱ.\n"
- f"× {sql.num_warn_filters()} ᴡᴀʀɴ ꜰɪʟᴛᴇʀꜱ, ᴀᴄʀᴏꜱꜱ {sql.num_warn_filter_chats()} ᴄʜᴀᴛꜱ."
- )
-
-
-def __import_data__(chat_id, data):
- for user_id, count in data.get("warns", {}).items():
- for _ in range(int(count)):
- sql.warn_user(user_id, chat_id)
-
-
-def __migrate__(old_chat_id, new_chat_id):
- sql.migrate_chat(old_chat_id, new_chat_id)
-
-
-def __chat_settings__(chat_id, user_id):
- num_warn_filters = sql.num_warn_chat_filters(chat_id)
- limit, soft_warn = sql.get_warn_setting(chat_id)
- return (
- f"ᴛʜɪꜱ ᴄʜᴀᴛ ʜᴀꜱ `{num_warn_filters}` ᴡᴀʀɴ ꜰɪʟᴛᴇʀꜱ. "
- f"ɪᴛ ᴛᴀᴋᴇꜱ `{limit}` ᴡᴀʀɴᴀ ʙᴇꜰᴏʀᴇ ᴛʜᴇ ᴜꜱᴇʀ ɢᴇᴛꜱ *{'kicked' if soft_warn else 'banned'}*."
- )
-
-
-WARN_HANDLER = CommandHandler(
- ["warn", "dwarn"], warn_user, filters=Filters.chat_type.groups, run_async=True
-)
-RESET_WARN_HANDLER = CommandHandler(
- ["resetwarn", "resetwarns"],
- reset_warns,
- filters=Filters.chat_type.groups,
- run_async=True,
-)
-CALLBACK_QUERY_HANDLER = CallbackQueryHandler(
- button, pattern=r"rm_warn", run_async=True
-)
-MYWARNS_HANDLER = DisableAbleCommandHandler(
- "warns", warns, filters=Filters.chat_type.groups, run_async=True
-)
-ADD_WARN_HANDLER = CommandHandler(
- "addwarn", add_warn_filter, filters=Filters.chat_type.groups, run_async=True
-)
-RM_WARN_HANDLER = CommandHandler(
- ["nowarn", "stopwarn"],
- remove_warn_filter,
- filters=Filters.chat_type.groups,
- run_async=True,
-)
-LIST_WARN_HANDLER = DisableAbleCommandHandler(
- ["warnlist", "warnfilters"],
- list_warn_filters,
- filters=Filters.chat_type.groups,
- admin_ok=True,
- run_async=True,
-)
-WARN_FILTER_HANDLER = MessageHandler(
- CustomFilters.has_text & Filters.chat_type.groups, reply_filter, run_async=True
-)
-WARN_LIMIT_HANDLER = CommandHandler(
- "warnlimit", set_warn_limit, filters=Filters.chat_type.groups, run_async=True
-)
-WARN_STRENGTH_HANDLER = CommandHandler(
- "strongwarn", set_warn_strength, filters=Filters.chat_type.groups, run_async=True
-)
-
-dispatcher.add_handler(WARN_HANDLER)
-dispatcher.add_handler(CALLBACK_QUERY_HANDLER)
-dispatcher.add_handler(RESET_WARN_HANDLER)
-dispatcher.add_handler(MYWARNS_HANDLER)
-dispatcher.add_handler(ADD_WARN_HANDLER)
-dispatcher.add_handler(RM_WARN_HANDLER)
-dispatcher.add_handler(LIST_WARN_HANDLER)
-dispatcher.add_handler(WARN_LIMIT_HANDLER)
-dispatcher.add_handler(WARN_STRENGTH_HANDLER)
-dispatcher.add_handler(WARN_FILTER_HANDLER, WARN_HANDLER_GROUP)
-
-__mod_name__ = "𝐖ᴀʀɴs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "warns_help")
-
-# """
diff --git a/Exon/modules/watcher.py b/Exon/modules/watcher.py
deleted file mode 100644
index 9c28675c..00000000
--- a/Exon/modules/watcher.py
+++ /dev/null
@@ -1,259 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import re
-import time
-
-from Abg.helpers.human_read import get_readable_time
-from pyrogram import filters
-from pyrogram.enums import MessageEntityType
-
-from Exon import Abishnoi as app
-from Exon.modules.no_sql.afk_db import is_afk, remove_afk
-
-chat_watcher_group = 1
-
-
-@app.on_message(
- ~filters.me & ~filters.bot & ~filters.via_bot,
- group=chat_watcher_group,
-)
-async def chat_watcher_func(c: app, message):
- if message.sender_chat:
- return
- userid = message.from_user.id
- user_name = message.from_user.first_name
- if message.entities:
- possible = ["/afk", f"/afk@{c.me.username}"]
- message_text = message.text or message.caption
- for entity in message.entities:
- if entity.type == MessageEntityType.BOT_COMMAND and message_text[: 0 + entity.length].lower() in possible:
- return
-
- msg = ""
- replied_user_id = 0
-
- # Self AFK
- verifier, reasondb = await is_afk(userid)
- if verifier:
- await remove_afk(userid)
- try:
- afktype = reasondb["type"]
- timeafk = reasondb["time"]
- data = reasondb["data"]
- reasonafk = reasondb["reason"]
- seenago = get_readable_time((int(time.time() - timeafk)))
- if afktype == "animation":
- send = (
- await message.reply_animation(
- data,
- caption=f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_animation(
- data,
- caption=f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "photo":
- send = (
- await message.reply_photo(
- photo=f"downloads/{userid}.jpg",
- caption=f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_photo(
- photo=f"downloads/{userid}.jpg",
- caption=f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "text":
- msg += f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\n"
- elif afktype == "text_reason":
- msg += f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ ᴀɴᴅ ᴡᴀs ᴀᴡᴀʏ ғᴏʀ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n"
- except Exception:
- msg += f"**{user_name[:25]}** ɪs ʙᴀᴄᴋ ᴏɴʟɪɴᴇ\n\n"
-
- # Replied to a User which is AFK
- if message.reply_to_message:
- try:
- replied_first_name = message.reply_to_message.from_user.first_name
- replied_user_id = message.reply_to_message.from_user.id
- verifier, reasondb = await is_afk(replied_user_id)
- if verifier:
- try:
- afktype = reasondb["type"]
- timeafk = reasondb["time"]
- data = reasondb["data"]
- reasonafk = reasondb["reason"]
- seenago = get_readable_time((int(time.time() - timeafk)))
- if afktype == "animation":
- send = (
- await message.reply_animation(
- data,
- caption=f"**{replied_first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_animation(
- data,
- caption=f"**{replied_first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "photo":
- send = (
- await message.reply_photo(
- photo=f"downloads/{replied_user_id}.jpg",
- caption=f"**{replied_first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_photo(
- photo=f"downloads/{replied_user_id}.jpg",
- caption=f"**{replied_first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "text":
- msg += (
- f"**{replied_first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n"
- )
- elif afktype == "text_reason":
- msg += f"**{replied_first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n"
- except Exception:
- msg += f"**{replied_first_name}** ɪs ᴀғᴋ,\nᴩᴀᴛᴀ ɴɪ ʙᴄ ᴋᴀʙ sᴇ\n\n"
- except Exception:
- pass
-
- if message.entities:
- entity = message.entities
- j = 0
- for _ in range(len(entity)):
- if (entity[j].type) == MessageEntityType.MENTION:
- found = re.findall("@([_0-9a-zA-Z]+)", message.text)
- try:
- get_user = found[j]
- user = await app.get_users(get_user)
- if user.id == replied_user_id:
- j += 1
- continue
- except Exception:
- j += 1
- continue
- verifier, reasondb = await is_afk(user.id)
- if verifier:
- try:
- afktype = reasondb["type"]
- timeafk = reasondb["time"]
- data = reasondb["data"]
- reasonafk = reasondb["reason"]
- seenago = get_readable_time((int(time.time() - timeafk)))
- if afktype == "animation":
- send = (
- await message.reply_animation(
- data,
- caption=f"**{user.first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_animation(
- data,
- caption=f"**{user.first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "photo":
- send = (
- await message.reply_photo(
- photo=f"downloads/{user.id}.jpg",
- caption=f"**{user.first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_photo(
- photo=f"downloads/{user.id}.jpg",
- caption=f"**{user.first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "text":
- msg += (
- f"**{user.first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n"
- )
- elif afktype == "text_reason":
- msg += f"**{user.first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n"
- except Exception:
- msg += f"**{user.first_name[:25]}** ɪs ᴀғᴋ\n\n"
- elif (entity[j].type) == MessageEntityType.TEXT_MENTION:
- try:
- user_id = entity[j].user.id
- if user_id == replied_user_id:
- j += 1
- continue
- first_name = entity[j].user.first_name
- except Exception:
- j += 1
- continue
- verifier, reasondb = await is_afk(user_id)
- if verifier:
- try:
- afktype = reasondb["type"]
- timeafk = reasondb["time"]
- data = reasondb["data"]
- reasonafk = reasondb["reason"]
- seenago = get_readable_time((int(time.time() - timeafk)))
- if afktype == "animation":
- send = (
- await message.reply_animation(
- data,
- caption=f"**{first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_animation(
- data,
- caption=f"**{first_name[:25]}** ɪs AFK sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "photo":
- send = (
- await message.reply_photo(
- photo=f"downloads/{user_id}.jpg",
- caption=f"**{first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n",
- )
- if str(reasonafk) == "None"
- else await message.reply_photo(
- photo=f"downloads/{user_id}.jpg",
- caption=f"**{first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n",
- )
- )
- elif afktype == "text":
- msg += f"**{first_name[:25]}** is ᴀғᴋ sɪɴᴄᴇ {seenago}\n\n"
- elif afktype == "text_reason":
- msg += f"**{first_name[:25]}** ɪs ᴀғᴋ sɪɴᴄᴇ {seenago}\n\nʀᴇᴀsᴏɴ: `{reasonafk}`\n\n"
- except Exception:
- msg += f"**{first_name[:25]}** ɪs ᴀғᴋ\n\n"
- j += 1
- if msg != "":
- try:
- send = await message.reply_text(msg, disable_web_page_preview=True)
- except Exception:
- return
diff --git a/Exon/modules/weather.py b/Exon/modules/weather.py
deleted file mode 100644
index b0845825..00000000
--- a/Exon/modules/weather.py
+++ /dev/null
@@ -1,98 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-
-import httpx
-from pyrogram import Client
-from pyrogram.types import Message
-
-from Exon import Abishnoi
-
-timeout = httpx.Timeout(40, pool=None)
-
-http = httpx.AsyncClient(http2=True, timeout=timeout)
-
-# Api key used in weather.com's mobile app.
-weather_apikey = "8de2d8b3a93542c9a2d8b3a935a2c909"
-
-get_coords = "https://api.weather.com/v3/location/search"
-url = "https://api.weather.com/v3/aggcommon/v3-wx-observations-current"
-
-headers = {
- "User-Agent": "Dalvik/2.1.0 (Linux; U; Android 12; M2012K11AG Build/SQ1D.211205.017)"
-}
-
-
-@Abishnoi.on_cmd("weather")
-async def weather(c: Client, m: Message):
- if len(m.command) == 1:
- return await m.reply_text(
- "ᴜsᴀɢᴇ: /weather location ᴏʀ city
- ɢᴇᴛ ɪɴғᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴛʜᴇ ᴡᴇᴀᴛʜᴇʀ ɪɴ ʟᴏᴄᴀᴛɪᴏɴ ᴏʀ ᴄɪᴛʏ"
- )
-
- r = await http.get(
- get_coords,
- headers=headers,
- params=dict(
- apiKey=weather_apikey,
- format="json",
- language="en",
- query=m.text.split(maxsplit=1)[1],
- ),
- )
- loc_json = r.json()
-
- if not loc_json.get("location"):
- await m.reply_text("ʟᴏᴄᴀᴛɪᴏɴ ɴᴏᴛ ғᴏᴜɴᴅ")
- else:
- pos = f"{loc_json['location']['latitude'][0]},{loc_json['location']['longitude'][0]}"
- r = await http.get(
- url,
- headers=headers,
- params=dict(
- apiKey=weather_apikey,
- format="json",
- language="en",
- geocode=pos,
- units="m",
- ),
- )
- res_json = r.json()
-
- obs_dict = res_json["v3-wx-observations-current"]
-
- res = "{location}:\n\nᴛᴇᴍᴘᴇʀᴀᴛᴜʀᴇ: {temperature} °C
\nᴛᴇᴍᴘᴇʀᴀᴛᴜʀᴇ ғᴇᴇʟs ʟɪᴋᴇ: {feels_like} °C
\nᴀɪʀ ʜᴜᴍɪᴅɪᴛʏ: {air_humidity}%
\nᴡɪɴᴅ sᴘᴇᴇᴅ: {wind_speed} km/h
\n\n- {overview}".format(
- location=loc_json["location"]["address"][0],
- temperature=obs_dict["temperature"],
- feels_like=obs_dict["temperatureFeelsLike"],
- air_humidity=obs_dict["relativeHumidity"],
- wind_speed=obs_dict["windSpeed"],
- overview=obs_dict["wxPhraseLong"],
- )
-
- await m.reply_text(res)
diff --git a/Exon/modules/webss.py b/Exon/modules/webss.py
deleted file mode 100644
index 28b4b88e..00000000
--- a/Exon/modules/webss.py
+++ /dev/null
@@ -1,123 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABISHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# :- Abishnoi_bots
-# GITHUB :- Abishnoi69 ""
-
-
-from base64 import b64decode
-from inspect import getfullargspec
-from io import BytesIO
-
-from pyrogram.types import Message
-
-from Exon import Abishnoi as app
-from Exon import aiohttpsession as session
-
-
-async def post(url: str, *args, **kwargs):
- async with session.post(url, *args, **kwargs) as resp:
- try:
- data = await resp.json()
- except Exception:
- data = await resp.text()
- return data
-
-
-async def take_screenshot(url: str, full: bool = False):
- url = url if url.startswith("http") else f"https://{url}"
- payload = {
- "url": url,
- "width": 1920,
- "height": 1080,
- "scale": 1,
- "format": "jpeg",
- }
- if full:
- payload["full"] = True
- data = await post(
- "https://webscreenshot.vercel.app/api",
- data=payload,
- )
- if "image" not in data:
- return None
- b = data["image"].replace("data:image/jpeg;base64,", "")
- file = BytesIO(b64decode(b))
- file.name = "webss.jpg"
- return file
-
-
-async def eor(msg: Message, **kwargs):
- func = (
- (msg.edit_text if msg.from_user.is_self else msg.reply)
- if msg.from_user
- else msg.reply
- )
- spec = getfullargspec(func.__wrapped__).args
- return await func(**{k: v for k, v in kwargs.items() if k in spec})
-
-
-@app.on_cmd(["webss", "ss", "webshot"])
-async def take_ss(_, message: Message):
- if len(message.command) < 2:
- return await eor(message, text="ɢɪᴠᴇ ᴀ ᴜʀʟ ᴛᴏ ғᴇᴛᴄʜ sᴄʀᴇᴇɴsʜᴏᴛ.")
-
- if len(message.command) == 2:
- url = message.text.split(None, 1)[1]
- full = False
- elif len(message.command) == 3:
- url = message.text.split(None, 2)[1]
- full = message.text.split(None, 2)[2].lower().strip() in [
- "yes",
- "y",
- "1",
- "true",
- ]
- else:
- return await eor(message, text="ɪɴᴠᴀʟɪᴅ ᴄᴏᴍᴍᴀɴᴅ.")
-
- m = await eor(message, text="ᴄᴀᴘᴛᴜʀɪɴɢ sᴄʀᴇᴇɴsʜᴏᴛ...")
-
- try:
- photo = await take_screenshot(url, full)
- if not photo:
- return await m.edit("ғᴀɪʟᴇᴅ ᴛᴏ ᴛᴀᴋᴇ sᴄʀᴇᴇɴsʜᴏᴛ.")
-
- m = await m.edit("ᴜᴘʟᴏᴀᴅɪɴɢ...")
-
- await message.reply_document(photo)
- await m.delete()
- except Exception as e:
- await m.edit(str(e))
-
-
-__mod_name__ = "𝐖ᴇʙsʜᴏᴛ"
-
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "webss_help")
diff --git a/Exon/modules/welcome.py b/Exon/modules/welcome.py
deleted file mode 100644
index b46bc40c..00000000
--- a/Exon/modules/welcome.py
+++ /dev/null
@@ -1,1366 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 AshokShau
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-# ""DEAR PRO PEOPLE, DON'T REMOVE & CHANGE THIS LINE
-# TG :- @AshokShau
-# UPDATE :- Abishnoi_bots
-# GITHUB :- AshokShau ""
-import html
-import random
-import re
-import time
-from functools import partial
-from io import BytesIO
-
-from telegram import (
- ChatPermissions,
- InlineKeyboardButton,
- InlineKeyboardMarkup,
- ParseMode,
- Update,
- User,
-)
-from telegram.error import BadRequest, TelegramError
-from telegram.ext import CallbackContext, Filters
-from telegram.utils.helpers import escape_markdown, mention_html, mention_markdown
-
-import Exon.modules.sql.log_channel_sql as logsql
-import Exon.modules.sql.welcome_sql as sql
-from Exon import DEMONS, DEV_USERS, DRAGONS, LOGGER, OWNER_ID
-from Exon import SUPPORT_CHAT as AbishnoiMF
-from Exon import WOLVES, dispatcher, sw
-from Exon.modules.helper_funcs.anonymous import AdminPerms, user_admin
-from Exon.modules.helper_funcs.chat_status import is_user_ban_protected
-from Exon.modules.helper_funcs.chat_status import user_admin as u_admin
-from Exon.modules.helper_funcs.decorators import Exoncallback, Exoncmd, Exonmsg
-from Exon.modules.helper_funcs.misc import build_keyboard, revert_buttons
-from Exon.modules.helper_funcs.msg_types import get_welcome_type
-from Exon.modules.helper_funcs.string_handling import (
- escape_invalid_curly_brackets,
- markdown_parser,
-)
-from Exon.modules.log_channel import loggable
-from Exon.modules.no_sql.global_bans_db import is_user_gbanned
-
-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 = {}
-CAPTCHA_ANS_DICT = {}
-WELCOME_GROUP = 19
-
-from multicolorcaptcha import CaptchaGenerator
-
-
-# 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(
- message,
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=keyboard,
- reply_to_message_id=reply,
- )
- except BadRequest as excp:
- if excp.message == "Button_url_invalid":
- msg = update.effective_message.reply_text(
- markdown_parser(
- (
- 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 == "Have no rights to send a message":
- return
- elif excp.message == "Reply message not found":
- msg = update.effective_message.reply_text(
- message,
- parse_mode=ParseMode.MARKDOWN,
- reply_markup=keyboard,
- quote=False,
- )
-
- elif excp.message == "Unsupported url protocol":
- msg = update.effective_message.reply_text(
- markdown_parser(
- (
- 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":
- msg = update.effective_message.reply_text(
- markdown_parser(
- (
- 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")
- else:
- msg = update.effective_message.reply_text(
- markdown_parser(
- (
- backup_message
- + "\nNote: An error occured when sending the custom message. Please update."
- )
- ),
- parse_mode=ParseMode.MARKDOWN,
- reply_to_message_id=reply,
- )
-
- LOGGER.exception()
- return msg
-
-
-@Exonmsg((Filters.status_update.new_chat_members), group=WELCOME_GROUP)
-@loggable
-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)
- )
- log_setting = logsql.get_chat_setting(chat.id)
- 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:
- welcome_log = None
- res = None
- sent = None
- should_mute = True
- welcome_bool = True
- media_wel = False
-
- if sw != None:
- if sw_ban := sw.get_ban(new_mem.id):
- return
-
- reply = update.message.message_id
- if cleanserv := sql.clean_service(chat.id):
- try:
- dispatcher.bot.delete_message(chat.id, update.message.message_id)
- except BadRequest:
- pass
- reply = False
-
- if should_welc:
- # Give the owner a special welcome
- if new_mem.id == OWNER_ID:
- update.effective_message.reply_text(
- f"ᴡᴇʟᴄᴏᴍᴇ ᴛᴏ {html.escape(chat.title)} ᴍʏ ᴅᴀʀʟɪɴɢ.",
- reply_to_message_id=reply,
- )
- welcome_log = (
- f"{html.escape(chat.title)}\n"
- f"#USER_JOINED\n"
- f"ᴍʏ ᴅᴀʀʟɪɴɢ ʜᴀꜱ ᴄᴏᴍᴇ ᴛᴏ ᴛʜɪꜱ ɢʀᴏᴜᴘ ꜰᴏʀ ᴍᴀᴋᴇ ᴛʜᴇᴇ ᴄʜɪʟᴅ ᴡɪᴛʜ ᴍᴇ"
- )
- continue
-
- elif new_mem.id in DEV_USERS:
- update.effective_message.reply_text(
- "ᴡʜᴏᴀ! ᴛʜᴇ ᴅᴇꜱᴛʀᴏʏᴇʀꜱ ᴊᴜꜱᴛ ᴀʀʀɪᴠᴇᴅ!",
- reply_to_message_id=reply,
- )
- continue
-
- elif new_mem.id in DRAGONS:
- update.effective_message.reply_text(
- "ʜᴜʜ! ꜱʜᴀᴅᴏᴡ ꜱʟᴀʏᴇʀ ᴊᴜꜱᴛ ᴊᴏɪɴᴇᴅ! ꜱᴛᴀʏ ᴀʟᴇʀᴛ!",
- reply_to_message_id=reply,
- )
- continue
-
- elif new_mem.id in DEMONS:
- update.effective_message.reply_text(
- "ʜᴜʜ! ꜱᴏᴍᴇᴏɴᴇ ᴡɪᴛʜ ɢᴜʀᴅɪᴀɴ ᴊᴜꜱᴛ ᴊᴏɪɴᴇᴅ!",
- reply_to_message_id=reply,
- )
- continue
-
- elif new_mem.id in WOLVES:
- update.effective_message.reply_text(
- "ᴏᴏꜰ! ᴀ ᴠɪʟʟᴀɪɴ ᴜꜱᴇʀ ᴊᴜꜱᴛ ᴊᴏɪɴᴇᴅ!", reply_to_message_id=reply
- )
- continue
-
- elif new_mem.id == bot.id:
- update.effective_message.reply_text(
- f"ᴛʜᴀɴᴋꜱ ꜰᴏʀ ᴀᴅᴅɪɴɢ ᴍᴇ! ᴊᴏɪɴ @{AbishnoiMF} ꜰᴏʀ ꜱᴜᴘᴘᴏʀᴛ.",
- 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"
- ) # 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 = f"@{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
-
- # User exceptions from welcomemutes
- if (
- is_user_ban_protected(update, new_mem.id, chat.get_member(new_mem.id))
- 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,
- }
- }
- )
- 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}, ᴄʟɪᴄᴋ ᴛʜᴇ ʙᴜᴛᴛᴏɴ ʙᴇʟᴏᴡᴡ ᴛᴏ ᴘʀᴏᴠᴇ ʏᴏᴜ ᴀʀᴇ ʜᴜᴍᴀɴ.\nʏᴏᴜᴜ ʜᴀᴠᴇ 120 ꜱᴇᴄᴏɴᴅꜱ.",
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ʏᴇꜱ, ɪ'ᴍ ʜᴜᴍᴀɴ.",
- callback_data=f"user_join_({new_mem.id})",
- )
- ]
- ]
- ),
- parse_mode=ParseMode.MARKDOWN,
- reply_to_message_id=reply,
- )
- 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,
- }
- }
- )
-
- 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 = 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,
- )
- 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 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)
- if prev_welc := sql.get_clean_pref(chat.id):
- try:
- bot.delete_message(chat.id, prev_welc)
- except BadRequest:
- pass
-
- if sent:
- sql.set_clean_welcome(chat.id, sent.message_id)
-
- if not log_setting.log_joins:
- return ""
- if welcome_log:
- return welcome_log
-
- return ""
-
-
-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))
- member_status = member_dict.get("status")
- if not member_status:
- try:
- bot.unban_chat_member(chat_id, member.id)
- except BadRequest:
- pass
-
- try:
- bot.edit_message_text(
- "*ᴋɪᴄᴋꜱ ᴛʜᴇ ᴜꜱᴇʀ*\nᴛʜᴇʏ ᴄᴀɴ ᴀʟᴡᴀʏꜱ ʀᴇᴊᴏɪɴ ᴀɴᴅ ᴛʀʏ.",
- chat_id=chat_id,
- message_id=message_id,
- )
- except TelegramError:
- bot.delete_message(chat_id=chat_id, message_id=message_id)
- bot.send_message(
- f"{mention_html(member.id, member.first_name)} ᴡᴀꜱ ᴋɪᴄᴋᴇᴅ ᴀꜱ ᴛʜᴇʏ ꜰᴀɪʟᴇᴅ ᴛᴏ ᴠᴀʀɪꜰʏ ᴛʜᴇᴍꜱᴇʟᴠᴇꜱ",
- chat_id=chat_id,
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exonmsg((Filters.status_update.left_chat_member), group=WELCOME_GROUP)
-def left_member(update: Update, context: CallbackContext): # sourcery no-metrics
- 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
-
- reply = update.message.message_id
- if cleanserv := sql.clean_service(chat.id):
- try:
- dispatcher.bot.delete_message(chat.id, update.message.message_id)
- except BadRequest:
- pass
- reply = False
-
- if should_goodbye:
- if left_mem := update.effective_message.left_chat_member:
- # Thingy for spamwatched users
- if sw:
- if sw_ban := sw.get_ban(left_mem.id):
- return
-
- # Dont say goodbyes to gbanned users
- if is_user_gbanned(left_mem.id):
- return
-
- # Ignore bot being kicked
- if left_mem.id == bot.id:
- return
-
- # Give the owner a special goodbye
- if left_mem.id == OWNER_ID:
- update.effective_message.reply_text(
- "ꜱᴇᴇ ʏᴏᴜ ᴀᴛ ʜᴏᴍᴇ ᴍʏ ᴅᴀʀʟɪɴɢ :(", reply_to_message_id=reply
- )
- return
-
- # Give the devs a special goodbye
- elif left_mem.id in DEV_USERS:
- update.effective_message.reply_text(
- "ꜱᴇᴇ ʏᴏᴜ ʟᴀᴛᴇʀ ᴀᴛ ᴛʜᴇ ꜱᴜᴋᴜʀᴀ ᴇᴍᴘɪʀᴇ",
- reply_to_message_id=reply,
- )
- return
-
- # if media goodbye, use appropriate function for it
- if goodbye_type not in [sql.Types.TEXT, sql.Types.BUTTON_TEXT]:
- ENUM_FUNC_MAP[goodbye_type](chat.id, cust_goodbye)
- return
-
- first_name = (
- left_mem.first_name or "PersonWithNoName"
- ) # edge case of empty name - occurs for some bugs.
- if cust_goodbye:
- if cust_goodbye == sql.DEFAULT_GOODBYE:
- cust_goodbye = random.choice(sql.DEFAULT_GOODBYE_MESSAGES).format(
- first=escape_markdown(first_name)
- )
- if left_mem.last_name:
- fullname = escape_markdown(f"{first_name} {left_mem.last_name}")
- else:
- fullname = escape_markdown(first_name)
- count = chat.get_member_count()
- mention = mention_markdown(left_mem.id, first_name)
- if left_mem.username:
- username = f"@{escape_markdown(left_mem.username)}"
- else:
- username = mention
-
- valid_format = escape_invalid_curly_brackets(
- cust_goodbye, VALID_WELCOME_FORMATTERS
- )
- res = valid_format.format(
- first=escape_markdown(first_name),
- last=escape_markdown(left_mem.last_name or first_name),
- fullname=escape_markdown(fullname),
- username=username,
- mention=mention,
- count=count,
- chatname=escape_markdown(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)
-
- send(
- update,
- res,
- keyboard,
- random.choice(sql.DEFAULT_GOODBYE_MESSAGES).format(first=first_name),
- )
-
-
-@Exoncmd(command="welcome")
-@u_admin
-def welcome(update: Update, context: CallbackContext):
- args = context.args
- chat = update.effective_chat
- # if no args, show current replies.
- if not args or args[0].lower() == "noformat":
- noformat = True
- pref, welcome_m, cust_content, welcome_type = sql.get_welc_pref(chat.id)
- update.effective_message.reply_text(
- f"ᴛʜɪꜱ ᴄʜᴀᴛ ʜᴀꜱ ɪᴛ's ᴡᴇʟᴄᴏᴍᴇ ꜱᴇᴛᴛɪɴɢ ꜱᴇᴛ ᴛᴏ : `{pref}`.\n"
- f"*ᴛʜᴇ ᴡᴇʟᴄᴏᴍᴇ ᴍᴇꜱꜱᴀɢᴇ (ɴᴏᴛ ꜰɪʟʟɪɴɢ ᴛʜᴇ {{}}) ɪꜱ:*",
- parse_mode=ParseMode.MARKDOWN,
- )
-
- if welcome_type in [sql.Types.BUTTON_TEXT, sql.Types.TEXT]:
- buttons = sql.get_welc_buttons(chat.id)
- if noformat:
- welcome_m += revert_buttons(buttons)
- update.effective_message.reply_text(welcome_m)
-
- else:
- keyb = build_keyboard(buttons)
- keyboard = InlineKeyboardMarkup(keyb)
-
- send(
- update,
- welcome_m,
- keyboard,
- random.choice(sql.DEFAULT_WELCOME_MESSAGES),
- )
- else:
- buttons = sql.get_welc_buttons(chat.id)
- if noformat:
- welcome_m += revert_buttons(buttons)
- 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)
- 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)
- update.effective_message.reply_text(
- "ɪ'ʟʟ ɢᴏ ʟᴏᴀꜰ ᴀʀʀᴏᴜɴᴅ ᴀɴᴅ ɴᴏᴛ ᴡᴇʟᴄᴏᴍᴇ ᴀɴʏᴏɴᴇ ᴛʜᴇɴ."
- )
-
- else:
- update.effective_message.reply_text(
- "ɪ ᴜɴᴅᴇʀꜱᴛᴀɴᴅ 'on/yes' ᴏʀ 'off/no' ᴏɴʟʏ!"
- )
-
-
-@Exoncmd(command="goodbye")
-@u_admin
-def goodbye(update: Update, context: CallbackContext):
- 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)
- update.effective_message.reply_text(
- f"ᴛʜɪꜱ ᴄʜᴀᴛ ʜᴀꜱ ɪᴛ's ɢᴏᴏᴅʙʏᴇ ꜱᴇᴛᴛɪɴɢ ꜱᴇᴛ ᴛᴏ : `{pref}`.\n"
- f"*ᴛʜᴇᴇ ɢᴏᴏᴅʙʏᴇ ᴍᴇꜱꜱᴀɢᴇ (ɴᴏᴛ ꜰᴇᴇʟɪɴɢ ᴛʜᴇ {{}}) ɪꜱ:*",
- 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)
- update.effective_message.reply_text(goodbye_m)
-
- else:
- keyb = build_keyboard(buttons)
- keyboard = InlineKeyboardMarkup(keyb)
-
- send(
- update,
- goodbye_m,
- keyboard,
- random.choice(sql.DEFAULT_GOODBYE_MESSAGES),
- )
-
- elif noformat:
- ENUM_FUNC_MAP[goodbye_type](chat.id, goodbye_m)
-
- else:
- 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)
- update.effective_message.reply_text("Ok!")
-
- elif args[0].lower() in ("off", "no"):
- sql.set_gdbye_preference(str(chat.id), False)
- update.effective_message.reply_text("Ok!")
-
- else:
- # idek what you're writing, say yes or no
- update.effective_message.reply_text(
- "I understand 'on/yes' or 'off/no' only!"
- )
-
-
-@Exoncmd(command="setwelcome")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def set_welcome(update: Update, context: CallbackContext) -> str:
- 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:
- msg.reply_text("ʏᴏᴜ ᴅɪᴅɴ'ᴛ ꜱᴘᴇᴄɪꜰʏ ᴡʜᴀᴛ ᴛᴏ ʀᴇᴘʟʏ ᴡɪᴛʜ!")
- return ""
-
- sql.set_custom_welcome(chat.id, content, text, data_type, buttons)
- msg.reply_text("ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ꜱᴇᴛ ᴄᴜꜱᴛᴏᴍ ᴡᴇʟᴄᴏᴍᴇ ᴍᴇꜱꜱᴀɢᴇ!")
-
- return (
- f"{html.escape(chat.title)}:\n"
- f"#SET_WELCOME\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ꜱᴇᴛ ᴛʜᴇ ᴡᴇʟᴄᴏᴍᴇ ᴍᴇꜱꜱᴀɢᴇ."
- )
-
-
-@Exoncmd(command="resetwelcome")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def reset_welcome(update: Update, context: CallbackContext) -> str:
- chat = update.effective_chat
- user = update.effective_user
-
- sql.set_custom_welcome(
- chat.id, None, random.choice(sql.DEFAULT_WELCOME_MESSAGES), sql.Types.TEXT
- )
- update.effective_message.reply_text(
- "ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ʀᴇꜱᴇᴛ ᴡᴇʟᴄᴏᴍᴇ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴅᴇꜰᴀᴜʟᴛ!"
- )
-
- return (
- f"{html.escape(chat.title)}:\n"
- f"#RESET_WELCOME\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ʀᴇꜱᴇᴛ ᴡᴇʟᴄᴏᴍᴇ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴅᴇꜰᴀᴜʟᴛ."
- )
-
-
-@Exoncmd(command="setgoodbye")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def set_goodbye(update: Update, context: CallbackContext) -> str:
- 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:
- msg.reply_text("ʏᴏᴜ ᴅɪᴅɴ'ᴛ ꜱᴘᴇᴄɪꜰʏ ᴡʜᴀᴛ ᴛᴏ ʀᴇᴘʟʏ ᴡɪᴛʜ!")
- return ""
-
- sql.set_custom_gdbye(chat.id, content or text, data_type, buttons)
- msg.reply_text("Successfully set custom goodbye message!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#SET_GOODBYE\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ꜱᴇᴛ ᴛʜᴇ ɢᴏᴏᴅʙʏᴇ ᴍᴇꜱꜱᴀɢᴇ."
- )
-
-
-@Exoncmd(command="resetgoodbye")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def reset_goodbye(update: Update, context: CallbackContext) -> str:
- chat = update.effective_chat
- user = update.effective_user
-
- sql.set_custom_gdbye(
- chat.id, random.choice(sql.DEFAULT_GOODBYE_MESSAGES), sql.Types.TEXT
- )
- update.effective_message.reply_text(
- "ꜱᴜᴄᴄᴇꜱꜱꜰᴜʟʟʏ ʀᴇꜱᴇᴛ ɢᴏᴏᴅʙʏᴇ ᴍᴇꜱꜱᴀɢᴇ ᴛᴏ ᴅᴇꜰᴀᴜʟᴛ!"
- )
-
- return (
- f"{html.escape(chat.title)}:\n"
- f"#RESET_GOODBYE\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ʀᴇꜱᴇᴛ ᴛʜᴇ ɢᴏᴏᴅʙʏᴇ ᴍᴇꜱꜱᴀɢᴇ."
- )
-
-
-@Exoncmd(command="welcomemute")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def welcomemute(update: Update, context: CallbackContext) -> 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)
- msg.reply_text("ɪ ᴡɪʟʟ ɴᴏ ʟᴏɴɢᴇʀ ᴍᴜᴛᴇ ᴘᴇᴏᴘʟᴇ ᴏɴ ᴊᴏɪɴɪɴɢ!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#WELCOME_MUTE\n"
- f"• ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ʜᴀꜱ ᴛᴏɢɢʟᴇᴅ ᴡᴇʟᴄᴏᴍᴇ ᴍᴜᴛᴇ ᴛᴏ OFF."
- )
- elif args[0].lower() in ["soft"]:
- sql.set_welcome_mutes(chat.id, "soft")
- msg.reply_text(
- "ɪ ᴡɪʟʟ ʀᴇꜱᴛʀɪᴄᴛ ᴜꜱᴇʀꜱ' ᴘᴇʀᴍɪꜱꜱɪᴏɴ ᴛᴏ ꜱᴇɴᴅ ᴍᴇᴅɪᴀ ꜰᴏʀ 24 ʜᴏᴜʀꜱ."
- )
- return (
- f"{html.escape(chat.title)}:\n"
- f"#WELCOME_MUTE\n"
- f"• ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"ʜᴀꜱ ᴛᴏɢɢʟᴇᴅ ᴡᴇʟᴄᴏᴍᴇ ᴍᴜᴛᴇ ᴛᴏ SOFT."
- )
- elif args[0].lower() in ["strong"]:
- sql.set_welcome_mutes(chat.id, "strong")
- msg.reply_text(
- "ɪ ᴡɪʟʟ ɴᴏᴡ ᴍᴜᴛᴇ ᴘᴇᴏᴘʟᴇ ᴡʜᴇɴ ᴛʜᴇʏ ᴊᴏɪɴ ᴜɴᴛɪʟ ᴛʜᴇʏ ᴘʀᴏᴠᴇ ᴛʜᴇʏ ᴀʀᴇ ɴᴏᴛ ᴀ ʙᴏᴛ.\nᴛʜᴇʏ ᴡɪʟʟ ʜᴀᴠᴇ 120 ꜱᴇᴄᴏɴᴅꜱ "
- "before they get kicked. "
- )
- return (
- f"{html.escape(chat.title)}:\n"
- f"#WELCOME_MUTE\n"
- f"• ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"Has toggled welcome mute to STRONG."
- )
- elif args[0].lower() in ["captcha"]:
- sql.set_welcome_mutes(chat.id, "captcha")
- msg.reply_text(
- "ɪ ᴡɪʟʟ ɴᴏᴡ ᴍᴜᴛᴇ ᴘᴇᴏᴘʟᴇ ᴡʜᴇɴ ᴛʜᴇʏ ᴊᴏɪɴ ᴜɴᴛɪʟʟ ᴛʜᴇʏ ᴘʀᴏᴠᴇ ᴛʜᴇʏ ᴀʀᴇ ɴᴏᴛ ʙᴏᴛ.\nᴛʜᴇʏ ʜᴀᴠᴇ ᴛᴏ ꜱᴏʟᴠᴇ ᴀ "
- "ᴄᴀᴘᴛᴄʜᴀ ᴛᴏ ɢᴇᴛ ᴜɴᴍᴜᴛᴇᴅ. "
- )
- return (
- f"{html.escape(chat.title)}:\n"
- f"#WELCOME_MUTE\n"
- f"• ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"Has toggled welcome mute to CAPTCHA."
- )
- else:
- msg.reply_text(
- "Please enter `off`/`no`/`soft`/`strong`/`captcha`!",
- parse_mode=ParseMode.MARKDOWN,
- )
- return ""
- else:
- curr_setting = sql.welcome_mutes(chat.id)
- reply = (
- f"\n Give me a setting!\nChoose one out of: `off`/`no` or `soft`, `strong` or `captcha` only! \n"
- f"Current setting: `{curr_setting}`"
- )
- msg.reply_text(reply, parse_mode=ParseMode.MARKDOWN)
- return ""
-
-
-@Exoncmd(command="cleanwelcome")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-@loggable
-def clean_welcome(update: Update, context: CallbackContext) -> str:
- args = context.args
- chat = update.effective_chat
- user = update.effective_user
-
- if not args:
- if clean_pref := sql.get_clean_pref(chat.id):
- update.effective_message.reply_text(
- "I should be deleting welcome messages up to two days old."
- )
- else:
- 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)
- update.effective_message.reply_text("I'll try to delete old welcome messages!")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#CLEAN_WELCOME\n"
- f"Admin: {mention_html(user.id, user.first_name)}\n"
- f"Has toggled clean welcomes to ON
."
- )
- elif args[0].lower() in ("off", "no"):
- sql.set_clean_welcome(str(chat.id), False)
- update.effective_message.reply_text("ɪ ᴡᴏɴ'ᴛ ᴅᴇʟᴇᴛᴇ ᴏʟᴅ ᴡᴇʟᴄᴏᴍᴇ ᴍᴇꜱꜱᴀɢᴇ.")
- return (
- f"{html.escape(chat.title)}:\n"
- f"#CLEAN_WELCOME\n"
- f"ᴀᴅᴍɪɴ: {mention_html(user.id, user.first_name)}\n"
- f"Has toggled clean welcomes to OFF
."
- )
- else:
- update.effective_message.reply_text("I understand 'on/yes' or 'off/no' only!")
- return ""
-
-
-@Exoncmd(command="cleanservice")
-@user_admin(AdminPerms.CAN_CHANGE_INFO)
-def cleanservice(update: Update, context: CallbackContext) -> str:
- args = context.args
- chat = update.effective_chat # type: Optional[Chat]
- if chat.type == chat.PRIVATE:
- if curr := sql.clean_service(chat.id):
- update.effective_message.reply_text(
- "Welcome clean service is : on", parse_mode=ParseMode.MARKDOWN
- )
- else:
- update.effective_message.reply_text(
- "Welcome clean service is : off", parse_mode=ParseMode.MARKDOWN
- )
-
- elif len(args) >= 1:
- var = args[0]
- if var in ("no", "off"):
- sql.set_clean_service(chat.id, False)
- update.effective_message.reply_text("Welcome clean service is : off")
- elif var in ("yes", "on"):
- sql.set_clean_service(chat.id, True)
- update.effective_message.reply_text("Welcome clean service is : on")
- else:
- update.effective_message.reply_text(
- "Invalid option", parse_mode=ParseMode.MARKDOWN
- )
- else:
- update.effective_message.reply_text(
- "Usage is on/yes or off/no", parse_mode=ParseMode.MARKDOWN
- )
-
-
-@Exoncallback(pattern=r"user_join_")
-def user_button(update: Update, context: CallbackContext):
- chat = update.effective_chat
- user = update.effective_user
- query = update.callback_query
- bot = context.bot
- match = re.match(r"user_join_\((.+?)\)", query.data)
- join_user = int(match[1])
-
- if join_user == user.id:
- sql.set_human_checks(user.id, chat.id)
- member_dict = VERIFIED_USER_WAITLIST[(chat.id, user.id)]
- member_dict["status"] = True
- query.answer(text="Yeet! You're a human, unmuted!")
- 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,
- ),
- )
- message = update.effective_message
- try:
- bot.deleteMessage(chat.id, message.message_id)
- except Exception:
- pass
- if member_dict["should_welc"]:
- if member_dict["media_wel"]:
- sent = 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 = send(
- member_dict["update"],
- member_dict["res"],
- member_dict["keyboard"],
- member_dict["backup_message"],
- )
-
- if prev_welc := sql.get_clean_pref(chat.id):
- try:
- bot.delete_message(chat.id, prev_welc)
- except BadRequest:
- pass
-
- if sent:
- sql.set_clean_welcome(chat.id, sent.message_id)
-
- else:
- query.answer(text="You're not allowed to do this!")
-
-
-@Exoncallback(pattern=r"user_captchajoin_\([\d\-]+,\d+\)_\(\d{4}\)")
-def user_captcha_button(update: Update, context: CallbackContext):
- # sourcery no-metrics
- chat = update.effective_chat
- user = update.effective_user
- query = update.callback_query
- bot = context.bot
- # print(query.data)
- match = re.match(r"user_captchajoin_\(([\d\-]+),(\d+)\)_\((\d{4})\)", query.data)
- message = update.effective_message
- join_chat = int(match[1])
- join_user = int(match[2])
- captcha_ans = int(match[3])
- join_usr_data = bot.getChat(join_user)
-
- if join_user == user.id:
- c_captcha_ans = CAPTCHA_ANS_DICT.pop((join_chat, join_user))
- if c_captcha_ans == captcha_ans:
- sql.set_human_checks(user.id, chat.id)
- member_dict = VERIFIED_USER_WAITLIST[(chat.id, user.id)]
- member_dict["status"] = True
- query.answer(text="Yeet! You're a human, unmuted!")
- 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,
- ),
- )
- try:
- bot.deleteMessage(chat.id, message.message_id)
- except Exception:
- pass
- if member_dict["should_welc"]:
- if member_dict["media_wel"]:
- sent = 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 = send(
- member_dict["update"],
- member_dict["res"],
- member_dict["keyboard"],
- member_dict["backup_message"],
- )
-
- if prev_welc := sql.get_clean_pref(chat.id):
- try:
- bot.delete_message(chat.id, prev_welc)
- except BadRequest:
- pass
-
- if sent:
- sql.set_clean_welcome(chat.id, sent.message_id)
- else:
- try:
- bot.deleteMessage(chat.id, message.message_id)
- except Exception:
- pass
- kicked_msg = f"""
- ❌ [{escape_markdown(join_usr_data.first_name)}](tg://user?id={join_user}) failed the captcha and was kicked.
- """
- query.answer(text="Wrong answer")
- if res := chat.unban_member(join_user):
- bot.sendMessage(
- chat_id=chat.id, text=kicked_msg, parse_mode=ParseMode.MARKDOWN
- )
-
- else:
- query.answer(text="You're not allowed to do this!")
-
-
-"""
-@Exoncmd(command="lockgroup", pass_args=True)
-@u_admin(AdminPerms.CAN_CHANGE_INFO)
-def setDefense(update: Update, context: CallbackContext):
-
- context.bot
- args = context.args
- chat = update.effective_chat
- msg = update.effective_message
- u = update.effective_user
- res_user(u, msg.message_id, chat)
- stat, time, acttime = sql.getDefenseStatus(chat.id)
- if len(args) != 1:
- text = (
- "Give me some arguments to choose a setting! on/off, yes/no!\n\nYour current setting is: {}\nWhen True, every user that joins will be auto kicked."
- "".format(stat)
- )
- msg.reply_text(text, parse_mode=ParseMode.HTML)
- return
- param = args[0]
- if param in ["on", "true"]:
- sql.setDefenseStatus(chat.id, True, time, acttime)
- msg.reply_text(
- "Lockgroup mode has been turned on, this group is under attack. Every user that now joins will be auto kicked."
- )
- elif param in ["off", "false"]:
- sql.setDefenseStatus(chat.id, False, time, acttime)
- msg.reply_text(
- "Lockgroup mode has been turned off, group is no longer under attack."
- )
- else:
- msg.reply_text("Invalid status to set!") # on or off ffs
-
- return
-
-
- """
-
-WELC_HELP_TXT = (
- "Your group's welcome/goodbye messages can be personalised 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 user has no "
- "last name.\n"
- " × `{fullname}`*:* this represents the user's *full* name. Defaults to *first name* if user has no "
- "last name.\n"
- " × `{username}`*:* this represents the user's *username*. Defaults to a *mention* of the user's "
- "first name if has 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.\n"
- f"To create a button linking to your rules, use this: `[Rules](buttonurl://t.me/{dispatcher.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; this is required, so please don't "
- "remove it.\n"
- "You can even set images/gifs/videos/voice messages as the welcome message by "
- "replying to the desired media, and calling `/setwelcome`."
-)
-
-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 till they tap on a button thereby verifying they're human.\n"
- "× `/welcomemute captcha`*:* mutes new members till they solve a button captcha thereby verifying they're human.\n"
- "× `/welcomemute off`*:* turns off welcomemute.\n"
- "*Note:* Strong mode kicks a user from the chat if they dont verify in 120seconds. They can always rejoin though"
-)
-
-
-@Exoncmd(command="welcomehelp")
-@u_admin
-def welcome_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(WELC_HELP_TXT, parse_mode=ParseMode.MARKDOWN)
-
-
-@Exoncmd(command="welcomemutehelp")
-@u_admin
-def welcome_mute_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- WELC_MUTE_HELP_TXT, parse_mode=ParseMode.MARKDOWN
- )
-
-
-# TODO: get welcome data from group butler snap
-# def __import_data__(chat_id, data):
-# welcome = data.get('info', {}).get('rules')
-# welcome = welcome.replace('$username', '{username}')
-# welcome = welcome.replace('$name', '{fullname}')
-# welcome = welcome.replace('$id', '{id}')
-# welcome = welcome.replace('$title', '{chatname}')
-# welcome = welcome.replace('$surname', '{lastname}')
-# welcome = welcome.replace('$rules', '{rules}')
-# sql.set_custom_welcome(chat_id, welcome, sql.Types.TEXT)
-
-
-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 it's welcome preference set to `{welcome_pref}`.\nIt's goodbye preference is `{goodbye_pref}`."
-
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-from Exon.modules.language import gs
-
-
-def wlc_m_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "welcome_mutes"),
- parse_mode=ParseMode.HTML,
- )
-
-
-def wlc_fill_help(update: Update, context: CallbackContext):
- update.effective_message.reply_text(
- gs(update.effective_chat.id, "welcome_help"),
- parse_mode=ParseMode.HTML,
- )
-
-
-@Exoncallback(pattern=r"wlc_help_")
-def fmt_help(update: Update, context: CallbackContext):
- query = update.callback_query
- bot = context.bot
- help_info = query.data.split("wlc_help_")[1]
- if help_info == "m":
- help_text = gs(update.effective_chat.id, "welcome_mutes")
- elif help_info == "h":
- help_text = gs(
- update.effective_chat.id, "welcome_help"
- ) # .format(escape_markdown(dispatcher.bot.username)))
- query.message.edit_text(
- text=help_text,
- parse_mode=ParseMode.HTML,
- reply_markup=InlineKeyboardMarkup(
- [
- [
- InlineKeyboardButton(
- text="ʙᴀᴄᴋ",
- callback_data=f"help_module({__mod_name__.lower()})",
- )
- ]
- ]
- ),
- )
- bot.answer_callback_query(query.id)
-
-
-# """
-def get_help(chat):
- return [
- gs(chat, "greetings_help"),
- [
- InlineKeyboardButton(text="ᴡᴇʟᴄᴏᴍᴇᴇ ᴍᴜᴛᴇꜱ", callback_data="wlc_help_m"),
- InlineKeyboardButton(text="ᴡᴇʟᴄᴏᴍᴇ ꜰᴏʀᴍᴀᴛᴛɪɴɢ", callback_data="wlc_help_h"),
- ],
- ]
-
-
-# """
-
-__mod_name__ = "𝐖ᴇʟᴄᴏᴍᴇ"
diff --git a/Exon/modules/zombies.py b/Exon/modules/zombies.py
deleted file mode 100644
index b6328ecc..00000000
--- a/Exon/modules/zombies.py
+++ /dev/null
@@ -1,124 +0,0 @@
-from asyncio import sleep
-
-from telethon import events
-from telethon.errors import ChatAdminRequiredError, UserAdminInvalidError
-from telethon.tl.functions.channels import EditBannedRequest
-from telethon.tl.types import ChannelParticipantsAdmins, ChatBannedRights
-
-from Exon import DEMONS, DEV_USERS, DRAGONS, OWNER_ID, telethn
-
-# =================== CONSTANT ===================
-
-BANNED_RIGHTS = ChatBannedRights(
- until_date=None,
- view_messages=True,
- send_messages=True,
- send_media=True,
- send_stickers=True,
- send_gifs=True,
- send_games=True,
- send_inline=True,
- embed_links=True,
-)
-
-UNBAN_RIGHTS = ChatBannedRights(
- until_date=None,
- send_messages=None,
- send_media=None,
- send_stickers=None,
- send_gifs=None,
- send_games=None,
- send_inline=None,
- embed_links=None,
-)
-
-OFFICERS = [OWNER_ID] + DEV_USERS + DRAGONS + DEMONS
-
-
-# Check if user has admin rights
-async def is_administrator(user_id: int, message):
- admin = False
- async for user in telethn.iter_participants(
- message.chat_id, filter=ChannelParticipantsAdmins
- ):
- if user_id == user.id or user_id in OFFICERS:
- admin = True
- break
- return admin
-
-
-@telethn.on(events.NewMessage(pattern="^[!/]zombies ?(.*)"))
-async def zombies(event):
- """For .zombies command, list all the zombies in a chat."""
- con = event.pattern_match.group(1).lower()
- del_u = 0
- del_status = "ɴᴏ ᴅᴇʟᴇᴛᴇᴅ ᴀᴄᴄᴏᴜɴᴛꜱ ꜰᴏᴜɴᴅ, ɢʀᴏᴜᴘ ɪꜱ ᴄʟᴇᴀɴ ᴇɴᴊᴏʏ."
-
- if con != "clean":
- find_zombies = await event.respond("ꜱᴇᴀʀᴄʜɪɴɢ ꜰᴏʀ ᴢᴏᴍʙɪᴇꜱ...")
- async for user in event.client.iter_participants(event.chat_id):
- if user.deleted:
- del_u += 1
- await sleep(1)
- if del_u > 0:
- del_status = f"ꜰᴏᴜɴᴅ **{del_u}** ᴢᴏᴍʙɪᴇꜱ ɪɴ ᴛʜɪꜱ ɢʀᴏᴜᴘ.\
- \nᴄʟᴇᴀɴ ᴛʜᴇᴍ ʙʏ ᴜꜱɪɴɢ - `/zombies clean`"
- await find_zombies.edit(del_status)
- return
-
- # Here laying the sanity check
- chat = await event.get_chat()
- admin = chat.admin_rights
- creator = chat.creator
-
- # Well
- if not await is_administrator(user_id=event.sender_id, message=event):
- await event.respond("You're Not An Admin!")
- return
-
- if not admin and not creator:
- await event.respond("ɪ ᴀᴍ ɴᴏᴛ ᴀᴅᴍɪɴ ʜᴇʀᴇ!")
- return
-
- cleaning_zombies = await event.respond("ᴄʟᴇᴀɴɪɴɢ ᴢᴏᴍʙɪᴇꜱ...")
- del_u = 0
- del_a = 0
-
- async for user in event.client.iter_participants(event.chat_id):
- if user.deleted:
- try:
- await event.client(
- EditBannedRequest(event.chat_id, user.id, BANNED_RIGHTS)
- )
- except ChatAdminRequiredError:
- await cleaning_zombies.edit("ɪ ᴅᴏɴᴛ ʜᴀᴠᴇ ʙᴀɴ ʀɪɢʜᴛ ɪɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ.")
- return
- except UserAdminInvalidError:
- del_u -= 1
- del_a += 1
- await event.client(EditBannedRequest(event.chat_id, user.id, UNBAN_RIGHTS))
- del_u += 1
-
- if del_u > 0:
- del_status = f"ᴄʟᴇᴀɴᴇᴅ `{del_u}` ᴢᴏᴍʙɪᴇꜱ"
-
- if del_a > 0:
- del_status = f"ᴄʟᴇᴀɴᴇᴅ `{del_u}` ᴢᴏᴍʙɪᴇꜱ \
- \n`{del_a}` ᴢᴏᴍʙɪᴇꜱ ᴀᴅᴍɪɴ ᴀᴄᴄᴏᴜɴᴛꜱ ᴀʀᴇ ɴᴏᴛ ʀᴇᴍᴏᴠᴇᴅ!"
-
- await cleaning_zombies.edit(del_status)
-
-
-__mod_name__ = "𝐙ᴏᴍʙɪᴇs"
-
-# ғᴏʀ ʜᴇʟᴘ ᴍᴇɴᴜ
-
-
-# """
-from Exon.modules.language import gs
-
-
-def get_help(chat):
- return gs(chat, "zombies_help")
-
-# """
diff --git "a/Exon/utils/ABISHNOI \302\251" "b/Exon/utils/ABISHNOI \302\251"
deleted file mode 100644
index 639077b5..00000000
--- "a/Exon/utils/ABISHNOI \302\251"
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
diff --git a/Exon/utils/__init__.py b/Exon/utils/__init__.py
deleted file mode 100644
index 639077b5..00000000
--- a/Exon/utils/__init__.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
diff --git a/Exon/utils/adminpermissions.py b/Exon/utils/adminpermissions.py
deleted file mode 100644
index 645f29c2..00000000
--- a/Exon/utils/adminpermissions.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from Exon import Abishnoi as AsuX
-
-
-async def member_permissions(chat_id: int, user_id: int):
- perms = []
- member = await AsuX.get_chat_member(chat_id, user_id)
- if member.can_post_messages:
- perms.append("can_post_messages")
- if member.can_edit_messages:
- perms.append("can_edit_messages")
- if member.can_delete_messages:
- perms.append("can_delete_messages")
- if member.can_restrict_members:
- perms.append("can_restrict_members")
- if member.can_promote_members:
- perms.append("can_promote_members")
- if member.can_change_info:
- perms.append("can_change_info")
- if member.can_invite_users:
- perms.append("can_invite_users")
- if member.can_pin_messages:
- perms.append("can_pin_messages")
- if member.can_manage_voice_chats:
- perms.append("can_manage_voice_chats")
- return perms
diff --git a/Exon/utils/aiodownloader.py b/Exon/utils/aiodownloader.py
deleted file mode 100644
index 9c19c751..00000000
--- a/Exon/utils/aiodownloader.py
+++ /dev/null
@@ -1,155 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import asyncio
-import os
-from typing import Optional
-
-import aiofiles
-import aiohttp
-
-
-class DownloadJob:
- """
- Download Job
- :param file_url: url where the file is located
- :param session: aiohttp session to be used on the job
- :param file_name: name to be used on the file. Defaults to the last part of the url
- :param save_path: dir where the file should be saved. Defaults to the current dir
- """
-
- def __init__(
- self,
- session: aiohttp.ClientSession,
- file_url: str,
- save_path: Optional[str] = None,
- chunk_size: Optional[int] = 1024,
- ):
- self.file_url = file_url
- self._session = session
- self._chunk_size = chunk_size
-
- self.file_name = file_url.split("/")[~0][:230]
- self.file_path = (
- os.path.join(save_path, self.file_name) if save_path else self.file_name
- )
-
- self.completed = False
- self.progress = 0
- self.size = 0
-
- async def get_size(self) -> int:
- """
- Gets the content-length of the file from the file url.
- :return: the files size in bytes
- """
- if not self.size:
- async with self._session.get(self.file_url) as resp:
- if 200 <= resp.status < 300:
- self.size = int(resp.headers["Content-Length"])
-
- else:
- raise aiohttp.errors.HttpProcessingError(
- message=f"There was a problem processing {self.file_url}",
- code=resp.status,
- )
-
- return self.size
-
- def _downloaded(self, chunk_size):
- """
- Method to be called when a chunk of the file is downloaded. It updates the
- progress, adds the size to the _advance variable and checks if the download
- is completed
- """
- self.progress += chunk_size
-
- async def download(self):
- """
- Downloads the file from the given url to a file in the given path.
- """
-
- async with self._session.get(self.file_url) as resp:
- # Checkning the response code
- if 200 <= resp.status < 300:
- # Saving the data to the file chunk by chunk.
- async with aiofiles.open(self.file_path, "wb") as file:
- # Downloading the file using the aiohttp.StreamReader
- async for data in resp.content.iter_chunked(self._chunk_size):
- await file.write(data)
- self._downloaded(self._chunk_size)
-
- self.completed = True
- return self
- raise aiohttp.errors.HttpProcessingError(
- message=f"There was a problem processing {self.file_url}",
- code=resp.status,
- )
-
-
-class Handler:
- """
- Top level interface with the downloader. It creates the download jobs and handles them.
- :param loop: asyncio loop. if not provided asyncio.get_event_loop() will be used
- :param session: aiohttp session to be used on all downloads. If not provided it will be
- created
- :param chunk_size: chunk bytes sizes to get from the file source. Defaults to 1024 bytes
- """
-
- def __init__(
- self,
- loop: Optional[asyncio.BaseEventLoop] = None,
- session: Optional[aiohttp.ClientSession] = None,
- chunk_size: Optional[int] = 1024,
- ):
- self._loop = loop or asyncio.get_event_loop()
- self._session = session or aiohttp.ClientSession(loop=self._loop)
- self._chunk_size = chunk_size
-
- def _job_factory(
- self, file_url: str, save_path: Optional[str] = None
- ) -> DownloadJob:
- """
- Shortcut for creating a download job. It adds the session and the chunk size.
- :param file_url: url where the file is located
- :param save_path: save path for the download
- :return:
- """
- return DownloadJob(self._session, file_url, save_path, self._chunk_size)
-
- async def download(self, url: str, save_path: Optional[str] = None) -> DownloadJob:
- """
- Downloads a bulk of files from the given list of urls to the given path.
- :param files_url: list of urls where the files are located
- :param save_path: path to be used for saving the files. Defaults to the current dir
- """
-
- job = self._job_factory(url, save_path=save_path)
-
- task = asyncio.ensure_future(job.download())
-
- await task
- file_name = url.split("/")[-1]
- file_name = file_name[:230] if len(file_name) > 230 else file_name
- return save_path or f"{os.getcwd()}/{file_name}"
diff --git a/Exon/utils/dbfunctions.py b/Exon/utils/dbfunctions.py
deleted file mode 100644
index b344708f..00000000
--- a/Exon/utils/dbfunctions.py
+++ /dev/null
@@ -1,724 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import codecs
-import pickle
-from typing import Dict, List, Union
-
-from Exon.modules.no_sql import db
-
-# SOME THINGS ARE FUCKED UP HERE, LIKE TOGGLEABLES HAVE THEIR OWN COLLECTION
-# (SHOULD FIX IT WITH SOMETHING LIKE TOGGLEDB), MOST OF THE CODE IS BAD AF
-# AND NEEDS TO BE REWRITTEN, BUT I WON'T, AS IT WILL TAKE
-# TOO MUCH TIME AND WILL BE BAD FOR ALREADY STORED DATA
-
-
-notesdb = db.notes
-filtersdb = db.filters
-warnsdb = db.warns
-nsfwdb = db.nsfw
-karmadb = db.karma
-chatsdb = db.chats
-usersdb = db.users
-gbansdb = db.gban
-coupledb = db.couple
-captchadb = db.captcha
-solved_captcha_db = db.solved_captcha
-captcha_cachedb = db.captcha_cache
-antiservicedb = db.antiservice
-pmpermitdb = db.pmpermit
-welcomedb = db.welcome_text
-blacklist_filtersdb = db.blacklistFilters
-pipesdb = db.pipes
-sudoersdb = db.sudoers
-blacklist_chatdb = db.blacklistChat
-restart_stagedb = db.restart_stage
-flood_toggle_db = db.flood_toggle
-rssdb = db.rss
-
-
-def obj_to_str(obj):
- return codecs.encode(pickle.dumps(obj), "base64").decode() if obj else False
-
-
-def str_to_obj(string: str):
- return pickle.loads(codecs.decode(string.encode(), "base64"))
-
-
-async def get_notes_count() -> dict:
- chats = notesdb.find({"chat_id": {"$exists": 1}})
- if not chats:
- return {}
- chats_count = 0
- notes_count = 0
- for chat in await chats.to_list(length=1000000000):
- notes_name = await get_note_names(chat["chat_id"])
- notes_count += len(notes_name)
- chats_count += 1
- return {"chats_count": chats_count, "notes_count": notes_count}
-
-
-async def _get_notes(chat_id: int) -> Dict[str, int]:
- _notes = await notesdb.find_one({"chat_id": chat_id})
- return _notes["notes"] if _notes else {}
-
-
-async def get_note_names(chat_id: int) -> List[str]:
- return list(await _get_notes(chat_id))
-
-
-async def get_note(chat_id: int, name: str) -> Union[bool, dict]:
- name = name.lower().strip()
- _notes = await _get_notes(chat_id)
- return _notes[name] if name in _notes else False
-
-
-async def save_note(chat_id: int, name: str, note: dict):
- name = name.lower().strip()
- _notes = await _get_notes(chat_id)
- _notes[name] = note
-
- await notesdb.update_one(
- {"chat_id": chat_id}, {"$set": {"notes": _notes}}, upsert=True
- )
-
-
-async def delete_note(chat_id: int, name: str) -> bool:
- notesd = await _get_notes(chat_id)
- name = name.lower().strip()
- if name in notesd:
- del notesd[name]
- await notesdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"notes": notesd}},
- upsert=True,
- )
- return True
- return False
-
-
-async def get_filters_count() -> dict:
- chats = filtersdb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return {}
- chats_count = 0
- filters_count = 0
- for chat in await chats.to_list(length=1000000000):
- filters_name = await get_filters_names(chat["chat_id"])
- filters_count += len(filters_name)
- chats_count += 1
- return {
- "chats_count": chats_count,
- "filters_count": filters_count,
- }
-
-
-async def _get_filters(chat_id: int) -> Dict[str, int]:
- _filters = await filtersdb.find_one({"chat_id": chat_id})
- return _filters["filters"] if _filters else {}
-
-
-async def get_filters_names(chat_id: int) -> List[str]:
- return list(await _get_filters(chat_id))
-
-
-async def get_filter(chat_id: int, name: str) -> Union[bool, dict]:
- name = name.lower().strip()
- _filters = await _get_filters(chat_id)
- return _filters[name] if name in _filters else False
-
-
-async def save_filter(chat_id: int, name: str, _filter: dict):
- name = name.lower().strip()
- _filters = await _get_filters(chat_id)
- _filters[name] = _filter
- await filtersdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"filters": _filters}},
- upsert=True,
- )
-
-
-async def delete_filter(chat_id: int, name: str) -> bool:
- filtersd = await _get_filters(chat_id)
- name = name.lower().strip()
- if name in filtersd:
- del filtersd[name]
- await filtersdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"filters": filtersd}},
- upsert=True,
- )
- return True
- return False
-
-
-async def int_to_alpha(user_id: int) -> str:
- alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
- user_id = str(user_id)
- return "".join(alphabet[int(i)] for i in user_id)
-
-
-async def alpha_to_int(user_id_alphabet: str) -> int:
- alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
- user_id = ""
- for i in user_id_alphabet:
- index = alphabet.index(i)
- user_id += str(index)
- return int(user_id)
-
-
-async def get_warns_count() -> dict:
- chats = warnsdb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return {}
- chats_count = 0
- warns_count = 0
- for chat in await chats.to_list(length=100000000):
- for user in chat["warns"]:
- warns_count += chat["warns"][user]["warns"]
- chats_count += 1
- return {"chats_count": chats_count, "warns_count": warns_count}
-
-
-async def get_warns(chat_id: int) -> Dict[str, int]:
- warns = await warnsdb.find_one({"chat_id": chat_id})
- return warns["warns"] if warns else {}
-
-
-async def get_warn(chat_id: int, name: str) -> Union[bool, dict]:
- name = name.lower().strip()
- warns = await get_warns(chat_id)
- if name in warns:
- return warns[name]
-
-
-async def add_warn(chat_id: int, name: str, warn: dict):
- name = name.lower().strip()
- warns = await get_warns(chat_id)
- warns[name] = warn
-
- await warnsdb.update_one(
- {"chat_id": chat_id}, {"$set": {"warns": warns}}, upsert=True
- )
-
-
-async def remove_warns(chat_id: int, name: str) -> bool:
- warnsd = await get_warns(chat_id)
- name = name.lower().strip()
- if name in warnsd:
- del warnsd[name]
- await warnsdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"warns": warnsd}},
- upsert=True,
- )
- return True
- return False
-
-
-async def get_karmas_count() -> dict:
- chats = karmadb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return {}
- chats_count = 0
- karmas_count = 0
- for chat in await chats.to_list(length=1000000):
- for i in chat["karma"]:
- karma_ = chat["karma"][i]["karma"]
- if karma_ > 0:
- karmas_count += karma_
- chats_count += 1
- return {"chats_count": chats_count, "karmas_count": karmas_count}
-
-
-async def user_global_karma(user_id) -> int:
- chats = karmadb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return 0
- total_karma = 0
- for chat in await chats.to_list(length=1000000):
- karma = await get_karma(chat["chat_id"], await int_to_alpha(user_id))
- if karma and (int(karma["karma"]) > 0):
- total_karma += int(karma["karma"])
- return total_karma
-
-
-async def get_karmas(chat_id: int) -> Dict[str, int]:
- karma = karmadb.find_one({"chat_id": chat_id})
- return karma["karma"] if karma else {}
-
-
-async def get_karma(chat_id: int, name: str) -> Union[bool, dict]:
- name = name.lower().strip()
- karmas = await get_karmas(chat_id)
- if name in karmas:
- return karmas[name]
-
-
-async def update_karma(chat_id: int, name: str, karma: dict):
- name = name.lower().strip()
- karmas = await get_karmas(chat_id)
- karmas[name] = karma
- karmadb.update_one({"chat_id": chat_id}, {"$set": {"karma": karmas}}, upsert=True)
-
-
-async def is_karma_on(chat_id: int) -> bool:
- chat = karmadb.find_one({"chat_id_toggle": chat_id})
- return not chat
-
-
-async def karma_on(chat_id: int):
- is_karma = await is_karma_on(chat_id)
- if is_karma:
- return
- return karmadb.delete_one({"chat_id_toggle": chat_id})
-
-
-async def karma_off(chat_id: int):
- is_karma = await is_karma_on(chat_id)
- if not is_karma:
- return
- return karmadb.insert_one({"chat_id_toggle": chat_id})
-
-
-async def is_nsfw_on(chat_id: int) -> bool:
- chat = nsfwdb.find_one({"chat_id": chat_id})
- return not chat
-
-
-async def nsfw_on(chat_id: int):
- if is_nsfw := is_nsfw_on(chat_id):
- return
- return nsfwdb.delete_one({"chat_id": chat_id})
-
-
-async def nsfw_off(chat_id: int):
- if is_nsfw := is_nsfw_on(chat_id):
- return nsfwdb.insert_one({"chat_id": chat_id})
- else:
- return
-
-
-async def is_served_chat(chat_id: int) -> bool:
- chat = await chatsdb.find_one({"chat_id": chat_id})
- return bool(chat)
-
-
-async def get_served_chats() -> list:
- chats = chatsdb.find({"chat_id": {"$lt": 0}})
- return list(await chats.to_list(length=1000000000)) if chats else []
-
-
-async def add_served_chat(chat_id: int):
- is_served = await is_served_chat(chat_id)
- if is_served:
- return
- return await chatsdb.insert_one({"chat_id": chat_id})
-
-
-async def remove_served_chat(chat_id: int):
- is_served = await is_served_chat(chat_id)
- if not is_served:
- return
- return await chatsdb.delete_one({"chat_id": chat_id})
-
-
-async def is_served_user(user_id: int) -> bool:
- user = await usersdb.find_one({"user_id": user_id})
- return bool(user)
-
-
-async def get_served_users() -> list:
- users = usersdb.find({"user_id": {"$gt": 0}})
- return list(await users.to_list(length=1000000000)) if users else []
-
-
-async def add_served_user(user_id: int):
- is_served = await is_served_user(user_id)
- if is_served:
- return
- return await usersdb.insert_one({"user_id": user_id})
-
-
-async def get_gbans_count() -> int:
- users = gbansdb.find({"user_id": {"$gt": 0}})
- users = await users.to_list(length=100000)
- return len(users)
-
-
-async def is_gbanned_user(user_id: int) -> bool:
- user = gbansdb.find_one({"user_id": user_id})
- return bool(user)
-
-
-async def add_gban_user(user_id: int):
- is_gbanned = await is_gbanned_user(user_id)
- if is_gbanned:
- return
- return gbansdb.insert_one({"user_id": user_id})
-
-
-async def remove_gban_user(user_id: int):
- is_gbanned = await is_gbanned_user(user_id)
- if not is_gbanned:
- return
- return gbansdb.delete_one({"user_id": user_id})
-
-
-async def _get_lovers(chat_id: int):
- lovers = coupledb.find_one({"chat_id": chat_id})
- return lovers["couple"] if lovers else {}
-
-
-async def get_couple(chat_id: int, date: str):
- lovers = await _get_lovers(chat_id)
- return lovers[date] if date in lovers else False
-
-
-async def save_couple(chat_id: int, date: str, couple: dict):
- lovers = await _get_lovers(chat_id)
- lovers[date] = couple
- coupledb.update_one(
- {"chat_id": chat_id},
- {"$set": {"couple": lovers}},
- upsert=True,
- )
-
-
-async def is_captcha_on(chat_id: int) -> bool:
- chat = captchadb.find_one({"chat_id": chat_id})
- return not chat
-
-
-async def captcha_on(chat_id: int):
- is_captcha = await is_captcha_on(chat_id)
- if is_captcha:
- return
- return captchadb.delete_one({"chat_id": chat_id})
-
-
-async def captcha_off(chat_id: int):
- is_captcha = await is_captcha_on(chat_id)
- if not is_captcha:
- return
- return captchadb.insert_one({"chat_id": chat_id})
-
-
-async def has_solved_captcha_once(chat_id: int, user_id: int):
- has_solved = await solved_captcha_db.find_one(
- {"chat_id": chat_id, "user_id": user_id}
- )
- return bool(has_solved)
-
-
-async def save_captcha_solved(chat_id: int, user_id: int):
- return await solved_captcha_db.update_one(
- {"chat_id": chat_id},
- {"$set": {"user_id": user_id}},
- upsert=True,
- )
-
-
-async def is_antiservice_on(chat_id: int) -> bool:
- chat = await antiservicedb.find_one({"chat_id": chat_id})
- return not chat
-
-
-async def antiservice_on(chat_id: int):
- is_antiservice = await is_antiservice_on(chat_id)
- if is_antiservice:
- return
- return await antiservicedb.delete_one({"chat_id": chat_id})
-
-
-async def antiservice_off(chat_id: int):
- is_antiservice = await is_antiservice_on(chat_id)
- if not is_antiservice:
- return
- return await antiservicedb.insert_one({"chat_id": chat_id})
-
-
-async def is_pmpermit_approved(user_id: int) -> bool:
- user = pmpermitdb.find_one({"user_id": user_id})
- return bool(user)
-
-
-async def approve_pmpermit(user_id: int):
- is_pmpermit = await is_pmpermit_approved(user_id)
- if is_pmpermit:
- return
- return pmpermitdb.insert_one({"user_id": user_id})
-
-
-async def disapprove_pmpermit(user_id: int):
- is_pmpermit = await is_pmpermit_approved(user_id)
- if not is_pmpermit:
- return
- return pmpermitdb.delete_one({"user_id": user_id})
-
-
-async def get_welcome(chat_id: int) -> str:
- text = await welcomedb.find_one({"chat_id": chat_id})
- return text["text"] if text else ""
-
-
-async def set_welcome(chat_id: int, text: str):
- return await welcomedb.update_one(
- {"chat_id": chat_id}, {"$set": {"text": text}}, upsert=True
- )
-
-
-async def del_welcome(chat_id: int):
- return await welcomedb.delete_one({"chat_id": chat_id})
-
-
-async def update_captcha_cache(captcha_dict):
- pickle = obj_to_str(captcha_dict)
- captcha_cachedb.delete_one({"captcha": "cache"})
- if not pickle:
- return
- captcha_cachedb.update_one(
- {"captcha": "cache"},
- {"$set": {"pickled": pickle}},
- upsert=True,
- )
-
-
-async def get_captcha_cache():
- cache = captcha_cachedb.find_one({"captcha": "cache"})
- return str_to_obj(cache["pickled"]) if cache else []
-
-
-async def get_blacklist_filters_count() -> dict:
- chats = blacklist_filtersdb.find({"chat_id": {"$lt": 0}})
- if not chats:
- return {"chats_count": 0, "filters_count": 0}
- chats_count = 0
- filters_count = 0
- for chat in await chats.to_list(length=1000000000):
- filters = await get_blacklisted_words(chat["chat_id"])
- filters_count += len(filters)
- chats_count += 1
- return {
- "chats_count": chats_count,
- "filters_count": filters_count,
- }
-
-
-async def get_blacklisted_words(chat_id: int) -> List[str]:
- _filters = await blacklist_filtersdb.find_one({"chat_id": chat_id})
- return _filters["filters"] if _filters else []
-
-
-async def save_blacklist_filter(chat_id: int, word: str):
- word = word.lower().strip()
- _filters = await get_blacklisted_words(chat_id)
- _filters.append(word)
- await blacklist_filtersdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"filters": _filters}},
- upsert=True,
- )
-
-
-async def delete_blacklist_filter(chat_id: int, word: str) -> bool:
- filtersd = await get_blacklisted_words(chat_id)
- word = word.lower().strip()
- if word in filtersd:
- filtersd.remove(word)
- await blacklist_filtersdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"filters": filtersd}},
- upsert=True,
- )
- return True
- return False
-
-
-async def activate_pipe(from_chat_id: int, to_chat_id: int, fetcher: str):
- pipes = await show_pipes()
- pipe = {
- "from_chat_id": from_chat_id,
- "to_chat_id": to_chat_id,
- "fetcher": fetcher,
- }
- pipes.append(pipe)
- return await pipesdb.update_one(
- {"pipe": "pipe"}, {"$set": {"pipes": pipes}}, upsert=True
- )
-
-
-async def deactivate_pipe(from_chat_id: int, to_chat_id: int):
- pipes = await show_pipes()
- if not pipes:
- return
- for pipe in pipes:
- if pipe["from_chat_id"] == from_chat_id and pipe["to_chat_id"] == to_chat_id:
- pipes.remove(pipe)
- return await pipesdb.update_one(
- {"pipe": "pipe"}, {"$set": {"pipes": pipes}}, upsert=True
- )
-
-
-async def is_pipe_active(from_chat_id: int, to_chat_id: int) -> bool:
- for pipe in await show_pipes():
- if pipe["from_chat_id"] == from_chat_id and pipe["to_chat_id"] == to_chat_id:
- return True
-
-
-async def show_pipes() -> list:
- pipes = await pipesdb.find_one({"pipe": "pipe"})
- return pipes["pipes"] if pipes else []
-
-
-async def get_sudoers() -> list:
- sudoers = await sudoersdb.find_one({"sudo": "sudo"})
- return sudoers["sudoers"] if sudoers else []
-
-
-async def add_sudo(user_id: int) -> bool:
- sudoers = await get_sudoers()
- sudoers.append(user_id)
- await sudoersdb.update_one(
- {"sudo": "sudo"}, {"$set": {"sudoers": sudoers}}, upsert=True
- )
- return True
-
-
-async def remove_sudo(user_id: int) -> bool:
- sudoers = await get_sudoers()
- sudoers.remove(user_id)
- await sudoersdb.update_one(
- {"sudo": "sudo"}, {"$set": {"sudoers": sudoers}}, upsert=True
- )
- return True
-
-
-async def blacklisted_chats() -> list:
- chats = blacklist_chatdb.find({"chat_id": {"$lt": 0}})
- return [chat["chat_id"] for chat in await chats.to_list(length=1000000000)]
-
-
-async def blacklist_chat(chat_id: int) -> bool:
- if not await blacklist_chatdb.find_one({"chat_id": chat_id}):
- await blacklist_chatdb.insert_one({"chat_id": chat_id})
- return True
- return False
-
-
-async def whitelist_chat(chat_id: int) -> bool:
- if await blacklist_chatdb.find_one({"chat_id": chat_id}):
- await blacklist_chatdb.delete_one({"chat_id": chat_id})
- return True
- return False
-
-
-async def start_restart_stage(chat_id: int, message_id: int):
- await restart_stagedb.update_one(
- {"something": "something"},
- {
- "$set": {
- "chat_id": chat_id,
- "message_id": message_id,
- }
- },
- upsert=True,
- )
-
-
-async def clean_restart_stage() -> dict:
- data = await restart_stagedb.find_one({"something": "something"})
- if not data:
- return {}
- await restart_stagedb.delete_one({"something": "something"})
- return {
- "chat_id": data["chat_id"],
- "message_id": data["message_id"],
- }
-
-
-async def is_flood_on(chat_id: int) -> bool:
- chat = await flood_toggle_db.find_one({"chat_id": chat_id})
- return not chat
-
-
-async def flood_on(chat_id: int):
- is_flood = await is_flood_on(chat_id)
- if is_flood:
- return
- return await flood_toggle_db.delete_one({"chat_id": chat_id})
-
-
-async def flood_off(chat_id: int):
- is_flood = await is_flood_on(chat_id)
- if not is_flood:
- return
- return await flood_toggle_db.insert_one({"chat_id": chat_id})
-
-
-async def add_rss_feed(chat_id: int, url: str, last_title: str):
- return await rssdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"url": url, "last_title": last_title}},
- upsert=True,
- )
-
-
-# @AshokShau
-async def remove_rss_feed(chat_id: int):
- return await rssdb.delete_one({"chat_id": chat_id})
-
-
-async def update_rss_feed(chat_id: int, last_title: str):
- return await rssdb.update_one(
- {"chat_id": chat_id},
- {"$set": {"last_title": last_title}},
- upsert=True,
- )
-
-
-async def is_rss_active(chat_id: int) -> bool:
- return await rssdb.find_one({"chat_id": chat_id})
-
-
-async def get_rss_feeds() -> list:
- feeds = rssdb.find({"chat_id": {"$exists": 1}})
- feeds = await feeds.to_list(length=10000000)
- if not feeds:
- return
- return [
- dict(
- chat_id=feed["chat_id"],
- url=feed["url"],
- last_title=feed["last_title"],
- )
- for feed in feeds
- ]
-
-
-async def get_rss_feeds_count() -> int:
- feeds = rssdb.find({"chat_id": {"$exists": 1}})
- feeds = await feeds.to_list(length=10000000)
- return len(feeds)
diff --git a/Exon/utils/errors.py b/Exon/utils/errors.py
deleted file mode 100644
index 56d41b5d..00000000
--- a/Exon/utils/errors.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import sys
-import traceback
-from functools import wraps
-
-from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
-
-from Exon import SUPPORT_CHAT, Abishnoi
-
-
-def split_limits(text):
- if len(text) < 2048:
- return [text]
-
- lines = text.splitlines(True)
- small_msg = ""
- result = []
- for line in lines:
- if len(small_msg) + len(line) < 2048:
- small_msg += line
- else:
- result.append(small_msg)
- small_msg = line
-
- result.append(small_msg)
-
- return result
-
-
-def capture_err(func):
- @wraps(func)
- async def capture(client, message, *args, **kwargs):
- try:
- return await func(client, message, *args, **kwargs)
- except ChatWriteForbidden:
- await Abishnoi.leave_chat(message.chat.id)
- return
- except Exception as err:
- exc_type, exc_obj, exc_tb = sys.exc_info()
- errors = traceback.format_exception(
- etype=exc_type,
- value=exc_obj,
- tb=exc_tb,
- )
- error_feedback = split_limits(
- "**ᴇʀʀᴏʀ** | `{}` | `{}`\n\n```{}```\n\n```{}```\n".format(
- message.from_user.id if message.from_user else 0,
- message.chat.id if message.chat else 0,
- message.text or message.caption,
- "".join(errors),
- ),
- )
- for x in error_feedback:
- await Abishnoi.send_message(SUPPORT_CHAT, x)
- raise err
-
- return capture
diff --git a/Exon/utils/exceptions.py b/Exon/utils/exceptions.py
deleted file mode 100644
index 792afee5..00000000
--- a/Exon/utils/exceptions.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-
-class CancelProcess(Exception):
- """
- Cancel Process
- """
diff --git a/Exon/utils/fetch.py b/Exon/utils/fetch.py
deleted file mode 100644
index 093cdb16..00000000
--- a/Exon/utils/fetch.py
+++ /dev/null
@@ -1,39 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from Exon import aiohttpsession
-
-headers = {
- "Accept": "application/json",
- "Content-Type": "application/json",
-}
-
-
-async def fetch(url: str):
- async with aiohttpsession.get(url, headers=headers) as resp:
- try:
- data = await resp.json()
- except Exception:
- data = await resp.text()
- return data
diff --git a/Exon/utils/formatter.py b/Exon/utils/formatter.py
deleted file mode 100644
index 9627d63e..00000000
--- a/Exon/utils/formatter.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-
-def get_readable_time(seconds: int) -> str:
- count = 0
- ping_time = ""
- time_list = []
- time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"]
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
- for i in range(len(time_list)):
- time_list[i] = str(time_list[i]) + time_suffix_list[i]
- if len(time_list) == 4:
- ping_time += f"{time_list.pop()}, "
- time_list.reverse()
- ping_time += ":".join(time_list)
- return ping_time
-
-
-# Convert seconds to mm:ss @AbishnoiMF
-async def convert_seconds_to_minutes(seconds: int):
- seconds = seconds
- seconds %= 24 * 3600
- seconds %= 3600
- minutes = seconds // 60
- seconds %= 60
- return "%02d:%02d" % (minutes, seconds)
diff --git a/Exon/utils/functions.py b/Exon/utils/functions.py
deleted file mode 100644
index 38b20a18..00000000
--- a/Exon/utils/functions.py
+++ /dev/null
@@ -1,332 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import codecs
-import pickle
-from asyncio import gather, get_running_loop
-from datetime import datetime, timedelta
-from math import atan2, cos, radians, sin, sqrt
-from os import execvp
-from random import randint
-from re import findall
-from re import sub as re_sub
-from sys import executable
-
-import aiofiles
-import aiohttp
-import speedtest
-from PIL import Image, ImageDraw, ImageFilter, ImageFont
-from carbonnow import Carbon
-from pyrogram.types import Message
-from wget import download
-
-from Exon.utils import aiodownloader
-from Exon.utils.dbfunctions import start_restart_stage
-from Exon.utils.fetch import fetch
-
-"""
-Just import 'downloader' anywhere and do downloader.download() to
-download file from a given url
-"""
-downloader = aiodownloader.Handler()
-
-
-# Another downloader, but with wget
-
-
-async def restart(m: Message):
- if m:
- await start_restart_stage(m.chat.id, m.message_id)
- execvp(executable, [executable, "-m", "Exon"])
-
-
-async def download_url(url: str):
- loop = get_running_loop()
- return await loop.run_in_executor(None, download, url)
-
-
-def generate_captcha():
- # Generate one letter
- def gen_letter():
- return chr(randint(65, 90))
-
- def rndColor():
- return (randint(64, 255), randint(64, 255), randint(64, 255))
-
- def rndColor2():
- return (randint(32, 127), randint(32, 127), randint(32, 127))
-
- # Generate a 4 letter word
- def gen_wrong_answer():
- return "".join(gen_letter() for _ in range(4))
-
- # Generate 8 wrong captcha answers
- wrong_answers = []
- for _ in range(8):
- wrong_answers.append(gen_wrong_answer())
-
- width = 80 * 4
- height = 100
- correct_answer = ""
- font = ImageFont.truetype("assets/arial.ttf", 55)
- file = f"assets/{randint(1000, 9999)}.jpg"
- image = Image.new("RGB", (width, height), (255, 255, 255))
- draw = ImageDraw.Draw(image)
-
- # Draw random points on image
- for x in range(width):
- for y in range(height):
- draw.point((x, y), fill=rndColor())
-
- for t in range(4):
- letter = gen_letter()
- correct_answer += letter
- draw.text((60 * t + 50, 15), letter, font=font, fill=rndColor2())
- image = image.filter(ImageFilter.BLUR)
- image.save(file, "jpeg")
- return [file, correct_answer, wrong_answers]
-
-
-def test_speedtest():
- def speed_convert(size):
- power = 2 ** 10
- zero = 0
- units = {0: "", 1: "Kb/s", 2: "Mb/s", 3: "Gb/s", 4: "Tb/s"}
- while size > power:
- size /= power
- zero += 1
- return f"{round(size, 2)} {units[zero]}"
-
- speed = speedtest.Speedtest()
- info = speed.get_best_server()
- download = speed.download()
- upload = speed.upload()
- return [speed_convert(download), speed_convert(upload), info]
-
-
-async def file_size_from_url(url: str) -> int:
- async with aiohttp.ClientSession() as session, session.head(url) as resp:
- size = int(resp.headers["content-length"])
- return size
-
-
-async def get_http_status_code(url: str) -> int:
- async with aiohttp.ClientSession() as session, session.head(url) as resp:
- return resp.status
-
-
-async def make_carbon(code):
- carbon = Carbon(code=code)
- return await carbon.save(str(randint(1000, 10000)))
-
-
-async def transfer_sh(file):
- async with aiofiles.open(file, "rb") as f:
- params = {file: await f.read()}
- async with aiohttp.ClientSession() as session, session.post(
- "https://transfer.sh/", data=params
- ) as resp:
- download_link = str(await resp.text()).strip()
- return download_link
-
-
-def obj_to_str(object):
- if not object:
- return False
- return codecs.encode(pickle.dumps(object), "base64").decode()
-
-
-def str_to_obj(string: str):
- return pickle.loads(codecs.decode(string.encode(), "base64"))
-
-
-async def calc_distance_from_ip(ip1: str, ip2: str) -> float:
- Radius_Earth = 6371.0088
- data1, data2 = await gather(
- fetch(f"http://ipinfo.io/{ip1}"), fetch(f"http://ipinfo.io/{ip2}")
- )
- lat1, lon1 = data1["loc"].split(",")
- lat2, lon2 = data2["loc"].split(",")
- lat1, lon1 = radians(float(lat1)), radians(float(lon1))
- lat2, lon2 = radians(float(lat2)), radians(float(lon2))
- dlon = lon2 - lon1
- dlat = lat2 - lat1
- a = sin(dlat / 2) ** 2 + cos(lat1) * cos(lat2) * sin(dlon / 2) ** 2
- c = 2 * atan2(sqrt(a), sqrt(1 - a))
- return Radius_Earth * c
-
-
-def get_urls_from_text(text: str) -> bool:
- regex = r"""(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]
- [.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(
- \([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\
- ()<>]+\)))*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’]))""".strip()
- return [x[0] for x in findall(regex, text)]
-
-
-async def time_converter(message: Message, time_value: str) -> int:
- unit = ["m", "h", "d"] # m == minutes | h == hours | d == days
- check_unit = "".join(list(filter(time_value[-1].lower().endswith, unit)))
- currunt_time = datetime.now()
- time_digit = time_value[:-1]
- if not time_digit.isdigit():
- return await message.reply_text("Incorrect time specified")
- if check_unit == "m":
- temp_time = currunt_time + timedelta(minutes=int(time_digit))
- elif check_unit == "h":
- temp_time = currunt_time + timedelta(hours=int(time_digit))
- elif check_unit == "d":
- temp_time = currunt_time + timedelta(days=int(time_digit))
- else:
- return await message.reply_text("Incorrect time specified.")
- return int(datetime.timestamp(temp_time))
-
-
-async def extract_userid(message, text: str):
- """
- NOT TO BE USED OUTSIDE THIS FILE
- """
-
- def is_int(text: str):
- try:
- int(text)
- except ValueError:
- return False
- return True
-
- text = text.strip()
-
- if is_int(text):
- return int(text)
-
- entities = message.entities
- app = message._client
- if len(entities) < 2:
- return (await app.get_users(text)).id
- entity = entities[1]
- if entity.type == "mention":
- return (await app.get_users(text)).id
- return entity.user.id if entity.type == "text_mention" else None
-
-
-async def extract_user_and_reason(message):
- args = message.text.strip().split()
- text = message.text
- user = None
- reason = None
- if message.reply_to_message:
- reply = message.reply_to_message
- # if reply to a message and no reason is given
- if not reply.from_user:
- return None, None
- reason = None if len(args) < 2 else text.split(None, 1)[1]
- return reply.from_user.id, reason
-
- # if not reply to a message and no reason is given
- if len(args) == 2:
- user = text.split(None, 1)[1]
- return await extract_userid(message, user), None
-
- # if reason is given
- if len(args) > 2:
- user, reason = text.split(None, 2)[1:]
- return await extract_userid(message, user), reason
-
- return user, reason
-
-
-async def extract_user(message):
- return (await extract_user_and_reason(message))[0]
-
-
-def get_file_id_from_message(
- message,
- max_file_size=3145728,
- mime_types=None,
-):
- if mime_types is None:
- mime_types = ["image/png", "image/jpeg"]
- file_id = None
- if message.document:
- if int(message.document.file_size) > max_file_size:
- return
-
- mime_type = message.document.mime_type
-
- if mime_types and mime_type not in mime_types:
- return
- file_id = message.document.file_id
-
- if message.sticker:
- if message.sticker.is_animated:
- if not message.sticker.thumbs:
- return
- file_id = message.sticker.thumbs[0].file_id
- else:
- file_id = message.sticker.file_id
-
- if message.photo:
- file_id = message.photo.file_id
-
- if message.animation:
- if not message.animation.thumbs:
- return
- file_id = message.animation.thumbs[0].file_id
-
- if message.video:
- if not message.video.thumbs:
- return
- file_id = message.video.thumbs[0].file_id
- return file_id
-
-
-def extract_text_and_keyb(ikb, text: str, row_width: int = 2):
- keyboard = {}
- try:
- text = text.strip()
- text = text.removeprefix("`")
- text = text.removesuffix("`")
- text, keyb = text.split("~")
-
- keyb = findall(r"\[.+\,.+\]", keyb)
- for btn_str in keyb:
- btn_str = re_sub(r"[\[\]]", "", btn_str)
- btn_str = btn_str.split(",")
- btn_txt, btn_url = btn_str[0], btn_str[1].strip()
-
- if not get_urls_from_text(btn_url):
- continue
- keyboard[btn_txt] = btn_url
- keyboard = ikb(keyboard, row_width)
- except Exception:
- return
- return text, keyboard
-
-
-async def get_user_id_and_usernames(client) -> dict:
- with client.storage.lock, client.storage.conn:
- users = client.storage.conn.execute(
- 'SELECT * FROM peers WHERE type in ("user", "bot") AND username NOT null'
- ).fetchall()
- return {user[0]: user[3] for user in users}
diff --git a/Exon/utils/http.py b/Exon/utils/http.py
deleted file mode 100644
index 3d549da1..00000000
--- a/Exon/utils/http.py
+++ /dev/null
@@ -1,74 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from asyncio import gather
-
-from Exon import aiohttpsession as session
-
-
-async def get(url: str, *args, **kwargs):
- async with session.get(url, *args, **kwargs) as resp:
- try:
- data = await resp.json()
- except Exception:
- data = await resp.text()
- return data
-
-
-async def head(url: str, *args, **kwargs):
- async with session.head(url, *args, **kwargs) as resp:
- try:
- data = await resp.json()
- except Exception:
- data = await resp.text()
- return data
-
-
-async def post(url: str, *args, **kwargs):
- async with session.post(url, *args, **kwargs) as resp:
- try:
- data = await resp.json()
- except Exception:
- data = await resp.text()
- return data
-
-
-async def multiget(url: str, times: int, *args, **kwargs):
- return await gather(*[get(url, *args, **kwargs) for _ in range(times)])
-
-
-async def multihead(url: str, times: int, *args, **kwargs):
- return await gather(*[head(url, *args, **kwargs) for _ in range(times)])
-
-
-async def multipost(url: str, times: int, *args, **kwargs):
- return await gather(*[post(url, *args, **kwargs) for _ in range(times)])
-
-
-async def resp_get(url: str, *args, **kwargs):
- return await session.get(url, *args, **kwargs)
-
-
-async def resp_post(url: str, *args, **kwargs):
- return await session.post(url, *args, **kwargs)
diff --git a/Exon/utils/keyboard.py b/Exon/utils/keyboard.py
deleted file mode 100644
index a8147563..00000000
--- a/Exon/utils/keyboard.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from pykeyboard import InlineKeyboard
-from pyrogram.types import InlineKeyboardButton as Ikb
-
-from Exon.utils.functions import get_urls_from_text as is_url
-
-
-def keyboard(buttons_list, row_width: int = 2):
- """
- Buttons builder, pass buttons in a list and it will
- return pyrogram.types.IKB object
- Ex: keyboard([["click here", "https://google.com"]])
- if theres, a url, it will make url button, else callback button
- """
- buttons = InlineKeyboard(row_width=row_width)
- data = [
- (
- Ikb(text=str(i[0]), url=str(i[1])) if is_url(i[1]) else Ikb(text=str(i[0]), callback_data=str(i[1]))
- )
- for i in buttons_list
- ]
- buttons.add(*data)
- return buttons
-
-
-def ikb(data: dict, row_width: int = 2):
- """
- Converts a dict to pyrogram buttons
- Ex: dict_to_keyboard({"click here": "this is callback data"})
- """
- return keyboard(data.items(), row_width=row_width)
diff --git a/Exon/utils/pastebin.py b/Exon/utils/pastebin.py
deleted file mode 100644
index e97fc9e6..00000000
--- a/Exon/utils/pastebin.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import base64
-import json
-import socket
-import typing
-import zlib
-from asyncio import get_running_loop
-from functools import partial
-from urllib.parse import urljoin, urlparse, urlunparse
-
-import base58
-import requests
-from Crypto import Hash, Protocol, Random
-from Crypto.Cipher import AES
-
-from Exon.utils.http import post
-
-headers = {
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36",
- "content-type": "application/json",
-}
-
-BASE = "https://batbin.me/"
-
-
-def _netcat(host, port, content):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.connect((host, port))
- s.sendall(content.encode())
- s.shutdown(socket.SHUT_WR)
- while True:
- if data := s.recv(4096).decode("utf-8").strip("\n\x00"):
- return data
- else:
- break
- s.close()
-
-
-async def paste(content):
- loop = get_running_loop()
- return await loop.run_in_executor(
- None, partial(_netcat, "ezup.dev", 9999, content)
- )
-
-
-async def hpaste(content: str):
- resp = await post(f"{BASE}api/v2/paste", data=content)
- if not resp["success"]:
- return
- return BASE + resp["message"]
-
-
-def upload_text(data: str) -> typing.Optional[str]:
- passphrase = Random.get_random_bytes(32)
- salt = Random.get_random_bytes(8)
- key = Protocol.KDF.PBKDF2(
- passphrase, salt, 32, 100000, hmac_hash_module=Hash.SHA256
- )
- compress = zlib.compressobj(wbits=-15)
- paste_blob = (
- compress.compress(json.dumps({"paste": data}, separators=(",", ":")).encode())
- + compress.flush()
- )
- cipher = AES.new(key, AES.MODE_GCM)
- paste_meta = [
- [
- base64.b64encode(cipher.nonce).decode(),
- base64.b64encode(salt).decode(),
- 100000,
- 256,
- 128,
- "aes",
- "gcm",
- "zlib",
- ],
- "syntaxhighlighting",
- 0,
- 0,
- ]
- cipher.update(json.dumps(paste_meta, separators=(",", ":")).encode())
- ct, tag = cipher.encrypt_and_digest(paste_blob)
- resp = requests.post(
- "https://bin.nixnet.services",
- headers={"X-Requested-With": "JSONHttpRequest"},
- data=json.dumps(
- {
- "v": 2,
- "adata": paste_meta,
- "ct": base64.b64encode(ct + tag).decode(),
- "meta": {"expire": "1week"},
- },
- separators=(",", ":"),
- ),
- )
- data = resp.json()
- url = list(urlparse(urljoin("https://bin.nixnet.services", data["url"])))
- url[5] = base58.b58encode(passphrase).decode()
- return urlunparse(url)
diff --git a/Exon/utils/permissions.py b/Exon/utils/permissions.py
deleted file mode 100644
index d16e2a2c..00000000
--- a/Exon/utils/permissions.py
+++ /dev/null
@@ -1,84 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-from functools import wraps
-
-from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
-from pyrogram.types import Message
-
-from Exon import DRAGONS, Abishnoi
-from Exon.utils.pluginhelp import member_permissions
-
-
-async def authorised(func, subFunc2, client, message, *args, **kwargs):
- chatID = message.chat.id
- try:
- await func(client, message, *args, **kwargs)
- except ChatWriteForbidden:
- await Abishnoi.leave_chat(chatID)
- except Exception as e:
- try:
- await message.reply_text(str(e))
- except ChatWriteForbidden:
- await Abishnoi.leave_chat(chatID)
- return subFunc2
-
-
-async def unauthorised(message: Message, permission, subFunc2):
- text = f"ʏᴏᴜ ᴅᴏɴ'ᴛ ʜᴀᴠᴇ ᴛʜᴇ ʀᴇǫᴜɪʀᴇᴅ ᴘᴇʀᴍɪssɪᴏɴ ᴛᴏ ᴘᴇʀғᴏʀᴍ ᴛʜɪs ᴀᴄᴛɪᴏɴ.\n**𝐏𝐞𝐫𝐦𝐢𝐬𝐬𝐢𝐨𝐧:** __{permission}__"
- chatID = message.chat.id
- try:
- await message.reply_text(text)
- except ChatWriteForbidden:
- await Abishnoi.leave_chat(chatID)
- return subFunc2
-
-
-def adminsOnly(permission):
- def subFunc(func):
- @wraps(func)
- async def subFunc2(client, message: Message, *args, **kwargs):
- chatID = message.chat.id
- if not message.from_user:
- # For anonymous admins
- if message.sender_chat and message.sender_chat.id == message.chat.id:
- return await authorised(
- func,
- subFunc2,
- client,
- message,
- *args,
- **kwargs,
- )
- return await unauthorised(message, permission, subFunc2)
- # For admins and sudo users
- userID = message.from_user.id
- permissions = await member_permissions(chatID, userID)
- if userID not in DRAGONS and permission not in permissions:
- return await unauthorised(message, permission, subFunc2)
- return await authorised(func, subFunc2, client, message, *args, **kwargs)
-
- return subFunc2
-
- return subFunc
diff --git a/Exon/utils/pluginhelp.py b/Exon/utils/pluginhelp.py
deleted file mode 100644
index 091ed6cd..00000000
--- a/Exon/utils/pluginhelp.py
+++ /dev/null
@@ -1,365 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import asyncio
-import math
-import shlex
-import sys
-import time
-import traceback
-from functools import wraps
-from typing import Callable, Coroutine, Dict, List, Tuple, Union
-
-from PIL import Image
-from pyrogram import Client
-from pyrogram.errors import FloodWait, MessageNotModified
-from pyrogram.types import Chat, Message, User
-
-from Exon import OWNER_ID, SUPPORT_CHAT, Abishnoi
-from Exon.utils.errors import split_limits
-
-
-def get_user(message: Message, text: str) -> [int, str, None]:
- asplit = None if text is None else text.split(" ", 1)
- user_s = None
- reason_ = None
- if message.reply_to_message:
- user_s = message.reply_to_message.from_user.id
- reason_ = text or None
- elif asplit is None:
- return None, None
- elif len(asplit[0]) > 0:
- user_s = int(asplit[0]) if asplit[0].isdigit() else asplit[0]
- if len(asplit) == 2:
- reason_ = asplit[1]
- return user_s, reason_
-
-
-def get_readable_time(seconds: int) -> int:
- count = 0
- ping_time = ""
- time_list = []
- time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"]
-
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
-
- for x in range(len(time_list)):
- time_list[x] = str(time_list[x]) + time_suffix_list[x]
- if len(time_list) == 4:
- ping_time += f"{time_list.pop()}, "
-
- time_list.reverse()
- ping_time += ":".join(time_list)
-
- return ping_time
-
-
-def time_formatter(milliseconds: int) -> str:
- seconds, milliseconds = divmod(milliseconds, 1000)
- minutes, seconds = divmod(seconds, 60)
- hours, minutes = divmod(minutes, 60)
- days, hours = divmod(hours, 24)
- tmp = (
- (f"{str(days)} day(s), " if days else "")
- + (f"{str(hours)} hour(s), " if hours else "")
- + (f"{str(minutes)} minute(s), " if minutes else "")
- + (f"{str(seconds)} second(s), " if seconds else "")
- + (f"{str(milliseconds)} millisecond(s), " if milliseconds else "")
- )
- return tmp[:-2]
-
-
-async def delete_or_pass(message):
- if message.from_user.id == 1141839926:
- return message
- return await message.delete()
-
-
-def humanbytes(size):
- if not size:
- return ""
- power = 2 ** 10
- raised_to_pow = 0
- dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
- while size > power:
- size /= power
- raised_to_pow += 1
- return f"{str(round(size, 2))} {dict_power_n[raised_to_pow]}B"
-
-
-async def progress(current, total, message, start, type_of_ps, file_name=None):
- now = time.time()
- diff = now - start
- if round(diff % 10.00) == 0 or current == total:
- percentage = current * 100 / total
- speed = current / diff
- elapsed_time = round(diff) * 1000
- if elapsed_time == 0:
- return
- time_to_completion = round((total - current) / speed) * 1000
- estimated_total_time = elapsed_time + time_to_completion
- progress_str = "{0}{1} {2}%\n".format(
- "".join("🔴" for _ in range(math.floor(percentage / 10))),
- "".join("🔘" for _ in range(10 - math.floor(percentage / 10))),
- round(percentage, 2),
- )
-
- tmp = progress_str + "{0} of {1}\nETA: {2}".format(
- humanbytes(current), humanbytes(total), time_formatter(estimated_total_time)
- )
- if file_name:
- try:
- await message.edit(f"{type_of_ps}\n**ғɪʟᴇ ɴᴀᴍᴇ:** `{file_name}`\n{tmp}")
- except FloodWait as e:
- await asyncio.sleep(e.x)
- except MessageNotModified:
- pass
- else:
- try:
- await message.edit(f"{type_of_ps}\n{tmp}")
- except FloodWait as e:
- await asyncio.sleep(e.x)
- except MessageNotModified:
- pass
-
-
-def get_text(message: Message) -> [None, str]:
- text_to_return = message.text
- if message.text is None:
- return None
- if " " not in text_to_return:
- return None
-
- try:
- return message.text.split(None, 1)[1]
- except IndexError:
- return None
-
-
-async def iter_chats(client):
- chats = []
- async for dialog in client.iter_dialogs():
- if dialog.chat.type in ["supergroup", "channel"]:
- chats.append(dialog.chat.id)
- return chats
-
-
-async def fetch_audio(client, message):
- time.time()
- if not message.reply_to_message:
- await message.reply("`ʀᴇᴘʟʏ ᴛᴏ ᴀ ᴠɪᴅᴇᴏ / ᴀᴜᴅɪᴏ.`")
- return
- warner_stark = message.reply_to_message
- if warner_stark.audio is None and warner_stark.video is None:
- await message.reply("`ғᴏʀᴍᴀᴛ ɴᴏᴛ sᴜᴘᴘᴏʀᴛᴇᴅ`")
- return
- if warner_stark.video:
- lel = await message.reply("`ᴠɪᴅᴇᴏ ᴅᴇᴛᴇᴄᴛᴇᴅ, ᴄᴏɴᴠᴇʀᴛɪɴɢ ᴛᴏ ᴀᴜᴅɪᴏ !`")
- warner_bros = await message.reply_to_message.download()
- stark_cmd = f"ffmpeg -i {warner_bros} -map 0:a friday.mp3"
- await runcmd(stark_cmd)
- final_warner = "friday.mp3"
- elif warner_stark.audio:
- lel = await edit_or_reply(message, "`ᴅᴏᴡɴʟᴏᴀᴅ sᴛᴀʀᴛᴇᴅ !`")
- final_warner = await message.reply_to_message.download()
- await lel.edit("`ᴀʟᴍᴏsᴛ ᴅᴏɴᴇ!`")
- await lel.delete()
- return final_warner
-
-
-async def edit_or_reply(message, text, parse_mode="md"):
- if message.from_user.id:
- if message.reply_to_message:
- kk = message.reply_to_message.message_id
- return await message.reply_text(
- text, reply_to_message_id=kk, parse_mode=parse_mode
- )
- return await message.reply_text(text, parse_mode=parse_mode)
- return await message.edit(text, parse_mode=parse_mode)
-
-
-async def runcmd(cmd: str) -> Tuple[str, str, int, int]:
- """run command in terminal"""
- args = shlex.split(cmd)
- process = await asyncio.create_subprocess_exec(
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
- )
- stdout, stderr = await process.communicate()
- return (
- stdout.decode("utf-8", "replace").strip(),
- stderr.decode("utf-8", "replace").strip(),
- process.returncode,
- process.pid,
- )
-
-
-async def convert_to_image(message, client) -> [None, str]:
- """Convert Most Media Formats To Raw Image"""
- final_path = None
- if not (
- message.reply_to_message.photo
- or message.reply_to_message.sticker
- or message.reply_to_message.media
- or message.reply_to_message.animation
- or message.reply_to_message.audio
- ):
- return None
- if message.reply_to_message.photo:
- final_path = await message.reply_to_message.download()
- elif message.reply_to_message.sticker:
- if message.reply_to_message.sticker.mime_type == "image/webp":
- final_path = "webp_to_png_s_proton.png"
- path_s = await message.reply_to_message.download()
- im = Image.open(path_s)
- im.save(final_path, "PNG")
- else:
- path_s = await client.download_media(message.reply_to_message)
- final_path = "lottie_proton.png"
- cmd = (
- f"lottie_convert.py --frame 0 -if lottie -of png {path_s} {final_path}"
- )
- await runcmd(cmd)
- elif message.reply_to_message.audio:
- thumb = message.reply_to_message.audio.thumbs[0].file_id
- final_path = await client.download_media(thumb)
- elif message.reply_to_message.video or message.reply_to_message.animation:
- final_path = "fetched_thumb.png"
- vid_path = await client.download_media(message.reply_to_message)
- await runcmd(f"ffmpeg -i {vid_path} -filter:v scale=500:500 -an {final_path}")
- return final_path
-
-
-def get_text(message: Message) -> [None, str]:
- """Extract Text From Commands"""
- text_to_return = message.text
- if message.text is None:
- return None
- if " " not in text_to_return:
- return None
-
- try:
- return message.text.split(None, 1)[1]
- except IndexError:
- return None
-
-
-# Admin check
-
-admins: Dict[str, List[User]] = {}
-
-
-def set(chat_id: Union[str, int], admins_: List[User]):
- if isinstance(chat_id, int):
- chat_id = str(chat_id)
-
- admins[chat_id] = admins_
-
-
-def get(chat_id: Union[str, int]) -> Union[List[User], bool]:
- if isinstance(chat_id, int):
- chat_id = str(chat_id)
-
- return admins[chat_id] if chat_id in admins else False
-
-
-async def get_administrators(chat: Chat) -> List[User]:
- if _get := get(chat.id):
- return _get
- set(
- chat.id,
- (member.user for member in await chat.get_member(filter="administrators")),
- )
-
- return await get_administrators(chat)
-
-
-def admins_only(func: Callable) -> Coroutine:
- async def wrapper(client: Client, message: Message):
- if message.from_user.id == OWNER_ID:
- return await func(client, message)
- admins = await get_administrators(message.chat)
- for admin in admins:
- if admin.id == message.from_user.id:
- return await func(client, message)
-
- return wrapper
-
-
-# @Mr_Dark_Prince
-def capture_err(func):
- @wraps(func)
- async def capture(client, message, *args, **kwargs):
- try:
- return await func(client, message, *args, **kwargs)
- except Exception as err:
- exc_type, exc_obj, exc_tb = sys.exc_info()
- errors = traceback.format_exception(
- etype=exc_type,
- value=exc_obj,
- tb=exc_tb,
- )
- error_feedback = split_limits(
- "**ᴇʀʀᴏʀ** | `{}` | `{}`\n\n```{}```\n\n```{}```\n".format(
- message.from_user.id if message.from_user else 0,
- message.chat.id if message.chat else 0,
- message.text or message.caption,
- "".join(errors),
- ),
- )
- for x in error_feedback:
- await Abishnoi.send_message(SUPPORT_CHAT, x)
- raise err
-
- return capture
-
-
-# @AshokShau
-
-
-async def member_permissions(chat_id, user_id):
- perms = []
- member = await Abishnoi.get_chat_member(chat_id, user_id)
- if member.can_post_messages:
- perms.append("can_post_messages")
- if member.can_edit_messages:
- perms.append("can_edit_messages")
- if member.can_delete_messages:
- perms.append("can_delete_messages")
- if member.can_restrict_members:
- perms.append("can_restrict_members")
- if member.can_promote_members:
- perms.append("can_promote_members")
- if member.can_change_info:
- perms.append("can_change_info")
- if member.can_invite_users:
- perms.append("can_invite_users")
- if member.can_pin_messages:
- perms.append("can_pin_messages")
- return perms
diff --git a/Exon/utils/pluginhelpers.py b/Exon/utils/pluginhelpers.py
deleted file mode 100644
index 97ece633..00000000
--- a/Exon/utils/pluginhelpers.py
+++ /dev/null
@@ -1,464 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import asyncio
-import math
-import shlex
-import sys
-import time
-import traceback
-from functools import wraps
-from typing import Callable, Coroutine, Dict, List, Tuple, Union
-
-import aiohttp
-from PIL import Image
-from pyrogram import Client
-from pyrogram.errors import FloodWait, MessageNotModified
-from pyrogram.types import Chat, Message, User
-
-from Exon import OWNER_ID, SUPPORT_CHAT, Abishnoi
-from Exon.utils.errors import split_limits
-
-
-def get_user(message: Message, text: str) -> [int, str, None]:
- asplit = None if text is None else text.split(" ", 1)
- user_s = None
- reason_ = None
- if message.reply_to_message:
- user_s = message.reply_to_message.from_user.id
- reason_ = text or None
- elif asplit is None:
- return None, None
- elif len(asplit[0]) > 0:
- user_s = int(asplit[0]) if asplit[0].isdigit() else asplit[0]
- if len(asplit) == 2:
- reason_ = asplit[1]
- return user_s, reason_
-
-
-async def is_admin(event, user):
- try:
- sed = await event.client.get_permissions(event.chat_id, user)
- is_mod = bool(sed.is_admin)
- except Exception:
- is_mod = False
- return is_mod
-
-
-def get_readable_time(seconds: int) -> int:
- count = 0
- ping_time = ""
- time_list = []
- time_suffix_list = ["s", "m", "h", "days"]
-
- while count < 4:
- count += 1
- remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)
- if seconds == 0 and remainder == 0:
- break
- time_list.append(int(result))
- seconds = int(remainder)
-
- for x in range(len(time_list)):
- time_list[x] = str(time_list[x]) + time_suffix_list[x]
- if len(time_list) == 4:
- ping_time += f"{time_list.pop()}, "
-
- time_list.reverse()
- ping_time += ":".join(time_list)
-
- return ping_time
-
-
-def time_formatter(milliseconds: int) -> str:
- seconds, milliseconds = divmod(milliseconds, 1000)
- minutes, seconds = divmod(seconds, 60)
- hours, minutes = divmod(minutes, 60)
- days, hours = divmod(hours, 24)
- tmp = (
- (f"{str(days)} day(s), " if days else "")
- + (f"{str(hours)} hour(s), " if hours else "")
- + (f"{str(minutes)} minute(s), " if minutes else "")
- + (f"{str(seconds)} second(s), " if seconds else "")
- + (f"{str(milliseconds)} millisecond(s), " if milliseconds else "")
- )
- return tmp[:-2]
-
-
-async def delete_or_pass(message):
- if message.from_user.id == 1141839926:
- return message
- return await message.delete()
-
-
-def humanbytes(size):
- if not size:
- return ""
- power = 2 ** 10
- raised_to_pow = 0
- dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}
- while size > power:
- size /= power
- raised_to_pow += 1
- return f"{str(round(size, 2))} {dict_power_n[raised_to_pow]}B"
-
-
-async def progress(current, total, message, start, type_of_ps, file_name=None):
- now = time.time()
- diff = now - start
- if round(diff % 10.00) == 0 or current == total:
- percentage = current * 100 / total
- speed = current / diff
- elapsed_time = round(diff) * 1000
- if elapsed_time == 0:
- return
- time_to_completion = round((total - current) / speed) * 1000
- estimated_total_time = elapsed_time + time_to_completion
- progress_str = "{0}{1} {2}%\n".format(
- "".join("🔴" for _ in range(math.floor(percentage / 10))),
- "".join("🔘" for _ in range(10 - math.floor(percentage / 10))),
- round(percentage, 2),
- )
-
- tmp = progress_str + "{0} of {1}\nETA: {2}".format(
- humanbytes(current), humanbytes(total), time_formatter(estimated_total_time)
- )
- if file_name:
- try:
- await message.edit(f"{type_of_ps}\n**File Name:** `{file_name}`\n{tmp}")
- except FloodWait as e:
- await asyncio.sleep(e.x)
- except MessageNotModified:
- pass
- else:
- try:
- await message.edit(f"{type_of_ps}\n{tmp}")
- except FloodWait as e:
- await asyncio.sleep(e.x)
- except MessageNotModified:
- pass
-
-
-def get_text(message: Message) -> [None, str]:
- text_to_return = message.text
- if message.text is None:
- return None
- if " " not in text_to_return:
- return None
-
- try:
- return message.text.split(None, 1)[1]
- except IndexError:
- return None
-
-
-async def iter_chats(client):
- chats = []
- async for dialog in client.iter_dialogs():
- if dialog.chat.type in ["supergroup", "channel"]:
- chats.append(dialog.chat.id)
- return chats
-
-
-async def fetch_audio(client, message):
- time.time()
- if not message.reply_to_message:
- await message.reply("`Reply To A Video / Audio.`")
- return
- warner_stark = message.reply_to_message
- if warner_stark.audio is None and warner_stark.video is None:
- await message.reply("`Format Not Supported`")
- return
- if warner_stark.video:
- lel = await message.reply("`Video Detected, Converting To Audio !`")
- warner_bros = await message.reply_to_message.download()
- stark_cmd = f"ffmpeg -i {warner_bros} -map 0:a friday.mp3"
- await runcmd(stark_cmd)
- final_warner = "friday.mp3"
- elif warner_stark.audio:
- lel = await edit_or_reply(message, "`Download Started !`")
- final_warner = await message.reply_to_message.download()
- await lel.edit("`Almost Done!`")
- await lel.delete()
- return final_warner
-
-
-async def edit_or_reply(message, text, parse_mode="md"):
- if message.from_user.id:
- if message.reply_to_message:
- kk = message.reply_to_message.message_id
- return await message.reply_text(
- text, reply_to_message_id=kk, parse_mode=parse_mode
- )
- return await message.reply_text(text, parse_mode=parse_mode)
- return await message.edit(text, parse_mode=parse_mode)
-
-
-async def runcmd(cmd: str) -> Tuple[str, str, int, int]:
- """run command in terminal"""
- args = shlex.split(cmd)
- process = await asyncio.create_subprocess_exec(
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
- )
- stdout, stderr = await process.communicate()
- return (
- stdout.decode("utf-8", "replace").strip(),
- stderr.decode("utf-8", "replace").strip(),
- process.returncode,
- process.pid,
- )
-
-
-async def convert_to_image(message, client) -> [None, str]:
- """Convert Most Media Formats To Raw Image"""
- final_path = None
- if not (
- message.reply_to_message.photo
- or message.reply_to_message.sticker
- or message.reply_to_message.media
- or message.reply_to_message.animation
- or message.reply_to_message.audio
- ):
- return None
- if message.reply_to_message.photo:
- final_path = await message.reply_to_message.download()
- elif message.reply_to_message.sticker:
- if message.reply_to_message.sticker.mime_type == "image/webp":
- final_path = "webp_to_png_s_proton.png"
- path_s = await message.reply_to_message.download()
- im = Image.open(path_s)
- im.save(final_path, "PNG")
- else:
- path_s = await client.download_media(message.reply_to_message)
- final_path = "lottie_proton.png"
- cmd = (
- f"lottie_convert.py --frame 0 -if lottie -of png {path_s} {final_path}"
- )
- await runcmd(cmd)
- elif message.reply_to_message.audio:
- thumb = message.reply_to_message.audio.thumbs[0].file_id
- final_path = await client.download_media(thumb)
- elif message.reply_to_message.video or message.reply_to_message.animation:
- final_path = "fetched_thumb.png"
- vid_path = await client.download_media(message.reply_to_message)
- await runcmd(f"ffmpeg -i {vid_path} -filter:v scale=500:500 -an {final_path}")
- return final_path
-
-
-def get_text(message: Message) -> [None, str]:
- """Extract Text From Commands"""
- text_to_return = message.text
- if message.text is None:
- return None
- if " " not in text_to_return:
- return None
-
- try:
- return message.text.split(None, 1)[1]
- except IndexError:
- return None
-
-
-# Admin check
-
-admins: Dict[str, List[User]] = {}
-
-
-def get(chat_id: Union[str, int]) -> Union[List[User], bool]:
- if isinstance(chat_id, int):
- chat_id = str(chat_id)
-
- return admins[chat_id] if chat_id in admins else False
-
-
-async def get_administrators(chat: Chat) -> List[User]:
- if _get := get(chat.id):
- return _get
- set(
- chat.id,
- (member.user for member in await chat.get_member(filter="administrators")),
- )
-
- return await get_administrators(chat)
-
-
-def admins_only(func: Callable) -> Coroutine:
- async def wrapper(client: Client, message: Message):
- if message.from_user.id == OWNER_ID:
- return await func(client, message)
- admins = await get_administrators(message.chat)
- for admin in admins:
- if admin.id == message.from_user.id:
- return await func(client, message)
-
- return wrapper
-
-
-# @Mr_Dark_Prince
-def capture_err(func):
- @wraps(func)
- async def capture(client, message, *args, **kwargs):
- try:
- return await func(client, message, *args, **kwargs)
- except Exception as err:
- exc_type, exc_obj, exc_tb = sys.exc_info()
- errors = traceback.format_exception(
- etype=exc_type,
- value=exc_obj,
- tb=exc_tb,
- )
- error_feedback = split_limits(
- "**ERROR** | `{}` | `{}`\n\n```{}```\n\n```{}```\n".format(
- message.from_user.id if message.from_user else 0,
- message.chat.id if message.chat else 0,
- message.text or message.caption,
- "".join(errors),
- ),
- )
- for x in error_feedback:
- await Abishnoi.send_message(SUPPORT_CHAT, x)
- raise err
-
- return capture
-
-
-# Special credits to TheHamkerCat
-
-
-async def member_permissions(chat_id, user_id):
- perms = []
- member = await Abishnoi.get_chat_member(chat_id, user_id)
- if member.can_post_messages:
- perms.append("can_post_messages")
- if member.can_edit_messages:
- perms.append("can_edit_messages")
- if member.can_delete_messages:
- perms.append("can_delete_messages")
- if member.can_restrict_members:
- perms.append("can_restrict_members")
- if member.can_promote_members:
- perms.append("can_promote_members")
- if member.can_change_info:
- perms.append("can_change_info")
- if member.can_invite_users:
- perms.append("can_invite_users")
- if member.can_pin_messages:
- perms.append("can_pin_messages")
- return perms
-
-
-async def current_chat_permissions(chat_id):
- perms = []
- perm = (await Abishnoi.get_chat(chat_id)).permissions
- if perm.can_send_messages:
- perms.append("can_send_messages")
- if perm.can_send_media_messages:
- perms.append("can_send_media_messages")
- if perm.can_send_stickers:
- perms.append("can_send_stickers")
- if perm.can_send_animations:
- perms.append("can_send_animations")
- if perm.can_send_games:
- perms.append("can_send_games")
- if perm.can_use_inline_bots:
- perms.append("can_use_inline_bots")
- if perm.can_add_web_page_previews:
- perms.append("can_add_web_page_previews")
- if perm.can_send_polls:
- perms.append("can_send_polls")
- if perm.can_change_info:
- perms.append("can_change_info")
- if perm.can_invite_users:
- perms.append("can_invite_users")
- if perm.can_pin_messages:
- perms.append("can_pin_messages")
-
- return perms
-
-
-# URL LOCK
-
-
-def get_url(message_1: Message) -> Union[str, None]:
- messages = [message_1]
-
- if message_1.reply_to_message:
- messages.append(message_1.reply_to_message)
-
- text = ""
- offset = None
- length = None
-
- for message in messages:
- if offset:
- break
-
- if message.entities:
- for entity in message.entities:
- if entity.type == "url":
- text = message.text or message.caption
- offset, length = entity.offset, entity.length
- break
-
- return None if offset in (None,) else text[offset: offset + length]
-
-
-async def fetch(url):
- async with aiohttp.ClientSession() as session, session.get(url) as resp:
- try:
- data = await resp.json()
- except Exception:
- data = await resp.text()
- return data
-
-
-async def convert_seconds_to_minutes(seconds: int):
- seconds = seconds
- seconds %= 24 * 3600
- seconds %= 3600
- minutes = seconds // 60
- seconds %= 60
- return "%02d:%02d" % (minutes, seconds)
-
-
-async def json_object_prettify(objecc):
- dicc = objecc.__dict__
- return "".join(
- f"**{key}:** `{value}`\n"
- for key, value in dicc.items()
- if key not in ["pinned_message", "photo", "_", "_client"]
- )
-
-
-async def json_prettify(data):
- output = ""
- try:
- for key, value in data.items():
- output += f"**{key}:** `{value}`\n"
- except Exception:
- for datas in data:
- for key, value in datas.items():
- output += f"**{key}:** `{value}`\n"
- output += "------------------------\n"
- return output
diff --git a/Exon/utils/progress.py b/Exon/utils/progress.py
deleted file mode 100644
index feec3d22..00000000
--- a/Exon/utils/progress.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import math
-import time
-
-from .exceptions import CancelProcess
-from .tools import humanbytes, time_formatter
-
-
-async def progress(
- current, total, gdrive, start, prog_type, file_name=None, is_cancelled=False
-):
- now = time.time()
- diff = now - start
- if is_cancelled is True:
- raise CancelProcess
-
- if round(diff % 10.00) == 0 or current == total:
- percentage = current * 100 / total
- speed = current / diff
- elapsed_time = round(diff)
- eta = round((total - current) / speed)
- if "upload" in prog_type.lower():
- status = "Uploading"
- elif "download" in prog_type.lower():
- status = "Downloading"
- else:
- status = "Unknown"
- progress_str = "`{0}` | [{1}{2}] `{3}%`".format(
- status,
- "".join("●" for _ in range(math.floor(percentage / 10))),
- "".join("○" for _ in range(10 - math.floor(percentage / 10))),
- round(percentage, 2),
- )
- tmp = (
- f"{progress_str}\n"
- f"`{humanbytes(current)} of {humanbytes(total)}"
- f" @ {humanbytes(speed)}`\n"
- f"`ETA` -> {time_formatter(eta)}\n"
- f"`Duration` -> {time_formatter(elapsed_time)}"
- )
- await gdrive.edit(f"`{prog_type}`\n\n" f"`Status`\n{tmp}")
diff --git a/Exon/utils/sections.py b/Exon/utils/sections.py
deleted file mode 100644
index d4584657..00000000
--- a/Exon/utils/sections.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2022 ABIAHNOI69
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-n = "\n"
-w = " "
-
-bold = lambda x: f"**{x}:** "
-bold_ul = lambda x: f"**--{x}:**-- "
-
-mono = lambda x: f"`{x}`{n}"
-
-
-def section(
- title: str,
- body: dict,
- indent: int = 2,
- underline: bool = False,
-) -> str:
- text = (bold_ul(title) + n) if underline else bold(title) + n
-
- for key, value in body.items():
- text += (
- indent * w
- + bold(key)
- + ((value[0] + n) if isinstance(value, list) else mono(value))
- )
- return text
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 0d5669cc..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2023 ᴍʀ. x
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/Procfile b/Procfile
deleted file mode 100644
index 36ad736e..00000000
--- a/Procfile
+++ /dev/null
@@ -1 +0,0 @@
-worker: bash start
diff --git a/SECURITY.md b/SECURITY.md
deleted file mode 100644
index daedb44a..00000000
--- a/SECURITY.md
+++ /dev/null
@@ -1,36 +0,0 @@
-## sᴇᴄᴜʀɪᴛʏ ᴘᴏʟɪᴄʏ
-
-## sᴜᴘᴘᴏʀᴛᴇᴅ ᴠᴇʀsɪᴏɴs
-
-ʙᴇʟᴏᴡ ᴛᴀʙʟᴇ shows ᴡʜɪᴄʜ ᴠᴇʀsɪᴏɴ ɪs sᴛᴀʙʟᴇ ᴀɴᴅ sᴇᴄᴜʀɪᴛʏ ᴜᴘᴅᴀᴛᴇᴅ ᴀɴᴅ ᴡʜɪᴄʜ ɪs ɴᴏᴛ
-| ᴠᴇʀsɪᴏɴ | sᴜᴘᴘᴏʀᴛᴇᴅ |
-| -------| ------------------|
-| v2.69 | :white_check_mark: |
-
-
-## ʀᴇᴘᴏʀᴛɪɴɢ ᴀ ᴠᴜʟɴᴇʀᴀʙɪʟɪᴛʏ
-
-ɪғ ʏᴏᴜ ᴡᴀɴᴛ ᴛᴏ ʀᴇᴘᴏʀᴛ ᴀ ᴍᴀᴊᴏʀ ᴏʀ ᴍɪɴᴏʀ ᴠᴜʟɴᴇʀᴀʙɪʟɪᴛʏ ғʀᴏᴍ ᴏᴜʀ ᴘʀᴏᴊᴇᴄᴛ?
-
-ғɪʀsᴛ ᴏғ ᴀʟʟ ɪɴғᴏʀᴍ ᴛʜᴇ ᴏʀɪɢɪɴᴀʟ ᴄʀᴇᴀᴛᴏʀ ᴏғ ᴛʜᴇ ᴘᴀᴄᴋᴀɢᴇ ғʀᴏᴍ PyPi
-ᴀɴᴅ ᴛʜᴇɴ ᴍᴀᴋᴇ ᴀ ɪssᴜᴇ ɪɴ ᴏᴜʀ ᴘʀᴏᴊᴇᴄᴛ.
-
-## ᴄʀᴇᴅɪᴛ ꜰᴏʀ ᴇxᴏɴ ʀᴏʙᴏᴛ
-- [ɢɪᴛʜᴜʙ](https://github.com/AshokShau)
-- [ᴛᴇʟᴇɢʀᴀᴍ](https://t.me/AshokShau)
-- [ᴄʜᴀᴛ ɢʀᴏᴜᴘ](https://t.me/AbishnoiMF)
-
-## ɪɴғᴏ
-*ᴛʜɪs ɪs ᴇxᴏɴ ʀᴏʙᴏᴛ ,ᴏᴩᴇɴ sᴏᴜʀᴄᴇ ᴛᴇʟᴇɢʀᴀᴍ ɢʀᴏᴜᴩ ᴍᴀɴᴀɢᴇᴍᴇɴᴛ ʙᴏᴛ.*
-
-ᴡʀɪᴛᴛᴇɴ ɪɴ ᴩʏᴛʜᴏɴ ᴡɪᴛʜ ᴛʜᴇ ʜᴇʟᴩ ᴏғ : [ᴛᴇʟᴇᴛʜᴏɴ](https://github.com/LonamiWebs/Telethon),
-[ᴩʏʀᴏɢʀᴀᴍ](https://github.com/pyrogram/pyrogram),
-[ᴩʏᴛʜᴏɴ-ᴛᴇʟᴇɢʀᴀᴍ-ʙᴏᴛ](https://github.com/python-telegram-bot/python-telegram-bot),
-ᴀɴᴅ ᴜsɪɴɢ [sǫʟᴀʟᴄʜᴇᴍʏ](https://www.sqlalchemy.org) ᴀɴᴅ [ᴍᴏɴɢᴏ](https://cloud.mongodb.com) ᴀs ᴅᴀᴛᴀʙᴀsᴇ.
-
-*ʜᴇʀᴇ ɪs ᴍʏ sᴏᴜʀᴄᴇ ᴄᴏᴅᴇ :* [ɢɪᴛʜᴜʙ-ʟɪɴᴋ](https://github.com/AshokShau/ExonRobot)
-
-
-ᴇxᴏɴ ʀᴏʙᴏᴛ ɪs ʟɪᴄᴇɴsᴇᴅ ᴜɴᴅᴇʀ ᴛʜᴇ [ᴍɪᴛ ʟɪᴄᴇɴsᴇ](https://github.com/AshokShau/ExonRobot/blob/master/LICENSE).
-
-© 2022 - 2023 [@ᴀʙɪsʜɴᴏɪᴍғ](https://t.me/AbishnoiMF), ᴀʟʟ ʀɪɢʜᴛs ʀᴇsᴇʀᴠᴇᴅ
diff --git a/Telegram/__init__.py b/Telegram/__init__.py
new file mode 100644
index 00000000..85785e09
--- /dev/null
+++ b/Telegram/__init__.py
@@ -0,0 +1,77 @@
+import logging
+import os
+from time import time
+
+import pytz
+from ptbmod import TelegramHandler
+from telegram import LinkPreviewOptions
+from telegram.constants import ParseMode
+from telegram.ext import Application, ApplicationBuilder, Defaults, PicklePersistence
+
+import config
+from Telegram.database import mongo
+
+logging.basicConfig(
+ format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
+ handlers=[logging.FileHandler("logs.txt"), logging.StreamHandler()],
+ level=config.LOGGER_LEVEL,
+)
+
+logging.getLogger("apscheduler").setLevel(logging.WARNING)
+logging.getLogger("httpx").setLevel(logging.ERROR)
+
+LOGGER = logging.getLogger(__name__)
+
+HELP_COMMANDS = {}
+bot_data = "bot_data.pickle"
+
+defaults = Defaults(
+ allow_sending_without_reply=True,
+ parse_mode=ParseMode.HTML,
+ link_preview_options=LinkPreviewOptions(is_disabled=True),
+ block=False,
+ tzinfo=pytz.timezone(config.TIME_ZONE),
+)
+
+
+async def post_init(app: Application) -> None:
+ """
+ Initialize the application after startup.
+
+ This function sets the bot's start time in the application data,
+ which can be used to track how long the bot has been running.
+ """
+ await mongo.connect()
+ app.bot_data["StartTime"] = time()
+
+
+async def post_shutdown(_: Application) -> None:
+ """Cleanup after shutdown.
+
+ If the bot data file exists, remove it.
+ """
+ if os.path.exists(bot_data):
+ os.remove(bot_data)
+ await mongo.close()
+
+
+application = (
+ ApplicationBuilder()
+ .token(config.TOKEN)
+ .defaults(defaults)
+ .read_timeout(80)
+ .write_timeout(60)
+ .get_updates_read_timeout(50)
+ .post_init(post_init)
+ .post_shutdown(post_shutdown)
+ .concurrent_updates(True)
+ .persistence(PicklePersistence(filepath=bot_data))
+ .arbitrary_callback_data(True)
+ .build()
+)
+
+Cmd = TelegramHandler(application).command
+Msg = TelegramHandler(application).message
+Cb = TelegramHandler(application).callback_query
+Inline = TelegramHandler(application).inline_query
+CMember = TelegramHandler(application).chat_member
diff --git a/Telegram/__main__.py b/Telegram/__main__.py
new file mode 100644
index 00000000..c97fcc8e
--- /dev/null
+++ b/Telegram/__main__.py
@@ -0,0 +1,58 @@
+import importlib
+
+from ptbmod import verifyAnonymousAdmin
+from telegram import Update
+from telegram.ext import CallbackQueryHandler
+
+from Telegram import HELP_COMMANDS, LOGGER, application
+from Telegram.modules import ALL_MODULES
+from Telegram.modules.errorHandler import error_handler
+
+
+def setup() -> None:
+ """
+ Initialize the application and load all modules.
+
+ This function imports all the modules in the modules directory, adds them to
+ HELP_COMMANDS and starts the application with polling.
+
+ Raises:
+ SystemExit: If duplicate modules are found.
+ """
+ for single in ALL_MODULES:
+ imported_module = importlib.import_module(f"Telegram.modules.{single}")
+ plugin_name = getattr(imported_module, "__mod_name__", single).lower()
+ plugin_dict_name = f"modules.{plugin_name}"
+
+ plugin_help = getattr(imported_module, "__help__", None)
+ if not plugin_help:
+ continue
+
+ if plugin_dict_name in HELP_COMMANDS:
+ raise SystemExit(f"Duplicate modules found: {plugin_dict_name}.")
+
+ HELP_COMMANDS[plugin_dict_name] = {
+ "buttons": getattr(imported_module, "__buttons__", []),
+ "alt_cmd": getattr(imported_module, "__alt_name__", []) + [plugin_name],
+ "help_msg": plugin_help,
+ }
+
+ LOGGER.info(
+ "Total Modules: %s, Loaded Help Modules: %s",
+ len(ALL_MODULES),
+ len(HELP_COMMANDS),
+ )
+
+ application.add_handler(
+ CallbackQueryHandler(verifyAnonymousAdmin, pattern=r"^anon.")
+ )
+ application.add_error_handler(error_handler)
+
+ application.run_polling(
+ drop_pending_updates=True,
+ allowed_updates=Update.ALL_TYPES,
+ )
+
+
+if __name__ == "__main__":
+ setup()
diff --git a/Telegram/database/__init__.py b/Telegram/database/__init__.py
new file mode 100644
index 00000000..34d6d605
--- /dev/null
+++ b/Telegram/database/__init__.py
@@ -0,0 +1,36 @@
+from motor.motor_asyncio import AsyncIOMotorClient
+
+from config import MONGO
+
+
+class MongoDB:
+ def __init__(self):
+ """Initialize the MongoDB client."""
+ if not MONGO:
+ raise SystemExit(
+ "MONGO environment variable is not configured. Please set it to connect to the database."
+ )
+
+ self.client = AsyncIOMotorClient(MONGO)
+ self.db = self.client.TelegramTest
+
+ async def connect(self) -> None:
+ """Check if we can connect to the database.
+
+ Raises:
+ SystemExit: If the connection to the database fails.
+ """
+ try:
+ await self.client.admin.command("ping")
+ print("Successfully connected to the database.")
+ except Exception as e:
+ raise SystemExit(f"Database connection failed: {e}") from e
+
+ async def close(self) -> None:
+ """Close the MongoDB connection."""
+ self.client.close()
+
+
+mongo = MongoDB()
+
+__all__ = ["mongo"]
diff --git a/Telegram/database/afk_db.py b/Telegram/database/afk_db.py
new file mode 100644
index 00000000..16c19027
--- /dev/null
+++ b/Telegram/database/afk_db.py
@@ -0,0 +1,73 @@
+from typing import Optional
+
+from pymongo.errors import PyMongoError
+
+from . import mongo
+from .. import LOGGER
+
+
+class AfkDB:
+ collection_name = "Afk"
+
+ def __init__(self, user_id: int) -> None:
+ self.collection = mongo.db[self.collection_name]
+ self.user_id = user_id
+
+ async def check_afk(self) -> Optional[dict]:
+ try:
+ return await self.collection.find_one({"_id": self.user_id})
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving afk for user {self.user_id}: {e}")
+ return None
+
+ async def add_afk(self, time, reason, media_type, media=None) -> bool:
+ try:
+ await self.collection.update_one(
+ {"_id": self.user_id},
+ {
+ "$set": {
+ "reason": reason,
+ "time": time,
+ "media_type": media_type,
+ "media": media,
+ }
+ },
+ upsert=True,
+ )
+ LOGGER.info(f"Afk for user {self.user_id} added or updated successfully.")
+ return True
+ except PyMongoError as e:
+ LOGGER.error(f"Error adding afk for user {self.user_id}: {e}")
+ return False
+
+ async def remove_afk(self) -> bool:
+ try:
+ result = await self.collection.delete_one({"_id": self.user_id})
+ if result.deleted_count > 0:
+ LOGGER.info(f"Afk for user {self.user_id} removed successfully.")
+ return True
+ LOGGER.warning(
+ f"Afk for user {self.user_id} delete found no matching documents."
+ )
+ return False
+ except PyMongoError as e:
+ LOGGER.error(f"Error deleting afk for user {self.user_id}: {e}")
+ return False
+
+ async def get_all_afk(self, limit: int = 100000) -> list[dict]:
+ try:
+ afk_users = await self.collection.find().limit(limit).to_list(length=limit)
+ LOGGER.info(f"Retrieved {len(afk_users)} afk users.")
+ return afk_users
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving all afk users: {e}")
+ return []
+
+ @classmethod
+ async def get_afk(cls, user_id: int) -> Optional[dict]:
+ collection = mongo.db[cls.collection_name]
+ try:
+ return await collection.find_one({"_id": user_id})
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving afk for user {user_id}: {e}")
+ return None
diff --git a/Telegram/database/antiRaid_db.py b/Telegram/database/antiRaid_db.py
new file mode 100644
index 00000000..9d7d128f
--- /dev/null
+++ b/Telegram/database/antiRaid_db.py
@@ -0,0 +1,85 @@
+from typing import Dict, Optional, Union
+
+from pymongo.errors import PyMongoError
+
+from . import mongo
+from .. import LOGGER
+
+
+class AntiRaidDB:
+ collection_name = "AntiRaid"
+
+ def __init__(self, chat_id: int) -> None:
+ self.collection = mongo.db[self.collection_name]
+ self.chat_id = chat_id
+
+ async def get_anti_raid(self) -> Dict[str, Optional[Union[str, bool]]]:
+ # Default anti-raid settings if not found in the database
+ default_settings = {
+ "raid_mode": "ban",
+ "ban_time": "30m",
+ "raid_time": "15m",
+ "anti_raid": False,
+ }
+ try:
+ anti_raid = await self.collection.find_one({"_id": self.chat_id})
+ return anti_raid or default_settings
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving anti-raid for chat {self.chat_id}: {e}")
+ return default_settings
+
+ async def set_raid_mode(
+ self, raid_mode: str
+ ) -> Dict[str, Optional[Union[str, bool]]]:
+ settings = await self.get_anti_raid()
+ settings["raid_mode"] = raid_mode
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id}, {"$set": {"raid_mode": raid_mode}}, upsert=True
+ )
+ LOGGER.info(f"Raid mode for chat {self.chat_id} set to {raid_mode}.")
+ except PyMongoError as e:
+ LOGGER.error(f"Error setting raid mode for chat {self.chat_id}: {e}")
+ return settings
+
+ async def set_ban_time(
+ self, ban_time: str
+ ) -> Dict[str, Optional[Union[str, bool]]]:
+ settings = await self.get_anti_raid()
+ settings["ban_time"] = ban_time
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id}, {"$set": {"ban_time": ban_time}}, upsert=True
+ )
+ LOGGER.info(f"Ban time for chat {self.chat_id} set to {ban_time}.")
+ except PyMongoError as e:
+ LOGGER.error(f"Error setting ban time for chat {self.chat_id}: {e}")
+ return settings
+
+ async def set_raid_time(
+ self, raid_time: str
+ ) -> Dict[str, Optional[Union[str, bool]]]:
+ settings = await self.get_anti_raid()
+ settings["raid_time"] = raid_time
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id}, {"$set": {"raid_time": raid_time}}, upsert=True
+ )
+ LOGGER.info(f"Raid time for chat {self.chat_id} set to {raid_time}.")
+ except PyMongoError as e:
+ LOGGER.error(f"Error setting raid time for chat {self.chat_id}: {e}")
+ return settings
+
+ async def set_anti_raid(
+ self, anti_raid: bool
+ ) -> Dict[str, Optional[Union[str, bool]]]:
+ settings = await self.get_anti_raid()
+ settings["anti_raid"] = anti_raid
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id}, {"$set": {"anti_raid": anti_raid}}, upsert=True
+ )
+ LOGGER.info(f"Anti-raid for chat {self.chat_id} set to {anti_raid}.")
+ except PyMongoError as e:
+ LOGGER.error(f"Error setting anti-raid for chat {self.chat_id}: {e}")
+ return settings
diff --git a/Telegram/database/chats_db.py b/Telegram/database/chats_db.py
new file mode 100644
index 00000000..a74dcd8b
--- /dev/null
+++ b/Telegram/database/chats_db.py
@@ -0,0 +1,92 @@
+from typing import Optional
+
+from pymongo.errors import PyMongoError
+
+from . import mongo
+from .. import LOGGER
+
+
+class ChatsDB:
+ collection_name = "Chats"
+
+ def __init__(self, chat_id: int) -> None:
+ """
+ Initialize the Chats class with a specific MongoDB collection.
+
+ :param chat_id: Unique identifier for the chat.
+ """
+ self.collection = mongo.db[self.collection_name]
+ self.chat_id = chat_id
+
+ async def get_chat(self) -> Optional[dict]:
+ """
+ Retrieve a single chat document by its ID.
+
+ :return: Chat document if found, otherwise None.
+ """
+ try:
+ return await self.collection.find_one({"_id": self.chat_id})
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving chat with ID {self.chat_id}: {e}")
+ return None
+
+ async def update_chat(self, title: str, username: str) -> bool:
+ """
+ Update the title and username of a specific chat, or insert if it doesn't exist.
+
+ :param title: Title of the chat.
+ :param username: Username of the chat.
+ :return: True if the operation was successful, False otherwise.
+ """
+ try:
+ result = await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"title": title, "username": username}},
+ upsert=True,
+ )
+ if result.matched_count > 0:
+ LOGGER.info(
+ f"Chat {self.chat_id} updated successfully with title '{title}' and username '{username}'."
+ )
+ else:
+ LOGGER.info(
+ f"Chat {self.chat_id} created with title '{title}' and username '{username}'."
+ )
+ return True
+ except PyMongoError as e:
+ LOGGER.error(
+ f"Error updating or inserting chat with ID {self.chat_id}: {e}"
+ )
+ return False
+
+ async def remove_chat(self) -> bool:
+ """
+ Remove a chat document by its ID.
+
+ :return: True if deletion was successful, False if no matching document was found.
+ """
+ try:
+ result = await self.collection.delete_one({"_id": self.chat_id})
+ if result.deleted_count > 0:
+ LOGGER.info(f"Chat {self.chat_id} removed successfully.")
+ return True
+ LOGGER.warning(f"No chat found for deletion with ID {self.chat_id}.")
+ return False
+ except PyMongoError as e:
+ LOGGER.error(f"Error deleting chat with ID {self.chat_id}: {e}")
+ return False
+
+ async def get_all_chats(self, limit: int = 100000) -> list[dict]:
+ """
+ Retrieve all chat documents, with an optional limit.
+
+ :param limit: Maximum number of chat documents to retrieve.
+ :return: List of chat documents.
+ """
+ try:
+ chats = await self.collection.find().limit(limit).to_list(length=limit)
+ LOGGER.info(f"Retrieved {len(chats)} chats.")
+ return chats
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving all chats: {e}")
+ return []
diff --git a/Telegram/database/locks_db.py b/Telegram/database/locks_db.py
new file mode 100644
index 00000000..ae6bde74
--- /dev/null
+++ b/Telegram/database/locks_db.py
@@ -0,0 +1,109 @@
+from typing import Union
+
+from pymongo.errors import PyMongoError
+
+from . import mongo
+from .. import LOGGER
+
+
+class LockDB:
+ collection_name = "Locks"
+
+ def __init__(self, chat_id: int) -> None:
+ self.collection = mongo.db[self.collection_name]
+ self.chat_id = chat_id
+
+ async def get_locks(self) -> dict[str, Union[list, bool]]:
+ # Default lock settings if not found in the database
+ default_settings = {"locked": [], "lock_warn": False}
+ try:
+ locks = await self.collection.find_one({"_id": self.chat_id})
+ return locks or default_settings
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving locks for chat {self.chat_id}: {e}")
+ return default_settings
+
+ async def add_lock(self, lock_type: Union[str, list[str]]) -> bool:
+ try:
+ current_locks = (await self.get_locks())["locked"]
+ if isinstance(lock_type, str):
+ lock_type = [lock_type]
+ current_locks.extend(lock_type)
+ new_locks = list(set(current_locks))
+ await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"locked": new_locks}},
+ upsert=True,
+ )
+ LOGGER.info(f"Lock(s) added for chat {self.chat_id}: {lock_type}")
+ return True
+ except PyMongoError as e:
+ LOGGER.error(f"Error adding lock(s) for chat {self.chat_id}: {e}")
+ return False
+
+ async def is_locked(self, lock_type: str) -> bool:
+ try:
+ current_locks = (await self.get_locks())["locked"]
+ return lock_type in current_locks
+ except PyMongoError as e:
+ LOGGER.error(f"Error checking lock status for chat {self.chat_id}: {e}")
+ return False
+
+ async def remove_lock(self, lock_type: Union[str, list[str]]) -> bool:
+ try:
+ current_locks = (await self.get_locks())["locked"]
+ if isinstance(lock_type, str):
+ lock_type = [lock_type]
+ new_locks = [lock for lock in current_locks if lock not in lock_type]
+ if len(new_locks) != len(current_locks):
+ await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"locked": new_locks}},
+ upsert=True,
+ )
+ LOGGER.info(f"Lock(s) removed for chat {self.chat_id}: {lock_type}")
+ return True
+ return False
+ except PyMongoError as e:
+ LOGGER.error(f"Error removing lock(s) for chat {self.chat_id}: {e}")
+ return False
+
+ async def unlock_all(self) -> bool:
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id}, {"$set": {"locked": []}}, upsert=True
+ )
+ LOGGER.info(f"All locks removed for chat {self.chat_id}.")
+ return True
+ except PyMongoError as e:
+ LOGGER.error(f"Error removing all locks for chat {self.chat_id}: {e}")
+ return False
+
+ async def set_lock_warn(self, lock_warn: bool) -> bool:
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id}, {"$set": {"lock_warn": lock_warn}}, upsert=True
+ )
+ LOGGER.info(f"Lock warn for chat {self.chat_id} set to {lock_warn}.")
+ return True
+ except PyMongoError as e:
+ LOGGER.error(f"Error setting lock warn for chat {self.chat_id}: {e}")
+ return False
+
+ async def get_lock_warn(self) -> bool:
+ try:
+ return (await self.get_locks()).get("lock_warn", False)
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving lock warn for chat {self.chat_id}: {e}")
+ return False
+
+ @classmethod
+ async def get_all_locks(cls, limit: int = 100000) -> list[dict]:
+ collection = mongo.db[cls.collection_name]
+ try:
+ locks = await collection.find().limit(limit).to_list(length=limit)
+ LOGGER.info(f"Retrieved {len(locks)} locked chats.")
+ return locks
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving all locked chats: {e}")
+ return []
diff --git a/Telegram/database/users_db.py b/Telegram/database/users_db.py
new file mode 100644
index 00000000..ac133ad4
--- /dev/null
+++ b/Telegram/database/users_db.py
@@ -0,0 +1,117 @@
+from typing import Optional, Union
+
+from pymongo.errors import PyMongoError
+
+from . import mongo
+from .. import LOGGER
+
+
+class Users:
+ collection_name = "Users"
+
+ def __init__(self, user_id: int) -> None:
+ """Initialize the Users class with a specific MongoDB collection."""
+ self.collection = mongo.db[self.collection_name]
+ self.user_id = user_id or 0
+
+ @classmethod
+ async def get_user_info(cls, user: Union[int, str]) -> Optional[dict]:
+ """
+ Retrieve user information based on user ID or username.
+
+ :param user: Either the user ID (int) or username (str).
+ :return: User document if found, otherwise None.
+ """
+ collection = mongo.db[cls.collection_name]
+
+ # Prepare the query based on user type
+ query = (
+ {"_id": user} if isinstance(user, int) else {"username": user.lstrip("@")}
+ )
+
+ try:
+ user_info = await collection.find_one(query)
+ if user_info:
+ LOGGER.info(
+ f"Retrieved user info for {'ID' if isinstance(user, int) else 'username'} '{user}'."
+ )
+ else:
+ LOGGER.warning(
+ f"No user found for {'ID' if isinstance(user, int) else 'username'} '{user}'."
+ )
+ return user_info or {}
+ except PyMongoError as e:
+ LOGGER.error(
+ f"Error retrieving user info for {'ID' if isinstance(user, int) else 'username'} '{user}': {e}"
+ )
+ return None
+
+ async def get_user(self) -> Optional[dict]:
+ """Retrieve a single user document by its ID."""
+ try:
+ return await self.collection.find_one({"_id": self.user_id})
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving user with ID {self.user_id}: {e}")
+ return None
+
+ async def update_user(
+ self, full_name: str, username: str, pm: bool = False
+ ) -> bool:
+ """
+ Update the fullName, username, and pm status of a user, or insert if it doesn't exist.
+
+ :param full_name: Full name of the user.
+ :param username: Username of the user.
+ :param pm: PM status (boolean).
+ :return: True if the operation was successful, False otherwise.
+ """
+ try:
+ result = await self.collection.update_one(
+ {"_id": self.user_id},
+ {"$set": {"fullName": full_name, "username": username, "pm": pm}},
+ upsert=True,
+ )
+ if result.matched_count > 0:
+ LOGGER.info(f"User {self.user_id} updated successfully.")
+ else:
+ LOGGER.info(
+ f"User {self.user_id} created with fullName '{full_name}', username '{username}', and pm={pm}."
+ )
+ return True
+ except PyMongoError as e:
+ LOGGER.error(
+ f"Error updating or inserting user with ID {self.user_id}: {e}"
+ )
+ return False
+
+ async def remove_user(self) -> bool:
+ """
+ Remove a user document by its ID.
+
+ :return: True if deletion was successful, False if no matching document was found.
+ """
+ try:
+ result = await self.collection.delete_one({"_id": self.user_id})
+ if result.deleted_count > 0:
+ LOGGER.info(f"User {self.user_id} removed successfully.")
+ return True
+ LOGGER.warning(f"No user found for deletion with ID {self.user_id}.")
+ return False
+ except PyMongoError as e:
+ LOGGER.error(f"Error deleting user with ID {self.user_id}: {e}")
+ return False
+
+ async def get_all_users(self, limit: int = 100000) -> list[dict]:
+ """
+ Retrieve all user documents, with an optional limit.
+
+ :param limit: Maximum number of user documents to retrieve.
+ :return: List of user documents.
+ """
+ try:
+ users = await self.collection.find().limit(limit).to_list(length=limit)
+ LOGGER.info(f"Retrieved {len(users)} users.")
+ return users
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving all users: {e}")
+ return []
diff --git a/Telegram/database/warns_db.py b/Telegram/database/warns_db.py
new file mode 100644
index 00000000..2c7add9f
--- /dev/null
+++ b/Telegram/database/warns_db.py
@@ -0,0 +1,134 @@
+from typing import Union, Dict, List
+from pymongo.errors import PyMongoError
+from . import mongo
+from .. import LOGGER
+
+
+class WarnsDB:
+ collection_name = "Warns"
+
+ def __init__(self, chat_id: int) -> None:
+ self.collection = mongo.db[self.collection_name]
+ self.chat_id = chat_id
+
+ async def get_warns(self, user_id: int) -> Dict[str, Union[List[str], int]]:
+ # Default warning data if not found in the database
+ default_data = {
+ "warns": [], # List to store warnings (e.g., reason for warning)
+ "num_warns": 0, # Count of warnings
+ "warn_limit": 5, # Maximum number of warnings before action
+ "warn_mode": "none", # The warning mode (e.g., "none", "kick", "ban")
+ }
+ try:
+ warn_data = await self.collection.find_one({"_id": self.chat_id})
+ return warn_data.get("warned_users", {}).get(user_id, default_data)
+ except PyMongoError as e:
+ LOGGER.error(
+ f"Error retrieving warns for user {user_id} in chat {self.chat_id}: {e}"
+ )
+ return default_data
+
+ async def warn_user(
+ self, user_id: int, warn_reason: str = None
+ ) -> Dict[str, Union[List[str], int]]:
+ try:
+ warn_data = await self.collection.find_one({"_id": self.chat_id}) or {
+ "warned_users": {},
+ "warn_limit": 5,
+ "warn_mode": "none",
+ }
+ user_warnings = warn_data["warned_users"].get(user_id, [])
+ user_warnings.append(warn_reason)
+ warn_data["warned_users"][user_id] = user_warnings
+
+ await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"warned_users": warn_data["warned_users"]}},
+ upsert=True,
+ )
+ LOGGER.info(
+ f"User {user_id} warned in chat {self.chat_id}. Total warns: {len(user_warnings)}"
+ )
+ return {"warns": user_warnings, "num_warns": len(user_warnings)}
+ except PyMongoError as e:
+ LOGGER.error(f"Error warning user {user_id} in chat {self.chat_id}: {e}")
+ return {"warns": [], "num_warns": 0}
+
+ async def remove_warn(self, user_id: int) -> Dict[str, Union[List[str], int]]:
+ try:
+ warn_data = await self.collection.find_one({"_id": self.chat_id}) or {
+ "warned_users": {},
+ "warn_limit": 5,
+ "warn_mode": "none",
+ }
+ user_warnings = warn_data["warned_users"].get(user_id, [])
+ if user_warnings:
+ user_warnings.pop()
+ warn_data["warned_users"][user_id] = user_warnings
+
+ await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"warned_users": warn_data["warned_users"]}},
+ upsert=True,
+ )
+ LOGGER.info(
+ f"Warn removed for user {user_id} in chat {self.chat_id}. Total warns: {len(user_warnings)}"
+ )
+ return {"warns": user_warnings, "num_warns": len(user_warnings)}
+ except PyMongoError as e:
+ LOGGER.error(
+ f"Error removing warn for user {user_id} in chat {self.chat_id}: {e}"
+ )
+ return {"warns": [], "num_warns": 0}
+
+ async def reset_warns(self, user_id: int) -> bool:
+ try:
+ warn_data = await self.collection.find_one({"_id": self.chat_id}) or {
+ "warned_users": {}
+ }
+ if user_id in warn_data["warned_users"]:
+ del warn_data["warned_users"][user_id]
+ await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"warned_users": warn_data["warned_users"]}},
+ upsert=True,
+ )
+ LOGGER.info(f"Warns reset for user {user_id} in chat {self.chat_id}.")
+ return True
+ except PyMongoError as e:
+ LOGGER.error(
+ f"Error resetting warns for user {user_id} in chat {self.chat_id}: {e}"
+ )
+ return False
+
+ async def get_warn_settings(self) -> Dict[str, Union[str, int]]:
+ # Default warning settings if not found
+ default_settings = {"warn_mode": "none", "warn_limit": 5}
+ try:
+ warn_data = await self.collection.find_one({"_id": self.chat_id})
+ return (
+ {
+ "warn_mode": warn_data.get("warn_mode", "none"),
+ "warn_limit": warn_data.get("warn_limit", 5),
+ }
+ if warn_data
+ else default_settings
+ )
+ except PyMongoError as e:
+ LOGGER.error(f"Error retrieving warn settings for chat {self.chat_id}: {e}")
+ return default_settings
+
+ async def set_warn_settings(self, warn_mode: str, warn_limit: int) -> bool:
+ try:
+ await self.collection.update_one(
+ {"_id": self.chat_id},
+ {"$set": {"warn_mode": warn_mode, "warn_limit": warn_limit}},
+ upsert=True,
+ )
+ LOGGER.info(
+ f"Warn settings updated for chat {self.chat_id}: mode={warn_mode}, limit={warn_limit}"
+ )
+ return True
+ except PyMongoError as e:
+ LOGGER.error(f"Error setting warn settings for chat {self.chat_id}: {e}")
+ return False
diff --git a/Telegram/modules/__init__.py b/Telegram/modules/__init__.py
new file mode 100644
index 00000000..48e45155
--- /dev/null
+++ b/Telegram/modules/__init__.py
@@ -0,0 +1,20 @@
+from pathlib import Path
+
+
+def all_modules():
+ """
+ Returns a sorted list of all modules in this directory.
+
+ This function iterates over all the files in the current directory,
+ and returns a sorted list of all the filenames without the .py extension
+ and excluding the __init__.py file.
+ """
+ module_dir = Path(__file__).parent
+ return [
+ f.stem
+ for f in module_dir.glob("*.py")
+ if f.is_file() and f.name != "__init__.py"
+ ]
+
+
+ALL_MODULES = sorted(all_modules())
diff --git a/Telegram/modules/admins.py b/Telegram/modules/admins.py
new file mode 100644
index 00000000..2fc9e368
--- /dev/null
+++ b/Telegram/modules/admins.py
@@ -0,0 +1,252 @@
+from ptbmod import Admins
+from ptbmod.decorator.cache import get_admin_cache_user, is_admin, load_admin_cache
+from telegram import ChatMemberAdministrator, Update
+from telegram.constants import ChatMemberStatus
+from telegram.ext import ContextTypes
+from telegram.helpers import mention_html
+
+from .. import Cmd
+from ..utils.extract_user import extract_user
+
+
+@Cmd(command="adminList")
+@Admins(permissions="can_promote_members", is_bot=True)
+async def adminList(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Gets a list of admins in a chat."""
+ chat = update.effective_chat
+ _, admins = await load_admin_cache(context.bot, chat.id)
+
+ admin_list_text = "Admins in this chat:\n\n"
+ owner_text = ""
+ admin_texts = []
+
+ for admin in admins.user_info:
+ user = admin.user
+ name = (
+ f"{user.full_name} (@{user.username})" if user.username else user.full_name
+ )
+ role = (
+ "Owner"
+ if admin.status == ChatMemberStatus.OWNER
+ else (admin.custom_title or "Admin")
+ )
+
+ if role == "Owner":
+ owner_text = f"Owner: {name}\n\n"
+ else:
+ admin_texts.append(f"• {name} - {role}")
+
+ admin_list_text += owner_text + "Admins:\n" + "\n".join(admin_texts)
+
+ await update.effective_message.reply_text(admin_list_text)
+
+
+@Cmd(command="promote")
+@Admins(permissions="can_promote_members", is_both=True)
+async def promote(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Promotes a user to admin."""
+ msg = update.effective_message
+ chat = update.effective_chat
+ user_id, name, _, custom_title = await extract_user(msg, context)
+
+ # Basic validation for the user ID
+ if not user_id:
+ await msg.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ )
+ return
+ if user_id < 0:
+ await msg.reply_text("This can only be used on regular users.")
+ return
+ if await is_admin(chat.id, user_id):
+ await msg.reply_text(
+ f"{mention_html(user_id, name)} is already an admin, so promotion isn't necessary."
+ )
+ return
+ if user_id == context.bot.id:
+ await msg.reply_text("I can't promote myself.")
+ return
+
+ # Get the bot's current admin status and permissions
+ _, bot = await get_admin_cache_user(chat.id, context.bot.id)
+
+ if bot and isinstance(bot, ChatMemberAdministrator):
+ try:
+ # Attempt to promote the user with bot's permissions
+ await chat.promote_member(
+ user_id,
+ can_manage_chat=bot.can_manage_chat,
+ can_delete_messages=bot.can_delete_messages,
+ can_delete_stories=bot.can_delete_stories,
+ can_invite_users=bot.can_invite_users,
+ can_change_info=bot.can_change_info,
+ can_pin_messages=bot.can_pin_messages,
+ can_manage_video_chats=bot.can_manage_video_chats,
+ )
+ except Exception as e:
+ await msg.reply_text(
+ "I don't have sufficient permissions to promote this user or or they may be promoted by another admin;"
+ )
+ raise e
+
+ text = f"Successfully promoted {mention_html(user_id, name)}."
+
+ # Set a custom title if provided and within character limit
+ if custom_title:
+ custom_title = custom_title[:16]
+ try:
+ await chat.set_administrator_custom_title(user_id, custom_title)
+ text += "\nCustom Title: %s
" % custom_title
+ except Exception as e:
+ await msg.reply_text("Failed to set a custom title.")
+ raise e
+
+ await msg.reply_text(text)
+ else:
+ await msg.reply_text(
+ "I am not an administrator or can't fetch my admin status."
+ )
+
+
+@Cmd(command="demote")
+@Admins(permissions="can_promote_members", is_both=True)
+async def demote(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Demotes an admin to a regular user."""
+ msg = update.effective_message
+ chat = update.effective_chat
+ user_id, name, _, _ = await extract_user(msg, context)
+
+ # Basic validation for the user ID
+ if not user_id:
+ await msg.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ )
+ return
+ if user_id < 0:
+ await msg.reply_text("This can only be used on regular users.")
+ return
+ if not await is_admin(chat.id, user_id):
+ await msg.reply_text(
+ f"{mention_html(user_id, name)} is not an admin, so demotion isn't necessary."
+ )
+ return
+ if user_id == context.bot.id:
+ await msg.reply_text("I can't demote myself.")
+ return
+
+ try:
+ await chat.promote_member(user_id, can_manage_chat=False)
+ except Exception as e:
+ await msg.reply_text(
+ "Failed to demote; I might not be the admin, or they may be promoted by another admin"
+ )
+ raise e
+
+ await msg.reply_text(f"Successfully demoted {name}.")
+
+
+@Cmd(command="setTitle")
+@Admins(permissions="can_promote_members", is_both=True)
+async def setTitle(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Sets a custom title for an admin."""
+ msg = update.effective_message
+ chat = update.effective_chat
+ user_id, name, _, custom_title = await extract_user(msg, context)
+
+ # Basic validation for the user ID
+ if not user_id:
+ await msg.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ )
+ return
+ if user_id < 0:
+ await msg.reply_text("This can only be used on regular users.")
+ return
+ if not await is_admin(chat.id, user_id):
+ await msg.reply_text(f"{name} is not an admin, so demotion isn't necessary.")
+ return
+ if user_id == context.bot.id:
+ await msg.reply_text("I can't demote myself.")
+ return
+
+ if not custom_title:
+ await msg.reply_text("You need to specify a custom title.")
+ return
+
+ title = custom_title[:16]
+ try:
+ await chat.set_administrator_custom_title(user_id, title)
+ except Exception as e:
+ raise e
+
+ await msg.reply_text(
+ f"Successfully set custom title to {title} for {mention_html(user_id, name)}"
+ )
+
+
+@Cmd(command=["inviteLink", "link"])
+@Admins(permissions="can_invite_users", is_both=True)
+async def getInviteLinks(update: Update, _: ContextTypes.DEFAULT_TYPE) -> None:
+ """Gets the invite link for a chat."""
+ chat = update.effective_chat
+ if chat.username:
+ invite_link = f"https://t.me/{chat.username}"
+ else:
+ invite_link = await chat.export_invite_link()
+
+ await update.effective_message.reply_text(f"Invite Link: {invite_link}")
+
+
+@Cmd(command=["adminCache", "reload"])
+async def adminCache(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Reloads the admin cache."""
+ chat = update.effective_chat
+ user = update.effective_user
+
+ chat_member = await chat.get_member(user.id)
+ if chat_member.status not in [
+ ChatMemberStatus.ADMINISTRATOR,
+ ChatMemberStatus.OWNER,
+ ]:
+ await update.effective_message.reply_text(
+ "You need to be an admin to use this command."
+ )
+ return
+
+ done, _ = await load_admin_cache(context.bot, chat.id, True)
+ if done:
+ await update.effective_message.reply_text("Reloaded admin cache.")
+ else:
+ await update.effective_message.reply_text("Failed to reload admin cache.")
+
+
+__help__ = """
+Description:
+This module contains commands to manage admins and their permissions in the group.
+────────────────────────
+
+User Commands:
+๏ /adminList
: Lists all the admins in the group.
+
+The Following Commands Are Admin Only:
+๏ /promote
: Promotes a user to an admin.
+๏ /demote
: Demotes an admin to a regular user.
+๏ /title
: Sets a custom title for an admin.
+๏ /link
: Gets the invite link of the group.
+๏ /reload
: Reloads the admin cache.
+
+Note: The admin list may be cached for performance reasons. Use /adminCache
to reload the cache.
+"""
+
+__mod_name__ = "Admins"
+__alt_name__ = [
+ "admin",
+ "adminList",
+ "promote",
+ "demote",
+ "title",
+ "inviteLink",
+ "link",
+ "reload",
+ "adminCache",
+]
diff --git a/Telegram/modules/afk.py b/Telegram/modules/afk.py
new file mode 100644
index 00000000..4042aa90
--- /dev/null
+++ b/Telegram/modules/afk.py
@@ -0,0 +1,171 @@
+from datetime import datetime
+from typing import Optional, Union
+
+from telegram import MessageEntity, Update
+from telegram.ext import ContextTypes, filters
+from telegram.helpers import mention_html
+
+from Telegram import Cmd, Msg
+from Telegram.database.afk_db import AfkDB
+from Telegram.database.users_db import Users
+from Telegram.utils.msg_types import Types, get_welcome_type, send_cmd
+
+
+def till_date(date):
+ """Converts date to datetime object"""
+ form = "%Y-%m-%d %H:%M:%S"
+ return datetime.strptime(date, form)
+
+
+def get_hours(hour: str):
+ """Converts time to hours, minutes and seconds"""
+ tim = hour.strip().split(":")
+ txt = ""
+ if int(tim[0]):
+ txt += f"{tim[0]} Hours "
+ if int(tim[1]):
+ txt += f"{tim[1]} Minutes "
+ if int(round(float(tim[2]))):
+ txt += f"{str(round(float(tim[2])))} Seconds"
+
+ return txt
+
+
+@Cmd(command=["afk", "brb"])
+async def afkUser(update: Update, _: ContextTypes.DEFAULT_TYPE) -> None:
+ """Sets you as AFK"""
+ user = update.effective_user
+ msg = update.effective_message
+
+ time = str(datetime.now()).rsplit(".", 1)[0]
+ reason, data_type, content = await get_welcome_type(msg)
+ await AfkDB(user.id).add_afk(time, reason, data_type, content)
+ reply = f"{mention_html(user.id, user.full_name)} is AFK."
+ if reason:
+ reply += f"\nReason: {reason}"
+ await msg.reply_text(reply)
+
+
+@Msg(filters.ChatType.GROUPS, group=2)
+async def afk_checker(
+ update: Update, context: ContextTypes.DEFAULT_TYPE
+) -> Union[(Optional[int], Optional[str])]:
+ """Checks if user is AFK"""
+ user = update.effective_user
+ chat = update.effective_chat
+ m = update.effective_message
+ bot = context.bot
+ repl = m.reply_to_message
+
+ rep_user_id = None
+ rep_user_name = None
+
+ if m.entities and m.parse_entities(
+ [MessageEntity.TEXT_MENTION, MessageEntity.MENTION],
+ ):
+ entities = m.parse_entities(
+ [MessageEntity.TEXT_MENTION, MessageEntity.MENTION],
+ )
+
+ for ent in entities:
+ if ent.type == MessageEntity.TEXT_MENTION:
+ rep_user_id = ent.user.id
+ rep_user_name = ent.user.first_name
+
+ elif ent.type == MessageEntity.MENTION:
+ userInfo = await Users.get_user_info(
+ m.text[ent.offset : ent.offset + ent.length]
+ )
+ try:
+ rep_user_id = userInfo["_id"]
+ rep_user_name = userInfo["name"]
+ except KeyError:
+ return None
+ if not rep_user_id:
+ return None
+
+ elif repl and repl.from_user:
+ rep_user_id = repl.from_user.id
+ rep_user_name = repl.from_user.first_name
+
+ is_afk = await AfkDB(user.id).check_afk()
+ is_rep_afk = await AfkDB(rep_user_id).check_afk() if rep_user_id else False
+ if is_rep_afk and rep_user_id != user:
+ con = await AfkDB.get_afk(rep_user_id)
+ time = till_date(con["time"])
+ media = con["media"]
+ media_type = con["media_type"]
+ tim_ = datetime.now() - time
+ tim_ = str(tim_).split(",")
+ tim = get_hours(tim_[-1])
+ tims = ""
+ if len(tim_) == 1:
+ tims = tim
+ elif len(tim_) == 2:
+ tims = f"{tim_[0]} {tim}"
+ reason = f"{rep_user_name} is AFK.\nSince: {tims}"
+ if con["reason"]:
+ reason += f"\nReason: {con['reason']}"
+ txt = reason
+
+ if media_type == Types.TEXT:
+ await (await send_cmd(bot, media_type))(
+ chat.id,
+ txt,
+ reply_to_message_id=m.id,
+ )
+ elif media_type in (
+ Types.STICKER,
+ Types.VIDEO_NOTE,
+ Types.CONTACT,
+ Types.ANIMATED_STICKER,
+ ):
+ await (await send_cmd(bot, media_type))(
+ chat.id, media, reply_to_message_id=m.id
+ )
+ else:
+ await (await send_cmd(bot, media_type))(
+ chat.id, media, txt, reply_to_message_id=m.id
+ )
+
+ if is_afk:
+ txt = False
+ if m.text:
+ txt = m.text.split(None, 1)[0]
+
+ if txt and txt in ["!afk", "brb", "/afk"]:
+ return None
+
+ con = await AfkDB.get_afk(user.id)
+ time = till_date(con["time"])
+ tim_ = datetime.now() - time
+ tim_ = str(tim_).split(",")
+ tim = get_hours(tim_[-1])
+ tims = ""
+ if len(tim_) == 1:
+ tims = tim
+ elif len(tim_) == 2:
+ tims = f"{tim_[0]} {tim}"
+ txt = f"{user.mention_html()} is back online\nAFK for: {tims}"
+ if con["reason"]:
+ txt += f"\nReason: {con['reason']}"
+ await m.reply_text(txt)
+
+ await AfkDB(user.id).remove_afk()
+ return
+
+
+__help__ = """
+Description:
+When someone mentions you in a chat, the user will be notified you are AFK. You can even provide a reason for going AFK, which will be provided to the user as well.
+────────────────────────
+
+User Commands:
+• /afk: This will set you offline.
+• /afk reason: This will set you offline with a reason.
+• /afk replied to a sticker/photo: This will set you offline with an image or sticker.
+• /afk replied to a sticker/photo reason: This will set you AFK with an image and reason both.
+"""
+
+__mod_name__ = "AFK"
+__alt_name__ = ["afk", "away"]
diff --git a/Telegram/modules/antiRaid.py b/Telegram/modules/antiRaid.py
new file mode 100644
index 00000000..af332448
--- /dev/null
+++ b/Telegram/modules/antiRaid.py
@@ -0,0 +1,167 @@
+import re
+
+from ptbmod import Admins
+from telegram import Update
+from telegram.ext import ContextTypes
+
+from Telegram import Cmd
+from Telegram.database.antiRaid_db import AntiRaidDB
+from Telegram.utils.formatters import create_time, tl_time
+
+
+# Remove existing job by name
+def remove_job_if_exists(name: str, context: ContextTypes.DEFAULT_TYPE) -> bool:
+ """Remove existing job by name"""
+ current_jobs = context.job_queue.get_jobs_by_name(name)
+ if not current_jobs:
+ return False
+ for job in current_jobs:
+ job.schedule_removal()
+ return True
+
+
+# Anti-raid mode timeout function
+async def raid_timeout(context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Anti-raid mode timeout function"""
+ await AntiRaidDB(context.job.chat_id).set_anti_raid(False)
+ await context.bot.send_message(
+ chat_id=context.job.chat_id, text="Anti-Raid mode has been disabled. Timeout!"
+ )
+ return None
+
+
+@Cmd(command=["autoEndRaid", "endRaid"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def raid_raidTime(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Anti-raid mode timeout function"""
+ m = update.effective_message
+ db = AntiRaidDB(update.effective_chat.id)
+ raid_db = await db.get_anti_raid()
+ args = context.args
+
+ if len(args) >= 1:
+ timeout = args[0]
+ if not re.match(r"^(\d+[dhms])+$", timeout.lower()):
+ await m.reply_text("Invalid time format! Use: 1d, 2h, 3m, or 60s.")
+ return
+
+ await db.set_raid_time(timeout)
+ await m.reply_text(f"Anti-Raid mode will be disabled after {tl_time(timeout)}")
+ if raid_time := raid_db.get("raid_time"):
+ await m.reply_text(
+ f"Anti-Raid mode will be disabled after {tl_time(raid_time)}"
+ )
+ else:
+ await m.reply_text("No raid timeout is set.")
+
+
+@Cmd(command=["raidBanTime", "raidMuteTime"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def raid_banTime(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Set raid ban time"""
+ m = update.effective_message
+ db = AntiRaidDB(update.effective_chat.id)
+ args = context.args
+
+ if len(args) >= 1:
+ banTime = args[0]
+ if not re.match(r"^(\d+[dhms])+$", banTime.lower()):
+ await m.reply_text("Invalid time format! Use: 1d, 2h, 3m, or 60s.")
+ return
+
+ await db.set_ban_time(banTime)
+ await m.reply_text(f"Raid ban time set to {tl_time(banTime)}.")
+ return
+
+ # Display current ban time if no argument is provided
+ raid_db = await db.get_anti_raid()
+ if ban_time := raid_db.get("ban_time"):
+ await m.reply_text(f"Current raid ban time is {tl_time(ban_time)}.")
+ else:
+ await m.reply_text("No raid ban time is set.")
+
+
+@Cmd(command=["raidMode", "antiRaidMode"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def raid_mode(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Set raid mode"""
+ m = update.effective_message
+ db = AntiRaidDB(update.effective_chat.id)
+ args = context.args
+
+ if len(args) >= 1:
+ mode = args[0].lower()
+
+ if mode not in ["ban", "mute"]:
+ await m.reply_text("Invalid raid mode! Use: ban or mute.")
+ return
+
+ await db.set_raid_mode(mode)
+ await m.reply_text(f"Raid mode set to {mode}.")
+ return
+
+ # Display current raid mode if no argument is provided
+ raid_db = await db.get_anti_raid()
+ if raidMode := raid_db.get("raid_mode"):
+ await m.reply_text(f"Current raid mode is {raidMode}.")
+ else:
+ await m.reply_text("No raid mode is set.")
+
+
+@Cmd(command=["raid", "antiRaid"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def raid(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Enable or disable Anti-Raid"""
+ m = update.effective_message
+ chat_id = update.effective_chat.id
+ db = AntiRaidDB(chat_id)
+ raid_db = await db.get_anti_raid()
+ args = context.args
+
+ if len(args) >= 1:
+ if args[0].lower() in ("on", "yes"):
+ time = raid_db["raid_time"]
+ duration = create_time(time)
+ job_removed = remove_job_if_exists(f"ANTI_RAID_{chat_id}", context)
+ context.job_queue.run_once(
+ raid_timeout,
+ duration,
+ name=f"ANTI_RAID_{chat_id}",
+ data=update.effective_chat.full_name,
+ chat_id=chat_id,
+ )
+ text = "Anti-Raid mode has been enabled."
+ if job_removed:
+ text += "\nPrevious job has been removed."
+ await m.reply_text(text)
+ await db.set_anti_raid(True)
+ return
+ if args[0].lower() in ("off", "no"):
+ await m.reply_text("Anti-Raid mode has been disabled.")
+ await db.set_anti_raid(False)
+ return
+ await m.reply_text("Invalid argument. Use: on or off.")
+
+ await m.reply_text(f"Anti-Raid mode is {raid_db['anti_raid']}")
+
+
+__mod_name__ = "Anti-Raid"
+__alt_name__ = ["antiRaid", "raid", "raidMode", "raidBanTime", "autoEndRaid"]
+__help__ = """
+Description:
+Some people on telegram find it entertaining to "raid" chats. During a raid, hundreds of users join a chat to spam.
+
+The antiRaid module allows you to quickly stop anyone from joining when such a raid is happening.
+All new joins will be temporarily banned for the next few hours, allowing you to wait out the spam attack until the trolls stop.
+────────────────────────
+
+- /raid [on/off]: Enable or disable Anti-Raid mode.
+- /raidMode [ban/mute]: Set the raid mode to (ban or mute).
+- /raidBanTime [time]: Set the raid ban time.
+- /autoEndRaid [time]: Set the raid timeout.
+
+Example:
+- /raid on
+- /raidMode ban
+- /raidBanTime 1h
+"""
diff --git a/Telegram/modules/bans.py b/Telegram/modules/bans.py
new file mode 100644
index 00000000..48d2b1ff
--- /dev/null
+++ b/Telegram/modules/bans.py
@@ -0,0 +1,280 @@
+import asyncio
+import re
+
+from ptbmod import Admins
+from ptbmod.decorator.cache import is_admin
+from telegram import ChatMember, ChatPermissions, Message, Update
+from telegram.ext import ContextTypes
+from telegram.helpers import mention_html
+
+from Telegram import Cmd
+from Telegram.utils.extract_user import extract_user
+from Telegram.utils.formatters import create_time, tl_time
+from Telegram.utils.misc import try_to_delete
+
+
+@Cmd(command=["ban", "dban", "tBan", "dtBan", "sBan", "stBan"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def ban(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str | None:
+ """Ban a user."""
+ chat = update.effective_chat
+ m = update.effective_message
+ reply_msg = m.reply_to_message or m
+
+ user_id, user_first_name, _, _reason = await extract_user(m, context)
+
+ if not user_id or user_id == context.bot.id or await is_admin(chat.id, user_id):
+ await m.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ if user_id is None
+ else (
+ "I can't ban myself."
+ if user_id == context.bot.id
+ else "What are you trying to do? You can't ban someone who's an admin."
+ )
+ )
+ return None
+
+ ban_time = "367d"
+ reason = ""
+
+ if _reason:
+ if match := re.match(r"([0-9]{1,})([dhms])\s*(.*)", _reason):
+ ban_time = match[1] + match[2]
+ reason = match[3] if match.lastindex > 2 else ""
+ else:
+ reason = _reason
+
+ delete = bool(m.text.startswith("/d") or m.text.startswith("!d"))
+ silent = bool(m.text.startswith("/s") or m.text.startswith("!s"))
+
+ try:
+ if user_id < 0:
+ await chat.ban_sender_chat(user_id)
+ else:
+ await chat.ban_member(user_id, until_date=create_time(ban_time))
+ except Exception as e:
+ await m.reply_text("Failed to ban;")
+ raise e
+ if delete:
+ await try_to_delete(reply_msg)
+ elif silent:
+ await asyncio.gather(try_to_delete(reply_msg), try_to_delete(m))
+ return
+
+ text = (
+ f"{mention_html(user_id, user_first_name)} was banned for {tl_time(ban_time)}."
+ + (f"\nReason: {reason}
" if reason else "")
+ )
+ await m.reply_text(text)
+ return None
+
+
+@Cmd(command=["unban", "sUnban"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def unban(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str | None:
+ """Unban a user."""
+ chat = update.effective_chat
+ m = update.effective_message
+ reply_msg = m.reply_to_message or m
+
+ user_id, user_first_name, _, _reason = await extract_user(m, context)
+
+ if not user_id or user_id == context.bot.id or await is_admin(chat.id, user_id):
+ await m.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ if user_id is None
+ else (
+ "wtf; What are you trying to do?"
+ if user_id == context.bot.id
+ else "What are you trying to do? You can't ban someone who's an admin."
+ )
+ )
+ return None
+
+ try:
+ await chat.unban_member(user_id, only_if_banned=True)
+ except Exception as e:
+ await m.reply_text("Failed to unban;")
+ raise e
+
+ delete = bool(m.text.startswith("/d") or m.text.startswith("!d"))
+ silent = bool(m.text.startswith("/s") or m.text.startswith("!s"))
+
+ if delete:
+ await try_to_delete(reply_msg)
+ elif silent:
+ await asyncio.gather(try_to_delete(reply_msg), try_to_delete(m))
+ return
+
+ text = f"{mention_html(user_id, user_first_name)} was unbanned."
+ if _reason:
+ text += f"\nReason: {_reason}
"
+ await m.reply_text(text)
+ return
+
+
+@Cmd(command=["kick", "dKick", "skick"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def kick(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Message:
+ """Kick a user."""
+ chat = update.effective_chat
+ m = update.effective_message
+ reply_msg = m.reply_to_message or m
+
+ user_id, user_first_name, _, _reason = await extract_user(m, context)
+
+ if not user_id or user_id == context.bot.id or await is_admin(chat.id, user_id):
+ return await m.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ if user_id is None
+ else (
+ "I can't kick myself."
+ if user_id == context.bot.id
+ else "What are you trying to do? You can't kick someone who's an admin."
+ )
+ )
+
+ try:
+ await chat.unban_member(user_id)
+ except Exception as e:
+ await m.reply_text("Failed to kick;")
+ raise e
+
+ delete = bool(m.text.startswith("/d") or m.text.startswith("!d"))
+ silent = bool(m.text.startswith("/s") or m.text.startswith("!s"))
+
+ if delete:
+ await try_to_delete(reply_msg)
+ elif silent:
+ await asyncio.gather(try_to_delete(reply_msg), try_to_delete(m))
+
+ text = f"{mention_html(user_id, user_first_name)} was kicked."
+ if _reason:
+ text += f"\nReason: {_reason}
"
+ await m.reply_text(text)
+
+
+@Cmd(command=["mute", "dMute", "sMute", "tMute"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def mute(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Message | None:
+ """Mute a user."""
+ chat = update.effective_chat
+ m = update.effective_message
+ reply_msg = m.reply_to_message or m
+
+ user_id, user_first_name, _, _reason = await extract_user(m, context)
+ if not user_id or user_id == context.bot.id or await is_admin(chat.id, user_id):
+ return await m.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ if user_id is None
+ else (
+ "I can't mute myself."
+ if user_id == context.bot.id
+ else "What are you trying to do? You can't mute someone who's an admin."
+ )
+ )
+
+ delete = bool(m.text.startswith("/d") or m.text.startswith("!d"))
+ silent = bool(m.text.startswith("/s") or m.text.startswith("!s"))
+
+ match = re.match(r"([0-9]{1,})([dhms])*$", _reason) if _reason else None
+ if match:
+ ban_time = match.group(0)
+ reason = _reason[match.end() :].strip()
+ else:
+ ban_time = "367d"
+ reason = _reason
+
+ try:
+ await chat.restrict_member(
+ user_id, until_date=create_time(ban_time), permissions=ChatPermissions()
+ )
+ except Exception as e:
+ await m.reply_text("Failed to mute;")
+ raise e
+
+ if delete:
+ await try_to_delete(reply_msg)
+ elif silent:
+ await asyncio.gather(try_to_delete(reply_msg), try_to_delete(m))
+ return None
+
+ text = f"{mention_html(user_id, user_first_name)} was muted for {tl_time(ban_time)}."
+ if reason:
+ text += f"\nReason: {reason}
"
+ await m.reply_text(text)
+ return None
+
+
+@Cmd(command=["unmute", "sUnmute"])
+@Admins(permissions="can_restrict_members", is_both=True)
+async def unmute(update: Update, context: ContextTypes.DEFAULT_TYPE) -> str | None:
+ """Unmute a user."""
+ chat = update.effective_chat
+ m = update.effective_message
+
+ reply_msg = m.reply_to_message or m
+
+ user_id, user_first_name, _, _reason = await extract_user(m, context)
+
+ if not user_id or user_id == context.bot.id or await is_admin(chat.id, user_id):
+ await m.reply_text(
+ "I don't know who you're talking about, you need to specify a user."
+ if user_id is None
+ else (
+ "look I can speak."
+ if user_id == context.bot.id
+ else "What are you trying to do? This user is admin so how possible is it to unmute them."
+ )
+ )
+ return None
+
+ member = await chat.get_member(int(user_id))
+ if member.status != ChatMember.RESTRICTED:
+ await m.reply_text("This user is not muted.")
+ return None
+
+ delete = bool(m.text.startswith("/d") or m.text.startswith("!d"))
+ silent = bool(m.text.startswith("/s") or m.text.startswith("!s"))
+
+ try:
+ await chat.restrict_member(
+ user_id, permissions=ChatPermissions.all_permissions()
+ )
+ except Exception as e:
+ await m.reply_text("Failed to unmute;")
+ raise e
+ if delete:
+ await try_to_delete(reply_msg)
+ elif silent:
+ await asyncio.gather(try_to_delete(reply_msg), try_to_delete(m))
+ return
+
+ text = f"Fine, {mention_html(user_id, user_first_name)} can speak again."
+ if _reason:
+ text += f"\nReason: {_reason}
"
+ await m.reply_text(text)
+ return
+
+
+__mod_name__ = "Bans"
+
+__alt_name__ = ["ban", "unban", "mute", "unmute", "kick"]
+
+__help__ = """
+Description :
+Some people need to be publicly banned; spammers, annoyances, or just trolls.
+
+This module allows you to do that easily, by exposing some common actions, so everyone will see!
+────────────────────────
+
+The Following Commands Are Admin Only :
+
+๏ /ban X time reason: Bans the user replied to or tagged.
+๏ /sBan X time : Bans the user replied or tagged and deletes your message.
+๏ /dban X time reason: Bans the user replied and deletes their message.
+๏ /mute X time reason: Mutes the user replied to or tagged.
+๏ /sMute X time : Mutes the user replied or tagged and deletes your message.
+๏ /dMute X time reason: Mutes the user replied and deletes their message.
+"""
diff --git a/Telegram/modules/bot_update.py b/Telegram/modules/bot_update.py
new file mode 100644
index 00000000..2e2ff19b
--- /dev/null
+++ b/Telegram/modules/bot_update.py
@@ -0,0 +1,73 @@
+from ptbmod.decorator.cache import load_admin_cache
+from telegram import ChatMember, InlineKeyboardButton, InlineKeyboardMarkup, Update
+from telegram.constants import ChatType
+from telegram.ext import ChatMemberHandler, ContextTypes
+
+from Telegram import CMember
+from Telegram.database.chats_db import ChatsDB
+
+
+@CMember(ChatMemberHandler.CHAT_MEMBER, group=-1)
+async def chat_member_update(
+ update: Update, context: ContextTypes.DEFAULT_TYPE
+) -> None:
+ """Update admins cache when admins are added or removed from a group."""
+ status_change = update.chat_member.difference().get("status")
+
+ if status_change is None:
+ return None
+
+ old_status, new_status = status_change
+
+ # luckily, we need do not worry about creator demote, they get promoted to admin automatically
+ if old_status == ChatMember.ADMINISTRATOR and new_status != ChatMember.OWNER:
+ await load_admin_cache(context.bot, update.effective_chat.id, True)
+ elif new_status in [ChatMember.ADMINISTRATOR, ChatMember.OWNER]:
+ await load_admin_cache(context.bot, update.effective_chat.id, True)
+
+
+@CMember(ChatMemberHandler.MY_CHAT_MEMBER, group=-1)
+async def my_chat_member_update(
+ update: Update, context: ContextTypes.DEFAULT_TYPE
+) -> None:
+ """The bot was added or removed from a group."""
+ if update.effective_chat.type not in [ChatType.GROUP, ChatType.SUPERGROUP]:
+ # we only care if we were added or removed from a group
+ return None
+
+ status_change = update.my_chat_member.difference().get("status")
+
+ if status_change is None:
+ return None
+
+ _, new_status = status_change
+ chats_db = ChatsDB(update.effective_chat.id)
+
+ if new_status in [
+ ChatMember.LEFT,
+ ChatMember.BANNED,
+ ChatMember.RESTRICTED,
+ ]:
+ await chats_db.remove_chat()
+ elif new_status in [ChatMember.ADMINISTRATOR, ChatMember.MEMBER]:
+ chat = update.effective_chat
+
+ await chats_db.update_chat(chat.title, chat.username)
+ await load_admin_cache(context.bot, update.effective_chat.id)
+
+ keyboard = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="Oᴘᴇɴ Hᴇʟᴘ",
+ url=f"t.me/{context.bot.username}?start=start_help",
+ ),
+ ],
+ ],
+ )
+
+ return await context.bot.send_message(
+ chat.id,
+ f"ᴡᴇʟᴄᴏᴍᴇ {context.bot.first_name} !\n\nCheck out the help for more information on how best to protect your groups.",
+ reply_markup=keyboard,
+ )
diff --git a/Telegram/modules/devs.py b/Telegram/modules/devs.py
new file mode 100644
index 00000000..e40cf85c
--- /dev/null
+++ b/Telegram/modules/devs.py
@@ -0,0 +1,188 @@
+import html
+import inspect
+import io
+import os
+import re
+import subprocess as sub
+import sys
+import traceback
+import uuid
+from html import escape
+from sys import executable
+from typing import Any, List, Optional, Tuple, cast
+
+import telegram
+from meval import meval
+from ptbmod import Admins
+from telegram import Message, Update
+from telegram.ext import ContextTypes
+
+from Telegram import LOGGER, Cmd
+
+
+@Cmd(command="logs")
+@Admins(no_reply=True, only_devs=True)
+async def logs(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ pass
+
+
+@Cmd(command=["restart", "update"])
+@Admins(no_reply=True, only_devs=True)
+async def update_(update: Update, _: ContextTypes.DEFAULT_TYPE) -> Optional[Message]:
+ """Update and Restart the bot"""
+ m = cast(Message, update.effective_message)
+ cmd = m.text.split(sep=None, maxsplit=1)
+ command = cmd[0][1:]
+ msg: Message = await m.reply_text(
+ f"Restarting{' and updating ' if command == 'update' else ' '}the bot..."
+ )
+ try:
+ if command == "update":
+ try:
+ out = sub.check_output(["git", "pull"], universal_newlines=True)
+ if "Already up to date." in out:
+ return await msg.edit_text("Already up to date.")
+ if len(out) > 4096:
+ with io.BytesIO(str.encode(out)) as out_file:
+ out_file.name = str(uuid.uuid4()).split("-")[0].upper() + ".TXT"
+ caption = "Log of the update"
+ await m.reply_document(
+ document=out_file,
+ caption=caption,
+ disable_notification=True,
+ )
+ else:
+ await msg.edit_text(f"{html.escape(out)}
")
+ except Exception as e:
+ return await msg.edit_text(str(e))
+ await msg.reply_text("Restarting and pushing the changes...")
+
+ if command == "restart":
+ LOGGER.info("Restarting")
+
+ os.execvp(executable, args=[executable, "-m", "Telegram"])
+
+ except Exception as e:
+ return await msg.edit_text(f"Failed to restart the bot due to\n{e}")
+
+
+def format_exception(
+ exp: BaseException, tb: Optional[List[traceback.FrameSummary]] = None
+) -> str:
+ """Formats an exception traceback as a string."""
+ if tb is None:
+ tb = traceback.extract_tb(exp.__traceback__)
+
+ # Replace absolute paths with relative paths
+ cwd = os.getcwd()
+ for frame in tb:
+ if cwd in frame.filename:
+ frame.filename = os.path.relpath(frame.filename)
+
+ stack = "".join(traceback.format_list(tb))
+ msg = str(exp)
+ return f"Traceback (most recent call last):\n{stack}{type(exp).__name__}{f': {msg}' if msg else ''}"
+
+
+@Cmd(command=["py", "eval"], allow_edit=True)
+@Admins(only_devs=True)
+async def eval_(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ bot = context.bot
+ m = update.effective_message
+ text = m.text.split(None, 1)
+ if len(text) <= 1:
+ return
+ code = text[1]
+ out_buf = io.StringIO()
+
+ async def _eval() -> Tuple[str, Optional[str]]:
+ # Message sending helper for convenience
+ async def send(*args: Any, **kwargs: Any) -> telegram.Message:
+ return await m.reply_text(*args, **kwargs)
+
+ # Print wrapper to capture output
+ # We don't override sys.stdout to avoid interfering with other output
+ def _print(*args: Any, **kwargs: Any) -> None:
+ if "file" not in kwargs:
+ kwargs["file"] = out_buf
+ return print(*args, **kwargs)
+
+ eval_vars = {
+ # Contextual info,
+ "bot": bot,
+ "c": bot,
+ "stdout": out_buf,
+ # Convenience aliases
+ "update": update,
+ "context": context,
+ "m": m,
+ "msg": m,
+ "reply": m.reply_to_message,
+ "chat": update.effective_chat,
+ "user": update.effective_user,
+ "IKB": telegram.InlineKeyboardButton,
+ "IKM": telegram.InlineKeyboardMarkup,
+ # Helper functions
+ "send": send,
+ "print": _print,
+ # Built-in modules
+ "inspect": inspect,
+ "os": os,
+ "re": re,
+ "sys": sys,
+ "traceback": traceback,
+ # Third-party modules
+ "telegram": telegram,
+ "error": telegram.error,
+ }
+
+ try:
+ return "", await meval(code, globals(), **eval_vars)
+ except Exception as e:
+ # Find first traceback frame involving the snippet
+ first_snip_idx = -1
+ tb = traceback.extract_tb(e.__traceback__)
+ for i, frame in enumerate(tb):
+ if frame.filename == "" or frame.filename.endswith("ast.py"):
+ first_snip_idx = i
+ break
+
+ # Re-raise exception if it wasn't caused by the snippet
+ if first_snip_idx == -1:
+ raise e
+ # Return formatted stripped traceback
+ stripped_tb = tb[first_snip_idx:]
+ formatted_tb = format_exception(e, tb=stripped_tb)
+ return "⚠️ Error: \n\n", formatted_tb
+
+ prefix, result = await _eval()
+
+ # Always write result if no output has been collected thus far
+ if not out_buf.getvalue() or result is not None:
+ print(result, file=out_buf)
+
+ out = out_buf.getvalue()
+ # Strip only ONE final newline to compensate for our message formatting
+ if out.endswith("\n"):
+ out = out[:-1]
+
+ result = f"""{prefix}Eval:
+{escape(code)}
+ᴏᴜᴛ:
+{escape(out)}
"""
+
+ if len(result) > 4096:
+ with io.BytesIO(str.encode(out)) as out_file:
+ out_file.name = str(uuid.uuid4()).split("-")[0].upper() + ".txt"
+ caption = f"""{prefix}Eval:
+{escape(code)}
"""
+ await m.reply_document(
+ document=out_file,
+ caption=caption,
+ disable_notification=True,
+ )
+ return None
+
+ await m.reply_text(
+ result,
+ )
diff --git a/Telegram/modules/errorHandler.py b/Telegram/modules/errorHandler.py
new file mode 100644
index 00000000..3d0882dd
--- /dev/null
+++ b/Telegram/modules/errorHandler.py
@@ -0,0 +1,60 @@
+import html
+import json
+import traceback
+from typing import cast
+
+from telegram import Update
+from telegram.error import BadRequest, Forbidden
+from telegram.ext import ContextTypes
+
+from Telegram import LOGGER
+from config import LOGGER_ID
+
+
+async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """
+ if update.callback_query:
+ await update.callback_query.answer(
+ "Hey, an error happened. I notified my developer. If you think you can help him, PM @AshokShau. Thanks",
+ show_alert=True,
+ )
+ else:
+ await update.effective_message.reply_text(
+ "Hey, an error happened. I notified my developer. If you think you can help him, PM @Shau. Thanks"
+ )
+ """
+ """Log the error and send a telegram message to notify the developer."""
+ # Log the error before we do anything else, so we can see it even if something breaks.
+ LOGGER.error(msg="Exception while handling an update:", exc_info=context.error)
+
+ # traceback.format_exception returns the usual python message about an exception, but as a
+ # list of strings rather than a single string, so we have to join them together.
+ tb_list = traceback.format_exception(
+ None, context.error, cast(Exception, context.error).__traceback__
+ )
+ tb_string = "".join(tb_list)
+
+ # Build the message with some markup and additional information about what happened.
+ # You might need to add some logic to deal with messages longer than the 4096 character limit.
+ update_str = update.to_dict() if isinstance(update, Update) else str(update)
+ message_1 = (
+ f"An exception was raised while handling an update\n\n"
+ f"update = {html.escape(json.dumps(update_str, indent=2, ensure_ascii=False))}
"
+ )
+ message_2 = f"{html.escape(tb_string)}
"
+
+ # Finally, send the messages
+ # We send update and traceback in two parts to reduce the chance of hitting max length
+ try:
+ sent_message = await context.bot.send_message(chat_id=LOGGER_ID, text=message_1)
+ await sent_message.reply_html(message_2)
+ except BadRequest as exc:
+ if "too long" not in str(exc):
+ raise exc
+ message = (
+ f"Hey.\nThe error {html.escape(str(context.error))}
happened."
+ f" The traceback is too long to send, but it was written to the log."
+ )
+ await context.bot.send_message(chat_id=LOGGER_ID, text=message)
+ except Forbidden:
+ LOGGER.error(msg="bot can't send error on log group:", exc_info=context.error)
diff --git a/Telegram/modules/misc.py b/Telegram/modules/misc.py
new file mode 100644
index 00000000..6e7a1ec8
--- /dev/null
+++ b/Telegram/modules/misc.py
@@ -0,0 +1,81 @@
+from typing import cast
+
+from telegram import (
+ Message,
+ Update,
+ MessageOriginUser,
+ MessageOriginChat,
+ MessageOriginChannel,
+ MessageOriginHiddenUser,
+)
+from telegram.constants import ChatType, MessageOriginType
+from telegram.ext import ContextTypes
+
+from Telegram import Cmd
+from Telegram.database.users_db import Users
+from Telegram.utils.extract_user import extract_user
+
+
+@Cmd(command=["id"])
+async def get_id(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Message:
+ """Retrieve and display user and chat IDs based on the command context."""
+ message = cast(Message, update.message)
+ args = context.args
+ chat = update.effective_chat
+ user = message.from_user or message.sender_chat
+ your_id = user.id if message.from_user else message.sender_chat.id
+ reply = message.reply_to_message
+
+ # Base message with user and chat ID if available
+ text = f"Your ID: {your_id}\n"
+ if chat.type != ChatType.PRIVATE:
+ text += f"Chat ID: {chat.id}\n"
+
+ # If replying to a message, provide the replied user's or chat's ID
+ if reply:
+ if not reply.sender_chat and not reply.forward_origin:
+ text += f"Replied User ID: {reply.from_user.id}\n"
+ await Users(reply.from_user.id).update_user(
+ reply.from_user.full_name, reply.from_user.username, False
+ )
+
+ # Determine the forward origin type and add appropriate details
+ if (
+ isinstance(reply.forward_origin, MessageOriginUser)
+ and reply.forward_origin.type == MessageOriginType.USER
+ ):
+ text += f"Forwarded User: {reply.forward_origin.sender_user.first_name} with ID: {reply.forward_origin.sender_user.id}\n"
+ elif (
+ isinstance(reply.forward_origin, MessageOriginChat)
+ and reply.forward_origin.type == MessageOriginType.CHAT
+ ):
+ text += f"Forwarded Chat: {reply.forward_origin.sender_chat.full_name} with ID: {reply.forward_origin.sender_chat.id}\n"
+ elif (
+ isinstance(reply.forward_origin, MessageOriginChannel)
+ and reply.forward_origin.type == MessageOriginType.CHANNEL
+ ):
+ text += f"Forwarded Channel: {reply.forward_origin.chat.full_name} with ID: {reply.forward_origin.chat.id}\n"
+ elif (
+ isinstance(reply.forward_origin, MessageOriginHiddenUser)
+ and reply.forward_origin.type == MessageOriginType.HIDDEN_USER
+ ):
+ text += f"Unable to retrieve the forwarded {reply.forward_origin.sender_user_name} ID.\n"
+
+ # Additional media IDs if present
+ if reply.animation:
+ text += f"GIF ID: {reply.animation.file_id}\n"
+ if reply.sticker:
+ text += f"Sticker ID: {reply.sticker.file_id}\n"
+
+ # Sender chat ID if applicable
+ if reply.sender_chat:
+ text += f"ID of Replied Chat/Channel: {reply.sender_chat.id}\n"
+
+ # If arguments are provided, try to extract user details
+ if len(args) >= 1:
+ user_id, user_first_name, _, _ = await extract_user(message, context)
+ if user_id:
+ text += f"{user_first_name}: {user_id}\n"
+
+ # Reply to the message with the accumulated information
+ return await message.reply_text(text)
diff --git a/Telegram/modules/purge.py b/Telegram/modules/purge.py
new file mode 100644
index 00000000..cfa07649
--- /dev/null
+++ b/Telegram/modules/purge.py
@@ -0,0 +1,44 @@
+import asyncio
+
+from ptbmod import Admins
+from telegram import Update
+from telegram.ext import ContextTypes
+
+from Telegram import Cmd
+
+
+@Cmd(command=["delete", "del"])
+@Admins(permissions="can_delete_messages", is_both=True)
+async def delete(update: Update, _: ContextTypes.DEFAULT_TYPE) -> None:
+ message = update.effective_message
+ replied = message.reply_to_message
+ tasks = [message.delete()]
+
+ if replied:
+ tasks.append(replied.delete())
+ else:
+ tasks.append(message.reply_text(text="Reply to a message to delete it."))
+
+ await asyncio.gather(*tasks)
+
+
+@Cmd(command=["purge", "spurge"])
+@Admins(permissions="can_delete_messages", is_both=True)
+async def purge(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ bot = context.bot
+ m = update.effective_message
+ if m.reply_to_message:
+ message_ids = list(range(m.reply_to_message.id, m.id))
+ await asyncio.gather(
+ *(
+ bot.delete_messages(chat_id=m.chat.id, message_ids=x)
+ for x in (
+ message_ids[i : i + 100] for i in range(0, len(message_ids), 100)
+ )
+ )
+ )
+ await m.delete()
+ await m.reply_text(text=f"Deleted {len(message_ids)} messages")
+ return None
+ await m.reply_text("Reply to a message to delete it.")
+ return None
diff --git a/Telegram/modules/start.py b/Telegram/modules/start.py
new file mode 100644
index 00000000..8a5f27f1
--- /dev/null
+++ b/Telegram/modules/start.py
@@ -0,0 +1,264 @@
+import html
+from random import choice
+from typing import cast
+
+from telegram import (
+ CallbackQuery,
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ Message,
+ Update,
+)
+from telegram.constants import ChatType
+from telegram.error import BadRequest, Forbidden
+from telegram.ext import ContextTypes
+
+from Telegram import HELP_COMMANDS, LOGGER, Cb, Cmd
+from Telegram.utils.misc import StartPic, ikb
+from Telegram.utils.start import (
+ PM_HELP_TEXT,
+ PM_START_TEXT,
+ gen_help_keyboard,
+ get_help_msg,
+)
+
+
+@Cmd(command="start")
+async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Start command"""
+ args = context.args
+ message = update.effective_message
+ chat = update.effective_chat
+ if chat.type == ChatType.PRIVATE:
+ if args:
+ help_option = args[0].lower()
+ if help_option.startswith("rules") and (
+ help_option not in ("rule", "rules")
+ ):
+ return None
+
+ if help_option.startswith("note") and (
+ help_option not in ("note", "notes")
+ ):
+ return None
+
+ if help_option.startswith("captcha") and (
+ help_option not in ("captcha", "captchas")
+ ):
+ return None
+
+ help_msg, help_kb = await get_help_msg(help_option)
+ if not help_msg:
+ LOGGER.warning(f"No help_msg found for help_option - {help_option}.")
+ return None
+ await message.reply_photo(
+ photo=choice(StartPic),
+ caption=help_msg,
+ reply_markup=help_kb,
+ )
+ return None
+
+ try:
+ await message.reply_photo(
+ photo=choice(StartPic),
+ caption=PM_START_TEXT.format(
+ html.escape(update.effective_user.first_name),
+ context.bot.first_name,
+ ),
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="Aᴅᴅ ᴍᴇ ɪɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ",
+ url=f"https://t.me/{context.bot.username}?startgroup=new",
+ )
+ ],
+ [
+ InlineKeyboardButton(
+ text="Hᴇʟᴘ & Cᴏᴍᴍᴀɴᴅs",
+ callback_data="commands",
+ )
+ ],
+ ]
+ ),
+ )
+ except BadRequest as exc:
+ raise exc
+ except Forbidden as exc:
+ if "user is deactivated" not in exc.message:
+ raise exc
+
+ else:
+ help_option = args[0].lower() if args else "help"
+ await message.reply_photo(
+ photo=choice(StartPic),
+ caption="ʜᴇʏᴀ; ᴘᴍ ᴍᴇ ɪғ ʏᴏᴜ ʜᴀᴠᴇ ᴀɴʏ ǫᴜᴇsᴛɪᴏɴs ᴏɴ ʜᴏᴡ ᴛᴏ ᴜsᴇ ᴍᴇ.",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text=" ᴏᴩᴇɴ ɪɴ ᴩʀɪᴠᴀᴛᴇ ",
+ url=f"https://t.me/{context.bot.username}?start={help_option}",
+ )
+ ]
+ ]
+ ),
+ )
+
+ return None
+
+
+@Cmd(command="help")
+async def help_(update: Update, context: ContextTypes.DEFAULT_TYPE) -> Message | None:
+ """Help command"""
+ arg = context.args
+ m = cast(Message, update.effective_message)
+ if arg:
+ help_option = arg[0]
+ help_msg, help_kb = await get_help_msg(help_option)
+ if not help_msg:
+ LOGGER.warning(f"ɴᴏ ʜᴇʟᴘ_ᴍsɢ ғᴏᴜɴᴅ ғᴏʀ ʜᴇʟᴘ_ᴏᴘᴛɪᴏɴ - {help_option}.")
+ return None
+ if update.effective_chat.type == ChatType.PRIVATE:
+ if len(help_msg) >= 1026:
+ return await m.reply_text(help_msg, reply_markup=help_kb)
+ await m.reply_photo(
+ photo=str(choice(StartPic)),
+ caption=help_msg,
+ reply_markup=help_kb,
+ )
+ else:
+ await m.reply_photo(
+ photo=str(choice(StartPic)),
+ caption=f"ᴘʀᴇss ᴛʜᴇ ʙᴜᴛᴛᴏɴ ʙᴇʟᴏᴡ ᴛᴏ ɢᴇᴛ ʜᴇʟᴘ ғᴏʀ {help_option}",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ "Hᴇʟᴘ",
+ url=f"t.me/{context.bot.username}?start={help_option}",
+ ),
+ ],
+ ],
+ ),
+ )
+ else:
+ if m.chat.type == ChatType.PRIVATE:
+ keyboard = ikb(gen_help_keyboard(), "start_back")
+ msg = "ᴄʟɪᴄᴋ ᴏɴ ᴛʜᴇ ʜᴇʟᴩ ʙᴜᴛᴛᴏɴ ᴛᴏ ɢᴇᴛ ɪɴғᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴍʏ ᴍᴏᴅᴜʟᴇs ᴀɴᴅ ᴄᴏᴍᴍᴀɴᴅs."
+ else:
+ keyboard = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ "Hᴇʟᴘ",
+ url=f"t.me/{context.bot.username}?start=start_help",
+ ),
+ ],
+ ],
+ )
+ msg = "ᴄᴏɴᴛᴀᴄᴛ ᴍᴇ ɪɴ PM ᴛᴏ ɢᴇᴛ ᴛʜᴇ ʟɪsᴛ ᴏғ ᴘᴏssɪʙʟᴇ ᴄᴏᴍᴍᴀɴᴅs."
+ await m.reply_photo(
+ photo=str(choice(StartPic)),
+ caption=msg,
+ reply_markup=keyboard,
+ )
+
+
+@Cb(pattern="^modules.")
+async def modules(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Callback for help command"""
+ q = cast(CallbackQuery, update.callback_query)
+ module = q.data.split(".", 1)[1]
+
+ help_msg = HELP_COMMANDS[f"modules.{module}"]["help_msg"]
+
+ help_kb = HELP_COMMANDS[f"modules.{module}"]["buttons"]
+ try:
+ await q.edit_message_caption(
+ caption=help_msg,
+ reply_markup=ikb(help_kb, "commands"),
+ )
+ except BadRequest as exc:
+ if exc.message in [
+ "Message is not modified",
+ "Message to edit not found",
+ "Message is not modified: specified new message content",
+ ]:
+ pass
+ elif "too long" in str(exc):
+ await q.message.delete()
+ await context.bot.send_message(
+ chat_id=q.message.chat.id,
+ text=help_msg,
+ reply_markup=ikb(help_kb, "commands"),
+ )
+ else:
+ raise exc
+
+
+@Cb(pattern="^commands")
+async def commands(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Callback for help command"""
+ query = cast(CallbackQuery, update.callback_query)
+ keyboard = ikb(gen_help_keyboard(), "start_back")
+ try:
+ await query.message.edit_caption(
+ caption=PM_HELP_TEXT,
+ reply_markup=keyboard,
+ )
+ except BadRequest as exc:
+ if exc.message in [
+ "Message is not modified",
+ "Message to edit not found",
+ "Message is not modified: specified new message content",
+ ]:
+ pass
+ elif "too long" in str(exc):
+ await context.bot.send_message(
+ chat_id=query.message.chat.id,
+ text=PM_HELP_TEXT,
+ reply_markup=keyboard,
+ )
+ return await query.message.delete()
+ else:
+ raise exc
+
+
+@Cb(pattern="^start_")
+async def callbacks(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+ """Callback for help command"""
+ query = update.callback_query
+ if query.data == "start_back":
+ await query.answer(text="Home menu")
+ try:
+ await query.message.edit_caption(
+ caption=PM_START_TEXT.format(
+ html.escape(update.effective_user.first_name),
+ context.bot.first_name,
+ ),
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="Aᴅᴅ ᴍᴇ ɪɴ ʏᴏᴜʀ ɢʀᴏᴜᴘ",
+ url=f"https://t.me/{context.bot.username}?startgroup=new",
+ )
+ ],
+ [
+ InlineKeyboardButton(
+ text="Hᴇʟᴘ & Cᴏᴍᴍᴀɴᴅs",
+ callback_data="commands",
+ )
+ ],
+ ]
+ ),
+ )
+ except BadRequest as exc:
+ if exc.message not in [
+ "Message is not modified",
+ "Message to edit not found",
+ "Can't access the chat",
+ "Chat not found",
+ ]:
+ raise exc
diff --git a/Telegram/modules/users.py b/Telegram/modules/users.py
new file mode 100644
index 00000000..2c76b91e
--- /dev/null
+++ b/Telegram/modules/users.py
@@ -0,0 +1,53 @@
+from telegram import Update, MessageOriginUser, MessageOriginChat
+from telegram.constants import ChatType
+from telegram.ext import filters, ContextTypes
+
+from Telegram import Msg
+from Telegram.database.chats_db import ChatsDB
+from Telegram.database.users_db import Users
+
+
+@Msg(~filters.COMMAND, group=-2)
+async def _tracker(update: Update, _: ContextTypes.DEFAULT_TYPE) -> None:
+ """Saves Users In Database"""
+ message = update.effective_message
+ chat = update.effective_chat
+ user = update.effective_user
+
+ # save chats
+ chat_db = ChatsDB(chat.id)
+ if chat.type in [ChatType.GROUP, ChatType.SUPERGROUP]:
+ await chat_db.update_chat(chat.title, chat.username)
+ elif chat.type == ChatType.PRIVATE:
+ await Users(user.id).update_user(user.full_name, user.username, True)
+
+ if reply := message.reply_to_message:
+ if not reply.sender_chat and not reply.forward_origin:
+ await Users(reply.from_user.id).update_user(
+ reply.from_user.full_name, reply.from_user.username, False
+ )
+
+ if isinstance(reply.forward_origin, MessageOriginUser):
+ await Users(reply.forward_origin.sender_user.id).update_user(
+ reply.forward_origin.sender_user.full_name,
+ reply.forward_origin.sender_user.username,
+ False,
+ )
+ await Users(user.id).update_user(user.full_name, user.username, False)
+
+ if message and message.forward_origin:
+ if isinstance(message.forward_origin, MessageOriginUser):
+ await Users(message.forward_origin.sender_user.id).update_user(
+ message.forward_origin.sender_user.full_name,
+ reply.forward_origin.sender_user.username,
+ False,
+ )
+ await Users(message.from_user.id).update_user(
+ message.from_user.full_name, message.from_user.username, False
+ )
+ elif isinstance(message.forward_origin, MessageOriginChat):
+ await Users(message.from_user.id).update_user(
+ message.from_user.full_name, message.from_user.username, False
+ )
+
+ await Users(user.id).update_user(user.full_name, user.username, False)
diff --git a/Telegram/utils/extract_user.py b/Telegram/utils/extract_user.py
new file mode 100644
index 00000000..d2e0af19
--- /dev/null
+++ b/Telegram/utils/extract_user.py
@@ -0,0 +1,79 @@
+from typing import Optional, Tuple
+
+from telegram import Message, MessageEntity
+from telegram.error import BadRequest
+from telegram.ext import ContextTypes
+
+from Telegram.database.users_db import Users
+
+
+async def extract_user(
+ m: Message,
+ context: ContextTypes.DEFAULT_TYPE,
+ sender: bool = False,
+) -> Tuple[Optional[int], Optional[str], Optional[str], Optional[str]]:
+ """
+ Extract user information from a message based on various conditions:
+ replies, mentions, usernames, or user IDs.
+
+ returns: user_id, full_name, username, args
+ """
+ reply_message = m.reply_to_message
+ args = context.args
+ if reply_message and reply_message.from_user:
+ user = reply_message.from_user
+ if user.id == 136817688:
+ user = reply_message.sender_chat
+ return user.id, user.full_name, user.username, (m.text.split(None, 1) + [""])[1]
+
+ if entities := list(m.parse_entities([MessageEntity.TEXT_MENTION])):
+ ent = entities[0]
+ if ent.offset == len(m.text) - len(m.text.split(None, 1)[1]):
+ return (
+ ent.user.id,
+ ent.user.full_name,
+ ent.user.username,
+ m.text[ent.offset + ent.length :],
+ )
+
+ if len(args) >= 1 and args[0].startswith("@"):
+ user = await Users.get_user_info(args[0].lstrip("@"))
+ if user:
+ return (
+ user["_id"],
+ user["name"],
+ user["username"],
+ (m.text.split(None, 2) + [""])[2],
+ )
+ return None, None, None, (m.text.split(None, 2) + [""])[2]
+
+ if len(args) >= 1 and args[0].isdigit():
+ user_id = int(args[0])
+ user = await Users.get_user_info(user_id)
+ if user:
+ return (
+ user_id,
+ user["name"],
+ user["username"],
+ (m.text.split(None, 2) + [""])[2],
+ )
+ try:
+ user = await context.bot.get_chat(user_id)
+ return (
+ user.id,
+ user.full_name,
+ user.username,
+ (m.text.split(None, 2) + [""])[2],
+ )
+ except BadRequest:
+ return None, None, None, None
+
+ if sender:
+ return (
+ m.from_user.id,
+ m.from_user.full_name,
+ m.from_user.username,
+ (m.text.split(None, 1) + [""])[1],
+ )
+
+ return None, None, None, (m.text.split(None, 1) + [""])[1]
diff --git a/Telegram/utils/formatters.py b/Telegram/utils/formatters.py
new file mode 100644
index 00000000..845af4cb
--- /dev/null
+++ b/Telegram/utils/formatters.py
@@ -0,0 +1,50 @@
+from datetime import datetime, timedelta
+
+import pytz
+
+
+def create_time(time_raw: str) -> datetime:
+ """Creates a datetime object from time_raw string"""
+ unit_map = {
+ "d": "days",
+ "h": "hours",
+ "m": "minutes",
+ "s": "seconds",
+ }
+ now = datetime.now(pytz.timezone("Asia/Kolkata"))
+ time_val = int(time_raw[:-1])
+ unit = time_raw[-1]
+ if unit == "s" and time_val < 30:
+ time_val = 40
+ return now + timedelta(**{unit_map[unit]: time_val})
+
+
+def tl_time(time_raw):
+ """Converts time_raw string to readable format"""
+ time_val = int(time_raw[:-1])
+ unit = time_raw[-1]
+
+ if unit == "d":
+ return (
+ "ғᴏʀᴇᴠᴇʀ"
+ if time_val > 366
+ else f"{time_val} {'ᴅᴀʏ' if time_val == 1 else 'ᴅᴀʏs'}"
+ )
+ elif unit == "h":
+ return (
+ "ғᴏʀᴇᴠᴇʀ"
+ if time_val > 8786
+ else f"{time_val} {'ʜᴏᴜʀ' if time_val == 1 else 'ʜᴏᴜʀs'}"
+ )
+ elif unit == "m":
+ return (
+ "ғᴏʀᴇᴠᴇʀ"
+ if time_val > 525600
+ else f"{time_val} {'ᴍɪɴᴜᴛᴇ' if time_val == 1 else 'ᴍɪɴᴜᴛᴇs'}"
+ )
+ elif unit == "s":
+ if time_val > 31539600:
+ return "ғᴏʀᴇᴠᴇʀ"
+ return f"{time_val if time_val >= 30 else 40} {'sᴇᴄᴏɴᴅ' if time_val == 1 else 'sᴇᴄᴏɴᴅs'}"
+
+ return ""
diff --git a/Telegram/utils/misc.py b/Telegram/utils/misc.py
new file mode 100644
index 00000000..a2cfef74
--- /dev/null
+++ b/Telegram/utils/misc.py
@@ -0,0 +1,121 @@
+from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Message
+from telegram.error import BadRequest, Forbidden
+
+
+async def try_to_delete(message: Message) -> bool:
+ """Try to delete message"""
+ try:
+ return await message.delete()
+ except BadRequest as exc:
+ return exc.message == "Reply message not found"
+ except Forbidden:
+ return False
+
+
+ParseWords: list[str] = [
+ "first",
+ "last",
+ "fullname",
+ "id",
+ "username",
+ "mention",
+ # "chatname",
+ "preview",
+ "protect",
+ "spoiler",
+ "owner",
+ "user",
+ "admin",
+]
+
+StartPic: list[str] = [
+ "https://telegra.ph//file/0879fbdb307005c1fa8ab.jpg",
+ "https://telegra.ph//file/19e3a9d5c0985702497fb.jpg",
+ "https://telegra.ph//file/b5fa277081dddbddd0b12.jpg",
+ "https://telegra.ph//file/96e96245fe1afb82d0398.jpg",
+ "https://telegra.ph//file/fb140807129a3ccb60164.jpg",
+ "https://telegra.ph//file/09c9ea0e2660efae6f62a.jpg",
+ "https://telegra.ph//file/3b59b15e1914b4fa18b71.jpg",
+ "https://telegra.ph//file/efb26cc17eef6fe82d910.jpg",
+ "https://telegra.ph//file/ab4925a050e07b00f63c5.jpg",
+ "https://telegra.ph//file/d169a77fd52b46e421414.jpg",
+ "https://telegra.ph//file/dab9fc41f214f9cded1bb.jpg",
+ "https://telegra.ph//file/e05d6e4faff7497c5ae56.jpg",
+ "https://telegra.ph//file/1e54f0fff666dd53da66f.jpg",
+ "https://telegra.ph//file/18e98c60b253d4d926f5f.jpg",
+ "https://telegra.ph//file/b1f7d9702f8ea590b2e0c.jpg",
+ "https://telegra.ph//file/7bb62c8a0f399f6ee1f33.jpg",
+ "https://telegra.ph//file/dd00c759805082830b6b6.jpg",
+ "https://telegra.ph//file/3b996e3241cf93d102adc.jpg",
+ "https://telegra.ph//file/610cc4522c7d0f69e1eb8.jpg",
+ "https://telegra.ph//file/bc97b1e9bbe6d6db36984.jpg",
+ "https://telegra.ph//file/2ddf3521636d4b17df6dd.jpg",
+ "https://telegra.ph//file/72e4414f618111ea90a57.jpg",
+ "https://telegra.ph//file/a958417dcd966d341bfe2.jpg",
+ "https://telegra.ph//file/0afd9c2f70c6328a1e53a.jpg",
+ "https://telegra.ph//file/82ff887aad046c3bcc9a3.jpg",
+ "https://telegra.ph//file/8ba64d5506c23acb67ff4.jpg",
+ "https://telegra.ph//file/8ba64d5506c23acb67ff4.jpg",
+ "https://telegra.ph//file/a7cba6e78bb63e1b4aefb.jpg",
+ "https://telegra.ph//file/f8ba75bdbb9931cbc8229.jpg",
+ "https://telegra.ph//file/07bb5f805178ec24871d3.jpg",
+]
+
+
+def ikb(rows=None, back=None):
+ """
+ Helper function to create inline keyboard.
+
+ Args:
+ rows (list, optional): List of lists of tuples, where each tuple contains
+ the text and value of the button. Defaults to None.
+ back (str, optional): Callback data for the back button. Defaults to None.
+
+ Returns:
+ InlineKeyboardMarkup: Inline keyboard.
+ """
+ if rows is None:
+ rows = []
+ lines = []
+ try:
+ for row in rows:
+ line = []
+ for button in row:
+ btn_text = button.split(".")[1].capitalize()
+ button = btn(btn_text, button)
+ line.append(button)
+ lines.append(line)
+ except AttributeError:
+ for row in rows:
+ line = []
+ for button in row:
+ button = btn(*button)
+ line.append(button)
+ lines.append(line)
+ except TypeError:
+ line = []
+ for button in rows:
+ button = btn(*button)
+ line.append(button)
+ lines.append(line)
+
+ if back:
+ back_btn = [(btn("« ʙᴀᴄᴋ", back))]
+ lines.append(back_btn)
+ return InlineKeyboardMarkup(inline_keyboard=lines)
+
+
+def btn(
+ text: str, value: str, button_type: str = "callback_data"
+) -> InlineKeyboardButton:
+ """Helper function to create inline keyboard button.
+
+ Args:
+ text: Button text.
+ value: Callback data for the button.
+ button_type: Type of the button. Defaults to "callback_data".
+
+ Returns:
+ InlineKeyboardButton: Inline keyboard button.
+ """
+ return InlineKeyboardButton(text, **{button_type: value})
diff --git a/Telegram/utils/msg_types.py b/Telegram/utils/msg_types.py
new file mode 100644
index 00000000..703bd409
--- /dev/null
+++ b/Telegram/utils/msg_types.py
@@ -0,0 +1,173 @@
+from enum import IntEnum, unique
+
+from telegram import Bot, Message
+
+
+@unique
+class Types(IntEnum):
+ """Get type of message"""
+
+ TEXT = 1
+ DOCUMENT = 2
+ PHOTO = 3
+ VIDEO = 4
+ STICKER = 5
+ AUDIO = 6
+ VOICE = 7
+ VIDEO_NOTE = 8
+ ANIMATION = 9
+ ANIMATED_STICKER = 10
+ CONTACT = 11
+
+
+async def send_cmd(bot: Bot, msg_type: int):
+ """Send Helper"""
+ get_format = {
+ Types.TEXT.value: bot.send_message,
+ Types.DOCUMENT.value: bot.send_document,
+ Types.PHOTO.value: bot.send_photo,
+ Types.VIDEO.value: bot.send_video,
+ Types.STICKER.value: bot.send_sticker,
+ Types.AUDIO.value: bot.send_audio,
+ Types.VOICE.value: bot.send_voice,
+ Types.VIDEO_NOTE.value: bot.send_video_note,
+ Types.ANIMATION.value: bot.send_animation,
+ Types.ANIMATED_STICKER.value: bot.send_sticker,
+ Types.CONTACT: bot.send_contact,
+ }
+ return get_format[msg_type]
+
+
+async def get_note_type(m: Message):
+ """Get type of note."""
+ if len(m.text.split()) <= 1:
+ return None, None, None, None
+
+ data_type = None
+ content = None
+ raw_text = m.text_html or m.caption_html
+ args = raw_text.split(None, 2)
+ note_name = args[1]
+
+ if len(args) >= 3:
+ text = args[2]
+ data_type = Types.TEXT
+
+ elif m.reply_to_message:
+ if m.reply_to_message.text:
+ text = m.reply_to_message.text_html
+ elif m.reply_to_message.caption:
+ text = m.reply_to_message.caption_html
+ else:
+ text = ""
+
+ if len(args) >= 2 and m.reply_to_message.text_html: # not caption, text
+ data_type = Types.TEXT
+
+ elif m.reply_to_message.sticker:
+ content = m.reply_to_message.sticker.file_id
+ data_type = Types.STICKER
+
+ elif m.reply_to_message.document:
+ if m.reply_to_message.document.mime_type == "application/x-bad-tgsticker":
+ data_type = Types.ANIMATED_STICKER
+ else:
+ data_type = Types.DOCUMENT
+ content = m.reply_to_message.document.file_id
+
+ elif m.reply_to_message.photo:
+ content = m.reply_to_message.photo[-1].file_id # last elem = best quality
+ data_type = Types.PHOTO
+
+ elif m.reply_to_message.audio:
+ content = m.reply_to_message.audio.file_id
+ data_type = Types.AUDIO
+
+ elif m.reply_to_message.voice:
+ content = m.reply_to_message.voice.file_id
+ data_type = Types.VOICE
+
+ elif m.reply_to_message.video:
+ content = m.reply_to_message.video.file_id
+ data_type = Types.VIDEO
+
+ elif m.reply_to_message.video_note:
+ content = m.reply_to_message.video_note.file_id
+ data_type = Types.VIDEO_NOTE
+
+ elif m.reply_to_message.animation:
+ content = m.reply_to_message.animation.file_id
+ data_type = Types.ANIMATION
+
+ else:
+ return None, None, None, None
+
+ return note_name, text, data_type, content
+
+
+async def get_welcome_type(m: Message):
+ """Get type of welcome/AFK."""
+ data_type = None
+ content = None
+ raw_text = m.text_html or m.caption_html
+ args = raw_text.split(None, 1)
+
+ if not m.reply_to_message and m.text and len(m.text.split()) >= 2:
+ content = None
+ text = m.text.split(None, 1)[1]
+ data_type = Types.TEXT
+
+ elif m.reply_to_message:
+ if m.reply_to_message.text:
+ text = m.reply_to_message.text_html
+ elif m.reply_to_message.caption:
+ text = m.reply_to_message.caption_html
+ elif m.text and len(m.text.split()) >= 2:
+ text = m.text.split(None, 1)[1]
+ else:
+ text = ""
+
+ if len(args) >= 1 and m.reply_to_message.text_html: # not caption, text
+ data_type = Types.TEXT
+
+ elif m.reply_to_message.sticker:
+ content = m.reply_to_message.sticker.file_id
+ data_type = Types.STICKER
+
+ elif m.reply_to_message.document:
+ if m.reply_to_message.document.mime_type == "application/x-bad-tgsticker":
+ data_type = Types.ANIMATED_STICKER
+ else:
+ data_type = Types.DOCUMENT
+ content = m.reply_to_message.document.file_id
+
+ elif m.reply_to_message.photo:
+ content = m.reply_to_message.photo[-1].file_id
+ data_type = Types.PHOTO
+
+ elif m.reply_to_message.audio:
+ content = m.reply_to_message.audio.file_id
+ data_type = Types.AUDIO
+
+ elif m.reply_to_message.voice:
+ content = m.reply_to_message.voice.file_id
+ data_type = Types.VOICE
+
+ elif m.reply_to_message.video:
+ content = m.reply_to_message.video.file_id
+ data_type = Types.VIDEO
+
+ elif m.reply_to_message.video_note:
+ content = m.reply_to_message.video_note.file_id
+ data_type = Types.VIDEO_NOTE
+
+ elif m.reply_to_message.animation:
+ content = m.reply_to_message.animation.file_id
+ data_type = Types.ANIMATION
+
+ else:
+ text = None
+ data_type = None
+ content = None
+
+ return text, data_type, content
diff --git a/Telegram/utils/start.py b/Telegram/utils/start.py
new file mode 100644
index 00000000..4dca2bbf
--- /dev/null
+++ b/Telegram/utils/start.py
@@ -0,0 +1,60 @@
+from Telegram import HELP_COMMANDS
+from Telegram.utils.misc import ikb
+
+PM_START_TEXT = """
+нєу {} 🥀
+
+๏ ᴛʜɪs ɪs {} !
+➻ ᴛʜᴇ ᴍᴏsᴛ ᴄᴏᴍᴘʟᴇᴛᴇ ᴛᴇʟᴇɢʀᴀᴍ ʙᴏᴛ ғᴏʀ ᴍᴀɴᴀɢɪɴɢ ᴀɴᴅ ᴘʀᴏᴛᴇᴄᴛɪɴɢ ɢʀᴏᴜᴘs ᴄʜᴀᴛ ғʀᴏᴍ sᴘᴀᴍᴍᴇʀ ᴀɴᴅ sᴄᴏғғʟᴀᴡ.
+
+──────────────────
+๏ ᴄʟɪᴄᴋ ᴏɴ ᴛʜᴇ ʜᴇʟᴩ ʙᴜᴛᴛᴏɴ ᴛᴏ ɢᴇᴛ ɪɴғᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴍʏ ᴍᴏᴅᴜʟᴇs ᴀɴᴅ ᴄᴏᴍᴍᴀɴᴅs.
+"""
+
+PM_HELP_TEXT = """
+────────────────────
+๏ ᴄʟɪᴄᴋ ᴏɴ ᴛʜᴇ ʜᴇʟᴩ ʙᴜᴛᴛᴏɴ ᴛᴏ ɢᴇᴛ ɪɴғᴏʀᴍᴀᴛɪᴏɴ ᴀʙᴏᴜᴛ ᴍʏ ᴍᴏᴅᴜʟᴇs ᴀɴᴅ ᴄᴏᴍᴍᴀɴᴅs.
+ ──────────────────
+"""
+
+
+def gen_help_keyboard():
+ """
+ Generate a keyboard layout for help commands.
+
+ This function creates a keyboard layout by organizing the keys of the HELP_COMMANDS into rows, with each row containing up to three keys. The keys are sorted alphabetically to ensure a consistent order in the generated keyboard.
+
+ Returns:
+ list: A list of lists, where each inner list contains up to three help command keys.
+
+ """
+ kb = sorted(list(HELP_COMMANDS.keys()))
+ return [kb[i : i + 3] for i in range(0, len(kb), 3)]
+
+
+async def get_help_msg(help_option: str):
+ """
+ Get the help message and keyboard based on the provided help option.
+
+ This asynchronous function retrieves a help message and a corresponding keyboard layout based on the specified help option. If the help option is found in the predefined commands, it returns the associated help message and buttons; otherwise, it returns a general help message and a default keyboard.
+
+ Args:
+ help_option (str): The help option to look up in the HELP_COMMANDS.
+
+ Returns:
+ tuple: A tuple containing the help message (str) and the keyboard layout (various types depending on ikb implementation).
+
+ """
+ if help_option_data := next(
+ (data for data in HELP_COMMANDS.values() if help_option in data["alt_cmd"]),
+ None,
+ ):
+ help_msg = help_option_data["help_msg"]
+ buttons = help_option_data["buttons"]
+ help_kb = ikb(buttons, "commands")
+ else:
+ help_msg = PM_HELP_TEXT
+ buttons = gen_help_keyboard()
+ help_kb = ikb(buttons, "start_back")
+
+ return help_msg, help_kb
diff --git a/app.json b/app.json
deleted file mode 100644
index 4d3d8eff..00000000
--- a/app.json
+++ /dev/null
@@ -1,77 +0,0 @@
-
-{
- "name": "ᴇxᴏɴᴏʙᴏᴛ",
- "description": "Telegram Group Management Bot Written In Python Using python-telegram-bot.",
- "repository": "https://github.com/AshokShau/ExonRobot",
- "logo": "https://te.legra.ph/file/b0e09aabe796209f01d3d.jpg",
- "keywords": [
- "python3",
- "telegram",
- "bot",
- "ExonRobot",
- "telegram-bot",
- "management",
- "ptb",
- "pyrogram"
- ],
- "buildpacks": [
- {
- "url": "https://github.com/heroku/heroku-buildpack-python"
- },
- {
- "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest"
- }
- ],
- "stack": "heroku-22",
- "addons": [
- {
- "options": {
- "version": "14"
- },
- "plan": "heroku-postgresql"
- }
- ],
- "env": {
- "API_ID": {
- "description": "ɢᴇᴛ ᴛʜɪs ᴠᴀʟᴜᴇ ғʀᴏᴍ my.telegram.org/apps.",
- "required": true,
- "value": ""
- },
- "API_HASH": {
- "description": "ɢᴇᴛ ᴛʜɪs ᴠᴀʟᴜᴇ ғʀᴏᴍ my.telegram.org/apps.",
- "required": true,
- "value": ""
- },
- "OWNER_ID": {
- "description": "ʏᴏᴜʀ ᴜsᴇʀ ID ᴀs ᴀɴ ɪɴᴛᴇɢᴇʀ.",
- "required": true,
- "value": "5938660179"
- },
- "DEV_USERS": {
- "description": "ᴅᴇᴠs ᴜsᴇʀ ID ᴀs ᴀɴ ɪɴᴛᴇɢᴇʀ.",
- "required": true,
- "value": "5938660179"
- },
- "OWNER_USERNAME": {
- "description": "ʏᴏᴜʀ ᴛɢ ᴜsᴇʀɴᴀᴍᴇ",
- "required": true,
- "value": "AshokShau"
- },
- "LOGGER_ID": {
- "description": "ᴇᴠᴇɴᴛ ʟᴏɢs ᴄʜᴀɴɴᴇʟ ᴛᴏ ɴᴏᴛᴇ ᴅᴏᴡɴ ɪᴍᴘᴏʀᴛᴀɴᴛ ʙᴏᴛ ʟᴇᴠᴇʟ ᴇᴠᴇɴᴛs, ᴇx: '-10023456'",
- "required": true,
- "value": "-100"
- },
- "MONGO_DB_URI": {
- "description": "ʀᴇǫᴜɪʀᴇᴅ ғᴏʀ ᴅᴀᴛᴀʙᴀsᴇ ᴄᴏɴɴᴇᴄᴛɪᴏɴs (ᴍᴏɴɢᴏ).",
- "required": true,
- "value": "mongodb+srv://public:abishnoimf@cluster0.rqk6ihd.mongodb.net/?retryWrites=true&w=majority"
- },
- "TOKEN": {
- "description": "Get bot token from @BotFather on TG",
- "required": true,
- "value": ""
- }
- }
-}
-
diff --git a/config.py b/config.py
index c3438a11..da7f8676 100644
--- a/config.py
+++ b/config.py
@@ -4,35 +4,20 @@
load_dotenv()
+TOKEN = getenv("TOKEN")
+"bot token, get from @BotFather"
-class Config(object):
- LOGGER = True
-
- API_ID = int(getenv("API_ID", 6))
- API_HASH = getenv("API_HASH", None)
- ARQ_API_KEY = "PMPTTD-HOMLMF-SRBHNH-RZMWXL-ARQ"
- SPAMWATCH_API = None
- TOKEN = getenv("TOKEN", None)
- OWNER_ID = int(getenv("OWNER_ID", 5938660179))
- OWNER_USERNAME = getenv("OWNER_USERNAME", "AshokShau")
- SUPPORT_CHAT = getenv("SUPPORT_CHAT", "AbishnoiMF")
- LOGGER_ID = int(getenv("LOGGER_ID", "-1001819078701"))
- MONGO_URI = getenv(
- "MONGO_DB_URI",
- "mongodb+srv://public:abishnoimf@cluster0.rqk6ihd.mongodb.net/?retryWrites=true&w=majority",
- )
- DB_NAME = getenv("DB_NAME", "ExonRobot")
- REDIS_URL = "redis://default:wK6ZCiclq4iQKYpgfY90v6kd6WdPfEwl@redis-10186.c263.us-east-1-2.ec2.cloud.redislabs.com:10186/default"
- DATABASE_URL = getenv("DATABASE_URL", None)
-
- # ɴᴏ ᴇᴅɪᴛ ᴢᴏɴᴇ
- if DATABASE_URL.startswith("postgres://"):
- DATABASE_URL = DATABASE_URL.replace("postgres://", "postgresql://")
-
-
-class Production(Config):
- LOGGER = True
-
-
-class Development(Config):
- LOGGER = True
+LOGGER_LEVEL = getenv("LOGGER_LEVEL")
+"logger level, `debug(10)`, `info(20)`, `warn(30)` and `error(40)`. default is `info`"
+
+MONGO = getenv("MONGO")
+"mongo db uri, get from mongodb.com"
+
+TIME_ZONE = getenv("TIME_ZONE", "Asia/Kolkata")
+"bot time zone, get from https://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
+
+OWNER_ID = int(getenv("OWNER_ID"))
+"owner id, get from @GuardxRobot"
+
+LOGGER_ID = int(getenv("LOGGER_ID"))
+"logger id, get from @GuardxRobot"
diff --git a/docker-compose.yml b/docker-compose.yml
deleted file mode 100644
index 10075f81..00000000
--- a/docker-compose.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-version: "1.0"
-services:
- worker:
- build: .
- environment:
- APP_ID: $API_ID
- API_HASH: $API_HASH
- TOKEN: $TOKEN
- OWNER_ID: $OWNER_ID
- OWNER_USERNAME: $OWNER_USERNAME
- DATABASE_URL: $DATABASE_URL
- MONGO_URI: $MONGO_DB_URI
diff --git a/heroku.yml b/heroku.yml
deleted file mode 100644
index 437324ab..00000000
--- a/heroku.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-build:
- docker:
- worker: Dockerfile
-run:
- worker: bash start
diff --git a/okteto-pipeline.yml b/okteto-pipeline.yml
deleted file mode 100644
index d4f6975d..00000000
--- a/okteto-pipeline.yml
+++ /dev/null
@@ -1,3 +0,0 @@
-icon: https://img.shields.io/github/v/release/AshokShau/ExonRobot?color=black&logo=github&logoColor=black&style=social
-deploy:
- - okteto stack deploy --build -f docker-compose.yml
diff --git a/requirements.txt b/requirements.txt
index 3404c020..70eedbbf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,57 +1,8 @@
-abg==2.5.1
-aiofiles
-aiohttp>=3.9.2
-httpx[http2]>=0.18.1,<1.0.0
-alphabet_detector==0.0.7
-beautifulsoup4==4.11.1
-bleach==6.1.0
-cachetools
-configparser==5.3.0
-dateparser
-emoji==1.7.0
-feedparser==6.0.10
-ffmpeg-python==0.2.0
-future==0.18.3
-gitpython==3.1.43
-markdown2==2.5.1
-multicolorcaptcha==1.2.0
-Pillow>=10.2.0
-psutil==5.9.8
-psycopg2-binary==2.9.10
-pyYAML==6.0.2
-pyrate-limiter==2.8.5
-python-telegram-bot==13.15
-requests==2.32.3
-spamwatch==0.3.0
-speedtest-cli==2.1.3
-SQLAlchemy==1.4.44
-telethon==1.35.0
-ujson==5.8.0
-pycryptodome==3.20.0
-prettyconf
-base58==2.1.1
-pytimeparse==1.1.8
-SibylSystem==0.0.24
-tgcrypto-pyrofork
-pyrofork
-python-arq==6.0.7
-python-dotenv==1.0.1
-redis==5.2.0
-telegraph==2.2.0
-motor
-pymongo==4.10.1
-odmantic==0.9.2
-opencv-python-headless==4.10.0.82
-pykeyboard
-wget==3.2
-wikipedia==1.4.0
-bing_image_downloader==1.1.2
-lyricsgenius==3.0.1
-jikanpy==4.3.2
-gtts==2.5.1
-search_engine_parser
-googletrans==2.4.0
-gpytranslate==1.5.1
-cloudscraper==1.2.70
-carbonnow
-pretty_errors
+ptbmod~=0.4
+pytz~=2024.2
+motor~=3.6.0
+meval~=2.5
+
+python-telegram-bot[job-queue, callback-data]~=21.6
+pymongo~=4.9.2
+python-dotenv~=1.0.1
diff --git a/restart.bat b/restart.bat
deleted file mode 100644
index 5d3e9ed4..00000000
--- a/restart.bat
+++ /dev/null
@@ -1 +0,0 @@
-start cmd.exe /c start_service.bat
diff --git a/runtime.txt b/runtime.txt
deleted file mode 100644
index 81db544d..00000000
--- a/runtime.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-python-3.11.4
-
-
-
diff --git a/sample.env b/sample.env
deleted file mode 100644
index 1fa78caa..00000000
--- a/sample.env
+++ /dev/null
@@ -1,10 +0,0 @@
-API_ID=12334
-API_HASH=
-TOKEN=
-OWNER_ID=5938660179
-OWNER_USERNAME=AshokShau
-SUPPORT_CHAT=AbishnoiMF
-LOGGER_ID=-1001573019550
-DEV_USERS=5938660179
-MONGO_DB_URI=
-DATABASE_URL=
diff --git a/start b/start
index fe0cc5d3..803b7e90 100644
--- a/start
+++ b/start
@@ -1,7 +1 @@
-#!/bin/bash
-
-#git clone $REPO_URL Repo
-#cd Repo
-#pip3 install -U -r requirements.txt
-python3 -m Exon
-
+python3 -m Telegram
diff --git a/start.bat b/start.bat
deleted file mode 100644
index 125507c9..00000000
--- a/start.bat
+++ /dev/null
@@ -1,4 +0,0 @@
-@echo off
-TITLE Exon bot
-:: Enables virtual env mode and then starts Telegram bot
-env\scripts\activate.bat && py -m Exon
diff --git a/start_service.bat b/start_service.bat
deleted file mode 100644
index cce75562..00000000
--- a/start_service.bat
+++ /dev/null
@@ -1,29 +0,0 @@
-@echo off
-
-:: BatchGotAdmin
-:-------------------------------------
-REM --> Check for permissions
->nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
-
-REM --> If error flag set, we do not have admin.
-if '%errorlevel%' NEQ '0' (
- echo Requesting administrative privileges...
- goto UACPrompt
-) else ( goto gotAdmin )
-
-:UACPrompt
- echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
- set params = %*:"=""
- echo UAC.ShellExecute "cmd.exe", "/c %~s0 %params%", "", "runas", 1 >> "%temp%\getadmin.vbs"
-
- "%temp%\getadmin.vbs"
- del "%temp%\getadmin.vbs"
- exit /B
-
-:gotAdmin
- pushd "%CD%"
- CD /D "%~dp0"
-:--------------------------------------
-:: your commands begin from this point.
-:: stops the service and then starts it
-nssm restart Exon