@@ -233,6 +233,7 @@ class DiscordWebhook:
233233 username : Optional [str ]
234234 avatar_url : Optional [str ]
235235 tts : bool
236+ attachments : Optional [List [Dict [str , Any ]]]
236237 files : Dict [str , Tuple [Optional [str ], Union [bytes , str ]]]
237238 embeds : List [Dict [str , Any ]]
238239 proxies : Optional [Dict [str , str ]]
@@ -249,6 +250,7 @@ def __init__(
249250 username : Optional [str ] = None ,
250251 avatar_url : Optional [str ] = None ,
251252 tts : bool = False ,
253+ attachments : Optional [List [Dict [str , Any ]]] = None ,
252254 files : Optional [Dict [str , Tuple [Optional [str ], Union [bytes , str ]]]] = None ,
253255 embeds : Optional [List [Dict [str , Any ]]] = None ,
254256 proxies : Optional [Dict [str , str ]] = None ,
@@ -265,11 +267,11 @@ def __init__(
265267 :keyword ``username:`` override the default username of the webhook\n
266268 :keyword ``avatar_url:`` override the default avatar of the webhook\n
267269 :keyword ``tts:`` true if this is a TTS message\n
268- :keyword ``file``: to apply file(s) with message
269- (For example: file=f.read() (here, f = variable that contain
270- attachement path as "rb" mode)) \n
271- :keyword ``filename:`` apply custom file name on attached file
272- content(s )\n
270+ :keyword ``attachments`` optional dict of attachments.
271+ Will be set after executing a webhook \n
272+ :keyword ``files``: to apply file(s) with message
273+ (For example: file=f.read() (here, f = variable that contains the
274+ attachment path as "rb" mode) )\n
273275 :keyword ``embeds:`` list of embedded rich content\n
274276 :keyword ``allowed_mentions:`` allowed mentions for the message\n
275277 :keyword ``proxies:`` dict of proxies\n
@@ -282,12 +284,15 @@ def __init__(
282284 files = {}
283285 if allowed_mentions is None :
284286 allowed_mentions = []
287+ if attachments is None :
288+ attachments = []
285289 self .url = url
286290 self .id = id
287291 self .content = content
288292 self .username = username
289293 self .avatar_url = avatar_url
290294 self .tts = tts
295+ self .attachments = attachments
291296 self .files = files
292297 self .embeds = embeds
293298 self .proxies = proxies
@@ -320,16 +325,50 @@ def remove_embed(self, index: int) -> None:
320325
321326 def remove_file (self , filename : str ) -> None :
322327 """
323- Remove file from `self.files` using specified `filename` if it exists.
328+ Remove file by given `filename` if it exists.
324329 :param filename: filename
325330 """
326- filename = f"_{ filename } "
327- if filename in self .files :
328- del self .files [filename ]
331+ self .files .pop (f'_{ filename } ' , None )
332+ if self .attachments :
333+ index = next (
334+ (
335+ i
336+ for i , item in enumerate (self .attachments )
337+ if item .get ('filename' ) == filename
338+ ),
339+ None ,
340+ )
341+ if index is not None :
342+ self .attachments .pop (index )
343+
344+ def remove_embeds (self ) -> None :
345+ """
346+ Remove all embeds.
347+ :return: None
348+ """
349+ self .embeds = []
350+
351+ def remove_files (self , clear_attachments : bool = True ) -> None :
352+ """
353+ Remove all files and optionally clear the attachments.
354+ :keyword clear_attachments: Clear the attachments.
355+ :type clear_attachments: bool
356+ :return: None
357+ """
358+ self .files = {}
359+ if clear_attachments :
360+ self .clear_attachments ()
361+
362+ def clear_attachments (self ) -> None :
363+ """
364+ Remove all attachments.
365+ :return: None
366+ """
367+ self .attachments = []
329368
330369 def get_embeds (self ) -> List [Dict [str , Any ]]:
331370 """
332- Get all self. embeds as list.
371+ Get all embeds as a list.
333372 :return: self.embeds
334373 """
335374 return self .embeds
@@ -364,25 +403,13 @@ def json(self) -> Dict[str, Any]:
364403 data = {
365404 key : value
366405 for key , value in self .__dict__ .items ()
367- if value and key not in { " url" , " files" , "filename" }
406+ if value and key not in [ ' url' , ' files' ] or key in [ 'embeds' , 'attachments' ]
368407 }
369408 embeds_empty = not any (data ["embeds" ]) if "embeds" in data else True
370409 if embeds_empty and "content" not in data and bool (self .files ) is False :
371410 logger .error ("webhook message is empty! set content or embed data" )
372411 return data
373412
374- def remove_embeds (self ) -> None :
375- """
376- Set `self.embeds` to empty `list`.
377- """
378- self .embeds = []
379-
380- def remove_files (self ) -> None :
381- """
382- Set `self.files` to empty `dict`.
383- """
384- self .files = {}
385-
386413 def api_post_request (self ) -> requests .post :
387414 if bool (self .files ) is False :
388415 return requests .post (
@@ -422,14 +449,11 @@ def handle_rate_limit(self, response, request):
422449 def execute (
423450 self ,
424451 remove_embeds : bool = False ,
425- remove_files : bool = False ,
426452 ) -> requests .Response :
427453 """
428454 Execute the Webhook.
429455 :param remove_embeds: if set to True, calls `self.remove_embeds()`
430456 to empty `self.embeds` after webhook is executed
431- :param remove_files: if set to True, calls `self.remove_files()`
432- to empty `self.files` after webhook is executed
433457 :return: Webhook response
434458 """
435459 response = self .api_post_request ()
@@ -447,10 +471,12 @@ def execute(
447471 )
448472 if remove_embeds :
449473 self .remove_embeds ()
450- if remove_files :
451- self . remove_files ( )
452- if webhook_id := json . loads ( response . content . decode ( "utf-8" )) .get ('id' ):
474+ self . remove_files ( clear_attachments = False )
475+ response_content = json . loads ( response . content . decode ( "utf-8" ) )
476+ if webhook_id := response_content .get ('id' ):
453477 self .id = webhook_id
478+ if attachments := response_content .get ('attachments' ):
479+ self .attachments = attachments
454480 return response
455481
456482 def edit (self ) -> requests .Response :
0 commit comments