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 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