├── 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 | [![Deploy](https://www.herokucdn.com/deploy/button.svg)](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 [![GenerateStringName](https://img.shields.io/badge/repl.it-generateStringName-yellowgreen)](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 | --------------------------------------------------------------------------------