Skip to content

Commit

Permalink
Improved multicommand alias v3.3.1-dev1
Browse files Browse the repository at this point in the history
  • Loading branch information
Taaku18 committed Nov 7, 2019
1 parent de71ab2 commit 1453108
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 116 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,18 @@ This project mostly adheres to [Semantic Versioning](https://semver.org/spec/v2.
however, insignificant breaking changes does not guarantee a major version bump, see the reasoning [here](https://github.com/kyb3r/modmail/issues/319).


# v3.3.1-dev0
# v3.3.1-dev1

### Added

- "enable" and "disable" support for yes or no config vars.
- Added "perhaps you meant" section to `?config help`.
- Multi-command alias is now more stable. With support for a single quote escape `\"`.

### Internal

- Commit to black format line width max = 99, consistent with pylint.
- Alias parser is rewritten without shlex.

# v3.3.0

Expand Down
2 changes: 1 addition & 1 deletion bot.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = "3.3.1-dev0"
__version__ = "3.3.1-dev1"

import asyncio
import logging
Expand Down
151 changes: 64 additions & 87 deletions cogs/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import discord
from discord.enums import ActivityType, Status
from discord.ext import commands, tasks
from discord.ext.commands.view import StringView
from discord.utils import escape_markdown, escape_mentions

from aiohttp import ClientResponseError
Expand Down Expand Up @@ -1002,6 +1003,7 @@ async def alias_add(self, ctx, name: str.lower, *, value):
return await ctx.send(embed=embed)

values = utils.parse_alias(value)
save_aliases = []

if not values:
embed = discord.Embed(
Expand All @@ -1012,59 +1014,45 @@ async def alias_add(self, ctx, name: str.lower, *, value):
embed.set_footer(text=f'See "{self.bot.prefix}alias add" for more details.')
return await ctx.send(embed=embed)

if len(values) == 1:
linked_command, *messages = values[0].split(maxsplit=1)
multiple_alias = len(values) > 1

embed = discord.Embed(
title="Added alias",
color=self.bot.main_color
)

if multiple_alias:
embed.description = f'`{name}` points to: "{values[0]}".'
else:
embed.description = f"`{name}` now points to the following steps:"

for i, val in enumerate(values, start=1):
view = StringView(val)
linked_command = view.get_word()
message = view.read_rest()

if not self.bot.get_command(linked_command):
alias_command = self.bot.aliases.get(linked_command)
if alias_command is not None:
if messages:
values = [f"{alias_command} {messages[0]}"]
else:
values = [alias_command]
save_aliases.append(f"{alias_command} {message}".strip())
else:
embed = discord.Embed(
title="Error",
color=self.bot.error_color,
description="The command you are attempting to point "
f"to does not exist: `{linked_command}`.",
)
return await ctx.send(embed=embed)
embed = discord.Embed(title="Error", color=self.bot.error_color)

embed = discord.Embed(
title="Added alias",
color=self.bot.main_color,
description=f'`{name}` points to: "{values[0]}".',
)
if multiple_alias:
embed.description = ("The command you are attempting to point "
f"to does not exist: `{linked_command}`.")
else:
embed.description = ("The command you are attempting to point "
f"to n step {i} does not exist: `{linked_command}`.")

else:
embed = discord.Embed(
title="Added alias",
color=self.bot.main_color,
description=f"`{name}` now points to the following steps:",
)
return await ctx.send(embed=embed)
else:
save_aliases.append(val)

for i, val in enumerate(values, start=1):
linked_command, *messages = val.split(maxsplit=1)
if not self.bot.get_command(linked_command):
alias_command = self.bot.aliases.get(linked_command)
if alias_command is not None:
if messages:
values = [f"{alias_command} {messages[0]}"]
else:
values = [alias_command]
else:
embed = discord.Embed(
title="Error",
color=self.bot.error_color,
description="The command you are attempting to point "
f"to n step {i} does not exist: `{linked_command}`.",
)
return await ctx.send(embed=embed)
embed.description += f"\n{i}: {val}"
embed.description += f"\n{i}: {val}"

self.bot.aliases[name] = " && ".join(values)
self.bot.aliases[name] = " && ".join(f"\"{a}\"" for a in save_aliases)
await self.bot.config.update()

return await ctx.send(embed=embed)

@alias.command(name="remove", aliases=["del", "delete"])
Expand Down Expand Up @@ -1097,6 +1085,7 @@ async def alias_edit(self, ctx, name: str.lower, *, value):
return await ctx.send(embed=embed)

values = utils.parse_alias(value)
save_aliases = []

if not values:
embed = discord.Embed(
Expand All @@ -1107,56 +1096,44 @@ async def alias_edit(self, ctx, name: str.lower, *, value):
embed.set_footer(text=f'See "{self.bot.prefix}alias add" for more details.')
return await ctx.send(embed=embed)

if len(values) == 1:
linked_command, *messages = values[0].split(maxsplit=1)
multiple_alias = len(values) > 1

embed = discord.Embed(
title="Edited alias",
color=self.bot.main_color
)

if multiple_alias:
embed.description = f'`{name}` points to: "{values[0]}".'
else:
embed.description = f"`{name}` now points to the following steps:"

for i, val in enumerate(values, start=1):
view = StringView(val)
linked_command = view.get_word()
message = view.read_rest()

if not self.bot.get_command(linked_command):
alias_command = self.bot.aliases.get(linked_command)
if alias_command is not None:
if messages:
values = [f"{alias_command} {messages[0]}"]
else:
values = [alias_command]
save_aliases.append(f"{alias_command} {message}".strip())
else:
embed = discord.Embed(
title="Error",
color=self.bot.error_color,
description="The command you are attempting to point "
f"to does not exist: `{linked_command}`.",
)
return await ctx.send(embed=embed)
embed = discord.Embed(
title="Edited alias",
color=self.bot.main_color,
description=f'`{name}` now points to: "{values[0]}".',
)
embed = discord.Embed(title="Error", color=self.bot.error_color)

else:
embed = discord.Embed(
title="Edited alias",
color=self.bot.main_color,
description=f"`{name}` now points to the following steps:",
)

for i, val in enumerate(values, start=1):
linked_command, *messages = val.split(maxsplit=1)
if not self.bot.get_command(linked_command):
alias_command = self.bot.aliases.get(linked_command)
if alias_command is not None:
if messages:
values = [f"{alias_command} {messages[0]}"]
else:
values = [alias_command]
if multiple_alias:
embed.description = ("The command you are attempting to point "
f"to does not exist: `{linked_command}`.")
else:
embed = discord.Embed(
title="Error",
color=self.bot.error_color,
description="The command you are attempting to point "
f"to on step {i} does not exist: `{linked_command}`.",
)
return await ctx.send(embed=embed)
embed.description += f"\n{i}: {val}"
embed.description = ("The command you are attempting to point "
f"to n step {i} does not exist: `{linked_command}`.")

return await ctx.send(embed=embed)
else:
save_aliases.append(val)

embed.description += f"\n{i}: {val}"

self.bot.aliases[name] = "&&".join(values)
self.bot.aliases[name] = " && ".join(f"\"{a}\"" for a in save_aliases)
await self.bot.config.update()
return await ctx.send(embed=embed)

Expand Down
40 changes: 13 additions & 27 deletions core/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import base64
import functools
import re
import shlex
import typing
from difflib import get_close_matches
from distutils.util import strtobool as _stb # pylint: disable=import-error
Expand Down Expand Up @@ -215,35 +215,21 @@ def create_not_found_embed(word, possibilities, name, n=2, cutoff=0.6) -> discor


def parse_alias(alias):
if "&&" not in alias:
if alias.startswith('"') and alias.endswith('"'):
return [alias[1:-1]]
return [alias]
def encode_alias(m):
return "\x1AU" + base64.b64encode(m.group(1).encode()).decode() + "\x1AU"

buffer = ""
cmd = []
try:
for token in shlex.shlex(alias, punctuation_chars="&"):
if token != "&&":
buffer += " " + token
continue

buffer = buffer.strip()
if buffer.startswith('"') and buffer.endswith('"'):
buffer = buffer[1:-1]
cmd += [buffer]
buffer = ""
except ValueError:
return []
def decode_alias(m):
return base64.b64decode(m.group(1).encode()).decode()

alias = re.sub(r"(?:(?<=^)(?:\s*(?<!\\)(?:\")\s*)|(?<=&&)(?:\s*(?<!\\)(?:\")\s*))(.+?)"
r"(?:(?:\s*(?<!\\)(?:\")\s*)(?=&&)|(?:\s*(?<!\\)(?:\")\s*)(?=$))",
encode_alias, alias)

buffer = buffer.strip()
if buffer.startswith('"') and buffer.endswith('"'):
buffer = buffer[1:-1]
cmd += [buffer]
aliases = []
for alias in re.split(r"\s*&&\s*", alias):
aliases.append(re.sub("\x1AU(.+?)\x1AU", decode_alias, alias))

if not all(cmd):
return []
return cmd
return aliases


def format_description(i, names):
Expand Down

0 comments on commit 1453108

Please sign in to comment.