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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2cda9ebb75413427151ae533a04d020a9e9db638
4
- data.tar.gz: 582468f8b8eb1760fceb92b3b26f6dd83aa07957
3
+ metadata.gz: f8af98612f787abf18da9970dae3c2774eb02617
4
+ data.tar.gz: b293a5cba0cc0c58fab718447b2d1646f1a73fa5
5
5
  SHA512:
6
- metadata.gz: 85575d21f7b3e1c04d65f9a685e133eeb941e42e8bdffbe5637690be61c09f7e9995d0cc963f1c63a6db035ee3b55c2d7e98218f209f93432ae0575e1c9cd971
7
- data.tar.gz: 526f35c3436c164a3df4846a7a3641a5107130b04d8c8f204191c666d9cca1e10de4d6837e9b0dad265bee7eb6a20ac20f458f9e1f3eec9060db13647e83455a
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 Subtypes Event
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
- client.start
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
- @callbacks[:hello] ||= []
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 hear(pattern, &block)
33
- @callbacks[:message] ||= []
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 monitor(type, &block)
39
- @callbacks[type.to_sym] ||= []
40
- @callbacks[type.to_sym].push Listener::TypeListener.new(type, block)
41
- Debug.log "Add monitor event(#{@callbacks[type.to_sym].size}): #{type}"
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
- Messanger.new(options).message
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
@@ -2,7 +2,8 @@ module Slappy
2
2
  module DSL
3
3
  extend Forwardable
4
4
 
5
- def_delegators :Slappy, :hello, :hear, :say, :start, :logger, :schedule, :monitor
5
+ def_delegators :Slappy, :hello, :hear, :say, :start, :logger,
6
+ :schedule, :monitor, :goodnight, :respond
6
7
  end
7
8
  end
8
9
 
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
@@ -1,4 +1,3 @@
1
- require 'slappy/listeners/concerns/listenable'
2
1
  require 'slappy/listeners/base'
3
2
  require 'slappy/listeners/text_listener'
4
3
  require 'slappy/listeners/type_listener'
@@ -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 Listenable
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 Listenable
4
- include ActiveSupport::Concern
3
+ module Validatable
5
4
  include Slappy::Debuggable
6
5
 
7
- attr_reader :pattern
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
- Debug.log "Callback event call: #{pattern}"
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 target_element
45
- self.class.name.split('::').last.gsub(/Listener$/, '').underscore.to_sym
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 Messanger
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
@@ -2,6 +2,11 @@ module Slappy
2
2
  module SlackAPI
3
3
  class Base
4
4
  include Findable
5
+
6
+ def ==(other)
7
+ return false unless other.instance_of? self.class
8
+ other.id == id
9
+ end
5
10
  end
6
11
  end
7
12
  end
@@ -1,7 +1,8 @@
1
1
  module Slappy
2
2
  module SlackAPI
3
3
  class Channel < Base
4
- self.monitor_event = 'channel_created'
4
+ self.monitor_event =
5
+ %w(channel_created channel_deleted channel_rename channel_archive channel_unarchieve)
5
6
 
6
7
  def name
7
8
  '#' + @data.name
@@ -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 list(options = {})
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
- @list = Slack.send(method_name, options)[list_name].map { |data| new(data) }
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,8 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class File < Base
4
+ self.monitor_event =
5
+ %w(file_created file_deleted file_change file_public file_shared file_unshared)
6
+ end
7
+ end
8
+ end
@@ -1,7 +1,7 @@
1
1
  module Slappy
2
2
  module SlackAPI
3
3
  class Group < Base
4
- self.monitor_event = %w(group_joined group_open)
4
+ self.monitor_event = %w(group_joined group_open group_rename group_unarchive group_archieve)
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,8 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class Pin < Base
4
+ self.list_name = 'items'
5
+ self.monitor_event = %w(pin_added pin_removed)
6
+ end
7
+ end
8
+ end
@@ -2,7 +2,7 @@ module Slappy
2
2
  module SlackAPI
3
3
  class User < Base
4
4
  self.list_name = 'members'
5
- self.monitor_event = 'team_join'
5
+ self.monitor_event = %w(team_join user_change)
6
6
 
7
7
  def name
8
8
  '@' + @data.name
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Slappy
2
- VERSION = '0.5.2'
2
+ VERSION = '0.6.0'
3
3
  end
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/concerns/findable'
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/messanger'
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.5.2
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-18 00:00:00.000000000 Z
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/listenable.rb
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/messanger.rb
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