slappy 0.5.2 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +48 -10
- data/lib/slappy/client.rb +35 -13
- data/lib/slappy/dsl.rb +2 -1
- data/lib/slappy/event.rb +16 -0
- data/lib/slappy/listener.rb +0 -1
- data/lib/slappy/listeners/base.rb +32 -1
- data/lib/slappy/listeners/concerns/targettable.rb +67 -0
- data/lib/slappy/listeners/concerns/{listenable.rb → validatable.rb} +9 -22
- data/lib/slappy/{messanger.rb → messenger.rb} +3 -2
- data/lib/slappy/slack_api/base.rb +5 -0
- data/lib/slappy/slack_api/channel.rb +2 -1
- data/lib/slappy/slack_api/concerns/findable.rb +23 -5
- data/lib/slappy/slack_api/file.rb +8 -0
- data/lib/slappy/slack_api/group.rb +1 -1
- data/lib/slappy/slack_api/pin.rb +8 -0
- data/lib/slappy/slack_api/user.rb +1 -1
- data/lib/slappy/slack_api.rb +28 -0
- data/lib/slappy/version.rb +1 -1
- data/lib/slappy.rb +3 -8
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8af98612f787abf18da9970dae3c2774eb02617
|
4
|
+
data.tar.gz: b293a5cba0cc0c58fab718447b2d1646f1a73fa5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0838f8be93626934b4b8d8c0322ad19db775140536ae31764b0ba7f72e70938d2e26bf68130e488bed397beb4135e1249d8d32893bf16205bc9a0eeb4143f528
|
7
|
+
data.tar.gz: b95e4c625e0a4f32d35844885cfafd3533538396e64c7439169e3ce025d156d70f937019b89260529b835b99a5c4f2506ebddab22e456d13dbcd8f39bcb30337
|
data/README.md
CHANGED
@@ -151,7 +151,7 @@ hear(/^foobar/) do
|
|
151
151
|
end
|
152
152
|
```
|
153
153
|
|
154
|
-
#### Monitoring
|
154
|
+
#### Monitoring Types Event
|
155
155
|
|
156
156
|
```ruby
|
157
157
|
monitor 'channel_joined' do |event|
|
@@ -169,7 +169,19 @@ end
|
|
169
169
|
schedule '* * * * *' do
|
170
170
|
logger.info 'Slappy alive...' #=> Repeat every minutes.
|
171
171
|
end
|
172
|
+
```
|
173
|
+
|
174
|
+
#### Sleep Event
|
175
|
+
|
176
|
+
There conditions, this event be called:
|
177
|
+
|
178
|
+
- `raise StandardError` in script
|
179
|
+
- trap SIGTERM or SIGINT
|
172
180
|
|
181
|
+
```
|
182
|
+
goodnight do
|
183
|
+
logger.info 'goodnight'
|
184
|
+
end
|
173
185
|
```
|
174
186
|
|
175
187
|
### DSL Methods
|
@@ -178,8 +190,27 @@ end
|
|
178
190
|
|:---:|:---|
|
179
191
|
|hello|start up|
|
180
192
|
|hear|message (match pattern)|
|
193
|
+
|respond|message (match pattern and botname prefix given)|
|
181
194
|
|monitor|[Slack RTM event](https://api.slack.com/rtm)|
|
182
195
|
|schedule|specify time ([Syntax is here](https://github.com/r7kamura/chrono)) - Thanks to Chrono!|
|
196
|
+
|goodinight|bot dead (StandardError, SIGTERM, and SIGINT received)|
|
197
|
+
|
198
|
+
### Event Methods
|
199
|
+
|
200
|
+
```
|
201
|
+
hear 'slappy' do |event|
|
202
|
+
return if event.bot_message? #=> check message from webhook or integration
|
203
|
+
event.relpy 'slappy' #=> relpy to event channel
|
204
|
+
event.reaction 'thumbsup' #=> add reaction to event message
|
205
|
+
end
|
206
|
+
```
|
207
|
+
|
208
|
+
|method|description|
|
209
|
+
|:---:|:---|
|
210
|
+
|bot_message?|check message from bot (webhook or integration is true)|
|
211
|
+
|reply|reply message to event channel|
|
212
|
+
|reaction|add reaction to event message|
|
213
|
+
|
183
214
|
|
184
215
|
### In your Application
|
185
216
|
|
@@ -199,6 +230,22 @@ Slappy.start #=> Start WebSocket connection
|
|
199
230
|
|
200
231
|
## Release Note
|
201
232
|
|
233
|
+
- v0.6.0
|
234
|
+
- respond method
|
235
|
+
- respond event call when add message to botname prefix
|
236
|
+
- goodnight method
|
237
|
+
- goodnight event call when bod dead (StandardError, SIGTERM, and SIGINT received)
|
238
|
+
- New SlackAPI
|
239
|
+
- File
|
240
|
+
- Pin
|
241
|
+
- New Event methods
|
242
|
+
- bot_message? (contribute from [dnond](https://github.com/dnond))
|
243
|
+
- check message from bot(webhook, and integration)
|
244
|
+
- reaction
|
245
|
+
- reaction to event(add emoji reaction)
|
246
|
+
- reply
|
247
|
+
- relpy to event
|
248
|
+
|
202
249
|
- v0.5.2
|
203
250
|
- Add debug logging
|
204
251
|
- Fix schedule id is not normality
|
@@ -238,15 +285,6 @@ Slappy.start #=> Start WebSocket connection
|
|
238
285
|
- v0.1.0
|
239
286
|
- Release
|
240
287
|
|
241
|
-
## Feature
|
242
|
-
|
243
|
-
- [ ] Execute in shell (because testable).
|
244
|
-
- [ ] Support private channel
|
245
|
-
- [ ] Support Schedule event (cron like)
|
246
|
-
- [ ] Add bot name
|
247
|
-
- [ ] client#respond (hubot#respond like)
|
248
|
-
- [ ] Split chat adapter
|
249
|
-
|
250
288
|
## Contributing
|
251
289
|
|
252
290
|
1. Fork it ( http://github.com/wakaba260/slappy/fork )
|
data/lib/slappy/client.rb
CHANGED
@@ -20,30 +20,42 @@ module Slappy
|
|
20
20
|
end
|
21
21
|
set_signal_trap
|
22
22
|
Debug.log 'Slappy start'
|
23
|
-
|
23
|
+
begin
|
24
|
+
client.start
|
25
|
+
rescue StandardError => e
|
26
|
+
@callbacks[:goodnight].each(&:call) if @callbacks[:goodnight]
|
27
|
+
STDERR.puts e.backtrace.slice!(0) + ': ' + e.message
|
28
|
+
STDERR.puts "\tfrom " + e.backtrace.join("\n\tfrom ")
|
29
|
+
exit 1
|
30
|
+
end
|
24
31
|
end
|
25
32
|
|
26
33
|
def hello(&block)
|
27
|
-
|
28
|
-
@callbacks[:hello].push block
|
29
|
-
Debug.log "Add hello event(#{@callbacks[:hello].size})"
|
34
|
+
register_callback(:hello, :hello, block)
|
30
35
|
end
|
31
36
|
|
32
|
-
def
|
33
|
-
|
34
|
-
@callbacks[:message].push Listener::TextListener.new(pattern, block)
|
35
|
-
Debug.log "Add here event(#{@callbacks[:message].size}): #{pattern}"
|
37
|
+
def goodnight(&block)
|
38
|
+
register_callback(:goodnight, :goodnight, block)
|
36
39
|
end
|
37
40
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
41
|
+
def hear(pattern, options = {}, &block)
|
42
|
+
register_callback(:hear, :message, Listener::TextListener.new(pattern, options, &block))
|
43
|
+
end
|
44
|
+
|
45
|
+
def respond(pattern, options = {}, &block)
|
46
|
+
bot_name = options[:bot_name] || config.robot.botname || config.robot.username
|
47
|
+
|
48
|
+
pattern = "^#{bot_name}[[:blank:]]#{pattern}"
|
49
|
+
register_callback(:respond, :message, Listener::TextListener.new(pattern, options, &block))
|
50
|
+
end
|
51
|
+
|
52
|
+
def monitor(type, options = {}, &block)
|
53
|
+
register_callback(:monitor, type.to_sym, Listener::TypeListener.new(type, options, &block))
|
42
54
|
end
|
43
55
|
|
44
56
|
def say(text, options = {})
|
45
57
|
options[:text] = text
|
46
|
-
|
58
|
+
Messenger.new(options).message
|
47
59
|
end
|
48
60
|
|
49
61
|
def schedule(pattern, options = {}, &block)
|
@@ -54,9 +66,19 @@ module Slappy
|
|
54
66
|
|
55
67
|
private
|
56
68
|
|
69
|
+
def register_callback(name, type, callback)
|
70
|
+
@callbacks[type] ||= []
|
71
|
+
@callbacks[type].push callback
|
72
|
+
Debug.log "Add #{name} event(#{@callbacks[type.to_sym].size}): #{type}"
|
73
|
+
end
|
74
|
+
|
57
75
|
def set_signal_trap
|
58
76
|
[:TERM, :INT].each do |signal|
|
59
77
|
Signal.trap(signal) do
|
78
|
+
@callbacks[:goodnight].try(:each) do |callback|
|
79
|
+
th = Thread.new { callback.call }
|
80
|
+
th.join
|
81
|
+
end
|
60
82
|
EventMachine.stop
|
61
83
|
end
|
62
84
|
end
|
data/lib/slappy/dsl.rb
CHANGED
data/lib/slappy/event.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Slappy
|
2
2
|
class Event
|
3
3
|
extend Forwardable
|
4
|
+
include Debuggable
|
4
5
|
|
5
6
|
attr_accessor :matches
|
6
7
|
|
@@ -27,5 +28,20 @@ module Slappy
|
|
27
28
|
def ts
|
28
29
|
Time.at(@data['ts'].to_f)
|
29
30
|
end
|
31
|
+
|
32
|
+
def reply(text, options = {})
|
33
|
+
options[:text] = text
|
34
|
+
options[:channel] = channel
|
35
|
+
Messenger.new(options).message
|
36
|
+
end
|
37
|
+
|
38
|
+
def reaction(emoji)
|
39
|
+
result = ::Slack.reactions_add name: emoji, channel: @data['channel'], timestamp: @data['ts']
|
40
|
+
Debug.log "Reaction response: #{result}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def bot_message?
|
44
|
+
@data['subtype'] && @data['subtype'] == 'bot_message'
|
45
|
+
end
|
30
46
|
end
|
31
47
|
end
|
data/lib/slappy/listener.rb
CHANGED
@@ -1,7 +1,38 @@
|
|
1
|
+
require 'slappy/listeners/concerns/targettable'
|
2
|
+
require 'slappy/listeners/concerns/validatable'
|
3
|
+
|
1
4
|
module Slappy
|
2
5
|
module Listener
|
3
6
|
class Base
|
4
|
-
include
|
7
|
+
include Validatable
|
8
|
+
include Targettable
|
9
|
+
|
10
|
+
def initialize(pattern, options = {}, &callback)
|
11
|
+
self.pattern = pattern
|
12
|
+
if options[:from]
|
13
|
+
target.channel = options[:from][:channel]
|
14
|
+
target.user = options[:from][:user]
|
15
|
+
end
|
16
|
+
@callback = callback
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(event)
|
20
|
+
channel = "channel: #{event.try(:channel).try(:name)}"
|
21
|
+
element = "#{target_element}: #{event.try(target_element)}"
|
22
|
+
Debug.log "Listen event call(#{channel} / #{element})"
|
23
|
+
|
24
|
+
return unless valid?(event)
|
25
|
+
return unless target?(event)
|
26
|
+
|
27
|
+
Debug.log "Callback event call: #{pattern}"
|
28
|
+
@callback.call(event)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def target_element
|
34
|
+
self.class.name.split('::').last.gsub(/Listener$/, '').underscore.to_sym
|
35
|
+
end
|
5
36
|
end
|
6
37
|
end
|
7
38
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Slappy
|
2
|
+
module Listener
|
3
|
+
module Targettable
|
4
|
+
include Slappy::Debuggable
|
5
|
+
|
6
|
+
def target?(event)
|
7
|
+
target.valid? event
|
8
|
+
end
|
9
|
+
|
10
|
+
def target
|
11
|
+
@target ||= Target.new
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
class Target
|
17
|
+
def valid?(event)
|
18
|
+
return true if channel.blank? && user.blank?
|
19
|
+
|
20
|
+
result = []
|
21
|
+
|
22
|
+
result << false unless validation(:channel, event)
|
23
|
+
result << false unless validation(:user, event)
|
24
|
+
|
25
|
+
result.blank?
|
26
|
+
end
|
27
|
+
|
28
|
+
def validation(target, event)
|
29
|
+
return true if send(target).compact.blank?
|
30
|
+
unless send(:list, target).include? event.send target
|
31
|
+
Debug.log "Message from restrict #{target}(expect: #{target_names(target)})"
|
32
|
+
return false
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
def channel=(value)
|
38
|
+
value = [value] unless value.instance_of? Array
|
39
|
+
@channel = value
|
40
|
+
end
|
41
|
+
|
42
|
+
def list(target)
|
43
|
+
send(target).each_with_object([]) do |t, result|
|
44
|
+
result << Slappy::SlackAPI.find(t)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def channel
|
49
|
+
@channel ||= []
|
50
|
+
end
|
51
|
+
|
52
|
+
def target_names(target)
|
53
|
+
send(target).join(',')
|
54
|
+
end
|
55
|
+
|
56
|
+
def user=(value)
|
57
|
+
value = [value] unless value.instance_of? Array
|
58
|
+
@user = value
|
59
|
+
end
|
60
|
+
|
61
|
+
def user
|
62
|
+
@user ||= []
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -1,48 +1,35 @@
|
|
1
1
|
module Slappy
|
2
2
|
module Listener
|
3
|
-
module
|
4
|
-
include ActiveSupport::Concern
|
3
|
+
module Validatable
|
5
4
|
include Slappy::Debuggable
|
6
5
|
|
7
|
-
|
8
|
-
|
9
|
-
def initialize(target, callback)
|
10
|
-
@pattern = target
|
11
|
-
@callback = callback
|
12
|
-
end
|
13
|
-
|
14
|
-
def call(event)
|
15
|
-
Debug.log "Listen event call: #{target_element}:#{event.send(target_element)}"
|
6
|
+
attr_accessor :pattern
|
16
7
|
|
8
|
+
def valid?(event)
|
17
9
|
unless time_valid?(event)
|
18
10
|
Debug.log 'Event happend in before start time'
|
19
|
-
return
|
11
|
+
return false
|
20
12
|
end
|
21
13
|
|
22
14
|
target = event.send(target_element)
|
23
15
|
unless target
|
24
16
|
Debug.log 'Target is nil'
|
25
|
-
return
|
17
|
+
return false
|
26
18
|
end
|
27
19
|
|
28
20
|
event.matches = target.match pattern
|
29
21
|
unless event.matches
|
30
22
|
Debug.log "Target is not match pattern(#{pattern})"
|
31
|
-
return
|
23
|
+
return false
|
32
24
|
end
|
33
25
|
|
34
|
-
|
35
|
-
@callback.call(event)
|
36
|
-
end
|
37
|
-
|
38
|
-
def time_valid?(event)
|
39
|
-
event.ts > Slappy.client.start_time
|
26
|
+
true
|
40
27
|
end
|
41
28
|
|
42
29
|
private
|
43
30
|
|
44
|
-
def
|
45
|
-
|
31
|
+
def time_valid?(event)
|
32
|
+
event.ts > Slappy.client.start_time
|
46
33
|
end
|
47
34
|
end
|
48
35
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Slappy
|
2
|
-
class
|
2
|
+
class Messenger
|
3
3
|
class MissingChannelException < StandardError; end
|
4
4
|
|
5
5
|
CHANNEL_APIS = [SlackAPI::Channel, SlackAPI::Group, SlackAPI::Direct]
|
@@ -27,7 +27,8 @@ module Slappy
|
|
27
27
|
end
|
28
28
|
|
29
29
|
options[:channel] = id
|
30
|
-
Slack.chat_postMessage options
|
30
|
+
response = Slack.chat_postMessage options
|
31
|
+
fail SlackAPI::SlackError.new, response['error'] unless response['ok']
|
31
32
|
end
|
32
33
|
|
33
34
|
private
|
@@ -11,7 +11,7 @@ module Slappy
|
|
11
11
|
end
|
12
12
|
|
13
13
|
module ClassMethods
|
14
|
-
attr_reader :list_name, :api_name, :monitor_event
|
14
|
+
attr_reader :list_name, :api_name, :monitor_event, :monitor_registerd
|
15
15
|
|
16
16
|
def api_name=(api_name)
|
17
17
|
@api_name = api_name
|
@@ -26,23 +26,41 @@ module Slappy
|
|
26
26
|
@monitor_event = target
|
27
27
|
end
|
28
28
|
|
29
|
-
def
|
29
|
+
def register_monitor
|
30
|
+
return if @monitor_registerd
|
30
31
|
@monitor_event.each do |event|
|
31
32
|
Slappy.monitor event do
|
32
33
|
@list = nil
|
33
34
|
end
|
34
35
|
end
|
36
|
+
@monitor_registerd = true
|
37
|
+
end
|
38
|
+
|
39
|
+
def list(options = {})
|
40
|
+
register_monitor
|
35
41
|
|
36
42
|
unless @list
|
37
|
-
api_name = self.api_name || name.split('::').last.downcase + 's'
|
38
|
-
list_name = self.list_name || api_name
|
39
43
|
method_name = "#{api_name}_list"
|
40
44
|
|
41
|
-
|
45
|
+
options[:channel] = SlackAPI.find(options[:channel]).id if options[:channel]
|
46
|
+
result = Slack.send(method_name, options)
|
47
|
+
unless result['ok']
|
48
|
+
exception = SlackError.new "Error message from slack (#{result['error']})"
|
49
|
+
fail exception, exception.message
|
50
|
+
end
|
51
|
+
@list = result[list_name].map { |data| new(data) }
|
42
52
|
end
|
43
53
|
@list
|
44
54
|
end
|
45
55
|
|
56
|
+
def api_name
|
57
|
+
@api_name || name.split('::').last.downcase + 's'
|
58
|
+
end
|
59
|
+
|
60
|
+
def list_name
|
61
|
+
@list_name || api_name
|
62
|
+
end
|
63
|
+
|
46
64
|
def find(arg)
|
47
65
|
return find_by_keyword(arg) if arg.instance_of? Hash
|
48
66
|
find id: arg
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'slappy/slack_api/concerns/findable'
|
2
|
+
require 'slappy/slack_api/base'
|
3
|
+
require 'slappy/slack_api/channel'
|
4
|
+
require 'slappy/slack_api/direct'
|
5
|
+
require 'slappy/slack_api/file'
|
6
|
+
require 'slappy/slack_api/group'
|
7
|
+
require 'slappy/slack_api/user'
|
8
|
+
require 'slappy/slack_api/pin'
|
9
|
+
|
10
|
+
module Slappy
|
11
|
+
module SlackAPI
|
12
|
+
class SlackError < StandardError
|
13
|
+
def exception(error_message = nil)
|
14
|
+
error_message = "#{error_message}. Error detail is see: https://api.slack.com/methods"
|
15
|
+
super(error_message)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.find(value)
|
20
|
+
[:Channel, :Group, :Direct, :User].each do |klass|
|
21
|
+
klass = "Slappy::SlackAPI::#{klass}".constantize
|
22
|
+
result = (klass.find(id: value) || klass.find(name: value))
|
23
|
+
return result if result
|
24
|
+
end
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/slappy/version.rb
CHANGED
data/lib/slappy.rb
CHANGED
@@ -12,7 +12,7 @@ module Slappy
|
|
12
12
|
extend Forwardable
|
13
13
|
|
14
14
|
def_delegators :configuration, :logger
|
15
|
-
def_delegators :client, :start, :hello, :hear, :say, :schedule, :monitor
|
15
|
+
def_delegators :client, :start, :hello, :hear, :say, :schedule, :monitor, :goodnight, :respond
|
16
16
|
|
17
17
|
def configure
|
18
18
|
@configuration = Configuration.new
|
@@ -33,12 +33,7 @@ module Slappy
|
|
33
33
|
end
|
34
34
|
|
35
35
|
require 'slappy/concerns/debuggable'
|
36
|
-
require 'slappy/slack_api
|
37
|
-
require 'slappy/slack_api/base'
|
38
|
-
require 'slappy/slack_api/channel'
|
39
|
-
require 'slappy/slack_api/direct'
|
40
|
-
require 'slappy/slack_api/group'
|
41
|
-
require 'slappy/slack_api/user'
|
36
|
+
require 'slappy/slack_api'
|
42
37
|
require 'slappy/cli'
|
43
38
|
require 'slappy/client'
|
44
39
|
require 'slappy/configuration'
|
@@ -47,6 +42,6 @@ require 'slappy/commands/generator.rb'
|
|
47
42
|
require 'slappy/commands/run.rb'
|
48
43
|
require 'slappy/event'
|
49
44
|
require 'slappy/listener'
|
50
|
-
require 'slappy/
|
45
|
+
require 'slappy/messenger'
|
51
46
|
require 'slappy/schedule'
|
52
47
|
require 'slappy/version'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: slappy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- wakaba260
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-11-
|
11
|
+
date: 2015-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: slack-api
|
@@ -252,17 +252,21 @@ files:
|
|
252
252
|
- lib/slappy/event.rb
|
253
253
|
- lib/slappy/listener.rb
|
254
254
|
- lib/slappy/listeners/base.rb
|
255
|
-
- lib/slappy/listeners/concerns/
|
255
|
+
- lib/slappy/listeners/concerns/targettable.rb
|
256
|
+
- lib/slappy/listeners/concerns/validatable.rb
|
256
257
|
- lib/slappy/listeners/subtype_listener.rb
|
257
258
|
- lib/slappy/listeners/text_listener.rb
|
258
259
|
- lib/slappy/listeners/type_listener.rb
|
259
|
-
- lib/slappy/
|
260
|
+
- lib/slappy/messenger.rb
|
260
261
|
- lib/slappy/schedule.rb
|
262
|
+
- lib/slappy/slack_api.rb
|
261
263
|
- lib/slappy/slack_api/base.rb
|
262
264
|
- lib/slappy/slack_api/channel.rb
|
263
265
|
- lib/slappy/slack_api/concerns/findable.rb
|
264
266
|
- lib/slappy/slack_api/direct.rb
|
267
|
+
- lib/slappy/slack_api/file.rb
|
265
268
|
- lib/slappy/slack_api/group.rb
|
269
|
+
- lib/slappy/slack_api/pin.rb
|
266
270
|
- lib/slappy/slack_api/user.rb
|
267
271
|
- lib/slappy/version.rb
|
268
272
|
- slappy.gemspec
|