discordrb 2.1.3 → 3.0.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/.gitignore +1 -0
- data/CHANGELOG.md +76 -0
- data/README.md +4 -2
- data/discordrb.gemspec +1 -1
- data/examples/commands.rb +2 -0
- data/examples/data/music.dca +0 -0
- data/examples/data/music.mp3 +0 -0
- data/examples/eval.rb +6 -3
- data/examples/ping.rb +14 -1
- data/examples/ping_with_respond_time.rb +6 -4
- data/examples/pm_send.rb +3 -0
- data/examples/shutdown.rb +7 -2
- data/examples/voice_send.rb +51 -0
- data/lib/discordrb/api.rb +66 -460
- data/lib/discordrb/api/channel.rb +306 -0
- data/lib/discordrb/api/invite.rb +41 -0
- data/lib/discordrb/api/server.rb +357 -0
- data/lib/discordrb/api/user.rb +134 -0
- data/lib/discordrb/bot.rb +266 -576
- data/lib/discordrb/cache.rb +27 -28
- data/lib/discordrb/commands/command_bot.rb +44 -15
- data/lib/discordrb/commands/container.rb +3 -2
- data/lib/discordrb/commands/parser.rb +14 -6
- data/lib/discordrb/container.rb +30 -3
- data/lib/discordrb/data.rb +823 -189
- data/lib/discordrb/errors.rb +145 -0
- data/lib/discordrb/events/channels.rb +63 -3
- data/lib/discordrb/events/members.rb +1 -2
- data/lib/discordrb/events/message.rb +96 -17
- data/lib/discordrb/events/presence.rb +15 -0
- data/lib/discordrb/events/typing.rb +7 -1
- data/lib/discordrb/gateway.rb +724 -0
- data/lib/discordrb/light/light_bot.rb +6 -4
- data/lib/discordrb/logger.rb +26 -9
- data/lib/discordrb/permissions.rb +6 -3
- data/lib/discordrb/version.rb +1 -1
- data/lib/discordrb/voice/voice_bot.rb +29 -6
- metadata +12 -5
- data/lib/discordrb/token_cache.rb +0 -181
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'discordrb/api'
|
4
|
+
require 'discordrb/api/invite'
|
5
|
+
require 'discordrb/api/user'
|
4
6
|
require 'discordrb/light/data'
|
5
7
|
require 'discordrb/light/integrations'
|
6
8
|
|
@@ -29,13 +31,13 @@ module Discordrb::Light
|
|
29
31
|
|
30
32
|
# @return [LightProfile] the details of the user this bot is connected to.
|
31
33
|
def profile
|
32
|
-
response = Discordrb::API.profile(@token)
|
34
|
+
response = Discordrb::API::User.profile(@token)
|
33
35
|
LightProfile.new(JSON.parse(response), self)
|
34
36
|
end
|
35
37
|
|
36
38
|
# @return [Array<LightServer>] the servers this bot is connected to.
|
37
39
|
def servers
|
38
|
-
response = Discordrb::API.servers(@token)
|
40
|
+
response = Discordrb::API::User.servers(@token)
|
39
41
|
JSON.parse(response).map { |e| LightServer.new(e, self) }
|
40
42
|
end
|
41
43
|
|
@@ -43,13 +45,13 @@ module Discordrb::Light
|
|
43
45
|
# @param code [String] The code part of the invite (for example 0cDvIgU2voWn4BaD if the invite URL is
|
44
46
|
# https://discord.gg/0cDvIgU2voWn4BaD)
|
45
47
|
def join(code)
|
46
|
-
Discordrb::API.
|
48
|
+
Discordrb::API::Invite.accept(@token, code)
|
47
49
|
end
|
48
50
|
|
49
51
|
# Gets the connections associated with this account.
|
50
52
|
# @return [Array<Connection>] this account's connections.
|
51
53
|
def connections
|
52
|
-
response = Discordrb::API.connections(@token)
|
54
|
+
response = Discordrb::API::User.connections(@token)
|
53
55
|
JSON.parse(response).map { |e| Connection.new(e, self) }
|
54
56
|
end
|
55
57
|
end
|
data/lib/discordrb/logger.rb
CHANGED
@@ -9,11 +9,20 @@ module Discordrb
|
|
9
9
|
# @return [true, false] whether this logger is in extra-fancy mode!
|
10
10
|
attr_writer :fancy
|
11
11
|
|
12
|
+
# @return [String, nil] The bot token to be redacted or nil if it shouldn't.
|
13
|
+
attr_writer :token
|
14
|
+
|
15
|
+
# @return [Array<IO>, Array<#puts & #flush>] the streams the logger should write to.
|
16
|
+
attr_accessor :streams
|
17
|
+
|
12
18
|
# Creates a new logger.
|
13
19
|
# @param fancy [true, false] Whether this logger uses fancy mode (ANSI escape codes to make the output colourful)
|
14
|
-
|
20
|
+
# @param streams [Array<IO>, Array<#puts & #flush>] the streams the logger should write to.
|
21
|
+
def initialize(fancy = false, streams = [STDOUT])
|
15
22
|
@fancy = fancy
|
16
23
|
self.mode = :normal
|
24
|
+
|
25
|
+
@streams = streams
|
17
26
|
end
|
18
27
|
|
19
28
|
# The modes this logger can have. This is probably useless unless you want to write your own Logger
|
@@ -80,19 +89,27 @@ module Discordrb
|
|
80
89
|
def write(message, mode)
|
81
90
|
thread_name = Thread.current[:discordrb_name]
|
82
91
|
timestamp = Time.now.strftime(LOG_TIMESTAMP_FORMAT)
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
92
|
+
|
93
|
+
# Redact token if set
|
94
|
+
message.gsub!(@token, 'REDACTED_TOKEN') if @token
|
95
|
+
|
96
|
+
@streams.each do |stream|
|
97
|
+
if @fancy && !stream.is_a?(File)
|
98
|
+
fancy_write(stream, message, mode, thread_name, timestamp)
|
99
|
+
else
|
100
|
+
simple_write(stream, message, mode, thread_name, timestamp)
|
101
|
+
end
|
87
102
|
end
|
88
103
|
end
|
89
104
|
|
90
|
-
def fancy_write(message, mode, thread_name, timestamp)
|
91
|
-
puts "#{timestamp} #{FORMAT_BOLD}#{thread_name.ljust(16)}#{FORMAT_RESET} #{mode[:format_code]}#{mode[:short]}#{FORMAT_RESET} #{message}"
|
105
|
+
def fancy_write(stream, message, mode, thread_name, timestamp)
|
106
|
+
stream.puts "#{timestamp} #{FORMAT_BOLD}#{thread_name.ljust(16)}#{FORMAT_RESET} #{mode[:format_code]}#{mode[:short]}#{FORMAT_RESET} #{message}"
|
107
|
+
stream.flush
|
92
108
|
end
|
93
109
|
|
94
|
-
def simple_write(message, mode, thread_name, timestamp)
|
95
|
-
puts "[#{mode[:long]} : #{thread_name} @ #{timestamp}] #{message}"
|
110
|
+
def simple_write(stream, message, mode, thread_name, timestamp)
|
111
|
+
stream.puts "[#{mode[:long]} : #{thread_name} @ #{timestamp}] #{message}"
|
112
|
+
stream.flush
|
96
113
|
end
|
97
114
|
end
|
98
115
|
end
|
@@ -10,7 +10,7 @@ module Discordrb
|
|
10
10
|
0 => :create_instant_invite, # 1
|
11
11
|
1 => :kick_members, # 2
|
12
12
|
2 => :ban_members, # 4
|
13
|
-
3 => :
|
13
|
+
3 => :administrator, # 8
|
14
14
|
4 => :manage_channels, # 16
|
15
15
|
5 => :manage_server, # 32
|
16
16
|
# 6 # 64
|
@@ -25,7 +25,7 @@ module Discordrb
|
|
25
25
|
15 => :attach_files, # 32768
|
26
26
|
16 => :read_message_history, # 65536
|
27
27
|
17 => :mention_everyone, # 131072
|
28
|
-
|
28
|
+
18 => :use_external_emoji, # 262144
|
29
29
|
# 19 # 524288
|
30
30
|
20 => :connect, # 1048576
|
31
31
|
21 => :speak, # 2097152
|
@@ -34,7 +34,8 @@ module Discordrb
|
|
34
34
|
24 => :move_members, # 16777216
|
35
35
|
25 => :use_voice_activity, # 33554432
|
36
36
|
26 => :change_nickname, # 67108864
|
37
|
-
27 => :manage_nicknames
|
37
|
+
27 => :manage_nicknames, # 134217728
|
38
|
+
28 => :manage_roles # 268435456, also Manage Permissions
|
38
39
|
}.freeze
|
39
40
|
|
40
41
|
Flags.each do |position, flag|
|
@@ -52,6 +53,8 @@ module Discordrb
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
56
|
+
alias_method :can_administrate=, :can_administrator=
|
57
|
+
|
55
58
|
attr_reader :bits
|
56
59
|
|
57
60
|
# Set the raw bitset of this permission object
|
data/lib/discordrb/version.rb
CHANGED
@@ -21,6 +21,9 @@ module Discordrb::Voice
|
|
21
21
|
# should check the parameters and adjust them to your connection: {VoiceBot#adjust_interval},
|
22
22
|
# {VoiceBot#adjust_offset}, and {VoiceBot#adjust_average}.
|
23
23
|
class VoiceBot
|
24
|
+
# @return [Channel] the current voice channel
|
25
|
+
attr_reader :channel
|
26
|
+
|
24
27
|
# @return [Integer, nil] the amount of time the stream has been playing, or `nil` if nothing has been played yet.
|
25
28
|
attr_reader :stream_time
|
26
29
|
|
@@ -88,6 +91,7 @@ module Discordrb::Voice
|
|
88
91
|
@adjust_debug = true
|
89
92
|
|
90
93
|
@volume = 1.0
|
94
|
+
@playing = false
|
91
95
|
|
92
96
|
@encoder = Encoder.new
|
93
97
|
@ws.connect
|
@@ -120,6 +124,14 @@ module Discordrb::Voice
|
|
120
124
|
@paused = true
|
121
125
|
end
|
122
126
|
|
127
|
+
# @see #play
|
128
|
+
# @return [true, false] Whether it is playing sound or not.
|
129
|
+
def playing?
|
130
|
+
@playing
|
131
|
+
end
|
132
|
+
|
133
|
+
alias_method :isplaying?, :playing?
|
134
|
+
|
123
135
|
# Continue playback. This change may take up to 100 ms to take effect, which is usually negligible.
|
124
136
|
def continue
|
125
137
|
@paused = false
|
@@ -140,11 +152,19 @@ module Discordrb::Voice
|
|
140
152
|
end
|
141
153
|
|
142
154
|
# Stops the current playback entirely.
|
143
|
-
|
155
|
+
# @param wait_for_confirmation [true, false] Whether the method should wait for confirmation from the playback
|
156
|
+
# method that the playback has actually stopped.
|
157
|
+
def stop_playing(wait_for_confirmation = false)
|
144
158
|
@was_playing_before = @playing
|
145
159
|
@speaking = false
|
146
160
|
@playing = false
|
147
161
|
sleep IDEAL_LENGTH / 1000.0 if @was_playing_before
|
162
|
+
|
163
|
+
if wait_for_confirmation
|
164
|
+
@has_stopped_playing = false
|
165
|
+
sleep IDEAL_LENGTH / 1000.0 until @has_stopped_playing
|
166
|
+
@has_stopped_playing = false
|
167
|
+
end
|
148
168
|
end
|
149
169
|
|
150
170
|
# Permanently disconnects from the voice channel; to reconnect you will have to call {Bot#voice_connect} again.
|
@@ -160,7 +180,7 @@ module Discordrb::Voice
|
|
160
180
|
# methods in separate threads.
|
161
181
|
# @param encoded_io [IO] A stream of raw PCM data (s16le)
|
162
182
|
def play(encoded_io)
|
163
|
-
stop_playing if @playing
|
183
|
+
stop_playing(true) if @playing
|
164
184
|
@retry_attempts = 3
|
165
185
|
@first_packet = true
|
166
186
|
|
@@ -180,7 +200,7 @@ module Discordrb::Voice
|
|
180
200
|
# Check whether the buffer has enough data
|
181
201
|
if !buf || buf.length != DATA_LENGTH
|
182
202
|
@bot.debug("No data is available! Retrying #{@retry_attempts} more times")
|
183
|
-
break if @retry_attempts
|
203
|
+
break if @retry_attempts.zero?
|
184
204
|
|
185
205
|
@retry_attempts -= 1
|
186
206
|
next
|
@@ -233,7 +253,7 @@ module Discordrb::Voice
|
|
233
253
|
# @see https://github.com/bwmarrin/dca
|
234
254
|
# @see #play
|
235
255
|
def play_dca(file)
|
236
|
-
stop_playing if @playing
|
256
|
+
stop_playing(true) if @playing
|
237
257
|
|
238
258
|
@bot.debug "Reading DCA file #{file}"
|
239
259
|
input_stream = open(file)
|
@@ -362,12 +382,15 @@ module Discordrb::Voice
|
|
362
382
|
|
363
383
|
# Final cleanup
|
364
384
|
stop_playing
|
385
|
+
|
386
|
+
# Notify any stop_playing methods running right now that we have actually stopped
|
387
|
+
@has_stopped_playing = true
|
365
388
|
end
|
366
389
|
|
367
390
|
# Increment sequence and time
|
368
391
|
def increment_packet_headers
|
369
|
-
|
370
|
-
|
392
|
+
@sequence + 10 < 65_535 ? @sequence += 1 : @sequence = 0
|
393
|
+
@time + 9600 < 4_294_967_295 ? @time += 960 : @time = 0
|
371
394
|
end
|
372
395
|
end
|
373
396
|
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:
|
4
|
+
version: 3.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- meew0
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -142,14 +142,14 @@ dependencies:
|
|
142
142
|
requirements:
|
143
143
|
- - '='
|
144
144
|
- !ruby/object:Gem::Version
|
145
|
-
version: 0.
|
145
|
+
version: 0.42.0
|
146
146
|
type: :development
|
147
147
|
prerelease: false
|
148
148
|
version_requirements: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - '='
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: 0.
|
152
|
+
version: 0.42.0
|
153
153
|
description: A Ruby implementation of the Discord (https://discordapp.com) API.
|
154
154
|
email:
|
155
155
|
- ''
|
@@ -172,13 +172,20 @@ files:
|
|
172
172
|
- bin/setup
|
173
173
|
- discordrb.gemspec
|
174
174
|
- examples/commands.rb
|
175
|
+
- examples/data/music.dca
|
176
|
+
- examples/data/music.mp3
|
175
177
|
- examples/eval.rb
|
176
178
|
- examples/ping.rb
|
177
179
|
- examples/ping_with_respond_time.rb
|
178
180
|
- examples/pm_send.rb
|
179
181
|
- examples/shutdown.rb
|
182
|
+
- examples/voice_send.rb
|
180
183
|
- lib/discordrb.rb
|
181
184
|
- lib/discordrb/api.rb
|
185
|
+
- lib/discordrb/api/channel.rb
|
186
|
+
- lib/discordrb/api/invite.rb
|
187
|
+
- lib/discordrb/api/server.rb
|
188
|
+
- lib/discordrb/api/user.rb
|
182
189
|
- lib/discordrb/await.rb
|
183
190
|
- lib/discordrb/bot.rb
|
184
191
|
- lib/discordrb/cache.rb
|
@@ -202,13 +209,13 @@ files:
|
|
202
209
|
- lib/discordrb/events/roles.rb
|
203
210
|
- lib/discordrb/events/typing.rb
|
204
211
|
- lib/discordrb/events/voice_state_update.rb
|
212
|
+
- lib/discordrb/gateway.rb
|
205
213
|
- lib/discordrb/light.rb
|
206
214
|
- lib/discordrb/light/data.rb
|
207
215
|
- lib/discordrb/light/integrations.rb
|
208
216
|
- lib/discordrb/light/light_bot.rb
|
209
217
|
- lib/discordrb/logger.rb
|
210
218
|
- lib/discordrb/permissions.rb
|
211
|
-
- lib/discordrb/token_cache.rb
|
212
219
|
- lib/discordrb/version.rb
|
213
220
|
- lib/discordrb/voice/encoder.rb
|
214
221
|
- lib/discordrb/voice/network.rb
|
@@ -1,181 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'base64'
|
4
|
-
require 'json'
|
5
|
-
require 'openssl'
|
6
|
-
require 'discordrb/api'
|
7
|
-
|
8
|
-
# Discordrb
|
9
|
-
module Discordrb
|
10
|
-
# Amount of bytes the token encryption key should be long (32 bytes = 256 bits -> AES256)
|
11
|
-
KEYLEN = 32
|
12
|
-
|
13
|
-
# Represents a cached token with encryption data
|
14
|
-
class CachedToken
|
15
|
-
# Parse the cached token from the JSON data read from the file.
|
16
|
-
def initialize(data = nil)
|
17
|
-
if data
|
18
|
-
@verify_salt = Base64.decode64(data['verify_salt'])
|
19
|
-
@password_hash = Base64.decode64(data['password_hash'])
|
20
|
-
@encrypt_salt = Base64.decode64(data['encrypt_salt'])
|
21
|
-
@iv = Base64.decode64(data['iv'])
|
22
|
-
@encrypted_token = Base64.decode64(data['encrypted_token'])
|
23
|
-
else
|
24
|
-
generate_salts
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
# @return [Hash<Symbol => String>] the data representing the token and encryption data, all encrypted and base64-encoded
|
29
|
-
def data
|
30
|
-
{
|
31
|
-
verify_salt: Base64.encode64(@verify_salt),
|
32
|
-
password_hash: Base64.encode64(@password_hash),
|
33
|
-
encrypt_salt: Base64.encode64(@encrypt_salt),
|
34
|
-
iv: Base64.encode64(@iv),
|
35
|
-
encrypted_token: Base64.encode64(@encrypted_token)
|
36
|
-
}
|
37
|
-
end
|
38
|
-
|
39
|
-
# Verifies this encrypted token with a given password
|
40
|
-
# @param password [String] A plaintext password to verify
|
41
|
-
# @see #hash_password
|
42
|
-
# @return [true, false] whether or not the verification succeeded
|
43
|
-
def verify_password(password)
|
44
|
-
hash_password(password) == @password_hash
|
45
|
-
end
|
46
|
-
|
47
|
-
# Sets the given password as the verification password
|
48
|
-
# @param password [String] A plaintext password to set
|
49
|
-
# @see #hash_password
|
50
|
-
def generate_verify_hash(password)
|
51
|
-
@password_hash = hash_password(password)
|
52
|
-
end
|
53
|
-
|
54
|
-
# Generates a key from a given password using PBKDF2 with a SHA1 HMAC, 300k iterations and 32 bytes long
|
55
|
-
# @param password [String] A password to use as the base for the key
|
56
|
-
# @return [String] The generated key
|
57
|
-
def obtain_key(password)
|
58
|
-
@key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(password, @encrypt_salt, 300_000, KEYLEN)
|
59
|
-
end
|
60
|
-
|
61
|
-
# Generates cryptographically random salts for this token
|
62
|
-
def generate_salts
|
63
|
-
@verify_salt = OpenSSL::Random.random_bytes(KEYLEN)
|
64
|
-
@encrypt_salt = OpenSSL::Random.random_bytes(KEYLEN)
|
65
|
-
end
|
66
|
-
|
67
|
-
# Decrypts a token using a given password
|
68
|
-
# @param password [String] The plaintext password to decrypt the token with
|
69
|
-
# @return [String] the plaintext token
|
70
|
-
def decrypt_token(password)
|
71
|
-
key = obtain_key(password)
|
72
|
-
decipher = OpenSSL::Cipher::AES256.new(:CBC)
|
73
|
-
decipher.decrypt
|
74
|
-
decipher.key = key
|
75
|
-
decipher.iv = @iv
|
76
|
-
decipher.update(@encrypted_token) + decipher.final
|
77
|
-
end
|
78
|
-
|
79
|
-
# Encrypts a given token with the given password, using AES256 CBC
|
80
|
-
# @param password [String] The plaintext password to encrypt the token with
|
81
|
-
# @param token [String] The plaintext token to encrypt
|
82
|
-
# @return [String] the encrypted token
|
83
|
-
def encrypt_token(password, token)
|
84
|
-
key = obtain_key(password)
|
85
|
-
cipher = OpenSSL::Cipher::AES256.new(:CBC)
|
86
|
-
cipher.encrypt
|
87
|
-
cipher.key = key
|
88
|
-
@iv = cipher.random_iv
|
89
|
-
@encrypted_token = cipher.update(token) + cipher.final
|
90
|
-
end
|
91
|
-
|
92
|
-
# Tests a token by making an API request, throws an error if not successful
|
93
|
-
# @param token [String] A plaintext token to test
|
94
|
-
def test_token(token)
|
95
|
-
Discordrb::API.validate_token(token)
|
96
|
-
end
|
97
|
-
|
98
|
-
# Hashes a password using PBKDF2 with a SHA256 digest
|
99
|
-
# @param password [String] The password to hash
|
100
|
-
# @return [String] The hashed password
|
101
|
-
def hash_password(password)
|
102
|
-
digest = OpenSSL::Digest::SHA256.new
|
103
|
-
OpenSSL::PKCS5.pbkdf2_hmac(password, @verify_salt, 300_000, digest.digest_length, digest)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Path where the token cache file will be stored
|
108
|
-
CACHE_PATH = Dir.home + '/.discordrb_token_cache.json'
|
109
|
-
|
110
|
-
# Represents a token file
|
111
|
-
class TokenCache
|
112
|
-
def initialize
|
113
|
-
if File.file? CACHE_PATH
|
114
|
-
@data = JSON.parse(File.read(CACHE_PATH))
|
115
|
-
else
|
116
|
-
LOGGER.debug("Cache file #{CACHE_PATH} not found. Using empty cache")
|
117
|
-
@data = {}
|
118
|
-
end
|
119
|
-
rescue => e
|
120
|
-
LOGGER.debug('Exception occurred while parsing token cache file:', true)
|
121
|
-
LOGGER.log_exception(e)
|
122
|
-
LOGGER.debug('Continuing with empty cache')
|
123
|
-
@data = {}
|
124
|
-
end
|
125
|
-
|
126
|
-
# Gets a token from this token cache
|
127
|
-
# @param email [String] The email to get the token for
|
128
|
-
# @param password [String] The plaintext password to get the token for
|
129
|
-
# @return [String, nil] the stored token, or nil if unsuccessful (e. g. token not cached or cached token invalid)
|
130
|
-
def token(email, password)
|
131
|
-
if @data[email]
|
132
|
-
begin
|
133
|
-
cached = CachedToken.new(@data[email])
|
134
|
-
if cached.verify_password(password)
|
135
|
-
token = cached.decrypt_token(password)
|
136
|
-
if token
|
137
|
-
begin
|
138
|
-
cached.test_token(token)
|
139
|
-
token
|
140
|
-
rescue => e
|
141
|
-
fail_token('Token cached, verified and decrypted, but rejected by Discord', email, e)
|
142
|
-
sleep 1 # wait some time so we don't get immediately rate limited
|
143
|
-
nil
|
144
|
-
end
|
145
|
-
else; fail_token('Token cached and verified, but decryption failed', email)
|
146
|
-
end
|
147
|
-
else; fail_token('Token verification failed', email)
|
148
|
-
end
|
149
|
-
rescue => e; fail_token('Token cached but invalid', email, e)
|
150
|
-
end
|
151
|
-
else; fail_token('Token not cached at all')
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
# Caches a token
|
156
|
-
# @param email [String] The email to store this token under
|
157
|
-
# @param password [String] The plaintext password to encrypt the token with
|
158
|
-
# @param token [String] The plaintext token to cache
|
159
|
-
def store_token(email, password, token)
|
160
|
-
cached = CachedToken.new
|
161
|
-
cached.generate_verify_hash(password)
|
162
|
-
cached.encrypt_token(password, token)
|
163
|
-
@data[email] = cached.data
|
164
|
-
write_cache
|
165
|
-
end
|
166
|
-
|
167
|
-
# Writes the cache to a file
|
168
|
-
def write_cache
|
169
|
-
File.write(CACHE_PATH, @data.to_json)
|
170
|
-
end
|
171
|
-
|
172
|
-
private
|
173
|
-
|
174
|
-
def fail_token(msg, email = nil, e = nil)
|
175
|
-
LOGGER.warn("Token not retrieved from cache - #{msg}")
|
176
|
-
LOGGER.log_exception(e) if e
|
177
|
-
@data.delete(email) if email
|
178
|
-
nil
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|