slappy 0.5.2 → 0.6.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/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
|