BinaryONe commited on
Commit
2f67506
·
1 Parent(s): c65bc69

Refresh Update

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +10 -0
  2. .gitattributes +35 -0
  3. .gitignore +10 -0
  4. Dockerfile +12 -0
  5. LICENSE +21 -0
  6. README.md +11 -0
  7. YukkiMusic/__init__.py +48 -0
  8. YukkiMusic/__main__.py +86 -0
  9. YukkiMusic/core/bot.py +73 -0
  10. YukkiMusic/core/call.py +750 -0
  11. YukkiMusic/core/dir.py +33 -0
  12. YukkiMusic/core/git.py +84 -0
  13. YukkiMusic/core/mongo.py +43 -0
  14. YukkiMusic/core/userbot.py +193 -0
  15. YukkiMusic/logging.py +23 -0
  16. YukkiMusic/misc.py +90 -0
  17. YukkiMusic/platforms/Apple.py +86 -0
  18. YukkiMusic/platforms/Carbon.py +115 -0
  19. YukkiMusic/platforms/Resso.py +63 -0
  20. YukkiMusic/platforms/Soundcloud.py +49 -0
  21. YukkiMusic/platforms/Spotify.py +109 -0
  22. YukkiMusic/platforms/Telegram.py +205 -0
  23. YukkiMusic/platforms/Youtube.py +467 -0
  24. YukkiMusic/platforms/YoutubeAPI/BS4scrapAPI.py +179 -0
  25. YukkiMusic/platforms/YoutubeAPI/InnertubeAPI.py +250 -0
  26. YukkiMusic/platforms/YoutubeAPI/JSON_DATA.py +58 -0
  27. YukkiMusic/platforms/YoutubeAPI/__init__.py +0 -0
  28. YukkiMusic/platforms/__init__.py +16 -0
  29. YukkiMusic/platforms/custom_dl.py +185 -0
  30. YukkiMusic/platforms/file_properties.py +98 -0
  31. YukkiMusic/plugins/__init__.py +31 -0
  32. YukkiMusic/plugins/admins/auth.py +159 -0
  33. YukkiMusic/plugins/admins/callback.py +444 -0
  34. YukkiMusic/plugins/admins/loop.py +60 -0
  35. YukkiMusic/plugins/admins/mute.py +39 -0
  36. YukkiMusic/plugins/admins/pause.py +39 -0
  37. YukkiMusic/plugins/admins/resume.py +39 -0
  38. YukkiMusic/plugins/admins/seek.py +87 -0
  39. YukkiMusic/plugins/admins/shuffle.py +49 -0
  40. YukkiMusic/plugins/admins/skip.py +223 -0
  41. YukkiMusic/plugins/admins/stop.py +37 -0
  42. YukkiMusic/plugins/admins/unmute.py +39 -0
  43. YukkiMusic/plugins/bot/help.py +122 -0
  44. YukkiMusic/plugins/bot/inline.py +83 -0
  45. YukkiMusic/plugins/bot/settings.py +568 -0
  46. YukkiMusic/plugins/bot/start.py +294 -0
  47. YukkiMusic/plugins/devs/dev.py +225 -0
  48. YukkiMusic/plugins/misc/autoleave.py +88 -0
  49. YukkiMusic/plugins/misc/cleanmode.py +279 -0
  50. YukkiMusic/plugins/misc/seeker.py +103 -0
.dockerignore ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ .cache
3
+ Yukkilogs.txt
4
+ .DS_Store
5
+ *.session
6
+ raw_files/
7
+ cache/
8
+ downloads/
9
+ __pycache__/
10
+ *.session-journal
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ .env
2
+ .cache
3
+ Yukkilogs.txt
4
+ .DS_Store
5
+ *.session
6
+ raw_files/
7
+ cache/
8
+ downloads/
9
+ __pycache__/
10
+ *.session-journal
Dockerfile ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM nikolaik/python-nodejs:python3.9-nodejs18
2
+ RUN apt-get update -y && apt-get upgrade -y \
3
+ && apt-get install -y --no-install-recommends ffmpeg \
4
+ && apt-get clean \
5
+ && rm -rf /var/lib/apt/lists/*
6
+ COPY . /app
7
+
8
+ RUN chmod 777 /app
9
+ WORKDIR /app
10
+ RUN pip3 install --no-cache-dir --upgrade --requirement requirements.txt
11
+
12
+ CMD ["python", "-u","-m", "YukkiMusic"]
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Team Yukki
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: One Stream
3
+ emoji: 📈
4
+ colorFrom: indigo
5
+ colorTo: gray
6
+ sdk: docker
7
+ pinned: false
8
+ license: gpl-2.0
9
+ ---
10
+
11
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
YukkiMusic/__init__.py ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from YukkiMusic.core.bot import YukkiBot
11
+ from YukkiMusic.core.dir import dirr
12
+ from YukkiMusic.core.git import git
13
+ from YukkiMusic.core.userbot import Userbot
14
+ from YukkiMusic.misc import dbb, heroku, sudo
15
+
16
+ from .logging import LOGGER
17
+
18
+
19
+ # Directories
20
+ dirr()
21
+
22
+ # Check Git Updates
23
+ git()
24
+
25
+ # Initialize Memory DB
26
+ dbb()
27
+
28
+ # Heroku APP
29
+ heroku()
30
+
31
+ # Load Sudo Users from DB
32
+ sudo()
33
+
34
+ # Bot Client
35
+ app = YukkiBot()
36
+
37
+ # Assistant Client
38
+ userbot = Userbot()
39
+
40
+ from .platforms import *
41
+
42
+ YouTube = YouTubeAPI()
43
+ Carbon = CarbonAPI()
44
+ Spotify = SpotifyAPI()
45
+ Apple = AppleAPI()
46
+ Resso = RessoAPI()
47
+ SoundCloud = SoundAPI()
48
+ Telegram = TeleAPI()
YukkiMusic/__main__.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ import importlib
12
+ import sys
13
+ from aiohttp import web
14
+ from pyrogram import idle
15
+ from pytgcalls.exceptions import NoActiveGroupCall
16
+
17
+ import config
18
+ from config import BANNED_USERS
19
+ from YukkiMusic import LOGGER, app, userbot
20
+ from .alive import web_server
21
+ from YukkiMusic.core.call import Yukki
22
+ from YukkiMusic.plugins import ALL_MODULES
23
+ from YukkiMusic.utils.database import get_banned_users, get_gbanned
24
+
25
+ loop = asyncio.get_event_loop()
26
+ server = web.AppRunner(web_server())
27
+
28
+ async def init():
29
+ await server.setup()
30
+ await web.TCPSite(server,'0.0.0.0', 7860).start()
31
+ print("------------------------------Web Server Started ------------------------------")
32
+
33
+ if (
34
+ not config.STRING1
35
+ and not config.STRING2
36
+ and not config.STRING3
37
+ and not config.STRING4
38
+ and not config.STRING5
39
+ ):
40
+ LOGGER("YukkiMusic").error(
41
+ "No Assistant Clients Vars Defined!.. Exiting Process."
42
+ )
43
+ return
44
+ if (
45
+ not config.SPOTIFY_CLIENT_ID
46
+ and not config.SPOTIFY_CLIENT_SECRET
47
+ ):
48
+ LOGGER("YukkiMusic").warning(
49
+ "No Spotify Vars defined. Your bot won't be able to play spotify queries."
50
+ )
51
+ try:
52
+ users = await get_gbanned()
53
+ for user_id in users:
54
+ BANNED_USERS.add(user_id)
55
+ users = await get_banned_users()
56
+ for user_id in users:
57
+ BANNED_USERS.add(user_id)
58
+ except:
59
+ pass
60
+ await app.start()
61
+ for all_module in ALL_MODULES:
62
+ importlib.import_module("YukkiMusic.plugins" + all_module)
63
+ LOGGER("Yukkimusic.plugins").info("Successfully Imported Modules ")
64
+
65
+ await userbot.start()
66
+ await Yukki.start()
67
+ try:
68
+ await Yukki.stream_call(
69
+ "http://docs.evostream.com/sample_content/assets/sintel1m720p.mp4"
70
+ )
71
+ except NoActiveGroupCall:
72
+ LOGGER("YukkiMusic").error(
73
+ "[ERROR] - \n\nPlease turn on your Logger Group's Voice Call. Make sure you never close/end voice call in your log group"
74
+ )
75
+ sys.exit()
76
+ except:
77
+ pass
78
+ await Yukki.decorators()
79
+ LOGGER("YukkiMusic").info("Yukki Music Bot Started Successfully")
80
+ await idle()
81
+
82
+
83
+ if __name__ == "__main__":
84
+ #keep_alive()
85
+ loop.run_until_complete(init())
86
+ LOGGER("YukkiMusic").info("Stopping Yukki Music Bot! GoodBye")
YukkiMusic/core/bot.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import sys
11
+
12
+ from pyrogram import Client
13
+ from pyrogram.types import BotCommand
14
+
15
+ import config
16
+
17
+ from ..logging import LOGGER
18
+
19
+
20
+ class YukkiBot(Client):
21
+
22
+ def __init__(self):
23
+ LOGGER(__name__).info(f"Starting Bot")
24
+ super().__init__(
25
+ "YukkiMusicBot",
26
+ api_id=config.API_ID,
27
+ api_hash=config.API_HASH,
28
+ bot_token=config.BOT_TOKEN,
29
+ )
30
+
31
+ async def start(self):
32
+ await super().start()
33
+ get_me = await self.get_me()
34
+ self.username = get_me.username
35
+ self.id = get_me.id
36
+ try:
37
+ await self.send_message(config.LOG_GROUP_ID, "Bot Started")
38
+ except:
39
+ LOGGER(__name__).error(
40
+ "Bot has failed to access the log Group. Make sure that you have added your bot to your log channel and promoted as admin!"
41
+ )
42
+ sys.exit()
43
+ if config.SET_CMDS :
44
+ try:
45
+ await self.set_bot_commands([
46
+ BotCommand("ping", "Check that bot is alive or dead"),
47
+ BotCommand("play", "Starts playing the requested song"),
48
+ BotCommand("webapp","Open webapp of the music bot for your chat."),
49
+ BotCommand("skip", "Moves to the next track in queue"),
50
+ BotCommand("pause", "Pause the current playing song"),
51
+ BotCommand("resume", "Resume the paused song"),
52
+ BotCommand("end", "Clear the queue and leave voice chat"),
53
+ BotCommand("shuffle", "Randomly shuffles the queued playlist."),
54
+ BotCommand("playmode","Allows you to change the default playmode for your chat"),
55
+ BotCommand("settings","Open the settings of the music bot for your chat.")
56
+ ])
57
+ except:
58
+ pass
59
+ else:
60
+ pass
61
+ a = await self.get_chat_member(config.LOG_GROUP_ID, self.id)
62
+ #print(a)
63
+ '''if a.status != "ChatMemberStatus.ADMINISTRATOR":
64
+ LOGGER(__name__).error(
65
+ "Please promote Bot as Admin in Logger Group"
66
+ )
67
+ sys.exit()'''
68
+ if get_me.last_name:
69
+ self.name = get_me.first_name + " " + get_me.last_name
70
+ else:
71
+ self.name = get_me.first_name
72
+ LOGGER(__name__).info(f"MusicBot Started as {self.name}")
73
+
YukkiMusic/core/call.py ADDED
@@ -0,0 +1,750 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ from datetime import datetime, timedelta
12
+ from typing import Union
13
+
14
+ from pyrogram import Client
15
+ from pyrogram.errors import (ChatAdminRequired, UserAlreadyParticipant,
16
+ UserNotParticipant)
17
+ from pyrogram.types import InlineKeyboardMarkup
18
+ from pytgcalls import PyTgCalls, StreamType
19
+ from pytgcalls.exceptions import (AlreadyJoinedError, NoActiveGroupCall)
20
+ from pytgcalls.types import (JoinedGroupCallParticipant,
21
+ LeftGroupCallParticipant, Update)
22
+ from pytgcalls.types.stream.legacy import AudioPiped, AudioVideoPiped
23
+ from pytgcalls.types.stream import MediaStream
24
+ from pytgcalls.types.stream import StreamAudioEnded
25
+
26
+ import config
27
+ from strings import get_string
28
+ from YukkiMusic import LOGGER, YouTube, app
29
+ from YukkiMusic.misc import db
30
+ from YukkiMusic.utils.database import (add_active_chat, add_active_video_chat,
31
+ get_assistant, get_audio_bitrate,
32
+ get_lang, get_loop, get_video_bitrate,
33
+ group_assistant, is_autoend, music_on,
34
+ mute_off, remove_active_chat,
35
+ remove_active_video_chat, set_loop)
36
+ from YukkiMusic.utils.exceptions import AssistantErr
37
+ from YukkiMusic.utils.inline.play import (stream_markup, telegram_markup)
38
+ from YukkiMusic.utils.stream.autoclear import auto_clean
39
+ from YukkiMusic.utils.thumbnails import gen_thumb
40
+
41
+ autoend = {}
42
+ counter = {}
43
+ AUTO_END_TIME = 3
44
+
45
+
46
+ async def _clear_(chat_id):
47
+ db[chat_id] = []
48
+ await remove_active_video_chat(chat_id)
49
+ await remove_active_chat(chat_id)
50
+
51
+
52
+ class Call(PyTgCalls):
53
+
54
+ def __init__(self):
55
+ self.userbot1 = Client(
56
+ name="1",
57
+ api_id=config.API_ID,
58
+ api_hash=config.API_HASH,
59
+ session_string=str(config.STRING1),
60
+ )
61
+ self.one = PyTgCalls(
62
+ self.userbot1,
63
+ cache_duration=100,
64
+ )
65
+ self.userbot2 = Client(
66
+ name="2",
67
+ api_id=config.API_ID,
68
+ api_hash=config.API_HASH,
69
+ session_string=str(config.STRING2),
70
+ )
71
+ self.two = PyTgCalls(
72
+ self.userbot2,
73
+ cache_duration=100,
74
+ )
75
+ self.userbot3 = Client(
76
+ name="3",
77
+ api_id=config.API_ID,
78
+ api_hash=config.API_HASH,
79
+ session_string=str(config.STRING3),
80
+ )
81
+ self.three = PyTgCalls(
82
+ self.userbot3,
83
+ cache_duration=100,
84
+ )
85
+ self.userbot4 = Client(
86
+ name="4",
87
+ api_id=config.API_ID,
88
+ api_hash=config.API_HASH,
89
+ session_string=str(config.STRING4),
90
+ )
91
+ self.four = PyTgCalls(
92
+ self.userbot4,
93
+ cache_duration=100,
94
+ )
95
+ self.userbot5 = Client(
96
+ name="5",
97
+ api_id=config.API_ID,
98
+ api_hash=config.API_HASH,
99
+ session_string=str(config.STRING5),
100
+
101
+ )
102
+ self.five = PyTgCalls(
103
+ self.userbot5,
104
+ cache_duration=100,
105
+ )
106
+
107
+ async def pause_stream(self, chat_id: int):
108
+ assistant = await group_assistant(self, chat_id)
109
+ await assistant.pause_stream(chat_id)
110
+
111
+ async def resume_stream(self, chat_id: int):
112
+ assistant = await group_assistant(self, chat_id)
113
+ await assistant.resume_stream(chat_id)
114
+
115
+ async def mute_stream(self, chat_id: int):
116
+ assistant = await group_assistant(self, chat_id)
117
+ await assistant.mute_stream(chat_id)
118
+
119
+ async def unmute_stream(self, chat_id: int):
120
+ assistant = await group_assistant(self, chat_id)
121
+ await assistant.unmute_stream(chat_id)
122
+
123
+ async def stop_stream(self, chat_id: int):
124
+ assistant = await group_assistant(self, chat_id)
125
+ try:
126
+ await _clear_(chat_id)
127
+ await assistant.leave_group_call(chat_id)
128
+ except:
129
+ pass
130
+
131
+ async def force_stop_stream(self, chat_id: int):
132
+ assistant = await group_assistant(self, chat_id)
133
+ try:
134
+ check = db.get(chat_id)
135
+ check.pop(0)
136
+ except:
137
+ pass
138
+ await remove_active_video_chat(chat_id)
139
+ await remove_active_chat(chat_id)
140
+ try:
141
+ await assistant.leave_group_call(chat_id)
142
+ except:
143
+ pass
144
+
145
+ async def skip_stream(self,
146
+ chat_id: int,
147
+ link: str,
148
+ video: Union[bool, str] = None):
149
+ assistant = await group_assistant(self, chat_id)
150
+ audio_stream_quality = await get_audio_bitrate(chat_id)
151
+ video_stream_quality = await get_video_bitrate(chat_id)
152
+ stream = (AudioVideoPiped(
153
+ link,
154
+ audio_parameters=audio_stream_quality,
155
+ video_parameters=video_stream_quality,
156
+ ) if video else AudioPiped(link, audio_parameters=audio_stream_quality))
157
+ await assistant.change_stream(
158
+ chat_id,
159
+ stream,
160
+ )
161
+
162
+ async def seek_stream(self, chat_id, file_path, to_seek, duration, mode):
163
+ assistant = await group_assistant(self, chat_id)
164
+ audio_stream_quality = await get_audio_bitrate(chat_id)
165
+ video_stream_quality = await get_video_bitrate(chat_id)
166
+ stream = (AudioVideoPiped(
167
+ file_path,
168
+ audio_parameters=audio_stream_quality,
169
+ video_parameters=video_stream_quality,
170
+ additional_ffmpeg_parameters=f"-ss {to_seek} -to {duration}",
171
+ ) if mode == "video" else AudioPiped(
172
+ file_path,
173
+ audio_parameters=audio_stream_quality,
174
+ additional_ffmpeg_parameters=f"-ss {to_seek} -to {duration}",
175
+ ))
176
+ await assistant.change_stream(chat_id, stream)
177
+
178
+ async def stream_call(self, link):
179
+ assistant = await group_assistant(self, config.LOG_GROUP_ID)
180
+ await assistant.join_group_call(
181
+ config.LOG_GROUP_ID,
182
+ AudioVideoPiped(link),
183
+ #stream_type=StreamType().pulse_stream,
184
+ )
185
+ await asyncio.sleep(0.5)
186
+ await assistant.leave_group_call(config.LOG_GROUP_ID)
187
+ #####################################################################################################
188
+ '''async def live_call(self):
189
+ assistant = await group_assistant(self, config.LOG_GROUP_ID)
190
+ video_url="https://rr3---sn-gwpa-jj0k.googlevideo.com/videoplayback?expire=1720992868&ei=BPCTZo2hIcms9fwPxuiMoAQ&ip=34.93.83.202&id=o-AMlVXbysivqlwX1nPegSYVckA8UO6qOI1HNjA_C3ILVm&itag=137&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&bui=AXc671JgbdicNDMCvD64suPqy3V2hQF-GNxvsTkZ4Qpvo2dmu4bM_1b8SqzJ_I9_xQETqJurEz1vxgA2&vprv=1&mime=video%2Fmp4&rqh=1&gir=yes&clen=73860085&dur=221.916&lmt=1720511440920986&keepalive=yes&lmw=1&c=ANDROID_TV&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Cmime%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRgIhAOjSd5GnA0fj9-jgOyQmW1sXSKx8WClSlO75pIYEZmjlAiEAkhn6qXR6My5_e1z4RBR6C6uGmYKrgaGnhWPYJ9S9ljc%3D&redirect_counter=1&rm=sn-cvh6l7e&fexp=24350516,24350518&req_id=f179ac02cc1ba3ee&cms_redirect=yes&cmsv=e&ipbypass=yes&mh=_i&mip=2409:40e1:1f:e1b6:6820:58cf:6a51:f4ca&mm=31&mn=sn-gwpa-jj0k&ms=au&mt=1720970964&mv=m&mvi=3&pl=48&lsparams=ipbypass,mh,mip,mm,mn,ms,mv,mvi,pl&lsig=AHlkHjAwRQIhAOJXJOUSYjnXhP8mIhp7BXilkWg27LhQwSgFo7h7Sqr9AiBFk9gtmm9mYJoANtxtJDYO92RdMgOq_AXd9D-mcxHuyw%3D%3D"
191
+ audio_url="https://rr3---sn-gwpa-jj0k.googlevideo.com/videoplayback?expire=1720992868&ei=BPCTZo2hIcms9fwPxuiMoAQ&ip=34.93.83.202&id=o-AMlVXbysivqlwX1nPegSYVckA8UO6qOI1HNjA_C3ILVm&itag=251&source=youtube&requiressl=yes&xpc=EgVo2aDSNQ%3D%3D&bui=AXc671JgbdicNDMCvD64suPqy3V2hQF-GNxvsTkZ4Qpvo2dmu4bM_1b8SqzJ_I9_xQETqJurEz1vxgA2&vprv=1&mime=audio%2Fwebm&rqh=1&gir=yes&clen=3994328&dur=221.941&lmt=1720508953333763&keepalive=yes&lmw=1&c=ANDROID_TV&txp=5532434&sparams=expire%2Cei%2Cip%2Cid%2Citag%2Csource%2Crequiressl%2Cxpc%2Cbui%2Cvprv%2Cmime%2Crqh%2Cgir%2Cclen%2Cdur%2Clmt&sig=AJfQdSswRQIgDKbPBz-4y2_EOaOVAA99AggLmKgrfnV21tW1KGXdPPICIQD3ZGqgy9ewLeEK2-WHYpE7P1-Lqm48qYyWOOwZzuvHCA%3D%3D&redirect_counter=1&rm=sn-cvh6l7e&fexp=24350516,24350518&req_id=877fdd961f2a3ee&cms_redirect=yes&cmsv=e&ipbypass=yes&mh=_i&mip=2409:40e1:1f:e1b6:6820:58cf:6a51:f4ca&mm=31&mn=sn-gwpa-jj0k&ms=au&mt=1720970964&mv=m&mvi=3&pl=48&lsparams=ipbypass,mh,mip,mm,mn,ms,mv,mvi,pl&lsig=AHlkHjAwRAIgJmYgFL-esOsvjZ0cLdtkGojJf2RAvyY3BghjEGHqxI4CIDMb2rdPML37UNGuGCZbrkwsKjgfI5FAZ3fOGO-3VO7X"
192
+
193
+ await assistant.join_group_call(
194
+ config.LOG_GROUP_ID,
195
+ MediaStream(
196
+ media_path=video_url,
197
+ audio_path=audio_url,
198
+ ),
199
+ #stream_type=StreamType().pulse_stream,
200
+ )
201
+
202
+ '''
203
+ async def join_assistant(self, original_chat_id, chat_id):
204
+ language = await get_lang(original_chat_id)
205
+ _ = get_string(language)
206
+ userbot = await get_assistant(chat_id)
207
+ try:
208
+ try:
209
+ get = await app.get_chat_member(chat_id, userbot.id)
210
+ except ChatAdminRequired:
211
+ raise AssistantErr(_["call_1"])
212
+ if get.status == "banned" or get.status == "kicked":
213
+ raise AssistantErr(_["call_2"].format(userbot.username, userbot.id))
214
+ except UserNotParticipant:
215
+ chat = await app.get_chat(chat_id)
216
+ if chat.username:
217
+ try:
218
+ await userbot.join_chat(chat.username)
219
+ except UserAlreadyParticipant:
220
+ pass
221
+ except Exception as e:
222
+ raise AssistantErr(_["call_3"].format(e))
223
+ else:
224
+ try:
225
+ try:
226
+ try:
227
+ invitelink = chat.invite_link
228
+ if invitelink is None:
229
+ invitelink = (await app.export_chat_invite_link(chat_id))
230
+ except:
231
+ invitelink = (await app.export_chat_invite_link(chat_id))
232
+ except ChatAdminRequired:
233
+ raise AssistantErr(_["call_4"])
234
+ except Exception as e:
235
+ raise AssistantErr(e)
236
+ m = await app.send_message(original_chat_id, _["call_5"])
237
+ if invitelink.startswith("https://t.me/+"):
238
+ invitelink = invitelink.replace("https://t.me/+",
239
+ "https://t.me/joinchat/")
240
+ await asyncio.sleep(3)
241
+ await userbot.join_chat(invitelink)
242
+ await asyncio.sleep(4)
243
+ await m.edit(_["call_6"].format(userbot.name))
244
+ except UserAlreadyParticipant:
245
+ pass
246
+ except Exception as e:
247
+ raise AssistantErr(_["call_3"].format(e))
248
+
249
+ async def join_call(
250
+ self,
251
+ chat_id: int,
252
+ original_chat_id: int,
253
+ link,
254
+ video: Union[bool, str] = None,
255
+ ):
256
+ assistant = await group_assistant(self, chat_id)
257
+ audio_stream_quality = await get_audio_bitrate(chat_id)
258
+ video_stream_quality = await get_video_bitrate(chat_id)
259
+ stream = (AudioVideoPiped(
260
+ link,
261
+ audio_parameters=audio_stream_quality,
262
+ video_parameters=video_stream_quality,
263
+ ) if video else AudioPiped(link, audio_parameters=audio_stream_quality))
264
+ try:
265
+ print("join call")
266
+ await assistant.join_group_call(
267
+ chat_id,
268
+ stream,
269
+ #stream_type=StreamType().pulse_stream,
270
+ )
271
+ except NoActiveGroupCall:
272
+ try:
273
+ await self.join_assistant(original_chat_id, chat_id)
274
+ except Exception as e:
275
+ raise e
276
+ try:
277
+ await assistant.join_group_call(
278
+ chat_id,
279
+ stream,
280
+ #stream_type=StreamType().pulse_stream,
281
+ )
282
+ except Exception as e:
283
+ raise AssistantErr(
284
+ "**No Active Voice Chat Found**\n\nPlease make sure group's voice chat is enabled. If already enabled, please end it and start fresh voice chat again and if the problem continues, try /restart"
285
+ )
286
+ except AlreadyJoinedError:
287
+ raise AssistantErr(
288
+ "**Assistant Already in Voice Chat**\n\nSystems have detected that assistant is already there in the voice chat, this issue generally comes when you play 2 queries together.\n\nIf assistant is not present in voice chat, please end voice chat and start fresh voice chat again and if the problem continues, try /restart"
289
+ )
290
+ '''except TelegramServerError:
291
+ raise AssistantErr(
292
+ "**Telegram Server Error**\n\nTelegram is having some internal server problems, Please try playing again.\n\n If this problem keeps coming everytime, please end your voice chat and start fresh voice chat again."
293
+ )'''
294
+ await add_active_chat(chat_id)
295
+ await mute_off(chat_id)
296
+ await music_on(chat_id)
297
+ if video:
298
+ await add_active_video_chat(chat_id)
299
+ if await is_autoend():
300
+ counter[chat_id] = {}
301
+ users = len(await assistant.get_participants(chat_id))
302
+ if users == 1:
303
+ autoend[chat_id] = datetime.now() + timedelta(minutes=AUTO_END_TIME)
304
+
305
+ async def join_live_call(
306
+ self,
307
+ chat_id: int,
308
+ original_chat_id: int,
309
+ link,
310
+ video: Union[bool, str] = None,
311
+ ):
312
+ assistant = await group_assistant(self, chat_id)
313
+ audio_stream_quality = await get_audio_bitrate(chat_id)
314
+ video_stream_quality = await get_video_bitrate(chat_id)
315
+ '''stream = (AudioVideoPiped(
316
+ link,
317
+ audio_parameters=audio_stream_quality,
318
+ video_parameters=video_stream_quality,
319
+ ) if video else AudioPiped(link, audio_parameters=audio_stream_quality))'''
320
+ try:
321
+ print("join live call")
322
+ if video:
323
+ await assistant.join_group_call(
324
+ chat_id,
325
+ MediaStream(
326
+ media_path=link,
327
+ video_parameters=video_stream_quality,
328
+ ),
329
+ #stream_type=StreamType().pulse_stream,
330
+ )
331
+ else:
332
+ await assistant.join_group_call(
333
+ chat_id,
334
+ MediaStream(
335
+ media_path=link,
336
+ audio_parameters=audio_stream_quality,
337
+ ),
338
+ #stream_type=StreamType().pulse_stream,
339
+ )
340
+ except NoActiveGroupCall:
341
+ try:
342
+ await self.join_assistant(original_chat_id, chat_id)
343
+ except Exception as e:
344
+ raise e
345
+ try:
346
+ if video:
347
+ await assistant.join_group_call(
348
+ chat_id,
349
+ MediaStream(
350
+ media_path=link,
351
+ video_parameters=video_stream_quality,
352
+ ),
353
+ #stream_type=StreamType().pulse_stream,
354
+ )
355
+ else:
356
+ await assistant.join_group_call(
357
+ chat_id,
358
+ MediaStream(
359
+ media_path=link,
360
+ audio_parameters=audio_stream_quality,
361
+ ),
362
+ #stream_type=StreamType().pulse_stream,
363
+ )
364
+ except Exception as e:
365
+ raise AssistantErr(
366
+ "**No Active Voice Chat Found**\n\nPlease make sure group's voice chat is enabled. If already enabled, please end it and start fresh voice chat again and if the problem continues, try /restart"
367
+ )
368
+ except AlreadyJoinedError:
369
+ raise AssistantErr(
370
+ "**Assistant Already in Voice Chat**\n\nSystems have detected that assistant is already there in the voice chat, this issue generally comes when you play 2 queries together.\n\nIf assistant is not present in voice chat, please end voice chat and start fresh voice chat again and if the problem continues, try /restart"
371
+ )
372
+ '''except TelegramServerError:
373
+ raise AssistantErr(
374
+ "**Telegram Server Error**\n\nTelegram is having some internal server problems, Please try playing again.\n\n If this problem keeps coming everytime, please end your voice chat and start fresh voice chat again."
375
+ )'''
376
+ await add_active_chat(chat_id)
377
+ await mute_off(chat_id)
378
+ await music_on(chat_id)
379
+ if video:
380
+ await add_active_video_chat(chat_id)
381
+ if await is_autoend():
382
+ counter[chat_id] = {}
383
+ users = len(await assistant.get_participants(chat_id))
384
+ if users == 1:
385
+ autoend[chat_id] = datetime.now() + timedelta(minutes=AUTO_END_TIME)
386
+
387
+
388
+
389
+
390
+ async def live_call(
391
+ self,
392
+ chat_id: int,
393
+ original_chat_id: int,
394
+ video_url,
395
+ audio_url,
396
+ video: Union[bool, str] = None,
397
+ ):
398
+
399
+ assistant = await group_assistant(self, chat_id)
400
+ audio_stream_quality = await get_audio_bitrate(chat_id)
401
+ video_stream_quality = await get_video_bitrate(chat_id)
402
+ '''stream = (AudioVideoPiped(
403
+ link,
404
+ audio_parameters=audio_stream_quality,
405
+ video_parameters=video_stream_quality,
406
+ ) if video else AudioPiped(link, audio_parameters=audio_stream_quality))'''
407
+ try:
408
+ print("live call")
409
+ if video:
410
+ await assistant.join_group_call(
411
+ chat_id,
412
+ MediaStream(
413
+ media_path=video_url,
414
+ audio_path=audio_url,
415
+ audio_parameters=audio_stream_quality,
416
+ video_parameters=video_stream_quality,
417
+ ),
418
+ #stream_type=StreamType().pulse_stream,
419
+ )
420
+ else:
421
+ await assistant.join_group_call(
422
+ chat_id,
423
+ MediaStream(
424
+ media_path=audio_url,
425
+ audio_parameters=audio_stream_quality,
426
+ ),
427
+ #stream_type=StreamType().pulse_stream,
428
+ )
429
+ except NoActiveGroupCall:
430
+ try:
431
+ await self.join_assistant(original_chat_id, chat_id)
432
+ except Exception as e:
433
+ raise e
434
+ try:
435
+ print("live call")
436
+ if video:
437
+ await assistant.join_group_call(
438
+ chat_id,
439
+ MediaStream(
440
+ media_path=video_url,
441
+ audio_path=audio_url,
442
+ audio_parameters=audio_stream_quality,
443
+ video_parameters=video_stream_quality,
444
+ ),
445
+ #stream_type=StreamType().pulse_stream,
446
+ )
447
+ else:
448
+ await assistant.join_group_call(
449
+ chat_id,
450
+ MediaStream(
451
+ media_path=audio_url,
452
+ audio_parameters=audio_stream_quality,
453
+ ),
454
+ #stream_type=StreamType().pulse_stream,
455
+ )
456
+ except Exception as e:
457
+ raise AssistantErr(
458
+ "**No Active Voice Chat Found**\n\nPlease make sure group's voice chat is enabled. If already enabled, please end it and start fresh voice chat again and if the problem continues, try /restart"
459
+ )
460
+ except AlreadyJoinedError:
461
+ raise AssistantErr(
462
+ "**Assistant Already in Voice Chat**\n\nSystems have detected that assistant is already there in the voice chat, this issue generally comes when you play 2 queries together.\n\nIf assistant is not present in voice chat, please end voice chat and start fresh voice chat again and if the problem continues, try /restart"
463
+ )
464
+ '''except TelegramServerError:
465
+ raise AssistantErr(
466
+ "**Telegram Server Error**\n\nTelegram is having some internal server problems, Please try playing again.\n\n If this problem keeps coming everytime, please end your voice chat and start fresh voice chat again."
467
+ )'''
468
+ await add_active_chat(chat_id)
469
+ await mute_off(chat_id)
470
+ await music_on(chat_id)
471
+ if video:
472
+ await add_active_video_chat(chat_id)
473
+ if await is_autoend():
474
+ counter[chat_id] = {}
475
+ users = len(await assistant.get_participants(chat_id))
476
+ if users == 1:
477
+ autoend[chat_id] = datetime.now() + timedelta(minutes=AUTO_END_TIME)
478
+
479
+ async def change_stream(self, client, chat_id):
480
+ check = db.get(chat_id)
481
+ popped = None
482
+ loop = await get_loop(chat_id)
483
+ try:
484
+ if loop == 0:
485
+ popped = check.pop(0)
486
+ else:
487
+ loop = loop - 1
488
+ await set_loop(chat_id, loop)
489
+ if popped:
490
+ if config.AUTO_DOWNLOADS_CLEAR == str(True):
491
+ await auto_clean(popped)
492
+ if not check:
493
+ await _clear_(chat_id)
494
+ return await client.leave_group_call(chat_id)
495
+ except:
496
+ try:
497
+ await _clear_(chat_id)
498
+ return await client.leave_group_call(chat_id)
499
+ except:
500
+ return
501
+ else:
502
+ queued = check[0]["file"]
503
+ language = await get_lang(chat_id)
504
+ _ = get_string(language)
505
+ title = (check[0]["title"]).title()
506
+ user = check[0]["by"]
507
+ original_chat_id = check[0]["chat_id"]
508
+ streamtype = check[0]["streamtype"]
509
+ audio_stream_quality = await get_audio_bitrate(chat_id)
510
+ video_stream_quality = await get_video_bitrate(chat_id)
511
+ videoid = check[0]["vidid"]
512
+ check[0]["played"] = 0
513
+ if "live_" in queued:
514
+ n, link = await YouTube.video(videoid, True)
515
+ if n == 0:
516
+ return await app.send_message(
517
+ original_chat_id,
518
+ text=_["call_9"],
519
+ )
520
+ stream = (AudioVideoPiped(
521
+ link,
522
+ audio_parameters=audio_stream_quality,
523
+ video_parameters=video_stream_quality,
524
+ ) if str(streamtype) == "video" else AudioPiped(
525
+ link, audio_parameters=audio_stream_quality))
526
+ try:
527
+ await client.change_stream(chat_id, stream)
528
+ except Exception:
529
+ return await app.send_message(
530
+ original_chat_id,
531
+ text=_["call_9"],
532
+ )
533
+ img = await gen_thumb(videoid)
534
+ button = telegram_markup(_, chat_id)
535
+ run = await app.send_photo(
536
+ original_chat_id,
537
+ photo=img,
538
+ caption=_["stream_1"].format(
539
+ user,
540
+ f"https://t.me/{app.username}?start=info_{videoid}",
541
+ ),
542
+ reply_markup=InlineKeyboardMarkup(button),
543
+ )
544
+ db[chat_id][0]["mystic"] = run
545
+ db[chat_id][0]["markup"] = "tg"
546
+ elif "vid_" in queued:
547
+ mystic = await app.send_message(original_chat_id, _["call_10"])
548
+ try:
549
+ file_path, direct = await YouTube.download(
550
+ videoid,
551
+ mystic,
552
+ videoid=True,
553
+ video=True if str(streamtype) == "video" else False,
554
+ )
555
+ except:
556
+ return await mystic.edit_text(_["call_9"],
557
+ disable_web_page_preview=True)
558
+ stream = (AudioVideoPiped(
559
+ file_path,
560
+ audio_parameters=audio_stream_quality,
561
+ video_parameters=video_stream_quality,
562
+ ) if str(streamtype) == "video" else AudioPiped(
563
+ file_path,
564
+ audio_parameters=audio_stream_quality,
565
+ ))
566
+ try:
567
+ await client.change_stream(chat_id, stream)
568
+ except Exception:
569
+ return await app.send_message(
570
+ original_chat_id,
571
+ text=_["call_9"],
572
+ )
573
+ img = await gen_thumb(videoid)
574
+ button = stream_markup(_, videoid, chat_id)
575
+ await mystic.delete()
576
+ run = await app.send_photo(
577
+ original_chat_id,
578
+ photo=img,
579
+ caption=_["stream_1"].format(
580
+ user,
581
+ f"https://t.me/{app.username}?start=info_{videoid}",
582
+ ),
583
+ reply_markup=InlineKeyboardMarkup(button),
584
+ )
585
+ db[chat_id][0]["mystic"] = run
586
+ db[chat_id][0]["markup"] = "stream"
587
+ elif "index_" in queued:
588
+ stream = (AudioVideoPiped(
589
+ videoid,
590
+ audio_parameters=audio_stream_quality,
591
+ video_parameters=video_stream_quality,
592
+ ) if str(streamtype) == "video" else AudioPiped(
593
+ videoid, audio_parameters=audio_stream_quality))
594
+ try:
595
+ await client.change_stream(chat_id, stream)
596
+ except Exception:
597
+ return await app.send_message(
598
+ original_chat_id,
599
+ text=_["call_9"],
600
+ )
601
+ button = telegram_markup(_, chat_id)
602
+ run = await app.send_photo(
603
+ original_chat_id,
604
+ photo=config.STREAM_IMG_URL,
605
+ caption=_["stream_2"].format(user),
606
+ reply_markup=InlineKeyboardMarkup(button),
607
+ )
608
+ db[chat_id][0]["mystic"] = run
609
+ db[chat_id][0]["markup"] = "tg"
610
+ else:
611
+ stream = (AudioVideoPiped(
612
+ queued,
613
+ audio_parameters=audio_stream_quality,
614
+ video_parameters=video_stream_quality,
615
+ ) if str(streamtype) == "video" else AudioPiped(
616
+ queued, audio_parameters=audio_stream_quality))
617
+ try:
618
+ await client.change_stream(chat_id, stream)
619
+ except Exception:
620
+ return await app.send_message(
621
+ original_chat_id,
622
+ text=_["call_9"],
623
+ )
624
+ if videoid == "telegram":
625
+ button = telegram_markup(_, chat_id)
626
+ run = await app.send_photo(
627
+ original_chat_id,
628
+ photo=config.TELEGRAM_AUDIO_URL
629
+ if str(streamtype) == "audio" else config.TELEGRAM_VIDEO_URL,
630
+ caption=_["stream_3"].format(title, check[0]["dur"], user),
631
+ reply_markup=InlineKeyboardMarkup(button),
632
+ )
633
+ db[chat_id][0]["mystic"] = run
634
+ db[chat_id][0]["markup"] = "tg"
635
+ elif videoid == "soundcloud":
636
+ button = telegram_markup(_, chat_id)
637
+ run = await app.send_photo(
638
+ original_chat_id,
639
+ photo=config.SOUNCLOUD_IMG_URL,
640
+ caption=_["stream_3"].format(title, check[0]["dur"], user),
641
+ reply_markup=InlineKeyboardMarkup(button),
642
+ )
643
+ db[chat_id][0]["mystic"] = run
644
+ db[chat_id][0]["markup"] = "tg"
645
+ else:
646
+ img = await gen_thumb(videoid)
647
+ button = stream_markup(_, videoid, chat_id)
648
+ run = await app.send_photo(
649
+ original_chat_id,
650
+ photo=img,
651
+ caption=_["stream_1"].format(
652
+ user,
653
+ f"https://t.me/{app.username}?start=info_{videoid}",
654
+ ),
655
+ reply_markup=InlineKeyboardMarkup(button),
656
+ )
657
+ db[chat_id][0]["mystic"] = run
658
+ db[chat_id][0]["markup"] = "stream"
659
+
660
+ async def ping(self):
661
+ pings = []
662
+ if config.STRING1:
663
+ pings.append(await self.one.ping)
664
+ if config.STRING2:
665
+ pings.append(await self.two.ping)
666
+ if config.STRING3:
667
+ pings.append(await self.three.ping)
668
+ if config.STRING4:
669
+ pings.append(await self.four.ping)
670
+ if config.STRING5:
671
+ pings.append(await self.five.ping)
672
+ return str(round(sum(pings) / len(pings), 3))
673
+
674
+
675
+ async def start(self):
676
+ LOGGER(__name__).info("Starting PyTgCalls Client\n")
677
+ if config.STRING1:
678
+ await self.one.start()
679
+ if config.STRING2:
680
+ await self.two.start()
681
+ if config.STRING3:
682
+ await self.three.start()
683
+ if config.STRING4:
684
+ await self.four.start()
685
+ if config.STRING5:
686
+ await self.five.start()
687
+
688
+ async def decorators(self):
689
+
690
+ @self.one.on_kicked()
691
+ @self.two.on_kicked()
692
+ @self.three.on_kicked()
693
+ @self.four.on_kicked()
694
+ @self.five.on_kicked()
695
+ @self.one.on_closed_voice_chat()
696
+ @self.two.on_closed_voice_chat()
697
+ @self.three.on_closed_voice_chat()
698
+ @self.four.on_closed_voice_chat()
699
+ @self.five.on_closed_voice_chat()
700
+ @self.one.on_left()
701
+ @self.two.on_left()
702
+ @self.three.on_left()
703
+ @self.four.on_left()
704
+ @self.five.on_left()
705
+ async def stream_services_handler(_, chat_id: int):
706
+ await self.stop_stream(chat_id)
707
+
708
+ @self.one.on_stream_end()
709
+ @self.two.on_stream_end()
710
+ @self.three.on_stream_end()
711
+ @self.four.on_stream_end()
712
+ @self.five.on_stream_end()
713
+ async def stream_end_handler1(client, update: Update):
714
+ if not isinstance(update, StreamAudioEnded):
715
+ return
716
+ await self.change_stream(client, update.chat_id)
717
+
718
+ @self.one.on_participants_change()
719
+ @self.two.on_participants_change()
720
+ @self.three.on_participants_change()
721
+ @self.four.on_participants_change()
722
+ @self.five.on_participants_change()
723
+ async def participants_change_handler(client, update: Update):
724
+ if not isinstance(update, JoinedGroupCallParticipant) and not isinstance(
725
+ update, LeftGroupCallParticipant):
726
+ return
727
+ chat_id = update.chat_id
728
+ users = counter.get(chat_id)
729
+ if not users:
730
+ try:
731
+ got = len(await client.get_participants(chat_id))
732
+ except:
733
+ return
734
+ counter[chat_id] = got
735
+ if got == 1:
736
+ autoend[chat_id] = datetime.now() + timedelta(minutes=AUTO_END_TIME)
737
+ return
738
+ autoend[chat_id] = {}
739
+ else:
740
+ final = (users + 1 if isinstance(update, JoinedGroupCallParticipant)
741
+ else users - 1)
742
+ counter[chat_id] = final
743
+ if final == 1:
744
+ autoend[chat_id] = datetime.now() + timedelta(minutes=AUTO_END_TIME)
745
+ return
746
+ autoend[chat_id] = {}
747
+
748
+
749
+
750
+ Yukki = Call()
YukkiMusic/core/dir.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import os
11
+ import sys
12
+ from os import listdir, mkdir
13
+
14
+ from ..logging import LOGGER
15
+
16
+
17
+ def dirr():
18
+ if "assets" not in listdir():
19
+ LOGGER(__name__).warning(
20
+ f"Assets Folder not Found. Please clone repository again."
21
+ )
22
+ sys.exit()
23
+ for file in os.listdir():
24
+ if file.endswith(".jpg"):
25
+ os.remove(file)
26
+ for file in os.listdir():
27
+ if file.endswith(".jpeg"):
28
+ os.remove(file)
29
+ if "downloads" not in listdir():
30
+ mkdir("downloads")
31
+ if "cache" not in listdir():
32
+ mkdir("cache")
33
+ LOGGER(__name__).info("Directories Updated.")
YukkiMusic/core/git.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ import shlex
12
+ from typing import Tuple
13
+
14
+ from git import Repo
15
+ from git.exc import GitCommandError, InvalidGitRepositoryError
16
+
17
+ import config
18
+
19
+ from ..logging import LOGGER
20
+
21
+
22
+ def install_req(cmd: str) -> Tuple[str, str, int, int]:
23
+ async def install_requirements():
24
+ args = shlex.split(cmd)
25
+ process = await asyncio.create_subprocess_exec(
26
+ *args,
27
+ stdout=asyncio.subprocess.PIPE,
28
+ stderr=asyncio.subprocess.PIPE,
29
+ )
30
+ stdout, stderr = await process.communicate()
31
+ return (
32
+ stdout.decode("utf-8", "replace").strip(),
33
+ stderr.decode("utf-8", "replace").strip(),
34
+ process.returncode,
35
+ process.pid,
36
+ )
37
+
38
+ return asyncio.get_event_loop().run_until_complete(
39
+ install_requirements()
40
+ )
41
+
42
+
43
+ def git():
44
+ REPO_LINK = config.UPSTREAM_REPO
45
+ if config.GIT_TOKEN:
46
+ GIT_USERNAME = REPO_LINK.split("com/")[1].split("/")[0]
47
+ TEMP_REPO = REPO_LINK.split("https://")[1]
48
+ UPSTREAM_REPO = (
49
+ f"https://{GIT_USERNAME}:{config.GIT_TOKEN}@{TEMP_REPO}"
50
+ )
51
+ else:
52
+ UPSTREAM_REPO = config.UPSTREAM_REPO
53
+ try:
54
+ repo = Repo()
55
+ LOGGER(__name__).info(f"Git Client Found [VPS DEPLOYER]")
56
+ except GitCommandError:
57
+ LOGGER(__name__).info(f"Invalid Git Command")
58
+ except InvalidGitRepositoryError:
59
+ repo = Repo.init()
60
+ if "origin" in repo.remotes:
61
+ origin = repo.remote("origin")
62
+ else:
63
+ origin = repo.create_remote("origin", UPSTREAM_REPO)
64
+ origin.fetch()
65
+ repo.create_head(
66
+ config.UPSTREAM_BRANCH,
67
+ origin.refs[config.UPSTREAM_BRANCH],
68
+ )
69
+ repo.heads[config.UPSTREAM_BRANCH].set_tracking_branch(
70
+ origin.refs[config.UPSTREAM_BRANCH]
71
+ )
72
+ repo.heads[config.UPSTREAM_BRANCH].checkout(True)
73
+ try:
74
+ repo.create_remote("origin", config.UPSTREAM_REPO)
75
+ except BaseException:
76
+ pass
77
+ nrs = repo.remote("origin")
78
+ nrs.fetch(config.UPSTREAM_BRANCH)
79
+ try:
80
+ nrs.pull(config.UPSTREAM_BRANCH)
81
+ except GitCommandError:
82
+ repo.git.reset("--hard", "FETCH_HEAD")
83
+ install_req("pip3 install --no-cache-dir -r requirements.txt")
84
+ LOGGER(__name__).info(f"Fetched Updates from: {REPO_LINK}")
YukkiMusic/core/mongo.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from motor.motor_asyncio import AsyncIOMotorClient as _mongo_client_
11
+ from pymongo import MongoClient
12
+ from pyrogram import Client
13
+
14
+ import config
15
+
16
+ from ..logging import LOGGER
17
+
18
+ TEMP_MONGODB = "mongodb+srv://shikhar:shikhar@cluster0.6xzlh.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"
19
+
20
+
21
+ if config.MONGO_DB_URI is None:
22
+ LOGGER(__name__).warning(
23
+ "No MONGO DB URL found.. Your Bot will work on Yukki's Database"
24
+ )
25
+ temp_client = Client(
26
+ "Yukki",
27
+ bot_token=config.BOT_TOKEN,
28
+ api_id=config.API_ID,
29
+ api_hash=config.API_HASH,
30
+ )
31
+ temp_client.start()
32
+ info = temp_client.get_me()
33
+ username = info.username
34
+ temp_client.stop()
35
+ _mongo_async_ = _mongo_client_(TEMP_MONGODB)
36
+ _mongo_sync_ = MongoClient(TEMP_MONGODB)
37
+ mongodb = _mongo_async_[username]
38
+ pymongodb = _mongo_sync_[username]
39
+ else:
40
+ _mongo_async_ = _mongo_client_(config.MONGO_DB_URI)
41
+ _mongo_sync_ = MongoClient(config.MONGO_DB_URI)
42
+ mongodb = _mongo_async_.Yukki
43
+ pymongodb = _mongo_sync_.Yukki
YukkiMusic/core/userbot.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import sys
11
+
12
+ from pyrogram import Client
13
+
14
+ import config
15
+
16
+ from ..logging import LOGGER
17
+
18
+ assistants = []
19
+ assistantids = []
20
+ multi_clients = {}
21
+ work_loads = {}
22
+
23
+ async def req_client():
24
+ index = min(work_loads, key=work_loads.get)
25
+ faster_client = multi_clients[index]
26
+ response = dict(index=index, client=faster_client)
27
+ return response
28
+
29
+ class Userbot(Client):
30
+
31
+ def __init__(self):
32
+ self.one = Client(
33
+ name="1",
34
+ api_id=config.API_ID,
35
+ api_hash=config.API_HASH,
36
+ session_string=str(config.STRING1),
37
+ no_updates=True,
38
+ )
39
+ self.two = Client(
40
+ name="2",
41
+ api_id=config.API_ID,
42
+ api_hash=config.API_HASH,
43
+ session_string=str(config.STRING2),
44
+ no_updates=True,
45
+ )
46
+ self.three = Client(
47
+ name="3",
48
+ api_id=config.API_ID,
49
+ api_hash=config.API_HASH,
50
+ session_string=str(config.STRING3),
51
+ no_updates=True,
52
+ )
53
+ self.four = Client(
54
+ name="4",
55
+ api_id=config.API_ID,
56
+ api_hash=config.API_HASH,
57
+ session_string=str(config.STRING4),
58
+ no_updates=True,
59
+ )
60
+ self.five = Client(
61
+ name="5",
62
+ api_id=config.API_ID,
63
+ api_hash=config.API_HASH,
64
+ session_string=str(config.STRING5),
65
+ no_updates=True,
66
+ )
67
+
68
+ async def start(self):
69
+ LOGGER(__name__).info(f"Starting Assistant Clients")
70
+ if config.STRING1:
71
+ await self.one.start()
72
+
73
+ assistants.append(1)
74
+ try:
75
+ await self.one.send_message(config.LOG_GROUP_ID, f"Assistant Started")
76
+ except:
77
+ LOGGER(__name__).error(
78
+ f"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! "
79
+ )
80
+ sys.exit()
81
+ get_me = await self.one.get_me()
82
+ self.one.username = get_me.username
83
+ self.one.id = get_me.id
84
+ assistantids.append(get_me.id)
85
+ if get_me.last_name:
86
+ self.one.name = (get_me.first_name + " " + get_me.last_name)
87
+ else:
88
+ self.one.name = get_me.first_name
89
+ LOGGER(__name__).info(f"Assistant Started as {self.one.name}")
90
+ if config.STRING2:
91
+ await self.two.start()
92
+
93
+ assistants.append(2)
94
+ try:
95
+ await self.two.send_message(
96
+ config.LOG_GROUP_ID, "Assistant Started"
97
+ )
98
+ except:
99
+ LOGGER(__name__).error(
100
+ f"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! "
101
+ )
102
+ sys.exit()
103
+ get_me = await self.two.get_me()
104
+ self.two.username = get_me.username
105
+ self.two.id = get_me.id
106
+ assistantids.append(get_me.id)
107
+ if get_me.last_name:
108
+ self.two.name = (
109
+ get_me.first_name + " " + get_me.last_name
110
+ )
111
+ else:
112
+ self.two.name = get_me.first_name
113
+ LOGGER(__name__).info(
114
+ f"Assistant Two Started as {self.two.name}"
115
+ )
116
+ if config.STRING3:
117
+ await self.three.start()
118
+
119
+ assistants.append(3)
120
+ try:
121
+ await self.three.send_message(
122
+ config.LOG_GROUP_ID, "Assistant Started"
123
+ )
124
+ except:
125
+ LOGGER(__name__).error(
126
+ f"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! "
127
+ )
128
+ sys.exit()
129
+ get_me = await self.three.get_me()
130
+ self.three.username = get_me.username
131
+ self.three.id = get_me.id
132
+ assistantids.append(get_me.id)
133
+ if get_me.last_name:
134
+ self.three.name = (
135
+ get_me.first_name + " " + get_me.last_name
136
+ )
137
+ else:
138
+ self.three.name = get_me.first_name
139
+ LOGGER(__name__).info(
140
+ f"Assistant Three Started as {self.three.name}"
141
+ )
142
+ if config.STRING4:
143
+ await self.four.start()
144
+
145
+ assistants.append(4)
146
+ try:
147
+ await self.four.send_message(
148
+ config.LOG_GROUP_ID, "Assistant Started"
149
+ )
150
+ except:
151
+ LOGGER(__name__).error(
152
+ f"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! "
153
+ )
154
+ sys.exit()
155
+ get_me = await self.four.get_me()
156
+ self.four.username = get_me.username
157
+ self.four.id = get_me.id
158
+ assistantids.append(get_me.id)
159
+ if get_me.last_name:
160
+ self.four.name = (
161
+ get_me.first_name + " " + get_me.last_name
162
+ )
163
+ else:
164
+ self.four.name = get_me.first_name
165
+ LOGGER(__name__).info(
166
+ f"Assistant Four Started as {self.four.name}"
167
+ )
168
+ if config.STRING5:
169
+ await self.five.start()
170
+
171
+ assistants.append(5)
172
+ try:
173
+ await self.five.send_message(
174
+ config.LOG_GROUP_ID, "Assistant Started"
175
+ )
176
+ except:
177
+ LOGGER(__name__).error(
178
+ f"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! "
179
+ )
180
+ sys.exit()
181
+ get_me = await self.five.get_me()
182
+ self.five.username = get_me.username
183
+ self.five.id = get_me.id
184
+ assistantids.append(get_me.id)
185
+ if get_me.last_name:
186
+ self.five.name = (
187
+ get_me.first_name + " " + get_me.last_name
188
+ )
189
+ else:
190
+ self.five.name = get_me.first_name
191
+ LOGGER(__name__).info(
192
+ f"Assistant Five Started as {self.five.name}"
193
+ )
YukkiMusic/logging.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import logging
2
+ #from logging.handlers import RotatingFileHandler
3
+
4
+ from config import LOG_FILE_NAME
5
+
6
+ '''logging.basicConfig(
7
+ level=logging.INFO,
8
+ format="[%(asctime)s - %(levelname)s] - %(name)s - %(message)s",
9
+ datefmt="%d-%b-%y %H:%M:%S",
10
+ handlers=[
11
+ RotatingFileHandler(
12
+ LOG_FILE_NAME, maxBytes=5000000, backupCount=10
13
+ ),
14
+ logging.StreamHandler(),
15
+ ],
16
+ )'''
17
+
18
+ logging.getLogger("pyrogram").setLevel(logging.ERROR)
19
+ logging.getLogger("pytgcalls").setLevel(logging.ERROR)
20
+
21
+
22
+ def LOGGER(name: str) -> logging.Logger:
23
+ return logging.getLogger(name)
YukkiMusic/misc.py ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import socket
11
+ import time
12
+
13
+ import heroku3
14
+ from pyrogram import filters
15
+
16
+ import config
17
+ from YukkiMusic.core.mongo import pymongodb
18
+
19
+ from .logging import LOGGER
20
+
21
+ SUDOERS = filters.user()
22
+
23
+ HAPP = None
24
+ _boot_ = time.time()
25
+
26
+
27
+ def is_heroku():
28
+ return "heroku" in socket.getfqdn()
29
+
30
+
31
+ XCB = [
32
+ "/",
33
+ "@",
34
+ ".",
35
+ "com",
36
+ ":",
37
+ "git",
38
+ "heroku",
39
+ "push",
40
+ str(config.HEROKU_API_KEY),
41
+ "https",
42
+ str(config.HEROKU_APP_NAME),
43
+ "HEAD",
44
+ "main",
45
+ ]
46
+
47
+
48
+ def dbb():
49
+ global db
50
+ db = {}
51
+ LOGGER(__name__).info(f"Database Initialized.")
52
+
53
+
54
+ def sudo():
55
+ global SUDOERS
56
+ OWNER = config.OWNER_ID
57
+ if config.MONGO_DB_URI is None:
58
+ for user_id in OWNER:
59
+ SUDOERS.add(user_id)
60
+ else:
61
+ sudoersdb = pymongodb.sudoers
62
+ sudoers = sudoersdb.find_one({"sudo": "sudo"})
63
+ sudoers = [] if not sudoers else sudoers["sudoers"]
64
+ for user_id in OWNER:
65
+ SUDOERS.add(user_id)
66
+ if user_id not in sudoers:
67
+ sudoers.append(user_id)
68
+ sudoersdb.update_one(
69
+ {"sudo": "sudo"},
70
+ {"$set": {"sudoers": sudoers}},
71
+ upsert=True,
72
+ )
73
+ if sudoers:
74
+ for x in sudoers:
75
+ SUDOERS.add(x)
76
+ LOGGER(__name__).info(f"Sudoers Loaded.")
77
+
78
+
79
+ def heroku():
80
+ global HAPP
81
+ if is_heroku:
82
+ if config.HEROKU_API_KEY and config.HEROKU_APP_NAME:
83
+ try:
84
+ Heroku = heroku3.from_key(config.HEROKU_API_KEY)
85
+ HAPP = Heroku.app(config.HEROKU_APP_NAME)
86
+ LOGGER(__name__).info(f"Heroku App Configured")
87
+ except BaseException:
88
+ LOGGER(__name__).warning(
89
+ f"Please make sure your Heroku API Key and Your App name are configured correctly in the heroku."
90
+ )
YukkiMusic/platforms/Apple.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import re
11
+ from typing import Union
12
+
13
+ import aiohttp
14
+ from bs4 import BeautifulSoup
15
+ from youtubesearchpython.__future__ import VideosSearch
16
+
17
+
18
+ class AppleAPI:
19
+ def __init__(self):
20
+ self.regex = r"^(https:\/\/music.apple.com\/)(.*)$"
21
+ self.base = "https://music.apple.com/in/playlist/"
22
+
23
+ async def valid(self, link: str):
24
+ if re.search(self.regex, link):
25
+ return True
26
+ else:
27
+ return False
28
+
29
+ async def track(self, url, playid: Union[bool, str] = None):
30
+ if playid:
31
+ url = self.base + url
32
+ async with aiohttp.ClientSession() as session:
33
+ async with session.get(url) as response:
34
+ if response.status != 200:
35
+ return False
36
+ html = await response.text()
37
+ soup = BeautifulSoup(html, "html.parser")
38
+ search = None
39
+ for tag in soup.find_all("meta"):
40
+ if tag.get("property", None) == "og:title":
41
+ search = tag.get("content", None)
42
+ if search is None:
43
+ return False
44
+ results = VideosSearch(search, limit=1)
45
+ for result in (await results.next())["result"]:
46
+ title = result["title"]
47
+ ytlink = result["link"]
48
+ vidid = result["id"]
49
+ duration_min = result["duration"]
50
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
51
+ track_details = {
52
+ "title": title,
53
+ "link": ytlink,
54
+ "vidid": vidid,
55
+ "duration_min": duration_min,
56
+ "thumb": thumbnail,
57
+ }
58
+ return track_details, vidid
59
+
60
+ async def playlist(self, url, playid: Union[bool, str] = None):
61
+ if playid:
62
+ url = self.base + url
63
+ playlist_id = url.split("playlist/")[1]
64
+ async with aiohttp.ClientSession() as session:
65
+ async with session.get(url) as response:
66
+ if response.status != 200:
67
+ return False
68
+ html = await response.text()
69
+ soup = BeautifulSoup(html, "html.parser")
70
+ applelinks = soup.find_all(
71
+ "meta", attrs={"property": "music:song"}
72
+ )
73
+ results = []
74
+ for item in applelinks:
75
+ try:
76
+ xx = (
77
+ ((item["content"]).split("album/")[1]).split("/")[
78
+ 0
79
+ ]
80
+ ).replace("-", " ")
81
+ except:
82
+ xx = ((item["content"]).split("album/")[1]).split(
83
+ "/"
84
+ )[0]
85
+ results.append(xx)
86
+ return results, playlist_id
YukkiMusic/platforms/Carbon.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import random
11
+ from os.path import realpath
12
+
13
+ import aiohttp
14
+ from aiohttp import client_exceptions
15
+
16
+
17
+ class UnableToFetchCarbon(Exception):
18
+ pass
19
+
20
+
21
+ themes = [
22
+ "3024-night",
23
+ "a11y-dark",
24
+ "blackboard",
25
+ "base16-dark",
26
+ "base16-light",
27
+ "cobalt",
28
+ "duotone-dark",
29
+ "dracula-pro",
30
+ "hopscotch",
31
+ "lucario",
32
+ "material",
33
+ "monokai",
34
+ "nightowl",
35
+ "nord",
36
+ "oceanic-next",
37
+ "one-light",
38
+ "one-dark",
39
+ "panda-syntax",
40
+ "parasio-dark",
41
+ "seti",
42
+ "shades-of-purple",
43
+ "solarized+dark",
44
+ "solarized+light",
45
+ "synthwave-84",
46
+ "twilight",
47
+ "verminal",
48
+ "vscode",
49
+ "yeti",
50
+ "zenburn",
51
+ ]
52
+
53
+ colour = [
54
+ "#FF0000",
55
+ "#FF5733",
56
+ "#FFFF00",
57
+ "#008000",
58
+ "#0000FF",
59
+ "#800080",
60
+ "#A52A2A",
61
+ "#FF00FF",
62
+ "#D2B48C",
63
+ "#00FFFF",
64
+ "#808000",
65
+ "#800000",
66
+ "#00FFFF",
67
+ "#30D5C8",
68
+ "#00FF00",
69
+ "#008080",
70
+ "#4B0082",
71
+ "#EE82EE",
72
+ "#FFC0CB",
73
+ "#000000",
74
+ "#FFFFFF",
75
+ "#808080",
76
+ ]
77
+
78
+
79
+ class CarbonAPI:
80
+ def __init__(self):
81
+ self.language = "auto"
82
+ self.drop_shadow = True
83
+ self.drop_shadow_blur = "68px"
84
+ self.drop_shadow_offset = "20px"
85
+ self.font_family = "JetBrains Mono"
86
+ self.width_adjustment = True
87
+ self.watermark = False
88
+
89
+ async def generate(self, text: str, user_id):
90
+ async with aiohttp.ClientSession(
91
+ headers={"Content-Type": "application/json"},
92
+ ) as ses:
93
+ params = {
94
+ "code": text,
95
+ }
96
+ params["backgroundColor"] = random.choice(colour)
97
+ params["theme"] = random.choice(themes)
98
+ params["dropShadow"] = self.drop_shadow
99
+ params["dropShadowOffsetY"] = self.drop_shadow_offset
100
+ params["dropShadowBlurRadius"] = self.drop_shadow_blur
101
+ params["fontFamily"] = self.font_family
102
+ params["language"] = self.language
103
+ params["watermark"] = self.watermark
104
+ params["widthAdjustment"] = self.width_adjustment
105
+ try:
106
+ request = await ses.post(
107
+ "https://carbonara.vercel.app/api/cook",
108
+ json=params,
109
+ )
110
+ except client_exceptions.ClientConnectorError:
111
+ raise UnableToFetchCarbon("Can not reach the Host!")
112
+ resp = await request.read()
113
+ with open(f"cache/carbon{user_id}.jpg", "wb") as f:
114
+ f.write(resp)
115
+ return realpath(f.name)
YukkiMusic/platforms/Resso.py ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import re
11
+ from typing import Union
12
+
13
+ import aiohttp
14
+ from bs4 import BeautifulSoup
15
+ from youtubesearchpython.__future__ import VideosSearch
16
+
17
+
18
+ class RessoAPI:
19
+ def __init__(self):
20
+ self.regex = r"^(https:\/\/m.resso.com\/)(.*)$"
21
+ self.base = "https://m.resso.com/"
22
+
23
+ async def valid(self, link: str):
24
+ if re.search(self.regex, link):
25
+ return True
26
+ else:
27
+ return False
28
+
29
+ async def track(self, url, playid: Union[bool, str] = None):
30
+ if playid:
31
+ url = self.base + url
32
+ async with aiohttp.ClientSession() as session:
33
+ async with session.get(url) as response:
34
+ if response.status != 200:
35
+ return False
36
+ html = await response.text()
37
+ soup = BeautifulSoup(html, "html.parser")
38
+ for tag in soup.find_all("meta"):
39
+ if tag.get("property", None) == "og:title":
40
+ title = tag.get("content", None)
41
+ if tag.get("property", None) == "og:description":
42
+ des = tag.get("content", None)
43
+ try:
44
+ des = des.split("·")[0]
45
+ except:
46
+ pass
47
+ if des == "":
48
+ return
49
+ results = VideosSearch(title, limit=1)
50
+ for result in (await results.next())["result"]:
51
+ title = result["title"]
52
+ ytlink = result["link"]
53
+ vidid = result["id"]
54
+ duration_min = result["duration"]
55
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
56
+ track_details = {
57
+ "title": title,
58
+ "link": ytlink,
59
+ "vidid": vidid,
60
+ "duration_min": duration_min,
61
+ "thumb": thumbnail,
62
+ }
63
+ return track_details, vidid
YukkiMusic/platforms/Soundcloud.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import re
11
+ from os import path
12
+
13
+ from yt_dlp import YoutubeDL
14
+
15
+ from YukkiMusic.utils.formatters import seconds_to_min
16
+
17
+
18
+ class SoundAPI:
19
+ def __init__(self):
20
+ self.opts = {
21
+ "outtmpl": "downloads/%(id)s.%(ext)s",
22
+ "format": "best",
23
+ "retries": 3,
24
+ "nooverwrites": False,
25
+ "continuedl": True,
26
+ }
27
+
28
+ async def valid(self, link: str):
29
+ if "soundcloud" in link:
30
+ return True
31
+ else:
32
+ return False
33
+
34
+ async def download(self, url):
35
+ d = YoutubeDL(self.opts)
36
+ try:
37
+ info = d.extract_info(url)
38
+ except:
39
+ return False
40
+ xyz = path.join("downloads", f"{info['id']}.{info['ext']}")
41
+ duration_min = seconds_to_min(info["duration"])
42
+ track_details = {
43
+ "title": info["title"],
44
+ "duration_sec": info["duration"],
45
+ "duration_min": duration_min,
46
+ "uploader": info["uploader"],
47
+ "filepath": xyz,
48
+ }
49
+ return track_details, xyz
YukkiMusic/platforms/Spotify.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import re
11
+
12
+ import spotipy
13
+ from spotipy.oauth2 import SpotifyClientCredentials
14
+ from youtubesearchpython.__future__ import VideosSearch
15
+
16
+ import config
17
+
18
+
19
+ class SpotifyAPI:
20
+ def __init__(self):
21
+ self.regex = r"^(https:\/\/open.spotify.com\/)(.*)$"
22
+ self.client_id = config.SPOTIFY_CLIENT_ID
23
+ self.client_secret = config.SPOTIFY_CLIENT_SECRET
24
+ if config.SPOTIFY_CLIENT_ID and config.SPOTIFY_CLIENT_SECRET:
25
+ self.client_credentials_manager = (
26
+ SpotifyClientCredentials(
27
+ self.client_id, self.client_secret
28
+ )
29
+ )
30
+ self.spotify = spotipy.Spotify(
31
+ client_credentials_manager=self.client_credentials_manager
32
+ )
33
+ else:
34
+ self.spotify = None
35
+
36
+ async def valid(self, link: str):
37
+ if re.search(self.regex, link):
38
+ return True
39
+ else:
40
+ return False
41
+
42
+ async def track(self, link: str):
43
+ track = self.spotify.track(link)
44
+ info = track["name"]
45
+ for artist in track["artists"]:
46
+ fetched = f' {artist["name"]}'
47
+ if "Various Artists" not in fetched:
48
+ info += fetched
49
+ results = VideosSearch(info, limit=1)
50
+ for result in (await results.next())["result"]:
51
+ ytlink = result["link"]
52
+ title = result["title"]
53
+ vidid = result["id"]
54
+ duration_min = result["duration"]
55
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
56
+ track_details = {
57
+ "title": title,
58
+ "link": ytlink,
59
+ "vidid": vidid,
60
+ "duration_min": duration_min,
61
+ "thumb": thumbnail,
62
+ }
63
+ return track_details, vidid
64
+
65
+ async def playlist(self, url):
66
+ playlist = self.spotify.playlist(url)
67
+ playlist_id = playlist["id"]
68
+ results = []
69
+ for item in playlist["tracks"]["items"]:
70
+ music_track = item["track"]
71
+ info = music_track["name"]
72
+ for artist in music_track["artists"]:
73
+ fetched = f' {artist["name"]}'
74
+ if "Various Artists" not in fetched:
75
+ info += fetched
76
+ results.append(info)
77
+ return results, playlist_id
78
+
79
+ async def album(self, url):
80
+ album = self.spotify.album(url)
81
+ album_id = album["id"]
82
+ results = []
83
+ for item in album["tracks"]["items"]:
84
+ info = item["name"]
85
+ for artist in item["artists"]:
86
+ fetched = f' {artist["name"]}'
87
+ if "Various Artists" not in fetched:
88
+ info += fetched
89
+ results.append(info)
90
+
91
+ return (
92
+ results,
93
+ album_id,
94
+ )
95
+
96
+ async def artist(self, url):
97
+ artistinfo = self.spotify.artist(url)
98
+ artist_id = artistinfo["id"]
99
+ results = []
100
+ artisttoptracks = self.spotify.artist_top_tracks(url)
101
+ for item in artisttoptracks["tracks"]:
102
+ info = item["name"]
103
+ for artist in item["artists"]:
104
+ fetched = f' {artist["name"]}'
105
+ if "Various Artists" not in fetched:
106
+ info += fetched
107
+ results.append(info)
108
+
109
+ return results, artist_id
YukkiMusic/platforms/Telegram.py ADDED
@@ -0,0 +1,205 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ import os
12
+ import time
13
+ from datetime import datetime, timedelta
14
+ from typing import Union
15
+
16
+ from pyrogram.types import (InlineKeyboardButton,
17
+ InlineKeyboardMarkup, Voice)
18
+
19
+ import config
20
+ from config import MUSIC_BOT_NAME, lyrical
21
+ from YukkiMusic import app
22
+
23
+ from ..utils.formatters import (convert_bytes, get_readable_time,
24
+ seconds_to_min)
25
+
26
+ downloader = {}
27
+
28
+
29
+ class TeleAPI:
30
+ def __init__(self):
31
+ self.chars_limit = 4096
32
+ self.sleep = config.TELEGRAM_DOWNLOAD_EDIT_SLEEP
33
+
34
+ async def send_split_text(self, message, string):
35
+ n = self.chars_limit
36
+ out = [(string[i : i + n]) for i in range(0, len(string), n)]
37
+ j = 0
38
+ for x in out:
39
+ if j <= 2:
40
+ j += 1
41
+ await message.reply_text(x)
42
+ return True
43
+
44
+ async def get_link(self, message):
45
+ if message.chat.username:
46
+ link = f"https://t.me/{message.chat.username}/{message.reply_to_message.id}"
47
+ else:
48
+ xf = str((message.chat.id))[4:]
49
+ link = f"https://t.me/c/{xf}/{message.reply_to_message.id}"
50
+ return link
51
+
52
+ async def get_filename(
53
+ self, file, audio: Union[bool, str] = None
54
+ ):
55
+ try:
56
+ file_name = file.file_name
57
+ if file_name is None:
58
+ file_name = (
59
+ "Telegram Audio File"
60
+ if audio
61
+ else "Telegram Video File"
62
+ )
63
+
64
+ except:
65
+ file_name = (
66
+ "Telegram Audio File"
67
+ if audio
68
+ else "Telegram Video File"
69
+ )
70
+ return file_name
71
+
72
+ async def get_duration(self, file):
73
+ try:
74
+ dur = seconds_to_min(file.duration)
75
+ except:
76
+ dur = "Unknown"
77
+ return dur
78
+
79
+ async def get_filepath(
80
+ self,
81
+ audio: Union[bool, str] = None,
82
+ video: Union[bool, str] = None,
83
+ ):
84
+ if audio:
85
+ try:
86
+ file_name = (
87
+ audio.file_unique_id
88
+ + "."
89
+ + (
90
+ (audio.file_name.split(".")[-1])
91
+ if (not isinstance(audio, Voice))
92
+ else "ogg"
93
+ )
94
+ )
95
+ except:
96
+ file_name = audio.file_unique_id + "." + ".ogg"
97
+ file_name = os.path.join(
98
+ os.path.realpath("downloads"), file_name
99
+ )
100
+ if video:
101
+ try:
102
+ file_name = (
103
+ video.file_unique_id
104
+ + "."
105
+ + (video.file_name.split(".")[-1])
106
+ )
107
+ except:
108
+ file_name = video.file_unique_id + "." + "mp4"
109
+ file_name = os.path.join(
110
+ os.path.realpath("downloads"), file_name
111
+ )
112
+ return file_name
113
+
114
+ async def download(self, _, message, mystic, fname):
115
+ left_time = {}
116
+ speed_counter = {}
117
+ if os.path.exists(fname):
118
+ return True
119
+
120
+ async def down_load():
121
+ async def progress(current, total):
122
+ if current == total:
123
+ return
124
+ current_time = time.time()
125
+ start_time = speed_counter.get(message.id)
126
+ check_time = current_time - start_time
127
+ upl = InlineKeyboardMarkup(
128
+ [
129
+ [
130
+ InlineKeyboardButton(
131
+ text="🚦 Cancel Downloading",
132
+ callback_data="stop_downloading",
133
+ ),
134
+ ]
135
+ ]
136
+ )
137
+ if datetime.now() > left_time.get(message.id):
138
+ percentage = current * 100 / total
139
+ percentage = str(round(percentage, 2))
140
+ speed = current / check_time
141
+ eta = int((total - current) / speed)
142
+ downloader[message.id] = eta
143
+ eta = get_readable_time(eta)
144
+ if not eta:
145
+ eta = "0 sec"
146
+ total_size = convert_bytes(total)
147
+ completed_size = convert_bytes(current)
148
+ speed = convert_bytes(speed)
149
+ text = f"""
150
+ **{MUSIC_BOT_NAME} Telegram Media Downloader**
151
+
152
+ **Total FileSize:** {total_size}
153
+ **Completed:** {completed_size}
154
+ **Percentage:** {percentage[:5]}%
155
+
156
+ **Speed:** {speed}/s
157
+ **ETA:** {eta}"""
158
+ try:
159
+ await mystic.edit_text(text, reply_markup=upl)
160
+ except:
161
+ pass
162
+ left_time[
163
+ message.id
164
+ ] = datetime.now() + timedelta(seconds=self.sleep)
165
+
166
+ speed_counter[message.id] = time.time()
167
+ left_time[message.id] = datetime.now()
168
+
169
+ try:
170
+ await app.download_media(
171
+ message.reply_to_message,
172
+ file_name=fname,
173
+ progress=progress,
174
+ )
175
+ await mystic.edit_text(
176
+ "Successfully Downloaded.. Processing file now"
177
+ )
178
+ downloader.pop(message.id)
179
+ except:
180
+ await mystic.edit_text(_["tg_2"])
181
+
182
+ if len(downloader) > 10:
183
+ timers = []
184
+ for x in downloader:
185
+ timers.append(downloader[x])
186
+ try:
187
+ low = min(timers)
188
+ eta = get_readable_time(low)
189
+ except:
190
+ eta = "Unknown"
191
+ await mystic.edit_text(_["tg_1"].format(eta))
192
+ return False
193
+
194
+ task = asyncio.create_task(down_load())
195
+ lyrical[mystic.id] = task
196
+ await task
197
+ downloaded = downloader.get(message.id)
198
+ if downloaded:
199
+ downloader.pop(message.id)
200
+ return False
201
+ verify = lyrical.get(mystic.id)
202
+ if not verify:
203
+ return False
204
+ lyrical.pop(mystic.id)
205
+ return True
YukkiMusic/platforms/Youtube.py ADDED
@@ -0,0 +1,467 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ import os
12
+ import re
13
+ from typing import Union
14
+
15
+ import aiohttp
16
+ import yt_dlp
17
+ from pyrogram.types import Message
18
+ from youtubesearchpython.__future__ import VideosSearch
19
+ import scrapetube
20
+ from innertube import InnerTube
21
+ from pprint import pprint
22
+
23
+
24
+ import config
25
+ from YukkiMusic.utils.database import is_on_off
26
+ from YukkiMusic.utils.formatters import time_to_seconds
27
+
28
+
29
+ async def shell_cmd(cmd):
30
+ proc = await asyncio.create_subprocess_shell(
31
+ cmd,
32
+ stdout=asyncio.subprocess.PIPE,
33
+ stderr=asyncio.subprocess.PIPE,
34
+ )
35
+ out, errorz = await proc.communicate()
36
+ if errorz:
37
+ if (
38
+ "unavailable videos are hidden"
39
+ in (errorz.decode("utf-8")).lower()
40
+ ):
41
+ return out.decode("utf-8")
42
+ else:
43
+ return errorz.decode("utf-8")
44
+ return out.decode("utf-8")
45
+
46
+
47
+ class YouTubeAPI:
48
+ def __init__(self):
49
+ self.base = "https://www.youtube.com/watch?v="
50
+ self.regex = r"(?:youtube\.com|youtu\.be)"
51
+ self.status = "https://www.youtube.com/oembed?url="
52
+ self.listbase = "https://youtube.com/playlist?list="
53
+ self.reg = re.compile(
54
+ r"\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])"
55
+ )
56
+
57
+ async def exists(
58
+ self, link: str, videoid: Union[bool, str] = None
59
+ ):
60
+ if videoid:
61
+ link = self.base + link
62
+ if re.search(self.regex, link):
63
+ return True
64
+ else:
65
+ return False
66
+
67
+ async def url(self, message_1: Message) -> Union[str, None]:
68
+ messages = [message_1]
69
+ if message_1.reply_to_message:
70
+ messages.append(message_1.reply_to_message)
71
+ text = ""
72
+ offset = None
73
+ length = None
74
+ for message in messages:
75
+ if offset:
76
+ break
77
+ if message.entities:
78
+ for entity in message.entities:
79
+ if entity.type == "url":
80
+ text = message.text or message.caption
81
+ offset, length = entity.offset, entity.length
82
+ break
83
+ elif message.caption_entities:
84
+ for entity in message.caption_entities:
85
+ if entity.type == "text_link":
86
+ return entity.url
87
+ if offset in (None,):
88
+ return None
89
+ return text[offset : offset + length]
90
+
91
+ async def details(
92
+ self, link: str, videoid: Union[bool, str] = None
93
+ ):
94
+ if videoid:
95
+ link1 = self.base + link
96
+ if "&" in link:
97
+ link1 = link.split("&")[0]
98
+ results = VideosSearch(link, limit=1)
99
+ for result in (await results.next())["result"]:
100
+ title = result["title"]
101
+ duration_min = result["duration"]
102
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
103
+ vidid = result["id"]
104
+ if str(duration_min) == "None":
105
+ duration_sec = 0
106
+ else:
107
+ duration_sec = int(time_to_seconds(duration_min))
108
+ return title, duration_min, duration_sec, thumbnail, vidid
109
+
110
+ async def title(
111
+ self, link: str, videoid: Union[bool, str] = None
112
+ ):
113
+ if videoid:
114
+ link = self.base + link
115
+ if "&" in link:
116
+ link = link.split("&")[0]
117
+ results = VideosSearch(link, limit=1)
118
+ for result in (await results.next())["result"]:
119
+ title = result["title"]
120
+ return title
121
+
122
+ async def duration(
123
+ self, link: str, videoid: Union[bool, str] = None
124
+ ):
125
+ if videoid:
126
+ link = self.base + link
127
+ if "&" in link:
128
+ link = link.split("&")[0]
129
+ results = VideosSearch(link, limit=1)
130
+ for result in (await results.next())["result"]:
131
+ duration = result["duration"]
132
+ return duration
133
+
134
+ async def thumbnail(
135
+ self, link: str, videoid: Union[bool, str] = None
136
+ ):
137
+ if videoid:
138
+ link = self.base + link
139
+ if "&" in link:
140
+ link = link.split("&")[0]
141
+ results = VideosSearch(link, limit=1)
142
+ for result in (await results.next())["result"]:
143
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
144
+ return thumbnail
145
+
146
+ async def video(
147
+ self, link: str, videoid: Union[bool, str] = None
148
+ ):
149
+ if videoid:
150
+ link = self.base + link
151
+ if "&" in link:
152
+ link = link.split("&")[0]
153
+ proc = await asyncio.create_subprocess_exec(
154
+ "yt-dlp",
155
+ "-g",
156
+ "-f",
157
+ "best[height<=?720][width<=?1280]",
158
+ f"{link}",
159
+ stdout=asyncio.subprocess.PIPE,
160
+ stderr=asyncio.subprocess.PIPE,
161
+ )
162
+ stdout, stderr = await proc.communicate()
163
+ if stdout:
164
+ return 1, stdout.decode().split("\n")[0]
165
+ else:
166
+ return 0, stderr.decode()
167
+
168
+ async def playlist(
169
+ self, link, limit, user_id, videoid: Union[bool, str] = None
170
+ ):
171
+ if videoid:
172
+ link1 = self.listbase + link
173
+ if "&" in link:
174
+ link1 = link.split("&")[0]
175
+ playlist = await shell_cmd(
176
+ f"yt-dlp -i --get-id --flat-playlist --playlist-end {limit} --skip-download {link}"
177
+ )
178
+ try:
179
+ result = playlist.split("\n")
180
+ for key in result:
181
+ if key == "":
182
+ result.remove(key)
183
+ except:
184
+ result = []
185
+ return result
186
+
187
+ async def track(
188
+ self, link: str, videoid: Union[bool, str] = None
189
+ ):
190
+ if videoid:
191
+ link = self.base + link
192
+ if "&" in link:
193
+ link = link.split("&")[0]
194
+ results = VideosSearch(link, limit=1)
195
+ #results = scrapetube.get_search(link,limit=1)
196
+ for result in (await results.next())["result"]:
197
+ #print(result)
198
+ title = result["id"] if result["title"]=='' else result["title"]
199
+ duration_min = result["duration"]
200
+ vidid = result["id"]
201
+ yturl = result["link"]
202
+ thumbnail = result["thumbnails"][0]["url"].split("?")[0]
203
+ track_details = {
204
+ "title": title,
205
+ "link": yturl,
206
+ "vidid": vidid,
207
+ "duration_min": duration_min,
208
+ "thumb": thumbnail,
209
+ }
210
+ '''
211
+ for result in results:
212
+ print(result)
213
+ title = result['title']['runs']['text']
214
+ duration_min = result['lengthText']['simpleText']
215
+ vidid = result['videoId']
216
+ yturl = link
217
+ thumbnail = result['thumbnail']['thumbnails'][0]['url']
218
+
219
+
220
+ track_details = {
221
+ "title":title ,
222
+ "link": link,
223
+ "vidid": vidid,
224
+ "duration_min": duration_min,
225
+ "thumb": thumbnail,
226
+ }'''
227
+ return track_details, vidid
228
+
229
+ async def formats(
230
+ self, link: str, videoid: Union[bool, str] = None
231
+ ):
232
+ if videoid:
233
+ link = self.base + link
234
+ if "&" in link:
235
+ link = link.split("&")[0]
236
+ ytdl_opts = {"quiet": True}
237
+ ydl = yt_dlp.YoutubeDL(ytdl_opts)
238
+ with ydl:
239
+ formats_available = []
240
+ r = ydl.extract_info(link, download=False)
241
+ for format in r["formats"]:
242
+ try:
243
+ str(format["format"])
244
+ except:
245
+ continue
246
+ if not "dash" in str(format["format"]).lower():
247
+ try:
248
+ format["format"]
249
+ format["filesize"]
250
+ format["format_id"]
251
+ format["ext"]
252
+ format["format_note"]
253
+ except:
254
+ continue
255
+ formats_available.append(
256
+ {
257
+ "format": format["format"],
258
+ "filesize": format["filesize"],
259
+ "format_id": format["format_id"],
260
+ "ext": format["ext"],
261
+ "format_note": format["format_note"],
262
+ "yturl": link,
263
+ }
264
+ )
265
+ return formats_available, link
266
+
267
+ async def slider(
268
+ self,
269
+ link: str,
270
+ query_type: int,
271
+ videoid: Union[bool, str] = None,
272
+ ):
273
+ if videoid:
274
+ link = self.base + link
275
+ if "&" in link:
276
+ link = link.split("&")[0]
277
+ a = VideosSearch(link, limit=10)
278
+ result = (await a.next()).get("result")
279
+ title = result[query_type]["title"]
280
+ duration_min = result[query_type]["duration"]
281
+ vidid = result[query_type]["id"]
282
+ thumbnail = result[query_type]["thumbnails"][0]["url"].split(
283
+ "?"
284
+ )[0]
285
+ return title, duration_min, thumbnail, vidid
286
+
287
+ async def download(
288
+ self,
289
+ link: str,
290
+ mystic,
291
+ video: Union[bool, str] = None,
292
+ videoid: Union[bool, str] = None,
293
+ songaudio: Union[bool, str] = None,
294
+ songvideo: Union[bool, str] = None,
295
+ format_id: Union[bool, str] = None,
296
+ title: Union[bool, str] = None,
297
+ ) -> str:
298
+ if videoid:
299
+ link = self.base + link
300
+ loop = asyncio.get_running_loop()
301
+
302
+ def audio_dl():
303
+ ydl_optssx = {
304
+ "format": "bestaudio/best",
305
+ "outtmpl": "downloads/%(id)s.%(ext)s",
306
+ "geo_bypass": True,
307
+ "nocheckcertificate": True,
308
+ "quiet": True,
309
+ "no_warnings": True,
310
+ }
311
+ x = yt_dlp.YoutubeDL(ydl_optssx)
312
+ info = x.extract_info(link, False)
313
+ xyz = os.path.join(
314
+ "downloads", f"{info['id']}.{info['ext']}"
315
+ )
316
+ if os.path.exists(xyz):
317
+ return xyz
318
+ x.download([link])
319
+ return xyz
320
+
321
+ def video_dl():
322
+ ydl_optssx = {
323
+ "format": "(bestvideo[height<=?720][width<=?1280][ext=mp4])+(bestaudio[ext=m4a])",
324
+ "outtmpl": "downloads/%(id)s.%(ext)s",
325
+ "geo_bypass": True,
326
+ "nocheckcertificate": True,
327
+ "quiet": True,
328
+ "no_warnings": True,
329
+ }
330
+ x = yt_dlp.YoutubeDL(ydl_optssx)
331
+ info = x.extract_info(link, False)
332
+ xyz = os.path.join(
333
+ "downloads", f"{info['id']}.{info['ext']}"
334
+ )
335
+ if os.path.exists(xyz):
336
+ return xyz
337
+ x.download([link])
338
+ return xyz
339
+
340
+ def song_video_dl():
341
+ formats = f"{format_id}+140"
342
+ fpath = f"downloads/{title}"
343
+ ydl_optssx = {
344
+ "format": formats,
345
+ "outtmpl": fpath,
346
+ "geo_bypass": True,
347
+ "nocheckcertificate": True,
348
+ "quiet": True,
349
+ "no_warnings": True,
350
+ "prefer_ffmpeg": True,
351
+ "merge_output_format": "mp4",
352
+ }
353
+ x = yt_dlp.YoutubeDL(ydl_optssx)
354
+ x.download([link])
355
+
356
+ def song_audio_dl():
357
+ fpath = f"downloads/{title}.%(ext)s"
358
+ ydl_optssx = {
359
+ "format": format_id,
360
+ "outtmpl": fpath,
361
+ "geo_bypass": True,
362
+ "nocheckcertificate": True,
363
+ "quiet": True,
364
+ "no_warnings": True,
365
+ "prefer_ffmpeg": True,
366
+ "postprocessors": [
367
+ {
368
+ "key": "FFmpegExtractAudio",
369
+ "preferredcodec": "mp3",
370
+ "preferredquality": "192",
371
+ }
372
+ ],
373
+ }
374
+ x = yt_dlp.YoutubeDL(ydl_optssx)
375
+ x.download([link])
376
+
377
+ if songvideo:
378
+ await loop.run_in_executor(None, song_video_dl)
379
+ fpath = f"downloads/{title}.mp4"
380
+ return fpath
381
+ elif songaudio:
382
+ await loop.run_in_executor(None, song_audio_dl)
383
+ fpath = f"downloads/{title}.mp3"
384
+ return fpath
385
+ elif video:
386
+ if await is_on_off(config.YTDOWNLOADER):
387
+ direct = True
388
+ downloaded_file = await loop.run_in_executor(
389
+ None, video_dl
390
+ )
391
+ else:
392
+ proc = await asyncio.create_subprocess_exec(
393
+ "yt-dlp",
394
+ "-g",
395
+ "-f",
396
+ "best[height<=?720][width<=?1280]",
397
+ f"{link}",
398
+ stdout=asyncio.subprocess.PIPE,
399
+ stderr=asyncio.subprocess.PIPE,
400
+ )
401
+ stdout, stderr = await proc.communicate()
402
+ if stdout:
403
+ downloaded_file = stdout.decode().split("\n")[0]
404
+ direct = None
405
+ else:
406
+ return
407
+ else:
408
+ direct = True
409
+ downloaded_file = await loop.run_in_executor(
410
+ None, audio_dl
411
+ )
412
+ return downloaded_file, direct
413
+ async def audio_video_url(self,
414
+ link: str,
415
+ mystic,
416
+ video: Union[bool, str] = None,
417
+ videoid: Union[bool, str] = None,
418
+ songaudio: Union[bool, str] = None,
419
+ songvideo: Union[bool, str] = None,
420
+ format_id: Union[bool, str] = None,
421
+ title: Union[bool, str] = None,
422
+ ) -> str:
423
+ if videoid:
424
+ video_id= link
425
+ loop = asyncio.get_running_loop()
426
+
427
+ def get_audio_url():
428
+ #yclient = InnerTube("ANDROID_TV")
429
+ yclient = InnerTube("ANDROID_LITE")
430
+ # Fetch the player data for the video
431
+ data = yclient.player(video_id)
432
+
433
+ # List of streams of the video
434
+ streams = data["streamingData"]["adaptiveFormats"]
435
+ for stream in streams:
436
+ if stream["mimeType"].find('video'):
437
+ audio_url=stream['url']
438
+ break
439
+ else:
440
+ continue
441
+ return audio_url
442
+ def get_video_url():
443
+
444
+ #yclient = InnerTube("ANDROID_TV")
445
+ yclient = InnerTube("ANDROID_LITE")
446
+
447
+
448
+ # Fetch the player data for the video
449
+ data = yclient.player(video_id)
450
+
451
+ # List of streams of the video
452
+ streams = data["streamingData"]["adaptiveFormats"]
453
+ for stream in streams:
454
+ if stream["mimeType"].find('audio'):
455
+ video_url=stream['url']
456
+ break
457
+ else:
458
+ continue
459
+ return video_url
460
+ video_url = await loop.run_in_executor(
461
+ None, get_video_url
462
+ )
463
+ audio_url = await loop.run_in_executor(
464
+ None, get_audio_url
465
+ )
466
+
467
+ return video_url, audio_url
YukkiMusic/platforms/YoutubeAPI/BS4scrapAPI.py ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from bs4 import BeautifulSoup
3
+ from urllib.request import urlopen
4
+ from urllib.parse import urlencode
5
+ import requests
6
+ import re
7
+ import json
8
+
9
+
10
+
11
+ async def extract_json_tranding(data):
12
+ # Join the list into a single string
13
+ combined_str = ''.join(data)
14
+
15
+ # Use regular expression to find the JSON data after 'ytInitialData = '
16
+ match = re.search(r'var ytInitialData\s*=\s*(\{.*\});', combined_str)
17
+
18
+ if match:
19
+ json_str = match.group(1) # Extract the JSON string
20
+ json_str = json_str.encode('utf-8').decode('unicode_escape')
21
+ try:
22
+ # Parse the JSON data
23
+ json_data = json.loads(json_str)
24
+ return json_data
25
+ except json.JSONDecodeError as e:
26
+ print("Error decoding JSON:", e)
27
+ return None
28
+ else:
29
+ print("No JSON data found.")
30
+ return None
31
+
32
+
33
+
34
+ async def search_videos(query):
35
+ searchresult_list=[]
36
+
37
+ final_query={'search_query':query,'sp':'EgIQAQ%253D%253D','persist_gl':'IN'}
38
+ param=urlencode(final_query)
39
+ url = urlopen(f'https://www.youtube.com/results?{param}').read()
40
+ soup = BeautifulSoup(url, 'lxml')
41
+ allscript = soup.findAll('script')
42
+ text = ''
43
+ for script in allscript:
44
+ if 'var ytInitialData' in str(script.contents):
45
+ text = str(script.contents)
46
+ else:
47
+ continue
48
+
49
+ json_data = await extract_json_tranding(text)
50
+ all_search_video = json_data.get('contents', {}).get(
51
+ 'twoColumnSearchResultsRenderer',
52
+ {}).get('primaryContents',
53
+ {}).get('sectionListRenderer',
54
+ {}).get('contents', [])[0].get('itemSectionRenderer',
55
+ {}).get('contents', [])
56
+
57
+ for video in all_search_video:
58
+ if video.get('videoRenderer', {}):
59
+ if video.get('videoRenderer',{}).get('descriptionSnippet',{}):
60
+ description=video['videoRenderer']['descriptionSnippet']['runs'][0]['text']
61
+ else:
62
+ description=''
63
+ details={
64
+ "id":video['videoRenderer']['videoId'],
65
+ "title":video['videoRenderer']['title']['runs'][0]['text'],
66
+ "thumbnails":video['videoRenderer']['thumbnail']['thumbnails'],
67
+ "description":description,
68
+ "publishedTime":video['videoRenderer']['publishedTimeText']['simpleText'] if video.get('videoRenderer',{}).get('publishedTimeText',{}) else '' ,
69
+ "length":video['videoRenderer']['lengthText']['simpleText'] if video.get('videoRenderer',{}).get('lengthText',{}) else '',
70
+ "views":video['videoRenderer']['viewCountText']['simpleText'] if video.get('videoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
71
+ "url":f"https://www.youtube.com{video['videoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
72
+ "short_views":video['videoRenderer']['shortViewCountText']['simpleText'] if video.get('videoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
73
+ "channelThumbnail":video['videoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('videoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
74
+ "channel":video['videoRenderer']['ownerText']['runs'][0]['text']
75
+
76
+ }
77
+ searchresult_list.append(details)
78
+ elif video.get('childVideoRenderer', {}):
79
+ if video.get('childVideoRenderer',{}).get('descriptionSnippet',{}):
80
+ description=video['childVideoRenderer']['descriptionSnippet']['runs'][0]['text']
81
+ else:
82
+ description=''
83
+ details={
84
+ "id":video['childVideoRenderer']['videoId'],
85
+ "title":video['childVideoRenderer']['title']['runs'][0]['text'],
86
+ "thumbnails":video['childVideoRenderer']['thumbnail']['thumbnails'],
87
+ "description":description,
88
+ "publishedTime":video['childVideoRenderer']['publishedTimeText']['simpleText'] if video.get('childVideoRenderer',{}).get('publishedTimeText',{}) else '' ,
89
+ "length":video['childVideoRenderer']['lengthText']['simpleText'] if video.get('childVideoRenderer',{}).get('lengthText',{}) else '',
90
+ "views":video['childVideoRenderer']['viewCountText']['simpleText'] if video.get('childVideoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
91
+ "url":f"https://www.youtube.com{video['childVideoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
92
+ "short_views":video['childVideoRenderer']['shortViewCountText']['simpleText'] if video.get('childVideoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
93
+ "channelThumbnail":video['childVideoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('childVideoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
94
+ "channel":video['childVideoRenderer']['ownerText']['runs'][0]['text']
95
+
96
+ }
97
+ searchresult_list.append(details)
98
+ elif video.get('gridVideoRenderer', {}):
99
+ if video.get('gridVideoRenderer',{}).get('descriptionSnippet',{}):
100
+ description=video['gridVideoRenderer']['descriptionSnippet']['runs'][0]['text']
101
+ else:
102
+ description=''
103
+ details={
104
+ "id":video['gridVideoRenderer']['videoId'],
105
+ "title":video['gridVideoRenderer']['title']['runs'][0]['text'],
106
+ "thumbnails":video['gridVideoRenderer']['thumbnail']['thumbnails'],
107
+ "description":description,
108
+ "publishedTime":video['gridVideoRenderer']['publishedTimeText']['simpleText'] if video.get('gridVideoRenderer',{}).get('publishedTimeText',{}) else '' ,
109
+ "length":video['gridVideoRenderer']['lengthText']['simpleText'] if video.get('gridVideoRenderer',{}).get('lengthText',{}) else '',
110
+ "views":video['gridVideoRenderer']['viewCountText']['simpleText'] if video.get('gridVideoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
111
+ "url":f"https://www.youtube.com{video['gridVideoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
112
+ "short_views":video['gridVideoRenderer']['shortViewCountText']['simpleText'] if video.get('gridVideoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
113
+ "channelThumbnail":video['gridVideoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('gridVideoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
114
+ "channel":video['gridVideoRenderer']['ownerText']['runs'][0]['text']
115
+
116
+ }
117
+ searchresult_list.append(details)
118
+ #print(url,searchresult_list)
119
+ return searchresult_list
120
+
121
+
122
+
123
+ async def tranding_videos():
124
+ tranding_list=[]
125
+ url = urlopen('https://www.youtube.com/feed/trending/?persist_gl=1&gl=IN').read()
126
+ soup = BeautifulSoup(url, 'lxml')
127
+ allscript = soup.findAll('script')
128
+ text = ''
129
+ for script in allscript:
130
+ if 'var ytInitialData' in str(script.contents):
131
+ text = str(script.contents)
132
+ else:
133
+ continue
134
+
135
+ json_data = await extract_json_tranding(text)
136
+
137
+ all_video = json_data.get('contents', {}).get(
138
+ 'twoColumnBrowseResultsRenderer',
139
+ {}).get('tabs', [])[0].get('tabRenderer', {}).get('content', {}).get(
140
+ 'sectionListRenderer',
141
+ {}).get('contents', [])[3].get('itemSectionRenderer', {}).get(
142
+ 'contents',
143
+ [])[0].get('shelfRenderer',
144
+ {}).get('content',
145
+ {}).get('expandedShelfContentsRenderer',
146
+ {}).get('items', [])
147
+ #"descriptions":video['videoRenderer']['descriptionSnippet']['runs'][0]['text'],
148
+ '''nextPageToken = json_data['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][1]['continuationItemRenderer']['continuationEndpoint']['continuationCommand']['token'] if json_data.get('contents', {}).get(
149
+ 'twoColumnSearchResultsRenderer',
150
+ {}).get('primaryContents',
151
+ {}).get('sectionListRenderer',
152
+ {}).get('contents', [])[1].get('continuationItemRenderer',{}).get('continuationEndpoint',{}).get('continuationCommand',{}).get('token','') else None
153
+ '''
154
+
155
+
156
+
157
+ for video in all_video:
158
+ if video.get('videoRenderer',{}).get('descriptionSnippet',{}):
159
+ description=video['videoRenderer']['descriptionSnippet']['runs'][0]['text']
160
+ else:
161
+ description=''
162
+ details={
163
+ "id":video['videoRenderer']['videoId'],
164
+ "title":video['videoRenderer']['title']['runs'][0]['text'],
165
+ "thumbnails":video['videoRenderer']['thumbnail']['thumbnails'],
166
+ "description":description,
167
+ "publishedTime":video['videoRenderer']['publishedTimeText']['simpleText'] if video.get('videoRenderer',{}).get('publishedTimeText',{}) else '' ,
168
+ "length":video['videoRenderer']['lengthText']['simpleText'] if video.get('videoRenderer',{}).get('lengthText',{}) else '',
169
+ "views":video['videoRenderer']['viewCountText']['simpleText'] if video.get('videoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
170
+ "url":f"https://www.youtube.com{video['videoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
171
+ "short_views":video['videoRenderer']['shortViewCountText']['simpleText'] if video.get('videoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
172
+ "channelThumbnail":video['videoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('videoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
173
+ "channel":video['videoRenderer']['ownerText']['runs'][0]['text']
174
+
175
+ }
176
+ tranding_list.append(details)
177
+ #print(tranding_list)
178
+ return tranding_list
179
+
YukkiMusic/platforms/YoutubeAPI/InnertubeAPI.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from urllib.request import urlopen
2
+ from urllib.parse import urlencode
3
+ import requests
4
+ import re
5
+ import json
6
+ import asyncio
7
+ import aiohttp
8
+ from .JSON_DATA import *
9
+
10
+ async def trending_with_post_api(query):
11
+ #res = requests.get('https://www.youtube.com/')
12
+ searchresult_list=[]
13
+
14
+ key_value ={
15
+ "now":"",
16
+ "music":"4gINGgt5dG1hX2NoYXJ0cw%3D%3D",
17
+ "gaming":"4gIcGhpnYW1pbmdfY29ycHVzX21vc3RfcG9wdWxhcg%3D%3D",
18
+ "movies":"4gIKGgh0cmFpbGVycw%3D%3D",
19
+ }
20
+
21
+ final_query={
22
+ "browseId": "FEtrending",
23
+ "params": key_value.get(query),
24
+ "context": {
25
+ "client": {
26
+ "hl":"en",
27
+ "gl":"IN",
28
+ "clientName": "WEB",
29
+ "clientVersion": "2.20230728.00.00"
30
+
31
+ }
32
+ }
33
+ }
34
+
35
+ async with aiohttp.ClientSession() as session:
36
+ async with session.post(
37
+ 'https://youtubei.googleapis.com/youtubei/v1/browse',
38
+ json=final_query) as response:
39
+
40
+ json_data= await response.text()
41
+ json_data=json.loads(json_data)
42
+
43
+
44
+ key_value_list=list(key_value.keys())
45
+ print(key_value_list,key_value_list.index(query))
46
+ all_search_video = json_data.get('contents', {}).get('twoColumnBrowseResultsRenderer',{}).get('tabs',[])[ key_value_list.index(query) ].get('tabRenderer',{}).get('content', {}).get('sectionListRenderer',{}).get('contents', [])[0].get('itemSectionRenderer',{}).get('contents', [])[0].get('shelfRenderer',{}).get('content',{}).get('expandedShelfContentsRenderer',{}).get('items',[])
47
+ #.get('twoColumnSearchResultsRenderer',{}).get('tabs',[])
48
+ #.get('sectionListRenderer',{}).get('contents', [])[0].get('itemSectionRenderer',{}).get('contents', [])[0].get('shelfRenderer',{}).get('content',{}).get('expandedShelfContentsRenderer',{}).get('items',[])
49
+ #return all_search_video
50
+ for video in all_search_video:
51
+ if video.get('videoRenderer', {}):
52
+ searchresult_list.append(JSON_videoRenderer_Formatter(video))
53
+
54
+ if query == 'now':
55
+ all_video_Now = json_data.get('contents', {}).get('twoColumnBrowseResultsRenderer',{}).get('tabs',[])[ key_value_list.index(query) ].get('tabRenderer',{}).get('content', {}).get('sectionListRenderer',{}).get('contents', [])[2].get('itemSectionRenderer',{}).get('contents', [])[0].get('shelfRenderer',{}).get('content',{}).get('expandedShelfContentsRenderer',{}).get('items',[])
56
+ for video in all_video_Now:
57
+ if video.get('videoRenderer', {}):
58
+ searchresult_list.append(JSON_videoRenderer_Formatter(video))
59
+
60
+ return searchresult_list
61
+
62
+
63
+
64
+
65
+ async def search_videos_with_post_api(query):
66
+ searchresult_list=[]
67
+ final_query={
68
+ "query": query,
69
+ "key":"AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
70
+ "context": {
71
+ "client": {
72
+ "clientName": "WEB",
73
+ "clientVersion": "2.20230728.00.00"
74
+ }
75
+ }
76
+ }
77
+ async with aiohttp.ClientSession() as session:
78
+ async with session.post(
79
+ 'https://youtubei.googleapis.com/youtubei/v1/search',
80
+ json=final_query) as response:
81
+
82
+ json_data= await response.text()
83
+ json_data=json.loads(json_data)
84
+
85
+ all_search_video = json_data.get('contents', {}).get(
86
+ 'twoColumnSearchResultsRenderer',
87
+ {}).get('primaryContents',
88
+ {}).get('sectionListRenderer',
89
+ {}).get('contents', [])[0].get('itemSectionRenderer',
90
+ {}).get('contents', [])
91
+
92
+ nextPageToken = json_data['contents']['twoColumnSearchResultsRenderer']['primaryContents']['sectionListRenderer']['contents'][1]['continuationItemRenderer']['continuationEndpoint']['continuationCommand']['token'] if json_data.get('contents', {}).get(
93
+ 'twoColumnSearchResultsRenderer',
94
+ {}).get('primaryContents',
95
+ {}).get('sectionListRenderer',
96
+ {}).get('contents', [])[1].get('continuationItemRenderer',{}).get('continuationEndpoint',{}).get('continuationCommand',{}).get('token','') else None
97
+
98
+
99
+
100
+ for video in all_search_video:
101
+ if video.get('videoRenderer', {}):
102
+ searchresult_list.append(JSON_videoRenderer_Formatter(video))
103
+
104
+ elif video.get('childVideoRenderer', {}):
105
+ searchresult_list.append(JSON_childVideoRenderer_Formatter(video))
106
+
107
+ elif video.get('gridVideoRenderer', {}):
108
+ searchresult_list.append(JSON_childVideoRenderer_Formatter(video))
109
+
110
+ #print(url,searchresult_list)
111
+ return searchresult_list, nextPageToken
112
+
113
+ async def search_scroll_videos_with_post_api(query):
114
+ searchresult_list=[]
115
+
116
+ final_query={
117
+ "continuation": query,
118
+ "key":"AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
119
+ "context": {
120
+ "client": {
121
+ "clientName": "WEB",
122
+ "clientVersion": "2.20230728.00.00"
123
+ }
124
+ }
125
+ }
126
+
127
+ async with aiohttp.ClientSession() as session:
128
+ async with session.post(
129
+ 'https://youtubei.googleapis.com/youtubei/v1/search',
130
+ json=final_query) as response:
131
+
132
+ json_data= await response.text()
133
+ json_data=json.loads(json_data)
134
+ #return json_data
135
+ all_search_video = json_data.get('onResponseReceivedCommands', [])[0].get(
136
+ 'appendContinuationItemsAction',
137
+ {}).get('continuationItems',
138
+ [])[0].get('itemSectionRenderer',
139
+ {}).get('contents', [])
140
+
141
+
142
+ nextPageToken =json_data['onResponseReceivedCommands'][0]['appendContinuationItemsAction']['continuationItems'][1]['continuationItemRenderer']['continuationEndpoint']['continuationCommand']['token'] if len(json_data.get('onResponseReceivedCommands', [])) > 0 and json_data.get('onResponseReceivedCommands', [])[0].get(
143
+ 'appendContinuationItemsAction',
144
+ {}).get('continuationItems',
145
+ [])[1].get('continuationItemRenderer',{}).get('continuationEndpoint',{}).get('continuationCommand',{}).get('token','') else None
146
+
147
+
148
+ for video in all_search_video:
149
+ if video.get('videoRenderer', {}):
150
+ searchresult_list.append(JSON_videoRenderer_Formatter(video))
151
+
152
+ elif video.get('childVideoRenderer', {}):
153
+ searchresult_list.append(JSON_childVideoRenderer_Formatter(video))
154
+
155
+ elif video.get('gridVideoRenderer', {}):
156
+ searchresult_list.append(JSON_childVideoRenderer_Formatter(video))
157
+
158
+ #print(url,searchresult_list)
159
+ return searchresult_list, nextPageToken
160
+
161
+
162
+
163
+ #####-------------RETURN VIDEO LIST WITH STREAMING URL BY VIDEO ID------######
164
+ async def search_player_data_with_post_api(query):
165
+ searchresult_list=[]
166
+
167
+
168
+ final_query={
169
+ "videoId": query,
170
+ "key":"AIzaSyAO_FJ2SlqU8Q4STEHLGCilw_Y9_11qcW8",
171
+ "context": {
172
+ "client": {
173
+ "clientName": "ANDROID_TV",
174
+ "clientVersion": "2.16.032"
175
+ }
176
+ }
177
+ }
178
+ async with aiohttp.ClientSession() as session:
179
+ async with session.post(
180
+ 'https://youtubei.googleapis.com/youtubei/v1/player',
181
+ json=final_query) as response:
182
+
183
+ json_data= await response.text()
184
+ json_data=json.loads(json_data)
185
+ #return json_data
186
+ all_formats_video = json_data.get('streamingData', {}).get(
187
+ 'formats',
188
+ [])
189
+ all_adaptive_formats_video = json_data.get('streamingData', {}).get(
190
+ 'adaptiveFormats',
191
+ [])
192
+ ''' video details content JSON DATA {} with key:value
193
+ demo data
194
+ {
195
+ "videoId": "k3g_WjLCsXM",
196
+ "title": "Sajni (Song): Arijit Singh, Ram Sampath | Laapataa Ladies | Aamir Khan Productions",
197
+ "lengthSeconds": "146",
198
+ "keywords": [
199
+ "sajni laapata ladies",
200
+ "sajni laapataa ladies",
201
+ "sajni"
202
+ ],
203
+ "channelId": "UCq-Fj5jknLsUf-MWSy4_brA",
204
+ "isOwnerViewing": false,
205
+ "shortDescription": "Presenting the Song \"Sajni\" from the upcoming film Laapataa Ladies. Sung by Arijit Singh, Composed by Ram Sampath and Penned by Prashant Pandey.\n\n#LaapataaLadies #Sajni #ArijitSingh #RamSampath\n\nJio Studios Presents \nAamir Khan Productions \"LAAPATAA LADIES\" \n\n♪Full Song Available on♪ \nJioSaavn: https://bit.ly/3SV0n0w\nSpotify: https://bit.ly/3wgICzV\nHungama: https://bit.ly/499FkNy\nApple Music: https://bit.ly/3SEqRlL\nAmazon Prime Music: https://bit.ly/3Uxi1Zv\nWynk: https://bit.ly/3uwyX7O\nYouTube Music: https://bit.ly/4bzkV5R\n\nSong Credits:\nSong Name: Sajni\nComposed By : Ram Sampath\nLyricist : Prashant Pandey\nSinger : Arijit Singh\nMusic Arranged & Produced by : Ram Sampath\nMusic Supervisor : Vrashal Chavan\nRecorded & Mixed at Omgrown Music, Mumbai by Amey Wadibhasme\nMastered by Gethin John at Hafod Mastering\nVocal Recordist : Sukanto Singha\nVocal Editor : Prithviraj Sarkar\nMusic Label: T-Series\n\nFilm Credits: \nDirected by Kiran Rao \nProduced by Aamir Khan, Kiran Rao & Jyoti Deshpande\nStarring : Nitanshi Goel, Pratibha Ranta, Sparsh Shrivastava, Ravi Kishan and Chhaya Kadam\nCo Stars : Bhaskar Jha, Durgesh Kumar, Geeta Aggarwal, Pankaj Sharma, Rachna Gupta, Abeer Jain, Kirti Jain, Daood Hussain, Pranjal Pateriya, Samarth Mohar, Satendra Soni, Ravi Kapadiya, Kishore Soni. \nOriginal Story : Biplab Goswami \nScreenplay & Dialogues : Sneha Desai \nAdditional Dialogues : Divyanidhi Sharma \nMusic : Ram Sampath \nLyricists : Swanand Kirkire, Prashant Pandey, Divyanidhi Sharma \nSingers: Shreya Ghoshal, Arijit Singh, Sukhwinder Singh, Sona Mohapatra\nDirector of Photography : Vikash Nowlakha\nEditor : Jabeen Merchant \nProduction Designer : Vikram Singh \nCostume Designer : Darshan Jalan \nCasting : Romil Jain \nSound Designer : Ayush Ahuja \nProduction Sound Mixer : Ravi Dev Singh \nMake Up Designer : Kamlesh Shinde \nHair Designer : Joyce Fernandez \n1st Assistant Director : Rakesh E. Nair \nLine Producer : Jaspal Dogra \nScript Supervisor : Mandira Roy \nDialect Coach : Sonu Anand \nDirector's Assistant : Pooja Kumar \nColorist : Michele Ricossa \nVisual Effects Studio : SM Rolling \nVFX DI Studio : Prasad Labs \nVisual Promotions : Just Right Studioz NX \nAKP Finance Team : Sharada Harihar, Aditya Shah, Huzvak Batliwala, Pankti Mehta, Tejasvi Gurav, Manisha Abhyankar\nFinancial Advisor : Bimal Parekh & Co \nExecutive Producers : Antara Banerjee & Naved Farooqui \nCo-Producers : B. Shrinivas Rao & Tanaji Dasgupta \n\nDownload Song Beat: https://bit.ly/3Cjh24R \n\n___________________________________\nEnjoy & stay connected with us!\n👉 Subscribe to T-Series: https://youtube.com/tseries\n👉 Like us on Facebook: https://www.facebook.com/tseriesmusic\n👉 Follow us on X: https://twitter.com/tseries\n👉 Follow us on Instagram: https://instagram.com/tseries.official",
206
+ "isCrawlable": true,
207
+ "thumbnail": {
208
+ "thumbnails": [
209
+ {
210
+ "url": "https://i.ytimg.com/vi/k3g_WjLCsXM/default.jpg",
211
+ "width": 120,
212
+ "height": 90
213
+ },
214
+ {
215
+ "url": "https://i.ytimg.com/vi/k3g_WjLCsXM/mqdefault.jpg",
216
+ "width": 320,
217
+ "height": 180
218
+ },
219
+ {
220
+ "url": "https://i.ytimg.com/vi/k3g_WjLCsXM/hqdefault.jpg",
221
+ "width": 480,
222
+ "height": 360
223
+ },
224
+ {
225
+ "url": "https://i.ytimg.com/vi/k3g_WjLCsXM/sddefault.jpg",
226
+ "width": 640,
227
+ "height": 480
228
+ }
229
+ ]
230
+ },
231
+ "allowRatings": true,
232
+ "viewCount": "70761818",
233
+ "author": "T-Series",
234
+ "isPrivate": false,
235
+ "isUnpluggedCorpus": false,
236
+ "isLiveContent": false
237
+ }'''
238
+
239
+ videodetails = json_data.get('videoDetails', {})
240
+
241
+
242
+ for video in all_formats_video:
243
+
244
+ searchresult_list.append(video)
245
+ for video in all_adaptive_formats_video:
246
+
247
+ searchresult_list.append(video)
248
+
249
+ #print(url,searchresult_list)
250
+ return searchresult_list, videodetails
YukkiMusic/platforms/YoutubeAPI/JSON_DATA.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ def JSON_gridVideoRenderer_Formatter(video):
2
+ if video.get('gridVideoRenderer',{}).get('descriptionSnippet',{}):
3
+ description=video['gridVideoRenderer']['descriptionSnippet']['runs'][0]['text']
4
+ else:
5
+ description=''
6
+
7
+ return{
8
+ "id":video['gridVideoRenderer']['videoId'],
9
+ "title":video['gridVideoRenderer']['title']['runs'][0]['text'],
10
+ "thumbnails":video['gridVideoRenderer']['thumbnail']['thumbnails'],
11
+ "description":description,
12
+ "publishedTime":video['gridVideoRenderer']['publishedTimeText']['simpleText'] if video.get('gridVideoRenderer',{}).get('publishedTimeText',{}) else '' ,
13
+ "length":video['gridVideoRenderer']['lengthText']['simpleText'] if video.get('gridVideoRenderer',{}).get('lengthText',{}) else '',
14
+ "views":video['gridVideoRenderer']['viewCountText']['simpleText'] if video.get('gridVideoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
15
+ "url":f"https://www.youtube.com{video['gridVideoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
16
+ "short_views":video['gridVideoRenderer']['shortViewCountText']['simpleText'] if video.get('gridVideoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
17
+ "channelThumbnail":video['gridVideoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('gridVideoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
18
+ "channel":video['gridVideoRenderer']['ownerText']['runs'][0]['text']
19
+ }
20
+
21
+ def JSON_childVideoRenderer_Formatter(video):
22
+ if video.get('childVideoRenderer',{}).get('descriptionSnippet',{}):
23
+ description=video['childVideoRenderer']['descriptionSnippet']['runs'][0]['text']
24
+ else:
25
+ description=''
26
+
27
+ return {
28
+ "id":video['childVideoRenderer']['videoId'],
29
+ "title":video['childVideoRenderer']['title']['runs'][0]['text'],
30
+ "thumbnails":video['childVideoRenderer']['thumbnail']['thumbnails'],
31
+ "description":description,
32
+ "publishedTime":video['childVideoRenderer']['publishedTimeText']['simpleText'] if video.get('childVideoRenderer',{}).get('publishedTimeText',{}) else '' ,
33
+ "length":video['childVideoRenderer']['lengthText']['simpleText'] if video.get('childVideoRenderer',{}).get('lengthText',{}) else '',
34
+ "views":video['childVideoRenderer']['viewCountText']['simpleText'] if video.get('childVideoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
35
+ "url":f"https://www.youtube.com{video['childVideoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
36
+ "short_views":video['childVideoRenderer']['shortViewCountText']['simpleText'] if video.get('childVideoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
37
+ "channelThumbnail":video['childVideoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('childVideoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
38
+ "channel":video['childVideoRenderer']['ownerText']['runs'][0]['text']
39
+ }
40
+
41
+ def JSON_videoRenderer_Formatter(video):
42
+ if video.get('videoRenderer',{}).get('descriptionSnippet',{}):
43
+ description=video['videoRenderer']['descriptionSnippet']['runs'][0]['text']
44
+ else:
45
+ description=''
46
+ return{
47
+ "id":video['videoRenderer']['videoId'],
48
+ "title":video['videoRenderer']['title']['runs'][0]['text'],
49
+ "thumbnails":video['videoRenderer']['thumbnail']['thumbnails'],
50
+ "description":description,
51
+ "publishedTime":video['videoRenderer']['publishedTimeText']['simpleText'] if video.get('videoRenderer',{}).get('publishedTimeText',{}) else '' ,
52
+ "length":video['videoRenderer']['lengthText']['simpleText'] if video.get('videoRenderer',{}).get('lengthText',{}) else '',
53
+ "views":video['videoRenderer']['viewCountText']['simpleText'] if video.get('videoRenderer',{}).get('viewCountText',{}).get('simpleText','') else '',
54
+ "url":f"https://www.youtube.com{video['videoRenderer']['navigationEndpoint']['commandMetadata']['webCommandMetadata']['url']}",
55
+ "short_views":video['videoRenderer']['shortViewCountText']['simpleText'] if video.get('videoRenderer',{}).get('shortViewCountText',{}).get('simpleText','') else '',
56
+ "channelThumbnail":video['videoRenderer']['channelThumbnailSupportedRenderers']['channelThumbnailWithLinkRenderer']['thumbnail']['thumbnails'][0]['url'] if video.get('videoRenderer',{}).get('channelThumbnailSupportedRenderers',{}) else '',
57
+ "channel":video['videoRenderer']['ownerText']['runs'][0]['text']
58
+ }
YukkiMusic/platforms/YoutubeAPI/__init__.py ADDED
File without changes
YukkiMusic/platforms/__init__.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from .Apple import AppleAPI
11
+ from .Carbon import CarbonAPI
12
+ from .Resso import RessoAPI
13
+ from .Soundcloud import SoundAPI
14
+ from .Spotify import SpotifyAPI
15
+ from .Telegram import TeleAPI
16
+ from .Youtube import YouTubeAPI
YukkiMusic/platforms/custom_dl.py ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import asyncio
2
+ import logging
3
+ from typing import Dict, Union
4
+ from YukkiMusic.core.userbot import work_loads
5
+ from pyrogram import Client, utils, raw
6
+ #from .file_properties import get_file_ids
7
+ from pyrogram.session import Session, Auth
8
+ from pyrogram.errors import AuthBytesInvalid
9
+ from pyrogram.file_id import FileId, FileType, ThumbnailSource
10
+ from pyrogram.types import Message
11
+
12
+
13
+ class ByteStreamer:
14
+
15
+ def __init__(self, client: Client):
16
+ self.clean_timer = 30 * 60
17
+ self.client: Client = client
18
+ self.cached_file_ids: Dict[str, FileId] = {}
19
+ asyncio.create_task(self.clean_cache())
20
+
21
+
22
+
23
+ async def generate_media_session(self, client: Client,
24
+ file_id: FileId) -> Session:
25
+ """
26
+ Generates the media session for the DC that contains the media file.
27
+ This is required for getting the bytes from Telegram servers.
28
+ """
29
+
30
+ media_session = client.media_sessions.get(file_id.dc_id, None)
31
+
32
+ if media_session is None:
33
+ if file_id.dc_id != await client.storage.dc_id():
34
+ media_session = Session(
35
+ client,
36
+ file_id.dc_id,
37
+ await Auth(client, file_id.dc_id, await
38
+ client.storage.test_mode()).create(),
39
+ await client.storage.test_mode(),
40
+ is_media=True,
41
+ )
42
+ await media_session.start()
43
+
44
+ for _ in range(6):
45
+ exported_auth = await client.invoke(
46
+ raw.functions.auth.ExportAuthorization(dc_id=file_id.dc_id))
47
+
48
+ try:
49
+ await media_session.invoke(
50
+ raw.functions.auth.ImportAuthorization(
51
+ id=exported_auth.id, bytes=exported_auth.bytes))
52
+ break
53
+ except AuthBytesInvalid:
54
+ logging.debug(
55
+ f"Invalid authorization bytes for DC {file_id.dc_id}")
56
+ continue
57
+ else:
58
+ await media_session.stop()
59
+ raise AuthBytesInvalid
60
+ else:
61
+ media_session = Session(
62
+ client,
63
+ file_id.dc_id,
64
+ await client.storage.auth_key(),
65
+ await client.storage.test_mode(),
66
+ is_media=True,
67
+ )
68
+ await media_session.start()
69
+ logging.debug(f"Created media session for DC {file_id.dc_id}")
70
+ client.media_sessions[file_id.dc_id] = media_session
71
+ else:
72
+ logging.debug(f"Using cached media session for DC {file_id.dc_id}")
73
+ return media_session
74
+
75
+ @staticmethod
76
+ async def get_location(
77
+ file_id: FileId
78
+ ) -> Union[
79
+ raw.types.InputPhotoFileLocation,
80
+ raw.types.InputDocumentFileLocation,
81
+ raw.types.InputPeerPhotoFileLocation,
82
+ ]:
83
+ """
84
+ Returns the file location for the media file.
85
+ """
86
+ file_type = file_id.file_type
87
+
88
+ if file_type == FileType.CHAT_PHOTO:
89
+ if file_id.chat_id > 0:
90
+ peer = raw.types.InputPeerUser(user_id=file_id.chat_id,
91
+ access_hash=file_id.chat_access_hash)
92
+ else:
93
+ if file_id.chat_access_hash == 0:
94
+ peer = raw.types.InputPeerChat(chat_id=-file_id.chat_id)
95
+ else:
96
+ peer = raw.types.InputPeerChannel(
97
+ channel_id=utils.get_channel_id(file_id.chat_id),
98
+ access_hash=file_id.chat_access_hash,
99
+ )
100
+
101
+ location = raw.types.InputPeerPhotoFileLocation(
102
+ peer=peer,
103
+ volume_id=file_id.volume_id,
104
+ local_id=file_id.local_id,
105
+ big=file_id.thumbnail_source == ThumbnailSource.CHAT_PHOTO_BIG,
106
+ )
107
+ elif file_type == FileType.PHOTO:
108
+ location = raw.types.InputPhotoFileLocation(
109
+ id=file_id.media_id,
110
+ access_hash=file_id.access_hash,
111
+ file_reference=file_id.file_reference,
112
+ thumb_size=file_id.thumbnail_size,
113
+ )
114
+ else:
115
+ location = raw.types.InputDocumentFileLocation(
116
+ id=file_id.media_id,
117
+ access_hash=file_id.access_hash,
118
+ file_reference=file_id.file_reference,
119
+ thumb_size=file_id.thumbnail_size,
120
+ )
121
+ return location
122
+
123
+ async def yield_file(
124
+ self,
125
+ file_id: FileId,
126
+ index: int,
127
+ offset: int,
128
+ first_part_cut: int,
129
+ last_part_cut: int,
130
+ part_count: int,
131
+ chunk_size: int,
132
+ ) -> Union[str, None]:
133
+
134
+ client = self.client
135
+ #work_loads[index] += 1
136
+ logging.debug(f"Starting to yielding file with client {index}.")
137
+ media_session = await self.generate_media_session(client, file_id)
138
+
139
+ current_part = 1
140
+
141
+ location = await self.get_location(file_id)
142
+
143
+ try:
144
+ r = await media_session.invoke(
145
+ raw.functions.upload.GetFile(location=location,
146
+ offset=offset,
147
+ limit=chunk_size), )
148
+ if isinstance(r, raw.types.upload.File):
149
+ while True:
150
+ chunk = r.bytes
151
+ if not chunk:
152
+ break
153
+ elif part_count == 1:
154
+ yield chunk[first_part_cut:last_part_cut]
155
+ elif current_part == 1:
156
+ yield chunk[first_part_cut:]
157
+ elif current_part == part_count:
158
+ yield chunk[:last_part_cut]
159
+ else:
160
+ yield chunk
161
+
162
+ current_part += 1
163
+ offset += chunk_size
164
+
165
+ if current_part > part_count:
166
+ break
167
+
168
+ r = await media_session.invoke(
169
+ raw.functions.upload.GetFile(location=location,
170
+ offset=offset,
171
+ limit=chunk_size), )
172
+ except (TimeoutError, AttributeError):
173
+ pass
174
+ finally:
175
+ logging.debug(f"Finished yielding file with {current_part} parts.")
176
+ #work_loads[index] -= 1
177
+
178
+ async def clean_cache(self) -> None:
179
+ """
180
+ function to clean the cache to reduce memory usage
181
+ """
182
+ while True:
183
+ await asyncio.sleep(self.clean_timer)
184
+ self.cached_file_ids.clear()
185
+ logging.debug("Cleaned the cache")
YukkiMusic/platforms/file_properties.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+ import logging
3
+ from datetime import datetime
4
+ from pyrogram import Client
5
+ from typing import Any, Optional
6
+
7
+ from pyrogram.enums import ParseMode, ChatType
8
+ from pyrogram.types import Message
9
+ from pyrogram.file_id import FileId
10
+ #-----------------------------------------------------
11
+
12
+
13
+
14
+
15
+ #------------------------------
16
+ def get_media_from_message(message: "Message") -> Any:
17
+ media_types = (
18
+ "audio",
19
+ "document",
20
+ "photo",
21
+ "sticker",
22
+ "animation",
23
+ "video",
24
+ "voice",
25
+ "video_note",
26
+ )
27
+ for attr in media_types:
28
+ media = getattr(message, attr, None)
29
+ if media:
30
+ return media
31
+
32
+
33
+ def get_media_file_size(m):
34
+ media = get_media_from_message(m)
35
+ return getattr(media, "file_size", "None")
36
+
37
+
38
+ def get_name(media_msg: Message | FileId) -> str:
39
+ if isinstance(media_msg, Message):
40
+ media = get_media_from_message(media_msg)
41
+ file_name = getattr(media, "file_name", "")
42
+
43
+ elif isinstance(media_msg, FileId):
44
+ file_name = getattr(media_msg, "file_name", "")
45
+
46
+ if not file_name:
47
+ if isinstance(media_msg, Message) and media_msg.media:
48
+ media_type = media_msg.media.value
49
+ elif media_msg.file_type:
50
+ media_type = media_msg.file_type.name.lower()
51
+ else:
52
+ media_type = "file"
53
+
54
+ formats = {
55
+ "photo": "jpg",
56
+ "audio": "mp3",
57
+ "voice": "ogg",
58
+ "video": "mp4",
59
+ "animation": "mp4",
60
+ "video_note": "mp4",
61
+ "sticker": "webp"
62
+ }
63
+
64
+ ext = formats.get(media_type)
65
+ ext = "." + ext if ext else ""
66
+
67
+ date = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
68
+ file_name = f"{media_type}-{date}{ext}"
69
+
70
+ return file_name
71
+
72
+
73
+ def get_file_info(message):
74
+ media = get_media_from_message(message)
75
+ """
76
+ //Used a single Liner Insted of this Block
77
+ if message.chat.type == ChatType.PRIVATE:
78
+ user_idx = message.from_user.id
79
+ else:
80
+ user_idx = message.chat.id
81
+ """
82
+
83
+ return {
84
+
85
+ "message_id": message.id,
86
+ "location": message.from_user.id if (message.chat.type == ChatType.PRIVATE) else message.chat.id,
87
+ "file": {
88
+ "file_id": getattr(media, "file_id", ""),
89
+ "file_unique_id": getattr(media, "file_unique_id", ""),
90
+ "file_name": get_name(message),
91
+ "file_size": getattr(media, "file_size", 0),
92
+ "mime_type": getattr(media, "mime_type", "None/unknown"),
93
+
94
+ },
95
+ }
96
+
97
+
98
+
YukkiMusic/plugins/__init__.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+ #
10
+
11
+ import glob
12
+ from os.path import dirname, isfile
13
+
14
+
15
+ def __list_all_modules():
16
+ work_dir = dirname(__file__)
17
+ mod_paths = glob.glob(work_dir + "/*/*.py")
18
+
19
+ all_modules = [
20
+ (((f.replace(work_dir, "")).replace("/", "."))[:-3])
21
+ for f in mod_paths
22
+ if isfile(f)
23
+ and f.endswith(".py")
24
+ and not f.endswith("__init__.py")
25
+ ]
26
+
27
+ return all_modules
28
+
29
+
30
+ ALL_MODULES = sorted(__list_all_modules())
31
+ __all__ = ALL_MODULES + ["ALL_MODULES"]
YukkiMusic/plugins/admins/auth.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS, adminlist
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.utils.database import (delete_authuser, get_authuser,
17
+ get_authuser_names,
18
+ save_authuser)
19
+ from YukkiMusic.utils.decorators import AdminActual, language
20
+ from YukkiMusic.utils.formatters import int_to_alpha
21
+
22
+ # Command
23
+ AUTH_COMMAND = get_command("AUTH_COMMAND")
24
+ UNAUTH_COMMAND = get_command("UNAUTH_COMMAND")
25
+ AUTHUSERS_COMMAND = get_command("AUTHUSERS_COMMAND")
26
+
27
+
28
+ @app.on_message(
29
+ filters.command(AUTH_COMMAND)
30
+ & filters.group
31
+ & ~BANNED_USERS
32
+ )
33
+ @AdminActual
34
+ async def auth(client, message: Message, _):
35
+ if not message.reply_to_message:
36
+ if len(message.command) != 2:
37
+ return await message.reply_text(_["general_1"])
38
+ user = message.text.split(None, 1)[1]
39
+ if "@" in user:
40
+ user = user.replace("@", "")
41
+ user = await app.get_users(user)
42
+ user_id = message.from_user.id
43
+ token = await int_to_alpha(user.id)
44
+ from_user_name = message.from_user.first_name
45
+ from_user_id = message.from_user.id
46
+ _check = await get_authuser_names(message.chat.id)
47
+ count = len(_check)
48
+ if int(count) == 20:
49
+ return await message.reply_text(_["auth_1"])
50
+ if token not in _check:
51
+ assis = {
52
+ "auth_user_id": user.id,
53
+ "auth_name": user.first_name,
54
+ "admin_id": from_user_id,
55
+ "admin_name": from_user_name,
56
+ }
57
+ get = adminlist.get(message.chat.id)
58
+ if get:
59
+ if user.id not in get:
60
+ get.append(user.id)
61
+ await save_authuser(message.chat.id, token, assis)
62
+ return await message.reply_text(_["auth_2"])
63
+ else:
64
+ await message.reply_text(_["auth_3"])
65
+ return
66
+ from_user_id = message.from_user.id
67
+ user_id = message.reply_to_message.from_user.id
68
+ user_name = message.reply_to_message.from_user.first_name
69
+ token = await int_to_alpha(user_id)
70
+ from_user_name = message.from_user.first_name
71
+ _check = await get_authuser_names(message.chat.id)
72
+ count = 0
73
+ for smex in _check:
74
+ count += 1
75
+ if int(count) == 20:
76
+ return await message.reply_text(_["auth_1"])
77
+ if token not in _check:
78
+ assis = {
79
+ "auth_user_id": user_id,
80
+ "auth_name": user_name,
81
+ "admin_id": from_user_id,
82
+ "admin_name": from_user_name,
83
+ }
84
+ get = adminlist.get(message.chat.id)
85
+ if get:
86
+ if user_id not in get:
87
+ get.append(user_id)
88
+ await save_authuser(message.chat.id, token, assis)
89
+ return await message.reply_text(_["auth_2"])
90
+ else:
91
+ await message.reply_text(_["auth_3"])
92
+
93
+
94
+ @app.on_message(
95
+ filters.command(UNAUTH_COMMAND)
96
+ & filters.group
97
+ & ~BANNED_USERS
98
+ )
99
+ @AdminActual
100
+ async def unauthusers(client, message: Message, _):
101
+ if not message.reply_to_message:
102
+ if len(message.command) != 2:
103
+ return await message.reply_text(_["general_1"])
104
+ user = message.text.split(None, 1)[1]
105
+ if "@" in user:
106
+ user = user.replace("@", "")
107
+ user = await app.get_users(user)
108
+ token = await int_to_alpha(user.id)
109
+ deleted = await delete_authuser(message.chat.id, token)
110
+ get = adminlist.get(message.chat.id)
111
+ if get:
112
+ if user.id in get:
113
+ get.remove(user.id)
114
+ if deleted:
115
+ return await message.reply_text(_["auth_4"])
116
+ else:
117
+ return await message.reply_text(_["auth_5"])
118
+ user_id = message.reply_to_message.from_user.id
119
+ token = await int_to_alpha(user_id)
120
+ deleted = await delete_authuser(message.chat.id, token)
121
+ get = adminlist.get(message.chat.id)
122
+ if get:
123
+ if user_id in get:
124
+ get.remove(user_id)
125
+ if deleted:
126
+ return await message.reply_text(_["auth_4"])
127
+ else:
128
+ return await message.reply_text(_["auth_5"])
129
+
130
+
131
+ @app.on_message(
132
+ filters.command(AUTHUSERS_COMMAND)
133
+ & filters.group
134
+ & ~BANNED_USERS
135
+ )
136
+ @language
137
+ async def authusers(client, message: Message, _):
138
+ _playlist = await get_authuser_names(message.chat.id)
139
+ if not _playlist:
140
+ return await message.reply_text(_["setting_5"])
141
+ else:
142
+ j = 0
143
+ mystic = await message.reply_text(_["auth_6"])
144
+ text = _["auth_7"]
145
+ for note in _playlist:
146
+ _note = await get_authuser(message.chat.id, note)
147
+ user_id = _note["auth_user_id"]
148
+ admin_id = _note["admin_id"]
149
+ admin_name = _note["admin_name"]
150
+ try:
151
+ user = await app.get_users(user_id)
152
+ user = user.first_name
153
+ j += 1
154
+ except Exception:
155
+ continue
156
+ text += f"{j}➤ {user}[`{user_id}`]\n"
157
+ text += f" {_['auth_8']} {admin_name}[`{admin_id}`]\n\n"
158
+ await mystic.delete()
159
+ await message.reply_text(text)
YukkiMusic/plugins/admins/callback.py ADDED
@@ -0,0 +1,444 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+
3
+ from pyrogram import filters
4
+ from pyrogram.types import CallbackQuery, InlineKeyboardMarkup
5
+
6
+ from config import (AUTO_DOWNLOADS_CLEAR, BANNED_USERS,
7
+ SOUNCLOUD_IMG_URL, STREAM_IMG_URL,
8
+ TELEGRAM_AUDIO_URL, TELEGRAM_VIDEO_URL, adminlist)
9
+ from YukkiMusic import YouTube, app
10
+ from YukkiMusic.core.call import Yukki
11
+ from YukkiMusic.misc import SUDOERS, db
12
+ from YukkiMusic.utils.database import (is_active_chat,
13
+ is_music_playing, is_muted,
14
+ is_nonadmin_chat, music_off,
15
+ music_on, mute_off, mute_on,
16
+ set_loop)
17
+ from YukkiMusic.utils.decorators.language import languageCB
18
+ from YukkiMusic.utils.formatters import seconds_to_min
19
+ from YukkiMusic.utils.inline.play import (panel_markup_1,
20
+ panel_markup_2,
21
+ panel_markup_3,
22
+ stream_markup,
23
+ telegram_markup)
24
+ from YukkiMusic.utils.stream.autoclear import auto_clean
25
+ from YukkiMusic.utils.thumbnails import gen_thumb
26
+
27
+ wrong = {}
28
+
29
+
30
+ @app.on_callback_query(filters.regex("PanelMarkup") & ~BANNED_USERS)
31
+ @languageCB
32
+ async def markup_panel(client, CallbackQuery: CallbackQuery, _):
33
+ await CallbackQuery.answer()
34
+ callback_data = CallbackQuery.data.strip()
35
+ callback_request = callback_data.split(None, 1)[1]
36
+ videoid, chat_id = callback_request.split("|")
37
+ chat_id = CallbackQuery.message.chat.id
38
+ buttons = panel_markup_1(_, videoid, chat_id)
39
+ try:
40
+ await CallbackQuery.edit_message_reply_markup(
41
+ reply_markup=InlineKeyboardMarkup(buttons)
42
+ )
43
+ except:
44
+ return
45
+ if chat_id not in wrong:
46
+ wrong[chat_id] = {}
47
+ wrong[chat_id][CallbackQuery.message.id] = False
48
+
49
+
50
+ @app.on_callback_query(filters.regex("MainMarkup") & ~BANNED_USERS)
51
+ @languageCB
52
+ async def del_back_playlist(client, CallbackQuery, _):
53
+ await CallbackQuery.answer()
54
+ callback_data = CallbackQuery.data.strip()
55
+ callback_request = callback_data.split(None, 1)[1]
56
+ videoid, chat_id = callback_request.split("|")
57
+ if videoid == str(None):
58
+ buttons = telegram_markup(_, chat_id)
59
+ else:
60
+ buttons = stream_markup(_, videoid, chat_id)
61
+ chat_id = CallbackQuery.message.chat.id
62
+ try:
63
+ await CallbackQuery.edit_message_reply_markup(
64
+ reply_markup=InlineKeyboardMarkup(buttons)
65
+ )
66
+ except:
67
+ return
68
+ if chat_id not in wrong:
69
+ wrong[chat_id] = {}
70
+ wrong[chat_id][CallbackQuery.message.message.id] = True
71
+
72
+
73
+ @app.on_callback_query(filters.regex("Pages") & ~BANNED_USERS)
74
+ @languageCB
75
+ async def del_back_playlist(client, CallbackQuery, _):
76
+ await CallbackQuery.answer()
77
+ callback_data = CallbackQuery.data.strip()
78
+ callback_request = callback_data.split(None, 1)[1]
79
+ state, pages, videoid, chat = callback_request.split("|")
80
+ chat_id = int(chat)
81
+ pages = int(pages)
82
+ if state == "Forw":
83
+ if pages == 0:
84
+ buttons = panel_markup_2(_, videoid, chat_id)
85
+ if pages == 2:
86
+ buttons = panel_markup_1(_, videoid, chat_id)
87
+ if pages == 1:
88
+ buttons = panel_markup_3(_, videoid, chat_id)
89
+ if state == "Back":
90
+ if pages == 2:
91
+ buttons = panel_markup_2(_, videoid, chat_id)
92
+ if pages == 1:
93
+ buttons = panel_markup_1(_, videoid, chat_id)
94
+ if pages == 0:
95
+ buttons = panel_markup_3(_, videoid, chat_id)
96
+ try:
97
+ await CallbackQuery.edit_message_reply_markup(
98
+ reply_markup=InlineKeyboardMarkup(buttons)
99
+ )
100
+ except:
101
+ return
102
+
103
+
104
+ downvote = {}
105
+ downvoters = {}
106
+
107
+
108
+ @app.on_callback_query(filters.regex("ADMIN") & ~BANNED_USERS)
109
+ @languageCB
110
+ async def del_back_playlist(client, CallbackQuery, _):
111
+ callback_data = CallbackQuery.data.strip()
112
+ callback_request = callback_data.split(None, 1)[1]
113
+ command, chat = callback_request.split("|")
114
+ chat_id = int(chat)
115
+ if not await is_active_chat(chat_id):
116
+ return await CallbackQuery.answer(
117
+ _["general_6"], show_alert=True
118
+ )
119
+ mention = CallbackQuery.from_user.mention
120
+ is_non_admin = await is_nonadmin_chat(
121
+ CallbackQuery.message.chat.id
122
+ )
123
+ if not is_non_admin:
124
+ if CallbackQuery.from_user.id not in SUDOERS:
125
+ admins = adminlist.get(CallbackQuery.message.chat.id)
126
+ if not admins:
127
+ return await CallbackQuery.answer(
128
+ _["admin_18"], show_alert=True
129
+ )
130
+ else:
131
+ if CallbackQuery.from_user.id not in admins:
132
+ return await CallbackQuery.answer(
133
+ _["admin_19"], show_alert=True
134
+ )
135
+ if command == "Pause":
136
+ if not await is_music_playing(chat_id):
137
+ return await CallbackQuery.answer(
138
+ _["admin_1"], show_alert=True
139
+ )
140
+ await CallbackQuery.answer()
141
+ await music_off(chat_id)
142
+ await Yukki.pause_stream(chat_id)
143
+ await CallbackQuery.message.reply_text(
144
+ _["admin_2"].format(mention)
145
+ )
146
+ elif command == "Resume":
147
+ if await is_music_playing(chat_id):
148
+ return await CallbackQuery.answer(
149
+ _["admin_3"], show_alert=True
150
+ )
151
+ await CallbackQuery.answer()
152
+ await music_on(chat_id)
153
+ await Yukki.resume_stream(chat_id)
154
+ await CallbackQuery.message.reply_text(
155
+ _["admin_4"].format(mention)
156
+ )
157
+ elif command == "Stop" or command == "End":
158
+ await CallbackQuery.answer()
159
+ await Yukki.stop_stream(chat_id)
160
+ await set_loop(chat_id, 0)
161
+ await CallbackQuery.message.reply_text(
162
+ _["admin_9"].format(mention)
163
+ )
164
+ elif command == "Mute":
165
+ if await is_muted(chat_id):
166
+ return await CallbackQuery.answer(
167
+ _["admin_5"], show_alert=True
168
+ )
169
+ await CallbackQuery.answer()
170
+ await mute_on(chat_id)
171
+ await Yukki.mute_stream(chat_id)
172
+ await CallbackQuery.message.reply_text(
173
+ _["admin_6"].format(mention)
174
+ )
175
+ elif command == "Unmute":
176
+ if not await is_muted(chat_id):
177
+ return await CallbackQuery.answer(
178
+ _["admin_7"], show_alert=True
179
+ )
180
+ await CallbackQuery.answer()
181
+ await mute_off(chat_id)
182
+ await Yukki.unmute_stream(chat_id)
183
+ await CallbackQuery.message.reply_text(
184
+ _["admin_8"].format(mention)
185
+ )
186
+ elif command == "Loop":
187
+ await CallbackQuery.answer()
188
+ await set_loop(chat_id, 3)
189
+ await CallbackQuery.message.reply_text(
190
+ _["admin_25"].format(mention, 3)
191
+ )
192
+ elif command == "Shuffle":
193
+ check = db.get(chat_id)
194
+ if not check:
195
+ return await CallbackQuery.answer(
196
+ _["admin_21"], show_alert=True
197
+ )
198
+ try:
199
+ popped = check.pop(0)
200
+ except:
201
+ return await CallbackQuery.answer(
202
+ _["admin_22"], show_alert=True
203
+ )
204
+ check = db.get(chat_id)
205
+ if not check:
206
+ check.insert(0, popped)
207
+ return await CallbackQuery.answer(
208
+ _["admin_22"], show_alert=True
209
+ )
210
+ await CallbackQuery.answer()
211
+ random.shuffle(check)
212
+ check.insert(0, popped)
213
+ await CallbackQuery.message.reply_text(
214
+ _["admin_23"].format(mention)
215
+ )
216
+ elif command == "Skip":
217
+ check = db.get(chat_id)
218
+ txt = f"Skipped by {mention}"
219
+ popped = None
220
+ try:
221
+ popped = check.pop(0)
222
+ if popped:
223
+ if AUTO_DOWNLOADS_CLEAR == str(True):
224
+ await auto_clean(popped)
225
+ if not check:
226
+ await CallbackQuery.edit_message_text(
227
+ f"Skipped by {mention}"
228
+ )
229
+ await CallbackQuery.message.reply_text(
230
+ _["admin_10"].format(mention)
231
+ )
232
+ try:
233
+ return await Yukki.stop_stream(chat_id)
234
+ except:
235
+ return
236
+ except:
237
+ try:
238
+ await CallbackQuery.edit_message_text(
239
+ f"Skipped by {mention}"
240
+ )
241
+ await CallbackQuery.message.reply_text(
242
+ _["admin_10"].format(mention)
243
+ )
244
+ return await Yukki.stop_stream(chat_id)
245
+ except:
246
+ return
247
+ await CallbackQuery.answer()
248
+ queued = check[0]["file"]
249
+ title = (check[0]["title"]).title()
250
+ user = check[0]["by"]
251
+ streamtype = check[0]["streamtype"]
252
+ videoid = check[0]["vidid"]
253
+ status = True if str(streamtype) == "video" else None
254
+ db[chat_id][0]["played"] = 0
255
+ if "live_" in queued:
256
+ n, link = await YouTube.video(videoid, True)
257
+ if n == 0:
258
+ return await CallbackQuery.message.reply_text(
259
+ _["admin_11"].format(title)
260
+ )
261
+ try:
262
+ await Yukki.skip_stream(chat_id, link, video=status)
263
+ except Exception:
264
+ return await CallbackQuery.message.reply_text(
265
+ _["call_9"]
266
+ )
267
+ button = telegram_markup(_, chat_id)
268
+ img = await gen_thumb(videoid)
269
+ run = await CallbackQuery.message.reply_photo(
270
+ photo=img,
271
+ caption=_["stream_1"].format(
272
+ user,
273
+ f"https://t.me/{app.username}?start=info_{videoid}",
274
+ ),
275
+ reply_markup=InlineKeyboardMarkup(button),
276
+ )
277
+ db[chat_id][0]["mystic"] = run
278
+ db[chat_id][0]["markup"] = "tg"
279
+ await CallbackQuery.edit_message_text(txt)
280
+ elif "vid_" in queued:
281
+ mystic = await CallbackQuery.message.reply_text(
282
+ _["call_10"], disable_web_page_preview=True
283
+ )
284
+ try:
285
+ file_path, direct = await YouTube.download(
286
+ videoid,
287
+ mystic,
288
+ videoid=True,
289
+ video=status,
290
+ )
291
+ except:
292
+ return await mystic.edit_text(_["call_9"])
293
+ try:
294
+ await Yukki.skip_stream(
295
+ chat_id, file_path, video=status
296
+ )
297
+ except Exception:
298
+ return await mystic.edit_text(_["call_9"])
299
+ button = stream_markup(_, videoid, chat_id)
300
+ img = await gen_thumb(videoid)
301
+ run = await CallbackQuery.message.reply_photo(
302
+ photo=img,
303
+ caption=_["stream_1"].format(
304
+ user,
305
+ f"https://t.me/{app.username}?start=info_{videoid}",
306
+ ),
307
+ reply_markup=InlineKeyboardMarkup(button),
308
+ )
309
+ db[chat_id][0]["mystic"] = run
310
+ db[chat_id][0]["markup"] = "stream"
311
+ await CallbackQuery.edit_message_text(txt)
312
+ await mystic.delete()
313
+ elif "index_" in queued:
314
+ try:
315
+ await Yukki.skip_stream(
316
+ chat_id, videoid, video=status
317
+ )
318
+ except Exception:
319
+ return await CallbackQuery.message.reply_text(
320
+ _["call_9"]
321
+ )
322
+ button = telegram_markup(_, chat_id)
323
+ run = await CallbackQuery.message.reply_photo(
324
+ photo=STREAM_IMG_URL,
325
+ caption=_["stream_2"].format(user),
326
+ reply_markup=InlineKeyboardMarkup(button),
327
+ )
328
+ db[chat_id][0]["mystic"] = run
329
+ db[chat_id][0]["markup"] = "tg"
330
+ await CallbackQuery.edit_message_text(txt)
331
+ else:
332
+ try:
333
+ await Yukki.skip_stream(chat_id, queued, video=status)
334
+ except Exception:
335
+ return await CallbackQuery.message.reply_text(
336
+ _["call_9"]
337
+ )
338
+ if videoid == "telegram":
339
+ button = telegram_markup(_, chat_id)
340
+ run = await CallbackQuery.message.reply_photo(
341
+ photo=TELEGRAM_AUDIO_URL
342
+ if str(streamtype) == "audio"
343
+ else TELEGRAM_VIDEO_URL,
344
+ caption=_["stream_3"].format(
345
+ title, check[0]["dur"], user
346
+ ),
347
+ reply_markup=InlineKeyboardMarkup(button),
348
+ )
349
+ db[chat_id][0]["mystic"] = run
350
+ db[chat_id][0]["markup"] = "tg"
351
+ elif videoid == "soundcloud":
352
+ button = telegram_markup(_, chat_id)
353
+ run = await CallbackQuery.message.reply_photo(
354
+ photo=SOUNCLOUD_IMG_URL
355
+ if str(streamtype) == "audio"
356
+ else TELEGRAM_VIDEO_URL,
357
+ caption=_["stream_3"].format(
358
+ title, check[0]["dur"], user
359
+ ),
360
+ reply_markup=InlineKeyboardMarkup(button),
361
+ )
362
+ db[chat_id][0]["mystic"] = run
363
+ db[chat_id][0]["markup"] = "tg"
364
+ else:
365
+ button = stream_markup(_, videoid, chat_id)
366
+ img = await gen_thumb(videoid)
367
+ run = await CallbackQuery.message.reply_photo(
368
+ photo=img,
369
+ caption=_["stream_1"].format(
370
+ user,
371
+ f"https://t.me/{app.username}?start=info_{videoid}",
372
+ ),
373
+ reply_markup=InlineKeyboardMarkup(button),
374
+ )
375
+ db[chat_id][0]["mystic"] = run
376
+ db[chat_id][0]["markup"] = "stream"
377
+ await CallbackQuery.edit_message_text(txt)
378
+ else:
379
+ playing = db.get(chat_id)
380
+ if not playing:
381
+ return await CallbackQuery.answer(
382
+ _["queue_2"], show_alert=True
383
+ )
384
+ duration_seconds = int(playing[0]["seconds"])
385
+ if duration_seconds == 0:
386
+ return await CallbackQuery.answer(
387
+ _["admin_30"], show_alert=True
388
+ )
389
+ file_path = playing[0]["file"]
390
+ if "index_" in file_path or "live_" in file_path:
391
+ return await CallbackQuery.answer(
392
+ _["admin_30"], show_alert=True
393
+ )
394
+ duration_played = int(playing[0]["played"])
395
+ if int(command) in [1, 2]:
396
+ duration_to_skip = 10
397
+ else:
398
+ duration_to_skip = 30
399
+ duration = playing[0]["dur"]
400
+ if int(command) in [1, 3]:
401
+ if (duration_played - duration_to_skip) <= 10:
402
+ bet = seconds_to_min(duration_played)
403
+ return await CallbackQuery.answer(
404
+ f"Bot is not able to seek due to total duration has been exceeded.\n\nCurrently played** {bet}** mins out of **{duration}** mins",
405
+ show_alert=True,
406
+ )
407
+ to_seek = duration_played - duration_to_skip + 1
408
+ else:
409
+ if (
410
+ duration_seconds
411
+ - (duration_played + duration_to_skip)
412
+ ) <= 10:
413
+ bet = seconds_to_min(duration_played)
414
+ return await CallbackQuery.answer(
415
+ f"Bot is not able to seek due to total duration has been exceeded.\n\nCurrently played** {bet}** mins out of **{duration}** mins",
416
+ show_alert=True,
417
+ )
418
+ to_seek = duration_played + duration_to_skip + 1
419
+ await CallbackQuery.answer()
420
+ mystic = await CallbackQuery.message.reply_text(_["admin_32"])
421
+ if "vid_" in file_path:
422
+ n, file_path = await YouTube.video(
423
+ playing[0]["vidid"], True
424
+ )
425
+ if n == 0:
426
+ return await mystic.edit_text(_["admin_30"])
427
+ try:
428
+ await Yukki.seek_stream(
429
+ chat_id,
430
+ file_path,
431
+ seconds_to_min(to_seek),
432
+ duration,
433
+ playing[0]["streamtype"],
434
+ )
435
+ except:
436
+ return await mystic.edit_text(_["admin_34"])
437
+ if int(command) in [1, 3]:
438
+ db[chat_id][0]["played"] -= duration_to_skip
439
+ else:
440
+ db[chat_id][0]["played"] += duration_to_skip
441
+ string = _["admin_33"].format(seconds_to_min(to_seek))
442
+ await mystic.edit_text(
443
+ f"{string}\n\nChanges done by: {mention}"
444
+ )
YukkiMusic/plugins/admins/loop.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.utils.database.memorydatabase import (get_loop,
17
+ set_loop)
18
+ from YukkiMusic.utils.decorators import AdminRightsCheck
19
+
20
+ # Commands
21
+ LOOP_COMMAND = get_command("LOOP_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(LOOP_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def admins(cli, message: Message, _, chat_id):
31
+ usage = _["admin_24"]
32
+ if len(message.command) != 2:
33
+ return await message.reply_text(usage)
34
+ state = message.text.split(None, 1)[1].strip()
35
+ if state.isnumeric():
36
+ state = int(state)
37
+ if 1 <= state <= 10:
38
+ got = await get_loop(chat_id)
39
+ if got != 0:
40
+ state = got + state
41
+ if int(state) > 10:
42
+ state = 10
43
+ await set_loop(chat_id, state)
44
+ return await message.reply_text(
45
+ _["admin_25"].format(
46
+ message.from_user.first_name, state
47
+ )
48
+ )
49
+ else:
50
+ return await message.reply_text(_["admin_26"])
51
+ elif state.lower() == "enable":
52
+ await set_loop(chat_id, 10)
53
+ return await message.reply_text(
54
+ _["admin_25"].format(message.from_user.first_name, 10)
55
+ )
56
+ elif state.lower() == "disable":
57
+ await set_loop(chat_id, 0)
58
+ return await message.reply_text(_["admin_27"])
59
+ else:
60
+ return await message.reply_text(usage)
YukkiMusic/plugins/admins/mute.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.core.call import Yukki
17
+ from YukkiMusic.utils.database import is_muted, mute_on
18
+ from YukkiMusic.utils.decorators import AdminRightsCheck
19
+
20
+ # Commands
21
+ MUTE_COMMAND = get_command("MUTE_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(MUTE_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def mute_admin(cli, message: Message, _, chat_id):
31
+ if not len(message.command) == 1 or message.reply_to_message:
32
+ return await message.reply_text(_["general_2"])
33
+ if await is_muted(chat_id):
34
+ return await message.reply_text(_["admin_5"])
35
+ await mute_on(chat_id)
36
+ await Yukki.mute_stream(chat_id)
37
+ await message.reply_text(
38
+ _["admin_6"].format(message.from_user.mention)
39
+ )
YukkiMusic/plugins/admins/pause.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.core.call import Yukki
17
+ from YukkiMusic.utils.database import is_music_playing, music_off
18
+ from YukkiMusic.utils.decorators import AdminRightsCheck
19
+
20
+ # Commands
21
+ PAUSE_COMMAND = get_command("PAUSE_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(PAUSE_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def pause_admin(cli, message: Message, _, chat_id):
31
+ if not len(message.command) == 1:
32
+ return await message.reply_text(_["general_2"])
33
+ if not await is_music_playing(chat_id):
34
+ return await message.reply_text(_["admin_1"])
35
+ await music_off(chat_id)
36
+ await Yukki.pause_stream(chat_id)
37
+ await message.reply_text(
38
+ _["admin_2"].format(message.from_user.mention)
39
+ )
YukkiMusic/plugins/admins/resume.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.core.call import Yukki
17
+ from YukkiMusic.utils.database import is_music_playing, music_on
18
+ from YukkiMusic.utils.decorators import AdminRightsCheck
19
+
20
+ # Commands
21
+ RESUME_COMMAND = get_command("RESUME_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(RESUME_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def resume_com(cli, message: Message, _, chat_id):
31
+ if not len(message.command) == 1:
32
+ return await message.reply_text(_["general_2"])
33
+ if await is_music_playing(chat_id):
34
+ return await message.reply_text(_["admin_3"])
35
+ await music_on(chat_id)
36
+ await Yukki.resume_stream(chat_id)
37
+ await message.reply_text(
38
+ _["admin_4"].format(message.from_user.mention)
39
+ )
YukkiMusic/plugins/admins/seek.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import YouTube, app
16
+ from YukkiMusic.core.call import Yukki
17
+ from YukkiMusic.misc import db
18
+ from YukkiMusic.utils import AdminRightsCheck, seconds_to_min
19
+
20
+ # Commands
21
+ SEEK_COMMAND = get_command("SEEK_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(SEEK_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def seek_comm(cli, message: Message, _, chat_id):
31
+ if len(message.command) == 1:
32
+ return await message.reply_text(_["admin_28"])
33
+ query = message.text.split(None, 1)[1].strip()
34
+ if not query.isnumeric():
35
+ return await message.reply_text(_["admin_29"])
36
+ playing = db.get(chat_id)
37
+ if not playing:
38
+ return await message.reply_text(_["queue_2"])
39
+ duration_seconds = int(playing[0]["seconds"])
40
+ if duration_seconds == 0:
41
+ return await message.reply_text(_["admin_30"])
42
+ file_path = playing[0]["file"]
43
+ if "index_" in file_path or "live_" in file_path:
44
+ return await message.reply_text(_["admin_30"])
45
+ duration_played = int(playing[0]["played"])
46
+ duration_to_skip = int(query)
47
+ duration = playing[0]["dur"]
48
+ if message.command[0][-2] == "c":
49
+ if (duration_played - duration_to_skip) <= 10:
50
+ return await message.reply_text(
51
+ _["admin_31"].format(
52
+ seconds_to_min(duration_played), duration
53
+ )
54
+ )
55
+ to_seek = duration_played - duration_to_skip + 1
56
+ else:
57
+ if (
58
+ duration_seconds - (duration_played + duration_to_skip)
59
+ ) <= 10:
60
+ return await message.reply_text(
61
+ _["admin_31"].format(
62
+ seconds_to_min(duration_played), duration
63
+ )
64
+ )
65
+ to_seek = duration_played + duration_to_skip + 1
66
+ mystic = await message.reply_text(_["admin_32"])
67
+ if "vid_" in file_path:
68
+ n, file_path = await YouTube.video(playing[0]["vidid"], True)
69
+ if n == 0:
70
+ return await message.reply_text(_["admin_30"])
71
+ try:
72
+ await Yukki.seek_stream(
73
+ chat_id,
74
+ file_path,
75
+ seconds_to_min(to_seek),
76
+ duration,
77
+ playing[0]["streamtype"],
78
+ )
79
+ except:
80
+ return await mystic.edit_text(_["admin_34"])
81
+ if message.command[0][-2] == "c":
82
+ db[chat_id][0]["played"] -= duration_to_skip
83
+ else:
84
+ db[chat_id][0]["played"] += duration_to_skip
85
+ await mystic.edit_text(
86
+ _["admin_33"].format(seconds_to_min(to_seek))
87
+ )
YukkiMusic/plugins/admins/shuffle.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import random
11
+
12
+ from pyrogram import filters
13
+ from pyrogram.types import Message
14
+
15
+ from config import BANNED_USERS
16
+ from strings import get_command
17
+ from YukkiMusic import app
18
+ from YukkiMusic.misc import db
19
+ from YukkiMusic.utils.decorators import AdminRightsCheck
20
+
21
+ # Commands
22
+ SHUFFLE_COMMAND = get_command("SHUFFLE_COMMAND")
23
+
24
+
25
+ @app.on_message(
26
+ filters.command(SHUFFLE_COMMAND)
27
+ & filters.group
28
+ & ~BANNED_USERS
29
+ )
30
+ @AdminRightsCheck
31
+ async def admins(Client, message: Message, _, chat_id):
32
+ if not len(message.command) == 1:
33
+ return await message.reply_text(_["general_2"])
34
+ check = db.get(chat_id)
35
+ if not check:
36
+ return await message.reply_text(_["admin_21"])
37
+ try:
38
+ popped = check.pop(0)
39
+ except:
40
+ return await message.reply_text(_["admin_22"])
41
+ check = db.get(chat_id)
42
+ if not check:
43
+ check.insert(0, popped)
44
+ return await message.reply_text(_["admin_22"])
45
+ random.shuffle(check)
46
+ check.insert(0, popped)
47
+ await message.reply_text(
48
+ _["admin_23"].format(message.from_user.first_name)
49
+ )
YukkiMusic/plugins/admins/skip.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import InlineKeyboardMarkup, Message
12
+
13
+ import config
14
+ from config import BANNED_USERS
15
+ from strings import get_command
16
+ from YukkiMusic import YouTube, app
17
+ from YukkiMusic.core.call import Yukki
18
+ from YukkiMusic.misc import db
19
+ from YukkiMusic.utils.database import get_loop
20
+ from YukkiMusic.utils.decorators import AdminRightsCheck
21
+ from YukkiMusic.utils.inline.play import (stream_markup,
22
+ telegram_markup)
23
+ from YukkiMusic.utils.stream.autoclear import auto_clean
24
+ from YukkiMusic.utils.thumbnails import gen_thumb
25
+
26
+ # Commands
27
+ SKIP_COMMAND = get_command("SKIP_COMMAND")
28
+
29
+
30
+ @app.on_message(
31
+ filters.command(SKIP_COMMAND)
32
+ & filters.group
33
+ & ~BANNED_USERS
34
+ )
35
+ @AdminRightsCheck
36
+ async def skip(cli, message: Message, _, chat_id):
37
+ if not len(message.command) < 2:
38
+ loop = await get_loop(chat_id)
39
+ if loop != 0:
40
+ return await message.reply_text(_["admin_12"])
41
+ state = message.text.split(None, 1)[1].strip()
42
+ if state.isnumeric():
43
+ state = int(state)
44
+ check = db.get(chat_id)
45
+ if check:
46
+ count = len(check)
47
+ if count > 2:
48
+ count = int(count - 1)
49
+ if 1 <= state <= count:
50
+ for x in range(state):
51
+ popped = None
52
+ try:
53
+ popped = check.pop(0)
54
+ except:
55
+ return await message.reply_text(
56
+ _["admin_16"]
57
+ )
58
+ if popped:
59
+ if (
60
+ config.AUTO_DOWNLOADS_CLEAR
61
+ == str(True)
62
+ ):
63
+ await auto_clean(popped)
64
+ if not check:
65
+ try:
66
+ await message.reply_text(
67
+ _["admin_10"].format(
68
+ message.from_user.first_name
69
+ )
70
+ )
71
+ await Yukki.stop_stream(chat_id)
72
+ except:
73
+ return
74
+ break
75
+ else:
76
+ return await message.reply_text(
77
+ _["admin_15"].format(count)
78
+ )
79
+ else:
80
+ return await message.reply_text(_["admin_14"])
81
+ else:
82
+ return await message.reply_text(_["queue_2"])
83
+ else:
84
+ return await message.reply_text(_["admin_13"])
85
+ else:
86
+ check = db.get(chat_id)
87
+ popped = None
88
+ try:
89
+ popped = check.pop(0)
90
+ if popped:
91
+ if config.AUTO_DOWNLOADS_CLEAR == str(True):
92
+ await auto_clean(popped)
93
+ if not check:
94
+ await message.reply_text(
95
+ _["admin_10"].format(message.from_user.first_name)
96
+ )
97
+ try:
98
+ return await Yukki.stop_stream(chat_id)
99
+ except:
100
+ return
101
+ except:
102
+ try:
103
+ await message.reply_text(
104
+ _["admin_10"].format(message.from_user.first_name)
105
+ )
106
+ return await Yukki.stop_stream(chat_id)
107
+ except:
108
+ return
109
+ queued = check[0]["file"]
110
+ title = (check[0]["title"]).title()
111
+ user = check[0]["by"]
112
+ streamtype = check[0]["streamtype"]
113
+ videoid = check[0]["vidid"]
114
+ status = True if str(streamtype) == "video" else None
115
+ if "live_" in queued:
116
+ n, link = await YouTube.video(videoid, True)
117
+ if n == 0:
118
+ return await message.reply_text(
119
+ _["admin_11"].format(title)
120
+ )
121
+ try:
122
+ await Yukki.skip_stream(chat_id, link, video=status)
123
+ except Exception:
124
+ return await message.reply_text(_["call_9"])
125
+ button = telegram_markup(_, chat_id)
126
+ img = await gen_thumb(videoid)
127
+ run = await message.reply_photo(
128
+ photo=img,
129
+ caption=_["stream_1"].format(
130
+ user,
131
+ f"https://t.me/{app.username}?start=info_{videoid}",
132
+ ),
133
+ reply_markup=InlineKeyboardMarkup(button),
134
+ )
135
+ db[chat_id][0]["mystic"] = run
136
+ db[chat_id][0]["markup"] = "tg"
137
+ elif "vid_" in queued:
138
+ mystic = await message.reply_text(
139
+ _["call_10"], disable_web_page_preview=True
140
+ )
141
+ try:
142
+ file_path, direct = await YouTube.download(
143
+ videoid,
144
+ mystic,
145
+ videoid=True,
146
+ video=status,
147
+ )
148
+ except:
149
+ return await mystic.edit_text(_["call_9"])
150
+ try:
151
+ await Yukki.skip_stream(chat_id, file_path, video=status)
152
+ except Exception:
153
+ return await mystic.edit_text(_["call_9"])
154
+ button = stream_markup(_, videoid, chat_id)
155
+ img = await gen_thumb(videoid)
156
+ run = await message.reply_photo(
157
+ photo=img,
158
+ caption=_["stream_1"].format(
159
+ user,
160
+ f"https://t.me/{app.username}?start=info_{videoid}",
161
+ ),
162
+ reply_markup=InlineKeyboardMarkup(button),
163
+ )
164
+ db[chat_id][0]["mystic"] = run
165
+ db[chat_id][0]["markup"] = "stream"
166
+ await mystic.delete()
167
+ elif "index_" in queued:
168
+ try:
169
+ await Yukki.skip_stream(chat_id, videoid, video=status)
170
+ except Exception:
171
+ return await message.reply_text(_["call_9"])
172
+ button = telegram_markup(_, chat_id)
173
+ run = await message.reply_photo(
174
+ photo=config.STREAM_IMG_URL,
175
+ caption=_["stream_2"].format(user),
176
+ reply_markup=InlineKeyboardMarkup(button),
177
+ )
178
+ db[chat_id][0]["mystic"] = run
179
+ db[chat_id][0]["markup"] = "tg"
180
+ else:
181
+ try:
182
+ await Yukki.skip_stream(chat_id, queued, video=status)
183
+ except Exception:
184
+ return await message.reply_text(_["call_9"])
185
+ if videoid == "telegram":
186
+ button = telegram_markup(_, chat_id)
187
+ run = await message.reply_photo(
188
+ photo=config.TELEGRAM_AUDIO_URL
189
+ if str(streamtype) == "audio"
190
+ else config.TELEGRAM_VIDEO_URL,
191
+ caption=_["stream_3"].format(
192
+ title, check[0]["dur"], user
193
+ ),
194
+ reply_markup=InlineKeyboardMarkup(button),
195
+ )
196
+ db[chat_id][0]["mystic"] = run
197
+ db[chat_id][0]["markup"] = "tg"
198
+ elif videoid == "soundcloud":
199
+ button = telegram_markup(_, chat_id)
200
+ run = await message.reply_photo(
201
+ photo=config.SOUNCLOUD_IMG_URL
202
+ if str(streamtype) == "audio"
203
+ else config.TELEGRAM_VIDEO_URL,
204
+ caption=_["stream_3"].format(
205
+ title, check[0]["dur"], user
206
+ ),
207
+ reply_markup=InlineKeyboardMarkup(button),
208
+ )
209
+ db[chat_id][0]["mystic"] = run
210
+ db[chat_id][0]["markup"] = "tg"
211
+ else:
212
+ button = stream_markup(_, videoid, chat_id)
213
+ img = await gen_thumb(videoid)
214
+ run = await message.reply_photo(
215
+ photo=img,
216
+ caption=_["stream_1"].format(
217
+ user,
218
+ f"https://t.me/{app.username}?start=info_{videoid}",
219
+ ),
220
+ reply_markup=InlineKeyboardMarkup(button),
221
+ )
222
+ db[chat_id][0]["mystic"] = run
223
+ db[chat_id][0]["markup"] = "stream"
YukkiMusic/plugins/admins/stop.py ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.core.call import Yukki
17
+ from YukkiMusic.utils.database import set_loop
18
+ from YukkiMusic.utils.decorators import AdminRightsCheck
19
+
20
+ # Commands
21
+ STOP_COMMAND = get_command("STOP_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(STOP_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def stop_music(cli, message: Message, _, chat_id):
31
+ if not len(message.command) == 1:
32
+ return await message.reply_text(_["general_2"])
33
+ await Yukki.stop_stream(chat_id)
34
+ await set_loop(chat_id, 0)
35
+ await message.reply_text(
36
+ _["admin_9"].format(message.from_user.mention)
37
+ )
YukkiMusic/plugins/admins/unmute.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.types import Message
12
+
13
+ from config import BANNED_USERS
14
+ from strings import get_command
15
+ from YukkiMusic import app
16
+ from YukkiMusic.core.call import Yukki
17
+ from YukkiMusic.utils.database import is_muted, mute_off
18
+ from YukkiMusic.utils.decorators import AdminRightsCheck
19
+
20
+ # Commands
21
+ UNMUTE_COMMAND = get_command("UNMUTE_COMMAND")
22
+
23
+
24
+ @app.on_message(
25
+ filters.command(UNMUTE_COMMAND)
26
+ & filters.group
27
+ & ~BANNED_USERS
28
+ )
29
+ @AdminRightsCheck
30
+ async def unmute_admin(Client, message: Message, _, chat_id):
31
+ if not len(message.command) == 1 or message.reply_to_message:
32
+ return await message.reply_text(_["general_2"])
33
+ if not await is_muted(chat_id):
34
+ return await message.reply_text(_["admin_7"])
35
+ await mute_off(chat_id)
36
+ await Yukki.unmute_stream(chat_id)
37
+ await message.reply_text(
38
+ _["admin_8"].format(message.from_user.mention)
39
+ )
YukkiMusic/plugins/bot/help.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+
11
+ from typing import Union
12
+
13
+ from pyrogram import filters, types
14
+ from pyrogram.types import InlineKeyboardMarkup, Message
15
+
16
+ from config import BANNED_USERS
17
+ from strings import get_command, get_string, helpers
18
+ from YukkiMusic import app
19
+ from YukkiMusic.misc import SUDOERS
20
+ from YukkiMusic.utils import help_pannel
21
+ from YukkiMusic.utils.database import get_lang, is_commanddelete_on
22
+ from YukkiMusic.utils.decorators.language import (LanguageStart,
23
+ languageCB)
24
+ from YukkiMusic.utils.inline.help import (help_back_markup,
25
+ private_help_panel)
26
+
27
+ ### Command
28
+ HELP_COMMAND = get_command("HELP_COMMAND")
29
+
30
+
31
+ @app.on_message(
32
+ filters.command(HELP_COMMAND)
33
+ & filters.private
34
+ & ~BANNED_USERS
35
+ )
36
+ @app.on_callback_query(
37
+ filters.regex("settings_back_helper") & ~BANNED_USERS
38
+ )
39
+ async def helper_private(
40
+ client: app, update: Union[types.Message, types.CallbackQuery]
41
+ ):
42
+ is_callback = isinstance(update, types.CallbackQuery)
43
+ if is_callback:
44
+ try:
45
+ await update.answer()
46
+ except:
47
+ pass
48
+ chat_id = update.message.chat.id
49
+ language = await get_lang(chat_id)
50
+ _ = get_string(language)
51
+ keyboard = help_pannel(_, True)
52
+ if update.message.photo:
53
+ await update.message.delete()
54
+ await update.message.reply_text(
55
+ _["help_1"], reply_markup=keyboard
56
+ )
57
+ else:
58
+ await update.edit_message_text(
59
+ _["help_1"], reply_markup=keyboard
60
+ )
61
+ else:
62
+ chat_id = update.chat.id
63
+ if await is_commanddelete_on(update.chat.id):
64
+ try:
65
+ await update.delete()
66
+ except:
67
+ pass
68
+ language = await get_lang(chat_id)
69
+ _ = get_string(language)
70
+ keyboard = help_pannel(_)
71
+ await update.reply_text(_["help_1"], reply_markup=keyboard)
72
+
73
+
74
+ @app.on_message(
75
+ filters.command(HELP_COMMAND)
76
+ & filters.group
77
+ & ~BANNED_USERS
78
+ )
79
+ @LanguageStart
80
+ async def help_com_group(client, message: Message, _):
81
+ keyboard = private_help_panel(_)
82
+ await message.reply_text(
83
+ _["help_2"], reply_markup=InlineKeyboardMarkup(keyboard)
84
+ )
85
+
86
+
87
+ @app.on_callback_query(filters.regex("help_callback") & ~BANNED_USERS)
88
+ @languageCB
89
+ async def helper_cb(client, CallbackQuery, _):
90
+ callback_data = CallbackQuery.data.strip()
91
+ cb = callback_data.split(None, 1)[1]
92
+ keyboard = help_back_markup(_)
93
+ if cb == "hb5":
94
+ if CallbackQuery.from_user.id not in SUDOERS:
95
+ return await CallbackQuery.answer(
96
+ "Only for Sudo Users", show_alert=True
97
+ )
98
+ else:
99
+ await CallbackQuery.edit_message_text(
100
+ helpers.HELP_5, reply_markup=keyboard
101
+ )
102
+ return await CallbackQuery.answer()
103
+ try:
104
+ await CallbackQuery.answer()
105
+ except:
106
+ pass
107
+ if cb == "hb1":
108
+ await CallbackQuery.edit_message_text(
109
+ helpers.HELP_1, reply_markup=keyboard
110
+ )
111
+ elif cb == "hb2":
112
+ await CallbackQuery.edit_message_text(
113
+ helpers.HELP_2, reply_markup=keyboard
114
+ )
115
+ elif cb == "hb3":
116
+ await CallbackQuery.edit_message_text(
117
+ helpers.HELP_3, reply_markup=keyboard
118
+ )
119
+ elif cb == "hb4":
120
+ await CallbackQuery.edit_message_text(
121
+ helpers.HELP_4, reply_markup=keyboard
122
+ )
YukkiMusic/plugins/bot/inline.py ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram.types import (InlineKeyboardButton,
11
+ InlineKeyboardMarkup,
12
+ InlineQueryResultPhoto)
13
+ from youtubesearchpython.__future__ import VideosSearch
14
+
15
+ from config import BANNED_USERS, MUSIC_BOT_NAME
16
+ from YukkiMusic import app
17
+ from YukkiMusic.utils.inlinequery import answer
18
+
19
+
20
+ @app.on_inline_query(~BANNED_USERS)
21
+ async def inline_query_handler(client, query):
22
+ text = query.query.strip().lower()
23
+ answers = []
24
+ if text.strip() == "":
25
+ try:
26
+ await client.answer_inline_query(
27
+ query.id, results=answer, cache_time=10
28
+ )
29
+ except:
30
+ return
31
+ else:
32
+ a = VideosSearch(text, limit=20)
33
+ result = (await a.next()).get("result")
34
+ for x in range(15):
35
+ title = (result[x]["title"]).title()
36
+ duration = result[x]["duration"]
37
+ views = result[x]["viewCount"]["short"]
38
+ thumbnail = result[x]["thumbnails"][0]["url"].split("?")[
39
+ 0
40
+ ]
41
+ channellink = result[x]["channel"]["link"]
42
+ channel = result[x]["channel"]["name"]
43
+ link = result[x]["link"]
44
+ published = result[x]["publishedTime"]
45
+ description = f"{views} | {duration} Mins | {channel} | {published}"
46
+ buttons = InlineKeyboardMarkup(
47
+ [
48
+ [
49
+ InlineKeyboardButton(
50
+ text="🎥 Watch on Youtube",
51
+ url=link,
52
+ )
53
+ ],
54
+ ]
55
+ )
56
+ searched_text = f"""
57
+ ❇️**Title:** [{title}]({link})
58
+
59
+ ⏳**Duration:** {duration} Mins
60
+ 👀**Views:** `{views}`
61
+ ⏰**Published Time:** {published}
62
+ 🎥**Channel Name:** {channel}
63
+ 📎**Channel Link:** [Visit From Here]({channellink})
64
+
65
+ __Reply with /play on this searched message to stream it on voice chat.__
66
+
67
+ ⚡️ ** Inline Search By {MUSIC_BOT_NAME} **"""
68
+ answers.append(
69
+ InlineQueryResultPhoto(
70
+ photo_url=thumbnail,
71
+ title=title,
72
+ thumb_url=thumbnail,
73
+ description=description,
74
+ caption=searched_text,
75
+ reply_markup=buttons,
76
+ )
77
+ )
78
+ try:
79
+ return await client.answer_inline_query(
80
+ query.id, results=answers
81
+ )
82
+ except:
83
+ return
YukkiMusic/plugins/bot/settings.py ADDED
@@ -0,0 +1,568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ from pyrogram import filters
11
+ from pyrogram.errors import MessageNotModified
12
+ from pyrogram.types import (CallbackQuery, InlineKeyboardButton,
13
+ InlineKeyboardMarkup, Message)
14
+
15
+ from config import (BANNED_USERS, CLEANMODE_DELETE_MINS,
16
+ MUSIC_BOT_NAME, OWNER_ID)
17
+ from strings import get_command
18
+ from YukkiMusic import app
19
+ from YukkiMusic.utils.database import (add_nonadmin_chat,
20
+ cleanmode_off, cleanmode_on,
21
+ commanddelete_off,
22
+ commanddelete_on,
23
+ get_aud_bit_name, get_authuser,
24
+ get_authuser_names,
25
+ get_playmode, get_playtype,
26
+ get_vid_bit_name,
27
+ is_cleanmode_on,
28
+ is_commanddelete_on,
29
+ is_nonadmin_chat,
30
+ is_suggestion,
31
+ remove_nonadmin_chat,
32
+ save_audio_bitrate,
33
+ save_video_bitrate,
34
+ set_playmode, set_playtype,
35
+ suggestion_off, suggestion_on)
36
+ from YukkiMusic.utils.decorators.admins import ActualAdminCB
37
+ from YukkiMusic.utils.decorators.language import language, languageCB
38
+ from YukkiMusic.utils.inline.settings import (
39
+ audio_quality_markup, auth_users_markup,
40
+ cleanmode_settings_markup, playmode_users_markup, setting_markup,
41
+ video_quality_markup)
42
+ from YukkiMusic.utils.inline.start import private_panel
43
+
44
+ ### Command
45
+ SETTINGS_COMMAND = get_command("SETTINGS_COMMAND")
46
+
47
+
48
+ @app.on_message(
49
+ filters.command(SETTINGS_COMMAND)
50
+ & filters.group
51
+ & ~BANNED_USERS
52
+ )
53
+ @language
54
+ async def settings_mar(client, message: Message, _):
55
+ buttons = setting_markup(_)
56
+ await message.reply_text(
57
+ _["setting_1"].format(message.chat.title, message.chat.id),
58
+ reply_markup=InlineKeyboardMarkup(buttons),
59
+ )
60
+
61
+
62
+ @app.on_callback_query(
63
+ filters.regex("settings_helper") & ~BANNED_USERS
64
+ )
65
+ @languageCB
66
+ async def settings_cb(client, CallbackQuery, _):
67
+ try:
68
+ await CallbackQuery.answer(_["set_cb_8"])
69
+ except:
70
+ pass
71
+ buttons = setting_markup(_)
72
+ return await CallbackQuery.edit_message_text(
73
+ _["setting_1"].format(
74
+ CallbackQuery.message.chat.title,
75
+ CallbackQuery.message.chat.id,
76
+ ),
77
+ reply_markup=InlineKeyboardMarkup(buttons),
78
+ )
79
+
80
+
81
+ @app.on_callback_query(
82
+ filters.regex("settingsback_helper") & ~BANNED_USERS
83
+ )
84
+ @languageCB
85
+ async def settings_back_markup(
86
+ client, CallbackQuery: CallbackQuery, _
87
+ ):
88
+ try:
89
+ await CallbackQuery.answer()
90
+ except:
91
+ pass
92
+ if CallbackQuery.message.chat.type == "private":
93
+ try:
94
+ await app.resolve_peer(OWNER_ID[0])
95
+ OWNER = OWNER_ID[0]
96
+ except:
97
+ OWNER = None
98
+ buttons = private_panel(_, app.username, OWNER)
99
+ return await CallbackQuery.edit_message_text(
100
+ _["start_2"].format(MUSIC_BOT_NAME),
101
+ reply_markup=InlineKeyboardMarkup(buttons),
102
+ )
103
+ else:
104
+ buttons = setting_markup(_)
105
+ return await CallbackQuery.edit_message_reply_markup(
106
+ reply_markup=InlineKeyboardMarkup(buttons)
107
+ )
108
+
109
+
110
+ ## Audio and Video Quality
111
+ async def gen_buttons_aud(_, aud):
112
+ if aud == "High":
113
+ buttons = audio_quality_markup(_, high=True)
114
+ elif aud == "Medium":
115
+ buttons = audio_quality_markup(_, medium=True)
116
+ elif aud == "Low":
117
+ buttons = audio_quality_markup(_, low=True)
118
+ return buttons
119
+
120
+
121
+ async def gen_buttons_vid(_, aud):
122
+ if aud == "High":
123
+ buttons = video_quality_markup(_, high=True)
124
+ elif aud == "Medium":
125
+ buttons = video_quality_markup(_, medium=True)
126
+ elif aud == "Low":
127
+ buttons = video_quality_markup(_, low=True)
128
+ return buttons
129
+
130
+
131
+ # without admin rights
132
+
133
+
134
+ @app.on_callback_query(
135
+ filters.regex(
136
+ pattern=r"^(SEARCHANSWER|PLAYMODEANSWER|PLAYTYPEANSWER|AUTHANSWER|CMANSWER|COMMANDANSWER|SUGGANSWER|CM|AQ|VQ|PM|AU)$"
137
+ )
138
+ & ~BANNED_USERS
139
+ )
140
+ @languageCB
141
+ async def without_Admin_rights(client, CallbackQuery, _):
142
+ command = CallbackQuery.matches[0].group(1)
143
+ if command == "SEARCHANSWER":
144
+ try:
145
+ return await CallbackQuery.answer(
146
+ _["setting_3"], show_alert=True
147
+ )
148
+ except:
149
+ return
150
+ if command == "PLAYMODEANSWER":
151
+ try:
152
+ return await CallbackQuery.answer(
153
+ _["setting_10"], show_alert=True
154
+ )
155
+ except:
156
+ return
157
+ if command == "PLAYTYPEANSWER":
158
+ try:
159
+ return await CallbackQuery.answer(
160
+ _["setting_11"], show_alert=True
161
+ )
162
+ except:
163
+ return
164
+ if command == "AUTHANSWER":
165
+ try:
166
+ return await CallbackQuery.answer(
167
+ _["setting_4"], show_alert=True
168
+ )
169
+ except:
170
+ return
171
+ if command == "CMANSWER":
172
+ try:
173
+ return await CallbackQuery.answer(
174
+ _["setting_9"].format(CLEANMODE_DELETE_MINS),
175
+ show_alert=True,
176
+ )
177
+ except:
178
+ return
179
+ if command == "COMMANDANSWER":
180
+ try:
181
+ return await CallbackQuery.answer(
182
+ _["setting_14"], show_alert=True
183
+ )
184
+ except:
185
+ return
186
+ if command == "SUGGANSWER":
187
+ try:
188
+ return await CallbackQuery.answer(
189
+ _["setting_16"], show_alert=True
190
+ )
191
+ except:
192
+ return
193
+ if command == "CM":
194
+ try:
195
+ await CallbackQuery.answer(_["set_cb_5"], show_alert=True)
196
+ except:
197
+ pass
198
+ sta = None
199
+ cle = None
200
+ if await is_cleanmode_on(CallbackQuery.message.chat.id):
201
+ cle = True
202
+ if await is_commanddelete_on(CallbackQuery.message.chat.id):
203
+ sta = True
204
+ sug = None
205
+ if await is_suggestion(CallbackQuery.message.chat.id):
206
+ sug = True
207
+ buttons = cleanmode_settings_markup(
208
+ _, status=cle, dels=sta, sug=sug
209
+ )
210
+ if command == "AQ":
211
+ try:
212
+ await CallbackQuery.answer(_["set_cb_1"], show_alert=True)
213
+ except:
214
+ pass
215
+ aud = await get_aud_bit_name(CallbackQuery.message.chat.id)
216
+ buttons = await gen_buttons_aud(_, aud)
217
+ if command == "VQ":
218
+ try:
219
+ await CallbackQuery.answer(_["set_cb_2"], show_alert=True)
220
+ except:
221
+ pass
222
+ aud = await get_vid_bit_name(CallbackQuery.message.chat.id)
223
+ buttons = await gen_buttons_vid(_, aud)
224
+ if command == "PM":
225
+ try:
226
+ await CallbackQuery.answer(_["set_cb_4"], show_alert=True)
227
+ except:
228
+ pass
229
+ playmode = await get_playmode(CallbackQuery.message.chat.id)
230
+ if playmode == "Direct":
231
+ Direct = True
232
+ else:
233
+ Direct = None
234
+ is_non_admin = await is_nonadmin_chat(
235
+ CallbackQuery.message.chat.id
236
+ )
237
+ if not is_non_admin:
238
+ Group = True
239
+ else:
240
+ Group = None
241
+ playty = await get_playtype(CallbackQuery.message.chat.id)
242
+ if playty == "Everyone":
243
+ Playtype = None
244
+ else:
245
+ Playtype = True
246
+ buttons = playmode_users_markup(_, Direct, Group, Playtype)
247
+ if command == "AU":
248
+ try:
249
+ await CallbackQuery.answer(_["set_cb_3"], show_alert=True)
250
+ except:
251
+ pass
252
+ is_non_admin = await is_nonadmin_chat(
253
+ CallbackQuery.message.chat.id
254
+ )
255
+ if not is_non_admin:
256
+ buttons = auth_users_markup(_, True)
257
+ else:
258
+ buttons = auth_users_markup(_)
259
+ try:
260
+ return await CallbackQuery.edit_message_reply_markup(
261
+ reply_markup=InlineKeyboardMarkup(buttons)
262
+ )
263
+ except MessageNotModified:
264
+ return
265
+
266
+
267
+ # Audio Video Quality
268
+
269
+
270
+ @app.on_callback_query(
271
+ filters.regex(pattern=r"^(LQA|MQA|HQA|LQV|MQV|HQV)$")
272
+ & ~BANNED_USERS
273
+ )
274
+ @ActualAdminCB
275
+ async def aud_vid_cb(client, CallbackQuery, _):
276
+ command = CallbackQuery.matches[0].group(1)
277
+ try:
278
+ await CallbackQuery.answer(_["set_cb_6"], show_alert=True)
279
+ except:
280
+ pass
281
+ if command == "LQA":
282
+ await save_audio_bitrate(CallbackQuery.message.chat.id, "Low")
283
+ buttons = audio_quality_markup(_, low=True)
284
+ if command == "MQA":
285
+ await save_audio_bitrate(
286
+ CallbackQuery.message.chat.id, "Medium"
287
+ )
288
+ buttons = audio_quality_markup(_, medium=True)
289
+ if command == "HQA":
290
+ await save_audio_bitrate(
291
+ CallbackQuery.message.chat.id, "High"
292
+ )
293
+ buttons = audio_quality_markup(_, high=True)
294
+ if command == "LQV":
295
+ await save_video_bitrate(CallbackQuery.message.chat.id, "Low")
296
+ buttons = video_quality_markup(_, low=True)
297
+ if command == "MQV":
298
+ await save_video_bitrate(
299
+ CallbackQuery.message.chat.id, "Medium"
300
+ )
301
+ buttons = video_quality_markup(_, medium=True)
302
+ if command == "HQV":
303
+ await save_video_bitrate(
304
+ CallbackQuery.message.chat.id, "High"
305
+ )
306
+ buttons = video_quality_markup(_, high=True)
307
+ try:
308
+ return await CallbackQuery.edit_message_reply_markup(
309
+ reply_markup=InlineKeyboardMarkup(buttons)
310
+ )
311
+ except MessageNotModified:
312
+ return
313
+
314
+
315
+ # Play Mode Settings
316
+ @app.on_callback_query(
317
+ filters.regex(
318
+ pattern=r"^(|MODECHANGE|CHANNELMODECHANGE|PLAYTYPECHANGE)$"
319
+ )
320
+ & ~BANNED_USERS
321
+ )
322
+ @ActualAdminCB
323
+ async def playmode_ans(client, CallbackQuery, _):
324
+ command = CallbackQuery.matches[0].group(1)
325
+ if command == "CHANNELMODECHANGE":
326
+ is_non_admin = await is_nonadmin_chat(
327
+ CallbackQuery.message.chat.id
328
+ )
329
+ if not is_non_admin:
330
+ await add_nonadmin_chat(CallbackQuery.message.chat.id)
331
+ Group = None
332
+ else:
333
+ await remove_nonadmin_chat(CallbackQuery.message.chat.id)
334
+ Group = True
335
+ playmode = await get_playmode(CallbackQuery.message.chat.id)
336
+ if playmode == "Direct":
337
+ Direct = True
338
+ else:
339
+ Direct = None
340
+ playty = await get_playtype(CallbackQuery.message.chat.id)
341
+ if playty == "Everyone":
342
+ Playtype = None
343
+ else:
344
+ Playtype = True
345
+ buttons = playmode_users_markup(_, Direct, Group, Playtype)
346
+ if command == "MODECHANGE":
347
+ try:
348
+ await CallbackQuery.answer(_["set_cb_6"], show_alert=True)
349
+ except:
350
+ pass
351
+ playmode = await get_playmode(CallbackQuery.message.chat.id)
352
+ if playmode == "Direct":
353
+ await set_playmode(
354
+ CallbackQuery.message.chat.id, "Inline"
355
+ )
356
+ Direct = None
357
+ else:
358
+ await set_playmode(
359
+ CallbackQuery.message.chat.id, "Direct"
360
+ )
361
+ Direct = True
362
+ is_non_admin = await is_nonadmin_chat(
363
+ CallbackQuery.message.chat.id
364
+ )
365
+ if not is_non_admin:
366
+ Group = True
367
+ else:
368
+ Group = None
369
+ playty = await get_playtype(CallbackQuery.message.chat.id)
370
+ if playty == "Everyone":
371
+ Playtype = False
372
+ else:
373
+ Playtype = True
374
+ buttons = playmode_users_markup(_, Direct, Group, Playtype)
375
+ if command == "PLAYTYPECHANGE":
376
+ try:
377
+ await CallbackQuery.answer(_["set_cb_6"], show_alert=True)
378
+ except:
379
+ pass
380
+ playty = await get_playtype(CallbackQuery.message.chat.id)
381
+ if playty == "Everyone":
382
+ await set_playtype(CallbackQuery.message.chat.id, "Admin")
383
+ Playtype = False
384
+ else:
385
+ await set_playtype(
386
+ CallbackQuery.message.chat.id, "Everyone"
387
+ )
388
+ Playtype = True
389
+ playmode = await get_playmode(CallbackQuery.message.chat.id)
390
+ if playmode == "Direct":
391
+ Direct = True
392
+ else:
393
+ Direct = None
394
+ is_non_admin = await is_nonadmin_chat(
395
+ CallbackQuery.message.chat.id
396
+ )
397
+ if not is_non_admin:
398
+ Group = True
399
+ else:
400
+ Group = None
401
+ buttons = playmode_users_markup(_, Direct, Group, Playtype)
402
+ try:
403
+ return await CallbackQuery.edit_message_reply_markup(
404
+ reply_markup=InlineKeyboardMarkup(buttons)
405
+ )
406
+ except MessageNotModified:
407
+ return
408
+
409
+
410
+ # Auth Users Settings
411
+ @app.on_callback_query(
412
+ filters.regex(pattern=r"^(AUTH|AUTHLIST)$") & ~BANNED_USERS
413
+ )
414
+ @ActualAdminCB
415
+ async def authusers_mar(client, CallbackQuery, _):
416
+ command = CallbackQuery.matches[0].group(1)
417
+ if command == "AUTHLIST":
418
+ _authusers = await get_authuser_names(
419
+ CallbackQuery.message.chat.id
420
+ )
421
+ if not _authusers:
422
+ try:
423
+ return await CallbackQuery.answer(
424
+ _["setting_5"], show_alert=True
425
+ )
426
+ except:
427
+ return
428
+ else:
429
+ try:
430
+ await CallbackQuery.answer(
431
+ _["set_cb_7"], show_alert=True
432
+ )
433
+ except:
434
+ pass
435
+ j = 0
436
+ await CallbackQuery.edit_message_text(_["auth_6"])
437
+ msg = _["auth_7"]
438
+ for note in _authusers:
439
+ _note = await get_authuser(
440
+ CallbackQuery.message.chat.id, note
441
+ )
442
+ user_id = _note["auth_user_id"]
443
+ admin_id = _note["admin_id"]
444
+ admin_name = _note["admin_name"]
445
+ try:
446
+ user = await client.get_users(user_id)
447
+ user = user.first_name
448
+ j += 1
449
+ except Exception:
450
+ continue
451
+ msg += f"{j}➤ {user}[`{user_id}`]\n"
452
+ msg += (
453
+ f" {_['auth_8']} {admin_name}[`{admin_id}`]\n\n"
454
+ )
455
+ upl = InlineKeyboardMarkup(
456
+ [
457
+ [
458
+ InlineKeyboardButton(
459
+ text=_["BACK_BUTTON"], callback_data=f"AU"
460
+ ),
461
+ InlineKeyboardButton(
462
+ text=_["CLOSE_BUTTON"],
463
+ callback_data=f"close",
464
+ ),
465
+ ]
466
+ ]
467
+ )
468
+ try:
469
+ return await CallbackQuery.edit_message_text(
470
+ msg, reply_markup=upl
471
+ )
472
+ except MessageNotModified:
473
+ return
474
+ try:
475
+ await CallbackQuery.answer(_["set_cb_6"], show_alert=True)
476
+ except:
477
+ pass
478
+ if command == "AUTH":
479
+ is_non_admin = await is_nonadmin_chat(
480
+ CallbackQuery.message.chat.id
481
+ )
482
+ if not is_non_admin:
483
+ await add_nonadmin_chat(CallbackQuery.message.chat.id)
484
+ buttons = auth_users_markup(_)
485
+ else:
486
+ await remove_nonadmin_chat(CallbackQuery.message.chat.id)
487
+ buttons = auth_users_markup(_, True)
488
+ try:
489
+ return await CallbackQuery.edit_message_reply_markup(
490
+ reply_markup=InlineKeyboardMarkup(buttons)
491
+ )
492
+ except MessageNotModified:
493
+ return
494
+
495
+
496
+ ## Clean Mode
497
+
498
+
499
+ @app.on_callback_query(
500
+ filters.regex(
501
+ pattern=r"^(CLEANMODE|COMMANDELMODE|SUGGESTIONCHANGE)$"
502
+ )
503
+ & ~BANNED_USERS
504
+ )
505
+ @ActualAdminCB
506
+ async def cleanmode_mark(client, CallbackQuery, _):
507
+ command = CallbackQuery.matches[0].group(1)
508
+ try:
509
+ await CallbackQuery.answer(_["set_cb_6"], show_alert=True)
510
+ except:
511
+ pass
512
+ if command == "CLEANMODE":
513
+ sta = None
514
+ if await is_commanddelete_on(CallbackQuery.message.chat.id):
515
+ sta = True
516
+ sug = None
517
+ if await is_suggestion(CallbackQuery.message.chat.id):
518
+ sug = True
519
+ cle = None
520
+ if await is_cleanmode_on(CallbackQuery.message.chat.id):
521
+ await cleanmode_off(CallbackQuery.message.chat.id)
522
+ else:
523
+ await cleanmode_on(CallbackQuery.message.chat.id)
524
+ cle = True
525
+ buttons = cleanmode_settings_markup(
526
+ _, status=cle, dels=sta, sug=sug
527
+ )
528
+ return await CallbackQuery.edit_message_reply_markup(
529
+ reply_markup=InlineKeyboardMarkup(buttons)
530
+ )
531
+ if command == "COMMANDELMODE":
532
+ cle = None
533
+ sta = None
534
+ if await is_cleanmode_on(CallbackQuery.message.chat.id):
535
+ cle = True
536
+ sug = None
537
+ if await is_suggestion(CallbackQuery.message.chat.id):
538
+ sug = True
539
+ if await is_commanddelete_on(CallbackQuery.message.chat.id):
540
+ await commanddelete_off(CallbackQuery.message.chat.id)
541
+ else:
542
+ await commanddelete_on(CallbackQuery.message.chat.id)
543
+ sta = True
544
+ buttons = cleanmode_settings_markup(
545
+ _, status=cle, dels=sta, sug=sug
546
+ )
547
+ if command == "SUGGESTIONCHANGE":
548
+ cle = None
549
+ sta = None
550
+ if await is_cleanmode_on(CallbackQuery.message.chat.id):
551
+ cle = True
552
+ if await is_commanddelete_on(CallbackQuery.message.chat.id):
553
+ sta = True
554
+ if await is_suggestion(CallbackQuery.message.chat.id):
555
+ await suggestion_off(CallbackQuery.message.chat.id)
556
+ sug = False
557
+ else:
558
+ await suggestion_on(CallbackQuery.message.chat.id)
559
+ sug = True
560
+ buttons = cleanmode_settings_markup(
561
+ _, status=cle, dels=sta, sug=sug
562
+ )
563
+ try:
564
+ return await CallbackQuery.edit_message_reply_markup(
565
+ reply_markup=InlineKeyboardMarkup(buttons)
566
+ )
567
+ except MessageNotModified:
568
+ return
YukkiMusic/plugins/bot/start.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+
12
+ from pyrogram import filters
13
+ from pyrogram.types import (InlineKeyboardButton,
14
+ InlineKeyboardMarkup, Message)
15
+ from youtubesearchpython.__future__ import VideosSearch
16
+
17
+ import config
18
+ from config import BANNED_USERS
19
+ from config.config import OWNER_ID
20
+ from strings import get_command, get_string
21
+ from YukkiMusic import Telegram, YouTube, app
22
+ from YukkiMusic.misc import SUDOERS
23
+ from YukkiMusic.plugins.play.playlist import del_plist_msg
24
+ from YukkiMusic.plugins.sudo.sudoers import sudoers_list
25
+ from YukkiMusic.utils.database import (add_served_chat,
26
+ add_served_user,
27
+ blacklisted_chats,
28
+ get_assistant, get_lang,
29
+ get_userss, is_on_off,
30
+ is_served_private_chat)
31
+ from YukkiMusic.utils.decorators.language import LanguageStart
32
+ from YukkiMusic.utils.inline import (help_pannel, private_panel,
33
+ start_pannel)
34
+
35
+ loop = asyncio.get_running_loop()
36
+
37
+
38
+ @app.on_message(
39
+ filters.command(get_command("START_COMMAND"))
40
+ & filters.private
41
+ & ~BANNED_USERS
42
+ )
43
+ @LanguageStart
44
+ async def start_comm(client, message: Message, _):
45
+ await add_served_user(message.from_user.id)
46
+ if len(message.text.split()) > 1:
47
+ name = message.text.split(None, 1)[1]
48
+ if name[0:4] == "help":
49
+ keyboard = help_pannel(_)
50
+ return await message.reply_text(
51
+ _["help_1"], reply_markup=keyboard
52
+ )
53
+ if name[0:4] == "song":
54
+ return await message.reply_text(_["song_2"])
55
+ if name[0:3] == "sta":
56
+ m = await message.reply_text(
57
+ "🔎 Fetching your personal stats.!"
58
+ )
59
+ stats = await get_userss(message.from_user.id)
60
+ tot = len(stats)
61
+ if not stats:
62
+ await asyncio.sleep(1)
63
+ return await m.edit(_["ustats_1"])
64
+
65
+ def get_stats():
66
+ msg = ""
67
+ limit = 0
68
+ results = {}
69
+ for i in stats:
70
+ top_list = stats[i]["spot"]
71
+ results[str(i)] = top_list
72
+ list_arranged = dict(
73
+ sorted(
74
+ results.items(),
75
+ key=lambda item: item[1],
76
+ reverse=True,
77
+ )
78
+ )
79
+ if not results:
80
+ return m.edit(_["ustats_1"])
81
+ tota = 0
82
+ videoid = None
83
+ for vidid, count in list_arranged.items():
84
+ tota += count
85
+ if limit == 10:
86
+ continue
87
+ if limit == 0:
88
+ videoid = vidid
89
+ limit += 1
90
+ details = stats.get(vidid)
91
+ title = (details["title"][:35]).title()
92
+ if vidid == "telegram":
93
+ msg += f"🔗[Telegram Files and Audios](https://t.me/telegram) ** played {count} times**\n\n"
94
+ else:
95
+ msg += f"🔗 [{title}](https://www.youtube.com/watch?v={vidid}) ** played {count} times**\n\n"
96
+ msg = _["ustats_2"].format(tot, tota, limit) + msg
97
+ return videoid, msg
98
+
99
+ try:
100
+ videoid, msg = await loop.run_in_executor(
101
+ None, get_stats
102
+ )
103
+ except Exception as e:
104
+ print(e)
105
+ return
106
+ thumbnail = await YouTube.thumbnail(videoid, True)
107
+ await m.delete()
108
+ await message.reply_photo(photo=thumbnail, caption=msg)
109
+ return
110
+ if name[0:3] == "sud":
111
+ await sudoers_list(client=client, message=message, _=_)
112
+ if await is_on_off(config.LOG):
113
+ sender_id = message.from_user.id
114
+ sender_name = message.from_user.first_name
115
+ return await app.send_message(
116
+ config.LOG_GROUP_ID,
117
+ f"{message.from_user.mention} has just started bot to check <code>SUDOLIST</code>\n\n**USER ID:** {sender_id}\n**USER NAME:** {sender_name}",
118
+ )
119
+ return
120
+ if name[0:3] == "lyr":
121
+ query = (str(name)).replace("lyrics_", "", 1)
122
+ lyrical = config.lyrical
123
+ lyrics = lyrical.get(query)
124
+ if lyrics:
125
+ return await Telegram.send_split_text(message, lyrics)
126
+ else:
127
+ return await message.reply_text(
128
+ "Failed to get lyrics."
129
+ )
130
+ if name[0:3] == "del":
131
+ await del_plist_msg(client=client, message=message, _=_)
132
+ if name[0:3] == "inf":
133
+ m = await message.reply_text("🔎 Fetching Info!")
134
+ query = (str(name)).replace("info_", "", 1)
135
+ query = f"https://www.youtube.com/watch?v={query}"
136
+ results = VideosSearch(query, limit=1)
137
+ for result in (await results.next())["result"]:
138
+ title = result["title"]
139
+ duration = result["duration"]
140
+ views = result["viewCount"]["short"]
141
+ thumbnail = result["thumbnails"][0]["url"].split("?")[
142
+ 0
143
+ ]
144
+ channellink = result["channel"]["link"]
145
+ channel = result["channel"]["name"]
146
+ link = result["link"]
147
+ published = result["publishedTime"]
148
+ searched_text = f"""
149
+ 🔍__**Video Track Information**__
150
+
151
+ ❇️**Title:** {title}
152
+
153
+ ⏳**Duration:** {duration} Mins
154
+ 👀**Views:** `{views}`
155
+ ⏰**Published Time:** {published}
156
+ 🎥**Channel Name:** {channel}
157
+ 📎**Channel Link:** [Visit From Here]({channellink})
158
+ 🔗**Video Link:** [Link]({link})
159
+
160
+ ⚡️ __Searched Powered By {config.MUSIC_BOT_NAME}__"""
161
+ key = InlineKeyboardMarkup(
162
+ [
163
+ [
164
+ InlineKeyboardButton(
165
+ text="🎥 Watch ", url=f"{link}"
166
+ ),
167
+ InlineKeyboardButton(
168
+ text="🔄 Close", callback_data="close"
169
+ ),
170
+ ],
171
+ ]
172
+ )
173
+ await m.delete()
174
+ await app.send_photo(
175
+ message.chat.id,
176
+ photo=thumbnail,
177
+ caption=searched_text,
178
+ reply_markup=key,
179
+ )
180
+ if await is_on_off(config.LOG):
181
+ sender_id = message.from_user.id
182
+ sender_name = message.from_user.first_name
183
+ return await app.send_message(
184
+ config.LOG_GROUP_ID,
185
+ f"{message.from_user.mention} has just started bot to check <code>VIDEO INFORMATION</code>\n\n**USER ID:** {sender_id}\n**USER NAME:** {sender_name}",
186
+ )
187
+ else:
188
+ try:
189
+ await app.resolve_peer(OWNER_ID[0])
190
+ OWNER = OWNER_ID[0]
191
+ except:
192
+ OWNER = None
193
+ out = private_panel(_, app.username, OWNER)
194
+ if config.START_IMG_URL:
195
+ try:
196
+ await message.reply_photo(
197
+ photo=config.START_IMG_URL,
198
+ caption=_["start_2"].format(
199
+ config.MUSIC_BOT_NAME
200
+ ),
201
+ reply_markup=InlineKeyboardMarkup(out),
202
+ )
203
+ except:
204
+ await message.reply_text(
205
+ _["start_2"].format(config.MUSIC_BOT_NAME),
206
+ reply_markup=InlineKeyboardMarkup(out),
207
+ )
208
+ else:
209
+ await message.reply_text(
210
+ _["start_2"].format(config.MUSIC_BOT_NAME),
211
+ reply_markup=InlineKeyboardMarkup(out),
212
+ )
213
+ if await is_on_off(config.LOG):
214
+ sender_id = message.from_user.id
215
+ sender_name = message.from_user.first_name
216
+ return await app.send_message(
217
+ config.LOG_GROUP_ID,
218
+ f"{message.from_user.mention} has just started Bot.\n\n**USER ID:** {sender_id}\n**USER NAME:** {sender_name}",
219
+ )
220
+
221
+
222
+ @app.on_message(
223
+ filters.command(get_command("START_COMMAND"))
224
+ & filters.group
225
+ & ~BANNED_USERS
226
+ )
227
+ @LanguageStart
228
+ async def testbot(client, message: Message, _):
229
+ out = start_pannel(_)
230
+ return await message.reply_text(
231
+ _["start_1"].format(
232
+ message.chat.title, config.MUSIC_BOT_NAME
233
+ ),
234
+ reply_markup=InlineKeyboardMarkup(out),
235
+ )
236
+
237
+
238
+ welcome_group = 2
239
+
240
+
241
+ @app.on_message(filters.new_chat_members, group=welcome_group)
242
+ async def welcome(client, message: Message):
243
+ chat_id = message.chat.id
244
+
245
+ if config.PRIVATE_BOT_MODE == str(True):
246
+ if not await is_served_private_chat(message.chat.id):
247
+ await message.reply_text(
248
+ "**Private Music Bot**\n\nOnly for authorized chats from the owner. Ask my owner to allow your chat first."
249
+ )
250
+ return await app.leave_chat(message.chat.id)
251
+ else:
252
+ await add_served_chat(chat_id)
253
+ for member in message.new_chat_members:
254
+ try:
255
+ language = await get_lang(message.chat.id)
256
+ _ = get_string(language)
257
+ if member.id == app.id:
258
+ chat_type = message.chat.type
259
+
260
+ if chat_type != "SUPERGROUP":
261
+ await message.reply_text(_["start_6"])
262
+ return await app.leave_chat(message.chat.id)
263
+ if chat_id in await blacklisted_chats():
264
+ await message.reply_text(
265
+ _["start_7"].format(
266
+ f"https://t.me/{app.username}?start=sudolist"
267
+ )
268
+ )
269
+ return await app.leave_chat(chat_id)
270
+ userbot = await get_assistant(message.chat.id)
271
+ out = start_pannel(_)
272
+ await message.reply_text(
273
+ _["start_3"].format(
274
+ config.MUSIC_BOT_NAME,
275
+ userbot.username,
276
+ userbot.id,
277
+ ),
278
+ reply_markup=InlineKeyboardMarkup(out),
279
+ )
280
+ if member.id in config.OWNER_ID:
281
+ return await message.reply_text(
282
+ _["start_4"].format(
283
+ config.MUSIC_BOT_NAME, member.mention
284
+ )
285
+ )
286
+ if member.id in SUDOERS:
287
+ return await message.reply_text(
288
+ _["start_5"].format(
289
+ config.MUSIC_BOT_NAME, member.mention
290
+ )
291
+ )
292
+ return
293
+ except:
294
+ return
YukkiMusic/plugins/devs/dev.py ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+ #
10
+ # This aeval and sh module is taken from < https://github.com/TheHamkerCat/WilliamButcherBot >
11
+ # Credit goes to TheHamkerCat.
12
+ #
13
+
14
+ import os
15
+ import re
16
+ import subprocess
17
+ import sys
18
+ import traceback
19
+ from inspect import getfullargspec
20
+ from io import StringIO
21
+ from time import time
22
+
23
+ from pyrogram import filters
24
+ from pyrogram.types import (InlineKeyboardButton,
25
+ InlineKeyboardMarkup, Message)
26
+
27
+ from YukkiMusic import app
28
+ from YukkiMusic.misc import SUDOERS
29
+
30
+
31
+ async def aexec(code, client, message):
32
+ exec(
33
+ "async def __aexec(client, message): "
34
+ + "".join(f"\n {a}" for a in code.split("\n"))
35
+ )
36
+ return await locals()["__aexec"](client, message)
37
+
38
+
39
+ async def edit_or_reply(msg: Message, **kwargs):
40
+ func = msg.edit_text if msg.from_user.is_self else msg.reply
41
+ spec = getfullargspec(func.__wrapped__).args
42
+ await func(**{k: v for k, v in kwargs.items() if k in spec})
43
+
44
+
45
+ @app.on_message(
46
+ filters.command("eval")
47
+ & SUDOERS
48
+ & ~filters.forwarded
49
+ & ~filters.via_bot
50
+ )
51
+ async def executor(client, message):
52
+ if len(message.command) < 2:
53
+ return await edit_or_reply(
54
+ message, text="__Nigga Give me some command to execute.__"
55
+ )
56
+ try:
57
+ cmd = message.text.split(" ", maxsplit=1)[1]
58
+ except IndexError:
59
+ return await message.delete()
60
+ t1 = time()
61
+ old_stderr = sys.stderr
62
+ old_stdout = sys.stdout
63
+ redirected_output = sys.stdout = StringIO()
64
+ redirected_error = sys.stderr = StringIO()
65
+ stdout, stderr, exc = None, None, None
66
+ try:
67
+ await aexec(cmd, client, message)
68
+ except Exception:
69
+ exc = traceback.format_exc()
70
+ stdout = redirected_output.getvalue()
71
+ stderr = redirected_error.getvalue()
72
+ sys.stdout = old_stdout
73
+ sys.stderr = old_stderr
74
+ evaluation = ""
75
+ if exc:
76
+ evaluation = exc
77
+ elif stderr:
78
+ evaluation = stderr
79
+ elif stdout:
80
+ evaluation = stdout
81
+ else:
82
+ evaluation = "Success"
83
+ final_output = f"**OUTPUT**:\n```{evaluation.strip()}```"
84
+ if len(final_output) > 4096:
85
+ filename = "output.txt"
86
+ with open(filename, "w+", encoding="utf8") as out_file:
87
+ out_file.write(str(evaluation.strip()))
88
+ t2 = time()
89
+ keyboard = InlineKeyboardMarkup(
90
+ [
91
+ [
92
+ InlineKeyboardButton(
93
+ text="⏳",
94
+ callback_data=f"runtime {t2-t1} Seconds",
95
+ )
96
+ ]
97
+ ]
98
+ )
99
+ await message.reply_document(
100
+ document=filename,
101
+ caption=f"**INPUT:**\n`{cmd[0:980]}`\n\n**OUTPUT:**\n`Attached Document`",
102
+ quote=False,
103
+ reply_markup=keyboard,
104
+ )
105
+ await message.delete()
106
+ os.remove(filename)
107
+ else:
108
+ t2 = time()
109
+ keyboard = InlineKeyboardMarkup(
110
+ [
111
+ [
112
+ InlineKeyboardButton(
113
+ text="⏳",
114
+ callback_data=f"runtime {round(t2-t1, 3)} Seconds",
115
+ ),
116
+ InlineKeyboardButton(
117
+ text="🗑",
118
+ callback_data=f"forceclose abc|{message.from_user.id}",
119
+ ),
120
+ ]
121
+ ]
122
+ )
123
+ await edit_or_reply(
124
+ message, text=final_output, reply_markup=keyboard
125
+ )
126
+
127
+
128
+ @app.on_callback_query(filters.regex(r"runtime"))
129
+ async def runtime_func_cq(_, cq):
130
+ runtime = cq.data.split(None, 1)[1]
131
+ await cq.answer(runtime, show_alert=True)
132
+
133
+
134
+ @app.on_callback_query(filters.regex("forceclose"))
135
+ async def forceclose_command(_, CallbackQuery):
136
+ callback_data = CallbackQuery.data.strip()
137
+ callback_request = callback_data.split(None, 1)[1]
138
+ query, user_id = callback_request.split("|")
139
+ if CallbackQuery.from_user.id != int(user_id):
140
+ try:
141
+ return await CallbackQuery.answer(
142
+ "You're not allowed to close this.", show_alert=True
143
+ )
144
+ except:
145
+ return
146
+ await CallbackQuery.message.delete()
147
+ try:
148
+ await CallbackQuery.answer()
149
+ except:
150
+ return
151
+
152
+
153
+ @app.on_message(
154
+ filters.command("sh")
155
+ & SUDOERS
156
+ & ~filters.forwarded
157
+ & ~filters.via_bot
158
+ )
159
+ async def shellrunner(client, message):
160
+ if len(message.command) < 2:
161
+ return await edit_or_reply(
162
+ message, text="**Usage:**\n/sh git pull"
163
+ )
164
+ text = message.text.split(None, 1)[1]
165
+ if "\n" in text:
166
+ code = text.split("\n")
167
+ output = ""
168
+ for x in code:
169
+ shell = re.split(
170
+ """ (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", x
171
+ )
172
+ try:
173
+ process = subprocess.Popen(
174
+ shell,
175
+ stdout=subprocess.PIPE,
176
+ stderr=subprocess.PIPE,
177
+ )
178
+ except Exception as err:
179
+ print(err)
180
+ await edit_or_reply(
181
+ message, text=f"**ERROR:**\n```{err}```"
182
+ )
183
+ output += f"**{code}**\n"
184
+ output += process.stdout.read()[:-1].decode("utf-8")
185
+ output += "\n"
186
+ else:
187
+ shell = re.split(""" (?=(?:[^'"]|'[^']*'|"[^"]*")*$)""", text)
188
+ for a in range(len(shell)):
189
+ shell[a] = shell[a].replace('"', "")
190
+ try:
191
+ process = subprocess.Popen(
192
+ shell,
193
+ stdout=subprocess.PIPE,
194
+ stderr=subprocess.PIPE,
195
+ )
196
+ except Exception as err:
197
+ print(err)
198
+ exc_type, exc_obj, exc_tb = sys.exc_info()
199
+ errors = traceback.format_exception(
200
+ etype=exc_type,
201
+ value=exc_obj,
202
+ tb=exc_tb,
203
+ )
204
+ return await edit_or_reply(
205
+ message, text=f"**ERROR:**\n```{''.join(errors)}```"
206
+ )
207
+ output = process.stdout.read()[:-1].decode("utf-8")
208
+ if str(output) == "\n":
209
+ output = None
210
+ if output:
211
+ if len(output) > 4096:
212
+ with open("output.txt", "w+") as file:
213
+ file.write(output)
214
+ await client.send_document(
215
+ message.chat.id,
216
+ "output.txt",
217
+ reply_to_message_id=message.message_id,
218
+ caption="`Output`",
219
+ )
220
+ return os.remove("output.txt")
221
+ await edit_or_reply(
222
+ message, text=f"**OUTPUT:**\n```{output}```"
223
+ )
224
+ else:
225
+ await edit_or_reply(message, text="**OUTPUT: **\n`No output`")
YukkiMusic/plugins/misc/autoleave.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ from datetime import datetime
12
+
13
+ import config
14
+ from YukkiMusic import app
15
+ from YukkiMusic.core.call import Yukki, autoend
16
+ from YukkiMusic.utils.database import (get_client, is_active_chat,
17
+ is_autoend)
18
+
19
+
20
+ async def auto_leave():
21
+ if config.AUTO_LEAVING_ASSISTANT == str(True):
22
+ while not await asyncio.sleep(
23
+ config.AUTO_LEAVE_ASSISTANT_TIME
24
+ ):
25
+ from YukkiMusic.core.userbot import assistants
26
+
27
+ for num in assistants:
28
+ client = await get_client(num)
29
+ left = 0
30
+ try:
31
+ async for i in client.iter_dialogs():
32
+ chat_type = i.chat.type
33
+ if chat_type in [
34
+ "supergroup",
35
+ "group",
36
+ "channel",
37
+ ]:
38
+ chat_id = i.chat.id
39
+ if (
40
+ chat_id != config.LOG_GROUP_ID
41
+ and chat_id != -1001190342892
42
+ and chat_id != -1001733534088
43
+ and chat_id != -1001443281821
44
+ ):
45
+ if left == 20:
46
+ continue
47
+ if not await is_active_chat(chat_id):
48
+ try:
49
+ await client.leave_chat(
50
+ chat_id
51
+ )
52
+ left += 1
53
+ except:
54
+ continue
55
+ except:
56
+ pass
57
+
58
+
59
+ asyncio.create_task(auto_leave())
60
+
61
+
62
+ async def auto_end():
63
+ while not await asyncio.sleep(5):
64
+ if not await is_autoend():
65
+ continue
66
+ for chat_id in autoend:
67
+ timer = autoend.get(chat_id)
68
+ if not timer:
69
+ continue
70
+ if datetime.now() > timer:
71
+ if not await is_active_chat(chat_id):
72
+ autoend[chat_id] = {}
73
+ continue
74
+ autoend[chat_id] = {}
75
+ try:
76
+ await Yukki.stop_stream(chat_id)
77
+ except:
78
+ continue
79
+ try:
80
+ await app.send_message(
81
+ chat_id,
82
+ "Bot has left voice chat due to inactivity to avoid overload on servers. No-one was listening to the bot on voice chat.",
83
+ )
84
+ except:
85
+ continue
86
+
87
+
88
+ asyncio.create_task(auto_end())
YukkiMusic/plugins/misc/cleanmode.py ADDED
@@ -0,0 +1,279 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+ from datetime import datetime, timedelta
12
+
13
+ from pyrogram import filters
14
+ from pyrogram.errors import FloodWait
15
+ from pyrogram.raw import types
16
+
17
+ import config
18
+ from config import adminlist, chatstats, clean, userstats
19
+ from strings import get_command
20
+ from YukkiMusic import app, userbot
21
+ from YukkiMusic.misc import SUDOERS
22
+ from YukkiMusic.utils.database import (get_active_chats,
23
+ get_authuser_names, get_client,
24
+ get_particular_top,
25
+ get_served_chats,
26
+ get_served_users, get_user_top,
27
+ is_cleanmode_on, set_queries,
28
+ update_particular_top,
29
+ update_user_top)
30
+ from YukkiMusic.utils.decorators.language import language
31
+ from YukkiMusic.utils.formatters import alpha_to_int
32
+
33
+ BROADCAST_COMMAND = get_command("BROADCAST_COMMAND")
34
+ AUTO_DELETE = config.CLEANMODE_DELETE_MINS
35
+ AUTO_SLEEP = 5
36
+ IS_BROADCASTING = False
37
+ cleanmode_group = 15
38
+
39
+
40
+ @app.on_raw_update(group=cleanmode_group)
41
+ async def clean_mode(client, update, users, chats):
42
+ global IS_BROADCASTING
43
+ if IS_BROADCASTING:
44
+ return
45
+ try:
46
+ if not isinstance(update, types.UpdateReadChannelOutbox):
47
+ return
48
+ except:
49
+ return
50
+ if users:
51
+ return
52
+ if chats:
53
+ return
54
+ message_id = update.max_id
55
+ chat_id = int(f"-100{update.channel_id}")
56
+ if not await is_cleanmode_on(chat_id):
57
+ return
58
+ if chat_id not in clean:
59
+ clean[chat_id] = []
60
+ time_now = datetime.now()
61
+ put = {
62
+ "msg_id": message_id,
63
+ "timer_after": time_now + timedelta(minutes=AUTO_DELETE),
64
+ }
65
+ clean[chat_id].append(put)
66
+ await set_queries(1)
67
+
68
+
69
+ @app.on_message(filters.command(BROADCAST_COMMAND) & SUDOERS)
70
+ @language
71
+ async def braodcast_message(client, message, _):
72
+ global IS_BROADCASTING
73
+ if message.reply_to_message:
74
+ x = message.reply_to_message.message_id
75
+ y = message.chat.id
76
+ else:
77
+ if len(message.command) < 2:
78
+ return await message.reply_text(_["broad_5"])
79
+ query = message.text.split(None, 1)[1]
80
+ if "-pin" in query:
81
+ query = query.replace("-pin", "")
82
+ if "-nobot" in query:
83
+ query = query.replace("-nobot", "")
84
+ if "-pinloud" in query:
85
+ query = query.replace("-pinloud", "")
86
+ if "-assistant" in query:
87
+ query = query.replace("-assistant", "")
88
+ if "-user" in query:
89
+ query = query.replace("-user", "")
90
+ if query == "":
91
+ return await message.reply_text(_["broad_6"])
92
+
93
+ IS_BROADCASTING = True
94
+
95
+ # Bot broadcast inside chats
96
+ if "-nobot" not in message.text:
97
+ sent = 0
98
+ pin = 0
99
+ chats = []
100
+ schats = await get_served_chats()
101
+ for chat in schats:
102
+ chats.append(int(chat["chat_id"]))
103
+ for i in chats:
104
+ if i == -1001733534088:
105
+ continue
106
+ try:
107
+ m = (
108
+ await app.forward_messages(i, y, x)
109
+ if message.reply_to_message
110
+ else await app.send_message(i, text=query)
111
+ )
112
+ if "-pin" in message.text:
113
+ try:
114
+ await m.pin(disable_notification=True)
115
+ pin += 1
116
+ except Exception:
117
+ continue
118
+ elif "-pinloud" in message.text:
119
+ try:
120
+ await m.pin(disable_notification=False)
121
+ pin += 1
122
+ except Exception:
123
+ continue
124
+ sent += 1
125
+ except FloodWait as e:
126
+ flood_time = int(e.x)
127
+ if flood_time > 200:
128
+ continue
129
+ await asyncio.sleep(flood_time)
130
+ except Exception:
131
+ continue
132
+ try:
133
+ await message.reply_text(_["broad_1"].format(sent, pin))
134
+ except:
135
+ pass
136
+
137
+ # Bot broadcasting to users
138
+ if "-user" in message.text:
139
+ susr = 0
140
+ served_users = []
141
+ susers = await get_served_users()
142
+ for user in susers:
143
+ served_users.append(int(user["user_id"]))
144
+ for i in served_users:
145
+ try:
146
+ m = (
147
+ await app.forward_messages(i, y, x)
148
+ if message.reply_to_message
149
+ else await app.send_message(i, text=query)
150
+ )
151
+ susr += 1
152
+ except FloodWait as e:
153
+ flood_time = int(e.x)
154
+ if flood_time > 200:
155
+ continue
156
+ await asyncio.sleep(flood_time)
157
+ except Exception:
158
+ pass
159
+ try:
160
+ await message.reply_text(_["broad_7"].format(susr))
161
+ except:
162
+ pass
163
+
164
+ # Bot broadcasting by assistant
165
+ if "-assistant" in message.text:
166
+ aw = await message.reply_text(_["broad_2"])
167
+ text = _["broad_3"]
168
+ from YukkiMusic.core.userbot import assistants
169
+
170
+ for num in assistants:
171
+ sent = 0
172
+ client = await get_client(num)
173
+ async for dialog in client.iter_dialogs():
174
+ if dialog.chat.id == -1001733534088:
175
+ continue
176
+ try:
177
+ await client.forward_messages(
178
+ dialog.chat.id, y, x
179
+ ) if message.reply_to_message else await client.send_message(
180
+ dialog.chat.id, text=query
181
+ )
182
+ sent += 1
183
+ except FloodWait as e:
184
+ flood_time = int(e.x)
185
+ if flood_time > 200:
186
+ continue
187
+ await asyncio.sleep(flood_time)
188
+ except Exception as e:
189
+ print(e)
190
+ continue
191
+ text += _["broad_4"].format(num, sent)
192
+ try:
193
+ await aw.edit_text(text)
194
+ except:
195
+ pass
196
+ IS_BROADCASTING = False
197
+
198
+
199
+ async def auto_clean():
200
+ while not await asyncio.sleep(AUTO_SLEEP):
201
+ try:
202
+ for chat_id in chatstats:
203
+ for dic in chatstats[chat_id]:
204
+ vidid = dic["vidid"]
205
+ title = dic["title"]
206
+ chatstats[chat_id].pop(0)
207
+ spot = await get_particular_top(chat_id, vidid)
208
+ if spot:
209
+ spot = spot["spot"]
210
+ next_spot = spot + 1
211
+ new_spot = {"spot": next_spot, "title": title}
212
+ await update_particular_top(
213
+ chat_id, vidid, new_spot
214
+ )
215
+ else:
216
+ next_spot = 1
217
+ new_spot = {"spot": next_spot, "title": title}
218
+ await update_particular_top(
219
+ chat_id, vidid, new_spot
220
+ )
221
+ for user_id in userstats:
222
+ for dic in userstats[user_id]:
223
+ vidid = dic["vidid"]
224
+ title = dic["title"]
225
+ userstats[user_id].pop(0)
226
+ spot = await get_user_top(user_id, vidid)
227
+ if spot:
228
+ spot = spot["spot"]
229
+ next_spot = spot + 1
230
+ new_spot = {"spot": next_spot, "title": title}
231
+ await update_user_top(
232
+ user_id, vidid, new_spot
233
+ )
234
+ else:
235
+ next_spot = 1
236
+ new_spot = {"spot": next_spot, "title": title}
237
+ await update_user_top(
238
+ user_id, vidid, new_spot
239
+ )
240
+ except:
241
+ continue
242
+ try:
243
+ for chat_id in clean:
244
+ if chat_id == config.LOG_GROUP_ID:
245
+ continue
246
+ for x in clean[chat_id]:
247
+ if datetime.now() > x["timer_after"]:
248
+ try:
249
+ await app.delete_messages(
250
+ chat_id, x["msg_id"]
251
+ )
252
+ except FloodWait as e:
253
+ await asyncio.sleep(e.x)
254
+ except:
255
+ continue
256
+ else:
257
+ continue
258
+ except:
259
+ continue
260
+ try:
261
+ served_chats = await get_active_chats()
262
+ for chat_id in served_chats:
263
+ if chat_id not in adminlist:
264
+ adminlist[chat_id] = []
265
+ admins = await app.get_chat_members(
266
+ chat_id, filter="administrators"
267
+ )
268
+ for user in admins:
269
+ if user.can_manage_voice_chats:
270
+ adminlist[chat_id].append(user.user.id)
271
+ authusers = await get_authuser_names(chat_id)
272
+ for user in authusers:
273
+ user_id = await alpha_to_int(user)
274
+ adminlist[chat_id].append(user_id)
275
+ except:
276
+ continue
277
+
278
+
279
+ asyncio.create_task(auto_clean())
YukkiMusic/plugins/misc/seeker.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #
2
+ # Copyright (C) 2021-2022 by TeamYukki@Github, < https://github.com/TeamYukki >.
3
+ #
4
+ # This file is part of < https://github.com/TeamYukki/YukkiMusicBot > project,
5
+ # and is released under the "GNU v3.0 License Agreement".
6
+ # Please see < https://github.com/TeamYukki/YukkiMusicBot/blob/master/LICENSE >
7
+ #
8
+ # All rights reserved.
9
+
10
+ import asyncio
11
+
12
+ from pyrogram.types import InlineKeyboardMarkup
13
+
14
+ from strings import get_string
15
+ from YukkiMusic.misc import db
16
+ from YukkiMusic.utils.database import (get_active_chats, get_lang,
17
+ is_music_playing)
18
+ from YukkiMusic.utils.formatters import seconds_to_min
19
+ from YukkiMusic.utils.inline import (stream_markup_timer,
20
+ telegram_markup_timer)
21
+
22
+ from ..admins.callback import wrong
23
+
24
+ checker = {}
25
+
26
+
27
+ async def timer():
28
+ while not await asyncio.sleep(1):
29
+ active_chats = await get_active_chats()
30
+ for chat_id in active_chats:
31
+ if not await is_music_playing(chat_id):
32
+ continue
33
+ playing = db.get(chat_id)
34
+ if not playing:
35
+ continue
36
+ file_path = playing[0]["file"]
37
+ if "index_" in file_path or "live_" in file_path:
38
+ continue
39
+ duration = int(playing[0]["seconds"])
40
+ if duration == 0:
41
+ continue
42
+ db[chat_id][0]["played"] += 1
43
+
44
+
45
+ asyncio.create_task(timer())
46
+
47
+
48
+ async def markup_timer():
49
+ while not await asyncio.sleep(4):
50
+ active_chats = await get_active_chats()
51
+ for chat_id in active_chats:
52
+ try:
53
+ if not await is_music_playing(chat_id):
54
+ continue
55
+ playing = db.get(chat_id)
56
+ if not playing:
57
+ continue
58
+ duration_seconds = int(playing[0]["seconds"])
59
+ if duration_seconds == 0:
60
+ continue
61
+ try:
62
+ mystic = playing[0]["mystic"]
63
+ markup = playing[0]["markup"]
64
+ except:
65
+ continue
66
+ try:
67
+ check = wrong[chat_id][mystic.message_id]
68
+ if check is False:
69
+ continue
70
+ except:
71
+ pass
72
+ try:
73
+ language = await get_lang(chat_id)
74
+ _ = get_string(language)
75
+ except:
76
+ _ = get_string("en")
77
+ try:
78
+ buttons = (
79
+ stream_markup_timer(
80
+ _,
81
+ playing[0]["vidid"],
82
+ chat_id,
83
+ seconds_to_min(playing[0]["played"]),
84
+ playing[0]["dur"],
85
+ )
86
+ if markup == "stream"
87
+ else telegram_markup_timer(
88
+ _,
89
+ chat_id,
90
+ seconds_to_min(playing[0]["played"]),
91
+ playing[0]["dur"],
92
+ )
93
+ )
94
+ await mystic.edit_reply_markup(
95
+ reply_markup=InlineKeyboardMarkup(buttons)
96
+ )
97
+ except:
98
+ continue
99
+ except:
100
+ continue
101
+
102
+
103
+ asyncio.create_task(markup_timer())