Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
yt live stream fixed
custom quality support
clean code and typo fixes
  • Loading branch information
AsmSafone committed Dec 24, 2021
1 parent 79c6cee commit 3cf7780
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
*.env
.env
.vscode
__pycache__
*/__pycache__
Expand Down
79 changes: 22 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,66 +75,31 @@ $ sudo docker run musicplayer
- `SESSION`: Pyrogram string session. You can generate from [here](https://replit.com/@AsmSafone/genStr).
- `SUDOERS`: ID of sudo users (separate multiple ids with space).
- `PREFIX`: Commad prefixes (separate multiple prefix with space). Eg: `! /`
- `LANGUAGE`: An [available](#languages) bot language (can change it anytime). Default: `en`.
- `LANGUAGE`: An [available](#languages) bot language (can change it anytime). Default: `en`
- `CUSTOM_QUALITY`: Custom stream quality for the userbot in vc. Default: `high`

## 📄 <a name="commands"></a>Commands

```text
• <prefix>ping
Usage: Check if alive or not
• <prefix>start | <prefix>help
Usage: Show the help for commands
• <prefix>mode | <prefix>switch
Usage: Switch the stream mode (audio/video)
• <prefix>p | <prefix>play [song name | youtube link]
Usage: Play a song in vc, if already playing add to queue
• <prefix>radio | <prefix>stream [radio url | stream link]
Usage: Play a live stream in vc, if already playing add to queue
• <prefix>pl | <prefix>playlist [youtube playlist link]
Usage: Play the whole youtube playlist at once
• <prefix>skip | <prefix>next
Usage: Skip to the next song
• <prefix>m | <prefix>mute
Usage: Mute the current stream
• <prefix>um | <prefix>unmute
Usage: Unmute the muted stream
• <prefix>ps | <prefix>pause
Usage: Pause the current stream
• <prefix>rs | <prefix>resume
Usage: Resume the paused stream
• <prefix>list | <prefix>queue
Usage: Show the songs in the queue
• <prefix>mix | <prefix>shuffle
Usage: Shuflle the queued playlist
• <prefix>loop | <prefix>repeat
Usage: Enable or disable the loop mode
• <prefix>lang | language [language code]
Usage: Set the bot language in a group
• <prefix>ip | <prefix>import
Usage: Import queue from exported file
• <prefix>ep | <prefix>export
Usage: Export the queue for import in future
• <prefix>stop | <prefix>leave
Usage: Leave from vc and clear the queue
```
Command | Description
:--- | :---
• !ping | Check if alive or not
• !start / !help | Show the help for commands
• !mode / !switch | Switch the stream mode (audio/video)
• !p / !play [song name or youtube link] | Play a song in vc, if already playing add to queue
• !radio / !stream [radio url or stream link] | Play a live stream in vc, if already playing add to queue
• !pl / !playlist [youtube playlist link] | Play the whole youtube playlist at once
• !skip / !next | Skip to the next song
• !m / !mute | Mute the current stream
• !um / !unmute | Unmute the muted stream
• !ps / !pause | Pause the current stream
• !rs / !resume | Resume the paused stream
• !list / !queue | Show the songs in the queue
• !mix / !shuffle | Shuflle the queued playlist
• !loop / !repeat | Enable or disable the loop mode
• !lang / language [language code] | Set the bot language
• !ip / !import | Import queue from exported file
• !ep / !export | Export the queue for import in future
• !stop / !leave | Leave from vc and clear the queue

## 🗣 <a name="languages"></a>Languages

Expand Down
5 changes: 5 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@
"description": "An available bot language (read the README.md for more info)",
"value": "en",
"required": false
},
"CUSTOM_QUALITY": {
"description": "An available stream quality (read the README.md for more info)",
"value": "high",
"required": false
}
},
"formation": {
Expand Down
1 change: 1 addition & 0 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(self) -> None:
quit(0)
self.PREFIXES: list = os.environ.get("PREFIX", "!").split()
self.LANGUAGE: str = os.environ.get("LANGUAGE", "en").lower()
self.CUSTOM_QUALITY: str = os.environ.get("CUSTOM_QUALITY", "high").lower()


config = Config()
1 change: 1 addition & 0 deletions core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from core.funcs import (
app,
search,
safone,
pytgcalls,
extract_args,
skip_stream,
Expand Down
75 changes: 50 additions & 25 deletions core/funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
from PIL import Image, ImageDraw, ImageFont
from core.groups import get_group, set_title
from youtubesearchpython import VideosSearch
from typing import Optional, Tuple, AsyncIterator
from typing import Optional, Union, Tuple, AsyncIterator
from pytgcalls.types.input_stream import AudioPiped, AudioVideoPiped
from pytgcalls.types.input_stream.quality import HighQualityAudio, HighQualityVideo
from pytgcalls.types.input_stream.quality import HighQualityAudio, HighQualityVideo, MediumQualityAudio, MediumQualityVideo, LowQualityAudio, LowQualityVideo


safone = {}
Expand All @@ -58,6 +58,10 @@ def search(message: Message) -> Optional[Song]:
if message.reply_to_message:
if message.reply_to_message.audio:
query = message.reply_to_message.audio.title
elif message.reply_to_message.video:
query = message.reply_to_message.video.file_name
elif message.reply_to_message.document:
query = message.reply_to_message.document.file_name
else:
query = message.reply_to_message.text
else:
Expand Down Expand Up @@ -96,6 +100,46 @@ def extract_args(text: str) -> str:
return text.split(" ", 1)[1]


def get_quality(song: Song) -> Union[AudioPiped, AudioVideoPiped]:
group = get_group(song.request_msg.chat.id)
if group["is_video"]:
if config.CUSTOM_QUALITY.lower() == 'high':
return AudioVideoPiped(
song.remote_url, HighQualityAudio(), HighQualityVideo(), song.headers
)
elif config.CUSTOM_QUALITY.lower() == 'medium':
return AudioVideoPiped(
song.remote_url, MediumQualityAudio(), MediumQualityVideo(), song.headers
)
elif config.CUSTOM_QUALITY.lower() == 'low':
return AudioVideoPiped(
song.remote_url, LowQualityAudio(), LowQualityVideo(), song.headers
)
else:
print("Invalid Quality Specified. Defaulting to High!")
return AudioVideoPiped(
song.remote_url, HighQualityAudio(), HighQualityVideo(), song.headers
)
else:
if config.CUSTOM_QUALITY.lower() == 'high':
return AudioPiped(
song.remote_url, HighQualityAudio(), song.headers
)
elif config.CUSTOM_QUALITY.lower() == 'medium':
return AudioPiped(
song.remote_url, MediumQualityAudio(), song.headers
)
elif config.CUSTOM_QUALITY.lower() == 'low':
return AudioPiped(
song.remote_url, LowQualityAudio(), song.headers
)
else:
print("Invalid Quality Specified. Defaulting to High!")
return AudioPiped(
song.remote_url, HighQualityAudio(), song.headers
)


async def delete_messages(messages):
await asyncio.sleep(10)
for msg in messages:
Expand All @@ -113,19 +157,10 @@ async def skip_stream(song: Song, lang):
await safone[chat.id].delete()
except:
pass
group = get_group(chat.id)
infomsg = await song.request_msg.reply_text(lang["downloading"])
if group["is_video"]:
await pytgcalls.change_stream(
await pytgcalls.change_stream(
chat.id,
AudioVideoPiped(
song.remote_url, HighQualityAudio(), HighQualityVideo(), song.headers
),
)
else:
await pytgcalls.change_stream(
chat.id,
AudioPiped(song.remote_url, HighQualityAudio(), song.headers),
get_quality(song),
)
await set_title(chat.id, song.title, client=app)
thumb = await generate_cover(
Expand Down Expand Up @@ -159,20 +194,10 @@ async def start_stream(song: Song, lang):
await safone[chat.id].delete()
except:
pass
group = get_group(chat.id)
infomsg = await song.request_msg.reply_text(lang["downloading"])
if group["is_video"]:
await pytgcalls.join_group_call(
chat.id,
AudioVideoPiped(
song.remote_url, HighQualityAudio(), HighQualityVideo(), song.headers
),
stream_type=StreamType().pulse_stream,
)
else:
await pytgcalls.join_group_call(
await pytgcalls.join_group_call(
chat.id,
AudioPiped(song.remote_url, HighQualityAudio(), song.headers),
get_quality(song),
stream_type=StreamType().pulse_stream,
)
await set_title(chat.id, song.title, client=app)
Expand Down
6 changes: 2 additions & 4 deletions core/song.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,11 @@ async def parse(self) -> Tuple[bool, str]:
except json.JSONDecodeError:
self._retries += 1
return await self.parse()
check_audio = await self.check_remote_url(video["url"], video["http_headers"])
check_video = await self.check_remote_url(video["url"], video["http_headers"])
check_image = await self.check_remote_url(
video["thumbnail"], video["http_headers"]
)
if check_audio and check_image:
if video["is_live"]:
return (False, "LIVE_STREAM_ERROR")
if check_video and check_image:
self.title = self._escape(video["title"])
self.duration = str(timedelta(seconds=video["duration"]))
self.thumb = video["thumbnail"]
Expand Down
23 changes: 23 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import os
import json
import asyncio
from config import config
from core.song import Song
from pyrogram import filters
Expand All @@ -26,6 +27,7 @@
from core import (
app,
search,
safone,
pytgcalls,
set_group,
set_title,
Expand Down Expand Up @@ -566,6 +568,11 @@ async def stream_end(_, update: Update, lang):
set_group(chat_id, now_playing=next_song)
await skip_stream(next_song, lang)
else:
if safone.get(chat_id) is not None:
try:
await safone[chat_id].delete()
except:
pass
await set_title(chat_id, "", client=app)
set_group(chat_id, is_playing=False, now_playing=None)
await pytgcalls.leave_group_call(chat_id)
Expand All @@ -575,6 +582,11 @@ async def stream_end(_, update: Update, lang):
@handle_error
async def closed_vc(_, chat_id: int):
if chat_id not in all_groups():
if safone.get(chat_id) is not None:
try:
await safone[chat_id].delete()
except:
pass
await set_title(chat_id, "", client=app)
set_group(chat_id, now_playing=None, is_playing=False)
clear_queue(chat_id)
Expand All @@ -584,6 +596,11 @@ async def closed_vc(_, chat_id: int):
@handle_error
async def kicked_vc(_, chat_id: int):
if chat_id not in all_groups():
if safone.get(chat_id) is not None:
try:
await safone[chat_id].delete()
except:
pass
await set_title(chat_id, "", client=app)
set_group(chat_id, now_playing=None, is_playing=False)
clear_queue(chat_id)
Expand All @@ -593,9 +610,15 @@ async def kicked_vc(_, chat_id: int):
@handle_error
async def left_vc(_, chat_id: int):
if chat_id not in all_groups():
if safone.get(chat_id) is not None:
try:
await safone[chat_id].delete()
except:
pass
await set_title(chat_id, "", client=app)
set_group(chat_id, now_playing=None, is_playing=False)
clear_queue(chat_id)


print("Music Player UserBot Started!")
pytgcalls.run()
24 changes: 24 additions & 0 deletions sample.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# api id and api hash (my.telegram.org)
# required
API_ID=''
API_HASH=''

# pyrogram session string (@genstr_robot)
# required
SESSION=''

# sudo user ids (separate with space)
# optional
SUDOERS=''

# command prefix (separate with space)
# optional
PREFIX='!'

# default language for the bot in groups
# optional
LANGUAGE='en'

# custom stream quality for the bot in groups
# optional
CUSTOM_QUALITY='high'

0 comments on commit 3cf7780

Please sign in to comment.