discorb 0.12.4 → 0.13.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.
data/lib/discorb/event.rb CHANGED
@@ -1,35 +1,276 @@
1
- # frozen_string_literal: true
2
-
3
1
  module Discorb
4
- #
5
- # Represents a event.
6
- # This class shouldn't be instantiated directly.
7
- # Use {Client#on} instead.
8
- #
9
- class Event
10
- # @return [Proc] the block to be called.
11
- attr_reader :block
12
- # @return [Symbol] the event id.
2
+ class ScheduledEvent < DiscordModel
3
+ @privacy_level = {
4
+ 2 => :guild_only,
5
+ }
6
+ @status = {
7
+ 1 => :scheduled,
8
+ 2 => :active,
9
+ 3 => :completed,
10
+ 4 => :canceled,
11
+ }
12
+ @entity_type = {
13
+ 1 => :stage_instance,
14
+ 2 => :voice,
15
+ 3 => :external,
16
+ }
17
+
18
+ # @!visibility private
19
+ def initialize(client, data)
20
+ @client = client
21
+ @data = data
22
+ _set_data(data)
23
+ end
24
+
25
+ #
26
+ # Represents the metadata of the event.
27
+ #
28
+ class Metadata
29
+ # @return [String, nil] The location of the event. Only present if the event is a external event.
30
+ attr_reader :location
31
+ # @!visibility private
32
+ def initialize(data)
33
+ @location = data[:location]
34
+ end
35
+ end
36
+
37
+ # @return [Discorb::Snowflake] The ID of the event.
13
38
  attr_reader :id
14
- # @return [Hash] the event metadata.
39
+ # @return [String] The name of the event.
40
+ attr_reader :name
41
+ # @return [String] The description of the event.
42
+ attr_reader :description
43
+
44
+ # @return [Time] The time the event starts.
45
+ attr_reader :scheduled_start_time
46
+ alias start_time scheduled_start_time
47
+ alias start_at scheduled_start_time
48
+ # @return [Time] The time the event ends.
49
+ attr_reader :scheduled_end_time
50
+ alias end_time scheduled_end_time
51
+ alias end_at scheduled_end_time
52
+ # @return [:guild_only] The privacy level of the event.
53
+ attr_reader :privacy_level
54
+ # @return [:scheduled, :active, :completed, :canceled] The status of the event.
55
+ attr_reader :status
56
+ # @return [:stage_instance, :voice, :external] The type of the event.
57
+ attr_reader :entity_type
58
+ # @return [Discorb::Snowflake] The ID of the entity the event is for.
59
+ attr_reader :entity_id
60
+ # @return [Discorb::ScheduledEvent::Metadata] The metadata of the event.
15
61
  attr_reader :metadata
16
- # @return [Boolean] whether the event is once or not.
17
- attr_reader :once
18
- alias once? once
62
+ # @return [Integer] The user count of the event.
63
+ attr_reader :user_count
64
+
65
+ # @!attribute [r] guild
66
+ # @return [Discorb::Guild, nil] The guild of the event.
67
+ # @!attribute [r] channel
68
+ # @return [Discorb::Channel, nil] The channel of the event.
69
+ # Only present if the event will do in stage instance or voice channel.
70
+ # @!attribute [r] creator
71
+ # @return [Discorb::User] The user who created the event.#
72
+ # @!attribute [r] time
73
+ # @return [Range<Time>] The time range of the event.
74
+
75
+ def guild
76
+ @client.guilds[@guild_id]
77
+ end
78
+
79
+ def channel
80
+ @client.channels[@channel_id]
81
+ end
82
+
83
+ def creator
84
+ @creator || @client.users[@creator_id]
85
+ end
86
+
87
+ def time
88
+ @scheduled_start_time..@scheduled_end_time
89
+ end
90
+
91
+ #
92
+ # Create a scheduled event for the guild.
93
+ # @macro async
94
+ # @macro http
95
+ #
96
+ # @param [:stage_instance, :voice, :external] type The type of event to create.
97
+ # @param [String] name The name of the event.
98
+ # @param [String] description The description of the event.
99
+ # @param [Time] start_time The start time of the event.
100
+ # @param [Time, nil] end_time The end time of the event. Defaults to `nil`.
101
+ # @param [Discorb::Channel, Discorb::Snowflake, nil] channel The channel to run the event in.
102
+ # @param [String, nil] location The location of the event. Defaults to `nil`.
103
+ # @param [:guild_only] privacy_level The privacy level of the event. This must be `:guild_only`.
104
+ # @param [:active, :completed, :canceled] status The status of the event.
105
+ #
106
+ # @see Event#start
107
+ # @see Event#cancel
108
+ # @see Event#complete
109
+ #
110
+ def edit(
111
+ type: Discorb::Unset,
112
+ name: Discorb::Unset,
113
+ description: Discorb::Unset,
114
+ start_time: Discorb::Unset,
115
+ end_time: Discorb::Unset,
116
+ privacy_level: Discorb::Unset,
117
+ location: Discorb::Unset,
118
+ channel: Discorb::Unset,
119
+ status: Discorb::Unset
120
+ )
121
+ Async do
122
+ payload = case (type == Discorb::Unset) ? @entity_type : type
123
+ when :stage_instance
124
+ raise ArgumentError, "channel must be provided for stage_instance events" unless channel
125
+ {
126
+ name: name,
127
+ description: description,
128
+ scheduled_start_time: start_time.iso8601,
129
+ scheduled_end_time: end_time&.iso8601,
130
+ privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level) || Discorb::Unset,
131
+ channel_id: channel&.id,
132
+ entity_type: Discorb::ScheduledEvent.entity_type.key(:stage_instance),
133
+ status: Discorb::ScheduledEvent.status.key(status) || Discorb::Unset,
134
+ }.reject { |_, v| v == Discorb::Unset }
135
+ when :voice
136
+ raise ArgumentError, "channel must be provided for voice events" unless channel
137
+ {
138
+ name: name,
139
+ description: description,
140
+ scheduled_start_time: start_time.iso8601,
141
+ scheduled_end_time: end_time&.iso8601,
142
+ privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level) || Discorb::Unset,
143
+ channel_id: channel&.id,
144
+ entity_type: Discorb::ScheduledEvent.entity_type.key(:voice),
145
+ status: Discorb::ScheduledEvent.status.key(status) || Discorb::Unset,
146
+ }.reject { |_, v| v == Discorb::Unset }
147
+ when :external
148
+ raise ArgumentError, "location must be provided for external events" unless location
149
+ raise ArgumentError, "end_time must be provided for external events" unless end_time
150
+ {
151
+ name: name,
152
+ description: description,
153
+ channel_id: nil,
154
+ scheduled_start_time: start_time.iso8601,
155
+ scheduled_end_time: end_time.iso8601,
156
+ privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level) || Discorb::Unset,
157
+ entity_type: Discorb::ScheduledEvent.entity_type.key(:external),
158
+ entity_metadata: {
159
+ location: location,
160
+ },
161
+ status: Discorb::ScheduledEvent.status.key(status) || Discorb::Unset,
162
+ }.reject { |_, v| v == Discorb::Unset }
163
+ else
164
+ raise ArgumentError, "Invalid scheduled event type: #{type}"
165
+ end
166
+ @client.http.patch("/guilds/#{@guild_id}/scheduled-events/#{@id}", payload).wait
167
+ end
168
+ end
169
+
170
+ alias modify edit
19
171
 
20
- def initialize(block, id, metadata)
21
- @block = block
22
- @id = id
23
- @once = metadata.fetch(:once, false)
24
- @metadata = metadata
25
- @rescue = nil
172
+ #
173
+ # Starts the event. Shortcut for `edit(status: :active)`.
174
+ #
175
+ def start
176
+ edit(status: :active)
26
177
  end
27
178
 
28
179
  #
29
- # Calls the block associated with the event.
180
+ # Completes the event. Shortcut for `edit(status: :completed)`.
181
+ #
182
+ def complete
183
+ edit(status: :completed)
184
+ end
185
+
186
+ alias finish complete
187
+
188
+ #
189
+ # Cancels the event. Shortcut for `edit(status: :canceled)`.
30
190
  #
31
- def call(...)
32
- @block.call(...)
191
+ def cancel
192
+ edit(status: :canceled)
193
+ end
194
+
195
+ #
196
+ # Deletes the event.
197
+ # @macro async
198
+ # @macro http
199
+ #
200
+ def delete!
201
+ Async do
202
+ @client.http.delete("/guilds/#{@guild_id}/scheduled-events/#{@id}").wait
203
+ end
204
+ end
205
+
206
+ alias destroy! delete!
207
+
208
+ #
209
+ # Fetches the event users.
210
+ # @macro async
211
+ # @macro http
212
+ #
213
+ # @note You can fetch all of members by not specifying a parameter.
214
+ #
215
+ # @param [Integer] limit The maximum number of users to fetch. Defaults to `100`.
216
+ # @param [#to_s] after The ID of the user to start fetching from. Defaults to `nil`.
217
+ # @param [#to_s] before The ID of the user to stop fetching at. Defaults to `nil`.
218
+ # @param [Boolean] with_member Whether to include the member object of the event. Defaults to `false`.
219
+ # This should be used for manual fetching of members.
220
+ #
221
+ # @return [Array<Discorb::Member>] The event users.
222
+ #
223
+ def fetch_users(limit = nil, before: nil, after: nil, with_member: true)
224
+ Async do
225
+ if limit.nil?
226
+ after = 0
227
+ res = []
228
+ while true
229
+ _resp, users = @client.http.get("/guilds/#{@guild_id}/scheduled-events/#{@id}/users?limit=100&after=#{after}&with_member=true").wait
230
+ if users.empty?
231
+ break
232
+ end
233
+ res += users.map { |u| Member.new(@client, @guild_id, u[:user], u[:member]) }
234
+ after = users.last[:user][:id]
235
+ end
236
+ res
237
+ else
238
+ params = {
239
+ limit: limit,
240
+ before: Discorb::Utils.try(after, :id),
241
+ after: Discorb::Utils.try(around, :id),
242
+ with_member: with_member,
243
+ }.filter { |_k, v| !v.nil? }.to_h
244
+ _resp, messages = @client.http.get("/channels/#{channel_id.wait}/messages?#{URI.encode_www_form(params)}").wait
245
+ messages.map { |m| Message.new(@client, m.merge({ guild_id: @guild_id.to_s })) }
246
+ end
247
+ end
248
+ end
249
+
250
+ alias fetch_members fetch_users
251
+
252
+ private
253
+
254
+ def _set_data(data)
255
+ @id = Snowflake.new(data[:id])
256
+ @guild_id = Snowflake.new(data[:guild_id])
257
+ @channel_id = data[:channel_id] && Snowflake.new(data[:channel_id])
258
+ @creator_id = data[:creator_id] && Snowflake.new(data[:creator_id])
259
+ @name = data[:name]
260
+ @description = data[:description]
261
+ @scheduled_start_time = Time.iso8601(data[:scheduled_start_time])
262
+ @scheduled_end_time = data[:scheduled_end_time] && Time.iso8601(data[:scheduled_end_time])
263
+ @privacy_level = :guild_only # data[:privacy_level]
264
+ @status = self.class.status[data[:status]]
265
+ @entity_type = self.class.entity_type[data[:entity_type]]
266
+ @entity_id = data[:entity_id] && Snowflake.new(data[:entity_id])
267
+ @entity_metadata = data[:entity_metadata] && Metadata.new(data[:entity_metadata])
268
+ @creator = @client.users[@creator_id] || (data[:creator] && User.new(@client, data[:creator]))
269
+ @user_count = data[:user_count]
270
+ end
271
+
272
+ class << self
273
+ attr_reader :status, :entity_type, :privacy_level
33
274
  end
34
275
  end
35
276
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Discorb
4
+ #
5
+ # Represents a event handler.
6
+ # This class shouldn't be instantiated directly.
7
+ # Use {Client#on} instead.
8
+ #
9
+ class EventHandler
10
+ # @return [Proc] the block to be called.
11
+ attr_reader :block
12
+ # @return [Symbol] the event id.
13
+ attr_reader :id
14
+ # @return [Hash] the event metadata.
15
+ attr_reader :metadata
16
+ # @return [Boolean] whether the event is once or not.
17
+ attr_reader :once
18
+ alias once? once
19
+
20
+ def initialize(block, id, metadata)
21
+ @block = block
22
+ @id = id
23
+ @once = metadata.fetch(:once, false)
24
+ @metadata = metadata
25
+ @rescue = nil
26
+ end
27
+
28
+ def inspect
29
+ "#<#{self.class} @id=#{@id}"
30
+ end
31
+
32
+ #
33
+ # Calls the block associated with the event.
34
+ #
35
+ def call(...)
36
+ @block.call(...)
37
+ end
38
+ end
39
+ end
@@ -17,7 +17,7 @@ module Discorb
17
17
  ret = {}
18
18
  self.class.events.each do |event, handlers|
19
19
  ret[event] = handlers.map do |handler|
20
- Discorb::Event.new(Proc.new { |*args, **kwargs| instance_exec(*args, **kwargs, &handler[2]) }, handler[0], handler[1])
20
+ Discorb::EventHandler.new(Proc.new { |*args, **kwargs| instance_exec(*args, **kwargs, &handler[2]) }, handler[0], handler[1])
21
21
  end
22
22
  end
23
23
  @events = ret
@@ -38,7 +38,7 @@ module Discorb
38
38
  # @param [Symbol] id The id of the event. Used to delete the event.
39
39
  # @param [Hash] metadata Other metadata.
40
40
  #
41
- # @return [Discorb::Event] The event.
41
+ # @return [Discorb::EventHandler] The event.
42
42
  #
43
43
  def event(event_name, id: nil, **metadata, &block)
44
44
  raise ArgumentError, "Event name must be a symbol" unless event_name.is_a?(Symbol)
@@ -57,13 +57,13 @@ module Discorb
57
57
  # @param [Hash] metadata Other metadata.
58
58
  # @param [Proc] block The block to execute when the event is triggered.
59
59
  #
60
- # @return [Discorb::Event] The event.
60
+ # @return [Discorb::EventHandler] The event.
61
61
  #
62
62
  def once_event(event_name, id: nil, **metadata, &block)
63
63
  event(event_name, id: id, once: true, **metadata, &block)
64
64
  end
65
65
 
66
- # @return [Hash{Symbol => Array<Discorb::Event>}] The events of the extension.
66
+ # @return [Hash{Symbol => Array<Discorb::EventHandler>}] The events of the extension.
67
67
  attr_reader :events
68
68
  # @return [Array<Discorb::ApplicationCommand::Command>] The commands of the extension.
69
69
  attr_reader :commands
data/lib/discorb/file.rb CHANGED
@@ -89,5 +89,9 @@ module Discorb
89
89
  filename ||= string.object_id.to_s + ".txt"
90
90
  new(io, filename, content_type: content_type)
91
91
  end
92
+
93
+ def inspect
94
+ "#<#{self.class} filename=#{@filename} content_type=#{@content_type}>"
95
+ end
92
96
  end
93
97
  end
data/lib/discorb/flag.rb CHANGED
@@ -96,6 +96,10 @@ module Discorb
96
96
  self.class.new(~@value)
97
97
  end
98
98
 
99
+ def inspect
100
+ "#<#{self.class}: #{@value}>"
101
+ end
102
+
99
103
  class << self
100
104
  # @return [Hash{Integer => Symbol}] the bits of the flag.
101
105
  attr_reader :bits
@@ -210,6 +210,28 @@ module Discorb
210
210
  end
211
211
  end
212
212
 
213
+ #
214
+ # Represents a `GUILD_SCHEDULED_EVENT_USER_ADD` and `GUILD_SCHEDULED_EVENT_USER_REMOVE` event.
215
+ #
216
+ class ScheduledEventUserEvent < GatewayEvent
217
+ # @return [Discorb::User] The user that triggered the event.
218
+ attr_reader :user
219
+ # @return [Discorb::Guild] The guild the event was triggered in.
220
+ attr_reader :guild
221
+ # @return [Discorb::ScheduledEvent] The scheduled event.
222
+ attr_reader :scheduled_event
223
+ # @private
224
+ def initialize(client, data)
225
+ @client = client
226
+ @scheduled_event_id = Snowflake.new(data[:scheduled_event_id])
227
+ @user_id = Snowflake.new(data[:user_id])
228
+ @guild_id = Snowflake.new(data[:guild_id])
229
+ @guild = client.guilds[data[:guild_id]]
230
+ @scheduled_event = @guild.scheduled_events[@scheduled_event_id]
231
+ @user = client.users[data[:user_id]]
232
+ end
233
+ end
234
+
213
235
  #
214
236
  # Represents a `MESSAGE_UPDATE` event.
215
237
  #
@@ -1042,11 +1064,44 @@ module Discorb
1042
1064
  @log.info("Successfully resumed connection")
1043
1065
  @tasks << handle_heartbeat
1044
1066
  dispatch(:resumed)
1067
+ when "GUILD_SCHEDULED_EVENT_CREATE"
1068
+ @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
1069
+ event = ScheduledEvent.new(self, data)
1070
+ guild.scheduled_events[data[:id]] = event
1071
+ dispatch(:scheduled_event_create, event)
1072
+ when "GUILD_SCHEDULED_EVENT_UPDATE"
1073
+ @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
1074
+ @log.warn("Unknown scheduled event id #{data[:id]}, ignoring") unless (event = guild.scheduled_events[data[:id]])
1075
+ old = event.dup
1076
+ event.send(:_set_data, data)
1077
+ dispatch(:scheduled_event_update, old, event)
1078
+ if old.status != event.status
1079
+ case event.status
1080
+ when :active
1081
+ dispatch(:scheduled_event_start, event)
1082
+ when :completed
1083
+ dispatch(:scheduled_event_end, event)
1084
+ end
1085
+ else
1086
+ dispatch(:scheduled_event_edit, old, event)
1087
+ end
1088
+ when "GUILD_SCHEDULED_EVENT_DELETE"
1089
+ @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
1090
+ @log.warn("Unknown scheduled event id #{data[:id]}, ignoring") unless (event = guild.scheduled_events[data[:id]])
1091
+ guild.scheduled_events.remove(data[:id])
1092
+ dispatch(:scheduled_event_delete, event)
1093
+ dispatch(:scheduled_event_cancel, event)
1094
+ when "GUILD_SCHEDULED_EVENT_USER_ADD"
1095
+ @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
1096
+ dispatch(:scheduled_event_user_add, ScheduledEventUserEvent.new(self, data))
1097
+ when "GUILD_SCHEDULED_EVENT_USER_REMOVE"
1098
+ @log.warn("Unknown guild id #{data[:guild_id]}, ignoring") unless (guild = @guilds[data[:guild_id]])
1099
+ dispatch(:scheduled_event_user_remove, ScheduledEventUserEvent.new(self, data))
1045
1100
  else
1046
1101
  if respond_to?("event_" + event_name.downcase)
1047
1102
  __send__("event_" + event_name.downcase, data)
1048
1103
  else
1049
- @log.debug "#{event_name}\n#{data.inspect}"
1104
+ @log.debug "Unhandled event: #{event_name}\n#{data.inspect}"
1050
1105
  end
1051
1106
  end
1052
1107
  end
@@ -39,6 +39,10 @@ module Discorb
39
39
  }
40
40
  end
41
41
 
42
+ def inspect
43
+ "#<#{self.class} @type=#{@type}>"
44
+ end
45
+
42
46
  class << self
43
47
  # @private
44
48
  attr_reader :types
data/lib/discorb/guild.rb CHANGED
@@ -96,6 +96,9 @@ module Discorb
96
96
  # @return [Boolean] Whether the guild is available.
97
97
  attr_reader :available
98
98
  alias available? available
99
+ # @return [Dictionary{Discorb::Snowflake => Discorb::ScheduledEvent}] A dictionary of scheduled events in the guild.
100
+ attr_reader :scheduled_events
101
+ alias events scheduled_events
99
102
 
100
103
  # @!attribute [r] afk_channel
101
104
  # @return [Discorb::VoiceChannel] The AFK channel for this guild.
@@ -169,6 +172,113 @@ module Discorb
169
172
  end
170
173
  end
171
174
 
175
+ #
176
+ # Fetch scheduled events for the guild.
177
+ # @macro async
178
+ # @macro http
179
+ #
180
+ # @param [Boolean] with_user_count Whether to include the user count in the events.
181
+ # Defaults to `true`.
182
+ #
183
+ # @return [Array<Discorb::ScheduledEvent>] The events for the guild.
184
+ #
185
+ def fetch_scheduled_events(with_user_count: true)
186
+ Async do
187
+ _resp, events = @client.http.get("/guilds/#{@id}/scheduled-events?with_user_count=#{with_user_count}").wait
188
+ @scheduled_events = events.map { |e| ScheduledEvent.new(@client, e) }
189
+ end
190
+ end
191
+
192
+ #
193
+ # Fetch the scheduled event by ID.
194
+ # @macro async
195
+ # @macro http
196
+ #
197
+ # @param [#to_s] id The ID of the scheduled event.
198
+ #
199
+ # @return [Discorb::ScheduledEvent] The event with the given ID.
200
+ # @return [nil] If no event with the given ID exists.
201
+ #
202
+ def fetch_scheduled_event(id)
203
+ Async do
204
+ _resp, event = @client.http.get("/guilds/#{@id}/scheduled-events/#{id}").wait
205
+ rescue Discorb::NotFoundError
206
+ return nil
207
+ else
208
+ ScheduledEvent.new(@client, event)
209
+ end
210
+ end
211
+
212
+ #
213
+ # Create a scheduled event for the guild.
214
+ #
215
+ # @param [:stage_instance, :voice, :external] type The type of event to create.
216
+ # @param [String] name The name of the event.
217
+ # @param [String] description The description of the event.
218
+ # @param [Time] start_time The start time of the event.
219
+ # @param [Time, nil] end_time The end time of the event. Defaults to `nil`.
220
+ # @param [Discorb::Channel, Discorb::Snowflake, nil] channel The channel to run the event in.
221
+ # @param [String, nil] location The location of the event. Defaults to `nil`.
222
+ # @param [:guild_only] privacy_level The privacy level of the event. This must be `:guild_only`.
223
+ #
224
+ # @return [Discorb::ScheduledEvent] The created event.
225
+ #
226
+ def create_scheduled_event(
227
+ type,
228
+ name,
229
+ description,
230
+ start_time,
231
+ end_time = nil,
232
+ privacy_level: :guild_only,
233
+ location: nil,
234
+ channel: nil
235
+ )
236
+ Async do
237
+ payload = case type
238
+ when :stage_instance
239
+ raise ArgumentError, "channel must be provided for stage_instance events" unless channel
240
+ {
241
+ name: name,
242
+ description: description,
243
+ scheduled_start_time: start_time.iso8601,
244
+ scheduled_end_time: end_time&.iso8601,
245
+ privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level),
246
+ channel_id: channel&.id,
247
+ entity_type: Discorb::ScheduledEvent.entity_type.key(:stage_instance),
248
+ }
249
+ when :voice
250
+ raise ArgumentError, "channel must be provided for voice events" unless channel
251
+ {
252
+ name: name,
253
+ description: description,
254
+ scheduled_start_time: start_time.iso8601,
255
+ scheduled_end_time: end_time&.iso8601,
256
+ privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level),
257
+ channel_id: channel&.id,
258
+ entity_type: Discorb::ScheduledEvent.entity_type.key(:voice),
259
+ }
260
+ when :external
261
+ raise ArgumentError, "location must be provided for external events" unless location
262
+ raise ArgumentError, "end_time must be provided for external events" unless end_time
263
+ {
264
+ name: name,
265
+ description: description,
266
+ scheduled_start_time: start_time.iso8601,
267
+ scheduled_end_time: end_time.iso8601,
268
+ privacy_level: Discorb::ScheduledEvent.privacy_level.key(privacy_level),
269
+ entity_type: Discorb::ScheduledEvent.entity_type.key(:external),
270
+ entity_metadata: {
271
+ location: location,
272
+ },
273
+ }
274
+ else
275
+ raise ArgumentError, "Invalid scheduled event type: #{type}"
276
+ end
277
+ _resp, event = @client.http.post("/guilds/#{@id}/scheduled-events", payload).wait
278
+ Discorb::ScheduledEvent.new(@client, event)
279
+ end
280
+ end
281
+
172
282
  #
173
283
  # Fetch emoji list of the guild.
174
284
  # @macro async
@@ -1143,6 +1253,7 @@ module Discorb
1143
1253
  @presences = Dictionary.new(data[:presences].map { |pr| [Snowflake.new(pr[:user][:id]), Presence.new(@client, pr)] }.to_h)
1144
1254
  @max_presences = data[:max_presences]
1145
1255
  @stage_instances = Dictionary.new(data[:stage_instances].map { |s| [Snowflake.new(s[:id]), StageInstance.new(@client, s)] }.to_h)
1256
+ @scheduled_events = Dictionary.new(data[:guild_scheduled_events].map { |s| [Snowflake.new(s[:id]), ScheduledEvent.new(@client, s)] }.to_h)
1146
1257
  @data.update(data)
1147
1258
  end
1148
1259
  end
@@ -1155,12 +1266,14 @@ module Discorb
1155
1266
  # |`1 << 0`|`:member_join`|
1156
1267
  # |`1 << 1`|`:server_boost`|
1157
1268
  # |`1 << 2`|`:setup_tips`|
1269
+ # |`1 << 3`|`:join_stickers`|
1158
1270
  #
1159
1271
  class SystemChannelFlag < Flag
1160
1272
  @bits = {
1161
1273
  member_join: 0,
1162
1274
  server_boost: 1,
1163
1275
  setup_tips: 2,
1276
+ join_stickers: 3,
1164
1277
  }.freeze
1165
1278
  end
1166
1279
 
data/lib/discorb/image.rb CHANGED
@@ -16,12 +16,10 @@ module Discorb
16
16
  #
17
17
  def initialize(source, type = nil)
18
18
  if source.respond_to?(:read)
19
- @bytes = source.read
19
+ @io = source
20
20
  @type = type || MIME::Types.type_for(source.path).first.content_type
21
21
  elsif ::File.exist?(source)
22
- ::File.open(source, "rb") do |file|
23
- @bytes = file.read
24
- end
22
+ @io = ::File.open(source, "rb")
25
23
  @type = MIME::Types.type_for(source).first.to_s
26
24
  else
27
25
  raise ArgumentError, "Couldn't read file."
@@ -34,7 +32,11 @@ module Discorb
34
32
  # @return [String] The image as a Discord style.
35
33
  #
36
34
  def to_s
37
- "data:#{@type};base64,#{Base64.strict_encode64(@bytes)}"
35
+ "data:#{@type};base64,#{Base64.strict_encode64(@io.read)}"
36
+ end
37
+
38
+ def inspect
39
+ "#<#{self.class} #{@type}>"
38
40
  end
39
41
  end
40
42
  end