discordrb 1.3.4 → 1.3.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of discordrb might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66f79878220c4bf42ad27bc01ab409d6613670be
4
- data.tar.gz: 4bd26ca3ca4739a855344b3d0d867f8d616958ad
3
+ metadata.gz: 53406fbf27f1a8d7537644738f10b13967bd606b
4
+ data.tar.gz: 19cb23917078868028f4e02cc74d7f7ac6a4aa97
5
5
  SHA512:
6
- metadata.gz: 6e83dde0d98d3cb8ad65d64964c5731d97b526fc89865f25a0c57fa2c9bf0cd6d936b28fd81b39e74156a64e602253476479a588f9ff92a76eb39cf9c1d1e756
7
- data.tar.gz: 174fd8785f53d910b88b6146b3ae657e83bed445163de278f9be0f3a848d9097206835e82da5f18f8051ab5c2676bbeba42dae48e58cc480d83d5368072cdf46
6
+ metadata.gz: e2f4c1621d4ecde3d6b7a67a003febc31944b5592060d24a2c9e47ae98cd53b8a882d6661cc9a0e91949bd9b18838d2fde5891876d37367b8f7c54516c888a1d
7
+ data.tar.gz: 71e2d4c6fd71a900ef779e4a647e226fdcc7ef42f1198eb65e4d9bfddcf450af2cc93855965875fa49413ebe715d661446e585847a96e28ab29d430dccba0227
data/.rubocop.yml ADDED
@@ -0,0 +1,44 @@
1
+ # Disable all metrics.
2
+ Metrics/AbcSize:
3
+ Enabled: false
4
+
5
+ Metrics/BlockNesting:
6
+ Enabled: false
7
+
8
+ Metrics/ClassLength:
9
+ Enabled: false
10
+
11
+ Metrics/ModuleLength:
12
+ Enabled: false
13
+
14
+ Metrics/CyclomaticComplexity:
15
+ Enabled: false
16
+
17
+ Metrics/LineLength:
18
+ Enabled: false
19
+
20
+ Metrics/MethodLength:
21
+ Enabled: false
22
+
23
+ Metrics/ParameterLists:
24
+ Enabled: false
25
+
26
+ Metrics/PerceivedComplexity:
27
+ Enabled: false
28
+
29
+ # Prefer compact module/class defs
30
+ Style/ClassAndModuleChildren:
31
+ Enabled: false
32
+
33
+ # Allow CamelCase constants as well as SCREAMING_SNAKE_CASE
34
+ Style/ConstantName:
35
+ Enabled: false
36
+
37
+ # Allow 'Pokémon-style' exception handling
38
+ Lint/RescueException:
39
+ Enabled: false
40
+
41
+ # Exclude the list of games
42
+ AllCops:
43
+ Exclude:
44
+ - '**/games_list.rb'
data/lib/discordrb.rb CHANGED
@@ -1,7 +1,8 @@
1
- require "discordrb/version"
2
- require "discordrb/bot"
3
- require "discordrb/commands/command-bot"
1
+ require 'discordrb/version'
2
+ require 'discordrb/bot'
3
+ require 'discordrb/commands/command-bot'
4
4
 
5
+ # All discordrb functionality, to be extended by other files
5
6
  module Discordrb
6
7
  # Your code goes here...
7
8
  end
data/lib/discordrb/api.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  require 'rest-client'
2
2
  require 'json'
3
3
 
4
+ # List of methods representing endpoints in Discord's API
4
5
  module Discordrb::API
5
6
  APIBASE = 'https://discordapp.com/api'
7
+
6
8
  module_function
7
9
 
8
10
  # Ban a user from a server and delete their messages from the last message_days days
@@ -170,7 +172,7 @@ module Discordrb::API
170
172
  def send_file(token, channel_id, file)
171
173
  RestClient.post(
172
174
  "#{APIBASE}/channels/#{channel_id}/messages",
173
- {:file => file},
175
+ { file: file },
174
176
  Authorization: token
175
177
  )
176
178
  end
@@ -187,7 +189,7 @@ module Discordrb::API
187
189
  # Permissions are the Discord defaults; allowed: invite creation, reading/sending messages,
188
190
  # sending TTS messages, embedding links, sending files, reading the history, mentioning everybody,
189
191
  # connecting to voice, speaking and voice activity (push-to-talk isn't mandatory)
190
- def update_role(token, server_id, role_id, name, colour, hoist = false, packed_permissions = 36953089)
192
+ def update_role(token, server_id, role_id, name, colour, hoist = false, packed_permissions = 36_953_089)
191
193
  RestClient.patch(
192
194
  "#{APIBASE}/guilds/#{server_id}/roles/#{role_id}",
193
195
  { 'color' => colour, 'name' => name, 'hoist' => hoist, 'permissions' => packed_permissions }.to_json,
@@ -275,5 +277,4 @@ module Discordrb::API
275
277
  Authorization: token
276
278
  )
277
279
  end
278
-
279
280
  end
data/lib/discordrb/bot.rb CHANGED
@@ -21,6 +21,7 @@ require 'discordrb/exceptions'
21
21
  require 'discordrb/data'
22
22
 
23
23
  module Discordrb
24
+ # Represents a Discord bot, including servers, users, etc.
24
25
  class Bot
25
26
  include Discordrb::Events
26
27
 
@@ -28,8 +29,8 @@ module Discordrb
28
29
 
29
30
  def initialize(email, password, debug = false)
30
31
  # Make sure people replace the login details in the example files...
31
- if email.end_with? "example.com"
32
- puts "You have to replace the login details in the example files with your own!"
32
+ if email.end_with? 'example.com'
33
+ puts 'You have to replace the login details in the example files with your own!'
33
34
  exit
34
35
  end
35
36
 
@@ -46,23 +47,42 @@ module Discordrb
46
47
  @users = {}
47
48
  end
48
49
 
49
- def run
50
+ def run(async = false)
51
+ run_async
52
+ return if async
53
+
54
+ debug('Oh wait! Not exiting yet as run was run synchronously.')
55
+ loop {}
56
+ end
57
+
58
+ def run_async
50
59
  # Handle heartbeats
51
60
  @heartbeat_interval = 1
52
61
  @heartbeat_active = false
53
62
  @heartbeat_thread = Thread.new do
54
- while true do
63
+ loop do
55
64
  sleep @heartbeat_interval
56
65
  send_heartbeat if @heartbeat_active
57
66
  end
58
67
  end
59
68
 
60
- while true do
61
- websocket_connect
62
- debug("Disconnected! Attempting to reconnect in 5 seconds.")
63
- sleep 5
64
- @token = login
69
+ @ws_thread = Thread.new do
70
+ loop do
71
+ websocket_connect
72
+ debug('Disconnected! Attempting to reconnect in 5 seconds.')
73
+ sleep 5
74
+ @token = login
75
+ end
65
76
  end
77
+
78
+ debug('WS thread created! Now waiting for confirmation that everything worked')
79
+ @ws_success = false
80
+ sleep(0.5) until @ws_success
81
+ debug('Confirmation received! Exiting run.')
82
+ end
83
+
84
+ def sync
85
+ @ws_thread.join
66
86
  end
67
87
 
68
88
  def channel(id)
@@ -78,17 +98,13 @@ module Discordrb
78
98
  debug("Creating private channel with user id #{id}")
79
99
  return @private_channels[id] if @private_channels[id]
80
100
 
81
- data = {
82
- 'recipient_id' => id
83
- }
84
-
85
101
  response = API.create_private(@token, @bot_user.id, id)
86
102
  channel = Channel.new(JSON.parse(response), self)
87
103
  @private_channels[id] = channel
88
104
  end
89
105
 
90
106
  def join(invite)
91
- invite = invite[invite.rindex('/')+1..-1] if invite.start_with?('http') || invite.start_with?('discord.gg')
107
+ invite = invite[invite.rindex('/') + 1..-1] if invite.start_with?('http') || invite.start_with?('discord.gg')
92
108
  resolved = JSON.parse(API.resolve_invite(@token, invite))['code']
93
109
  API.join_server(@token, resolved)
94
110
  end
@@ -103,10 +119,6 @@ module Discordrb
103
119
 
104
120
  def send_message(channel_id, content)
105
121
  debug("Sending message to #{channel_id} with content '#{content}'")
106
- data = {
107
- 'content' => content.to_s,
108
- 'mentions' => []
109
- }
110
122
  response = API.send_message(@token, channel_id, content)
111
123
  Message.new(JSON.parse(response), self)
112
124
  end
@@ -123,7 +135,7 @@ module Discordrb
123
135
  'op' => 3,
124
136
  'd' => {
125
137
  'idle_since' => nil,
126
- 'game_id' => game ? game.id : 60 # 60 blanks out the game playing
138
+ 'game_id' => game ? game.id : 60 # 60 blanks out the game playing
127
139
  }
128
140
  }
129
141
 
@@ -131,9 +143,7 @@ module Discordrb
131
143
  game
132
144
  end
133
145
 
134
- def debug=(debug)
135
- @debug = debug
136
- end
146
+ attr_writer :debug
137
147
 
138
148
  def message(attributes = {}, &block)
139
149
  register_event(MessageEvent, attributes, block)
@@ -207,7 +217,7 @@ module Discordrb
207
217
  end
208
218
 
209
219
  def debug(message, important = false)
210
- puts "[DEBUG @ #{Time.now.to_s}] #{message}" if @debug || important
220
+ puts "[DEBUG @ #{Time.now}] #{message}" if @debug || important
211
221
  end
212
222
 
213
223
  alias_method :<<, :add_handler
@@ -219,22 +229,23 @@ module Discordrb
219
229
  user_id = data['user']['id'].to_i
220
230
  server_id = data['guild_id'].to_i
221
231
  server = @servers[server_id]
222
- return if !server
232
+ return unless server
223
233
 
224
234
  user = @users[user_id]
225
- if !user
235
+ unless user
226
236
  user = User.new(data['user'], self)
227
237
  @users[user_id] = user
228
238
  end
229
239
 
230
240
  status = data['status'].to_sym
231
241
  if status != :offline
232
- if !(server.members.find {|u| u.id == user.id })
242
+ unless server.members.find { |u| u.id == user.id }
233
243
  server.members << user
234
244
  end
235
245
  end
236
246
  user.status = status
237
247
  user.game = Discordrb::Games.find_game(data['game_id'])
248
+ user
238
249
  end
239
250
 
240
251
  # Internal handler for VOICE_STATUS_UPDATE
@@ -242,7 +253,7 @@ module Discordrb
242
253
  user_id = data['user_id'].to_i
243
254
  server_id = data['guild_id'].to_i
244
255
  server = @servers[server_id]
245
- return if !server
256
+ return unless server
246
257
 
247
258
  user = @users[user_id]
248
259
  user.server_mute = data['mute']
@@ -252,9 +263,7 @@ module Discordrb
252
263
 
253
264
  channel_id = data['channel_id']
254
265
  channel = nil
255
- if channel_id
256
- channel = @channels[channel_id.to_i]
257
- end
266
+ channel = @channels[channel_id.to_i] if channel_id
258
267
  user.move(channel)
259
268
  end
260
269
 
@@ -269,9 +278,8 @@ module Discordrb
269
278
  # Internal handler for CHANNEL_UPDATE
270
279
  def update_channel(data)
271
280
  channel = Channel.new(data, self)
272
- server = channel.server
273
281
  old_channel = @channels[channel.id]
274
- return if !old_channel
282
+ return unless old_channel
275
283
  old_channel.update_from(channel)
276
284
  end
277
285
 
@@ -280,7 +288,7 @@ module Discordrb
280
288
  channel = Channel.new(data, self)
281
289
  server = channel.server
282
290
  @channels[channel.id] = nil
283
- server.channels.reject! {|c| c.id == channel.id}
291
+ server.channels.reject! { |c| c.id == channel.id }
284
292
  end
285
293
 
286
294
  # Internal handler for GUILD_MEMBER_UPDATE
@@ -291,7 +299,7 @@ module Discordrb
291
299
  roles = []
292
300
  data['roles'].each do |element|
293
301
  role_id = element.to_i
294
- roles << server.roles.find {|r| r.id == role_id}
302
+ roles << server.roles.find { |r| r.id == role_id }
295
303
  end
296
304
  user_id = user_data['id'].to_i
297
305
  user = @users[user_id]
@@ -305,7 +313,7 @@ module Discordrb
305
313
  server = @servers[server_id]
306
314
  new_role = Role.new(role_data, self, server)
307
315
  role_id = role_data['id'].to_i
308
- old_role = server.roles.find {|r| r.id == role_id}
316
+ old_role = server.roles.find { |r| r.id == role_id }
309
317
  old_role.update_from(new_role)
310
318
  end
311
319
 
@@ -334,22 +342,22 @@ module Discordrb
334
342
  def start_typing(data); end
335
343
 
336
344
  def login
337
- debug("Logging in")
338
- login_attempts = login_attempts || 0
345
+ debug('Logging in')
346
+ login_attempts ||= 0
339
347
 
340
348
  # Login
341
349
  login_response = API.login(@email, @password)
342
- raise HTTPStatusException.new(login_response.code) if login_response.code >= 400
350
+ fail HTTPStatusException, login_response.code if login_response.code >= 400
343
351
 
344
352
  # Parse response
345
353
  login_response_object = JSON.parse(login_response)
346
- raise InvalidAuthenticationException unless login_response_object['token']
354
+ fail InvalidAuthenticationException unless login_response_object['token']
347
355
 
348
356
  debug("Received token: #{login_response_object['token']}")
349
357
  login_response_object['token']
350
358
  rescue Exception => e
351
359
  response_code = login_response.nil? ? 0 : login_response.code ######## mackmm145
352
- if login_attempts < 100 && (e.inspect.include?("No such host is known.") || response_code == 523)
360
+ if login_attempts < 100 && (e.inspect.include?('No such host is known.') || response_code == 523)
353
361
  debug("Login failed! Reattempting in 5 seconds. #{100 - login_attempts} attempts remaining.")
354
362
  debug("Error was: #{e.inspect}")
355
363
  sleep 5
@@ -360,44 +368,46 @@ module Discordrb
360
368
 
361
369
  # Apparently we get a 400 if the password or username is incorrect. In that case, tell the user
362
370
  debug("Are you sure you're using the correct username and password?") if e.class == RestClient::BadRequest
363
- raise $!
371
+ raise $ERROR_INFO
364
372
  end
365
373
  end
366
374
 
367
- def get_gateway
375
+ def find_gateway
368
376
  # Get updated websocket_hub
369
377
  response = API.gateway(@token)
370
- JSON.parse(response)["url"]
378
+ JSON.parse(response)['url']
371
379
  end
372
380
 
373
381
  def websocket_connect
374
- debug("Attempting to get gateway URL...")
375
- websocket_hub = get_gateway
382
+ debug('Attempting to get gateway URL...')
383
+ websocket_hub = find_gateway
376
384
  debug("Success! Gateway URL is #{websocket_hub}.")
377
- debug("Now running bot")
385
+ debug('Now running bot')
378
386
 
379
- EM.run {
387
+ EM.run do
380
388
  @ws = Faye::WebSocket::Client.new(websocket_hub)
381
389
 
382
- @ws.on :open do |event|; websocket_open(event); end
383
- @ws.on :message do |event|; websocket_message(event); end
384
- @ws.on :error do |event|; debug(event.message); end
385
- @ws.on :close do |event|; websocket_close(event); @ws = nil; end
386
- }
390
+ @ws.on(:open) { |event| websocket_open(event) }
391
+ @ws.on(:message) { |event| websocket_message(event) }
392
+ @ws.on(:error) { |event| debug(event.message) }
393
+ @ws.on :close do |event|
394
+ websocket_close(event)
395
+ @ws = nil
396
+ end
397
+ end
387
398
  end
388
399
 
389
400
  def websocket_message(event)
390
- begin
391
401
  debug("Received packet #{event.data}")
392
402
 
393
403
  # Parse packet
394
404
  packet = JSON.parse(event.data)
395
405
 
396
- raise "Invalid Packet" unless packet['op'] == 0 # TODO
406
+ fail 'Invalid Packet' unless packet['op'] == 0 # TODO
397
407
 
398
408
  data = packet['d']
399
409
  case packet['t']
400
- when "READY"
410
+ when 'READY'
401
411
  # Activate the heartbeats
402
412
  @heartbeat_interval = data['heartbeat_interval'].to_f / 1000.0
403
413
  @heartbeat_active = true
@@ -412,12 +422,12 @@ module Discordrb
412
422
  @servers[server.id] = server
413
423
 
414
424
  # Initialize users
415
- server.members.each do |element|
416
- unless @users[element.id]
417
- @users[element.id] = element
418
- else
425
+ server.members.each do |member|
426
+ if @users[member.id]
419
427
  # If the user is already cached, just add the new roles
420
- @users[element.id].merge_roles(server, element.roles[server.id])
428
+ @users[member.id].merge_roles(server, member.roles[server.id])
429
+ else
430
+ @users[member.id] = member
421
431
  end
422
432
  end
423
433
 
@@ -435,7 +445,10 @@ module Discordrb
435
445
 
436
446
  # Make sure to raise the event
437
447
  raise_event(ReadyEvent.new)
438
- when "MESSAGE_CREATE"
448
+
449
+ # Tell the run method that everything was successful
450
+ @ws_success = true
451
+ when 'MESSAGE_CREATE'
439
452
  create_message(data)
440
453
 
441
454
  message = Message.new(data, self)
@@ -446,84 +459,83 @@ module Discordrb
446
459
  event = MentionEvent.new(message, self)
447
460
  raise_event(event)
448
461
  end
449
- when "TYPING_START"
462
+ when 'TYPING_START'
450
463
  start_typing(data)
451
464
 
452
465
  event = TypingEvent.new(data, self)
453
466
  raise_event(event)
454
- when "PRESENCE_UPDATE"
467
+ when 'PRESENCE_UPDATE'
455
468
  update_presence(data)
456
469
 
457
470
  event = PresenceEvent.new(data, self)
458
471
  raise_event(event)
459
- when "VOICE_STATE_UPDATE"
472
+ when 'VOICE_STATE_UPDATE'
460
473
  update_voice_state(data)
461
474
 
462
475
  event = VoiceStateUpdateEvent.new(data, self)
463
476
  raise_event(event)
464
- when "CHANNEL_CREATE"
477
+ when 'CHANNEL_CREATE'
465
478
  create_channel(data)
466
479
 
467
480
  event = ChannelCreateEvent.new(data, self)
468
481
  raise_event(event)
469
- when "CHANNEL_UPDATE"
482
+ when 'CHANNEL_UPDATE'
470
483
  update_channel(data)
471
484
 
472
485
  event = ChannelUpdateEvent.new(data, self)
473
486
  raise_event(event)
474
- when "CHANNEL_DELETE"
487
+ when 'CHANNEL_DELETE'
475
488
  delete_channel(data)
476
489
 
477
490
  event = ChannelDeleteEvent.new(data, self)
478
491
  raise_event(event)
479
- when "GUILD_MEMBER_UPDATE"
492
+ when 'GUILD_MEMBER_UPDATE'
480
493
  update_guild_member(data)
481
494
 
482
495
  event = GuildMemberUpdateEvent.new(data, self)
483
496
  raise_event(event)
484
- when "GUILD_ROLE_UPDATE"
497
+ when 'GUILD_ROLE_UPDATE'
485
498
  update_guild_role(data)
486
499
 
487
500
  event = GuildRoleUpdateEvent.new(data, self)
488
501
  raise_event(event)
489
- when "GUILD_ROLE_CREATE"
502
+ when 'GUILD_ROLE_CREATE'
490
503
  create_guild_role(data)
491
504
 
492
505
  event = GuildRoleCreateEvent.new(data, self)
493
506
  raise_event(event)
494
- when "GUILD_ROLE_DELETE"
507
+ when 'GUILD_ROLE_DELETE'
495
508
  delete_guild_role(data)
496
509
 
497
510
  event = GuildRoleDeleteEvent.new(data, self)
498
511
  raise_event(event)
499
512
  end
500
- rescue Exception => e
501
- debug("Exception: #{e.inspect}", true)
502
- e.backtrace.each {|line| debug(line) }
503
- end
513
+ rescue Exception => e
514
+ debug("Exception: #{e.inspect}", true)
515
+ e.backtrace.each { |line| debug(line) }
504
516
  end
505
517
 
506
518
  def websocket_close(event)
507
- debug("Disconnected from WebSocket!")
519
+ debug('Disconnected from WebSocket!')
508
520
  debug(" (Reason: #{event.reason})")
509
521
  debug(" (Code: #{event.code})")
510
522
  raise_event(DisconnectEvent.new)
511
523
  EM.stop
512
524
  end
513
525
 
514
- def websocket_open(event)
526
+ def websocket_open(_)
515
527
  # Send the initial packet
516
528
  packet = {
517
- "op" => 2, # Packet identifier
518
- "d" => { # Packet data
519
- "v" => 2, # Another identifier
520
- "token" => @token,
521
- "properties" => { # I'm unsure what these values are for exactly, but they don't appear to impact bot functionality in any way.
522
- "$os" => "#{RUBY_PLATFORM}",
523
- "$browser" => "discordrb",
524
- "$device" => "discordrb",
525
- "$referrer" => "",
526
- "$referring_domain" => ""
529
+ 'op' => 2, # Packet identifier
530
+ 'd' => { # Packet data
531
+ 'v' => 2, # Another identifier
532
+ 'token' => @token,
533
+ 'properties' => { # I'm unsure what these values are for exactly, but they don't appear to impact bot functionality in any way.
534
+ '$os' => "#{RUBY_PLATFORM}",
535
+ '$browser' => 'discordrb',
536
+ '$device' => 'discordrb',
537
+ '$referrer' => '',
538
+ '$referring_domain' => ''
527
539
  }
528
540
  }
529
541
  }
@@ -550,7 +562,7 @@ module Discordrb
550
562
  end
551
563
 
552
564
  def send_heartbeat
553
- millis = Time.now.strftime("%s%L").to_i
565
+ millis = Time.now.strftime('%s%L').to_i
554
566
  debug("Sending heartbeat at #{millis}")
555
567
  data = {
556
568
  'op' => 1,
@@ -568,13 +580,13 @@ module Discordrb
568
580
 
569
581
  def event_class(handler_class)
570
582
  class_name = handler_class.to_s
571
- return nil unless class_name.end_with? "Handler"
583
+ return nil unless class_name.end_with? 'Handler'
572
584
 
573
585
  class_from_string(class_name[0..-8])
574
586
  end
575
587
 
576
588
  def handler_class(event_class)
577
- class_from_string(event_class.to_s + "Handler")
589
+ class_from_string(event_class.to_s + 'Handler')
578
590
  end
579
591
  end
580
592
  end