lita-karma 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fa005d01f58fb03aa07984d4441b9caa058d9598
4
- data.tar.gz: 041ea5301d6b8190b847497e59489d58b860979d
3
+ metadata.gz: 6582ca790003f6b94e624a9b7d8fd81103ca5261
4
+ data.tar.gz: 7017b65d8c0a75a412fe15856771f5889c24729d
5
5
  SHA512:
6
- metadata.gz: 14d8b05cf3a25c8bba3e6fd010d089915ac93982993497ccf34575a929c0dc580be77e74f7570db9d93521c416873df1db77c27d06347627dc320437cd5d25db
7
- data.tar.gz: b0683a98f70347a1e16ddd58cab5d7c0b64d0d862bcb7e6db60a30468fddb4228b9fad9f9f9269c3afd509f4ef8e77c622bcfa9efd75edd8a0f50da3d1787afb
6
+ metadata.gz: ddc01d87d46b225edd96e5b899db22f8f21b420aba0d402a2bea691cf7dc031465a471235d808e7102e5e5dda647f6c302320383b5248cf82d498bceac53f806
7
+ data.tar.gz: 95020fb1b2c6fbfe7f83a089230af1bad2ed966470af53c08e72bc58724a5685f1a43baef08b3263faccf615be12ed6855e620bd7f24c987cae0bd87f659326b
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ script: bundle exec rspec
5
+ before_install:
6
+ - gem update --system
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # lita-karma
2
2
 
3
+ [![Build Status](https://travis-ci.org/jimmycuadra/lita-karma.png)](https://travis-ci.org/jimmycuadra/lita-karma)
4
+ [![Code Climate](https://codeclimate.com/github/jimmycuadra/lita-karma.png)](https://codeclimate.com/github/jimmycuadra/lita-karma)
5
+ [![Coverage Status](https://coveralls.io/repos/jimmycuadra/lita-karma/badge.png)](https://coveralls.io/r/jimmycuadra/lita-karma)
6
+
3
7
  **lita-karma** is a handler for [Lita](https://github.com/jimmycuadra/lita) that tracks karma points for arbitrary terms. It listens for upvotes and downvotes and keeps a tally of the scores for them in Redis.
4
8
 
5
9
  ## Installation
@@ -10,6 +14,16 @@ Add lita-karma to your Lita instance's Gemfile:
10
14
  gem "lita-karma"
11
15
  ```
12
16
 
17
+ ## Configuration
18
+
19
+ lita-karma has one option, the cooldown, which controls how long a user must wait after modifying a term before they can modify it again. The value should be an integer number of seconds. The default is 300 (5 minutes). Set it to `nil` to disable rate limiting.
20
+
21
+ ```
22
+ Lita.configure do |config|
23
+ config.handlers.karma.cooldown = 600
24
+ end
25
+ ```
26
+
13
27
  ## Usage
14
28
 
15
29
  Lita will add a karma point whenever it hears a term upvoted:
@@ -32,6 +46,12 @@ term~~
32
46
 
33
47
  To list the top scoring terms:
34
48
 
49
+ ```
50
+ Lita: karma best
51
+ ```
52
+
53
+ or simply:
54
+
35
55
  ```
36
56
  Lita: karma
37
57
  ```
@@ -58,7 +78,7 @@ bar++
58
78
  Lita: foo += bar
59
79
  > bar has been linked to foo.
60
80
  foo~~
61
- > foo: 2
81
+ > foo: 2 (1), linked to: bar: 1
62
82
  bar~~
63
83
  > bar: 1
64
84
  Lita: foo -= bar
@@ -67,6 +87,8 @@ foo~~
67
87
  > foo: 1
68
88
  ```
69
89
 
90
+ When a term is linked, the total karma score is displayed first, followed by the score of the term without its linked terms in parentheses.
91
+
70
92
  ## License
71
93
 
72
94
  [MIT](http://opensource.org/licenses/MIT)
@@ -6,9 +6,12 @@ module Lita
6
6
  route %r{([^\s]{2,})\+\+}, to: :increment
7
7
  route %r{([^\s]{2,})\-\-}, to: :decrement
8
8
  route %r{([^\s]{2,})~~}, to: :check
9
- route %r{karma}, to: :list, command: true
10
- route %r{([^\s]{2,})\s*\+=\s*([^\s]{2,})}, to: :link, command: true
11
- route %r{([^\s]{2,})\s*-=\s*([^\s]{2,})}, to: :unlink, command: true
9
+ route %r{^karma\s+worst}, to: :list_worst, command: true
10
+ route %r{^karma\s+best}, to: :list_best, command: true
11
+ route %r{^karma\s+modified}, to: :modified, command: true
12
+ route %r{^karma\s*$}, to: :list_best, command: true
13
+ route %r{^([^\s]{2,})\s*\+=\s*([^\s]{2,})}, to: :link, command: true
14
+ route %r{^([^\s]{2,})\s*-=\s*([^\s]{2,})}, to: :unlink, command: true
12
15
 
13
16
  def increment(matches)
14
17
  modify(matches, 1)
@@ -23,39 +26,31 @@ module Lita
23
26
 
24
27
  matches.each do |match|
25
28
  term = match[0]
26
- score = redis.zscore("terms", term).to_i
29
+ own_score = score = redis.zscore("terms", term).to_i
30
+ links = []
27
31
  redis.smembers("links:#{term}").each do |link|
28
- score += redis.zscore("terms", link).to_i
32
+ link_score = redis.zscore("terms", link).to_i
33
+ links << "#{link}: #{link_score}"
34
+ score += link_score
29
35
  end
30
- output << "#{term}: #{score}"
36
+
37
+ string = "#{term}: #{score}"
38
+ unless links.empty?
39
+ string << " (#{own_score}), linked to: "
40
+ string << links.join(", ")
41
+ end
42
+ output << string
31
43
  end
32
44
 
33
45
  reply *output
34
46
  end
35
47
 
36
- def list(matches)
37
- redis_command = case args.first
38
- when "worst"
39
- :zrange
40
- else
41
- :zrevrange
42
- end
43
-
44
- n = (args[1] || 5).to_i - 1
45
-
46
- terms_scores = redis.public_send(
47
- redis_command, "terms", 0, n, with_scores: true
48
- )
49
-
50
- output = terms_scores.each_with_index.map do |term_score, index|
51
- "#{index + 1}. #{term_score[0]} (#{term_score[1].to_i})"
52
- end.join("\n")
48
+ def list_best(matches)
49
+ list(:zrevrange)
50
+ end
53
51
 
54
- if output.length == 0
55
- reply "There are no terms being tracked yet."
56
- else
57
- reply output
58
- end
52
+ def list_worst(matches)
53
+ list(:zrange)
59
54
  end
60
55
 
61
56
  def link(matches)
@@ -82,21 +77,69 @@ module Lita
82
77
  end
83
78
  end
84
79
 
80
+ def modified(matches)
81
+ term = args[1]
82
+
83
+ if term.nil? || term.strip.empty?
84
+ reply "Format: #{robot.name}: karma modified TERM"
85
+ return
86
+ end
87
+
88
+ user_ids = redis.smembers("modified:#{term}")
89
+
90
+ if user_ids.empty?
91
+ reply "#{term} has never been modified."
92
+ else
93
+ reply user_ids.map { |id| User.find_by_id(id).name }.join(", ")
94
+ end
95
+ end
96
+
85
97
  private
86
98
 
87
99
  def modify(matches, delta)
88
- output = []
89
-
90
100
  matches.each do |match|
91
101
  term = match[0]
92
- score = redis.zincrby("terms", delta, term).to_i
93
- output << "#{term}: #{score}"
102
+
103
+ ttl = redis.ttl("cooldown:#{user.id}:#{term}")
104
+ if ttl >= 0
105
+ cooldown_message =
106
+ "You cannot modify #{term} for another #{ttl} second"
107
+ cooldown_message << (ttl == 1 ? "." : "s.")
108
+ reply cooldown_message
109
+ else
110
+ redis.zincrby("terms", delta, term)
111
+ redis.sadd("modified:#{term}", user.id)
112
+ cooldown = Lita.config.handlers.karma.cooldown
113
+ if cooldown
114
+ redis.setex("cooldown:#{user.id}:#{term}", cooldown.to_i, 1)
115
+ end
116
+ end
94
117
  end
95
118
 
96
- reply *output
119
+ check(matches)
120
+ end
121
+
122
+ def list(redis_command)
123
+ n = (args[1] || 5).to_i - 1
124
+
125
+ terms_scores = redis.public_send(
126
+ redis_command, "terms", 0, n, with_scores: true
127
+ )
128
+
129
+ output = terms_scores.each_with_index.map do |term_score, index|
130
+ "#{index + 1}. #{term_score[0]} (#{term_score[1].to_i})"
131
+ end.join("\n")
132
+
133
+ if output.length == 0
134
+ reply "There are no terms being tracked yet."
135
+ else
136
+ reply output
137
+ end
97
138
  end
98
139
  end
99
140
 
141
+ Lita.config.handlers.karma = Config.new
142
+ Lita.config.handlers.karma.cooldown = 300
100
143
  Lita.register_handler(Karma)
101
144
  end
102
145
  end
data/lita-karma.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "lita-karma"
3
- spec.version = "0.0.1"
3
+ spec.version = "0.0.2"
4
4
  spec.authors = ["Jimmy Cuadra"]
5
5
  spec.email = ["jimmy@jimmycuadra.com"]
6
6
  spec.description = %q{A Lita handler for tracking karma points for arbitrary terms.}
@@ -13,9 +13,11 @@ 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", "~> 0.0.1"
16
+ spec.add_runtime_dependency "lita", "~> 1.0"
17
17
 
18
18
  spec.add_development_dependency "bundler", "~> 1.3"
19
19
  spec.add_development_dependency "rake"
20
20
  spec.add_development_dependency "rspec", ">= 2.14.0rc1"
21
+ spec.add_development_dependency "simplecov"
22
+ spec.add_development_dependency "coveralls"
21
23
  end
@@ -1,166 +1,188 @@
1
1
  require "spec_helper"
2
2
 
3
- describe Lita::Handlers::Karma, lita_handler: true do
3
+ describe Lita::Handlers::Karma, lita: true do
4
+ before { Lita.config.handlers.karma.cooldown = nil }
5
+
4
6
  it { routes("foo++").to(:increment) }
5
7
  it { routes("foo--").to(:decrement) }
6
8
  it { routes("foo~~").to(:check) }
7
- it { routes("#{robot.name}: karma").to(:list) }
9
+ it { routes("#{robot.name}: karma best").to(:list_best) }
10
+ it { routes("#{robot.name}: karma worst").to(:list_worst) }
11
+ it { routes("#{robot.name}: karma modified").to(:modified) }
12
+ it { routes("#{robot.name}: karma").to(:list_best) }
8
13
  it { routes("#{robot.name}: foo += bar").to(:link) }
9
14
  it { routes("#{robot.name}: foo -= bar").to(:unlink) }
10
15
 
11
- let(:source) { an_instance_of(Lita::Source) }
12
-
13
16
  describe "#increment" do
14
17
  it "increases the term's score by one and says the new score" do
15
- expect(robot).to receive(:send_messages).with(source, "foo: 1")
18
+ expect_reply("foo: 1")
16
19
  send_test_message("foo++")
17
20
  end
18
21
 
19
22
  it "matches multiple terms in one message" do
20
- expect(robot).to receive(:send_messages).with(source, "foo: 1", "bar: 1")
23
+ expect_replies("foo: 1", "bar: 1")
21
24
  send_test_message("foo++ bar++")
22
25
  end
23
26
 
24
27
  it "doesn't start from zero if the term already has a positive score" do
25
- allow(robot).to receive(:send_messages)
26
28
  send_test_message("foo++")
27
- expect(robot).to receive(:send_messages).with(source, "foo: 2")
29
+ expect_reply("foo: 2")
30
+ send_test_message("foo++")
31
+ end
32
+
33
+ it "replies with a warning if term increment is on cooldown" do
34
+ Lita.config.handlers.karma.cooldown = 10
35
+ send_test_message("foo++")
36
+ expect_reply(/cannot modify foo/)
28
37
  send_test_message("foo++")
29
38
  end
30
39
  end
31
40
 
32
41
  describe "#decrement" do
33
42
  it "decreases the term's score by one and says the new score" do
34
- expect(robot).to receive(:send_messages).with(source, "foo: -1")
43
+ expect_reply("foo: -1")
35
44
  send_test_message("foo--")
36
45
  end
37
46
 
38
47
  it "matches multiple terms in one message" do
39
- expect(robot).to receive(:send_messages).with(
40
- source,
41
- "foo: -1",
42
- "bar: -1"
43
- )
48
+ expect_replies("foo: -1", "bar: -1")
44
49
  send_test_message("foo-- bar--")
45
50
  end
46
51
 
47
52
  it "doesn't start from zero if the term already has a positive score" do
48
- allow(robot).to receive(:send_messages)
49
53
  send_test_message("foo++")
50
- expect(robot).to receive(:send_messages).with(source, "foo: 0")
54
+ expect_reply("foo: 0")
55
+ send_test_message("foo--")
56
+ end
57
+
58
+ it "replies with a warning if term increment is on cooldown" do
59
+ Lita.config.handlers.karma.cooldown = 10
60
+ send_test_message("foo--")
61
+ expect_reply(/cannot modify foo/)
51
62
  send_test_message("foo--")
52
63
  end
53
64
  end
54
65
 
55
66
  describe "#check" do
56
67
  it "says the term's current score" do
57
- expect(robot).to receive(:send_messages).with(source, "foo: 0")
68
+ expect_reply("foo: 0")
58
69
  send_test_message("foo~~")
59
70
  end
60
71
 
61
72
  it "matches multiple terms in one message" do
62
- expect(robot).to receive(:send_messages).with(
63
- source,
64
- "foo: 0",
65
- "bar: 0"
66
- )
73
+ expect_replies("foo: 0", "bar: 0")
67
74
  send_test_message("foo~~ bar~~")
68
75
  end
69
76
  end
70
77
 
71
78
  describe "#list" do
72
- before do
73
- allow(robot).to receive(:send_messages)
74
- send_test_message(
75
- "one++ one++ one++ two++ two++ three++ four++ four-- five--"
76
- )
79
+ it "replies with a warning if there are no terms" do
80
+ expect_reply(/no terms being tracked/)
81
+ send_test_message("#{robot.name}: karma")
77
82
  end
78
83
 
79
- it "lists the top 5 terms by default" do
80
- expect(robot).to receive(:send_messages).with source, <<-MSG.chomp
84
+ context "with modified terms" do
85
+ before do
86
+ send_test_message(
87
+ "one++ one++ one++ two++ two++ three++ four++ four-- five--"
88
+ )
89
+ end
90
+
91
+ it "lists the top 5 terms by default" do
92
+ expect_reply <<-MSG.chomp
81
93
  1. one (3)
82
94
  2. two (2)
83
95
  3. three (1)
84
96
  4. four (0)
85
97
  5. five (-1)
86
98
  MSG
87
- send_test_message("#{robot.name}: karma")
88
- end
99
+ send_test_message("#{robot.name}: karma")
100
+ end
89
101
 
90
- it 'lists the bottom 5 terms when passed "worst"' do
91
- expect(robot).to receive(:send_messages).with source, <<-MSG.chomp
102
+ it 'lists the bottom 5 terms when passed "worst"' do
103
+ expect_reply <<-MSG.chomp
92
104
  1. five (-1)
93
105
  2. four (0)
94
106
  3. three (1)
95
107
  4. two (2)
96
108
  5. one (3)
97
109
  MSG
98
- send_test_message("#{robot.name}: karma worst")
99
- end
110
+ send_test_message("#{robot.name}: karma worst")
111
+ end
100
112
 
101
- it "limits the list to the count passed as the second argument" do
102
- expect(robot).to receive(:send_messages).with source, <<-MSG.chomp
113
+ it "limits the list to the count passed as the second argument" do
114
+ expect_reply <<-MSG.chomp
103
115
  1. one (3)
104
116
  2. two (2)
105
117
  MSG
106
- send_test_message("#{robot.name}: karma best 2")
118
+ send_test_message("#{robot.name}: karma best 2")
119
+ end
107
120
  end
108
121
  end
109
122
 
110
123
  describe "#link" do
111
124
  it "says that it's linked term 2 to term 1" do
112
- expect(robot).to receive(:send_messages).with(
113
- source,
114
- "bar has been linked to foo."
115
- )
125
+ expect_reply("bar has been linked to foo.")
116
126
  send_test_message("#{robot.name}: foo += bar")
117
127
  end
118
128
 
119
129
  it "says that term 2 was already linked to term 1 if it was" do
120
- allow(robot).to receive(:send_messages)
121
130
  send_test_message("#{robot.name}: foo += bar")
122
- expect(robot).to receive(:send_messages).with(
123
- source,
124
- "bar is already linked to foo."
125
- )
131
+ expect_reply("bar is already linked to foo.")
126
132
  send_test_message("#{robot.name}: foo += bar")
127
133
  end
128
134
 
129
135
  it "causes term 1's score to be modified by term 2's" do
130
- allow(robot).to receive(:send_messages)
131
- send_test_message("foo++ bar++")
136
+ send_test_message("foo++ bar++ baz++")
132
137
  send_test_message("#{robot.name}: foo += bar")
133
- expect(robot).to receive(:send_messages).with(source, "foo: 2")
138
+ send_test_message("#{robot.name}: foo += baz")
139
+ expect_reply("foo: 3 (1), linked to: baz: 1, bar: 1")
134
140
  send_test_message("foo~~")
135
141
  end
136
142
  end
137
143
 
138
144
  describe "#unlink" do
139
145
  it "says that it's unlinked term 2 from term 1" do
140
- allow(robot).to receive(:send_messages)
141
146
  send_test_message("#{robot.name}: foo += bar")
142
- expect(robot).to receive(:send_messages).with(
143
- source,
144
- "bar has been unlinked from foo."
145
- )
147
+ expect_reply("bar has been unlinked from foo.")
146
148
  send_test_message("#{robot.name}: foo -= bar")
147
149
  end
148
150
 
149
151
  it "says that term 2 was not linked to term 1 if it wasn't" do
150
- expect(robot).to receive(:send_messages).with(
151
- source,
152
- "bar is not linked to foo."
153
- )
152
+ expect_reply("bar is not linked to foo.")
154
153
  send_test_message("#{robot.name}: foo -= bar")
155
154
  end
156
155
 
157
156
  it "causes term 1's score to stop being modified by term 2's" do
158
- allow(robot).to receive(:send_messages)
159
157
  send_test_message("foo++ bar++")
160
158
  send_test_message("#{robot.name}: foo += bar")
161
159
  send_test_message("#{robot.name}: foo -= bar")
162
- expect(robot).to receive(:send_messages).with(source, "foo: 1")
160
+ expect_reply("foo: 1")
163
161
  send_test_message("foo~~")
164
162
  end
165
163
  end
164
+
165
+ describe "#modified" do
166
+ it "replies with the required format if a term is not provided" do
167
+ expect_reply(/^Format:/)
168
+ send_test_message("#{robot.name}: karma modified")
169
+ end
170
+
171
+ it "replies with the required format if the term is an empty string" do
172
+ expect_reply(/^Format:/)
173
+ send_test_message("#{robot.name}: karma modified ' '")
174
+ end
175
+
176
+ it "replies with a message if the term hasn't been modified" do
177
+ expect_reply(/never been modified/)
178
+ send_test_message("#{robot.name}: karma modified foo")
179
+ end
180
+
181
+ it "lists users who have modified the given term" do
182
+ allow(Lita::User).to receive(:find_by_id).and_return(user)
183
+ send_test_message("foo++")
184
+ expect_reply(user.name)
185
+ send_test_message("#{robot.name}: karma modified foo")
186
+ end
187
+ end
166
188
  end
data/spec/spec_helper.rb CHANGED
@@ -1,3 +1,10 @@
1
- require "lita-karma"
1
+ require "simplecov"
2
+ require "coveralls"
3
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
4
+ SimpleCov::Formatter::HTMLFormatter,
5
+ Coveralls::SimpleCov::Formatter
6
+ ]
7
+ SimpleCov.start
2
8
 
9
+ require "lita-karma"
3
10
  require "lita/rspec"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-karma
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jimmy Cuadra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-15 00:00:00.000000000 Z
11
+ date: 2013-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: lita
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 0.0.1
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 0.0.1
26
+ version: '1.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: 2.14.0rc1
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  description: A Lita handler for tracking karma points for arbitrary terms.
70
98
  email:
71
99
  - jimmy@jimmycuadra.com
@@ -74,6 +102,7 @@ extensions: []
74
102
  extra_rdoc_files: []
75
103
  files:
76
104
  - .gitignore
105
+ - .travis.yml
77
106
  - Gemfile
78
107
  - README.md
79
108
  - Rakefile