Skip to content

Commit ae97e95

Browse files
committed
Add title and remix to file uploading
1 parent 0890463 commit ae97e95

File tree

2 files changed

+61
-12
lines changed

2 files changed

+61
-12
lines changed

discord/file.py

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,25 @@ def _strip_spoiler(filename: str) -> Tuple[str, bool]:
5959

6060

6161
class _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:

discord/types/message.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -275,17 +275,27 @@ class MessageSearchResult(TypedDict):
275275
MessageSearchSortOrder = Literal['desc', 'asc']
276276

277277

278-
class PartialAttachment(TypedDict):
279-
id: NotRequired[Snowflake]
280-
filename: str
281-
description: NotRequired[str]
282-
uploaded_filename: NotRequired[str]
278+
class PartialAttachment(TypedDict, total=False):
279+
id: Snowflake
280+
filename: Required[str]
281+
description: str
282+
uploaded_filename: str
283+
title: str
284+
duration_secs: float
285+
waveform: str
286+
is_spoiler: bool
287+
is_remix: bool
288+
is_clip: bool
289+
application_id: Snowflake
290+
clip_created_at: str
291+
clip_participant_ids: SnowflakeList
283292

284293

285294
class UploadedAttachment(TypedDict):
286295
id: NotRequired[Snowflake]
287296
filename: str
288297
file_size: int
298+
is_clip: NotRequired[bool]
289299

290300

291301
class CloudAttachment(TypedDict):

0 commit comments

Comments
 (0)