Просмотр исходного кода

Added custom filters | improved stuffs

thehamkercat 5 лет назад
Родитель
Сommit
96262258dc

+ 0 - 1
requirements.txt

@@ -11,7 +11,6 @@ pillow
 psutil
 psutil
 pykeyboard
 pykeyboard
 pyrogram
 pyrogram
-pyromod
 python-arq
 python-arq
 requests
 requests
 search_engine_parser
 search_engine_parser

+ 0 - 1
wbb/__init__.py

@@ -33,7 +33,6 @@ from motor.motor_asyncio import AsyncIOMotorClient as MongoClient
 from pyrogram import Client
 from pyrogram import Client
 from Python_ARQ import ARQ
 from Python_ARQ import ARQ
 
 
-from pyromod import listen
 
 
 # Setup logging
 # Setup logging
 log_file = "error.log"
 log_file = "error.log"

+ 23 - 0
wbb/core/decorators/misc.py

@@ -1,3 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2021 TheHamkerCat
+
+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 functools import wraps
 from time import time
 from time import time
 
 

+ 4 - 4
wbb/core/decorators/permissions.py

@@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 """
 """
 from functools import wraps
 from functools import wraps
+from traceback import format_exc as err
 
 
 from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
 from pyrogram.errors.exceptions.forbidden_403 import ChatWriteForbidden
 from pyrogram.types import Message
 from pyrogram.types import Message
@@ -37,10 +38,9 @@ async def authorised(func, subFunc2, client, message, *args, **kwargs):
     except ChatWriteForbidden:
     except ChatWriteForbidden:
         await app.leave_chat(chatID)
         await app.leave_chat(chatID)
     except Exception as e:
     except Exception as e:
-        try:
-            await message.reply_text(str(e))
-        except ChatWriteForbidden:
-            await app.leave_chat(chatID)
+        await message.reply_text(str(e.MESSAGE))
+        e = err()
+        print(str(e))
     return subFunc2
     return subFunc2
 
 
 
 

+ 109 - 0
wbb/core/filters.py

@@ -0,0 +1,109 @@
+"""
+MIT License
+
+Copyright (c) 2021 TheHamkerCat
+
+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 pyrogram import filters as filters_
+from pyrogram.types import Message
+
+from wbb import OWNER_ID, SUDOERS
+from wbb.modules.trust import get_spam_data
+from wbb.utils.functions import get_urls_from_text
+
+
+def url(_, __, message: Message) -> bool:
+    # Can't use entities to check for url because
+    # monospace removes url entity
+
+    # TODO Fix undetection of those urls which
+    # doesn't have schema, ex-facebook.com
+
+    text = message.text or message.caption
+    if not text:
+        return False
+    return bool(get_urls_from_text(text))
+
+
+async def spam(_, __, message: Message) -> bool:
+    text = message.text or message.caption
+    if not text:
+        return False
+    return (await get_spam_data(message, text)).is_spam
+
+
+async def admin(_, __, message: Message) -> bool:
+    if message.chat.type not in ["group", "supergroup"]:
+        return False
+    if not message.from_user:
+        if not message.sender_chat:
+            return False
+        return True
+    # Calling iter_chat_members again and again
+    # doesn't causes floodwaits, idk why, maybe it's
+    # cached or something, that's why using it.
+    return message.from_user.id in [
+        member.user.id
+        async for member in message._client.iter_chat_members(
+            message.chat.id, filter="administrators"
+        )
+    ]
+
+
+def entities(_, __, message: Message) -> bool:
+    return bool(message.entities)
+
+
+async def profanity(_, __, message: Message) -> bool:
+    text = message.text or message.caption
+    if not text:
+        return False
+    return (await get_spam_data(message, text)).profanity
+
+
+def anonymous(_, __, message: Message) -> bool:
+    return bool(message.sender_chat)
+
+
+def sudoers(_, __, message: Message) -> bool:
+    if not message.from_user:
+        return False
+    return message.from_user.id in SUDOERS
+
+
+def owner(_, __, message: Message) -> bool:
+    if not message.from_user:
+        return False
+    return message.from_user.id == OWNER_ID
+
+
+class Filters:
+    pass
+
+
+filters = Filters
+filters.url = filters_.create(url)
+filters.spam = filters_.create(spam)
+filters.admin = filters_.create(admin)
+filters.entities = filters_.create(entities)
+filters.profanity = filters_.create(profanity)
+filters.anonymous = filters_.create(anonymous)
+filters.sudoers = filters_.create(sudoers)
+filters.owner = filters_.create(owner)

+ 14 - 24
wbb/modules/images.py → wbb/core/keyboard.py

@@ -21,32 +21,22 @@ 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
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 """
 """
-import asyncio
-import json
-import urllib.request
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup
 
 
-from pyrogram import filters
+from wbb.utils.functions import get_urls_from_text
 
 
-from wbb import app
-from wbb.core.decorators.errors import capture_err
 
 
-__MODULE__ = "Images"
-__HELP__ = """/cat  - Get Cute Cats Images
-For more images search like wallpapers etc, use inline mode.
-"""
-
-
-async def delete_message_with_delay(delay, message):
-    await asyncio.sleep(delay)
-    await message.delete()
+def btn(text, data, type=None):
+    type = "url" if get_urls_from_text(data) else "callback_data"
+    return InlineKeyboardButton(text, **{type: data})
 
 
 
 
-@app.on_message(filters.command("cat") & ~filters.edited)
-@capture_err
-async def cat(_, message):
-    with urllib.request.urlopen(
-        "https://api.thecatapi.com/v1/images/search"
-    ) as url:
-        data = json.loads(url.read().decode())
-    cat_url = data[0]["url"]
-    await message.reply_photo(cat_url)
+def ikb(keyboard: list):
+    lines = []
+    for row in keyboard:
+        line = []
+        for button in row:
+            button = btn(*button)  # InlineKeyboardButton
+            line.append(button)
+        lines.append(line)
+    return InlineKeyboardMarkup(inline_keyboard=lines)

+ 23 - 0
wbb/core/types/InlineQueryResult.py

@@ -1,3 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2021 TheHamkerCat
+
+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 typing import List, Optional, Union
 
 
 import pyrogram
 import pyrogram

+ 142 - 144
wbb/modules/admin.py

@@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 """
 """
 import asyncio
 import asyncio
+from traceback import format_exc as err
 
 
 from pyrogram import filters
 from pyrogram import filters
 from pyrogram.types import (CallbackQuery, ChatPermissions,
 from pyrogram.types import (CallbackQuery, ChatPermissions,
@@ -30,8 +31,10 @@ from pyrogram.types import (CallbackQuery, ChatPermissions,
 
 
 from wbb import BOT_ID, SUDOERS, app
 from wbb import BOT_ID, SUDOERS, app
 from wbb.core.decorators.errors import capture_err
 from wbb.core.decorators.errors import capture_err
+from wbb.core.keyboard import ikb
 from wbb.utils.dbfunctions import (add_warn, get_warn, int_to_alpha,
 from wbb.utils.dbfunctions import (add_warn, get_warn, int_to_alpha,
                                    remove_warns)
                                    remove_warns)
+from wbb.utils.functions import extract_user, extract_user_and_reason
 
 
 __MODULE__ = "Admin"
 __MODULE__ = "Admin"
 __HELP__ = """/ban - Ban A User
 __HELP__ = """/ban - Ban A User
@@ -54,7 +57,10 @@ __HELP__ = """/ban - Ban A User
 
 
 async def member_permissions(chat_id: int, user_id: int):
 async def member_permissions(chat_id: int, user_id: int):
     perms = []
     perms = []
-    member = await app.get_chat_member(chat_id, user_id)
+    try:
+        member = await app.get_chat_member(chat_id, user_id)
+    except Exception:
+        return []
     if member.can_post_messages:
     if member.can_post_messages:
         perms.append("can_post_messages")
         perms.append("can_post_messages")
     if member.can_edit_messages:
     if member.can_edit_messages:
@@ -139,7 +145,7 @@ async def purgeFunc(client, message: Message):
         return
         return
     if not message.reply_to_message:
     if not message.reply_to_message:
         return await message.reply_text(
         return await message.reply_text(
-            "Reply To A Message To Delete From, Don't Make Fun Of Yourself!"
+            "Reply to a message to delete from, don't make fun of yourself!"
         )
         )
     await message.delete()
     await message.delete()
     for a_s_message_id in range(
     for a_s_message_id in range(
@@ -165,21 +171,28 @@ async def purgeFunc(client, message: Message):
 @app.on_message(filters.command("kick") & ~filters.edited)
 @app.on_message(filters.command("kick") & ~filters.edited)
 @adminsOnly("can_restrict_members")
 @adminsOnly("can_restrict_members")
 async def kickFunc(_, message: Message):
 async def kickFunc(_, message: Message):
-    if len(message.command) == 2:
-        user_id = (await app.get_users(message.text.split(None, 1)[1])).id
-    elif len(message.command) == 1 and message.reply_to_message:
-        user_id = message.reply_to_message.from_user.id
-    else:
+    user_id, reason = await extract_user_and_reason(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    if user_id == BOT_ID:
         return await message.reply_text(
         return await message.reply_text(
-            "Provide a username or reply to a user's message to kick."
+            "I can't kick myself, i can leave if you want."
         )
         )
     if user_id in SUDOERS:
     if user_id in SUDOERS:
-        await message.reply_text("You Wanna Kick The Elevated One?")
-    else:
-        await message.chat.kick_member(user_id)
-        await asyncio.sleep(1)
-        await message.reply_text("Kicked!")
-        await message.chat.unban_member(user_id)
+        return await message.reply_text("You Wanna Kick The Elevated One?")
+    if user_id in (await list_admins(message.chat.id)):
+        return await message.reply_text(
+            "I can't kick an admin, You know the rules, so do i."
+        )
+    mention = (await app.get_users(user_id)).mention
+    msg = f"""
+**Kicked User:** {mention}
+**Kicked By:** {message.from_user.mention if message.from_user else 'Anon'}
+**Reason:** {reason or 'No Reason Provided.'}"""
+    await message.chat.kick_member(user_id)
+    await message.reply_text(msg)
+    await asyncio.sleep(1)
+    await message.chat.unban_member(user_id)
 
 
 
 
 # Ban members
 # Ban members
@@ -188,19 +201,28 @@ async def kickFunc(_, message: Message):
 @app.on_message(filters.command("ban") & ~filters.edited)
 @app.on_message(filters.command("ban") & ~filters.edited)
 @adminsOnly("can_restrict_members")
 @adminsOnly("can_restrict_members")
 async def banFunc(_, message: Message):
 async def banFunc(_, message: Message):
-    if len(message.command) == 2:
-        user_id = (await app.get_users(message.text.split(None, 1)[1])).id
-    elif len(message.command) == 1 and message.reply_to_message:
-        user_id = message.reply_to_message.from_user.id
-    else:
+    user_id, reason = await extract_user_and_reason(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    if user_id == BOT_ID:
         return await message.reply_text(
         return await message.reply_text(
-            "Provide a username or reply to a user's message to ban."
+            "I can't ban myself, i can leave if you want."
         )
         )
     if user_id in SUDOERS:
     if user_id in SUDOERS:
-        await message.reply_text("You Wanna Ban The Elevated One?")
-    else:
-        await message.chat.kick_member(user_id)
-        await message.reply_text("Banned!")
+        return await message.reply_text(
+            "You Wanna Ban The Elevated One?, RECONSIDER!"
+        )
+    if user_id in (await list_admins(message.chat.id)):
+        return await message.reply_text(
+            "I can't ban an admin, You know the rules, so do i."
+        )
+    mention = (await app.get_users(user_id)).mention
+    msg = f"""
+**Banned User:** {mention}
+**Banned By:** {message.from_user.mention if message.from_user else 'Anon'}
+**Reason:** {reason or 'No Reason Provided.'}"""
+    await message.chat.kick_member(user_id)
+    await message.reply_text(msg)
 
 
 
 
 # Unban members
 # Unban members
@@ -209,6 +231,10 @@ async def banFunc(_, message: Message):
 @app.on_message(filters.command("unban") & ~filters.edited)
 @app.on_message(filters.command("unban") & ~filters.edited)
 @adminsOnly("can_restrict_members")
 @adminsOnly("can_restrict_members")
 async def unbanFunc(_, message: Message):
 async def unbanFunc(_, message: Message):
+    # we don't need reasons for unban, also, we
+    # don't need to get "text_mention" entity, because
+    # normal users won't get text_mention if the the user
+    # they want to unban is not in the group.
     if len(message.command) == 2:
     if len(message.command) == 2:
         user = message.text.split(None, 1)[1]
         user = message.text.split(None, 1)[1]
     elif len(message.command) == 1 and message.reply_to_message:
     elif len(message.command) == 1 and message.reply_to_message:
@@ -239,17 +265,14 @@ async def deleteFunc(_, message: Message):
 @app.on_message(filters.command("promote") & ~filters.edited)
 @app.on_message(filters.command("promote") & ~filters.edited)
 @adminsOnly("can_promote_members")
 @adminsOnly("can_promote_members")
 async def promoteFunc(_, message: Message):
 async def promoteFunc(_, message: Message):
-    chat_id = message.chat.id
-    bot = await app.get_chat_member(chat_id, BOT_ID)
-    if len(message.command) == 2:
-        username = message.text.split(None, 1)[1]
-        user_id = (await app.get_users(username)).id
-    elif len(message.command) == 1 and message.reply_to_message:
-        user_id = message.reply_to_message.from_user.id
-    else:
-        return await message.reply_text(
-            "Reply To A User's Message Or Give A Username To Promote."
-        )
+    user_id = await extract_user(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    bot = await app.get_chat_member(message.chat.id, BOT_ID)
+    if user_id == BOT_ID:
+        return await message.reply_text("I can't promote myself.")
+    if not bot.can_promote_members:
+        return await message.reply_text("I don't have enough permissions")
     await message.chat.promote_member(
     await message.chat.promote_member(
         user_id=user_id,
         user_id=user_id,
         can_change_info=bot.can_change_info,
         can_change_info=bot.can_change_info,
@@ -270,14 +293,18 @@ async def promoteFunc(_, message: Message):
 @app.on_message(filters.command("demote") & ~filters.edited)
 @app.on_message(filters.command("demote") & ~filters.edited)
 @adminsOnly("can_promote_members")
 @adminsOnly("can_promote_members")
 async def demote(_, message: Message):
 async def demote(_, message: Message):
-    if len(message.command) == 2:
-        username = message.text.split(None, 1)[1]
-        user_id = (await app.get_users(username)).id
-    elif len(message.command) == 1 and message.reply_to_message:
-        user_id = message.reply_to_message.from_user.id
-    else:
+    user_id = await extract_user(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    if user_id == BOT_ID:
+        return await message.reply_text("I can't demote myself.")
+    if user_id in SUDOERS:
+        return await message.reply_text(
+            "You wanna demote the elevated one?, RECONSIDER!"
+        )
+    if user_id in (await list_admins(message.chat.id)):
         return await message.reply_text(
         return await message.reply_text(
-            "Reply To A User's Message Or Give A Username To Demote."
+            "I can't demote an admin, You know the rules, so do i."
         )
         )
     await message.chat.promote_member(
     await message.chat.promote_member(
         user_id=user_id,
         user_id=user_id,
@@ -300,7 +327,7 @@ async def demote(_, message: Message):
 @adminsOnly("can_pin_messages")
 @adminsOnly("can_pin_messages")
 async def pin(_, message: Message):
 async def pin(_, message: Message):
     if not message.reply_to_message:
     if not message.reply_to_message:
-        return await message.reply_text("Reply To A Message To Pin.")
+        return await message.reply_text("Reply to a message to pin it.")
     await message.reply_to_message.pin(disable_notification=True)
     await message.reply_to_message.pin(disable_notification=True)
 
 
 
 
@@ -310,30 +337,27 @@ async def pin(_, message: Message):
 @app.on_message(filters.command("mute") & ~filters.edited)
 @app.on_message(filters.command("mute") & ~filters.edited)
 @adminsOnly("can_restrict_members")
 @adminsOnly("can_restrict_members")
 async def mute(_, message: Message):
 async def mute(_, message: Message):
-    if len(message.command) == 2:
-        user = await app.get_users(message.text.split(None, 1)[1])
-    elif len(message.command) == 1 and message.reply_to_message:
-        user = message.reply_to_message.from_user
-    else:
+    user_id, reason = await extract_user_and_reason(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    if user_id == BOT_ID:
+        return await message.reply_text("I can't mute myself.")
+    if user_id in SUDOERS:
         return await message.reply_text(
         return await message.reply_text(
-            "Provide a username or reply to a user's message to mute."
+            "You wanna mute the elevated one?, RECONSIDER!"
         )
         )
-    if user.id in SUDOERS:
-        return await message.reply_text("You Wanna Mute The Elevated One?")
-    await message.chat.restrict_member(user.id, permissions=ChatPermissions())
-    keyboard = InlineKeyboardMarkup(
-        [
-            [
-                InlineKeyboardButton(
-                    text="🚨   Unmute   🚨", callback_data=f"unmute_{user.id}"
-                )
-            ]
-        ]
-    )
-    await message.reply_text(
-        f"Enough freedom of speech, Muted {user.mention} !",
-        reply_markup=keyboard,
-    )
+    if user_id in (await list_admins(message.chat.id)):
+        return await message.reply_text(
+            "I can't mute an admin, You know the rules, so do i."
+        )
+    await message.chat.restrict_member(user_id, permissions=ChatPermissions())
+    mention = (await app.get_users(user_id)).mention
+    keyboard = ikb([[("🚨   Unmute   🚨", f"unmute_{user_id}")]])
+    msg = f"""
+**Muted User:** {mention}
+**Muted By:** {message.from_user.mention if message.from_user else 'Anon'}
+**Reason:** {reason or 'No Reason Provided.'}"""
+    await message.reply_text(msg, reply_markup=keyboard)
 
 
 
 
 # Unmute members
 # Unmute members
@@ -342,15 +366,10 @@ async def mute(_, message: Message):
 @app.on_message(filters.command("unmute") & ~filters.edited)
 @app.on_message(filters.command("unmute") & ~filters.edited)
 @adminsOnly("can_restrict_members")
 @adminsOnly("can_restrict_members")
 async def unmute(_, message: Message):
 async def unmute(_, message: Message):
-    if len(message.command) == 2:
-        user = message.text.split(None, 1)[1]
-    elif len(message.command) == 1 and message.reply_to_message:
-        user = message.reply_to_message.from_user.id
-    else:
-        return await message.reply_text(
-            "Provide a username or reply to a user's message to Unmute"
-        )
-    await message.chat.unban_member(user)
+    user_id = await extract_user(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    await message.chat.unban_member(user_id)
     await message.reply_text("Unmuted!")
     await message.reply_text("Unmuted!")
 
 
 
 
@@ -381,57 +400,51 @@ async def ban_deleted_accounts(_, message: Message):
 @app.on_message(filters.command("warn") & ~filters.edited)
 @app.on_message(filters.command("warn") & ~filters.edited)
 @adminsOnly("can_restrict_members")
 @adminsOnly("can_restrict_members")
 async def warn_user(_, message: Message):
 async def warn_user(_, message: Message):
-    if not message.reply_to_message:
-        return await message.reply_text("Reply to a message to warn a user.")
+    user_id, reason = await extract_user_and_reason(message)
     chat_id = message.chat.id
     chat_id = message.chat.id
-    user_id = message.reply_to_message.from_user.id
-    mention = message.reply_to_message.from_user.mention
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    if user_id == BOT_ID:
+        return await message.reply_text(
+            "I can't warn myself, i can leave if you want."
+        )
     if user_id in SUDOERS:
     if user_id in SUDOERS:
-        await message.reply_text("You Wanna Warn The Elevated One?")
-    elif user_id == BOT_ID:
-        await message.reply_text("Huh, Can't warn myself.")
-    elif user_id in await list_admins(message.chat.id):
-        await message.reply_text("Can't warn an admin.")
+        return await message.reply_text(
+            "You Wanna Warn The Elevated One?, RECONSIDER!"
+        )
+    if user_id in (await list_admins(chat_id)):
+        return await message.reply_text(
+            "I can't warn an admin, You know the rules, so do i."
+        )
+    if user_id not in (await list_members(chat_id)):
+        return await message.reply_text("This user isn't here.")
+    user, warns = await asyncio.gather(
+        app.get_users(user_id), get_warn(chat_id, await int_to_alpha(user_id))
+    )
+    mention = user.mention
+    keyboard = ikb([[("🚨  Remove Warn  🚨", f"unwarn_{user_id}")]])
+    if warns:
+        warns = warns["warns"]
     else:
     else:
-        if user_id in await list_members(chat_id):
-            warns = await get_warn(chat_id, await int_to_alpha(user_id))
-            keyboard = InlineKeyboardMarkup(
-                [
-                    [
-                        InlineKeyboardButton(
-                            text="🚨  Remove Warn  🚨",
-                            callback_data=f"unwarn_{user_id}",
-                        )
-                    ]
-                ]
-            )
-            if warns:
-                warns = warns["warns"]
-            else:
-                warn = {"warns": 1}
-                await add_warn(chat_id, await int_to_alpha(user_id), warn)
-                return await message.reply_text(
-                    f"Warned {mention} | 1/3 warnings now.",
-                    reply_markup=keyboard,
-                )
-            if warns >= 2:
-                await message.chat.kick_member(user_id)
-                await message.reply_text(
-                    f"Number of warns of {mention} exceeded, Banned!"
-                )
-                await remove_warns(chat_id, await int_to_alpha(user_id))
-            else:
-                warn = {"warns": warns + 1}
-
-                await message.reply_text(
-                    f"Warned {mention} | {warns+1}/3 warnings now.",
-                    reply_markup=keyboard,
-                )
-                return await add_warn(
-                    chat_id, await int_to_alpha(user_id), warn
-                )
-        else:
-            await message.reply_text("This user isn't here.")
+        warns = 0
+    if warns >= 2:
+        _, __, alpha = await asyncio.gather(
+            message.chat.kick_member(user_id),
+            message.reply_text(
+                "Number of warns of {mention} exceeded, BANNED!"
+            ),
+            int_to_alpha(user_id),
+        )
+        await remove_warns(chat_id, alpha)
+    else:
+        warn = {"warns": warns + 1}
+        msg = f"""
+**Warned User:** {mention}
+**Warned By:** {message.from_user.mention if message.from_user else 'Anon'}
+**Reason:** {reason or 'No Reason Provided.'}
+**Warns:** {warns + 1}/3"""
+        await message.reply_text(msg, reply_markup=keyboard)
+        await add_warn(chat_id, await int_to_alpha(user_id), warn)
 
 
 
 
 @app.on_callback_query(filters.regex("unwarn_"))
 @app.on_callback_query(filters.regex("unwarn_"))
@@ -489,31 +502,16 @@ async def remove_warnings(_, message: Message):
 @app.on_message(filters.command("warns") & ~filters.edited)
 @app.on_message(filters.command("warns") & ~filters.edited)
 @capture_err
 @capture_err
 async def check_warns(_, message: Message):
 async def check_warns(_, message: Message):
-    if not message.reply_to_message:
-        return await message.reply_text(
-            "Reply to a message to check a user's warnings."
-        )
-    user_id = message.reply_to_message.from_user.id
-    mention_user = message.reply_to_message.from_user.mention
-    mention_from_user = message.from_user.mention
-    chat_id = message.chat.id
-    if message.reply_to_message:
-        warns = await get_warn(chat_id, await int_to_alpha(user_id))
-        if warns:
-            warns = warns["warns"]
-        else:
-            return await message.reply_text(
-                f"{mention_user} have no warnings."
-            )
-        return await message.reply_text(
-            f"{mention_user} have {warns}/3 warnings."
-        )
-    warns = await get_warn(chat_id, await int_to_alpha(user_id))
+    user_id = await extract_user(message)
+    if not user_id:
+        return await message.reply_text("I can't find that user.")
+    warns = await get_warn(message.chat.id, await int_to_alpha(user_id))
+    mention = (await app.get_users(user_id)).mention
     if warns:
     if warns:
         warns = warns["warns"]
         warns = warns["warns"]
     else:
     else:
-        return await message.reply_text(f"{mention_user} have no warnings.")
-    await message.reply_text(f"{mention_from_user} have {warns}/3 warnings.")
+        return await message.reply_text(f"{mention} has no warnings.")
+    return await message.reply_text(f"{mention} has {warns}/3 warnings.")
 
 
 
 
 # Report
 # Report

+ 4 - 0
wbb/modules/admin_misc.py

@@ -52,6 +52,10 @@ async def set_chat_title(_, message):
 @app.on_message(filters.command("set_user_title") & ~filters.private)
 @app.on_message(filters.command("set_user_title") & ~filters.private)
 @adminsOnly("can_change_info")
 @adminsOnly("can_change_info")
 async def set_user_title(_, message):
 async def set_user_title(_, message):
+    if not message.reply_to_message:
+        return await message.reply_text("Reply to user's message to set his admin title")
+    if not message.reply_to_message.from_user:
+        return await message.reply_text("I can't change admin title of an unknown entity")
     chat_id = message.chat.id
     chat_id = message.chat.id
     from_user = message.reply_to_message.from_user
     from_user = message.reply_to_message.from_user
     if len(message.command) < 2:
     if len(message.command) < 2:

+ 2 - 2
wbb/modules/carbon.py

@@ -24,6 +24,6 @@ async def carbon_func(_, message):
     m = await message.reply_text("Preparing Carbon")
     m = await message.reply_text("Preparing Carbon")
     carbon = await make_carbon(message.reply_to_message.text)
     carbon = await make_carbon(message.reply_to_message.text)
     await m.edit("Uploading")
     await m.edit("Uploading")
-    await app.send_photo(message.chat.id, carbon)
+    await app.send_document(message.chat.id, carbon)
     await m.delete()
     await m.delete()
-    os.remove(carbon)
+    carbon.close()

+ 39 - 69
wbb/modules/chatbot.py

@@ -21,7 +21,9 @@ 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
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 """
 """
+from asyncio import sleep, gather
 from pyrogram import filters
 from pyrogram import filters
+from pyrogram.types import Message
 
 
 from wbb import (BOT_ID, SUDOERS, USERBOT_ID, USERBOT_PREFIX, USERBOT_USERNAME,
 from wbb import (BOT_ID, SUDOERS, USERBOT_ID, USERBOT_PREFIX, USERBOT_USERNAME,
                  app, app2, arq)
                  app, app2, arq)
@@ -37,43 +39,48 @@ __HELP__ = """
 active_chats_bot = []
 active_chats_bot = []
 active_chats_ubot = []
 active_chats_ubot = []
 
 
-
-# Enabled | Disable Chatbot
-
-
-@app.on_message(filters.command("chatbot") & ~filters.edited)
-@capture_err
-async def chatbot_status(_, message):
-    global active_chats_bot
-    if len(message.command) != 2:
-        return await message.reply_text("**Usage**\n/chatbot [ON|OFF]")
-    status = message.text.split(None, 1)[1]
+async def chat_bot_toggle(db, message):
+    status = message.text.split(None, 1)[1].lower()
     chat_id = message.chat.id
     chat_id = message.chat.id
-
-    if status == "ON" or status == "on" or status == "On":
-        if chat_id not in active_chats_bot:
-            active_chats_bot.append(chat_id)
+    if status == "on":
+        if chat_id not in db:
+            db.append(chat_id)
             text = (
             text = (
                 "Chatbot Enabled Reply To Any Message "
                 "Chatbot Enabled Reply To Any Message "
                 + "Of Mine To Get A Reply"
                 + "Of Mine To Get A Reply"
             )
             )
-            return await message.reply_text(text)
-        await message.reply_text("ChatBot Is Already Enabled.")
+            return await edit_or_reply(message, text=text)
+        await edit_or_reply(message, text="ChatBot Is Already Enabled.")
+    elif status == "off":
+        if chat_id in db:
+            db.remove(chat_id)
+            return await edit_or_reply(message, text="Chatbot Disabled!")
+        await edit_or_reply(message, text="ChatBot Is Already Disabled.")
+    else:
+        await edit_or_reply(message, text="**Usage**\n/chatbot [ON|OFF]")
 
 
-    elif status == "OFF" or status == "off" or status == "Off":
-        if chat_id in active_chats_bot:
-            active_chats_bot.remove(chat_id)
-            return await message.reply_text("Chatbot Disabled!")
-        await message.reply_text("ChatBot Is Already Disabled.")
+# Enabled | Disable Chatbot
 
 
-    else:
-        await message.reply_text("**Usage**\n/chatbot [ON|OFF]")
 
 
+@app.on_message(filters.command("chatbot") & ~filters.edited)
+@capture_err
+async def chatbot_status(_, message):
+    if len(message.command) != 2:
+        return await edit_or_reply(message, text="**Usage**\n/chatbot [ON|OFF]")
+    await chat_bot_toggle(active_chats_bot, message)
 
 
 async def lunaQuery(query: str, user_id: int):
 async def lunaQuery(query: str, user_id: int):
     luna = await arq.luna(query, user_id)
     luna = await arq.luna(query, user_id)
     return luna.result
     return luna.result
 
 
+async def type_and_send(message):
+    chat_id = message.chat.id
+    user_id = message.from_user.id if message.from_user else 0
+    query = message.text.strip()
+    await message._client.send_chat_action(chat_id, "typing")
+    response, _ = await gather(lunaQuery(query, user_id), sleep(3))
+    await message.reply_text(response)
+    await message._client.send_chat_action(chat_id, "cancel")
 
 
 @app.on_message(
 @app.on_message(
     filters.text
     filters.text
@@ -91,13 +98,7 @@ async def chatbot_talk(_, message):
         return
         return
     if message.reply_to_message.from_user.id != BOT_ID:
     if message.reply_to_message.from_user.id != BOT_ID:
         return
         return
-    query = message.text
-    await app.send_chat_action(message.chat.id, "typing")
-    response = await lunaQuery(
-        query, message.from_user.id if message.from_user else 0
-    )
-    await app.send_chat_action(message.chat.id, "cancel")
-    await message.reply_text(response)
+    await type_and_send(message)
 
 
 
 
 """ FOR USERBOT """
 """ FOR USERBOT """
@@ -110,32 +111,11 @@ async def chatbot_talk(_, message):
 )
 )
 @capture_err
 @capture_err
 async def chatbot_status_ubot(_, message):
 async def chatbot_status_ubot(_, message):
-    global active_chats_ubot
     if len(message.text.split()) != 2:
     if len(message.text.split()) != 2:
         return await edit_or_reply(
         return await edit_or_reply(
             message, text="**Usage**\n.chatbot [ON|OFF]"
             message, text="**Usage**\n.chatbot [ON|OFF]"
         )
         )
-    status = message.text.split(None, 1)[1]
-    chat_id = message.chat.id
-    if status == "ON" or status == "on" or status == "On":
-        if chat_id not in active_chats_ubot:
-            active_chats_ubot.append(chat_id)
-            text = (
-                "Chatbot Enabled Reply To Any Message "
-                + "Of Mine To Get A Reply"
-            )
-            return await edit_or_reply(message, text=text)
-        await edit_or_reply(message, text="ChatBot Is Already Enabled.")
-
-    elif status == "OFF" or status == "off" or status == "Off":
-        if chat_id in active_chats_ubot:
-            active_chats_ubot.remove(chat_id)
-            await edit_or_reply(message, text="Chatbot Disabled!")
-            return
-        await edit_or_reply(message, text="ChatBot Is Already Disabled.")
-
-    else:
-        await edit_or_reply(message, text="**Usage**\n/chatbot [ON|OFF]")
+    await chat_bot_toggle(active_chats_ubot, message)
 
 
 
 
 @app2.on_message(
 @app2.on_message(
@@ -147,22 +127,18 @@ async def chatbot_talk_ubot(_, message):
     if message.chat.id not in active_chats_ubot:
     if message.chat.id not in active_chats_ubot:
         return
         return
     username = "@" + str(USERBOT_USERNAME)
     username = "@" + str(USERBOT_USERNAME)
-    query = message.text
     if message.reply_to_message:
     if message.reply_to_message:
+        if not message.reply_to_message.from_user:
+            return
         if (
         if (
             message.reply_to_message.from_user.id != USERBOT_ID
             message.reply_to_message.from_user.id != USERBOT_ID
-            and username not in query
+            and username not in message.text
         ):
         ):
             return
             return
     else:
     else:
-        if username not in query:
+        if username not in message.text:
             return
             return
-    await app2.send_chat_action(message.chat.id, "typing")
-    response = await lunaQuery(
-        query, message.from_user.id if message.from_user else 0
-    )
-    await app2.send_chat_action(message.chat.id, "cancel")
-    await message.reply_text(response)
+    await type_and_send(message)
 
 
 
 
 @app2.on_message(
 @app2.on_message(
@@ -173,10 +149,4 @@ async def chatbot_talk_ubot(_, message):
 async def chatbot_talk_ubot_pm(_, message):
 async def chatbot_talk_ubot_pm(_, message):
     if message.chat.id not in active_chats_ubot:
     if message.chat.id not in active_chats_ubot:
         return
         return
-    query = message.text
-    await app2.send_chat_action(message.chat.id, "typing")
-    response = await lunaQuery(
-        query, message.from_user.id if message.from_user else 0
-    )
-    await message.reply_text(response)
-    await app2.send_chat_action(message.chat.id, "cancel")
+    await type_and_send(message)

+ 0 - 48
wbb/modules/covid.py

@@ -1,48 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2021 TheHamkerCat
-
-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 pyrogram import filters
-
-from wbb import app
-from wbb.core.decorators.errors import capture_err
-from wbb.utils.fetch import fetch
-from wbb.utils.json_prettify import json_prettify
-
-__MODULE__ = "Covid"
-__HELP__ = """/covid - To Get Global Stats of Covid.
-/covid [COUNTRY] - To Get Stats of A Single Country."""
-
-
-@app.on_message(filters.command("covid") & ~filters.edited)
-@capture_err
-async def covid(_, message):
-    if len(message.command) == 1:
-        data = await fetch("https://corona.lmao.ninja/v2/all")
-        data = await json_prettify(data)
-        return await app.send_message(message.chat.id, text=data)
-    if len(message.command) != 1:
-        country = message.text.split(None, 1)[1].strip()
-        country = country.replace(" ", "")
-        data = await fetch(f"https://corona.lmao.ninja/v2/countries/{country}")
-        data = await json_prettify(data)
-        await app.send_message(message.chat.id, text=data)

+ 1 - 1
wbb/modules/log.py

@@ -4,8 +4,8 @@ import aiofiles
 from pyrogram import filters
 from pyrogram import filters
 from pyrogram.types import CallbackQuery, Message
 from pyrogram.types import CallbackQuery, Message
 
 
-from pyromod.helpers import ikb
 from wbb import SUDOERS, app, log_file
 from wbb import SUDOERS, app, log_file
+from wbb.core.keyboard import ikb
 from wbb.utils.pastebin import paste
 from wbb.utils.pastebin import paste
 
 
 callback = "log_paste"
 callback = "log_paste"

+ 21 - 36
wbb/modules/misc.py

@@ -48,7 +48,8 @@ __HELP__ = """
 /tr [en] - Translate A Message
 /tr [en] - Translate A Message
 /json [URL] - Get JSON Response From An API or Something.
 /json [URL] - Get JSON Response From An API or Something.
 /arq - Statistics Of ARQ API.
 /arq - Statistics Of ARQ API.
-#RTFM - Check it lol
+/webss [URL] - Take A Screenshot Of A Webpage
+#RTFM - Tell noobs to read the manual
 """
 """
 
 
 
 
@@ -136,7 +137,6 @@ async def random(_, message):
             '"/random" Needs An Argurment.' " Ex: `/random 5`"
             '"/random" Needs An Argurment.' " Ex: `/random 5`"
         )
         )
     length = message.text.split(None, 1)[1]
     length = message.text.split(None, 1)[1]
-
     try:
     try:
         if 1 < int(length) < 1000:
         if 1 < int(length) < 1000:
             alphabet = string.ascii_letters + string.digits
             alphabet = string.ascii_letters + string.digits
@@ -148,10 +148,9 @@ async def random(_, message):
             await message.reply_text("Specify A Length Between 1-1000")
             await message.reply_text("Specify A Length Between 1-1000")
     except ValueError:
     except ValueError:
         await message.reply_text(
         await message.reply_text(
-            "Strings Won't Work!, Pass A" + " Positive Integer Between 1-1000"
+            "Strings Won't Work!, Pass A Positive Integer Less Than 1000"
         )
         )
 
 
-
 # Encrypt
 # Encrypt
 
 
 
 
@@ -218,21 +217,6 @@ async def cheat(_, message):
         await m.edit(str(e))
         await m.edit(str(e))
         print(str(e))
         print(str(e))
 
 
-
-# Weather
-
-
-@app.on_message(filters.command("weather") & ~filters.edited)
-@capture_err
-async def weather(_, message):
-    if len(message.command) != 2:
-        return await message.reply_text("/weather [city]")
-    city = message.text.split(None, 1)[1]
-    m = await message.reply_text("Fetching Data")
-    data = await fetch_text(f"https://wttr.in/{city}?mnTC0")
-    await m.edit(f"`{data}`")
-
-
 # Translate
 # Translate
 
 
 
 
@@ -262,35 +246,36 @@ async def tr(_, message):
 @app.on_message(filters.command("json") & ~filters.edited)
 @app.on_message(filters.command("json") & ~filters.edited)
 @capture_err
 @capture_err
 async def json_fetch(_, message):
 async def json_fetch(_, message):
-    global fetch_limit
     if len(message.command) != 2:
     if len(message.command) != 2:
         return await message.reply_text("/json [URL]")
         return await message.reply_text("/json [URL]")
     url = message.text.split(None, 1)[1]
     url = message.text.split(None, 1)[1]
+    m = await message.reply_text("Fetching")
     try:
     try:
         data = await fetch(url)
         data = await fetch(url)
         data = await json_prettify(data)
         data = await json_prettify(data)
-        fetch_limit += 1
         if len(data) < 4090:
         if len(data) < 4090:
-            await message.reply_text(data)
+            await m.edit(data)
         else:
         else:
             link = await paste(data)
             link = await paste(data)
-            await message.reply_text(
+            await m.edit(
                 f"[OUTPUT_TOO_LONG]({link})", disable_web_page_preview=True
                 f"[OUTPUT_TOO_LONG]({link})", disable_web_page_preview=True
             )
             )
     except Exception as e:
     except Exception as e:
-        await message.reply_text(str(e))
-        print(str(e))
+        await m.edit(str(e))
 
 
 
 
-@app.on_message(filters.command("bun"))
-async def bunn(_, message):
-    if message.reply_to_message:
-        await message.reply_to_message.reply_sticker(
-            "CAACAgUAAx0CWIlO9AABARyRYBhyjKXFATVhu7AGQwip3TzSFiMAAuMBAAJ7usBUIu2xBtXTmuweBA"
-        )
-        return await app.send_message(message.chat.id, text="Eat Bun")
-    if not message.reply_to_message:
-        await message.reply_sticker(
-            "CAACAgUAAx0CWIlO9AABARyRYBhyjKXFATVhu7AGQwip3TzSFiMAAuMBAAJ7usBUIu2xBtXTmuweBA"
+@app.on_message(filters.command("webss"))
+@capture_err
+async def take_ss(_, message):
+    if len(message.command) != 2:
+        return await message.reply_text("Give A Url To Fetch Screenshot.")
+    url = message.text.split(None, 1)[1]
+    m = await message.reply_text("**Uploading**")
+    try:
+        await app.send_photo(
+            message.chat.id,
+            photo=f"https://webshot.amanoteam.com/print?q={url}",
         )
         )
-        await app.send_message(message.chat.id, text="Eat Bun")
+    except Exception:
+        return await m.edit("No Such Website.")
+    await m.delete()

+ 0 - 172
wbb/modules/pipes.py

@@ -1,172 +0,0 @@
-"""
-MIT License
-
-Copyright (c) 2021 TheHamkerCat
-
-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
-
-from pyrogram import filters
-from pyrogram.types import Message
-
-from wbb import BOT_ID, SUDOERS, USERBOT_ID, app, app2
-from wbb.core.decorators.errors import capture_err
-from wbb.utils.dbfunctions import (activate_pipe, deactivate_pipe,
-                                   is_pipe_active, show_pipes)
-from wbb.utils.filter_groups import pipes_group
-
-__MODULE__ = "Pipes"
-__HELP__ = """
-**THIS MODULE IS ONLY FOR DEVS**
-
-Use this module to create a pipe that will forward messages of one chat/channel to another.
-
-
-/activate_pipe [FROM_CHAT_ID] [TO_CHAT_ID] [BOT|USERBOT]
-
-Active a pipe.
-
-choose 'BOT' or 'USERBOT' according to your needs, this will decide
-which client will fetch the message from 'FROM_CHAT'.
-
-
-/deactivate_pipe [FROM_CHAT_ID] [TO_CHAT_ID]
-
-Deactivete a pipe.
-
-
-/show_pipes
-
-Show all the active pipes.
-"""
-pipes_list_bot = []
-pipes_list_userbot = []
-
-
-async def load_pipes():
-    print("[INFO]: LOADING PIPES")
-    global pipes_list_bot, pipes_list_userbot
-    pipes_list_bot = []
-    pipes_list_userbot = []
-    pipes = await show_pipes()
-    for pipe in pipes:
-        if pipe["fetcher"] == "bot":
-            pipes_list_bot.append(pipe)
-            continue
-        pipes_list_userbot.append(pipe)
-    print("[INFO]: LOADED PIPES")
-
-
-loop = asyncio.get_running_loop()
-loop.create_task(load_pipes())
-
-
-@app.on_message(~filters.me, group=pipes_group)
-@capture_err
-async def pipes_worker_bot(_, message: Message):
-    for pipe in pipes_list_bot:
-        if pipe["from_chat_id"] == message.chat.id:
-            await message.forward(pipe["to_chat_id"])
-
-
-@app2.on_message(~filters.me, group=pipes_group)
-@capture_err
-async def pipes_worker_userbot(_, message: Message):
-    for pipe in pipes_list_userbot:
-        if pipe["from_chat_id"] == message.chat.id:
-            if not message.text:
-                m, temp = await asyncio.gather(
-                    app.listen(USERBOT_ID), message.copy(BOT_ID)
-                )
-                caption = f"Forwarded from `{pipe['from_chat_id']}`"
-                caption = (
-                    f"{temp.caption}\n\n{caption}" if temp.caption else caption
-                )
-                await app.copy_message(
-                    pipe["to_chat_id"],
-                    USERBOT_ID,
-                    m.message_id,
-                    caption=caption,
-                )
-                await asyncio.sleep(10)
-                await temp.delete()
-                return
-            caption = f"Forwarded from `{pipe['from_chat_id']}`"
-            await app.send_message(
-                pipe["to_chat_id"], text=message.text + "\n\n" + caption
-            )
-
-
-@app.on_message(filters.command("activate_pipe") & filters.user(SUDOERS))
-@capture_err
-async def activate_pipe_func(_, message: Message):
-    if len(message.command) != 4:
-        await message.reply_text(
-            "**Usage:**\n/activate_pipe [FROM_CHAT_ID] [TO_CHAT_ID] [BOT|USERBOT]"
-        )
-        return
-    text = message.text.strip().split()
-    from_chat = int(text[1])
-    to_chat = int(text[2])
-    fetcher = text[3].lower()
-    if fetcher != "bot" and fetcher != "userbot":
-        await message.reply_text("Wrong fetcher, see help menu.")
-        return
-    if await is_pipe_active(from_chat, to_chat):
-        await message.reply_text("This pipe is already active.")
-        return
-    await activate_pipe(from_chat, to_chat, fetcher)
-    await load_pipes()
-    await message.reply_text("Activated pipe.")
-
-
-@app.on_message(filters.command("deactivate_pipe") & filters.user(SUDOERS))
-@capture_err
-async def deactivate_pipe_func(_, message: Message):
-    if len(message.command) != 3:
-        await message.reply_text(
-            "**Usage:**\n/deactivate_pipe [FROM_CHAT_ID] [TO_CHAT_ID]"
-        )
-        return
-    text = message.text.strip().split()
-    from_chat = int(text[1])
-    to_chat = int(text[2])
-    if not await is_pipe_active(from_chat, to_chat):
-        await message.reply_text("This pipe is already inactive.")
-        return
-    await deactivate_pipe(from_chat, to_chat)
-    await load_pipes()
-    await message.reply_text("Deactivated pipe.")
-
-
-@app.on_message(filters.command("pipes") & filters.user(SUDOERS))
-@capture_err
-async def show_pipes_func(_, message: Message):
-    pipes = pipes_list_bot + pipes_list_userbot
-    if not pipes:
-        await message.reply_text("No pipe is active.")
-        return
-    text = ""
-    for count, pipe in enumerate(pipes, 1):
-        text += (
-            f"**Pipe:** `{count}`\n**From:** `{pipe['from_chat_id']}`\n"
-            + f"**To:** `{pipe['to_chat_id']}`\n**Fetcher:** `{pipe['fetcher']}`\n\n"
-        )
-    await message.reply_text(text)

+ 1 - 2
wbb/modules/quotly.py

@@ -123,11 +123,10 @@ async def quotly_func(client, message: Message):
         await m.delete()
         await m.delete()
         sticker.close()
         sticker.close()
     except Exception as e:
     except Exception as e:
-        await message.reply_text(
+        await m.edit(
             "Something wrong happened while quoting messages,"
             "Something wrong happened while quoting messages,"
             + " This error usually happens when there's a "
             + " This error usually happens when there's a "
             + " message containing something other than text."
             + " message containing something other than text."
         )
         )
-        await m.delete()
         e = format_exc()
         e = format_exc()
         print(e)
         print(e)

+ 11 - 6
wbb/modules/reddit.py

@@ -36,9 +36,10 @@ async def reddit(_, message):
     if len(message.command) != 2:
     if len(message.command) != 2:
         return await message.reply_text("/reddit needs an argument")
         return await message.reply_text("/reddit needs an argument")
     subreddit = message.text.split(None, 1)[1]
     subreddit = message.text.split(None, 1)[1]
+    m = await message.reply_text("Searching")
     reddit = await arq.reddit(subreddit)
     reddit = await arq.reddit(subreddit)
     if not reddit.ok:
     if not reddit.ok:
-        return await message.reply_text(reddit.result)
+        return await m.edit(reddit.result)
     reddit = reddit.result
     reddit = reddit.result
     nsfw = reddit.nsfw
     nsfw = reddit.nsfw
     sreddit = reddit.subreddit
     sreddit = reddit.subreddit
@@ -46,9 +47,13 @@ async def reddit(_, message):
     image = reddit.url
     image = reddit.url
     link = reddit.postLink
     link = reddit.postLink
     if nsfw:
     if nsfw:
-        return await message.reply_text("NSFW RESULTS COULD NOT BE SHOWN.")
-    caption = f"""**Title:** `{title}`
+        return await m.edit("NSFW RESULTS COULD NOT BE SHOWN.")
+    caption = f"""
+**Title:** `{title}`
 **Subreddit:** {sreddit}
 **Subreddit:** {sreddit}
-**PostLink:** {link}
-"""
-    await message.reply_photo(photo=image, caption=caption)
+**PostLink:** {link}"""
+    try:
+        await message.reply_photo(photo=image, caption=caption)
+        await m.delete()
+    except Exception as e:
+        await m.edit(e.MESSAGE)

+ 1 - 1
wbb/modules/taglogger.py

@@ -53,7 +53,7 @@ async def sendLog(message: Message):
 """
 """
     button = InlineKeyboard(row_width=1)
     button = InlineKeyboard(row_width=1)
     button.add(InlineKeyboardButton(text="Check Action", url=message.link))
     button.add(InlineKeyboardButton(text="Check Action", url=message.link))
-    await app.send_message(LOG_GROUP_ID, text=msg, reply_markup=button)
+    await app.send_message(LOG_GROUP_ID, text=msg, reply_markup=button, disable_web_page_preview=True)
 
 
 
 
 @app2.on_message(
 @app2.on_message(

+ 22 - 15
wbb/modules/tts.py

@@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 SOFTWARE.
 SOFTWARE.
 """
 """
 import traceback
 import traceback
+from asyncio import get_running_loop
 from io import BytesIO
 from io import BytesIO
 
 
 from googletrans import Translator
 from googletrans import Translator
@@ -34,25 +35,31 @@ from wbb import app
 __MODULE__ = "TTS"
 __MODULE__ = "TTS"
 __HELP__ = "/tts - Convert Text To Speech."
 __HELP__ = "/tts - Convert Text To Speech."
 
 
+def convert(text):
+    audio = BytesIO()
+    i = Translator().translate(text, dest="en")
+    lang = i.src
+    tts = gTTS(text, lang=lang)
+    audio.name = lang + ".mp3"
+    tts.write_to_fp(audio)
+    return audio
+
 
 
 @app.on_message(filters.command("tts"))
 @app.on_message(filters.command("tts"))
 async def text_to_speech(_, message: Message):
 async def text_to_speech(_, message: Message):
+    if not message.reply_to_message:
+        return await message.reply_text("Reply to some text ffs.")
+    if not message.reply_to_message.text:
+        return await message.reply_text("Reply to some text ffs.")
+    m = await message.reply_text("Processing")
+    text = message.reply_to_message.text
     try:
     try:
-        if message.reply_to_message:
-            if message.reply_to_message.text:
-                m = await message.reply_text("Processing")
-                audio = BytesIO()
-                text = message.reply_to_message.text
-                i = Translator().translate(text, dest="en")
-                lang = i.src
-                tts = gTTS(text, lang=lang)
-                audio.name = lang + ".mp3"
-                tts.write_to_fp(audio)
-                await m.delete()
-                await message.reply_audio(audio)
-                return audio.close()
-        await message.reply_text("Reply to some text ffs.")
+        loop = get_running_loop()
+        audio = await loop.run_in_executor(None, convert, text)
+        await message.reply_audio(audio)
+        await m.delete()
+        audio.close()
     except Exception as e:
     except Exception as e:
-        await message.reply_text(e)
+        await m.edit(e)
         e = traceback.format_exc()
         e = traceback.format_exc()
         print(e)
         print(e)

+ 0 - 21
wbb/modules/webss.py

@@ -27,25 +27,4 @@ from wbb import app
 from wbb.core.decorators.errors import capture_err
 from wbb.core.decorators.errors import capture_err
 
 
 __MODULE__ = "WebSS"
 __MODULE__ = "WebSS"
-__HELP__ = "/webss | .webss [URL] - Take A Screenshot Of A Webpage"
 
 
-
-@app.on_message(filters.command("webss"))
-@capture_err
-async def take_ss(_, message):
-    try:
-        if len(message.command) != 2:
-            return await message.reply_text("Give A Url To Fetch Screenshot.")
-        url = message.text.split(None, 1)[1]
-        m = await message.reply_text("**Taking Screenshot**")
-        await m.edit("**Uploading**")
-        try:
-            await app.send_photo(
-                message.chat.id,
-                photo=f"https://webshot.amanoteam.com/print?q={url}",
-            )
-        except TypeError:
-            return await m.edit("No Such Website.")
-        await m.delete()
-    except Exception as e:
-        await message.reply_text(str(e))

+ 0 - 3
wbb/modules/ytdl.py

@@ -68,7 +68,6 @@ async def ytdl_func(_, message):
         VIDEO_DATA[data] = {
         VIDEO_DATA[data] = {
             "url": url,
             "url": url,
             "title": title,
             "title": title,
-            "size": size,
             "quality": quality,
             "quality": quality,
             "duration": duration,
             "duration": duration,
             "format": format,
             "format": format,
@@ -99,12 +98,10 @@ async def ytdlCallback(_, cq):
         title = data["title"]
         title = data["title"]
         duration = data["duration"]
         duration = data["duration"]
         format = data["format"]
         format = data["format"]
-        size = data["size"]
         thumbnail = data["thumbnail"]
         thumbnail = data["thumbnail"]
         cc = data["cc"]
         cc = data["cc"]
         caption = f"""
         caption = f"""
 **Title:** {title}
 **Title:** {title}
-**Size:** {size}
 **Format:** {format}
 **Format:** {format}
 **Duration:** {await timeFormat(duration)}
 **Duration:** {await timeFormat(duration)}
 **CC:** {cc}
 **CC:** {cc}

+ 58 - 4
wbb/utils/functions.py

@@ -24,8 +24,10 @@ SOFTWARE.
 import codecs
 import codecs
 import pickle
 import pickle
 from asyncio import gather, get_running_loop
 from asyncio import gather, get_running_loop
+from io import BytesIO
 from math import atan2, cos, radians, sin, sqrt
 from math import atan2, cos, radians, sin, sqrt
 from random import randint
 from random import randint
+from re import findall
 
 
 import aiofiles
 import aiofiles
 import aiohttp
 import aiohttp
@@ -128,10 +130,8 @@ async def get_http_status_code(url: str) -> int:
 async def make_carbon(code):
 async def make_carbon(code):
     url = "https://carbonara.vercel.app/api/cook"
     url = "https://carbonara.vercel.app/api/cook"
     async with aiosession.post(url, json={"code": code}) as resp:
     async with aiosession.post(url, json={"code": code}) as resp:
-        data = await resp.read()
-    image = f"{randint(100, 10000)}.png"
-    async with aiofiles.open(image, mode="wb") as f:
-        await f.write(data)
+        image = BytesIO(await resp.read())
+    image.name = "carbon.png"
     return image
     return image
 
 
 
 
@@ -171,3 +171,57 @@ async def calc_distance_from_ip(ip1: str, ip2: str) -> float:
     c = 2 * atan2(sqrt(a), sqrt(1 - a))
     c = 2 * atan2(sqrt(a), sqrt(1 - a))
     distance = Radius_Earth * c
     distance = Radius_Earth * c
     return distance
     return distance
+
+
+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 extract_userid(message, text: str):
+    text = text.strip()
+    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
+    if entity.type == "text_mention":
+        return entity.user.id
+    return 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
+        if len(args) < 2:
+            reason = None
+        else:
+            reason = 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
+    elif 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())[0]

+ 2 - 2
wbb/utils/json_prettify.py

@@ -42,10 +42,10 @@ async def json_prettify(data):
     output = ""
     output = ""
     try:
     try:
         for key, value in data.items():
         for key, value in data.items():
-            output += f"**{key}:** `{value}`\n"
+            output += f"**{str(key).capitalize()}:** `{value}`\n"
     except Exception:
     except Exception:
         for datas in data:
         for datas in data:
             for key, value in datas.items():
             for key, value in datas.items():
-                output += f"**{key}:** `{value}`\n"
+                output += f"**{str(key).capitalize()}:** `{value}`\n"
             output += "------------------------\n"
             output += "------------------------\n"
     return output
     return output