lita-totems 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|