grape-slack-bot 1.3.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 669dbf492365849f4628ed362f0a047e70d15cb80a62a236260be26d76fbaacc
4
- data.tar.gz: e17819f3afa4096b5623c4a8d19f6443522c2010d528ac6a14fefc17fb3c3309
3
+ metadata.gz: 2d248818a6772bc6b90aaaff5e6a32f34ed8f1be71d3865435929e018f30d48b
4
+ data.tar.gz: 8719e28b6995efa871e4a834aa5ac884cbda4133034805e256ddf53786c1fdb2
5
5
  SHA512:
6
- metadata.gz: 05de3c891473d52722c368bd587e7a90b7d8e9eaa96c4f6bd59bd4bbb5f867c265e2fab1b2e95076abd8b75c0dd9460a51ea460909afd538e9c0c0962fe8250c
7
- data.tar.gz: c80d3a362202a526df44c32dad70270109ef344180d7d83d27cca9a24c9f308d422c7f8f91215a0a31b357ef2e86d14771b048f344051a7bc48ca27f80fa73d1
6
+ metadata.gz: 3a20d2e0f603d9f5a1cbfc24d8e08e9907b12d6d677442d63160cf0a5f57b3dc56234bd65b0d979749574e290a3a3fb00b8f014bf219c8bf969e2c4d1cd7f7f3
7
+ data.tar.gz: f3401998a0b1cd270e952107d86f2da78de98cc45b4260d7205998ff173e00f356d09185d08f50416bebe5b38593fe9cb40e829b2f4a4454bc3dafd53414227b
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # 1.5.0
2
+
3
+ * Complete upgrade of callback storage logic
4
+
5
+ # 1.4.0
6
+
7
+ * Allow setting callback expiration time on save and update
8
+
1
9
  # 1.3.0
2
10
 
3
11
  * Clean up callback arguments, remove unused `method_name`
@@ -3,42 +3,53 @@ require 'active_support/core_ext/numeric/time'
3
3
 
4
4
  module SlackBot
5
5
  class Callback
6
- CALLBACK_CACHE_KEY = "slack-bot-callback".freeze
6
+ CALLBACK_KEY_PREFIX = "slack-bot-callback".freeze
7
+ CALLBACK_RECORD_EXPIRES_IN = 15.minutes.freeze
7
8
 
8
- def self.find(id, config: nil)
9
+ def self.find(id, user: nil, config: nil)
9
10
  return if id.blank?
10
11
 
11
- callback = new(id: id, config: config)
12
+ callback = new(id: id, user: user, config: config)
12
13
  callback.reload
13
14
  rescue SlackBot::Errors::CallbackNotFound
14
15
  nil
15
16
  end
16
17
 
17
- def self.create(class_name:, user:, channel_id: nil, config: nil)
18
+ def self.create(class_name:, user:, channel_id: nil, config: nil, payload: nil, expires_in: nil, user_scope: nil)
18
19
  callback =
19
- new(class_name: class_name, user: user, channel_id: channel_id, config: config)
20
+ new(class_name: class_name, user: user, channel_id: channel_id, payload: payload, config: config, expires_in: expires_in, user_scope: user_scope)
20
21
  callback.save
21
22
  callback
22
23
  end
23
24
 
24
- attr_reader :id, :data, :args, :config
25
- def initialize(id: nil, class_name: nil, user: nil, channel_id: nil, extra: nil, config: nil)
25
+ def self.find_or_create(id:, class_name:, user:, channel_id: nil, config: nil, payload: nil, expires_in: nil, user_scope: nil)
26
+ callback = find(id, user: user, config: config)
27
+ return callback if callback.present?
28
+
29
+ create(class_name: class_name, user: user, channel_id: channel_id, payload: payload, config: config, expires_in: expires_in, user_scope: user_scope)
30
+ end
31
+
32
+ attr_reader :id, :data, :args, :config, :expires_in, :user_scope
33
+ def initialize(id: nil, class_name: nil, user: nil, channel_id: nil, payload: nil, config: nil, expires_in: nil, user_scope: nil)
26
34
  @id = id
27
35
  @data = {
28
36
  class_name: class_name,
29
37
  user_id: user&.id,
30
38
  channel_id: channel_id,
31
- extra: extra
39
+ payload: payload
32
40
  }
33
41
  @args = SlackBot::Args.new
34
42
  @config = config || SlackBot::Config.current_instance
43
+ @expires_in = expires_in || CALLBACK_RECORD_EXPIRES_IN
44
+ @user_scope = user_scope.nil? ? true : user_scope
35
45
  end
36
46
 
37
47
  def reload
38
- @data = read_data
39
- SlackBot::DevConsole.log_check("SlackBot::Callback#read_data: #{id} | #{data}")
40
- raise SlackBot::Errors::CallbackNotFound if data.nil?
48
+ cached_data = read_data
49
+ SlackBot::DevConsole.log_check("SlackBot::Callback#read_data: #{id} | #{cached_data}")
50
+ raise SlackBot::Errors::CallbackNotFound if cached_data.nil?
41
51
 
52
+ @data = cached_data
42
53
  parse_args
43
54
  self
44
55
  end
@@ -55,7 +66,12 @@ module SlackBot
55
66
  return if id.blank?
56
67
  return if data.blank?
57
68
 
58
- @data = data.merge(payload)
69
+ if @data[:payload].is_a?(Hash)
70
+ @data[:payload] = @data[:payload].merge(payload)
71
+ else
72
+ @data[:payload] = payload
73
+ end
74
+
59
75
  save
60
76
  end
61
77
 
@@ -72,6 +88,23 @@ module SlackBot
72
88
  end
73
89
  end
74
90
 
91
+ def user=(user)
92
+ @user = user
93
+ @data[:user_id] = user&.id
94
+ end
95
+
96
+ def class_name=(class_name)
97
+ @data[:class_name] = class_name
98
+ end
99
+
100
+ def channel_id=(channel_id)
101
+ @data[:channel_id] = channel_id
102
+ end
103
+
104
+ def payload=(payload)
105
+ @data[:payload] = payload
106
+ end
107
+
75
108
  def handler_class
76
109
  return if class_name.blank?
77
110
 
@@ -80,6 +113,7 @@ module SlackBot
80
113
 
81
114
  def method_missing(method_name, *args, &block)
82
115
  return data[method_name.to_sym] if data.key?(method_name.to_sym)
116
+ return data[:payload][method_name.to_s] if data[:payload].is_a?(Hash) && data[:payload].key?(method_name.to_s)
83
117
 
84
118
  super
85
119
  end
@@ -91,23 +125,34 @@ module SlackBot
91
125
  end
92
126
 
93
127
  def serialize_args
94
- data[:args] = args.to_s
128
+ @data[:args] = args.to_s
95
129
  end
96
130
 
97
131
  def generate_id
98
- SecureRandom.uuid
132
+ SecureRandom.hex(10)
133
+ end
134
+
135
+ def storage_key
136
+ if user_scope
137
+ raise "User is required for scoped callback" if user.blank?
138
+
139
+ "#{CALLBACK_KEY_PREFIX}:u#{user.id}:#{id}"
140
+ else
141
+ "#{CALLBACK_KEY_PREFIX}:#{id}"
142
+ end
99
143
  end
100
144
 
101
145
  def read_data
102
- config.callback_storage_instance.read("#{CALLBACK_CACHE_KEY}:#{id}")
146
+ config.callback_storage_instance.read(storage_key)
103
147
  end
104
148
 
105
- def write_data(data)
106
- config.callback_storage_instance.write("#{CALLBACK_CACHE_KEY}:#{id}", data, expires_in: 1.hour)
149
+ def write_data(data, expires_in: nil)
150
+ expires_in ||= CALLBACK_RECORD_EXPIRES_IN
151
+ config.callback_storage_instance.write(storage_key, data, expires_in: expires_in)
107
152
  end
108
153
 
109
154
  def delete_data
110
- config.callback_storage_instance.delete("#{CALLBACK_CACHE_KEY}:#{id}")
155
+ config.callback_storage_instance.delete(storage_key)
111
156
  end
112
157
  end
113
158
  end
@@ -88,7 +88,7 @@ module SlackBot
88
88
  callback = SlackBot::Callback.find(callback_id, config: config)
89
89
  raise SlackBot::Errors::CallbackNotFound.new if callback.blank?
90
90
 
91
- SlackBot::DevConsole.log_check "SlackApi::Interactions##{__method__}: #{callback.id} #{callback.extra} #{callback.user_id} #{user&.id}"
91
+ SlackBot::DevConsole.log_check "SlackApi::Interactions##{__method__}: #{callback.id} #{callback.payload} #{callback.user_id} #{user&.id}"
92
92
 
93
93
  if callback.user_id != user.id
94
94
  raise "Callback user is not equal to action user"
data/lib/slack_bot.rb CHANGED
@@ -22,5 +22,5 @@ require 'slack_bot/pager'
22
22
  require 'slack_bot/grape_extension'
23
23
 
24
24
  module SlackBot
25
- VERSION = '1.3.0'.freeze
25
+ VERSION = '1.5.1'.freeze
26
26
  end
@@ -6,7 +6,7 @@ describe SlackBot::Callback do
6
6
  class_name: "Test",
7
7
  user: user,
8
8
  channel_id: "test_channel_id",
9
- extra: { test: "test" },
9
+ payload: { test: "test" },
10
10
  config: config
11
11
  )
12
12
  }
@@ -26,174 +26,115 @@ describe SlackBot::Callback do
26
26
  let(:callback_id) { "test_callback_id" }
27
27
 
28
28
  describe ".find" do
29
- subject(:find) { described_class.find(callback_id, config: config) }
29
+ subject(:find) { described_class.find(callback_id, user: user, config: config) }
30
30
 
31
- before do
32
- allow(callback_storage_instance).to receive(:read).with("slack-bot-callback:test_callback_id").and_return(data)
33
- end
34
-
35
- context "when callback is found" do
36
- let(:data) { { class_name: "Test", user_id: 1, channel_id: "test_channel_id", extra: { test: "test" }, args: "" } }
37
-
38
- it "returns callback" do
39
- expect(find).to be_a(described_class)
40
- expect(find.id).to eq(callback_id)
41
- expect(find.class_name).to eq("Test")
42
- expect(find.user).to eq(user)
43
- expect(find.user_id).to eq(1)
44
- expect(find.channel_id).to eq("test_channel_id")
45
- expect(find.extra).to eq({ test: "test" })
46
- end
47
- end
48
-
49
- context "when callback is not found" do
50
- let(:data) { nil }
51
-
52
- it "returns nil" do
53
- expect(find).to eq(nil)
54
- end
55
- end
56
- end
57
-
58
- describe ".create" do
59
- subject(:create) { described_class.create(class_name: "Test", user: user, channel_id: "test_channel_id", config: config) }
60
-
61
- before do
62
- allow_any_instance_of(described_class).to receive(:generate_id).and_return("test_callback_id")
63
- allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
64
- args: "",
65
- class_name: "Test",
66
- user_id: 1,
67
- channel_id: "test_channel_id",
68
- extra: nil
69
- }, expires_in: 1.hour)
70
- end
71
-
72
- let(:data) { { class_name: "Test", user_id: 1, channel_id: "test_channel_id", extra: nil } }
73
-
74
- it "returns callback" do
75
- expect(create).to be_a(described_class)
76
- expect(create.id).to eq("test_callback_id")
77
- expect(create.class_name).to eq("Test")
78
- expect(create.user).to eq(user)
79
- expect(create.user_id).to eq(1)
80
- expect(create.channel_id).to eq("test_channel_id")
81
- expect(create.extra).to eq(nil)
82
- end
83
- end
84
-
85
- describe "#reload" do
86
- subject(:reload) { callback.reload }
87
- let(:callback) {
88
- described_class.new(id: "test_callback_id", config: config)
89
- }
90
- let(:data) {
31
+ let(:cached_data) {
91
32
  {
92
33
  class_name: "Test",
93
- user_id: 1,
34
+ user_id: user.id,
94
35
  channel_id: "test_channel_id",
95
- extra: { test: "test" },
96
- args: ""
36
+ payload: { test: "test" },
37
+ args: "test"
97
38
  }
98
39
  }
99
40
 
100
41
  before do
101
- allow(callback_storage_instance).to receive(:read).with("slack-bot-callback:test_callback_id").and_return(data)
42
+ allow(callback_storage_instance).to receive(:read).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}").and_return(cached_data)
102
43
  end
103
44
 
104
45
  it "returns callback" do
105
- expect(reload).to be_a(described_class)
106
- expect(reload.id).to eq("test_callback_id")
107
- expect(reload.class_name).to eq("Test")
108
- expect(reload.user).to eq(user)
109
- expect(reload.user_id).to eq(1)
110
- expect(reload.channel_id).to eq("test_channel_id")
111
- expect(reload.extra).to eq({ test: "test" })
46
+ expect(find).to be_a(described_class)
47
+ expect(find.id).to eq(callback_id)
48
+ expect(find.class_name).to eq("Test")
49
+ expect(find.user).to eq(user)
50
+ expect(find.channel_id).to eq("test_channel_id")
51
+ expect(find.payload).to eq({ test: "test" })
52
+ expect(find.args).to be_a(SlackBot::Args)
112
53
  end
113
54
 
114
55
  context "when callback is not found" do
115
- let(:data) { nil }
56
+ let(:cached_data) { nil }
116
57
 
117
- it "raises error" do
118
- expect { reload }.to raise_error(SlackBot::Errors::CallbackNotFound)
58
+ it "returns nil" do
59
+ expect(find).to be_nil
119
60
  end
120
61
  end
121
62
  end
122
63
 
123
- describe "#save" do
124
- subject(:save) { callback.save }
125
- let(:callback) {
126
- described_class.new(
64
+ describe ".create" do
65
+ subject(:create) {
66
+ described_class.create(
127
67
  class_name: "Test",
128
68
  user: user,
129
69
  channel_id: "test_channel_id",
130
- extra: { test: "test" },
70
+ payload: { test: "test" },
131
71
  config: config
132
72
  )
133
73
  }
134
74
 
135
- before do
136
- allow_any_instance_of(described_class).to receive(:generate_id).and_return("test_callback_id")
137
- allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
138
- args: "",
75
+ let(:cached_data) {
76
+ {
139
77
  class_name: "Test",
140
- user_id: 1,
78
+ user_id: user.id,
141
79
  channel_id: "test_channel_id",
142
- extra: { test: "test" }
143
- }, expires_in: 1.hour)
80
+ payload: { test: "test" },
81
+ args: ""
82
+ }
83
+ }
84
+
85
+ before do
86
+ allow_any_instance_of(described_class).to receive(:generate_id).and_return(callback_id)
87
+ allow(callback_storage_instance).to receive(:write).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}", cached_data, expires_in: SlackBot::Callback::CALLBACK_RECORD_EXPIRES_IN).and_return(cached_data)
88
+ allow(callback_storage_instance).to receive(:read).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}").and_return(cached_data)
144
89
  end
145
90
 
146
- it "returns callback" do
147
- expect { save }.not_to raise_error
148
- expect(callback).to be_a(described_class)
149
- expect(callback.id).to eq("test_callback_id")
150
- expect(callback.args).to be_a(SlackBot::Args)
91
+ it "creates callback" do
92
+ expect(create).to be_a(described_class)
93
+ expect(create.id).to be_present
94
+ expect(create.class_name).to eq("Test")
95
+ expect(create.user).to eq(user)
96
+ expect(create.channel_id).to eq("test_channel_id")
97
+ expect(create.payload).to eq({ test: "test" })
98
+ expect(create.args).to be_a(SlackBot::Args)
151
99
  end
152
100
  end
153
101
 
154
- describe "#update" do
155
- subject(:update) { callback.update(payload) }
156
- let(:callback) {
157
- described_class.new(
158
- id: "test_callback_id",
102
+ describe ".find_or_create" do
103
+ subject(:find_or_create) {
104
+ described_class.find_or_create(
105
+ id: callback_id,
159
106
  class_name: "Test",
160
107
  user: user,
161
108
  channel_id: "test_channel_id",
162
- extra: { test: "test" },
109
+ payload: { test: "test" },
163
110
  config: config
164
111
  )
165
112
  }
166
113
 
167
- before do
168
- allow(callback_storage_instance).to receive(:write).with("slack-bot-callback:test_callback_id", {
169
- args: "",
114
+ let(:cached_data) {
115
+ {
170
116
  class_name: "Test",
171
- user_id: 1,
117
+ user_id: user.id,
172
118
  channel_id: "test_channel_id",
173
- extra: { test: "test" },
174
- test: "test"
175
- }, expires_in: 1.hour)
176
- end
177
-
178
- let(:payload) { { test: "test" } }
119
+ payload: { test: "test" },
120
+ args: ""
121
+ }
122
+ }
179
123
 
180
- it "returns callback" do
181
- expect { update }.not_to raise_error
182
- expect(callback).to be_a(described_class)
183
- expect(callback.id).to eq("test_callback_id")
184
- expect(callback.args).to be_a(SlackBot::Args)
124
+ before do
125
+ allow_any_instance_of(described_class).to receive(:generate_id).and_return(callback_id)
126
+ allow(callback_storage_instance).to receive(:write).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}", cached_data, expires_in: SlackBot::Callback::CALLBACK_RECORD_EXPIRES_IN).and_return(cached_data)
127
+ allow(callback_storage_instance).to receive(:read).with("#{SlackBot::Callback::CALLBACK_KEY_PREFIX}:u#{user.id}:#{callback_id}").and_return(cached_data)
185
128
  end
186
- end
187
-
188
- describe "#destroy" do
189
-
190
- end
191
-
192
- describe "#user" do
193
-
194
- end
195
-
196
- describe "#handler_class" do
197
129
 
130
+ it "finds or creates callback" do
131
+ expect(find_or_create).to be_a(described_class)
132
+ expect(find_or_create.id).to eq(callback_id)
133
+ expect(find_or_create.class_name).to eq("Test")
134
+ expect(find_or_create.user).to eq(user)
135
+ expect(find_or_create.channel_id).to eq("test_channel_id")
136
+ expect(find_or_create.payload).to eq({ test: "test" })
137
+ expect(find_or_create.args).to be_a(SlackBot::Args)
138
+ end
198
139
  end
199
140
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-slack-bot
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Makarov