├── .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 |
5 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
/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 |
--------------------------------------------------------------------------------