lita-pubsub 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ca7175e47eec1333171f11b8525d8c47b072fb87
4
+ data.tar.gz: 12acd3d976d766a796647c1329236c2acef28546
5
+ SHA512:
6
+ metadata.gz: 5225391f61f94e2cf63ec77d292841b649153e67424d10948c8352bff9a228ed29db5edac8049e035b8f5acd7eb0c3c428f8fbe1ce7cc48152f8df6f03628313
7
+ data.tar.gz: ff11a64406a659ccf13d46d8d15b9e6e6ba206a1f557ab60c73fe903221edf3336b0374307ccf706d0f5da799332ce9e01a8797baef9ffd4490339f8f2b874de
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .byebug_history
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ script: bundle exec rake
5
+ before_install:
6
+ - gem update --system
7
+ services:
8
+ - redis-server
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # Lita PubSub
2
+
3
+ PubSub notification system for [Lita](https://www.lita.io/), ported from [Hubot
4
+ PubSub](https://github.com/spajus/hubot-pubsub).
5
+
6
+ [![Build Status](https://travis-ci.org/spajus/lita-pubsub.png?branch=master)](https://travis-ci.org/spajus/lita-pubsub?branch=master)
7
+ [![Coverage Status](https://coveralls.io/repos/github/spajus/lita-pubsub/badge.svg?branch=master)](https://coveralls.io/github/spajus/lita-pubsub?branch=master)
8
+
9
+ ## Possibilities
10
+
11
+ `lita-pubsub` allows you to build a simple, yet powerful monitoring / notification system using your corporate chat. Simply subscribe events in appropriate chat rooms and publish info about these events via HTTP calls or from other Lita handlers when they happen.
12
+
13
+ ```
14
+ Lita PubSub Event Flow
15
+
16
+ +--------------+ +--------------+ +---------------+
17
+ | Lita handler | | HTTP Request | | chat message |<--+
18
+ +-------+------+ +-------+------+ +-------+-------+ |
19
+ | | | |
20
+ | v | |
21
+ | +-------------+ | |
22
+ +------->| lita-pubsub |<---------+ |
23
+ +-------+-----+ |
24
+ | |
25
+ v |
26
+ +--------------+ |
27
+ +---+ Lita +---+ |
28
+ | +--------------+ | |
29
+ | | |
30
+ v v |
31
+ +---------------+ +---------------+ |
32
+ | chatroom #1 | | chatroom #2 +-----------+
33
+ +---------------+ +---------------+
34
+ ```
35
+
36
+ ## How It Works
37
+
38
+ ```console
39
+ $ bundle exec lita start
40
+ Type "exit" or "quit" to end the session.
41
+ Lita > lita help pubsub
42
+ Lita: all subscriptions - pubsub: shows all subscriptions
43
+ Lita: subscriptions - pubsub: shows current room subscriptions
44
+ Lita: subscribers [of] EVENT - pubsub: shows rooms subscribed to EVENT
45
+ Lita: subscribe EVENT - pubsub: subscribes room to event. subscribe to
46
+ `unsubscribed.event` to debug missing events.
47
+ Lita: unsubscribe EVENT - pubsub: subscribes current channel to event
48
+ Lita: unsubscribe all events - pubsub: unsubscribes current channel from all
49
+ events
50
+ Lita: publish EVENT DATA - pubsub: publishes DATA to EVENT subscribers
51
+ Lita > lita subscriptions
52
+ Subscriptions for shell: []
53
+ Lita > lita subscribe jenkins
54
+ Subscribed shell to jenkins events
55
+ # You would normally use HTTP API at lita:8080/publish for same result
56
+ Lita > lita publish jenkins.build.fail Build #12141 failed!
57
+ *jenkins.build.fail*: Build #12141 failed!
58
+ Lita > lita publish nothing emptiness
59
+ Lita > lita subscribe unsubscribed.event
60
+ Subscribed shell to unsubscribed.event events
61
+ Lita > lita publish nothing emptiness
62
+ *unsubscribed.event*: nothing: emptiness
63
+ Lita > lita subscribers of jenkins
64
+ Subscribers of jenkins: ["shell"]
65
+ ```
66
+
67
+ ## Installation
68
+
69
+ Add lita-pubsub to your Lita instance's Gemfile:
70
+
71
+ ``` ruby
72
+ gem "lita-pubsub"
73
+ ```
74
+
75
+ ## Configuration
76
+
77
+ ```ruby
78
+
79
+ # lita_config.rb
80
+
81
+ Lita.configure do |config|
82
+ # optional password protection
83
+ config.handlers.pubsub.http_password = 's3cr3t'
84
+ end
85
+ ```
86
+
87
+ ## Usage
88
+
89
+ ```
90
+ lita subscribe <event> # subscribes current room to event
91
+ lita unsubscribe <event> # unsubscribes current room from event
92
+ lita unsubscribe all events # unsubscribes current room from all events
93
+ lita subscriptions # show subscriptions of current room
94
+ lita subscribers of <event> # shows which rooms subscribe to event
95
+ lita all subscriptions # show all existing subscriptions
96
+ lita publish <event> <data> # triggers event
97
+ ```
98
+
99
+ ## HTTP Api
100
+
101
+ ```
102
+ GET /publish?event=<event>&data=<text>[&password=<password>]
103
+ ```
104
+
105
+ ```
106
+ POST /publish
107
+ ```
108
+
109
+ * Content-Type: `application/json`
110
+ * Body: `{ "password": "optional", "event": "event", "data": "text" }`
111
+
112
+ ## Event Namespaces
113
+
114
+ Lita PubSub uses `.` as event namespace separator. I.e.: subscribing to `x.y`
115
+ also subscribes to `x.y.*` events.
116
+
117
+ ## Handling unsubscribed events
118
+
119
+ Do `lita subscribe unsubscribed.event` in a room where you want all unrouted
120
+ events to get announced.
121
+
122
+ ## Warning
123
+
124
+ HTTP password protection is trivial, and should not be used in public networks.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,199 @@
1
+ module Lita
2
+ module Handlers
3
+ class Pubsub < Handler
4
+ config :http_password
5
+
6
+ http.get('/publish', :http_get)
7
+ http.post('/publish', :http_post)
8
+
9
+ route(
10
+ /^all subscriptions$/i,
11
+ :all_subscriptions,
12
+ command: true,
13
+ help: { 'all subscriptions' => 'pubsub: shows all subscriptions' }
14
+ )
15
+
16
+ route(
17
+ /^subscriptions$/i,
18
+ :subscriptions,
19
+ command: true,
20
+ help: { 'subscriptions' => 'pubsub: shows current room subscriptions' }
21
+ )
22
+
23
+ route(
24
+ /^subscribers (of )?([a-z0-9\-\.\:_]+)$/i,
25
+ :subscribers,
26
+ command: true,
27
+ help: { 'subscribers [of] EVENT' => 'pubsub: shows rooms subscribed to EVENT' }
28
+ )
29
+
30
+ route(
31
+ /^subscribe ([a-z0-9\-\.\:_]+)$/i,
32
+ :subscribe,
33
+ command: true,
34
+ help: { 'subscribe EVENT' => 'pubsub: subscribes room to event. subscribe to `unsubscribed.event` to debug missing events.' }
35
+ )
36
+
37
+ route(
38
+ /^unsubscribe ([a-z0-9\-\.\:_]+)$/i,
39
+ :unsubscribe,
40
+ command: true,
41
+ help: { 'unsubscribe EVENT' => 'pubsub: subscribes current channel to event' }
42
+ )
43
+
44
+ route(
45
+ /^unsubscribe all events$/i,
46
+ :unsubscribe_all,
47
+ command: true,
48
+ help: { 'unsubscribe all events' => 'pubsub: unsubscribes current channel from all events' }
49
+ )
50
+
51
+ route(
52
+ /^publish ([a-z0-9\-\.\:_]+) (.+)$/i,
53
+ :publish,
54
+ command: true,
55
+ help: { 'publish EVENT DATA' => 'pubsub: publishes DATA to EVENT subscribers' }
56
+ )
57
+
58
+ on(:publish) do |payload|
59
+ event = payload[:event]
60
+ rooms = find_subscriptions(event)
61
+ if rooms.any?
62
+ rooms.each do |room|
63
+ target = Source.new(room: room)
64
+ robot.send_message(target, format_message(event, payload[:data]))
65
+ end
66
+ else
67
+ if redis.smembers('pubsub.events.unsubscribed.event').any?
68
+ robot.trigger(
69
+ :publish,
70
+ event: 'unsubscribed.event',
71
+ data: "#{event}: #{payload[:data]}"
72
+ )
73
+ end
74
+ end
75
+ end
76
+
77
+ def http_get(request, response)
78
+ validate_http_password!(request.params['password'])
79
+ robot.trigger(
80
+ :publish,
81
+ event: request.params['event'],
82
+ data: request.params['data']
83
+ )
84
+ response.write('ok')
85
+ end
86
+
87
+ def http_post(request, response)
88
+ data = JSON.parse(request.body.read)
89
+ validate_http_password!(request.params['password'] || data['password'])
90
+ robot.trigger(
91
+ :publish,
92
+ event: data['event'],
93
+ data: data['data']
94
+ )
95
+ response.write('ok')
96
+ end
97
+
98
+ def all_subscriptions(response)
99
+ events = redis.smembers('pubsub.events').sort
100
+ subscriptions = events.map do |event|
101
+ "#{event} -> #{redis.smembers("pubsub.events.#{event}").sort}"
102
+ end
103
+ response.reply("All subscriptions:\n#{subscriptions.join("\n")}")
104
+ end
105
+
106
+ def subscriptions(response)
107
+ room = response.room
108
+ return response.reply('This command only works in a room') unless room
109
+ subscriptions = redis.smembers("pubsub.rooms.#{room.id}").sort
110
+ response.reply("Subscriptions for #{room.name}: #{subscriptions}")
111
+ end
112
+
113
+ def subscribers(response)
114
+ event = response.matches[0][1]
115
+ subscribers = find_subscriptions(event)
116
+ response.reply("Subscribers of #{event}: #{subscribers}")
117
+ end
118
+
119
+ def subscribe(response)
120
+ event = response.matches[0][0]
121
+ room = response.room
122
+ return response.reply('This command only works in a room') unless room
123
+ redis.sadd("pubsub.events", event)
124
+ redis.sadd("pubsub.rooms.#{room.id}", event)
125
+ redis.sadd("pubsub.events.#{event}", room.id)
126
+ response.reply("Subscribed #{room.name} to #{event} events")
127
+ end
128
+
129
+ def unsubscribe(response)
130
+ event = response.matches[0][0]
131
+ room = response.room
132
+ return response.reply('This command only works in a room') unless room
133
+ subscriptions = redis.smembers("pubsub.rooms.#{room.id}").sort
134
+ if subscriptions.include?(event)
135
+ redis.srem("pubsub.rooms.#{room.id}", event)
136
+ redis.srem("pubsub.events.#{event}", room.id)
137
+ subscribers = redis.smembers("pubsub.events.#{event}")
138
+ redis.srem("pubsub.events", event) if subscribers.empty?
139
+ response.reply("Unsubscribed #{room.name} from #{event} events")
140
+ else
141
+ response.reply(
142
+ "There is no #{event} subscription in #{room.name}.\n" \
143
+ "Current subscriptions: #{subscriptions}"
144
+ )
145
+ end
146
+ end
147
+
148
+ def unsubscribe_all(response)
149
+ room = response.room
150
+ return response.reply('This command only works in a room') unless room
151
+ subscriptions = redis.smembers("pubsub.rooms.#{room.id}").sort
152
+ subscriptions.each do |event|
153
+ redis.srem("pubsub.rooms.#{room.id}", event)
154
+ redis.srem("pubsub.events.#{event}", room.id)
155
+ subscribers = redis.smembers("pubsub.events.#{event}")
156
+ redis.srem("pubsub.events", event) if subscribers.empty?
157
+ response.reply("Unsubscribed #{room.name} from #{event} events")
158
+ end
159
+ end
160
+
161
+ def publish(response)
162
+ event, data = response.matches[0]
163
+ robot.trigger(:publish, event: event, data: data)
164
+ end
165
+
166
+ private
167
+
168
+ def format_message(event, data)
169
+ "*#{event}*: #{data}"
170
+ end
171
+
172
+ def find_subscriptions(event)
173
+ return [] if event.nil? || event.empty?
174
+ subscriptions = redis.smembers('pubsub.events').sort
175
+ if event.include?('.')
176
+ ev_parts = event.split('.')
177
+ matched = []
178
+ while ev_parts.any?
179
+ sub_ev = ev_parts.join('.')
180
+ if subscriptions.include?(sub_ev)
181
+ matched += redis.smembers("pubsub.events.#{sub_ev}").sort
182
+ end
183
+ ev_parts.pop
184
+ end
185
+ matched.sort.uniq
186
+ else
187
+ redis.smembers("pubsub.events.#{event}")
188
+ end
189
+ end
190
+
191
+ def validate_http_password!(password)
192
+ return if config.http_password.nil? || config.http_password.empty?
193
+ raise 'incorrect password!' if password != config.http_password
194
+ end
195
+
196
+ Lita.register_handler(self)
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+ require 'lita'
3
+
4
+ Lita.load_locales Dir[File.expand_path(
5
+ File.join("..", "..", "locales", "*.yml"), __FILE__
6
+ )]
7
+
8
+ require 'lita/handlers/pubsub'
9
+
10
+ Lita::Handlers::Pubsub.template_root File.expand_path(
11
+ File.join('..', '..', 'templates'),
12
+ __FILE__
13
+ )
@@ -0,0 +1,26 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = "lita-pubsub"
3
+ spec.version = "0.1.0"
4
+ spec.authors = ["Tomas Varaneckas"]
5
+ spec.email = ["tomas.varaneckas@gmail.com"]
6
+ spec.description = "PubSub notification system for Lita"
7
+ spec.summary = "PubSub notification system for Lita"
8
+ spec.homepage = "https://github.com/spajus/hubot-lita"
9
+ spec.license = "MIT License"
10
+ spec.metadata = { "lita_plugin_type" => "handler" }
11
+
12
+ spec.files = `git ls-files`.split($/)
13
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_runtime_dependency "lita", ">= 4.7"
18
+
19
+ spec.add_development_dependency "bundler", "~> 1.3"
20
+ spec.add_development_dependency "pry-byebug"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rack-test"
23
+ spec.add_development_dependency "rspec", ">= 3.0.0"
24
+ spec.add_development_dependency "simplecov"
25
+ spec.add_development_dependency "coveralls"
26
+ end
data/locales/en.yml ADDED
@@ -0,0 +1,4 @@
1
+ en:
2
+ lita:
3
+ handlers:
4
+ pubsub:
@@ -0,0 +1,153 @@
1
+ require "spec_helper"
2
+
3
+ describe Lita::Handlers::Pubsub, lita_handler: true do
4
+ let(:robot) { Lita::Robot.new(registry) }
5
+ subject { described_class.new(robot) }
6
+ let(:room) { Lita::Room.new('foos') }
7
+ let(:room2) { Lita::Room.new('bars') }
8
+
9
+ it 'subscribes current channel to event' do
10
+ send_message('lita subscribe foo', from: room)
11
+ send_message('lita subscriptions', from: room)
12
+ expect(replies.last).to eq('Subscriptions for foos: ["foo"]')
13
+ end
14
+
15
+ it 'unsubscribes current channel from event' do
16
+ send_message('lita subscribe foo', from: room)
17
+ send_message('lita subscriptions', from: room)
18
+ expect(replies.last).to eq('Subscriptions for foos: ["foo"]')
19
+
20
+ send_message('lita unsubscribe foo', from: room)
21
+ expect(replies.last).to eq("Unsubscribed foos from foo events")
22
+
23
+ send_message('lita subscriptions', from: room)
24
+ expect(replies.last).to eq('Subscriptions for foos: []')
25
+ end
26
+
27
+ it 'unsubscribes current channel from all events' do
28
+ send_message('lita subscribe foo', from: room)
29
+ send_message('lita subscribe bar', from: room)
30
+ send_message('lita subscribe baz', from: room)
31
+ send_message('lita unsubscribe all events', from: room)
32
+ expect(replies[-3]).to eq("Unsubscribed foos from bar events")
33
+ expect(replies[-2]).to eq("Unsubscribed foos from baz events")
34
+ expect(replies[-1]).to eq("Unsubscribed foos from foo events")
35
+
36
+ send_message('lita subscriptions', from: room)
37
+ expect(replies.last).to eq('Subscriptions for foos: []')
38
+ end
39
+
40
+ it 'shows room subscriptions' do
41
+ send_message('lita subscribe foo', from: room)
42
+ send_message('lita subscriptions', from: room)
43
+ expect(replies.last).to eq('Subscriptions for foos: ["foo"]')
44
+ end
45
+
46
+ it 'shows all subscriptions' do
47
+ send_message('lita subscribe foo', from: room)
48
+ send_message('lita subscribe bar', from: room)
49
+ send_message('lita subscribe bar', from: room2)
50
+ send_message('lita all subscriptions')
51
+ expect(replies.last).to eq("All subscriptions:\nbar -> [\"bars\", \"foos\"]\nfoo -> [\"foos\"]")
52
+ end
53
+
54
+ it 'shows subscribers of event' do
55
+ send_message("lita subscribe foo", from: room)
56
+ send_message("lita subscribe foo", from: room2)
57
+
58
+ send_message("lita subscribers foo")
59
+ expect(replies.last).to eq('Subscribers of foo: ["bars", "foos"]')
60
+
61
+ send_message("lita subscribers of foo")
62
+ expect(replies.last).to eq('Subscribers of foo: ["bars", "foos"]')
63
+ end
64
+
65
+ it 'publishes data to event subscribers' do
66
+ send_message("lita subscribe foo", from: room)
67
+ send_message("lita subscribe foo", from: room2)
68
+ send_message("lita publish foo bar de baz")
69
+ expect(replies[-1]).to eq('*foo*: bar de baz')
70
+ expect(replies[-2]).to eq('*foo*: bar de baz')
71
+ end
72
+
73
+ it 'publishes data to partial event subscribers' do
74
+ send_message("lita subscribe foo", from: room)
75
+ send_message("lita subscribe foo.bar", from: room2)
76
+ send_message("lita publish foo.bar i am foo.bar")
77
+ send_message("lita publish foo.baz i am foo.baz")
78
+ expect(replies.last(3).sort.uniq).to eq(
79
+ [
80
+ "*foo.bar*: i am foo.bar",
81
+ "*foo.baz*: i am foo.baz"
82
+ ]
83
+ )
84
+ end
85
+
86
+ it 'ignores unsubscribed events' do
87
+ send_message('lita publish foo bar de baz')
88
+ expect(replies).to be_empty
89
+ end
90
+
91
+ it 'publishes data to unsubscribed.event subscribers' do
92
+ send_message("lita subscribe unsubscribed.event", from: room)
93
+ send_message("lita publish foo bar de baz")
94
+ expect(replies.last).to eq('*unsubscribed.event*: foo: bar de baz')
95
+ end
96
+
97
+ it 'does not fail when unsubscribing unsubscribed event' do
98
+ send_message("lita unsubscribe bar", from: room)
99
+ expect(replies.last).to eq(
100
+ "There is no bar subscription in foos.\n" \
101
+ 'Current subscriptions: []'
102
+ )
103
+ end
104
+
105
+ context 'http request' do
106
+ before { Lita.config.handlers.pubsub.http_password = 'secret' }
107
+
108
+ it 'receives events via http get' do
109
+ send_message("lita subscribe foo", from: room)
110
+ http.get('/publish?event=foo&data=bar%20baz&password=secret')
111
+ expect(replies.last).to eq('*foo*: bar baz')
112
+ end
113
+
114
+ it 'receives events via http post' do
115
+ send_message("lita subscribe foo", from: room)
116
+ http.post(
117
+ '/publish',
118
+ '{"event": "foo", "data":"bar baz", "password":"secret"}',
119
+ 'Content-Type' => 'application/json'
120
+ )
121
+ expect(replies.last).to eq('*foo*: bar baz')
122
+ end
123
+
124
+ it 'receives events via http get when password is not set' do
125
+ send_message("lita subscribe foo", from: room)
126
+ Lita.config.handlers.pubsub.http_password = nil
127
+ http.get('/publish?event=foo&data=bar%20baz')
128
+ expect(replies.last).to eq('*foo*: bar baz')
129
+ end
130
+
131
+ it 'rejects http request without any password' do
132
+ expect {
133
+ http.get('/publish?event=foo&data=bar%20baz')
134
+ }.to raise_error('incorrect password!')
135
+ end
136
+
137
+ it 'rejects bad password via http get' do
138
+ expect {
139
+ http.get('/publish?event=foo&data=bar%20baz&password=haxor')
140
+ }.to raise_error('incorrect password!')
141
+ end
142
+
143
+ it 'rejects bad password via http post' do
144
+ expect {
145
+ http.post(
146
+ '/publish',
147
+ '{"event":"foo", "data":"bar baz", "password":"lol"}',
148
+ 'Content-Type' => 'application/json'
149
+ )
150
+ }.to raise_error('incorrect password!')
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,15 @@
1
+ require 'pry-byebug'
2
+ require "simplecov"
3
+ require "coveralls"
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ])
8
+ SimpleCov.start { add_filter "/spec/" }
9
+
10
+ require "lita-pubsub"
11
+ require "lita/rspec"
12
+
13
+ # A compatibility mode is provided for older plugins upgrading from Lita 3. Since this plugin
14
+ # was generated with Lita 4, the compatibility mode should be left disabled.
15
+ Lita.version_3_compatibility_mode = false
File without changes
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lita-pubsub
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tomas Varaneckas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-10-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lita
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '4.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '4.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack-test
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: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 3.0.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 3.0.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: coveralls
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: PubSub notification system for Lita
126
+ email:
127
+ - tomas.varaneckas@gmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".travis.yml"
134
+ - Gemfile
135
+ - README.md
136
+ - Rakefile
137
+ - lib/lita-pubsub.rb
138
+ - lib/lita/handlers/pubsub.rb
139
+ - lita-pubsub.gemspec
140
+ - locales/en.yml
141
+ - spec/lita/handlers/pubsub_spec.rb
142
+ - spec/spec_helper.rb
143
+ - templates/.gitkeep
144
+ homepage: https://github.com/spajus/hubot-lita
145
+ licenses:
146
+ - MIT License
147
+ metadata:
148
+ lita_plugin_type: handler
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.6.13
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: PubSub notification system for Lita
169
+ test_files:
170
+ - spec/lita/handlers/pubsub_spec.rb
171
+ - spec/spec_helper.rb