black --line-length 79

This commit is contained in:
Parker M. 2024-10-31 00:26:00 -05:00
parent c1b229f34c
commit 70e612882d
Signed by: parker
GPG Key ID: 505ED36FC12B5D5E
25 changed files with 650 additions and 206 deletions

View File

@ -28,24 +28,42 @@ class MyBot(commands.Bot):
bot.openai = openai.OpenAI(api_key=config.OPENAI_API_KEY)
config.LOG.info("Loading cogs...")
config.LOG.info("YouTube support is enabled" if config.YOUTUBE_SUPPORT else "YouTube support is disabled")
config.LOG.info(
"YouTube support is enabled"
if config.YOUTUBE_SUPPORT
else "YouTube support is disabled"
)
for ext in os.listdir("./code/cogs"):
if ext.endswith(".py"):
# Load the OPTIONAL feedback cog
if ext[:-3] == "feedback" and config.FEEDBACK_CHANNEL_ID == None:
config.LOG.info("Skipped loading feedback cog - channel ID not provided")
if (
ext[:-3] == "feedback"
and config.FEEDBACK_CHANNEL_ID == None
):
config.LOG.info(
"Skipped loading feedback cog - channel ID not"
" provided"
)
continue
# Load the OPTIONAL bug cog
if ext[:-3] == "bug" and config.BUG_CHANNEL_ID == None:
config.LOG.info("Skipped loading bug cog - channel ID not provided")
config.LOG.info(
"Skipped loading bug cog - channel ID not provided"
)
continue
# Load the OPTIONAL lyrics cog
if ext[:-3] == "lyrics" and config.GENIUS_CLIENT_ID == None:
config.LOG.info("Skipped loading lyrics cog - Genius API credentials not provided")
config.LOG.info(
"Skipped loading lyrics cog - Genius API credentials"
" not provided"
)
continue
# Load the OPTIONAL autoplay cog
if ext[:-3] == "autoplay" and config.OPENAI_API_KEY == None:
config.LOG.info("Skipped loading autoplay cog - OpenAI API credentials not provided")
config.LOG.info(
"Skipped loading autoplay cog - OpenAI API credentials"
" not provided"
)
continue
await self.load_extension(f"cogs.{ext[:-3]}")
@ -55,7 +73,10 @@ class MyBot(commands.Bot):
async def on_ready(self):
config.LOG.info(f"{bot.user} has connected to Discord.")
config.LOG.info(f"Startup complete. Sync slash commands by DMing the bot {bot.command_prefix}tree sync (guild id)")
config.LOG.info(
"Startup complete. Sync slash commands by DMing the bot"
f" {bot.command_prefix}tree sync (guild id)"
)
bot = MyBot()

View File

@ -25,7 +25,11 @@ class Autoplay(commands.Cog):
embed = discord.Embed(
title="Autoplay Off",
description="Autoplay has been turned off. I will no longer automatically add new songs to the queue based on AI recommendations.",
description=(
"Autoplay has been turned off. I will no longer"
" automatically add new songs to the queue based on AI"
" recommendations."
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed)
@ -35,17 +39,28 @@ class Autoplay(commands.Cog):
if interaction.guild.id in self.bot.autoplay:
embed = discord.Embed(
title="Autoplay Already Enabled",
description="Autoplay is already enabled. If you would like to turn it off, choose the `OFF` option in the </autoplay:1228216490386391052> command.",
description=(
"Autoplay is already enabled. If you would like to turn it"
" off, choose the `OFF` option in the"
" </autoplay:1228216490386391052> command."
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
player = self.bot.lavalink.player_manager.get(interaction.guild.id)
if len(player.queue) < 5:
embed = discord.Embed(
title="Not Enough Context",
description="You must have at least 5 songs in the queue so that I can get a good understanding of what music I should continue to play. Add some more music to the queue, then try again.",
description=(
"You must have at least 5 songs in the queue so that I can"
" get a good understanding of what music I should continue"
" to play. Add some more music to the queue, then try"
" again."
),
color=BOT_COLOR,
)
embed.set_footer(
@ -54,7 +69,9 @@ class Autoplay(commands.Cog):
)
+ " UTC"
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
inputs = {}
for song in player.queue[:10]:
@ -62,16 +79,26 @@ class Autoplay(commands.Cog):
embed = discord.Embed(
title="Getting AI Recommendations",
description="Attempting to generate recommendations based on the current songs in your queue. Just a moment...",
description=(
"Attempting to generate recommendations based on the current"
" songs in your queue. Just a moment..."
),
color=BOT_COLOR,
)
await interaction.response.send_message(embed=embed)
if await add_song_recommendations(self.bot.openai, self.bot.user, player, 5, inputs):
if await add_song_recommendations(
self.bot.openai, self.bot.user, player, 5, inputs
):
self.bot.autoplay.append(interaction.guild.id)
embed = discord.Embed(
title=":infinity: Autoplay Enabled :infinity:",
description=f"I have added a few similar songs to the queue and will continue to do so once the queue gets low again. Now just sit back and enjoy the music!\n\nEnabled by: {interaction.user.mention}",
description=(
"I have added a few similar songs to the queue and will"
" continue to do so once the queue gets low again. Now"
" just sit back and enjoy the music!\n\nEnabled by:"
f" {interaction.user.mention}"
),
color=BOT_COLOR,
)
await interaction.edit_original_response(embed=embed)
@ -79,7 +106,13 @@ class Autoplay(commands.Cog):
else:
embed = discord.Embed(
title="Autoplay Error",
description="Autoplay is an experimental feature, meaning sometimes it doesn't work as expected. I had an error when attempting to get similar songs for you, please try running the command again. If the issue persists, fill out a bug report with the </bug:1224840889906499626> command.",
description=(
"Autoplay is an experimental feature, meaning sometimes it"
" doesn't work as expected. I had an error when attempting"
" to get similar songs for you, please try running the"
" command again. If the issue persists, fill out a bug"
" report with the </bug:1224840889906499626> command."
),
color=BOT_COLOR,
)
embed.set_footer(

View File

@ -27,7 +27,8 @@ class BugReport(discord.ui.Modal, title="Report a bug"):
async def on_submit(self, interaction: discord.Interaction):
await interaction.response.send_message(
f"Thanks for your bug report. We will get back to you as soon as possible",
f"Thanks for your bug report. We will get back to you as soon as"
f" possible",
ephemeral=True,
)
channel = self.bot.get_channel(BUG_CHANNEL_ID)

View File

@ -20,7 +20,10 @@ class Clear(commands.Cog):
player.queue.clear()
embed = discord.Embed(
title="Queue Cleared",
description=f"The queue has been cleared of all songs!\n\nIssued by: {interaction.user.mention}",
description=(
"The queue has been cleared of all songs!\n\nIssued by:"
f" {interaction.user.mention}"
),
color=BOT_COLOR,
)
embed.set_footer(

View File

@ -31,7 +31,8 @@ class FeedbackForm(discord.ui.Modal, title="Give feedback about the bot"):
async def on_submit(self, interaction: discord.Interaction):
await interaction.response.send_message(
f"Thank you for your feedback. We love hearing from users!", ephemeral=True
f"Thank you for your feedback. We love hearing from users!",
ephemeral=True,
)
channel = self.bot.get_channel(FEEDBACK_CHANNEL_ID)
@ -40,8 +41,12 @@ class FeedbackForm(discord.ui.Modal, title="Give feedback about the bot"):
description=f"Submitted by {self.name} (<@{interaction.user.id}>)",
color=BOT_COLOR,
)
embed.add_field(name="Positive:", value=f"{self.positive}", inline=False)
embed.add_field(name="Negative:", value=f"{self.negative}", inline=False)
embed.add_field(
name="Positive:", value=f"{self.positive}", inline=False
)
embed.add_field(
name="Negative:", value=f"{self.negative}", inline=False
)
await channel.send(embed=embed)

View File

@ -13,32 +13,51 @@ commands_and_descriptions = {
"skip": {
"description": "Skips the song that is currently playing",
"optional_arguments": {
"number": "The number of songs to skip - leave blank to skip just the current song"
"number": (
"The number of songs to skip - leave blank to skip just the"
" current song"
)
},
"usage": "/skip (number)",
},
"queue": {
"description": "Sends the songs currently added to the queue",
"optional_arguments": {
"page": "Page number of the queue to view - leave blank to see only the first page"
"page": (
"Page number of the queue to view - leave blank to see only"
" the first page"
)
},
"usage": "/queue (page)",
},
"stop": {
"description": "Stops all music, clears the queue, and leave the voice channel",
"description": (
"Stops all music, clears the queue, and leave the voice channel"
),
"usage": "/stop",
},
"np": {"description": "Sends the song that is currently playing", "usage": "/np"},
"clear": {"description": "Removes all songs from the queue", "usage": "/clear"},
"np": {
"description": "Sends the song that is currently playing",
"usage": "/np",
},
"clear": {
"description": "Removes all songs from the queue",
"usage": "/clear",
},
"remove": {
"description": "Removes the specified song from the queue",
"arguments": {
"number": "The queue number of the song that should be removed from the queue"
"number": (
"The queue number of the song that should be removed from the"
" queue"
)
},
"usage": "/remove <number>",
},
"autoplay": {
"description": "Keep the music playing forever with music suggestions from OpenAI",
"description": (
"Keep the music playing forever with music suggestions from OpenAI"
),
"arguments": {
"on": "Turn autoplay feature on",
"off": "Turn autoplay feature off",
@ -49,7 +68,9 @@ commands_and_descriptions = {
"description": "Changes the looping state of the bot",
"arguments": {
"song": "Repeats the song that is currently playing until changed",
"queue": "Continuously repeat the songs in the queue until turned off",
"queue": (
"Continuously repeat the songs in the queue until turned off"
),
"off": "Stop all song or queue repetition",
},
"usage": "/repeat <song/queue/off>",
@ -79,11 +100,15 @@ commands_and_descriptions = {
"usage": "/news",
},
"bug": {
"description": "Fill out a bug report form to alert the developer of issues",
"description": (
"Fill out a bug report form to alert the developer of issues"
),
"usage": "/bug",
},
"feedback": {
"description": "Fill out a form to give the developer feedback on the bot",
"description": (
"Fill out a form to give the developer feedback on the bot"
),
"usage": "/feedback",
},
}
@ -93,7 +118,11 @@ class HelpView(discord.ui.View):
def __init__(self, timeout=180.0):
super().__init__(timeout=timeout)
if BOT_INVITE_LINK:
self.add_item(discord.ui.Button(label="Invite Me", url=BOT_INVITE_LINK, row=1))
self.add_item(
discord.ui.Button(
label="Invite Me", url=BOT_INVITE_LINK, row=1
)
)
@discord.ui.button(
label="View All Commands", style=discord.ButtonStyle.green, row=1
@ -103,14 +132,20 @@ class HelpView(discord.ui.View):
):
embed = discord.Embed(
title=":musical_note: All Commands :musical_note:",
description="**Check out recent news and updates about the bot with the </news:1260842465666007040> command!\n\u200b**",
description=(
"**Check out recent news and updates about the bot with the"
" </news:1260842465666007040> command!\n\u200b**"
),
color=BOT_COLOR,
)
embed.add_field(
name="All Commands",
value=", ".join(
[f"`{command}`" for command in commands_and_descriptions.keys()]
[
f"`{command}`"
for command in commands_and_descriptions.keys()
]
),
)
@ -122,30 +157,48 @@ class Help(commands.Cog):
self.bot = bot
@app_commands.command()
@app_commands.describe(command="Name of the command you want more information on")
async def help(self, interaction: discord.Interaction, command: str = None):
@app_commands.describe(
command="Name of the command you want more information on"
)
async def help(
self, interaction: discord.Interaction, command: str = None
):
"Sends the bots commands"
if command == None:
embed = discord.Embed(
title=f":musical_note: Help :musical_note:",
description="**Check out recent news and updates about the bot with the </news:1260842465666007040> command!\n\u200b**",
description=(
"**Check out recent news and updates about the bot with"
" the </news:1260842465666007040> command!\n\u200b**"
),
color=BOT_COLOR,
)
embed.add_field(
name="**Use Me**",
value="> To get started, use the </play:1224840890368000172> command and enter the name or link to the song of your choice.",
value=(
"> To get started, use the </play:1224840890368000172>"
" command and enter the name or link to the song of your"
" choice."
),
inline=False,
)
embed.add_field(
name="**Full Command List**",
value='> To view of a list of all available commands, click the "View All Commands" button below.',
value=(
"> To view of a list of all available commands, click the"
' "View All Commands" button below.'
),
inline=False,
)
embed.add_field(
name="**Help for Specific Commands**",
value="> If you want more information on how to use a specific command, use the </help:1224854217597124610> command and include the specific command.",
value=(
"> If you want more information on how to use a specific"
" command, use the </help:1224854217597124610> command and"
" include the specific command."
),
inline=False,
)
@ -160,16 +213,18 @@ class Help(commands.Cog):
command = command.lower().strip()
embed = discord.Embed(
title=f"**{command}**",
description=f"{commands_and_descriptions[command]['description']}",
description=(
f"{commands_and_descriptions[command]['description']}"
),
color=BOT_COLOR,
)
try:
if commands_and_descriptions[command]["arguments"]:
arguments_value = ""
for argument, explanation in commands_and_descriptions[command][
"arguments"
].items():
for argument, explanation in commands_and_descriptions[
command
]["arguments"].items():
arguments_value += f"{argument}\n> {explanation}\n\n"
embed.add_field(
@ -181,28 +236,36 @@ class Help(commands.Cog):
try:
if commands_and_descriptions[command]["optional_arguments"]:
arguments_value = ""
for argument, explanation in commands_and_descriptions[command][
"optional_arguments"
].items():
for argument, explanation in commands_and_descriptions[
command
]["optional_arguments"].items():
arguments_value += f"{argument}\n> {explanation}\n\n"
embed.add_field(
name="Optional Arguments", value=arguments_value, inline=False
name="Optional Arguments",
value=arguments_value,
inline=False,
)
except KeyError:
pass
embed.add_field(
name="Usage", value=f"` {commands_and_descriptions[command]['usage']} `"
name="Usage",
value=f"` {commands_and_descriptions[command]['usage']} `",
)
embed.set_thumbnail(url=self.bot.user.avatar.url)
await interaction.response.send_message(embed=embed, ephemeral=True)
await interaction.response.send_message(
embed=embed, ephemeral=True
)
else:
embed = discord.Embed(
title="Command Doesn't Exist",
description=f"The command you entered (` {command} `) does not exist, please try again with a different command name.",
description=(
f"The command you entered (` {command} `) does not exist,"
" please try again with a different command name."
),
color=BOT_COLOR,
)

View File

@ -21,7 +21,10 @@ class Lyrics(commands.Cog):
if not self.bot.genius:
embed = discord.Embed(
title="Lyrics Feature Error",
description="The lyrics feature is currently disabled due to errors with the Genius API.",
description=(
"The lyrics feature is currently disabled due to errors"
" with the Genius API."
),
color=BOT_COLOR,
)
embed.set_footer(
@ -30,20 +33,27 @@ class Lyrics(commands.Cog):
)
+ " UTC"
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
# Defer the interaction to avoid getting 404 Not Found errors
# if fetching the lyrics takes a long time
await interaction.response.defer(ephemeral=True)
# Search for the songs lyrics with Genius
song = self.bot.genius.search_song(player.current.title, player.current.author)
song = self.bot.genius.search_song(
player.current.title, player.current.author
)
# If no lyrics are found, send an error message
if song is None:
embed = discord.Embed(
title="Lyrics Not Found",
description="Unfortunately, I wasn't able to find any lyrics for the song that is currently playing.",
description=(
"Unfortunately, I wasn't able to find any lyrics for the"
" song that is currently playing."
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=player.current.artwork_url)
@ -64,8 +74,14 @@ class Lyrics(commands.Cog):
# If the lyrics are too long, send just a link to the lyrics
if len(lyrics) > 2048:
embed = discord.Embed(
title=f"Lyrics for {player.current.title} by {player.current.author}",
description=f"Song lyrics are too long to display on Discord. [Click here to view the lyrics on Genius]({song.url}).",
title=(
f"Lyrics for {player.current.title} by"
f" {player.current.author}"
),
description=(
"Song lyrics are too long to display on Discord. [Click"
f" here to view the lyrics on Genius]({song.url})."
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=player.current.artwork_url)
@ -79,7 +95,9 @@ class Lyrics(commands.Cog):
# If everything is successful, send the lyrics
embed = discord.Embed(
title=f"Lyrics for {player.current.title} by {player.current.author}",
title=(
f"Lyrics for {player.current.title} by {player.current.author}"
),
description=f"Provided from [Genius]({song.url})\n\n" + lyrics,
color=BOT_COLOR,
)

View File

@ -112,7 +112,8 @@ class Music(commands.Cog):
await node.get_version()
except lavalink.errors.ClientError:
LOG.error(
"Authentication to lavalink node failed. Check your login credentials."
"Authentication to lavalink node failed. Check your login"
" credentials."
)
else:
await node.connect()
@ -135,7 +136,11 @@ class Music(commands.Cog):
raise CheckPlayerError(
{
"title": "Lavalink Error",
"description": "An error occured with the Lavalink server. Please submit a bug report with </bug:1224840889906499626> if this issue persists.",
"description": (
"An error occured with the Lavalink server. Please"
" submit a bug report with </bug:1224840889906499626>"
" if this issue persists."
),
}
)
@ -147,14 +152,20 @@ class Music(commands.Cog):
raise CheckPlayerError(
{
"title": "Not in my VC",
"description": "You must join my voice channel to run that command.",
"description": (
"You must join my voice channel to run that"
" command."
),
}
)
raise CheckPlayerError(
{
"title": "No Channel",
"description": "You must join a voice channel before you can run that command.",
"description": (
"You must join a voice channel before you can run that"
" command."
),
}
)
@ -163,7 +174,10 @@ class Music(commands.Cog):
raise CheckPlayerError(
{
"title": "Not Connected",
"description": "I am not connected and playing music right now, therefore that command will not work.",
"description": (
"I am not connected and playing music right now,"
" therefore that command will not work."
),
}
)
@ -175,7 +189,10 @@ class Music(commands.Cog):
raise CheckPlayerError(
{
"title": "Missing Permissions",
"description": "I need the `CONNECT` and `SPEAK` permissions in order to work.",
"description": (
"I need the `CONNECT` and `SPEAK` permissions in"
" order to work."
),
}
)
@ -185,7 +202,10 @@ class Music(commands.Cog):
raise CheckPlayerError(
{
"title": "Not in my VC",
"description": "You must join my voice channel to run that command.",
"description": (
"You must join my voice channel to run that"
" command."
),
}
)
@ -211,7 +231,9 @@ class Music(commands.Cog):
inputs = {}
for song in event.player.queue[:10]:
inputs[song.title] = song.author
await add_song_recommendations(self.bot.openai, self.bot.user, event.player, 5, inputs)
await add_song_recommendations(
self.bot.openai, self.bot.user, event.player, 5, inputs
)
async def setup(bot):

View File

@ -14,23 +14,39 @@ class News(commands.Cog):
"Get recent news and updates about the bot"
embed = discord.Embed(
title="Recent News :newspaper2:",
description="View recent code commits [here](https://github.com/packetparker/guava/commits)\n\u200b",
description=(
"View recent code commits"
" [here](https://github.com/packetparker/guava/commits)\n\u200b"
),
color=BOT_COLOR,
)
embed.add_field(
name="**Lyrics!**",
value="> You can now get lyrics for the song that is currently playing. Just use the `/lyrics` command! Some songs may not have lyrics available, but the bot will do its best to find them.",
value=(
"> You can now get lyrics for the song that is currently"
" playing. Just use the `/lyrics` command! Some songs may not"
" have lyrics available, but the bot will do its best to find"
" them."
),
)
embed.add_field(
name="**Apple Music Support!**",
value="> After some trial and error, you can now play music through Apple Music links. Just paste the link and the bot will do the rest!",
value=(
"> After some trial and error, you can now play music through"
" Apple Music links. Just paste the link and the bot will do"
" the rest!"
),
)
embed.add_field(
name="**Autoplay Update**",
value="> Autoplay is now much more stable after a revamp of the previous system. If you experienced short outages recently, this was due to the update. Thank you for your patience!",
value=(
"> Autoplay is now much more stable after a revamp of the"
" previous system. If you experienced short outages recently,"
" this was due to the update. Thank you for your patience!"
),
inline=False,
)

View File

@ -27,7 +27,11 @@ class NowPlaying(commands.Cog):
embed = discord.Embed(
title="Now Playing 🎶",
description=f"**[{player.current.title}]({player.current.uri})** by {player.current.author}\n{f'` {time_in}/{total_duration} `'}\n\nQueued by: {player.current.requester.mention}",
description=(
f"**[{player.current.title}]({player.current.uri})** by"
f" {player.current.author}\n{f'` {time_in}/{total_duration} `'}\n\nQueued"
f" by: {player.current.requester.mention}"
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=player.current.artwork_url)

View File

@ -9,7 +9,10 @@ class CogCommands(commands.Cog):
@commands.dm_only()
@commands.is_owner()
async def cog(self, ctx):
await ctx.author.send(f"This is a group command. Use `{self.bot.command_prefix}cog load/unload/reload` followed by the name of the cog.")
await ctx.author.send(
f"This is a group command. Use `{self.bot.command_prefix}cog"
" load/unload/reload` followed by the name of the cog."
)
@cog.command()
@commands.dm_only()
@ -47,7 +50,9 @@ class CogCommands(commands.Cog):
@unload.error
async def cog_unload_error(self, ctx, error):
if isinstance(error.original, commands.ExtensionNotLoaded):
return await ctx.send("Cog not loaded. It might be that the cog does not exist.")
return await ctx.send(
"Cog not loaded. It might be that the cog does not exist."
)
else:
return await ctx.send("An unknown error occurred.")
@ -66,7 +71,9 @@ class CogCommands(commands.Cog):
@reload.error
async def cog_reload_error(self, ctx, error):
if isinstance(error.original, commands.ExtensionNotLoaded):
return await ctx.send("Cog not loaded. It might be that the cog does not exist.")
return await ctx.send(
"Cog not loaded. It might be that the cog does not exist."
)
else:
return await ctx.send("An unknown error occurred.")

View File

@ -17,7 +17,8 @@ class Stats(commands.Cog):
connection = sqlite3.connect("data/count.db")
cursor = connection.cursor()
cursor.execute(
"CREATE TABLE IF NOT EXISTS count (command_name, count, PRIMARY KEY (command_name))"
"CREATE TABLE IF NOT EXISTS count (command_name, count, PRIMARY"
" KEY (command_name))"
)
connection.commit()
connection.close()
@ -37,7 +38,8 @@ class Stats(commands.Cog):
)
except sqlite3.IntegrityError:
cursor.execute(
"UPDATE count SET count = count + ? WHERE command_name = ?",
"UPDATE count SET count = count + ? WHERE"
" command_name = ?",
(count, command_name),
)
@ -65,16 +67,25 @@ class Stats(commands.Cog):
).fetchall()
# Get the combined total amount of commands run
total_commands = cursor.execute("SELECT SUM(count) FROM count").fetchone()[0]
total_commands = cursor.execute(
"SELECT SUM(count) FROM count"
).fetchone()[0]
embed = discord.Embed(
title="Statistics",
description=f"Total Guilds: `{len(self.bot.guilds):,}`\nTotal Commands: `{total_commands:,}`\n\nTotal Players: `{self.bot.lavalink.nodes[0].stats.playing_players}`\nLoad: `{round(self.bot.lavalink.nodes[0].stats.lavalink_load * 100, 2)}%`",
description=(
f"Total Guilds: `{len(self.bot.guilds):,}`\nTotal Commands:"
f" `{total_commands:,}`\n\nTotal Players:"
f" `{self.bot.lavalink.nodes[0].stats.playing_players}`\nLoad:"
f" `{round(self.bot.lavalink.nodes[0].stats.lavalink_load * 100, 2)}%`"
),
color=BOT_COLOR,
)
for entry in data:
embed.add_field(name=entry[0], value=f"` {entry[1]:,} `", inline=True)
embed.add_field(
name=entry[0], value=f"` {entry[1]:,} `", inline=True
)
connection.close()
await ctx.send(embed=embed)

View File

@ -10,17 +10,27 @@ class TreeSync(commands.Cog):
@commands.dm_only()
@commands.is_owner()
async def tree(self, ctx):
await ctx.author.send(f"This is a group command. Use either `{self.bot.command_prefix}tree sync` or `{self.bot.command_prefix}tree clear` followed by an optional guild ID.")
await ctx.author.send(
"This is a group command. Use either"
f" `{self.bot.command_prefix}tree sync` or"
f" `{self.bot.command_prefix}tree clear` followed by an optional"
" guild ID."
)
@commands.dm_only()
@commands.is_owner()
@tree.command()
async def sync(self, ctx: commands.Context, *, guild: discord.Object = None):
async def sync(
self, ctx: commands.Context, *, guild: discord.Object = None
):
"""Sync the command tree to a guild or globally."""
if guild:
self.bot.tree.copy_global_to(guild=guild)
await self.bot.tree.sync(guild=guild)
return await ctx.author.send(f"Synced the command tree to `{self.bot.get_guild(guild.id).name}`")
return await ctx.author.send(
"Synced the command tree to"
f" `{self.bot.get_guild(guild.id).name}`"
)
else:
await self.bot.tree.sync()
return await ctx.author.send("Synced the command tree globally.")
@ -28,11 +38,17 @@ class TreeSync(commands.Cog):
@sync.error
async def tree_sync_error(self, ctx, error):
if isinstance(error, commands.ObjectNotFound):
return await ctx.author.send("The guild you provided does not exist.")
return await ctx.author.send(
"The guild you provided does not exist."
)
if isinstance(error, commands.CommandInvokeError):
return await ctx.author.send("Guild ID provided is not a guild that the bot is in.")
return await ctx.author.send(
"Guild ID provided is not a guild that the bot is in."
)
else:
return await ctx.author.send("An unknown error occurred. Perhaps you've been rate limited.")
return await ctx.author.send(
"An unknown error occurred. Perhaps you've been rate limited."
)
@commands.dm_only()
@commands.is_owner()
@ -41,18 +57,30 @@ class TreeSync(commands.Cog):
"""Clear the command tree from a guild."""
self.bot.tree.clear_commands(guild=guild)
await self.bot.tree.sync(guild=guild)
return await ctx.author.send(f"Cleared the command tree from `{self.bot.get_guild(guild.id).name}`")
return await ctx.author.send(
"Cleared the command tree from"
f" `{self.bot.get_guild(guild.id).name}`"
)
@clear.error
async def tree_sync_error(self, ctx, error):
if isinstance(error, commands.MissingRequiredArgument):
return await ctx.author.send("You need to provide a guild ID to clear the command tree from.")
return await ctx.author.send(
"You need to provide a guild ID to clear the command tree"
" from."
)
if isinstance(error, commands.ObjectNotFound):
return await ctx.author.send("The guild you provided does not exist.")
return await ctx.author.send(
"The guild you provided does not exist."
)
if isinstance(error, commands.CommandInvokeError):
return await ctx.author.send("Guild ID provided is not a guild that the bot is in.")
return await ctx.author.send(
"Guild ID provided is not a guild that the bot is in."
)
else:
return await ctx.author.send("An unknown error occurred. Perhaps you've been rate limited.")
return await ctx.author.send(
"An unknown error occurred. Perhaps you've been rate limited."
)
async def setup(bot):

View File

@ -20,7 +20,10 @@ class Pause(commands.Cog):
await player.set_pause(pause=True)
embed = discord.Embed(
title=f"Music Now Paused ⏸️",
description=f"**[{player.current.title}]({player.current.uri})**\n\nQueued by: {player.current.requester.mention}",
description=(
f"**[{player.current.title}]({player.current.uri})**\n\nQueued"
f" by: {player.current.requester.mention}"
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=player.current.artwork_url)

View File

@ -30,10 +30,18 @@ class Play(commands.Cog):
if not YOUTUBE_SUPPORT:
embed = discord.Embed(
title="YouTube Not Supported",
description="Unfortunately, YouTube does not allow bots to stream from their platform. Try sending a link for a different platform, or simply type the name of the song and I will automatically find it on a supported platform.",
description=(
"Unfortunately, YouTube does not allow bots to stream"
" from their platform. Try sending a link for a"
" different platform, or simply type the name of the"
" song and I will automatically find it on a supported"
" platform."
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
###
### APPLE MUSIC links, perform API requests and load all tracks from the playlist/album/track
@ -43,10 +51,17 @@ class Play(commands.Cog):
if not self.bot.apple_headers:
embed = discord.Embed(
title="Apple Music Error",
description="Apple Music support seems to be broken at the moment. Please try again and fill out a bug report with </bug:1224840889906499626> if this continues to happen.",
description=(
"Apple Music support seems to be broken at the moment."
" Please try again and fill out a bug report with"
" </bug:1224840889906499626> if this continues to"
" happen."
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
embed = discord.Embed(color=BOT_COLOR)
@ -54,32 +69,44 @@ class Play(commands.Cog):
playlist_id = query.split("/playlist/")[1].split("/")[1]
# Get all of the tracks in the playlist (limit at 250)
playlist_url = f"https://api.music.apple.com/v1/catalog/us/playlists/{playlist_id}/tracks?limit=100"
response = requests.get(playlist_url, headers=self.bot.apple_headers)
response = requests.get(
playlist_url, headers=self.bot.apple_headers
)
if response.status_code == 200:
playlist = response.json()
# Get the general playlist info (name, artwork)
playlist_info_url = f"https://api.music.apple.com/v1/catalog/us/playlists/{playlist_id}"
playlist_info = requests.get(playlist_info_url, headers=self.bot.apple_headers)
playlist_info = requests.get(
playlist_info_url, headers=self.bot.apple_headers
)
playlist_info = playlist_info.json()
try:
artwork_url = playlist_info["data"][0]["attributes"]["artwork"]["url"].replace(
"{w}x{h}", "300x300"
)
artwork_url = playlist_info["data"][0]["attributes"][
"artwork"
]["url"].replace("{w}x{h}", "300x300")
except KeyError:
artwork_url = None
embed.title = "Playlist Queued"
embed.description = f"**{playlist_info['data'][0]['attributes']['name']}**\n` {len(playlist['data'])} ` tracks\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{playlist_info['data'][0]['attributes']['name']}**\n`"
f" {len(playlist['data'])} ` tracks\n\nQueued by:"
f" {interaction.user.mention}"
)
embed.set_thumbnail(url=artwork_url)
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
)
text=datetime.datetime.now(
datetime.timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
+ " UTC"
)
# Add small alert if the playlist is the max size
if len(playlist["data"]) == 100:
embed.description += "\n\n*This playlist is longer than the 100 song maximum. Only the first 100 songs will be queued.*"
embed.description += (
"\n\n*This playlist is longer than the 100 song"
" maximum. Only the first 100 songs will be"
" queued.*"
)
await interaction.response.send_message(embed=embed)
@ -93,26 +120,35 @@ class Play(commands.Cog):
if "/album/" in query and "?i=" not in query:
album_id = query.split("/album/")[1].split("/")[1]
album_url = f"https://api.music.apple.com/v1/catalog/us/albums/{album_id}"
response = requests.get(album_url, headers=self.bot.apple_headers)
response = requests.get(
album_url, headers=self.bot.apple_headers
)
if response.status_code == 200:
album = response.json()
embed.title = "Album Queued"
embed.description = f"**{album['data'][0]['attributes']['name']}** by **{album['data'][0]['attributes']['artistName']}**\n` {len(album['data'][0]['relationships']['tracks']['data'])} ` tracks\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{album['data'][0]['attributes']['name']}** by"
f" **{album['data'][0]['attributes']['artistName']}**\n`"
f" {len(album['data'][0]['relationships']['tracks']['data'])} `"
f" tracks\n\nQueued by: {interaction.user.mention}"
)
embed.set_thumbnail(
url=album["data"][0]["attributes"]["artwork"]["url"].replace(
"{w}x{h}", "300x300"
)
url=album["data"][0]["attributes"]["artwork"][
"url"
].replace("{w}x{h}", "300x300")
)
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
)
text=datetime.datetime.now(
datetime.timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
+ " UTC"
)
await interaction.response.send_message(embed=embed)
tracks = await AppleSource.load_album(self, interaction.user, album)
tracks = await AppleSource.load_album(
self, interaction.user, album
)
for track in tracks["tracks"]:
player.add(requester=interaction.user, track=track)
@ -120,27 +156,37 @@ class Play(commands.Cog):
if "/album/" in query and "?i=" in query:
song_id = query.split("/album/")[1].split("?i=")[1]
song_url = f"https://api.music.apple.com/v1/catalog/us/songs/{song_id}"
response = requests.get(song_url, headers=self.bot.apple_headers)
response = requests.get(
song_url, headers=self.bot.apple_headers
)
if response.status_code == 200:
song = response.json()
embed.title = "Song Queued"
embed.description = f"**{song['data'][0]['attributes']['name']}** by **{song['data'][0]['attributes']['artistName']}**\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{song['data'][0]['attributes']['name']}** by"
f" **{song['data'][0]['attributes']['artistName']}**\n\nQueued"
f" by: {interaction.user.mention}"
)
embed.set_thumbnail(
url=song["data"][0]["attributes"]["artwork"]["url"].replace(
"{w}x{h}", "300x300"
)
url=song["data"][0]["attributes"]["artwork"][
"url"
].replace("{w}x{h}", "300x300")
)
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
)
text=datetime.datetime.now(
datetime.timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
+ " UTC"
)
await interaction.response.send_message(embed=embed)
results = await AppleSource.load_item(self, interaction.user, song)
player.add(requester=interaction.user, track=results.tracks[0])
results = await AppleSource.load_item(
self, interaction.user, song
)
player.add(
requester=interaction.user, track=results.tracks[0]
)
###
### SPOTIFY links, perform API requests and load all tracks from the playlist/album/track
@ -150,27 +196,43 @@ class Play(commands.Cog):
if not self.bot.spotify_headers:
embed = discord.Embed(
title="Spotify Error",
description="Spotify support seems to be broken at the moment. Please try again and fill out a bug report with </bug:1224840889906499626> if this continues to happen.",
description=(
"Spotify support seems to be broken at the moment."
" Please try again and fill out a bug report with"
" </bug:1224840889906499626> if this continues to"
" happen."
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
embed = discord.Embed(color=BOT_COLOR)
if "open.spotify.com/playlist" in query:
playlist_id = query.split("playlist/")[1].split("?si=")[0]
playlist_url = f"https://api.spotify.com/v1/playlists/{playlist_id}"
response = requests.get(playlist_url, headers=self.bot.spotify_headers)
playlist_url = (
f"https://api.spotify.com/v1/playlists/{playlist_id}"
)
response = requests.get(
playlist_url, headers=self.bot.spotify_headers
)
if response.status_code == 200:
playlist = response.json()
embed.title = "Playlist Queued"
embed.description = f"**{playlist['name']}** from **{playlist['owner']['display_name']}**\n` {len(playlist['tracks']['items'])} ` tracks\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{playlist['name']}** from"
f" **{playlist['owner']['display_name']}**\n`"
f" {len(playlist['tracks']['items'])} `"
f" tracks\n\nQueued by: {interaction.user.mention}"
)
embed.set_thumbnail(url=playlist["images"][0]["url"])
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
)
text=datetime.datetime.now(
datetime.timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
+ " UTC"
)
await interaction.response.send_message(embed=embed)
@ -184,17 +246,24 @@ class Play(commands.Cog):
if "open.spotify.com/album" in query:
album_id = query.split("album/")[1]
album_url = f"https://api.spotify.com/v1/albums/{album_id}"
response = requests.get(album_url, headers=self.bot.spotify_headers)
response = requests.get(
album_url, headers=self.bot.spotify_headers
)
if response.status_code == 200:
album = response.json()
embed.title = "Album Queued"
embed.description = f"**{album['name']}** by **{album['artists'][0]['name']}**\n` {len(album['tracks']['items'])} ` tracks\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{album['name']}** by"
f" **{album['artists'][0]['name']}**\n`"
f" {len(album['tracks']['items'])} ` tracks\n\nQueued"
f" by: {interaction.user.mention}"
)
embed.set_thumbnail(url=album["images"][0]["url"])
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
)
text=datetime.datetime.now(
datetime.timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
+ " UTC"
)
await interaction.response.send_message(embed=embed)
@ -208,17 +277,23 @@ class Play(commands.Cog):
if "open.spotify.com/track" in query:
track_id = query.split("track/")[1]
track_url = f"https://api.spotify.com/v1/tracks/{track_id}"
response = requests.get(track_url, headers=self.bot.spotify_headers)
response = requests.get(
track_url, headers=self.bot.spotify_headers
)
if response.status_code == 200:
track = response.json()
embed.title = "Track Queued"
embed.description = f"**{track['name']}** by **{track['artists'][0]['name']}**\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{track['name']}** by"
f" **{track['artists'][0]['name']}**\n\nQueued by:"
f" {interaction.user.mention}"
)
embed.set_thumbnail(url=track["album"]["images"][0]["url"])
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
)
text=datetime.datetime.now(
datetime.timezone.utc
).strftime("%Y-%m-%d %H:%M:%S")
+ " UTC"
)
await interaction.response.send_message(embed=embed)
@ -226,11 +301,16 @@ class Play(commands.Cog):
results = await SpotifySource.load_item(
self, interaction.user, track
)
player.add(requester=interaction.user, track=results.tracks[0])
player.add(
requester=interaction.user, track=results.tracks[0]
)
if "open.spotify.com/artists" in query:
embed.title = "Artists Cannot Be Played"
embed.description = "I cannot play just artists, you must provide a song/album/playlist. Please try again."
embed.description = (
"I cannot play just artists, you must provide a"
" song/album/playlist. Please try again."
)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
@ -267,7 +347,11 @@ class Play(commands.Cog):
LoadType.ERROR,
):
embed.title = "Nothing Found"
embed.description = "Nothing for that query could be found. If this continues happening for other songs, please run </bug:1224840889906499626> to let the developer know."
embed.description = (
"Nothing for that query could be found. If this continues"
" happening for other songs, please run"
" </bug:1224840889906499626> to let the developer know."
)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
@ -279,7 +363,10 @@ class Play(commands.Cog):
player.add(requester=interaction.user, track=track)
embed.title = "Songs Queued!"
embed.description = f"**{results.playlist_info.name}**\n` {len(tracks)} ` tracks\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{results.playlist_info.name}**\n` {len(tracks)} `"
f" tracks\n\nQueued by: {interaction.user.mention}"
)
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(
"%Y-%m-%d %H:%M:%S"
@ -293,7 +380,10 @@ class Play(commands.Cog):
player.add(requester=interaction.user, track=track)
embed.title = "Track Queued"
embed.description = f"**{track.title}** by **{track.author}**\n\nQueued by: {interaction.user.mention}"
embed.description = (
f"**{track.title}** by **{track.author}**\n\nQueued by:"
f" {interaction.user.mention}"
)
embed.set_thumbnail(url=track.artwork_url)
embed.set_footer(
text=datetime.datetime.now(datetime.timezone.utc).strftime(

View File

@ -15,7 +15,9 @@ class Queue(commands.Cog):
@app_commands.command()
@app_commands.check(Music.create_player)
@app_commands.describe(page="Queue page number - leave blank if you are unsure")
@app_commands.describe(
page="Queue page number - leave blank if you are unsure"
)
async def queue(self, interaction: discord.Interaction, page: int = 1):
"See the current queue of songs"
player = self.bot.lavalink.player_manager.get(interaction.guild.id)
@ -23,7 +25,10 @@ class Queue(commands.Cog):
if not player.queue:
embed = discord.Embed(
title="Nothing Queued",
description="Nothing is currently in the queue, add a song with the </play:1224840890368000172> command.",
description=(
"Nothing is currently in the queue, add a song with the"
" </play:1224840890368000172> command."
),
color=BOT_COLOR,
)
embed.set_footer(
@ -32,7 +37,9 @@ class Queue(commands.Cog):
)
+ " UTC"
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
items_per_page = 10
pages = math.ceil(len(player.queue) / items_per_page)
@ -48,11 +55,16 @@ class Queue(commands.Cog):
if track_duration.split(":")[0] == "00":
track_duration = track_duration[3:]
queue_list += f"`{index+1}. ` [{track.title}]({track.uri}) - {track.author} `({track_duration})`\n"
queue_list += (
f"`{index+1}. ` [{track.title}]({track.uri}) -"
f" {track.author} `({track_duration})`\n"
)
embed = discord.Embed(
title=f"Queue for {interaction.guild.name}",
description=f"**{len(player.queue)} tracks total**\n\n{queue_list}",
description=(
f"**{len(player.queue)} tracks total**\n\n{queue_list}"
),
color=BOT_COLOR,
)
embed.set_footer(text=f"Viewing page {page}/{pages}")

View File

@ -21,7 +21,10 @@ class Remove(commands.Cog):
if not player.queue:
embed = discord.Embed(
title="Nothing Queued",
description="Nothing is currently in the queue, so there is nothing for me to remove.",
description=(
"Nothing is currently in the queue, so there is nothing"
" for me to remove."
),
color=BOT_COLOR,
)
embed.set_footer(
@ -34,7 +37,8 @@ class Remove(commands.Cog):
if number > len(player.queue) or number < 1:
return await interaction.response.send_message(
"The number entered is not a number within the queue - please try again!",
"The number entered is not a number within the queue - please"
" try again!",
ephemeral=True,
)
@ -46,7 +50,11 @@ class Remove(commands.Cog):
embed = discord.Embed(
title="Song Removed from Queue",
description=f"**Song Removed - [{removed_title}]({removed_url})**\n\nIssued by: {interaction.user.mention}",
description=(
"**Song Removed -"
f" [{removed_title}]({removed_url})**\n\nIssued by:"
f" {interaction.user.mention}"
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=removed_artwork)

View File

@ -29,7 +29,9 @@ class Repeat(commands.GroupCog, name="repeat"):
)
+ " UTC"
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
player.loop = 0
@ -64,13 +66,18 @@ class Repeat(commands.GroupCog, name="repeat"):
)
+ " UTC"
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
player.loop = 1
embed = discord.Embed(
title=f"Repeating Current Song 🔁",
description=f"The song that is currently playing will be repeated until the </repeat off:1224840891395608737> command is run",
description=(
f"The song that is currently playing will be repeated until"
f" the </repeat off:1224840891395608737> command is run"
),
color=BOT_COLOR,
)
embed.set_footer(
@ -99,13 +106,18 @@ class Repeat(commands.GroupCog, name="repeat"):
)
+ " UTC"
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
player.loop = 2
embed = discord.Embed(
title=f"Repeating Current Song 🔂",
description=f"All songs in the queue will continue to repeat until the </repeat off:1224840891395608737> command is run.",
description=(
f"All songs in the queue will continue to repeat until the"
f" </repeat off:1224840891395608737> command is run."
),
color=BOT_COLOR,
)
embed.set_footer(

View File

@ -20,7 +20,10 @@ class Resume(commands.Cog):
await player.set_pause(pause=False)
embed = discord.Embed(
title=f"Music Now Resumed ⏯️",
description=f"**[{player.current.title}]({player.current.uri})**\n\nQueued by: {player.current.requester.mention}",
description=(
f"**[{player.current.title}]({player.current.uri})**\n\nQueued"
f" by: {player.current.requester.mention}"
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=player.current.artwork_url)

View File

@ -15,7 +15,9 @@ class Skip(commands.Cog):
@app_commands.command()
@app_commands.check(Music.create_player)
@app_commands.describe(number="Optional: Number of songs to skip, default is 1")
@app_commands.describe(
number="Optional: Number of songs to skip, default is 1"
)
async def skip(self, interaction: discord.Interaction, number: int = 1):
"Skips the song that is currently playing"
player = self.bot.lavalink.player_manager.get(interaction.guild.id)
@ -32,7 +34,11 @@ class Skip(commands.Cog):
elif number > len(player.queue):
embed.title = "Number too Large"
embed.description = "The number you entered is larger than the number of songs in queue. If you want to stop playing music entirely, try the </stop:1224840890866991305> command."
embed.description = (
"The number you entered is larger than the number of songs"
" in queue. If you want to stop playing music entirely,"
" try the </stop:1224840890866991305> command."
)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
@ -49,10 +55,16 @@ class Skip(commands.Cog):
if player.loop == 1:
embed = discord.Embed(
title="Song on Repeat",
description="There is nothing in queue, but the current song is on repeat. Use </stop:1224840890866991305> to stop playing music.",
description=(
"There is nothing in queue, but the current song is on"
" repeat. Use </stop:1224840890866991305> to stop"
" playing music."
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed, ephemeral=True)
return await interaction.response.send_message(
embed=embed, ephemeral=True
)
else:
pass
@ -67,7 +79,10 @@ class Skip(commands.Cog):
if not player.current:
embed = discord.Embed(
title="End of Queue",
description=f"All songs in queue have been played. Thank you for using me :wave:\n\nIssued by: {interaction.user.mention}",
description=(
"All songs in queue have been played. Thank you for using"
f" me :wave:\n\nIssued by: {interaction.user.mention}"
),
color=BOT_COLOR,
)
return await interaction.response.send_message(embed=embed)
@ -77,7 +92,11 @@ class Skip(commands.Cog):
await asyncio.sleep(0.5)
embed = discord.Embed(
title="Track Skipped",
description=f"**Now Playing: [{next_song.title}]({next_song.uri})** by {next_song.author}\n\nQueued by: {next_song.requester.mention}",
description=(
f"**Now Playing: [{next_song.title}]({next_song.uri})** by"
f" {next_song.author}\n\nQueued by:"
f" {next_song.requester.mention}"
),
color=BOT_COLOR,
)
embed.set_thumbnail(url=next_song.artwork_url)

View File

@ -27,7 +27,10 @@ class Stop(commands.Cog):
embed = discord.Embed(
title="Queue Cleared and Music Stopped",
description=f"Thank you for using me :wave:\n\nIssued by: {interaction.user.mention}",
description=(
"Thank you for using me :wave:\n\nIssued by:"
f" {interaction.user.mention}"
),
color=BOT_COLOR,
)
embed.set_footer(

View File

@ -15,7 +15,9 @@ class CheckPlayerError(app_commands.AppCommandError):
class Tree(app_commands.CommandTree):
async def on_error(
self, interaction: discord.Interaction, error: app_commands.AppCommandError
self,
interaction: discord.Interaction,
error: app_commands.AppCommandError,
):
music_commands = [
"play",
@ -48,7 +50,9 @@ class Tree(app_commands.CommandTree):
+ " UTC"
)
try:
await interaction.response.send_message(embed=embed, ephemeral=True)
await interaction.response.send_message(
embed=embed, ephemeral=True
)
except discord.errors.InteractionResponded:
await interaction.followup.send(embed=embed, ephemeral=True)
@ -60,7 +64,11 @@ class Tree(app_commands.CommandTree):
):
embed = discord.Embed(
title="Player Creation Error",
description="An error occured when trying to create a player. Please submit a bug report with </bug:1224840889906499626> if this issue persists.",
description=(
"An error occured when trying to create a player. Please"
" submit a bug report with </bug:1224840889906499626> if"
" this issue persists."
),
color=BOT_COLOR,
)
embed.set_footer(
@ -70,7 +78,9 @@ class Tree(app_commands.CommandTree):
+ " UTC"
)
try:
await interaction.response.send_message(embed=embed, ephemeral=True)
await interaction.response.send_message(
embed=embed, ephemeral=True
)
except discord.errors.InteractionResponded:
await interaction.followup.send(embed=embed, ephemeral=True)
@ -78,7 +88,13 @@ class Tree(app_commands.CommandTree):
elif isinstance(error, LoadError):
embed = discord.Embed(
title="Nothing Found",
description="Spotify does not allow direct play, meaning songs have to be found on a supported provider. In this case, the song couldn't be found. Please try again with a different song, or try searching for just the name and artist manually rather than sending a link.",
description=(
"Spotify does not allow direct play, meaning songs have to"
" be found on a supported provider. In this case, the song"
" couldn't be found. Please try again with a different"
" song, or try searching for just the name and artist"
" manually rather than sending a link."
),
color=BOT_COLOR,
)
embed.set_footer(
@ -88,7 +104,9 @@ class Tree(app_commands.CommandTree):
+ " UTC"
)
try:
await interaction.response.send_message(embed=embed, ephemeral=True)
await interaction.response.send_message(
embed=embed, ephemeral=True
)
except discord.errors.InteractionResponded:
await interaction.followup.send(embed=embed, ephemeral=True)

View File

@ -12,7 +12,8 @@ from colorlog import ColoredFormatter
log_level = logging.DEBUG
log_format = (
" %(log_color)s%(levelname)-8s%(reset)s | %(log_color)s%(message)s%(reset)s"
" %(log_color)s%(levelname)-8s%(reset)s |"
" %(log_color)s%(message)s%(reset)s"
)
logging.root.setLevel(log_level)
@ -138,7 +139,9 @@ lavalink:
sys.exit(
LOG.critical(
"Configuration file `config.yaml` has been generated. Please fill out all of the necessary information. Refer to the docs for information on what a specific configuration option is."
"Configuration file `config.yaml` has been generated. Please"
" fill out all of the necessary information. Refer to the docs"
" for information on what a specific configuration option is."
)
)
@ -173,7 +176,9 @@ def validate_config(file_contents):
if "bot_color" in config["bot_info"]:
if not bool(
re.match(hex_pattern_one, config["bot_info"]["bot_color"])
) and not bool(re.match(hex_pattern_two, config["bot_info"]["bot_color"])):
) and not bool(
re.match(hex_pattern_two, config["bot_info"]["bot_color"])
):
LOG.critical(
"Error in config.yaml file: bot_color is not a valid hex color"
)
@ -187,7 +192,8 @@ def validate_config(file_contents):
if len(str(config["bot_info"]["feedback_channel_id"])) != 0:
if len(str(config["bot_info"]["feedback_channel_id"])) != 19:
LOG.critical(
"Error in config.yaml file: feedback_channel_id is not a valid Discord channel ID"
"Error in config.yaml file: feedback_channel_id is not a"
" valid Discord channel ID"
)
else:
FEEDBACK_CHANNEL_ID = config["bot_info"]["feedback_channel_id"]
@ -196,7 +202,8 @@ def validate_config(file_contents):
if len(str(config["bot_info"]["bug_channel_id"])) != 0:
if len(str(config["bot_info"]["bug_channel_id"])) != 19:
LOG.critical(
"Error in config.yaml file: bug_channel_id is not a valid Discord channel ID"
"Error in config.yaml file: bug_channel_id is not a valid"
" Discord channel ID"
)
else:
BUG_CHANNEL_ID = config["bot_info"]["bug_channel_id"]
@ -223,7 +230,8 @@ def validate_config(file_contents):
SPOTIFY_CLIENT_SECRET = config["spotify"]["spotify_client_secret"]
else:
LOG.critical(
"Error in config.yaml file: Spotify client ID or secret is invalid"
"Error in config.yaml file: Spotify client ID or secret is"
" invalid"
)
#
@ -243,7 +251,8 @@ def validate_config(file_contents):
GENIUS_CLIENT_SECRET = config["genius"]["genius_client_secret"]
else:
LOG.critical(
"Error in config.yaml file: Genius client ID or secret is invalid"
"Error in config.yaml file: Genius client ID or secret is"
" invalid"
)
#
@ -256,7 +265,9 @@ def validate_config(file_contents):
client.models.list()
OPENAI_API_KEY = config["openai"]["openai_api_key"]
except openai.AuthenticationError:
LOG.critical("Error in config.yaml file: OpenAI API key is invalid")
LOG.critical(
"Error in config.yaml file: OpenAI API key is invalid"
)
# Set appropriate values for all non-optional variables
TOKEN = config["bot_info"]["token"]

View File

@ -1,7 +1,15 @@
from lavalink import LoadResult, LoadType, Source, DeferredAudioTrack, PlaylistInfo
from lavalink import (
LoadResult,
LoadType,
Source,
DeferredAudioTrack,
PlaylistInfo,
)
class LoadError(Exception): # We'll raise this if we have trouble loading our track.
class LoadError(
Exception
): # We'll raise this if we have trouble loading our track.
pass
@ -40,7 +48,9 @@ class CustomAudioTrack(DeferredAudioTrack):
):
raise LoadError
first_track = results.tracks[0] # Grab the first track from the results.
first_track = results.tracks[
0
] # Grab the first track from the results.
base64 = first_track.track # Extract the base64 string from the track.
self.track = base64 # We'll store this for later, as it allows us to save making network requests
# if this track is re-used (e.g. repeat).
@ -76,7 +86,9 @@ class SpotifySource(Source):
},
requester=user,
)
return LoadResult(LoadType.TRACK, [track], playlist_info=PlaylistInfo.none())
return LoadResult(
LoadType.TRACK, [track], playlist_info=PlaylistInfo.none()
)
async def load_album(self, user, metadata):
tracks = []
@ -102,7 +114,9 @@ class SpotifySource(Source):
)
)
return LoadResult(LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none())
return LoadResult(
LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none()
)
async def load_playlist(self, user, metadata):
tracks = []
@ -122,13 +136,17 @@ class SpotifySource(Source):
"title": track["track"]["name"],
"uri": track["track"]["external_urls"]["spotify"],
"duration": track["track"]["duration_ms"],
"artworkUrl": track["track"]["album"]["images"][0]["url"],
"artworkUrl": track["track"]["album"]["images"][0][
"url"
],
},
requster=user,
)
)
return LoadResult(LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none())
return LoadResult(
LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none()
)
"""
@ -146,18 +164,24 @@ class AppleSource(Source):
"identifier": metadata["data"][0]["id"],
"isSeekable": True,
"author": metadata["data"][0]["attributes"]["artistName"],
"length": metadata["data"][0]["attributes"]["durationInMillis"],
"length": metadata["data"][0]["attributes"][
"durationInMillis"
],
"isStream": False,
"title": metadata["data"][0]["attributes"]["name"],
"uri": metadata["data"][0]["attributes"]["url"],
"duration": metadata["data"][0]["attributes"]["durationInMillis"],
"artworkUrl": metadata["data"][0]["attributes"]["artwork"]["url"].replace(
"{w}x{h}", "300x300"
),
"duration": metadata["data"][0]["attributes"][
"durationInMillis"
],
"artworkUrl": metadata["data"][0]["attributes"]["artwork"][
"url"
].replace("{w}x{h}", "300x300"),
},
requester=user,
)
return LoadResult(LoadType.TRACK, [track], playlist_info=PlaylistInfo.none())
return LoadResult(
LoadType.TRACK, [track], playlist_info=PlaylistInfo.none()
)
async def load_album(self, user, metadata):
tracks = []
@ -175,19 +199,23 @@ class AppleSource(Source):
"title": track["attributes"]["name"],
"uri": track["attributes"]["url"],
"duration": track["attributes"]["durationInMillis"],
"artworkUrl": track["attributes"]["artwork"]["url"].replace(
"{w}x{h}", "300x300"
),
"artworkUrl": track["attributes"]["artwork"][
"url"
].replace("{w}x{h}", "300x300"),
},
requster=user,
)
)
return LoadResult(LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none())
return LoadResult(
LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none()
)
async def load_playlist(self, user, metadata):
tracks = []
for track in metadata["data"]: # Loop through each track in the playlist.
for track in metadata[
"data"
]: # Loop through each track in the playlist.
tracks.append(
CustomAudioTrack(
{ # Create an instance of our CustomAudioTrack.
@ -199,12 +227,14 @@ class AppleSource(Source):
"title": track["attributes"]["name"],
"uri": track["attributes"]["url"],
"duration": track["attributes"]["durationInMillis"],
"artworkUrl": track["attributes"]["artwork"]["url"].replace(
"{w}x{h}", "300x300"
),
"artworkUrl": track["attributes"]["artwork"][
"url"
].replace("{w}x{h}", "300x300"),
},
requster=user,
)
)
return LoadResult(LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none())
return LoadResult(
LoadType.PLAYLIST, tracks, playlist_info=PlaylistInfo.none()
)

View File

@ -19,11 +19,14 @@ def get_media_api_key():
for js_file in js_files:
response = requests.get(f"{url}/assets/{js_file}")
# "(?<token>(ey[\w-]+)\.([\w-]+)\.([\w-]+))" - Credit to https://github.com/topi314/LavaSrc
match = re.search(r'"(?P<token>ey[\w-]+\.[\w-]+\.[\w-]+)"', response.text)
match = re.search(
r'"(?P<token>ey[\w-]+\.[\w-]+\.[\w-]+)"', response.text
)
if match:
return match.group(1)
LOG.error(
"Failed to find media API key. Apple Music support will not work until a key is found or manually set."
"Failed to find media API key. Apple Music support will not work until"
" a key is found or manually set."
)
return None