mij-discord 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -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