From 8937456388ec95f2f91ddfa984ed85f37bd36b0d Mon Sep 17 00:00:00 2001 From: Droid Date: Fri, 24 Jan 2025 00:15:03 -0500 Subject: [PATCH] attachments in interaction responses * Attatchments in interaction responses * Minor fix * Debug * Another attempt? * Again * An attempt * Minor fix * M * Bugfix * M * Cleanup * Cleanup * Cleanup * Cleanup * fix typos * Remove unpacking operand. --- lib/discordrb/api/interaction.rb | 21 ++++++++++----- lib/discordrb/api/webhook.rb | 25 ++++++++++++++---- lib/discordrb/data/interaction.rb | 39 ++++++++++++++++------------ lib/discordrb/events/interactions.rb | 22 +++++++++------- 4 files changed, 69 insertions(+), 38 deletions(-) diff --git a/lib/discordrb/api/interaction.rb b/lib/discordrb/api/interaction.rb index cfa055220..36418f126 100644 --- a/lib/discordrb/api/interaction.rb +++ b/lib/discordrb/api/interaction.rb @@ -6,16 +6,25 @@ module Discordrb::API::Interaction # Respond to an interaction. # https://discord.com/developers/docs/interactions/slash-commands#create-interaction-response - def create_interaction_response(interaction_token, interaction_id, type, content = nil, tts = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil) - data = { tts: tts, content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, components: components }.compact + def create_interaction_response(interaction_token, interaction_id, type, content = nil, tts = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil) + body = { tts: tts, content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, components: components }.compact + + body = if attachments + files = [*0...attachments.size].zip(attachments).to_h + { **files, payload_json: { type: type, data: body }.to_json } + else + { type: type, data: body }.to_json + end + + headers = { content_type: :json } unless attachments Discordrb::API.request( :interactions_iid_token_callback, interaction_id, :post, "#{Discordrb::API.api_base}/interactions/#{interaction_id}/#{interaction_token}/callback", - { type: type, data: data }.to_json, - content_type: :json + body, + headers ) end @@ -42,8 +51,8 @@ def get_original_interaction_response(interaction_token, application_id) # Edit the original response to an interaction. # https://discord.com/developers/docs/interactions/slash-commands#edit-original-interaction-response - def edit_original_interaction_response(interaction_token, application_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil) - Discordrb::API::Webhook.token_edit_message(interaction_token, application_id, '@original', content, embeds, allowed_mentions, components) + def edit_original_interaction_response(interaction_token, application_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil) + Discordrb::API::Webhook.token_edit_message(interaction_token, application_id, '@original', content, embeds, allowed_mentions, components, attachments) end # Delete the original response to an interaction. diff --git a/lib/discordrb/api/webhook.rb b/lib/discordrb/api/webhook.rb index 18fbf3f40..33f0d0982 100644 --- a/lib/discordrb/api/webhook.rb +++ b/lib/discordrb/api/webhook.rb @@ -29,15 +29,19 @@ def token_webhook(webhook_token, webhook_id) # Execute a webhook via token. # https://discord.com/developers/docs/resources/webhook#execute-webhook - def token_execute_webhook(webhook_token, webhook_id, wait = false, content = nil, username = nil, avatar_url = nil, tts = nil, file = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil) + def token_execute_webhook(webhook_token, webhook_id, wait = false, content = nil, username = nil, avatar_url = nil, tts = nil, file = nil, embeds = nil, allowed_mentions = nil, flags = nil, components = nil, attachments = nil) body = { content: content, username: username, avatar_url: avatar_url, tts: tts, embeds: embeds&.map(&:to_hash), allowed_mentions: allowed_mentions, flags: flags, components: components } + body = if file { file: file, payload_json: body.to_json } + elsif attachments + files = [*0...attachments.size].zip(attachments).to_h + { **files, payload_json: body.to_json } else body.to_json end - headers = { content_type: :json } unless file + headers = { content_type: :json } unless file || attachments Discordrb::API.request( :webhooks_wid, @@ -116,14 +120,25 @@ def token_get_message(webhook_token, webhook_id, message_id) # Edit a webhook message via webhook token # https://discord.com/developers/docs/resources/webhook#edit-webhook-message - def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil) + def token_edit_message(webhook_token, webhook_id, message_id, content = nil, embeds = nil, allowed_mentions = nil, components = nil, attachments = nil) + body = { content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components } + + body = if attachments + files = [*0...attachments.size].zip(attachments).to_h + { **files, payload_json: body.to_json } + else + body.to_json + end + + headers = { content_type: :json } unless attachments + Discordrb::API.request( :webhooks_wid_messages, webhook_id, :patch, "#{Discordrb::API.api_base}/webhooks/#{webhook_id}/#{webhook_token}/messages/#{message_id}", - { content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components }.to_json, - content_type: :json + body, + headers ) end diff --git a/lib/discordrb/data/interaction.rb b/lib/discordrb/data/interaction.rb index 4f0bcebac..52b20d90c 100644 --- a/lib/discordrb/data/interaction.rb +++ b/lib/discordrb/data/interaction.rb @@ -89,10 +89,11 @@ def initialize(data, bot) # @param flags [Integer] Message flags. # @param ephemeral [true, false] Whether this message should only be visible to the interaction initiator. # @param wait [true, false] Whether this method should return a Message object of the interaction response. - # @param components [Array<#to_h>] An array of components + # @param components [Array<#to_h>] An array of components. + # @param attachments [Array] Files that can be referenced in embeds via `attachment://file.png`. # @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data. # @yieldparam view [Webhooks::View] A builder for creating interaction components. - def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil) + def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, attachments: nil) flags |= 1 << 6 if ephemeral builder = Discordrb::Webhooks::Builder.new @@ -105,7 +106,7 @@ def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0 components ||= view data = builder.to_json_hash - Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:channel_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a) + Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:channel_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a, attachments) return unless wait @@ -157,10 +158,11 @@ def show_modal(title:, custom_id:, components: nil) # @param flags [Integer] Message flags. # @param ephemeral [true, false] Whether this message should only be visible to the interaction initiator. # @param wait [true, false] Whether this method should return a Message object of the interaction response. - # @param components [Array<#to_h>] An array of components + # @param components [Array<#to_h>] An array of components. + # @param attachments [Array] Files that can be referenced in embeds via `attachment://file.png`. # @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data. # @yieldparam view [Webhooks::View] A builder for creating interaction components. - def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil) + def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, attachments: nil) flags |= 1 << 6 if ephemeral builder = Discordrb::Webhooks::Builder.new @@ -172,7 +174,7 @@ def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, f components ||= view data = builder.to_json_hash - Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:update_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a) + Discordrb::API::Interaction.create_interaction_response(@token, @id, CALLBACK_TYPES[:update_message], data[:content], tts, data[:embeds], data[:allowed_mentions], flags, components.to_a, attachments) return unless wait @@ -184,10 +186,11 @@ def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, f # @param content [String] The content of the message. # @param embeds [Array] The embeds for the message. # @param allowed_mentions [Hash, AllowedMentions] Mentions that can ping on this message. - # @param components [Array<#to_h>] An array of components + # @param components [Array<#to_h>] An array of components. + # @param attachments [Array] Files that can be referenced in embeds via `attachment://file.png`. # @return [InteractionMessage] The updated response message. # @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data. - def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: nil) + def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil) builder = Discordrb::Webhooks::Builder.new view = Discordrb::Webhooks::View.new @@ -196,7 +199,7 @@ def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: components ||= view data = builder.to_json_hash - resp = Discordrb::API::Interaction.edit_original_interaction_response(@token, @application_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a) + resp = Discordrb::API::Interaction.edit_original_interaction_response(@token, @application_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a, attachments) Interactions::Message.new(JSON.parse(resp), @bot, @interaction) end @@ -212,8 +215,9 @@ def delete_response # @param allowed_mentions [Hash, AllowedMentions] Mentions that can ping on this message. # @param flags [Integer] Message flags. # @param ephemeral [true, false] Whether this message should only be visible to the interaction initiator. + # @param attachments [Array] Files that can be referenced in embeds via `attachment://file.png`. # @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data. - def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, flags: 0, ephemeral: false, components: nil) + def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, flags: 0, ephemeral: false, components: nil, attachments: nil) flags |= 64 if ephemeral builder = Discordrb::Webhooks::Builder.new @@ -226,7 +230,7 @@ def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, f data = builder.to_json_hash resp = Discordrb::API::Webhook.token_execute_webhook( - @token, @application_id, true, data[:content], nil, nil, tts, nil, data[:embeds], data[:allowed_mentions], flags, components.to_a + @token, @application_id, true, data[:content], nil, nil, tts, nil, data[:embeds], data[:allowed_mentions], flags, components.to_a, attachments ) Interactions::Message.new(JSON.parse(resp), @bot, @interaction) end @@ -235,8 +239,9 @@ def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, f # @param content [String] The message content. # @param embeds [Array] The embeds for the message. # @param allowed_mentions [Hash, AllowedMentions] Mentions that can ping on this message. + # @param attachments [Array] Files that can be referenced in embeds via `attachment://file.png`. # @yieldparam builder [Webhooks::Builder] An optional message builder. Arguments passed to the method overwrite builder data. - def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, components: nil) + def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil) builder = Discordrb::Webhooks::Builder.new view = Discordrb::Webhooks::View.new @@ -247,7 +252,7 @@ def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, comp data = builder.to_json_hash resp = Discordrb::API::Webhook.token_edit_message( - @token, @application_id, message.resolve_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a + @token, @application_id, message.resolve_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a, attachments ) Interactions::Message.new(JSON.parse(resp), @bot, @interaction) end @@ -777,8 +782,8 @@ def channel # Respond to this message. # @param (see Interaction#send_message) # @yieldparam (see Interaction#send_message) - def respond(content: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: true, components: nil, &block) - @interaction.send_message(content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, &block) + def respond(content: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: true, components: nil, attachments: nil, &block) + @interaction.send_message(content: content, embeds: embeds, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, attachments: attachments, &block) end # Delete this message. @@ -791,8 +796,8 @@ def delete # @param embeds (see Interaction#send_message) # @param allowed_mentions (see Interaction#send_message) # @yieldparam (see Interaction#send_message) - def edit(content: nil, embeds: nil, allowed_mentions: nil, components: nil, &block) - @interaction.edit_message(@id, content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, &block) + def edit(content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil, &block) + @interaction.edit_message(@id, content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, attachments: attachments, &block) end # @return [Discordrb::Message] diff --git a/lib/discordrb/events/interactions.rb b/lib/discordrb/events/interactions.rb index c10a11e9e..1b0efa692 100644 --- a/lib/discordrb/events/interactions.rb +++ b/lib/discordrb/events/interactions.rb @@ -35,10 +35,11 @@ def initialize(data, bot) end # (see Interaction#respond) - def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, &block) + def respond(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, attachments: nil, &block) @interaction.respond( content: content, tts: tts, embeds: embeds, allowed_mentions: allowed_mentions, - flags: flags, ephemeral: ephemeral, wait: wait, components: components, &block + flags: flags, ephemeral: ephemeral, wait: wait, components: components, attachments: attachments, + &block ) end @@ -48,10 +49,11 @@ def defer(flags: 0, ephemeral: true) end # (see Interaction#update_message) - def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, &block) + def update_message(content: nil, tts: nil, embeds: nil, allowed_mentions: nil, flags: 0, ephemeral: nil, wait: false, components: nil, attachments: nil, &block) @interaction.update_message( content: content, tts: tts, embeds: embeds, allowed_mentions: allowed_mentions, - flags: flags, ephemeral: ephemeral, wait: wait, components: components, &block + flags: flags, ephemeral: ephemeral, wait: wait, components: components, attachments: attachments, + &block ) end @@ -61,8 +63,8 @@ def show_modal(title:, custom_id:, components: nil, &block) end # (see Interaction#edit_response) - def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: nil, &block) - @interaction.edit_response(content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, &block) + def edit_response(content: nil, embeds: nil, allowed_mentions: nil, components: nil, attachments: nil, &block) + @interaction.edit_response(content: content, embeds: embeds, allowed_mentions: allowed_mentions, components: components, attachments: attachments, &block) end # (see Interaction#delete_response) @@ -71,13 +73,13 @@ def delete_response end # (see Interaction#send_message) - def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, flags: 0, ephemeral: nil, components: nil, &block) - @interaction.send_message(content: content, embeds: embeds, tts: tts, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, &block) + def send_message(content: nil, embeds: nil, tts: false, allowed_mentions: nil, flags: 0, ephemeral: nil, components: nil, attachments: nil, &block) + @interaction.send_message(content: content, embeds: embeds, tts: tts, allowed_mentions: allowed_mentions, flags: flags, ephemeral: ephemeral, components: components, attachments: attachments, &block) end # (see Interaction#edit_message) - def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, &block) - @interaction.edit_message(message, content: content, embeds: embeds, allowed_mentions: allowed_mentions, &block) + def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, attachments: nil, &block) + @interaction.edit_message(message, content: content, embeds: embeds, allowed_mentions: allowed_mentions, attachments: attachments, &block) end # (see Interaction#delete_message)