discordrb-webhooks-3.5.0/0000755000004100000410000000000014476021554015351 5ustar www-datawww-datadiscordrb-webhooks-3.5.0/discordrb-webhooks.gemspec0000644000004100000410000000315514476021554022514 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: discordrb-webhooks 3.5.0 ruby lib Gem::Specification.new do |s| s.name = "discordrb-webhooks".freeze s.version = "3.5.0" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "rubygems_mfa_required" => "true" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["meew0".freeze, "swarley".freeze] s.bindir = "exe".freeze s.date = "2023-07-05" s.description = "A client for Discord's webhooks to fit alongside [discordrb](https://rubygems.org/gems/discordrb).".freeze s.email = ["".freeze] s.files = ["lib/discordrb/webhooks.rb".freeze, "lib/discordrb/webhooks/builder.rb".freeze, "lib/discordrb/webhooks/client.rb".freeze, "lib/discordrb/webhooks/embeds.rb".freeze, "lib/discordrb/webhooks/modal.rb".freeze, "lib/discordrb/webhooks/version.rb".freeze, "lib/discordrb/webhooks/view.rb".freeze] s.homepage = "https://github.com/shardlab/discordrb".freeze s.licenses = ["MIT".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.7".freeze) s.rubygems_version = "3.2.5".freeze s.summary = "Webhook client for discordrb".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_runtime_dependency(%q.freeze, [">= 2.0.0"]) else s.add_dependency(%q.freeze, [">= 2.0.0"]) end end discordrb-webhooks-3.5.0/lib/0000755000004100000410000000000014476021554016117 5ustar www-datawww-datadiscordrb-webhooks-3.5.0/lib/discordrb/0000755000004100000410000000000014476021554020072 5ustar www-datawww-datadiscordrb-webhooks-3.5.0/lib/discordrb/webhooks.rb0000644000004100000410000000046714476021554022247 0ustar www-datawww-data# frozen_string_literal: true require 'discordrb/webhooks/version' require 'discordrb/webhooks/embeds' require 'discordrb/webhooks/client' require 'discordrb/webhooks/builder' require 'discordrb/webhooks/view' require 'discordrb/webhooks/modal' module Discordrb # Webhook client module Webhooks end end discordrb-webhooks-3.5.0/lib/discordrb/webhooks/0000755000004100000410000000000014476021554021713 5ustar www-datawww-datadiscordrb-webhooks-3.5.0/lib/discordrb/webhooks/version.rb0000644000004100000410000000026314476021554023726 0ustar www-datawww-data# frozen_string_literal: true # Webhook support for discordrb module Discordrb module Webhooks # The current version of discordrb-webhooks. VERSION = '3.5.0' end end discordrb-webhooks-3.5.0/lib/discordrb/webhooks/client.rb0000644000004100000410000001265114476021554023523 0ustar www-datawww-data# frozen_string_literal: true require 'rest-client' require 'json' require 'discordrb/webhooks/builder' module Discordrb::Webhooks # A client for a particular webhook added to a Discord channel. class Client # Create a new webhook # @param url [String] The URL to post messages to. # @param id [Integer] The webhook's ID. Will only be used if `url` is not # set. # @param token [String] The webhook's authorisation token. Will only be used # if `url` is not set. def initialize(url: nil, id: nil, token: nil) @url = url || generate_url(id, token) end # Executes the webhook this client points to with the given data. # @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew. # @param wait [true, false] Whether Discord should wait for the message to be successfully received by clients, or # whether it should return immediately after sending the message. # @yield [builder] Gives the builder to the block to add additional steps, or to do the entire building process. # @yieldparam builder [Builder] The builder given as a parameter which is used as the initial step to start from. # @example Execute the webhook with an already existing builder # builder = Discordrb::Webhooks::Builder.new # ... # client.execute(builder) # @example Execute the webhook by building a new message # client.execute do |builder| # builder.content = 'Testing' # builder.username = 'discordrb' # builder.add_embed do |embed| # embed.timestamp = Time.now # embed.title = 'Testing' # embed.image = Discordrb::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg') # end # end # @return [RestClient::Response] the response returned by Discord. def execute(builder = nil, wait = false, components = nil) raise TypeError, 'builder needs to be nil or like a Discordrb::Webhooks::Builder!' unless (builder.respond_to?(:file) && builder.respond_to?(:to_multipart_hash)) || builder.respond_to?(:to_json_hash) || builder.nil? builder ||= Builder.new view = View.new yield(builder, view) if block_given? components ||= view if builder.file post_multipart(builder, components, wait) else post_json(builder, components, wait) end end # Modify this webhook's properties. # @param name [String, nil] The default name. # @param avatar [String, #read, nil] The new avatar, in base64-encoded JPG format. # @param channel_id [String, Integer, nil] The channel to move the webhook to. # @return [RestClient::Response] the response returned by Discord. def modify(name: nil, avatar: nil, channel_id: nil) RestClient.patch(@url, { name: name, avatar: avatarise(avatar), channel_id: channel_id }.compact.to_json, content_type: :json) end # Delete this webhook. # @param reason [String, nil] The reason this webhook was deleted. # @return [RestClient::Response] the response returned by Discord. # @note This is permanent and cannot be undone. def delete(reason: nil) RestClient.delete(@url, 'X-Audit-Log-Reason': reason) end # Edit a message from this webhook. # @param message_id [String, Integer] The ID of the message to edit. # @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew. # @param content [String] The message content. # @param embeds [Array] # @param allowed_mentions [Hash] # @return [RestClient::Response] the response returned by Discord. # @example Edit message content # client.edit_message(message_id, content: 'goodbye world!') # @example Edit a message via builder # client.edit_message(message_id) do |builder| # builder.add_embed do |e| # e.description = 'Hello World!' # end # end # @note Not all builder options are available when editing. def edit_message(message_id, builder: nil, content: nil, embeds: nil, allowed_mentions: nil) builder ||= Builder.new yield builder if block_given? data = builder.to_json_hash.merge({ content: content, embeds: embeds, allowed_mentions: allowed_mentions }.compact) RestClient.patch("#{@url}/messages/#{message_id}", data.compact.to_json, content_type: :json) end # Delete a message created by this webhook. # @param message_id [String, Integer] The ID of the message to delete. # @return [RestClient::Response] the response returned by Discord. def delete_message(message_id) RestClient.delete("#{@url}/messages/#{message_id}") end private # Convert an avatar to API ready data. # @param avatar [String, #read] Avatar data. def avatarise(avatar) if avatar.respond_to? :read "data:image/jpg;base64,#{Base64.strict_encode64(avatar.read)}" else avatar end end def post_json(builder, components, wait) data = builder.to_json_hash.merge({ components: components.to_a }) RestClient.post(@url + (wait ? '?wait=true' : ''), data.to_json, content_type: :json) end def post_multipart(builder, components, wait) data = builder.to_multipart_hash.merge({ components: components.to_a }) RestClient.post(@url + (wait ? '?wait=true' : ''), data) end def generate_url(id, token) "https://discord.com/api/v8/webhooks/#{id}/#{token}" end end end discordrb-webhooks-3.5.0/lib/discordrb/webhooks/modal.rb0000644000004100000410000000504114476021554023334 0ustar www-datawww-data# frozen_string_literal: true # Modal component builder. class Discordrb::Webhooks::Modal # A mapping of names to types of components usable in a modal. COMPONENT_TYPES = { action_row: 1, text_input: 4 }.freeze # This builder is used when constructing an ActionRow. All current components must be within an action row, but this can # change in the future. A message can have 5 action rows, each action row can hold a weight of 5. Buttons have a weight of 1, # and dropdowns have a weight of 5. class RowBuilder # A mapping of short names to types of input styles. `short` is a single line where `paragraph` is a block. TEXT_INPUT_STYLES = { short: 1, paragraph: 2 }.freeze # @!visibility private def initialize @components = [] end # Add a text input to this action row. # @param style [Symbol, Integer] The text input's style type. See {TEXT_INPUT_STYLES} # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param label [String, nil] The text label for the field. # @param min_length [Integer, nil] The minimum input length for a text input, min 0, max 4000. # @param max_length [Integer, nil] The maximum input length for a text input, min 1, max 4000. # @param required [true, false, nil] Whether this component is required to be filled, default true. # @param value [String, nil] A pre-filled value for this component, max 4000 characters. # @param placeholder [String, nil] Custom placeholder text if the input is empty, max 100 characters def text_input(style:, custom_id:, label: nil, min_length: nil, max_length: nil, required: nil, value: nil, placeholder: nil) style = TEXT_INPUT_STYLES[style] || style @components << { style: style, custom_id: custom_id, type: COMPONENT_TYPES[:text_input], label: label, min_length: min_length, max_length: max_length, required: required, value: value, placeholder: placeholder } end # @!visibility private def to_h { type: COMPONENT_TYPES[:action_row], components: @components } end end attr_reader :rows def initialize @rows = [] yield self if block_given? end # Add a new ActionRow to the view # @yieldparam [RowBuilder] def row new_row = RowBuilder.new yield new_row @rows << new_row end # @!visibility private def to_a @rows.map(&:to_h) end end discordrb-webhooks-3.5.0/lib/discordrb/webhooks/view.rb0000644000004100000410000002123414476021554023214 0ustar www-datawww-data# frozen_string_literal: true # A reusable view representing a component collection, with builder methods. class Discordrb::Webhooks::View # Possible button style names and values. BUTTON_STYLES = { primary: 1, secondary: 2, success: 3, danger: 4, link: 5 }.freeze # Component types. # @see https://discord.com/developers/docs/interactions/message-components#component-types COMPONENT_TYPES = { action_row: 1, button: 2, string_select: 3, # text_input: 4, # (defined in modal.rb) user_select: 5, role_select: 6, mentionable_select: 7, channel_select: 8 }.freeze # This builder is used when constructing an ActionRow. All current components must be within an action row, but this can # change in the future. A message can have 5 action rows, each action row can hold a weight of 5. Buttons have a weight of 1, # and dropdowns have a weight of 5. class RowBuilder # @!visibility private def initialize @components = [] end # Add a button to this action row. # @param style [Symbol, Integer] The button's style type. See {BUTTON_STYLES} # @param label [String, nil] The text label for the button. Either a label or emoji must be provided. # @param emoji [#to_h, String, Integer] An emoji ID, or unicode emoji to attach to the button. Can also be a object # that responds to `#to_h` which returns a hash in the format of `{ id: Integer, name: string }`. # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param disabled [true, false] Whether this button is disabled and shown as greyed out. # @param url [String, nil] The URL, when using a link style button. def button(style:, label: nil, emoji: nil, custom_id: nil, disabled: nil, url: nil) style = BUTTON_STYLES[style] || style emoji = case emoji when Integer, String emoji.to_i.positive? ? { id: emoji } : { name: emoji } else emoji.to_h end @components << { type: COMPONENT_TYPES[:button], label: label, emoji: emoji, style: style, custom_id: custom_id, disabled: disabled, url: url } end # Add a select string to this action row. # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param options [Array] Options that can be selected in this menu. Can also be provided via the yielded builder. # @param placeholder [String, nil] Default text to show when no entries are selected. # @param min_values [Integer, nil] The minimum amount of values a user must select. # @param max_values [Integer, nil] The maximum amount of values a user can select. # @param disabled [true, false, nil] Grey out the component to make it unusable. # @yieldparam builder [SelectMenuBuilder] def string_select(custom_id:, options: [], placeholder: nil, min_values: nil, max_values: nil, disabled: nil) builder = SelectMenuBuilder.new(custom_id, options, placeholder, min_values, max_values, disabled, select_type: :string_select) yield builder if block_given? @components << builder.to_h end alias_method :select_menu, :string_select # Add a select user to this action row. # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param placeholder [String, nil] Default text to show when no entries are selected. # @param min_values [Integer, nil] The minimum amount of values a user must select. # @param max_values [Integer, nil] The maximum amount of values a user can select. # @param disabled [true, false, nil] Grey out the component to make it unusable. def user_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil) @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :user_select).to_h end # Add a select role to this action row. # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param placeholder [String, nil] Default text to show when no entries are selected. # @param min_values [Integer, nil] The minimum amount of values a user must select. # @param max_values [Integer, nil] The maximum amount of values a user can select. # @param disabled [true, false, nil] Grey out the component to make it unusable. def role_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil) @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :role_select).to_h end # Add a select mentionable to this action row. # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param placeholder [String, nil] Default text to show when no entries are selected. # @param min_values [Integer, nil] The minimum amount of values a user must select. # @param max_values [Integer, nil] The maximum amount of values a user can select. # @param disabled [true, false, nil] Grey out the component to make it unusable. def mentionable_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil) @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :mentionable_select).to_h end # Add a select channel to this action row. # @param custom_id [String] Custom IDs are used to pass state to the events that are raised from interactions. # There is a limit of 100 characters to each custom_id. # @param placeholder [String, nil] Default text to show when no entries are selected. # @param min_values [Integer, nil] The minimum amount of values a user must select. # @param max_values [Integer, nil] The maximum amount of values a user can select. # @param disabled [true, false, nil] Grey out the component to make it unusable. def channel_select(custom_id:, placeholder: nil, min_values: nil, max_values: nil, disabled: nil) @components << SelectMenuBuilder.new(custom_id, [], placeholder, min_values, max_values, disabled, select_type: :channel_select).to_h end # @!visibility private def to_h { type: COMPONENT_TYPES[:action_row], components: @components } end end # A builder to assist in adding options to select menus. class SelectMenuBuilder # @!visibility hidden def initialize(custom_id, options = [], placeholder = nil, min_values = nil, max_values = nil, disabled = nil, select_type: :string_select) @custom_id = custom_id @options = options @placeholder = placeholder @min_values = min_values @max_values = max_values @disabled = disabled @select_type = select_type end # Add an option to this select menu. # @param label [String] The title of this option. # @param value [String] The value that this option represents. # @param description [String, nil] An optional description of the option. # @param emoji [#to_h, String, Integer] An emoji ID, or unicode emoji to attach to the button. Can also be a object # that responds to `#to_h` which returns a hash in the format of `{ id: Integer, name: string }`. # @param default [true, false, nil] Whether this is the default selected option. def option(label:, value:, description: nil, emoji: nil, default: nil) emoji = case emoji when Integer, String emoji.to_i.positive? ? { id: emoji } : { name: emoji } else emoji.to_h end @options << { label: label, value: value, description: description, emoji: emoji, default: default } end # @!visibility private def to_h { type: COMPONENT_TYPES[@select_type], options: @options, placeholder: @placeholder, min_values: @min_values, max_values: @max_values, custom_id: @custom_id, disabled: @disabled } end end attr_reader :rows def initialize @rows = [] yield self if block_given? end # Add a new ActionRow to the view # @yieldparam [RowBuilder] def row new_row = RowBuilder.new yield new_row @rows << new_row end # @!visibility private def to_a @rows.map(&:to_h) end end discordrb-webhooks-3.5.0/lib/discordrb/webhooks/builder.rb0000644000004100000410000000652714476021554023700 0ustar www-datawww-data# frozen_string_literal: true require 'discordrb/webhooks/embeds' module Discordrb::Webhooks # A class that acts as a builder for a webhook message object. class Builder def initialize(content: '', username: nil, avatar_url: nil, tts: false, file: nil, embeds: [], allowed_mentions: nil) @content = content @username = username @avatar_url = avatar_url @tts = tts @file = file @embeds = embeds @allowed_mentions = allowed_mentions end # The content of the message. May be 2000 characters long at most. # @return [String] the content of the message. attr_accessor :content # The username the webhook will display as. If this is not set, the default username set in the webhook's settings # will be used instead. # @return [String] the username. attr_accessor :username # The URL of an image file to be used as an avatar. If this is not set, the default avatar from the webhook's # settings will be used instead. # @return [String] the avatar URL. attr_accessor :avatar_url # Whether this message should use TTS or not. By default, it doesn't. # @return [true, false] the TTS status. attr_accessor :tts # Sets a file to be sent together with the message. Mutually exclusive with embeds; a webhook message can contain # either a file to be sent or an embed. # @param file [File] A file to be sent. def file=(file) raise ArgumentError, 'Embeds and files are mutually exclusive!' unless @embeds.empty? @file = file end # Adds an embed to this message. # @param embed [Embed] The embed to add. def <<(embed) raise ArgumentError, 'Embeds and files are mutually exclusive!' if @file @embeds << embed end # Convenience method to add an embed using a block-style builder pattern # @example Add an embed to a message # builder.add_embed do |embed| # embed.title = 'Testing' # embed.image = Discordrb::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg') # end # @param embed [Embed, nil] The embed to start the building process with, or nil if one should be created anew. # @return [Embed] The created embed. def add_embed(embed = nil) embed ||= Embed.new yield(embed) self << embed embed end # @return [File, nil] the file attached to this message. attr_reader :file # @return [Array] the embeds attached to this message. attr_reader :embeds # @return [Discordrb::AllowedMentions, Hash] Mentions that are allowed to ping in this message. # @see https://discord.com/developers/docs/resources/channel#allowed-mentions-object attr_accessor :allowed_mentions # @return [Hash] a hash representation of the created message, for JSON format. def to_json_hash { content: @content, username: @username, avatar_url: @avatar_url, tts: @tts, embeds: @embeds.map(&:to_hash), allowed_mentions: @allowed_mentions&.to_hash } end # @return [Hash] a hash representation of the created message, for multipart format. def to_multipart_hash { content: @content, username: @username, avatar_url: @avatar_url, tts: @tts, file: @file, allowed_mentions: @allowed_mentions&.to_hash } end end end discordrb-webhooks-3.5.0/lib/discordrb/webhooks/embeds.rb0000644000004100000410000002050114476021554023475 0ustar www-datawww-data# frozen_string_literal: true module Discordrb::Webhooks # An embed is a multipart-style attachment to a webhook message that can have a variety of different purposes and # appearances. class Embed def initialize(title: nil, description: nil, url: nil, timestamp: nil, colour: nil, color: nil, footer: nil, image: nil, thumbnail: nil, video: nil, provider: nil, author: nil, fields: []) @title = title @description = description @url = url @timestamp = timestamp self.colour = colour || color @footer = footer @image = image @thumbnail = thumbnail @video = video @provider = provider @author = author @fields = fields end # @return [String, nil] title of the embed that will be displayed above everything else. attr_accessor :title # @return [String, nil] description for this embed attr_accessor :description # @return [String, nil] URL the title should point to attr_accessor :url # @return [Time, nil] timestamp for this embed. Will be displayed just below the title. attr_accessor :timestamp # @return [Integer, nil] the colour of the bar to the side, in decimal form attr_reader :colour alias_method :color, :colour # Sets the colour of the bar to the side of the embed to something new. # @param value [String, Integer, {Integer, Integer, Integer}, #to_i, nil] The colour in decimal, hexadecimal, R/G/B decimal, or nil to clear the embeds colour # form. def colour=(value) if value.nil? @colour = nil elsif value.is_a? Integer raise ArgumentError, 'Embed colour must be 24-bit!' if value >= 16_777_216 @colour = value elsif value.is_a? String self.colour = value.delete('#').to_i(16) elsif value.is_a? Array raise ArgumentError, 'Colour tuple must have three values!' if value.length != 3 self.colour = (value[0] << 16) | (value[1] << 8) | value[2] else self.colour = value.to_i end end alias_method :color=, :colour= # @example Add a footer to an embed # embed.footer = Discordrb::Webhooks::EmbedFooter.new(text: 'Hello', icon_url: 'https://i.imgur.com/j69wMDu.jpg') # @return [EmbedFooter, nil] footer for this embed attr_accessor :footer # @see EmbedImage # @example Add a image to an embed # embed.image = Discordrb::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg') # @return [EmbedImage, nil] image for this embed attr_accessor :image # @see EmbedThumbnail # @example Add a thumbnail to an embed # embed.thumbnail = Discordrb::Webhooks::EmbedThumbnail.new(url: 'https://i.imgur.com/xTG3a1I.jpg') # @return [EmbedThumbnail, nil] thumbnail for this embed attr_accessor :thumbnail # @see EmbedAuthor # @example Add a author to an embed # embed.author = Discordrb::Webhooks::EmbedAuthor.new(name: 'meew0', url: 'https://github.com/meew0', icon_url: 'https://avatars2.githubusercontent.com/u/3662915?v=3&s=466') # @return [EmbedAuthor, nil] author for this embed attr_accessor :author # Add a field object to this embed. # @param field [EmbedField] The field to add. def <<(field) @fields << field end # Convenience method to add a field to the embed without having to create one manually. # @see EmbedField # @example Add a field to an embed, conveniently # embed.add_field(name: 'A field', value: "The field's content") # @param name [String] The field's name # @param value [String] The field's value # @param inline [true, false] Whether the field should be inline def add_field(name: nil, value: nil, inline: nil) self << EmbedField.new(name: name, value: value, inline: inline) end # @return [Array] the fields attached to this embed. attr_accessor :fields # @return [Hash] a hash representation of this embed, to be converted to JSON. def to_hash { title: @title, description: @description, url: @url, timestamp: @timestamp&.utc&.iso8601, color: @colour, footer: @footer&.to_hash, image: @image&.to_hash, thumbnail: @thumbnail&.to_hash, video: @video&.to_hash, provider: @provider&.to_hash, author: @author&.to_hash, fields: @fields.map(&:to_hash) } end end # An embed's footer will be displayed at the very bottom of an embed, together with the timestamp. An icon URL can be # set together with some text to be displayed. class EmbedFooter # @return [String, nil] text to be displayed in the footer attr_accessor :text # @return [String, nil] URL to an icon to be showed alongside the text attr_accessor :icon_url # Creates a new footer object. # @param text [String, nil] The text to be displayed in the footer. # @param icon_url [String, nil] The URL to an icon to be showed alongside the text. def initialize(text: nil, icon_url: nil) @text = text @icon_url = icon_url end # @return [Hash] a hash representation of this embed footer, to be converted to JSON. def to_hash { text: @text, icon_url: @icon_url } end end # An embed's image will be displayed at the bottom, in large format. It will replace a footer icon URL if one is set. class EmbedImage # @return [String, nil] URL of the image attr_accessor :url # Creates a new image object. # @param url [String, nil] The URL of the image. def initialize(url: nil) @url = url end # @return [Hash] a hash representation of this embed image, to be converted to JSON. def to_hash { url: @url } end end # An embed's thumbnail will be displayed at the right of the message, next to the description and fields. When clicked # it will point to the embed URL. class EmbedThumbnail # @return [String, nil] URL of the thumbnail attr_accessor :url # Creates a new thumbnail object. # @param url [String, nil] The URL of the thumbnail. def initialize(url: nil) @url = url end # @return [Hash] a hash representation of this embed thumbnail, to be converted to JSON. def to_hash { url: @url } end end # An embed's author will be shown at the top to indicate who "authored" the particular event the webhook was sent for. class EmbedAuthor # @return [String, nil] name of the author attr_accessor :name # @return [String, nil] URL the name should link to attr_accessor :url # @return [String, nil] URL of the icon to be displayed next to the author attr_accessor :icon_url # Creates a new author object. # @param name [String, nil] The name of the author. # @param url [String, nil] The URL the name should link to. # @param icon_url [String, nil] The URL of the icon to be displayed next to the author. def initialize(name: nil, url: nil, icon_url: nil) @name = name @url = url @icon_url = icon_url end # @return [Hash] a hash representation of this embed author, to be converted to JSON. def to_hash { name: @name, url: @url, icon_url: @icon_url } end end # A field is a small block of text with a header that can be relatively freely layouted with other fields. class EmbedField # @return [String, nil] name of the field, displayed in bold at the top of the field. attr_accessor :name # @return [String, nil] value of the field, displayed in normal text below the name. attr_accessor :value # @return [true, false] whether the field should be displayed inline with other fields. attr_accessor :inline # Creates a new field object. # @param name [String, nil] The name of the field, displayed in bold at the top of the field. # @param value [String, nil] The value of the field, displayed in normal text below the name. # @param inline [true, false] Whether the field should be displayed inline with other fields. def initialize(name: nil, value: nil, inline: false) @name = name @value = value @inline = inline end # @return [Hash] a hash representation of this embed field, to be converted to JSON. def to_hash { name: @name, value: @value, inline: @inline } end end end