discordrb 3.3.0 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +152 -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/codeql.yml +65 -0
- data/.markdownlint.json +4 -0
- data/.rubocop.yml +39 -36
- data/CHANGELOG.md +874 -552
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +80 -86
- data/Rakefile +2 -0
- data/bin/console +1 -0
- data/discordrb-webhooks.gemspec +9 -6
- data/discordrb.gemspec +21 -18
- data/lib/discordrb/allowed_mentions.rb +36 -0
- data/lib/discordrb/api/application.rb +202 -0
- data/lib/discordrb/api/channel.rb +236 -47
- data/lib/discordrb/api/interaction.rb +54 -0
- data/lib/discordrb/api/invite.rb +5 -5
- data/lib/discordrb/api/server.rb +94 -66
- data/lib/discordrb/api/user.rb +17 -11
- data/lib/discordrb/api/webhook.rb +63 -6
- data/lib/discordrb/api.rb +55 -16
- data/lib/discordrb/await.rb +0 -1
- data/lib/discordrb/bot.rb +480 -93
- data/lib/discordrb/cache.rb +31 -24
- data/lib/discordrb/colour_rgb.rb +43 -0
- data/lib/discordrb/commands/command_bot.rb +35 -12
- data/lib/discordrb/commands/container.rb +21 -24
- data/lib/discordrb/commands/parser.rb +20 -20
- data/lib/discordrb/commands/rate_limiter.rb +4 -3
- data/lib/discordrb/container.rb +209 -20
- data/lib/discordrb/data/activity.rb +271 -0
- data/lib/discordrb/data/application.rb +50 -0
- data/lib/discordrb/data/attachment.rb +71 -0
- data/lib/discordrb/data/audit_logs.rb +345 -0
- data/lib/discordrb/data/channel.rb +993 -0
- data/lib/discordrb/data/component.rb +229 -0
- data/lib/discordrb/data/embed.rb +251 -0
- data/lib/discordrb/data/emoji.rb +82 -0
- data/lib/discordrb/data/integration.rb +122 -0
- data/lib/discordrb/data/interaction.rb +800 -0
- data/lib/discordrb/data/invite.rb +137 -0
- data/lib/discordrb/data/member.rb +372 -0
- data/lib/discordrb/data/message.rb +414 -0
- data/lib/discordrb/data/overwrite.rb +108 -0
- data/lib/discordrb/data/profile.rb +91 -0
- data/lib/discordrb/data/reaction.rb +33 -0
- data/lib/discordrb/data/recipient.rb +34 -0
- data/lib/discordrb/data/role.rb +248 -0
- data/lib/discordrb/data/server.rb +1004 -0
- data/lib/discordrb/data/user.rb +264 -0
- data/lib/discordrb/data/voice_region.rb +45 -0
- data/lib/discordrb/data/voice_state.rb +41 -0
- data/lib/discordrb/data/webhook.rb +238 -0
- data/lib/discordrb/data.rb +28 -4180
- data/lib/discordrb/errors.rb +46 -4
- data/lib/discordrb/events/bans.rb +7 -5
- data/lib/discordrb/events/channels.rb +3 -1
- data/lib/discordrb/events/guilds.rb +16 -9
- data/lib/discordrb/events/interactions.rb +482 -0
- data/lib/discordrb/events/invites.rb +125 -0
- data/lib/discordrb/events/members.rb +6 -2
- data/lib/discordrb/events/message.rb +72 -27
- data/lib/discordrb/events/presence.rb +35 -18
- data/lib/discordrb/events/raw.rb +1 -3
- data/lib/discordrb/events/reactions.rb +49 -4
- data/lib/discordrb/events/threads.rb +96 -0
- data/lib/discordrb/events/typing.rb +6 -4
- data/lib/discordrb/events/voice_server_update.rb +47 -0
- data/lib/discordrb/events/voice_state_update.rb +15 -10
- data/lib/discordrb/events/webhooks.rb +9 -6
- data/lib/discordrb/gateway.rb +99 -71
- data/lib/discordrb/id_object.rb +39 -0
- data/lib/discordrb/light/integrations.rb +1 -1
- data/lib/discordrb/light/light_bot.rb +1 -1
- data/lib/discordrb/logger.rb +4 -4
- data/lib/discordrb/paginator.rb +57 -0
- data/lib/discordrb/permissions.rb +159 -39
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +16 -7
- data/lib/discordrb/voice/network.rb +99 -47
- data/lib/discordrb/voice/sodium.rb +98 -0
- data/lib/discordrb/voice/voice_bot.rb +33 -25
- data/lib/discordrb/webhooks.rb +2 -0
- data/lib/discordrb.rb +107 -1
- metadata +126 -54
- data/.codeclimate.yml +0 -16
- data/.travis.yml +0 -33
- data/bin/travis_build_docs.sh +0 -17
- /data/{CONTRIBUTING.md → .github/CONTRIBUTING.md} +0 -0
@@ -0,0 +1,229 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discordrb
|
4
|
+
# Components are interactable interfaces that can be attached to messages.
|
5
|
+
module Components
|
6
|
+
# @deprecated This alias will be removed in future releases.
|
7
|
+
class View < Webhooks::View
|
8
|
+
end
|
9
|
+
|
10
|
+
# @!visibility private
|
11
|
+
def self.from_data(data, bot)
|
12
|
+
case data['type']
|
13
|
+
when Webhooks::View::COMPONENT_TYPES[:action_row]
|
14
|
+
ActionRow.new(data, bot)
|
15
|
+
when Webhooks::View::COMPONENT_TYPES[:button]
|
16
|
+
Button.new(data, bot)
|
17
|
+
when Webhooks::View::COMPONENT_TYPES[:string_select]
|
18
|
+
SelectMenu.new(data, bot)
|
19
|
+
when Webhooks::Modal::COMPONENT_TYPES[:text_input]
|
20
|
+
TextInput.new(data, bot)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Represents a row of components
|
25
|
+
class ActionRow
|
26
|
+
include Enumerable
|
27
|
+
|
28
|
+
# @return [Array<Button>]
|
29
|
+
attr_reader :components
|
30
|
+
|
31
|
+
# @!visibility private
|
32
|
+
def initialize(data, bot)
|
33
|
+
@bot = bot
|
34
|
+
@components = data['components'].map { |component_data| Components.from_data(component_data, @bot) }
|
35
|
+
end
|
36
|
+
|
37
|
+
# Iterate over each component in the row.
|
38
|
+
def each(&block)
|
39
|
+
@components.each(&block)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Get all buttons in this row
|
43
|
+
# @return [Array<Button>]
|
44
|
+
def buttons
|
45
|
+
select { |component| component.is_a? Button }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Get all buttons in this row
|
49
|
+
# @return [Array<Button>]
|
50
|
+
def text_inputs
|
51
|
+
select { |component| component.is_a? TextInput }
|
52
|
+
end
|
53
|
+
|
54
|
+
# @!visibility private
|
55
|
+
def to_a
|
56
|
+
@components
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# An interactable button component.
|
61
|
+
class Button
|
62
|
+
# @return [String]
|
63
|
+
attr_reader :label
|
64
|
+
|
65
|
+
# @return [Integer]
|
66
|
+
attr_reader :style
|
67
|
+
|
68
|
+
# @return [String]
|
69
|
+
attr_reader :custom_id
|
70
|
+
|
71
|
+
# @return [true, false]
|
72
|
+
attr_reader :disabled
|
73
|
+
|
74
|
+
# @return [String, nil]
|
75
|
+
attr_reader :url
|
76
|
+
|
77
|
+
# @return [Emoji, nil]
|
78
|
+
attr_reader :emoji
|
79
|
+
|
80
|
+
# @!visibility private
|
81
|
+
def initialize(data, bot)
|
82
|
+
@bot = bot
|
83
|
+
|
84
|
+
@label = data['label']
|
85
|
+
@style = data['style']
|
86
|
+
@custom_id = data['custom_id']
|
87
|
+
@disabled = data['disabled']
|
88
|
+
@url = data['url']
|
89
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
90
|
+
end
|
91
|
+
|
92
|
+
# @method primary?
|
93
|
+
# @return [true, false]
|
94
|
+
# @method secondary?
|
95
|
+
# @return [true, false]
|
96
|
+
# @method success?
|
97
|
+
# @return [true, false]
|
98
|
+
# @method danger?
|
99
|
+
# @return [true, false]
|
100
|
+
# @method link?
|
101
|
+
# @return [true, false]
|
102
|
+
Webhooks::View::BUTTON_STYLES.each do |name, value|
|
103
|
+
define_method("#{name}?") do
|
104
|
+
@style == value
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Await a button click
|
109
|
+
def await_click(key, **attributes, &block)
|
110
|
+
@bot.add_await(key, Discordrb::Events::ButtonEvent, { custom_id: @custom_id }.merge(attributes), &block)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Await a button click, blocking.
|
114
|
+
def await_click!(**attributes, &block)
|
115
|
+
@bot.add_await!(Discordrb::Events::ButtonEvent, { custom_id: @custom_id }.merge(attributes), &block)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# An interactable select menu component.
|
120
|
+
class SelectMenu
|
121
|
+
# A select menu option.
|
122
|
+
class Option
|
123
|
+
# @return [String]
|
124
|
+
attr_reader :label
|
125
|
+
|
126
|
+
# @return [String]
|
127
|
+
attr_reader :value
|
128
|
+
|
129
|
+
# @return [String, nil]
|
130
|
+
attr_reader :description
|
131
|
+
|
132
|
+
# @return [Emoji, nil]
|
133
|
+
attr_reader :emoji
|
134
|
+
|
135
|
+
# @!visibility hidden
|
136
|
+
def initialize(data)
|
137
|
+
@label = data['label']
|
138
|
+
@value = data['value']
|
139
|
+
@description = data['description']
|
140
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# @return [String]
|
145
|
+
attr_reader :custom_id
|
146
|
+
|
147
|
+
# @return [Integer, nil]
|
148
|
+
attr_reader :max_values
|
149
|
+
|
150
|
+
# @return [Integer, nil]
|
151
|
+
attr_reader :min_values
|
152
|
+
|
153
|
+
# @return [String, nil]
|
154
|
+
attr_reader :placeholder
|
155
|
+
|
156
|
+
# @return [Array<Option>]
|
157
|
+
attr_reader :options
|
158
|
+
|
159
|
+
# @!visibility private
|
160
|
+
def initialize(data, bot)
|
161
|
+
@bot = bot
|
162
|
+
|
163
|
+
@max_values = data['max_values']
|
164
|
+
@min_values = data['min_values']
|
165
|
+
@placeholder = data['placeholder']
|
166
|
+
@custom_id = data['custom_id']
|
167
|
+
@emoji = Emoji.new(data['emoji'], @bot) if data['emoji']
|
168
|
+
@options = data['options'].map { |opt| Option.new(opt) }
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Text input component for use in modals. Can be either a line (`short`), or a multi line (`paragraph`) block.
|
173
|
+
class TextInput
|
174
|
+
# Single line text input
|
175
|
+
SHORT = 1
|
176
|
+
# Multi-line text input
|
177
|
+
PARAGRAPH = 2
|
178
|
+
|
179
|
+
# @return [String]
|
180
|
+
attr_reader :custom_id
|
181
|
+
|
182
|
+
# @return [Symbol]
|
183
|
+
attr_reader :style
|
184
|
+
|
185
|
+
# @return [String]
|
186
|
+
attr_reader :label
|
187
|
+
|
188
|
+
# @return [Integer, nil]
|
189
|
+
attr_reader :min_length
|
190
|
+
|
191
|
+
# @return [Integer, nil]
|
192
|
+
attr_reader :max_length
|
193
|
+
|
194
|
+
# @return [true, false]
|
195
|
+
attr_reader :required
|
196
|
+
|
197
|
+
# @return [String, nil]
|
198
|
+
attr_reader :value
|
199
|
+
|
200
|
+
# @return [String, nil]
|
201
|
+
attr_reader :placeholder
|
202
|
+
|
203
|
+
# @!visibility private
|
204
|
+
def initialize(data, bot)
|
205
|
+
@bot = bot
|
206
|
+
@style = data['style'] == SHORT ? :short : :paragraph
|
207
|
+
@label = data['label']
|
208
|
+
@min_length = data['min_length']
|
209
|
+
@max_length = data['max_length']
|
210
|
+
@required = data['required']
|
211
|
+
@value = data['value']
|
212
|
+
@placeholder = data['placeholder']
|
213
|
+
@custom_id = data['custom_id']
|
214
|
+
end
|
215
|
+
|
216
|
+
def short?
|
217
|
+
@style == :short
|
218
|
+
end
|
219
|
+
|
220
|
+
def paragraph?
|
221
|
+
@style == :paragraph
|
222
|
+
end
|
223
|
+
|
224
|
+
def required?
|
225
|
+
@required
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discordrb
|
4
|
+
# An Embed object that is contained in a message
|
5
|
+
# A freshly generated embed object will not appear in a message object
|
6
|
+
# unless grabbed from its ID in a channel.
|
7
|
+
class Embed
|
8
|
+
# @return [Message] the message this embed object is contained in.
|
9
|
+
attr_reader :message
|
10
|
+
|
11
|
+
# @return [String] the URL this embed object is based on.
|
12
|
+
attr_reader :url
|
13
|
+
|
14
|
+
# @return [String, nil] the title of the embed object. `nil` if there is not a title
|
15
|
+
attr_reader :title
|
16
|
+
|
17
|
+
# @return [String, nil] the description of the embed object. `nil` if there is not a description
|
18
|
+
attr_reader :description
|
19
|
+
|
20
|
+
# @return [Symbol] the type of the embed object. Possible types are:
|
21
|
+
#
|
22
|
+
# * `:link`
|
23
|
+
# * `:video`
|
24
|
+
# * `:image`
|
25
|
+
attr_reader :type
|
26
|
+
|
27
|
+
# @return [Time, nil] the timestamp of the embed object. `nil` if there is not a timestamp
|
28
|
+
attr_reader :timestamp
|
29
|
+
|
30
|
+
# @return [String, nil] the color of the embed object. `nil` if there is not a color
|
31
|
+
attr_reader :color
|
32
|
+
alias_method :colour, :color
|
33
|
+
|
34
|
+
# @return [EmbedFooter, nil] the footer of the embed object. `nil` if there is not a footer
|
35
|
+
attr_reader :footer
|
36
|
+
|
37
|
+
# @return [EmbedProvider, nil] the provider of the embed object. `nil` if there is not a provider
|
38
|
+
attr_reader :provider
|
39
|
+
|
40
|
+
# @return [EmbedImage, nil] the image of the embed object. `nil` if there is not an image
|
41
|
+
attr_reader :image
|
42
|
+
|
43
|
+
# @return [EmbedThumbnail, nil] the thumbnail of the embed object. `nil` if there is not a thumbnail
|
44
|
+
attr_reader :thumbnail
|
45
|
+
|
46
|
+
# @return [EmbedVideo, nil] the video of the embed object. `nil` if there is not a video
|
47
|
+
attr_reader :video
|
48
|
+
|
49
|
+
# @return [EmbedAuthor, nil] the author of the embed object. `nil` if there is not an author
|
50
|
+
attr_reader :author
|
51
|
+
|
52
|
+
# @return [Array<EmbedField>, nil] the fields of the embed object. `nil` if there are no fields
|
53
|
+
attr_reader :fields
|
54
|
+
|
55
|
+
# @!visibility private
|
56
|
+
def initialize(data, message)
|
57
|
+
@message = message
|
58
|
+
|
59
|
+
@url = data['url']
|
60
|
+
@title = data['title']
|
61
|
+
@type = data['type'].to_sym
|
62
|
+
@description = data['description']
|
63
|
+
@timestamp = data['timestamp'].nil? ? nil : Time.parse(data['timestamp'])
|
64
|
+
@color = data['color']
|
65
|
+
@footer = data['footer'].nil? ? nil : EmbedFooter.new(data['footer'], self)
|
66
|
+
@image = data['image'].nil? ? nil : EmbedImage.new(data['image'], self)
|
67
|
+
@video = data['video'].nil? ? nil : EmbedVideo.new(data['video'], self)
|
68
|
+
@provider = data['provider'].nil? ? nil : EmbedProvider.new(data['provider'], self)
|
69
|
+
@thumbnail = data['thumbnail'].nil? ? nil : EmbedThumbnail.new(data['thumbnail'], self)
|
70
|
+
@author = data['author'].nil? ? nil : EmbedAuthor.new(data['author'], self)
|
71
|
+
@fields = data['fields'].nil? ? nil : data['fields'].map { |field| EmbedField.new(field, self) }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# An Embed footer for the embed object.
|
76
|
+
class EmbedFooter
|
77
|
+
# @return [Embed] the embed object this is based on.
|
78
|
+
attr_reader :embed
|
79
|
+
|
80
|
+
# @return [String] the footer text.
|
81
|
+
attr_reader :text
|
82
|
+
|
83
|
+
# @return [String] the URL of the footer icon.
|
84
|
+
attr_reader :icon_url
|
85
|
+
|
86
|
+
# @return [String] the proxied URL of the footer icon.
|
87
|
+
attr_reader :proxy_icon_url
|
88
|
+
|
89
|
+
# @!visibility private
|
90
|
+
def initialize(data, embed)
|
91
|
+
@embed = embed
|
92
|
+
|
93
|
+
@text = data['text']
|
94
|
+
@icon_url = data['icon_url']
|
95
|
+
@proxy_icon_url = data['proxy_icon_url']
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# An Embed image for the embed object.
|
100
|
+
class EmbedImage
|
101
|
+
# @return [Embed] the embed object this is based on.
|
102
|
+
attr_reader :embed
|
103
|
+
|
104
|
+
# @return [String] the source URL of the image.
|
105
|
+
attr_reader :url
|
106
|
+
|
107
|
+
# @return [String] the proxy URL of the image.
|
108
|
+
attr_reader :proxy_url
|
109
|
+
|
110
|
+
# @return [Integer] the width of the image, in pixels.
|
111
|
+
attr_reader :width
|
112
|
+
|
113
|
+
# @return [Integer] the height of the image, in pixels.
|
114
|
+
attr_reader :height
|
115
|
+
|
116
|
+
# @!visibility private
|
117
|
+
def initialize(data, embed)
|
118
|
+
@embed = embed
|
119
|
+
|
120
|
+
@url = data['url']
|
121
|
+
@proxy_url = data['proxy_url']
|
122
|
+
@width = data['width']
|
123
|
+
@height = data['height']
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# An Embed video for the embed object
|
128
|
+
class EmbedVideo
|
129
|
+
# @return [Embed] the embed object this is based on.
|
130
|
+
attr_reader :embed
|
131
|
+
|
132
|
+
# @return [String] the source URL of the video.
|
133
|
+
attr_reader :url
|
134
|
+
|
135
|
+
# @return [Integer] the width of the video, in pixels.
|
136
|
+
attr_reader :width
|
137
|
+
|
138
|
+
# @return [Integer] the height of the video, in pixels.
|
139
|
+
attr_reader :height
|
140
|
+
|
141
|
+
# @!visibility private
|
142
|
+
def initialize(data, embed)
|
143
|
+
@embed = embed
|
144
|
+
|
145
|
+
@url = data['url']
|
146
|
+
@width = data['width']
|
147
|
+
@height = data['height']
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# An Embed thumbnail for the embed object
|
152
|
+
class EmbedThumbnail
|
153
|
+
# @return [Embed] the embed object this is based on.
|
154
|
+
attr_reader :embed
|
155
|
+
|
156
|
+
# @return [String] the CDN URL this thumbnail can be downloaded at.
|
157
|
+
attr_reader :url
|
158
|
+
|
159
|
+
# @return [String] the thumbnail's proxy URL - I'm not sure what exactly this does, but I think it has something to
|
160
|
+
# do with CDNs.
|
161
|
+
attr_reader :proxy_url
|
162
|
+
|
163
|
+
# @return [Integer] the width of this thumbnail file, in pixels.
|
164
|
+
attr_reader :width
|
165
|
+
|
166
|
+
# @return [Integer] the height of this thumbnail file, in pixels.
|
167
|
+
attr_reader :height
|
168
|
+
|
169
|
+
# @!visibility private
|
170
|
+
def initialize(data, embed)
|
171
|
+
@embed = embed
|
172
|
+
|
173
|
+
@url = data['url']
|
174
|
+
@proxy_url = data['proxy_url']
|
175
|
+
@width = data['width']
|
176
|
+
@height = data['height']
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# An Embed provider for the embed object
|
181
|
+
class EmbedProvider
|
182
|
+
# @return [Embed] the embed object this is based on.
|
183
|
+
attr_reader :embed
|
184
|
+
|
185
|
+
# @return [String] the provider's name.
|
186
|
+
attr_reader :name
|
187
|
+
|
188
|
+
# @return [String, nil] the URL of the provider, or `nil` if there is no URL.
|
189
|
+
attr_reader :url
|
190
|
+
|
191
|
+
# @!visibility private
|
192
|
+
def initialize(data, embed)
|
193
|
+
@embed = embed
|
194
|
+
|
195
|
+
@name = data['name']
|
196
|
+
@url = data['url']
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# An Embed author for the embed object
|
201
|
+
class EmbedAuthor
|
202
|
+
# @return [Embed] the embed object this is based on.
|
203
|
+
attr_reader :embed
|
204
|
+
|
205
|
+
# @return [String] the author's name.
|
206
|
+
attr_reader :name
|
207
|
+
|
208
|
+
# @return [String, nil] the URL of the author's website, or `nil` if there is no URL.
|
209
|
+
attr_reader :url
|
210
|
+
|
211
|
+
# @return [String, nil] the icon of the author, or `nil` if there is no icon.
|
212
|
+
attr_reader :icon_url
|
213
|
+
|
214
|
+
# @return [String, nil] the Discord proxy URL, or `nil` if there is no `icon_url`.
|
215
|
+
attr_reader :proxy_icon_url
|
216
|
+
|
217
|
+
# @!visibility private
|
218
|
+
def initialize(data, embed)
|
219
|
+
@embed = embed
|
220
|
+
|
221
|
+
@name = data['name']
|
222
|
+
@url = data['url']
|
223
|
+
@icon_url = data['icon_url']
|
224
|
+
@proxy_icon_url = data['proxy_icon_url']
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# An Embed field for the embed object
|
229
|
+
class EmbedField
|
230
|
+
# @return [Embed] the embed object this is based on.
|
231
|
+
attr_reader :embed
|
232
|
+
|
233
|
+
# @return [String] the field's name.
|
234
|
+
attr_reader :name
|
235
|
+
|
236
|
+
# @return [String] the field's value.
|
237
|
+
attr_reader :value
|
238
|
+
|
239
|
+
# @return [true, false] whether this field is inline.
|
240
|
+
attr_reader :inline
|
241
|
+
|
242
|
+
# @!visibility private
|
243
|
+
def initialize(data, embed)
|
244
|
+
@embed = embed
|
245
|
+
|
246
|
+
@name = data['name']
|
247
|
+
@value = data['value']
|
248
|
+
@inline = data['inline']
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discordrb
|
4
|
+
# Server emoji
|
5
|
+
class Emoji
|
6
|
+
include IDObject
|
7
|
+
|
8
|
+
# @return [String] the emoji name
|
9
|
+
attr_reader :name
|
10
|
+
|
11
|
+
# @return [Server, nil] the server of this emoji
|
12
|
+
attr_reader :server
|
13
|
+
|
14
|
+
# @return [Array<Role>, nil] roles this emoji is active for, or nil if the emoji's server is unknown
|
15
|
+
attr_reader :roles
|
16
|
+
|
17
|
+
# @return [true, false] if the emoji is animated
|
18
|
+
attr_reader :animated
|
19
|
+
alias_method :animated?, :animated
|
20
|
+
|
21
|
+
# @!visibility private
|
22
|
+
def initialize(data, bot, server = nil)
|
23
|
+
@bot = bot
|
24
|
+
@roles = nil
|
25
|
+
|
26
|
+
@name = data['name']
|
27
|
+
@server = server
|
28
|
+
@id = data['id'].nil? ? nil : data['id'].to_i
|
29
|
+
@animated = data['animated']
|
30
|
+
|
31
|
+
process_roles(data['roles']) if server
|
32
|
+
end
|
33
|
+
|
34
|
+
# ID or name based comparison
|
35
|
+
def ==(other)
|
36
|
+
return false unless other.is_a? Emoji
|
37
|
+
return Discordrb.id_compare(@id, other) if @id
|
38
|
+
|
39
|
+
name == other.name
|
40
|
+
end
|
41
|
+
|
42
|
+
alias_method :eql?, :==
|
43
|
+
|
44
|
+
# @return [String] the layout to mention it (or have it used) in a message
|
45
|
+
def mention
|
46
|
+
return name if id.nil?
|
47
|
+
|
48
|
+
"<#{'a' if animated}:#{name}:#{id}>"
|
49
|
+
end
|
50
|
+
|
51
|
+
alias_method :use, :mention
|
52
|
+
alias_method :to_s, :mention
|
53
|
+
|
54
|
+
# @return [String] the layout to use this emoji in a reaction
|
55
|
+
def to_reaction
|
56
|
+
return name if id.nil?
|
57
|
+
|
58
|
+
"#{name}:#{id}"
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String] the icon URL of the emoji
|
62
|
+
def icon_url
|
63
|
+
API.emoji_icon_url(id)
|
64
|
+
end
|
65
|
+
|
66
|
+
# The inspect method is overwritten to give more useful output
|
67
|
+
def inspect
|
68
|
+
"<Emoji name=#{name} id=#{id} animated=#{animated}>"
|
69
|
+
end
|
70
|
+
|
71
|
+
# @!visibility private
|
72
|
+
def process_roles(roles)
|
73
|
+
@roles = []
|
74
|
+
return unless roles
|
75
|
+
|
76
|
+
roles.each do |role_id|
|
77
|
+
role = server.role(role_id)
|
78
|
+
@roles << role
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Discordrb
|
4
|
+
# Integration Account
|
5
|
+
class IntegrationAccount
|
6
|
+
# @return [String] this account's name.
|
7
|
+
attr_reader :name
|
8
|
+
|
9
|
+
# @return [Integer] this account's ID.
|
10
|
+
attr_reader :id
|
11
|
+
|
12
|
+
def initialize(data)
|
13
|
+
@name = data['name']
|
14
|
+
@id = data['id'].to_i
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Bot/OAuth2 application for discord integrations
|
19
|
+
class IntegrationApplication
|
20
|
+
# @return [Integer] the ID of the application.
|
21
|
+
attr_reader :id
|
22
|
+
|
23
|
+
# @return [String] the name of the application.
|
24
|
+
attr_reader :name
|
25
|
+
|
26
|
+
# @return [String, nil] the icon hash of the application.
|
27
|
+
attr_reader :icon
|
28
|
+
|
29
|
+
# @return [String] the description of the application.
|
30
|
+
attr_reader :description
|
31
|
+
|
32
|
+
# @return [String] the summary of the application.
|
33
|
+
attr_reader :summary
|
34
|
+
|
35
|
+
# @return [User, nil] the bot associated with this application.
|
36
|
+
attr_reader :bot
|
37
|
+
|
38
|
+
def initialize(data, bot)
|
39
|
+
@id = data['id'].to_i
|
40
|
+
@name = data['name']
|
41
|
+
@icon = data['icon']
|
42
|
+
@description = data['description']
|
43
|
+
@summary = data['summary']
|
44
|
+
@bot = Discordrb::User.new(data['user'], bot) if data['user']
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Server integration
|
49
|
+
class Integration
|
50
|
+
include IDObject
|
51
|
+
|
52
|
+
# @return [String] the integration name
|
53
|
+
attr_reader :name
|
54
|
+
|
55
|
+
# @return [Server] the server the integration is linked to
|
56
|
+
attr_reader :server
|
57
|
+
|
58
|
+
# @return [User] the user the integration is linked to
|
59
|
+
attr_reader :user
|
60
|
+
|
61
|
+
# @return [Integer, nil] the role that this integration uses for "subscribers"
|
62
|
+
attr_reader :role_id
|
63
|
+
|
64
|
+
# @return [true, false] whether emoticons are enabled
|
65
|
+
attr_reader :emoticon
|
66
|
+
alias_method :emoticon?, :emoticon
|
67
|
+
|
68
|
+
# @return [String] the integration type (YouTube, Twitch, etc.)
|
69
|
+
attr_reader :type
|
70
|
+
|
71
|
+
# @return [true, false] whether the integration is enabled
|
72
|
+
attr_reader :enabled
|
73
|
+
|
74
|
+
# @return [true, false] whether the integration is syncing
|
75
|
+
attr_reader :syncing
|
76
|
+
|
77
|
+
# @return [IntegrationAccount] the integration account information
|
78
|
+
attr_reader :account
|
79
|
+
|
80
|
+
# @return [Time] the time the integration was synced at
|
81
|
+
attr_reader :synced_at
|
82
|
+
|
83
|
+
# @return [Symbol] the behaviour of expiring subscribers (:remove = Remove User from role; :kick = Kick User from server)
|
84
|
+
attr_reader :expire_behaviour
|
85
|
+
alias_method :expire_behavior, :expire_behaviour
|
86
|
+
|
87
|
+
# @return [Integer] the grace period before subscribers expire (in days)
|
88
|
+
attr_reader :expire_grace_period
|
89
|
+
|
90
|
+
# @return [Integer, nil] how many subscribers this integration has.
|
91
|
+
attr_reader :subscriber_count
|
92
|
+
|
93
|
+
# @return [true, false] has this integration been revoked.
|
94
|
+
attr_reader :revoked
|
95
|
+
|
96
|
+
def initialize(data, bot, server)
|
97
|
+
@bot = bot
|
98
|
+
|
99
|
+
@name = data['name']
|
100
|
+
@server = server
|
101
|
+
@id = data['id'].to_i
|
102
|
+
@enabled = data['enabled']
|
103
|
+
@syncing = data['syncing']
|
104
|
+
@type = data['type']
|
105
|
+
@account = IntegrationAccount.new(data['account'])
|
106
|
+
@synced_at = Time.parse(data['synced_at'])
|
107
|
+
@expire_behaviour = %i[remove kick][data['expire_behavior']]
|
108
|
+
@expire_grace_period = data['expire_grace_period']
|
109
|
+
@user = @bot.ensure_user(data['user'])
|
110
|
+
@role_id = data['role_id']&.to_i
|
111
|
+
@emoticon = data['enable_emoticons']
|
112
|
+
@subscriber_count = data['subscriber_count']&.to_i
|
113
|
+
@revoked = data['revoked']
|
114
|
+
@application = IntegrationApplication.new(data['application'], bot) if data['application']
|
115
|
+
end
|
116
|
+
|
117
|
+
# The inspect method is overwritten to give more useful output
|
118
|
+
def inspect
|
119
|
+
"<Integration name=#{@name} id=#{@id} type=#{@type} enabled=#{@enabled}>"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|