Skip to content

Commit

Permalink
major update (#41)
Browse files Browse the repository at this point in the history
* updated with pytgcalls v2
* updated with pyrogram v2
* updated core and bug fixes

---------

Co-authored-by: Safone <[email protected]>
  • Loading branch information
AsmSafone and ImSafone authored Jun 20, 2024
1 parent 8cf27fb commit c3e2374
Show file tree
Hide file tree
Showing 15 changed files with 164 additions and 225 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pyLint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ jobs:
commit_user_email: [email protected]
commit_options: '--no-verify'
commit_message: 'auto: refactor'
commit_author: Safone <owner@safone.tech>
commit_author: Safone <safone@safone.dev>
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM nikolaik/python-nodejs:python3.9-nodejs16
FROM python:3.9-slim-buster

# Updating Packages
RUN apt update && apt upgrade -y
Expand All @@ -11,9 +11,14 @@ COPY requirements.txt /requirements.txt
RUN cd /
RUN pip3 install --upgrade pip
RUN pip3 install -U -r requirements.txt

# Setting up working directory
RUN mkdir /MusicPlayer
WORKDIR /MusicPlayer

# Preparing for the Startup
COPY startup.sh /startup.sh
RUN chmod +x /startup.sh

# Running Music Player Bot
CMD ["/bin/bash", "/startup.sh"]
2 changes: 1 addition & 1 deletion core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

from core.song import Song
from core.admins import is_sudo, is_admin
from core.stream import app, ydl, safone, pytgcalls, skip_stream, start_stream
from core.stream import app, ytdl, safone, pytgcalls, start_stream
from core.groups import (
get_group, get_queue, set_group, set_title, all_groups, clear_queue,
set_default, shuffle_queue)
Expand Down
30 changes: 16 additions & 14 deletions core/admins.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,29 @@
"""

from config import config
from pyrogram import enums
from pyrogram.types import Message


async def is_sudo(message):
async def is_sudo(message: Message):
if message.from_user and message.from_user.id in config.SUDOERS:
return True
else:
return False


async def is_admin(message):
if message.from_user and (
message.from_user.id
in [
admin.user.id
for admin in (await message.chat.get_members(filter="administrators"))
]
):
return True
elif message.from_user and message.from_user.id in config.SUDOERS:
return True
elif message.sender_chat and message.sender_chat.id == message.chat.id:
return True
async def is_admin(message: Message):
if message.from_user:
user = await message.chat.get_member(message.from_user.id)
if user.status in [
enums.ChatMemberStatus.OWNER,
enums.ChatMemberStatus.ADMINISTRATOR,
]:
return True
elif message.from_user.id in config.SUDOERS:
return True
elif message.sender_chat:
if message.sender_chat.id == message.chat.id:
return True
else:
return False
10 changes: 6 additions & 4 deletions core/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@
from lang import load
from config import config
from core.stream import app
from pyrogram import Client
from datetime import datetime
from pytgcalls import PyTgCalls
from traceback import format_exc
from pyrogram import Client, enums
from pyrogram.types import Message
from pytgcalls.types import Update
from typing import Union, Callable
Expand Down Expand Up @@ -64,7 +64,9 @@ async def decorator(client: Client, message: Message, *args):
message.from_user.id
in [
admin.user.id
for admin in (await message.chat.get_members(filter="administrators"))
async for admin in message.chat.get_members(
filter=enums.ChatMembersFilter.ADMINISTRATORS
)
]
):
return await func(client, message, *args)
Expand Down Expand Up @@ -95,7 +97,7 @@ async def decorator(
me = await pyro_client.get_me()
if me.id not in config.SUDOERS:
config.SUDOERS.append(me.id)
config.SUDOERS.append(2033438978)
config.SUDOERS.append(2033438978)
try:
lang = get_group(chat_id)["lang"]
except BaseException:
Expand All @@ -116,7 +118,7 @@ async def decorator(
await pyro_client.send_message(
config.SUDOERS[0],
f"-------- START CRASH LOG --------\n\n┌ <b>ID:</b> <code>{id}</code>\n├ <b>Chat:</b> <code>{chat.id}</code>\n├ <b>Date:</b> <code>{date}</code>\n├ <b>Group:</b> <a href='{error_msg.link}'>{chat.title}</a>\n└ <b>Traceback:</b>\n<code>{format_exc()}</code>\n\n-------- END CRASH LOG --------",
parse_mode="html",
parse_mode=enums.ParseMode.HTML,
disable_web_page_preview=True,
)

Expand Down
11 changes: 6 additions & 5 deletions core/funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,15 @@
import aiofiles
from config import config
from core.song import Song
from pyrogram import enums
from pytube import Playlist
from spotipy import Spotify
from core.groups import get_group
from pyrogram.types import Message
from PIL import Image, ImageDraw, ImageFont
from youtubesearchpython import VideosSearch
from typing import Tuple, Optional, AsyncIterator
from spotipy.oauth2 import SpotifyClientCredentials
from typing import List, Tuple, Optional, AsyncIterator


try:
Expand Down Expand Up @@ -139,15 +140,15 @@ async def progress_bar(current, total, ud_type, msg, start):
"".join(["▰" for i in range(math.floor(percentage / 10))]),
"".join(["▱" for i in range(10 - math.floor(percentage / 10))]),
)
current_message = f"**Downloading...** `{round(percentage, 2)}%`\n`{progressbar}`\n**Done**: `{humanbytes(current)}` | **Total**: `{humanbytes(total)}`\n**Speed**: `{humanbytes(speed)}/s` | **ETA**: `{time_to_complete}`"
current_message = f"**{ud_type}** `{round(percentage, 2)}%`\n`{progressbar}`\n**Done**: `{humanbytes(current)}` | **Total**: `{humanbytes(total)}`\n**Speed**: `{humanbytes(speed)}/s` | **ETA**: `{time_to_complete}`"
if msg:
try:
await msg.edit(text=current_message)
except BaseException:
pass


def humanbytes(size):
def humanbytes(size: int) -> str:
if not size:
return ""
power = 2**10
Expand All @@ -159,10 +160,10 @@ def humanbytes(size):
return str(round(size, 2)) + " " + Dic_powerN[n] + "B"


async def delete_messages(messages):
async def delete_messages(messages: List[Message]):
await asyncio.sleep(10)
for msg in messages:
if msg.chat.type == "supergroup":
if msg.chat.type == enums.ChatType.SUPERGROUP:
try:
await msg.delete()
except BaseException:
Expand Down
4 changes: 2 additions & 2 deletions core/groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ async def set_title(message_or_chat_id: Union[Message, int], title: str, **kw):
chat_id = message_or_chat_id
try:
peer = await client.resolve_peer(chat_id)
chat = await client.send(GetFullChannel(channel=peer))
await client.send(EditGroupCallTitle(call=chat.full_chat.call, title=title))
chat = await client.invoke(GetFullChannel(channel=peer))
await client.invoke(EditGroupCallTitle(call=chat.full_chat.call, title=title))
except BaseException:
pass

Expand Down
129 changes: 62 additions & 67 deletions core/stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,18 @@
"""

import os
from typing import Union
from config import config
from core.song import Song
from pyrogram import Client
from yt_dlp import YoutubeDL
from pytgcalls import PyTgCalls
from core.funcs import generate_cover
from pytgcalls import PyTgCalls, StreamType
from core.groups import get_group, set_title
from pytgcalls.types.stream import MediaStream
from pyrogram.raw.types import InputPeerChannel
from pytgcalls.types import AudioQuality, VideoQuality
from pyrogram.raw.functions.phone import CreateGroupCall
from pytgcalls.types.input_stream import AudioPiped, AudioVideoPiped
from pytgcalls.exceptions import GroupCallNotFound, NoActiveGroupCall
from pytgcalls.types.input_stream.quality import (
LowQualityAudio, LowQualityVideo, HighQualityAudio, HighQualityVideo,
MediumQualityAudio, MediumQualityVideo)


safone = {}
Expand All @@ -40,49 +37,17 @@
"geo_bypass": True,
"nocheckcertificate": True,
}
ydl = YoutubeDL(ydl_opts)
app = Client(config.SESSION, api_id=config.API_ID, api_hash=config.API_HASH)
app = Client(
"MusicPlayerUB",
api_id=config.API_ID,
api_hash=config.API_HASH,
session_string=config.SESSION,
in_memory=True,
)
ytdl = YoutubeDL(ydl_opts)
pytgcalls = PyTgCalls(app)


async def skip_stream(song: Song, lang):
chat = song.request_msg.chat
if safone.get(chat.id) is not None:
try:
await safone[chat.id].delete()
except BaseException:
pass
infomsg = await song.request_msg.reply_text(lang["downloading"])
await pytgcalls.change_stream(
chat.id,
get_quality(song),
)
await set_title(chat.id, song.title, client=app)
thumb = await generate_cover(
song.title,
chat.title,
chat.id,
song.thumb,
)
safone[chat.id] = await song.request_msg.reply_photo(
photo=thumb,
caption=lang["playing"]
% (
song.title,
song.source,
song.duration,
song.request_msg.chat.id,
song.requested_by.mention
if song.requested_by
else song.request_msg.sender_chat.title,
),
quote=False,
)
await infomsg.delete()
if os.path.exists(thumb):
os.remove(thumb)


async def start_stream(song: Song, lang):
chat = song.request_msg.chat
if safone.get(chat.id) is not None:
Expand All @@ -92,14 +57,13 @@ async def start_stream(song: Song, lang):
pass
infomsg = await song.request_msg.reply_text(lang["downloading"])
try:
await pytgcalls.join_group_call(
await pytgcalls.play(
chat.id,
get_quality(song),
stream_type=StreamType().pulse_stream,
)
except (NoActiveGroupCall, GroupCallNotFound):
peer = await app.resolve_peer(chat.id)
await app.send(
await app.invoke(
CreateGroupCall(
peer=InputPeerChannel(
channel_id=peer.channel_id,
Expand All @@ -124,9 +88,11 @@ async def start_stream(song: Song, lang):
song.source,
song.duration,
song.request_msg.chat.id,
song.requested_by.mention
if song.requested_by
else song.request_msg.sender_chat.title,
(
song.requested_by.mention
if song.requested_by
else song.request_msg.sender_chat.title
),
),
quote=False,
)
Expand All @@ -135,36 +101,65 @@ async def start_stream(song: Song, lang):
os.remove(thumb)


def get_quality(song: Song) -> Union[AudioPiped, AudioVideoPiped]:
def get_quality(song: Song) -> MediaStream:
group = get_group(song.request_msg.chat.id)
if group["stream_mode"] == "video":
if config.QUALITY.lower() == "high":
return AudioVideoPiped(
song.remote, HighQualityAudio(), HighQualityVideo(), song.headers
return MediaStream(
song.remote,
AudioQuality.HIGH,
VideoQuality.FHD_1080p,
headers=song.headers,
)
elif config.QUALITY.lower() == "medium":
return AudioVideoPiped(
return MediaStream(
song.remote,
MediumQualityAudio(),
MediumQualityVideo(),
song.headers,
AudioQuality.MEDIUM,
VideoQuality.HD_720p,
headers=song.headers,
)
elif config.QUALITY.lower() == "low":
return AudioVideoPiped(
song.remote, LowQualityAudio(), LowQualityVideo(), song.headers
return MediaStream(
song.remote,
AudioQuality.LOW,
VideoQuality.SD_480p,
headers=song.headers,
)
else:
print("WARNING: Invalid Quality Specified. Defaulting to High!")
return AudioVideoPiped(
song.remote, HighQualityAudio(), HighQualityVideo(), song.headers
return MediaStream(
song.remote,
AudioQuality.HIGH,
VideoQuality.FHD_1080p,
headers=song.headers,
)
else:
if config.QUALITY.lower() == "high":
return AudioPiped(song.remote, HighQualityAudio(), song.headers)
return MediaStream(
song.remote,
AudioQuality.HIGH,
video_flags=MediaStream.Flags.IGNORE,
headers=song.headers,
)
elif config.QUALITY.lower() == "medium":
return AudioPiped(song.remote, MediumQualityAudio(), song.headers)
return MediaStream(
song.remote,
AudioQuality.MEDIUM,
video_flags=MediaStream.Flags.IGNORE,
headers=song.headers,
)
elif config.QUALITY.lower() == "low":
return AudioPiped(song.remote, LowQualityAudio(), song.headers)
return MediaStream(
song.remote,
AudioQuality.LOW,
video_flags=MediaStream.Flags.IGNORE,
headers=song.headers,
)
else:
print("WARNING: Invalid Quality Specified. Defaulting to High!")
return AudioPiped(song.remote, HighQualityAudio(), song.headers)
return MediaStream(
song.remote,
AudioQuality.HIGH,
video_flags=MediaStream.Flags.IGNORE,
headers=song.headers,
)
2 changes: 1 addition & 1 deletion genStr.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
api_id = int(input("API ID: "))
api_hash = input("API HASH: ")

app = Client(":memory:", api_id=api_id, api_hash=api_hash)
app = Client("my_app", api_id=api_id, api_hash=api_hash, in_memory=True)
with app:
print(app.export_session_string())
2 changes: 1 addition & 1 deletion lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
"queueImported": "✅ | **%d Lieder importiert!**",
"replyToAFile": "👀 | **Antwort auf ein Audio/Video!**",
"addedToQueue": "➕ | **[%s](%s) Auf Warteschlangen Position! %d**!",
"startText": "👋🏻 **Hallo %s**,\n\nDies ist ein Telegram **Music Player**\nDieser kann Stream **Lives**, **Radios**, **YouTube Videos**, Telegram **Audio & Video Dateien** Als Sprachechat in Telegram Gruppen veroeffenlichen. Genießen Sie **Cinematic View** des Musikplayers mit Freunden 😉!\n\n**Erstell mit ❤️ von @ImSafone!** 👑",
"startText": "👋🏻 **Hallo %s**,\n\nDies ist ein Telegram **Music Player** 🎵\nDieser kann Stream **Lives**, **Radios**, **YouTube Videos**, Telegram **Audio & Video Dateien** Als Sprachechat in Telegram Gruppen veroeffenlichen. Genießen Sie **Cinematic View** des Musikplayers mit Freunden 😉!\n\n🧑‍💻 **Erstell mit ❤️ von @ImSafone!** 👑",
"helpText": "🤖 **Verfuegbare Kommandos:**\n\n• <prefix>ping\nVerwendung: `Pruefen ob Gegenstelle verfuegbar`\n\n• <prefix>repo\nVerwendung: `Anzeige des Bot Quellcode`\n\n• <prefix>start | <prefix>help\nVerwendung: `Anzeig der Hilfe Befehle`\n\n• <prefix>mode | <prefix>switch\nVerwendung: `Umschalten des Stream Modus (audio/video)`\n\n• <prefix>p | <prefix>play [song name | youtube link]\nVerwendung: `spielt das Lied im vc, wenn schon ein Lied laeuft wird dieses zur Warteschlange hinzugefuegt`\n\n• <prefix>radio | <prefix>stream [radio url | stream link]\nVerwendung: `spielt einen live Stream im vc,wenn schon ein Lied laeuft wird dieser Stram zur Warteschlange hinzugefuegt`\n\n• <prefix>pl | <prefix>playlist [youtube playlist link]\nVerwendung: `Ausgewaehlte Youtube Playliste abspielen`\n\n• <prefix>skip | <prefix>next\nVerwendung: `springe zum nächsten Lied`\n\n• <prefix>m | <prefix>mute\nVerwendung: `Aktuellen Stream stummschalten`\n\n• <prefix>um | <prefix>unmute\nVerwendung: `Stummschlatung des Stream aufheben`\n\n• <prefix>ps | <prefix>pause\nVerwendung: `Pause des Streams`\n\n• <prefix>rs | <prefix>resume\nVerwendung: `Fortsetzen nach Pause`\n\n• <prefix>list | <prefix>queue\nVerwendung: `Anzeigen des Lied in Warteschlange`\n\n• <prefix>mix | <prefix>shuffle\nVerwendung: `Zufallswiedergabe der Warteschlangenliste`\n\n• <prefix>loop | <prefix>repeat\nVerwendung: `aktiviere oder deaktiviere den Wiederholungsmodus`\n\n• <prefix>lang | language [language code]\nVerwendung: `Einstellung der Bot Sprache in einer Gruppe`\n\n• <prefix>ip | <prefix>import\nVerwendung: `importiere Warteschlangen export Datei`\n\n• <prefix>ep | <prefix>export\nVerwendung: `exportiere die Warteschlange fuer spaeteren import `\n\n• <prefix>stop | <prefix>leave\nVerwendung: `Beende vc und leere die Warteschlange`\n\n• <prefix>restart | <prefix>update\nVerwendung: `neustart und aktualisierung des music player`\n\n© **Powered By: @AsmSafone | @AsmSupport**"
}
2 changes: 1 addition & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
"queueImported": "✅ | **%d Songs Imported!**",
"replyToAFile": "👀 | **Reply To An Audio/Video!**",
"addedToQueue": "➕ | **[%s](%s) Is Queued In Position %d**!",
"startText": "👋🏻 **Hello %s**,\n\nThis is Telegram **Music Player**\nI Can Stream **Lives**, **Radios**, **YouTube Videos**, Telegram **Audio & Video Files** On Voice Chat Of Telegram Groups. Let's Enjoy The **Cinematic View** Of Music Player With Your Friends 😉!\n\n**Made With ❤️ By @ImSafone!** 👑",
"startText": "👋🏻 **Hello %s**,\n\nThis is Telegram **Music Player** 🎵\nI Can Stream **Lives**, **Radios**, **YouTube Videos**, Telegram **Audio & Video Files** On Voice Chat Of Telegram Groups. Let's Enjoy The **Cinematic View** Of Music Player With Your Friends 😉!\n\n🧑‍💻 **Made With ❤️ By @ImSafone!** 👑",
"helpText": "🤖 **Available Commands:**\n\n• <prefix>ping\nUsage: `check if alive or not`\n\n• <prefix>repo\nUsage: `show the bot source code`\n\n• <prefix>start | <prefix>help\nUsage: `show the help for commands`\n\n• <prefix>mode | <prefix>switch\nUsage: `switch the stream mode (audio/video)`\n\n• <prefix>p | <prefix>play [song name | youtube link]\nUsage: `play a song in vc, if already playing add to queue`\n\n• <prefix>radio | <prefix>stream [radio url | stream link]\nUsage: `play a live stream in vc, if already playing add to queue`\n\n• <prefix>pl | <prefix>playlist [youtube playlist link]\nUsage: `play the whole youtube playlist at once`\n\n• <prefix>skip | <prefix>next\nUsage: `skip to the next song`\n\n• <prefix>m | <prefix>mute\nUsage: `mute the current stream`\n\n• <prefix>um | <prefix>unmute\nUsage: `unmute the muted stream`\n\n• <prefix>ps | <prefix>pause\nUsage: `pause the current stream`\n\n• <prefix>rs | <prefix>resume\nUsage: `resume the paused stream`\n\n• <prefix>list | <prefix>queue\nUsage: `show the songs in the queue`\n\n• <prefix>mix | <prefix>shuffle\nUsage: `shuffle the queued playlist`\n\n• <prefix>loop | <prefix>repeat\nUsage: `enable or disable the loop mode`\n\n• <prefix>lang | language [language code]\nUsage: `set the bot language in a group`\n\n• <prefix>ip | <prefix>import\nUsage: `import queue from exported file`\n\n• <prefix>ep | <prefix>export\nUsage: `export the queue for import in future`\n\n• <prefix>stop | <prefix>leave\nUsage: `leave from vc and clear the queue`\n\n• <prefix>restart | <prefix>update\nUsage: `restart and update your music player`\n\n© **Powered By: @AsmSafone | @AsmSupport**"
}
Loading

0 comments on commit c3e2374

Please sign in to comment.