@@ -59,15 +59,25 @@ def _strip_spoiler(filename: str) -> Tuple[str, bool]:
5959
6060
6161class _FileBase :
62- __slots__ = ('_filename' , 'spoiler' , 'description' )
62+ __slots__ = ('_filename' , 'spoiler' , 'description' , 'title' , 'remix' )
6363
64- def __init__ (self , filename : str , * , spoiler : bool = False , description : Optional [str ] = None ):
64+ def __init__ (
65+ self ,
66+ filename : str ,
67+ * ,
68+ spoiler : bool = False ,
69+ description : Optional [str ] = None ,
70+ title : Optional [str ] = None ,
71+ remix : bool = False ,
72+ ) -> None :
6573 self ._filename , filename_spoiler = _strip_spoiler (filename )
6674 if spoiler is MISSING :
6775 spoiler = filename_spoiler
6876
6977 self .spoiler : bool = spoiler
7078 self .description : Optional [str ] = description
79+ self .title : Optional [str ] = title
80+ self .remix : bool = remix
7181
7282 @property
7383 def filename (self ) -> str :
@@ -85,10 +95,16 @@ def to_dict(self, index: int) -> PartialAttachmentPayload:
8595 payload : PartialAttachmentPayload = {
8696 'id' : str (index ),
8797 'filename' : self .filename ,
98+ # n.b. this is set by the filename anyway
99+ # 'is_spoiler': self.spoiler,
88100 }
89101
90102 if self .description is not None :
91103 payload ['description' ] = self .description
104+ if self .title is not None :
105+ payload ['title' ] = self .title
106+ if self .remix :
107+ payload ['is_remix' ] = True
92108
93109 return payload
94110
@@ -125,10 +141,18 @@ class File(_FileBase):
125141 spoiler: :class:`bool`
126142 Whether the attachment is a spoiler. If left unspecified, the :attr:`~File.filename` is used
127143 to determine if the file is a spoiler.
144+ remix: :class:`bool`
145+ Whether the attachment is a remix.
146+
147+ .. versionadded:: 2.1
128148 description: Optional[:class:`str`]
129149 The file description to display, currently only supported for images.
130150
131151 .. versionadded:: 2.0
152+ title: Optional[:class:`str`]
153+ The normalized attachment filename or title of the clip.
154+
155+ .. versionadded:: 2.1
132156 """
133157
134158 __slots__ = ('fp' , '_original_pos' , '_owner' , '_closer' , '_cs_md5' , '_cs_size' )
@@ -140,6 +164,8 @@ def __init__(
140164 * ,
141165 spoiler : bool = MISSING ,
142166 description : Optional [str ] = None ,
167+ title : Optional [str ] = None ,
168+ remix : bool = False ,
143169 ):
144170 if isinstance (fp , io .IOBase ):
145171 if not (fp .seekable () and fp .readable ()):
@@ -164,7 +190,7 @@ def __init__(
164190 else :
165191 filename = getattr (fp , 'name' , 'untitled' )
166192
167- super ().__init__ (filename , spoiler = spoiler , description = description )
193+ super ().__init__ (filename , spoiler = spoiler , description = description , title = title , remix = remix )
168194
169195 @cached_slot_property ('_cs_md5' )
170196 def md5 (self ):
@@ -230,15 +256,18 @@ class CloudFile(_FileBase):
230256
231257 .. note::
232258
233- This URL cannot be used to download the file,
234- it is merely used to send the file to Discord.
259+ This URL cannot be used to download the file, it is merely used to send the file to Discord.
235260 upload_filename: :class:`str`
236261 The filename that Discord has assigned to the file.
237262 spoiler: :class:`bool`
238263 Whether the attachment is a spoiler. If left unspecified, the :attr:`~CloudFile.filename` is used
239264 to determine if the file is a spoiler.
265+ remix: :class:`bool`
266+ Whether the attachment is a remix.
240267 description: Optional[:class:`str`]
241268 The file description to display, currently only supported for images.
269+ title: Optional[:class:`str`]
270+ The normalized attachment filename or title of the clip.
242271 """
243272
244273 __slots__ = ('url' , 'upload_filename' , '_state' )
@@ -251,17 +280,27 @@ def __init__(
251280 * ,
252281 spoiler : bool = MISSING ,
253282 description : Optional [str ] = None ,
283+ title : Optional [str ] = None ,
284+ remix : bool = False ,
254285 state : ConnectionState ,
255286 ):
256- super ().__init__ (filename , spoiler = spoiler , description = description )
287+ super ().__init__ (filename , spoiler = spoiler , description = description , title = title , remix = remix )
257288 self .url = url
258289 self .upload_filename = upload_filename
259290 self ._state = state
260291
261292 @classmethod
262293 async def from_file (cls , * , file : File , state : ConnectionState , data : CloudAttachmentPayload ) -> Self :
263294 await state .http .upload_to_cloud (data ['upload_url' ], file )
264- return cls (data ['upload_url' ], file ._filename , data ['upload_filename' ], description = file .description , state = state )
295+ return cls (
296+ data ['upload_url' ],
297+ file ._filename ,
298+ data ['upload_filename' ],
299+ state = state ,
300+ description = file .description ,
301+ title = file .title ,
302+ remix = file .remix ,
303+ )
265304
266305 @property
267306 def upload_id (self ) -> str :
0 commit comments