<filename>DaisyXMusic/modules/song.py<gh_stars>1-10
"""

MIT License

Copyright (C) 2021 KennedyXMusic

This file is part of https://github.com/KennedyProject/KennedyXMusic

Permission is hereby granted, free of charge, to any person obtaining a copy

of this software and associated documentation files (the "Software"), to deal

in the Software without restriction, including without limitation the rights

to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

copies of the Software, and to permit persons to whom the Software is

furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all

copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

SOFTWARE.

"""

from __future__ import unicode_literals

import asyncio

import math

import os

import time

import aiofiles

import aiohttp

import requests

import wget

import yt_dlp

from io import BytesIO

from random import randint

from urllib.parse import urlparse

from pyrogram import Client, filters

from pyrogram.errors import FloodWait, MessageNotModified

from pyrogram.types import Message

from yt_dlp import YoutubeDL

from youtube_search import YoutubeSearch

from youtubesearchpython import SearchVideos

from DaisyXMusic.helpers.filters import command

from DaisyXMusic.config import DURATION_LIMIT, BOT_USERNAME, BOT_NAME

@Client.on_message(filters.command(["song", f"song@{BOT_USERNAME}"]) & ~filters.channel)

def song(client, message):

    user_id = message.from_user.id

    user_name = message.from_user.first_name

    rpk = "[" + user_name + "](tg://user?id=" + str(user_id) + ")"

    query = "".join(" " + str(i) for i in message.command[1:])

    print(query)

    m = message.reply("🔎 **Searching**")

    ydl_opts = {"format": "bestaudio[ext=m4a]"}

    try:

        results = YoutubeSearch(query, max_results=1).to_dict()

        link = f"https://www.youtube.com{results[0]['url_suffix']}"

        # print(results)

        title = results[0]["title"]

        thumbnail = results[0]["thumbnails"][0]

        thumb_name = f"thumb{title}.jpg"

        thumb = requests.get(thumbnail, allow_redirects=True)

        open(thumb_name, "wb").write(thumb.content)

        duration = results[0]["duration"]

        results[0]["url_suffix"]

        results[0]["views"]

    except Exception as e:

        m.edit("❌ **Song Not found.**\n\n**Try Entering a clearer song title.**")

        print(str(e))

        return

    m.edit("📥 **Downloading**")

    try:

        with yt_dlp.YoutubeDL(ydl_opts) as ydl:

            info_dict = ydl.extract_info(link, download=False)

            audio_file = ydl.prepare_filename(info_dict)

            ydl.process_info(info_dict)

        rep = f"""

**🏷 Title :** [{title}]({link})

**⏱️ Duration :** {duration}

**👁 Viewer :** {results[0]['views']}

**🤖 Uploader :** [{BOT_NAME}](https://t.me/{BOT_USERNAME})

**👤 Requested by :** {rpk}

"""

        secmul, dur, dur_arr = 1, 0, duration.split(":")

        for i in range(len(dur_arr) - 1, -1, -1):

            dur += int(dur_arr[i]) * secmul

            secmul *= 60

        message.reply_audio(

            audio_file,

            caption=rep,

            thumb=thumb_name,

            parse_mode="md",

            title=title,

            duration=dur,

        )

        m.delete()

    except Exception as e:

        m.edit("❌ **Error**")

        print(e)

    try:

        os.remove(audio_file)

        os.remove(thumb_name)

    except Exception as e:

        print(e)

def get_text(message: Message) -> [None, str]:

    text_to_return = message.text

    if message.text is None:

        return None

    if " " not in text_to_return:

        return None

    try:

        return message.text.split(None, 1)[1]

    except IndexError:

        return None

def humanbytes(size):

    if not size:

        return ""

    power = 2 ** 10

    raised_to_pow = 0

    dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}

    while size > power:

        size /= power

        raised_to_pow += 1

    return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B"

async def progress(current, total, message, start, type_of_ps, file_name=None):

    now = time.time()

    diff = now - start

    if round(diff % 10.00) == 0 or current == total:

        percentage = current * 100 / total

        speed = current / diff

        elapsed_time = round(diff) * 1000

        if elapsed_time == 0:

            return

        time_to_completion = round((total - current) / speed) * 1000

        estimated_total_time = elapsed_time + time_to_completion

        progress_str = "{0}{1} {2}%\n".format(

            "".join("🔴" for i in range(math.floor(percentage / 10))),

            "".join("🔘" for i in range(10 - math.floor(percentage / 10))),

            round(percentage, 2),

        )

        tmp = progress_str + "{0} of {1}\nETA: {2}".format(

            humanbytes(current), humanbytes(total), time_formatter(estimated_total_time)

        )

        if file_name:

            try:

                await message.edit(

                    "{}\n**File Name:** `{}`\n{}".format(type_of_ps, file_name, tmp)

                )

            except FloodWait as e:

                await asyncio.sleep(e.x)

            except MessageNotModified:

                pass

        else:

            try:

                await message.edit("{}\n{}".format(type_of_ps, tmp))

            except FloodWait as e:

                await asyncio.sleep(e.x)

            except MessageNotModified:

                pass

def get_user(message: Message, text: str) -> [int, str, None]:

    asplit = None if text is None else text.split(" ", 1)

    user_s = None

    reason_ = None

    if message.reply_to_message:

        user_s = message.reply_to_message.from_user.id

        reason_ = text or None

    elif asplit is None:

        return None, None

    elif len(asplit[0]) > 0:

        user_s = int(asplit[0]) if asplit[0].isdigit() else asplit[0]

        if len(asplit) == 2:

            reason_ = asplit[1]

    return user_s, reason_

def get_readable_time(seconds: int) -> int:

    count = 0

    ping_time = ""

    time_list = []

    time_suffix_list = ["d", "m", "j", "hari"]

    while count < 4:

        count += 1

        remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)

        if seconds == 0 and remainder == 0:

            break

        time_list.append(int(result))

        seconds = int(remainder)

    for x in range(len(time_list)):

        time_list[x] = str(time_list[x]) + time_suffix_list[x]

    if len(time_list) == 4:

        ping_time += time_list.pop() + ", "

    time_list.reverse()

    ping_time += ":".join(time_list)

    return ping_time

def time_formatter(milliseconds: int) -> str:

    seconds, milliseconds = divmod(int(milliseconds), 1000)

    minutes, seconds = divmod(seconds, 60)

    hours, minutes = divmod(minutes, 60)

    days, hours = divmod(hours, 24)

    tmp = (

        ((str(days) + " day(s), ") if days else "")

        + ((str(hours) + " hour(s), ") if hours else "")

        + ((str(minutes) + " minute(s), ") if minutes else "")

        + ((str(seconds) + " second(s), ") if seconds else "")

        + ((str(milliseconds) + " millisecond(s), ") if milliseconds else "")

    )

    return tmp[:-2]

ydl_opts = {

    "format": "bestaudio/best",

    "writethumbnail": True,

    "postprocessors": [

        {

            "key": "FFmpegExtractAudio",

            "preferredcodec": "mp3",

            "preferredquality": "192",

        }

    ],

}

def get_file_extension_from_url(url):

    url_path = urlparse(url).path

    basename = os.path.basename(url_path)

    return basename.split(".")[-1]

# Funtion To Download Song

async def download_song(url):

    song_name = f"{randint(6969, 6999)}.mp3"

    async with aiohttp.ClientSession() as session:

        async with session.get(url) as resp:

            if resp.status == 200:

                f = await aiofiles.open(song_name, mode="wb")

                await f.write(await resp.read())

                await f.close()

    return song_name

is_downloading = False

def time_to_seconds(time):

    stringt = str(time)

    return sum(int(x) * 60 ** i for i, x in enumerate(reversed(stringt.split(":"))))

@Client.on_message(command(["video", f"video@{BOT_USERNAME}"]))

async def ytmusic(client, message: Message):

    global is_downloading

    if is_downloading:

        await message.reply_text(

            "**Downloadan yang lain sedang berlangsung, coba lagi nanti**"

        )

        return

    urlissed = get_text(message)

    pablo = await client.send_message(

        message.chat.id, f"`Getting {urlissed} From YouTube. Please wait!`"

    )

    if not urlissed:

        await pablo.edit("**Syntax error** type /help for more info!`")

        return

    search = SearchVideos(f"{urlissed}", offset=1, mode="dict", max_results=1)

    mi = search.result()

    mio = mi["search_result"]

    mo = mio[0]["link"]

    thum = mio[0]["title"]

    fridayz = mio[0]["id"]

    thums = mio[0]["channel"]

    kekme = f"https://img.youtube.com/vi/{fridayz}/hqdefault.jpg"

    await asyncio.sleep(0.6)

    url = mo

    sedlyf = wget.download(kekme)

    opts = {

        "format": "best",

        "addmetadata": True,

        "key": "FFmpegMetadata",

        "prefer_ffmpeg": True,

        "geo_bypass": True,

        "nocheckcertificate": True,

        "postprocessors": [{"key": "FFmpegVideoConvertor", "preferedformat": "mp4"}],

        "outtmpl": "%(id)s.mp4",

        "logtostderr": False,

        "quiet": True,

    }

    try:

        is_downloading = True

        with yt_dlp.YoutubeDL(opts) as ytdl:

            infoo = ytdl.extract_info(url, False)

            duration = round(infoo["duration"] / 60)

            if duration > DURATION_LIMIT:

                await pablo.edit(

                    f"❌ **Videos longer than {DURATION_LIMIT} minutes are not allowed, videos you want to download are {duration} minutes**"

                )

                is_downloading = False

                return

            ytdl_data = ytdl.extract_info(url, download=True)

    except Exception:

        # await pablo.edit(event, f"**Failed To Download** \n**Error :** `{str(e)}`")

        is_downloading = False

        return

    c_time = time.time()

    file_stark = f"{ytdl_data['id']}.mp4"

    capy = f"**Title ➠** [{thum}]({mo}) \n**Channel ➠ ** {thums} \n**Requested for ➠** {urlissed} "

    await client.send_video(

        message.chat.id,

        video=open(file_stark, "rb"),

        duration=int(ytdl_data["duration"]),

        file_name=str(ytdl_data["title"]),

        thumb=sedlyf,

        caption=capy,

        supports_streaming=True,

        progress=progress,

        progress_args=(

            pablo,

            c_time,

            f"**Uploading** `{urlissed}` **From YouTube Music!**",

            file_stark,

        ),

    )

    await pablo.delete()

    is_downloading = False

    for files in (sedlyf, file_stark):

        if files and os.path.exists(files):

            os.remove(files)

async def download_song(url):

    async with session.get(url) as resp:

        song = await resp.read()

    song = BytesIO(song)

    song.name = "a.mp3"

    return song

@Client.on_message(command(["saavn", f"saavn@{BOT_USERNAME}"]))

async def jssong(_, message):

    global is_downloading

    if len(message.command) < 2:

        return await message.reply_text("/saavn requires an argument.")

    if is_downloading:

        return await message.reply_text("Another download is in progress, try again after sometime.")

    is_downloading = True

    text = message.text.split(None, 1)[1]

    m = await message.reply_text("Searching...")

    try:

        songs = await arq.saavn(text)

        if not songs.ok:

            await m.edit(songs.result)

            is_downloading = False

            return

        sname = songs.result[0].song

        slink = songs.result[0].media_url

        ssingers = songs.result[0].singers

        sduration = songs.result[0].duration

        await m.edit("Downloading")

        song = await download_song(slink)

        await m.edit("Uploading")

        await message.reply_audio(

            audio=song,

            title=sname,

            performer=ssingers,

            duration=sduration,

        )

        await m.delete()

    except Exception as e:

        is_downloading = False

        return await m.edit(str(e))

    is_downloading = False

    song.close()

<filename>DaisyXMusic/modules/song.py<gh_stars>1-10
"""

MIT License

Copyright (C) 2021 KennedyXMusic

This file is part of https://github.com/KennedyProject/KennedyXMusic

Permission is hereby granted, free of charge, to any person obtaining a copy

of this software and associated documentation files (the "Software"), to deal

in the Software without restriction, including without limitation the rights

to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

copies of the Software, and to permit persons to whom the Software is

furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all

copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR

IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,

FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE

AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER

LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,

OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE

SOFTWARE.

"""

from __future__ import unicode_literals

import asyncio

import math

import os

import time

import aiofiles

import aiohttp

import requests

import wget

import yt_dlp

from io import BytesIO

from random import randint

from urllib.parse import urlparse

from pyrogram import Client, filters

from pyrogram.errors import FloodWait, MessageNotModified

from pyrogram.types import Message

from yt_dlp import YoutubeDL

from youtube_search import YoutubeSearch

from youtubesearchpython import SearchVideos

from DaisyXMusic.helpers.filters import command

from DaisyXMusic.config import DURATION_LIMIT, BOT_USERNAME, BOT_NAME

@Client.on_message(filters.command(["song", f"song@{BOT_USERNAME}"]) & ~filters.channel)

def song(client, message):

    user_id = message.from_user.id

    user_name = message.from_user.first_name

    rpk = "[" + user_name + "](tg://user?id=" + str(user_id) + ")"

    query = "".join(" " + str(i) for i in message.command[1:])

    print(query)

    m = message.reply("🔎 **Searching**")

    ydl_opts = {"format": "bestaudio[ext=m4a]"}

    try:

        results = YoutubeSearch(query, max_results=1).to_dict()

        link = f"https://www.youtube.com{results[0]['url_suffix']}"

        # print(results)

        title = results[0]["title"]

        thumbnail = results[0]["thumbnails"][0]

        thumb_name = f"thumb{title}.jpg"

        thumb = requests.get(thumbnail, allow_redirects=True)

        open(thumb_name, "wb").write(thumb.content)

        duration = results[0]["duration"]

        results[0]["url_suffix"]

        results[0]["views"]

    except Exception as e:

        m.edit("❌ **Song Not found.**\n\n**Try Entering a clearer song title.**")

        print(str(e))

        return

    m.edit("📥 **Downloading**")

    try:

        with yt_dlp.YoutubeDL(ydl_opts) as ydl:

            info_dict = ydl.extract_info(link, download=False)

            audio_file = ydl.prepare_filename(info_dict)

            ydl.process_info(info_dict)

        rep = f"""

**🏷 Title :** [{title}]({link})

**⏱️ Duration :** {duration}

**👁 Viewer :** {results[0]['views']}

**🤖 Uploader :** [{BOT_NAME}](https://t.me/{BOT_USERNAME})

**👤 Requested by :** {rpk}

"""

        secmul, dur, dur_arr = 1, 0, duration.split(":")

        for i in range(len(dur_arr) - 1, -1, -1):

            dur += int(dur_arr[i]) * secmul

            secmul *= 60

        message.reply_audio(

            audio_file,

            caption=rep,

            thumb=thumb_name,

            parse_mode="md",

            title=title,

            duration=dur,

        )

        m.delete()

    except Exception as e:

        m.edit("❌ **Error**")

        print(e)

    try:

        os.remove(audio_file)

        os.remove(thumb_name)

    except Exception as e:

        print(e)

def get_text(message: Message) -> [None, str]:

    text_to_return = message.text

    if message.text is None:

        return None

    if " " not in text_to_return:

        return None

    try:

        return message.text.split(None, 1)[1]

    except IndexError:

        return None

def humanbytes(size):

    if not size:

        return ""

    power = 2 ** 10

    raised_to_pow = 0

    dict_power_n = {0: "", 1: "Ki", 2: "Mi", 3: "Gi", 4: "Ti"}

    while size > power:

        size /= power

        raised_to_pow += 1

    return str(round(size, 2)) + " " + dict_power_n[raised_to_pow] + "B"

async def progress(current, total, message, start, type_of_ps, file_name=None):

    now = time.time()

    diff = now - start

    if round(diff % 10.00) == 0 or current == total:

        percentage = current * 100 / total

        speed = current / diff

        elapsed_time = round(diff) * 1000

        if elapsed_time == 0:

            return

        time_to_completion = round((total - current) / speed) * 1000

        estimated_total_time = elapsed_time + time_to_completion

        progress_str = "{0}{1} {2}%\n".format(

            "".join("🔴" for i in range(math.floor(percentage / 10))),

            "".join("🔘" for i in range(10 - math.floor(percentage / 10))),

            round(percentage, 2),

        )

        tmp = progress_str + "{0} of {1}\nETA: {2}".format(

            humanbytes(current), humanbytes(total), time_formatter(estimated_total_time)

        )

        if file_name:

            try:

                await message.edit(

                    "{}\n**File Name:** `{}`\n{}".format(type_of_ps, file_name, tmp)

                )

            except FloodWait as e:

                await asyncio.sleep(e.x)

            except MessageNotModified:

                pass

        else:

            try:

                await message.edit("{}\n{}".format(type_of_ps, tmp))

            except FloodWait as e:

                await asyncio.sleep(e.x)

            except MessageNotModified:

                pass

def get_user(message: Message, text: str) -> [int, str, None]:

    asplit = None if text is None else text.split(" ", 1)

    user_s = None

    reason_ = None

    if message.reply_to_message:

        user_s = message.reply_to_message.from_user.id

        reason_ = text or None

    elif asplit is None:

        return None, None

    elif len(asplit[0]) > 0:

        user_s = int(asplit[0]) if asplit[0].isdigit() else asplit[0]

        if len(asplit) == 2:

            reason_ = asplit[1]

    return user_s, reason_

def get_readable_time(seconds: int) -> int:

    count = 0

    ping_time = ""

    time_list = []

    time_suffix_list = ["d", "m", "j", "hari"]

    while count < 4:

        count += 1

        remainder, result = divmod(seconds, 60) if count < 3 else divmod(seconds, 24)

        if seconds == 0 and remainder == 0:

            break

        time_list.append(int(result))

        seconds = int(remainder)

    for x in range(len(time_list)):

        time_list[x] = str(time_list[x]) + time_suffix_list[x]

    if len(time_list) == 4:

        ping_time += time_list.pop() + ", "

    time_list.reverse()

    ping_time += ":".join(time_list)

    return ping_time

def time_formatter(milliseconds: int) -> str:

    seconds, milliseconds = divmod(int(milliseconds), 1000)

    minutes, seconds = divmod(seconds, 60)

    hours, minutes = divmod(minutes, 60)

    days, hours = divmod(hours, 24)

    tmp = (

        ((str(days) + " day(s), ") if days else "")

        + ((str(hours) + " hour(s), ") if hours else "")

        + ((str(minutes) + " minute(s), ") if minutes else "")

        + ((str(seconds) + " second(s), ") if seconds else "")

        + ((str(milliseconds) + " millisecond(s), ") if milliseconds else "")

    )

    return tmp[:-2]

ydl_opts = {

    "format": "bestaudio/best",

    "writethumbnail": True,

    "postprocessors": [

        {

            "key": "FFmpegExtractAudio",

            "preferredcodec": "mp3",

            "preferredquality": "192",

        }

    ],

}

def get_file_extension_from_url(url):

    url_path = urlparse(url).path

    basename = os.path.basename(url_path)

    return basename.split(".")[-1]

# Funtion To Download Song

async def download_song(url):

    song_name = f"{randint(6969, 6999)}.mp3"

    async with aiohttp.ClientSession() as session:

        async with session.get(url) as resp:

            if resp.status == 200:

                f = await aiofiles.open(song_name, mode="wb")

                await f.write(await resp.read())

                await f.close()

    return song_name

is_downloading = False

def time_to_seconds(time):

    stringt = str(time)

    return sum(int(x) * 60 ** i for i, x in enumerate(reversed(stringt.split(":"))))

@Client.on_message(command(["video", f"video@{BOT_USERNAME}"]))

async def ytmusic(client, message: Message):

    global is_downloading

    if is_downloading:

        await message.reply_text(

            "**Downloadan yang lain sedang berlangsung, coba lagi nanti**"

        )

        return

    urlissed = get_text(message)

    pablo = await client.send_message(

        message.chat.id, f"`Getting {urlissed} From YouTube. Please wait!`"

    )

    if not urlissed:

        await pablo.edit("**Syntax error** type /help for more info!`")

        return

    search = SearchVideos(f"{urlissed}", offset=1, mode="dict", max_results=1)

    mi = search.result()

    mio = mi["search_result"]

    mo = mio[0]["link"]

    thum = mio[0]["title"]

    fridayz = mio[0]["id"]

    thums = mio[0]["channel"]

    kekme = f"https://img.youtube.com/vi/{fridayz}/hqdefault.jpg"

    await asyncio.sleep(0.6)

    url = mo

    sedlyf = wget.download(kekme)

    opts = {

        "format": "best",

        "addmetadata": True,

        "key": "FFmpegMetadata",

        "prefer_ffmpeg": True,

        "geo_bypass": True,

        "nocheckcertificate": True,

        "postprocessors": [{"key": "FFmpegVideoConvertor", "preferedformat": "mp4"}],

        "outtmpl": "%(id)s.mp4",

        "logtostderr": False,

        "quiet": True,

    }

    try:

        is_downloading = True

        with yt_dlp.YoutubeDL(opts) as ytdl:

            infoo = ytdl.extract_info(url, False)

            duration = round(infoo["duration"] / 60)

            if duration > DURATION_LIMIT:

                await pablo.edit(

                    f"❌ **Videos longer than {DURATION_LIMIT} minutes are not allowed, videos you want to download are {duration} minutes**"

                )

                is_downloading = False

                return

            ytdl_data = ytdl.extract_info(url, download=True)

    except Exception:

        # await pablo.edit(event, f"**Failed To Download** \n**Error :** `{str(e)}`")

        is_downloading = False

        return

    c_time = time.time()

    file_stark = f"{ytdl_data['id']}.mp4"

    capy = f"**Title ➠** [{thum}]({mo}) \n**Channel ➠ ** {thums} \n**Requested for ➠** {urlissed} "

    await client.send_video(

        message.chat.id,

        video=open(file_stark, "rb"),

        duration=int(ytdl_data["duration"]),

        file_name=str(ytdl_data["title"]),

        thumb=sedlyf,

        caption=capy,

        supports_streaming=True,

        progress=progress,

        progress_args=(

            pablo,

            c_time,

            f"**Uploading** `{urlissed}` **From YouTube Music!**",

            file_stark,

        ),

    )

    await pablo.delete()

    is_downloading = False

    for files in (sedlyf, file_stark):

        if files and os.path.exists(files):

            os.remove(files)

async def download_song(url):

    async with session.get(url) as resp:

        song = await resp.read()

    song = BytesIO(song)

    song.name = "a.mp3"

    return song

@Client.on_message(command(["saavn", f"saavn@{BOT_USERNAME}"]))

async def jssong(_, message):

    global is_downloading

    if len(message.command) < 2:

        return await message.reply_text("/saavn requires an argument.")

    if is_downloading:

        return await message.reply_text("Another download is in progress, try again after sometime.")

    is_downloading = True

    text = message.text.split(None, 1)[1]

    m = await message.reply_text("Searching...")

    try:

        songs = await arq.saavn(text)

        if not songs.ok:

            await m.edit(songs.result)

            is_downloading = False

            return

        sname = songs.result[0].song

        slink = songs.result[0].media_url

        ssingers = songs.result[0].singers

        sduration = songs.result[0].duration

        await m.edit("Downloading")

        song = await download_song(slink)

        await m.edit("Uploading")

        await message.reply_audio(

            audio=song,

            title=sname,

            performer=ssingers,

            duration=sduration,

        )

        await m.delete()

    except Exception as e:

        is_downloading = False

        return await m.edit(str(e))

    is_downloading = False

    song.close()

MIT License  Copyright (C) 2021 KennedyXMusic  This file is part of https://github.com/KennedyProject/KennedyXMusic  Permission is hereby granted, free of charge, to any person obtaining a copy  of this software and associated documentation files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  copies of the Software, and to permit persons to whom the Software is  furnished to do so, subject to the following conditions:  The above copyright notice and this permission notice shall be included in all  copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  SOFTWARE. # print(results) **🏷 Title :** [{title}]({link})  **⏱️ Duration :** {duration}  **👁 Viewer :** {results[0]['views']}  **🤖 Uploader :** [{BOT_NAME}](https://t.me/{BOT_USERNAME})  **👤 Requested by :** {rpk} # Funtion To Download Song # await pablo.edit(event, f"**Failed To Download** \n**Error :** `{str(e)}`")