11import asyncio
22import logging
33from datetime import datetime
4+ from itertools import zip_longest , takewhile
45from typing import Optional , Union
56from types import SimpleNamespace as param
67
78import discord
89from discord .ext import commands
10+ from discord .utils import escape_markdown , escape_mentions
911
1012from dateutil import parser
1113from natural .date import duration
1517from core .models import PermissionLevel
1618from core .paginator import PaginatorSession
1719from 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
2022logger = 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