Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,5 @@ Style/Documentation:

Style/IfUnlessModifier:
Exclude:
- lib/discordrb/data/role.rb
- lib/discordrb/data/member.rb
- lib/discordrb/data/role.rb
10 changes: 8 additions & 2 deletions lib/discordrb/api/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -148,14 +148,20 @@ def update_member(token, server_id, user_id, nick: :undef, roles: :undef, mute:
# Update the current member's properties.
# https://discord.com/developers/docs/resources/guild#modify-current-member
def update_current_member(token, server_id, nick = :undef, reason = nil, bio = :undef, banner = :undef, avatar = :undef)
update_current_member!(token, server_id, nick: nick, avatar: avatar, banner: banner, bio: bio, reason: reason)
end

# Update the current member's properties.
# https://discord.com/developers/docs/resources/guild#modify-current-member
def update_current_member!(token, server_id, nick: :undef, avatar: :undef, banner: :undef, bio: :undef, reason: nil)
Discordrb::API.request(
:guilds_sid_members_me,
server_id,
:patch,
"#{Discordrb::API.api_base}/guilds/#{server_id}/members/@me",
{ nick: nick, bio: bio, banner: banner, avatar: avatar }.reject { |_, v| v == :undef }.to_json,
Authorization: token,
{ nick:, avatar:, banner:, bio: }.reject { |_, value| value == :undef }.to_json,
content_type: :json,
Authorization: token,
'X-Audit-Log-Reason': reason
)
end
Expand Down
18 changes: 12 additions & 6 deletions lib/discordrb/api/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,23 +43,29 @@ def change_own_nickname(token, server_id, nick, reason = nil)
)
end

# @deprecated Please use {update_current_user} instead.
# @deprecated Please use {update_current_user!} instead.
# https://discord.com/developers/docs/resources/user#modify-current-user
def update_profile(token, _email, _password, new_username, avatar, _new_password = nil)
update_current_user(token, new_username, avatar)
update_current_user!(token, username: new_username, avatar: avatar)
end

# Update the properties of the user for the current bot.
# @deprecated Please use {#update_current_user!} instead.
# https://discord.com/developers/docs/resources/user#modify-current-user
def update_current_user(token, username = :undef, avatar = :undef, banner = :undef)
update_current_user!(token, username: username, avatar: avatar, banner: banner)
end

# Update the properties of the user for the current bot.
# https://discord.com/developers/docs/resources/user#modify-current-user
def update_current_user!(token, username: :undef, avatar: :undef, banner: :undef)
Discordrb::API.request(
:users_me,
nil,
:patch,
"#{Discordrb::API.api_base}/users/@me",
{ username: username, avatar: avatar, banner: banner }.reject { |_, value| value == :undef }.to_json,
Authorization: token,
content_type: :json
{ username:, avatar:, banner: }.reject { |_, value| value == :undef }.to_json,
content_type: :json,
Authorization: token
)
end

Expand Down
120 changes: 71 additions & 49 deletions lib/discordrb/data/member.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ module MemberAttributes
# @return [Server] the server this member is on.
attr_reader :server

# @return [Time] When the user's timeout will expire.
# @return [Time, nil] When the user's timeout will expire.
attr_reader :communication_disabled_until
alias_method :timeout, :communication_disabled_until
alias_method :timeout_until, :communication_disabled_until

# @return [Integer] the flags set on this member.
attr_reader :flags
Expand Down Expand Up @@ -191,9 +192,7 @@ def communication_disabled?
# Set a user's timeout duration, or remove it by setting the timeout to `nil`.
# @param timeout_until [Time, nil] When the timeout will end.
def communication_disabled_until=(timeout_until)
raise ArgumentError, 'A time out cannot exceed 28 days' if timeout_until && timeout_until > (Time.now + 2_419_200)

update_member_data(communication_disabled_until: timeout_until&.iso8601)
modify(timeout_until: timeout_until)
end

alias_method :timeout=, :communication_disabled_until=
Expand All @@ -202,8 +201,7 @@ def communication_disabled_until=(timeout_until)
# @param role [Role, Array<Role>] The role(s) to set.
# @param reason [String] The reason the user's roles are being changed.
def set_roles(role, reason = nil)
role_ids = role_id_array(role)
update_member_data(roles: role_ids, reason: reason)
modify(roles: role_id_array(role), reason: reason)
end

# Adds and removes roles from a member.
Expand All @@ -220,7 +218,7 @@ def modify_roles(add, remove, reason = nil)
old_role_ids = resolve_role_ids
new_role_ids = (old_role_ids - remove_role_ids + add_role_ids).uniq

update_member_data(roles: new_role_ids, reason: reason)
modify(roles: new_role_ids, reason: reason)
end

# Adds one or more roles to this member.
Expand All @@ -234,7 +232,7 @@ def add_role(role, reason = nil)
else
old_role_ids = resolve_role_ids
new_role_ids = (old_role_ids + role_ids).uniq
update_member_data(roles: new_role_ids, reason: reason)
modify(roles: new_role_ids, reason: reason)
end
end

Expand All @@ -249,7 +247,7 @@ def remove_role(role, reason = nil)
else
old_role_ids = resolve_role_ids
new_role_ids = old_role_ids.reject { |i| role_ids.include?(i) }
update_member_data(roles: new_role_ids, reason: reason)
modify(roles: new_role_ids, reason: reason)
end
end

Expand Down Expand Up @@ -294,25 +292,25 @@ def sort_roles
# Server deafens this member.
# @param reason [String, nil] The reason for defeaning this member.
def server_deafen(reason: nil)
update_member_data(deaf: true, reason: reason)
modify(deaf: true, reason: reason)
end

# Server undeafens this member.
# @param reason [String, nil] The reason for un-defeaning this member.
def server_undeafen(reason: nil)
update_member_data(deaf: false, reason: reason)
modify(deaf: false, reason: reason)
end

# Server mutes this member.
# @param reason [String, nil] The reason for muting this member.
def server_mute(reason: nil)
update_member_data(mute: true, reason: reason)
modify(mute: true, reason: reason)
end

# Server unmutes this member.
# @param reason [String, nil] The reason for un-muting this member.
def server_unmute(reason: nil)
update_member_data(mute: false, reason: reason)
modify(mute: false, reason: reason)
end

# Bans this member from the server.
Expand Down Expand Up @@ -347,11 +345,7 @@ def nick=(nick)
# @param nick [String, nil] The string to set the nickname to, or nil if it should be reset.
# @param reason [String] The reason the user's nickname is being changed.
def set_nick(nick, reason = nil)
if @user.current_bot?
update_current_member_data(nick: nick, reason: reason)
else
update_member_data(nick: nick, reason: reason)
end
modify(nick: nick, reason: reason)
end

alias_method :set_nickname, :set_nick
Expand Down Expand Up @@ -381,31 +375,79 @@ def display_avatar_decoration
# Set the flags for this member.
# @param flags [Integer, nil] The new bitwise value of flags for this member, or nil.
def flags=(flags)
update_member_data(flags: flags)
modify(flags: flags)
end

# Set the server banner for the current bot.
# @param banner [File, nil] A file like object that responds to read, or `nil`.
def server_banner=(banner)
raise 'Can only set a banner for the current bot' unless current_bot?

update_current_member_data(banner: banner.respond_to?(:read) ? Discordrb.encode64(banner) : banner)
modify(banner: banner)
end

# Set the server avatar for the current bot.
# @param avatar [File, nil] A file like object that responds to read, or `nil`.
def server_avatar=(avatar)
raise 'Can only set an avatar for the current bot' unless current_bot?

update_current_member_data(avatar: avatar.respond_to?(:read) ? Discordrb.encode64(avatar) : avatar)
modify(avatar: avatar)
end

# Set the server bio for the current bot.
# @param bio [String, nil] The new server bio for the bot, or nil.
def server_bio=(bio)
raise 'Can only set a bio for the current bot' unless current_bot?

update_current_member_data(bio: bio)
modify(bio: bio)
end

# Modify the properties of the member.
# @param nick [String, nil] The new nickname of the member; between 1-32 characters. Can also be passed as `nickname:`.
# @param roles [Array<Role, Integer, String>, nil] The new roles to set for the member.
# @param mute [true, false, nil] Whether the member shoule be muted in the voice channel.
# @param deaf [true, false, nil] Whether the member should be deafened in the voice channel.
# @param voice_channel [Channel, Integer, String, nil] The voice channel to move the member to.
# @param timeout_until [Time, nil] When the member's timeout should expire. Must be a value between now and 28 days in the future.
# @param flags [Integer, nil] The new flags to set for the member. The only flag that can currently be changed is the `bypassed_verification` flag.
# @param avatar [#read, File, nil] The new server-specific avatar to set for the current bot. Should be a file-like object that responds to `#read`.
# @param banner [#read, File, nil] The new server-specific banner to set for the current bot. Should be a file-like object that responds to `#read`.
# @param bio [String, nil] The new server-specific bio to set for the current bot; between 1-190 characters.
# @param reason [String, nil] The reason to show in the server's audit log for modifying the member.
# @return [nil]
def modify(
nick: :undef, roles: :undef, mute: :undef, deaf: :undef, voice_channel: :undef,
timeout_until: :undef, flags: :undef, avatar: :undef, banner: :undef, bio: :undef,
nickname: :undef, reason: nil
)
if timeout_until.is_a?(Time) && timeout_until > (Time.now + 2_419_200)
raise ArgumentError, 'The timeout duration cannot be greater than 28 days in the future'
end

data = {
nick: nick == :undef ? nickname : nick,
roles: roles == :undef ? roles : roles&.map(&:resolve_id),
mute: mute,
deaf: deaf,
channel_id: voice_channel == :undef ? voice_channel : voice_channel&.resolve_id,
flags: flags,
communication_disabled_until: timeout_until == :undef ? timeout_until : timeout_until&.iso8601
}

if current_bot? && (nick != :undef || avatar != :undef || banner != :undef || bio != :undef)
me = {
bio: bio,
nick: data.delete(:nick),
avatar: avatar.respond_to?(:read) ? Discordrb.encode64(avatar) : avatar,
banner: banner.respond_to?(:read) ? Discordrb.encode64(banner) : banner
}

update_data(JSON.parse(API::Server.update_current_member!(@bot.token, @server_id, **me, reason: reason)))
return unless data.any? { |_, value| value != :undef }
end

update_data(JSON.parse(API::Server.update_member(@bot.token, @server_id, @user.id, **data, reason: reason)))
nil
end

# Update this member's roles
Expand Down Expand Up @@ -485,39 +527,19 @@ def inspect

private

# Utility method to get a list of role IDs from one role or an array of roles
def role_id_array(role)
if role.is_a? Array
role.map(&:resolve_id)
else
[role.resolve_id]
end
end

# Utility method to get data out of this member's voice state
def voice_state_attribute(name)
voice_state = server.voice_states[@user.id]
voice_state&.send name
end

# @!visibility private
# Utility method to get a list of this member's role IDs.
def resolve_role_ids
@roles ? @roles.collect(&:id) : @role_ids
end

# @!visibility private
def update_member_data(new_data)
update_data(JSON.parse(API::Server.update_member(@bot.token, @server_id, @user.id, **new_data)))
# Utility method to get data out of this member's voice state.
def voice_state_attribute(name)
server.voice_states[@user.resolve_id]&.send(name)
end

# @!visibility private
def update_current_member_data(new_data)
update_data(JSON.parse(API::Server.update_current_member(@bot.token, @server_id,
new_data.key?(:nick) ? new_data[:nick] : :undef,
new_data[:reason],
new_data.key?(:bio) ? new_data[:bio] : :undef,
new_data.key?(:banner) ? new_data[:banner] : :undef,
new_data.key?(:avatar) ? new_data[:avatar] : :undef)))
# Utility method to get a list of role IDs from one role or an array of roles.
def role_id_array(role)
role.is_a?(Array) ? role.map(&:resolve_id) : [role.resolve_id]
end
end
end
50 changes: 29 additions & 21 deletions lib/discordrb/data/profile.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def current_bot?
# Sets the bot's username.
# @param username [String] The new username.
def username=(username)
update_profile_data(username: username)
modify(username: username)
end

alias_method :name=, :username=
Expand All @@ -22,22 +22,40 @@ def username=(username)
# @param avatar [String, File, #read, nil] A file to be used as the avatar, either
# something readable (e.g. File Object) or a data URI.
def avatar=(avatar)
if avatar.respond_to?(:read)
update_profile_data(avatar: Discordrb.encode64(avatar))
else
update_profile_data(avatar: avatar)
end
modify(avatar: avatar)
end

# Changes the bot's banner.
# @param banner [String, File, #read, nil] A file to be used as the banner, either
# something readable (e.g. File Object) or a data URI.
def banner=(banner)
if banner.respond_to?(:read)
update_profile_data(banner: Discordrb.encode64(banner))
else
update_profile_data(banner: banner)
modify(banner: banner)
end

# Modify the properties of the current bot.
# @param username [String] The new username to set for the bot.
# @param avatar [String, File, #read, nil] The new avatar to set for the bot. Should
# be something readable (e.g. File Object) or a data URI.
# @param banner [String, File, #read, nil] The new banner to set for the bot. Should
# be something readable (e.g. File Object) or a data URI.
# @param bio [String, nil] The new global bio to set for the bot. Will be truncated to
# 190 characters when rendered in the offical Discord client.
# @return [nil]
def modify(username: :undef, avatar: :undef, banner: :undef, bio: :undef)
data = {
username: username,
avatar: avatar.respond_to?(:read) ? Discordrb.encode64(avatar) : avatar,
banner: banner.respond_to?(:read) ? Discordrb.encode64(banner) : banner
}

if bio != :undef
API::Application.update_current_application(@bot.token, description: bio)

return unless data.any? { |_, value| value != :undef }
end

update_data(JSON.parse(API::User.update_current_user!(@bot.token, **data)))
nil
end

# Get the bot's global bio.
Expand All @@ -49,7 +67,7 @@ def bio
# Set the bot's global bio.
# @param bio [String, nil] The bot's new global bio, or `nil` to remove the current bio.
def bio=(bio)
@bot.application.modify(description: bio)
modify(bio: bio)
end

# Updates the cached profile data with the new one.
Expand All @@ -65,15 +83,5 @@ def update_data(new_data)
def inspect
"<Profile user=#{super}>"
end

private

# @!visibility private
def update_profile_data(new_data)
update_data(JSON.parse(API::User.update_current_user(@bot.token,
new_data[:username] || :undef,
new_data.key?(:avatar) ? new_data[:avatar] : :undef,
new_data.key?(:banner) ? new_data[:banner] : :undef)))
end
end
end
Loading