lita-totems 0.1.0 → 0.2.0
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 +4 -4
- data/.gitignore +1 -0
- data/lib/lita/handlers/totems.rb +85 -37
- data/lita-totems.gemspec +7 -6
- data/spec/lita/handlers/totems_spec.rb +201 -38
- data/spec/spec_helper.rb +1 -0
- metadata +42 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fcebd655b6abfd2ae0fffb0e2477455a847b24fd
|
4
|
+
data.tar.gz: 078b012853bfc626e605eb8d7f20c128b99e9187
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 53da90a7de19a6d7143b77dc7ab7716cb6749b8acc130210b4f86f3a3463b0541637b5c4d43a459b02539a890be51f2308825774bf8a004dd72f909404beba1f
|
7
|
+
data.tar.gz: 2d4c22bc113044b5e75d4a4df7f2b97681a44c737d032dd7f383cc0d5cc6c8a73e48ca5cc34a7c52cd129ece6d430afabfee9e04ef42360225745d72444cbabb
|
data/.gitignore
CHANGED
data/lib/lita/handlers/totems.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require '
|
3
|
-
require 'active_support/core_ext/object/blank'
|
1
|
+
require 'lita'
|
2
|
+
require 'chronic_duration'
|
4
3
|
require 'redis-semaphore'
|
5
4
|
|
6
5
|
module Lita
|
@@ -56,11 +55,11 @@ module Lita
|
|
56
55
|
)?
|
57
56
|
$
|
58
57
|
}x,
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
:info,
|
59
|
+
help: {
|
60
|
+
'totems info' => "Shows info of all totems queues",
|
61
|
+
'totems info TOTEM' => 'Shows info of just one totem'
|
62
|
+
})
|
64
63
|
|
65
64
|
def destroy(response)
|
66
65
|
totem = response.match_data[:totem]
|
@@ -70,6 +69,7 @@ module Lita
|
|
70
69
|
redis.srem("totems", totem)
|
71
70
|
owning_user_id = redis.get("totem/#{totem}/owning_user_id")
|
72
71
|
redis.srem("user/#{owning_user_id}/totems", totem) if owning_user_id
|
72
|
+
redis.del("totem/#{totem}/waiting_since")
|
73
73
|
response.reply(%{Destroyed totem "#{totem}".})
|
74
74
|
else
|
75
75
|
response.reply(%{Error: totem "#{totem}" doesn't exist.})
|
@@ -98,45 +98,65 @@ module Lita
|
|
98
98
|
|
99
99
|
user_id = response.user.id
|
100
100
|
|
101
|
+
if queued_by_user(user_id).include?(totem)
|
102
|
+
response.reply %{Error: you are already in the queue for "#{totem}".}
|
103
|
+
return
|
104
|
+
end
|
105
|
+
|
106
|
+
if redis.smembers("user/#{user_id}/totems").include?(totem)
|
107
|
+
response.reply %{Error: you already have the totem "#{totem}".}
|
108
|
+
return
|
109
|
+
end
|
110
|
+
|
101
111
|
token_acquired = false
|
102
112
|
queue_size = nil
|
103
113
|
Redis::Semaphore.new("totem/#{totem}", redis: redis).lock do
|
104
|
-
if redis.llen("totem/#{totem}/list") == 0 && redis.get("totem/#{totem}/owning_user_id").
|
114
|
+
if redis.llen("totem/#{totem}/list") == 0 && redis.get("totem/#{totem}/owning_user_id").nil?
|
105
115
|
# take it:
|
106
116
|
token_acquired = true
|
107
117
|
redis.set("totem/#{totem}/owning_user_id", user_id)
|
118
|
+
redis.hset("totem/#{totem}/waiting_since", user_id, Time.now.to_i)
|
108
119
|
else
|
109
120
|
# queue:
|
110
|
-
queue_size = redis.
|
121
|
+
queue_size = redis.rpush("totem/#{totem}/list", user_id)
|
122
|
+
redis.hset("totem/#{totem}/waiting_since", user_id, Time.now.to_i)
|
111
123
|
end
|
112
124
|
end
|
113
125
|
|
114
126
|
if token_acquired
|
127
|
+
# TODO don't readd to totems you are already waiting for!
|
115
128
|
redis.sadd("user/#{user_id}/totems", totem)
|
116
129
|
response.reply(%{#{response.user.name}, you now have totem "#{totem}".})
|
117
130
|
else
|
118
|
-
response.reply(%{#{response.user.name}, you are
|
131
|
+
response.reply(%{#{response.user.name}, you are \##{queue_size} in line for totem "#{totem}".})
|
119
132
|
end
|
120
133
|
|
121
134
|
end
|
122
135
|
|
123
136
|
def yield(response)
|
124
|
-
user_id
|
125
|
-
totems_owned_by_user
|
126
|
-
|
137
|
+
user_id = response.user.id
|
138
|
+
totems_owned_by_user = redis.smembers("user/#{user_id}/totems")
|
139
|
+
totems_queued_by_user = queued_by_user(user_id)
|
140
|
+
if totems_owned_by_user.empty? && totems_queued_by_user.empty?
|
127
141
|
response.reply "Error: You do not have any totems to yield."
|
128
|
-
elsif totems_owned_by_user.size == 1
|
142
|
+
elsif totems_owned_by_user.size == 1 && !response.match_data[:totem] && totems_queued_by_user.empty?
|
129
143
|
yield_totem(totems_owned_by_user[0], user_id, response)
|
130
|
-
else
|
144
|
+
else
|
131
145
|
totem_specified = response.match_data[:totem]
|
146
|
+
# if they don't specify and are only queued for a single totem, yield that one
|
147
|
+
totem_specified = totems_queued_by_user.first if !totem_specified && totems_queued_by_user.size == 1 && totems_owned_by_user.empty?
|
132
148
|
if totem_specified
|
133
149
|
if totems_owned_by_user.include?(totem_specified)
|
134
150
|
yield_totem(totem_specified, user_id, response)
|
151
|
+
elsif totems_queued_by_user.include?(totem_specified)
|
152
|
+
redis.lrem("totem/#{totem_specified}/list", 0, user_id)
|
153
|
+
redis.hdel("totem/#{totem_specified}/waiting_since", user_id)
|
154
|
+
response.reply("You are no longer in line for the \"#{totem_specified}\" totem.")
|
135
155
|
else
|
136
|
-
response.reply %{Error: You don't own the "#{totem_specified}" totem.}
|
156
|
+
response.reply %{Error: You don't own and aren't waiting for the "#{totem_specified}" totem.}
|
137
157
|
end
|
138
158
|
else
|
139
|
-
response.reply "You must specify a totem to yield. Totems you own: #{totems_owned_by_user.sort}"
|
159
|
+
response.reply "You must specify a totem to yield. Totems you own: #{totems_owned_by_user.sort}. Totems you are in line for: #{totems_queued_by_user.sort}."
|
140
160
|
end
|
141
161
|
end
|
142
162
|
end
|
@@ -155,57 +175,85 @@ module Lita
|
|
155
175
|
end
|
156
176
|
|
157
177
|
redis.srem("user/#{past_owning_user_id}/totems", totem)
|
158
|
-
|
178
|
+
redis.hdel("totem/#{totem}/waiting_since", past_owning_user_id)
|
179
|
+
robot.send_messages(Lita::Source.new(user: Lita::User.find_by_id(past_owning_user_id)), %{You have been kicked from totem "#{totem}".})
|
159
180
|
next_user_id = redis.lpop("totem/#{totem}/list")
|
160
|
-
redis.set("totem/#{totem}/owning_user_id", next_user_id)
|
161
181
|
if next_user_id
|
182
|
+
redis.set("totem/#{totem}/owning_user_id", next_user_id)
|
162
183
|
redis.sadd("user/#{next_user_id}/totems", totem)
|
163
|
-
|
184
|
+
redis.hset("totem/#{totem}/waiting_since", next_user_id, Time.now.to_i)
|
185
|
+
robot.send_messages(Lita::Source.new(user: Lita::User.find_by_id(next_user_id)), %{You are now in possession of totem "#{totem}".})
|
186
|
+
else
|
187
|
+
redis.del("totem/#{totem}/owning_user_id")
|
164
188
|
end
|
165
189
|
|
166
190
|
end
|
167
191
|
|
168
192
|
def info(response)
|
169
193
|
totem_param = response.match_data[:totem]
|
170
|
-
resp
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
194
|
+
resp = unless totem_param.nil? || totem_param.empty?
|
195
|
+
list_users_print(totem_param)
|
196
|
+
else
|
197
|
+
users_cache = new_users_cache
|
198
|
+
r = "Totems:\n"
|
199
|
+
redis.smembers("totems").each do |totem|
|
200
|
+
r += "- #{totem}\n"
|
201
|
+
r += list_users_print(totem, ' ', users_cache)
|
202
|
+
end
|
203
|
+
r
|
204
|
+
end
|
180
205
|
response.reply resp
|
181
206
|
end
|
182
207
|
|
183
208
|
private
|
184
|
-
def
|
209
|
+
def new_users_cache
|
210
|
+
Hash.new { |h, id| h[id] = Lita::User.find_by_id(id) }
|
211
|
+
end
|
212
|
+
|
213
|
+
def list_users_print(totem, prefix='', users_cache=new_users_cache)
|
185
214
|
str = ''
|
186
215
|
first_id = redis.get("totem/#{totem}/owning_user_id")
|
187
216
|
if first_id
|
188
|
-
|
217
|
+
waiting_since_hash = redis.hgetall("totem/#{totem}/waiting_since")
|
218
|
+
str += "#{prefix}1. #{users_cache[first_id].name} (held for #{waiting_duration(waiting_since_hash[first_id])})\n"
|
189
219
|
rest = redis.lrange("totem/#{totem}/list", 0, -1)
|
190
220
|
rest.each_with_index do |user_id, index|
|
191
|
-
str += "#{prefix}#{index+2}.
|
221
|
+
str += "#{prefix}#{index+2}. #{users_cache[user_id].name} (waiting for #{waiting_duration(waiting_since_hash[user_id])})\n"
|
192
222
|
end
|
193
223
|
end
|
194
224
|
str
|
195
225
|
end
|
196
226
|
|
227
|
+
def waiting_duration(time)
|
228
|
+
ChronicDuration.output(Time.now.to_i - time.to_i, format: :short) || "0s"
|
229
|
+
end
|
230
|
+
|
197
231
|
def yield_totem(totem, user_id, response)
|
198
232
|
redis.srem("user/#{user_id}/totems", totem)
|
233
|
+
redis.hdel("totem/#{totem}/waiting_since", user_id)
|
199
234
|
next_user_id = redis.lpop("totem/#{totem}/list")
|
200
235
|
if next_user_id
|
236
|
+
redis.set("totem/#{totem}/owning_user_id", next_user_id)
|
201
237
|
redis.sadd("user/#{next_user_id}/totems", totem)
|
202
|
-
|
203
|
-
|
238
|
+
redis.hset("totem/#{totem}/waiting_since", next_user_id, Time.now.to_i)
|
239
|
+
next_user = Lita::User.find_by_id(next_user_id)
|
240
|
+
robot.send_messages(Lita::Source.new(user: next_user), %{You are now in possession of totem "#{totem}."})
|
241
|
+
response.reply "You have yielded the totem to #{next_user.name}."
|
204
242
|
else
|
243
|
+
redis.del("totem/#{totem}/owning_user_id")
|
205
244
|
response.reply %{You have yielded the "#{totem}" totem.}
|
206
245
|
end
|
207
|
-
redis.set("totem/#{totem}/owning_user_id", next_user_id)
|
208
246
|
end
|
247
|
+
|
248
|
+
def queued_by_user(user_id)
|
249
|
+
redis.smembers("totems").select do |totem|
|
250
|
+
# there's no easy way to check membership in a list in redis
|
251
|
+
# right now let's iterate through the list, but to make this
|
252
|
+
# more performant we could convert these lists to sorted sets
|
253
|
+
redis.lrange("totem/#{totem}/list", 0, -1).include?(user_id)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
209
257
|
end
|
210
258
|
|
211
259
|
Lita.register_handler(Totems)
|
data/lita-totems.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
Gem::Specification.new do |spec|
|
2
2
|
spec.name = "lita-totems"
|
3
|
-
spec.version = "0.
|
4
|
-
spec.authors = ["Charles Finkel"]
|
5
|
-
spec.email = ["cf@dropbox.com"]
|
3
|
+
spec.version = "0.2.0"
|
4
|
+
spec.authors = ["Charles Finkel", "Vijay Ramesh"]
|
5
|
+
spec.email = ["cf@dropbox.com", "vijay@change.org"]
|
6
6
|
spec.description = %q{Totems handler for Lita)}
|
7
7
|
spec.summary = %q{Adds support to Lita for Totems}
|
8
8
|
spec.homepage = "https://github.com/charleseff/lita-totems"
|
@@ -13,13 +13,14 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
14
|
spec.require_paths = ["lib"]
|
15
15
|
|
16
|
-
spec.add_runtime_dependency "lita", "
|
17
|
-
spec.add_runtime_dependency "
|
16
|
+
spec.add_runtime_dependency "lita", ">= 2.4"
|
17
|
+
spec.add_runtime_dependency "chronic_duration"
|
18
18
|
spec.add_runtime_dependency "redis-semaphore"
|
19
19
|
|
20
20
|
spec.add_development_dependency "bundler", "~> 1.3"
|
21
21
|
spec.add_development_dependency "rake"
|
22
|
-
spec.add_development_dependency "rspec", ">=
|
22
|
+
spec.add_development_dependency "rspec", ">= 3.0.0.beta1"
|
23
23
|
spec.add_development_dependency "simplecov"
|
24
|
+
spec.add_development_dependency "timecop"
|
24
25
|
spec.add_development_dependency "coveralls"
|
25
26
|
end
|
@@ -97,9 +97,30 @@ describe Lita::Handlers::Totems, lita_handler: true do
|
|
97
97
|
end
|
98
98
|
it "adds user to the queue" do
|
99
99
|
send_message("totems add chicken", as: carl)
|
100
|
-
expect(replies.last).to eq('Carl, you are
|
100
|
+
expect(replies.last).to eq('Carl, you are #2 in line for totem "chicken".')
|
101
101
|
end
|
102
102
|
end
|
103
|
+
context "when the user is already holding the totem" do
|
104
|
+
before do
|
105
|
+
send_message("totems add chicken", as: carl)
|
106
|
+
end
|
107
|
+
it "returns an error message" do
|
108
|
+
send_message("totems add chicken", as: carl)
|
109
|
+
expect(replies.last).to eq('Error: you already have the totem "chicken".')
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "when the user is already in line for the totem" do
|
114
|
+
before do
|
115
|
+
send_message("totems add chicken", as: another_user)
|
116
|
+
send_message("totems add chicken", as: carl)
|
117
|
+
end
|
118
|
+
it "returns an error message" do
|
119
|
+
send_message("totems add chicken", as: carl)
|
120
|
+
expect(replies.last).to eq('Error: you are already in the queue for "chicken".')
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
103
124
|
end
|
104
125
|
|
105
126
|
context "when the totem doesn't exist" do
|
@@ -107,39 +128,61 @@ describe Lita::Handlers::Totems, lita_handler: true do
|
|
107
128
|
send_message("totems add chicken", as: carl)
|
108
129
|
expect(replies.last).to eq('Error: there is no totem "chicken".')
|
109
130
|
end
|
110
|
-
|
111
131
|
end
|
112
|
-
|
113
132
|
end
|
114
133
|
|
115
134
|
describe "yield" do
|
116
135
|
before do
|
117
136
|
send_message("totems create chicken")
|
137
|
+
send_message("totems create duck")
|
118
138
|
end
|
119
139
|
|
120
140
|
context "when user has one totem" do
|
121
141
|
before do
|
122
|
-
|
142
|
+
Timecop.freeze("2014-03-01 11:00:00") do
|
143
|
+
send_message("totems add chicken", as: carl)
|
144
|
+
end
|
123
145
|
end
|
124
146
|
|
125
147
|
context "someone else is in line" do
|
126
148
|
before do
|
127
|
-
|
149
|
+
Timecop.freeze("2014-03-01 12:00:00") do
|
150
|
+
send_message("totems add chicken", as: another_user)
|
151
|
+
send_message("totems add chicken", as: yet_another_user)
|
152
|
+
end
|
128
153
|
end
|
129
154
|
it "yields that totem, gives to the next person in line" do
|
130
155
|
expect(robot).to receive(:send_messages) do |target, message|
|
131
|
-
expect(target.id).to eq(another_user.id)
|
156
|
+
expect(target.user.id).to eq(another_user.id)
|
132
157
|
expect(message).to eq(%{You are now in possession of totem "chicken."})
|
133
158
|
end
|
134
159
|
send_message("totems yield", as: carl)
|
135
160
|
# todo: check for message to other user
|
136
|
-
expect(replies.last).to eq("You have yielded the totem to #{another_user.
|
161
|
+
expect(replies.last).to eq("You have yielded the totem to #{another_user.name}.")
|
162
|
+
end
|
163
|
+
it "updates the waiting since value for the new holder" do
|
164
|
+
Timecop.freeze("2014-03-01 13:00:00") do
|
165
|
+
send_message("totems info chicken")
|
166
|
+
expect(replies.last).to eq <<-END
|
167
|
+
1. Carl (held for 2h)
|
168
|
+
2. Test User (waiting for 1h)
|
169
|
+
3. person_2 (waiting for 1h)
|
170
|
+
END
|
171
|
+
send_message("totems yield", as: carl)
|
172
|
+
send_message("totems info chicken")
|
173
|
+
expect(replies.last).to eq <<-END
|
174
|
+
1. Test User (held for 0s)
|
175
|
+
2. person_2 (waiting for 1h)
|
176
|
+
END
|
177
|
+
end
|
137
178
|
end
|
138
179
|
end
|
139
180
|
context "nobody else is in line" do
|
140
|
-
it "yields the totem" do
|
181
|
+
it "yields the totem and clears the owning_user_id" do
|
141
182
|
send_message("totems yield", as: carl)
|
142
183
|
expect(replies.last).to eq(%{You have yielded the "chicken" totem.})
|
184
|
+
send_message("totems info chicken")
|
185
|
+
expect(replies.last).to eq ""
|
143
186
|
end
|
144
187
|
end
|
145
188
|
end
|
@@ -159,7 +202,7 @@ describe Lita::Handlers::Totems, lita_handler: true do
|
|
159
202
|
context "user doesn't have that totem" do
|
160
203
|
it "sends error message" do
|
161
204
|
send_message("totems yield duck", as: carl)
|
162
|
-
expect(replies.last).to eq(%{Error: You don't own the "duck" totem.})
|
205
|
+
expect(replies.last).to eq(%{Error: You don't own and aren't waiting for the "duck" totem.})
|
163
206
|
end
|
164
207
|
end
|
165
208
|
context "user has that totem" do
|
@@ -173,36 +216,149 @@ describe Lita::Handlers::Totems, lita_handler: true do
|
|
173
216
|
context "when not specifying a totem" do
|
174
217
|
it "sends a message about which totem it can yield" do
|
175
218
|
send_message("totems yield", as: carl)
|
176
|
-
expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: ["chicken", "#{other_totem}"]})
|
219
|
+
expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: ["chicken", "#{other_totem}"]. Totems you are in line for: [].})
|
177
220
|
end
|
178
221
|
end
|
222
|
+
end
|
223
|
+
context "when the user is in line for a single totem" do
|
224
|
+
before do
|
225
|
+
Timecop.freeze("2014-03-02 13:00:00") do
|
226
|
+
send_message("totems add chicken", as: another_user)
|
227
|
+
send_message("totems add chicken", as: carl)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
context "when specifying a totem" do
|
231
|
+
context "user is not in line for that totem" do
|
232
|
+
it "sends error message" do
|
233
|
+
send_message("totems yield duck", as: carl)
|
234
|
+
expect(replies.last).to eq(%{Error: You don't own and aren't waiting for the "duck" totem.})
|
235
|
+
end
|
236
|
+
end
|
237
|
+
context "user is in line for that totem" do
|
238
|
+
it "yields totem and does not update holder" do
|
239
|
+
Timecop.freeze("2014-03-02 14:00:00") do
|
240
|
+
send_message("totems yield chicken", as: carl)
|
241
|
+
expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
|
242
|
+
send_message("totems info chicken")
|
243
|
+
expect(replies.last).to eq("1. Test User (held for 1h)\n")
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
context "when not specifying a totem" do
|
249
|
+
it "yields totem and does not update holder" do
|
250
|
+
Timecop.freeze("2014-03-02 14:00:00") do
|
251
|
+
send_message("totems yield", as: carl)
|
252
|
+
expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
|
253
|
+
send_message("totems info chicken")
|
254
|
+
expect(replies.last).to eq("1. Test User (held for 1h)\n")
|
255
|
+
end
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
179
259
|
|
260
|
+
context "when the user is in line for multiple totems" do
|
261
|
+
before do
|
262
|
+
Timecop.freeze("2014-03-02 13:00:00") do
|
263
|
+
send_message("totems add chicken", as: another_user)
|
264
|
+
send_message("totems add chicken", as: carl)
|
265
|
+
send_message("totems add chicken", as: yet_another_user)
|
266
|
+
send_message("totems add duck", as: yet_another_user)
|
267
|
+
send_message("totems add duck", as: carl)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
context "when specifying a totem" do
|
271
|
+
context "user is in line for that totem" do
|
272
|
+
it "yields totem and does not update holder" do
|
273
|
+
Timecop.freeze("2014-03-02 14:00:00") do
|
274
|
+
send_message("totems yield chicken", as: carl)
|
275
|
+
expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
|
276
|
+
send_message("totems info chicken")
|
277
|
+
expect(replies.last).to eq("1. Test User (held for 1h)\n2. person_2 (waiting for 1h)\n")
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
context "when not specifying a totem" do
|
283
|
+
it "sends error message" do
|
284
|
+
Timecop.freeze("2014-03-02 14:00:00") do
|
285
|
+
send_message("totems yield", as: carl)
|
286
|
+
expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: []. Totems you are in line for: ["chicken", "duck"].})
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
180
290
|
end
|
181
291
|
|
292
|
+
context "when the user is in line for a totem and has another totem" do
|
293
|
+
before do
|
294
|
+
Timecop.freeze("2014-03-02 13:00:00") do
|
295
|
+
send_message("totems add chicken", as: another_user)
|
296
|
+
send_message("totems add chicken", as: carl)
|
297
|
+
send_message("totems add chicken", as: yet_another_user)
|
298
|
+
send_message("totems add duck", as: carl)
|
299
|
+
send_message("totems add duck", as: another_user)
|
300
|
+
end
|
301
|
+
end
|
302
|
+
context "when specifying a totem" do
|
303
|
+
context "user is in line for that totem" do
|
304
|
+
it "yields totem and does not update holder" do
|
305
|
+
Timecop.freeze("2014-03-02 14:00:00") do
|
306
|
+
send_message("totems yield chicken", as: carl)
|
307
|
+
expect(replies.last).to eq(%{You are no longer in line for the "chicken" totem.})
|
308
|
+
send_message("totems info chicken")
|
309
|
+
expect(replies.last).to eq("1. Test User (held for 1h)\n2. person_2 (waiting for 1h)\n")
|
310
|
+
end
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
context "when not specifying a totem" do
|
315
|
+
it "sends error message" do
|
316
|
+
Timecop.freeze("2014-03-02 14:00:00") do
|
317
|
+
send_message("totems yield", as: carl)
|
318
|
+
expect(replies.last).to eq(%{You must specify a totem to yield. Totems you own: ["duck"]. Totems you are in line for: ["chicken"].})
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
182
323
|
end
|
183
324
|
|
325
|
+
|
326
|
+
|
184
327
|
describe "kick" do
|
185
328
|
before do
|
186
329
|
send_message("totems create chicken")
|
187
330
|
end
|
188
|
-
context "there is a user owning the totem" do
|
331
|
+
context "there is a user owning the totem and somebody else waiting for it" do
|
189
332
|
before do
|
190
333
|
send_message("totems add chicken", as: another_user)
|
191
334
|
send_message("totems add chicken", as: carl)
|
192
335
|
end
|
193
336
|
it "should notify that user that she has been kicked" do
|
194
337
|
expect(robot).to receive(:send_messages) do |target, message|
|
195
|
-
expect(target.id).to eq(another_user.id)
|
338
|
+
expect(target.user.id).to eq(another_user.id)
|
196
339
|
expect(message).to eq(%{You have been kicked from totem "chicken".})
|
197
340
|
end
|
198
341
|
send_message("totems kick chicken")
|
199
|
-
|
200
342
|
end
|
201
343
|
it "should notify next user in line that she now has the totem" do
|
202
344
|
send_message("totems kick chicken")
|
203
345
|
expect(replies.last).to eq(%{You are now in possession of totem "chicken".})
|
204
346
|
end
|
347
|
+
end
|
205
348
|
|
349
|
+
context "there is a user owning the totem" do
|
350
|
+
before do
|
351
|
+
send_message("totems add chicken", as: carl)
|
352
|
+
end
|
353
|
+
it "should notify that user that she has been kicked and clear the owning_user_id" do
|
354
|
+
expect(robot).to receive(:send_messages) do |target, message|
|
355
|
+
expect(target.user.id).to eq(carl.id)
|
356
|
+
expect(message).to eq(%{You have been kicked from totem "chicken".})
|
357
|
+
end
|
358
|
+
send_message("totems kick chicken")
|
359
|
+
send_message("totems info chicken")
|
360
|
+
expect(replies.last).to eq ""
|
361
|
+
end
|
206
362
|
end
|
207
363
|
|
208
364
|
context "nobody owns that totem" do
|
@@ -215,42 +371,49 @@ describe Lita::Handlers::Totems, lita_handler: true do
|
|
215
371
|
|
216
372
|
describe "info" do
|
217
373
|
before do
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
374
|
+
Timecop.freeze("2014-03-01 12:00:00") do
|
375
|
+
send_message("totems create chicken")
|
376
|
+
send_message("totems create duck")
|
377
|
+
send_message("totems create ball")
|
378
|
+
send_message("totems add chicken", as: carl)
|
379
|
+
send_message("totems add chicken", as: another_user)
|
380
|
+
send_message("totems add chicken", as: yet_another_user)
|
381
|
+
send_message("totems add duck", as: yet_another_user)
|
382
|
+
send_message("totems add duck", as: carl)
|
383
|
+
end
|
226
384
|
end
|
227
385
|
context "totem is passed" do
|
228
386
|
it "shows info for just that totem" do
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
387
|
+
Timecop.freeze("2014-03-01 13:00:00") do
|
388
|
+
send_message("totems info chicken")
|
389
|
+
expect(replies.last).to eq <<-END
|
390
|
+
1. Carl (held for 1h)
|
391
|
+
2. Test User (waiting for 1h)
|
392
|
+
3. person_2 (waiting for 1h)
|
393
|
+
END
|
394
|
+
end
|
235
395
|
end
|
236
396
|
end
|
237
397
|
|
238
398
|
context "totem isn't passed" do
|
239
399
|
it "shows info for all totems" do
|
240
|
-
|
241
|
-
|
400
|
+
Timecop.freeze("2014-03-02 13:00:00") do
|
401
|
+
send_message("totems info")
|
402
|
+
expect(replies.last).to include <<-END
|
242
403
|
- chicken
|
243
|
-
1.
|
244
|
-
2. User
|
245
|
-
|
246
|
-
|
404
|
+
1. Carl (held for 1d 1h)
|
405
|
+
2. Test User (waiting for 1d 1h)
|
406
|
+
3. person_2 (waiting for 1d 1h)
|
407
|
+
END
|
408
|
+
expect(replies.last).to include <<-END
|
247
409
|
- duck
|
248
|
-
1.
|
249
|
-
2.
|
250
|
-
|
251
|
-
|
410
|
+
1. person_2 (held for 1d 1h)
|
411
|
+
2. Carl (waiting for 1d 1h)
|
412
|
+
END
|
413
|
+
expect(replies.last).to include <<-END
|
252
414
|
- ball
|
253
|
-
|
415
|
+
END
|
416
|
+
end
|
254
417
|
end
|
255
418
|
end
|
256
419
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,136 +1,152 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lita-totems
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Charles Finkel
|
8
|
+
- Vijay Ramesh
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2014-03-07 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: lita
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
|
-
- -
|
18
|
+
- - ">="
|
18
19
|
- !ruby/object:Gem::Version
|
19
20
|
version: '2.4'
|
20
21
|
type: :runtime
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
|
-
- -
|
25
|
+
- - ">="
|
25
26
|
- !ruby/object:Gem::Version
|
26
27
|
version: '2.4'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
+
name: chronic_duration
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
|
-
- -
|
32
|
+
- - ">="
|
32
33
|
- !ruby/object:Gem::Version
|
33
34
|
version: '0'
|
34
35
|
type: :runtime
|
35
36
|
prerelease: false
|
36
37
|
version_requirements: !ruby/object:Gem::Requirement
|
37
38
|
requirements:
|
38
|
-
- -
|
39
|
+
- - ">="
|
39
40
|
- !ruby/object:Gem::Version
|
40
41
|
version: '0'
|
41
42
|
- !ruby/object:Gem::Dependency
|
42
43
|
name: redis-semaphore
|
43
44
|
requirement: !ruby/object:Gem::Requirement
|
44
45
|
requirements:
|
45
|
-
- -
|
46
|
+
- - ">="
|
46
47
|
- !ruby/object:Gem::Version
|
47
48
|
version: '0'
|
48
49
|
type: :runtime
|
49
50
|
prerelease: false
|
50
51
|
version_requirements: !ruby/object:Gem::Requirement
|
51
52
|
requirements:
|
52
|
-
- -
|
53
|
+
- - ">="
|
53
54
|
- !ruby/object:Gem::Version
|
54
55
|
version: '0'
|
55
56
|
- !ruby/object:Gem::Dependency
|
56
57
|
name: bundler
|
57
58
|
requirement: !ruby/object:Gem::Requirement
|
58
59
|
requirements:
|
59
|
-
- - ~>
|
60
|
+
- - "~>"
|
60
61
|
- !ruby/object:Gem::Version
|
61
62
|
version: '1.3'
|
62
63
|
type: :development
|
63
64
|
prerelease: false
|
64
65
|
version_requirements: !ruby/object:Gem::Requirement
|
65
66
|
requirements:
|
66
|
-
- - ~>
|
67
|
+
- - "~>"
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '1.3'
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
71
|
name: rake
|
71
72
|
requirement: !ruby/object:Gem::Requirement
|
72
73
|
requirements:
|
73
|
-
- -
|
74
|
+
- - ">="
|
74
75
|
- !ruby/object:Gem::Version
|
75
76
|
version: '0'
|
76
77
|
type: :development
|
77
78
|
prerelease: false
|
78
79
|
version_requirements: !ruby/object:Gem::Requirement
|
79
80
|
requirements:
|
80
|
-
- -
|
81
|
+
- - ">="
|
81
82
|
- !ruby/object:Gem::Version
|
82
83
|
version: '0'
|
83
84
|
- !ruby/object:Gem::Dependency
|
84
85
|
name: rspec
|
85
86
|
requirement: !ruby/object:Gem::Requirement
|
86
87
|
requirements:
|
87
|
-
- -
|
88
|
+
- - ">="
|
88
89
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
90
|
+
version: 3.0.0.beta1
|
90
91
|
type: :development
|
91
92
|
prerelease: false
|
92
93
|
version_requirements: !ruby/object:Gem::Requirement
|
93
94
|
requirements:
|
94
|
-
- -
|
95
|
+
- - ">="
|
95
96
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
97
|
+
version: 3.0.0.beta1
|
97
98
|
- !ruby/object:Gem::Dependency
|
98
99
|
name: simplecov
|
99
100
|
requirement: !ruby/object:Gem::Requirement
|
100
101
|
requirements:
|
101
|
-
- -
|
102
|
+
- - ">="
|
102
103
|
- !ruby/object:Gem::Version
|
103
104
|
version: '0'
|
104
105
|
type: :development
|
105
106
|
prerelease: false
|
106
107
|
version_requirements: !ruby/object:Gem::Requirement
|
107
108
|
requirements:
|
108
|
-
- -
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: timecop
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
109
124
|
- !ruby/object:Gem::Version
|
110
125
|
version: '0'
|
111
126
|
- !ruby/object:Gem::Dependency
|
112
127
|
name: coveralls
|
113
128
|
requirement: !ruby/object:Gem::Requirement
|
114
129
|
requirements:
|
115
|
-
- -
|
130
|
+
- - ">="
|
116
131
|
- !ruby/object:Gem::Version
|
117
132
|
version: '0'
|
118
133
|
type: :development
|
119
134
|
prerelease: false
|
120
135
|
version_requirements: !ruby/object:Gem::Requirement
|
121
136
|
requirements:
|
122
|
-
- -
|
137
|
+
- - ">="
|
123
138
|
- !ruby/object:Gem::Version
|
124
139
|
version: '0'
|
125
140
|
description: Totems handler for Lita)
|
126
141
|
email:
|
127
142
|
- cf@dropbox.com
|
143
|
+
- vijay@change.org
|
128
144
|
executables: []
|
129
145
|
extensions: []
|
130
146
|
extra_rdoc_files: []
|
131
147
|
files:
|
132
|
-
- .gitignore
|
133
|
-
- .travis.yml
|
148
|
+
- ".gitignore"
|
149
|
+
- ".travis.yml"
|
134
150
|
- Gemfile
|
135
151
|
- LICENSE
|
136
152
|
- README.md
|
@@ -150,17 +166,17 @@ require_paths:
|
|
150
166
|
- lib
|
151
167
|
required_ruby_version: !ruby/object:Gem::Requirement
|
152
168
|
requirements:
|
153
|
-
- -
|
169
|
+
- - ">="
|
154
170
|
- !ruby/object:Gem::Version
|
155
171
|
version: '0'
|
156
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
173
|
requirements:
|
158
|
-
- -
|
174
|
+
- - ">="
|
159
175
|
- !ruby/object:Gem::Version
|
160
176
|
version: '0'
|
161
177
|
requirements: []
|
162
178
|
rubyforge_project:
|
163
|
-
rubygems_version: 2.
|
179
|
+
rubygems_version: 2.2.2
|
164
180
|
signing_key:
|
165
181
|
specification_version: 4
|
166
182
|
summary: Adds support to Lita for Totems
|