[V3 Core] Embed toggling support (#1467)

* [V3 CogManagerUI] implement text-only support in [p]cogs

* Change page length to 1800 + workaround for pages starting with delim

* [V3 Core] text mode support for [p]contact and [p]dm

* Implement text-only support in modlog and fix everything that broke because of it

* Fix modlog stuff in filter too

* Fix tests

* Implement optional embed support in [p]help

* move to .format
This commit is contained in:
palmtree5
2018-03-28 16:15:51 -08:00
committed by Will
parent c2e7bfa641
commit 8eb075fa86
8 changed files with 255 additions and 121 deletions

View File

@@ -418,15 +418,40 @@ class CogManagerUI:
loaded = sorted(list(loaded), key=str.lower)
unloaded = sorted(list(unloaded), key=str.lower)
loaded = ('**{} loaded:**\n').format(len(loaded)) + ", ".join(loaded)
unloaded = ('**{} unloaded:**\n').format(len(unloaded)) + ", ".join(unloaded)
if await ctx.embed_requested():
loaded = ('**{} loaded:**\n').format(len(loaded)) + ", ".join(loaded)
unloaded = ('**{} unloaded:**\n').format(len(unloaded)) + ", ".join(unloaded)
for page in pagify(loaded, delims=[', ', '\n'], page_length=1000):
e = discord.Embed(description=page,
colour=discord.Colour.dark_green())
await ctx.send(embed=e)
for page in pagify(loaded, delims=[', ', '\n'], page_length=1800):
e = discord.Embed(description=page,
colour=discord.Colour.dark_green())
await ctx.send(embed=e)
for page in pagify(unloaded, delims=[', ', '\n'], page_length=1000):
e = discord.Embed(description=page,
colour=discord.Colour.dark_red())
await ctx.send(embed=e)
for page in pagify(unloaded, delims=[', ', '\n'], page_length=1800):
e = discord.Embed(description=page,
colour=discord.Colour.dark_red())
await ctx.send(embed=e)
else:
loaded_count = '**{} loaded:**\n'.format(len(loaded))
loaded = ", ".join(loaded)
unloaded_count = '**{} unloaded:**\n'.format(len(unloaded))
unloaded = ", ".join(unloaded)
loaded_count_sent = False
unloaded_count_sent = False
for page in pagify(loaded, delims=[", ", "\n"], page_length=1800):
if page.startswith(", "):
page = page[2:]
if not loaded_count_sent:
await ctx.send(loaded_count + box(page, lang="css"))
loaded_count_sent = True
else:
await ctx.send(box(page, lang="css"))
for page in pagify(unloaded, delims=[", ", "\n"], page_length=1800):
if page.startswith(", "):
page = page[2:]
if not unloaded_count_sent:
await ctx.send(unloaded_count + box(page, lang="ldif"))
unloaded_count_sent = True
else:
await ctx.send(box(page, lang="ldif"))

View File

@@ -626,7 +626,7 @@ class Core:
await ctx.send_help()
else:
await ctx.bot.change_presence(status=status, activity=game)
await ctx.send(_("Status changed to %s.") % status)
await ctx.send(_("Status changed to {}.").format(status))
@_set.command()
@checks.bot_in_a_guild()
@@ -863,13 +863,13 @@ class Core:
owner = discord.utils.get(ctx.bot.get_all_members(),
id=ctx.bot.owner_id)
author = ctx.message.author
footer = _("User ID: %s") % author.id
footer = _("User ID: {}").format(author.id)
if ctx.guild is None:
source = _("through DM")
else:
source = _("from {}").format(guild)
footer += _(" | Server ID: %s") % guild.id
footer += _(" | Server ID: {}").format(guild.id)
# We need to grab the DM command prefix (global)
# Since it can also be set through cli flags, bot.db is not a reliable
@@ -881,29 +881,43 @@ class Core:
content = _("Use `{}dm {} <text>` to reply to this user"
"").format(prefix, author.id)
description = _("Sent by {} {}").format(author, source)
if isinstance(author, discord.Member):
colour = author.colour
else:
colour = discord.Colour.red()
description = _("Sent by {} {}").format(author, source)
if await ctx.embed_requested():
e = discord.Embed(colour=colour, description=message)
if author.avatar_url:
e.set_author(name=description, icon_url=author.avatar_url)
else:
e.set_author(name=description)
e.set_footer(text=footer)
e = discord.Embed(colour=colour, description=message)
if author.avatar_url:
e.set_author(name=description, icon_url=author.avatar_url)
try:
await owner.send(content, embed=e)
except discord.InvalidArgument:
await ctx.send(_("I cannot send your message, I'm unable to find "
"my owner... *sigh*"))
except:
await ctx.send(_("I'm unable to deliver your message. Sorry."))
else:
await ctx.send(_("Your message has been sent."))
else:
e.set_author(name=description)
e.set_footer(text=footer)
try:
await owner.send(content, embed=e)
except discord.InvalidArgument:
await ctx.send(_("I cannot send your message, I'm unable to find "
"my owner... *sigh*"))
except:
await ctx.send(_("I'm unable to deliver your message. Sorry."))
else:
await ctx.send(_("Your message has been sent."))
msg_text = (
"{}\nMessage:\n\n{}\n{}".format(description, message, footer)
)
try:
await owner.send("{}\n{}".format(content, box(msg_text)))
except discord.InvalidArgument:
await ctx.send(_("I cannot send your message, I'm unable to find "
"my owner... *sigh*"))
except:
await ctx.send(_("I'm unable to deliver your message. Sorry."))
else:
await ctx.send(_("Your message has been sent."))
@commands.command()
@checks.is_owner()
@@ -922,25 +936,36 @@ class Core:
"with."))
return
e = discord.Embed(colour=discord.Colour.red(), description=message)
description = _("Owner of %s") % ctx.bot.user
fake_message = namedtuple('Message', 'guild')
prefixes = await ctx.bot.command_prefix(ctx.bot, fake_message(guild=None))
prefix = prefixes[0]
e.set_footer(text=_("You can reply to this message with %scontact"
"") % prefix)
if ctx.bot.user.avatar_url:
e.set_author(name=description, icon_url=ctx.bot.user.avatar_url)
else:
e.set_author(name=description)
description = _("Owner of {}").format(ctx.bot.user)
content = _("You can reply to this message with {}contact").format(prefix)
if await ctx.embed_requested():
e = discord.Embed(colour=discord.Colour.red(), description=message)
try:
await destination.send(embed=e)
except:
await ctx.send(_("Sorry, I couldn't deliver your message "
"to %s") % destination)
e.set_footer(text=content)
if ctx.bot.user.avatar_url:
e.set_author(name=description, icon_url=ctx.bot.user.avatar_url)
else:
e.set_author(name=description)
try:
await destination.send(embed=e)
except:
await ctx.send(_("Sorry, I couldn't deliver your message "
"to {}").format(destination))
else:
await ctx.send(_("Message delivered to {}").format(destination))
else:
await ctx.send(_("Message delivered to %s") % destination)
response = "{}\nMessage:\n\n{}".format(description, message)
try:
await destination.send("{}\n{}".format(box(response), content))
except:
await ctx.send(_("Sorry, I couldn't deliver your message "
"to {}").format(destination))
else:
await ctx.send(_("Message delivered to {}").format(destination))
@commands.group()
@checks.is_owner()

View File

@@ -280,10 +280,14 @@ async def help(ctx, *cmds: str):
def repl(obj):
return _mentions_transforms.get(obj.group(0), '')
use_embeds = await ctx.embed_requested()
f = formatter.HelpFormatter()
# help by itself just lists our own commands.
if len(cmds) == 0:
embeds = await ctx.bot.formatter.format_help_for(ctx, ctx.bot)
if use_embeds:
embeds = await ctx.bot.formatter.format_help_for(ctx, ctx.bot)
else:
embeds = await f.format_help_for(ctx, ctx.bot)
elif len(cmds) == 1:
# try to see if it is a cog name
name = _mention_pattern.sub(repl, cmds[0])
@@ -293,17 +297,29 @@ async def help(ctx, *cmds: str):
else:
command = ctx.bot.all_commands.get(name)
if command is None:
await destination.send(
embed=ctx.bot.formatter.cmd_not_found(ctx, name))
if use_embeds:
await destination.send(
embed=ctx.bot.formatter.cmd_not_found(ctx, name))
else:
await destination.send(
ctx.bot.command_not_found.format(name)
)
return
embeds = await ctx.bot.formatter.format_help_for(ctx, command)
if use_embeds:
embeds = await ctx.bot.formatter.format_help_for(ctx, command)
else:
embeds = await f.format_help_for(ctx, command)
else:
name = _mention_pattern.sub(repl, cmds[0])
command = ctx.bot.all_commands.get(name)
if command is None:
await destination.send(
embed=ctx.bot.formatter.cmd_not_found(ctx, name))
if use_embeds:
await destination.send(
embed=ctx.bot.formatter.cmd_not_found(ctx, name))
else:
await destination.send(
ctx.bot.command_not_found.format(name)
)
return
for key in cmds[1:]:
@@ -311,29 +327,48 @@ async def help(ctx, *cmds: str):
key = _mention_pattern.sub(repl, key)
command = command.all_commands.get(key)
if command is None:
await destination.send(
embed=ctx.bot.formatter.cmd_not_found(ctx, key))
if use_embeds:
await destination.send(
embed=ctx.bot.formatter.cmd_not_found(ctx, key))
else:
await destination.send(
ctx.bot.command_not_found.format(key)
)
return
except AttributeError:
await destination.send(
embed=ctx.bot.formatter.simple_embed(
ctx,
title='Command "{0.name}" has no subcommands.'.format(command),
color=ctx.bot.formatter.color,
author=ctx.author.display_name))
if use_embeds:
await destination.send(
embed=ctx.bot.formatter.simple_embed(
ctx,
title='Command "{0.name}" has no subcommands.'.format(command),
color=ctx.bot.formatter.color,
author=ctx.author.display_name))
else:
await destination.send(
ctx.bot.command_has_no_subcommands.format(command)
)
return
embeds = await ctx.bot.formatter.format_help_for(ctx, command)
if use_embeds:
embeds = await ctx.bot.formatter.format_help_for(ctx, command)
else:
embeds = await f.format_help_for(ctx, command)
if len(embeds) > 2:
destination = ctx.author
for embed in embeds:
try:
await destination.send(embed=embed)
except discord.HTTPException:
destination = ctx.author
await destination.send(embed=embed)
if use_embeds:
try:
await destination.send(embed=embed)
except discord.HTTPException:
destination = ctx.author
await destination.send(embed=embed)
else:
try:
await destination.send(embed)
except discord.HTTPException:
destination = ctx.author
await destination.send(embed)
@help.error

View File

@@ -59,12 +59,14 @@ class Case:
self.case_number = case_number
self.message = message
async def edit(self, data: dict):
async def edit(self, bot, data: dict):
"""
Edits a case
Parameters
----------
bot: Red
The bot instance
data: dict
The attributes to change
@@ -74,21 +76,31 @@ class Case:
"""
for item in list(data.keys()):
setattr(self, item, data[item])
case_emb = await self.message_content()
await self.message.edit(embed=case_emb)
use_embed = await bot.embed_requested(self.message.channel, self.guild.me)
case_content = await self.message_content(use_embed)
if use_embed:
await self.message.edit(embed=case_content)
else:
await self.message.edit(case_content)
await _conf.guild(self.guild).cases.set_raw(
str(self.case_number), value=self.to_json()
)
async def message_content(self):
async def message_content(self, embed: bool=True):
"""
Format a case message
Parameters
----------
embed: bool
Whether or not to get an embed
Returns
-------
discord.Embed
A rich embed representing a case message
discord.Embed or `str`
A rich embed or string representing a case message
"""
casetype = await get_casetype(self.action_type)
@@ -103,17 +115,16 @@ class Case:
self.case_number
)
emb = discord.Embed(title=title, description=reason)
user = "{}#{} ({})\n".format(
self.user.name, self.user.discriminator, self.user.id)
emb.set_author(name=user, icon_url=self.user.avatar_url)
if self.moderator is not None:
moderator = "{}#{} ({})\n".format(
self.moderator.name,
self.moderator.discriminator,
self.moderator.id
)
emb.add_field(name="Moderator", value=moderator, inline=False)
else:
moderator = "Unknown"
until = None
duration = None
if self.until:
start = datetime.fromtimestamp(self.created_at)
end = datetime.fromtimestamp(self.until)
@@ -122,27 +133,57 @@ class Case:
dur_fmt = _strfdelta(duration)
until = end_fmt
duration = dur_fmt
emb.add_field(name="Until", value=until)
emb.add_field(name="Duration", value=duration)
if self.channel:
emb.add_field(name="Channel", value=self.channel.name, inline=False)
amended_by = None
if self.amended_by:
amended_by = "{}#{} ({})".format(
self.amended_by.name,
self.amended_by.discriminator,
self.amended_by.id
)
emb.add_field(name="Amended by", value=amended_by)
last_modified = None
if self.modified_at:
last_modified = "{}".format(
datetime.fromtimestamp(
self.modified_at
).strftime('%Y-%m-%d %H:%M:%S')
)
emb.add_field(name="Last modified at", value=last_modified)
emb.timestamp = datetime.fromtimestamp(self.created_at)
return emb
user = "{}#{} ({})\n".format(
self.user.name, self.user.discriminator, self.user.id)
if embed:
emb = discord.Embed(title=title, description=reason)
emb.set_author(name=user, icon_url=self.user.avatar_url)
emb.add_field(name="Moderator", value=moderator, inline=False)
if until and duration:
emb.add_field(name="Until", value=until)
emb.add_field(name="Duration", value=duration)
if self.channel:
emb.add_field(name="Channel", value=self.channel.name, inline=False)
if amended_by:
emb.add_field(name="Amended by", value=amended_by)
if last_modified:
emb.add_field(name="Last modified at", value=last_modified)
emb.timestamp = datetime.fromtimestamp(self.created_at)
return emb
else:
case_text = ""
case_text += "{}\n".format(title)
case_text += "**User:** {}\n".format(user)
case_text += "**Moderator:** {}\n".format(moderator)
case_text += "{}\n".format(reason)
if until and duration:
case_text += "**Until:** {}\n**Duration:** {}\n".format(until, duration)
if self.channel:
case_text += "**Channel**: {}\n".format(self.channel.name)
if amended_by:
case_text += "**Amended by:** {}\n".format(amended_by)
if last_modified:
case_text += "**Last modified at:** {}\n".format(last_modified)
return case_text.strip()
def to_json(self) -> dict:
"""Transform the object to a dict
@@ -377,7 +418,7 @@ async def get_all_cases(guild: discord.Guild, bot: Red) -> List[Case]:
return case_list
async def create_case(guild: discord.Guild, created_at: datetime, action_type: str,
async def create_case(bot: Red, guild: discord.Guild, created_at: datetime, action_type: str,
user: Union[discord.User, discord.Member],
moderator: discord.Member=None, reason: str=None,
until: datetime=None, channel: discord.TextChannel=None
@@ -387,6 +428,8 @@ async def create_case(guild: discord.Guild, created_at: datetime, action_type: s
Parameters
----------
bot: `Red`
The bot object
guild: `discord.Guild`
The guild the action was taken in
created_at: datetime
@@ -438,8 +481,12 @@ async def create_case(guild: discord.Guild, created_at: datetime, action_type: s
next_case_number, reason, until, channel, amended_by=None,
modified_at=None, message=None)
if hasattr(mod_channel, "send"): # Not going to be the case for tests
case_emb = await case.message_content()
msg = await mod_channel.send(embed=case_emb)
use_embeds = await bot.embed_requested(mod_channel, guild.me)
case_content = await case.message_content(use_embeds)
if use_embeds:
msg = await mod_channel.send(embed=case_content)
else:
msg = await mod_channel.send(case_content)
case.message = msg
await _conf.guild(guild).cases.set_raw(str(next_case_number), value=case.to_json())
return case