|
29 | 29 | import os |
30 | 30 | from typing import TYPE_CHECKING |
31 | 31 |
|
32 | | -__all__ = ("File",) |
| 32 | +__all__ = ( |
| 33 | + "File", |
| 34 | + "VoiceMessage", |
| 35 | +) |
33 | 36 |
|
34 | 37 |
|
35 | 38 | class File: |
@@ -89,6 +92,7 @@ def __init__( |
89 | 92 | description: str | None = None, |
90 | 93 | spoiler: bool = False, |
91 | 94 | ): |
| 95 | + |
92 | 96 | if isinstance(fp, io.IOBase): |
93 | 97 | if not (fp.seekable() and fp.readable()): |
94 | 98 | raise ValueError(f"File buffer {fp!r} must be seekable and readable") |
@@ -143,3 +147,60 @@ def close(self) -> None: |
143 | 147 | self.fp.close = self._closer |
144 | 148 | if self._owner: |
145 | 149 | self._closer() |
| 150 | + |
| 151 | + |
| 152 | +class VoiceMessage(File): |
| 153 | + """A special case of the File class that represents a voice message. |
| 154 | +
|
| 155 | + .. versionadded:: 2.7 |
| 156 | +
|
| 157 | + .. note:: |
| 158 | +
|
| 159 | + Similar to File objects, VoiceMessage objects are single use and are not meant to be reused in |
| 160 | + multiple requests. |
| 161 | +
|
| 162 | + Attributes |
| 163 | + ---------- |
| 164 | + fp: Union[:class:`os.PathLike`, :class:`io.BufferedIOBase`] |
| 165 | + A audio file-like object opened in binary mode and read mode |
| 166 | + or a filename representing a file in the hard drive to |
| 167 | + open. |
| 168 | +
|
| 169 | + .. note:: |
| 170 | +
|
| 171 | + If the file-like object passed is opened via ``open`` then the |
| 172 | + modes 'rb' should be used. |
| 173 | +
|
| 174 | + To pass binary data, consider usage of ``io.BytesIO``. |
| 175 | +
|
| 176 | + filename: Optional[:class:`str`] |
| 177 | + The filename to display when uploading to Discord. |
| 178 | + If this is not given then it defaults to ``fp.name`` or if ``fp`` is |
| 179 | + a string then the ``filename`` will default to the string given. |
| 180 | + description: Optional[:class:`str`] |
| 181 | + The description of a file, used by Discord to display alternative text on images. |
| 182 | + spoiler: :class:`bool` |
| 183 | + Whether the attachment is a spoiler. |
| 184 | + waveform: Optional[:class:`str`] |
| 185 | + The base64 encoded bytearray representing a sampled waveform. |
| 186 | + duration_secs: Optional[:class:`float`] |
| 187 | + The duration of the voice message. |
| 188 | + """ |
| 189 | + |
| 190 | + __slots__ = ( |
| 191 | + "waveform", |
| 192 | + "duration_secs", |
| 193 | + ) |
| 194 | + |
| 195 | + def __init__( |
| 196 | + self, |
| 197 | + fp: str | bytes | os.PathLike | io.BufferedIOBase, |
| 198 | + filename: str | None = None, |
| 199 | + *, |
| 200 | + waveform: str = "", |
| 201 | + duration_secs: float = 0.0, |
| 202 | + **kwargs, |
| 203 | + ): |
| 204 | + super().__init__(fp, filename, **kwargs) |
| 205 | + self.waveform = waveform |
| 206 | + self.duration_secs = duration_secs |
0 commit comments