slappy 0.4.0 → 0.5.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: 8e79a1760b63ef1b9dc0b47ddc653346f56d972f
4
- data.tar.gz: 081b83f1f491f9173a1fd25f085c42faed243013
3
+ metadata.gz: 279a9dc258db912d4e7ed619595d66553ea75d69
4
+ data.tar.gz: 1937de721354dba64d166128b34bad6b24726723
5
5
  SHA512:
6
- metadata.gz: c5b60c4a6050e4df1e15f5f0d8ddd3a544edbf69669c18148dd505e05ddd152041dd14acfd662db472d73338ca32347a54cd409cdfee0e232a72374f0c78ed6b
7
- data.tar.gz: af1e4362d1387b85cc69e7492ed88b9b2f0f0a8e5bae0fd8eb042c2762742b597ad90c1cc4f3fddfb01db993d293742ed575173d3eddc9af1a2da81124edfecd
6
+ metadata.gz: 0ce87466b06fccd78a49e18e007dab3db1ec345e9c844437a05df2bc831a86ece70ebcb55cf00906a5312c7aa4b07a951216fc270500145066c819ce4388712c
7
+ data.tar.gz: 2b85a23ac6d034c6c9dd623d6d61da941466ea652753ba9cdcd816cea73b78a903a0263f1dd4aec2da5bf7c89d44c7c593ae50030c85a802c14c35288a33411e
data/README.md CHANGED
@@ -112,48 +112,104 @@ robot.username - default: 'slappy'
112
112
  robot.icon_emoji - default: nil
113
113
  robot.channel - default: '#general'
114
114
  robot.icon_url - default: nil
115
+ robot.as_user - default: false
115
116
  ```
116
117
 
117
118
  ### Basic Usage
118
119
 
119
- If you not want execute `slappy start` command, written by (require `'slappy/dsl'` use DSL):
120
-
121
120
  ```ruby
122
- require 'slappy'
123
-
124
121
  # called when start up
125
- Slappy.hello do
126
- Slappy.logger.info 'successfly connected'
122
+ hello do
123
+ logger.info 'successfly connected'
127
124
  end
125
+ ```
126
+
127
+ #### Send and Receive Message
128
128
 
129
+ ```ruby
129
130
  # called when match message
130
- Slappy.hear 'foo' do
131
- Slappy.logger.info 'foo'
131
+ hear 'foo' do
132
+ logger.info 'foo'
132
133
  end
133
134
 
134
135
  # use regexp in string literal
135
- Slappy.hear 'bar (.*)' do |event|
136
- Slappy.logger.info event.matches[1] #=> Event#matches return MatchData object
136
+ hear 'bar (.*)' do |event|
137
+ logger.info event.matches[1] #=> Event#matches return MatchData object
137
138
  end
138
139
 
139
140
  # event object is slack event JSON (convert to Hashie::Mash)
140
- Slappy.hear '^bar (.*)' do |event|
141
- Slappy.logger.info event.channel #=> channel id
142
- Slappy.say 'slappy!', channel: event.channel #=> to received message channel
143
- Slappy.say 'slappy!', channel: '#general'
144
- Slappy.say 'slappy!', username: 'slappy!', icon_emoji: ':slappy:'
141
+ hear '^bar (.*)' do |event|
142
+ say 'slappy!', channel: event.channel #=> to received channel object
143
+ say 'slappy!', channel: '#general' #=> send to public channel
144
+ say 'slappy!', channel: 'private-room' #=> send to private group
145
+ say 'slappy!', username: 'slappy!', icon_emoji: ':slappy:' #=> change config
145
146
  end
146
147
 
147
148
  # use regexp literal
148
- Slappy.hear /^foobar/ do
149
- Slappy.logger.info 'slappppy!'
149
+ hear(/^foobar/) do
150
+ logger.info 'slappppy!'
151
+ end
152
+ ```
153
+
154
+ #### Monitoring Subtypes Event
155
+
156
+ ```ruby
157
+ monitor 'channel_joined' do |event|
158
+ say "Welcome to #{event.name}!", channel: event.channel
150
159
  end
151
160
 
152
- Slappy.start #=> Start slappy process
161
+ monitor 'team_join' do |event|
162
+ say "Welcome to this team!", channel: "#general"
163
+ end
164
+ ```
165
+
166
+ #### Schedule Event
167
+
168
+ ```ruby
169
+ schedule '* * * * *' do
170
+ logger.info 'Slappy alive...' #=> Repeat every minutes.
171
+ end
172
+
173
+ ```
174
+
175
+ ### DSL Methods
176
+
177
+ |method|when execute callback|
178
+ |:---:|:---|
179
+ |hello|start up|
180
+ |hear|message (match pattern)|
181
+ |monitor|[Slack RTM event](https://api.slack.com/rtm)|
182
+ |schedule|specify time ([Syntax is here](https://github.com/r7kamura/chrono)) - Thanks to Chrono!|
183
+
184
+ ### In your Application
185
+
186
+ If you not want execute `slappy start` command, written by (require `'slappy/dsl'` use DSL):
187
+
188
+ ```
189
+ require 'slappy'
190
+
191
+ Slappy.hello do
192
+ # In your code..
193
+ end
194
+
195
+ Slappy.say 'message to slack'
196
+
197
+ Slappy.start #=> Start WebSocket connection
153
198
  ```
154
199
 
155
200
  ## Release Note
156
201
 
202
+ - v0.5.0
203
+ - Support Schedule
204
+ - Support Slack RMT Event
205
+ - Support private group
206
+ - Support as_user option
207
+ - Introduce SlackAPI objects
208
+ - Group
209
+ - Channel
210
+ - Direct
211
+ - User
212
+
157
213
  - v0.4.0
158
214
  - Support logger
159
215
  - Support load lib directory
data/lib/slappy/client.rb CHANGED
@@ -27,13 +27,22 @@ module Slappy
27
27
 
28
28
  def hear(pattern, &block)
29
29
  @callbacks[:message] ||= []
30
- @callbacks[:message].push Listener.new(pattern, block)
30
+ @callbacks[:message].push Listener::TextListener.new(pattern, block)
31
+ end
32
+
33
+ def monitor(subtype, &block)
34
+ @callbacks[:message] ||= []
35
+ @callbacks[:message].push Listener::SubtypeListener.new(subtype, block)
31
36
  end
32
37
 
33
38
  def say(text, options = {})
34
39
  options[:text] = text
35
- params = merge_send_params options
36
- Slack.chat_postMessage params
40
+ Messanger.new(options).message
41
+ end
42
+
43
+ def schedule(schedule, options = {}, &block)
44
+ @schedule ||= Schedule.new
45
+ @schedule.register schedule, options, &block
37
46
  end
38
47
 
39
48
  private
@@ -53,7 +62,7 @@ module Slappy
53
62
  when :hello
54
63
  listener.call
55
64
  when :message
56
- event = Event.new(data, listener.pattern)
65
+ event = Event.new(data)
57
66
  listener.call(event)
58
67
  end
59
68
  end
@@ -63,10 +72,5 @@ module Slappy
63
72
  def config
64
73
  Slappy.configuration
65
74
  end
66
-
67
- def merge_send_params(options)
68
- default = config.send_params
69
- default.merge options
70
- end
71
75
  end
72
76
  end
@@ -1,7 +1,11 @@
1
1
  module Slappy
2
2
  class Configuration
3
3
  class Robot
4
- attr_accessor :botname, :username, :channel, :icon_emoji, :icon_url
4
+ attr_accessor :botname, :username, :channel, :icon_emoji, :icon_url, :as_user
5
+
6
+ def as_user
7
+ @as_user || false
8
+ end
5
9
 
6
10
  def botname
7
11
  @botname || username
@@ -43,7 +43,8 @@ module Slappy
43
43
  username: robot.username,
44
44
  icon_emoji: robot.icon_emoji,
45
45
  channel: robot.channel,
46
- icon_url: robot.icon_url
46
+ icon_url: robot.icon_url,
47
+ as_user: robot.as_user
47
48
  }
48
49
  end
49
50
  end
data/lib/slappy/dsl.rb CHANGED
@@ -2,7 +2,7 @@ module Slappy
2
2
  module DSL
3
3
  extend Forwardable
4
4
 
5
- def_delegators :Slappy, :hello, :hear, :say, :start, :logger
5
+ def_delegators :Slappy, :hello, :hear, :say, :start, :logger, :schedule, :monitor
6
6
  end
7
7
  end
8
8
 
data/lib/slappy/event.rb CHANGED
@@ -2,17 +2,30 @@ module Slappy
2
2
  class Event
3
3
  extend Forwardable
4
4
 
5
- attr_reader :matches
5
+ attr_accessor :matches
6
6
 
7
7
  def_delegators :@data, :method_missing, :respond_to_missing?
8
8
 
9
- def initialize(data, pattern)
9
+ def initialize(data)
10
10
  @data = Hashie::Mash.new data
11
- @matches = text.match pattern
12
11
  end
13
12
 
14
13
  def text
15
14
  @data['text'].to_s
16
15
  end
16
+
17
+ def channel
18
+ SlackAPI::Channel.find(id: @data['channel']) ||
19
+ SlackAPI::Group.find(id: @data['channel']) ||
20
+ SlackAPI::Direct.find(id: @data['channel'])
21
+ end
22
+
23
+ def user
24
+ SlackAPI::User.find(id: @data['user'])
25
+ end
26
+
27
+ def ts
28
+ Time.at(@data['ts'].to_f)
29
+ end
17
30
  end
18
31
  end
@@ -1,19 +1,9 @@
1
- module Slappy
2
- class Listener
3
- def initialize(pattern, callback)
4
- pattern = /#{pattern}/ if pattern.is_a? String
5
- @regexp = pattern
6
- @callback = callback
7
- end
8
-
9
- def call(event)
10
- return unless Time.at(event.ts.to_f) > Slappy.client.start_time
11
- return unless event.text.match @regexp
12
- @callback.call(event)
13
- end
1
+ require 'slappy/listeners/concerns/listenable'
2
+ require 'slappy/listeners/base'
3
+ require 'slappy/listeners/text_listener'
4
+ require 'slappy/listeners/subtype_listener'
14
5
 
15
- def pattern
16
- @regexp
17
- end
6
+ module Slappy
7
+ module Listener
18
8
  end
19
9
  end
@@ -0,0 +1,7 @@
1
+ module Slappy
2
+ module Listener
3
+ class Base
4
+ include Listenable
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,36 @@
1
+ module Slappy
2
+ module Listener
3
+ module Listenable
4
+ include ActiveSupport::Concern
5
+
6
+ attr_reader :pattern
7
+
8
+ def initialize(target, callback)
9
+ @pattern = target
10
+ @callback = callback
11
+ end
12
+
13
+ def call(event)
14
+ return unless time_valid?(event)
15
+
16
+ target = event.send(target_element)
17
+ return unless target
18
+
19
+ event.matches = target.match pattern
20
+ return unless event.matches
21
+
22
+ @callback.call(event)
23
+ end
24
+
25
+ def time_valid?(event)
26
+ event.ts > Slappy.client.start_time
27
+ end
28
+
29
+ private
30
+
31
+ def target_element
32
+ self.class.name.split('::').last.gsub(/Listener$/, '').underscore.to_sym
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,6 @@
1
+ module Slappy
2
+ module Listener
3
+ class SubtypeListener < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,10 @@
1
+ module Slappy
2
+ module Listener
3
+ class TextListener < Base
4
+ def pattern
5
+ return /#{@pattern}/ if @pattern.instance_of? String
6
+ @pattern
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,44 @@
1
+ module Slappy
2
+ class Messanger
3
+ class MissingChannelException < StandardError; end
4
+
5
+ CHANNEL_APIS = [SlackAPI::Channel, SlackAPI::Group, SlackAPI::Direct]
6
+
7
+ def initialize(options)
8
+ @destination = {}
9
+ @destination = options[:channel]
10
+ options.delete :channel
11
+ @options = options
12
+ end
13
+
14
+ def message
15
+ options = merge_params(@options)
16
+
17
+ if @destination.is_a? SlackAPI::Base
18
+ id = @destination.id
19
+ else
20
+ instance = nil
21
+ CHANNEL_APIS.each do |klass|
22
+ instance = klass.find(name: @destination) || klass.find(id: @destination)
23
+ break unless instance.nil?
24
+ end
25
+ fail MissingChannelException.new, "channel / #{@destination} is not found" if instance.nil?
26
+ id = instance.id
27
+ end
28
+
29
+ options[:channel] = id
30
+ Slack.chat_postMessage options
31
+ end
32
+
33
+ private
34
+
35
+ def config
36
+ Slappy.configuration
37
+ end
38
+
39
+ def merge_params(options)
40
+ default = config.send_params
41
+ default.merge options
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,39 @@
1
+ require 'securerandom'
2
+
3
+ module Slappy
4
+ class Schedule
5
+ class OverScheduleError < StandardError; end
6
+ class InvalidFormatError < StandardError; end
7
+
8
+ DEFAULT_MAX_THREAD = 1000
9
+
10
+ def register(schedule, options = {}, &block)
11
+ id = options[:id] || generate_id
12
+ schedule_list[id] = Thread.new { Chrono::Trigger.new(schedule) { block.call }.run }
13
+ Slappy.logger.try(:debug, "Schedule registerd to #{schedule}")
14
+ id
15
+ end
16
+
17
+ def remove(id)
18
+ registered = @schedule_list.include? id
19
+ if registered
20
+ @schedule_list[id].kill
21
+ @schedule_list.delete id
22
+ end
23
+ registered
24
+ end
25
+
26
+ private
27
+
28
+ def schedule_list
29
+ @schedule_list ||= {}
30
+ end
31
+
32
+ def generate_id
33
+ figure = Math.log10(DEFAULT_MAX_THREAD) + 1
34
+ id = format("%0#{figure}d", SecureRandom.random_number(DEFAULT_MAX_THREAD))
35
+ id = generate_id if schedule_list.include? id
36
+ id
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,7 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class Base
4
+ include Findable
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class Channel < Base
4
+ self.monitor_event = 'channel_created'
5
+
6
+ def name
7
+ '#' + @data.name
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,57 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ module Findable
4
+ extend ActiveSupport::Concern
5
+ extend Forwardable
6
+
7
+ def_delegators :@data, :method_missing, :respond_to?
8
+
9
+ def initialize(data)
10
+ @data = Hashie::Mash.new data
11
+ end
12
+
13
+ module ClassMethods
14
+ attr_reader :list_name, :api_name, :monitor_event
15
+
16
+ def api_name=(api_name)
17
+ @api_name = api_name
18
+ end
19
+
20
+ def list_name=(list_name)
21
+ @list_name = list_name
22
+ end
23
+
24
+ def monitor_event=(target)
25
+ target = [target] unless target.instance_of? Array
26
+ @monitor_event = target
27
+ end
28
+
29
+ def list(options = {})
30
+ @monitor_event.each do |event|
31
+ Slappy.monitor event do
32
+ @list = nil
33
+ end
34
+ end
35
+
36
+ unless @list
37
+ api_name = self.api_name || name.split('::').last.downcase + 's'
38
+ list_name = self.list_name || api_name
39
+ method_name = "#{api_name}_list"
40
+
41
+ @list = Slack.send(method_name, options)[list_name].map { |data| new(data) }
42
+ end
43
+ @list
44
+ end
45
+
46
+ def find(arg)
47
+ return find_by_keyword(arg) if arg.instance_of? Hash
48
+ find id: arg
49
+ end
50
+
51
+ def find_by_keyword(hash)
52
+ hash.map { |key, value| list.find { |obj| obj.send(key) == value } }.first
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,9 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class Direct < Base
4
+ self.api_name = 'im'
5
+ self.list_name = 'ims'
6
+ self.monitor_event = 'im_open'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class Group < Base
4
+ self.monitor_event = %w(group_joined group_open)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ module Slappy
2
+ module SlackAPI
3
+ class User < Base
4
+ self.list_name = 'members'
5
+ self.monitor_event = 'team_join'
6
+
7
+ def name
8
+ '@' + @data.name
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,3 +1,3 @@
1
1
  module Slappy
2
- VERSION = '0.4.0'
2
+ VERSION = '0.5.0'
3
3
  end
data/lib/slappy.rb CHANGED
@@ -1,5 +1,8 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'active_support/concern'
4
+ require 'chrono'
1
5
  require 'forwardable'
2
- require 'active_support/core_ext/string/inflections'
3
6
  require 'hashie'
4
7
  require 'slack'
5
8
  require 'termcolor'
@@ -11,7 +14,7 @@ module Slappy
11
14
  extend Forwardable
12
15
 
13
16
  def_delegators :configuration, :logger
14
- def_delegators :client, :start, :hello, :hear, :say
17
+ def_delegators :client, :start, :hello, :hear, :say, :schedule, :monitor
15
18
 
16
19
  def configure
17
20
  @configuration = Configuration.new
@@ -31,6 +34,12 @@ module Slappy
31
34
  end
32
35
  end
33
36
 
37
+ require 'slappy/slack_api/concerns/findable'
38
+ require 'slappy/slack_api/base'
39
+ require 'slappy/slack_api/channel'
40
+ require 'slappy/slack_api/direct'
41
+ require 'slappy/slack_api/group'
42
+ require 'slappy/slack_api/user'
34
43
  require 'slappy/cli'
35
44
  require 'slappy/client'
36
45
  require 'slappy/configuration'
@@ -39,4 +48,6 @@ require 'slappy/commands/generator.rb'
39
48
  require 'slappy/commands/run.rb'
40
49
  require 'slappy/event'
41
50
  require 'slappy/listener'
51
+ require 'slappy/messanger'
52
+ require 'slappy/schedule'
42
53
  require 'slappy/version'
data/slappy.gemspec CHANGED
@@ -23,6 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_dependency 'thor'
24
24
  spec.add_dependency "activesupport"
25
25
  spec.add_dependency "termcolor"
26
+ spec.add_dependency "chrono"
26
27
  spec.add_development_dependency "bundler", "~> 1.10"
27
28
  spec.add_development_dependency "rake", "~> 10.0"
28
29
  spec.add_development_dependency "rspec"
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.0
4
+ version: 0.5.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-12 00:00:00.000000000 Z
11
+ date: 2015-11-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: slack-api
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: chrono
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: bundler
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -214,7 +228,6 @@ executables:
214
228
  extensions: []
215
229
  extra_rdoc_files: []
216
230
  files:
217
- - ".env.sample"
218
231
  - ".gitignore"
219
232
  - ".hound.yml"
220
233
  - ".rspec"
@@ -237,6 +250,18 @@ files:
237
250
  - lib/slappy/dsl.rb
238
251
  - lib/slappy/event.rb
239
252
  - lib/slappy/listener.rb
253
+ - lib/slappy/listeners/base.rb
254
+ - lib/slappy/listeners/concerns/listenable.rb
255
+ - lib/slappy/listeners/subtype_listener.rb
256
+ - lib/slappy/listeners/text_listener.rb
257
+ - lib/slappy/messanger.rb
258
+ - lib/slappy/schedule.rb
259
+ - lib/slappy/slack_api/base.rb
260
+ - lib/slappy/slack_api/channel.rb
261
+ - lib/slappy/slack_api/concerns/findable.rb
262
+ - lib/slappy/slack_api/direct.rb
263
+ - lib/slappy/slack_api/group.rb
264
+ - lib/slappy/slack_api/user.rb
240
265
  - lib/slappy/version.rb
241
266
  - slappy.gemspec
242
267
  - templates/example.rb
@@ -261,7 +286,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
261
286
  version: '0'
262
287
  requirements: []
263
288
  rubyforge_project:
264
- rubygems_version: 2.4.8
289
+ rubygems_version: 2.4.5.1
265
290
  signing_key:
266
291
  specification_version: 4
267
292
  summary: Simple Slack Bot Framework
data/.env.sample DELETED
@@ -1 +0,0 @@
1
- SLACK_TOKEN=