GalaxyCogs/musicdownloader/musicdownloader.py

98 lines
4.6 KiB
Python
Raw Normal View History

import asyncio
import re
2023-07-31 21:35:15 -04:00
import discord
2023-08-01 00:03:00 -04:00
import os
from yt_dlp import YoutubeDL
2023-07-31 21:35:15 -04:00
from redbot.core import commands, checks, Config, data_manager
class MusicDownloader(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=475728338)
self.config.register_global(
2023-08-01 00:03:00 -04:00
save_directory = str(data_manager.cog_data_path()) + f"{os.sep}MusicDownloader"
2023-07-31 21:35:15 -04:00
)
@commands.command()
async def change_data_path(self, ctx: commands.Context, data_path: str = None):
"""This command changes the data path this cog outputs to."""
old_path = await self.config.save_directory()
2023-08-01 00:03:00 -04:00
if os.path.isdir(data_path):
2023-07-31 21:35:15 -04:00
await self.config.save_directory.set(data_path)
embed=discord.Embed(color=await self.bot.get_embed_color(None), description=f"The save directory has been set to `{data_path}`.\n It was previously set to `{old_path}`.")
await ctx.send(embed=embed)
2023-08-01 00:03:00 -04:00
elif os.path.isfile(data_path):
2023-07-31 21:35:15 -04:00
await ctx.send("The path you've provided leads to a file, not a directory!")
2023-08-01 00:03:00 -04:00
elif os.path.exists(data_path) is False:
2023-07-31 21:35:15 -04:00
await ctx.send("The path you've provided doesn't exist!")
@commands.command(aliases=["dl"])
async def download(self, ctx: commands.Context, url: str, subfolder: str = None):
"""This command downloads a YouTube Video as an MP3 to the local music directory."""
def youtube_download(self, url: str, path: str, message: discord.Message):
"""This function does the actual downloading of the YouTube Video."""
class Logger:
def debug(self, msg):
if msg.startswith('[debug] '):
pass
else:
self.info(msg)
def info(self, msg):
pass
def warning(self, msg):
pass
def error(self, msg):
print(msg)
message.edit(msg)
def hook(d):
if d['status'] == 'finished':
message.edit(content='YouTube Downloader completed!')
ydl_opts = {
'logger': Logger(),
'progress_hooks': [hook],
'format': 'm4a/bestaudio/best',
'postprocessors': [{'key': 'FFmpegExtractAudio', 'preferredcodec': 'm4a',}],
2023-07-31 23:41:51 -04:00
'paths': {'home': path}
}
with YoutubeDL(ydl_opts) as ydl:
2023-08-01 00:07:30 -04:00
info = ydl.extract_info(url=url, download=True)
title = info['title']
id = info['id']
filename = title + f' [{id}.m4a]'
return filename
data_path = await self.config.save_directory()
if subfolder:
2023-08-01 00:03:00 -04:00
data_path = os.path.join(data_path, subfolder)
illegal_chars = r'<>:"/\|?*'
if any(char in illegal_chars for char in subfolder):
pattern = "[" + re.escape(illegal_chars) + "]"
modified_subfolder = re.sub(pattern, r'__**\g<0>**__', subfolder)
await ctx.send(f"Your subfolder contains illegal characters: `{modified_subfolder}`")
return
2023-08-01 00:03:00 -04:00
elif os.path.isfile(data_path):
await ctx.send("Your 'subfolder' is a file, not a directory!")
return
2023-08-01 00:03:00 -04:00
elif os.path.exists(data_path) is False:
message = await ctx.send("Your subfolder does not exist yet, would you like to continue? It will be automatically created.")
def check(message):
return message.author == ctx.author and message.content.lower() in ['yes', 'ye', 'y']
try:
await self.bot.wait_for('message', check=check, timeout=60) # Timeout after 60 seconds
except asyncio.TimeoutError:
await message.edit("You took too long to respond.")
else:
await message.edit("Confirmed!")
try:
2023-08-01 00:03:00 -04:00
os.makedirs(data_path)
except OSError as e:
await message.edit(f"Encountered an error attempting to create the subfolder!\n`{e}`")
2023-07-31 23:24:28 -04:00
msg = message.edit
2023-07-31 23:22:59 -04:00
else:
2023-07-31 23:24:28 -04:00
msg = ctx.send
message = await msg("YouTube Downloader started!")
filename = youtube_download(self, url, data_path, message)
full_filename = os.path.join(data_path, filename)
if os.path.isfile(full_filename):
with open(full_filename, 'rb') as file:
await ctx.send(content="Downloaded file:", file=discord.File(file, {filename}))