mij-discord 1.0.7 → 1.0.8

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.
@@ -41,6 +41,10 @@ module MijDiscord::Data
41
41
  FLAGS.map {|bit, name| list.include?(name) ? bit : 0 }.reduce(&:|)
42
42
  end
43
43
 
44
+ def self.flags(bits)
45
+ Set.new(FLAGS.map {|bit, name| (bits & bit).zero? ? nil : name }.reject(&:nil?))
46
+ end
47
+
44
48
  FLAGS.each do |bit, name|
45
49
  attr_reader name
46
50
  alias_method :"#{name}?", name
@@ -71,6 +75,14 @@ module MijDiscord::Data
71
75
  end
72
76
 
73
77
  alias_method :bits=, :set_bits
78
+
79
+ def flags
80
+ Permissions.flags(@bits)
81
+ end
82
+
83
+ def inspect
84
+ %(#<Permissions #{flags.to_a}>)
85
+ end
74
86
  end
75
87
 
76
88
  class Overwrite
@@ -117,5 +129,9 @@ module MijDiscord::Data
117
129
  def to_hash
118
130
  { id: @id, type: @type, allow: @allow.bits, deny: @deny.bits }
119
131
  end
132
+
133
+ def inspect
134
+ MijDiscord.make_inspect(self, :id, :type, :allow, :deny)
135
+ end
120
136
  end
121
137
  end
@@ -93,5 +93,10 @@ module MijDiscord::Data
93
93
  name, color&.to_i, hoist, mentionable, permissions&.to_i)
94
94
  @server.cache.put_role(JSON.parse(response), update: true)
95
95
  end
96
+
97
+ def inspect
98
+ MijDiscord.make_inspect(self,
99
+ :id, :name, :color, :position, :hoist, :mentionable, :managed, :permissions)
100
+ end
96
101
  end
97
102
  end
@@ -46,7 +46,7 @@ module MijDiscord::Data
46
46
  alias_method :embed_enabled?, :embed_enabled
47
47
  alias_method :has_embed?, :embed_enabled
48
48
 
49
- # attr_reader :member_count
49
+ attr_reader :member_count
50
50
 
51
51
  attr_reader :verification_level
52
52
 
@@ -101,7 +101,7 @@ module MijDiscord::Data
101
101
  id = data['afk_channel_id'].to_i
102
102
  @afk_channel = @bot.channel(id, self)
103
103
  end
104
- rescue MijDiscord::Errors::NoPermission
104
+ rescue MijDiscord::Errors::Forbidden
105
105
  @afk_channel = nil
106
106
  end
107
107
  end
@@ -239,6 +239,11 @@ module MijDiscord::Data
239
239
  JSON.parse(response).map {|x| Invite.new(x, @bot) }
240
240
  end
241
241
 
242
+ def webhooks
243
+ response = MijDiscord::Core::API::Server.webhooks(@bot.auth, @id)
244
+ JSON.parse(response).map {|x| Webhook.new(x, @bot) }
245
+ end
246
+
242
247
  def prune_count(days)
243
248
  raise ArgumentError, 'Days must be between 1 and 30' unless days.between?(1, 30)
244
249
 
@@ -419,10 +424,20 @@ module MijDiscord::Data
419
424
  response = MijDiscord::Core::API::Server.search_messages(@bot.auth, @id, options)
420
425
  SearchResults.new(JSON.parse(response), @bot)
421
426
  end
427
+
428
+ def inspect
429
+ MijDiscord.make_inspect(self,
430
+ :id, :name, :owner, :member_count, :features, :embed_enabled, :verification_level,
431
+ :content_filter_level, :default_notifications, :afk_timeout, :afk_channel)
432
+ end
422
433
  end
423
434
 
424
435
  class SearchResults
425
- ResultData = Struct.new(:result, :context)
436
+ ResultData = Struct.new(:result, :context) do
437
+ def inspect
438
+ MijDiscord.make_inspect(self, :result, :context)
439
+ end
440
+ end
426
441
 
427
442
  attr_reader :total_count
428
443
 
@@ -437,5 +452,9 @@ module MijDiscord::Data
437
452
  ResultData.new(result, context)
438
453
  end
439
454
  end
455
+
456
+ def inspect
457
+ MijDiscord.make_inspect(self, :total_count, :messages)
458
+ end
440
459
  end
441
460
  end
@@ -41,6 +41,7 @@ module MijDiscord::Data
41
41
  @url = data['url']
42
42
  @details = data['details']
43
43
  @state = data['state']
44
+ @application = data['application_id']
44
45
 
45
46
  if (start_time = data.dig('timestamps', 'start'))
46
47
  @start_time = Time.at(start_time).utc
@@ -72,32 +73,40 @@ module MijDiscord::Data
72
73
  url: @url,
73
74
  details: @details,
74
75
  state: @state,
76
+ application: @application,
75
77
  })
76
78
  end
77
79
 
80
+ def inspect
81
+ MijDiscord.make_inspect(self,
82
+ :type, :name, :url, :details, :state, :start_time, :end_time,
83
+ :application, :large_image, :large_text, :small_image, :small_text)
84
+ end
85
+
78
86
  def self.construct(data)
79
87
  data = {name: data} if data.is_a?(String)
80
88
 
81
89
  times = {
82
- start: data[:start_time]&.to_i,
83
- end: data[:end_time]&.to_i,
90
+ start: data.try_keys(:start_time, 'start_time')&.to_i,
91
+ end: data.try_keys(:end_time, 'end_time')&.to_i,
84
92
  }.delete_if {|_,v| v.nil? }
85
93
 
86
94
  assets = {
87
- large_image: data[:large_image],
88
- large_text: data[:large_text],
89
- small_image: data[:small_image],
90
- small_text: data[:small_text],
95
+ large_image: data.try_keys(:large_image, 'large_image'),
96
+ large_text: data.try_keys(:large_text, 'large_text'),
97
+ small_image: data.try_keys(:small_image, 'small_image'),
98
+ small_text: data.try_keys(:small_text, 'small_text'),
91
99
  }.delete_if {|_,v| v.nil? }
92
100
 
93
- type = PLAYING_TYPE.index(data[:type])
101
+ type = PLAYING_TYPE.index(data.try_keys(:type, 'type'))
94
102
 
95
103
  game = {
96
104
  type: type || 0,
97
- name: data[:name],
98
- url: data[:url],
99
- details: data[:details],
100
- state: data[:state],
105
+ name: data.try_keys(:name, 'name'),
106
+ url: data.try_keys(:url, 'url'),
107
+ details: data.try_keys(:details, 'details'),
108
+ state: data.try_keys(:state, 'state'),
109
+ application_id: data.try_keys(:application, 'application'),
101
110
 
102
111
  timestamps: times.empty? ? nil : times,
103
112
  assets: assets.empty? ? nil : assets,
@@ -233,6 +242,27 @@ module MijDiscord::Data
233
242
  end
234
243
 
235
244
  alias_method :avatar, :avatar_url
245
+
246
+ def inspect
247
+ MijDiscord.make_inspect(self,
248
+ :id, :username, :discriminator, :avatar_id, :bot_account)
249
+ end
250
+
251
+ class << self
252
+ def process_avatar(data, format = :png, empty = false)
253
+ if data.is_a?(String)
254
+ "data:image/#{format};base64,#{data}"
255
+ elsif data.respond_to?(:read)
256
+ data.binmode if data.respond_to?(:binmode)
257
+ data = Base64.strict_encode64(data.read)
258
+ "data:image/#{format};base64,#{data}"
259
+ elsif empty && %i[none empty].include?(data)
260
+ nil
261
+ else
262
+ raise ArgumentError, 'Invalid avatar data provided'
263
+ end
264
+ end
265
+ end
236
266
  end
237
267
 
238
268
  class Profile < User
@@ -256,17 +286,8 @@ module MijDiscord::Data
256
286
  alias_method :name=, :set_username
257
287
 
258
288
  def set_avatar(data, format = :png)
259
- if data.is_a?(String)
260
- data = "data:image/#{format};base64,#{data}"
261
- elsif data.respond_to?(:read)
262
- data.binmode if data.respond_to?(:binmode)
263
- data = Base64.strict_encode64(data.read)
264
- data = "data:image/#{format};base64,#{data}"
265
- else
266
- raise ArgumentError, 'Invalid avatar data provided'
267
- end
268
-
269
- response = MijDiscord::Core::API::User.update_profile(@bot.auth, @username, data)
289
+ data = User.process_avatar(data, format, false)
290
+ response = MijDiscord::Core::API::User.update_profile(@bot.auth, nil, data)
270
291
  update_data(JSON.parse(response))
271
292
  nil
272
293
  end
@@ -31,6 +31,11 @@ module MijDiscord::Data
31
31
  @self_mute = data.fetch('self_mute', @self_mute)
32
32
  @self_deaf = data.fetch('self_deaf', @self_deaf)
33
33
  end
34
+
35
+ def inspect
36
+ MijDiscord.make_inspect(self,
37
+ :user, :mute, :deaf, :self_mute, :self_deaf, :voice_channel)
38
+ end
34
39
  end
35
40
 
36
41
  class VoiceRegion
@@ -64,5 +69,11 @@ module MijDiscord::Data
64
69
  @deprecated = data['deprecated']
65
70
  @custom = data['custom']
66
71
  end
72
+
73
+ def inspect
74
+ MijDiscord.make_inspect(self,
75
+ :id, :name, :vip, :optimal, :deprecated, :custom,
76
+ :sample_hostname, :sample_port)
77
+ end
67
78
  end
68
79
  end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MijDiscord::Data
4
+ class Webhook
5
+ include IDObject
6
+
7
+ attr_reader :bot
8
+
9
+ attr_reader :name
10
+
11
+ attr_reader :channel
12
+
13
+ attr_reader :token
14
+
15
+ attr_reader :avatar_id
16
+
17
+ attr_reader :owner
18
+
19
+ def initialize(data, bot)
20
+ @bot = bot
21
+
22
+ @id = data['id'].to_id
23
+ @token = data['token']
24
+ update_data(data)
25
+
26
+ if (user = data['user'])
27
+ unless (@owner = server.member(user['id']))
28
+ @owner = @bot.cache.put_user(user)
29
+ end
30
+ end
31
+ end
32
+
33
+ def update_data(data)
34
+ @name = data['name']
35
+ @channel = @bot.channel(data['channel_id'])
36
+ @avatar_id = data['avatar']
37
+ end
38
+
39
+ def via_token?
40
+ @owner.nil?
41
+ end
42
+
43
+ def server
44
+ @channel.server
45
+ end
46
+
47
+ def avatar_url(format = nil)
48
+ return MijDiscord::Core::API::User.default_avatar(0) unless @avatar_id
49
+ MijDiscord::Core::API::User.avatar_url(@id, @avatar_id, format)
50
+ end
51
+
52
+ alias_method :avatar, :avatar_url
53
+
54
+ def set_options(reason = nil, name: nil, channel: nil, avatar: nil, format: :png)
55
+ data = {name: name, channel_id: channel&.to_id}
56
+ data[:avatar] = User.process_avatar(avatar, format, true) unless avatar.nil?
57
+ update_webhook(reason, **data.delete_if {|_,v| v.nil? })
58
+ end
59
+
60
+ def set_name(name, reason = nil)
61
+ update_webhook(reason, name: name)
62
+ end
63
+
64
+ alias_method :name=, :set_name
65
+
66
+ def set_channel(channel, reason = nil)
67
+ update_webhook(reason, channel_id: channel.to_id)
68
+ end
69
+
70
+ alias_method :channel=, :set_channel
71
+
72
+ def set_avatar(data, format = :png, reason = nil)
73
+ data = User.process_avatar(data, format, true)
74
+ update_webhook(reason, avatar: data)
75
+ end
76
+
77
+ alias_method :avatar=, :set_avatar
78
+
79
+ def delete(reason = nil)
80
+ if via_token?
81
+ MijDiscord::Core::API::Webhook.token_delete_webhook(@token, @id, reason)
82
+ else
83
+ MijDiscord::Core::API::Webhook.delete_webhook(@bot.auth, @id, reason)
84
+ end
85
+
86
+ nil
87
+ end
88
+
89
+ def execute(text: '', name: nil, avatar: nil, tts: false, embeds: [], file: nil, wait: true)
90
+ raise 'Not yet implemented' unless file.nil? # TODO: Implement
91
+
92
+ params = {
93
+ content: text,
94
+ username: name,
95
+ avatar_url: avatar,
96
+ tts: tts,
97
+ embeds: embeds.map(&:to_hash),
98
+ }.delete_if {|_,v| v.nil? }
99
+
100
+ response = MijDiscord::Core::API::Webhook.execute_json(@token, @id, params, wait)
101
+ wait ? Message.new(JSON.parse(response), @bot) : nil
102
+ end
103
+
104
+ def inspect
105
+ MijDiscord.make_inspect(self, :id, :name, :channel, :owner)
106
+ end
107
+
108
+ private
109
+
110
+ def update_webhook(reason, **data)
111
+ response = if via_token?
112
+ MijDiscord::Core::API::Webhook.token_update_webhook(@token, @id, data, reason)
113
+ else
114
+ MijDiscord::Core::API::Webhook.update_webhook(@bot.auth, @id, data, reason)
115
+ end
116
+
117
+ update_data(JSON.parse(response))
118
+ nil
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MijDiscord::Errors
4
+ class DiscordError < RuntimeError
5
+ attr_reader :code
6
+
7
+ attr_reader :response
8
+
9
+ def initialize(code, message, response)
10
+ super(message || "(Error #{code})")
11
+
12
+ @code, @response = code, response
13
+ end
14
+ end
15
+
16
+ class MessageTooLong < DiscordError
17
+ MATCH_PATTERNS = [['2000'], ['long', 'length', 'size'], ['fewer', 'maximum']]
18
+
19
+ # This is shitcode
20
+ def self.match_pattern?(error)
21
+ return false if error.nil?
22
+ MATCH_PATTERNS.reduce(true) {|a,x| a && x.reduce(false) {|b,y| b || error.include?(y) } }
23
+ end
24
+
25
+ def initialize(message, response)
26
+ super(nil, message, response)
27
+ end
28
+ end
29
+
30
+ class Unauthorized < DiscordError; end
31
+
32
+ class Forbidden < DiscordError; end
33
+
34
+ class BadRequest < DiscordError; end
35
+
36
+ class NotFound < DiscordError; end
37
+
38
+ HTTP_ERRORS = {
39
+ 400 => BadRequest,
40
+ 401 => Unauthorized,
41
+ 403 => Forbidden,
42
+ 404 => NotFound,
43
+ }.freeze
44
+ end
@@ -53,6 +53,10 @@ module MijDiscord::Events
53
53
  result.reduce(true, &:&)
54
54
  end
55
55
 
56
+ def inspect
57
+ MijDiscord.make_inspect(self)
58
+ end
59
+
56
60
  private
57
61
 
58
62
  def trigger_match?(match, key)
@@ -30,6 +30,8 @@ module MijDiscord::Events
30
30
 
31
31
  class DeleteChannel < Channel; end
32
32
 
33
+ class UpdateWebhooks < Channel; end
34
+
33
35
  class Recipient < Channel
34
36
  attr_reader :recipient
35
37
  alias_method :user, :recipient
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Integer
4
+ alias_method :to_id, :itself
5
+ end
6
+
7
+ class String
8
+ alias_method :to_id, :to_i
9
+ end
10
+
11
+ class Hash
12
+ def try_keys(*keys)
13
+ keys.each {|k| return self[k] if key?(k) }
14
+ nil
15
+ end
16
+ end
@@ -17,4 +17,13 @@ module MijDiscord
17
17
 
18
18
  "[#{sev}] [#{time}] #{prg.upcase}: #{text}\n"
19
19
  end
20
+
21
+ def self.make_inspect(obj, *vars)
22
+ data = [obj.class.to_s.split('::').last]
23
+ data += vars.map do |x|
24
+ value = obj.instance_variable_get(:"@#{x}")
25
+ "#{x}=#{value.inspect}"
26
+ end
27
+ %(#<#{data.join(' ')}>)
28
+ end
20
29
  end