discordrb 3.1.1 → 3.2.0
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 +4 -4
- data/.codeclimate.yml +16 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +9 -0
- data/.travis.yml +2 -1
- data/CHANGELOG.md +49 -0
- data/CONTRIBUTING.md +13 -0
- data/Gemfile +6 -1
- data/README.md +2 -0
- data/Rakefile +12 -1
- data/discordrb-webhooks.gemspec +25 -0
- data/discordrb.gemspec +6 -4
- data/lib/discordrb/api.rb +5 -0
- data/lib/discordrb/api/channel.rb +74 -6
- data/lib/discordrb/api/server.rb +37 -0
- data/lib/discordrb/bot.rb +116 -29
- data/lib/discordrb/commands/command_bot.rb +93 -9
- data/lib/discordrb/commands/container.rb +3 -0
- data/lib/discordrb/commands/parser.rb +45 -29
- data/lib/discordrb/commands/rate_limiter.rb +7 -9
- data/lib/discordrb/container.rb +126 -26
- data/lib/discordrb/data.rb +264 -36
- data/lib/discordrb/events/generic.rb +18 -2
- data/lib/discordrb/events/guilds.rb +117 -2
- data/lib/discordrb/events/message.rb +7 -5
- data/lib/discordrb/events/presence.rb +4 -12
- data/lib/discordrb/events/raw.rb +49 -0
- data/lib/discordrb/events/reactions.rb +104 -0
- data/lib/discordrb/events/typing.rb +4 -2
- data/lib/discordrb/events/voice_state_update.rb +17 -2
- data/lib/discordrb/gateway.rb +75 -17
- data/lib/discordrb/permissions.rb +5 -3
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/encoder.rb +2 -5
- data/lib/discordrb/voice/network.rb +2 -2
- data/lib/discordrb/voice/voice_bot.rb +5 -6
- data/lib/discordrb/webhooks.rb +12 -0
- metadata +35 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 337ea47519caa85873b29fa6a7ac2a77157cbdb1
|
4
|
+
data.tar.gz: 3e605cffe66fa9e5604cc4fd0832f00de8648700
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 938fcccefe4d46b647355c3500ca04bce24718aa01f60fabecdffec22801c17f9e3629629615682cd9ee2e070ad92858bcbac00cf76ce821fd88bab310baa7f5
|
7
|
+
data.tar.gz: c68a60e989731a168002f87bda571acdff25b8bda65cc2fea32f14fb05ed7056008b9c05428e1d9b844d3eeb1f049947d029c784aa7bce6a7678ceb9f2a6237a
|
data/.codeclimate.yml
ADDED
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -5,6 +5,9 @@ Metrics/AbcSize:
|
|
5
5
|
Metrics/BlockNesting:
|
6
6
|
Enabled: false
|
7
7
|
|
8
|
+
Metrics/BlockLength:
|
9
|
+
Enabled: false
|
10
|
+
|
8
11
|
Metrics/ClassLength:
|
9
12
|
Enabled: false
|
10
13
|
|
@@ -38,6 +41,12 @@ Style/ConstantName:
|
|
38
41
|
Lint/RescueException:
|
39
42
|
Enabled: false
|
40
43
|
|
44
|
+
# Prefer |m, e| for the `reduce` block arguments
|
45
|
+
Style/SingleLineBlockParams:
|
46
|
+
Methods:
|
47
|
+
- reduce: [m, e]
|
48
|
+
- inject: [m, e]
|
49
|
+
|
41
50
|
AllCops:
|
42
51
|
TargetRubyVersion: 2.1
|
43
52
|
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,54 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 3.2.0
|
4
|
+
|
5
|
+
- Various parts of gateway error handling were improved, leading to significant stability improvements:
|
6
|
+
- A long standing bug was fixed that prevented resumes in most cases, which caused unnecessary reconnections.
|
7
|
+
- The error handler that handles problems with sending the raw data over TCP now catches errors more broadly.
|
8
|
+
- Heartbeat ACKs (opcode 11) are now checked, which allows the client to detect zombie connections early on. If this causes problems for you you can disable it using `bot.gateway.check_heartbeat_acks = false`.
|
9
|
+
- Received heartbeats are now properly handled again
|
10
|
+
- Added a client for webhooks, implemented as a separate gem `discordrb-webhooks`. This allows the creation of applications that only use webhooks without the overhead provided by the rest of discordrb. The gem is added as a dependency by normal discordrb so you don't need to install it separately if you're already using that.
|
11
|
+
- Adding, updating or deleting custom emoji is now supported ([#285](https://github.com/meew0/discordrb/pull/285), thanks @Daniel-Worrall)
|
12
|
+
- Rich embeds can now be sent alongside messages, for example using the `embed` parameter in `send_message`, or with the new method `Channel#send_embed`
|
13
|
+
- `advanced_functionality` bots now support escaping using backslashes ([#293](https://github.com/meew0/discordrb/issues/293) / [#304](https://github.com/meew0/discordrb/pull/304), thanks @LikeLakers2)
|
14
|
+
- Added type checking and conversion for commands ([#298](https://github.com/meew0/discordrb/pull/298), thanks @ohtaavi)
|
15
|
+
- Bulk deleting messages now checks for message age (see also [hammerandchisel/discord-api-docs#208](https://github.com/hammerandchisel/discord-api-docs/issues/208)). By default, it will ignore messages that are too old to be bulk deleted, but there is also a `strict` mode setting now that raises an exception in such a case.
|
16
|
+
- Reactions can now be viewed for existing messages ([#262](https://github.com/meew0/discordrb/pull/262), thanks @z64), added to messages ([#266](https://github.com/meew0/discordrb/pull/266), thanks @z64), and listened for using gateway events as well as internal handlers ([#300](https://github.com/meew0/discordrb/issues/300)).
|
17
|
+
- Game types and stream URLs are now cached ([#297](https://github.com/meew0/discordrb/issues/297))
|
18
|
+
- The default non-streaming game was changed to be `0` instead of `nil` ([#277](https://github.com/meew0/discordrb/pull/277), thanks @zeyla)
|
19
|
+
- A method `Channel#delete_message` was added to support deleting single messages by ID without prior resolution.
|
20
|
+
- Permission overwrites can now be deleted from channels ([#268](https://github.com/meew0/discordrb/pull/268), thanks @greenbigfrog)
|
21
|
+
- There is now a utility method `IDObject.synthesise` that creates snowflakes with specific timestamps out of thin air.
|
22
|
+
- Typing events are now respondable, so you can call `#respond` on them for example ([#270](https://github.com/meew0/discordrb/pull/270), thanks @VxJasonxV)
|
23
|
+
- Message authors can now be `User` objects if a `Member` object could not be found or created ([#290](https://github.com/meew0/discordrb/issues/290))
|
24
|
+
- Added two new events, `unknown` ([#288](https://github.com/meew0/discordrb/issues/288)) and `raw`, that are raised for unknown dispatches and all dispatches, respectively.
|
25
|
+
- Bots can now be set to fully ignore other bots ([#257](https://github.com/meew0/discordrb/pull/257), thanks @greenbigfrog)
|
26
|
+
- Voice state update events now have an `old_channel` property/attribute that denotes the previous channel the user was in in case of joining/moving/leaving.
|
27
|
+
- The default help command no longer shows commands the user can't use ([#275](https://github.com/meew0/discordrb/pull/275), thanks @FormalHellhound)
|
28
|
+
- Updated the command example to no longer include user-specific stuff ([#260](https://github.com/meew0/discordrb/issues/260))
|
29
|
+
- `Server#role` now resolves IDs, so they can be passed as strings if necessary.
|
30
|
+
|
31
|
+
### Bugfixes
|
32
|
+
|
33
|
+
- Fixed bots' shard settings being ignored in certain cases
|
34
|
+
- Parsing role mentions using `Bot#parse_mention` works properly now.
|
35
|
+
- Fixed some specific REST methods that were broken by the API module refactor ([#302](https://github.com/meew0/discordrb/pull/302), thanks @LikeLakers2)
|
36
|
+
- Cached channel data is now updated properly on change ([#272](https://github.com/meew0/discordrb/issues/272))
|
37
|
+
- Users' avatars are now updated properly on change ([#265](https://github.com/meew0/discordrb/pull/265), thanks @Roughsketch)
|
38
|
+
- Fixed voice state tracking for newly created channels ([#292](https://github.com/meew0/discordrb/issues/292))
|
39
|
+
- Fixed event attribute handling for PlayingEvent ([#303](https://github.com/meew0/discordrb/pull/303), thanks @sven-strothoff)
|
40
|
+
- Getting specific emoji by ID no longer fails to resolve non-cached emoji ([#283](https://github.com/meew0/discordrb/pull/283), thanks @greenbigfrog)
|
41
|
+
- Voice state update events no longer fail to be raised for users leaving channels, if the event handler had a channel attribute set ([#301](https://github.com/meew0/discordrb/issues/301))
|
42
|
+
- Bots that don't define any events should work properly again
|
43
|
+
- Fixed error handling for messages over the character limit ([#276](https://github.com/meew0/discordrb/issues/276))
|
44
|
+
- Fixed some specific log messages not being called properly ([#263](https://github.com/meew0/discordrb/pull/263), thanks @Roughsketch)
|
45
|
+
- Fixed some edge case bugs in the default help command:
|
46
|
+
- In the case of too many commands to be sent in the channel, it no longer replies with "Sending help in PM!" when called from PM
|
47
|
+
- It no longer fails completely if called from PM if there are any commands that require server-specific checks ([#308](https://github.com/meew0/discordrb/issues/308))
|
48
|
+
- Fixed a slight formatting mistake
|
49
|
+
- Quoted command arguments in `advanced_functionality` are no longer split by newline
|
50
|
+
- Fixed a specific edge case in command chain handling where handling commands with the same name as the chain delimiter was broken
|
51
|
+
|
3
52
|
## 3.1.1
|
4
53
|
|
5
54
|
*Bugfix-only release.*
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributing guidelines
|
2
|
+
|
3
|
+
Any contributions are very much appreciated! This project is relatively relaxed when it comes to guidelines, however
|
4
|
+
there are still some things that would be nice to have considered.
|
5
|
+
|
6
|
+
For bug reports, please try to include a code sample if at all appropriate for
|
7
|
+
the issue, so we can reproduce it on our own machines.
|
8
|
+
|
9
|
+
For PRs, please make sure that you tested your code before every push; it's a little annoying to keep having to get back
|
10
|
+
to a PR because of small avoidable oversights. (Huge bonus points if you're adding specs for your code! This project
|
11
|
+
has very few specs in places where it should have more so every added spec is very much appreciated.)
|
12
|
+
|
13
|
+
If you have any questions at all, don't be afraid to ask in the [discordrb channel on Discord](https://discord.gg/0SBTUU1wZTWfFQL2).
|
data/Gemfile
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
|
+
# Test coverage reporting for CodeClimate
|
4
|
+
gem 'codeclimate-test-reporter', group: :test, require: nil
|
5
|
+
gem 'simplecov', group: :test
|
6
|
+
|
3
7
|
# Specify your gem's dependencies in discordrb.gemspec
|
4
|
-
gemspec
|
8
|
+
gemspec name: 'discordrb'
|
9
|
+
gemspec name: 'discordrb-webhooks', development_group: 'webhooks'
|
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
[![Gem](https://img.shields.io/gem/dt/discordrb.svg)](https://rubygems.org/gems/discordrb)
|
3
3
|
[![Build Status](https://travis-ci.org/meew0/discordrb.svg?branch=master)](https://travis-ci.org/meew0/discordrb)
|
4
4
|
[![Inline docs](http://inch-ci.org/github/meew0/discordrb.svg?branch=master&style=shields)](http://inch-ci.org/github/meew0/discordrb)
|
5
|
+
[![Code Climate](https://codeclimate.com/github/meew0/discordrb/badges/gpa.svg)](https://codeclimate.com/github/meew0/discordrb)
|
6
|
+
[![Test Coverage](https://codeclimate.com/github/meew0/discordrb/badges/coverage.svg)](https://codeclimate.com/github/meew0/discordrb/coverage)
|
5
7
|
[![Join Discord](https://img.shields.io/badge/discord-join-7289DA.svg)](https://discord.gg/0SBTUU1wZTWfFQL2)
|
6
8
|
# discordrb
|
7
9
|
|
data/Rakefile
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
require 'bundler/
|
1
|
+
require 'bundler/gem_helper'
|
2
|
+
|
3
|
+
namespace :main do
|
4
|
+
Bundler::GemHelper.install_tasks(name: 'discordrb')
|
5
|
+
end
|
6
|
+
|
7
|
+
namespace :webhooks do
|
8
|
+
Bundler::GemHelper.install_tasks(name: 'discordrb-webhooks')
|
9
|
+
end
|
10
|
+
|
11
|
+
task build: [:'main:build', :'webhooks:build']
|
12
|
+
task release: [:'main:release', :'webhooks:release']
|
2
13
|
|
3
14
|
# Make "build" the default task
|
4
15
|
task default: :build
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'discordrb/webhooks/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'discordrb-webhooks'
|
8
|
+
spec.version = Discordrb::Webhooks::VERSION
|
9
|
+
spec.authors = ['meew0']
|
10
|
+
spec.email = ['']
|
11
|
+
|
12
|
+
spec.summary = 'Webhook client for discordrb'
|
13
|
+
spec.description = "A client for Discord's webhooks to fit alongside [discordrb](https://rubygems.org/gems/discordrb)."
|
14
|
+
spec.homepage = 'https://github.com/meew0/discordrb'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z lib/discordrb/webhooks/`.split("\x0") + ['lib/discordrb/webhooks.rb']
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'rest-client'
|
23
|
+
|
24
|
+
spec.required_ruby_version = '>= 2.1.0'
|
25
|
+
end
|
data/discordrb.gemspec
CHANGED
@@ -14,16 +14,17 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = 'https://github.com/meew0/discordrb'
|
15
15
|
spec.license = 'MIT'
|
16
16
|
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples)/}) }
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|examples|lib/discordrb/webhooks)/}) }
|
18
18
|
spec.bindir = 'exe'
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
22
|
spec.add_dependency 'rest-client'
|
23
|
-
spec.add_dependency 'activesupport'
|
24
23
|
spec.add_dependency 'opus-ruby'
|
25
24
|
spec.add_dependency 'websocket-client-simple', '>= 0.3.0'
|
26
|
-
spec.add_dependency 'rbnacl'
|
25
|
+
spec.add_dependency 'rbnacl', '~> 3.4.0' # 24: update
|
26
|
+
|
27
|
+
spec.add_dependency 'discordrb-webhooks'
|
27
28
|
|
28
29
|
spec.required_ruby_version = '>= 2.1.0'
|
29
30
|
|
@@ -31,5 +32,6 @@ Gem::Specification.new do |spec|
|
|
31
32
|
spec.add_development_dependency 'rake', '~> 10.0'
|
32
33
|
spec.add_development_dependency 'yard', '~> 0.8.7.6'
|
33
34
|
spec.add_development_dependency 'rspec', '~> 3.4.0'
|
34
|
-
spec.add_development_dependency '
|
35
|
+
spec.add_development_dependency 'rspec-prof', '~> 0.0.7'
|
36
|
+
spec.add_development_dependency 'rubocop', '0.45.0'
|
35
37
|
end
|
data/lib/discordrb/api.rb
CHANGED
@@ -137,6 +137,11 @@ module Discordrb::API
|
|
137
137
|
"#{api_base}/guilds/#{server_id}/widget.png?style=#{style}"
|
138
138
|
end
|
139
139
|
|
140
|
+
# Make a splash URL from server and splash IDs
|
141
|
+
def splash_url(server_id, splash_id)
|
142
|
+
"https://cdn.discordapp.com/splashes/#{server_id}/#{splash_id}.jpg"
|
143
|
+
end
|
144
|
+
|
140
145
|
# Make an emoji icon URL from emoji ID
|
141
146
|
def emoji_icon_url(emoji_id)
|
142
147
|
"https://cdn.discordapp.com/emojis/#{emoji_id}.png"
|
@@ -66,18 +66,20 @@ module Discordrb::API::Channel
|
|
66
66
|
|
67
67
|
# Send a message to a channel
|
68
68
|
# https://discordapp.com/developers/docs/resources/channel#create-message
|
69
|
-
def create_message(token, channel_id, message, mentions = [], tts = false,
|
69
|
+
def create_message(token, channel_id, message, mentions = [], tts = false, embed = nil) # send message
|
70
70
|
Discordrb::API.request(
|
71
71
|
:channels_cid_messages_mid,
|
72
72
|
channel_id,
|
73
73
|
:post,
|
74
74
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages",
|
75
|
-
{ content: message, mentions: mentions, tts: tts }.to_json,
|
75
|
+
{ content: message, mentions: mentions, tts: tts, embed: embed }.to_json,
|
76
76
|
Authorization: token,
|
77
77
|
content_type: :json
|
78
78
|
)
|
79
|
-
rescue RestClient::
|
80
|
-
|
79
|
+
rescue RestClient::BadRequest => e
|
80
|
+
parsed = JSON.parse(e.response.body)
|
81
|
+
raise Discordrb::Errors::MessageTooLong, "Message over the character limit (#{message.length} > 2000)" if parsed['content'] && parsed['content'].is_a?(Array) && parsed['content'].first == 'Must be 2000 or less characters long.'
|
82
|
+
raise
|
81
83
|
end
|
82
84
|
|
83
85
|
# Send a file as a message to a channel
|
@@ -95,13 +97,13 @@ module Discordrb::API::Channel
|
|
95
97
|
|
96
98
|
# Edit a message
|
97
99
|
# https://discordapp.com/developers/docs/resources/channel#edit-message
|
98
|
-
def edit_message(token, channel_id, message_id, message, mentions = [])
|
100
|
+
def edit_message(token, channel_id, message_id, message, mentions = [], embed = nil)
|
99
101
|
Discordrb::API.request(
|
100
102
|
:channels_cid_messages_mid,
|
101
103
|
channel_id,
|
102
104
|
:patch,
|
103
105
|
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}",
|
104
|
-
{ content: message, mentions: mentions }.to_json,
|
106
|
+
{ content: message, mentions: mentions, embed: embed }.to_json,
|
105
107
|
Authorization: token,
|
106
108
|
content_type: :json
|
107
109
|
)
|
@@ -133,6 +135,72 @@ module Discordrb::API::Channel
|
|
133
135
|
)
|
134
136
|
end
|
135
137
|
|
138
|
+
# Create a reaction on a message using this client
|
139
|
+
# https://discordapp.com/developers/docs/resources/channel#create-reaction
|
140
|
+
def create_reaction(token, channel_id, message_id, emoji)
|
141
|
+
emoji = URI.encode(emoji) unless emoji.ascii_only?
|
142
|
+
Discordrb::API.request(
|
143
|
+
:channels_cid_messages_mid_reactions_emoji_me,
|
144
|
+
channel_id,
|
145
|
+
:put,
|
146
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}/@me",
|
147
|
+
nil,
|
148
|
+
Authorization: token,
|
149
|
+
content_type: :json
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Delete this client's own reaction on a message
|
154
|
+
# https://discordapp.com/developers/docs/resources/channel#delete-own-reaction
|
155
|
+
def delete_own_reaction(token, channel_id, message_id, emoji)
|
156
|
+
emoji = URI.encode(emoji) unless emoji.ascii_only?
|
157
|
+
Discordrb::API.request(
|
158
|
+
:channels_cid_messages_mid_reactions_emoji_me,
|
159
|
+
channel_id,
|
160
|
+
:delete,
|
161
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}/@me",
|
162
|
+
Authorization: token
|
163
|
+
)
|
164
|
+
end
|
165
|
+
|
166
|
+
# Delete another client's reaction on a message
|
167
|
+
# https://discordapp.com/developers/docs/resources/channel#delete-user-reaction
|
168
|
+
def delete_user_reaction(token, channel_id, message_id, emoji, user_id)
|
169
|
+
emoji = URI.encode(emoji) unless emoji.ascii_only?
|
170
|
+
Discordrb::API.request(
|
171
|
+
:channels_cid_messages_mid_reactions_emoji_uid,
|
172
|
+
channel_id,
|
173
|
+
:delete,
|
174
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}/#{user_id}",
|
175
|
+
Authorization: token
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
# Get a list of clients who reacted with a specific reaction on a message
|
180
|
+
# https://discordapp.com/developers/docs/resources/channel#get-reactions
|
181
|
+
def get_reactions(token, channel_id, message_id, emoji)
|
182
|
+
emoji = URI.encode(emoji) unless emoji.ascii_only?
|
183
|
+
Discordrb::API.request(
|
184
|
+
:channels_cid_messages_mid_reactions_emoji,
|
185
|
+
channel_id,
|
186
|
+
:get,
|
187
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions/#{emoji}",
|
188
|
+
Authorization: token
|
189
|
+
)
|
190
|
+
end
|
191
|
+
|
192
|
+
# Deletes all reactions on a message from all clients
|
193
|
+
# https://discordapp.com/developers/docs/resources/channel#delete-all-reactions
|
194
|
+
def delete_all_reactions(token, channel_id, message_id)
|
195
|
+
Discordrb::API.request(
|
196
|
+
:channels_cid_messages_mid_reactions,
|
197
|
+
channel_id,
|
198
|
+
:delete,
|
199
|
+
"#{Discordrb::API.api_base}/channels/#{channel_id}/messages/#{message_id}/reactions",
|
200
|
+
Authorization: token
|
201
|
+
)
|
202
|
+
end
|
203
|
+
|
136
204
|
# Update a channels permission for a role or member
|
137
205
|
# https://discordapp.com/developers/docs/resources/channel#edit-channel-permissions
|
138
206
|
def update_permission(token, channel_id, overwrite_id, allow, deny, type)
|
data/lib/discordrb/api/server.rb
CHANGED
@@ -354,4 +354,41 @@ module Discordrb::API::Server
|
|
354
354
|
Authorization: token
|
355
355
|
)
|
356
356
|
end
|
357
|
+
|
358
|
+
# Adds a custom emoji
|
359
|
+
def add_emoji(token, server_id, image, name)
|
360
|
+
Discordrb::API.request(
|
361
|
+
:guilds_sid_emojis,
|
362
|
+
server_id,
|
363
|
+
:post,
|
364
|
+
"#{Discordrb::API.api_base}/guilds/#{server_id}/emojis",
|
365
|
+
{ image: image, name: name }.to_json,
|
366
|
+
Authorization: token,
|
367
|
+
content_type: :json
|
368
|
+
)
|
369
|
+
end
|
370
|
+
|
371
|
+
# Changes an emoji name
|
372
|
+
def edit_emoji(token, server_id, emoji_id, name)
|
373
|
+
Discordrb::API.request(
|
374
|
+
:guilds_sid_emojis_eid,
|
375
|
+
server_id,
|
376
|
+
:patch,
|
377
|
+
"#{Discordrb::API.api_base}/guilds/#{server_id}/emojis/#{emoji_id}",
|
378
|
+
{ name: name }.to_json,
|
379
|
+
Authorization: token,
|
380
|
+
content_type: :json
|
381
|
+
)
|
382
|
+
end
|
383
|
+
|
384
|
+
# Deletes a custom emoji
|
385
|
+
def delete_emoji(token, server_id, emoji_id)
|
386
|
+
Discordrb::API.request(
|
387
|
+
:guilds_sid_emojis_eid,
|
388
|
+
server_id,
|
389
|
+
:delete,
|
390
|
+
"#{Discordrb::API.api_base}/guilds/#{server_id}/emojis/#{emoji_id}",
|
391
|
+
Authorization: token
|
392
|
+
)
|
393
|
+
end
|
357
394
|
end
|
data/lib/discordrb/bot.rb
CHANGED
@@ -15,6 +15,8 @@ require 'discordrb/events/roles'
|
|
15
15
|
require 'discordrb/events/guilds'
|
16
16
|
require 'discordrb/events/await'
|
17
17
|
require 'discordrb/events/bans'
|
18
|
+
require 'discordrb/events/raw'
|
19
|
+
require 'discordrb/events/reactions'
|
18
20
|
|
19
21
|
require 'discordrb/api'
|
20
22
|
require 'discordrb/api/channel'
|
@@ -91,11 +93,12 @@ module Discordrb
|
|
91
93
|
# @param num_shards [Integer] The total number of shards that should be running. See
|
92
94
|
# https://github.com/hammerandchisel/discord-api-docs/issues/17 for how to do sharding.
|
93
95
|
# @param redact_token [true, false] Whether the bot should redact the token in logs. Default is true.
|
96
|
+
# @param ignore_bots [true, false] Whether the bot should ignore bot accounts or not. Default is false.
|
94
97
|
def initialize(
|
95
98
|
log_mode: :normal,
|
96
|
-
token: nil, client_id: nil,
|
99
|
+
token: nil, client_id: nil,
|
97
100
|
type: nil, name: '', fancy_log: false, suppress_ready: false, parse_self: false,
|
98
|
-
shard_id: nil, num_shards: nil, redact_token: true
|
101
|
+
shard_id: nil, num_shards: nil, redact_token: true, ignore_bots: false
|
99
102
|
)
|
100
103
|
|
101
104
|
LOGGER.mode = if log_mode.is_a? TrueClass # Specifically check for `true` because people might not have updated yet
|
@@ -108,10 +111,6 @@ module Discordrb
|
|
108
111
|
|
109
112
|
@should_parse_self = parse_self
|
110
113
|
|
111
|
-
if application_id
|
112
|
-
raise ArgumentError, 'Starting with discordrb 3.0.0, the application_id parameter has been renamed to client_id! Make sure to change this in your bot. This check will be removed in 3.1.0.'
|
113
|
-
end
|
114
|
-
|
115
114
|
@client_id = client_id
|
116
115
|
|
117
116
|
@type = type || :bot
|
@@ -123,7 +122,7 @@ module Discordrb
|
|
123
122
|
@prevent_ready = suppress_ready
|
124
123
|
|
125
124
|
@token = process_token(@type, token)
|
126
|
-
@gateway = Gateway.new(self, @token)
|
125
|
+
@gateway = Gateway.new(self, @token, @shard_key)
|
127
126
|
|
128
127
|
init_cache
|
129
128
|
|
@@ -131,6 +130,7 @@ module Discordrb
|
|
131
130
|
@should_connect_to_voice = {}
|
132
131
|
|
133
132
|
@ignored_ids = Set.new
|
133
|
+
@ignore_bots = ignore_bots
|
134
134
|
|
135
135
|
@event_threads = []
|
136
136
|
@current_thread = 0
|
@@ -162,7 +162,8 @@ module Discordrb
|
|
162
162
|
def emoji(id = nil)
|
163
163
|
gateway_check
|
164
164
|
if id
|
165
|
-
emoji
|
165
|
+
emoji
|
166
|
+
@emoji.find { |sth| sth.id == id }
|
166
167
|
else
|
167
168
|
emoji = {}
|
168
169
|
@servers.each do |_, server|
|
@@ -170,7 +171,7 @@ module Discordrb
|
|
170
171
|
emoji[element.name] = GlobalEmoji.new(element, self)
|
171
172
|
end
|
172
173
|
end
|
173
|
-
emoji.values
|
174
|
+
@emoji = emoji.values
|
174
175
|
end
|
175
176
|
end
|
176
177
|
|
@@ -265,7 +266,7 @@ module Discordrb
|
|
265
266
|
# @param permission_bits [Integer, String] Permission bits that should be appended to invite url.
|
266
267
|
# @return [String] the OAuth invite URL.
|
267
268
|
def invite_url(server: nil, permission_bits: nil)
|
268
|
-
raise 'No application ID has been set during initialization! Add one as the `
|
269
|
+
raise 'No application ID has been set during initialization! Add one as the `client_id` named parameter while creating your bot.' unless @client_id
|
269
270
|
|
270
271
|
server_id_str = server ? "&guild_id=#{server.id}" : ''
|
271
272
|
permission_bits_str = permission_bits ? "&permissions=#{permission_bits}" : ''
|
@@ -346,13 +347,13 @@ module Discordrb
|
|
346
347
|
# @param channel_id [Integer] The ID that identifies the channel to send something to.
|
347
348
|
# @param content [String] The text that should be sent as a message. It is limited to 2000 characters (Discord imposed).
|
348
349
|
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
349
|
-
# @param
|
350
|
+
# @param embed [Hash, Discordrb::Webhooks::Embed, nil] The rich embed to append to this message.
|
350
351
|
# @return [Message] The message that was sent.
|
351
|
-
def send_message(channel_id, content, tts = false,
|
352
|
+
def send_message(channel_id, content, tts = false, embed = nil)
|
352
353
|
channel_id = channel_id.resolve_id
|
353
354
|
debug("Sending message to #{channel_id} with content '#{content}'")
|
354
355
|
|
355
|
-
response = API::Channel.create_message(token, channel_id, content, [], tts,
|
356
|
+
response = API::Channel.create_message(token, channel_id, content, [], tts, embed ? embed.to_hash : nil)
|
356
357
|
Message.new(JSON.parse(response), self)
|
357
358
|
end
|
358
359
|
|
@@ -362,10 +363,10 @@ module Discordrb
|
|
362
363
|
# @param content [String] The text that should be sent as a message. It is limited to 2000 characters (Discord imposed).
|
363
364
|
# @param timeout [Float] The amount of time in seconds after which the message sent will be deleted.
|
364
365
|
# @param tts [true, false] Whether or not this message should be sent using Discord text-to-speech.
|
365
|
-
# @param
|
366
|
-
def send_temporary_message(channel_id, content, timeout, tts = false,
|
366
|
+
# @param embed [Hash, Discordrb::Webhooks::Embed, nil] The rich embed to append to this message.
|
367
|
+
def send_temporary_message(channel_id, content, timeout, tts = false, embed = nil)
|
367
368
|
Thread.new do
|
368
|
-
message = send_message(channel_id, content, tts,
|
369
|
+
message = send_message(channel_id, content, tts, embed)
|
369
370
|
|
370
371
|
sleep(timeout)
|
371
372
|
|
@@ -440,11 +441,14 @@ module Discordrb
|
|
440
441
|
if /<@!?(?<id>\d+)>?/ =~ mention
|
441
442
|
user(id.to_i)
|
442
443
|
elsif /<@&(?<id>\d+)>?/ =~ mention
|
443
|
-
return server.role(id) if server
|
444
|
-
servers.each do |element|
|
445
|
-
role = element.role(id)
|
444
|
+
return server.role(id.to_i) if server
|
445
|
+
@servers.values.each do |element|
|
446
|
+
role = element.role(id.to_i)
|
446
447
|
return role unless role.nil?
|
447
448
|
end
|
449
|
+
|
450
|
+
# Return nil if no role is found
|
451
|
+
nil
|
448
452
|
elsif /<:(\w+):(?<id>\d+)>?/ =~ mention
|
449
453
|
emoji.find { |element| element.id.to_i == id.to_i }
|
450
454
|
end
|
@@ -463,7 +467,7 @@ module Discordrb
|
|
463
467
|
@game = game
|
464
468
|
@status = status
|
465
469
|
@streamurl = url
|
466
|
-
type = url ? 1 :
|
470
|
+
type = url ? 1 : 0
|
467
471
|
|
468
472
|
game_obj = game || url ? { name: game, url: url, type: type } : nil
|
469
473
|
@gateway.send_status_update(status, since, game_obj, afk)
|
@@ -640,21 +644,28 @@ module Discordrb
|
|
640
644
|
member.update_username(username)
|
641
645
|
end
|
642
646
|
|
643
|
-
member.
|
644
|
-
|
647
|
+
member.update_presence(data)
|
648
|
+
|
649
|
+
member.avatar_id = data['user']['avatar'] if data['user']['avatar']
|
645
650
|
|
646
651
|
server.cache_member(member)
|
647
652
|
end
|
648
653
|
|
649
|
-
# Internal handler for
|
654
|
+
# Internal handler for VOICE_STATE_UPDATE
|
650
655
|
def update_voice_state(data)
|
656
|
+
@session_id = data['session_id']
|
657
|
+
|
651
658
|
server_id = data['guild_id'].to_i
|
652
659
|
server = server(server_id)
|
653
660
|
return unless server
|
654
661
|
|
662
|
+
user_id = data['user_id'].to_i
|
663
|
+
old_voice_state = server.voice_states[user_id]
|
664
|
+
old_channel_id = old_voice_state.voice_channel.id if old_voice_state
|
665
|
+
|
655
666
|
server.update_voice_state(data)
|
656
667
|
|
657
|
-
|
668
|
+
old_channel_id
|
658
669
|
end
|
659
670
|
|
660
671
|
# Internal handler for VOICE_SERVER_UPDATE
|
@@ -686,7 +697,7 @@ module Discordrb
|
|
686
697
|
|
687
698
|
# Handle normal and private channels separately
|
688
699
|
if server
|
689
|
-
server.
|
700
|
+
server.add_channel(channel)
|
690
701
|
@channels[channel.id] = channel
|
691
702
|
elsif channel.pm?
|
692
703
|
@pm_channels[channel.recipient.id] = channel
|
@@ -711,7 +722,7 @@ module Discordrb
|
|
711
722
|
# Handle normal and private channels separately
|
712
723
|
if server
|
713
724
|
@channels.delete(channel.id)
|
714
|
-
server.
|
725
|
+
server.delete_channel(channel.id)
|
715
726
|
elsif channel.pm?
|
716
727
|
@pm_channels.delete(channel.recipient.id)
|
717
728
|
elsif channel.group?
|
@@ -813,6 +824,13 @@ module Discordrb
|
|
813
824
|
server.delete_role(role_id)
|
814
825
|
end
|
815
826
|
|
827
|
+
# Internal handler for GUILD_EMOJIS_UPDATE
|
828
|
+
def update_guild_emoji(data)
|
829
|
+
server_id = data['guild_id'].to_i
|
830
|
+
server = @servers[server_id]
|
831
|
+
server.update_emoji_data(data)
|
832
|
+
end
|
833
|
+
|
816
834
|
# Internal handler for MESSAGE_CREATE
|
817
835
|
def create_message(data); end
|
818
836
|
|
@@ -825,6 +843,15 @@ module Discordrb
|
|
825
843
|
# Internal handler for MESSAGE_DELETE
|
826
844
|
def delete_message(data); end
|
827
845
|
|
846
|
+
# Internal handler for MESSAGE_REACTION_ADD
|
847
|
+
def add_message_reaction(data); end
|
848
|
+
|
849
|
+
# Internal handler for MESSAGE_REACTION_REMOVE
|
850
|
+
def remove_message_reaction(data); end
|
851
|
+
|
852
|
+
# Internal handler for MESSAGE_REACTION_REMOVE_ALL
|
853
|
+
def remove_all_message_reactions(data); end
|
854
|
+
|
828
855
|
# Internal handler for GUILD_BAN_ADD
|
829
856
|
def add_user_ban(data); end
|
830
857
|
|
@@ -917,6 +944,11 @@ module Discordrb
|
|
917
944
|
return
|
918
945
|
end
|
919
946
|
|
947
|
+
if @ignore_bots && data['author']['bot']
|
948
|
+
debug("Ignored Bot account with ID #{data['author']['id']}")
|
949
|
+
return
|
950
|
+
end
|
951
|
+
|
920
952
|
# If create_message is overwritten with a method that returns the parsed message, use that instead, so we don't
|
921
953
|
# parse the message twice (which is just thrown away performance)
|
922
954
|
message = create_message(data)
|
@@ -979,6 +1011,21 @@ module Discordrb
|
|
979
1011
|
rescue Discordrb::Errors::NoPermission
|
980
1012
|
debug 'Typing started in channel the bot has no access to, ignoring'
|
981
1013
|
end
|
1014
|
+
when :MESSAGE_REACTION_ADD
|
1015
|
+
add_message_reaction(data)
|
1016
|
+
|
1017
|
+
event = ReactionAddEvent.new(data, self)
|
1018
|
+
raise_event(event)
|
1019
|
+
when :MESSAGE_REACTION_REMOVE
|
1020
|
+
remove_message_reaction(data)
|
1021
|
+
|
1022
|
+
event = ReactionRemoveEvent.new(data, self)
|
1023
|
+
raise_event(event)
|
1024
|
+
when :MESSAGE_REACTION_REMOVE_ALL
|
1025
|
+
remove_all_message_reactions(data)
|
1026
|
+
|
1027
|
+
event = ReactionRemoveAllEvent.new(data, self)
|
1028
|
+
raise_event(event)
|
982
1029
|
when :PRESENCE_UPDATE
|
983
1030
|
# Ignore friends list presences
|
984
1031
|
return unless data['guild_id']
|
@@ -996,9 +1043,9 @@ module Discordrb
|
|
996
1043
|
|
997
1044
|
raise_event(event)
|
998
1045
|
when :VOICE_STATE_UPDATE
|
999
|
-
update_voice_state(data)
|
1046
|
+
old_channel_id = update_voice_state(data)
|
1000
1047
|
|
1001
|
-
event = VoiceStateUpdateEvent.new(data, self)
|
1048
|
+
event = VoiceStateUpdateEvent.new(data, old_channel_id, self)
|
1002
1049
|
raise_event(event)
|
1003
1050
|
when :VOICE_SERVER_UPDATE
|
1004
1051
|
update_voice_server(data)
|
@@ -1100,9 +1147,49 @@ module Discordrb
|
|
1100
1147
|
|
1101
1148
|
event = ServerDeleteEvent.new(data, self)
|
1102
1149
|
raise_event(event)
|
1150
|
+
when :GUILD_EMOJIS_UPDATE
|
1151
|
+
server_id = data['guild_id'].to_i
|
1152
|
+
server = @servers[server_id]
|
1153
|
+
old_emoji_data = server.emoji.clone
|
1154
|
+
update_guild_emoji(data)
|
1155
|
+
new_emoji_data = server.emoji
|
1156
|
+
|
1157
|
+
created_ids = new_emoji_data.keys - old_emoji_data.keys
|
1158
|
+
deleted_ids = old_emoji_data.keys - new_emoji_data.keys
|
1159
|
+
updated_ids = old_emoji_data.select do |k, v|
|
1160
|
+
new_emoji_data[k] && (v.name != new_emoji_data[k].name || v.roles != new_emoji_data[k].roles)
|
1161
|
+
end.keys
|
1162
|
+
|
1163
|
+
event = ServerEmojiChangeEvent.new(server, data, self)
|
1164
|
+
raise_event(event)
|
1165
|
+
|
1166
|
+
created_ids.each do |e|
|
1167
|
+
event = ServerEmojiCreateEvent.new(server, new_emoji_data[e], self)
|
1168
|
+
raise_event(event)
|
1169
|
+
end
|
1170
|
+
|
1171
|
+
deleted_ids.each do |e|
|
1172
|
+
event = ServerEmojiDeleteEvent.new(server, old_emoji_data[e], self)
|
1173
|
+
raise_event(event)
|
1174
|
+
end
|
1175
|
+
|
1176
|
+
updated_ids.each do |e|
|
1177
|
+
event = ServerEmojiUpdateEvent.new(server, old_emoji_data[e], new_emoji_data[e], self)
|
1178
|
+
raise_event(event)
|
1179
|
+
end
|
1103
1180
|
else
|
1104
1181
|
# another event that we don't support yet
|
1105
|
-
debug "Event #{type} has been received but is unsupported
|
1182
|
+
debug "Event #{type} has been received but is unsupported. Raising UnknownEvent"
|
1183
|
+
|
1184
|
+
event = UnknownEvent.new(type, data, self)
|
1185
|
+
raise_event(event)
|
1186
|
+
end
|
1187
|
+
|
1188
|
+
# The existence of this array is checked before for performance reasons, since this has to be done for *every*
|
1189
|
+
# dispatch.
|
1190
|
+
if @event_handlers && @event_handlers[RawEvent]
|
1191
|
+
event = RawEvent.new(type, data, self)
|
1192
|
+
raise_event(event)
|
1106
1193
|
end
|
1107
1194
|
rescue Exception => e
|
1108
1195
|
LOGGER.error('Gateway message error!')
|