discorb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +56 -0
  3. data/.yardopts +6 -0
  4. data/Changelog.md +5 -0
  5. data/Gemfile +23 -0
  6. data/Gemfile.lock +70 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +53 -0
  9. data/Rakefile +46 -0
  10. data/bin/console +15 -0
  11. data/bin/setup +8 -0
  12. data/discorb.gemspec +37 -0
  13. data/docs/Examples.md +26 -0
  14. data/docs/events.md +480 -0
  15. data/docs/voice_events.md +283 -0
  16. data/examples/components/authorization_button.rb +43 -0
  17. data/examples/components/select_menu.rb +61 -0
  18. data/examples/extension/main.rb +12 -0
  19. data/examples/extension/message_expander.rb +41 -0
  20. data/examples/simple/eval.rb +32 -0
  21. data/examples/simple/ping_pong.rb +16 -0
  22. data/examples/simple/rolepanel.rb +65 -0
  23. data/examples/simple/wait_for_message.rb +30 -0
  24. data/lib/discorb/application.rb +157 -0
  25. data/lib/discorb/asset.rb +57 -0
  26. data/lib/discorb/audit_logs.rb +323 -0
  27. data/lib/discorb/channel.rb +1101 -0
  28. data/lib/discorb/client.rb +363 -0
  29. data/lib/discorb/color.rb +173 -0
  30. data/lib/discorb/common.rb +123 -0
  31. data/lib/discorb/components.rb +290 -0
  32. data/lib/discorb/dictionary.rb +119 -0
  33. data/lib/discorb/embed.rb +345 -0
  34. data/lib/discorb/emoji.rb +218 -0
  35. data/lib/discorb/emoji_table.rb +3799 -0
  36. data/lib/discorb/error.rb +98 -0
  37. data/lib/discorb/event.rb +35 -0
  38. data/lib/discorb/extend.rb +18 -0
  39. data/lib/discorb/extension.rb +54 -0
  40. data/lib/discorb/file.rb +69 -0
  41. data/lib/discorb/flag.rb +109 -0
  42. data/lib/discorb/gateway.rb +967 -0
  43. data/lib/discorb/gateway_requests.rb +47 -0
  44. data/lib/discorb/guild.rb +1244 -0
  45. data/lib/discorb/guild_template.rb +211 -0
  46. data/lib/discorb/image.rb +43 -0
  47. data/lib/discorb/integration.rb +111 -0
  48. data/lib/discorb/intents.rb +137 -0
  49. data/lib/discorb/interaction.rb +333 -0
  50. data/lib/discorb/internet.rb +285 -0
  51. data/lib/discorb/invite.rb +145 -0
  52. data/lib/discorb/log.rb +70 -0
  53. data/lib/discorb/member.rb +232 -0
  54. data/lib/discorb/message.rb +583 -0
  55. data/lib/discorb/modules.rb +138 -0
  56. data/lib/discorb/permission.rb +270 -0
  57. data/lib/discorb/presence.rb +308 -0
  58. data/lib/discorb/reaction.rb +48 -0
  59. data/lib/discorb/role.rb +189 -0
  60. data/lib/discorb/sticker.rb +157 -0
  61. data/lib/discorb/user.rb +163 -0
  62. data/lib/discorb/utils.rb +16 -0
  63. data/lib/discorb/voice_state.rb +251 -0
  64. data/lib/discorb/webhook.rb +420 -0
  65. data/lib/discorb.rb +51 -0
  66. metadata +120 -0
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Module for sending and reading messages.
6
+ #
7
+ module Messageable
8
+ #
9
+ # Post a message to the channel.
10
+ #
11
+ # @param [String] content The message content.
12
+ # @param [Boolean] tts Whether the message is tts.
13
+ # @param [Discorb::Embed] embed The embed to send.
14
+ # @param [Array<Discorb::Embed>] embeds The embeds to send.
15
+ # @param [Discorb::AllowedMentions] allowed_mentions The allowed mentions.
16
+ # @param [Discorb::Message, Discorb::Message::Reference] reference The message to reply to.
17
+ # @param [Array<Discorb::Components>, Array<Array<Discorb::Components>>] components The components to send.
18
+ # @param [Discorb::File] file The file to send.
19
+ # @param [Array<Discorb::File>] files The files to send.
20
+ #
21
+ # @return [Discorb::Message] The message sent.
22
+ #
23
+ def post(content = nil, tts: false, embed: nil, embeds: nil, allowed_mentions: nil,
24
+ reference: nil, components: nil, file: nil, files: nil)
25
+ Async do |_task|
26
+ payload = {}
27
+ payload[:content] = content if content
28
+ payload[:tts] = tts
29
+ tmp_embed = if embed
30
+ [embed]
31
+ elsif embeds
32
+ embeds
33
+ end
34
+ payload[:embeds] = tmp_embed.map(&:to_hash) if tmp_embed
35
+ payload[:allowed_mentions] =
36
+ allowed_mentions ? allowed_mentions.to_hash(@client.allowed_mentions) : @client.allowed_mentions.to_hash
37
+ payload[:message_reference] = reference.to_reference if reference
38
+ if components
39
+ tmp_components = []
40
+ tmp_row = []
41
+ components.each do |c|
42
+ case c
43
+ when Array
44
+ tmp_components << tmp_row
45
+ tmp_row = []
46
+ tmp_components << c
47
+ when SelectMenu
48
+ tmp_components << tmp_row
49
+ tmp_row = []
50
+ tmp_components << [c]
51
+ else
52
+ tmp_row << c
53
+ end
54
+ end
55
+ tmp_components << tmp_row
56
+ payload[:components] = tmp_components.filter { |c| c.length.positive? }.map { |c| { type: 1, components: c.map(&:to_hash) } }
57
+ end
58
+ files = [file] if file
59
+ if files
60
+ headers, payload = Internet.multipart(payload, files)
61
+ else
62
+ headers = {}
63
+ end
64
+ _resp, data = @client.internet.post("#{base_url.wait}/messages", payload, headers: headers).wait
65
+ Message.new(@client, data.merge({ guild_id: @guild_id.to_s }))
66
+ end
67
+ end
68
+
69
+ #
70
+ # Fetch a message from ID.
71
+ #
72
+ # @param [Discorb::Snowflake] id The ID of the message.
73
+ #
74
+ # @return [Discorb::Message] The message.
75
+ # @raise [Discorb::NotFoundError] If the message is not found.
76
+ #
77
+ def fetch_message(id)
78
+ Async do
79
+ _resp, data = @client.internet.get("#{base_url.wait}/messages/#{id}").wait
80
+ Message.new(@client, data.merge({ guild_id: @guild_id.to_s }))
81
+ end
82
+ end
83
+
84
+ #
85
+ # Fetch a message history.
86
+ #
87
+ # @param [Integer] limit The number of messages to fetch.
88
+ # @param [Discorb::Snowflake] before The ID of the message to fetch before.
89
+ # @param [Discorb::Snowflake] after The ID of the message to fetch after.
90
+ # @param [Discorb::Snowflake] around The ID of the message to fetch around.
91
+ #
92
+ # @return [Array<Discorb::Message>] The messages.
93
+ #
94
+ def fetch_messages(limit = 50, before: nil, after: nil, around: nil)
95
+ Async do
96
+ params = {
97
+ limit: limit,
98
+ before: Discorb::Utils.try(after, :id),
99
+ after: Discorb::Utils.try(around, :id),
100
+ around: Discorb::Utils.try(before, :id),
101
+ }.filter { |_k, v| !v.nil? }.to_h
102
+ _resp, messages = @client.internet.get("#{base_url.wait}/messages?#{URI.encode_www_form(params)}").wait
103
+ messages.map { |m| Message.new(@client, m.merge({ guild_id: @guild_id.to_s })) }
104
+ end
105
+ end
106
+
107
+ #
108
+ # Trigger the typing indicator in the channel.
109
+ # @macro async
110
+ # @macro http
111
+ #
112
+ # If block is given, trigger typing indicator during executing block.
113
+ # @example
114
+ # channel.typing do
115
+ # channel.post("Waiting for 60 seconds...")
116
+ # sleep 60
117
+ # channel.post("Done!")
118
+ # end
119
+ #
120
+ def typing
121
+ Async do |task|
122
+ if block_given?
123
+ begin
124
+ post_task = task.async do
125
+ @client.internet.post("/channels/#{@id}/typing", {})
126
+ sleep(5)
127
+ end
128
+ yield
129
+ ensure
130
+ post_task.stop
131
+ end
132
+ else
133
+ @client.internet.post("/channels/#{@id}/typing", {})
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,270 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a permission per guild.
6
+ # ## Flag fields
7
+ # |`1 << 0`|`:create_instant_invite`|
8
+ # |`1 << 1`|`:kick_members`|
9
+ # |`1 << 2`|`:ban_members`|
10
+ # |`1 << 3`|`:administrator`|
11
+ # |`1 << 4`|`:manage_channels`|
12
+ # |`1 << 5`|`:manage_guild`|
13
+ # |`1 << 6`|`:add_reactions`|
14
+ # |`1 << 7`|`:view_audit_log`|
15
+ # |`1 << 8`|`:priority_speaker`|
16
+ # |`1 << 9`|`:stream`|
17
+ # |`1 << 10`|`:view_channel`|
18
+ # |`1 << 11`|`:send_messages`|
19
+ # |`1 << 12`|`:send_tts_messages`|
20
+ # |`1 << 13`|`:manage_messages`|
21
+ # |`1 << 14`|`:embed_links`|
22
+ # |`1 << 15`|`:attach_files`|
23
+ # |`1 << 16`|`:read_message_history`|
24
+ # |`1 << 17`|`:mention_everyone`|
25
+ # |`1 << 18`|`:use_external_emojis`|
26
+ # |`1 << 19`|`:view_guild_insights`|
27
+ # |`1 << 20`|`:connect`|
28
+ # |`1 << 21`|`:speak`|
29
+ # |`1 << 22`|`:mute_members`|
30
+ # |`1 << 23`|`:deafen_members`|
31
+ # |`1 << 24`|`:move_members`|
32
+ # |`1 << 25`|`:use_vad`|
33
+ # |`1 << 26`|`:change_nickname`|
34
+ # |`1 << 27`|`:manage_nicknames`|
35
+ # |`1 << 28`|`:manage_roles`|
36
+ # |`1 << 29`|`:manage_webhooks`|
37
+ # |`1 << 30`|`:manage_emojis`|
38
+ # |`1 << 31`|`:use_slash_commands`|
39
+ # |`1 << 32`|`:request_to_speak`|
40
+ # |`1 << 34`|`:manage_threads`|
41
+ # |`1 << 35`|`:use_public_threads`|
42
+ # |`1 << 36`|`:use_private_threads`|
43
+ #
44
+ class Permission < Flag
45
+ @bits = {
46
+ create_instant_invite: 0,
47
+ kick_members: 1,
48
+ ban_members: 2,
49
+ administrator: 3,
50
+ manage_channels: 4,
51
+ manage_guild: 5,
52
+ add_reactions: 6,
53
+ view_audit_log: 7,
54
+ priority_speaker: 8,
55
+ stream: 9,
56
+ view_channel: 10,
57
+ send_messages: 11,
58
+ send_tts_messages: 12,
59
+ manage_messages: 13,
60
+ embed_links: 14,
61
+ attach_files: 15,
62
+ read_message_history: 16,
63
+ mention_everyone: 17,
64
+ use_external_emojis: 18,
65
+ view_guild_insights: 19,
66
+ connect: 20,
67
+ speak: 21,
68
+ mute_members: 22,
69
+ deafen_members: 23,
70
+ move_members: 24,
71
+ use_vad: 25,
72
+ change_nickname: 26,
73
+ manage_nicknames: 27,
74
+ manage_roles: 28,
75
+ manage_webhooks: 29,
76
+ manage_emojis: 30,
77
+ use_slash_commands: 31,
78
+ request_to_speak: 32,
79
+ manage_threads: 34,
80
+ use_public_threads: 35,
81
+ use_private_threads: 36,
82
+ }.freeze
83
+ end
84
+
85
+ #
86
+ # Represents a permission per channel.
87
+ #
88
+ class PermissionOverwrite
89
+ # @!attribute [r] allow
90
+ # @return [Discorb::Permission] The allowed permissions.
91
+ # @!attribute [r] deny
92
+ # @return [Discorb::Permission] The denied permissions.
93
+ # @!attribute [r] allow_value
94
+ # @return [Integer] The allowed permissions as an integer.
95
+ # @!attribute [r] deny_value
96
+ # @return [Integer] The denied permissions as an integer.
97
+
98
+ @raw_bits = {
99
+ create_instant_invite: 0,
100
+ kick_members: 1,
101
+ ban_members: 2,
102
+ administrator: 3,
103
+ manage_channels: 4,
104
+ manage_guild: 5,
105
+ add_reactions: 6,
106
+ view_audit_log: 7,
107
+ priority_speaker: 8,
108
+ stream: 9,
109
+ view_channel: 10,
110
+ send_messages: 11,
111
+ send_tts_messages: 12,
112
+ manage_messages: 13,
113
+ embed_links: 14,
114
+ attach_files: 15,
115
+ read_message_history: 16,
116
+ mention_everyone: 17,
117
+ use_external_emojis: 18,
118
+ view_guild_insights: 19,
119
+ connect: 20,
120
+ speak: 21,
121
+ mute_members: 22,
122
+ deafen_members: 23,
123
+ move_members: 24,
124
+ use_vad: 25,
125
+ change_nickname: 26,
126
+ manage_nicknames: 27,
127
+ manage_roles: 28,
128
+ manage_webhooks: 29,
129
+ manage_emojis: 30,
130
+ use_slash_commands: 31,
131
+ request_to_speak: 32,
132
+ manage_threads: 34,
133
+ use_public_threads: 35,
134
+ use_private_threads: 36,
135
+ }.freeze
136
+ @bits = @raw_bits.transform_values { |v| 1 << v }.freeze
137
+
138
+ # @!visibility private
139
+ def initialize(allow, deny)
140
+ @allow = allow
141
+ @deny = deny
142
+ end
143
+
144
+ def allow
145
+ self.class.bits.keys.filter { |field| @allow & self.class.bits[field] != 0 }
146
+ end
147
+
148
+ alias +@ allow
149
+
150
+ def deny
151
+ self.class.bits.keys.filter { |field| @deny & self.class.bits[field] != 0 }
152
+ end
153
+
154
+ alias -@ deny
155
+
156
+ def allow_value
157
+ @allow
158
+ end
159
+
160
+ def deny_value
161
+ @deny
162
+ end
163
+
164
+ #
165
+ # Converts the permission overwrite to a hash.
166
+ #
167
+ # @return [Hash] The permission overwrite as a hash.
168
+ #
169
+ def to_hash
170
+ self.class.bits.keys.map do |field|
171
+ [field, if @allow & self.class.bits[field] != 0
172
+ true
173
+ elsif @deny & self.class.bits[method] != 0
174
+ false
175
+ end]
176
+ end.to_h
177
+ end
178
+
179
+ #
180
+ # Union of the permission overwrites.
181
+ #
182
+ # @param [Discorb::PermissionOverwrite] other The other permission overwrite.
183
+ #
184
+ # @return [Discorb::PermissionOverwrite] The union of the permission overwrites.
185
+ #
186
+ def +(other)
187
+ result = to_hash
188
+ self.class.bits.each_key do |field|
189
+ result[field] = other[field] unless other[field].nil?
190
+ end
191
+ self.class.from_hash(result)
192
+ end
193
+
194
+ #
195
+ # Returns whether overwrite of the given field.
196
+ #
197
+ # @param [Symbol] field The field to check.
198
+ #
199
+ # @return [true, false, nil] Whether the field is allowed, denied or not set.
200
+ #
201
+ def [](field)
202
+ if @allow & self.class.bits[field] != 0
203
+ true
204
+ elsif @deny & self.class.bits[field] != 0
205
+ false
206
+ end
207
+ end
208
+
209
+ #
210
+ # Sets the given field to the given value.
211
+ #
212
+ # @param [Symbol] key The field to set.
213
+ # @param [Boolean] bool The value to set.
214
+ #
215
+ def []=(key, bool)
216
+ case bool
217
+ when true
218
+ @allow |= self.class.bits[key]
219
+ @deny &= ~self.class.bits[key]
220
+ when false
221
+ @allow &= ~self.class.bits[key]
222
+ @deny |= self.class.bits[key]
223
+ else
224
+ @allow &= ~self.class.bits[key]
225
+ @deny &= ~self.class.bits[key]
226
+ end
227
+ end
228
+
229
+ def method_missing(method, bool = nil)
230
+ if self.class.bits.key?(method)
231
+ self[method]
232
+ elsif self.class.bits.key?(method.to_s.delete_suffix("=").to_sym)
233
+ key = method.to_s.delete_suffix("=").to_sym
234
+ self[key] = bool
235
+ else
236
+ super
237
+ end
238
+ end
239
+
240
+ def respond_to_missing?(method, _arg)
241
+ self.class.bits.key?(method.to_s.delete_suffix("=").to_sym) ? true : super
242
+ end
243
+
244
+ class << self
245
+ # @!visibility private
246
+ attr_reader :bits
247
+
248
+ #
249
+ # Initializes a permission overwrite from a hash.
250
+ #
251
+ # @param [Hash] hash The hash to initialize the permission overwrite from.
252
+ #
253
+ # @return [Discorb::PermissionOverwrite] The permission overwrite.
254
+ #
255
+ def from_hash(hash)
256
+ allow = 0
257
+ deny = 0
258
+ hash.filter { |k, v| self.class.bits.keys.include?(k) && [true, false].include?(v) }.each do |k, v|
259
+ if v
260
+ allow += self.class.bits[k]
261
+ else
262
+ deny += self.class.bits[k]
263
+ end
264
+ end
265
+
266
+ new(allow, deny)
267
+ end
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,308 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a presence of user.
6
+ #
7
+ class Presence < DiscordModel
8
+ # @return [:online, :idle, :dnd, :offline] The status of the user.
9
+ attr_reader :status
10
+ # @return [Array<Discorb::Presence::Activity>] The activities of the user.
11
+ attr_reader :activities
12
+ # @return [Discorb::Presence::ClientStatus] The client status of the user.
13
+ attr_reader :client_status
14
+
15
+ # @!attribute [r] user
16
+ # @return [Discorb::User] The user of the presence.
17
+ # @!attribute [r] guild
18
+ # @return [Discorb::Guild] The guild of the presence.
19
+ # @!attribute [r] activity
20
+ # @return [Discorb::Presence::Activity] The activity of the presence.
21
+
22
+ # @!visibility private
23
+ def initialize(client, data)
24
+ @client = client
25
+ @data = data
26
+ _set_data(data)
27
+ end
28
+
29
+ def user
30
+ @client.users[@user_id]
31
+ end
32
+
33
+ def guild
34
+ @client.guilds[@guild_id]
35
+ end
36
+
37
+ def activity
38
+ @activities[0]
39
+ end
40
+
41
+ def inspect
42
+ "#<#{self.class} @status=#{@status.inspect} @activity=#{activity.inspect}>"
43
+ end
44
+
45
+ #
46
+ # Represents an activity of a user.
47
+ #
48
+ class Activity < DiscordModel
49
+ # @return [String] The name of the activity.
50
+ attr_reader :name
51
+ # @return [:game, :streaming, :listening, :watching, :custom, :competing] The type of the activity.
52
+ attr_reader :type
53
+ # @return [String] The url of the activity.
54
+ attr_reader :url
55
+ # @return [Time] The time the activity was created.
56
+ attr_reader :created_at
57
+ alias started_at created_at
58
+ # @return [Discorb::Presence::Activity::Timestamps] The timestamps of the activity.
59
+ attr_reader :timestamps
60
+ # @return [Discorb::Snowflake] The application id of the activity.
61
+ attr_reader :application_id
62
+ # @return [String] The details of the activity.
63
+ attr_reader :details
64
+ # @return [String] The state of party.
65
+ attr_reader :state
66
+ # @return [Discorb::Emoji] The emoji of the activity.
67
+ attr_reader :emoji
68
+ # @return [Discorb::Presence::Activity::Party] The party of the activity.
69
+ # @return [nil] If the activity is not a party activity.
70
+ attr_reader :party
71
+ # @return [Discorb::Presence::Activity::Asset] The assets of the activity.
72
+ # @return [nil] If the activity has no assets.
73
+ attr_reader :assets
74
+ # @return [Discorb::StageInstance] The instance of the activity.
75
+ # @return [nil] If the activity is not a stage activity.
76
+ attr_reader :instance
77
+ # @return [Array<Discorb::Presence::Activity::Button>] The buttons of the activity.
78
+ # @return [nil] If the activity has no buttons.
79
+ attr_reader :buttons
80
+ # @return [Discorb::Presence::Activity::Flag] The flags of the activity.
81
+ attr_reader :flags
82
+
83
+ @activity_types = {
84
+ 0 => :game,
85
+ 1 => :streaming,
86
+ 2 => :listening,
87
+ 3 => :watching,
88
+ 4 => :custom,
89
+ 5 => :competing,
90
+ }
91
+
92
+ # @!visibility private
93
+ def initialize(data)
94
+ @name = data[:name]
95
+ @type = self.class.activity_types[data[:type]]
96
+ @url = data[:url]
97
+ @created_at = Time.at(data[:created_at])
98
+ @timestamps = data[:timestamps] && Timestamps.new(data[:timestamps])
99
+ @application_id = data[:application_id] && Snowflake.new(data[:application_id])
100
+ @details = data[:details]
101
+ @state = data[:state]
102
+ @emoji = if data[:emoji]
103
+ data[:emoji][:id].nil? ? UnicodeEmoji.new(data[:emoji][:name]) : PartialEmoji.new(data[:emoji])
104
+ end
105
+ @party = data[:party] && Party.new(data[:party])
106
+ @assets = data[:assets] && Asset.new(data[:assets])
107
+ @instance = data[:instance]
108
+ @buttons = data[:buttons] && data[:buttons].map { |b| Button.new(b) }
109
+ @flags = data[:flags] && Flag.new(data[:flags])
110
+ end
111
+
112
+ #
113
+ # Convert the activity to a string.
114
+ #
115
+ # @return [String] The string representation of the activity.
116
+ #
117
+ def to_s
118
+ case @type
119
+ when :game
120
+ "Playing #{@name}"
121
+ when :streaming
122
+ "Streaming #{@details}"
123
+ when :listening
124
+ "Listening to #{@name}"
125
+ when :watching
126
+ "Watching #{@name}"
127
+ when :custom
128
+ "#{@emoji} #{@state}"
129
+ when :competing
130
+ "Competing in #{@name}"
131
+ end
132
+ end
133
+
134
+ #
135
+ # Represents the timestamps of an activity.
136
+ #
137
+ class Timestamps < DiscordModel
138
+ # @return [Time] The start time of the activity.
139
+ attr_reader :start
140
+ # @return [Time] The end time of the activity.
141
+ attr_reader :end
142
+
143
+ # @!visibility private
144
+ def initialize(data)
145
+ @start = data[:start] && Time.at(data[:start])
146
+ @end = data[:end] && Time.at(data[:end])
147
+ end
148
+ end
149
+
150
+ class Party < DiscordModel
151
+ # @return [String] The id of the party.
152
+ attr_reader :id
153
+
154
+ # @!attribute [r] current_size
155
+ # @return [Integer] The current size of the party.
156
+ # @!attribute [r] max_size
157
+ # @return [Integer] The max size of the party.
158
+
159
+ # @!visibility private
160
+ def initialize(data)
161
+ @id = data[:id]
162
+ @size = data[:size]
163
+ end
164
+
165
+ def current_size
166
+ @size[0]
167
+ end
168
+
169
+ def max_size
170
+ @size[1]
171
+ end
172
+ end
173
+
174
+ #
175
+ # Represents the assets of an activity.
176
+ #
177
+ class Asset < DiscordModel
178
+ # @return [String] The large image ID of the asset.
179
+ attr_reader :large_image
180
+ alias large_id large_image
181
+ # @return [String] The large text of the activity.
182
+ attr_reader :large_text
183
+ # @return [String] The small image ID of the activity.
184
+ attr_reader :small_image
185
+ alias small_id small_image
186
+ # @return [String] The small text of the activity.
187
+ attr_reader :small_text
188
+
189
+ def initialize(data)
190
+ @large_image = data[:large_image]
191
+ @large_text = data[:large_text]
192
+ @small_image = data[:small_image]
193
+ @small_text = data[:small_text]
194
+ end
195
+ end
196
+
197
+ #
198
+ # Represents the flags of an activity.
199
+ # ## Flag fields
200
+ # |`1 << 0`|`:instance`|
201
+ # |`1 << 1`|`:join`|
202
+ # |`1 << 2`|`:spectate`|
203
+ # |`1 << 3`|`:join_request`|
204
+ # |`1 << 4`|`:sync`|
205
+ # |`1 << 5`|`:play`|
206
+ #
207
+ class Flag < Discorb::Flag
208
+ @bits = {
209
+ instance: 0,
210
+ join: 1,
211
+ spectate: 2,
212
+ join_request: 3,
213
+ sync: 4,
214
+ play: 5,
215
+ }
216
+ end
217
+
218
+ #
219
+ # Represents a secrets of an activity.
220
+ #
221
+ class Secrets < DiscordModel
222
+ # @return [String] The join secret of the activity.
223
+ attr_reader :join
224
+ # @return [String] The spectate secret of the activity.
225
+ attr_reader :spectate
226
+ # @return [String] The match secret of the activity.
227
+ attr_reader :match
228
+
229
+ # @!visibility private
230
+ def initialize(data)
231
+ @join = data[:join]
232
+ @spectate = data[:spectate]
233
+ @match = data[:match]
234
+ end
235
+ end
236
+
237
+ #
238
+ # Represents a button of an activity.
239
+ #
240
+ class Button < DiscordModel
241
+ # @return [String] The text of the button.
242
+ attr_reader :label
243
+ # @return [String] The URL of the button.
244
+ attr_reader :url
245
+ alias text label
246
+
247
+ # @!visibility private
248
+ def initialize(data)
249
+ @label = data[0]
250
+ @url = data[1]
251
+ end
252
+ end
253
+
254
+ class << self
255
+ # @!visibility private
256
+ attr_reader :activity_types
257
+ end
258
+ end
259
+
260
+ #
261
+ # Represents a user's client status.
262
+ #
263
+ class ClientStatus < DiscordModel
264
+ # @return [Symbol] The desktop status of the user.
265
+ attr_reader :desktop
266
+ # @return [Symbol] The mobile status of the user.
267
+ attr_reader :mobile
268
+ # @return [Symbol] The web status of the user.
269
+ attr_reader :web
270
+
271
+ # @!attribute [r] desktop?
272
+ # @return [Boolean] Whether the user is not offline on desktop.
273
+ # @!attribute [r] mobile?
274
+ # @return [Boolean] Whether the user is not offline on mobile.
275
+ # @!attribute [r] web?
276
+ # @return [Boolean] Whether the user is not offline on web.
277
+
278
+ # @!visibility private
279
+ def initialize(data)
280
+ @desktop = data[:desktop]&.to_sym || :offline
281
+ @mobile = data[:mobile]&.to_sym || :offline
282
+ @web = data[:web]&.to_sym || :offline
283
+ end
284
+
285
+ def desktop?
286
+ @desktop != :offline
287
+ end
288
+
289
+ def mobile?
290
+ @mobile != :offline
291
+ end
292
+
293
+ def web?
294
+ @web != :offline
295
+ end
296
+ end
297
+
298
+ private
299
+
300
+ def _set_data(data)
301
+ @user_id = data[:user][:id]
302
+ @guild_id = data[:guild_id]
303
+ @status = data[:status].to_sym
304
+ @activities = data[:activities].map { |a| Activity.new(a) }
305
+ @client_status = ClientStatus.new(data[:client_status])
306
+ end
307
+ end
308
+ end