lib/discorb/embed.rb
# frozen_string_literal: true
module Discorb
#
# Represents an embed of discord.
#
class Embed
# @return [String, nil] The title of embed.
attr_accessor :title
# @return [String, nil] The description of embed.
attr_accessor :description
# @return [String, nil] The url of embed.
attr_accessor :url
# @return [Time, nil] The timestamp of embed.
attr_accessor :timestamp
# @return [Discorb::Color, nil] The color of embed.
attr_accessor :color
# @return [Discorb::Embed::Author, nil] The author of embed.
attr_accessor :author
# @return [Array<Discorb::Embed::Field>] The fields of embed.
attr_accessor :fields
# @return [Discorb::Embed::Footer, nil] The footer of embed.
attr_accessor :footer
# @return [Symbol] The type of embed.
attr_reader :type
attr_reader :image, :thumbnail
# @!attribute [rw] image
# @return [Discorb::Embed::Image] The image of embed.
# @!attribute [rw] thumbnail
# @return [Discorb::Embed::Thumbnail] The thumbnail of embed.
#
# Initialize a new Embed object.
#
# @param [String] title The title of embed.
# @param [String] description The description of embed.
# @param [Discorb::Color, Integer] color The color of embed.
# @param [String] url The url of embed.
# @param [Time] timestamp The timestamp of embed.
# @param [Discorb::Embed::Author] author The author field of embed.
# @param [Array<Discorb::Embed::Field>] fields The fields of embed.
# @param [Discorb::Embed::Footer] footer The footer of embed.
# @param [Discorb::Embed::Image, String] image The image of embed.
# @param [Discorb::Embed::Thumbnail, String] thumbnail The thumbnail of embed.
#
def initialize(
title = nil,
description = nil,
color: nil,
url: nil,
timestamp: nil,
author: nil,
fields: nil,
footer: nil,
image: nil,
thumbnail: nil
)
@title = title
@description = description
@url = url
@timestamp = timestamp
@color = color && (color.is_a?(Color) ? color : Color.new(color))
@author = author
@fields = fields || []
@footer = footer
@image = image && (image.is_a?(String) ? Image.new(image) : image)
@thumbnail =
thumbnail &&
(thumbnail.is_a?(String) ? Thumbnail.new(thumbnail) : thumbnail)
@type = :rich
end
#
# Initialize embed from hash.
# @private
#
# @param [Hash] data The hash data to initialize embed.
#
def initialize_hash(data)
@title = data[:title]
@description = data[:description]
@url = data[:url]
@timestamp = data[:timestamp] && Time.iso8601(data[:timestamp])
@type = data[:type]
@color = data[:color] && Color.new(data[:color])
@footer =
data[:footer] &&
Footer.new(data[:footer][:text], icon: data[:footer][:icon_url])
@author =
if data[:author]
Author.new(
data[:author][:name],
icon: data[:author][:icon_url],
url: data[:author][:url]
)
end
@thumbnail = data[:thumbnail] && Thumbnail.new(data[:thumbnail])
@image = data[:image] && Image.new(data[:image])
@video = data[:video] && Video.new(data[:video])
@provider = data[:provider] && Provider.new(data[:provider])
@fields =
(
if data[:fields]
data[:fields].map do |f|
Field.new(f[:name], f[:value], inline: f[:inline])
end
else
[]
end
)
end
def image=(value)
@image = value.is_a?(String) ? Image.new(value) : value
end
def thumbnail=(value)
@thumbnail = value.is_a?(String) ? Thumbnail.new(value) : value
end
def inspect
"#<#{self.class} \"#{@title}\">"
end
#
# Convert embed to hash.
#
# @see https://discord.com/developers/docs/resources/channel#embed-object-embed-structure Offical Discord API Docs
# @return [Hash] Converted embed.
#
def to_hash
# @type var ret: Hash[untyped, untyped]
ret = { type: "rich" }
ret[:title] = @title if @title
ret[:description] = @description if @description
ret[:url] = @url if @url
ret[:timestamp] = @timestamp&.iso8601 if @timestamp
ret[:color] = @color&.to_i if @color
ret[:footer] = @footer&.to_hash if @footer
ret[:image] = @image&.to_hash if @image
ret[:thumbnail] = @thumbnail&.to_hash if @thumbnail
ret[:author] = @author&.to_hash if @author
ret[:fields] = @fields&.map(&:to_hash) if @fields.any?
ret
end
def self.from_hash(data)
inst = allocate
inst.initialize_hash(data)
inst
end
#
# Represents an entry in embed.
# @abstract
# @private
#
class Entry
def inspect
"#<#{self.class}>"
end
end
#
# Represents an author of embed.
#
class Author < Entry
# @return [String] The name of author.
attr_accessor :name
# @return [String, nil] The url of author.
attr_accessor :url
# @return [String, nil] The icon url of author.
attr_accessor :icon
#
# Initialize a new Author object.
#
# @param [String] name The name of author.
# @param [String] url The url of author.
# @param [String] icon The icon url of author.
#
def initialize(name, url: nil, icon: nil)
@name = name
@url = url
@icon = icon
end
#
# Convert author to hash.
#
# @see https://discord.com/developers/docs/resources/channel#embed-object-embed-author-structure
# Offical Discord API Docs
# @return [Hash] Converted author.
#
def to_hash
{ name: @name, url: @url, icon_url: @icon }
end
end
#
# Represemts a footer of embed.
#
class Footer < Entry
attr_accessor :text, :icon
#
# Initialize a new Footer object.
#
# @param [String] text The text of footer.
# @param [String] icon The icon url of footer.
#
def initialize(text, icon: nil)
@text = text
@icon = icon
end
#
# Convert footer to hash.
#
# @see https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure
# Offical Discord API Docs
# @return [Hash] Converted footer.
#
def to_hash
{ text: @text, icon_url: @icon }
end
end
#
# Represents a field of embed.
#
class Field < Entry
# @return [String] The name of field.
attr_accessor :name
# @return [String] The value of field.
attr_accessor :value
# @return [Boolean] Whether the field is inline.
attr_accessor :inline
#
# Initialize a new Field object.
#
# @param [String] name The name of field.
# @param [String] value The value of field.
# @param [Boolean] inline Whether the field is inline.
#
def initialize(name, value, inline: true)
@name = name
@value = value
@inline = inline
end
#
# Convert field to hash.
#
# @see https://discord.com/developers/docs/resources/channel#embed-object-embed-field-structure
# Offical Discord API Docs
# @return [Hash] Converted field.
#
def to_hash
{ name: @name, value: @value, inline: @inline }
end
end
#
# Represents an image of embed.
#
class Image < Entry
# @return [String] The url of image.
attr_accessor :url
# @return [String] The proxy url of image.
# @return [nil] The Image object wasn't created from gateway.
attr_reader :proxy_url
# @return [Integer] The height of image.
# @return [nil] The Image object wasn't created from gateway.
attr_reader :height
# @return [Integer] The width of image.
# @return [nil] The Image object wasn't created from gateway.
attr_reader :width
#
# Initialize a new Image object.
#
# @param [String] url URL of image.
#
def initialize(url)
data = url
if data.is_a? String
@url = data
else
@url = data[:url]
@proxy_url = data[:proxy_url]
@height = data[:height]
@width = data[:width]
end
end
#
# Convert image to hash for sending.
#
# @see https://discord.com/developers/docs/resources/channel#embed-object-embed-image-structure
# Offical Discord API Docs
# @return [Hash] Converted image.
#
def to_hash
{ url: @url }
end
end
#
# Represents a thumbnail of embed.
#
class Thumbnail < Entry
# @return [String] The url of thumbnail.
attr_accessor :url
# @return [String] The proxy url of thumbnail.
# @return [nil] The Thumbnail object wasn't created from gateway.
attr_reader :proxy_url
# @return [Integer] The height of thumbnail.
# @return [nil] The Thumbnail object wasn't created from gateway.
attr_reader :height
# @return [Integer] The width of thumbnail.
# @return [nil] The Thumbnail object wasn't created from gateway.
attr_reader :width
#
# Initialize a new Thumbnail object.
#
# @param [String] url URL of thumbnail.
#
def initialize(url)
data = url
if data.is_a? String
@url = data
else
@url = data[:url]
@proxy_url = data[:proxy_url]
@height = data[:height]
@width = data[:width]
end
end
#
# Convert thumbnail to hash for sending.
#
# @see https://discord.com/developers/docs/resources/channel#embed-object-embed-thumbnail-structure
# Offical Discord API Docs
# @return [Hash] Converted thumbnail.
#
def to_hash
{ url: @url }
end
end
#
# Represents a video of embed.
#
class Video < Entry
# @return [String] The url of video.
attr_reader :url
# @return [String] The proxy url of video.
attr_reader :proxy_url
# @return [Integer] The height of video.
attr_reader :height
# @return [Integer] The width of video.
attr_reader :width
#
# Initialize a new Video object.
# @private
#
# @param [Hash] data The data of video.
#
def initialize(data)
@url = data[:url]
@proxy_url = data[:proxy_url]
@height = data[:height]
@width = data[:width]
end
end
#
# Represents a provider of embed.
#
class Provider < Entry
# @return [String] The name of provider.
attr_reader :name
# @return [String] The url of provider.
attr_reader :url
#
# Initialize a new Provider object.
# @private
#
# @param [Hash] data The data of provider.
#
def initialize(data)
@name = data[:name]
@url = data[:url]
end
end
end
end