improved bot ux/ui

This commit is contained in:
2021-11-06 11:21:44 +01:00
parent f8e72443f4
commit 4cbc56e4e2
3 changed files with 82 additions and 24 deletions
+60 -17
View File
@@ -1,10 +1,12 @@
import asyncio import asyncio
import datetime
import re import re
from typing import Optional from typing import Optional
import discord import discord
from discord.channel import TextChannel from discord.channel import TextChannel
from discord.ext.commands.context import Context from discord.ext.commands.context import Context
from discord.ext.commands.errors import CommandError
import lavalink import lavalink
from discord.ext import commands from discord.ext import commands
from lavalink.models import AudioTrack, DefaultPlayer from lavalink.models import AudioTrack, DefaultPlayer
@@ -16,6 +18,7 @@ from context import CustomContext
from discord import Embed from discord import Embed
from utils.database import Playlist from utils.database import Playlist
from utils.exceptions import EmbeddedCommandException
url_rx = re.compile(r"https?://(?:www\.)?.+") url_rx = re.compile(r"https?://(?:www\.)?.+")
@@ -122,6 +125,26 @@ class Music(commands.Cog):
) )
player.add(requester=self.bot.user.id, track=track) player.add(requester=self.bot.user.id, track=track)
async def create_track_embed(self, track: AudioTrack) -> Embed:
embed_color = self.bot.colors["embed"]
embed = discord.Embed(
title=f"Now playing...",
colour=embed_color,
)
embed.description = f"[{track.title}]({track.uri})"
embed.set_thumbnail(
url=f"https://i3.ytimg.com/vi/{track.identifier}/mqdefault.jpg"
)
try:
duration = str(datetime.timedelta(milliseconds=int(track.duration)))
except OverflowError:
duration = "🔴 LIVE"
embed.add_field(name="Duration", value=duration)
embed.add_field(name="Author", value=track.author)
return embed
def cog_unload(self): def cog_unload(self):
"""Cog unload handler. This removes any event hooks that were registered.""" """Cog unload handler. This removes any event hooks that were registered."""
self.bot.lavalink._event_hooks.clear() self.bot.lavalink._event_hooks.clear()
@@ -142,13 +165,15 @@ class Music(commands.Cog):
return guild_check return guild_check
async def cog_command_error(self, ctx, error): async def cog_command_error(self, ctx: CustomContext, error: CommandError):
if isinstance(error, commands.CommandInvokeError): if isinstance(error, commands.CommandInvokeError):
await ctx.send(error.original) await ctx.send(error.original)
# The above handles errors thrown in this cog and shows them to the user. # The above handles errors thrown in this cog and shows them to the user.
# This shouldn't be a problem as the only errors thrown in this cog are from `ensure_voice` # This shouldn't be a problem as the only errors thrown in this cog are from `ensure_voice`
# which contain a reason string, such as "Join a voicechannel" etc. You can modify the above # which contain a reason string, such as "Join a voicechannel" etc. You can modify the above
# if you want to do things differently. # if you want to do things differently.
elif isinstance(error, EmbeddedCommandException):
await error.send(ctx)
async def ensure_voice(self, ctx): async def ensure_voice(self, ctx):
"""This check ensures that the bot and command author are in the same voicechannel.""" """This check ensures that the bot and command author are in the same voicechannel."""
@@ -173,7 +198,14 @@ class Music(commands.Cog):
if not player.is_connected: if not player.is_connected:
if not should_connect: if not should_connect:
raise commands.CommandInvokeError("Not connected.") bot_name = self.bot.config["info"]["name"]
embed = await EmbedGenerator.Message(
ctx,
f"{bot_name} is not connected",
"However you can start playing music using `/connect`",
no_send=True,
)
raise EmbeddedCommandException(embed)
permissions = ctx.author.voice.channel.permissions_for(ctx.me) permissions = ctx.author.voice.channel.permissions_for(ctx.me)
@@ -201,14 +233,7 @@ class Music(commands.Cog):
elif isinstance(event, lavalink.events.TrackStartEvent): elif isinstance(event, lavalink.events.TrackStartEvent):
channel_id = int(event.player.fetch("channel")) channel_id = int(event.player.fetch("channel"))
channel: TextChannel = self.bot.get_channel(channel_id) channel: TextChannel = self.bot.get_channel(channel_id)
embed = await self.create_track_embed(event.player.current)
color = self.bot.colors["embed"]
current_track: AudioTrack = event.player.current
embed = Embed(
title="Now playing:",
description=f"[{current_track.title}]({current_track.uri})",
color=color,
)
await channel.send(embed=embed) await channel.send(embed=embed)
elif isinstance(event, lavalink.events.TrackEndEvent): elif isinstance(event, lavalink.events.TrackEndEvent):
await self.fill_player_queue(event.player, 1) await self.fill_player_queue(event.player, 1)
@@ -218,12 +243,13 @@ class Music(commands.Cog):
"""Starts playing Christmas bangers""" """Starts playing Christmas bangers"""
# Get the player for this guild from cache. # Get the player for this guild from cache.
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id)
await self.fill_player_queue(player, self.bot.config["queue_buffer_size"]) await self.fill_player_queue(player, self.bot.config["queue_buffer_size"] + 1)
if not player.is_playing: if not player.is_playing:
await player.play() await player.play()
await ctx.send("Started playing") await EmbedGenerator.Title(ctx, "*⃣ | Connected.")
return
@commands.command(name="skip", aliases=["next"]) @commands.command(name="skip", aliases=["next"])
async def skip(self, ctx: Context): async def skip(self, ctx: Context):
@@ -236,23 +262,33 @@ class Music(commands.Cog):
async def queue(self, ctx: Context): async def queue(self, ctx: Context):
"""Ghetto queue""" """Ghetto queue"""
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id)
await EmbedGenerator.Message(ctx, "Queue:", player.queue)
embed_color = self.bot.colors["embed"]
embed = Embed(title="Coming Up...", colour=embed_color)
if len(player.queue) > 0:
embed.description = "\n".join(
f"{index}. [{track.title}]({track.uri})"
for index, track in enumerate(player.queue, 1)
)
else:
embed.description = "We are still determining a playlist"
await ctx.send(embed=embed)
@commands.command(name="disconnect", aliases=["dc", "stop"]) @commands.command(name="disconnect", aliases=["dc", "stop"])
async def disconnect(self, ctx: Context): async def disconnect(self, ctx: Context):
"""Disconnects ChristmasBot""" """Disconnects ChristmasBot"""
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id)
if not player.is_connected:
return await EmbedGenerator.Title(ctx, "Not connected.")
if not ctx.author.voice or ( if not ctx.author.voice or (
player.is_connected player.is_connected
and ctx.author.voice.channel.id != int(player.channel_id) and ctx.author.voice.channel.id != int(player.channel_id)
): ):
# Abuse prevention. Users not in voice channels, or not in the same voice channel as the bot # Abuse prevention. Users not in voice channels, or not in the same voice channel as the bot
# may not disconnect the bot. # may not disconnect the bot.
return await EmbedGenerator.Title(ctx, "You're not in my voicechannel!") await EmbedGenerator.Title(ctx, "You're not in my voicechannel!")
return
# Clear the queue to ensure old tracks don't start playing # Clear the queue to ensure old tracks don't start playing
# when someone else queues something. # when someone else queues something.
@@ -263,6 +299,13 @@ class Music(commands.Cog):
await ctx.voice_client.disconnect(force=True) await ctx.voice_client.disconnect(force=True)
await EmbedGenerator.Title(ctx, "*⃣ | Disconnected.") await EmbedGenerator.Title(ctx, "*⃣ | Disconnected.")
@commands.command(name="now")
async def now_playing(self, ctx: CustomContext):
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id)
track = player.current
embed = await self.create_track_embed(track)
await ctx.send(embed=embed)
def setup(bot: ChristmasBot): def setup(bot: ChristmasBot):
bot.add_cog(Music(bot)) bot.add_cog(Music(bot))
+10 -6
View File
@@ -1,8 +1,8 @@
from typing import Optional from typing import Optional, Union
import discord import discord
from discord import Embed
from discord.ext.commands import Context from discord.ext.commands import Context
from discord import Embed
class EmbedGenerator: class EmbedGenerator:
@@ -13,7 +13,9 @@ class EmbedGenerator:
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@staticmethod @staticmethod
async def Message(ctx: Context, title: str, message: Optional[str] = "", **kwargs): async def Message(
ctx: Context, title: str, message: Optional[str] = "", **kwargs
) -> Embed:
color = ctx.bot.colors["embed"] color = ctx.bot.colors["embed"]
em = Embed(title=title, description=message, color=color) em = Embed(title=title, description=message, color=color)
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@@ -21,20 +23,22 @@ class EmbedGenerator:
@staticmethod @staticmethod
async def Image( async def Image(
ctx: Context, title: str, url: str, message: Optional[str] = "", **kwargs ctx: Context, title: str, url: str, message: Optional[str] = "", **kwargs
): ) -> Embed:
color = ctx.bot.colors["embed"] color = ctx.bot.colors["embed"]
em = Embed(title=title, description=message, url=url, color=color) em = Embed(title=title, description=message, url=url, color=color)
em.set_image(url=url) em.set_image(url=url)
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@staticmethod @staticmethod
async def Title(ctx: Context, title: str, **kwargs): async def Title(ctx: Context, title: str, **kwargs) -> Embed:
color = ctx.bot.colors["embed"] color = ctx.bot.colors["embed"]
em = Embed(title=title, color=color) em = Embed(title=title, color=color)
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@staticmethod @staticmethod
async def SendWithFooter(ctx: Context, em: Embed, **kwargs) -> discord.Message: async def SendWithFooter(
ctx: Context, em: Embed, **kwargs
) -> Union[discord.Message, Embed]:
avatar = ctx.author.avatar.with_static_format("jpeg") avatar = ctx.author.avatar.with_static_format("jpeg")
em.set_footer(text=f"Requested by: {ctx.author}", icon_url=avatar) em.set_footer(text=f"Requested by: {ctx.author}", icon_url=avatar)
if kwargs.get("no_send", False): if kwargs.get("no_send", False):
+11
View File
@@ -0,0 +1,11 @@
from discord.embeds import Embed
from context import CustomContext
from discord.ext.commands import CommandError
class EmbeddedCommandException(CommandError):
def __init__(self, embed: Embed) -> None:
self.embed = embed
async def send(self, ctx: CustomContext):
await ctx.send(embed=self.embed)