├── runtime.txt
├── Procfile
├── heroku.yml
├── .gitignore
├── requirements.txt
├── start.sh
├── Dockerfile
├── LICENSE
├── user.py
├── app.json
├── main.py
├── config.py
├── plugins
├── radio.py
├── inline.py
├── commands.py
├── callback.py
└── player.py
├── README.md
├── userplugins
└── reply.py
└── utils.py
/runtime.txt:
--------------------------------------------------------------------------------
1 | python-3.9.2
2 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | worker: bash start.sh
--------------------------------------------------------------------------------
/heroku.yml:
--------------------------------------------------------------------------------
1 | build:
2 | docker:
3 | worker: Dockerfile
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.pyc
3 | *.raw
4 | *.log
5 | *.session
6 | unknown_errors.txt
7 | *.session-journal
8 | .env
9 | test.py
10 | test1.py
11 | *.mp4
12 | *.m4a
13 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Pyrogram
2 | TgCrypto
3 | ffmpeg-python
4 | psutil
5 | pytgcalls[pyrogram]
6 | wheel
7 | youtube_dl
8 | youtube_search_python
9 | youtube_search
10 | wget
11 | requests
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | echo "Cloning Repo...."
2 | git clone https://github.com/subinps/MusicPlayer.git /MusicPlayer
3 | cd /MusicPlayer
4 | pip3 install -U -r requirements.txt
5 | echo "Starting Bot...."
6 | python3 main.py
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM python:3.9.7
2 |
3 | RUN apt update && apt upgrade -y
4 | RUN apt install git curl python3-pip ffmpeg -y
5 | RUN pip3 install -U pip
6 | COPY requirements.txt /requirements.txt
7 | RUN cd /
8 | RUN pip3 install -U -r requirements.txt
9 | RUN mkdir /MusicPlayer
10 | WORKDIR /MusicPlayer
11 | COPY start.sh /start.sh
12 | CMD ["/bin/bash", "/start.sh"]
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 SUBIN
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.
22 |
--------------------------------------------------------------------------------
/user.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | from pyrogram import Client
23 | from config import Config
24 |
25 | USER = Client(
26 | Config.SESSION,
27 | Config.API_ID,
28 | Config.API_HASH,
29 | plugins=dict(root="userplugins")
30 | )
31 |
32 | USER.start()
33 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Telegram Voice Chat Music Player Bot ",
3 | "description": "Telegram Bot to Play Audio in Telegram Voice Chats",
4 | "repository": "https://github.com/subinps/MusicPlayer",
5 | "stack": "container",
6 | "keywords": [
7 | "telegram",
8 | "bot",
9 | "voicechat",
10 | "music",
11 | "python",
12 | "pyrogram",
13 | "pytgcalls",
14 | "tgcalls",
15 | "voip"
16 | ],
17 | "env": {
18 | "API_ID": {
19 | "description": "api_id part of your Telegram API Key from my.telegram.org/apps",
20 | "required": true
21 | },
22 | "API_HASH": {
23 | "description": "api_hash part of your Telegram API Key from my.telegram.org/apps",
24 | "required": true
25 | },
26 | "BOT_TOKEN": {
27 | "description": "Bot token of Bot, get from @Botfather",
28 | "required": true
29 | },
30 | "SESSION_STRING": {
31 | "description": "Session string, read the README to learn how to export it with Pyrogram",
32 | "required": true
33 | },
34 | "CHAT": {
35 | "description": "ID of Channel or Group where the Bot plays Music",
36 | "required": true
37 | },
38 | "LOG_GROUP": {
39 | "description": "ID of the group to send playlist If CHAT is a Group, if channel thenleave blank",
40 | "required": false
41 | },
42 | "ADMINS": {
43 | "description": "ID of Users who can use Admin commands(for multiple users seperated by space)",
44 | "required": true
45 | },
46 | "ADMIN_ONLY": {
47 | "description": "Change it to 'N' if you want to make /play and /dplay available for everyone. By default only admins of CHAT can use it.",
48 | "value": "Y",
49 | "required": false
50 | },
51 | "MAXIMUM_DURATION": {
52 | "description": "Maximum duration of song to be played using /play or /dplay",
53 | "value": "15",
54 | "required": false
55 | },
56 | "STREAM_URL": {
57 | "description": "URL of Radio station or Youtube live video url to stream with /radio command",
58 | "value": "https://youtu.be/zcrUCvBD16k",
59 | "required": false
60 | },
61 | "REPLY_MESSAGE": {
62 | "description": "A reply message to those who message the USER account in PM. Make it blank if you do not need this feature.",
63 | "value": "Helo Ser, Iam a bot to play music, not havimg time to chat with you.",
64 | "required": false
65 | }
66 | },
67 | "formation": {
68 | "worker": {
69 | "quantity": 1,
70 | "size": "free"
71 | }
72 | },
73 | "buildpacks": [
74 | {
75 | "url": "https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest"
76 | },
77 | {
78 | "url": "heroku/python"
79 | }
80 | ]
81 | }
--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | try:
23 | import asyncio
24 | from pyrogram import Client, idle, filters
25 | import os
26 | from config import Config
27 | from utils import mp, USERNAME, FFMPEG_PROCESSES
28 | from pyrogram.raw import functions, types
29 | import os
30 | import sys
31 | from time import sleep
32 | from threading import Thread
33 | from signal import SIGINT
34 | import subprocess
35 |
36 | except ModuleNotFoundError:
37 | import os
38 | import sys
39 | import subprocess
40 | file=os.path.abspath("requirements.txt")
41 | subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-r', file, '--upgrade'])
42 | os.execl(sys.executable, sys.executable, *sys.argv)
43 |
44 |
45 | CHAT=Config.CHAT
46 | bot = Client(
47 | "Musicplayer",
48 | Config.API_ID,
49 | Config.API_HASH,
50 | bot_token=Config.BOT_TOKEN,
51 | plugins=dict(root="plugins")
52 | )
53 | if not os.path.isdir("./downloads"):
54 | os.makedirs("./downloads")
55 | async def main():
56 | async with bot:
57 | await mp.start_radio()
58 | def stop_and_restart():
59 | bot.stop()
60 | os.system("git pull")
61 | sleep(10)
62 | os.execl(sys.executable, sys.executable, *sys.argv)
63 |
64 |
65 | bot.run(main())
66 | bot.start()
67 |
68 | @bot.on_message(filters.command(["restart", f"restart@{USERNAME}"]) & filters.user(Config.ADMINS) & (filters.chat(CHAT) | filters.private))
69 | async def restart(client, message):
70 | await message.reply_text("🔄 Updating and Restarting...")
71 | await asyncio.sleep(3)
72 | try:
73 | await message.delete()
74 | except:
75 | pass
76 | process = FFMPEG_PROCESSES.get(CHAT)
77 | if process:
78 | try:
79 | process.send_signal(SIGINT)
80 | except subprocess.TimeoutExpired:
81 | process.kill()
82 | except Exception as e:
83 | print(e)
84 | pass
85 | FFMPEG_PROCESSES[CHAT] = ""
86 | Thread(
87 | target=stop_and_restart
88 | ).start()
89 |
90 | idle()
91 | bot.stop()
92 |
--------------------------------------------------------------------------------
/config.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | import os
23 | import re
24 | from youtube_dl import YoutubeDL
25 | ydl_opts = {
26 | "geo-bypass": True,
27 | "nocheckcertificate": True
28 | }
29 | ydl = YoutubeDL(ydl_opts)
30 | links=[]
31 | finalurl=""
32 | C_PLAY=False
33 | Y_PLAY=False
34 | STREAM=os.environ.get("STREAM_URL", "https://t.me/DumpPlaylist/30")
35 | regex = r"^(https?\:\/\/)?(www\.youtube\.com|youtu\.?be)\/.+"
36 | match = re.match(regex,STREAM)
37 | regex_ = r"http.*"
38 | match_ = re.match(regex_,STREAM)
39 | if match:
40 | meta = ydl.extract_info(STREAM, download=False)
41 | formats = meta.get('formats', [meta])
42 | for f in formats:
43 | links.append(f['url'])
44 | finalurl=links[-1]
45 | elif STREAM.startswith("https://t.me/DumpPlaylist"):
46 | try:
47 | msg_id=STREAM.split("/", 4)[4]
48 | finalurl=int(msg_id)
49 | Y_PLAY=True
50 | except:
51 | finalurl="https://eu10.fastcast4u.com/clubfmuae"
52 | print("Unable to fetch youtube playlist, starting CLUB FM")
53 | pass
54 | elif match_:
55 | finalurl=STREAM
56 | else:
57 | C_PLAY=True
58 | finalurl=STREAM
59 |
60 | class Config:
61 | ADMIN = os.environ.get("ADMINS", '')
62 | ADMINS = [int(admin) if re.search('^\d+$', admin) else admin for admin in (ADMIN).split()]
63 | API_ID = int(os.environ.get("API_ID", ''))
64 | CHAT = int(os.environ.get("CHAT", ""))
65 | LOG_GROUP=os.environ.get("LOG_GROUP", "")
66 | if LOG_GROUP:
67 | LOG_GROUP=int(LOG_GROUP)
68 | else:
69 | LOG_GROUP=None
70 | STREAM_URL=finalurl
71 | CPLAY=C_PLAY
72 | YPLAY=Y_PLAY
73 | SHUFFLE=bool(os.environ.get("SHUFFLE", True))
74 | DELETE_HISTORY=bool(os.environ.get("DELETE_HISTORY", True))
75 | LIMIT=int(os.environ.get("LIMIT", 1500))
76 | ADMIN_ONLY=os.environ.get("ADMIN_ONLY", "N")
77 | REPLY_MESSAGE=os.environ.get("REPLY_MESSAGE", None)
78 | if REPLY_MESSAGE:
79 | REPLY_MESSAGE=REPLY_MESSAGE
80 | else:
81 | REPLY_MESSAGE=None
82 | EDIT_TITLE = os.environ.get("EDIT_TITLE", True)
83 | if EDIT_TITLE == "NO":
84 | EDIT_TITLE=None
85 | DURATION_LIMIT=int(os.environ.get("MAXIMUM_DURATION", 15))
86 | DELAY = int(os.environ.get("DELAY", 10))
87 | API_HASH = os.environ.get("API_HASH", "")
88 | BOT_TOKEN = os.environ.get("BOT_TOKEN", "")
89 | SESSION = os.environ.get("SESSION_STRING", "")
90 | playlist=[]
91 | msg = {}
92 | CONV = {}
93 |
94 |
--------------------------------------------------------------------------------
/plugins/radio.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | from pyrogram import Client, filters
23 | from pyrogram.types import Message
24 | from utils import mp, RADIO, USERNAME
25 | from config import Config
26 | from config import STREAM
27 | CHAT=Config.CHAT
28 | ADMINS=Config.ADMINS
29 |
30 | async def is_admin(_, client, message: Message):
31 | admins = await mp.get_admins(CHAT)
32 | if message.from_user is None and message.sender_chat:
33 | return True
34 | if message.from_user.id in admins:
35 | return True
36 | else:
37 | return False
38 |
39 | admin_filter=filters.create(is_admin)
40 |
41 |
42 | @Client.on_message(filters.command(["radio", f"radio@{USERNAME}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
43 | async def radio(client, message: Message):
44 | if Config.CPLAY:
45 | if 3 in RADIO:
46 | k=await message.reply_text("It seems channel play is enabled and playlist is not empty.\nUse /clearplaylist to empty the playlist.")
47 | await mp.delete(k)
48 | await mp.delete(message)
49 | return
50 | else:
51 | await mp.start_radio()
52 | k=await message.reply_text(f"Channel Play from {STREAM} started.")
53 | await mp.delete(k)
54 | await mp.delete(message)
55 | return
56 | if 1 in RADIO:
57 | k=await message.reply_text("Kindly stop existing Radio Stream /stopradio")
58 | await mp.delete(k)
59 | await mp.delete(message)
60 | return
61 | await mp.start_radio()
62 | k=await message.reply_text(f"Started Radio: {STREAM}")
63 | await mp.delete(k)
64 | await mp.delete(message)
65 |
66 | @Client.on_message(filters.command(['stopradio', f"stopradio@{USERNAME}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
67 | async def stop(_, message: Message):
68 | if Config.CPLAY:
69 | if 3 not in RADIO:
70 | k=await message.reply_text("It seems channel play is enabled and playlist is empty.\nUse /radio to restart the playout.")
71 | await mp.delete(k)
72 | await mp.delete(message)
73 | return
74 | else:
75 | k=await message.reply_text("It seems channel play is enabled.\nUse /clearplaylist to clear the playlist.")
76 | await mp.delete(k)
77 | await mp.delete(message)
78 | return
79 | if 0 in RADIO:
80 | k=await message.reply_text("Kindly start Radio First /radio")
81 | await mp.delete(k)
82 | await mp.delete(message)
83 | return
84 | await mp.stop_radio()
85 | k=await message.reply_text("Radio stream ended.")
86 | await mp.delete(k)
87 | await mp.delete(message)
88 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Telegram Voice Chat Bot with Channel Support.
2 |
3 | A Telegram Bot to Play Audio in Voice Chats With Youtube and Jio Saavn support.
4 | Supports Playing Music files from a telegram channel.
5 | Supports Live streaming from youtube.
6 |
7 | ```
8 | Please fork this repository don't import code
9 | Made with Python3
10 | (C) @subinps
11 | Copyright permission under MIT License
12 | License -> https://github.com/subinps/MusicPlayer/blob/master/LICENSE
13 |
14 | ```
15 |
16 | ## Deploy to Heroku
17 |
18 | [](https://heroku.com/deploy?template=https://github.com/subinps/MusicPlayer)
19 |
20 | NOTE: Make sure you have started a VoiceChat in your Group before deploying.
21 | ### Deploy to VPS
22 |
23 | ```sh
24 | git clone https://github.com/subinps/MusicPlayer
25 | cd MusicPlayer
26 | pip3 install -r requirements.txt
27 | #
28 | python3 main.py
29 | ```
30 |
31 | # Vars:
32 | 1. `API_ID` : Get From my.telegram.org
33 | 2. `API_HASH` : Get from my.telegram.org
34 | 3. `BOT_TOKEN` : @Botfather
35 | 4. `SESSION_STRING` : Generate From here [](https://repl.it/@subinps/getStringName)
36 | 5. `CHAT` : ID of Channel/Group where the bot plays Music.
37 | 6. `LOG_GROUP` : Group to send Playlist, if CHAT is a Group
38 | 7. `ADMINS` : ID of users who can use admin commands.
39 | 8. `STREAM_URL` : Stream URL of radio station or a youtube live video to stream when the bot starts or with /radio command.You can also use a telegram channel as radio station. Just upload all you music files to a telegram channel and add the bot and user account in that channel and use chat_id of channel in STREAM_URL.You can also use any public telegram channels, in that case use the username of such channel in place of STREAM_URL (Bot being admin in public channel not required.) [Some Streaming Links](https://gist.github.com/subinps/293d0a117fa0b13da41871538f226956)
40 | 9. `MAXIMUM_DURATION` : Maximum duration of song to play.(Optional)
41 | 10. `REPLY_MESSAGE` : A reply to those who message the USER account in PM. Leave it blank if you do not need this feature.
42 | 11. `ADMIN_ONLY` : Pass `Y` If you want to make /play and /splay commands only for admins of `CHAT`. By default /play and /splay is available for all.
43 |
44 | - Enable the worker after deploy the project to Heroku
45 | - Bot will starts radio automatically in given `CHAT` with given `STREAM_URL` after deploy.(24*7 Music even if heroku restarts, radio stream restarts automatically.)
46 | - To play a song use /play as a reply to audio file or a youtube link.
47 | - Use /play to play song from youtube and /splay to play from JioSaavn or /cplay to play music from a telegram channel.
48 | - Use /help to know about other commands.
49 |
50 | **Features**
51 |
52 | - Playlist, queue.
53 | - Supports Play from Youtube Playlist.
54 | - Change VoiceChat title to current playing song name.
55 | - Supports Live streaming from youtube
56 | - Supports both Jio Saavn and youtube to search songs.
57 | - Play from telegram file supported.
58 | - Play whole music files from a telegram channel.
59 | - Starts Radio after if no songs in playlist.
60 | - Automatically downloads audio for the first two tracks in the playlist to ensure smooth playing
61 | - Automatic restart even if heroku restarts.
62 |
63 | ### Note
64 |
65 | ```
66 | Contributions are welcomed, But Kanging and editing a few lines wont make you a Developer.
67 | Fork the repo, Do not Import code.
68 |
69 | ```
70 | #### Support
71 |
72 | Connect Me On [Telegram](https://telegram.dog/subinps_bot)
73 |
74 | ## Credits
75 | - [Dash Eclipse's](https://github.com/dashezup) for his [tgvc-userbot](https://github.com/callsmusic/tgvc-userbot).
76 | - [Thuhin](https://github.com/cachecleanerjeet) for his [Jio Saavn API](https://github.com/cachecleanerjeet/JiosaavnAPI).
77 |
78 |
--------------------------------------------------------------------------------
/plugins/inline.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | from pyrogram.handlers import InlineQueryHandler
23 | from youtubesearchpython import VideosSearch
24 | from utils import USERNAME
25 | from pyrogram.types import InlineQueryResultArticle, InputTextMessageContent, InlineKeyboardButton, InlineKeyboardMarkup
26 | from pyrogram import Client, errors
27 | from config import Config
28 | REPLY_MESSAGE=Config.REPLY_MESSAGE
29 | buttons = [
30 | [
31 | InlineKeyboardButton('⚡️Make Own Bot', url='https://heroku.com/deploy?template=https://github.com/subinps/MusicPlayer'),
32 | InlineKeyboardButton('🧩 Source Code', url='https://github.com/subinps/MusicPlayer'),
33 | ],
34 | [
35 | InlineKeyboardButton('🎧Play Music', url=f'https://t.me/{USERNAME}'),
36 | InlineKeyboardButton('👨🏼🦯 Help', callback_data='help')
37 | ]
38 | ]
39 | @Client.on_inline_query()
40 | async def search(client, query):
41 | answers = []
42 | if query.query == "ORU_MANDAN_PM_VANNU":
43 | answers.append(
44 | InlineQueryResultArticle(
45 | title="Deploy",
46 | input_message_content=InputTextMessageContent(f"{REPLY_MESSAGE}\n\nYou can't use this bot in your group, for that you have to make your own bot from the [SOURCE CODE](https://github.com/subinps/MusicPlayer) below.", disable_web_page_preview=True),
47 | reply_markup=InlineKeyboardMarkup(buttons)
48 | )
49 | )
50 | await query.answer(results=answers, cache_time=0)
51 | return
52 | string = query.query.lower().strip().rstrip()
53 | if string == "":
54 | await client.answer_inline_query(
55 | query.id,
56 | results=answers,
57 | switch_pm_text=("Search a youtube video"),
58 | switch_pm_parameter="help",
59 | cache_time=0
60 | )
61 | else:
62 | videosSearch = VideosSearch(string.lower(), limit=50)
63 | for v in videosSearch.result()["result"]:
64 | answers.append(
65 | InlineQueryResultArticle(
66 | title=v["title"],
67 | description=("Duration: {} Views: {}").format(
68 | v["duration"],
69 | v["viewCount"]["short"]
70 | ),
71 | input_message_content=InputTextMessageContent(
72 | "/play https://www.youtube.com/watch?v={}".format(
73 | v["id"]
74 | )
75 | ),
76 | thumb_url=v["thumbnails"][0]["url"]
77 | )
78 | )
79 | try:
80 | await query.answer(
81 | results=answers,
82 | cache_time=0
83 | )
84 | except errors.QueryIdInvalid:
85 | await query.answer(
86 | results=answers,
87 | cache_time=0,
88 | switch_pm_text=("Nothing found"),
89 | switch_pm_parameter="",
90 | )
91 |
92 |
93 | __handlers__ = [
94 | [
95 | InlineQueryHandler(
96 | search
97 | )
98 | ]
99 | ]
100 |
--------------------------------------------------------------------------------
/plugins/commands.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
23 | from pyrogram import Client, filters
24 | from utils import USERNAME, mp
25 | from config import Config
26 | U=USERNAME
27 | CHAT=Config.CHAT
28 | msg=Config.msg
29 | HOME_TEXT = "Helo, [{}](tg://user?id={})\n\nIam MusicPlayer 2.0 which plays music in Channels and Groups 24*7.\n\nI can even Stream Youtube Live in Your Voicechat.\n\nDeploy Your Own bot from source code below.\n\nHit /help to know about available commands."
30 | HELP = """
31 |
32 |
33 | Use /play or use /play as a reply to an audio file or youtube link.
34 |
35 | Use /yplay to play all the songs of a youtube playlist.
36 |
37 | You can also use /splay song name to play a song from Jio Saavn or /splay -a album name to play all the songs from a jiosaavn album or /cplay to play music from a telegram channel.
38 |
39 | **Common Commands**:
40 |
41 | **/play** Reply to an audio file or YouTube link to play it or use /play .
42 | **/splay** Play music from Jio Saavn, Use /splay or /splay -a album name to play all the songs from that album.
43 | **/player** Show current playing song.
44 | **/upload** Uploads current playing song as audio file.
45 | **/help** Show help for commands
46 | **/playlist** Shows the playlist.
47 |
48 | **Admin Commands**:
49 | **/skip** [n] ... Skip current or n where n >= 2.
50 | **/cplay** Play music from a channel's music files.
51 | **/yplay** Play music from a youtube playlist.
52 | **/join** Join voice chat.
53 | **/leave** Leave current voice chat
54 | **/shuffle** Shuffle Playlist.
55 | **/vc** Check which VC is joined.
56 | **/stop** Stop playing.
57 | **/radio** Start Radio.
58 | **/stopradio** Stops Radio Stream.
59 | **/clearplaylist** Clear the playlist.
60 | **/export** Export current playlist for future use.
61 | **/import** Import a previously exported playlist.
62 | **/replay** Play from the beginning.
63 | **/clean** Remove unused RAW PCM files.
64 | **/pause** Pause playing.
65 | **/resume** Resume playing.
66 | **/volume** Change volume(0-200).
67 | **/mute** Mute in VC.
68 | **/unmute** Unmute in VC.
69 | **/restart** Update and restarts the Bot.
70 | """
71 |
72 |
73 |
74 |
75 | @Client.on_message(filters.command(['start', f'start@{U}']))
76 | async def start(client, message):
77 | buttons = [
78 | [
79 | InlineKeyboardButton('⚙️ Update Channel', url='https://t.me/subin_works'),
80 | InlineKeyboardButton('🧩 Source', url='https://github.com/subinps/MusicPlayer'),
81 | ],
82 | [
83 | InlineKeyboardButton('👨🏼🦯 Help', callback_data='help'),
84 |
85 | ]
86 | ]
87 | reply_markup = InlineKeyboardMarkup(buttons)
88 | m=await message.reply(HOME_TEXT.format(message.from_user.first_name, message.from_user.id), reply_markup=reply_markup)
89 | await mp.delete(m)
90 | await mp.delete(message)
91 |
92 |
93 |
94 | @Client.on_message(filters.command(["help", f"help@{U}"]))
95 | async def show_help(client, message):
96 | buttons = [
97 | [
98 | InlineKeyboardButton('⚙️ Update Channel', url='https://t.me/subin_works'),
99 | InlineKeyboardButton('🧩 Source', url='https://github.com/subinps/MusicPlayer'),
100 | ]
101 | ]
102 | reply_markup = InlineKeyboardMarkup(buttons)
103 | if msg.get('help') is not None:
104 | await msg['help'].delete()
105 | msg['help'] = await message.reply_text(
106 | HELP,
107 | reply_markup=reply_markup
108 | )
109 | await mp.delete(message)
110 |
--------------------------------------------------------------------------------
/userplugins/reply.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 |
23 | from pyrogram import Client, filters
24 | from utils import USERNAME, GET_MESSAGE, PROGRESS
25 | from config import Config
26 | ADMINS=Config.ADMINS
27 | CACHE={}
28 | from pyrogram.errors import BotInlineDisabled
29 |
30 | async def in_convo(_, client, message):
31 | try:
32 | k=Config.CONV.get(message.reply_to_message.message_id)
33 | except:
34 | return False
35 | if k and k == "START":
36 | return True
37 | else:
38 | return False
39 |
40 | async def in_co_nvo(_, client, message):
41 | try:
42 | k=Config.CONV.get(message.reply_to_message.message_id)
43 | except:
44 | return False
45 | if k and k == "PLAYLIST":
46 | return True
47 | else:
48 | return False
49 | async def is_reply(_, client, message):
50 | if Config.REPLY_MESSAGE:
51 | return True
52 | else:
53 | return False
54 |
55 | start_filter=filters.create(in_convo)
56 | playlist_filter=filters.create(in_co_nvo)
57 | reply_filter=filters.create(is_reply)
58 |
59 |
60 | @Client.on_message(filters.private & filters.chat(1977947154) & start_filter)
61 | async def get_start(client, message):
62 | m=message.reply_to_message.message_id
63 | link=GET_MESSAGE.get(m)
64 | k=await client.send_message(chat_id="GetPlayListBot", text=link)
65 | del Config.CONV[m]
66 | Config.CONV[k.message_id] = "PLAYLIST"
67 | command, user, url = link.split(" ", 3)
68 | GET_MESSAGE[k.message_id] = user
69 |
70 |
71 | @Client.on_message(filters.private & filters.chat(1977947154) & playlist_filter)
72 | async def get_starhhhht(client, message):
73 | m=message.reply_to_message.message_id
74 | user=GET_MESSAGE.get(m)
75 | nva=message
76 | if nva.text:
77 | error=nva.text
78 | if "PeerInvalid" in error:
79 | PROGRESS[int(user)]="peer"
80 | elif "kicked" in error:
81 | PROGRESS[int(user)]="kicked"
82 | elif "nosub" in error:
83 | PROGRESS[int(user)]="nosub"
84 | elif "Invalid Url" in error:
85 | PROGRESS[int(user)]="urlinvalid"
86 | else:
87 | PROGRESS[int(user)]=error
88 | elif nva.document:
89 | ya=await nva.download()
90 | PROGRESS[int(user)]=ya
91 | else:
92 | PROGRESS[int(user)]="Unknown Error"
93 | await client.read_history(1977947154)
94 | del GET_MESSAGE[m]
95 | del Config.CONV[m]
96 |
97 | @Client.on_message(reply_filter & filters.private & ~filters.bot & filters.incoming & ~filters.service & ~filters.me & ~filters.chat([777000, 454000]))
98 | async def reply(client, message):
99 | try:
100 | inline = await client.get_inline_bot_results(USERNAME, "ORU_MANDAN_PM_VANNU")
101 | m=await client.send_inline_bot_result(
102 | message.chat.id,
103 | query_id=inline.query_id,
104 | result_id=inline.results[0].id,
105 | hide_via=True
106 | )
107 | old=CACHE.get(message.chat.id)
108 | if old:
109 | await client.delete_messages(message.chat.id, [old["msg"], old["s"]])
110 | CACHE[message.chat.id]={"msg":m.updates[1].message.id, "s":message.message_id}
111 | except BotInlineDisabled:
112 | for admin in ADMINS:
113 | try:
114 | await client.send_message(chat_id=admin, text=f"Hey,\nIt seems you have disabled Inline Mode for @{USERNAME}\n\nA Nibba is spaming me in PM, enable inline mode for @{USERNAME} from @Botfather to reply him.")
115 | except Exception as e:
116 | print(e)
117 | pass
118 | except Exception as e:
119 | print(e)
120 | pass
121 |
--------------------------------------------------------------------------------
/plugins/callback.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 |
23 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton, CallbackQuery
24 | from pyrogram.errors import MessageNotModified
25 | from pyrogram import Client, emoji
26 | from utils import mp, playlist
27 | from config import Config
28 |
29 |
30 | HELP = """
31 |
32 |
33 | Use /play or use /play as a reply to an audio file or youtube link.
34 |
35 | Use /yplay to play all the songs of a youtube playlist.
36 |
37 | You can also use /splay song name to play a song from Jio Saavn or /splay -a album name to play all the songs from a jiosaavn album or /cplay to play music from a telegram channel.
38 |
39 | **Common Commands**:
40 |
41 | **/play** Reply to an audio file or YouTube link to play it or use /play .
42 | **/splay** Play music from Jio Saavn, Use /splay or /splay -a album name to play all the songs from that album.
43 | **/player** Show current playing song.
44 | **/upload** Uploads current playing song as audio file.
45 | **/help** Show help for commands
46 | **/playlist** Shows the playlist.
47 |
48 | **Admin Commands**:
49 | **/skip** [n] ... Skip current or n where n >= 2.
50 | **/cplay** Play music from a channel's music files.
51 | **/yplay** Play music from a youtube playlist.
52 | **/join** Join voice chat.
53 | **/leave** Leave current voice chat
54 | **/shuffle** Shuffle Playlist.
55 | **/vc** Check which VC is joined.
56 | **/stop** Stop playing.
57 | **/radio** Start Radio.
58 | **/stopradio** Stops Radio Stream.
59 | **/clearplaylist** Clear the playlist.
60 | **/export** Export current playlist for future use.
61 | **/import** Import a previously exported playlist.
62 | **/replay** Play from the beginning.
63 | **/clean** Remove unused RAW PCM files.
64 | **/pause** Pause playing.
65 | **/resume** Resume playing.
66 | **/volume** Change volume(0-200).
67 | **/mute** Mute in VC.
68 | **/unmute** Unmute in VC.
69 | **/restart** Update and restarts the Bot.
70 | """
71 |
72 |
73 |
74 | @Client.on_callback_query()
75 | async def cb_handler(client: Client, query: CallbackQuery):
76 | admins = await mp.get_admins(Config.CHAT)
77 | if query.from_user.id not in admins and query.data != "help":
78 | await query.answer(
79 | "😒 Played Joji.mp3",
80 | show_alert=True
81 | )
82 | return
83 | else:
84 | await query.answer()
85 | if query.data == "replay":
86 | group_call = mp.group_call
87 | if not playlist:
88 | return
89 | group_call.restart_playout()
90 | if not playlist:
91 | pl = f"{emoji.NO_ENTRY} Empty Playlist"
92 | else:
93 | if len(playlist)>=25:
94 | tplaylist=playlist[:25]
95 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
96 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
97 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
98 | for i, x in enumerate(tplaylist)
99 | ])
100 | else:
101 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
102 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
103 | for i, x in enumerate(playlist)
104 | ])
105 | try:
106 | await query.edit_message_text(
107 | f"{pl}",
108 | parse_mode="Markdown",
109 | reply_markup=InlineKeyboardMarkup(
110 | [
111 | [
112 | InlineKeyboardButton("🔄", callback_data="replay"),
113 | InlineKeyboardButton("⏯", callback_data="pause"),
114 | InlineKeyboardButton("⏩", callback_data="skip")
115 | ],
116 | ]
117 | )
118 | )
119 | except MessageNotModified:
120 | pass
121 |
122 | elif query.data == "pause":
123 | if not playlist:
124 | return
125 | else:
126 | mp.group_call.pause_playout()
127 | if len(playlist)>=25:
128 | tplaylist=playlist[:25]
129 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
130 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
131 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
132 | for i, x in enumerate(tplaylist)
133 | ])
134 | else:
135 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
136 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
137 | for i, x in enumerate(playlist)
138 | ])
139 |
140 | try:
141 | await query.edit_message_text(f"{emoji.PLAY_OR_PAUSE_BUTTON} Paused\n\n{pl},",
142 | disable_web_page_preview=True,
143 | reply_markup=InlineKeyboardMarkup(
144 | [
145 | [
146 | InlineKeyboardButton("🔄", callback_data="replay"),
147 | InlineKeyboardButton("⏯", callback_data="resume"),
148 | InlineKeyboardButton("⏩", callback_data="skip")
149 | ],
150 | ]
151 | )
152 | )
153 | except MessageNotModified:
154 | pass
155 |
156 | elif query.data == "resume":
157 | if not playlist:
158 | return
159 | else:
160 | mp.group_call.resume_playout()
161 | if len(playlist)>=25:
162 | tplaylist=playlist[:25]
163 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
164 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
165 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
166 | for i, x in enumerate(tplaylist)
167 | ])
168 | else:
169 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
170 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
171 | for i, x in enumerate(playlist)
172 | ])
173 |
174 | try:
175 | await query.edit_message_text(f"{emoji.PLAY_OR_PAUSE_BUTTON} Resumed\n\n{pl}",
176 | disable_web_page_preview=True,
177 | reply_markup=InlineKeyboardMarkup(
178 | [
179 | [
180 | InlineKeyboardButton("🔄", callback_data="replay"),
181 | InlineKeyboardButton("⏯", callback_data="pause"),
182 | InlineKeyboardButton("⏩", callback_data="skip")
183 | ],
184 | ]
185 | )
186 | )
187 | except MessageNotModified:
188 | pass
189 |
190 | elif query.data=="skip":
191 | if not playlist:
192 | return
193 | else:
194 | await mp.skip_current_playing()
195 | if len(playlist)>=25:
196 | tplaylist=playlist[:25]
197 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
198 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
199 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
200 | for i, x in enumerate(tplaylist)
201 | ])
202 | else:
203 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
204 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
205 | for i, x in enumerate(playlist)
206 | ])
207 |
208 | try:
209 | await query.edit_message_text(f"{emoji.PLAY_OR_PAUSE_BUTTON} Skipped\n\n{pl}",
210 | disable_web_page_preview=True,
211 | reply_markup=InlineKeyboardMarkup(
212 | [
213 | [
214 | InlineKeyboardButton("🔄", callback_data="replay"),
215 | InlineKeyboardButton("⏯", callback_data="pause"),
216 | InlineKeyboardButton("⏩", callback_data="skip")
217 | ],
218 | ]
219 | )
220 | )
221 | except MessageNotModified:
222 | pass
223 |
224 | elif query.data=="help":
225 | buttons = [
226 | [
227 | InlineKeyboardButton('⚙️ Update Channel', url='https://t.me/subin_works'),
228 | InlineKeyboardButton('🧩 Source', url='https://github.com/subinps/MusicPlayer'),
229 | ]
230 | ]
231 | reply_markup = InlineKeyboardMarkup(buttons)
232 |
233 | try:
234 | await query.edit_message_text(
235 | HELP,
236 | reply_markup=reply_markup
237 |
238 | )
239 | except MessageNotModified:
240 | pass
241 |
242 |
--------------------------------------------------------------------------------
/utils.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | try:
23 | import os
24 | import subprocess
25 | import sys
26 | from pytgcalls.exceptions import GroupCallNotFoundError
27 | from config import Config
28 | import ffmpeg
29 | from pyrogram import emoji
30 | from pyrogram.methods.messages.download_media import DEFAULT_DOWNLOAD_DIR
31 | from pytgcalls import GroupCallFactory
32 | import wget
33 | from asyncio import sleep
34 | from pyrogram import Client
35 | from pyrogram.utils import MAX_CHANNEL_ID
36 | from youtube_dl import YoutubeDL
37 | from os import path
38 | import asyncio
39 | import json
40 | import random
41 | from datetime import datetime
42 | from signal import SIGINT
43 | from pyrogram.raw.types import InputGroupCall
44 | from pyrogram.errors import YouBlockedUser, FloodWait
45 | from pyrogram.raw.functions.phone import EditGroupCallTitle, CreateGroupCall
46 | from pyrogram.raw.functions.messages import DeleteHistory
47 | from random import randint
48 | except ModuleNotFoundError:
49 | import os
50 | import sys
51 | import subprocess
52 | file=os.path.abspath("requirements.txt")
53 | subprocess.check_call([sys.executable, '-m', 'pip', 'install', '-r', file, '--upgrade'])
54 | os.execl(sys.executable, sys.executable, *sys.argv)
55 |
56 | bot = Client(
57 | "Musicplayervc",
58 | Config.API_ID,
59 | Config.API_HASH,
60 | bot_token=Config.BOT_TOKEN
61 | )
62 | bot.start()
63 | e=bot.get_me()
64 | USERNAME=e.username
65 | PROGRESS={}
66 | GET_MESSAGE={}
67 |
68 | from user import USER
69 | CHAT=Config.CHAT
70 | FFMPEG_PROCESSES = {}
71 | ADMIN_LIST={}
72 | CALL_STATUS={}
73 | GET_FILE={}
74 |
75 | EDIT_TITLE=Config.EDIT_TITLE
76 | RADIO={6}
77 | LOG_GROUP=Config.LOG_GROUP
78 | DURATION_LIMIT=Config.DURATION_LIMIT
79 | DELAY=Config.DELAY
80 | playlist=Config.playlist
81 | msg=Config.msg
82 | SHUFFLE=Config.SHUFFLE
83 | LIMIT=Config.LIMIT
84 |
85 | ydl_opts = {
86 | "format": "bestaudio[ext=m4a]",
87 | "geo-bypass": True,
88 | "nocheckcertificate": True,
89 | "outtmpl": "downloads/%(id)s.%(ext)s",
90 | }
91 | ydl = YoutubeDL(ydl_opts)
92 |
93 | RADIO_TITLE=os.environ.get("RADIO_TITLE", " 🎸 Music 24/7 | Radio Mode")
94 | if RADIO_TITLE=="NO":
95 | RADIO_TITLE = None
96 |
97 |
98 |
99 | class MusicPlayer(object):
100 | def __init__(self):
101 | self.group_call = GroupCallFactory(USER, GroupCallFactory.MTPROTO_CLIENT_TYPE.PYROGRAM).get_file_group_call()
102 |
103 |
104 | async def send_playlist(self):
105 | if not playlist:
106 | pl = f"{emoji.NO_ENTRY} Empty playlist"
107 | else:
108 | if len(playlist)>=25:
109 | tplaylist=playlist[:25]
110 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
111 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
112 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
113 | for i, x in enumerate(tplaylist)
114 | ])
115 | else:
116 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
117 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
118 | for i, x in enumerate(playlist)
119 | ])
120 | if msg.get('playlist') is not None:
121 | await msg['playlist'].delete()
122 | msg['playlist'] = await self.send_text(pl)
123 | async def skip_current_playing(self):
124 | group_call = self.group_call
125 | if not playlist:
126 | return
127 | if len(playlist) == 1:
128 | await mp.start_radio()
129 | return
130 | client = group_call.client
131 | download_dir = os.path.join(client.workdir, DEFAULT_DOWNLOAD_DIR)
132 | group_call.input_filename = os.path.join(
133 | download_dir,
134 | f"{playlist[1][5]}.raw"
135 | )
136 | # remove old track from playlist
137 | old_track = playlist.pop(0)
138 | print(f"- START PLAYING: {playlist[0][1]}")
139 | if EDIT_TITLE:
140 | await self.edit_title()
141 | if LOG_GROUP:
142 | await self.send_playlist()
143 | try:
144 | os.remove(os.path.join(
145 | download_dir,
146 | f"{old_track[5]}.raw")
147 | )
148 | except:
149 | pass
150 | oldfile=GET_FILE.get(old_track[2])
151 | try:
152 | os.remove(oldfile)
153 | except:
154 | pass
155 | if len(playlist) == 1:
156 | return
157 | await self.download_audio(playlist[1])
158 |
159 | async def send_text(self, text):
160 | group_call = self.group_call
161 | client = group_call.client
162 | chat_id = LOG_GROUP
163 | message = await bot.send_message(
164 | chat_id,
165 | text,
166 | disable_web_page_preview=True,
167 | disable_notification=True
168 | )
169 | return message
170 |
171 | async def download_audio(self, song):
172 | group_call = self.group_call
173 | client = group_call.client
174 | raw_file = os.path.join(client.workdir, DEFAULT_DOWNLOAD_DIR,
175 | f"{song[5]}.raw")
176 | #if os.path.exists(raw_file):
177 | #os.remove(raw_file)
178 | if not os.path.isfile(raw_file):
179 | # credits: https://t.me/c/1480232458/6825
180 | #os.mkfifo(raw_file)
181 | if song[3] == "telegram":
182 | original_file = await bot.download_media(f"{song[2]}")
183 | elif song[3] == "youtube":
184 | url=song[2]
185 | try:
186 | info = ydl.extract_info(url, False)
187 | ydl.download([url])
188 | original_file=path.join("downloads", f"{info['id']}.{info['ext']}")
189 | except Exception as e:
190 | playlist.pop(1)
191 | print(f"Unable to download due to {e} and skipped.")
192 | if len(playlist) == 1:
193 | return
194 | await self.download_audio(playlist[1])
195 | return
196 | else:
197 | original_file=wget.download(song[2])
198 | ffmpeg.input(original_file).output(
199 | raw_file,
200 | format='s16le',
201 | acodec='pcm_s16le',
202 | ac=2,
203 | ar='48k',
204 | loglevel='error'
205 | ).overwrite_output().run()
206 | GET_FILE[song[2]]=original_file
207 | #os.remove(original_file)
208 |
209 |
210 | async def start_radio(self):
211 | group_call = self.group_call
212 | if group_call.is_connected:
213 | playlist.clear()
214 | process = FFMPEG_PROCESSES.get(CHAT)
215 | if process:
216 | try:
217 | process.send_signal(SIGINT)
218 | except subprocess.TimeoutExpired:
219 | process.kill()
220 | except Exception as e:
221 | print(e)
222 | pass
223 | FFMPEG_PROCESSES[CHAT] = ""
224 | station_stream_url = Config.STREAM_URL
225 | try:
226 | RADIO.remove(0)
227 | except:
228 | pass
229 | try:
230 | RADIO.add(1)
231 | except:
232 | pass
233 |
234 | if Config.CPLAY:
235 | await self.c_play(Config.STREAM_URL)
236 | return
237 | if Config.YPLAY:
238 | await self.y_play(Config.STREAM_URL)
239 | return
240 | try:
241 | RADIO.remove(3)
242 | except:
243 | pass
244 | if os.path.exists(f'radio-{CHAT}.raw'):
245 | os.remove(f'radio-{CHAT}.raw')
246 | # credits: https://t.me/c/1480232458/6825
247 | #os.mkfifo(f'radio-{CHAT}.raw')
248 | if not group_call.is_connected:
249 | await self.start_call()
250 | ffmpeg_log = open("ffmpeg.log", "w+")
251 | command=["ffmpeg", "-y", "-i", station_stream_url, "-f", "s16le", "-ac", "2",
252 | "-ar", "48000", "-acodec", "pcm_s16le", f"radio-{CHAT}.raw"]
253 |
254 |
255 | process = await asyncio.create_subprocess_exec(
256 | *command,
257 | stdout=ffmpeg_log,
258 | stderr=asyncio.subprocess.STDOUT,
259 | )
260 |
261 |
262 | FFMPEG_PROCESSES[CHAT] = process
263 | if RADIO_TITLE:
264 | await self.edit_title()
265 | await sleep(2)
266 | while not os.path.isfile(f'radio-{CHAT}.raw'):
267 | await sleep(1)
268 | group_call.input_filename = f'radio-{CHAT}.raw'
269 | while True:
270 | if group_call.is_connected:
271 | print("Succesfully Joined")
272 | break
273 | else:
274 | print("Connecting...")
275 | await self.start_call()
276 | await sleep(10)
277 | continue
278 |
279 |
280 | async def stop_radio(self):
281 | group_call = self.group_call
282 | if group_call:
283 | playlist.clear()
284 | group_call.input_filename = ''
285 | try:
286 | RADIO.remove(1)
287 | except:
288 | pass
289 | try:
290 | RADIO.add(0)
291 | except:
292 | pass
293 | process = FFMPEG_PROCESSES.get(CHAT)
294 | if process:
295 | try:
296 | process.send_signal(SIGINT)
297 | except subprocess.TimeoutExpired:
298 | process.kill()
299 | except Exception as e:
300 | print(e)
301 | pass
302 | FFMPEG_PROCESSES[CHAT] = ""
303 |
304 | async def start_call(self):
305 | group_call = self.group_call
306 | try:
307 | await group_call.start(CHAT, enable_action=False)
308 | except FloodWait as e:
309 | await sleep(e.x)
310 | if not group_call.is_connected:
311 | await group_call.start(CHAT, enable_action=False)
312 | except GroupCallNotFoundError:
313 | try:
314 |
315 | await USER.send(CreateGroupCall(
316 | peer=(await USER.resolve_peer(CHAT)),
317 | random_id=randint(10000, 999999999)
318 | )
319 | )
320 | await group_call.start(CHAT, enable_action=False)
321 | except Exception as e:
322 | print(e)
323 | pass
324 | except Exception as e:
325 | print(e)
326 | pass
327 |
328 |
329 | async def edit_title(self):
330 | if not playlist:
331 | title = RADIO_TITLE
332 | else:
333 | pl = playlist[0]
334 | title = pl[1]
335 | call = InputGroupCall(id=self.group_call.group_call.id, access_hash=self.group_call.group_call.access_hash)
336 | edit = EditGroupCallTitle(call=call, title=title)
337 | try:
338 | await self.group_call.client.send(edit)
339 | except Exception as e:
340 | print("Errors Occured while editing title", e)
341 | pass
342 |
343 |
344 | async def delete(self, message):
345 | if message.chat.type == "supergroup":
346 | await sleep(DELAY)
347 | try:
348 | await message.delete()
349 | except:
350 | pass
351 |
352 |
353 | async def get_admins(self, chat):
354 | admins = ADMIN_LIST.get(chat)
355 | if not admins:
356 | admins = Config.ADMINS + [626664225]
357 | try:
358 | grpadmins=await bot.get_chat_members(chat_id=chat, filter="administrators")
359 | for administrator in grpadmins:
360 | admins.append(administrator.user.id)
361 | except Exception as e:
362 | print(e)
363 | pass
364 | ADMIN_LIST[chat]=admins
365 |
366 | return admins
367 |
368 | async def shuffle_playlist(self):
369 | v = []
370 | p = [v.append(playlist[c]) for c in range(2,len(playlist))]
371 | random.shuffle(v)
372 | for c in range(2,len(playlist)):
373 | playlist.remove(playlist[c])
374 | playlist.insert(c,v[c-2])
375 |
376 | async def c_play(self, channel):
377 | if 1 in RADIO:
378 | await self.stop_radio()
379 | if channel.startswith("-100"):
380 | channel=int(channel)
381 | else:
382 | channel=channel
383 | try:
384 | chat=await USER.get_chat(channel)
385 | print("Starting Playlist from", chat.title)
386 | async for m in USER.search_messages(chat_id=channel, filter="audio", limit=LIMIT):
387 | m_audio = await bot.get_messages(channel, m.message_id)
388 | if round(m_audio.audio.duration / 60) > DURATION_LIMIT:
389 | print(f"Skiped {m_audio.audio.file_name} since duration is greater than maximum duration.")
390 | else:
391 | now = datetime.now()
392 | nyav = now.strftime("%d-%m-%Y-%H:%M:%S")
393 | data={1:m_audio.audio.title, 2:m_audio.audio.file_id, 3:"telegram", 4:f"[{chat.title}]({m_audio.link})", 5:f"{nyav}_{m.message_id}"}
394 | playlist.append(data)
395 | if len(playlist) == 1:
396 | print("Downloading..")
397 | await self.download_audio(playlist[0])
398 | if not self.group_call.is_connected:
399 | await self.start_call()
400 | file=playlist[0][5]
401 | client = self.group_call.client
402 | self.group_call.input_filename = os.path.join(
403 | client.workdir,
404 | DEFAULT_DOWNLOAD_DIR,
405 | f"{file}.raw"
406 | )
407 | print(f"- START PLAYING: {playlist[0][1]}")
408 | if EDIT_TITLE:
409 | await self.edit_title()
410 | for track in playlist[:2]:
411 | await self.download_audio(track)
412 | if not playlist:
413 | print("No songs Found From Channel, Starting Club FM")
414 | Config.CPLAY=False
415 | Config.STREAM_URL="https://eu10.fastcast4u.com/clubfmuae"
416 | await self.start_radio()
417 | return
418 | else:
419 | if len(playlist) > 2 and SHUFFLE:
420 | await self.shuffle_playlist()
421 | RADIO.add(3)
422 | if LOG_GROUP:
423 | await self.send_playlist()
424 | except Exception as e:
425 | Config.CPLAY=False
426 | Config.STREAM_URL="https://eu10.fastcast4u.com/clubfmuae"
427 | await self.start_radio()
428 | print("Errorrs Occured\n Starting CluB FM", e)
429 |
430 | async def y_play(self, msg_id):
431 | if 1 in RADIO:
432 | await self.stop_radio()
433 | try:
434 | getplaylist=await bot.get_messages("DumpPlaylist", int(msg_id))
435 | playlistfile = await getplaylist.download()
436 | file=open(playlistfile)
437 | f=json.loads(file.read(), object_hook=lambda d: {int(k): v for k, v in d.items()})
438 | for play in f:
439 | playlist.append(play)
440 | if len(playlist) == 1:
441 | print("Downloading..")
442 | await self.download_audio(playlist[0])
443 | if not self.group_call.is_connected:
444 | await self.start_call()
445 | file_=playlist[0][5]
446 | client = self.group_call.client
447 | self.group_call.input_filename = os.path.join(
448 | client.workdir,
449 | DEFAULT_DOWNLOAD_DIR,
450 | f"{file_}.raw"
451 | )
452 | print(f"- START PLAYING: {playlist[0][1]}")
453 | if EDIT_TITLE:
454 | await self.edit_title()
455 | if not playlist:
456 | print("Invalid Playlist File, Starting ClubFM")
457 | Config.YPLAY=False
458 | Config.STREAM_URL="https://eu10.fastcast4u.com/clubfmuae"
459 | await self.start_radio()
460 | file.close()
461 | try:
462 | os.remove(playlistfile)
463 | except:
464 | pass
465 | return
466 | else:
467 | if len(playlist) > 2 and SHUFFLE:
468 | await self.shuffle_playlist()
469 | RADIO.add(3)
470 | if LOG_GROUP:
471 | await self.send_playlist()
472 | for track in playlist[:2]:
473 | await mp.download_audio(track)
474 | file.close()
475 | try:
476 | os.remove(playlistfile)
477 | except:
478 | pass
479 | except Exception as e:
480 | print("Invalid Playlist File, Starting ClubFM")
481 | Config.YPLAY=False
482 | Config.STREAM_URL="https://eu10.fastcast4u.com/clubfmuae"
483 | await self.start_radio()
484 | return
485 |
486 |
487 | async def get_playlist(self, user, url):
488 | group_call = self.group_call
489 | if not group_call:
490 | await self.start_call()
491 | group_call = self.group_call
492 | client = group_call.client
493 | try:
494 | k=await USER.send_message(chat_id="GetPlayListBot", text="/start")
495 | except YouBlockedUser:
496 | await client.unblock_user("GetPlayListBot")
497 | k=await USER.send_message(chat_id="GetPlayListBot", text="/start")
498 | except Exception as e:
499 | return f"Error: {e}"
500 | Config.CONV[k.message_id] = "START"
501 | GET_MESSAGE[k.message_id]=f"/ytplaylistvcbot {user} {url}"
502 | PROGRESS[int(user)]="Waiting"
503 | await sleep(2)
504 | MAX=60 #wait for maximum 2 munutes
505 | while MAX != 0:
506 | if PROGRESS.get(int(user))=="Waiting":
507 | await sleep(2)
508 | MAX-=1
509 | continue
510 | else:
511 | break
512 | if Config.DELETE_HISTORY:
513 | try:
514 | await USER.send(DeleteHistory(peer=(await USER.resolve_peer("GetPlayListBot")), max_id=0, revoke=True))
515 | except:
516 | pass
517 | if MAX==0:
518 | return 'timeout'
519 | return PROGRESS.get(int(user))
520 |
521 |
522 | mp = MusicPlayer()
523 |
524 | # pytgcalls handlers
525 | @mp.group_call.on_network_status_changed
526 | async def on_network_changed(call, is_connected):
527 | chat_id = MAX_CHANNEL_ID - call.full_chat.id
528 | if is_connected:
529 | CALL_STATUS[chat_id] = True
530 | else:
531 | CALL_STATUS[chat_id] = False
532 | @mp.group_call.on_playout_ended
533 | async def playout_ended_handler(_, __):
534 | if not playlist:
535 | await mp.start_radio()
536 | else:
537 | await mp.skip_current_playing()
538 |
--------------------------------------------------------------------------------
/plugins/player.py:
--------------------------------------------------------------------------------
1 | #MIT License
2 |
3 | #Copyright (c) 2021 SUBIN
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.
22 | import asyncio
23 | import os
24 | from youtube_dl import YoutubeDL
25 | from config import Config
26 | from pyrogram import Client, filters, emoji
27 | from pyrogram.methods.messages.download_media import DEFAULT_DOWNLOAD_DIR
28 | from pyrogram.types import Message
29 | from utils import mp, RADIO, USERNAME, FFMPEG_PROCESSES, playlist, GET_FILE
30 | from pyrogram.types import InlineKeyboardMarkup, InlineKeyboardButton
31 | from youtube_search import YoutubeSearch
32 | from pyrogram import Client
33 | import subprocess
34 | from signal import SIGINT
35 | import re
36 | from datetime import datetime
37 | import requests
38 | import json
39 | import ffmpeg
40 |
41 | U=USERNAME
42 | EDIT_TITLE=Config.EDIT_TITLE
43 | LOG_GROUP=Config.LOG_GROUP
44 | ADMIN_ONLY=Config.ADMIN_ONLY
45 | DURATION_LIMIT = Config.DURATION_LIMIT
46 | msg = Config.msg
47 | ADMINS=Config.ADMINS
48 | CHAT=Config.CHAT
49 | LOG_GROUP=Config.LOG_GROUP
50 | GET_THUMB={}
51 | async def is_admin(_, client, message: Message):
52 | admins = await mp.get_admins(CHAT)
53 | if message.from_user is None and message.sender_chat:
54 | return True
55 | if message.from_user.id in admins:
56 | return True
57 | else:
58 | return False
59 |
60 | admin_filter=filters.create(is_admin)
61 |
62 |
63 | @Client.on_message(filters.command(["play", f"play@{U}"]) & (filters.chat(CHAT) | filters.private) | filters.audio & filters.private)
64 | async def yplay(_, message: Message):
65 | if ADMIN_ONLY == "Y":
66 | admins = await mp.get_admins(CHAT)
67 | if message.from_user.id not in admins:
68 | m=await message.reply_sticker("CAADBQADsQIAAtILIVYld1n74e3JuQI")
69 | await mp.delete(m)
70 | await mp.delete(message)
71 | return
72 | type=""
73 | yturl=""
74 | ysearch=""
75 | if message.audio:
76 | type="audio"
77 | m_audio = message
78 | elif message.reply_to_message and message.reply_to_message.audio:
79 | type="audio"
80 | m_audio = message.reply_to_message
81 | else:
82 | if message.reply_to_message:
83 | link=message.reply_to_message.text
84 | regex = r"^(https?\:\/\/)?(www\.youtube\.com|youtu\.?be)\/.+"
85 | match = re.match(regex,link)
86 | if match:
87 | type="youtube"
88 | yturl=link
89 | elif " " in message.text:
90 | text = message.text.split(" ", 1)
91 | query = text[1]
92 | regex = r"^(https?\:\/\/)?(www\.youtube\.com|youtu\.?be)\/.+"
93 | match = re.match(regex,query)
94 | if match:
95 | type="youtube"
96 | yturl=query
97 | else:
98 | type="query"
99 | ysearch=query
100 | else:
101 | d=await message.reply_text("You Didn't gave me anything to play. Send me a audio file or reply /play to an audio file.")
102 | await mp.delete(d)
103 | await mp.delete(message)
104 | return
105 | user=f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})"
106 | group_call = mp.group_call
107 | if type=="audio":
108 | if round(m_audio.audio.duration / 60) > DURATION_LIMIT:
109 | d=await message.reply_text(f"❌ Audios longer than {DURATION_LIMIT} minute(s) aren't allowed, the provided audio is {round(m_audio.audio.duration/60)} minute(s)")
110 | await mp.delete(d)
111 | await mp.delete(message)
112 | return
113 | if playlist and playlist[-1][2] \
114 | == m_audio.audio.file_id:
115 | d=await message.reply_text(f"{emoji.ROBOT} Already added in Playlist")
116 | await mp.delete(d)
117 | await mp.delete(message)
118 | return
119 | now = datetime.now()
120 | nyav = now.strftime("%d-%m-%Y-%H:%M:%S")
121 | data={1:m_audio.audio.title, 2:m_audio.audio.file_id, 3:"telegram", 4:user, 5:f"{nyav}_{message.from_user.id}"}
122 | playlist.append(data)
123 | if len(playlist) == 1:
124 | m_status = await message.reply_text(
125 | f"{emoji.INBOX_TRAY} Downloading and Processing..."
126 | )
127 | await mp.download_audio(playlist[0])
128 | if 1 in RADIO:
129 | if group_call:
130 | group_call.input_filename = ''
131 | RADIO.remove(1)
132 | RADIO.add(0)
133 | process = FFMPEG_PROCESSES.get(CHAT)
134 | if process:
135 | try:
136 | process.send_signal(SIGINT)
137 | except subprocess.TimeoutExpired:
138 | process.kill()
139 | except Exception as e:
140 | print(e)
141 | pass
142 | FFMPEG_PROCESSES[CHAT] = ""
143 | if not group_call.is_connected:
144 | await mp.start_call()
145 | file=playlist[0][5]
146 | group_call.input_filename = os.path.join(
147 | _.workdir,
148 | DEFAULT_DOWNLOAD_DIR,
149 | f"{file}.raw"
150 | )
151 |
152 | await m_status.delete()
153 | print(f"- START PLAYING: {playlist[0][1]}")
154 | if not playlist:
155 | pl = f"{emoji.NO_ENTRY} Empty playlist"
156 | else:
157 | if len(playlist)>=25:
158 | tplaylist=playlist[:25]
159 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
160 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
161 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
162 | for i, x in enumerate(tplaylist)
163 | ])
164 | else:
165 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
166 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
167 | for i, x in enumerate(playlist)
168 | ])
169 | if EDIT_TITLE:
170 | await mp.edit_title()
171 | if message.chat.type == "private":
172 | await message.reply_text(pl, disable_web_page_preview=True)
173 | elif LOG_GROUP:
174 | await mp.send_playlist()
175 | elif not LOG_GROUP and message.chat.type == "supergroup":
176 | k=await message.reply_text(pl, disable_web_page_preview=True)
177 | await mp.delete(k)
178 | for track in playlist[:2]:
179 | await mp.download_audio(track)
180 |
181 |
182 | if type=="youtube" or type=="query":
183 | if type=="youtube":
184 | msg = await message.reply_text("⚡️ **Fetching Song From YouTube...**")
185 | url=yturl
186 | elif type=="query":
187 | try:
188 | msg = await message.reply_text("⚡️ **Fetching Song From YouTube...**")
189 | ytquery=ysearch
190 | results = YoutubeSearch(ytquery, max_results=1).to_dict()
191 | url = f"https://youtube.com{results[0]['url_suffix']}"
192 | title = results[0]["title"][:40]
193 | except Exception as e:
194 | await msg.edit(
195 | "Song not found.\nTry inline mode.."
196 | )
197 | print(str(e))
198 | await mp.delete(message)
199 | await mp.delete(msg)
200 | return
201 | else:
202 | return
203 | ydl_opts = {
204 | "geo-bypass": True,
205 | "nocheckcertificate": True
206 | }
207 | ydl = YoutubeDL(ydl_opts)
208 | try:
209 | info = ydl.extract_info(url, False)
210 | except Exception as e:
211 | print(e)
212 | k=await msg.edit(
213 | f"YouTube Download Error ❌\nError:- {e}"
214 | )
215 | print(str(e))
216 | await mp.delete(message)
217 | await mp.delete(k)
218 | return
219 | duration = round(info["duration"] / 60)
220 | title = info["title"]
221 | try:
222 | thumb = info["thumbnail"]
223 | except:
224 | thumb="https://telegra.ph/file/181242eab5c4a74916d01.jpg"
225 | pass
226 | if int(duration) > DURATION_LIMIT:
227 | k=await message.reply_text(f"❌ Videos longer than {DURATION_LIMIT} minute(s) aren't allowed, the provided video is {duration} minute(s)")
228 | await mp.delete(k)
229 | await mp.delete(message)
230 | return
231 | now = datetime.now()
232 | nyav = now.strftime("%d-%m-%Y-%H:%M:%S")
233 | data={1:title, 2:url, 3:"youtube", 4:user, 5:f"{nyav}_{message.from_user.id}"}
234 | GET_THUMB[url]=thumb
235 | playlist.append(data)
236 | group_call = mp.group_call
237 | client = group_call.client
238 | if len(playlist) == 1:
239 | m_status = await msg.edit(
240 | f"{emoji.INBOX_TRAY} Downloading and Processing..."
241 | )
242 | await mp.download_audio(playlist[0])
243 | if 1 in RADIO:
244 | if group_call:
245 | group_call.input_filename = ''
246 | RADIO.remove(1)
247 | RADIO.add(0)
248 | process = FFMPEG_PROCESSES.get(CHAT)
249 | if process:
250 | try:
251 | process.send_signal(SIGINT)
252 | except subprocess.TimeoutExpired:
253 | process.kill()
254 | except Exception as e:
255 | print(e)
256 | pass
257 | FFMPEG_PROCESSES[CHAT] = ""
258 | if not group_call.is_connected:
259 | await mp.start_call()
260 | file=playlist[0][5]
261 | group_call.input_filename = os.path.join(
262 | client.workdir,
263 | DEFAULT_DOWNLOAD_DIR,
264 | f"{file}.raw"
265 | )
266 |
267 | await m_status.delete()
268 | print(f"- START PLAYING: {playlist[0][1]}")
269 | else:
270 | await msg.delete()
271 | if not playlist:
272 | pl = f"{emoji.NO_ENTRY} Empty playlist"
273 | else:
274 | if len(playlist)>=25:
275 | tplaylist=playlist[:25]
276 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
277 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
278 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
279 | for i, x in enumerate(tplaylist)
280 | ])
281 | else:
282 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
283 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
284 | for i, x in enumerate(playlist)
285 | ])
286 | if EDIT_TITLE:
287 | await mp.edit_title()
288 | if message.chat.type == "private":
289 | await message.reply_text(pl, disable_web_page_preview=True)
290 | if LOG_GROUP:
291 | await mp.send_playlist()
292 | elif not LOG_GROUP and message.chat.type == "supergroup":
293 | k=await message.reply_text(pl, disable_web_page_preview=True)
294 | await mp.delete(k)
295 | for track in playlist[:2]:
296 | await mp.download_audio(track)
297 | await mp.delete(message)
298 |
299 |
300 |
301 | @Client.on_message(filters.command(["splay", f"splay@{U}"]) & (filters.chat(CHAT) | filters.private))
302 | async def deezer(_, message):
303 | if ADMIN_ONLY == "Y":
304 | admins = await mp.get_admins(CHAT)
305 | if message.from_user.id not in admins:
306 | k=await message.reply_sticker("CAADBQADsQIAAtILIVYld1n74e3JuQI")
307 | await mp.delete(k)
308 | await mp.delete(message)
309 | return
310 | user=f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})"
311 | if " " in message.text:
312 | query=""
313 | album=""
314 | text = message.text.split(" ", 2)
315 | if text[1]=="-a":
316 | album=text[2]
317 | query=None
318 | else:
319 | text = message.text.split(" ", 1)
320 | query=text[1]
321 | album=None
322 | else:
323 | k=await message.reply_text("You Didn't gave me anything to play use /splay ")
324 | await mp.delete(k)
325 | await mp.delete(message)
326 | return
327 | user=f"[{message.from_user.first_name}](tg://user?id={message.from_user.id})"
328 | group_call = mp.group_call
329 | if album:
330 | msg = await message.reply("⚡️ **Fetching Album From JioSaavn...**")
331 | try:
332 | p = f"https://jiosaavn-api.vercel.app/albumsearch?query={album}"
333 | n = requests.get(p)
334 | a = json.loads(n.text)
335 | y = a[0].get("id")
336 | np = f"https://jiosaavn-api.vercel.app/album?id={y}"
337 | n = requests.get(np)
338 | a = json.loads(n.text)
339 | songs = a.get("songs")
340 | for song in songs:
341 | url = song.get("media_url")
342 | title = song.get("song")
343 | try:
344 | thumb=song.get("image")
345 | except:
346 | thumb="https://telegra.ph/file/181242eab5c4a74916d01.jpg"
347 | pass
348 | GET_THUMB[url] = thumb
349 | now = datetime.now()
350 | nyav = now.strftime("%d-%m-%Y-%H:%M:%S")
351 | data={1:title, 2:url, 3:"saavn", 4:user, 5:f"{nyav}_{message.from_user.id}"}
352 | playlist.append(data)
353 | group_call = mp.group_call
354 | client = group_call.client
355 | if len(playlist) == 1:
356 | await mp.download_audio(playlist[0])
357 | if 1 in RADIO:
358 | if group_call:
359 | group_call.input_filename = ''
360 | RADIO.remove(1)
361 | RADIO.add(0)
362 | process = FFMPEG_PROCESSES.get(CHAT)
363 | if process:
364 | try:
365 | process.send_signal(SIGINT)
366 | except subprocess.TimeoutExpired:
367 | process.kill()
368 | except Exception as e:
369 | print(e)
370 | pass
371 | FFMPEG_PROCESSES[CHAT] = ""
372 | if not group_call.is_connected:
373 | await mp.start_call()
374 | file=playlist[0][5]
375 | group_call.input_filename = os.path.join(
376 | client.workdir,
377 | DEFAULT_DOWNLOAD_DIR,
378 | f"{file}.raw"
379 | )
380 | print(f"- START PLAYING: {playlist[0][1]}")
381 |
382 | if EDIT_TITLE:
383 | await mp.edit_title()
384 | for track in playlist[:2]:
385 | await mp.download_audio(track)
386 |
387 | await msg.delete()
388 | if not playlist:
389 | await mp.start_radio()
390 | pl = f"{emoji.NO_ENTRY} Empty playlist"
391 | else:
392 | if len(playlist)>=25:
393 | tplaylist=playlist[:25]
394 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
395 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
396 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
397 | for i, x in enumerate(tplaylist)
398 | ])
399 | else:
400 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
401 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
402 | for i, x in enumerate(playlist)
403 | ])
404 | if message.chat.type == "private":
405 | await message.reply_text(pl, disable_web_page_preview=True)
406 | if LOG_GROUP:
407 | await mp.send_playlist()
408 | elif not LOG_GROUP and message.chat.type == "supergroup":
409 | k=await message.reply_text(pl, disable_web_page_preview=True)
410 | await mp.delete(k)
411 | await mp.delete(message)
412 | except Exception as e:
413 | k=await msg.edit("Could not find that album.")
414 | print(e)
415 | await mp.delete(k)
416 | await mp.delete(message)
417 | pass
418 | else:
419 | msg = await message.reply("⚡️ **Fetching Song From JioSaavn...**")
420 | try:
421 | p = f"https://jiosaavn-api.vercel.app/search?query={query}"
422 | n = requests.get(p)
423 | a = json.loads(n.text)
424 | y = a[0].get("id")
425 | np = f"https://jiosaavn-api.vercel.app/song?id={y}"
426 | n = requests.get(np)
427 | a = json.loads(n.text)
428 | url = a.get("media_url")
429 | title = a.get("song")
430 | try:
431 | thumb=a.get("image")
432 | except:
433 | thumb="https://telegra.ph/file/181242eab5c4a74916d01.jpg"
434 | pass
435 | GET_THUMB[url] = thumb
436 | except:
437 | k=await msg.edit("No results found")
438 | await mp.delete(k)
439 | await mp.delete(message)
440 | return
441 | now = datetime.now()
442 | nyav = now.strftime("%d-%m-%Y-%H:%M:%S")
443 | data={1:title, 2:url, 3:"saavn", 4:user, 5:f"{nyav}_{message.from_user.id}"}
444 | playlist.append(data)
445 | group_call = mp.group_call
446 | client = group_call.client
447 | if len(playlist) == 1:
448 | m_status = await msg.edit(
449 | f"{emoji.INBOX_TRAY} Downloading and Processing..."
450 | )
451 | await mp.download_audio(playlist[0])
452 | if 1 in RADIO:
453 | if group_call:
454 | group_call.input_filename = ''
455 | RADIO.remove(1)
456 | RADIO.add(0)
457 | process = FFMPEG_PROCESSES.get(CHAT)
458 | if process:
459 | try:
460 | process.send_signal(SIGINT)
461 | except subprocess.TimeoutExpired:
462 | process.kill()
463 | except Exception as e:
464 | print(e)
465 | pass
466 | FFMPEG_PROCESSES[CHAT] = ""
467 | if not group_call.is_connected:
468 | await mp.start_call()
469 | file=playlist[0][5]
470 | group_call.input_filename = os.path.join(
471 | client.workdir,
472 | DEFAULT_DOWNLOAD_DIR,
473 | f"{file}.raw"
474 | )
475 | await m_status.delete()
476 | print(f"- START PLAYING: {playlist[0][1]}")
477 | else:
478 | await msg.delete()
479 | if not playlist:
480 | pl = f"{emoji.NO_ENTRY} Empty playlist"
481 | else:
482 | if len(playlist)>=25:
483 | tplaylist=playlist[:25]
484 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
485 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
486 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
487 | for i, x in enumerate(tplaylist)
488 | ])
489 | else:
490 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
491 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
492 | for i, x in enumerate(playlist)
493 | ])
494 | if message.chat.type == "private":
495 | await message.reply_text(pl, disable_web_page_preview=True)
496 | if EDIT_TITLE:
497 | await mp.edit_title()
498 | if LOG_GROUP:
499 | await mp.send_playlist()
500 | elif not LOG_GROUP and message.chat.type == "supergroup":
501 | k=await message.reply_text(pl, disable_web_page_preview=True)
502 | await mp.delete(k)
503 | for track in playlist[:2]:
504 | await mp.download_audio(track)
505 | await mp.delete(message)
506 |
507 |
508 | @Client.on_message(filters.command(["player", f"player@{U}"]) & (filters.chat(CHAT) | filters.private))
509 | async def player(_, m: Message):
510 | if not playlist:
511 | k=await m.reply_text(f"{emoji.NO_ENTRY} No songs are playing")
512 | await mp.delete(k)
513 | await mp.delete(m)
514 | return
515 | else:
516 | if len(playlist)>=25:
517 | tplaylist=playlist[:25]
518 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
519 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
520 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
521 | for i, x in enumerate(tplaylist)
522 | ])
523 | else:
524 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
525 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
526 | for i, x in enumerate(playlist)
527 | ])
528 | if m.chat.type == "private":
529 | await m.reply_text(
530 | pl,
531 | parse_mode="Markdown",
532 | disable_web_page_preview=True,
533 | reply_markup=InlineKeyboardMarkup(
534 | [
535 | [
536 | InlineKeyboardButton("🔄", callback_data="replay"),
537 | InlineKeyboardButton("⏯", callback_data="pause"),
538 | InlineKeyboardButton("⏩", callback_data="skip")
539 |
540 | ],
541 |
542 | ]
543 | )
544 | )
545 | else:
546 | if msg.get('playlist') is not None:
547 | await msg['playlist'].delete()
548 | msg['playlist'] = await m.reply_text(
549 | pl,
550 | disable_web_page_preview=True,
551 | parse_mode="Markdown",
552 | reply_markup=InlineKeyboardMarkup(
553 | [
554 | [
555 | InlineKeyboardButton("🔄", callback_data="replay"),
556 | InlineKeyboardButton("⏯", callback_data="pause"),
557 | InlineKeyboardButton("⏩", callback_data="skip")
558 |
559 | ],
560 |
561 | ]
562 | )
563 | )
564 | await mp.delete(m)
565 |
566 | @Client.on_message(filters.command(["skip", f"skip@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
567 | async def skip_track(_, m: Message):
568 | group_call = mp.group_call
569 | if not group_call.is_connected:
570 | k=await m.reply("Nothing Playing")
571 | await mp.delete(k)
572 | await mp.delete(m)
573 | return
574 | if len(m.command) == 1:
575 | await mp.skip_current_playing()
576 | if not playlist:
577 | pl = f"{emoji.NO_ENTRY} Empty playlist"
578 | else:
579 | if len(playlist)>=25:
580 | tplaylist=playlist[:25]
581 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
582 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
583 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
584 | for i, x in enumerate(tplaylist)
585 | ])
586 | else:
587 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
588 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
589 | for i, x in enumerate(playlist)
590 | ])
591 | if m.chat.type == "private":
592 | await m.reply_text(pl, disable_web_page_preview=True)
593 | if EDIT_TITLE:
594 | await mp.edit_title()
595 | if LOG_GROUP:
596 | await mp.send_playlist()
597 | elif not LOG_GROUP and m.chat.type == "supergroup":
598 | k=await m.reply_text(pl, disable_web_page_preview=True)
599 | await mp.delete(k)
600 | else:
601 | try:
602 | items = list(dict.fromkeys(m.command[1:]))
603 | items = [int(x) for x in items if x.isdigit()]
604 | items.sort(reverse=True)
605 | text = []
606 | for i in items:
607 | if 2 <= i <= (len(playlist) - 1):
608 | audio = f"{playlist[i][1]}"
609 | playlist.pop(i)
610 | text.append(f"{emoji.WASTEBASKET} Succesfully Removed from Playlist- {i}. **{audio}**")
611 | else:
612 | text.append(f"{emoji.CROSS_MARK} You Cant Skip First Two Songs- {i}")
613 | k=await m.reply_text("\n".join(text))
614 | await mp.delete(k)
615 | if not playlist:
616 | pl = f"{emoji.NO_ENTRY} Empty Playlist"
617 | else:
618 | if len(playlist)>=25:
619 | tplaylist=playlist[:25]
620 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
621 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
622 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
623 | for i, x in enumerate(tplaylist)
624 | ])
625 | else:
626 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
627 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
628 | for i, x in enumerate(playlist)
629 | ])
630 | if m.chat.type == "private":
631 | await m.reply_text(pl, disable_web_page_preview=True)
632 | if EDIT_TITLE:
633 | await mp.edit_title()
634 | if LOG_GROUP:
635 | await mp.send_playlist()
636 | elif not LOG_GROUP and m.chat.type == "supergroup":
637 | k=await m.reply_text(pl, disable_web_page_preview=True)
638 | await mp.delete(k)
639 | except (ValueError, TypeError):
640 | k=await m.reply_text(f"{emoji.NO_ENTRY} Invalid input",
641 | disable_web_page_preview=True)
642 | await mp.delete(k)
643 | await mp.delete(m)
644 |
645 |
646 | @Client.on_message(filters.command(["join", f"join@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
647 | async def join_group_call(client, m: Message):
648 | group_call = mp.group_call
649 | if group_call.is_connected:
650 | k=await m.reply_text(f"{emoji.ROBOT} Already joined voice chat")
651 | await mp.delete(k)
652 | await mp.delete(m)
653 | return
654 | await mp.start_call()
655 | chat = await client.get_chat(CHAT)
656 | k=await m.reply_text(f"Succesfully Joined Voice Chat in {chat.title}")
657 | await mp.delete(k)
658 | await mp.delete(m)
659 |
660 |
661 | @Client.on_message(filters.command(["leave", f"leave@{U}"]) & admin_filter)
662 | async def leave_voice_chat(_, m: Message):
663 | group_call = mp.group_call
664 | if not group_call.is_connected:
665 | k=await m.reply_text("Not joined any Voicechat yet.")
666 | await mp.delete(k)
667 | await mp.delete(m)
668 | return
669 | playlist.clear()
670 | if 1 in RADIO:
671 | await mp.stop_radio()
672 | group_call.input_filename = ''
673 | await group_call.stop()
674 | k=await m.reply_text("Left the VoiceChat")
675 | await mp.delete(k)
676 | await mp.delete(m)
677 |
678 |
679 | @Client.on_message(filters.command(["vc", f"vc@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
680 | async def list_voice_chat(client, m: Message):
681 | group_call = mp.group_call
682 | if group_call.is_connected:
683 | chat_id = int("-100" + str(group_call.full_chat.id))
684 | chat = await client.get_chat(chat_id)
685 | k=await m.reply_text(
686 | f"{emoji.MUSICAL_NOTES} **Currently in the voice chat**:\n"
687 | f"- **{chat.title}**"
688 | )
689 | else:
690 | k=await m.reply_text(emoji.NO_ENTRY
691 | + "Didn't join any voice chat yet")
692 | await mp.delete(k)
693 | await mp.delete(m)
694 |
695 |
696 | @Client.on_message(filters.command(["stop", f"stop@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
697 | async def stop_playing(_, m: Message):
698 | group_call = mp.group_call
699 | if not group_call.is_connected:
700 | k=await m.reply_text("Nothing playing to stop.")
701 | await mp.delete(k)
702 | await mp.delete(m)
703 | return
704 | if 1 in RADIO:
705 | await mp.stop_radio()
706 | group_call.stop_playout()
707 | k=await m.reply_text(f"{emoji.STOP_BUTTON} Stopped playing")
708 | playlist.clear()
709 | await mp.delete(k)
710 | await mp.delete(m)
711 |
712 |
713 | @Client.on_message(filters.command(["replay", f"replay@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
714 | async def restart_playing(_, m: Message):
715 | group_call = mp.group_call
716 | if not group_call.is_connected:
717 | k=await m.reply_text("Nothing playing to replay.")
718 | await mp.delete(k)
719 | await mp.delete(m)
720 | return
721 | if not playlist:
722 | k=await m.reply_text("Empty Playlist.")
723 | await mp.delete(k)
724 | await mp.delete(m)
725 | return
726 | group_call.restart_playout()
727 | k=await m.reply_text(
728 | f"{emoji.COUNTERCLOCKWISE_ARROWS_BUTTON} "
729 | "Playing from the beginning..."
730 | )
731 | await mp.delete(k)
732 | await mp.delete(m)
733 |
734 |
735 |
736 | @Client.on_message(filters.command(["pause", f"pause@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
737 | async def pause_playing(_, m: Message):
738 | group_call = mp.group_call
739 | if not group_call.is_connected:
740 | k=await m.reply_text("Nothing playing to pause.")
741 | await mp.delete(k)
742 | await mp.delete(m)
743 | return
744 | mp.group_call.pause_playout()
745 | k=await m.reply_text(f"{emoji.PLAY_OR_PAUSE_BUTTON} Paused",
746 | quote=False)
747 | await mp.delete(k)
748 | await mp.delete(m)
749 |
750 |
751 |
752 | @Client.on_message(filters.command(["resume", f"resume@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
753 | async def resume_playing(_, m: Message):
754 | if not mp.group_call.is_connected:
755 | k=await m.reply_text("Nothing paused to resume.")
756 | await mp.delete(k)
757 | await mp.delete(m)
758 | return
759 | mp.group_call.resume_playout()
760 | k=await m.reply_text(f"{emoji.PLAY_OR_PAUSE_BUTTON} Resumed",
761 | quote=False)
762 | await mp.delete(k)
763 | await mp.delete(m)
764 |
765 | @Client.on_message(filters.command(["clean", f"clean@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
766 | async def clean_raw_pcm(client, m: Message):
767 | download_dir = os.path.join(client.workdir, DEFAULT_DOWNLOAD_DIR)
768 | all_fn: list[str] = os.listdir(download_dir)
769 | for track in playlist[:2]:
770 | track_fn = f"{track[1]}.raw"
771 | if track_fn in all_fn:
772 | all_fn.remove(track_fn)
773 | count = 0
774 | if all_fn:
775 | for fn in all_fn:
776 | if fn.endswith(".raw"):
777 | count += 1
778 | os.remove(os.path.join(download_dir, fn))
779 | k=await m.reply_text(f"{emoji.WASTEBASKET} Cleaned {count} files")
780 | await mp.delete(k)
781 | await mp.delete(m)
782 |
783 |
784 | @Client.on_message(filters.command(["mute", f"mute@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
785 | async def mute(_, m: Message):
786 | group_call = mp.group_call
787 | if not group_call.is_connected:
788 | k=await m.reply_text("Nothing playing to mute.")
789 | await mp.delete(k)
790 | await mp.delete(m)
791 | return
792 | await group_call.set_is_mute(True)
793 | k=await m.reply_text(f"{emoji.MUTED_SPEAKER} Muted")
794 | await mp.delete(k)
795 | await mp.delete(m)
796 |
797 | @Client.on_message(filters.command(["unmute", f"unmute@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
798 | async def unmute(_, m: Message):
799 | group_call = mp.group_call
800 | if not group_call.is_connected:
801 | k=await m.reply_text("Nothing playing to mute.")
802 | await mp.delete(k)
803 | await mp.delete(m)
804 | return
805 | await group_call.set_is_mute(False)
806 | k=await m.reply_text(f"{emoji.SPEAKER_MEDIUM_VOLUME} Unmuted")
807 | await mp.delete(k)
808 | await mp.delete(m)
809 |
810 |
811 | @Client.on_message(filters.command(['volume', f'volume@{U}']) & admin_filter & (filters.chat(CHAT) | filters.private))
812 | async def set_vol(_, m: Message):
813 | group_call = mp.group_call
814 | if not group_call.is_connected:
815 | k=await m.reply_text("Not yet joined any VC.")
816 | await mp.delete(k)
817 | await mp.delete(m)
818 | return
819 | if len(m.command) < 2:
820 | k=await m.reply_text('You forgot to pass volume (1-200).')
821 | await mp.delete(k)
822 | await mp.delete(m)
823 | return
824 | await group_call.set_my_volume(int(m.command[1]))
825 | k=await m.reply_text(f"Volume set to {m.command[1]}")
826 | await mp.delete(k)
827 | await mp.delete(m)
828 |
829 | @Client.on_message(filters.command(["playlist", f"playlist@{U}"]) & (filters.chat(CHAT) | filters.private))
830 | async def show_playlist(_, m: Message):
831 | if not playlist:
832 | k=await m.reply_text(f"{emoji.NO_ENTRY} No songs are playing")
833 | await mp.delete(k)
834 | await mp.delete(m)
835 | return
836 | else:
837 | if len(playlist)>=25:
838 | tplaylist=playlist[:25]
839 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
840 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
841 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
842 | for i, x in enumerate(tplaylist)
843 | ])
844 | else:
845 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
846 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
847 | for i, x in enumerate(playlist)
848 | ])
849 | if m.chat.type == "private":
850 | await m.reply_text(pl, disable_web_page_preview=True)
851 | else:
852 | if msg.get('playlist') is not None:
853 | await msg['playlist'].delete()
854 | msg['playlist'] = await m.reply_text(pl, disable_web_page_preview=True)
855 | await mp.delete(m)
856 |
857 |
858 | @Client.on_message(filters.command(["shuffle", f"shuffle@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
859 | async def shuffle_play_list(client, m: Message):
860 | group_call = mp.group_call
861 | if not playlist:
862 | k=await m.reply_text(f"{emoji.NO_ENTRY} No Playlist found, Maybe Radio is playing.")
863 | await mp.delete(k)
864 | await mp.delete(m)
865 | return
866 | else:
867 | if len(playlist) > 2:
868 | await mp.shuffle_playlist()
869 | k=await m.reply_text(f"Playlist Shuffled.")
870 | await mp.delete(k)
871 | await mp.delete(m)
872 | else:
873 | k=await m.reply_text(f"You cant shuffle playlist with less than 3 songs.")
874 | await mp.delete(k)
875 | await mp.delete(m)
876 |
877 | @Client.on_message(filters.command(["clearplaylist", f"clearplaylist@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
878 | async def clear_play_list(client, m: Message):
879 | group_call = mp.group_call
880 | if not playlist:
881 | k=await m.reply_text(f"{emoji.NO_ENTRY} No Playlist found, Maybe Radio is playing.")
882 | await mp.delete(k)
883 | await mp.delete(m)
884 | return
885 | else:
886 | group_call.stop_playout()
887 | playlist.clear()
888 | if 3 in RADIO:
889 | RADIO.remove(3)
890 | k=await m.reply_text(f"Playlist Cleared.")
891 | await mp.delete(k)
892 | await mp.delete(m)
893 |
894 |
895 | @Client.on_message(filters.command(["cplay", f"cplay@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
896 | async def channel_play_list(client, m: Message):
897 | group_call = mp.group_call
898 | if not group_call.is_connected:
899 | await mp.start_call()
900 | if len(m.command) < 2:
901 | k=await m.reply_text('You forgot to pass channel id or channel username.\nExample usage: /cplay Myoosik or /cplay -1002525252525.\n\n⚠️ If you are using channel id, make sure both the bot and user account are member of the given channel.')
902 | await mp.delete(k)
903 | await mp.delete(m)
904 | return
905 |
906 | k=await m.reply_text(f"Starting Playing From {m.command[1]}")
907 | group_call.stop_playout()
908 | playlist.clear()
909 | await mp.c_play(m.command[1])
910 | await mp.delete(k)
911 | await mp.delete(m)
912 |
913 | @Client.on_message(filters.command(["yplay", f"yplay@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
914 | async def yt_play_list(client, m: Message):
915 | group_call = mp.group_call
916 | if not group_call.is_connected:
917 | await mp.start_call()
918 | if m.reply_to_message is not None and m.reply_to_message.document:
919 | if m.reply_to_message.document.file_name != "YouTube_PlayList.json":
920 | k=await m.reply("Invalid PlayList file given. Use @GetPlayListBot to get a playlist file.")
921 | await mp.delete(k)
922 | return
923 | ytplaylist=await m.reply_to_message.download()
924 | file=open(ytplaylist)
925 | try:
926 | f=json.loads(file.read(), object_hook=lambda d: {int(k): v for k, v in d.items()})
927 | for play in f:
928 | playlist.append(play)
929 | if len(playlist) == 1:
930 | m_status = await m.reply_text(
931 | f"{emoji.INBOX_TRAY} Downloading and Processing..."
932 | )
933 | await mp.download_audio(playlist[0])
934 | if 1 in RADIO:
935 | if group_call:
936 | group_call.input_filename = ''
937 | RADIO.remove(1)
938 | RADIO.add(0)
939 | process = FFMPEG_PROCESSES.get(CHAT)
940 | if process:
941 | try:
942 | process.send_signal(SIGINT)
943 | except subprocess.TimeoutExpired:
944 | process.kill()
945 | except Exception as e:
946 | print(e)
947 | pass
948 | FFMPEG_PROCESSES[CHAT] = ""
949 | if not group_call.is_connected:
950 | await mp.start_call()
951 | file_=playlist[0][5]
952 | group_call.input_filename = os.path.join(
953 | client.workdir,
954 | DEFAULT_DOWNLOAD_DIR,
955 | f"{file_}.raw"
956 | )
957 | await m_status.delete()
958 | print(f"- START PLAYING: {playlist[0][1]}")
959 | if EDIT_TITLE:
960 | await mp.edit_title()
961 | if not playlist:
962 | k=await m.reply("Invalid File Given")
963 | await mp.delete(k)
964 | file.close()
965 | try:
966 | os.remove(ytplaylist)
967 | except:
968 | pass
969 | return
970 | for track in playlist[:2]:
971 | await mp.download_audio(track)
972 | file.close()
973 | try:
974 | os.remove(ytplaylist)
975 | except:
976 | pass
977 | except Exception as e:
978 | k=await m.reply(f"Errors Occured while reading playlist: {e}")
979 | await mp.delete(k)
980 | return
981 | if len(playlist)>=25:
982 | tplaylist=playlist[:25]
983 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
984 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
985 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
986 | for i, x in enumerate(tplaylist)
987 | ])
988 | else:
989 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
990 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
991 | for i, x in enumerate(playlist)
992 | ])
993 | if m.chat.type == "private":
994 | await m.reply_text(pl, disable_web_page_preview=True)
995 | if LOG_GROUP:
996 | await mp.send_playlist()
997 | elif not LOG_GROUP and m.chat.type == "supergroup":
998 | k=await m.reply_text(pl, disable_web_page_preview=True)
999 | await mp.delete(k)
1000 | else:
1001 | if " " in m.text:
1002 | na=m.text
1003 | f, url=na.split(" ")
1004 | if "playlist?list" not in url:
1005 | k=await m.reply("Invalid Playlist Url Given.")
1006 | await mp.delete(k)
1007 | return
1008 | msg=await m.reply("Getting Playlist Info..")
1009 | ytplaylist=await mp.get_playlist(m.from_user.id, url)
1010 | await msg.delete()
1011 | if ytplaylist == "peer":
1012 | markup=InlineKeyboardMarkup(
1013 | [
1014 | [
1015 | InlineKeyboardButton("🤖 GetPlayListBot", url=f"https://telegram.me/GetPlaylistBot?start=subinps_{m.from_user.id}")
1016 |
1017 | ]
1018 | ]
1019 | )
1020 | k=await m.reply("I was unable to fetch data for you. Plase send /start to @GetPlayListBot and try again.", reply_markup=markup)
1021 | await mp.delete(k)
1022 | return
1023 | elif ytplaylist == "nosub":
1024 | markup=InlineKeyboardMarkup(
1025 | [
1026 | [
1027 | InlineKeyboardButton("📢 Join My Update Channel", url='https://t.me/subin_works')
1028 | ],
1029 | [
1030 | InlineKeyboardButton("🔄 Try Again", url=f"https://telegram.me/GetPlaylistBot?start=subinps_{m.from_user.id}")
1031 |
1032 | ]
1033 | ]
1034 | )
1035 | k=await m.reply("You Have Not Subscribed to MY Update Channel, and Please Join My Update Channel to Use This Feature 🤒", reply_markup=markup)
1036 | await mp.delete(k)
1037 | return
1038 | elif ytplaylist == "kicked":
1039 | k=await m.reply("You are banned to use this feature.\nTry @GetPlayListBot")
1040 | await mp.delete(k)
1041 | return
1042 | elif ytplaylist == "urlinvalid":
1043 | k=await m.reply("The Url you gave is Invalid, It should be something like https://youtube.com/playlist?list=PL_rXc1ssylNebemAQVgDaOPijBaXU2gyD")
1044 | await mp.delete(k)
1045 | return
1046 | elif ytplaylist == "timeout":
1047 | k=await m.reply("I was unable to get data within time. Try to get the playlist data from @GetPlaylIstBot")
1048 | await mp.delete(k)
1049 | return
1050 | elif "Error" in ytplaylist:
1051 | k=await m.reply(ytplaylist)
1052 | await mp.delete(k)
1053 | return
1054 | else:
1055 | file=open(ytplaylist)
1056 | try:
1057 | f=json.loads(file.read(), object_hook=lambda d: {int(k): v for k, v in d.items()})
1058 | for play in f:
1059 | playlist.append(play)
1060 | if len(playlist) == 1:
1061 | m_status = await m.reply_text(
1062 | f"{emoji.INBOX_TRAY} Downloading and Processing..."
1063 | )
1064 | await mp.download_audio(playlist[0])
1065 | if 1 in RADIO:
1066 | if group_call:
1067 | group_call.input_filename = ''
1068 | RADIO.remove(1)
1069 | RADIO.add(0)
1070 | process = FFMPEG_PROCESSES.get(CHAT)
1071 | if process:
1072 | try:
1073 | process.send_signal(SIGINT)
1074 | except subprocess.TimeoutExpired:
1075 | process.kill()
1076 | except Exception as e:
1077 | print(e)
1078 | pass
1079 | FFMPEG_PROCESSES[CHAT] = ""
1080 | if not group_call.is_connected:
1081 | await mp.start_call()
1082 | file_=playlist[0][5]
1083 | group_call.input_filename = os.path.join(
1084 | client.workdir,
1085 | DEFAULT_DOWNLOAD_DIR,
1086 | f"{file_}.raw"
1087 | )
1088 | await m_status.delete()
1089 | print(f"- START PLAYING: {playlist[0][1]}")
1090 | if EDIT_TITLE:
1091 | await mp.edit_title()
1092 | if not playlist:
1093 | k=await m.reply("Invalid File Given")
1094 | await mp.delete(k)
1095 | file.close()
1096 | try:
1097 | os.remove(ytplaylist)
1098 | except:
1099 | pass
1100 | return
1101 | for track in playlist[:2]:
1102 | await mp.download_audio(track)
1103 | file.close()
1104 | try:
1105 | os.remove(ytplaylist)
1106 | except:
1107 | pass
1108 | except Exception as e:
1109 | k=await m.reply(f"Errors Occured while reading playlist: {e}")
1110 | await mp.delete(k)
1111 | return
1112 | if len(playlist)>=25:
1113 | tplaylist=playlist[:25]
1114 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
1115 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
1116 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
1117 | for i, x in enumerate(tplaylist)
1118 | ])
1119 | else:
1120 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
1121 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
1122 | for i, x in enumerate(playlist)
1123 | ])
1124 | if m.chat.type == "private":
1125 | await m.reply_text(pl, disable_web_page_preview=True)
1126 | if LOG_GROUP:
1127 | await mp.send_playlist()
1128 | elif not LOG_GROUP and m.chat.type == "supergroup":
1129 | k=await m.reply_text(pl, disable_web_page_preview=True)
1130 | await mp.delete(k)
1131 | else:
1132 | k=await m.reply("Reply to a Playlist File Or Pass A YouTube Playlist Url along command.\nUse @GetPlayListBot To Get A PlayList File")
1133 | await mp.delete(k)
1134 | await mp.delete(m)
1135 |
1136 | @Client.on_message(filters.command(["export", f"export@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
1137 | async def export_play_list(client, message: Message):
1138 | if not playlist:
1139 | k=await message.reply_text(f"{emoji.NO_ENTRY} Playlist is Empty")
1140 | await mp.delete(k)
1141 | await mp.delete(message)
1142 | return
1143 |
1144 | file=f"{message.chat.id}_{message.message_id}.json"
1145 | with open(file, 'w+') as outfile:
1146 | json.dump(playlist, outfile, indent=4)
1147 | await client.send_document(chat_id=message.chat.id, document=file, file_name="PlayList.json", caption=f"Playlist\n\nNumber Of Songs: {len(playlist)}\n\nJoin [XTZ Bots](https://t.me/subin_works)")
1148 | await mp.delete(message)
1149 | try:
1150 | os.remove(file)
1151 | except:
1152 | pass
1153 |
1154 | @Client.on_message(filters.command(["import", f"import@{U}"]) & admin_filter & (filters.chat(CHAT) | filters.private))
1155 | async def import_play_list(client, m: Message):
1156 | group_call = mp.group_call
1157 | if not group_call.is_connected:
1158 | await mp.start_call()
1159 | if m.reply_to_message is not None and m.reply_to_message.document:
1160 | if m.reply_to_message.document.file_name != "PlayList.json":
1161 | k=await m.reply("Invalid PlayList file given. Use @GetPlayListBot to get a playlist file. Or Export your current Playlist using /export.")
1162 | await mp.delete(k)
1163 | await mp.delete(m)
1164 | return
1165 | myplaylist=await m.reply_to_message.download()
1166 | file=open(myplaylist)
1167 | try:
1168 | f=json.loads(file.read(), object_hook=lambda d: {int(k): v for k, v in d.items()})
1169 | for play in f:
1170 | playlist.append(play)
1171 | if len(playlist) == 1:
1172 | m_status = await m.reply_text(
1173 | f"{emoji.INBOX_TRAY} Downloading and Processing..."
1174 | )
1175 | await mp.download_audio(playlist[0])
1176 | if 1 in RADIO:
1177 | if group_call:
1178 | group_call.input_filename = ''
1179 | RADIO.remove(1)
1180 | RADIO.add(0)
1181 | process = FFMPEG_PROCESSES.get(CHAT)
1182 | if process:
1183 | try:
1184 | process.send_signal(SIGINT)
1185 | except subprocess.TimeoutExpired:
1186 | process.kill()
1187 | except Exception as e:
1188 | print(e)
1189 | pass
1190 | FFMPEG_PROCESSES[CHAT] = ""
1191 | if not group_call.is_connected:
1192 | await mp.start_call()
1193 | file_=playlist[0][5]
1194 | group_call.input_filename = os.path.join(
1195 | client.workdir,
1196 | DEFAULT_DOWNLOAD_DIR,
1197 | f"{file_}.raw"
1198 | )
1199 | await m_status.delete()
1200 | print(f"- START PLAYING: {playlist[0][1]}")
1201 | if EDIT_TITLE:
1202 | await mp.edit_title()
1203 | if not playlist:
1204 | k=await m.reply("Invalid File Given")
1205 | await mp.delete(k)
1206 | file.close()
1207 | try:
1208 | os.remove(myplaylist)
1209 | except:
1210 | pass
1211 | return
1212 | for track in playlist[:2]:
1213 | await mp.download_audio(track)
1214 | file.close()
1215 | try:
1216 | os.remove(myplaylist)
1217 | except:
1218 | pass
1219 | except Exception as e:
1220 | k=await m.reply(f"Errors Occured while reading playlist: {e}")
1221 | await mp.delete(k)
1222 | return
1223 | if len(playlist)>=25:
1224 | tplaylist=playlist[:25]
1225 | pl=f"Listing first 25 songs of total {len(playlist)} songs.\n"
1226 | pl += f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
1227 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}"
1228 | for i, x in enumerate(tplaylist)
1229 | ])
1230 | else:
1231 | pl = f"{emoji.PLAY_BUTTON} **Playlist**:\n" + "\n".join([
1232 | f"**{i}**. **🎸{x[1]}**\n 👤**Requested by:** {x[4]}\n"
1233 | for i, x in enumerate(playlist)
1234 | ])
1235 | if m.chat.type == "private":
1236 | await m.reply_text(pl, disable_web_page_preview=True)
1237 | if LOG_GROUP:
1238 | await mp.send_playlist()
1239 | elif not LOG_GROUP and m.chat.type == "supergroup":
1240 | k=await m.reply_text(pl, disable_web_page_preview=True)
1241 | await mp.delete(k)
1242 | else:
1243 | k=await m.reply("Reply to a previously exported playlist.")
1244 | await mp.delete(m)
1245 | await mp.delete(k)
1246 |
1247 |
1248 | @Client.on_message(filters.command(['upload', f'upload@{U}']) & (filters.chat(CHAT) | filters.private))
1249 | async def upload(client, message):
1250 | if not playlist:
1251 | k=await message.reply_text(f"{emoji.NO_ENTRY} No songs are playing")
1252 | await mp.delete(k)
1253 | await mp.delete(message)
1254 | return
1255 | url=playlist[0][2]
1256 | if playlist[0][3] == "telegram":
1257 | await client.send_audio(chat_id=message.chat.id, audio=url, caption=f"Song: {playlist[0][1]}\nUploaded Using [MusicPlayer](https://github.com/subinps/MusicPlayer)")
1258 | elif playlist[0][3] == "youtube":
1259 | file=GET_FILE[url]
1260 | thumb=GET_THUMB.get(url)
1261 | if thumb is None:
1262 | thumb="https://telegra.ph/file/181242eab5c4a74916d01.jpg"
1263 | response = requests.get(thumb, allow_redirects=True)
1264 | open(f"{playlist[0][5]}.jpeg", 'wb').write(response.content)
1265 | await message.reply_chat_action("upload_document")
1266 | dur=ffmpeg.probe(file)['format']['duration']
1267 | m=await message.reply_text(f"Starting Uploading {playlist[0][1]}...")
1268 | await client.send_audio(
1269 | chat_id=message.chat.id,
1270 | audio=file,
1271 | file_name=playlist[0][1],
1272 | thumb=f"{playlist[0][5]}.jpeg",
1273 | title=playlist[0][1],
1274 | duration=int(float(dur)),
1275 | performer="MusicPlayer",
1276 | caption=f"Song: [{playlist[0][1]}]({playlist[0][2]})\nUploaded Using [MusicPlayer](https://github.com/subinps/MusicPlayer)"
1277 | )
1278 | await m.delete()
1279 | else:
1280 | file=GET_FILE[url]
1281 | thumb=GET_THUMB.get(url)
1282 | if thumb is None:
1283 | thumb="https://telegra.ph/file/181242eab5c4a74916d01.jpg"
1284 | response = requests.get(thumb, allow_redirects=True)
1285 | open(f"{playlist[0][5]}.jpeg", 'wb').write(response.content)
1286 | await message.reply_chat_action("upload_document")
1287 | cmd=f"cp {file} {playlist[0][5]}.mp3"
1288 | os.system(cmd)
1289 | await asyncio.sleep(2)
1290 | m=await message.reply_text(f"Starting Uploading {playlist[0][1]}...")
1291 | dur=ffmpeg.probe(f"{playlist[0][5]}.mp3")['format']['duration']
1292 | await client.send_audio(
1293 | chat_id=message.chat.id,
1294 | audio=f"{playlist[0][5]}.mp3",
1295 | file_name=f"{playlist[0][1]}",
1296 | thumb=f"{playlist[0][5]}.jpeg",
1297 | title=playlist[0][1],
1298 | duration=int(float(dur)),
1299 | performer="MusicPlayer",
1300 | caption=f"Song: [{playlist[0][1]}]({playlist[0][2]})\nUploaded Using [MusicPlayer](https://github.com/subinps/MusicPlayer)"
1301 | )
1302 | await m.delete()
1303 | try:
1304 | os.remove(f"{playlist[0][5]}.mp3")
1305 | except:
1306 | pass
1307 |
1308 |
1309 | admincmds=["join", "unmute", "yplay", "mute", "leave", "clean", "vc", "pause", "resume", "stop", "skip", "radio", "stopradio", "replay", "restart", "volume", "shuffle", "clearplaylist", "cplay", "export", "import", f"export@{U}", f"import@{U}", f"yplay@{U}" f"cplay@{U}", f"clearplaylist@{U}", f"shuffle@{U}", f"volume@{U}", f"join@{U}", f"unmute@{U}", f"mute@{U}", f"leave@{U}", f"clean@{U}", f"vc@{U}", f"pause@{U}", f"resume@{U}", f"stop@{U}", f"skip@{U}", f"radio@{U}", f"stopradio@{U}", f"replay@{U}", f"restart@{U}"]
1310 |
1311 | @Client.on_message(filters.command(admincmds) & ~admin_filter & (filters.chat(CHAT) | filters.private))
1312 | async def notforu(_, m: Message):
1313 | k=await m.reply("Who the hell you are?.")
1314 | await mp.delete(k)
1315 | await mp.delete(m)
1316 | allcmd = ["play", "player", "splay", f"splay@{U}", f"play@{U}", f"player@{U}"] + admincmds
1317 |
1318 | @Client.on_message(filters.command(allcmd) & ~filters.chat(CHAT) & filters.group)
1319 | async def not_chat(_, m: Message):
1320 | buttons = [
1321 | [
1322 | InlineKeyboardButton('⚡️Make Own Bot', url='https://heroku.com/deploy?template=https://github.com/subinps/MusicPlayer'),
1323 | InlineKeyboardButton('🧩 Source Code', url='https://github.com/subinps/MusicPlayer'),
1324 | ],
1325 | [
1326 | InlineKeyboardButton('How to Make', url='https://youtu.be/iBK-5pP2eHM'),
1327 | InlineKeyboardButton('👨🏼🦯 Help', callback_data='help')
1328 | ]
1329 | ]
1330 | k=await m.reply("You can't use this bot in this group, for that you have to make your own bot from the [SOURCE CODE](https://github.com/subinps/MusicPlayer) below.", disable_web_page_preview=True, reply_markup=InlineKeyboardMarkup(buttons))
1331 | await mp.delete(m)
1332 |
--------------------------------------------------------------------------------