From ac58cf5853c5c5b4948e9a26ab305a203fac5651 Mon Sep 17 00:00:00 2001 From: Matt Carey Date: Sat, 8 Oct 2022 21:37:48 -0400 Subject: [PATCH] feat: add role icons (#159) Co-authored-by: PixeL --- lib/discordrb/api.rb | 8 ++++++++ lib/discordrb/api/server.rb | 19 +++++++++++++++++-- lib/discordrb/data/role.rb | 24 +++++++++++++++++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/lib/discordrb/api.rb b/lib/discordrb/api.rb index 15fa1b789..1e8b0f993 100644 --- a/lib/discordrb/api.rb +++ b/lib/discordrb/api.rb @@ -223,6 +223,14 @@ def achievement_icon_url(application_id, achievement_id, icon_hash, format = 'we "#{cdn_url}/app-assets/#{application_id}/achievements/#{achievement_id}/icons/#{icon_hash}.#{format}" end + # @param role_id [String, Integer] + # @param icon_hash [String] + # @param format ['webp', 'png', 'jpeg'] + # @return [String] + def role_icon_url(role_id, icon_hash, format = 'webp') + "#{cdn_url}/role-icons/#{role_id}/#{icon_hash}.#{format}" + end + # Login to the server def login(email, password) request( diff --git a/lib/discordrb/api/server.rb b/lib/discordrb/api/server.rb index 6751fa303..1cfc5e80c 100644 --- a/lib/discordrb/api/server.rb +++ b/lib/discordrb/api/server.rb @@ -248,13 +248,28 @@ def create_role(token, server_id, name, colour, hoist, mentionable, packed_permi # sending TTS messages, embedding links, sending files, reading the history, mentioning everybody, # connecting to voice, speaking and voice activity (push-to-talk isn't mandatory) # https://discord.com/developers/docs/resources/guild#batch-modify-guild-role - def update_role(token, server_id, role_id, name, colour, hoist = false, mentionable = false, packed_permissions = 104_324_161, reason = nil) + # @param icon [:undef, File] + def update_role(token, server_id, role_id, name, colour, hoist = false, mentionable = false, packed_permissions = 104_324_161, reason = nil, icon = :undef) + data = { color: colour, name: name, hoist: hoist, mentionable: mentionable, permissions: packed_permissions } + + if icon != :undef && icon + path_method = %i[original_filename path local_path].find { |meth| icon.respond_to?(meth) } + + raise ArgumentError, 'File object must respond to original_filename, path, or local path.' unless path_method + raise ArgumentError, 'File must respond to read' unless icon.respond_to? :read + + mime_type = MIME::Types.type_for(icon.__send__(path_method)).first&.to_s || 'image/jpeg' + data[:icon] = "data:#{mime_type};base64,#{Base64.encode64(icon.read).strip}" + elsif icon.nil? + data[:icon] = nil + end + Discordrb::API.request( :guilds_sid_roles_rid, server_id, :patch, "#{Discordrb::API.api_base}/guilds/#{server_id}/roles/#{role_id}", - { color: colour, name: name, hoist: hoist, mentionable: mentionable, permissions: packed_permissions }.to_json, + data.to_json, Authorization: token, content_type: :json, 'X-Audit-Log-Reason': reason diff --git a/lib/discordrb/data/role.rb b/lib/discordrb/data/role.rb index a2addd2b0..f63d2b8b8 100644 --- a/lib/discordrb/data/role.rb +++ b/lib/discordrb/data/role.rb @@ -32,6 +32,9 @@ class Role # @return [Integer] the position of this role in the hierarchy attr_reader :position + # @return [String, nil] The icon hash for this role. + attr_reader :icon + # This class is used internally as a wrapper to a Role object that allows easy writing of permission data. class RoleWriter # @!visibility private @@ -67,6 +70,8 @@ def initialize(data, bot, server = nil) @managed = data['managed'] @colour = ColourRGB.new(data['color']) + + @icon = data['icon'] end # @return [String] a string that will mention this role, if it is mentionable. @@ -92,6 +97,7 @@ def update_from(other) @colour = other.colour @position = other.position @managed = other.managed + @icon = other.icon end # Updates the data cache from a hash containing data @@ -128,6 +134,20 @@ def colour=(colour) update_role_data(colour: colour) end + # Upload a role icon for servers with the ROLE_ICONS feature. + # @param file [File] + def icon=(file) + update_role_data(icon: file) + end + + # @param format ['webp', 'png', 'jpeg'] + # @return [String] URL to the icon on Discord's CDN. + def icon_url(format = 'webp') + return nil unless @icon + + Discordrb::API.role_icon_url(@id, @icon, format) + end + alias_method :color=, :colour= # Changes this role's permissions to a fixed bitfield. This allows setting multiple permissions at once with just @@ -184,7 +204,9 @@ def update_role_data(new_data) (new_data[:colour] || @colour).combined, new_data[:hoist].nil? ? @hoist : new_data[:hoist], new_data[:mentionable].nil? ? @mentionable : new_data[:mentionable], - new_data[:permissions] || @permissions.bits) + new_data[:permissions] || @permissions.bits, + nil, + new_data.key?(:icon) ? new_data[:icon] : :undef) update_data(new_data) end end