├── .dockerignore ├── .gitignore ├── Dockerfile ├── InflexMusic ├── __init__.py ├── __main__.py ├── assets │ ├── Corbert W00 Heavy.ttf │ ├── font.ttf │ ├── font2.ttf │ ├── font3.ttf │ ├── play_icons.png │ └── shuffle_icon.png ├── core │ ├── bot.py │ ├── call.py │ ├── dir.py │ ├── git.py │ ├── mongo.py │ └── userbot.py ├── logging.py ├── misc.py ├── platforms │ ├── Apple.py │ ├── Carbon.py │ ├── Resso.py │ ├── Soundcloud.py │ ├── Spotify.py │ ├── Telegram.py │ ├── Youtube.py │ └── __init__.py ├── plugins │ ├── __init__.py │ ├── admins │ │ ├── auth.py │ │ ├── callback.py │ │ ├── loop.py │ │ ├── pause.py │ │ ├── resume.py │ │ ├── seek.py │ │ ├── shuffle.py │ │ ├── skip.py │ │ ├── speed.py │ │ └── stop.py │ ├── bot │ │ ├── help.py │ │ ├── inline.py │ │ ├── settings.py │ │ └── start.py │ ├── misc │ │ ├── autoleave.py │ │ ├── broadcast.py │ │ ├── seeker.py │ │ └── watcher.py │ ├── play │ │ ├── channel.py │ │ ├── live.py │ │ ├── play.py │ │ └── playmode.py │ ├── sudo │ │ ├── autoend.py │ │ ├── blchat.py │ │ ├── block.py │ │ ├── gban.py │ │ ├── logger.py │ │ ├── maintenance.py │ │ ├── restart.py │ │ └── sudoers.py │ └── tools │ │ ├── active.py │ │ ├── dev.py │ │ ├── language.py │ │ ├── ping.py │ │ ├── queue.py │ │ ├── reload.py │ │ ├── speedtest.py │ │ └── stats.py └── utils │ ├── __init__.py │ ├── channelplay.py │ ├── database.py │ ├── decorators │ ├── __init__.py │ ├── admins.py │ ├── language.py │ └── play.py │ ├── exceptions.py │ ├── extraction.py │ ├── formatters.py │ ├── inline │ ├── __init__.py │ ├── extras.py │ ├── help.py │ ├── play.py │ ├── queue.py │ ├── settings.py │ ├── song.py │ ├── speed.py │ ├── start.py │ └── stats.py │ ├── inlinequery.py │ ├── logger.py │ ├── pastebin.py │ ├── stream │ ├── autoclear.py │ ├── queue.py │ └── stream.py │ ├── sys.py │ └── thumbnails.py ├── LICENSE ├── Procfile ├── README.md ├── app.json ├── config.py ├── cookies └── addyourcookies.txt ├── heroku.yml ├── requirements.txt ├── runtime.txt ├── sample.env ├── setup ├── start └── strings ├── __init__.py ├── helpers.py └── langs ├── ar.yml ├── en.yml ├── hi.yml └── pa.yml /.dockerignore: -------------------------------------------------------------------------------- 1 | .env 2 | .cache 3 | log.txt 4 | .DS_Store 5 | *.session 6 | raw_files/ 7 | cache/ 8 | downloads/ 9 | __pycache__/ 10 | *.session-journal 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nikolaik/python-nodejs:python3.10-nodejs19 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y --no-install-recommends ffmpeg \ 5 | && apt-get clean \ 6 | && rm -rf /var/lib/apt/lists/* 7 | 8 | COPY . /app/ 9 | WORKDIR /app/ 10 | RUN pip3 install --no-cache-dir -U -r requirements.txt 11 | 12 | CMD bash start 13 | -------------------------------------------------------------------------------- /InflexMusic/__init__.py: -------------------------------------------------------------------------------- 1 | from InflexMusic.core.bot import Inflex 2 | from InflexMusic.core.dir import dirr 3 | from InflexMusic.core.git import git 4 | from InflexMusic.core.userbot import Userbot 5 | from InflexMusic.misc import dbb, heroku 6 | 7 | from .logging import LOGGER 8 | 9 | dirr() 10 | git() 11 | dbb() 12 | heroku() 13 | 14 | app = Inflex() 15 | userbot = Userbot() 16 | 17 | 18 | from .platforms import * 19 | 20 | Apple = AppleAPI() 21 | Carbon = CarbonAPI() 22 | SoundCloud = SoundAPI() 23 | Spotify = SpotifyAPI() 24 | Resso = RessoAPI() 25 | Telegram = TeleAPI() 26 | YouTube = YouTubeAPI() 27 | -------------------------------------------------------------------------------- /InflexMusic/__main__.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import importlib 3 | 4 | from pyrogram import idle 5 | from pytgcalls.exceptions import NoActiveGroupCall 6 | 7 | import config 8 | from InflexMusic import LOGGER, app, userbot 9 | from InflexMusic.core.call import Inflex 10 | from InflexMusic.misc import sudo 11 | from InflexMusic.plugins import ALL_MODULES 12 | from InflexMusic.utils.database import get_banned_users, get_gbanned 13 | from config import BANNED_USERS 14 | 15 | 16 | async def init(): 17 | if ( 18 | not config.STRING1 19 | and not config.STRING2 20 | and not config.STRING3 21 | and not config.STRING4 22 | and not config.STRING5 23 | ): 24 | LOGGER(__name__).error("Assistant client variables not defined, exiting...") 25 | exit() 26 | await sudo() 27 | try: 28 | users = await get_gbanned() 29 | for user_id in users: 30 | BANNED_USERS.add(user_id) 31 | users = await get_banned_users() 32 | for user_id in users: 33 | BANNED_USERS.add(user_id) 34 | except: 35 | pass 36 | await app.start() 37 | for all_module in ALL_MODULES: 38 | importlib.import_module("InflexMusic.plugins" + all_module) 39 | LOGGER("InflexMusic.plugins").info("Successfully Imported Modules...") 40 | await userbot.start() 41 | await Inflex.start() 42 | try: 43 | await Inflex.stream_call("https://te.legra.ph/file/29f784eb49d230ab62e9e.mp4") 44 | except NoActiveGroupCall: 45 | LOGGER("InflexMusic").error( 46 | "Please turn on the videochat of your log group\channel.\n\nStopping Bot..." 47 | ) 48 | exit() 49 | except: 50 | pass 51 | await Inflex.decorators() 52 | LOGGER("InflexMusic").info( 53 | "Inflex Music Bot Started Successfully" 54 | ) 55 | await idle() 56 | await app.stop() 57 | await userbot.stop() 58 | LOGGER("InflexMusic").info("Stopping Inflex Music Bot...") 59 | 60 | 61 | if __name__ == "__main__": 62 | asyncio.get_event_loop().run_until_complete(init()) 63 | -------------------------------------------------------------------------------- /InflexMusic/assets/Corbert W00 Heavy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamInflex/InflexMusicBot/2030d6a7a46c9ba4074adb0d1b14a5c8785ebf50/InflexMusic/assets/Corbert W00 Heavy.ttf -------------------------------------------------------------------------------- /InflexMusic/assets/font.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamInflex/InflexMusicBot/2030d6a7a46c9ba4074adb0d1b14a5c8785ebf50/InflexMusic/assets/font.ttf -------------------------------------------------------------------------------- /InflexMusic/assets/font2.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamInflex/InflexMusicBot/2030d6a7a46c9ba4074adb0d1b14a5c8785ebf50/InflexMusic/assets/font2.ttf -------------------------------------------------------------------------------- /InflexMusic/assets/font3.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamInflex/InflexMusicBot/2030d6a7a46c9ba4074adb0d1b14a5c8785ebf50/InflexMusic/assets/font3.ttf -------------------------------------------------------------------------------- /InflexMusic/assets/play_icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamInflex/InflexMusicBot/2030d6a7a46c9ba4074adb0d1b14a5c8785ebf50/InflexMusic/assets/play_icons.png -------------------------------------------------------------------------------- /InflexMusic/assets/shuffle_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TeamInflex/InflexMusicBot/2030d6a7a46c9ba4074adb0d1b14a5c8785ebf50/InflexMusic/assets/shuffle_icon.png -------------------------------------------------------------------------------- /InflexMusic/core/bot.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client, errors 2 | from pyrogram.enums import ChatMemberStatus, ParseMode 3 | 4 | import config 5 | 6 | from ..logging import LOGGER 7 | 8 | 9 | class Inflex(Client): 10 | def __init__(self): 11 | LOGGER(__name__).info(f"Starting Bot...") 12 | super().__init__( 13 | name="InflexMusic", 14 | api_id=config.API_ID, 15 | api_hash=config.API_HASH, 16 | bot_token=config.BOT_TOKEN, 17 | in_memory=True, 18 | parse_mode=ParseMode.HTML, 19 | max_concurrent_transmissions=7, 20 | ) 21 | 22 | async def start(self): 23 | await super().start() 24 | self.id = self.me.id 25 | self.name = self.me.first_name + " " + (self.me.last_name or "") 26 | self.username = self.me.username 27 | self.mention = self.me.mention 28 | 29 | try: 30 | await self.send_message( 31 | chat_id=config.LOG_GROUP_ID, 32 | text=f"» {self.mention} 𝖡𝗈𝗍 𝖲𝗍𝖺𝗋𝗍𝖾𝖽 :\n\n𝖨𝖣 : {self.id}\n𝖭𝖺𝗆𝖾 : {self.name}\n𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 : @{self.username}", 33 | ) 34 | except (errors.ChannelInvalid, errors.PeerIdInvalid): 35 | LOGGER(__name__).error( 36 | "Bot has failed to access the log group/channel. Make sure that you have added your bot to your log group/channel." 37 | ) 38 | exit() 39 | except Exception as ex: 40 | LOGGER(__name__).error( 41 | f"Bot has failed to access the log group/channel.\n Reason : {type(ex).__name__}." 42 | ) 43 | exit() 44 | 45 | a = await self.get_chat_member(config.LOG_GROUP_ID, self.id) 46 | if a.status != ChatMemberStatus.ADMINISTRATOR: 47 | LOGGER(__name__).error( 48 | "Please promote your bot as an admin in your log group/channel." 49 | ) 50 | exit() 51 | LOGGER(__name__).info(f"Music Bot Started As {self.name}") 52 | 53 | async def stop(self): 54 | await super().stop() 55 | -------------------------------------------------------------------------------- /InflexMusic/core/dir.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from ..logging import LOGGER 4 | 5 | 6 | def dirr(): 7 | for file in os.listdir(): 8 | if file.endswith(".jpg"): 9 | os.remove(file) 10 | elif file.endswith(".jpeg"): 11 | os.remove(file) 12 | elif file.endswith(".png"): 13 | os.remove(file) 14 | 15 | if "downloads" not in os.listdir(): 16 | os.mkdir("downloads") 17 | if "cache" not in os.listdir(): 18 | os.mkdir("cache") 19 | 20 | LOGGER(__name__).info("Directories Updated.") 21 | -------------------------------------------------------------------------------- /InflexMusic/core/git.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import shlex 3 | from typing import Tuple 4 | 5 | from git import Repo 6 | from git.exc import GitCommandError, InvalidGitRepositoryError 7 | 8 | import config 9 | 10 | from ..logging import LOGGER 11 | 12 | 13 | def install_req(cmd: str) -> Tuple[str, str, int, int]: 14 | async def install_requirements(): 15 | args = shlex.split(cmd) 16 | process = await asyncio.create_subprocess_exec( 17 | *args, 18 | stdout=asyncio.subprocess.PIPE, 19 | stderr=asyncio.subprocess.PIPE, 20 | ) 21 | stdout, stderr = await process.communicate() 22 | return ( 23 | stdout.decode("utf-8", "replace").strip(), 24 | stderr.decode("utf-8", "replace").strip(), 25 | process.returncode, 26 | process.pid, 27 | ) 28 | 29 | return asyncio.get_event_loop().run_until_complete(install_requirements()) 30 | 31 | 32 | def git(): 33 | REPO_LINK = config.UPSTREAM_REPO 34 | if config.GIT_TOKEN: 35 | GIT_USERNAME = REPO_LINK.split("com/")[1].split("/")[0] 36 | TEMP_REPO = REPO_LINK.split("https://")[1] 37 | UPSTREAM_REPO = f"https://{GIT_USERNAME}:{config.GIT_TOKEN}@{TEMP_REPO}" 38 | else: 39 | UPSTREAM_REPO = config.UPSTREAM_REPO 40 | try: 41 | repo = Repo() 42 | LOGGER(__name__).info(f"Git Client Found [VPS DEPLOYER]") 43 | except GitCommandError: 44 | LOGGER(__name__).info(f"Invalid Git Command") 45 | except InvalidGitRepositoryError: 46 | repo = Repo.init() 47 | if "origin" in repo.remotes: 48 | origin = repo.remote("origin") 49 | else: 50 | origin = repo.create_remote("origin", UPSTREAM_REPO) 51 | origin.fetch() 52 | repo.create_head( 53 | config.UPSTREAM_BRANCH, 54 | origin.refs[config.UPSTREAM_BRANCH], 55 | ) 56 | repo.heads[config.UPSTREAM_BRANCH].set_tracking_branch( 57 | origin.refs[config.UPSTREAM_BRANCH] 58 | ) 59 | repo.heads[config.UPSTREAM_BRANCH].checkout(True) 60 | try: 61 | repo.create_remote("origin", config.UPSTREAM_REPO) 62 | except BaseException: 63 | pass 64 | nrs = repo.remote("origin") 65 | nrs.fetch(config.UPSTREAM_BRANCH) 66 | try: 67 | nrs.pull(config.UPSTREAM_BRANCH) 68 | except GitCommandError: 69 | repo.git.reset("--hard", "FETCH_HEAD") 70 | install_req("pip3 install --no-cache-dir -r requirements.txt") 71 | LOGGER(__name__).info(f"Fetching updates from upstream repository...") 72 | -------------------------------------------------------------------------------- /InflexMusic/core/mongo.py: -------------------------------------------------------------------------------- 1 | from motor.motor_asyncio import AsyncIOMotorClient 2 | 3 | from config import MONGO_DB_URI 4 | 5 | from ..logging import LOGGER 6 | 7 | LOGGER(__name__).info("Connecting to your Mongo Database...") 8 | try: 9 | _mongo_async_ = AsyncIOMotorClient(MONGO_DB_URI) 10 | mongodb = _mongo_async_.Inflex 11 | LOGGER(__name__).info("Connected to your Mongo Database.") 12 | except: 13 | LOGGER(__name__).error("Failed to connect to your Mongo Database.") 14 | exit() 15 | -------------------------------------------------------------------------------- /InflexMusic/core/userbot.py: -------------------------------------------------------------------------------- 1 | from pyrogram import Client 2 | 3 | import config 4 | 5 | from ..logging import LOGGER 6 | 7 | assistants = [] 8 | assistantids = [] 9 | 10 | 11 | class Userbot(Client): 12 | def __init__(self): 13 | self.one = Client( 14 | name="InflexAss1", 15 | api_id=config.API_ID, 16 | api_hash=config.API_HASH, 17 | session_string=str(config.STRING1), 18 | no_updates=True, 19 | ) 20 | self.two = Client( 21 | name="InflexAss2", 22 | api_id=config.API_ID, 23 | api_hash=config.API_HASH, 24 | session_string=str(config.STRING2), 25 | no_updates=True, 26 | ) 27 | self.three = Client( 28 | name="InflexAss3", 29 | api_id=config.API_ID, 30 | api_hash=config.API_HASH, 31 | session_string=str(config.STRING3), 32 | no_updates=True, 33 | ) 34 | self.four = Client( 35 | name="InflexAss4", 36 | api_id=config.API_ID, 37 | api_hash=config.API_HASH, 38 | session_string=str(config.STRING4), 39 | no_updates=True, 40 | ) 41 | self.five = Client( 42 | name="InflexAss5", 43 | api_id=config.API_ID, 44 | api_hash=config.API_HASH, 45 | session_string=str(config.STRING5), 46 | no_updates=True, 47 | ) 48 | 49 | async def start(self): 50 | LOGGER(__name__).info(f"Starting Assistants...") 51 | if config.STRING1: 52 | await self.one.start() 53 | try: 54 | await self.one.join_chat("TeamInflex") 55 | await self.one.join_chat("InflexSupport") 56 | except: 57 | pass 58 | assistants.append(1) 59 | try: 60 | await self.one.send_message(config.LOG_GROUP_ID, "Assistant Started") 61 | except: 62 | LOGGER(__name__).error( 63 | "Assistant Account 1 has failed to access the log Group. Make sure that you have added your assistant to your log group and promoted as admin!" 64 | ) 65 | exit() 66 | self.one.id = self.one.me.id 67 | self.one.name = self.one.me.mention 68 | self.one.username = self.one.me.username 69 | assistantids.append(self.one.id) 70 | LOGGER(__name__).info(f"Assistant Started as {self.one.name}") 71 | 72 | if config.STRING2: 73 | await self.two.start() 74 | try: 75 | await self.two.join_chat("TeamInflex") 76 | await self.two.join_chat("InflexSupport") 77 | except: 78 | pass 79 | assistants.append(2) 80 | try: 81 | await self.two.send_message(config.LOG_GROUP_ID, "Assistant Started") 82 | except: 83 | LOGGER(__name__).error( 84 | "Assistant Account 2 has failed to access the log Group. Make sure that you have added your assistant to your log group and promoted as admin!" 85 | ) 86 | exit() 87 | self.two.id = self.two.me.id 88 | self.two.name = self.two.me.mention 89 | self.two.username = self.two.me.username 90 | assistantids.append(self.two.id) 91 | LOGGER(__name__).info(f"Assistant Two Started as {self.two.name}") 92 | 93 | if config.STRING3: 94 | await self.three.start() 95 | try: 96 | await self.three.join_chat("TeamInflex") 97 | await self.three.join_chat("InflexSupport") 98 | except: 99 | pass 100 | assistants.append(3) 101 | try: 102 | await self.three.send_message(config.LOG_GROUP_ID, "Assistant Started") 103 | except: 104 | LOGGER(__name__).error( 105 | "Assistant Account 3 has failed to access the log Group. Make sure that you have added your assistant to your log group and promoted as admin! " 106 | ) 107 | exit() 108 | self.three.id = self.three.me.id 109 | self.three.name = self.three.me.mention 110 | self.three.username = self.three.me.username 111 | assistantids.append(self.three.id) 112 | LOGGER(__name__).info(f"Assistant Three Started as {self.three.name}") 113 | 114 | if config.STRING4: 115 | await self.four.start() 116 | try: 117 | await self.four.join_chat("TeamInflex") 118 | await self.four.join_chat("InflexSupport") 119 | except: 120 | pass 121 | assistants.append(4) 122 | try: 123 | await self.four.send_message(config.LOG_GROUP_ID, "Assistant Started") 124 | except: 125 | LOGGER(__name__).error( 126 | "Assistant Account 4 has failed to access the log Group. Make sure that you have added your assistant to your log group and promoted as admin! " 127 | ) 128 | exit() 129 | self.four.id = self.four.me.id 130 | self.four.name = self.four.me.mention 131 | self.four.username = self.four.me.username 132 | assistantids.append(self.four.id) 133 | LOGGER(__name__).info(f"Assistant Four Started as {self.four.name}") 134 | 135 | if config.STRING5: 136 | await self.five.start() 137 | try: 138 | await self.five.join_chat("TeamInflex") 139 | await self.five.join_chat("InflexSupport") 140 | except: 141 | pass 142 | assistants.append(5) 143 | try: 144 | await self.five.send_message(config.LOG_GROUP_ID, "Assistant Started") 145 | except: 146 | LOGGER(__name__).error( 147 | "Assistant Account 5 has failed to access the log Group. Make sure that you have added your assistant to your log group and promoted as admin! " 148 | ) 149 | exit() 150 | self.five.id = self.five.me.id 151 | self.five.name = self.five.me.mention 152 | self.five.username = self.five.me.username 153 | assistantids.append(self.five.id) 154 | LOGGER(__name__).info(f"Assistant Five Started as {self.five.name}") 155 | 156 | async def stop(self): 157 | LOGGER(__name__).info(f"Stopping Assistants...") 158 | try: 159 | if config.STRING1: 160 | await self.one.stop() 161 | if config.STRING2: 162 | await self.two.stop() 163 | if config.STRING3: 164 | await self.three.stop() 165 | if config.STRING4: 166 | await self.four.stop() 167 | if config.STRING5: 168 | await self.five.stop() 169 | except: 170 | pass 171 | -------------------------------------------------------------------------------- /InflexMusic/logging.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | logging.basicConfig( 4 | level=logging.INFO, 5 | format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s", 6 | datefmt="%d-%b-%y %H:%M:%S", 7 | handlers=[ 8 | logging.FileHandler("log.txt"), 9 | logging.StreamHandler(), 10 | ], 11 | ) 12 | 13 | logging.getLogger("httpx").setLevel(logging.ERROR) 14 | logging.getLogger("pyrogram").setLevel(logging.ERROR) 15 | logging.getLogger("pytgcalls").setLevel(logging.ERROR) 16 | 17 | 18 | def LOGGER(name: str) -> logging.Logger: 19 | return logging.getLogger(name) 20 | -------------------------------------------------------------------------------- /InflexMusic/misc.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import time 3 | 4 | import heroku3 5 | from pyrogram import filters 6 | 7 | import config 8 | from InflexMusic.core.mongo import mongodb 9 | 10 | from .logging import LOGGER 11 | 12 | SUDOERS = filters.user() 13 | 14 | HAPP = None 15 | _boot_ = time.time() 16 | 17 | 18 | def is_heroku(): 19 | return "heroku" in socket.getfqdn() 20 | 21 | 22 | XCB = [ 23 | "/", 24 | "@", 25 | ".", 26 | "com", 27 | ":", 28 | "git", 29 | "heroku", 30 | "push", 31 | str(config.HEROKU_API_KEY), 32 | "https", 33 | str(config.HEROKU_APP_NAME), 34 | "HEAD", 35 | "master", 36 | ] 37 | 38 | 39 | def dbb(): 40 | global db 41 | db = {} 42 | LOGGER(__name__).info(f"Local Database Initialized.") 43 | 44 | 45 | async def sudo(): 46 | global SUDOERS 47 | SUDOERS.add(config.OWNER_ID) 48 | sudoersdb = mongodb.sudoers 49 | sudoers = await sudoersdb.find_one({"sudo": "sudo"}) 50 | sudoers = [] if not sudoers else sudoers["sudoers"] 51 | if config.OWNER_ID not in sudoers: 52 | sudoers.append(config.OWNER_ID) 53 | await sudoersdb.update_one( 54 | {"sudo": "sudo"}, 55 | {"$set": {"sudoers": sudoers}}, 56 | upsert=True, 57 | ) 58 | if sudoers: 59 | for user_id in sudoers: 60 | SUDOERS.add(user_id) 61 | LOGGER(__name__).info(f"Sudoers Loaded.") 62 | 63 | 64 | def heroku(): 65 | global HAPP 66 | if is_heroku: 67 | if config.HEROKU_API_KEY and config.HEROKU_APP_NAME: 68 | try: 69 | Heroku = heroku3.from_key(config.HEROKU_API_KEY) 70 | HAPP = Heroku.app(config.HEROKU_APP_NAME) 71 | LOGGER(__name__).info(f"Heroku App Configured") 72 | except BaseException: 73 | LOGGER(__name__).warning( 74 | f"Please make sure your Heroku API Key and Your App name are configured correctly in the heroku." 75 | ) 76 | -------------------------------------------------------------------------------- /InflexMusic/platforms/Apple.py: -------------------------------------------------------------------------------- 1 | import re 2 | from typing import Union 3 | 4 | import aiohttp 5 | from bs4 import BeautifulSoup 6 | from youtubesearchpython.__future__ import VideosSearch 7 | 8 | 9 | class AppleAPI: 10 | def __init__(self): 11 | self.regex = r"^(https:\/\/music.apple.com\/)(.*)$" 12 | self.base = "https://music.apple.com/in/playlist/" 13 | 14 | async def valid(self, link: str): 15 | if re.search(self.regex, link): 16 | return True 17 | else: 18 | return False 19 | 20 | async def track(self, url, playid: Union[bool, str] = None): 21 | if playid: 22 | url = self.base + url 23 | async with aiohttp.ClientSession() as session: 24 | async with session.get(url) as response: 25 | if response.status != 200: 26 | return False 27 | html = await response.text() 28 | soup = BeautifulSoup(html, "html.parser") 29 | search = None 30 | for tag in soup.find_all("meta"): 31 | if tag.get("property", None) == "og:title": 32 | search = tag.get("content", None) 33 | if search is None: 34 | return False 35 | results = VideosSearch(search, limit=1) 36 | for result in (await results.next())["result"]: 37 | title = result["title"] 38 | ytlink = result["link"] 39 | vidid = result["id"] 40 | duration_min = result["duration"] 41 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 42 | track_details = { 43 | "title": title, 44 | "link": ytlink, 45 | "vidid": vidid, 46 | "duration_min": duration_min, 47 | "thumb": thumbnail, 48 | } 49 | return track_details, vidid 50 | 51 | async def playlist(self, url, playid: Union[bool, str] = None): 52 | if playid: 53 | url = self.base + url 54 | playlist_id = url.split("playlist/")[1] 55 | async with aiohttp.ClientSession() as session: 56 | async with session.get(url) as response: 57 | if response.status != 200: 58 | return False 59 | html = await response.text() 60 | soup = BeautifulSoup(html, "html.parser") 61 | applelinks = soup.find_all("meta", attrs={"property": "music:song"}) 62 | results = [] 63 | for item in applelinks: 64 | try: 65 | xx = (((item["content"]).split("album/")[1]).split("/")[0]).replace( 66 | "-", " " 67 | ) 68 | except: 69 | xx = ((item["content"]).split("album/")[1]).split("/")[0] 70 | results.append(xx) 71 | return results, playlist_id 72 | -------------------------------------------------------------------------------- /InflexMusic/platforms/Carbon.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os.path import realpath 3 | 4 | import aiohttp 5 | from aiohttp import client_exceptions 6 | 7 | 8 | class UnableToFetchCarbon(Exception): 9 | pass 10 | 11 | 12 | themes = [ 13 | "3024-night", 14 | "a11y-dark", 15 | "blackboard", 16 | "base16-dark", 17 | "base16-light", 18 | "cobalt", 19 | "duotone-dark", 20 | "dracula-pro", 21 | "hopscotch", 22 | "lucario", 23 | "material", 24 | "monokai", 25 | "nightowl", 26 | "nord", 27 | "oceanic-next", 28 | "one-light", 29 | "one-dark", 30 | "panda-syntax", 31 | "parasio-dark", 32 | "seti", 33 | "shades-of-purple", 34 | "solarized+dark", 35 | "solarized+light", 36 | "synthwave-84", 37 | "twilight", 38 | "verminal", 39 | "vscode", 40 | "yeti", 41 | "zenburn", 42 | ] 43 | 44 | colour = [ 45 | "#FF0000", 46 | "#FF5733", 47 | "#FFFF00", 48 | "#008000", 49 | "#0000FF", 50 | "#800080", 51 | "#A52A2A", 52 | "#FF00FF", 53 | "#D2B48C", 54 | "#00FFFF", 55 | "#808000", 56 | "#800000", 57 | "#00FFFF", 58 | "#30D5C8", 59 | "#00FF00", 60 | "#008080", 61 | "#4B0082", 62 | "#EE82EE", 63 | "#FFC0CB", 64 | "#000000", 65 | "#FFFFFF", 66 | "#808080", 67 | ] 68 | 69 | 70 | class CarbonAPI: 71 | def __init__(self): 72 | self.language = "auto" 73 | self.drop_shadow = True 74 | self.drop_shadow_blur = "68px" 75 | self.drop_shadow_offset = "20px" 76 | self.font_family = "JetBrains Mono" 77 | self.width_adjustment = True 78 | self.watermark = False 79 | 80 | async def generate(self, text: str, user_id): 81 | async with aiohttp.ClientSession( 82 | headers={"Content-Type": "application/json"}, 83 | ) as ses: 84 | params = { 85 | "code": text, 86 | } 87 | params["backgroundColor"] = random.choice(colour) 88 | params["theme"] = random.choice(themes) 89 | params["dropShadow"] = self.drop_shadow 90 | params["dropShadowOffsetY"] = self.drop_shadow_offset 91 | params["dropShadowBlurRadius"] = self.drop_shadow_blur 92 | params["fontFamily"] = self.font_family 93 | params["language"] = self.language 94 | params["watermark"] = self.watermark 95 | params["widthAdjustment"] = self.width_adjustment 96 | try: 97 | request = await ses.post( 98 | "https://carbonara.solopov.dev/api/cook", 99 | json=params, 100 | ) 101 | except client_exceptions.ClientConnectorError: 102 | raise UnableToFetchCarbon("Can not reach the Host!") 103 | resp = await request.read() 104 | with open(f"cache/carbon{user_id}.jpg", "wb") as f: 105 | f.write(resp) 106 | return realpath(f.name) 107 | -------------------------------------------------------------------------------- /InflexMusic/platforms/Resso.py: -------------------------------------------------------------------------------- 1 | import re 2 | from typing import Union 3 | 4 | import aiohttp 5 | from bs4 import BeautifulSoup 6 | from youtubesearchpython.__future__ import VideosSearch 7 | 8 | 9 | class RessoAPI: 10 | def __init__(self): 11 | self.regex = r"^(https:\/\/m.resso.com\/)(.*)$" 12 | self.base = "https://m.resso.com/" 13 | 14 | async def valid(self, link: str): 15 | if re.search(self.regex, link): 16 | return True 17 | else: 18 | return False 19 | 20 | async def track(self, url, playid: Union[bool, str] = None): 21 | if playid: 22 | url = self.base + url 23 | async with aiohttp.ClientSession() as session: 24 | async with session.get(url) as response: 25 | if response.status != 200: 26 | return False 27 | html = await response.text() 28 | soup = BeautifulSoup(html, "html.parser") 29 | for tag in soup.find_all("meta"): 30 | if tag.get("property", None) == "og:title": 31 | title = tag.get("content", None) 32 | if tag.get("property", None) == "og:description": 33 | des = tag.get("content", None) 34 | try: 35 | des = des.split("·")[0] 36 | except: 37 | pass 38 | if des == "": 39 | return 40 | results = VideosSearch(title, limit=1) 41 | for result in (await results.next())["result"]: 42 | title = result["title"] 43 | ytlink = result["link"] 44 | vidid = result["id"] 45 | duration_min = result["duration"] 46 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 47 | track_details = { 48 | "title": title, 49 | "link": ytlink, 50 | "vidid": vidid, 51 | "duration_min": duration_min, 52 | "thumb": thumbnail, 53 | } 54 | return track_details, vidid 55 | -------------------------------------------------------------------------------- /InflexMusic/platforms/Soundcloud.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | 3 | from yt_dlp import YoutubeDL 4 | 5 | from InflexMusic.utils.formatters import seconds_to_min 6 | 7 | 8 | class SoundAPI: 9 | def __init__(self): 10 | self.opts = { 11 | "outtmpl": "downloads/%(id)s.%(ext)s", 12 | "format": "best", 13 | "retries": 3, 14 | "nooverwrites": False, 15 | "continuedl": True, 16 | } 17 | 18 | async def valid(self, link: str): 19 | if "soundcloud" in link: 20 | return True 21 | else: 22 | return False 23 | 24 | async def download(self, url): 25 | d = YoutubeDL(self.opts) 26 | try: 27 | info = d.extract_info(url) 28 | except: 29 | return False 30 | xyz = path.join("downloads", f"{info['id']}.{info['ext']}") 31 | duration_min = seconds_to_min(info["duration"]) 32 | track_details = { 33 | "title": info["title"], 34 | "duration_sec": info["duration"], 35 | "duration_min": duration_min, 36 | "uploader": info["uploader"], 37 | "filepath": xyz, 38 | } 39 | return track_details, xyz 40 | -------------------------------------------------------------------------------- /InflexMusic/platforms/Spotify.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | import spotipy 4 | from spotipy.oauth2 import SpotifyClientCredentials 5 | from youtubesearchpython.__future__ import VideosSearch 6 | 7 | import config 8 | 9 | 10 | class SpotifyAPI: 11 | def __init__(self): 12 | self.regex = r"^(https:\/\/open.spotify.com\/)(.*)$" 13 | self.client_id = config.SPOTIFY_CLIENT_ID 14 | self.client_secret = config.SPOTIFY_CLIENT_SECRET 15 | if config.SPOTIFY_CLIENT_ID and config.SPOTIFY_CLIENT_SECRET: 16 | self.client_credentials_manager = SpotifyClientCredentials( 17 | self.client_id, self.client_secret 18 | ) 19 | self.spotify = spotipy.Spotify( 20 | client_credentials_manager=self.client_credentials_manager 21 | ) 22 | else: 23 | self.spotify = None 24 | 25 | async def valid(self, link: str): 26 | if re.search(self.regex, link): 27 | return True 28 | else: 29 | return False 30 | 31 | async def track(self, link: str): 32 | track = self.spotify.track(link) 33 | info = track["name"] 34 | for artist in track["artists"]: 35 | fetched = f' {artist["name"]}' 36 | if "Various Artists" not in fetched: 37 | info += fetched 38 | results = VideosSearch(info, limit=1) 39 | for result in (await results.next())["result"]: 40 | ytlink = result["link"] 41 | title = result["title"] 42 | vidid = result["id"] 43 | duration_min = result["duration"] 44 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 45 | track_details = { 46 | "title": title, 47 | "link": ytlink, 48 | "vidid": vidid, 49 | "duration_min": duration_min, 50 | "thumb": thumbnail, 51 | } 52 | return track_details, vidid 53 | 54 | async def playlist(self, url): 55 | playlist = self.spotify.playlist(url) 56 | playlist_id = playlist["id"] 57 | results = [] 58 | for item in playlist["tracks"]["items"]: 59 | music_track = item["track"] 60 | info = music_track["name"] 61 | for artist in music_track["artists"]: 62 | fetched = f' {artist["name"]}' 63 | if "Various Artists" not in fetched: 64 | info += fetched 65 | results.append(info) 66 | return results, playlist_id 67 | 68 | async def album(self, url): 69 | album = self.spotify.album(url) 70 | album_id = album["id"] 71 | results = [] 72 | for item in album["tracks"]["items"]: 73 | info = item["name"] 74 | for artist in item["artists"]: 75 | fetched = f' {artist["name"]}' 76 | if "Various Artists" not in fetched: 77 | info += fetched 78 | results.append(info) 79 | 80 | return ( 81 | results, 82 | album_id, 83 | ) 84 | 85 | async def artist(self, url): 86 | artistinfo = self.spotify.artist(url) 87 | artist_id = artistinfo["id"] 88 | results = [] 89 | artisttoptracks = self.spotify.artist_top_tracks(url) 90 | for item in artisttoptracks["tracks"]: 91 | info = item["name"] 92 | for artist in item["artists"]: 93 | fetched = f' {artist["name"]}' 94 | if "Various Artists" not in fetched: 95 | info += fetched 96 | results.append(info) 97 | 98 | return results, artist_id 99 | -------------------------------------------------------------------------------- /InflexMusic/platforms/Telegram.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import time 4 | from typing import Union 5 | 6 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Voice 7 | 8 | import config 9 | from InflexMusic import app 10 | from InflexMusic.utils.formatters import ( 11 | check_duration, 12 | convert_bytes, 13 | get_readable_time, 14 | seconds_to_min, 15 | ) 16 | 17 | 18 | class TeleAPI: 19 | def __init__(self): 20 | self.chars_limit = 4096 21 | self.sleep = 5 22 | 23 | async def send_split_text(self, message, string): 24 | n = self.chars_limit 25 | out = [(string[i : i + n]) for i in range(0, len(string), n)] 26 | j = 0 27 | for x in out: 28 | if j <= 2: 29 | j += 1 30 | await message.reply_text(x, disable_web_page_preview=True) 31 | return True 32 | 33 | async def get_link(self, message): 34 | return message.link 35 | 36 | async def get_filename(self, file, audio: Union[bool, str] = None): 37 | try: 38 | file_name = file.file_name 39 | if file_name is None: 40 | file_name = "ᴛᴇʟᴇɢʀᴀᴍ ᴀᴜᴅɪᴏ" if audio else "ᴛᴇʟᴇɢʀᴀᴍ ᴠɪᴅᴇᴏ" 41 | except: 42 | file_name = "ᴛᴇʟᴇɢʀᴀᴍ ᴀᴜᴅɪᴏ" if audio else "ᴛᴇʟᴇɢʀᴀᴍ ᴠɪᴅᴇᴏ" 43 | return file_name 44 | 45 | async def get_duration(self, file): 46 | try: 47 | dur = seconds_to_min(file.duration) 48 | except: 49 | dur = "Unknown" 50 | return dur 51 | 52 | async def get_duration(self, filex, file_path): 53 | try: 54 | dur = seconds_to_min(filex.duration) 55 | except: 56 | try: 57 | dur = await asyncio.get_event_loop().run_in_executor( 58 | None, check_duration, file_path 59 | ) 60 | dur = seconds_to_min(dur) 61 | except: 62 | return "Unknown" 63 | return dur 64 | 65 | async def get_filepath( 66 | self, 67 | audio: Union[bool, str] = None, 68 | video: Union[bool, str] = None, 69 | ): 70 | if audio: 71 | try: 72 | file_name = ( 73 | audio.file_unique_id 74 | + "." 75 | + ( 76 | (audio.file_name.split(".")[-1]) 77 | if (not isinstance(audio, Voice)) 78 | else "ogg" 79 | ) 80 | ) 81 | except: 82 | file_name = audio.file_unique_id + "." + "ogg" 83 | file_name = os.path.join(os.path.realpath("downloads"), file_name) 84 | if video: 85 | try: 86 | file_name = ( 87 | video.file_unique_id + "." + (video.file_name.split(".")[-1]) 88 | ) 89 | except: 90 | file_name = video.file_unique_id + "." + "mp4" 91 | file_name = os.path.join(os.path.realpath("downloads"), file_name) 92 | return file_name 93 | 94 | async def download(self, _, message, mystic, fname): 95 | lower = [0, 8, 17, 38, 64, 77, 96] 96 | higher = [5, 10, 20, 40, 66, 80, 99] 97 | checker = [5, 10, 20, 40, 66, 80, 99] 98 | speed_counter = {} 99 | if os.path.exists(fname): 100 | return True 101 | 102 | async def down_load(): 103 | async def progress(current, total): 104 | if current == total: 105 | return 106 | current_time = time.time() 107 | start_time = speed_counter.get(message.id) 108 | check_time = current_time - start_time 109 | upl = InlineKeyboardMarkup( 110 | [ 111 | [ 112 | InlineKeyboardButton( 113 | text="ᴄᴀɴᴄᴇʟ", 114 | callback_data="stop_downloading", 115 | ), 116 | ] 117 | ] 118 | ) 119 | percentage = current * 100 / total 120 | percentage = str(round(percentage, 2)) 121 | speed = current / check_time 122 | eta = int((total - current) / speed) 123 | eta = get_readable_time(eta) 124 | if not eta: 125 | eta = "0 sᴇᴄᴏɴᴅs" 126 | total_size = convert_bytes(total) 127 | completed_size = convert_bytes(current) 128 | speed = convert_bytes(speed) 129 | percentage = int((percentage.split("."))[0]) 130 | for counter in range(7): 131 | low = int(lower[counter]) 132 | high = int(higher[counter]) 133 | check = int(checker[counter]) 134 | if low < percentage <= high: 135 | if high == check: 136 | try: 137 | await mystic.edit_text( 138 | text=_["tg_1"].format( 139 | app.mention, 140 | total_size, 141 | completed_size, 142 | percentage[:5], 143 | speed, 144 | eta, 145 | ), 146 | reply_markup=upl, 147 | ) 148 | checker[counter] = 100 149 | except: 150 | pass 151 | 152 | speed_counter[message.id] = time.time() 153 | try: 154 | await app.download_media( 155 | message.reply_to_message, 156 | file_name=fname, 157 | progress=progress, 158 | ) 159 | try: 160 | elapsed = get_readable_time( 161 | int(int(time.time()) - int(speed_counter[message.id])) 162 | ) 163 | except: 164 | elapsed = "0 sᴇᴄᴏɴᴅs" 165 | await mystic.edit_text(_["tg_2"].format(elapsed)) 166 | except: 167 | await mystic.edit_text(_["tg_3"]) 168 | 169 | task = asyncio.create_task(down_load()) 170 | config.lyrical[mystic.id] = task 171 | await task 172 | verify = config.lyrical.get(mystic.id) 173 | if not verify: 174 | return False 175 | config.lyrical.pop(mystic.id) 176 | return True 177 | -------------------------------------------------------------------------------- /InflexMusic/platforms/__init__.py: -------------------------------------------------------------------------------- 1 | from .Apple import AppleAPI 2 | from .Carbon import CarbonAPI 3 | from .Resso import RessoAPI 4 | from .Soundcloud import SoundAPI 5 | from .Spotify import SpotifyAPI 6 | from .Telegram import TeleAPI 7 | from .Youtube import YouTubeAPI 8 | -------------------------------------------------------------------------------- /InflexMusic/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | import glob 2 | from os.path import dirname, isfile 3 | 4 | 5 | def __list_all_modules(): 6 | work_dir = dirname(__file__) 7 | mod_paths = glob.glob(work_dir + "/*/*.py") 8 | 9 | all_modules = [ 10 | (((f.replace(work_dir, "")).replace("/", "."))[:-3]) 11 | for f in mod_paths 12 | if isfile(f) and f.endswith(".py") and not f.endswith("__init__.py") 13 | ] 14 | 15 | return all_modules 16 | 17 | 18 | ALL_MODULES = sorted(__list_all_modules()) 19 | __all__ = ALL_MODULES + ["ALL_MODULES"] 20 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/auth.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.utils import extract_user, int_to_alpha 6 | from InflexMusic.utils.database import ( 7 | delete_authuser, 8 | get_authuser, 9 | get_authuser_names, 10 | save_authuser, 11 | ) 12 | from InflexMusic.utils.decorators import AdminActual, language 13 | from InflexMusic.utils.inline import close_markup 14 | from config import BANNED_USERS, adminlist 15 | 16 | 17 | @app.on_message(filters.command("auth") & filters.group & ~BANNED_USERS) 18 | @AdminActual 19 | async def auth(client, message: Message, _): 20 | if not message.reply_to_message: 21 | if len(message.command) != 2: 22 | return await message.reply_text(_["general_1"]) 23 | user = await extract_user(message) 24 | token = await int_to_alpha(user.id) 25 | _check = await get_authuser_names(message.chat.id) 26 | count = len(_check) 27 | if int(count) == 25: 28 | return await message.reply_text(_["auth_1"]) 29 | if token not in _check: 30 | assis = { 31 | "auth_user_id": user.id, 32 | "auth_name": user.first_name, 33 | "admin_id": message.from_user.id, 34 | "admin_name": message.from_user.first_name, 35 | } 36 | get = adminlist.get(message.chat.id) 37 | if get: 38 | if user.id not in get: 39 | get.append(user.id) 40 | await save_authuser(message.chat.id, token, assis) 41 | return await message.reply_text(_["auth_2"].format(user.mention)) 42 | else: 43 | return await message.reply_text(_["auth_3"].format(user.mention)) 44 | 45 | 46 | @app.on_message(filters.command("unauth") & filters.group & ~BANNED_USERS) 47 | @AdminActual 48 | async def unauthusers(client, message: Message, _): 49 | if not message.reply_to_message: 50 | if len(message.command) != 2: 51 | return await message.reply_text(_["general_1"]) 52 | user = await extract_user(message) 53 | token = await int_to_alpha(user.id) 54 | deleted = await delete_authuser(message.chat.id, token) 55 | get = adminlist.get(message.chat.id) 56 | if get: 57 | if user.id in get: 58 | get.remove(user.id) 59 | if deleted: 60 | return await message.reply_text(_["auth_4"].format(user.mention)) 61 | else: 62 | return await message.reply_text(_["auth_5"].format(user.mention)) 63 | 64 | 65 | @app.on_message( 66 | filters.command(["authlist", "authusers"]) & filters.group & ~BANNED_USERS 67 | ) 68 | @language 69 | async def authusers(client, message: Message, _): 70 | _wtf = await get_authuser_names(message.chat.id) 71 | if not _wtf: 72 | return await message.reply_text(_["setting_4"]) 73 | else: 74 | j = 0 75 | mystic = await message.reply_text(_["auth_6"]) 76 | text = _["auth_7"].format(message.chat.title) 77 | for umm in _wtf: 78 | _umm = await get_authuser(message.chat.id, umm) 79 | user_id = _umm["auth_user_id"] 80 | admin_id = _umm["admin_id"] 81 | admin_name = _umm["admin_name"] 82 | try: 83 | user = (await app.get_users(user_id)).first_name 84 | j += 1 85 | except: 86 | continue 87 | text += f"{j}➤ {user}[{user_id}]\n" 88 | text += f" {_['auth_8']} {admin_name}[{admin_id}]\n\n" 89 | await mystic.edit_text(text, reply_markup=close_markup(_)) 90 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/loop.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.utils.database import get_loop, set_loop 6 | from InflexMusic.utils.decorators import AdminRightsCheck 7 | from InflexMusic.utils.inline import close_markup 8 | from config import BANNED_USERS 9 | 10 | 11 | @app.on_message(filters.command(["loop", "cloop"]) & filters.group & ~BANNED_USERS) 12 | @AdminRightsCheck 13 | async def admins(cli, message: Message, _, chat_id): 14 | usage = _["admin_17"] 15 | if len(message.command) != 2: 16 | return await message.reply_text(usage) 17 | state = message.text.split(None, 1)[1].strip() 18 | if state.isnumeric(): 19 | state = int(state) 20 | if 1 <= state <= 10: 21 | got = await get_loop(chat_id) 22 | if got != 0: 23 | state = got + state 24 | if int(state) > 10: 25 | state = 10 26 | await set_loop(chat_id, state) 27 | return await message.reply_text( 28 | text=_["admin_18"].format(state, message.from_user.mention), 29 | reply_markup=close_markup(_), 30 | ) 31 | else: 32 | return await message.reply_text(_["admin_17"]) 33 | elif state.lower() == "enable": 34 | await set_loop(chat_id, 10) 35 | return await message.reply_text( 36 | text=_["admin_18"].format(state, message.from_user.mention), 37 | reply_markup=close_markup(_), 38 | ) 39 | elif state.lower() == "disable": 40 | await set_loop(chat_id, 0) 41 | return await message.reply_text( 42 | _["admin_19"].format(message.from_user.mention), 43 | reply_markup=close_markup(_), 44 | ) 45 | else: 46 | return await message.reply_text(usage) 47 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/pause.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.core.call import Inflex 6 | from InflexMusic.utils.database import is_music_playing, music_off 7 | from InflexMusic.utils.decorators import AdminRightsCheck 8 | from InflexMusic.utils.inline import close_markup 9 | from config import BANNED_USERS 10 | 11 | 12 | @app.on_message(filters.command(["pause", "cpause"]) & filters.group & ~BANNED_USERS) 13 | @AdminRightsCheck 14 | async def pause_admin(cli, message: Message, _, chat_id): 15 | if not await is_music_playing(chat_id): 16 | return await message.reply_text(_["admin_1"]) 17 | await music_off(chat_id) 18 | await Inflex.pause_stream(chat_id) 19 | await message.reply_text( 20 | _["admin_2"].format(message.from_user.mention), reply_markup=close_markup(_) 21 | ) 22 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/resume.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.core.call import Inflex 6 | from InflexMusic.utils.database import is_music_playing, music_on 7 | from InflexMusic.utils.decorators import AdminRightsCheck 8 | from InflexMusic.utils.inline import close_markup 9 | from config import BANNED_USERS 10 | 11 | 12 | @app.on_message(filters.command(["resume", "cresume"]) & filters.group & ~BANNED_USERS) 13 | @AdminRightsCheck 14 | async def resume_com(cli, message: Message, _, chat_id): 15 | if await is_music_playing(chat_id): 16 | return await message.reply_text(_["admin_3"]) 17 | await music_on(chat_id) 18 | await Inflex.resume_stream(chat_id) 19 | await message.reply_text( 20 | _["admin_4"].format(message.from_user.mention), reply_markup=close_markup(_) 21 | ) 22 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/seek.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import YouTube, app 5 | from InflexMusic.core.call import Inflex 6 | from InflexMusic.misc import db 7 | from InflexMusic.utils import AdminRightsCheck, seconds_to_min 8 | from InflexMusic.utils.inline import close_markup 9 | from config import BANNED_USERS 10 | 11 | 12 | @app.on_message( 13 | filters.command(["seek", "cseek", "seekback", "cseekback"]) 14 | & filters.group 15 | & ~BANNED_USERS 16 | ) 17 | @AdminRightsCheck 18 | async def seek_comm(cli, message: Message, _, chat_id): 19 | if len(message.command) == 1: 20 | return await message.reply_text(_["admin_20"]) 21 | query = message.text.split(None, 1)[1].strip() 22 | if not query.isnumeric(): 23 | return await message.reply_text(_["admin_21"]) 24 | playing = db.get(chat_id) 25 | if not playing: 26 | return await message.reply_text(_["queue_2"]) 27 | duration_seconds = int(playing[0]["seconds"]) 28 | if duration_seconds == 0: 29 | return await message.reply_text(_["admin_22"]) 30 | file_path = playing[0]["file"] 31 | duration_played = int(playing[0]["played"]) 32 | duration_to_skip = int(query) 33 | duration = playing[0]["dur"] 34 | if message.command[0][-2] == "c": 35 | if (duration_played - duration_to_skip) <= 10: 36 | return await message.reply_text( 37 | text=_["admin_23"].format(seconds_to_min(duration_played), duration), 38 | reply_markup=close_markup(_), 39 | ) 40 | to_seek = duration_played - duration_to_skip + 1 41 | else: 42 | if (duration_seconds - (duration_played + duration_to_skip)) <= 10: 43 | return await message.reply_text( 44 | text=_["admin_23"].format(seconds_to_min(duration_played), duration), 45 | reply_markup=close_markup(_), 46 | ) 47 | to_seek = duration_played + duration_to_skip + 1 48 | mystic = await message.reply_text(_["admin_24"]) 49 | if "vid_" in file_path: 50 | n, file_path = await YouTube.video(playing[0]["vidid"], True) 51 | if n == 0: 52 | return await message.reply_text(_["admin_22"]) 53 | check = (playing[0]).get("speed_path") 54 | if check: 55 | file_path = check 56 | if "index_" in file_path: 57 | file_path = playing[0]["vidid"] 58 | try: 59 | await Inflex.seek_stream( 60 | chat_id, 61 | file_path, 62 | seconds_to_min(to_seek), 63 | duration, 64 | playing[0]["streamtype"], 65 | ) 66 | except: 67 | return await mystic.edit_text(_["admin_26"], reply_markup=close_markup(_)) 68 | if message.command[0][-2] == "c": 69 | db[chat_id][0]["played"] -= duration_to_skip 70 | else: 71 | db[chat_id][0]["played"] += duration_to_skip 72 | await mystic.edit_text( 73 | text=_["admin_25"].format(seconds_to_min(to_seek), message.from_user.mention), 74 | reply_markup=close_markup(_), 75 | ) 76 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/shuffle.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from pyrogram import filters 4 | from pyrogram.types import Message 5 | 6 | from InflexMusic import app 7 | from InflexMusic.misc import db 8 | from InflexMusic.utils.decorators import AdminRightsCheck 9 | from InflexMusic.utils.inline import close_markup 10 | from config import BANNED_USERS 11 | 12 | 13 | @app.on_message( 14 | filters.command(["shuffle", "cshuffle"]) & filters.group & ~BANNED_USERS 15 | ) 16 | @AdminRightsCheck 17 | async def admins(Client, message: Message, _, chat_id): 18 | check = db.get(chat_id) 19 | if not check: 20 | return await message.reply_text(_["queue_2"]) 21 | try: 22 | popped = check.pop(0) 23 | except: 24 | return await message.reply_text(_["admin_15"], reply_markup=close_markup(_)) 25 | check = db.get(chat_id) 26 | if not check: 27 | check.insert(0, popped) 28 | return await message.reply_text(_["admin_15"], reply_markup=close_markup(_)) 29 | random.shuffle(check) 30 | check.insert(0, popped) 31 | await message.reply_text( 32 | _["admin_16"].format(message.from_user.mention), reply_markup=close_markup(_) 33 | ) 34 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/speed.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.core.call import Inflex 6 | from InflexMusic.misc import SUDOERS, db 7 | from InflexMusic.utils import AdminRightsCheck 8 | from InflexMusic.utils.database import is_active_chat, is_nonadmin_chat 9 | from InflexMusic.utils.decorators.language import languageCB 10 | from InflexMusic.utils.inline import close_markup, speed_markup 11 | from config import BANNED_USERS, adminlist 12 | 13 | checker = [] 14 | 15 | 16 | @app.on_message( 17 | filters.command(["cspeed", "speed", "cslow", "slow", "playback", "cplayback"]) 18 | & filters.group 19 | & ~BANNED_USERS 20 | ) 21 | @AdminRightsCheck 22 | async def playback(cli, message: Message, _, chat_id): 23 | playing = db.get(chat_id) 24 | if not playing: 25 | return await message.reply_text(_["queue_2"]) 26 | duration_seconds = int(playing[0]["seconds"]) 27 | if duration_seconds == 0: 28 | return await message.reply_text(_["admin_27"]) 29 | file_path = playing[0]["file"] 30 | if "downloads" not in file_path: 31 | return await message.reply_text(_["admin_27"]) 32 | upl = speed_markup(_, chat_id) 33 | return await message.reply_text( 34 | text=_["admin_28"].format(app.mention), 35 | reply_markup=upl, 36 | ) 37 | 38 | 39 | @app.on_callback_query(filters.regex("SpeedUP") & ~BANNED_USERS) 40 | @languageCB 41 | async def del_back_playlist(client, CallbackQuery, _): 42 | callback_data = CallbackQuery.data.strip() 43 | callback_request = callback_data.split(None, 1)[1] 44 | chat, speed = callback_request.split("|") 45 | chat_id = int(chat) 46 | if not await is_active_chat(chat_id): 47 | return await CallbackQuery.answer(_["general_5"], show_alert=True) 48 | is_non_admin = await is_nonadmin_chat(CallbackQuery.message.chat.id) 49 | if not is_non_admin: 50 | if CallbackQuery.from_user.id not in SUDOERS: 51 | admins = adminlist.get(CallbackQuery.message.chat.id) 52 | if not admins: 53 | return await CallbackQuery.answer(_["admin_13"], show_alert=True) 54 | else: 55 | if CallbackQuery.from_user.id not in admins: 56 | return await CallbackQuery.answer(_["admin_14"], show_alert=True) 57 | playing = db.get(chat_id) 58 | if not playing: 59 | return await CallbackQuery.answer(_["queue_2"], show_alert=True) 60 | duration_seconds = int(playing[0]["seconds"]) 61 | if duration_seconds == 0: 62 | return await CallbackQuery.answer(_["admin_27"], show_alert=True) 63 | file_path = playing[0]["file"] 64 | if "downloads" not in file_path: 65 | return await CallbackQuery.answer(_["admin_27"], show_alert=True) 66 | checkspeed = (playing[0]).get("speed") 67 | if checkspeed: 68 | if str(checkspeed) == str(speed): 69 | if str(speed) == str("1.0"): 70 | return await CallbackQuery.answer( 71 | _["admin_29"], 72 | show_alert=True, 73 | ) 74 | else: 75 | if str(speed) == str("1.0"): 76 | return await CallbackQuery.answer( 77 | _["admin_29"], 78 | show_alert=True, 79 | ) 80 | if chat_id in checker: 81 | return await CallbackQuery.answer( 82 | _["admin_30"], 83 | show_alert=True, 84 | ) 85 | else: 86 | checker.append(chat_id) 87 | try: 88 | await CallbackQuery.answer( 89 | _["admin_31"], 90 | ) 91 | except: 92 | pass 93 | mystic = await CallbackQuery.edit_message_text( 94 | text=_["admin_32"].format(CallbackQuery.from_user.mention), 95 | ) 96 | try: 97 | await Inflex.speedup_stream( 98 | chat_id, 99 | file_path, 100 | speed, 101 | playing, 102 | ) 103 | except: 104 | if chat_id in checker: 105 | checker.remove(chat_id) 106 | return await mystic.edit_text(_["admin_33"], reply_markup=close_markup(_)) 107 | if chat_id in checker: 108 | checker.remove(chat_id) 109 | await mystic.edit_text( 110 | text=_["admin_34"].format(speed, CallbackQuery.from_user.mention), 111 | reply_markup=close_markup(_), 112 | ) 113 | -------------------------------------------------------------------------------- /InflexMusic/plugins/admins/stop.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.core.call import Inflex 6 | from InflexMusic.utils.database import set_loop 7 | from InflexMusic.utils.decorators import AdminRightsCheck 8 | from InflexMusic.utils.inline import close_markup 9 | from config import BANNED_USERS 10 | 11 | 12 | @app.on_message( 13 | filters.command(["end", "stop", "cend", "cstop"]) & filters.group & ~BANNED_USERS 14 | ) 15 | @AdminRightsCheck 16 | async def stop_music(cli, message: Message, _, chat_id): 17 | if not len(message.command) == 1: 18 | return 19 | await Inflex.stop_stream(chat_id) 20 | await set_loop(chat_id, 0) 21 | await message.reply_text( 22 | _["admin_5"].format(message.from_user.mention), reply_markup=close_markup(_) 23 | ) 24 | -------------------------------------------------------------------------------- /InflexMusic/plugins/bot/help.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram import filters, types 4 | from pyrogram.types import InlineKeyboardMarkup, Message 5 | 6 | from InflexMusic import app 7 | from InflexMusic.utils import help_pannel 8 | from InflexMusic.utils.database import get_lang 9 | from InflexMusic.utils.decorators.language import LanguageStart, languageCB 10 | from InflexMusic.utils.inline.help import help_back_markup, private_help_panel 11 | from config import BANNED_USERS, START_IMG_URL, SUPPORT_GROUP 12 | from strings import get_string, helpers 13 | 14 | 15 | @app.on_message(filters.command(["help"]) & filters.private & ~BANNED_USERS) 16 | @app.on_callback_query(filters.regex("settings_back_helper") & ~BANNED_USERS) 17 | async def helper_private( 18 | client: app, update: Union[types.Message, types.CallbackQuery] 19 | ): 20 | is_callback = isinstance(update, types.CallbackQuery) 21 | if is_callback: 22 | try: 23 | await update.answer() 24 | except: 25 | pass 26 | chat_id = update.message.chat.id 27 | language = await get_lang(chat_id) 28 | _ = get_string(language) 29 | keyboard = help_pannel(_, True) 30 | await update.edit_message_text( 31 | _["help_1"].format(SUPPORT_GROUP), reply_markup=keyboard 32 | ) 33 | else: 34 | try: 35 | await update.delete() 36 | except: 37 | pass 38 | language = await get_lang(update.chat.id) 39 | _ = get_string(language) 40 | keyboard = help_pannel(_) 41 | await update.reply_photo( 42 | photo=START_IMG_URL, 43 | caption=_["help_1"].format(SUPPORT_GROUP), 44 | reply_markup=keyboard, 45 | ) 46 | 47 | 48 | @app.on_message(filters.command(["help"]) & filters.group & ~BANNED_USERS) 49 | @LanguageStart 50 | async def help_com_group(client, message: Message, _): 51 | keyboard = private_help_panel(_) 52 | await message.reply_text(_["help_2"], reply_markup=InlineKeyboardMarkup(keyboard)) 53 | 54 | 55 | @app.on_callback_query(filters.regex("help_callback") & ~BANNED_USERS) 56 | @languageCB 57 | async def helper_cb(client, CallbackQuery, _): 58 | callback_data = CallbackQuery.data.strip() 59 | cb = callback_data.split(None, 1)[1] 60 | keyboard = help_back_markup(_) 61 | if cb == "hb1": 62 | await CallbackQuery.edit_message_text(helpers.HELP_1, reply_markup=keyboard) 63 | elif cb == "hb2": 64 | await CallbackQuery.edit_message_text(helpers.HELP_2, reply_markup=keyboard) 65 | elif cb == "hb3": 66 | await CallbackQuery.edit_message_text(helpers.HELP_3, reply_markup=keyboard) 67 | elif cb == "hb4": 68 | await CallbackQuery.edit_message_text(helpers.HELP_4, reply_markup=keyboard) 69 | elif cb == "hb5": 70 | await CallbackQuery.edit_message_text(helpers.HELP_5, reply_markup=keyboard) 71 | elif cb == "hb6": 72 | await CallbackQuery.edit_message_text(helpers.HELP_6, reply_markup=keyboard) 73 | elif cb == "hb7": 74 | await CallbackQuery.edit_message_text(helpers.HELP_7, reply_markup=keyboard) 75 | elif cb == "hb8": 76 | await CallbackQuery.edit_message_text(helpers.HELP_8, reply_markup=keyboard) 77 | elif cb == "hb9": 78 | await CallbackQuery.edit_message_text(helpers.HELP_9, reply_markup=keyboard) 79 | elif cb == "hb10": 80 | await CallbackQuery.edit_message_text(helpers.HELP_10, reply_markup=keyboard) 81 | elif cb == "hb11": 82 | await CallbackQuery.edit_message_text(helpers.HELP_11, reply_markup=keyboard) 83 | elif cb == "hb12": 84 | await CallbackQuery.edit_message_text(helpers.HELP_12, reply_markup=keyboard) 85 | elif cb == "hb13": 86 | await CallbackQuery.edit_message_text(helpers.HELP_13, reply_markup=keyboard) 87 | elif cb == "hb14": 88 | await CallbackQuery.edit_message_text(helpers.HELP_14, reply_markup=keyboard) 89 | elif cb == "hb15": 90 | await CallbackQuery.edit_message_text(helpers.HELP_15, reply_markup=keyboard) 91 | -------------------------------------------------------------------------------- /InflexMusic/plugins/bot/inline.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import ( 2 | InlineKeyboardButton, 3 | InlineKeyboardMarkup, 4 | InlineQueryResultPhoto, 5 | ) 6 | from youtubesearchpython.__future__ import VideosSearch 7 | 8 | from InflexMusic import app 9 | from InflexMusic.utils.inlinequery import answer 10 | from config import BANNED_USERS 11 | 12 | 13 | @app.on_inline_query(~BANNED_USERS) 14 | async def inline_query_handler(client, query): 15 | text = query.query.strip().lower() 16 | answers = [] 17 | if text.strip() == "": 18 | try: 19 | await client.answer_inline_query(query.id, results=answer, cache_time=10) 20 | except: 21 | return 22 | else: 23 | a = VideosSearch(text, limit=20) 24 | result = (await a.next()).get("result") 25 | for x in range(15): 26 | title = (result[x]["title"]).title() 27 | duration = result[x]["duration"] 28 | views = result[x]["viewCount"]["short"] 29 | thumbnail = result[x]["thumbnails"][0]["url"].split("?")[0] 30 | channellink = result[x]["channel"]["link"] 31 | channel = result[x]["channel"]["name"] 32 | link = result[x]["link"] 33 | published = result[x]["publishedTime"] 34 | description = f"{views} | {duration} ᴍɪɴᴜᴛᴇs | {channel} | {published}" 35 | buttons = InlineKeyboardMarkup( 36 | [ 37 | [ 38 | InlineKeyboardButton( 39 | text="𝖸𝗈𝗎𝖳𝗎𝖻𝖾 🎄", 40 | url=link, 41 | ) 42 | ], 43 | ] 44 | ) 45 | searched_text = f""" 46 | ❄ ᴛɪᴛʟᴇ : {title} 47 | 48 | ⏳ 𝖣𝗎𝗋𝖺𝗍𝗂𝗈𝗇 : {duration} ᴍɪɴᴜᴛᴇs 49 | 👀 𝖵𝗂𝖾𝗐𝗌 : {views} 50 | 🎥 𝖢𝗁𝖺𝗇𝗇𝖾𝗅 : {channel} 51 | ⏰ 𝖯𝗎𝖻𝗅𝗂𝗌𝗁𝖾𝖽 𝖮𝗇 : {published} 52 | 53 | 54 | ➻ ɪɴʟɪɴᴇ sᴇᴀʀᴄʜ ᴍᴏᴅᴇ ʙʏ {app.name}""" 55 | answers.append( 56 | InlineQueryResultPhoto( 57 | photo_url=thumbnail, 58 | title=title, 59 | thumb_url=thumbnail, 60 | description=description, 61 | caption=searched_text, 62 | reply_markup=buttons, 63 | ) 64 | ) 65 | try: 66 | return await client.answer_inline_query(query.id, results=answers) 67 | except: 68 | return 69 | -------------------------------------------------------------------------------- /InflexMusic/plugins/bot/start.py: -------------------------------------------------------------------------------- 1 | import time 2 | import random 3 | 4 | from pyrogram import filters 5 | from pyrogram.enums import ChatType 6 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message 7 | from youtubesearchpython.__future__ import VideosSearch 8 | 9 | import config 10 | from config import START_IMG_URL 11 | from InflexMusic import app 12 | from InflexMusic.misc import _boot_ 13 | from InflexMusic.plugins.sudo.sudoers import sudoers_list 14 | from InflexMusic.utils.database import ( 15 | add_served_chat, 16 | add_served_user, 17 | blacklisted_chats, 18 | get_lang, 19 | is_banned_user, 20 | is_on_off, 21 | ) 22 | from InflexMusic.utils.decorators.language import LanguageStart 23 | from InflexMusic.utils.formatters import get_readable_time 24 | from InflexMusic.utils.inline import help_pannel, private_panel, start_panel 25 | from config import BANNED_USERS 26 | from strings import get_string 27 | 28 | 29 | @app.on_message(filters.command(["start"]) & filters.private & ~BANNED_USERS) 30 | @LanguageStart 31 | async def start_pm(client, message: Message, _): 32 | await add_served_user(message.from_user.id) 33 | if len(message.text.split()) > 1: 34 | name = message.text.split(None, 1)[1] 35 | if name[0:4] == "help": 36 | keyboard = help_pannel(_) 37 | return await message.reply_photo( 38 | photo=random.choice(START_IMG_URL), 39 | caption=_["help_1"].format(config.SUPPORT_GROUP), 40 | reply_markup=keyboard, 41 | ) 42 | if name[0:3] == "sud": 43 | await sudoers_list(client=client, message=message, _=_) 44 | if await is_on_off(2): 45 | return await app.send_message( 46 | chat_id=config.LOG_GROUP_ID, 47 | text=f"{message.from_user.mention} ᴊᴜsᴛ sᴛᴀʀᴛᴇᴅ ᴛʜᴇ ʙᴏᴛ ᴛᴏ ᴄʜᴇᴄᴋ sᴜᴅᴏʟɪsᴛ.\n\nᴜsᴇʀ ɪᴅ : {message.from_user.id}\nᴜsᴇʀɴᴀᴍᴇ : @{message.from_user.username}", 48 | ) 49 | return 50 | if name[0:3] == "inf": 51 | m = await message.reply_text("🔎") 52 | query = (str(name)).replace("info_", "", 1) 53 | query = f"https://www.youtube.com/watch?v={query}" 54 | results = VideosSearch(query, limit=1) 55 | for result in (await results.next())["result"]: 56 | title = result["title"] 57 | duration = result["duration"] 58 | views = result["viewCount"]["short"] 59 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 60 | channellink = result["channel"]["link"] 61 | channel = result["channel"]["name"] 62 | link = result["link"] 63 | published = result["publishedTime"] 64 | searched_text = _["start_6"].format( 65 | title, duration, views, published, channellink, channel, app.mention 66 | ) 67 | key = InlineKeyboardMarkup( 68 | [ 69 | [ 70 | InlineKeyboardButton(text=_["S_B_8"], url=link), 71 | InlineKeyboardButton(text=_["S_B_9"], url=config.SUPPORT_GROUP), 72 | ], 73 | ] 74 | ) 75 | await m.delete() 76 | await app.send_photo( 77 | chat_id=message.chat.id, 78 | photo=thumbnail, 79 | caption=searched_text, 80 | reply_markup=key, 81 | ) 82 | if await is_on_off(2): 83 | return await app.send_message( 84 | chat_id=config.LOG_GROUP_ID, 85 | text=f"{message.from_user.mention} ᴊᴜsᴛ sᴛᴀʀᴛᴇᴅ ᴛʜᴇ ʙᴏᴛ ᴛᴏ ᴄʜᴇᴄᴋ ᴛʀᴀᴄᴋ ɪɴғᴏʀᴍᴀᴛɪᴏɴ.\n\nᴜsᴇʀ ɪᴅ : {message.from_user.id}\nᴜsᴇʀɴᴀᴍᴇ : @{message.from_user.username}", 86 | ) 87 | else: 88 | out = private_panel(_) 89 | await message.reply_photo( 90 | photo=random.choice(START_IMG_URL), 91 | caption=_["start_2"].format(message.from_user.mention, app.mention), 92 | reply_markup=InlineKeyboardMarkup(out), 93 | ) 94 | if await is_on_off(2): 95 | return await app.send_message( 96 | chat_id=config.LOG_GROUP_ID, 97 | text=f"{message.from_user.mention} ᴊᴜsᴛ sᴛᴀʀᴛᴇᴅ ᴛʜᴇ ʙᴏᴛ.\n\nᴜsᴇʀ ɪᴅ : {message.from_user.id}\nᴜsᴇʀɴᴀᴍᴇ : @{message.from_user.username}", 98 | ) 99 | 100 | 101 | @app.on_message(filters.command(["start"]) & filters.group & ~BANNED_USERS) 102 | @LanguageStart 103 | async def start_gp(client, message: Message, _): 104 | out = start_panel(_) 105 | uptime = int(time.time() - _boot_) 106 | await message.reply_photo( 107 | photo=random.choice(START_IMG_URL), 108 | caption=_["start_1"].format(app.mention, get_readable_time(uptime)), 109 | reply_markup=InlineKeyboardMarkup(out), 110 | ) 111 | return await add_served_chat(message.chat.id) 112 | 113 | 114 | @app.on_message(filters.new_chat_members, group=-1) 115 | async def welcome(client, message: Message): 116 | for member in message.new_chat_members: 117 | try: 118 | language = await get_lang(message.chat.id) 119 | _ = get_string(language) 120 | if await is_banned_user(member.id): 121 | try: 122 | await message.chat.ban_member(member.id) 123 | except: 124 | pass 125 | if member.id == app.id: 126 | if message.chat.type != ChatType.SUPERGROUP: 127 | await message.reply_text(_["start_4"]) 128 | return await app.leave_chat(message.chat.id) 129 | if message.chat.id in await blacklisted_chats(): 130 | await message.reply_text( 131 | _["start_5"].format( 132 | app.mention, 133 | f"https://t.me/{app.username}?start=sudolist", 134 | config.SUPPORT_GROUP, 135 | ), 136 | disable_web_page_preview=True, 137 | ) 138 | return await app.leave_chat(message.chat.id) 139 | 140 | out = start_panel(_) 141 | await message.reply_photo( 142 | photo=random.choice(START_IMG_URL), 143 | caption=_["start_3"].format( 144 | message.from_user.first_name, 145 | app.mention, 146 | message.chat.title, 147 | app.mention, 148 | ), 149 | reply_markup=InlineKeyboardMarkup(out), 150 | ) 151 | await add_served_chat(message.chat.id) 152 | await message.stop_propagation() 153 | except Exception as ex: 154 | print(ex) 155 | -------------------------------------------------------------------------------- /InflexMusic/plugins/misc/autoleave.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from datetime import datetime 3 | 4 | from pyrogram.enums import ChatType 5 | 6 | import config 7 | from InflexMusic import app 8 | from InflexMusic.core.call import Inflex, autoend 9 | from InflexMusic.utils.database import get_client, is_active_chat, is_autoend 10 | 11 | 12 | async def auto_leave(): 13 | if config.AUTO_LEAVING_ASSISTANT: 14 | while not await asyncio.sleep(900): 15 | from InflexMusic.core.userbot import assistants 16 | 17 | for num in assistants: 18 | client = await get_client(num) 19 | left = 0 20 | try: 21 | async for i in client.get_dialogs(): 22 | if i.chat.type in [ 23 | ChatType.SUPERGROUP, 24 | ChatType.GROUP, 25 | ChatType.CHANNEL, 26 | ]: 27 | if ( 28 | i.chat.id != config.LOG_GROUP_ID 29 | and i.chat.id != -1001686672798 30 | and i.chat.id != -1001549206010 31 | ): 32 | if left == 20: 33 | continue 34 | if not await is_active_chat(i.chat.id): 35 | try: 36 | await client.leave_chat(i.chat.id) 37 | left += 1 38 | except: 39 | continue 40 | except: 41 | pass 42 | 43 | 44 | asyncio.create_task(auto_leave()) 45 | 46 | 47 | async def auto_end(): 48 | while not await asyncio.sleep(5): 49 | ender = await is_autoend() 50 | if not ender: 51 | continue 52 | for chat_id in autoend: 53 | timer = autoend.get(chat_id) 54 | if not timer: 55 | continue 56 | if datetime.now() > timer: 57 | if not await is_active_chat(chat_id): 58 | autoend[chat_id] = {} 59 | continue 60 | autoend[chat_id] = {} 61 | try: 62 | await Inflex.stop_stream(chat_id) 63 | except: 64 | continue 65 | try: 66 | await app.send_message( 67 | chat_id, 68 | "» ʙᴏᴛ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ʟᴇғᴛ ᴠɪᴅᴇᴏᴄʜᴀᴛ ʙᴇᴄᴀᴜsᴇ ɴᴏ ᴏɴᴇ ᴡᴀs ʟɪsᴛᴇɴɪɴɢ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 69 | ) 70 | except: 71 | continue 72 | 73 | 74 | asyncio.create_task(auto_end()) 75 | -------------------------------------------------------------------------------- /InflexMusic/plugins/misc/seeker.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from InflexMusic.misc import db 4 | from InflexMusic.utils.database import get_active_chats, is_music_playing 5 | 6 | 7 | async def timer(): 8 | while not await asyncio.sleep(1): 9 | active_chats = await get_active_chats() 10 | for chat_id in active_chats: 11 | if not await is_music_playing(chat_id): 12 | continue 13 | playing = db.get(chat_id) 14 | if not playing: 15 | continue 16 | duration = int(playing[0]["seconds"]) 17 | if duration == 0: 18 | continue 19 | if db[chat_id][0]["played"] >= duration: 20 | continue 21 | db[chat_id][0]["played"] += 1 22 | 23 | 24 | asyncio.create_task(timer()) 25 | -------------------------------------------------------------------------------- /InflexMusic/plugins/misc/watcher.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.core.call import Inflex 6 | 7 | welcome = 20 8 | close = 30 9 | 10 | 11 | @app.on_message(filters.video_chat_started, group=welcome) 12 | @app.on_message(filters.video_chat_ended, group=close) 13 | async def welcome(_, message: Message): 14 | await Inflex.stop_stream_force(message.chat.id) 15 | -------------------------------------------------------------------------------- /InflexMusic/plugins/play/channel.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.enums import ChatMembersFilter, ChatMemberStatus, ChatType 3 | from pyrogram.types import Message 4 | 5 | from InflexMusic import app 6 | from InflexMusic.utils.database import set_cmode 7 | from InflexMusic.utils.decorators.admins import AdminActual 8 | from config import BANNED_USERS 9 | 10 | 11 | @app.on_message(filters.command(["channelplay"]) & filters.group & ~BANNED_USERS) 12 | @AdminActual 13 | async def playmode_(client, message: Message, _): 14 | if len(message.command) < 2: 15 | return await message.reply_text(_["cplay_1"].format(message.chat.title)) 16 | query = message.text.split(None, 2)[1].lower().strip() 17 | if (str(query)).lower() == "disable": 18 | await set_cmode(message.chat.id, None) 19 | return await message.reply_text(_["cplay_7"]) 20 | elif str(query) == "linked": 21 | chat = await app.get_chat(message.chat.id) 22 | if chat.linked_chat: 23 | chat_id = chat.linked_chat.id 24 | await set_cmode(message.chat.id, chat_id) 25 | return await message.reply_text( 26 | _["cplay_3"].format(chat.linked_chat.title, chat.linked_chat.id) 27 | ) 28 | else: 29 | return await message.reply_text(_["cplay_2"]) 30 | else: 31 | try: 32 | chat = await app.get_chat(query) 33 | except: 34 | return await message.reply_text(_["cplay_4"]) 35 | if chat.type != ChatType.CHANNEL: 36 | return await message.reply_text(_["cplay_5"]) 37 | try: 38 | async for user in app.get_chat_members( 39 | chat.id, filter=ChatMembersFilter.ADMINISTRATORS 40 | ): 41 | if user.status == ChatMemberStatus.OWNER: 42 | cusn = user.user.username 43 | crid = user.user.id 44 | except: 45 | return await message.reply_text(_["cplay_4"]) 46 | if crid != message.from_user.id: 47 | return await message.reply_text(_["cplay_6"].format(chat.title, cusn)) 48 | await set_cmode(message.chat.id, chat.id) 49 | return await message.reply_text(_["cplay_3"].format(chat.title, chat.id)) 50 | -------------------------------------------------------------------------------- /InflexMusic/plugins/play/live.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | 3 | from InflexMusic import YouTube, app 4 | from InflexMusic.utils.channelplay import get_channeplayCB 5 | from InflexMusic.utils.decorators.language import languageCB 6 | from InflexMusic.utils.stream.stream import stream 7 | from config import BANNED_USERS 8 | 9 | 10 | @app.on_callback_query(filters.regex("LiveStream") & ~BANNED_USERS) 11 | @languageCB 12 | async def play_live_stream(client, CallbackQuery, _): 13 | callback_data = CallbackQuery.data.strip() 14 | callback_request = callback_data.split(None, 1)[1] 15 | vidid, user_id, mode, cplay, fplay = callback_request.split("|") 16 | if CallbackQuery.from_user.id != int(user_id): 17 | try: 18 | return await CallbackQuery.answer(_["playcb_1"], show_alert=True) 19 | except: 20 | return 21 | try: 22 | chat_id, channel = await get_channeplayCB(_, cplay, CallbackQuery) 23 | except: 24 | return 25 | video = True if mode == "v" else None 26 | user_name = CallbackQuery.from_user.first_name 27 | await CallbackQuery.message.delete() 28 | try: 29 | await CallbackQuery.answer() 30 | except: 31 | pass 32 | mystic = await CallbackQuery.message.reply_text( 33 | _["play_2"].format(channel) if channel else _["play_1"] 34 | ) 35 | try: 36 | details, track_id = await YouTube.track(vidid, True) 37 | except: 38 | return await mystic.edit_text(_["play_3"]) 39 | ffplay = True if fplay == "f" else None 40 | if not details["duration_min"]: 41 | try: 42 | await stream( 43 | _, 44 | mystic, 45 | user_id, 46 | details, 47 | chat_id, 48 | user_name, 49 | CallbackQuery.message.chat.id, 50 | video, 51 | streamtype="live", 52 | forceplay=ffplay, 53 | ) 54 | except Exception as e: 55 | ex_type = type(e).__name__ 56 | err = e if ex_type == "AssistantErr" else _["general_2"].format(ex_type) 57 | return await mystic.edit_text(err) 58 | else: 59 | return await mystic.edit_text("» ɴᴏᴛ ᴀ ʟɪᴠᴇ sᴛʀᴇᴀᴍ.") 60 | await mystic.delete() 61 | -------------------------------------------------------------------------------- /InflexMusic/plugins/play/playmode.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import InlineKeyboardMarkup, Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.utils.database import get_playmode, get_playtype, is_nonadmin_chat 6 | from InflexMusic.utils.decorators import language 7 | from InflexMusic.utils.inline.settings import playmode_users_markup 8 | from config import BANNED_USERS 9 | 10 | 11 | @app.on_message(filters.command(["playmode", "mode"]) & filters.group & ~BANNED_USERS) 12 | @language 13 | async def playmode_(client, message: Message, _): 14 | playmode = await get_playmode(message.chat.id) 15 | if playmode == "Direct": 16 | Direct = True 17 | else: 18 | Direct = None 19 | is_non_admin = await is_nonadmin_chat(message.chat.id) 20 | if not is_non_admin: 21 | Group = True 22 | else: 23 | Group = None 24 | playty = await get_playtype(message.chat.id) 25 | if playty == "Everyone": 26 | Playtype = None 27 | else: 28 | Playtype = True 29 | buttons = playmode_users_markup(_, Direct, Group, Playtype) 30 | response = await message.reply_text( 31 | _["play_22"].format(message.chat.title), 32 | reply_markup=InlineKeyboardMarkup(buttons), 33 | ) 34 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/autoend.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.misc import SUDOERS 6 | from InflexMusic.utils.database import autoend_off, autoend_on 7 | 8 | 9 | @app.on_message(filters.command("autoend") & SUDOERS) 10 | async def auto_end_stream(_, message: Message): 11 | usage = "ᴇxᴀᴍᴘʟᴇ :\n\n/autoend [ᴇɴᴀʙʟᴇ | ᴅɪsᴀʙʟᴇ]" 12 | if len(message.command) != 2: 13 | return await message.reply_text(usage) 14 | state = message.text.split(None, 1)[1].strip().lower() 15 | if state == "enable": 16 | await autoend_on() 17 | await message.reply_text( 18 | "» ᴀᴜᴛᴏ ᴇɴᴅ sᴛʀᴇᴀᴍ ᴇɴᴀʙʟᴇᴅ.\n\nᴀssɪsᴛᴀɴᴛ ᴡɪʟʟ ᴀᴜᴛᴏᴍᴀᴛɪᴄᴀʟʟʏ ʟᴇᴀᴠᴇ ᴛʜᴇ ᴠɪᴅᴇᴏᴄʜᴀᴛ ᴀғᴛᴇʀ ғᴇᴡ ᴍɪɴs ᴡʜᴇɴ ɴᴏ ᴏɴᴇ ɪs ʟɪsᴛᴇɴɪɴɢ." 19 | ) 20 | elif state == "disable": 21 | await autoend_off() 22 | await message.reply_text("» ᴀᴜᴛᴏ ᴇɴᴅ sᴛʀᴇᴀᴍ ᴅɪsᴀʙʟᴇᴅ.") 23 | else: 24 | await message.reply_text(usage) 25 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/blchat.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.misc import SUDOERS 6 | from InflexMusic.utils.database import blacklist_chat, blacklisted_chats, whitelist_chat 7 | from InflexMusic.utils.decorators.language import language 8 | from config import BANNED_USERS 9 | 10 | 11 | @app.on_message(filters.command(["blchat", "blacklistchat"]) & SUDOERS) 12 | @language 13 | async def blacklist_chat_func(client, message: Message, _): 14 | if len(message.command) != 2: 15 | return await message.reply_text(_["black_1"]) 16 | chat_id = int(message.text.strip().split()[1]) 17 | if chat_id in await blacklisted_chats(): 18 | return await message.reply_text(_["black_2"]) 19 | blacklisted = await blacklist_chat(chat_id) 20 | if blacklisted: 21 | await message.reply_text(_["black_3"]) 22 | else: 23 | await message.reply_text(_["black_9"]) 24 | try: 25 | await app.leave_chat(chat_id) 26 | except: 27 | pass 28 | 29 | 30 | @app.on_message( 31 | filters.command(["whitelistchat", "unblacklistchat", "unblchat"]) & SUDOERS 32 | ) 33 | @language 34 | async def white_funciton(client, message: Message, _): 35 | if len(message.command) != 2: 36 | return await message.reply_text(_["black_4"]) 37 | chat_id = int(message.text.strip().split()[1]) 38 | if chat_id not in await blacklisted_chats(): 39 | return await message.reply_text(_["black_5"]) 40 | whitelisted = await whitelist_chat(chat_id) 41 | if whitelisted: 42 | return await message.reply_text(_["black_6"]) 43 | await message.reply_text(_["black_9"]) 44 | 45 | 46 | @app.on_message(filters.command(["blchats", "blacklistedchats"]) & ~BANNED_USERS) 47 | @language 48 | async def all_chats(client, message: Message, _): 49 | text = _["black_7"] 50 | j = 0 51 | for count, chat_id in enumerate(await blacklisted_chats(), 1): 52 | try: 53 | title = (await app.get_chat(chat_id)).title 54 | except: 55 | title = "ᴘʀɪᴠᴀᴛᴇ ᴄʜᴀᴛ" 56 | j = 1 57 | text += f"{count}. {title}[{chat_id}]\n" 58 | if j == 0: 59 | await message.reply_text(_["black_8"].format(app.mention)) 60 | else: 61 | await message.reply_text(text) 62 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/block.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.misc import SUDOERS 6 | from InflexMusic.utils.database import add_gban_user, remove_gban_user 7 | from InflexMusic.utils.decorators.language import language 8 | from InflexMusic.utils.extraction import extract_user 9 | from config import BANNED_USERS 10 | 11 | 12 | @app.on_message(filters.command(["block"]) & SUDOERS) 13 | @language 14 | async def useradd(client, message: Message, _): 15 | if not message.reply_to_message: 16 | if len(message.command) != 2: 17 | return await message.reply_text(_["general_1"]) 18 | user = await extract_user(message) 19 | if user.id in BANNED_USERS: 20 | return await message.reply_text(_["block_1"].format(user.mention)) 21 | await add_gban_user(user.id) 22 | BANNED_USERS.add(user.id) 23 | await message.reply_text(_["block_2"].format(user.mention)) 24 | 25 | 26 | @app.on_message(filters.command(["unblock"]) & SUDOERS) 27 | @language 28 | async def userdel(client, message: Message, _): 29 | if not message.reply_to_message: 30 | if len(message.command) != 2: 31 | return await message.reply_text(_["general_1"]) 32 | user = await extract_user(message) 33 | if user.id not in BANNED_USERS: 34 | return await message.reply_text(_["block_3"].format(user.mention)) 35 | await remove_gban_user(user.id) 36 | BANNED_USERS.remove(user.id) 37 | await message.reply_text(_["block_4"].format(user.mention)) 38 | 39 | 40 | @app.on_message(filters.command(["blocked", "blockedusers", "blusers"]) & SUDOERS) 41 | @language 42 | async def sudoers_list(client, message: Message, _): 43 | if not BANNED_USERS: 44 | return await message.reply_text(_["block_5"]) 45 | mystic = await message.reply_text(_["block_6"]) 46 | msg = _["block_7"] 47 | count = 0 48 | for users in BANNED_USERS: 49 | try: 50 | user = await app.get_users(users) 51 | user = user.first_name if not user.mention else user.mention 52 | count += 1 53 | except: 54 | continue 55 | msg += f"{count}➤ {user}\n" 56 | if count == 0: 57 | return await mystic.edit_text(_["block_5"]) 58 | else: 59 | return await mystic.edit_text(msg) 60 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/gban.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from pyrogram import filters 4 | from pyrogram.errors import FloodWait 5 | from pyrogram.types import Message 6 | 7 | from InflexMusic import app 8 | from InflexMusic.misc import SUDOERS 9 | from config import OWNER_ID 10 | from InflexMusic.utils import get_readable_time 11 | from InflexMusic.utils.database import ( 12 | add_banned_user, 13 | get_banned_count, 14 | get_banned_users, 15 | get_served_chats, 16 | is_banned_user, 17 | remove_banned_user, 18 | ) 19 | from InflexMusic.utils.decorators.language import language 20 | from InflexMusic.utils.extraction import extract_user 21 | from config import BANNED_USERS 22 | 23 | 24 | @app.on_message(filters.command(["gban", "globalban"]) & SUDOERS) 25 | @language 26 | async def global_ban(client, message: Message, _): 27 | if not message.reply_to_message: 28 | if len(message.command) != 2: 29 | return await message.reply_text(_["general_1"]) 30 | user = await extract_user(message) 31 | if user.id == message.from_user.id: 32 | return await message.reply_text(_["gban_1"]) 33 | elif user.id == app.id: 34 | return await message.reply_text(_["gban_2"]) 35 | elif user.id in SUDOERS: 36 | return await message.reply_text(_["gban_3"]) 37 | is_gbanned = await is_banned_user(user.id) 38 | if is_gbanned: 39 | return await message.reply_text(_["gban_4"].format(user.mention)) 40 | if user.id not in BANNED_USERS: 41 | BANNED_USERS.add(user.id) 42 | served_chats = [] 43 | chats = await get_served_chats() 44 | for chat in chats: 45 | served_chats.append(int(chat["chat_id"])) 46 | time_expected = get_readable_time(len(served_chats)) 47 | mystic = await message.reply_text(_["gban_5"].format(user.mention, time_expected)) 48 | number_of_chats = 0 49 | for chat_id in served_chats: 50 | try: 51 | await app.ban_chat_member(chat_id, user.id) 52 | number_of_chats += 1 53 | except FloodWait as fw: 54 | await asyncio.sleep(int(fw.value)) 55 | except: 56 | continue 57 | await add_banned_user(user.id) 58 | await message.reply_text( 59 | _["gban_6"].format( 60 | app.mention, 61 | message.chat.title, 62 | message.chat.id, 63 | user.mention, 64 | user.id, 65 | message.from_user.mention, 66 | number_of_chats, 67 | ) 68 | ) 69 | await mystic.delete() 70 | 71 | 72 | @app.on_message(filters.command(["ungban"]) & filters.user(OWNER_ID)) 73 | @language 74 | async def global_un(client, message: Message, _): 75 | if not message.reply_to_message: 76 | if len(message.command) != 2: 77 | return await message.reply_text(_["general_1"]) 78 | user = await extract_user(message) 79 | is_gbanned = await is_banned_user(user.id) 80 | if not is_gbanned: 81 | return await message.reply_text(_["gban_7"].format(user.mention)) 82 | if user.id in BANNED_USERS: 83 | BANNED_USERS.remove(user.id) 84 | served_chats = [] 85 | chats = await get_served_chats() 86 | for chat in chats: 87 | served_chats.append(int(chat["chat_id"])) 88 | time_expected = get_readable_time(len(served_chats)) 89 | mystic = await message.reply_text(_["gban_8"].format(user.mention, time_expected)) 90 | number_of_chats = 0 91 | for chat_id in served_chats: 92 | try: 93 | await app.unban_chat_member(chat_id, user.id) 94 | number_of_chats += 1 95 | except FloodWait as fw: 96 | await asyncio.sleep(int(fw.value)) 97 | except: 98 | continue 99 | await remove_banned_user(user.id) 100 | await message.reply_text(_["gban_9"].format(user.mention, number_of_chats)) 101 | await mystic.delete() 102 | 103 | 104 | @app.on_message(filters.command(["gbannedusers", "gbanlist"]) & SUDOERS) 105 | @language 106 | async def gbanned_list(client, message: Message, _): 107 | counts = await get_banned_count() 108 | if counts == 0: 109 | return await message.reply_text(_["gban_10"]) 110 | mystic = await message.reply_text(_["gban_11"]) 111 | msg = _["gban_12"] 112 | count = 0 113 | users = await get_banned_users() 114 | for user_id in users: 115 | count += 1 116 | try: 117 | user = await app.get_users(user_id) 118 | user = user.first_name if not user.mention else user.mention 119 | msg += f"{count}➤ {user}\n" 120 | except Exception: 121 | msg += f"{count}➤ {user_id}\n" 122 | continue 123 | if count == 0: 124 | return await mystic.edit_text(_["gban_10"]) 125 | else: 126 | return await mystic.edit_text(msg) 127 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/logger.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | 3 | from InflexMusic import app 4 | from InflexMusic.misc import SUDOERS 5 | from InflexMusic.utils.database import add_off, add_on 6 | from InflexMusic.utils.decorators.language import language 7 | 8 | 9 | @app.on_message(filters.command(["logger"]) & SUDOERS) 10 | @language 11 | async def logger(client, message, _): 12 | usage = _["log_1"] 13 | if len(message.command) != 2: 14 | return await message.reply_text(usage) 15 | state = message.text.split(None, 1)[1].strip().lower() 16 | if state == "enable": 17 | await add_on(2) 18 | await message.reply_text(_["log_2"]) 19 | elif state == "disable": 20 | await add_off(2) 21 | await message.reply_text(_["log_3"]) 22 | else: 23 | await message.reply_text(usage) 24 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/maintenance.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.misc import SUDOERS 6 | from InflexMusic.utils.database import ( 7 | get_lang, 8 | is_maintenance, 9 | maintenance_off, 10 | maintenance_on, 11 | ) 12 | from strings import get_string 13 | 14 | 15 | @app.on_message(filters.command(["maintenance"]) & SUDOERS) 16 | async def maintenance(client, message: Message): 17 | try: 18 | language = await get_lang(message.chat.id) 19 | _ = get_string(language) 20 | except: 21 | _ = get_string("en") 22 | usage = _["maint_1"] 23 | if len(message.command) != 2: 24 | return await message.reply_text(usage) 25 | state = message.text.split(None, 1)[1].strip().lower() 26 | if state == "enable": 27 | if await is_maintenance() is False: 28 | await message.reply_text(_["maint_4"]) 29 | else: 30 | await maintenance_on() 31 | await message.reply_text(_["maint_2"].format(app.mention)) 32 | elif state == "disable": 33 | if await is_maintenance() is False: 34 | await maintenance_off() 35 | await message.reply_text(_["maint_3"].format(app.mention)) 36 | else: 37 | await message.reply_text(_["maint_5"]) 38 | else: 39 | await message.reply_text(usage) 40 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/restart.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import os 3 | import shutil 4 | import socket 5 | from datetime import datetime 6 | 7 | import urllib3 8 | from git import Repo 9 | from git.exc import GitCommandError, InvalidGitRepositoryError 10 | from pyrogram import filters 11 | 12 | import config 13 | from config import OWNER_ID 14 | from InflexMusic import app 15 | from InflexMusic.misc import HAPP, SUDOERS, XCB 16 | from InflexMusic.utils.database import ( 17 | get_active_chats, 18 | remove_active_chat, 19 | remove_active_video_chat, 20 | ) 21 | from InflexMusic.utils.decorators.language import language 22 | from InflexMusic.utils.pastebin import InflexBin 23 | 24 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 25 | 26 | 27 | async def is_heroku(): 28 | return "heroku" in socket.getfqdn() 29 | 30 | 31 | @app.on_message(filters.command(["getlog", "logs", "getlogs"]) & filters.user(OWNER_ID)) 32 | @language 33 | async def log_(client, message, _): 34 | try: 35 | await message.reply_document(document="log.txt") 36 | except: 37 | await message.reply_text(_["server_1"]) 38 | 39 | 40 | @app.on_message(filters.command(["update", "gitpull"]) & filters.user(OWNER_ID)) 41 | @language 42 | async def update_(client, message, _): 43 | if await is_heroku(): 44 | if HAPP is None: 45 | return await message.reply_text(_["server_2"]) 46 | response = await message.reply_text(_["server_3"]) 47 | try: 48 | repo = Repo() 49 | except GitCommandError: 50 | return await response.edit(_["server_4"]) 51 | except InvalidGitRepositoryError: 52 | return await response.edit(_["server_5"]) 53 | to_exc = f"git fetch origin {config.UPSTREAM_BRANCH} &> /dev/null" 54 | os.system(to_exc) 55 | await asyncio.sleep(7) 56 | verification = "" 57 | REPO_ = repo.remotes.origin.url.split(".git")[0] 58 | for checks in repo.iter_commits(f"HEAD..origin/{config.UPSTREAM_BRANCH}"): 59 | verification = str(checks.count()) 60 | if verification == "": 61 | return await response.edit(_["server_6"]) 62 | updates = "" 63 | ordinal = lambda format: "%d%s" % ( 64 | format, 65 | "tsnrhtdd"[(format // 10 % 10 != 1) * (format % 10 < 4) * format % 10 :: 4], 66 | ) 67 | for info in repo.iter_commits(f"HEAD..origin/{config.UPSTREAM_BRANCH}"): 68 | updates += f"➣ #{info.count()}: {info.summary} 𝖡𝗒 -> {info.author}\n\t\t\t\t➥ 𝖢𝗈𝗆𝗆𝗂𝗍𝗍𝖾𝖽 𝖮𝗇 : {ordinal(int(datetime.fromtimestamp(info.committed_date).strftime('%d')))} {datetime.fromtimestamp(info.committed_date).strftime('%b')}, {datetime.fromtimestamp(info.committed_date).strftime('%Y')}\n\n" 69 | _update_response_ = "𝖠 𝖭𝖾𝗐 𝖴𝗉𝖽𝖺𝗍𝖾 𝖨𝗌 𝖠𝗏𝖺𝗂𝗅𝖺𝖻𝗅𝖾 𝖥𝗈𝗋 𝖳𝗁𝖾 𝖡𝗈𝗍 !\n\n➣ 𝖯𝗎𝗌𝗁𝗂𝗇𝗀 𝖴𝗉𝖽𝖺𝗍𝖾𝗌 𝖭𝗈𝗐\n\n𝖴𝗉𝖽𝖺𝗍𝖾𝗌 :\n\n" 70 | _final_updates_ = _update_response_ + updates 71 | if len(_final_updates_) > 4096: 72 | url = await InflexBin(updates) 73 | nrs = await response.edit( 74 | f"𝖠 𝖭𝖾𝗐 𝖴𝗉𝖽𝖺𝗍𝖾 𝖨𝗌 𝖠𝗏𝖺𝗂𝗅𝖺𝖻𝗅𝖾 𝖥𝗈𝗋 𝖳𝗁𝖾 𝖡𝗈𝗍 !\n\n➣ 𝖯𝗎𝗌𝗁𝗂𝗇𝗀 𝖴𝗉𝖽𝖺𝗍𝖾𝗌 𝖭𝗈𝗐\n\n𝖴𝗉𝖽𝖺𝗍𝖾𝗌 :\n\n𝖢𝗁𝖾𝖼𝗄 𝖴𝗉𝖽𝖺𝗍𝖾𝗌" 75 | ) 76 | else: 77 | nrs = await response.edit(_final_updates_, disable_web_page_preview=True) 78 | os.system("git stash &> /dev/null && git pull") 79 | 80 | try: 81 | served_chats = await get_active_chats() 82 | for x in served_chats: 83 | try: 84 | await app.send_message( 85 | chat_id=int(x), 86 | text=_["server_8"].format(app.mention), 87 | ) 88 | await remove_active_chat(x) 89 | await remove_active_video_chat(x) 90 | except: 91 | pass 92 | await response.edit(f"{nrs.text}\n\n{_['server_7']}") 93 | except: 94 | pass 95 | 96 | if await is_heroku(): 97 | try: 98 | os.system( 99 | f"{XCB[5]} {XCB[7]} {XCB[9]}{XCB[4]}{XCB[0]*2}{XCB[6]}{XCB[4]}{XCB[8]}{XCB[1]}{XCB[5]}{XCB[2]}{XCB[6]}{XCB[2]}{XCB[3]}{XCB[0]}{XCB[10]}{XCB[2]}{XCB[5]} {XCB[11]}{XCB[4]}{XCB[12]}" 100 | ) 101 | return 102 | except Exception as err: 103 | await response.edit(f"{nrs.text}\n\n{_['server_9']}") 104 | return await app.send_message( 105 | chat_id=config.LOG_GROUP_ID, 106 | text=_["server_10"].format(err), 107 | ) 108 | else: 109 | os.system("pip3 install -r requirements.txt") 110 | os.system(f"kill -9 {os.getpid()} && bash start") 111 | exit() 112 | 113 | 114 | @app.on_message(filters.command(["restart"]) & SUDOERS) 115 | async def restart_(_, message): 116 | response = await message.reply_text("𝖱𝖾𝗌𝗍𝖺𝗋𝗍𝗂𝗇𝗀 ...") 117 | ac_chats = await get_active_chats() 118 | for x in ac_chats: 119 | try: 120 | await app.send_message( 121 | chat_id=int(x), 122 | text=f"{app.mention} 𝖨𝗌 𝖱𝖾𝗌𝗍𝖺𝗋𝗍𝗂𝗇𝗀 ...\n\n𝖸𝗈𝗎 𝖢𝖺𝗇 𝖲𝗍𝖺𝗋𝗍 𝖯𝗅𝖺𝗒𝗂𝗇𝗀 𝖠𝖿𝗍𝖾𝗋 15 - 20 𝖲𝖾𝖼𝗈𝗇𝖽𝗌 .", 123 | ) 124 | await remove_active_chat(x) 125 | await remove_active_video_chat(x) 126 | except: 127 | pass 128 | 129 | try: 130 | shutil.rmtree("downloads") 131 | shutil.rmtree("raw_files") 132 | shutil.rmtree("cache") 133 | except: 134 | pass 135 | await response.edit_text( 136 | "» 𝖱𝖾𝗌𝗍𝖺𝗋𝗍 𝖯𝗋𝗈𝖼𝖾𝗌𝗌 𝖲𝗍𝖺𝗋𝗍𝖾𝖽 , 𝖯𝗅𝖾𝖺𝗌𝖾 𝖶𝖺𝗂𝗍 𝖥𝗈𝗋 𝖥𝖾𝗐 𝖲𝖾𝖼𝗈𝗇𝖽𝗌 𝖴𝗇𝗍𝗂𝗅 𝖳𝗁𝖾 𝖡𝗈𝗍 𝖲𝗍𝖺𝗋𝗍𝗌 ...." 137 | ) 138 | os.system(f"kill -9 {os.getpid()} && python3 -m InflexMusic") 139 | -------------------------------------------------------------------------------- /InflexMusic/plugins/sudo/sudoers.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | 4 | from InflexMusic import app 5 | from InflexMusic.misc import SUDOERS 6 | from InflexMusic.utils.database import add_sudo, remove_sudo 7 | from InflexMusic.utils.decorators.language import language 8 | from InflexMusic.utils.extraction import extract_user 9 | from InflexMusic.utils.inline import close_markup 10 | from config import BANNED_USERS, OWNER_ID 11 | 12 | 13 | @app.on_message(filters.command(["addsudo"]) & filters.user(OWNER_ID)) 14 | @language 15 | async def useradd(client, message: Message, _): 16 | if not message.reply_to_message: 17 | if len(message.command) != 2: 18 | return await message.reply_text(_["general_1"]) 19 | user = await extract_user(message) 20 | if user.id in SUDOERS: 21 | return await message.reply_text(_["sudo_1"].format(user.mention)) 22 | added = await add_sudo(user.id) 23 | if added: 24 | SUDOERS.add(user.id) 25 | await message.reply_text(_["sudo_2"].format(user.mention)) 26 | else: 27 | await message.reply_text(_["sudo_8"]) 28 | 29 | 30 | @app.on_message(filters.command(["delsudo", "rmsudo"]) & filters.user(OWNER_ID)) 31 | @language 32 | async def userdel(client, message: Message, _): 33 | if not message.reply_to_message: 34 | if len(message.command) != 2: 35 | return await message.reply_text(_["general_1"]) 36 | user = await extract_user(message) 37 | if user.id not in SUDOERS: 38 | return await message.reply_text(_["sudo_3"].format(user.mention)) 39 | removed = await remove_sudo(user.id) 40 | if removed: 41 | SUDOERS.remove(user.id) 42 | await message.reply_text(_["sudo_4"].format(user.mention)) 43 | else: 44 | await message.reply_text(_["sudo_8"]) 45 | 46 | 47 | @app.on_message(filters.command(["sudolist", "listsudo", "sudoers"]) & ~BANNED_USERS) 48 | @language 49 | async def sudoers_list(client, message: Message, _): 50 | text = _["sudo_5"] 51 | user = await app.get_users(OWNER_ID) 52 | user = user.first_name if not user.mention else user.mention 53 | text += f"1➤ {user}\n" 54 | count = 0 55 | smex = 0 56 | for user_id in SUDOERS: 57 | if user_id != OWNER_ID: 58 | try: 59 | user = await app.get_users(user_id) 60 | user = user.first_name if not user.mention else user.mention 61 | if smex == 0: 62 | smex += 1 63 | text += _["sudo_6"] 64 | count += 1 65 | text += f"{count}➤ {user}\n" 66 | except: 67 | continue 68 | if not text: 69 | await message.reply_text(_["sudo_7"]) 70 | else: 71 | await message.reply_text(text, reply_markup=close_markup(_)) 72 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/active.py: -------------------------------------------------------------------------------- 1 | from pyrogram import filters 2 | from pyrogram.types import Message 3 | from unidecode import unidecode 4 | 5 | from InflexMusic import app 6 | from config import OWNER_ID 7 | from InflexMusic.misc import SUDOERS 8 | from InflexMusic.utils.database import ( 9 | get_active_chats, 10 | get_active_video_chats, 11 | remove_active_chat, 12 | remove_active_video_chat, 13 | ) 14 | 15 | 16 | @app.on_message(filters.command(["activevc", "activevoice", "voice", "ac"]) & SUDOERS) 17 | async def activevc(_, message: Message): 18 | mystic = await message.reply_text("» 𝖦𝖾𝗍𝗍𝗂𝗇𝗀 𝖠𝖼𝗍𝗂𝗏𝖾-𝖵𝗈𝗂𝖼𝖾 𝖢𝗁𝖺𝗍𝗌 𝖫𝗂𝗌𝗍 ...") 19 | served_chats = await get_active_chats() 20 | text = "" 21 | j = 0 22 | for x in served_chats: 23 | try: 24 | title = (await app.get_chat(x)).title 25 | except: 26 | await remove_active_chat(x) 27 | continue 28 | try: 29 | if (await app.get_chat(x)).username: 30 | user = (await app.get_chat(x)).username 31 | text += f"{j + 1}. {unidecode(title).upper()} [{x}]\n" 32 | else: 33 | text += ( 34 | f"{j + 1}. {unidecode(title).upper()} [{x}]\n" 35 | ) 36 | j += 1 37 | except: 38 | continue 39 | if not text: 40 | await mystic.edit_text(f"» 𝖭𝗈 𝖠𝖼𝗍𝗂𝗏𝖾-𝖵𝗈𝗂𝖼𝖾 𝖢𝗁𝖺𝗍𝗌 𝖮𝗇 {app.mention}.") 41 | else: 42 | await mystic.edit_text( 43 | f"» 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖢𝗎𝗋𝗋𝖾𝗇𝗍 𝖠𝖼𝗍𝗂𝗏𝖾-𝖵𝗈𝗂𝖼𝖾 𝖢𝗁𝖺𝗍𝗌 :\n\n{text}", 44 | disable_web_page_preview=True, 45 | ) 46 | 47 | 48 | @app.on_message(filters.command(["activev", "activevideo", "video"]) & filters.user(OWNER_ID)) 49 | async def activevi_(_, message: Message): 50 | mystic = await message.reply_text("» 𝖦𝖾𝗍𝗍𝗂𝗇𝗀 𝖠𝖼𝗍𝗂𝗏𝖾-𝖵𝗂𝖽𝖾𝗈 𝖢𝗁𝖺𝗍𝗌 𝖫𝗂𝗌𝗍 ...") 51 | served_chats = await get_active_video_chats() 52 | text = "" 53 | j = 0 54 | for x in served_chats: 55 | try: 56 | title = (await app.get_chat(x)).title 57 | except: 58 | await remove_active_video_chat(x) 59 | continue 60 | try: 61 | if (await app.get_chat(x)).username: 62 | user = (await app.get_chat(x)).username 63 | text += f"{j + 1}. {unidecode(title).upper()} [{x}]\n" 64 | else: 65 | text += ( 66 | f"{j + 1}. {unidecode(title).upper()} [{x}]\n" 67 | ) 68 | j += 1 69 | except: 70 | continue 71 | if not text: 72 | await mystic.edit_text(f"» 𝖭𝗈 𝖠𝖼𝗍𝗂𝗏𝖾-𝖵𝗂𝖽𝖾𝗈 𝖢𝗁𝖺𝗍𝗌 𝖮𝗇 {app.mention}.") 73 | else: 74 | await mystic.edit_text( 75 | f"» 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖢𝗎𝗋𝗋𝖾𝗇𝗍 𝖠𝖼𝗍𝗂𝗏𝖾-𝖵𝗂𝖽𝖾𝗈 𝖢𝗁𝖺𝗍𝗌 :\n\n{text}", 76 | disable_web_page_preview=True, 77 | ) 78 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/dev.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import subprocess 4 | import sys 5 | import traceback 6 | from inspect import getfullargspec 7 | from io import StringIO 8 | from time import time 9 | 10 | from pyrogram import filters 11 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup, Message 12 | 13 | from InflexMusic import app 14 | from config import OWNER_ID 15 | 16 | 17 | async def aexec(code, client, message): 18 | exec( 19 | "async def __aexec(client, message): " 20 | + "".join(f"\n {a}" for a in code.split("\n")) 21 | ) 22 | return await locals()["__aexec"](client, message) 23 | 24 | 25 | async def edit_or_reply(msg: Message, **kwargs): 26 | func = msg.edit_text if msg.from_user.is_self else msg.reply 27 | spec = getfullargspec(func.__wrapped__).args 28 | await func(**{k: v for k, v in kwargs.items() if k in spec}) 29 | 30 | 31 | @app.on_edited_message( 32 | filters.command("eval") 33 | & filters.user(OWNER_ID) 34 | & ~filters.forwarded 35 | & ~filters.via_bot 36 | ) 37 | @app.on_message( 38 | filters.command("eval") 39 | & filters.user(OWNER_ID) 40 | & ~filters.forwarded 41 | & ~filters.via_bot 42 | ) 43 | async def executor(client: app, message: Message): 44 | if len(message.command) < 2: 45 | return await edit_or_reply(message, text="𝖶𝗁𝖺𝗍 𝖸𝗈𝗎 𝖶𝖺𝗇𝗇𝖺 𝖤𝗑𝖾𝖼𝗎𝗍𝖾 𝖡𝖺𝖻𝗒 ?") 46 | try: 47 | cmd = message.text.split(" ", maxsplit=1)[1] 48 | except IndexError: 49 | return await message.delete() 50 | t1 = time() 51 | old_stderr = sys.stderr 52 | old_stdout = sys.stdout 53 | redirected_output = sys.stdout = StringIO() 54 | redirected_error = sys.stderr = StringIO() 55 | stdout, stderr, exc = None, None, None 56 | try: 57 | await aexec(cmd, client, message) 58 | except Exception: 59 | exc = traceback.format_exc() 60 | stdout = redirected_output.getvalue() 61 | stderr = redirected_error.getvalue() 62 | sys.stdout = old_stdout 63 | sys.stderr = old_stderr 64 | evaluation = "\n" 65 | if exc: 66 | evaluation += exc 67 | elif stderr: 68 | evaluation += stderr 69 | elif stdout: 70 | evaluation += stdout 71 | else: 72 | evaluation += "Success" 73 | final_output = f"⥤ ʀᴇsᴜʟᴛ :\n
{evaluation}
" 74 | if len(final_output) > 4096: 75 | filename = "output.txt" 76 | with open(filename, "w+", encoding="utf8") as out_file: 77 | out_file.write(str(evaluation)) 78 | t2 = time() 79 | keyboard = InlineKeyboardMarkup( 80 | [ 81 | [ 82 | InlineKeyboardButton( 83 | text="⏳", 84 | callback_data=f"runtime {t2-t1} Seconds", 85 | ) 86 | ] 87 | ] 88 | ) 89 | await message.reply_document( 90 | document=filename, 91 | caption=f"⥤ ᴇᴠᴀʟ :\n{cmd[0:980]}\n\n⥤ ʀᴇsᴜʟᴛ :\nAttached Document", 92 | quote=False, 93 | reply_markup=keyboard, 94 | ) 95 | await message.delete() 96 | os.remove(filename) 97 | else: 98 | t2 = time() 99 | keyboard = InlineKeyboardMarkup( 100 | [ 101 | [ 102 | InlineKeyboardButton( 103 | text="⏳", 104 | callback_data=f"runtime {round(t2-t1, 3)} Seconds", 105 | ), 106 | InlineKeyboardButton( 107 | text="🗑", 108 | callback_data=f"forceclose abc|{message.from_user.id}", 109 | ), 110 | ] 111 | ] 112 | ) 113 | await edit_or_reply(message, text=final_output, reply_markup=keyboard) 114 | 115 | 116 | @app.on_callback_query(filters.regex(r"runtime")) 117 | async def runtime_func_cq(_, cq): 118 | runtime = cq.data.split(None, 1)[1] 119 | await cq.answer(runtime, show_alert=True) 120 | 121 | 122 | @app.on_callback_query(filters.regex("forceclose")) 123 | async def forceclose_command(_, CallbackQuery): 124 | callback_data = CallbackQuery.data.strip() 125 | callback_request = callback_data.split(None, 1)[1] 126 | query, user_id = callback_request.split("|") 127 | if CallbackQuery.from_user.id != int(user_id): 128 | try: 129 | return await CallbackQuery.answer( 130 | "> 𝖨𝗍 𝖶𝗂𝗅𝗅 𝖡𝖾 𝖡𝖾𝗍𝗍𝖾𝗋 𝖨𝖿 𝖸𝗈𝗎 𝖲𝗍𝖺𝗒 𝖨𝗇 𝖸𝗈𝗎𝗋 𝖫𝗂𝗆𝗂𝗍𝗌 .", show_alert=True 131 | ) 132 | except: 133 | return 134 | await CallbackQuery.message.delete() 135 | try: 136 | await CallbackQuery.answer() 137 | except: 138 | return 139 | 140 | 141 | @app.on_edited_message( 142 | filters.command("sh") 143 | & filters.user(OWNER_ID) 144 | & ~filters.forwarded 145 | & ~filters.via_bot 146 | ) 147 | @app.on_message( 148 | filters.command("sh") 149 | & filters.user(OWNER_ID) 150 | & ~filters.forwarded 151 | & ~filters.via_bot 152 | ) 153 | async def shellrunner(_, message: Message): 154 | if len(message.command) < 2: 155 | return await edit_or_reply(message, text="Example :\n/sh git pull") 156 | text = message.text.split(None, 1)[1] 157 | if "\n" in text: 158 | code = text.split("\n") 159 | output = "" 160 | for x in code: 161 | shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x) 162 | try: 163 | process = subprocess.Popen( 164 | shell, 165 | stdout=subprocess.PIPE, 166 | stderr=subprocess.PIPE, 167 | ) 168 | except Exception as err: 169 | await edit_or_reply(message, text=f"ERROR :\n
{err}
") 170 | output += f"{code}\n" 171 | output += process.stdout.read()[:-1].decode("utf-8") 172 | output += "\n" 173 | else: 174 | shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text) 175 | for a in range(len(shell)): 176 | shell[a] = shell[a].replace('"', "") 177 | try: 178 | process = subprocess.Popen( 179 | shell, 180 | stdout=subprocess.PIPE, 181 | stderr=subprocess.PIPE, 182 | ) 183 | except Exception as err: 184 | print(err) 185 | exc_type, exc_obj, exc_tb = sys.exc_info() 186 | errors = traceback.format_exception( 187 | etype=exc_type, 188 | value=exc_obj, 189 | tb=exc_tb, 190 | ) 191 | return await edit_or_reply( 192 | message, text=f"ERROR :\n
{''.join(errors)}
" 193 | ) 194 | output = process.stdout.read()[:-1].decode("utf-8") 195 | if str(output) == "\n": 196 | output = None 197 | if output: 198 | if len(output) > 4096: 199 | with open("output.txt", "w+") as file: 200 | file.write(output) 201 | await app.send_document( 202 | message.chat.id, 203 | "output.txt", 204 | reply_to_message_id=message.id, 205 | caption="Output", 206 | ) 207 | return os.remove("output.txt") 208 | await edit_or_reply(message, text=f"OUTPUT :\n
{output}
") 209 | else: 210 | await edit_or_reply(message, text="OUTPUT :\nNone") 211 | await message.stop_propagation() 212 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/language.py: -------------------------------------------------------------------------------- 1 | from pykeyboard import InlineKeyboard 2 | from pyrogram import filters 3 | from pyrogram.types import InlineKeyboardButton, Message 4 | 5 | from InflexMusic import app 6 | from InflexMusic.utils.database import get_lang, set_lang 7 | from InflexMusic.utils.decorators import ActualAdminCB, language, languageCB 8 | from config import BANNED_USERS 9 | from strings import get_string, languages_present 10 | 11 | 12 | def lanuages_keyboard(_): 13 | keyboard = InlineKeyboard(row_width=2) 14 | keyboard.add( 15 | *[ 16 | ( 17 | InlineKeyboardButton( 18 | text=languages_present[i], 19 | callback_data=f"languages:{i}", 20 | ) 21 | ) 22 | for i in languages_present 23 | ] 24 | ) 25 | keyboard.row( 26 | InlineKeyboardButton( 27 | text=_["BACK_BUTTON"], 28 | callback_data=f"settingsback_helper", 29 | ), 30 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data=f"close"), 31 | ) 32 | return keyboard 33 | 34 | 35 | @app.on_message(filters.command(["lang", "setlang", "language"]) & ~BANNED_USERS) 36 | @language 37 | async def langs_command(client, message: Message, _): 38 | keyboard = lanuages_keyboard(_) 39 | await message.reply_text( 40 | _["lang_1"], 41 | reply_markup=keyboard, 42 | ) 43 | 44 | 45 | @app.on_callback_query(filters.regex("LG") & ~BANNED_USERS) 46 | @languageCB 47 | async def lanuagecb(client, CallbackQuery, _): 48 | try: 49 | await CallbackQuery.answer() 50 | except: 51 | pass 52 | keyboard = lanuages_keyboard(_) 53 | return await CallbackQuery.edit_message_reply_markup(reply_markup=keyboard) 54 | 55 | 56 | @app.on_callback_query(filters.regex(r"languages:(.*?)") & ~BANNED_USERS) 57 | @ActualAdminCB 58 | async def language_markup(client, CallbackQuery, _): 59 | langauge = (CallbackQuery.data).split(":")[1] 60 | old = await get_lang(CallbackQuery.message.chat.id) 61 | if str(old) == str(langauge): 62 | return await CallbackQuery.answer(_["lang_4"], show_alert=True) 63 | try: 64 | _ = get_string(langauge) 65 | await CallbackQuery.answer(_["lang_2"], show_alert=True) 66 | except: 67 | _ = get_string(old) 68 | return await CallbackQuery.answer( 69 | _["lang_3"], 70 | show_alert=True, 71 | ) 72 | await set_lang(CallbackQuery.message.chat.id, langauge) 73 | keyboard = lanuages_keyboard(_) 74 | return await CallbackQuery.edit_message_reply_markup(reply_markup=keyboard) 75 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/ping.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | import random 3 | 4 | from pyrogram import filters 5 | from pyrogram.types import Message 6 | 7 | from InflexMusic import app 8 | from InflexMusic.core.call import Inflex 9 | from InflexMusic.utils import bot_sys_stats 10 | from InflexMusic.utils.decorators.language import language 11 | from InflexMusic.utils.inline import supp_markup 12 | from config import BANNED_USERS, PING_IMG_URL 13 | 14 | 15 | @app.on_message(filters.command(["ping", "alive"]) & ~BANNED_USERS) 16 | @language 17 | async def ping_com(client, message: Message, _): 18 | start = datetime.now() 19 | response = await message.reply_photo( 20 | photo=random.choice(PING_IMG_URL), 21 | caption=_["ping_1"].format(app.mention), 22 | ) 23 | pytgping = await Inflex.ping() 24 | UP, CPU, RAM, DISK = await bot_sys_stats() 25 | resp = (datetime.now() - start).microseconds / 1000 26 | await response.edit_text( 27 | _["ping_2"].format(resp, app.mention, UP, RAM, CPU, DISK, pytgping), 28 | reply_markup=supp_markup(_), 29 | ) 30 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/reload.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import time 3 | 4 | from pyrogram import filters 5 | from pyrogram.enums import ChatMembersFilter 6 | from pyrogram.types import CallbackQuery, Message 7 | 8 | from InflexMusic import app 9 | from InflexMusic.core.call import Inflex 10 | from InflexMusic.misc import db 11 | from InflexMusic.utils.database import get_assistant, get_authuser_names, get_cmode 12 | from InflexMusic.utils.decorators import ActualAdminCB, AdminActual, language 13 | from InflexMusic.utils.formatters import alpha_to_int, get_readable_time 14 | from config import BANNED_USERS, adminlist, lyrical 15 | 16 | rel = {} 17 | 18 | 19 | @app.on_message( 20 | filters.command(["admincache", "reload", "refresh"]) & filters.group & ~BANNED_USERS 21 | ) 22 | @language 23 | async def reload_admin_cache(client, message: Message, _): 24 | try: 25 | if message.chat.id not in rel: 26 | rel[message.chat.id] = {} 27 | else: 28 | saved = rel[message.chat.id] 29 | if saved > time.time(): 30 | left = get_readable_time((int(saved) - int(time.time()))) 31 | return await message.reply_text(_["reload_1"].format(left)) 32 | adminlist[message.chat.id] = [] 33 | async for user in app.get_chat_members( 34 | message.chat.id, filter=ChatMembersFilter.ADMINISTRATORS 35 | ): 36 | if user.privileges.can_manage_video_chats: 37 | adminlist[message.chat.id].append(user.user.id) 38 | authusers = await get_authuser_names(message.chat.id) 39 | for user in authusers: 40 | user_id = await alpha_to_int(user) 41 | adminlist[message.chat.id].append(user_id) 42 | now = int(time.time()) + 180 43 | rel[message.chat.id] = now 44 | await message.reply_text(_["reload_2"]) 45 | except: 46 | await message.reply_text(_["reload_3"]) 47 | 48 | 49 | @app.on_message(filters.command(["reboot"]) & filters.group & ~BANNED_USERS) 50 | @AdminActual 51 | async def restartbot(client, message: Message, _): 52 | mystic = await message.reply_text(_["reload_4"].format(app.mention)) 53 | await asyncio.sleep(1) 54 | try: 55 | db[message.chat.id] = [] 56 | await Inflex.stop_stream_force(message.chat.id) 57 | except: 58 | pass 59 | userbot = await get_assistant(message.chat.id) 60 | try: 61 | if message.chat.username: 62 | await userbot.resolve_peer(message.chat.username) 63 | else: 64 | await userbot.resolve_peer(message.chat.id) 65 | except: 66 | pass 67 | chat_id = await get_cmode(message.chat.id) 68 | if chat_id: 69 | try: 70 | got = await app.get_chat(chat_id) 71 | except: 72 | pass 73 | userbot = await get_assistant(chat_id) 74 | try: 75 | if got.username: 76 | await userbot.resolve_peer(got.username) 77 | else: 78 | await userbot.resolve_peer(chat_id) 79 | except: 80 | pass 81 | try: 82 | db[chat_id] = [] 83 | await Inflex.stop_stream_force(chat_id) 84 | except: 85 | pass 86 | return await mystic.edit_text(_["reload_5"].format(app.mention)) 87 | 88 | 89 | @app.on_callback_query(filters.regex("close") & ~BANNED_USERS) 90 | async def close_menu(_, query: CallbackQuery): 91 | try: 92 | await query.answer() 93 | await query.message.delete() 94 | umm = await query.message.reply_text( 95 | f"➜ 𝖢𝗅𝗈𝗌𝖾𝖽 𝖡𝗒 : {query.from_user.mention}" 96 | ) 97 | await asyncio.sleep(7) 98 | await umm.delete() 99 | except: 100 | pass 101 | 102 | 103 | @app.on_callback_query(filters.regex("stop_downloading") & ~BANNED_USERS) 104 | @ActualAdminCB 105 | async def stop_download(client, CallbackQuery: CallbackQuery, _): 106 | message_id = CallbackQuery.message.id 107 | task = lyrical.get(message_id) 108 | if not task: 109 | return await CallbackQuery.answer(_["tg_4"], show_alert=True) 110 | if task.done() or task.cancelled(): 111 | return await CallbackQuery.answer(_["tg_5"], show_alert=True) 112 | if not task.done(): 113 | try: 114 | task.cancel() 115 | try: 116 | lyrical.pop(message_id) 117 | except: 118 | pass 119 | await CallbackQuery.answer(_["tg_6"], show_alert=True) 120 | return await CallbackQuery.edit_message_text( 121 | _["tg_7"].format(CallbackQuery.from_user.mention) 122 | ) 123 | except: 124 | return await CallbackQuery.answer(_["tg_8"], show_alert=True) 125 | await CallbackQuery.answer(_["tg_9"], show_alert=True) 126 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/speedtest.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | import speedtest 4 | from pyrogram import filters 5 | from pyrogram.types import Message 6 | 7 | from InflexMusic import app 8 | from config import OWNER_ID 9 | from InflexMusic.misc import SUDOERS 10 | from InflexMusic.utils.decorators.language import language 11 | 12 | 13 | def testspeed(m, _): 14 | try: 15 | test = speedtest.Speedtest() 16 | test.get_best_server() 17 | m = m.edit_text(_["server_12"]) 18 | test.download() 19 | m = m.edit_text(_["server_13"]) 20 | test.upload() 21 | test.results.share() 22 | result = test.results.dict() 23 | m = m.edit_text(_["server_14"]) 24 | except Exception as e: 25 | return m.edit_text(f"{e}") 26 | return result 27 | 28 | 29 | @app.on_message(filters.command(["speedtest", "spt"]) & SUDOERS) 30 | @language 31 | async def speedtest_function(client, message: Message, _): 32 | m = await message.reply_text(_["server_11"]) 33 | loop = asyncio.get_event_loop() 34 | result = await loop.run_in_executor(None, testspeed, m, _) 35 | output = _["server_15"].format( 36 | result["client"]["isp"], 37 | result["client"]["country"], 38 | result["server"]["name"], 39 | result["server"]["country"], 40 | result["server"]["cc"], 41 | result["server"]["sponsor"], 42 | result["server"]["latency"], 43 | result["ping"], 44 | ) 45 | msg = await message.reply_photo(photo=result["share"], caption=output) 46 | await m.delete() 47 | -------------------------------------------------------------------------------- /InflexMusic/plugins/tools/stats.py: -------------------------------------------------------------------------------- 1 | import platform 2 | import random 3 | from sys import version as pyver 4 | 5 | import psutil 6 | from pyrogram import __version__ as pyrover 7 | from pyrogram import filters 8 | from pyrogram.errors import MessageIdInvalid 9 | from pyrogram.types import InputMediaPhoto, Message 10 | from pytgcalls.__version__ import __version__ as pytgver 11 | 12 | import config 13 | from config import STATS_IMG_URL 14 | from InflexMusic import app 15 | from InflexMusic.core.userbot import assistants 16 | from InflexMusic.misc import SUDOERS, mongodb 17 | from InflexMusic.plugins import ALL_MODULES 18 | from InflexMusic.utils.database import get_served_chats, get_served_users, get_sudoers 19 | from InflexMusic.utils.decorators.language import language, languageCB 20 | from InflexMusic.utils.inline.stats import back_stats_buttons, stats_buttons 21 | from config import BANNED_USERS 22 | from config import OWNER_ID 23 | 24 | 25 | @app.on_message(filters.command(["stats", "gstats"]) & filters.group & ~BANNED_USERS) 26 | @language 27 | async def stats_global(client, message: Message, _): 28 | upl = stats_buttons(_, True if message.from_user.id in SUDOERS else False) 29 | await message.reply_photo( 30 | photo=random.choice(STATS_IMG_URL), 31 | caption=_["gstats_2"].format(app.mention), 32 | reply_markup=upl, 33 | ) 34 | 35 | 36 | @app.on_callback_query(filters.regex("stats_back") & ~BANNED_USERS) 37 | @languageCB 38 | async def home_stats(client, CallbackQuery, _): 39 | upl = stats_buttons(_, True if CallbackQuery.from_user.id in SUDOERS else False) 40 | await CallbackQuery.edit_message_text( 41 | text=_["gstats_2"].format(app.mention), 42 | reply_markup=upl, 43 | ) 44 | 45 | 46 | @app.on_callback_query(filters.regex("TopOverall") & ~BANNED_USERS) 47 | @languageCB 48 | async def overall_stats(client, CallbackQuery, _): 49 | await CallbackQuery.answer() 50 | upl = back_stats_buttons(_) 51 | try: 52 | await CallbackQuery.answer() 53 | except: 54 | pass 55 | await CallbackQuery.edit_message_text(_["gstats_1"].format(app.mention)) 56 | served_chats = len(await get_served_chats()) 57 | served_users = len(await get_served_users()) 58 | text = _["gstats_3"].format( 59 | app.mention, 60 | len(assistants), 61 | len(BANNED_USERS), 62 | served_chats, 63 | served_users, 64 | len(ALL_MODULES), 65 | len(SUDOERS), 66 | config.AUTO_LEAVING_ASSISTANT, 67 | config.DURATION_LIMIT_MIN, 68 | ) 69 | med = InputMediaPhoto(media=random.choice(STATS_IMG_URL), caption=text) 70 | try: 71 | await CallbackQuery.edit_message_media(media=med, reply_markup=upl) 72 | except MessageIdInvalid: 73 | await CallbackQuery.message.reply_photo( 74 | photo=random.choice(STATS_IMG_URL), caption=text, reply_markup=upl 75 | ) 76 | 77 | 78 | @app.on_callback_query(filters.regex("bot_stats_sudo")) 79 | @languageCB 80 | async def bot_stats(client, CallbackQuery, _): 81 | if CallbackQuery.from_user.id not in SUDOERS: 82 | return await CallbackQuery.answer(_["gstats_4"], show_alert=True) 83 | upl = back_stats_buttons(_) 84 | try: 85 | await CallbackQuery.answer() 86 | except: 87 | pass 88 | await CallbackQuery.edit_message_text(_["gstats_1"].format(app.mention)) 89 | p_core = psutil.cpu_count(logical=False) 90 | t_core = psutil.cpu_count(logical=True) 91 | ram = str(round(psutil.virtual_memory().total / (1024.0**3))) + " ɢʙ" 92 | try: 93 | cpu_freq = psutil.cpu_freq().current 94 | if cpu_freq >= 1000: 95 | cpu_freq = f"{round(cpu_freq / 1000, 2)}ɢʜᴢ" 96 | else: 97 | cpu_freq = f"{round(cpu_freq, 2)}ᴍʜᴢ" 98 | except: 99 | cpu_freq = "𝖥𝖺𝗂𝗅𝖾𝖽 𝖳𝗈 𝖥𝖾𝗍𝖼𝗁" 100 | hdd = psutil.disk_usage("/") 101 | total = hdd.total / (1024.0**3) 102 | used = hdd.used / (1024.0**3) 103 | free = hdd.free / (1024.0**3) 104 | call = await mongodb.command("dbstats") 105 | datasize = call["dataSize"] / 1024 106 | storage = call["storageSize"] / 1024 107 | served_chats = len(await get_served_chats()) 108 | served_users = len(await get_served_users()) 109 | text = _["gstats_5"].format( 110 | app.mention, 111 | len(ALL_MODULES), 112 | platform.system(), 113 | ram, 114 | p_core, 115 | t_core, 116 | cpu_freq, 117 | pyver.split()[0], 118 | pyrover, 119 | pytgver, 120 | str(total)[:4], 121 | str(used)[:4], 122 | str(free)[:4], 123 | served_chats, 124 | served_users, 125 | len(BANNED_USERS), 126 | len(await get_sudoers()), 127 | str(datasize)[:6], 128 | storage, 129 | call["collections"], 130 | call["objects"], 131 | ) 132 | med = InputMediaPhoto(media=random.choice(STATS_IMG_URL), caption=text) 133 | try: 134 | await CallbackQuery.edit_message_media(media=med, reply_markup=upl) 135 | except MessageIdInvalid: 136 | await CallbackQuery.message.reply_photo( 137 | photo=random.choice(STATS_IMG_URL), caption=text, reply_markup=upl 138 | ) 139 | -------------------------------------------------------------------------------- /InflexMusic/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .channelplay import * 2 | from .database import * 3 | from .decorators import * 4 | from .extraction import * 5 | from .formatters import * 6 | from .inline import * 7 | from .pastebin import * 8 | from .sys import * 9 | -------------------------------------------------------------------------------- /InflexMusic/utils/channelplay.py: -------------------------------------------------------------------------------- 1 | from InflexMusic import app 2 | from InflexMusic.utils.database import get_cmode 3 | 4 | 5 | async def get_channeplayCB(_, command, CallbackQuery): 6 | if command == "c": 7 | chat_id = await get_cmode(CallbackQuery.message.chat.id) 8 | if chat_id is None: 9 | try: 10 | return await CallbackQuery.answer(_["setting_7"], show_alert=True) 11 | except: 12 | return 13 | try: 14 | channel = (await app.get_chat(chat_id)).title 15 | except: 16 | try: 17 | return await CallbackQuery.answer(_["cplay_4"], show_alert=True) 18 | except: 19 | return 20 | else: 21 | chat_id = CallbackQuery.message.chat.id 22 | channel = None 23 | return chat_id, channel 24 | -------------------------------------------------------------------------------- /InflexMusic/utils/decorators/__init__.py: -------------------------------------------------------------------------------- 1 | from .admins import * 2 | from .language import * 3 | -------------------------------------------------------------------------------- /InflexMusic/utils/decorators/admins.py: -------------------------------------------------------------------------------- 1 | from pyrogram.enums import ChatType 2 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 3 | 4 | from InflexMusic import app 5 | from InflexMusic.misc import SUDOERS, db 6 | from InflexMusic.utils.database import ( 7 | get_authuser_names, 8 | get_cmode, 9 | get_lang, 10 | get_upvote_count, 11 | is_active_chat, 12 | is_maintenance, 13 | is_nonadmin_chat, 14 | is_skipmode, 15 | ) 16 | from config import SUPPORT_GROUP, adminlist, confirmer 17 | from strings import get_string 18 | 19 | from ..formatters import int_to_alpha 20 | 21 | 22 | def AdminRightsCheck(mystic): 23 | async def wrapper(client, message): 24 | if await is_maintenance() is False: 25 | if message.from_user.id not in SUDOERS: 26 | return await message.reply_text( 27 | text=f"{app.mention} 𝖨𝗌 𝖴𝗇𝖽𝖾𝗋 𝖬𝖺𝗂𝗇𝗍𝖾𝗇𝖺𝗇𝖼𝖾 , 𝖵𝗂𝗌𝗂𝗍 𝖲𝗎𝗉𝗉𝗈𝗋𝗍 𝖢𝗁𝖺𝗍 𝖥𝗈𝗋 𝖪𝗇𝗈𝗐𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝖺𝗌𝗈𝗇 .", 28 | disable_web_page_preview=True, 29 | ) 30 | 31 | try: 32 | await message.delete() 33 | except: 34 | pass 35 | 36 | try: 37 | language = await get_lang(message.chat.id) 38 | _ = get_string(language) 39 | except: 40 | _ = get_string("en") 41 | if message.sender_chat: 42 | upl = InlineKeyboardMarkup( 43 | [ 44 | [ 45 | InlineKeyboardButton( 46 | text="𝖧𝗈𝗐 𝖳𝗈 𝖥𝗂𝗑 ?", 47 | callback_data="AnonymousAdmin", 48 | ), 49 | ] 50 | ] 51 | ) 52 | return await message.reply_text(_["general_3"], reply_markup=upl) 53 | if message.command[0][0] == "c": 54 | chat_id = await get_cmode(message.chat.id) 55 | if chat_id is None: 56 | return await message.reply_text(_["setting_7"]) 57 | try: 58 | await app.get_chat(chat_id) 59 | except: 60 | return await message.reply_text(_["cplay_4"]) 61 | else: 62 | chat_id = message.chat.id 63 | if not await is_active_chat(chat_id): 64 | return await message.reply_text(_["general_5"]) 65 | is_non_admin = await is_nonadmin_chat(message.chat.id) 66 | if not is_non_admin: 67 | if message.from_user.id not in SUDOERS: 68 | admins = adminlist.get(message.chat.id) 69 | if not admins: 70 | return await message.reply_text(_["admin_13"]) 71 | else: 72 | if message.from_user.id not in admins: 73 | if await is_skipmode(message.chat.id): 74 | upvote = await get_upvote_count(chat_id) 75 | text = f"""𝖠𝖽𝗆𝗂𝗇 𝖱𝗂𝗀𝗁𝗍𝗌 𝖭𝖾𝖾𝖽𝖾𝖽 76 | 77 | 𝖱𝖾𝖿𝗋𝖾𝗌𝗁 𝖠𝖽𝗆𝗂𝗇 𝖢𝖺𝖼𝗁𝖾 𝖵𝗂𝖺 : /reload""" 78 | 79 | command = message.command[0] 80 | if command[0] == "c": 81 | command = command[1:] 82 | if command == "speed": 83 | return await message.reply_text(_["admin_14"]) 84 | MODE = command.title() 85 | upl = InlineKeyboardMarkup( 86 | [ 87 | [ 88 | InlineKeyboardButton( 89 | text="𝖢𝗅𝗈𝗌𝖾", 90 | callback_data="close", 91 | ), 92 | ] 93 | ] 94 | ) 95 | if chat_id not in confirmer: 96 | confirmer[chat_id] = {} 97 | try: 98 | vidid = db[chat_id][0]["vidid"] 99 | file = db[chat_id][0]["file"] 100 | except: 101 | return await message.reply_text(_["admin_14"]) 102 | senn = await message.reply_text(text, reply_markup=upl) 103 | confirmer[chat_id][senn.id] = { 104 | "vidid": vidid, 105 | "file": file, 106 | } 107 | return 108 | else: 109 | return await message.reply_text(_["admin_14"]) 110 | 111 | return await mystic(client, message, _, chat_id) 112 | 113 | return wrapper 114 | 115 | 116 | def AdminActual(mystic): 117 | async def wrapper(client, message): 118 | if await is_maintenance() is False: 119 | if message.from_user.id not in SUDOERS: 120 | return await message.reply_text( 121 | text=f"{app.mention} 𝖨𝗌 𝖴𝗇𝖽𝖾𝗋 𝖬𝖺𝗂𝗇𝗍𝖾𝗇𝖺𝗇𝖼𝖾 , 𝖵𝗂𝗌𝗂𝗍 𝖲𝗎𝗉𝗉𝗈𝗋𝗍 𝖢𝗁𝖺𝗍 𝖥𝗈𝗋 𝖪𝗇𝗈𝗐𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝖺𝗌𝗈𝗇 .", 122 | disable_web_page_preview=True, 123 | ) 124 | 125 | try: 126 | await message.delete() 127 | except: 128 | pass 129 | 130 | try: 131 | language = await get_lang(message.chat.id) 132 | _ = get_string(language) 133 | except: 134 | _ = get_string("en") 135 | if message.sender_chat: 136 | upl = InlineKeyboardMarkup( 137 | [ 138 | [ 139 | InlineKeyboardButton( 140 | text="𝖧𝗈𝗐 𝖳𝗈 𝖥𝗂𝗑 ?", 141 | callback_data="AnonymousAdmin", 142 | ), 143 | ] 144 | ] 145 | ) 146 | return await message.reply_text(_["general_3"], reply_markup=upl) 147 | if message.from_user.id not in SUDOERS: 148 | try: 149 | member = ( 150 | await app.get_chat_member(message.chat.id, message.from_user.id) 151 | ).privileges 152 | except: 153 | return 154 | if not member.can_manage_video_chats: 155 | return await message.reply(_["general_4"]) 156 | return await mystic(client, message, _) 157 | 158 | return wrapper 159 | 160 | 161 | def ActualAdminCB(mystic): 162 | async def wrapper(client, CallbackQuery): 163 | if await is_maintenance() is False: 164 | if CallbackQuery.from_user.id not in SUDOERS: 165 | return await CallbackQuery.answer( 166 | f"{app.mention} 𝖨𝗌 𝖴𝗇𝖽𝖾𝗋 𝖬𝖺𝗂𝗇𝗍𝖾𝗇𝖺𝗇𝖼𝖾 , 𝖵𝗂𝗌𝗂𝗍 𝖲𝗎𝗉𝗉𝗈𝗋𝗍 𝖢𝗁𝖺𝗍 𝖥𝗈𝗋 𝖪𝗇𝗈𝗐𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝖺𝗌𝗈𝗇 .", 167 | show_alert=True, 168 | ) 169 | try: 170 | language = await get_lang(CallbackQuery.message.chat.id) 171 | _ = get_string(language) 172 | except: 173 | _ = get_string("en") 174 | if CallbackQuery.message.chat.type == ChatType.PRIVATE: 175 | return await mystic(client, CallbackQuery, _) 176 | is_non_admin = await is_nonadmin_chat(CallbackQuery.message.chat.id) 177 | if not is_non_admin: 178 | try: 179 | a = ( 180 | await app.get_chat_member( 181 | CallbackQuery.message.chat.id, 182 | CallbackQuery.from_user.id, 183 | ) 184 | ).privileges 185 | except: 186 | return await CallbackQuery.answer(_["general_4"], show_alert=True) 187 | if not a.can_manage_video_chats: 188 | if CallbackQuery.from_user.id not in SUDOERS: 189 | token = await int_to_alpha(CallbackQuery.from_user.id) 190 | _check = await get_authuser_names(CallbackQuery.from_user.id) 191 | if token not in _check: 192 | try: 193 | return await CallbackQuery.answer( 194 | _["general_4"], 195 | show_alert=True, 196 | ) 197 | except: 198 | return 199 | return await mystic(client, CallbackQuery, _) 200 | 201 | return wrapper 202 | -------------------------------------------------------------------------------- /InflexMusic/utils/decorators/language.py: -------------------------------------------------------------------------------- 1 | from strings import get_string 2 | 3 | from InflexMusic import app 4 | from InflexMusic.misc import SUDOERS 5 | from InflexMusic.utils.database import get_lang, is_maintenance 6 | 7 | 8 | def language(mystic): 9 | async def wrapper(_, message, **kwargs): 10 | if await is_maintenance() is False: 11 | if message.from_user.id not in SUDOERS: 12 | return await message.reply_text( 13 | text=f"{app.mention} ɪs ᴜɴᴅᴇʀ ᴍᴀɪɴᴛᴇɴᴀɴᴄᴇ, ᴠɪsɪᴛ sᴜᴘᴘᴏʀᴛ ᴄʜᴀᴛ ғᴏʀ ᴋɴᴏᴡɪɴɢ ᴛʜᴇ ʀᴇᴀsᴏɴ.", 14 | disable_web_page_preview=True, 15 | ) 16 | try: 17 | await message.delete() 18 | except: 19 | pass 20 | 21 | try: 22 | language = await get_lang(message.chat.id) 23 | language = get_string(language) 24 | except: 25 | language = get_string("en") 26 | return await mystic(_, message, language) 27 | 28 | return wrapper 29 | 30 | 31 | def languageCB(mystic): 32 | async def wrapper(_, CallbackQuery, **kwargs): 33 | if await is_maintenance() is False: 34 | if CallbackQuery.from_user.id not in SUDOERS: 35 | return await CallbackQuery.answer( 36 | f"{app.mention} ɪs ᴜɴᴅᴇʀ ᴍᴀɪɴᴛᴇɴᴀɴᴄᴇ, ᴠɪsɪᴛ sᴜᴘᴘᴏʀᴛ ᴄʜᴀᴛ ғᴏʀ ᴋɴᴏᴡɪɴɢ ᴛʜᴇ ʀᴇᴀsᴏɴ.", 37 | show_alert=True, 38 | ) 39 | try: 40 | language = await get_lang(CallbackQuery.message.chat.id) 41 | language = get_string(language) 42 | except: 43 | language = get_string("en") 44 | return await mystic(_, CallbackQuery, language) 45 | 46 | return wrapper 47 | 48 | 49 | def LanguageStart(mystic): 50 | async def wrapper(_, message, **kwargs): 51 | try: 52 | language = await get_lang(message.chat.id) 53 | language = get_string(language) 54 | except: 55 | language = get_string("en") 56 | return await mystic(_, message, language) 57 | 58 | return wrapper 59 | -------------------------------------------------------------------------------- /InflexMusic/utils/decorators/play.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | 3 | from pyrogram.enums import ChatMemberStatus 4 | from pyrogram.errors import ( 5 | ChatAdminRequired, 6 | InviteRequestSent, 7 | UserAlreadyParticipant, 8 | UserNotParticipant, 9 | ) 10 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 11 | 12 | from InflexMusic import YouTube, app 13 | from InflexMusic.misc import SUDOERS 14 | from InflexMusic.utils.database import ( 15 | get_assistant, 16 | get_cmode, 17 | get_lang, 18 | get_playmode, 19 | get_playtype, 20 | is_active_chat, 21 | is_maintenance, 22 | ) 23 | from InflexMusic.utils.inline import botplaylist_markup 24 | from config import PLAYLIST_IMG_URL, SUPPORT_GROUP, adminlist 25 | from strings import get_string 26 | 27 | links = {} 28 | 29 | 30 | def PlayWrapper(command): 31 | async def wrapper(client, message): 32 | language = await get_lang(message.chat.id) 33 | _ = get_string(language) 34 | if message.sender_chat: 35 | upl = InlineKeyboardMarkup( 36 | [ 37 | [ 38 | InlineKeyboardButton( 39 | text="ʜᴏᴡ ᴛᴏ ғɪx ?", 40 | callback_data="AnonymousAdmin", 41 | ), 42 | ] 43 | ] 44 | ) 45 | return await message.reply_text(_["general_3"], reply_markup=upl) 46 | 47 | if await is_maintenance() is False: 48 | if message.from_user.id not in SUDOERS: 49 | return await message.reply_text( 50 | text=f"{app.mention} ɪs ᴜɴᴅᴇʀ ᴍᴀɪɴᴛᴇɴᴀɴᴄᴇ, ᴠɪsɪᴛ sᴜᴘᴘᴏʀᴛ ᴄʜᴀᴛ ғᴏʀ ᴋɴᴏᴡɪɴɢ ᴛʜᴇ ʀᴇᴀsᴏɴ.", 51 | disable_web_page_preview=True, 52 | ) 53 | 54 | try: 55 | await message.delete() 56 | except: 57 | pass 58 | 59 | audio_telegram = ( 60 | (message.reply_to_message.audio or message.reply_to_message.voice) 61 | if message.reply_to_message 62 | else None 63 | ) 64 | video_telegram = ( 65 | (message.reply_to_message.video or message.reply_to_message.document) 66 | if message.reply_to_message 67 | else None 68 | ) 69 | url = await YouTube.url(message) 70 | if audio_telegram is None and video_telegram is None and url is None: 71 | if len(message.command) < 2: 72 | if "stream" in message.command: 73 | return await message.reply_text(_["str_1"]) 74 | buttons = botplaylist_markup(_) 75 | return await message.reply_photo( 76 | photo=PLAYLIST_IMG_URL, 77 | caption=_["play_18"], 78 | reply_markup=InlineKeyboardMarkup(buttons), 79 | ) 80 | if message.command[0][0] == "c": 81 | chat_id = await get_cmode(message.chat.id) 82 | if chat_id is None: 83 | return await message.reply_text(_["setting_7"]) 84 | try: 85 | chat = await app.get_chat(chat_id) 86 | except: 87 | return await message.reply_text(_["cplay_4"]) 88 | channel = chat.title 89 | else: 90 | chat_id = message.chat.id 91 | channel = None 92 | playmode = await get_playmode(message.chat.id) 93 | playty = await get_playtype(message.chat.id) 94 | if playty != "Everyone": 95 | if message.from_user.id not in SUDOERS: 96 | admins = adminlist.get(message.chat.id) 97 | if not admins: 98 | return await message.reply_text(_["admin_13"]) 99 | else: 100 | if message.from_user.id not in admins: 101 | return await message.reply_text(_["play_4"]) 102 | if message.command[0][0] == "v": 103 | video = True 104 | else: 105 | if "-v" in message.text: 106 | video = True 107 | else: 108 | video = True if message.command[0][1] == "v" else None 109 | if message.command[0][-1] == "e": 110 | if not await is_active_chat(chat_id): 111 | return await message.reply_text(_["play_16"]) 112 | fplay = True 113 | else: 114 | fplay = None 115 | 116 | if not await is_active_chat(chat_id): 117 | userbot = await get_assistant(chat_id) 118 | try: 119 | try: 120 | get = await app.get_chat_member(chat_id, userbot.id) 121 | except ChatAdminRequired: 122 | return await message.reply_text(_["call_1"]) 123 | if ( 124 | get.status == ChatMemberStatus.BANNED 125 | or get.status == ChatMemberStatus.RESTRICTED 126 | ): 127 | return await message.reply_text( 128 | _["call_2"].format( 129 | app.mention, userbot.id, userbot.name, userbot.username 130 | ) 131 | ) 132 | except UserNotParticipant: 133 | if chat_id in links: 134 | invitelink = links[chat_id] 135 | else: 136 | if message.chat.username: 137 | invitelink = message.chat.username 138 | try: 139 | await userbot.resolve_peer(invitelink) 140 | except: 141 | pass 142 | else: 143 | try: 144 | invitelink = await app.export_chat_invite_link(chat_id) 145 | except ChatAdminRequired: 146 | return await message.reply_text(_["call_1"]) 147 | except Exception as e: 148 | return await message.reply_text( 149 | _["call_3"].format(app.mention, type(e).__name__) 150 | ) 151 | 152 | if invitelink.startswith("https://t.me/+"): 153 | invitelink = invitelink.replace( 154 | "https://t.me/+", "https://t.me/joinchat/" 155 | ) 156 | myu = await message.reply_text(_["call_4"].format(app.mention)) 157 | try: 158 | await asyncio.sleep(1) 159 | await userbot.join_chat(invitelink) 160 | except InviteRequestSent: 161 | try: 162 | await app.approve_chat_join_request(chat_id, userbot.id) 163 | except Exception as e: 164 | return await message.reply_text( 165 | _["call_3"].format(app.mention, type(e).__name__) 166 | ) 167 | await asyncio.sleep(3) 168 | await myu.edit(_["call_5"].format(app.mention)) 169 | except UserAlreadyParticipant: 170 | pass 171 | except Exception as e: 172 | return await message.reply_text( 173 | _["call_3"].format(app.mention, type(e).__name__) 174 | ) 175 | 176 | links[chat_id] = invitelink 177 | 178 | try: 179 | await userbot.resolve_peer(chat_id) 180 | except: 181 | pass 182 | 183 | return await command( 184 | client, 185 | message, 186 | _, 187 | chat_id, 188 | video, 189 | channel, 190 | playmode, 191 | url, 192 | fplay, 193 | ) 194 | 195 | return wrapper 196 | -------------------------------------------------------------------------------- /InflexMusic/utils/exceptions.py: -------------------------------------------------------------------------------- 1 | class AssistantErr(Exception): 2 | def __init__(self, errr: str): 3 | super().__init__(errr) 4 | -------------------------------------------------------------------------------- /InflexMusic/utils/extraction.py: -------------------------------------------------------------------------------- 1 | from pyrogram.enums import MessageEntityType 2 | from pyrogram.types import Message, User 3 | 4 | from InflexMusic import app 5 | 6 | 7 | async def extract_user(m: Message) -> User: 8 | if m.reply_to_message: 9 | return m.reply_to_message.from_user 10 | msg_entities = m.entities[1] if m.text.startswith("/") else m.entities[0] 11 | return await app.get_users( 12 | msg_entities.user.id 13 | if msg_entities.type == MessageEntityType.TEXT_MENTION 14 | else int(m.command[1]) 15 | if m.command[1].isdecimal() 16 | else m.command[1] 17 | ) 18 | -------------------------------------------------------------------------------- /InflexMusic/utils/formatters.py: -------------------------------------------------------------------------------- 1 | import json 2 | import subprocess 3 | 4 | 5 | def get_readable_time(seconds: int) -> str: 6 | count = 0 7 | ping_time = "" 8 | time_list = [] 9 | time_suffix_list = ["s", "ᴍ", "ʜ", "ᴅᴀʏs"] 10 | while count < 4: 11 | count += 1 12 | if count < 3: 13 | remainder, result = divmod(seconds, 60) 14 | else: 15 | remainder, result = divmod(seconds, 24) 16 | if seconds == 0 and remainder == 0: 17 | break 18 | time_list.append(int(result)) 19 | seconds = int(remainder) 20 | for i in range(len(time_list)): 21 | time_list[i] = str(time_list[i]) + time_suffix_list[i] 22 | if len(time_list) == 4: 23 | ping_time += time_list.pop() + ", " 24 | time_list.reverse() 25 | ping_time += ":".join(time_list) 26 | return ping_time 27 | 28 | 29 | def convert_bytes(size: float) -> str: 30 | """humanize size""" 31 | if not size: 32 | return "" 33 | power = 1024 34 | t_n = 0 35 | power_dict = {0: " ", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"} 36 | while size > power: 37 | size /= power 38 | t_n += 1 39 | return "{:.2f} {}B".format(size, power_dict[t_n]) 40 | 41 | 42 | async def int_to_alpha(user_id: int) -> str: 43 | alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] 44 | text = "" 45 | user_id = str(user_id) 46 | for i in user_id: 47 | text += alphabet[int(i)] 48 | return text 49 | 50 | 51 | async def alpha_to_int(user_id_alphabet: str) -> int: 52 | alphabet = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] 53 | user_id = "" 54 | for i in user_id_alphabet: 55 | index = alphabet.index(i) 56 | user_id += str(index) 57 | user_id = int(user_id) 58 | return user_id 59 | 60 | 61 | def time_to_seconds(time): 62 | stringt = str(time) 63 | return sum(int(x) * 60**i for i, x in enumerate(reversed(stringt.split(":")))) 64 | 65 | 66 | def seconds_to_min(seconds): 67 | if seconds is not None: 68 | seconds = int(seconds) 69 | d, h, m, s = ( 70 | seconds // (3600 * 24), 71 | seconds // 3600 % 24, 72 | seconds % 3600 // 60, 73 | seconds % 3600 % 60, 74 | ) 75 | if d > 0: 76 | return "{:02d}:{:02d}:{:02d}:{:02d}".format(d, h, m, s) 77 | elif h > 0: 78 | return "{:02d}:{:02d}:{:02d}".format(h, m, s) 79 | elif m > 0: 80 | return "{:02d}:{:02d}".format(m, s) 81 | elif s > 0: 82 | return "00:{:02d}".format(s) 83 | return "-" 84 | 85 | 86 | def speed_converter(seconds, speed): 87 | if str(speed) == str("0.5"): 88 | seconds = seconds * 2 89 | if str(speed) == str("0.75"): 90 | seconds = seconds + ((50 * seconds) // 100) 91 | if str(speed) == str("1.5"): 92 | seconds = seconds - ((25 * seconds) // 100) 93 | if str(speed) == str("2.0"): 94 | seconds = seconds - ((50 * seconds) // 100) 95 | collect = seconds 96 | if seconds is not None: 97 | seconds = int(seconds) 98 | d, h, m, s = ( 99 | seconds // (3600 * 24), 100 | seconds // 3600 % 24, 101 | seconds % 3600 // 60, 102 | seconds % 3600 % 60, 103 | ) 104 | if d > 0: 105 | convert = "{:02d}:{:02d}:{:02d}:{:02d}".format(d, h, m, s) 106 | return convert, collect 107 | elif h > 0: 108 | convert = "{:02d}:{:02d}:{:02d}".format(h, m, s) 109 | return convert, collect 110 | elif m > 0: 111 | convert = "{:02d}:{:02d}".format(m, s) 112 | return convert, collect 113 | elif s > 0: 114 | convert = "00:{:02d}".format(s) 115 | return convert, collect 116 | return "-" 117 | 118 | 119 | def check_duration(file_path): 120 | command = [ 121 | "ffprobe", 122 | "-loglevel", 123 | "quiet", 124 | "-print_format", 125 | "json", 126 | "-show_format", 127 | "-show_streams", 128 | file_path, 129 | ] 130 | 131 | pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 132 | out, err = pipe.communicate() 133 | _json = json.loads(out) 134 | 135 | if "format" in _json: 136 | if "duration" in _json["format"]: 137 | return float(_json["format"]["duration"]) 138 | 139 | if "streams" in _json: 140 | for s in _json["streams"]: 141 | if "duration" in s: 142 | return float(s["duration"]) 143 | 144 | return "Unknown" 145 | 146 | 147 | formats = [ 148 | "webm", 149 | "mkv", 150 | "flv", 151 | "vob", 152 | "ogv", 153 | "ogg", 154 | "rrc", 155 | "gifv", 156 | "mng", 157 | "mov", 158 | "avi", 159 | "qt", 160 | "wmv", 161 | "yuv", 162 | "rm", 163 | "asf", 164 | "amv", 165 | "mp4", 166 | "m4p", 167 | "m4v", 168 | "mpg", 169 | "mp2", 170 | "mpeg", 171 | "mpe", 172 | "mpv", 173 | "m4v", 174 | "svi", 175 | "3gp", 176 | "3g2", 177 | "mxf", 178 | "roq", 179 | "nsv", 180 | "flv", 181 | "f4v", 182 | "f4p", 183 | "f4a", 184 | "f4b", 185 | ] 186 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/__init__.py: -------------------------------------------------------------------------------- 1 | from .extras import * 2 | from .help import * 3 | from .play import * 4 | from .queue import * 5 | from .settings import * 6 | from .speed import * 7 | from .start import * 8 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/extras.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | from config import SUPPORT_GROUP 4 | 5 | 6 | def botplaylist_markup(_): 7 | buttons = [ 8 | [ 9 | InlineKeyboardButton(text=_["S_B_9"], url=SUPPORT_GROUP), 10 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 11 | ], 12 | ] 13 | return buttons 14 | 15 | 16 | def close_markup(_): 17 | upl = InlineKeyboardMarkup( 18 | [ 19 | [ 20 | InlineKeyboardButton( 21 | text=_["CLOSE_BUTTON"], 22 | callback_data="close", 23 | ), 24 | ] 25 | ] 26 | ) 27 | return upl 28 | 29 | 30 | def supp_markup(_): 31 | upl = InlineKeyboardMarkup( 32 | [ 33 | [ 34 | InlineKeyboardButton( 35 | text=_["S_B_9"], 36 | url=SUPPORT_GROUP, 37 | ), 38 | ] 39 | ] 40 | ) 41 | return upl 42 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/help.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 4 | 5 | from InflexMusic import app 6 | 7 | 8 | def help_pannel(_, START: Union[bool, int] = None): 9 | first = [InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data=f"close")] 10 | second = [ 11 | InlineKeyboardButton( 12 | text=_["BACK_BUTTON"], 13 | callback_data=f"settingsback_helper", 14 | ), 15 | ] 16 | mark = second if START else first 17 | upl = InlineKeyboardMarkup( 18 | [ 19 | [ 20 | InlineKeyboardButton( 21 | text=_["H_B_1"], 22 | callback_data="help_callback hb1", 23 | ), 24 | InlineKeyboardButton( 25 | text=_["H_B_2"], 26 | callback_data="help_callback hb2", 27 | ), 28 | InlineKeyboardButton( 29 | text=_["H_B_3"], 30 | callback_data="help_callback hb3", 31 | ), 32 | ], 33 | [ 34 | InlineKeyboardButton( 35 | text=_["H_B_4"], 36 | callback_data="help_callback hb4", 37 | ), 38 | InlineKeyboardButton( 39 | text=_["H_B_5"], 40 | callback_data="help_callback hb5", 41 | ), 42 | InlineKeyboardButton( 43 | text=_["H_B_6"], 44 | callback_data="help_callback hb6", 45 | ), 46 | ], 47 | [ 48 | InlineKeyboardButton( 49 | text=_["H_B_7"], 50 | callback_data="help_callback hb7", 51 | ), 52 | InlineKeyboardButton( 53 | text=_["H_B_8"], 54 | callback_data="help_callback hb8", 55 | ), 56 | InlineKeyboardButton( 57 | text=_["H_B_9"], 58 | callback_data="help_callback hb9", 59 | ), 60 | ], 61 | [ 62 | InlineKeyboardButton( 63 | text=_["H_B_10"], 64 | callback_data="help_callback hb10", 65 | ), 66 | InlineKeyboardButton( 67 | text=_["H_B_11"], 68 | callback_data="help_callback hb11", 69 | ), 70 | InlineKeyboardButton( 71 | text=_["H_B_12"], 72 | callback_data="help_callback hb12", 73 | ), 74 | ], 75 | [ 76 | InlineKeyboardButton( 77 | text=_["H_B_13"], 78 | callback_data="help_callback hb13", 79 | ), 80 | InlineKeyboardButton( 81 | text=_["H_B_14"], 82 | callback_data="help_callback hb14", 83 | ), 84 | InlineKeyboardButton( 85 | text=_["H_B_15"], 86 | callback_data="help_callback hb15", 87 | ), 88 | ], 89 | mark, 90 | ] 91 | ) 92 | return upl 93 | 94 | 95 | def help_back_markup(_): 96 | upl = InlineKeyboardMarkup( 97 | [ 98 | [ 99 | InlineKeyboardButton( 100 | text=_["BACK_BUTTON"], 101 | callback_data=f"settings_back_helper", 102 | ), 103 | ] 104 | ] 105 | ) 106 | return upl 107 | 108 | 109 | def private_help_panel(_): 110 | buttons = [ 111 | [ 112 | InlineKeyboardButton( 113 | text=_["S_B_4"], 114 | url=f"https://t.me/{app.username}?start=help", 115 | ), 116 | ], 117 | ] 118 | return buttons 119 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/play.py: -------------------------------------------------------------------------------- 1 | import config 2 | import math 3 | 4 | from pyrogram.types import InlineKeyboardButton 5 | 6 | from InflexMusic.utils.formatters import time_to_seconds 7 | 8 | 9 | def track_markup(_, videoid, user_id, channel, fplay): 10 | buttons = [ 11 | [ 12 | InlineKeyboardButton( 13 | text=_["P_B_1"], 14 | callback_data=f"MusicStream {videoid}|{user_id}|a|{channel}|{fplay}", 15 | ), 16 | InlineKeyboardButton( 17 | text=_["P_B_2"], 18 | callback_data=f"MusicStream {videoid}|{user_id}|v|{channel}|{fplay}", 19 | ), 20 | ], 21 | [ 22 | InlineKeyboardButton( 23 | text=_["CLOSE_BUTTON"], 24 | callback_data=f"forceclose {videoid}|{user_id}", 25 | ) 26 | ], 27 | ] 28 | return buttons 29 | 30 | 31 | def stream_markup_timer(_, chat_id, played, dur): 32 | played_sec = time_to_seconds(played) 33 | duration_sec = time_to_seconds(dur) 34 | percentage = (played_sec / duration_sec) * 100 35 | umm = math.floor(percentage) 36 | if 0 < umm <= 10: 37 | bar = "─▷─────────" 38 | elif 10 < umm < 20: 39 | bar = "──▷────────" 40 | elif 20 <= umm < 30: 41 | bar = "───▷───────" 42 | elif 30 <= umm < 40: 43 | bar = "────▷──────" 44 | elif 40 <= umm < 50: 45 | bar = "─────▷─────" 46 | elif 50 <= umm < 60: 47 | bar = "──────▷────" 48 | elif 60 <= umm < 70: 49 | bar = "───────▷───" 50 | elif 70 <= umm < 80: 51 | bar = "────────▷──" 52 | elif 80 <= umm < 95: 53 | bar = "─────────▷─" 54 | else: 55 | bar = "──────────▷" 56 | buttons = [ 57 | [ 58 | InlineKeyboardButton( 59 | text=f"{played} {bar} {dur}", 60 | callback_data="GetTimer", 61 | ) 62 | ], 63 | [ 64 | InlineKeyboardButton(text=_["S_B_6"], url=config.SUPPORT_CHANNEL), 65 | InlineKeyboardButton(text=_["S_B_2"], url=config.SUPPORT_GROUP), 66 | ], 67 | [InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close")], 68 | ] 69 | return buttons 70 | 71 | 72 | def stream_markup(_, chat_id): 73 | buttons = [ 74 | [ 75 | InlineKeyboardButton(text=_["S_B_6"], url=config.SUPPORT_CHANNEL), 76 | InlineKeyboardButton(text=_["S_B_2"], url=config.SUPPORT_GROUP), 77 | ], 78 | [InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close")], 79 | ] 80 | return buttons 81 | 82 | 83 | def playlist_markup(_, videoid, user_id, ptype, channel, fplay): 84 | buttons = [ 85 | [ 86 | InlineKeyboardButton( 87 | text=_["P_B_1"], 88 | callback_data=f"InflexPlaylists {videoid}|{user_id}|{ptype}|a|{channel}|{fplay}", 89 | ), 90 | InlineKeyboardButton( 91 | text=_["P_B_2"], 92 | callback_data=f"InflexPlaylists {videoid}|{user_id}|{ptype}|v|{channel}|{fplay}", 93 | ), 94 | ], 95 | [ 96 | InlineKeyboardButton( 97 | text=_["CLOSE_BUTTON"], 98 | callback_data=f"forceclose {videoid}|{user_id}", 99 | ), 100 | ], 101 | ] 102 | return buttons 103 | 104 | 105 | def livestream_markup(_, videoid, user_id, mode, channel, fplay): 106 | buttons = [ 107 | [ 108 | InlineKeyboardButton( 109 | text=_["P_B_3"], 110 | callback_data=f"LiveStream {videoid}|{user_id}|{mode}|{channel}|{fplay}", 111 | ), 112 | ], 113 | [ 114 | InlineKeyboardButton( 115 | text=_["CLOSE_BUTTON"], 116 | callback_data=f"forceclose {videoid}|{user_id}", 117 | ), 118 | ], 119 | ] 120 | return buttons 121 | 122 | 123 | def slider_markup(_, videoid, user_id, query, query_type, channel, fplay): 124 | query = f"{query[:20]}" 125 | buttons = [ 126 | [ 127 | InlineKeyboardButton( 128 | text=_["P_B_1"], 129 | callback_data=f"MusicStream {videoid}|{user_id}|a|{channel}|{fplay}", 130 | ), 131 | InlineKeyboardButton( 132 | text=_["P_B_2"], 133 | callback_data=f"MusicStream {videoid}|{user_id}|v|{channel}|{fplay}", 134 | ), 135 | ], 136 | [ 137 | InlineKeyboardButton( 138 | text="◁", 139 | callback_data=f"slider B|{query_type}|{query}|{user_id}|{channel}|{fplay}", 140 | ), 141 | InlineKeyboardButton( 142 | text=_["CLOSE_BUTTON"], 143 | callback_data=f"forceclose {query}|{user_id}", 144 | ), 145 | InlineKeyboardButton( 146 | text="▷", 147 | callback_data=f"slider F|{query_type}|{query}|{user_id}|{channel}|{fplay}", 148 | ), 149 | ], 150 | ] 151 | return buttons 152 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/queue.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | import config 3 | 4 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 5 | 6 | 7 | def queue_markup( 8 | _, 9 | DURATION, 10 | CPLAY, 11 | videoid, 12 | played: Union[bool, int] = None, 13 | dur: Union[bool, int] = None, 14 | ): 15 | not_dur = [ 16 | [ 17 | InlineKeyboardButton( 18 | text=_["QU_B_1"], 19 | callback_data=f"GetQueued {CPLAY}|{videoid}", 20 | ), 21 | InlineKeyboardButton( 22 | text=_["CLOSE_BUTTON"], 23 | callback_data="close", 24 | ), 25 | ] 26 | ] 27 | dur = [ 28 | [ 29 | InlineKeyboardButton( 30 | text=_["QU_B_2"].format(played, dur), 31 | callback_data="GetTimer", 32 | ) 33 | ], 34 | [ 35 | InlineKeyboardButton( 36 | text=_["QU_B_1"], 37 | callback_data=f"GetQueued {CPLAY}|{videoid}", 38 | ), 39 | InlineKeyboardButton( 40 | text=_["CLOSE_BUTTON"], 41 | callback_data="close", 42 | ), 43 | ], 44 | ] 45 | upl = InlineKeyboardMarkup(not_dur if DURATION == "Unknown" else dur) 46 | return upl 47 | 48 | 49 | def queue_back_markup(_, CPLAY): 50 | upl = InlineKeyboardMarkup( 51 | [ 52 | [ 53 | InlineKeyboardButton( 54 | text=_["BACK_BUTTON"], 55 | callback_data=f"queue_back_timer {CPLAY}", 56 | ), 57 | InlineKeyboardButton( 58 | text=_["CLOSE_BUTTON"], 59 | callback_data="close", 60 | ), 61 | ] 62 | ] 63 | ) 64 | return upl 65 | 66 | 67 | def aq_markup(_, chat_id): 68 | buttons = [ 69 | [ 70 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 71 | ], 72 | ] 73 | return buttons 74 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/settings.py: -------------------------------------------------------------------------------- 1 | from typing import Union 2 | 3 | from pyrogram.types import InlineKeyboardButton 4 | 5 | 6 | def setting_markup(_): 7 | buttons = [ 8 | [ 9 | InlineKeyboardButton(text=_["ST_B_1"], callback_data="AU"), 10 | InlineKeyboardButton(text=_["ST_B_3"], callback_data="LG"), 11 | ], 12 | [ 13 | InlineKeyboardButton(text=_["ST_B_2"], callback_data="PM"), 14 | ], 15 | [ 16 | InlineKeyboardButton(text=_["ST_B_4"], callback_data="VM"), 17 | ], 18 | [ 19 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 20 | ], 21 | ] 22 | return buttons 23 | 24 | 25 | def vote_mode_markup(_, current, mode: Union[bool, str] = None): 26 | buttons = [ 27 | [ 28 | InlineKeyboardButton(text="𝖵𝗈𝗍𝗂𝗇𝗀 𝖬𝗈𝖽𝖾 ➜", callback_data="VOTEANSWER"), 29 | InlineKeyboardButton( 30 | text=_["ST_B_5"] if mode == True else _["ST_B_6"], 31 | callback_data="VOMODECHANGE", 32 | ), 33 | ], 34 | [ 35 | InlineKeyboardButton(text="-2", callback_data="FERRARIUDTI M"), 36 | InlineKeyboardButton( 37 | text=f"ᴄᴜʀʀᴇɴᴛ : {current}", 38 | callback_data="ANSWERVOMODE", 39 | ), 40 | InlineKeyboardButton(text="+2", callback_data="FERRARIUDTI A"), 41 | ], 42 | [ 43 | InlineKeyboardButton( 44 | text=_["BACK_BUTTON"], 45 | callback_data="settings_helper", 46 | ), 47 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 48 | ], 49 | ] 50 | return buttons 51 | 52 | 53 | def auth_users_markup(_, status: Union[bool, str] = None): 54 | buttons = [ 55 | [ 56 | InlineKeyboardButton(text=_["ST_B_7"], callback_data="AUTHANSWER"), 57 | InlineKeyboardButton( 58 | text=_["ST_B_8"] if status == True else _["ST_B_9"], 59 | callback_data="AUTH", 60 | ), 61 | ], 62 | [ 63 | InlineKeyboardButton(text=_["ST_B_1"], callback_data="AUTHLIST"), 64 | ], 65 | [ 66 | InlineKeyboardButton( 67 | text=_["BACK_BUTTON"], 68 | callback_data="settings_helper", 69 | ), 70 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 71 | ], 72 | ] 73 | return buttons 74 | 75 | 76 | def playmode_users_markup( 77 | _, 78 | Direct: Union[bool, str] = None, 79 | Group: Union[bool, str] = None, 80 | Playtype: Union[bool, str] = None, 81 | ): 82 | buttons = [ 83 | [ 84 | InlineKeyboardButton(text=_["ST_B_10"], callback_data="SEARCHANSWER"), 85 | InlineKeyboardButton( 86 | text=_["ST_B_11"] if Direct == True else _["ST_B_12"], 87 | callback_data="MODECHANGE", 88 | ), 89 | ], 90 | [ 91 | InlineKeyboardButton(text=_["ST_B_13"], callback_data="AUTHANSWER"), 92 | InlineKeyboardButton( 93 | text=_["ST_B_8"] if Group == True else _["ST_B_9"], 94 | callback_data="CHANNELMODECHANGE", 95 | ), 96 | ], 97 | [ 98 | InlineKeyboardButton(text=_["ST_B_14"], callback_data="PLAYTYPEANSWER"), 99 | InlineKeyboardButton( 100 | text=_["ST_B_8"] if Playtype == True else _["ST_B_9"], 101 | callback_data="PLAYTYPECHANGE", 102 | ), 103 | ], 104 | [ 105 | InlineKeyboardButton( 106 | text=_["BACK_BUTTON"], 107 | callback_data="settings_helper", 108 | ), 109 | InlineKeyboardButton(text=_["CLOSE_BUTTON"], callback_data="close"), 110 | ], 111 | ] 112 | return buttons 113 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/song.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton 2 | 3 | 4 | def song_markup(_, vidid): 5 | buttons = [ 6 | [ 7 | InlineKeyboardButton( 8 | text=_["P_B_1"], 9 | callback_data=f"song_helper audio|{vidid}", 10 | ), 11 | InlineKeyboardButton( 12 | text=_["P_B_2"], 13 | callback_data=f"song_helper video|{vidid}", 14 | ), 15 | ], 16 | [ 17 | InlineKeyboardButton( 18 | text=_["CLOSE_BUTTON"], callback_data="close" 19 | ), 20 | ], 21 | ] 22 | return buttons 23 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/speed.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | 4 | def speed_markup(_, chat_id): 5 | upl = InlineKeyboardMarkup( 6 | [ 7 | [ 8 | InlineKeyboardButton( 9 | text="🕒 0.5x", 10 | callback_data=f"SpeedUP {chat_id}|0.5", 11 | ), 12 | InlineKeyboardButton( 13 | text="🕓 0.75x", 14 | callback_data=f"SpeedUP {chat_id}|0.75", 15 | ), 16 | ], 17 | [ 18 | InlineKeyboardButton( 19 | text=_["P_B_4"], 20 | callback_data=f"SpeedUP {chat_id}|1.0", 21 | ), 22 | ], 23 | [ 24 | InlineKeyboardButton( 25 | text="🕤 1.5x", 26 | callback_data=f"SpeedUP {chat_id}|1.5", 27 | ), 28 | InlineKeyboardButton( 29 | text="🕛 2.0x", 30 | callback_data=f"SpeedUP {chat_id}|2.0", 31 | ), 32 | ], 33 | [ 34 | InlineKeyboardButton( 35 | text=_["CLOSE_BUTTON"], 36 | callback_data="close", 37 | ), 38 | ], 39 | ] 40 | ) 41 | return upl 42 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/start.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton 2 | 3 | import config 4 | from InflexMusic import app 5 | 6 | 7 | def start_panel(_): 8 | buttons = [ 9 | [ 10 | InlineKeyboardButton( 11 | text=_["S_B_1"], url=f"https://t.me/{app.username}?startgroup=true" 12 | ), 13 | InlineKeyboardButton(text=_["S_B_2"], url=config.SUPPORT_GROUP), 14 | ], 15 | ] 16 | return buttons 17 | 18 | 19 | def private_panel(_): 20 | buttons = [ 21 | [ 22 | InlineKeyboardButton( 23 | text=_["S_B_3"], 24 | url=f"https://t.me/{app.username}?startgroup=s&admin=delete_messages+manage_video_chats+pin_messages+invite_users", 25 | ) 26 | ], 27 | [InlineKeyboardButton(text=_["S_B_4"], callback_data="settings_back_helper")], 28 | [ 29 | InlineKeyboardButton(text=_["S_B_6"], url=config.SUPPORT_CHANNEL), 30 | InlineKeyboardButton(text=_["S_B_2"], url=config.SUPPORT_GROUP), 31 | ], 32 | [ 33 | InlineKeyboardButton(text=_["S_B_5"], user_id=config.OWNER_ID), 34 | InlineKeyboardButton(text=_["S_B_7"], url=config.UPSTREAM_REPO), 35 | ], 36 | ] 37 | return buttons 38 | -------------------------------------------------------------------------------- /InflexMusic/utils/inline/stats.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineKeyboardButton, InlineKeyboardMarkup 2 | 3 | 4 | def stats_buttons(_, status): 5 | not_sudo = [ 6 | InlineKeyboardButton( 7 | text=_["SA_B_1"], 8 | callback_data="TopOverall", 9 | ) 10 | ] 11 | sudo = [ 12 | InlineKeyboardButton( 13 | text=_["SA_B_2"], 14 | callback_data="bot_stats_sudo", 15 | ), 16 | InlineKeyboardButton( 17 | text=_["SA_B_3"], 18 | callback_data="TopOverall", 19 | ), 20 | ] 21 | upl = InlineKeyboardMarkup( 22 | [ 23 | sudo if status else not_sudo, 24 | [ 25 | InlineKeyboardButton( 26 | text=_["CLOSE_BUTTON"], 27 | callback_data="close", 28 | ), 29 | ], 30 | ] 31 | ) 32 | return upl 33 | 34 | 35 | def back_stats_buttons(_): 36 | upl = InlineKeyboardMarkup( 37 | [ 38 | [ 39 | InlineKeyboardButton( 40 | text=_["BACK_BUTTON"], 41 | callback_data="stats_back", 42 | ), 43 | InlineKeyboardButton( 44 | text=_["CLOSE_BUTTON"], 45 | callback_data="close", 46 | ), 47 | ], 48 | ] 49 | ) 50 | return upl 51 | -------------------------------------------------------------------------------- /InflexMusic/utils/inlinequery.py: -------------------------------------------------------------------------------- 1 | from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent 2 | 3 | answer = [] 4 | 5 | answer.extend( 6 | [ 7 | InlineQueryResultArticle( 8 | title="Pᴀᴜsᴇ", 9 | description=f"ᴩᴀᴜsᴇ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 10 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 11 | input_message_content=InputTextMessageContent("/pause"), 12 | ), 13 | InlineQueryResultArticle( 14 | title="Rᴇsᴜᴍᴇ", 15 | description=f"ʀᴇsᴜᴍᴇ ᴛʜᴇ ᴩᴀᴜsᴇᴅ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 16 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 17 | input_message_content=InputTextMessageContent("/resume"), 18 | ), 19 | InlineQueryResultArticle( 20 | title="Sᴋɪᴩ", 21 | description=f"sᴋɪᴩ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ ᴀɴᴅ ᴍᴏᴠᴇs ᴛᴏ ᴛʜᴇ ɴᴇxᴛ sᴛʀᴇᴀᴍ.", 22 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 23 | input_message_content=InputTextMessageContent("/skip"), 24 | ), 25 | InlineQueryResultArticle( 26 | title="Eɴᴅ", 27 | description="ᴇɴᴅ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ sᴛʀᴇᴀᴍ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 28 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 29 | input_message_content=InputTextMessageContent("/end"), 30 | ), 31 | InlineQueryResultArticle( 32 | title="Sʜᴜғғʟᴇ", 33 | description="sʜᴜғғʟᴇ ᴛʜᴇ ǫᴜᴇᴜᴇᴅ sᴏɴɢs ɪɴ ᴩʟᴀʏʟɪsᴛ.", 34 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 35 | input_message_content=InputTextMessageContent("/shuffle"), 36 | ), 37 | InlineQueryResultArticle( 38 | title="Lᴏᴏᴩ", 39 | description="ʟᴏᴏᴩ ᴛʜᴇ ᴄᴜʀʀᴇɴᴛ ᴩʟᴀʏɪɴɢ ᴛʀᴀᴄᴋ ᴏɴ ᴠɪᴅᴇᴏᴄʜᴀᴛ.", 40 | thumb_url="https://telegra.ph/file/c5952790fa8235f499749.jpg", 41 | input_message_content=InputTextMessageContent("/loop 3"), 42 | ), 43 | ] 44 | ) 45 | -------------------------------------------------------------------------------- /InflexMusic/utils/logger.py: -------------------------------------------------------------------------------- 1 | from pyrogram.enums import ParseMode 2 | 3 | from InflexMusic import app 4 | from InflexMusic.utils.database import is_on_off 5 | from config import LOG_GROUP_ID 6 | 7 | 8 | async def play_logs(message, streamtype): 9 | if await is_on_off(2): 10 | logger_text = f""" 11 | {app.mention} 𝖯𝗅𝖺𝗒 𝖫𝗈𝗀 12 | 13 | 𝖢𝗁𝖺𝗍 𝖨𝖣 : {message.chat.id} 14 | 𝖢𝗁𝖺𝗍 𝖭𝖺𝗆𝖾 : {message.chat.title} 15 | 𝖢𝗁𝖺𝗍 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 : @{message.chat.username} 16 | 17 | 𝖴𝗌𝖾𝗋 𝖨𝖣 : {message.from_user.id} 18 | 𝖭𝖺𝗆𝖾 : {message.from_user.mention} 19 | 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 : @{message.from_user.username} 20 | 21 | 𝖰𝗎𝖾𝗋𝗒 : {message.text.split(None, 1)[1]} 22 | 𝖲𝗍𝗋𝖾𝖺𝗆-𝖳𝗒𝗉𝖾 : {streamtype}""" 23 | if message.chat.id != LOG_GROUP_ID: 24 | try: 25 | await app.send_message( 26 | chat_id=LOG_GROUP_ID, 27 | text=logger_text, 28 | parse_mode=ParseMode.HTML, 29 | disable_web_page_preview=True, 30 | ) 31 | except: 32 | pass 33 | return 34 | -------------------------------------------------------------------------------- /InflexMusic/utils/pastebin.py: -------------------------------------------------------------------------------- 1 | import aiohttp 2 | 3 | BASE = "https://batbin.me/" 4 | 5 | 6 | async def post(url: str, *args, **kwargs): 7 | async with aiohttp.ClientSession() as session: 8 | async with session.post(url, *args, **kwargs) as resp: 9 | try: 10 | data = await resp.json() 11 | except Exception: 12 | data = await resp.text() 13 | return data 14 | 15 | 16 | async def InflexBin(text): 17 | resp = await post(f"{BASE}api/v2/paste", data=text) 18 | if not resp["success"]: 19 | return 20 | link = BASE + resp["message"] 21 | return link 22 | -------------------------------------------------------------------------------- /InflexMusic/utils/stream/autoclear.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from config import autoclean 4 | 5 | 6 | async def auto_clean(popped): 7 | try: 8 | rem = popped["file"] 9 | autoclean.remove(rem) 10 | count = autoclean.count(rem) 11 | if count == 0: 12 | if "vid_" not in rem or "live_" not in rem or "index_" not in rem: 13 | try: 14 | os.remove(rem) 15 | except: 16 | pass 17 | except: 18 | pass 19 | -------------------------------------------------------------------------------- /InflexMusic/utils/stream/queue.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from typing import Union 3 | 4 | from InflexMusic.misc import db 5 | from InflexMusic.utils.formatters import check_duration, seconds_to_min 6 | from config import autoclean, time_to_seconds 7 | 8 | 9 | async def put_queue( 10 | chat_id, 11 | original_chat_id, 12 | file, 13 | title, 14 | duration, 15 | user, 16 | vidid, 17 | user_id, 18 | stream, 19 | forceplay: Union[bool, str] = None, 20 | ): 21 | title = title.title() 22 | try: 23 | duration_in_seconds = time_to_seconds(duration) - 3 24 | except: 25 | duration_in_seconds = 0 26 | put = { 27 | "title": title, 28 | "dur": duration, 29 | "streamtype": stream, 30 | "by": user, 31 | "user_id": user_id, 32 | "chat_id": original_chat_id, 33 | "file": file, 34 | "vidid": vidid, 35 | "seconds": duration_in_seconds, 36 | "played": 0, 37 | } 38 | if forceplay: 39 | check = db.get(chat_id) 40 | if check: 41 | check.insert(0, put) 42 | else: 43 | db[chat_id] = [] 44 | db[chat_id].append(put) 45 | else: 46 | db[chat_id].append(put) 47 | autoclean.append(file) 48 | 49 | 50 | async def put_queue_index( 51 | chat_id, 52 | original_chat_id, 53 | file, 54 | title, 55 | duration, 56 | user, 57 | vidid, 58 | stream, 59 | forceplay: Union[bool, str] = None, 60 | ): 61 | if "20.212.146.162" in vidid: 62 | try: 63 | dur = await asyncio.get_event_loop().run_in_executor( 64 | None, check_duration, vidid 65 | ) 66 | duration = seconds_to_min(dur) 67 | except: 68 | duration = "ᴜʀʟ sᴛʀᴇᴀᴍ" 69 | dur = 0 70 | else: 71 | dur = 0 72 | put = { 73 | "title": title, 74 | "dur": duration, 75 | "streamtype": stream, 76 | "by": user, 77 | "chat_id": original_chat_id, 78 | "file": file, 79 | "vidid": vidid, 80 | "seconds": dur, 81 | "played": 0, 82 | } 83 | if forceplay: 84 | check = db.get(chat_id) 85 | if check: 86 | check.insert(0, put) 87 | else: 88 | db[chat_id] = [] 89 | db[chat_id].append(put) 90 | else: 91 | db[chat_id].append(put) 92 | -------------------------------------------------------------------------------- /InflexMusic/utils/sys.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import psutil 4 | 5 | from InflexMusic.misc import _boot_ 6 | from InflexMusic.utils.formatters import get_readable_time 7 | 8 | 9 | async def bot_sys_stats(): 10 | bot_uptime = int(time.time() - _boot_) 11 | UP = f"{get_readable_time(bot_uptime)}" 12 | CPU = f"{psutil.cpu_percent(interval=0.5)}%" 13 | RAM = f"{psutil.virtual_memory().percent}%" 14 | DISK = f"{psutil.disk_usage('/').percent}%" 15 | return UP, CPU, RAM, DISK 16 | -------------------------------------------------------------------------------- /InflexMusic/utils/thumbnails.py: -------------------------------------------------------------------------------- 1 | # This File Is A Part Of https://github.com/CyberPixelPro/AviaxMusic 2 | 3 | # ALL CREDIT GOES TO THE OWNER OF AVIAX 4 | 5 | import os 6 | import re 7 | import aiofiles 8 | import aiohttp 9 | from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageFont, ImageOps 10 | from unidecode import unidecode 11 | from youtubesearchpython.__future__ import VideosSearch 12 | from InflexMusic import app 13 | from config import YOUTUBE_IMG_URL 14 | 15 | def changeImageSize(maxWidth, maxHeight, image): 16 | widthRatio = maxWidth / image.size[0] 17 | heightRatio = maxHeight / image.size[1] 18 | newWidth = int(widthRatio * image.size[0]) 19 | newHeight = int(heightRatio * image.size[1]) 20 | newImage = image.resize((newWidth, newHeight)) 21 | return newImage 22 | 23 | def truncate(text): 24 | list = text.split(" ") 25 | text1 = "" 26 | text2 = "" 27 | for i in list: 28 | if len(text1) + len(i) < 30: 29 | text1 += " " + i 30 | elif len(text2) + len(i) < 30: 31 | text2 += " " + i 32 | 33 | text1 = text1.strip() 34 | text2 = text2.strip() 35 | return [text1,text2] 36 | 37 | def crop_center_circle(img, output_size, border, crop_scale=1.5): 38 | half_the_width = img.size[0] / 2 39 | half_the_height = img.size[1] / 2 40 | larger_size = int(output_size * crop_scale) 41 | img = img.crop( 42 | ( 43 | half_the_width - larger_size/2, 44 | half_the_height - larger_size/2, 45 | half_the_width + larger_size/2, 46 | half_the_height + larger_size/2 47 | ) 48 | ) 49 | 50 | img = img.resize((output_size - 2*border, output_size - 2*border)) 51 | 52 | 53 | final_img = Image.new("RGBA", (output_size, output_size), "white") 54 | 55 | 56 | mask_main = Image.new("L", (output_size - 2*border, output_size - 2*border), 0) 57 | draw_main = ImageDraw.Draw(mask_main) 58 | draw_main.ellipse((0, 0, output_size - 2*border, output_size - 2*border), fill=255) 59 | 60 | final_img.paste(img, (border, border), mask_main) 61 | 62 | 63 | mask_border = Image.new("L", (output_size, output_size), 0) 64 | draw_border = ImageDraw.Draw(mask_border) 65 | draw_border.ellipse((0, 0, output_size, output_size), fill=255) 66 | 67 | result = Image.composite(final_img, Image.new("RGBA", final_img.size, (0, 0, 0, 0)), mask_border) 68 | 69 | return result 70 | 71 | 72 | 73 | async def get_thumb(videoid): 74 | if os.path.isfile(f"cache/{videoid}_v4.png"): 75 | return f"cache/{videoid}_v4.png" 76 | 77 | url = f"https://www.youtube.com/watch?v={videoid}" 78 | results = VideosSearch(url, limit=1) 79 | for result in (await results.next())["result"]: 80 | try: 81 | title = result["title"] 82 | title = re.sub("\W+", " ", title) 83 | title = title.title() 84 | except: 85 | title = "Unsupported Title" 86 | try: 87 | duration = result["duration"] 88 | except: 89 | duration = "Unknown Mins" 90 | thumbnail = result["thumbnails"][0]["url"].split("?")[0] 91 | try: 92 | views = result["viewCount"]["short"] 93 | except: 94 | views = "Unknown Views" 95 | try: 96 | channel = result["channel"]["name"] 97 | except: 98 | channel = "Unknown Channel" 99 | 100 | async with aiohttp.ClientSession() as session: 101 | async with session.get(thumbnail) as resp: 102 | if resp.status == 200: 103 | f = await aiofiles.open(f"cache/thumb{videoid}.png", mode="wb") 104 | await f.write(await resp.read()) 105 | await f.close() 106 | 107 | youtube = Image.open(f"cache/thumb{videoid}.png") 108 | image1 = changeImageSize(1280, 720, youtube) 109 | image2 = image1.convert("RGBA") 110 | background = image2.filter(filter=ImageFilter.BoxBlur(20)) 111 | enhancer = ImageEnhance.Brightness(background) 112 | background = enhancer.enhance(0.6) 113 | draw = ImageDraw.Draw(background) 114 | arial = ImageFont.truetype("InflexMusic/assets/font2.ttf", 30) 115 | font = ImageFont.truetype("InflexMusic/assets/font.ttf", 30) 116 | title_font = ImageFont.truetype("InflexMusic/assets/font3.ttf", 45) 117 | 118 | 119 | circle_thumbnail = crop_center_circle(youtube, 400, 20) 120 | circle_thumbnail = circle_thumbnail.resize((400, 400)) 121 | circle_position = (120, 160) 122 | background.paste(circle_thumbnail, circle_position, circle_thumbnail) 123 | 124 | text_x_position = 565 125 | 126 | title1 = truncate(title) 127 | draw.text((text_x_position, 180), title1[0], fill=(255, 255, 255), font=title_font) 128 | draw.text((text_x_position, 230), title1[1], fill=(255, 255, 255), font=title_font) 129 | draw.text((text_x_position, 320), f"{channel} | {views[:23]}", (255, 255, 255), font=arial) 130 | 131 | 132 | line_length = 580 133 | 134 | 135 | red_length = int(line_length * 0.6) 136 | white_length = line_length - red_length 137 | 138 | 139 | start_point_red = (text_x_position, 380) 140 | end_point_red = (text_x_position + red_length, 380) 141 | draw.line([start_point_red, end_point_red], fill="red", width=9) 142 | 143 | 144 | start_point_white = (text_x_position + red_length, 380) 145 | end_point_white = (text_x_position + line_length, 380) 146 | draw.line([start_point_white, end_point_white], fill="white", width=8) 147 | 148 | 149 | circle_radius = 10 150 | circle_position = (end_point_red[0], end_point_red[1]) 151 | draw.ellipse([circle_position[0] - circle_radius, circle_position[1] - circle_radius, 152 | circle_position[0] + circle_radius, circle_position[1] + circle_radius], fill="red") 153 | draw.text((text_x_position, 400), "00:00", (255, 255, 255), font=arial) 154 | draw.text((1080, 400), duration, (255, 255, 255), font=arial) 155 | 156 | play_icons = Image.open("InflexMusic/assets/play_icons.png") 157 | play_icons = play_icons.resize((580, 62)) 158 | background.paste(play_icons, (text_x_position, 450), play_icons) 159 | 160 | try: 161 | os.remove(f"cache/thumb{videoid}.png") 162 | except: 163 | pass 164 | background.save(f"cache/{videoid}_v4.png") 165 | return f"cache/{videoid}_v4.png" 166 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | worker: bash start 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Inflex Music Bot <\>

2 | 3 |

4 | Inflex Music Logo 5 |

6 | 7 |

8 | Stars 9 | 10 | License 11 | Python 12 | 13 |

14 | 15 | 16 |

Delivering Superior Music Experience To Telegram

17 | 18 | --- 19 | 20 | ### 🌟 Features 21 | 22 | - 🎵 **Multiple Sources:** Play Music From Various Platforms. 23 | - 📃 **Queue System:** Line Up Your Favorite Songs. 24 | - 🔀 **Advanced Controls:** Shuffle, Repeat, And More. 25 | - 🎛 **Customizable Settings:** From Equalizer To Normalization. 26 | - 📢 **Crystal Clear Audio:** High-Quality Playback. 27 | - 🎚 **Volume Mastery:** Adjust To Your Preferred Loudness. 28 | 29 | --- 30 | 31 | 32 |

33 | ─「 <\> Deploy On Heroku <\> 」─ 34 |

35 | 36 |

37 | 38 | 39 | ### 🔧 Quick Setup 40 | 41 | 1. **Upgrade & Update:** 42 | ```bash 43 | sudo apt-get update && sudo apt-get upgrade -y 44 | ``` 45 | 46 | 2. **Install Required Packages:** 47 | ```bash 48 | sudo apt-get install python3-pip ffmpeg -y 49 | ``` 50 | 3. **Setting up PIP** 51 | ```bash 52 | sudo pip3 install -U pip 53 | ``` 54 | 4. **Installing Node** 55 | ```bash 56 | curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash && source ~/.bashrc && nvm install v18 57 | ``` 58 | 5. **Clone the Repository** 59 | ```bash 60 | git clone https://github.com/TeamInflex/InflexMusicBot && cd InflexMusicBot 61 | ``` 62 | 6. **Install Requirements** 63 | ```bash 64 | pip3 install -U -r requirements.txt 65 | ``` 66 | 7. **Create .env with sample.env** 67 | ```bash 68 | cp sample.env .env 69 | ``` 70 | - Edit .env with your vars 71 | 8. **Editing Vars:** 72 | ```bash 73 | vi .env 74 | ``` 75 | - Press `I` Button On Keyboard To Start Editing. 76 | - Edit .env With Your Values. 77 | - Press `Ctrl + C` Once You Are Done With Editing Vars And Type `:wq` To Save .env Or `:qa` To Exit Editing. 78 | 10. **Installing tmux** 79 | ```bash 80 | sudo apt install tmux -y && tmux 81 | ``` 82 | 11. **Run The Bot** 83 | ```bash 84 | bash start 85 | ``` 86 | 87 | --- 88 | 89 | ### 🛠 Commands & Usage 90 | 91 | The Inflex Music Bot Offers A Range Of Commands To Enhance Your Music Listening Experience On Telegram: 92 | 93 | | Command | Description | 94 | |-------------------------|---------------------------------------------| 95 | | `/play ` | Play The Requested Song. | 96 | | `/pause` | Pause The Currently Playing Song. | 97 | | `/resume` | Resume The Paused Song. | 98 | | `/skip` | Move To The Next Song In The Queue. | 99 | | `/stop` | Stop The Bot And Clear The Queue. | 100 | | `/queue` | Display The List Of Songs In The Queue. | 101 | 102 | For A Full List Of Commands, Use `/help` in [Telegram](https://t.me/InflexMusicBot). 103 | 104 | --- 105 | 106 | ### 🔄 Updates & Support 107 | 108 | Stay Updated With The Latest Features And Improvements To Inflex Music Bot: 109 | 110 |

111 | 112 | 113 | 114 | 115 | 116 | 117 |

118 | 119 | --- 120 | 121 | ### 🤝 Contributing 122 | 123 | We Welcome Contributions To The Inflex Music Bot Project. If You'd Like To Contribute, Please Follow These Steps : 124 | 125 | 1. [Fork The Repository.](https://github.com/TeamInflex/InflexMusicBot/fork) 126 | 2. Create A New Branch With A Meaningful Name. 127 | 3. Make Your Changes And Commit Them With A Descriptive Commit Message. 128 | 4. Open A Pull Request Against Our `main` Branch. 129 | 5. Our Team Will Review Your Changes And Provide Feedback. 130 | 131 | For More Details, Reach Out Us On Telegram. 132 | 133 | --- 134 | 135 | ### 📜 License 136 | 137 | This project Is Licensed Under The MIT License. For More Details, See The [LICENSE](LICENSE) File. 138 | 139 | --- 140 | 141 | ### 🙏 Acknowledgements 142 | 143 | Special Thanks To All The Contributors , Supporters , And Users Of The Inflex Music Bot. Your Feedback And Support Keep Us Going ! 144 | - [Yukki Music](https://github.com/TeamYukki/YukkiMusicBot) , [AviaxMusic](https://github.com/TeamAviax/AviaxMusic) And [AnonXMusic](https://github.com/AnonymousX1025/AnonXMusic) For Their Source Codes. 145 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Inflex Music Bot", 3 | "description": "A Telegram Music Player Bot, written in Python with Pyrogram and Py-Tgcalls.", 4 | "logo": "https://graph.org/file/d6a63fe91240f0b271f7f.jpg", 5 | "keywords": [ 6 | "python3", 7 | "telegram", 8 | "bot", 9 | "Aviax", 10 | "MusicBot", 11 | "telegram-bot", 12 | "pyrogram" 13 | ], 14 | "env": { 15 | "API_ID": { 16 | "description": "Get this value from https://my.telegram.org", 17 | "value": "", 18 | "required": true 19 | }, 20 | "API_HASH": { 21 | "description": "Get this value from https://my.telegram.org", 22 | "value": "", 23 | "required": true 24 | }, 25 | "BOT_TOKEN": { 26 | "description": "A Bot's token from Botfather", 27 | "value": "", 28 | "required": true 29 | }, 30 | "MONGO_DB_URI": { 31 | "description": "Get a mongodb url from https://cloud.mongodb.com.", 32 | "value": "", 33 | "required": true 34 | }, 35 | "OWNER_ID": { 36 | "description": "The user id of user whom you would like to add as OWNER.", 37 | "value": "", 38 | "required": true 39 | }, 40 | "STRING_SESSION": { 41 | "description": "A Pyrogram v2 String Session .", 42 | "value": "", 43 | "required": true 44 | }, 45 | "QUEUE_LIMIT": { 46 | "description": "Fill Queue Limit . Example - 15", 47 | "value": "", 48 | "required": false 49 | }, 50 | "HEROKU_API_KEY": { 51 | "description": "Your Heroku account's API key", 52 | "value": "", 53 | "required": false 54 | }, 55 | "HEROKU_APP_NAME": { 56 | "description": "Your heroku app name", 57 | "value": "", 58 | "required": false 59 | }, 60 | "LOG_GROUP_ID": { 61 | "description": "Your Log Group ID, add your bot and promote as an admin with full rights!. Do not ever try to put channel ID here.", 62 | "value": "", 63 | "required": true 64 | } 65 | }, 66 | "buildpacks": [ 67 | { 68 | "url": "heroku/python" 69 | }, 70 | { 71 | "url": "heroku/nodejs" 72 | }, 73 | { 74 | "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest.git" 75 | } 76 | ], 77 | "stack": "container" 78 | } 79 | -------------------------------------------------------------------------------- /cookies/addyourcookies.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /heroku.yml: -------------------------------------------------------------------------------- 1 | build: 2 | docker: 3 | worker: Dockerfile 4 | run: 5 | worker: bash start -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | httpx==0.27.2 2 | aiofiles 3 | apscheduler 4 | aiohttp 5 | asyncio 6 | beautifulsoup4 7 | dnspython 8 | ffmpeg-python 9 | gitpython 10 | hachoir 11 | heroku3 12 | motor 13 | pillow==9.5.0 14 | psutil 15 | py-tgcalls==0.9.7 16 | pykeyboard 17 | https://github.com/KurimuzonAkuma/pyrogram/archive/v2.1.24.zip 18 | python-dotenv 19 | pyyaml 20 | requests 21 | speedtest-cli 22 | spotipy 23 | tgcrypto 24 | unidecode 25 | yt-dlp 26 | youtube-search 27 | youtube-search-python 28 | -------------------------------------------------------------------------------- /runtime.txt: -------------------------------------------------------------------------------- 1 | python-3.11.4 2 | -------------------------------------------------------------------------------- /sample.env: -------------------------------------------------------------------------------- 1 | API_ID= 2 | API_HASH= 3 | BOT_TOKEN= 4 | LOG_GROUP_ID= 5 | MONGO_DB_URI= 6 | OWNER_ID= 7 | STRING_SESSION= 8 | -------------------------------------------------------------------------------- /setup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pprint (){ 4 | cred='\033[0;31m' 5 | cgreen='\033[0;32m' 6 | cyellow='\033[0;33m' 7 | cblue='\033[0;34m' 8 | cpurple='\033[0;35m' 9 | eval "export color='$cpurple'" 10 | [ ! -z $2 ] && eval "export color=\"\$$2\"" 11 | printf "$color $1" 12 | } 13 | 14 | color_reset(){ printf '\033[0;37m';} 15 | 16 | yesnoprompt(){ 17 | old_stty_cfg=$(stty -g) 18 | stty raw -echo ; answer=$(head -c 1) 19 | stty $old_stty_cfg 20 | echo "$answer" | grep -iq "^y" 21 | } 22 | 23 | update() { 24 | pprint "\n\nUpdating package list.. " 25 | sudo apt update 2>&1 | grep "can be upgraded" &>/dev/null 26 | if [ $? -eq 0 ]; then 27 | pprint "UPDATE AVAILABLE" "cgreen" 28 | pprint "\n\nDo you want to automatically upgrade (y/n)?" 29 | if yesnoprompt; then 30 | pprint "\n\nUpgrading packages.. " 31 | sudo apt upgrade -y &>/dev/null && 32 | pprint "DONE!\n\n" "cgreen" || (pprint "FAIL.\n\n" "cred"; exit 1) 33 | else 34 | echo 35 | fi 36 | else 37 | pprint "ALREADY UP TO DATE\n\n" "cgreen" 38 | fi 39 | } 40 | 41 | packages(){ 42 | if ! command -v pip &>/dev/null; then 43 | pprint "Couldn't found pip, installing now..." 44 | sudo apt install python3-pip -y 2>pypilog.txt 1>/dev/null && 45 | pprint "SUCCESS.\n\n" "cgreen" || (pprint "FAIL.\n\n" "cred"; exit 1) 46 | fi 47 | 48 | if ! command -v ffmpeg &>/dev/null; then 49 | pprint "Couldn't found ffmpeg, installing now..." 50 | if sudo apt install ffmpeg -y &>/dev/null;then 51 | pprint "SUCCESS.\n\n" "cgreen" 52 | else 53 | pprint "FAIL.\n\n" "cred" 54 | pprint "You need to install ffmpeg manually in order to deploy InflexMusic, exiting...\n" "cblue" 55 | exit 1 56 | fi 57 | fi 58 | 59 | # Check ffmpeg version and warn user if necessary. 60 | fv=$(grep -Po 'version (3.*?) ' <<< $(ffmpeg -version)) && 61 | pprint "Playing live streams not going to work since you have ffmpeg $fv, live streams are supported by version 4+.\n" "cblue" 62 | } 63 | 64 | 65 | node(){ 66 | command -v npm &>/dev/null && return 67 | pprint "Installing Nodejs and Npm.. " 68 | curl -fssL https://deb.nodesource.com/setup_19.x | sudo -E bash - &>nodelog.txt && 69 | sudo apt install -y nodejs &>>nodelog.txt && 70 | sudo npm i -g npm &>>nodelog.txt && 71 | pprint "SUCCESS!\n" "cgreen" || (pprint "FAIL.\n" "cred"; exit 1) 72 | } 73 | 74 | 75 | installation(){ 76 | pprint "\n\nUpgrading pip and installing dependency packages..." 77 | pip3 install -U pip &>>pypilog.txt && 78 | pip3 install -U -r requirements.txt &>>pypilog.txt && 79 | pprint "DONE.\n" "cgreen" && return 80 | pprint "FAIL.\n" "cred" 81 | exit 1 82 | } 83 | 84 | clear 85 | pprint "Welcome to InflexMusic Setup Installer\n\n" 86 | pprint "If you see any error during Installation Process, Please refer to these files for logs: " 87 | pprint "\nFor node js errors , Checkout nodelog.txt" 88 | pprint "\nFor pypi packages errors , Checkout pypilog.txt" 89 | sleep 1 90 | pprint "\n\nScript needs sudo privileges in order to update & install packages.\n" 91 | sudo test 92 | 93 | update 94 | packages 95 | node 96 | installation 97 | pprint "\n\n\n\n\nInflexMusic Installation Completed !" "cgreen" 98 | sleep 1 99 | clear 100 | 101 | pprint "\nEnter Your Values Below\n\n\n" 102 | pprint "API ID: "; color_reset; read api_id 103 | pprint "\nAPI HASH: "; color_reset; read api_hash 104 | pprint "\nBOT TOKEN: "; color_reset; read bot_token 105 | pprint "\nOWNER ID:"; color_reset; read ownid 106 | pprint "\nMONGO DB URI: "; color_reset; read mongo_db 107 | pprint "\nLOG GROUP ID: "; color_reset; read logger 108 | pprint "\nSTRING SESSION: "; color_reset; read string_session 109 | 110 | pprint "\n\nProcessing your vars, wait a while !" "cgreen" 111 | 112 | if [ -f .env ]; then 113 | rm .env 114 | fi 115 | 116 | echo """API_ID = $api_id 117 | API_HASH = $api_hash 118 | BOT_TOKEN = $bot_token 119 | MONGO_DB_URI = $mongo_db 120 | LOG_GROUP_ID = $logger 121 | STRING_SESSION = $string_session 122 | OWNER_ID = $ownid""" > .env 123 | clear 124 | 125 | pprint "\n\n\nThanks for using InflexMusic installer, your vars have been saved successfully ! \nIf you wanna add more variables add them in your env by : vi .env" 126 | pprint "\n\nNow you can start the bot by : bash start\n\n" 127 | -------------------------------------------------------------------------------- /start: -------------------------------------------------------------------------------- 1 | python3 -m InflexMusic -------------------------------------------------------------------------------- /strings/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | from typing import List 3 | 4 | import yaml 5 | 6 | languages = {} 7 | languages_present = {} 8 | 9 | 10 | def get_string(lang: str): 11 | return languages[lang] 12 | 13 | 14 | for filename in os.listdir(r"./strings/langs/"): 15 | if "en" not in languages: 16 | languages["en"] = yaml.safe_load( 17 | open(r"./strings/langs/en.yml", encoding="utf8") 18 | ) 19 | languages_present["en"] = languages["en"]["name"] 20 | if filename.endswith(".yml"): 21 | language_name = filename[:-4] 22 | if language_name == "en": 23 | continue 24 | languages[language_name] = yaml.safe_load( 25 | open(r"./strings/langs/" + filename, encoding="utf8") 26 | ) 27 | for item in languages["en"]: 28 | if item not in languages[language_name]: 29 | languages[language_name][item] = languages["en"][item] 30 | try: 31 | languages_present[language_name] = languages[language_name]["name"] 32 | except: 33 | print("There is some issue with the language file inside bot.") 34 | exit() 35 | -------------------------------------------------------------------------------- /strings/helpers.py: -------------------------------------------------------------------------------- 1 | HELP_1 = """𝖠𝖽𝗆𝗂𝗇 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 : 2 | 3 | 𝖩𝗎𝗌𝗍 𝖠𝖽𝖽 𝖨𝗇 𝖳𝗁𝖾 𝖲𝗍𝖺𝗋𝗍𝗂𝗇𝗀 𝖮𝖿 𝖳𝗁𝖾 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 𝖳𝗈 𝖴𝗌𝖾 𝖳𝗁𝖾𝗇 𝖥𝗈𝗋 𝖢𝗁𝖺𝗇𝗇𝖾𝗅 . 4 | 5 | 6 | /pause : 𝖯𝖺𝗎𝗌𝖾 𝖳𝗁𝖾 𝖢𝗎𝗋𝗋𝖾𝗇𝗍 𝖯𝗅𝖺𝗒𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 . 7 | 8 | /resume : 𝖱𝖾𝗌𝗎𝗆𝖾 𝖳𝗁𝖾 𝖯𝖺𝗎𝗌𝖾𝖽 𝖲𝗍𝗋𝖾𝖺𝗆 . 9 | 10 | /skip : 𝖲𝗄𝗂𝗉 𝖳𝗁𝖾 𝖢𝗎𝗋𝗋𝖾𝗇𝗍 𝖯𝗅𝖺𝗒𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 𝖠𝗇𝖽 𝖲𝗍𝖺𝗋𝗍 𝖲𝗍𝗋𝖾𝖺𝗆 𝖳𝗁𝖾 𝖭𝖾𝗑𝗍 𝖳𝗋𝖺𝖼𝗄 𝖨𝗇 𝖰𝗎𝖾𝗎𝖾 . 11 | 12 | /end 𝖮𝗋 /stop : 𝖢𝗅𝖾𝖺𝗋𝗌 𝖳𝗁𝖾 𝖰𝗎𝖾𝗎𝖾 𝖠𝗇𝖽 𝖤𝗇𝖽 𝖳𝗁𝖾 𝖢𝗎𝗋𝗋𝖾𝗇𝗍 𝖯𝗅𝖺𝗒𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 . 13 | 14 | /player : 𝖦𝖾𝗍 𝖠 𝖨𝗇𝗍𝖾𝗋𝖺𝖼𝗏𝗍𝗂𝖼𝖾 𝖯𝗅𝖺𝗒𝖾𝗋 𝖯𝖺𝗇𝖾𝗅 . 15 | 16 | /queue : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖰𝗎𝖾𝗎𝖾𝖽 𝖳𝗋𝖺𝖼𝗄𝗌 𝖫𝗂𝗌𝗍 . 17 | """ 18 | 19 | HELP_2 = """ 20 | 𝖠𝗎𝗍𝗁 𝖴𝗌𝖾𝗋𝗌 : 21 | 22 | 𝖠𝗎𝗍𝗁 𝖴𝗌𝖾𝗋𝗌 𝖢𝖺𝗇 𝖴𝗌𝖾 𝖠𝖽𝗆𝗂𝗇 𝖱𝗂𝗀𝗁𝗍𝗌 𝖨𝗇 𝖳𝗁𝖾 𝖡𝗈𝗍 𝖶𝗂𝗍𝗁𝗈𝗎𝗍 𝖠𝖽𝗆𝗂𝗇 𝖱𝗂𝗀𝗁𝗍𝗌 𝖨𝗇 𝖳𝗁𝖾 𝖢𝗁𝖺𝗍 . 23 | 24 | /auth [ 𝖴𝗌𝖾𝗋 𝖨𝖣 / 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 ] : 𝖠𝖽𝖽 𝖠 𝖴𝗌𝖾𝗋 𝖳𝗈 𝖠𝗎𝗍𝗁 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 25 | /unauth [ 𝖴𝗌𝖾𝗋 𝖨𝖣 / 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 ] : 𝖱𝖾𝗆𝗈𝗏𝖾𝖽 𝖠 𝖠𝗎𝗍𝗁 𝖴𝗌𝖾𝗋𝗌 𝖥𝗋𝗈𝗆 𝖳𝗁𝖾 𝖠𝗎𝗍𝗁 𝖴𝗌𝖾𝗋𝗌 𝖫𝗂𝗌𝗍 . 26 | /authusers : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖠𝗎𝗍𝗁 𝖴𝗌𝖾𝗋𝗌 𝖮𝖿 𝖳𝗁𝖾 𝖦𝗋𝗈𝗎𝗉 . 27 | """ 28 | 29 | HELP_3 = """ 30 | 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍 𝖥𝖾𝖺𝗍𝗎𝗋𝖾 [ 𝖮𝗇𝗅𝗒 𝖥𝗈𝗋 𝖲𝗎𝖽𝗈𝖾𝗋𝗌 ] : 31 | 32 | /broadcast [ 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖮𝗋 𝖱𝖾𝗉𝗅𝗒 𝖳𝗈 𝖠 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 ] : 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍 𝖠 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖳𝗈 𝖲𝖾𝗋𝗏𝖾𝖽 𝖢𝗁𝖺𝗍𝗌 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 33 | 34 | 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍𝗂𝗇𝗀 𝖬𝗈𝖽𝖾𝗌 : 35 | -pin : 𝖯𝗂𝗇𝗌 𝖸𝗈𝗎𝗋 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍𝖾𝖽 𝖬𝖾𝗌𝗌𝖺𝗀𝖾𝗌 𝖨𝗇 𝖲𝖾𝗋𝗏𝖾𝖽 𝖢𝗁𝖺𝗍𝗌 . 36 | -pinloud : 𝖯𝗂𝗇𝗌 𝖸𝗈𝗎𝗋 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍𝖾𝖽 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖨𝗇 𝖲𝖾𝗋𝗏𝖾𝖽 𝖢𝗁𝖺𝗍𝗌 𝖠𝗇𝖽 𝖲𝖾𝗇𝖽 𝖭𝗈𝗍𝗂𝖿𝗂𝖼𝖺𝗍𝗂𝗈𝗇 𝖳𝗈 𝖳𝗁𝖾 𝖬𝖾𝗆𝖻𝖾𝗋𝗌 . 37 | -user : 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍𝗌 𝖳𝗁𝖾 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖳𝗈 𝖳𝗁𝖾 𝖴𝗌𝖾𝗋𝗌 𝖶𝗁𝗈 𝖧𝖺𝗏𝖾 𝖲𝗍𝖺𝗋𝗍𝖾𝖽 𝖸𝗈𝗎𝗋 𝖡𝗈𝗍 . 38 | -assistant : 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍 𝖸𝗈𝗎𝗋 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖥𝗋𝗈𝗆 𝖳𝗁𝖾 𝖠𝗌𝗌𝗂𝗌𝗍𝖺𝗇𝗍 𝖠𝖼𝖼𝗈𝗎𝗇𝗍 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 39 | -nobot : 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍 𝖸𝗈𝗎𝗋 𝖬𝖾𝗌𝗌𝖺𝗀𝖾 𝖥𝗋𝗈𝗆 𝖳𝗁𝖾 𝖠𝗌𝗌𝗂𝗌𝗍𝖺𝗇𝗍 𝖠𝖼𝖼𝗈𝗎𝗇𝗍 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 40 | 41 | 𝖤𝗑𝖺𝗆𝗉𝗅𝖾 : /broadcast -user -assistant -pin 𝖳𝖾𝗌𝗍𝗂𝗇𝗀 𝖡𝗋𝗈𝖺𝖽𝖼𝖺𝗌𝗍 . 42 | """ 43 | 44 | HELP_4 = """𝖢𝗁𝖺𝗍 𝖡𝗅𝖺𝖼𝗄𝗅𝗂𝗌𝗍 𝖥𝖾𝖺𝗍𝗎𝗋𝖾 : [ 𝖮𝗇𝗅𝗒 𝖥𝗈𝗋 𝖲𝗎𝖽𝗈𝖾𝗋𝗌 ] 45 | 46 | 𝖱𝖾𝗌𝗍𝗋𝗂𝖼𝗍 𝖲𝗁𝗂𝗍 𝖢𝗁𝖺𝗍𝗌 𝖳𝗈 𝖴𝗎𝖾 𝖮𝗎𝗋 𝖯𝗋𝖾𝖼𝗂𝗈𝗎𝗌 𝖡𝗈𝗍 . 47 | 48 | /blacklistchat [ 𝖢𝗁𝖺𝗍 𝖨𝖣 ] : 𝖡𝗅𝖺𝖼𝗄𝗅𝗂𝗌𝗍 𝖠 𝖢𝗁𝖺𝗍 𝖥𝗋𝗈𝗆 𝖴𝗌𝗂𝗇𝗀 𝖳𝗁𝖾 𝖡𝗈𝗍 . 49 | /whitelistchat [ 𝖢𝗁𝖺𝗍 𝖨𝖣 ] : 𝖶𝗁𝗂𝗍𝖾𝗅𝗂𝗌𝗍 𝖳𝗁𝖾 𝖡𝗅𝖺𝖼𝗄𝗅𝗂𝗌𝗍𝖾𝖽 𝖢𝗁𝖺𝗍 . 50 | /blacklistedchat : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖡𝗅𝖺𝖼𝗄𝗅𝗂𝗌𝗍𝖾𝖽 𝖢𝗁𝖺𝗍𝗌 . 51 | """ 52 | 53 | HELP_5 = """ 54 | 𝖡𝗅𝗈𝖼𝗄 𝖴𝗌𝖾𝗋𝗌 : [ 𝖮𝗇𝗅𝗒 𝖥𝗈𝗋 𝖲𝗎𝖽𝗈𝖾𝗋𝗌 ] 55 | 56 | 𝖲𝗍𝖺𝗋𝗍𝗌 𝖨𝗀𝗇𝗈𝗋𝗂𝗇𝗀 𝖳𝗁𝖾 𝖡𝗅𝖺𝖼𝗄𝗅𝗂𝗌𝗍𝖾𝖽 𝖴𝗌𝖾𝗋 , 𝖲𝗈 𝖳𝗁𝖺𝗍 𝖧𝖾 𝖢𝖺𝗇'𝗍 𝖴𝗌𝖾 𝖡𝗈𝗍 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 . 57 | 58 | /block [ 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 𝖮𝗋 𝖱𝖾𝗉𝗅𝗒 𝖳𝗈 𝖠 𝖴𝗌𝖾𝗋 ] : 𝖡𝗅𝗈𝖼𝗄 𝖳𝗁𝖾 𝖴𝗌𝖾𝗋 𝖥𝗋𝗈𝗆 𝖮𝗎𝗋 𝖡𝗈𝗍 . 59 | /unblock [ 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 𝖮𝗋 𝖱𝖾𝗉𝗅𝗒 𝖳𝗈 𝖠 𝖴𝗌𝖾𝗋 ] : 𝖴𝗇-𝖡𝗅𝗈𝖼𝗄𝗌 𝖳𝗁𝖾 𝖡𝗅𝗈𝖼𝗄𝖾𝖽-𝖴𝗌𝖾𝗋 . 60 | /blockedusers : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗅𝗈𝖼𝗄𝖾𝖽 𝖴𝗌𝖾𝗋𝗌 . 61 | """ 62 | 63 | HELP_6 = """ 64 | 𝖢𝗁𝖺𝗇𝗇𝖾𝗅 𝖯𝗅𝖺𝗒 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 : 65 | 66 | 𝖸𝗈𝗎 𝖢𝖺𝗇 𝖲𝗍𝗋𝖾𝖺𝗆 𝖠𝗎𝖽𝗂𝗈 / 𝖵𝗂𝖽𝖾𝗈 𝖨𝗇 𝖢𝗁𝖺𝗇𝗇𝖾𝗅 . 67 | 68 | /cplay : 𝖲𝗍𝖺𝗋𝗍𝗌 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝗊𝗎𝖾𝗌𝗍𝖾𝖽 𝖠𝗎𝖽𝗂𝗈 𝖳𝗋𝖺𝖼𝗄 𝖮𝗇 𝖢𝗁𝖺𝗇𝗇𝖾𝗅'𝗌 𝖵𝗂𝖽𝖾𝗈𝖢𝗁𝖺𝗍 . 69 | /cvplay : 𝖲𝗍𝖺𝗋𝗍𝗌 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝗊𝗎𝖾𝗌𝗍𝖾𝖽 𝖵𝗂𝖽𝖾𝗈 𝖳𝗋𝖺𝖼𝗄 𝖮𝗇 𝖢𝗁𝖺𝗇𝗇𝖾𝗅'𝗌 𝖵𝗂𝖽𝖾𝗈𝖢𝗁𝖺𝗍 . 70 | /cplayforce 𝖮𝗋 /cvplayforce : 𝖲𝗍𝗈𝗉𝗌 𝖳𝗁𝖾 𝖮𝗇𝗀𝗈𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 𝖠𝗇𝖽 𝖲𝗍𝖺𝗋𝗍𝗌 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝗊𝗎𝖾𝗌𝗍𝖾𝖽 𝖳𝗋𝖺𝖼𝗄 . 71 | 72 | /channelplay [ 𝖢𝗁𝖺𝗍 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 𝖮𝗋 𝖨𝖣 ] 𝖮𝗋 [ 𝖣𝗂𝗌𝖺𝖻𝗅𝖾 ] : 𝖢𝗈𝗇𝗇𝖾𝖼𝗍 𝖳𝗈 𝖠 𝖦𝗋𝗈𝗎𝗉 𝖠𝗇𝖽 𝖲𝗍𝖺𝗋𝗍𝗌 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗋𝖺𝖼𝗄𝗌 𝖡𝗒 𝖳𝗁𝖾 𝖧𝖾𝗅𝗉 𝖮𝖿 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 𝖲𝖾𝗇𝗍 𝖨𝗇 𝖦𝗋𝗈𝗎𝗉 . 73 | """ 74 | 75 | HELP_7 = """ 76 | 𝖦𝗅𝗈𝖻𝖺𝗅 𝖡𝖺𝗇 𝖥𝖾𝖺𝗍𝗎𝗋𝖾 [ 𝖮𝗇𝗅𝗒 𝖥𝗈𝗋 𝖲𝗎𝖽𝗈𝖾𝗋𝗌 ] : 77 | 78 | /gban [ 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 𝖮𝗋 𝖱𝖾𝗉𝗅𝗒 𝖳𝗈 𝖠 𝖴𝗌𝖾𝗋 ] : 𝖦𝗅𝗈𝖻𝖺𝗅𝗅𝗒 𝖡𝖺𝗇 𝖳𝗁𝖾 𝖴𝗌𝖾𝗋 𝖥𝗋𝗈𝗆 𝖠𝗅𝗅 𝖳𝗁𝖾 𝖲𝖾𝗋𝗏𝖾𝖽 𝖢𝗁𝖺𝗍𝗌 𝖠𝗇𝖽 𝖡𝗅𝖺𝖼𝗄𝗅𝗂𝗌𝗍 𝖧𝗂𝗆 𝖥𝗋𝗈𝗆 𝖴𝗌𝗂𝗇𝗀 𝖳𝗁𝖾 𝖡𝗈𝗍 . 79 | /ungban [ 𝖴𝗌𝖾𝗋𝗇𝖺𝗆𝖾 𝖮𝗋 𝖱𝖾𝗉𝗅𝗒 𝖳𝗈 𝖠 𝖴𝗌𝖾𝗋 ] : 𝖦𝗅𝗈𝖻𝖺𝗅𝗅𝗒 𝖴𝗇𝖻𝖺𝗇𝗌 𝖳𝗁𝖾 𝖦𝗅𝗈𝖻𝖺𝗅𝗅𝗒 𝖡𝖺𝗇𝗇𝖾𝖽 𝖴𝗌𝖾𝗋 . 80 | /gbannedusers : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖫𝗂𝗌𝗍 𝖮𝖿 𝖦𝗅𝗈𝖻𝖺𝗅𝗅𝗒 𝖡𝖺𝗇𝗇𝖾𝖽 𝖴𝗌𝖾𝗋𝗌 . 81 | """ 82 | 83 | HELP_8 = """ 84 | 𝖫𝗈𝗈𝗉 𝖲𝗍𝗋𝖾𝖺𝗆 : 85 | 86 | 𝖲𝗍𝖺𝗋𝗍 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗁𝖾 𝖮𝗇𝗀𝗈𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 𝖨𝗇 𝖫𝗈𝗈𝗉 87 | 88 | /loop [ 𝖤𝗇𝖺𝖻𝗅𝖾 / 𝖣𝗂𝗌𝖺𝖻𝗅𝖾 ] : 𝖤𝗇𝖺𝖻𝗅𝖾𝗌 / 𝖣𝗂𝗌𝖺𝖻𝗅𝖾𝗌 𝖫𝗈𝗈𝗉 𝖥𝗈𝗋 𝖳𝗁𝖾 𝖮𝗇𝗀𝗈𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 89 | /loop [1 , 2 , 3 , ...] : 𝖤𝗇𝖺𝖻𝗅𝖾𝗌 𝖳𝗁𝖾 𝖫𝗈𝗈𝗉 𝖥𝗈𝗋 𝖳𝗁𝖾 𝖦𝗂𝗏𝖾𝗇 𝖵𝖺𝗅𝗎𝖾 . 90 | """ 91 | 92 | HELP_9 = """ 93 | 𝖬𝖺𝗂𝗇𝗍𝖾𝗇𝖺𝗇𝖼𝖾 𝖬𝗈𝖽𝖾 [ 𝖮𝗇𝗅𝗒 𝖥𝗈𝗋 𝖲𝗎𝖽𝗈𝖾𝗋𝗌 ] : 94 | 95 | /logs : 𝖦𝖾𝗍 𝖫𝗈𝗀𝗌 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 96 | 97 | /logger [ Enable / Disable ] : Bot Will Start Logging The Activities Happen On Bot . 98 | 99 | /maintenance [ 𝖤𝗇𝖺𝖻𝗅𝖾 / 𝖣𝗂𝗌𝖺𝖻𝗅𝖾 ] : 𝖤𝗇𝖺𝖻𝗅𝖾 𝖮𝗋 𝖣𝗂𝗌𝖺𝖻𝗅𝖾 𝖳𝗁𝖾 𝖬𝖺𝗂𝗇𝗍𝖾𝗇𝖺𝗇𝖼𝖾 𝖬𝗈𝖽𝖾 𝖮𝖿 𝖸𝗈𝗎𝗋 𝖡𝗈𝗍 . 100 | """ 101 | 102 | HELP_10 = """ 103 | 𝖯𝗂𝗇𝗀 𝖠𝗇𝖽 𝖲𝗍𝖺𝗍𝗌 : 104 | 105 | /start : 𝖲𝗍𝖺𝗋𝗍 𝖳𝗁𝖾 𝖬𝗎𝗌𝗂𝖼 𝖡𝗈𝗍 . 106 | /help : 𝖦𝖾𝗍 𝖧𝖾𝗅𝗉 𝖬𝖾𝗇𝗎 𝖶𝗂𝗍𝗁 𝖤𝗑𝗉𝗅𝖺𝗇𝖺𝗍𝗂𝗈𝗇 𝖮𝖿 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 . 107 | 108 | /ping : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖯𝗂𝗇𝗀 𝖠𝗇𝖽 𝖲𝗒𝗌𝗍𝖾𝗆 𝖲𝗍𝖺𝗍𝗌 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 109 | 110 | /stats : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖮𝗏𝖾𝗋𝖺𝗅𝗅 𝖲𝗍𝖺𝗍𝗌 𝖮𝖿 𝖳𝗁𝖾 𝖡𝗈𝗍 . 111 | """ 112 | 113 | HELP_11 = """ 114 | 𝖯𝗅𝖺𝗒 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 : 115 | 116 | v : 𝖲𝗍𝖺𝗇𝖽𝗌 𝖥𝗈𝗋 𝖵𝗂𝖽𝖾𝗈 𝖯𝗅𝖺𝗒 . 117 | force : 𝖲𝗍𝖺𝗇𝖽𝗌 𝖥𝗈𝗋 𝖥𝗈𝗋𝖼𝖾 𝖯𝗅𝖺𝗒 . 118 | 119 | /play 𝖮𝗋 /vplay : 𝖲𝗍𝖺𝗋𝗍𝗌 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝗊𝗎𝖾𝗌𝗍𝖾𝖽 𝖳𝗋𝖺𝖼𝗄 𝖮𝗇 𝖵𝗂𝖽𝖾𝗈𝖢𝗁𝖺𝗍 . 120 | 121 | /playforce 𝖮𝗋 /vplayforce : 𝖲𝗍𝗈𝗉𝗌 𝖳𝗁𝖾 𝖮𝗇𝗀𝗈𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 𝖠𝗇𝖽 𝖲𝗍𝖺𝗋𝗍𝗌 𝖲𝗍𝗋𝖾𝖺𝗆𝗂𝗇𝗀 𝖳𝗁𝖾 𝖱𝖾𝗊𝗎𝖾𝗌𝗍𝖾𝖽 𝖳𝗋𝖺𝖼𝗄 . 122 | """ 123 | 124 | HELP_12 = """ 125 | 𝖲𝗁𝗎𝖿𝖿𝗅𝖾 𝖰𝗎𝖾𝗎𝖾 : 126 | 127 | /shuffle : 𝖲𝗁𝗎𝖿𝖿𝗅𝖾'𝗌 𝖳𝗁𝖾 𝖰𝗎𝖾𝗎𝖾 . 128 | /queue : 𝖲𝗁𝗈𝗐𝗌 𝖳𝗁𝖾 𝖲𝗁𝗎𝖿𝖿𝗅𝖾'𝗌 𝖰𝗎𝖾𝗎𝖾 . 129 | """ 130 | 131 | HELP_13 = """ 132 | 𝖲𝖾𝖾𝗄 𝖲𝗍𝗋𝖾𝖺𝗆 : 133 | 134 | /seek [ 𝖣𝗎𝗋𝖺𝗍𝗂𝗈𝗇 𝖨𝗇 𝖲𝖾𝖼𝗈𝗇𝖽𝗌 ] : 𝖲𝖾𝖾𝗄 𝖳𝗁𝖾 𝖲𝗍𝗋𝖾𝖺𝗆 𝖳𝗈 𝖳𝗁𝖾 𝖦𝗂𝗏𝖾𝗇 𝖣𝗎𝗋𝖺𝗍𝗂𝗈𝗇 . 135 | /seekback [ 𝖣𝗎𝗋𝖺𝗍𝗂𝗈𝗇 𝖨𝗇 𝖲𝖾𝖼𝗈𝗇𝖽𝗌 ] : 𝖡𝖺𝖼𝗄𝗐𝖺𝗋𝖽 𝖲𝖾𝖾𝗄 𝖳𝗁𝖾 𝖲𝗍𝗋𝖾𝖺𝗆 𝖳𝗈 𝖳𝗁𝖾 𝖦𝗂𝗏𝖾𝗇 𝖣𝗎𝗋𝖺𝗍𝗂𝗈𝗇 . 136 | """ 137 | 138 | HELP_14 = """ 139 | 𝖲𝗈𝗇𝗀 𝖣𝗈𝗐𝗇𝗅𝗈𝖺𝖽 140 | 141 | /song [ 𝖲𝗈𝗇𝗀 𝖭𝖺𝗆𝖾 / 𝖸𝗈𝗎𝖳𝗎𝖻𝖾 𝖴𝗋𝗅 ] : 𝖣𝗈𝗐𝗇𝗅𝗈𝖺𝖽 𝖠𝗇𝗒 𝖳𝗋𝖺𝖼𝗄 𝖥𝗋𝗈𝗆 𝖸𝗈𝗎𝖳𝗎𝖻𝖾 𝖨𝗇 𝖬𝗉3 𝖮𝗋 𝖬𝗉4 𝖥𝗈𝗋𝗆𝖺𝗍𝗌 . 142 | """ 143 | 144 | HELP_15 = """ 145 | 𝖲𝗉𝖾𝖾𝖽 𝖢𝗈𝗆𝗆𝖺𝗇𝖽𝗌 : 146 | 147 | 𝖸𝗈𝗎 𝖢𝖺𝗇 𝖢𝗈𝗇𝗍𝗋𝗈𝗅 𝖳𝗁𝖾 𝖯𝗅𝖺𝗒𝖡𝖺𝖼𝗄 𝖲𝗉𝖾𝖾𝖽 𝖮𝖿 𝖳𝗁𝖾 𝖮𝗇𝗀𝗈𝗂𝗇𝗀 𝖲𝗍𝗋𝖾𝖺𝗆 . [ 𝖠𝖽𝗆𝗂𝗇𝗌 𝖮𝗇𝗅𝗒 ] 148 | 149 | /speed 𝖮𝗋 /playback : 𝖥𝗈𝗋 𝖠𝖽𝗃𝗎𝗌𝗍𝗂𝗇𝗀 𝖳𝗁𝖾 𝖠𝗎𝖽𝗂𝗈 𝖯𝗅𝖺𝗒𝖡𝖺𝖼𝗄 𝖲𝗉𝖾𝖾𝖽 𝖨𝗇 𝖦𝗋𝗈𝗎𝗉 . 150 | /cspeed 𝖮𝗋 /cplayback : 𝖥𝗈𝗋 𝖠𝖽𝗃𝗎𝗌𝗍𝗂𝗇𝗀 𝖳𝗁𝖾 𝖠𝗎𝖽𝗂𝗈 𝖯𝗅𝖺𝗒𝖡𝖺𝖼𝗄 𝖲𝗉𝖾𝖾𝖽 𝖨𝗇 𝖢𝗁𝖺𝗇𝗇𝖾𝗅 . 151 | """ 152 | --------------------------------------------------------------------------------