def send_message( self, token: str, interaction_id: int, *, type: int, initial_response: bool, content: str = None, embed: discord.Embed = None, embeds: List[discord.Embed] = [], tts: bool = False, allowed_mentions: discord.AllowedMentions = None, flags: int = None, ): payload = {"type": type} if embed is not None: embeds = [embed] if allowed_mentions is None: allowed_mentions = self.bot.allowed_mentions data = {} if content: data["content"] = content if tts: data["tts"] = True if embeds: data["embeds"] = [e.to_dict() for e in embeds] if allowed_mentions: data["allowed_mentions"] = allowed_mentions.to_dict() if flags: data["flags"] = flags if embeds: data["embeds"] = [e.to_dict() for e in embeds] if flags: data["flags"] = flags if data: data["allowed_mentions"] = allowed_mentions.to_dict() payload["data"] = data if initial_response: url = "/interactions/{interaction_id}/{token}/callback" send_data = payload else: url = "/webhooks/{application_id}/{token}" send_data = data route = Route( "POST", url, interaction_id=interaction_id, token=token, application_id=self.application_id, ) log.debug( f"sending response, initial = {initial_response}: {send_data}") return self.request(route, json=send_data)
async def send(self, send_type: int = 4, content: str = "", embeds: typing.List[discord.Embed] = None, tts: bool = False, allowed_mentions: discord.AllowedMentions = None, hidden: bool = False): """ Sends response of the slash command. .. note:: Param ``hidden`` ONLY works without embeds. :param send_type: Type of the response. Refer Discord API DOCS for more info about types. Default ``4``. :type send_type: int :param content: Content of the response. Can be ``None``. :type content: str :param embeds: Embeds of the response. Maximum 10, can be empty. :type embeds: List[discord.Embed] :param tts: Whether to speak message using tts. Default ``False``. :type tts: bool :param allowed_mentions: AllowedMentions of the message. :type allowed_mentions: discord.AllowedMentions :param hidden: Whether the message is hidden, which means message content will only be seen to the author. :return: ``None`` """ if embeds and len(embeds) > 10: raise error.IncorrectFormat("Embed must be 10 or fewer.") base = { "type": send_type, "data": { "tts": tts, "content": content, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self._discord.allowed_mentions.to_dict() if self._discord.allowed_mentions else {} } } if not self.sent else { "content": content, "tts": tts, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self._discord.allowed_mentions.to_dict() if self._discord.allowed_mentions else {} } if hidden: if self.sent: base["flags"] = 64 else: base["data"]["flags"] = 64 initial = True if not self.sent else False resp = await self._http.post(base, self._discord.user.id, self.interaction_id, self.__token, initial) self.sent = True return resp
async def edit_button_msg( self, message: Message, content: str = "", *, tts: bool = False, embed: Embed = None, allowed_mentions: AllowedMentions = None, buttons: List[Button] = None, **options, ): state = self.bot._get_state() if embed: embed = embed.to_dict() if allowed_mentions: if state.allowed_mentions: allowed_mentions = state.allowed_mentions.merge(allowed_mentions).to_dict() else: allowed_mentions = allowed_mentions.to_dict() else: allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict() data = { "content": content, **self._get_buttons_json(buttons), **options, "embed": embed, "allowed_mentions": allowed_mentions, "tts": tts, } await self.bot.http.request( Route("PATCH", f"/channels/{message.channel.id}/messages/{message.id}"), json=data )
def edit_message( self, token: str, message_id: int, *, content: str = None, embed: discord.Embed = None, embeds: List[discord.Embed] = None, allowed_mentions: discord.AllowedMentions = None, ): route = Route( "PATCH", "/webhooks/{application_id}/{token}/messages/{message_id}", application_id=self.application_id, token=token, message_id=message_id, ) if embed is not None: embeds = [embed] if allowed_mentions is None: allowed_mentions = self.bot.allowed_mentions payload = {} if content: payload["content"] = content if embeds: payload["embeds"] = [e.to_dict() for e in embeds] payload["allowed_mentions"] = allowed_mentions.to_dict() return self.request(route, json=payload)
def edit_message( self, token: str, message_id: int = None, *, content: str = None, embed: discord.Embed = None, embeds: List[discord.Embed] = None, allowed_mentions: discord.AllowedMentions = None, original: bool = False, components: list = None, ): url = "/webhooks/{application_id}/{token}/messages/" url += "@original" if original else "{message_id}" route = Route( "PATCH", url, application_id=self.application_id, token=token, message_id=message_id, ) if embed is not None: embeds = [embed] if allowed_mentions is None: allowed_mentions = self.bot.allowed_mentions payload = {"content": content} if embeds: payload["embeds"] = [e.to_dict() for e in embeds] if components is not None: payload["components"] = [c.to_dict() for c in components] payload["allowed_mentions"] = allowed_mentions.to_dict() return self.request(route, json=payload)
async def send_button_msg( self, channel: TextChannel, content: str = "", *, tts: bool = False, embed: Embed = None, allowed_mentions: AllowedMentions = None, buttons: List[Button] = None, **options, ) -> Message: state = self.bot._get_state() if embed: embed = embed.to_dict() if allowed_mentions: if state.allowed_mentions: allowed_mentions = state.allowed_mentions.merge(allowed_mentions).to_dict() else: allowed_mentions = allowed_mentions.to_dict() else: allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict() data = { "content": content, **self._get_buttons_json(buttons), **options, "embed": embed, "allowed_mentions": allowed_mentions, "tts": tts, } data = await self.bot.http.request( Route("POST", f"/channels/{channel.id}/messages"), json=data ) return Message(state=state, channel=channel, data=data)
async def edit(self, message_id: typing.Union[int, str] = "@original", content: str = "", embeds: typing.List[discord.Embed] = None, tts: bool = False, allowed_mentions: discord.AllowedMentions = None): """ Edits response of the slash command. :param message_id: Response message ID. Default initial message. :param content: Text of the response. Can be ``None``. :type content: str :param embeds: Embeds of the response. Maximum 10, can be empty. :type embeds: List[discord.Embed] :param tts: Whether to speak message using tts. Default ``False``. :type tts: bool :param allowed_mentions: AllowedMentions of the message. :type allowed_mentions: discord.AllowedMentions :return: ``None`` """ if embeds and len(embeds) > 10: raise error.IncorrectFormat("Embed must be 10 or fewer.") base = { "content": content, "tts": tts, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self._discord.allowed_mentions.to_dict() if self._discord.allowed_mentions else {} } await self._http.edit(base, self._discord.user.id, self.__token, message_id)
async def respond( self, *, type: int, content: str = None, embed: Embed = None, embeds: List[Embed] = [], allowed_mentions: AllowedMentions = None, tts: bool = False, flags: int = 64, ): state = self.bot._get_state() if embed and embeds: embeds.append(embed) elif embed: embeds = embed if embeds: embeds = list(map(lambda x: x.to_dict(), embeds)) if allowed_mentions: if state.allowed_mentions: allowed_mentions = state.allowed_mentions.merge(allowed_mentions).to_dict() else: allowed_mentions = allowed_mentions.to_dict() else: allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict() data = { "content": content, "embeds": embeds, "allowed_mentions": allowed_mentions, "tts": tts, "flags": flags, } await self.bot.http.request( Route("POST", f"/interactions/{self.interaction_id}/{self.interaction_token}/callback"), json={"type": type, "data": data}, )
async def edit_original(self, content: str = None, *, embeds: List[Embed] = None, allowed_mentions: discord.AllowedMentions = None, hidden: bool = False): self.responded = True async with aiohttp.ClientSession() as sess: r = { "content": content, "embeds": [embed.to_dict() for embed in embeds], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else {} } if hidden: r["data"] = {"flags": 64} else: r["data"] = {"flags": 0} resp = await sess.patch( f"{BASE}/webhooks/{self.bot.user.id}/{self.token}/messages/@original", json=r) resp.raise_for_status()
async def reply(self, content: str = None, *, embeds: List[Embed] = None, allowed_mentions: discord.AllowedMentions = None, hidden: bool = False): embeds = embeds or [] if self.deferred and not self.responded: return await self.edit_original(content, embeds=embeds, allowed_mentions=allowed_mentions, hidden=hidden) async with aiohttp.ClientSession() as sess: r = { "content": content, "embeds": [embed.to_dict() for embed in embeds], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else {} } if hidden: r["data"] = {"flags": 64} resp = await sess.post( f"{BASE}/webhooks/{self.bot.user.id}/{self.token}", json=r) resp.raise_for_status()
async def send_button_msg( self, channel: TextChannel, content: str = "", *, tts: bool = False, embed: Embed = None, file: File = None, allowed_mentions: AllowedMentions = None, buttons: List[Button] = None, **options, ) -> Message: state = self.bot._get_state() if embed: embed = embed.to_dict() if allowed_mentions: if state.allowed_mentions: allowed_mentions = state.allowed_mentions.merge( allowed_mentions).to_dict() else: allowed_mentions = allowed_mentions.to_dict() else: allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict( ) data = { "content": content, **self._get_buttons_json(buttons), **options, "embed": embed, "allowed_mentions": allowed_mentions, "tts": tts, } if file: try: await self.bot.http.request( Route("POST", f"/channels/{channel.id}/messages"), form=[ { "name": "payload_json", "value": dumps(data, separators=(",", ":"), ensure_ascii=True), }, { "name": "file", "value": file.fp, "filename": file.filename, "content_type": "application/octet-stream", }, ], files=[file], ) finally: file.close() else: data = await self.bot.http.request(Route( "POST", f"/channels/{channel.id}/messages"), json=data) return Message(state=state, channel=channel, data=data)
def send_message( self, token: str, interaction_id: int, *, type: int, initial_response: bool, content: str = None, file: discord.File = None, files: List[discord.File] = None, embed: discord.Embed = None, embeds: List[discord.Embed] = None, tts: bool = False, allowed_mentions: discord.AllowedMentions = None, flags: int = None, components: list = None, ): if embed is not None: embeds = [embed] if file is not None: files = [file] if allowed_mentions is None: allowed_mentions = self.bot.allowed_mentions data = {} if content: data["content"] = str(content) if tts: data["tts"] = True if embeds: data["embeds"] = [e.to_dict() for e in embeds] if flags: data["flags"] = flags if embeds: data["embeds"] = [e.to_dict() for e in embeds] if flags: data["flags"] = flags if components is not None: data["components"] = [c.to_dict() for c in components] payload = {"type": type.value} if data: data["allowed_mentions"] = allowed_mentions.to_dict() payload["data"] = data if initial_response: url = "/interactions/{interaction_id}/{token}/callback" send_data = payload else: url = "/webhooks/{application_id}/{token}" send_data = data # logic taken from discord.py # https://github.com/Rapptz/discord.py/blob/45d498c1b76deaf3b394d17ccf56112fa691d160/discord/http.py#L462 form = [{"name": "payload_json", "value": self._to_json(send_data)}] if files and len(files) == 1: file = files[0] form.append({ "name": "file", "value": file.fp, "filename": file.filename, "content_type": "application/octet-stream", }) elif files: for index, file in enumerate(files): form.append({ "name": f"file{index}", "value": file.fp, "filename": file.filename, "content_type": "application/octet-stream", }) route = Route( "POST", url, interaction_id=interaction_id, token=token, application_id=self.application_id, ) log.debug("sending response, initial = %r: %r", initial_response, send_data) return self.request(route, form=form, files=files)
async def send(self, content: str = "", *, embed: discord.Embed = None, embeds: typing.List[discord.Embed] = None, tts: bool = False, file: discord.File = None, files: typing.List[discord.File] = None, allowed_mentions: discord.AllowedMentions = None, hidden: bool = False, delete_after: float = None) -> model.SlashMessage: """ Sends response of the slash command. .. note:: - Param ``hidden`` doesn't support embed and file. .. warning:: - Since Release 1.0.9, this is completely changed. If you are migrating from older version, please make sure to fix the usage. - You can't use both ``embed`` and ``embeds`` at the same time, also applies to ``file`` and ``files``. - You cannot send files in the initial response :param content: Content of the response. :type content: str :param embed: Embed of the response. :type embed: discord.Embed :param embeds: Embeds of the response. Maximum 10. :type embeds: List[discord.Embed] :param tts: Whether to speak message using tts. Default ``False``. :type tts: bool :param file: File to send. :type file: discord.File :param files: Files to send. :type files: List[discord.File] :param allowed_mentions: AllowedMentions of the message. :type allowed_mentions: discord.AllowedMentions :param hidden: Whether the message is hidden, which means message content will only be seen to the author. :type hidden: bool :param delete_after: If provided, the number of seconds to wait in the background before deleting the message we just sent. If the deletion fails, then it is silently ignored. :type delete_after: float :return: Union[discord.Message, dict] """ if embed and embeds: raise error.IncorrectFormat( "You can't use both `embed` and `embeds`!") if embed: embeds = [embed] if embeds: if not isinstance(embeds, list): raise error.IncorrectFormat("Provide a list of embeds.") elif len(embeds) > 10: raise error.IncorrectFormat( "Do not provide more than 10 embeds.") if file and files: raise error.IncorrectFormat( "You can't use both `file` and `files`!") if file: files = [file] if delete_after and hidden: raise error.IncorrectFormat("You can't delete a hidden message!") base = { "content": content, "tts": tts, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self.bot.allowed_mentions.to_dict() if self.bot.allowed_mentions else {} } if hidden: if embeds or files: self._logger.warning( "Embed/File is not supported for `hidden`!") base["flags"] = 64 initial_message = False if not self.responded: initial_message = True if files: raise error.IncorrectFormat( "You cannot send files in the initial response!") if self.deferred: if self._deferred_hidden != hidden: self._logger.warning( "deferred response might not be what you set it to! (hidden / visible) " "This is because it was deferred in a different state") resp = await self._http.edit(base, self.__token) self.deferred = False else: json_data = {"type": 4, "data": base} await self._http.post_initial_response(json_data, self.interaction_id, self.__token) if not hidden: resp = await self._http.edit({}, self.__token) else: resp = {} self.responded = True else: resp = await self._http.post_followup(base, self.__token, files=files) if not hidden: smsg = model.SlashMessage(state=self.bot._connection, data=resp, channel=self.channel or discord.Object(id=self.channel_id), _http=self._http, interaction_token=self.__token) if delete_after: self.bot.loop.create_task(smsg.delete(delay=delete_after)) if initial_message: self.message = smsg return smsg else: return resp
async def respond( self, *, type: int = InteractionType.IgnoredChannelMessageWithSource, content: str = None, embed: Embed = None, embeds: List[Embed] = [], allowed_mentions: AllowedMentions = None, tts: bool = False, flags: int = FlagsType.Ephemeral, ) -> None: """Function to send response to discord .. note:: If you don't use this function after using `wait_for_button_click`, a interaction error will be raised :returns: :class:`None` Parameters ---------- type: :class:`int` The interaction's type. (4 or more and 6 or less) Default 6 (InteractionType.IgnoredChannelMessageWithSource) content: Optional[:class:`str`] The response message's content embed: Optional[:class:`discord.Embed`] The response message's embed embeds: Optional[List[:class:`discord.Embed`]] The response message's embeds allowed_mentions: Optional[:class:`discord.AllowedMentions`] The response message's allowed mentions tts: Optional[:class:`bool`] The response message's tts (default False) flags: Optional[:class:`int`] The response message's flags (default 64) """ state = self.bot._get_state() if embed and embeds: embeds.append(embed) elif embed: embeds = embed if len(embeds) > 0: raise InvalidArgument("Do not provide more than 10 embeds") if embeds: embeds = list(map(lambda x: x.to_dict(), embeds)) if allowed_mentions: if state.allowed_mentions: allowed_mentions = state.allowed_mentions.merge( allowed_mentions).to_dict() else: allowed_mentions = allowed_mentions.to_dict() else: allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict( ) data = { "content": content, "embeds": embeds, "allowed_mentions": allowed_mentions, "tts": tts, "flags": flags, } await self.bot.http.request( Route( "POST", f"/interactions/{self.interaction_id}/{self.interaction_token}/callback" ), json={ "type": type, "data": data }, )
async def send(self, content: str = "", *, embed: discord.Embed = None, embeds: typing.List[discord.Embed] = None, tts: bool = False, file: discord.File = None, files: typing.List[discord.File] = None, allowed_mentions: discord.AllowedMentions = None, hidden: bool = False, delete_after: float = None) -> model.SlashMessage: """ Sends response of the slash command. .. note:: - Param ``hidden`` doesn't support embed and file. .. warning:: - Since Release 1.0.9, this is completely changed. If you are migrating from older version, please make sure to fix the usage. - You can't use both ``embed`` and ``embeds`` at the same time, also applies to ``file`` and ``files``. :param content: Content of the response. :type content: str :param embed: Embed of the response. :type embed: discord.Embed :param embeds: Embeds of the response. Maximum 10. :type embeds: List[discord.Embed] :param tts: Whether to speak message using tts. Default ``False``. :type tts: bool :param file: File to send. :type file: discord.File :param files: Files to send. :type files: List[discord.File] :param allowed_mentions: AllowedMentions of the message. :type allowed_mentions: discord.AllowedMentions :param hidden: Whether the message is hidden, which means message content will only be seen to the author. :type hidden: bool :param delete_after: If provided, the number of seconds to wait in the background before deleting the message we just sent. If the deletion fails, then it is silently ignored. :type delete_after: float :return: Union[discord.Message, dict] """ if isinstance(content, int) and 2 <= content <= 5: raise error.IncorrectFormat( "`.send` Method is rewritten at Release 1.0.9. Please read the docs and fix all the usages." ) if not self.sent: self.logger.info( f"At command `{self.name}`: It is recommended to call `.respond()` first!" ) await self.respond(eat=hidden) if hidden: if embeds or embed or files or file: self.logger.warning( "Embed/File is not supported for `hidden`!") return await self.send_hidden(content) if embed and embeds: raise error.IncorrectFormat( "You can't use both `embed` and `embeds`!") if embed: embeds = [embed] if embeds: if not isinstance(embeds, list): raise error.IncorrectFormat("Provide a list of embeds.") elif len(embeds) > 10: raise error.IncorrectFormat( "Do not provide more than 10 embeds.") if file and files: raise error.IncorrectFormat( "You can't use both `file` and `files`!") if file: files = [file] base = { "content": content, "tts": tts, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self.bot.allowed_mentions.to_dict() if self.bot.allowed_mentions else {} } resp = await self._http.post(base, self.interaction_id, self.__token, files=files) smsg = model.SlashMessage(state=self.bot._connection, data=resp, channel=self.channel or discord.Object(id=self.channel_id), _http=self._http, interaction_token=self.__token) if delete_after: self.bot.loop.create_task(smsg.delete(delay=delete_after)) return smsg
async def send(self, send_type: int = 4, content: str = "", *, embeds: typing.List[discord.Embed] = None, tts: bool = False, allowed_mentions: discord.AllowedMentions = None, hidden: bool = False, complete_hidden: bool = False): """ Sends response of the slash command. .. note:: Every args except `send_type` and `content` must be passed as keyword args. .. warning:: Param ``hidden`` only works without embeds. :param send_type: Type of the response. Refer Discord API DOCS for more info about types. Default ``4``. :type send_type: int :param content: Content of the response. Can be ``None``. :type content: str :param embeds: Embeds of the response. Maximum 10, can be empty. :type embeds: List[discord.Embed] :param tts: Whether to speak message using tts. Default ``False``. :type tts: bool :param allowed_mentions: AllowedMentions of the message. :type allowed_mentions: discord.AllowedMentions :param hidden: Whether the message is hidden, which means message content will only be seen to the author. :type hidden: bool :param complete_hidden: If this is ``True``, it will be both hidden and `send_type` will be 3. Default ``False``. :type complete_hidden: bool :return: ``None`` """ if not isinstance(embeds, list): raise error.IncorrectFormat("Provide a list of embeds.") elif len(embeds) > 10: raise error.IncorrectFormat("Do not provide more than 10 embeds.") if complete_hidden: # Overrides both `hidden` and `send_type`. hidden = True send_type = 3 base = { "type": send_type, "data": { "tts": tts, "content": content, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self._discord.allowed_mentions.to_dict() if self._discord.allowed_mentions else {} } } if not self.sent else { "content": content, "tts": tts, "embeds": [x.to_dict() for x in embeds] if embeds else [], "allowed_mentions": allowed_mentions.to_dict() if allowed_mentions else self._discord.allowed_mentions.to_dict() if self._discord.allowed_mentions else {} } if hidden: if self.sent: base["flags"] = 64 else: base["data"]["flags"] = 64 if hidden and embeds: self.logger.warning( "You cannot use both `hidden` and `embeds` at the same time!") if send_type in (2, 5) and not self.sent: base = {"type": send_type} resp = await self._http.post(base, self._discord.user.id, self.interaction_id, self.__token, not self.sent) self.sent = True return resp
def send_message( self, token: str, interaction_id: int, *, type: int, initial_response: bool, content: str = None, embed: discord.Embed = None, embeds: List[discord.Embed] = [], tts: bool = False, allowed_mentions: discord.AllowedMentions = None, flags: int = None, components: list = None, ): payload = {"type": type.value} if embed is not None: embeds = [embed] if allowed_mentions is None: allowed_mentions = self.bot.allowed_mentions data = {} if content: data["content"] = str(content) if tts: data["tts"] = True if embeds: data["embeds"] = [e.to_dict() for e in embeds] if allowed_mentions: data["allowed_mentions"] = ( allowed_mentions.to_dict() ) # its 1:30 am but i should check later whether this is necessary if flags: data["flags"] = flags if embeds: data["embeds"] = [e.to_dict() for e in embeds] if flags: data["flags"] = flags if components is not None: data["components"] = [c.to_dict() for c in components] if data: data["allowed_mentions"] = allowed_mentions.to_dict() payload["data"] = data if initial_response: url = "/interactions/{interaction_id}/{token}/callback" send_data = payload else: url = "/webhooks/{application_id}/{token}" send_data = data route = Route( "POST", url, interaction_id=interaction_id, token=token, application_id=self.application_id, ) log.debug("sending response, initial = %r: %r" % (initial_response, send_data)) return self.request(route, json=send_data)
async def send_button_msg( self, channel: TextChannel, content: str = "", *, tts: bool = False, embed: Embed = None, file: File = None, allowed_mentions: AllowedMentions = None, buttons: List[Button] = None, **options, ) -> Message: """A function that sends a message with buttons :returns: :class:`discord.Message` Parameters ---------- channel: :class:`discord.Messageable` The channel to send the message content: str The message's content tts: :class:`bool` Indicates if the message should be sent using text-to-speech. embed: :class:`discord.Embed` The rich embed for the content. file: :class:`discord.File` The file to upload. allowed_mentions: :class:`discord.AllowedMentions` Controls the mentions being processed in this message. If this is passed, then the object is merged with :attr:`discord.Client.allowed_mentions`. The merging behaviour only overrides attributes that have been explicitly passed to the object, otherwise it uses the attributes set in :attr:`discord.Client.allowed_mentions`. If no object is passed at all then the defaults given by :attr:`discord.Client.allowed_mentions` are used instead. buttons: List[Union[:class:`~discord_buttons.Button`, List[:class:`~discord_buttons.Button`]]] The buttons to send. If this is 2-dimensional array, a array is a line """ state = self.bot._get_state() if embed: embed = embed.to_dict() if allowed_mentions: if state.allowed_mentions: allowed_mentions = state.allowed_mentions.merge(allowed_mentions).to_dict() else: allowed_mentions = allowed_mentions.to_dict() else: allowed_mentions = state.allowed_mentions and state.allowed_mentions.to_dict() data = { "content": content, **self._get_buttons_json(buttons), **options, "embed": embed, "allowed_mentions": allowed_mentions, "tts": tts, } if file: try: await self.bot.http.request( Route("POST", f"/channels/{channel.id}/messages"), form=[ { "name": "payload_json", "value": dumps(data, separators=(",", ":"), ensure_ascii=True), }, { "name": "file", "value": file.fp, "filename": file.filename, "content_type": "application/octet-stream", }, ], files=[file], ) finally: file.close() else: data = await self.bot.http.request( Route("POST", f"/channels/{channel.id}/messages"), json=data ) return ButtonMessage(buttons=buttons, state=state, channel=channel, data=data)