onyxcord 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.devcontainer/Dockerfile +13 -0
- data/.devcontainer/devcontainer.json +29 -0
- data/.devcontainer/postcreate.sh +4 -0
- data/.github/CONTRIBUTING.md +13 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/pull_request_template.md +37 -0
- data/.github/workflows/ci.yml +78 -0
- data/.github/workflows/codeql.yml +65 -0
- data/.github/workflows/deploy.yml +54 -0
- data/.github/workflows/release.yml +51 -0
- data/.gitignore +16 -0
- data/.markdownlint.json +4 -0
- data/.overcommit.yml +7 -0
- data/.rspec +2 -0
- data/.rubocop.yml +129 -0
- data/.yardopts +1 -0
- data/CHANGELOG.md +0 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +305 -0
- data/Rakefile +17 -0
- data/bin/console +15 -0
- data/bin/setup +7 -0
- data/lib/onyxcord/allowed_mentions.rb +43 -0
- data/lib/onyxcord/api/application.rb +316 -0
- data/lib/onyxcord/api/channel.rb +700 -0
- data/lib/onyxcord/api/interaction.rb +67 -0
- data/lib/onyxcord/api/invite.rb +44 -0
- data/lib/onyxcord/api/server.rb +775 -0
- data/lib/onyxcord/api/user.rb +158 -0
- data/lib/onyxcord/api/webhook.rb +163 -0
- data/lib/onyxcord/api.rb +335 -0
- data/lib/onyxcord/await.rb +51 -0
- data/lib/onyxcord/bot.rb +1971 -0
- data/lib/onyxcord/cache.rb +326 -0
- data/lib/onyxcord/colour_rgb.rb +43 -0
- data/lib/onyxcord/commands/command_bot.rb +511 -0
- data/lib/onyxcord/commands/container.rb +112 -0
- data/lib/onyxcord/commands/events.rb +11 -0
- data/lib/onyxcord/commands/parser.rb +327 -0
- data/lib/onyxcord/commands/rate_limiter.rb +144 -0
- data/lib/onyxcord/configuration.rb +125 -0
- data/lib/onyxcord/container.rb +988 -0
- data/lib/onyxcord/data/activity.rb +271 -0
- data/lib/onyxcord/data/application.rb +341 -0
- data/lib/onyxcord/data/attachment.rb +91 -0
- data/lib/onyxcord/data/audit_logs.rb +438 -0
- data/lib/onyxcord/data/avatar_decoration.rb +26 -0
- data/lib/onyxcord/data/call.rb +22 -0
- data/lib/onyxcord/data/channel.rb +1355 -0
- data/lib/onyxcord/data/channel_tag.rb +69 -0
- data/lib/onyxcord/data/collectibles.rb +47 -0
- data/lib/onyxcord/data/component.rb +583 -0
- data/lib/onyxcord/data/embed.rb +258 -0
- data/lib/onyxcord/data/emoji.rb +123 -0
- data/lib/onyxcord/data/install_params.rb +24 -0
- data/lib/onyxcord/data/integration.rb +144 -0
- data/lib/onyxcord/data/interaction.rb +1141 -0
- data/lib/onyxcord/data/invite.rb +137 -0
- data/lib/onyxcord/data/member.rb +528 -0
- data/lib/onyxcord/data/message.rb +612 -0
- data/lib/onyxcord/data/message_activity.rb +41 -0
- data/lib/onyxcord/data/overwrite.rb +109 -0
- data/lib/onyxcord/data/poll.rb +365 -0
- data/lib/onyxcord/data/primary_server.rb +60 -0
- data/lib/onyxcord/data/profile.rb +79 -0
- data/lib/onyxcord/data/reaction.rb +64 -0
- data/lib/onyxcord/data/recipient.rb +34 -0
- data/lib/onyxcord/data/role.rb +449 -0
- data/lib/onyxcord/data/role_connection_data.rb +69 -0
- data/lib/onyxcord/data/role_subscription.rb +41 -0
- data/lib/onyxcord/data/scheduled_event.rb +513 -0
- data/lib/onyxcord/data/server.rb +1614 -0
- data/lib/onyxcord/data/server_preview.rb +68 -0
- data/lib/onyxcord/data/snapshot.rb +112 -0
- data/lib/onyxcord/data/team.rb +98 -0
- data/lib/onyxcord/data/timestamp.rb +69 -0
- data/lib/onyxcord/data/user.rb +324 -0
- data/lib/onyxcord/data/voice_region.rb +46 -0
- data/lib/onyxcord/data/voice_state.rb +41 -0
- data/lib/onyxcord/data/webhook.rb +238 -0
- data/lib/onyxcord/data.rb +57 -0
- data/lib/onyxcord/errors.rb +246 -0
- data/lib/onyxcord/event_executor.rb +80 -0
- data/lib/onyxcord/events/await.rb +48 -0
- data/lib/onyxcord/events/bans.rb +60 -0
- data/lib/onyxcord/events/channels.rb +225 -0
- data/lib/onyxcord/events/generic.rb +129 -0
- data/lib/onyxcord/events/guilds.rb +269 -0
- data/lib/onyxcord/events/integrations.rb +100 -0
- data/lib/onyxcord/events/interactions.rb +624 -0
- data/lib/onyxcord/events/invites.rb +127 -0
- data/lib/onyxcord/events/lifetime.rb +31 -0
- data/lib/onyxcord/events/members.rb +110 -0
- data/lib/onyxcord/events/message.rb +399 -0
- data/lib/onyxcord/events/polls.rb +118 -0
- data/lib/onyxcord/events/presence.rb +131 -0
- data/lib/onyxcord/events/raw.rb +74 -0
- data/lib/onyxcord/events/reactions.rb +218 -0
- data/lib/onyxcord/events/roles.rb +87 -0
- data/lib/onyxcord/events/scheduled_events.rb +171 -0
- data/lib/onyxcord/events/threads.rb +100 -0
- data/lib/onyxcord/events/typing.rb +73 -0
- data/lib/onyxcord/events/voice_server_update.rb +48 -0
- data/lib/onyxcord/events/voice_state_update.rb +106 -0
- data/lib/onyxcord/events/webhooks.rb +65 -0
- data/lib/onyxcord/gateway.rb +890 -0
- data/lib/onyxcord/id_object.rb +39 -0
- data/lib/onyxcord/light/data.rb +62 -0
- data/lib/onyxcord/light/integrations.rb +73 -0
- data/lib/onyxcord/light/light_bot.rb +58 -0
- data/lib/onyxcord/light.rb +8 -0
- data/lib/onyxcord/logger.rb +120 -0
- data/lib/onyxcord/message_components.rb +70 -0
- data/lib/onyxcord/paginator.rb +60 -0
- data/lib/onyxcord/permissions.rb +255 -0
- data/lib/onyxcord/rate_limiter/gateway.rb +42 -0
- data/lib/onyxcord/rate_limiter/rest.rb +89 -0
- data/lib/onyxcord/version.rb +7 -0
- data/lib/onyxcord/voice/encoder.rb +115 -0
- data/lib/onyxcord/voice/network.rb +380 -0
- data/lib/onyxcord/voice/opcodes.rb +29 -0
- data/lib/onyxcord/voice/sodium.rb +157 -0
- data/lib/onyxcord/voice/timer.rb +19 -0
- data/lib/onyxcord/voice/voice_bot.rb +386 -0
- data/lib/onyxcord/webhooks.rb +14 -0
- data/lib/onyxcord/websocket.rb +62 -0
- data/lib/onyxcord.rb +180 -0
- data/onyxcord-webhooks.gemspec +30 -0
- data/onyxcord.gemspec +50 -0
- metadata +421 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# Voice regions are the locations of servers that handle voice communication in Discord
|
|
5
|
+
class VoiceRegion
|
|
6
|
+
# @return [String] unique ID for the region
|
|
7
|
+
attr_reader :id
|
|
8
|
+
alias_method :to_s, :id
|
|
9
|
+
|
|
10
|
+
# @return [String] name of the region
|
|
11
|
+
attr_reader :name
|
|
12
|
+
|
|
13
|
+
# @return [String] an example hostname for the region
|
|
14
|
+
attr_reader :sample_hostname
|
|
15
|
+
|
|
16
|
+
# @return [Integer] an example port for the region
|
|
17
|
+
attr_reader :sample_port
|
|
18
|
+
|
|
19
|
+
# @return [true, false] if this is a VIP-only server
|
|
20
|
+
attr_reader :vip
|
|
21
|
+
|
|
22
|
+
# @return [true, false] if this voice server is the closest to the client
|
|
23
|
+
attr_reader :optimal
|
|
24
|
+
|
|
25
|
+
# @return [true, false] whether this is a deprecated voice region (avoid switching to these)
|
|
26
|
+
attr_reader :deprecated
|
|
27
|
+
|
|
28
|
+
# @return [true, false] whether this is a custom voice region (used for events/etc)
|
|
29
|
+
attr_reader :custom
|
|
30
|
+
|
|
31
|
+
# @!visibility private
|
|
32
|
+
def initialize(data)
|
|
33
|
+
@id = data['id']
|
|
34
|
+
|
|
35
|
+
@name = data['name']
|
|
36
|
+
|
|
37
|
+
@sample_hostname = data['sample_hostname']
|
|
38
|
+
@sample_port = data['sample_port']
|
|
39
|
+
|
|
40
|
+
@vip = data['vip']
|
|
41
|
+
@optimal = data['optimal']
|
|
42
|
+
@deprecated = data['deprecated']
|
|
43
|
+
@custom = data['custom']
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# A voice state represents the state of a member's connection to a voice channel. It includes data like the voice
|
|
5
|
+
# channel the member is connected to and mute/deaf flags.
|
|
6
|
+
class VoiceState
|
|
7
|
+
# @return [Integer] the ID of the user whose voice state is represented by this object.
|
|
8
|
+
attr_reader :user_id
|
|
9
|
+
|
|
10
|
+
# @return [true, false] whether this voice state's member is muted server-wide.
|
|
11
|
+
attr_reader :mute
|
|
12
|
+
|
|
13
|
+
# @return [true, false] whether this voice state's member is deafened server-wide.
|
|
14
|
+
attr_reader :deaf
|
|
15
|
+
|
|
16
|
+
# @return [true, false] whether this voice state's member has muted themselves.
|
|
17
|
+
attr_reader :self_mute
|
|
18
|
+
|
|
19
|
+
# @return [true, false] whether this voice state's member has deafened themselves.
|
|
20
|
+
attr_reader :self_deaf
|
|
21
|
+
|
|
22
|
+
# @return [Channel] the voice channel this voice state's member is in.
|
|
23
|
+
attr_reader :voice_channel
|
|
24
|
+
|
|
25
|
+
# @!visibility private
|
|
26
|
+
def initialize(user_id)
|
|
27
|
+
@user_id = user_id
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Update this voice state with new data from Discord
|
|
31
|
+
# @note For internal use only.
|
|
32
|
+
# @!visibility private
|
|
33
|
+
def update(channel, mute, deaf, self_mute, self_deaf)
|
|
34
|
+
@voice_channel = channel
|
|
35
|
+
@mute = mute
|
|
36
|
+
@deaf = deaf
|
|
37
|
+
@self_mute = self_mute
|
|
38
|
+
@self_deaf = self_deaf
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'onyxcord/webhooks/builder'
|
|
4
|
+
require 'onyxcord/webhooks/view'
|
|
5
|
+
require 'onyxcord/message_components'
|
|
6
|
+
|
|
7
|
+
module OnyxCord
|
|
8
|
+
# A webhook on a server channel
|
|
9
|
+
class Webhook
|
|
10
|
+
include IDObject
|
|
11
|
+
|
|
12
|
+
# @return [String] the webhook name.
|
|
13
|
+
attr_reader :name
|
|
14
|
+
|
|
15
|
+
# @return [Channel] the channel that the webhook is currently connected to.
|
|
16
|
+
attr_reader :channel
|
|
17
|
+
|
|
18
|
+
# @return [Server] the server that the webhook is currently connected to.
|
|
19
|
+
attr_reader :server
|
|
20
|
+
|
|
21
|
+
# @return [String, nil] the webhook's token, if this is an Incoming Webhook.
|
|
22
|
+
attr_reader :token
|
|
23
|
+
|
|
24
|
+
# @return [String] the webhook's avatar id.
|
|
25
|
+
attr_reader :avatar
|
|
26
|
+
|
|
27
|
+
# @return [Integer] the webhook's type (1: Incoming, 2: Channel Follower)
|
|
28
|
+
attr_reader :type
|
|
29
|
+
|
|
30
|
+
# Gets the user object of the creator of the webhook. May be limited to username, discriminator,
|
|
31
|
+
# ID and avatar if the bot cannot reach the owner
|
|
32
|
+
# @return [Member, User, nil] the user object of the owner or nil if the webhook was requested using the token.
|
|
33
|
+
attr_reader :owner
|
|
34
|
+
|
|
35
|
+
# @!visibility private
|
|
36
|
+
def initialize(data, bot)
|
|
37
|
+
@bot = bot
|
|
38
|
+
|
|
39
|
+
@name = data['name']
|
|
40
|
+
@id = data['id'].to_i
|
|
41
|
+
@channel = bot.channel(data['channel_id'])
|
|
42
|
+
@server = @channel.server
|
|
43
|
+
@token = data['token']
|
|
44
|
+
@avatar = data['avatar']
|
|
45
|
+
@type = data['type']
|
|
46
|
+
|
|
47
|
+
# Will not exist if the data was requested through a webhook token
|
|
48
|
+
return unless data['user']
|
|
49
|
+
|
|
50
|
+
@owner = @server.member(data['user']['id'].to_i)
|
|
51
|
+
return if @owner
|
|
52
|
+
|
|
53
|
+
OnyxCord::LOGGER.debug("Member with ID #{data['user']['id']} not cached (possibly left the server).")
|
|
54
|
+
@owner = @bot.ensure_user(data['user'])
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Sets the webhook's avatar.
|
|
58
|
+
# @param avatar [String, #read] The new avatar, in base64-encoded JPG format.
|
|
59
|
+
def avatar=(avatar)
|
|
60
|
+
update_webhook(avatar: avatarise(avatar))
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# Deletes the webhook's avatar.
|
|
64
|
+
def delete_avatar
|
|
65
|
+
update_webhook(avatar: nil)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Sets the webhook's channel
|
|
69
|
+
# @param channel [Channel, String, Integer] The channel the webhook should use.
|
|
70
|
+
def channel=(channel)
|
|
71
|
+
update_webhook(channel_id: channel.resolve_id)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Sets the webhook's name.
|
|
75
|
+
# @param name [String] The webhook's new name.
|
|
76
|
+
def name=(name)
|
|
77
|
+
update_webhook(name: name)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Updates the webhook if you need to edit more than 1 attribute.
|
|
81
|
+
# @param data [Hash] the data to update.
|
|
82
|
+
# @option data [String, #read, nil] :avatar The new avatar, in base64-encoded JPG format, or nil to delete the avatar.
|
|
83
|
+
# @option data [Channel, String, Integer] :channel The channel the webhook should use.
|
|
84
|
+
# @option data [String] :name The webhook's new name.
|
|
85
|
+
# @option data [String] :reason The reason for the webhook changes.
|
|
86
|
+
def update(data)
|
|
87
|
+
# Only pass a value for avatar if the key is defined as sending nil will delete the
|
|
88
|
+
data[:avatar] = avatarise(data[:avatar]) if data.key?(:avatar)
|
|
89
|
+
data[:channel_id] = data[:channel]&.resolve_id
|
|
90
|
+
data.delete(:channel)
|
|
91
|
+
update_webhook(**data)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Deletes the webhook.
|
|
95
|
+
# @param reason [String] The reason the webhook is being deleted.
|
|
96
|
+
def delete(reason = nil)
|
|
97
|
+
if token?
|
|
98
|
+
API::Webhook.token_delete_webhook(@token, @id, reason)
|
|
99
|
+
else
|
|
100
|
+
API::Webhook.delete_webhook(@bot.token, @id, reason)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Execute a webhook.
|
|
105
|
+
# @param content [String] The content of the message. May be 2000 characters long at most.
|
|
106
|
+
# @param username [String] The username the webhook will display as. If this is not set, the default username set in the webhook's settings.
|
|
107
|
+
# @param avatar_url [String] The URL of an image file to be used as an avatar. If this is not set, the default avatar from the webhook's
|
|
108
|
+
# @param tts [true, false] Whether this message should use TTS or not. By default, it doesn't.
|
|
109
|
+
# @param file [File] File to be sent together with the message. Mutually exclusive with embeds; a webhook message can contain
|
|
110
|
+
# either a file to be sent or embeds.
|
|
111
|
+
# @param embeds [Array<Webhooks::Embed, Hash>] Embeds to attach to this message.
|
|
112
|
+
# @param allowed_mentions [AllowedMentions, Hash] Mentions that are allowed to ping in the `content`.
|
|
113
|
+
# @param wait [true, false] Whether Discord should wait for the message to be successfully received by clients, or
|
|
114
|
+
# whether it should return immediately after sending the message. If `true` a {Message} object will be returned.
|
|
115
|
+
# @yield [builder] Gives the builder to the block to add additional steps, or to do the entire building process.
|
|
116
|
+
# @yieldparam builder [Builder] The builder given as a parameter which is used as the initial step to start from.
|
|
117
|
+
# @example Execute the webhook with kwargs
|
|
118
|
+
# client.execute(
|
|
119
|
+
# content: 'Testing',
|
|
120
|
+
# username: 'onyxcord',
|
|
121
|
+
# embeds: [
|
|
122
|
+
# { timestamp: Time.now.iso8601, title: 'testing', image: { url: 'https://i.imgur.com/PcMltU7.jpg' } }
|
|
123
|
+
# ])
|
|
124
|
+
# @example Execute the webhook with an already existing builder
|
|
125
|
+
# builder = OnyxCord::Webhooks::Builder.new # ...
|
|
126
|
+
# client.execute(builder)
|
|
127
|
+
# @example Execute the webhook by building a new message
|
|
128
|
+
# client.execute do |builder|
|
|
129
|
+
# builder.content = 'Testing'
|
|
130
|
+
# builder.username = 'onyxcord'
|
|
131
|
+
# builder.add_embed do |embed|
|
|
132
|
+
# embed.timestamp = Time.now
|
|
133
|
+
# embed.title = 'Testing'
|
|
134
|
+
# embed.image = OnyxCord::Webhooks::EmbedImage.new(url: 'https://i.imgur.com/PcMltU7.jpg')
|
|
135
|
+
# end
|
|
136
|
+
# end
|
|
137
|
+
# @return [Message, nil] If `wait` is `true`, a {Message} will be returned. Otherwise this method will return `nil`.
|
|
138
|
+
# @note This is only available to webhooks with publically exposed tokens. This excludes channel follow webhooks and webhooks retrieved
|
|
139
|
+
# via the audit log.
|
|
140
|
+
def execute(content: nil, username: nil, avatar_url: nil, tts: nil, file: nil, embeds: nil, allowed_mentions: nil, wait: true, builder: nil, components: nil, flags: 0, has_components: false, components_v2: false)
|
|
141
|
+
raise OnyxCord::Errors::UnauthorizedWebhook unless @token
|
|
142
|
+
|
|
143
|
+
params = { content: content, username: username, avatar_url: avatar_url, tts: tts, file: file, embeds: embeds, allowed_mentions: allowed_mentions }
|
|
144
|
+
|
|
145
|
+
builder ||= Webhooks::Builder.new
|
|
146
|
+
view = Webhooks::View.new
|
|
147
|
+
|
|
148
|
+
yield(builder, view) if block_given?
|
|
149
|
+
|
|
150
|
+
data = builder.to_json_hash.merge(params.compact)
|
|
151
|
+
components ||= view
|
|
152
|
+
flags = OnyxCord::MessageComponents.apply_v2_flag(flags, components, force: has_components || components_v2)
|
|
153
|
+
|
|
154
|
+
resp = API::Webhook.token_execute_webhook(@token, @id, wait, data[:content], data[:username], data[:avatar_url], data[:tts], data[:file], data[:embeds], data[:allowed_mentions], flags, components.to_a)
|
|
155
|
+
|
|
156
|
+
Message.new(JSON.parse(resp), @bot) if wait
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Delete a message created by this webhook.
|
|
160
|
+
# @param message [Message, String, Integer] The ID of the message to delete.
|
|
161
|
+
def delete_message(message)
|
|
162
|
+
raise OnyxCord::Errors::UnauthorizedWebhook unless @token
|
|
163
|
+
|
|
164
|
+
API::Webhook.token_delete_message(@token, @id, message.resolve_id)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# Edit a message created by this webhook.
|
|
168
|
+
# @param message [Message, String, Integer] The ID of the message to edit.
|
|
169
|
+
# @param content [String] The content of the message. May be 2000 characters long at most.
|
|
170
|
+
# @param embeds [Array<Webhooks::Embed, Hash>] Embeds to be attached to the message.
|
|
171
|
+
# @param allowed_mentions [AllowedMentions, Hash] Mentions that are allowed to ping in the `content`.
|
|
172
|
+
# @param builder [Builder, nil] The builder to start out with, or nil if one should be created anew.
|
|
173
|
+
# @yield [builder] Gives the builder to the block to add additional steps, or to do the entire building process.
|
|
174
|
+
# @yieldparam builder [Webhooks::Builder] The builder given as a parameter which is used as the initial step to start from.
|
|
175
|
+
# @return [Message] The updated message.
|
|
176
|
+
# @param components [View, Array<Hash>] Interaction components to associate with this message.
|
|
177
|
+
# @note When editing `allowed_mentions`, it will update visually in the client but not alert the user with a notification.
|
|
178
|
+
def edit_message(message, content: nil, embeds: nil, allowed_mentions: nil, builder: nil, components: nil, flags: 0, has_components: false, components_v2: false)
|
|
179
|
+
raise OnyxCord::Errors::UnauthorizedWebhook unless @token
|
|
180
|
+
|
|
181
|
+
params = { content: content, embeds: embeds, allowed_mentions: allowed_mentions }.compact
|
|
182
|
+
|
|
183
|
+
builder ||= Webhooks::Builder.new
|
|
184
|
+
view ||= Webhooks::View.new
|
|
185
|
+
|
|
186
|
+
yield(builder, view) if block_given?
|
|
187
|
+
|
|
188
|
+
data = builder.to_json_hash.merge(params.compact)
|
|
189
|
+
components ||= view
|
|
190
|
+
flags = OnyxCord::MessageComponents.apply_v2_flag(flags, components, force: has_components || components_v2)
|
|
191
|
+
|
|
192
|
+
resp = API::Webhook.token_edit_message(@token, @id, message.resolve_id, data[:content], data[:embeds], data[:allowed_mentions], components.to_a, nil, flags)
|
|
193
|
+
Message.new(JSON.parse(resp), @bot)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Utility function to get a webhook's avatar URL.
|
|
197
|
+
# @return [String] the URL to the avatar image
|
|
198
|
+
def avatar_url
|
|
199
|
+
return API::User.default_avatar(@id) unless @avatar
|
|
200
|
+
|
|
201
|
+
API::User.avatar_url(@id, @avatar)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# The `inspect` method is overwritten to give more useful output.
|
|
205
|
+
def inspect
|
|
206
|
+
"<Webhook name=#{@name} id=#{@id}>"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# Utility function to know if the webhook was requested through a webhook token, rather than auth.
|
|
210
|
+
# @return [true, false] whether the webhook was requested by token or not.
|
|
211
|
+
def token?
|
|
212
|
+
@owner.nil?
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
private
|
|
216
|
+
|
|
217
|
+
def avatarise(avatar)
|
|
218
|
+
avatar.respond_to?(:read) ? OnyxCord.encode64(avatar) : avatar
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def update_internal(data)
|
|
222
|
+
@name = data['name']
|
|
223
|
+
@avatar_id = data['avatar']
|
|
224
|
+
@channel = @bot.channel(data['channel_id'])
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
def update_webhook(new_data)
|
|
228
|
+
reason = new_data.delete(:reason)
|
|
229
|
+
data = JSON.parse(if token?
|
|
230
|
+
API::Webhook.token_update_webhook(@token, @id, new_data, reason)
|
|
231
|
+
else
|
|
232
|
+
API::Webhook.update_webhook(@bot.token, @id, new_data, reason)
|
|
233
|
+
end)
|
|
234
|
+
# Only update cache if API call worked
|
|
235
|
+
update_internal(data) if data['name']
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'onyxcord/allowed_mentions'
|
|
4
|
+
require 'onyxcord/permissions'
|
|
5
|
+
require 'onyxcord/id_object'
|
|
6
|
+
require 'onyxcord/colour_rgb'
|
|
7
|
+
require 'onyxcord/errors'
|
|
8
|
+
require 'onyxcord/api'
|
|
9
|
+
require 'onyxcord/api/channel'
|
|
10
|
+
require 'onyxcord/api/server'
|
|
11
|
+
require 'onyxcord/api/invite'
|
|
12
|
+
require 'onyxcord/api/user'
|
|
13
|
+
require 'onyxcord/api/webhook'
|
|
14
|
+
require 'onyxcord/webhooks/embeds'
|
|
15
|
+
require 'onyxcord/webhooks/view'
|
|
16
|
+
require 'onyxcord/paginator'
|
|
17
|
+
require 'time'
|
|
18
|
+
require 'base64'
|
|
19
|
+
|
|
20
|
+
require 'onyxcord/data/activity'
|
|
21
|
+
require 'onyxcord/data/application'
|
|
22
|
+
require 'onyxcord/data/user'
|
|
23
|
+
require 'onyxcord/data/voice_state'
|
|
24
|
+
require 'onyxcord/data/voice_region'
|
|
25
|
+
require 'onyxcord/data/member'
|
|
26
|
+
require 'onyxcord/data/recipient'
|
|
27
|
+
require 'onyxcord/data/profile'
|
|
28
|
+
require 'onyxcord/data/role'
|
|
29
|
+
require 'onyxcord/data/invite'
|
|
30
|
+
require 'onyxcord/data/overwrite'
|
|
31
|
+
require 'onyxcord/data/channel'
|
|
32
|
+
require 'onyxcord/data/embed'
|
|
33
|
+
require 'onyxcord/data/attachment'
|
|
34
|
+
require 'onyxcord/data/message'
|
|
35
|
+
require 'onyxcord/data/reaction'
|
|
36
|
+
require 'onyxcord/data/emoji'
|
|
37
|
+
require 'onyxcord/data/integration'
|
|
38
|
+
require 'onyxcord/data/server'
|
|
39
|
+
require 'onyxcord/data/webhook'
|
|
40
|
+
require 'onyxcord/data/audit_logs'
|
|
41
|
+
require 'onyxcord/data/interaction'
|
|
42
|
+
require 'onyxcord/data/component'
|
|
43
|
+
require 'onyxcord/data/avatar_decoration'
|
|
44
|
+
require 'onyxcord/data/collectibles'
|
|
45
|
+
require 'onyxcord/data/primary_server'
|
|
46
|
+
require 'onyxcord/data/server_preview'
|
|
47
|
+
require 'onyxcord/data/call'
|
|
48
|
+
require 'onyxcord/data/snapshot'
|
|
49
|
+
require 'onyxcord/data/role_subscription'
|
|
50
|
+
require 'onyxcord/data/message_activity'
|
|
51
|
+
require 'onyxcord/data/team'
|
|
52
|
+
require 'onyxcord/data/install_params'
|
|
53
|
+
require 'onyxcord/data/role_connection_data'
|
|
54
|
+
require 'onyxcord/data/channel_tag'
|
|
55
|
+
require 'onyxcord/data/timestamp'
|
|
56
|
+
require 'onyxcord/data/scheduled_event'
|
|
57
|
+
require 'onyxcord/data/poll'
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module OnyxCord
|
|
4
|
+
# Custom errors raised in various places
|
|
5
|
+
module Errors
|
|
6
|
+
# Raised when authentication data is invalid or incorrect.
|
|
7
|
+
class InvalidAuthenticationError < RuntimeError
|
|
8
|
+
# Default message for this exception
|
|
9
|
+
def message
|
|
10
|
+
'User login failed due to an invalid email or password!'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Raised when a message is over the character limit
|
|
15
|
+
class MessageTooLong < RuntimeError; end
|
|
16
|
+
|
|
17
|
+
# Raised when the bot can't do something because its permissions on the server are insufficient
|
|
18
|
+
class NoPermission < RuntimeError; end
|
|
19
|
+
|
|
20
|
+
# Raised when the bot gets a HTTP 502 error, which is usually caused by Cloudflare.
|
|
21
|
+
class CloudflareError < RuntimeError; end
|
|
22
|
+
|
|
23
|
+
# Raised when using a webhook method without an associated token.
|
|
24
|
+
class UnauthorizedWebhook < RuntimeError; end
|
|
25
|
+
|
|
26
|
+
# Generic class for errors denoted by API error codes
|
|
27
|
+
class CodeError < RuntimeError
|
|
28
|
+
class << self
|
|
29
|
+
# @return [Integer] The error code represented by this error class.
|
|
30
|
+
attr_reader :code
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Create a new error with a particular message (the code should be defined by the class instance variable)
|
|
34
|
+
# @param message [String] the message to use
|
|
35
|
+
# @param errors [Hash] API errors
|
|
36
|
+
def initialize(message, errors = nil)
|
|
37
|
+
@message = message
|
|
38
|
+
|
|
39
|
+
@errors = errors ? flatten_errors(errors) : []
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @return [Integer] The error code represented by this error.
|
|
43
|
+
def code
|
|
44
|
+
self.class.code
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# @return [String] A message including the message and flattened errors.
|
|
48
|
+
def full_message(*)
|
|
49
|
+
error_list = @errors.collect { |err| "\t- #{err}" }
|
|
50
|
+
|
|
51
|
+
"#{@message}\n#{error_list.join("\n")}"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [String] This error's represented message
|
|
55
|
+
attr_reader :message
|
|
56
|
+
|
|
57
|
+
# @return [Hash] More precise errors
|
|
58
|
+
attr_reader :errors
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
# @!visibility hidden
|
|
63
|
+
# Flattens errors into a more easily read format.
|
|
64
|
+
# @example Flattening errors of a bad field
|
|
65
|
+
# flatten_errors(data['errors'])
|
|
66
|
+
# # => ["embed.fields[0].name: This field is required", "embed.fields[0].value: This field is required"]
|
|
67
|
+
def flatten_errors(err, prev_key = nil)
|
|
68
|
+
err.collect do |key, sub_err|
|
|
69
|
+
if prev_key
|
|
70
|
+
key = /\A\d+\Z/.match?(key) ? "#{prev_key}[#{key}]" : "#{prev_key}.#{key}"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
if (errs = sub_err['_errors'])
|
|
74
|
+
"#{key}: #{errs.map { |e| e['message'] }.join(' ')}"
|
|
75
|
+
elsif sub_err['message'] || sub_err['code']
|
|
76
|
+
"#{"#{sub_err['code']}: " if sub_err['code']}#{err_msg}"
|
|
77
|
+
elsif sub_err.is_a? String
|
|
78
|
+
sub_err
|
|
79
|
+
else
|
|
80
|
+
flatten_errors(sub_err, key)
|
|
81
|
+
end
|
|
82
|
+
end.flatten
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Create a new code error class
|
|
87
|
+
# rubocop:disable Naming/MethodName
|
|
88
|
+
def self.Code(code)
|
|
89
|
+
classy = Class.new(CodeError)
|
|
90
|
+
classy.instance_variable_set(:@code, code)
|
|
91
|
+
|
|
92
|
+
@code_classes ||= {}
|
|
93
|
+
@code_classes[code] = classy
|
|
94
|
+
|
|
95
|
+
classy
|
|
96
|
+
end
|
|
97
|
+
# rubocop:enable Naming/MethodName
|
|
98
|
+
|
|
99
|
+
# @param code [Integer] The code to check
|
|
100
|
+
# @return [Class] the error class for the given code
|
|
101
|
+
def self.error_class_for(code)
|
|
102
|
+
@code_classes[code] || Code(code)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Used when Discord doesn't provide a more specific code
|
|
106
|
+
UnknownError = Code(0)
|
|
107
|
+
|
|
108
|
+
# Unknown Account
|
|
109
|
+
UnknownAccount = Code(10_001)
|
|
110
|
+
|
|
111
|
+
# Unknown Application
|
|
112
|
+
UnknownApplication = Code(10_002)
|
|
113
|
+
|
|
114
|
+
# Unknown Channel
|
|
115
|
+
UnknownChannel = Code(10_003)
|
|
116
|
+
|
|
117
|
+
# Unknown Server
|
|
118
|
+
UnknownServer = Code(10_004)
|
|
119
|
+
|
|
120
|
+
# Unknown Integration
|
|
121
|
+
UnknownIntegration = Code(10_005)
|
|
122
|
+
|
|
123
|
+
# Unknown Invite
|
|
124
|
+
UnknownInvite = Code(10_006)
|
|
125
|
+
|
|
126
|
+
# Unknown Member
|
|
127
|
+
UnknownMember = Code(10_007)
|
|
128
|
+
|
|
129
|
+
# Unknown Message
|
|
130
|
+
UnknownMessage = Code(10_008)
|
|
131
|
+
|
|
132
|
+
# Unknown Overwrite
|
|
133
|
+
UnknownOverwrite = Code(10_009)
|
|
134
|
+
|
|
135
|
+
# Unknown Provider
|
|
136
|
+
UnknownProvider = Code(10_010)
|
|
137
|
+
|
|
138
|
+
# Unknown Role
|
|
139
|
+
UnknownRole = Code(10_011)
|
|
140
|
+
|
|
141
|
+
# Unknown Token
|
|
142
|
+
UnknownToken = Code(10_012)
|
|
143
|
+
|
|
144
|
+
# Unknown User
|
|
145
|
+
UnknownUser = Code(10_013)
|
|
146
|
+
|
|
147
|
+
# Unknown Emoji
|
|
148
|
+
UnknownEmoji = Code(10_014)
|
|
149
|
+
|
|
150
|
+
# Bots cannot use this endpoint
|
|
151
|
+
EndpointNotForBots = Code(20_001)
|
|
152
|
+
|
|
153
|
+
# Only bots can use this endpoint
|
|
154
|
+
EndpointOnlyForBots = Code(20_002)
|
|
155
|
+
|
|
156
|
+
# Maximum number of servers reached (100)
|
|
157
|
+
ServerLimitReached = Code(30_001)
|
|
158
|
+
|
|
159
|
+
# Maximum number of friends reached (1000)
|
|
160
|
+
FriendLimitReached = Code(30_002)
|
|
161
|
+
|
|
162
|
+
# Maximum number of pins reached (50)
|
|
163
|
+
PinLimitReached = Code(30_003)
|
|
164
|
+
|
|
165
|
+
# Maximum number of guild roles reached (250)
|
|
166
|
+
RoleLimitReached = Code(30_005)
|
|
167
|
+
|
|
168
|
+
# Too many reactions
|
|
169
|
+
ReactionLimitReached = Code(30_010)
|
|
170
|
+
|
|
171
|
+
# Maximum number of guild channels reached (500)
|
|
172
|
+
ChannelLimitReached = Code(30_013)
|
|
173
|
+
|
|
174
|
+
# Unauthorized
|
|
175
|
+
Unauthorized = Unauthorised = Code(40_001)
|
|
176
|
+
|
|
177
|
+
# Unable to bulk ban any users
|
|
178
|
+
UnableToBulkBanUsers = Code(500_000)
|
|
179
|
+
|
|
180
|
+
# Missing Access
|
|
181
|
+
MissingAccess = Code(50_001)
|
|
182
|
+
|
|
183
|
+
# Invalid Account Type
|
|
184
|
+
InvalidAccountType = Code(50_002)
|
|
185
|
+
|
|
186
|
+
# Cannot execute action on a DM channel
|
|
187
|
+
InvalidActionForDM = Code(50_003)
|
|
188
|
+
|
|
189
|
+
# Embed Disabled
|
|
190
|
+
EmbedDisabled = Code(50_004)
|
|
191
|
+
|
|
192
|
+
# Cannot edit a message authored by another user
|
|
193
|
+
MessageAuthoredByOtherUser = Code(50_005)
|
|
194
|
+
|
|
195
|
+
# Cannot send an empty message
|
|
196
|
+
MessageEmpty = Code(50_006)
|
|
197
|
+
|
|
198
|
+
# Cannot send messages to this user
|
|
199
|
+
NoMessagesToUser = Code(50_007)
|
|
200
|
+
|
|
201
|
+
# Cannot send messages in a voice channel
|
|
202
|
+
NoMessagesInVoiceChannel = Code(50_008)
|
|
203
|
+
|
|
204
|
+
# Channel verification level is too high
|
|
205
|
+
VerificationLevelTooHigh = Code(50_009)
|
|
206
|
+
|
|
207
|
+
# OAuth2 application does not have a bot
|
|
208
|
+
NoBotForApplication = Code(50_010)
|
|
209
|
+
|
|
210
|
+
# OAuth2 application limit reached
|
|
211
|
+
ApplicationLimitReached = Code(50_011)
|
|
212
|
+
|
|
213
|
+
# Invalid OAuth State
|
|
214
|
+
InvalidOAuthState = Code(50_012)
|
|
215
|
+
|
|
216
|
+
# Missing Permissions
|
|
217
|
+
MissingPermissions = Code(50_013)
|
|
218
|
+
|
|
219
|
+
# Invalid authentication token
|
|
220
|
+
InvalidAuthToken = Code(50_014)
|
|
221
|
+
|
|
222
|
+
# Note is too long
|
|
223
|
+
NoteTooLong = Code(50_015)
|
|
224
|
+
|
|
225
|
+
# Provided too few or too many messages to delete. Must provide at least 2 and fewer than 100 messages to delete.
|
|
226
|
+
InvalidBulkDeleteCount = Code(50_016)
|
|
227
|
+
|
|
228
|
+
# A message can only be pinned to the channel it was sent in
|
|
229
|
+
CannotPinInDifferentChannel = Code(50_019)
|
|
230
|
+
|
|
231
|
+
# Cannot execute action on a system message
|
|
232
|
+
InvalidActionForSystemMessage = Code(50_021)
|
|
233
|
+
|
|
234
|
+
# A message provided was too old to bulk delete
|
|
235
|
+
MessageTooOld = Code(50_034)
|
|
236
|
+
|
|
237
|
+
# Invalid Form Body
|
|
238
|
+
InvalidFormBody = Code(50_035)
|
|
239
|
+
|
|
240
|
+
# An invite was accepted to a guild the application's bot is not in
|
|
241
|
+
MissingBotMember = Code(50_036)
|
|
242
|
+
|
|
243
|
+
# Reaction Blocked
|
|
244
|
+
ReactionBlocked = Code(90_001)
|
|
245
|
+
end
|
|
246
|
+
end
|