Skip to content

Commit b3e8f62

Browse files
committed
Snippets/aliases
1 parent 8877a1b commit b3e8f62

File tree

5 files changed

+149
-98
lines changed

5 files changed

+149
-98
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2929
- `?plugin enabled` results are now sorted alphabetically.
3030
- `?plugin registry` results are now sorted alphabetically, helps user find plugins more easily.
3131
- `?plugin registry page-number` plugin registry can specify a page number for quick access.
32+
- A reworked interface for `?snippet` and `?alias`.
33+
- Add an `?snippet raw <name>` command for viewing the raw content of a snippet (escaped markdown).
3234

3335
### Fixes
3436

@@ -37,6 +39,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3739
- `mod_typing` and `user_typing` will no longer show when user is blocked.
3840
- Better `?block` usage message.
3941
- Resolves errors when message was sent by mods after thread is closed somehow.
42+
- Recipient join/leave server messages are limited to only the guild set by `GUILD_ID`.
43+
- When creating snippets and aliases, it now checks if another snippets/aliases with the same name exists.
4044

4145
### Internal
4246

bot.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def __init__(self):
8787
self.db = AsyncIOMotorClient(mongo_uri).modmail_bot
8888
except ConfigurationError as e:
8989
logger.critical(
90-
"Your MONGO_URI is copied wrong, try re-copying from the source again."
90+
"Your MONGO_URI might be copied wrong, try re-copying from the source again. "
91+
"Otherwise noted in the following message:"
9192
)
9293
logger.critical(str(e))
9394
sys.exit(0)

cogs/modmail.py

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import asyncio
22
import logging
33
from datetime import datetime
4+
from itertools import zip_longest, takewhile
45
from typing import Optional, Union
56
from types import SimpleNamespace as param
67

78
import discord
89
from discord.ext import commands
10+
from discord.utils import escape_markdown, escape_mentions
911

1012
from dateutil import parser
1113
from natural.date import duration
@@ -15,7 +17,7 @@
1517
from core.models import PermissionLevel
1618
from core.paginator import PaginatorSession
1719
from core.time import UserFriendlyTime, human_timedelta
18-
from core.utils import format_preview, User
20+
from core.utils import format_preview, User, create_not_found_embed
1921

2022
logger = logging.getLogger("Modmail")
2123

@@ -100,60 +102,74 @@ async def setup(self, ctx):
100102

101103
@commands.group(aliases=["snippets"], invoke_without_command=True)
102104
@checks.has_permissions(PermissionLevel.SUPPORTER)
103-
async def snippet(self, ctx):
105+
async def snippet(self, ctx, *, name: str.lower = None):
104106
"""
105107
Create pre-defined messages for use in threads.
106108
107109
When `{prefix}snippet` is used by itself, this will retrieve
108-
a list of snippets that are currently set.
110+
a list of snippets that are currently set. `{prefix}snippet-name` will show what the
111+
snippet point to.
109112
110-
To use snippets:
111-
112-
First create a snippet using:
113+
To create a snippet:
113114
- `{prefix}snippet add snippet-name A pre-defined text.`
114115
115-
Afterwards, you can use your snippet in a thread channel
116+
You can use your snippet in a thread channel
116117
with `{prefix}snippet-name`, the message "A pre-defined text."
117118
will be sent to the recipient.
118119
120+
Currently, there is not a default anonymous snippet command; however, a workaround
121+
is available using `{prefix}alias`. Here is how:
122+
- `{prefix}alias add snippet-name anonreply A pre-defined anonymous text.`
123+
119124
See also `{prefix}alias`.
120125
"""
121126

122-
embeds = []
127+
if name is not None:
128+
val = self.bot.snippets.get(name)
129+
if val is None:
130+
embed = create_not_found_embed(name, self.bot.snippets.keys(), 'Snippet')
131+
return await ctx.send(embed=embed)
132+
return await ctx.send(escape_mentions(val))
123133

124-
if self.bot.snippets:
125-
embed = discord.Embed(
126-
color=self.bot.main_color,
127-
description="Here is a list of snippets "
128-
"that are currently configured.",
129-
)
130-
else:
134+
if not self.bot.snippets:
131135
embed = discord.Embed(
132136
color=discord.Color.red(),
133137
description="You dont have any snippets at the moment.",
134138
)
135139
embed.set_footer(
136140
text=f"Do {self.bot.prefix}help snippet for more commands."
137141
)
142+
embed.set_author(name="Snippets", icon_url=ctx.guild.icon_url)
143+
return await ctx.send(embed=embed)
138144

139-
embed.set_author(name="Snippets", icon_url=ctx.guild.icon_url)
140-
embeds.append(embed)
145+
embeds = []
141146

142-
for name, value in self.bot.snippets.items():
143-
if len(embed.fields) == 5:
144-
embed = discord.Embed(
145-
color=self.bot.main_color, description=embed.description
147+
for names in zip_longest(*(iter(sorted(self.bot.snippets)),) * 15):
148+
description = "\n".join(
149+
": ".join((str(a), b))
150+
for a, b in enumerate(
151+
takewhile(lambda x: x is not None, names), start=1
146152
)
147-
embed.set_author(name="Snippets", icon_url=ctx.guild.icon_url)
148-
embeds.append(embed)
149-
embed.add_field(name=name, value=value, inline=False)
153+
)
154+
embed = discord.Embed(color=self.bot.main_color, description=description)
155+
embed.set_author(name="Snippets", icon_url=ctx.guild.icon_url)
156+
embeds.append(embed)
150157

151158
session = PaginatorSession(ctx, *embeds)
152159
await session.run()
153160

161+
@snippet.command(name="raw")
162+
@checks.has_permissions(PermissionLevel.SUPPORTER)
163+
async def snippet_raw(self, ctx, *, name: str.lower):
164+
val = self.bot.snippets.get(name)
165+
if val is None:
166+
embed = create_not_found_embed(name, self.bot.snippets.keys(), 'Snippet')
167+
return await ctx.send(embed=embed)
168+
return await ctx.send(escape_markdown(escape_mentions(val)).replace('<', '\\<'))
169+
154170
@snippet.command(name="add")
155171
@checks.has_permissions(PermissionLevel.SUPPORTER)
156-
async def snippet_add(self, ctx, name: str.lower, *, value):
172+
async def snippet_add(self, ctx, name: str.lower, *, value: commands.clean_content):
157173
"""
158174
Add a snippet.
159175
@@ -167,19 +183,35 @@ async def snippet_add(self, ctx, name: str.lower, *, value):
167183
color=discord.Color.red(),
168184
description=f"Snippet `{name}` already exists.",
169185
)
170-
else:
171-
self.bot.snippets[name] = value
172-
await self.bot.config.update()
186+
return await ctx.send(embed=embed)
173187

188+
if name in self.bot.aliases:
174189
embed = discord.Embed(
175-
title="Added snippet",
176-
color=self.bot.main_color,
177-
description=f'`{name}` will now send "{value}".',
190+
title="Error",
191+
color=discord.Color.red(),
192+
description=f"An alias with the same name already exists: `{name}`.",
193+
)
194+
return await ctx.send(embed=embed)
195+
196+
if len(name) > 120:
197+
embed = discord.Embed(
198+
title="Error",
199+
color=discord.Color.red(),
200+
description=f"Snippet names cannot be longer than 120 characters.",
178201
)
202+
return await ctx.send(embed=embed)
179203

180-
await ctx.send(embed=embed)
204+
self.bot.snippets[name] = value
205+
await self.bot.config.update()
206+
207+
embed = discord.Embed(
208+
title="Added snippet",
209+
color=self.bot.main_color,
210+
description=f'Successfully created snippet.',
211+
)
212+
return await ctx.send(embed=embed)
181213

182-
@snippet.command(name="remove", aliases=["del", "delete", "rm"])
214+
@snippet.command(name="remove", aliases=["del", "delete"])
183215
@checks.has_permissions(PermissionLevel.SUPPORTER)
184216
async def snippet_remove(self, ctx, *, name: str.lower):
185217
"""Remove a snippet."""
@@ -188,18 +220,12 @@ async def snippet_remove(self, ctx, *, name: str.lower):
188220
embed = discord.Embed(
189221
title="Removed snippet",
190222
color=self.bot.main_color,
191-
description=f"`{name}` no longer exists.",
223+
description=f"Snippet `{name}` is now deleted.",
192224
)
193225
self.bot.snippets.pop(name)
194226
await self.bot.config.update()
195-
196227
else:
197-
embed = discord.Embed(
198-
title="Error",
199-
color=discord.Color.red(),
200-
description=f"Snippet `{name}` does not exist.",
201-
)
202-
228+
embed = create_not_found_embed(name, self.bot.snippets.keys(), 'Snippet')
203229
await ctx.send(embed=embed)
204230

205231
@snippet.command(name="edit")
@@ -221,13 +247,8 @@ async def snippet_edit(self, ctx, name: str.lower, *, value):
221247
color=self.bot.main_color,
222248
description=f'`{name}` will now send "{value}".',
223249
)
224-
225250
else:
226-
embed = discord.Embed(
227-
title="Error",
228-
color=discord.Color.red(),
229-
description=f"Snippet `{name}` does not exist.",
230-
)
251+
embed = create_not_found_embed(name, self.bot.snippets.keys(), 'Snippet')
231252
await ctx.send(embed=embed)
232253

233254
@commands.command()

0 commit comments

Comments
 (0)