discordrb 1.4.0 → 1.4.1

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: 1318b8f7407048d6ba422c2d3732ed9536fdb56d
4
- data.tar.gz: d7f68a7d482a60a961c61c96c23c3a34592014e6
3
+ metadata.gz: ad6998ddf964b9fbb9898312e7d41d503a207bff
4
+ data.tar.gz: c2bfb298aacd612fee0800f8f1ff434fc0cfe90c
5
5
  SHA512:
6
- metadata.gz: 8063043dce37200550f85b17d8a521e5da6f9f16c31d2663d5d7d0a2b64ac918644d7124e00a19e5acc50fc6a6fe00b537adae056a0e3b2b72b40395a26c6eb5
7
- data.tar.gz: 5b2719cfb5f73cffe7b34957d9ca957766d7c277f57d951ffe2ad9af8ec1fc95af54c193032a4f7a4c0c832475f2227a1410e6351b37ddf22ac4d53f63e993dc
6
+ metadata.gz: cfcf66d6d21815e39b66b9dfdc1508abfd2f22e11e0d435073aa9d7de45dec0dcef62fb6a50f1921d28ddadd3e8e5c4972364e70a65813bb2284859f305b685d
7
+ data.tar.gz: f43645f7d126eda651ee82027eb829b7b66e6661b4fe81a6283d81b7935bcb7305e66a7d7614c03af4355a5b6e6b05f71396aae1c720f949a1c36fd20a2c4311
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown
data/discordrb.gemspec CHANGED
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency 'rest-client'
24
24
  spec.add_dependency 'activesupport'
25
25
 
26
+ spec.required_ruby_version = '>= 2.1.0'
27
+
26
28
  spec.add_development_dependency 'bundler', '~> 1.10'
27
29
  spec.add_development_dependency 'rake', '~> 10.0'
28
30
  end
data/lib/discordrb/api.rb CHANGED
@@ -3,6 +3,7 @@ require 'json'
3
3
 
4
4
  # List of methods representing endpoints in Discord's API
5
5
  module Discordrb::API
6
+ # The base URL of the Discord REST API.
6
7
  APIBASE = 'https://discordapp.com/api'
7
8
 
8
9
  module_function
@@ -1,8 +1,29 @@
1
1
  module Discordrb
2
- # Class that represents an await to wait for a further event
2
+ # Awaits are a way to register new, temporary event handlers on the fly. Awaits can be
3
+ # registered using {Bot#add_await}, {User#await}, {Message#await} and {Channel#await}.
4
+ #
5
+ # Awaits contain a block that will be called before the await event will be triggered.
6
+ # If this block returns anything that is not `false` exactly, the await will be deleted.
7
+ # If no block is present, the await will also be deleted. This is an easy way to make
8
+ # temporary events that are only temporary under certain conditions.
9
+ #
10
+ # Besides the given block, an {AwaitEvent} will also be executed with the key and
11
+ # the type of the await that was triggered. It's possible to register multiple events
12
+ # that trigger on the same await.
3
13
  class Await
4
- attr_reader :key, :type, :attributes
14
+ # The key that uniquely identifies this await.
15
+ # @return [Symbol] The unique key.
16
+ attr_reader :key
5
17
 
18
+ # The class of the event that this await listens for.
19
+ # @return [Class] The event class.
20
+ attr_reader :type
21
+
22
+ # The attributes of the event that will be listened for.
23
+ # @return [Hash] A hash of attributes.
24
+ attr_reader :attributes
25
+
26
+ # Makes a new await. For internal use only.
6
27
  def initialize(bot, key, type, attributes, block = nil)
7
28
  @bot = bot
8
29
  @key = key
@@ -11,6 +32,10 @@ module Discordrb
11
32
  @block = block
12
33
  end
13
34
 
35
+ # Checks whether the await can be triggered by the given event, and if it can, execute the block
36
+ # and return its result along with this await's key.
37
+ # @param event [Event] An event to check for.
38
+ # @return [Array] This await's key and whether or not it should be deleted. If there was no match, both are nil.
14
39
  def match(event)
15
40
  dummy_handler = @bot.handler_class(@type).new(@attributes, @bot)
16
41
  return [nil, nil] unless dummy_handler.matches?(event)
data/lib/discordrb/bot.rb CHANGED
@@ -28,9 +28,43 @@ module Discordrb
28
28
  class Bot
29
29
  include Discordrb::Events
30
30
 
31
- attr_reader :bot_user, :token, :users, :servers, :event_threads, :profile
31
+ # The user that represents the bot itself. This version will always be identical to
32
+ # the user determined by {#user} called with the bot's ID.
33
+ # @return [User] The bot user.
34
+ attr_reader :bot_user
35
+
36
+ # The Discord API token received when logging in. Useful to explicitly call
37
+ # {API} methods.
38
+ # @return [String] The API token.
39
+ attr_reader :token
40
+
41
+ # The list of users the bot shares a server with.
42
+ # @return [Array<User>] The users.
43
+ attr_reader :users
44
+
45
+ # The list of servers the bot is currently in.
46
+ # @return [Array<Server>] The servers.
47
+ attr_reader :servers
48
+
49
+ # The list of currently running threads used to parse and call events.
50
+ # The threads will have a local variable `:discordrb_name` in the format of `et-1234`, where
51
+ # "et" stands for "event thread" and the number is a continually incrementing number representing
52
+ # how many events were executed before.
53
+ # @return [Array<Thread>] The threads.
54
+ attr_reader :event_threads
55
+
56
+ # The bot's user profile. This special user object can be used
57
+ # to edit user data like the current username (see {Profile#username=}).
58
+ # @return [Profile] The bot's profile that can be used to edit data.
59
+ attr_reader :profile
60
+
61
+ # Whether or not the bot should parse its own messages. Off by default.
32
62
  attr_accessor :should_parse_self
33
63
 
64
+ # Makes a new bot with the given email and password. It will be ready to be added event handlers to and can eventually be run with {#run}.
65
+ # @param email [String] The email for your (or the bot's) Discord account.
66
+ # @param password [String] The valid password that should be used to log in to the account.
67
+ # @param debug [Boolean] Whether or not the bug should run in debug mode, which gives increased console output.
34
68
  def initialize(email, password, debug = false)
35
69
  # Make sure people replace the login details in the example files...
36
70
  if email.end_with? 'example.com'
@@ -57,6 +91,12 @@ module Discordrb
57
91
  @current_thread = 0
58
92
  end
59
93
 
94
+ # Runs the bot, which logs into Discord and connects the WebSocket. This prevents all further execution unless it is executed with `async` = `:async`.
95
+ # @param async [Symbol] If it is `:async`, then the bot will allow further execution.
96
+ # It doesn't necessarily have to be that, anything truthy will work,
97
+ # however it is recommended to use `:async` for code readability reasons.
98
+ # If the bot is run in async mode, make sure to eventually run {#sync} so
99
+ # the script doesn't stop prematurely.
60
100
  def run(async = false)
61
101
  run_async
62
102
  return if async
@@ -93,14 +133,20 @@ module Discordrb
93
133
  debug('Confirmation received! Exiting run.')
94
134
  end
95
135
 
136
+ # Prevents all further execution until the websocket thread stops (e. g. through a closed connection).
96
137
  def sync
97
138
  @ws_thread.join
98
139
  end
99
140
 
141
+ # Kills the websocket thread, stopping all connections to Discord.
100
142
  def stop
101
143
  @ws_thread.kill
102
144
  end
103
145
 
146
+ # Gets a channel given its ID. This queries the internal channel cache, and if the channel doesn't
147
+ # exist in there, it will get the data from Discord.
148
+ # @param id [Integer] The channel ID for which to search for.
149
+ # @return [Channel] The channel identified by the ID.
104
150
  def channel(id)
105
151
  debug("Obtaining data for channel with id #{id}")
106
152
  return @channels[id] if @channels[id]
@@ -110,6 +156,11 @@ module Discordrb
110
156
  @channels[id] = channel
111
157
  end
112
158
 
159
+ # Creates a private channel for the given user ID, or if one exists already, returns that one.
160
+ # It is recommended that you use {User#pm} instead, as this is mainly for internal use. However,
161
+ # usage of this method may be unavoidable if only the user ID is known.
162
+ # @param id [Integer] The user ID to generate a private channel for.
163
+ # @return [Channel] A private channel for that user.
113
164
  def private_channel(id)
114
165
  debug("Creating private channel with user id #{id}")
115
166
  return @private_channels[id] if @private_channels[id]
@@ -119,31 +170,61 @@ module Discordrb
119
170
  @private_channels[id] = channel
120
171
  end
121
172
 
173
+ # Gets the code for an invite.
174
+ # @param invite [String, Invite] The invite to get the code for. Possible formats are:
175
+ #
176
+ # * An {Invite} object
177
+ # * The code for an invite
178
+ # * A fully qualified invite URL (e. g. `https://discordapp.com/invite/0A37aN7fasF7n83q`)
179
+ # * A short invite URL with protocol (e. g. `https://discord.gg/0A37aN7fasF7n83q`)
180
+ # * A short invite URL without protocol (e. g. `discord.gg/0A37aN7fasF7n83q`)
181
+ # @return [String] Only the code for the invite.
122
182
  def resolve_invite_code(invite)
123
183
  invite = invite.code if invite.is_a? Discordrb::Invite
124
184
  invite = invite[invite.rindex('/') + 1..-1] if invite.start_with?('http') || invite.start_with?('discord.gg')
125
185
  invite
126
186
  end
127
187
 
188
+ # Makes the bot join an invite to a server.
189
+ # @param invite [String, Invite] The invite to join. For possible formats see {#resolve_invite_code}.
128
190
  def join(invite)
129
191
  invite = resolve_invite_code(invite)
130
192
  resolved = JSON.parse(API.resolve_invite(@token, invite))['code']
131
193
  API.join_server(@token, resolved)
132
194
  end
133
195
 
196
+ # Revokes an invite to a server. Will fail unless you have the *Manage Server* permission.
197
+ # It is recommended that you use {Invite#delete} instead.
198
+ # @param code [String, Invite] The invite to revoke. For possible formats see {#resolve_invite_code}.
134
199
  def delete_invite(code)
135
200
  invite = resolve_invite_code(code)
136
201
  API.delete_invite(@token, invite)
137
202
  end
138
203
 
204
+ # Gets a user by its ID.
205
+ # @note This can only resolve users known by the bot (i.e. that share a server with the bot).
206
+ # @param id [Integer] The user ID that should be resolved.
207
+ # @return [User, nil] The user identified by the ID, or `nil` if it couldn't be found.
139
208
  def user(id)
140
209
  @users[id]
141
210
  end
142
211
 
212
+ # Gets a server by its ID.
213
+ # @note This can only resolve servers the bot is currently in.
214
+ # @param id [Integer] The server ID that should be resolved.
215
+ # @return [Server, nil] The server identified by the ID, or `nil` if it couldn't be found.
143
216
  def server(id)
144
217
  @servers[id]
145
218
  end
146
219
 
220
+ # Finds a channel given its name and optionally the name of the server it is in. If the threshold
221
+ # is not 0, it will use a Levenshtein distance function to find the channel in a fuzzy way, which
222
+ # allows slight misspellings.
223
+ # @param channel_name [String] The channel to search for.
224
+ # @param server_name [String] The server to search for, or `nil` if only the channel should be searched for.
225
+ # @param threshold [Integer] The threshold for the Levenshtein algorithm. The larger
226
+ # the threshold is, the more misspellings will be allowed.
227
+ # @return [Array<Channel>] The array of channels that were found. May be empty if none were found.
147
228
  def find(channel_name, server_name = nil, threshold = 0)
148
229
  require 'levenshtein'
149
230
 
@@ -165,23 +246,51 @@ module Discordrb
165
246
  results
166
247
  end
167
248
 
249
+ # Sends a text message to a channel given its ID and the message's content.
250
+ # @param channel_id [Integer] The ID that identifies the channel to send something to.
251
+ # @param content [String] The text that should be sent as a message. It is limited to 2000 characters (Discord imposed).
252
+ # @return [Message] The message that was sent.
168
253
  def send_message(channel_id, content)
169
254
  debug("Sending message to #{channel_id} with content '#{content}'")
170
255
  response = API.send_message(@token, channel_id, content)
171
256
  Message.new(JSON.parse(response), self)
172
257
  end
173
258
 
259
+ # Sends a file to a channel. If it is an image, it will automatically be embedded.
260
+ # @note This executes in a blocking way, so if you're sending long files, be wary of delays.
261
+ # @param channel_id [Integer] The ID that identifies the channel to send something to.
262
+ # @param file [File] The file that should be sent.
174
263
  def send_file(channel_id, file)
175
264
  API.send_file(@token, channel_id, file)
176
265
  end
177
266
 
267
+ # Add an await the bot should listen to. For information on awaits, see {Await}.
268
+ # @param key [Symbol] The key that uniquely identifies the await for {AwaitEvent}s to listen to (see {#await}).
269
+ # @param type [Class] The event class that should be listened for.
270
+ # @param attributes [Hash] The attributes the event should check for. The block will only be executed if all attributes match.
271
+ # @yield Is executed when the await is triggered.
272
+ # @yieldparam event [Event] The event object that was triggered.
273
+ # @return [Await] The await that was created.
178
274
  def add_await(key, type, attributes = {}, &block)
179
275
  fail "You can't await an AwaitEvent!" if type == Discordrb::Events::AwaitEvent
180
276
  await = Await.new(self, key, type, attributes, block)
181
277
  @awaits[key] = await
182
278
  end
183
279
 
184
- # Regions: :london, :amsterdam, :frankfurt, :us-east, :us-west, :singapore, :sydney
280
+ # Creates a server on Discord with a specified name and a region.
281
+ # @note Discord's API doesn't directly return the server when creating it, so this method
282
+ # waits until the data has been received via the websocket. This may make the execution take a while.
283
+ # @param name [String] The name the new server should have. Doesn't have to be alphanumeric.
284
+ # @param region [Symbol] The region where the server should be created. Possible regions are:
285
+ #
286
+ # * `:london`
287
+ # * `:amsterdam`
288
+ # * `:frankfurt`
289
+ # * `:us-east`
290
+ # * `:us-west`
291
+ # * `:singapore`
292
+ # * `:sydney`
293
+ # @return [Server] The server that was created.
185
294
  def create_server(name, region = :london)
186
295
  response = API.create_server(@token, name, region)
187
296
  id = JSON.parse(response)['id'].to_i
@@ -191,12 +300,18 @@ module Discordrb
191
300
  server
192
301
  end
193
302
 
303
+ # Gets the user from a mention of the user.
304
+ # @param mention [String] The mention, which should look like <@12314873129>.
305
+ # @return [User] The user identified by the mention, or `nil` if none exists.
194
306
  def parse_mention(mention)
195
307
  # Mention format: <@id>
196
308
  return nil unless /\<@(?<id>\d+)\>?/ =~ mention
197
309
  user(id)
198
310
  end
199
311
 
312
+ # Sets the currently playing game to the specified game.
313
+ # @param name_or_id [String, Fixnum] The name or the ID of the game to be played.
314
+ # @return [Game] The game object that is being played now.
200
315
  def game=(name_or_id)
201
316
  game = Discordrb::Games.find_game(name_or_id)
202
317
  @game = game
@@ -213,6 +328,7 @@ module Discordrb
213
328
  game
214
329
  end
215
330
 
331
+ # Sets debug mode. If debug mode is on, many things will be outputted to STDOUT.
216
332
  attr_writer :debug
217
333
 
218
334
  ## ## ### ## ## ######## ## ######## ######## ######
@@ -223,6 +339,21 @@ module Discordrb
223
339
  ## ## ## ## ## ### ## ## ## ## ## ## ## ##
224
340
  ## ## ## ## ## ## ######## ######## ######## ## ## ######
225
341
 
342
+ # This **event** is raised when a message is sent to a text channel the bot is currently in.
343
+ # @param attributes [Hash] The event's attributes.
344
+ # @option attributes [String, Regexp] :start_with Matches the string the message starts with.
345
+ # @option attributes [String, Regexp] :end_with Matches the string the message ends with.
346
+ # @option attributes [String, Regexp] :contains Matches a string the message contains.
347
+ # @option attributes [String, Integer, Channel] :in Matches the channel the message was sent in.
348
+ # @option attributes [String, Integer, User] :from Matches the user that sent the message.
349
+ # @option attributes [String] :content Exactly matches the entire content of the message.
350
+ # @option attributes [String] :content Exactly matches the entire content of the message.
351
+ # @option attributes [Time] :after Matches a time after the time the message was sent at.
352
+ # @option attributes [Time] :before Matches a time before the time the message was sent at.
353
+ # @option attributes [Boolean] :private Matches whether or not the channel is private.
354
+ # @yield The block is executed when the event is raised.
355
+ # @yieldparam event [MessageEvent] The event that was raised.
356
+ # @return [MessageEventHandler] The event handler that was registered.
226
357
  def message(attributes = {}, &block)
227
358
  register_event(MessageEvent, attributes, block)
228
359
  end
@@ -308,6 +439,14 @@ module Discordrb
308
439
  register_event(GuildDeleteEvent, attributes, block)
309
440
  end
310
441
 
442
+ # This **event** is raised when an {Await} is triggered. It provides an easy way to execute code
443
+ # on an await without having to rely on the await's block.
444
+ # @param attributes [Hash] The event's attributes.
445
+ # @option attributes [Symbol] :key Exactly matches the await's key.
446
+ # @option attributes [Class] :type Exactly matches the event's type.
447
+ # @yield The block is executed when the event is raised.
448
+ # @yieldparam event [AwaitEvent] The event that was raised.
449
+ # @return [AwaitEventHandler] The event handler that was registered.
311
450
  def await(attributes = {}, &block)
312
451
  register_event(AwaitEvent, attributes, block)
313
452
  end
@@ -22,7 +22,8 @@ module Discordrb::Commands
22
22
  help_command: attributes[:help_command] || :help,
23
23
 
24
24
  # The message to display for when a command doesn't exist, %command% to get the command name in question and nil for no message
25
- command_doesnt_exist_message: attributes[:command_doesnt_exist_message] || "The command `%command%` doesn't exist!",
25
+ # No default value here because it may not be desired behaviour
26
+ command_doesnt_exist_message: attributes[:command_doesnt_exist_message],
26
27
 
27
28
  # All of the following need to be one character
28
29
  # String to designate previous result in command chain
@@ -129,7 +130,7 @@ module Discordrb::Commands
129
130
  debug("Parsing command chain #{chain}")
130
131
  result = (@attributes[:advanced_functionality]) ? CommandChain.new(chain, self).execute(event) : simple_execute(chain, event)
131
132
  result = event.saved_message + (result || '')
132
- event.respond result if result
133
+ event.respond result unless result.nil? || result.empty?
133
134
  rescue => e
134
135
  log_exception(e)
135
136
  ensure
@@ -2,11 +2,18 @@ require 'discordrb/events/generic'
2
2
  require 'discordrb/await'
3
3
 
4
4
  module Discordrb::Events
5
- # Event raised when an await is triggered
5
+ # @see Bot#await
6
6
  class AwaitEvent
7
- attr_reader :await, :event
7
+ # The await that was triggered.
8
+ # @return [Await] The await
9
+ attr_reader :await
10
+
11
+ # The event that triggered the await.
12
+ # @return [Event] The event
13
+ attr_reader :event
8
14
  delegate :key, :type, :attributes, to: :await
9
15
 
16
+ # For internal use only
10
17
  def initialize(await, event, bot)
11
18
  @await = await
12
19
  @event = event
@@ -14,7 +21,7 @@ module Discordrb::Events
14
21
  end
15
22
  end
16
23
 
17
- # Event handler for AwaitEvent
24
+ # Event handler for {AwaitEvent}
18
25
  class AwaitEventHandler < EventHandler
19
26
  def matches?(event)
20
27
  # Check for the proper event type
@@ -1,4 +1,4 @@
1
1
  # Discordrb and all its functionality, in this case only the version.
2
2
  module Discordrb
3
- VERSION = '1.4.0'
3
+ VERSION = '1.4.1'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: discordrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - meew0
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-12-04 00:00:00.000000000 Z
11
+ date: 2015-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faye-websocket
@@ -91,6 +91,7 @@ files:
91
91
  - ".rspec"
92
92
  - ".rubocop.yml"
93
93
  - ".travis.yml"
94
+ - ".yardopts"
94
95
  - Gemfile
95
96
  - LICENSE.txt
96
97
  - README.md
@@ -142,7 +143,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
143
  requirements:
143
144
  - - ">="
144
145
  - !ruby/object:Gem::Version
145
- version: '0'
146
+ version: 2.1.0
146
147
  required_rubygems_version: !ruby/object:Gem::Requirement
147
148
  requirements:
148
149
  - - ">="