chatty_crow 1.2.1 → 1.3.1
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.textile +61 -1
- data/Rakefile +9 -0
- data/chatty_crow.gemspec +2 -2
- data/lib/chatty_crow.rb +36 -0
- data/lib/chatty_crow/batch_notification_request.rb +126 -0
- data/lib/chatty_crow/config.rb +10 -4
- data/lib/chatty_crow/contacts_request.rb +4 -1
- data/lib/chatty_crow/message.rb +82 -0
- data/lib/chatty_crow/notification_request.rb +6 -1
- data/lib/chatty_crow/request.rb +33 -4
- data/lib/chatty_crow/request/hipchat.rb +17 -0
- data/lib/chatty_crow/request/mail.rb +1 -1
- data/lib/chatty_crow/request/slack.rb +17 -0
- data/lib/chatty_crow/response.rb +15 -5
- data/lib/chatty_crow/response/batch.rb +66 -0
- data/lib/chatty_crow/response/notification.rb +17 -2
- data/lib/chatty_crow/version.rb +1 -1
- data/test/base_request_test.rb +20 -0
- data/test/batch_test.rb +112 -0
- data/test/configuration_test.rb +6 -3
- data/test/helper.rb +15 -0
- metadata +15 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 934f0269b67bacd13a7806530f99771ecd2fb8ba
|
|
4
|
+
data.tar.gz: 7d196a82c2915d95b1c449cba03ae909c672580d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b0437f430fa57e8a0ec001be87591bb5ba25df06237fdb85081afe7868a7da895a24f928b6db3806c07df2d7e4e84663c9e23cbf07ac5e84fb5c3b75fa2a1b0d
|
|
7
|
+
data.tar.gz: 6ee8ed7c1d545790152af84ad81de1fecb04bb46ffaec019e1bcfd254a9ba7d86d8d3855f260f65980652979769e677cc7e7a7b0c2d1463fd22f18890929c638
|
data/README.textile
CHANGED
|
@@ -102,7 +102,7 @@ h3. IOS Push notification
|
|
|
102
102
|
|
|
103
103
|
<pre>
|
|
104
104
|
# Send request
|
|
105
|
-
response = ChattyCrow.send_ios(payload: { 'hello' }, channel: 'other_than_default', token: 'other', contacts: [ 'new_ios_id1', 'new_ios_id2' ])
|
|
105
|
+
response = ChattyCrow.send_ios(payload: { 'hello' }, channel: 'other_than_default', token: 'other', contacts: [ 'new_ios_id1', 'new_ios_id2' ], time: { start: DateTime.now.to_i, end: DateTime.now.advance(days: 7) }, location: { latitude: 14.302022, longitude: 43.20923, range: 1000 })
|
|
106
106
|
|
|
107
107
|
# Or simple message
|
|
108
108
|
response = ChattyCrow.send_ios('Dear users')
|
|
@@ -123,6 +123,8 @@ response = ChattyCrow.send_android(payload: { data: { key: 'key1', key2: 'key2'}
|
|
|
123
123
|
# response.success = 5
|
|
124
124
|
# response.failed = 1
|
|
125
125
|
# response.failed_contacts = [ 'new_ios_id1' ]
|
|
126
|
+
# response.message_id = your created message ID
|
|
127
|
+
# response.message = Response::Message instance
|
|
126
128
|
</pre>
|
|
127
129
|
|
|
128
130
|
h3. Skype notification
|
|
@@ -145,6 +147,26 @@ response = ChattyCrow.send_jabber('Dear users', channel: 'other_than_default', c
|
|
|
145
147
|
# response # ChattyCrow::Response::Notification
|
|
146
148
|
</pre>
|
|
147
149
|
|
|
150
|
+
h3. HipChat notifications
|
|
151
|
+
|
|
152
|
+
<pre>
|
|
153
|
+
# Send request
|
|
154
|
+
# Color (red, yellow, purple, random - yellow is default)
|
|
155
|
+
response = ChattyCrow.send_hipchat('Dear users', color: 'red', channel: 'other_than_default', contacts: [ 'new_ios_id1', 'new_ios_id2' ])
|
|
156
|
+
|
|
157
|
+
# Response
|
|
158
|
+
# response # ChattyCrow::Response::Notification
|
|
159
|
+
</pre>
|
|
160
|
+
|
|
161
|
+
h3. Slack notifications
|
|
162
|
+
|
|
163
|
+
<pre>
|
|
164
|
+
# Send request
|
|
165
|
+
response = ChattyCrow.send_hipchat('Dear users', channel: 'other_than_default', contacts: [ 'new_ios_id1', 'new_ios_id2' ])
|
|
166
|
+
|
|
167
|
+
# Response
|
|
168
|
+
# response # ChattyCrow::Response::Notification
|
|
169
|
+
</pre>
|
|
148
170
|
|
|
149
171
|
h3. SMS notification (only Czech Republic yet)
|
|
150
172
|
|
|
@@ -156,6 +178,16 @@ response = ChattyCrow.send_sms 'Dear Users', contacts: [ '+420111222333', '+4202
|
|
|
156
178
|
# response # ChattyCrow::Response::Notification
|
|
157
179
|
</pre>
|
|
158
180
|
|
|
181
|
+
h2. Message detail and state
|
|
182
|
+
|
|
183
|
+
We're providing uniq message id to check what's going on with your message. You obtain message instance from successfull response.
|
|
184
|
+
|
|
185
|
+
<pre>
|
|
186
|
+
message = response.message
|
|
187
|
+
message.refresh_data!
|
|
188
|
+
message.status # OK etc..
|
|
189
|
+
</pre>
|
|
190
|
+
|
|
159
191
|
h2. Working with contacts via API
|
|
160
192
|
|
|
161
193
|
It's actually very usable, you can automatically add or remove contacts in your application after user was registered.
|
|
@@ -181,3 +213,31 @@ h3. Remove contact
|
|
|
181
213
|
# response.failed_count = 1
|
|
182
214
|
# response.failed = [ 'new2failed' ]
|
|
183
215
|
</pre>
|
|
216
|
+
|
|
217
|
+
h2. Batch notifications
|
|
218
|
+
|
|
219
|
+
Allows sends multiple notifications with serveral restrictions, notifications are immediatelly aborted when:
|
|
220
|
+
* Token and channels not matched
|
|
221
|
+
* One of channel is suspended
|
|
222
|
+
* Times or locations are invalid in any case
|
|
223
|
+
|
|
224
|
+
<pre>
|
|
225
|
+
batch = ChattyCrow.create_batch("different token then default")
|
|
226
|
+
|
|
227
|
+
# Its almost the same as send_android, but channel is required!
|
|
228
|
+
batch.add_jabber 'Dear users', channel: 'channel', contacts: [ 'aa' ]
|
|
229
|
+
batch.execute # add '!' to raise error, when something is wrong
|
|
230
|
+
</pre>
|
|
231
|
+
|
|
232
|
+
h2. Changelog
|
|
233
|
+
|
|
234
|
+
h3. 1.3.0
|
|
235
|
+
|
|
236
|
+
* Add batch notifications (this is required for Redmine Plugin or Capistrano Plugin)
|
|
237
|
+
|
|
238
|
+
h3. 1.2.2
|
|
239
|
+
|
|
240
|
+
* Add messages state API
|
|
241
|
+
* Remove GET contact list methods
|
|
242
|
+
* Add support of change location API
|
|
243
|
+
* Add HipChat, Slack and Telegram
|
data/Rakefile
CHANGED
data/chatty_crow.gemspec
CHANGED
|
@@ -14,10 +14,10 @@ Gem::Specification.new do |s|
|
|
|
14
14
|
%w(chatty_crow.gemspec CHANGELOG Gemfile Guardfile INSTALL LICENSE Rakefile README.textile)
|
|
15
15
|
s.test_files = Dir.glob('{test}/**/*')
|
|
16
16
|
|
|
17
|
-
s.required_ruby_version = '>=
|
|
17
|
+
s.required_ruby_version = '>= 1.9'
|
|
18
18
|
|
|
19
19
|
s.add_runtime_dependency('multi_json', '~> 1.0')
|
|
20
|
-
s.add_runtime_dependency('
|
|
20
|
+
s.add_runtime_dependency('rest-client', '~> 1.7')
|
|
21
21
|
s.add_runtime_dependency('mime-types', '>= 1')
|
|
22
22
|
|
|
23
23
|
s.add_development_dependency('fakeweb', '~> 1.3')
|
data/lib/chatty_crow.rb
CHANGED
|
@@ -2,6 +2,7 @@ require 'rest-client'
|
|
|
2
2
|
require 'chatty_crow/config'
|
|
3
3
|
require 'chatty_crow/error'
|
|
4
4
|
require 'chatty_crow/response'
|
|
5
|
+
require 'chatty_crow/message'
|
|
5
6
|
require 'chatty_crow/request'
|
|
6
7
|
require 'chatty_crow/request/android'
|
|
7
8
|
require 'chatty_crow/request/ios'
|
|
@@ -9,7 +10,14 @@ require 'chatty_crow/request/jabber'
|
|
|
9
10
|
require 'chatty_crow/request/mail'
|
|
10
11
|
require 'chatty_crow/request/skype'
|
|
11
12
|
require 'chatty_crow/request/sms'
|
|
13
|
+
require 'chatty_crow/request/hipchat'
|
|
14
|
+
require 'chatty_crow/request/slack'
|
|
15
|
+
require 'chatty_crow/response/notification'
|
|
16
|
+
require 'chatty_crow/response/batch'
|
|
17
|
+
require 'chatty_crow/response/contacts_add'
|
|
18
|
+
require 'chatty_crow/response/contacts_remove'
|
|
12
19
|
require 'chatty_crow/notification_request'
|
|
20
|
+
require 'chatty_crow/batch_notification_request'
|
|
13
21
|
require 'chatty_crow/contacts_request'
|
|
14
22
|
|
|
15
23
|
# Load Rails Components
|
|
@@ -75,6 +83,14 @@ module ChattyCrow
|
|
|
75
83
|
NotificationRequest.send(Request::Skype, *args)
|
|
76
84
|
end
|
|
77
85
|
|
|
86
|
+
def self.send_hipchat(*args)
|
|
87
|
+
NotificationRequest.send(Request::HipChat, *args)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def self.send_slack(*args)
|
|
91
|
+
NotificationRequest.send(Request::Slack, *args)
|
|
92
|
+
end
|
|
93
|
+
|
|
78
94
|
def self.send_jabber(*args)
|
|
79
95
|
NotificationRequest.send(Request::Jabber, *args)
|
|
80
96
|
end
|
|
@@ -95,6 +111,11 @@ module ChattyCrow
|
|
|
95
111
|
ContactsRequest.remove(*args)
|
|
96
112
|
end
|
|
97
113
|
|
|
114
|
+
# Create batch request
|
|
115
|
+
def self.create_batch(token = nil)
|
|
116
|
+
BatchNotificationRequest.new(token)
|
|
117
|
+
end
|
|
118
|
+
|
|
98
119
|
# Helper method for wrapping non-array objects
|
|
99
120
|
# @param object [Object] Something
|
|
100
121
|
# @return [Array] Array
|
|
@@ -116,4 +137,19 @@ module ChattyCrow
|
|
|
116
137
|
{}
|
|
117
138
|
end
|
|
118
139
|
end
|
|
140
|
+
|
|
141
|
+
# Symbolize keys
|
|
142
|
+
def self.symbolize_keys!(hash)
|
|
143
|
+
hash.keys.each do |key|
|
|
144
|
+
# Get value
|
|
145
|
+
value = hash.delete(key)
|
|
146
|
+
|
|
147
|
+
# Save as sym
|
|
148
|
+
hash[(key.to_sym rescue key)] = value
|
|
149
|
+
|
|
150
|
+
# Recursive?
|
|
151
|
+
symbolize_keys!(hash[key.to_sym]) if value.is_a?(Hash)
|
|
152
|
+
end
|
|
153
|
+
true
|
|
154
|
+
end
|
|
119
155
|
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require 'rest_client'
|
|
2
|
+
|
|
3
|
+
module ChattyCrow
|
|
4
|
+
# Batch notification request
|
|
5
|
+
# use for send different kind
|
|
6
|
+
# of notifications
|
|
7
|
+
class BatchNotificationRequest
|
|
8
|
+
# Prepare data
|
|
9
|
+
attr_accessor :requests, :token
|
|
10
|
+
|
|
11
|
+
def initialize(token = nil)
|
|
12
|
+
@token = token
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def requests
|
|
16
|
+
@requests ||= []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Add requests by type
|
|
20
|
+
def add_mail(*args)
|
|
21
|
+
add_other Request::Mail.new(*args)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def add_ios(*args)
|
|
25
|
+
add_other Request::Ios.new(*args)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add_android(*args)
|
|
29
|
+
add_other Request::Android.new(*args)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def add_skype(*args)
|
|
33
|
+
add_other Request::Skype.new(*args)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def add_hipchat(*args)
|
|
37
|
+
add_other Request::HipChat.new(*args)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_slack(*args)
|
|
41
|
+
add_other Request::Slack.new(*args)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_jabber(*args)
|
|
45
|
+
add_other Request::Jabber.new(*args)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Add other with channel name
|
|
49
|
+
def add_other(instance)
|
|
50
|
+
# Throw error when instance has empty channel
|
|
51
|
+
fail ::ArgumentError, 'Channel is required' unless instance.channel
|
|
52
|
+
|
|
53
|
+
# Add
|
|
54
|
+
requests << instance
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Send
|
|
58
|
+
def execute
|
|
59
|
+
proceed(false)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Send with errors!
|
|
63
|
+
def execute!
|
|
64
|
+
proceed(true)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# :nodoc:
|
|
68
|
+
def self.batch_notification_url
|
|
69
|
+
ChattyCrow.configuration.batch_url
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Batch headers
|
|
73
|
+
def batch_headers
|
|
74
|
+
ChattyCrow.batch_headers(@token)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
# Method actually sends created request to server
|
|
80
|
+
# [Can be refactored, with request class]
|
|
81
|
+
# @param raise_errors [Boolean] Raise errors if error?
|
|
82
|
+
# @return [Object] Raise an exception or return Response::Notification
|
|
83
|
+
def proceed(raise_errors = true)
|
|
84
|
+
# Empty requests?
|
|
85
|
+
if requests.empty?
|
|
86
|
+
if raise_errors
|
|
87
|
+
fail ::ArgumentError, 'At least one message is required!'
|
|
88
|
+
else
|
|
89
|
+
return false
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Headers
|
|
94
|
+
options = { headers: batch_headers, url: self.class.batch_notification_url, method: :post }
|
|
95
|
+
|
|
96
|
+
# Create array!
|
|
97
|
+
options[:payload] = { channels: requests.map { |i| i.to_json(true)[:payload] } }.to_json
|
|
98
|
+
|
|
99
|
+
# Send
|
|
100
|
+
RestClient::Request.execute(options) do |response, request, result, &block|
|
|
101
|
+
begin
|
|
102
|
+
case response.code
|
|
103
|
+
when 200, 201
|
|
104
|
+
Response::Batch.new response, options
|
|
105
|
+
when 301, 302, 307
|
|
106
|
+
response.follow_redirection(request, result, &block)
|
|
107
|
+
when 400
|
|
108
|
+
fail Error::InvalidAttributes, response
|
|
109
|
+
when 401
|
|
110
|
+
fail Error::UnauthorizedRequest, response
|
|
111
|
+
when 404
|
|
112
|
+
fail Error::ChannelNotFound, response
|
|
113
|
+
else
|
|
114
|
+
fail Error::InvalidReturn, response
|
|
115
|
+
end
|
|
116
|
+
rescue => e
|
|
117
|
+
if raise_errors
|
|
118
|
+
raise e
|
|
119
|
+
else
|
|
120
|
+
false
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end # RestClient
|
|
124
|
+
end # Execute
|
|
125
|
+
end
|
|
126
|
+
end
|
data/lib/chatty_crow/config.rb
CHANGED
|
@@ -24,10 +24,14 @@ module ChattyCrow
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
def self.default_headers(channel, token)
|
|
27
|
+
batch_headers(token).merge('Channel' => (channel || configuration.default_channel))
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.batch_headers(token)
|
|
27
31
|
{
|
|
28
32
|
'Token' => token || configuration.token,
|
|
29
|
-
'
|
|
30
|
-
'
|
|
33
|
+
'Accept' => 'application/json',
|
|
34
|
+
'Content-Type' => 'application/json'
|
|
31
35
|
}
|
|
32
36
|
end
|
|
33
37
|
|
|
@@ -45,10 +49,10 @@ module ChattyCrow
|
|
|
45
49
|
attr_accessor :http_read_timeout
|
|
46
50
|
|
|
47
51
|
# Call urls
|
|
48
|
-
attr_reader :notification_url, :contacts_url
|
|
52
|
+
attr_reader :notification_url, :contacts_url, :messages_url, :batch_url
|
|
49
53
|
|
|
50
54
|
def initialize
|
|
51
|
-
self.host = 'https://
|
|
55
|
+
self.host = 'https://chattycrow.com/api/v1/'
|
|
52
56
|
@token = nil
|
|
53
57
|
@default_channel = nil
|
|
54
58
|
@http_open_timeout = 2
|
|
@@ -59,6 +63,8 @@ module ChattyCrow
|
|
|
59
63
|
@host = s
|
|
60
64
|
@notification_url = s + (s[-1] == '/' ? '' : '/') + 'notification'
|
|
61
65
|
@contacts_url = s + (s[-1] == '/' ? '' : '/') + 'contacts'
|
|
66
|
+
@messages_url = s + (s[-1] == '/' ? '' : '/') + 'message'
|
|
67
|
+
@batch_url = s + (s[-1] == '/' ? '' : '/') + 'batch'
|
|
62
68
|
end
|
|
63
69
|
end
|
|
64
70
|
end
|
|
@@ -28,7 +28,7 @@ module ChattyCrow
|
|
|
28
28
|
# Method prepare data from add/remove contact
|
|
29
29
|
# @params klass [Class] Initializable class for response
|
|
30
30
|
# @params method [String] HTTP method
|
|
31
|
-
# @params
|
|
31
|
+
# @params args [Arguments]
|
|
32
32
|
def self.send_contact_request(klass, method, *args)
|
|
33
33
|
# Parse options
|
|
34
34
|
options = ChattyCrow.extract_options!(args)
|
|
@@ -55,6 +55,9 @@ module ChattyCrow
|
|
|
55
55
|
options[:url] = contacts_url
|
|
56
56
|
options[:headers] = ChattyCrow.default_headers(options.delete(:channel), options.delete(:token))
|
|
57
57
|
|
|
58
|
+
# Convert payload to JSON
|
|
59
|
+
options[:payload] = options[:payload].to_json
|
|
60
|
+
|
|
58
61
|
# Send request
|
|
59
62
|
RestClient::Request.execute(options) do |response, request, result, &block|
|
|
60
63
|
case response.code
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'rest_client'
|
|
2
|
+
|
|
3
|
+
module ChattyCrow
|
|
4
|
+
# Message status
|
|
5
|
+
# It's bind to /api/message_id call
|
|
6
|
+
class Message
|
|
7
|
+
# Attribute
|
|
8
|
+
attr_accessor :channel, :token, :message_id
|
|
9
|
+
|
|
10
|
+
# Actual states
|
|
11
|
+
attr_accessor :success, :waiting, :error, :last_update, :status
|
|
12
|
+
|
|
13
|
+
# Only message_id is required, in case other options
|
|
14
|
+
# are not different from global configuration
|
|
15
|
+
def initialize(opts = {})
|
|
16
|
+
# Set variables
|
|
17
|
+
@channel = opts.delete(:channel)
|
|
18
|
+
@token = opts.delete(:token)
|
|
19
|
+
@message_id = opts.delete(:message_id)
|
|
20
|
+
|
|
21
|
+
# Refresh
|
|
22
|
+
refresh
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Refresh
|
|
26
|
+
def refresh!
|
|
27
|
+
refresh_data
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def refresh
|
|
31
|
+
refresh_data(true)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def data=(response)
|
|
37
|
+
# Parse body
|
|
38
|
+
body = JSON.parse(response.body)
|
|
39
|
+
@status = body.delete('status')
|
|
40
|
+
@success = body['notifications'].delete('success')
|
|
41
|
+
@waiting = body['notifications'].delete('waiting')
|
|
42
|
+
@error = body['notifications'].delete('error')
|
|
43
|
+
|
|
44
|
+
# Set last update
|
|
45
|
+
@last_update = Time.now
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def call_options
|
|
49
|
+
{
|
|
50
|
+
url: "#{ChattyCrow.configuration.messages_url}/#{@message_id}",
|
|
51
|
+
headers: ChattyCrow.default_headers(@channel, @token),
|
|
52
|
+
method: :get
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def refresh_data(raise_errors = false)
|
|
57
|
+
# Send request
|
|
58
|
+
RestClient::Request.execute(call_options) do |response, request, result, &block|
|
|
59
|
+
begin
|
|
60
|
+
case response.code
|
|
61
|
+
when 200
|
|
62
|
+
self.data = response
|
|
63
|
+
when 301, 302, 307
|
|
64
|
+
response.follow_redirection(request, result, &block)
|
|
65
|
+
when 401
|
|
66
|
+
fail Error::UnauthorizedRequest, response
|
|
67
|
+
when 404
|
|
68
|
+
fail Error::ChannelNotFound, response
|
|
69
|
+
else
|
|
70
|
+
fail Error::InvalidReturn, response
|
|
71
|
+
end
|
|
72
|
+
rescue => e
|
|
73
|
+
if raise_errors
|
|
74
|
+
raise e
|
|
75
|
+
else
|
|
76
|
+
false
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
@@ -23,13 +23,18 @@ module ChattyCrow
|
|
|
23
23
|
# @param raise_errors [Boolean] Raise errors if error?
|
|
24
24
|
# @return [Object] Raise an exception or return Response::Notification
|
|
25
25
|
def self.execute(instance, raise_errors = true)
|
|
26
|
+
# Get options
|
|
26
27
|
options = instance.to_json.merge(url: notification_url, method: :post)
|
|
27
28
|
|
|
29
|
+
# Set options to JSON string
|
|
30
|
+
options[:payload] = options[:payload].to_json
|
|
31
|
+
|
|
32
|
+
# Send
|
|
28
33
|
RestClient::Request.execute(options) do |response, request, result, &block|
|
|
29
34
|
begin
|
|
30
35
|
case response.code
|
|
31
36
|
when 200, 201
|
|
32
|
-
Response::Notification.new response
|
|
37
|
+
Response::Notification.new response, options
|
|
33
38
|
when 301, 302, 307
|
|
34
39
|
response.follow_redirection(request, result, &block)
|
|
35
40
|
when 400
|
data/lib/chatty_crow/request.rb
CHANGED
|
@@ -3,7 +3,10 @@ module ChattyCrow
|
|
|
3
3
|
# Parent of all requests to ChattyCrow API
|
|
4
4
|
class BaseRequest
|
|
5
5
|
# Methods
|
|
6
|
-
attr_accessor :contacts, :payload, :channel, :token
|
|
6
|
+
attr_accessor :contacts, :payload, :channel, :token, :time, :location
|
|
7
|
+
|
|
8
|
+
# Batch request method
|
|
9
|
+
attr_accessor :channel
|
|
7
10
|
|
|
8
11
|
# Intialize options!
|
|
9
12
|
attr_accessor :arguments, :options, :arguments_flatten
|
|
@@ -19,12 +22,32 @@ module ChattyCrow
|
|
|
19
22
|
@options = ChattyCrow.extract_options!(args)
|
|
20
23
|
@arguments = args
|
|
21
24
|
|
|
25
|
+
# Symbolize keys in options for validations
|
|
26
|
+
ChattyCrow.symbolize_keys!(@options)
|
|
27
|
+
|
|
22
28
|
# Create flatten arguments for (skype/android/sms.. requests)
|
|
23
29
|
@arguments_flatten = args.join(', ') if args.any?
|
|
24
30
|
|
|
25
31
|
# Recipients
|
|
26
32
|
@contacts = ChattyCrow.wrap(@options.delete(:contacts)).compact
|
|
27
33
|
|
|
34
|
+
# Time and location - validate!
|
|
35
|
+
if @time = @options.delete(:time)
|
|
36
|
+
{ start: Fixnum, end: Fixnum }.each do |key, klass|
|
|
37
|
+
unless @time[key].is_a?(klass)
|
|
38
|
+
fail ::ArgumentError, "#{key} must be instance of #{klass}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
if @location = @options.delete(:location)
|
|
44
|
+
{ latitude: Float, longitude: Float, range: Fixnum }.each do |key, klass|
|
|
45
|
+
unless @location[key].is_a?(klass)
|
|
46
|
+
fail ::ArgumentError, "#{key} must be instance of #{klass}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
28
51
|
# Channel
|
|
29
52
|
@channel = @options.delete(:channel)
|
|
30
53
|
|
|
@@ -39,14 +62,20 @@ module ChattyCrow
|
|
|
39
62
|
|
|
40
63
|
# Get request for send
|
|
41
64
|
# @return [Hash] Request
|
|
42
|
-
def to_json
|
|
43
|
-
{
|
|
65
|
+
def to_json(channel = false)
|
|
66
|
+
ret = {
|
|
44
67
|
payload: {
|
|
45
68
|
payload: payload,
|
|
46
|
-
contacts: @contacts
|
|
69
|
+
contacts: @contacts,
|
|
70
|
+
time: @time,
|
|
71
|
+
location: @location
|
|
47
72
|
},
|
|
48
73
|
headers: headers
|
|
49
74
|
}
|
|
75
|
+
|
|
76
|
+
ret[:payload][:channel] = @channel if channel
|
|
77
|
+
|
|
78
|
+
ret
|
|
50
79
|
end
|
|
51
80
|
end
|
|
52
81
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ChattyCrow
|
|
2
|
+
module Request
|
|
3
|
+
# HipChat request
|
|
4
|
+
class HipChat < BaseRequest
|
|
5
|
+
def initialize(*args)
|
|
6
|
+
super(*args)
|
|
7
|
+
|
|
8
|
+
# If arguments exists set as body into options!
|
|
9
|
+
# Its for just easy ChattyCrow.send_hipchat 'Hello'
|
|
10
|
+
@options[:body] = @arguments_flatten if @arguments_flatten
|
|
11
|
+
|
|
12
|
+
# Set payload
|
|
13
|
+
@payload = @options
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ChattyCrow
|
|
2
|
+
module Request
|
|
3
|
+
# Slack request
|
|
4
|
+
class Slack < BaseRequest
|
|
5
|
+
def initialize(*args)
|
|
6
|
+
super(*args)
|
|
7
|
+
|
|
8
|
+
# If arguments exists set as body into options!
|
|
9
|
+
# Its for just easy ChattyCrow.send_slack 'Hello'
|
|
10
|
+
@options[:body] = @arguments_flatten if @arguments_flatten
|
|
11
|
+
|
|
12
|
+
# Set payload
|
|
13
|
+
@payload = @options
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/chatty_crow/response.rb
CHANGED
|
@@ -7,22 +7,32 @@ module ChattyCrow
|
|
|
7
7
|
attr_accessor :code, :body, :status, :msg
|
|
8
8
|
|
|
9
9
|
def initialize(response)
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
if response.is_a?(String)
|
|
11
|
+
@code = response.code
|
|
12
|
+
@body = JSON.parse(response.body)
|
|
13
|
+
else
|
|
14
|
+
@code = -1
|
|
15
|
+
@body = response
|
|
16
|
+
end
|
|
17
|
+
|
|
12
18
|
@status = @body.delete('status')
|
|
13
19
|
@msg = @body.delete('msg')
|
|
14
20
|
end
|
|
15
21
|
|
|
22
|
+
def status
|
|
23
|
+
@status.to_s
|
|
24
|
+
end
|
|
25
|
+
|
|
16
26
|
def ok?
|
|
17
|
-
@status.
|
|
27
|
+
@status.downcase.downcase == 'ok'
|
|
18
28
|
end
|
|
19
29
|
|
|
20
30
|
def partial_error?
|
|
21
|
-
@status.
|
|
31
|
+
@status.downcase.downcase == 'perror'
|
|
22
32
|
end
|
|
23
33
|
|
|
24
34
|
def error?
|
|
25
|
-
@status.
|
|
35
|
+
@status.downcase.downcase == 'error'
|
|
26
36
|
end
|
|
27
37
|
end
|
|
28
38
|
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
module ChattyCrow
|
|
2
|
+
module Response
|
|
3
|
+
# Notification response
|
|
4
|
+
class Batch < Base
|
|
5
|
+
# Channels
|
|
6
|
+
attr_accessor :channels
|
|
7
|
+
|
|
8
|
+
# Actual channel & token
|
|
9
|
+
attr_accessor :token
|
|
10
|
+
|
|
11
|
+
# Initialize notification response
|
|
12
|
+
# @param response [RestClient::Response] Response from server
|
|
13
|
+
# @param options [Hash] Headers
|
|
14
|
+
def initialize(response, options)
|
|
15
|
+
super response
|
|
16
|
+
|
|
17
|
+
# Get Token
|
|
18
|
+
@token = options[:headers]['Token']
|
|
19
|
+
|
|
20
|
+
# Create an hash for channels
|
|
21
|
+
@channels ||= {}
|
|
22
|
+
|
|
23
|
+
# Parse channels!
|
|
24
|
+
@body['channels'].each do |channel|
|
|
25
|
+
@channels[channel['channel']] = BatchNotification.new(channel, @token)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def channels
|
|
30
|
+
@channels ||= {}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Batch notification response class
|
|
35
|
+
# Place for refactoring
|
|
36
|
+
class BatchNotification < Base
|
|
37
|
+
# Infos
|
|
38
|
+
attr_accessor :success, :total, :failed_contacts, :message_id
|
|
39
|
+
|
|
40
|
+
# Token & channel
|
|
41
|
+
attr_accessor :token, :channel
|
|
42
|
+
|
|
43
|
+
# Init from response
|
|
44
|
+
def initialize(body, token)
|
|
45
|
+
super(body)
|
|
46
|
+
|
|
47
|
+
# Set token
|
|
48
|
+
@token = token
|
|
49
|
+
|
|
50
|
+
# Parse response
|
|
51
|
+
@channel = @body.delete('channel')
|
|
52
|
+
@success = @body.delete('success')
|
|
53
|
+
@total = @body.delete('total')
|
|
54
|
+
@failed_contacts = @body.delete('contacts')
|
|
55
|
+
@message_id = @body.delete('message_id')
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Get instance of message
|
|
59
|
+
# @return Message [ChattyCrow::Message]
|
|
60
|
+
def message
|
|
61
|
+
@message ||= ::ChattyCrow::Message.new(channel: @channel, token: @token, message_id: @message_id)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
@@ -2,17 +2,32 @@ module ChattyCrow
|
|
|
2
2
|
module Response
|
|
3
3
|
# Notification response
|
|
4
4
|
class Notification < Base
|
|
5
|
-
attr_accessor :success, :total, :failed_contacts
|
|
5
|
+
attr_accessor :success, :total, :failed_contacts, :message_id
|
|
6
|
+
|
|
7
|
+
# Actual channel & token
|
|
8
|
+
attr_accessor :token, :channel
|
|
6
9
|
|
|
7
10
|
# Initialize notification response
|
|
8
11
|
# @param response [RestClient::Response] Response from server
|
|
9
|
-
|
|
12
|
+
# @param options [Hash] Headers
|
|
13
|
+
def initialize(response, options)
|
|
10
14
|
super response
|
|
11
15
|
|
|
12
16
|
# Parse response
|
|
13
17
|
@success = @body.delete('success')
|
|
14
18
|
@total = @body.delete('total')
|
|
15
19
|
@failed_contacts = @body.delete('contacts')
|
|
20
|
+
@message_id = @body.delete('message_id')
|
|
21
|
+
|
|
22
|
+
# Parse headers for message
|
|
23
|
+
@channel = options[:headers]['Channel']
|
|
24
|
+
@token = options[:headers]['Token']
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Get instance of message
|
|
28
|
+
# @return Message [ChattyCrow::Message]
|
|
29
|
+
def message
|
|
30
|
+
@message ||= ::ChattyCrow::Message.new(channel: @channel, token: @token, message_id: @message_id)
|
|
16
31
|
end
|
|
17
32
|
end
|
|
18
33
|
end
|
data/lib/chatty_crow/version.rb
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require File.expand_path '../helper', __FILE__
|
|
2
|
+
|
|
3
|
+
# Unit test for contact methods
|
|
4
|
+
class BaseRequestTest < MiniTest::Should::TestCase
|
|
5
|
+
should 'Raise argument error if location filed has an invalid type' do
|
|
6
|
+
expect { ChattyCrow.send_skype 'Test', location: { latitude: 'invalid string', longitude: 'invalid string', range: 'invalid string' } }.to_raise ArgumentError
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
should 'Raise argument error if some fields in locations missing' do
|
|
10
|
+
expect { ChattyCrow.send_skype 'Test', location: { latitude: 30.2010102, range: 200 } }.to_raise ArgumentError
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
should 'Raise argument error if some fields in time missing' do
|
|
14
|
+
expect { ChattyCrow.send_skype 'Test', time: { start: 4093903 } }.to_raise ArgumentError
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
should 'Raise argument error if some fields in time has an invalid type' do
|
|
18
|
+
expect { ChattyCrow.send_skype 'Test', time: { start: '40.2030', end: 'abcd' } }.to_raise ArgumentError
|
|
19
|
+
end
|
|
20
|
+
end
|
data/test/batch_test.rb
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
require File.expand_path '../helper', __FILE__
|
|
2
|
+
|
|
3
|
+
# Batch test
|
|
4
|
+
class BatchTest < MiniTest::Should::TestCase
|
|
5
|
+
should 'use default token' do
|
|
6
|
+
batch = ChattyCrow.create_batch
|
|
7
|
+
batch.add_ios payload: 'Dear users', channel: 'test#1'
|
|
8
|
+
|
|
9
|
+
# Mock batch
|
|
10
|
+
body = {
|
|
11
|
+
channels: [
|
|
12
|
+
{
|
|
13
|
+
channel: 'channel#2',
|
|
14
|
+
status: 'PERROR',
|
|
15
|
+
msg: '10 of 15 created',
|
|
16
|
+
success: 10,
|
|
17
|
+
total: 15,
|
|
18
|
+
contacts: %w(test1 test2),
|
|
19
|
+
message_id: 1
|
|
20
|
+
},
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
mock_batch status: %(200 Ok), body: body.to_json
|
|
24
|
+
|
|
25
|
+
# Call
|
|
26
|
+
batch.execute!
|
|
27
|
+
|
|
28
|
+
# Compare last token
|
|
29
|
+
expect(last_headers['token']).to_equal ChattyCrow.configuration.token
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
should 'raise error when try to add service without channel' do
|
|
33
|
+
batch = ChattyCrow.create_batch
|
|
34
|
+
expect { batch.add_ios(payload: 'Dear users') }.to_raise ::ArgumentError
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
should 'return valid notification response' do
|
|
38
|
+
FIRST_CHANNEL = 'channel#1'
|
|
39
|
+
|
|
40
|
+
# Mock notification
|
|
41
|
+
body = {
|
|
42
|
+
channels: [
|
|
43
|
+
{
|
|
44
|
+
channel: FIRST_CHANNEL,
|
|
45
|
+
status: 'OK',
|
|
46
|
+
msg: '15 of 15 created',
|
|
47
|
+
success: 15,
|
|
48
|
+
total: 15,
|
|
49
|
+
contacts: [],
|
|
50
|
+
message_id: 1
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
channel: 'channel#2',
|
|
54
|
+
status: 'PERROR',
|
|
55
|
+
msg: '10 of 15 created',
|
|
56
|
+
success: 10,
|
|
57
|
+
total: 15,
|
|
58
|
+
contacts: %w(test1 test2),
|
|
59
|
+
message_id: 1
|
|
60
|
+
},
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
mock_batch status: %(200 Ok), body: body.to_json
|
|
64
|
+
|
|
65
|
+
# Create batch
|
|
66
|
+
batch = ChattyCrow.create_batch
|
|
67
|
+
|
|
68
|
+
# Add some payloads
|
|
69
|
+
batch.add_ios(payload: 'Dear IOS users', channel: FIRST_CHANNEL)
|
|
70
|
+
batch.add_skype(payload: 'Dear SKYPE users', channel: 'channel#2')
|
|
71
|
+
|
|
72
|
+
# Response
|
|
73
|
+
response = batch.execute!
|
|
74
|
+
|
|
75
|
+
# Parse response
|
|
76
|
+
expect(response.channels.count).to_equal 2
|
|
77
|
+
|
|
78
|
+
# Get response for first channel
|
|
79
|
+
channel = response.channels[FIRST_CHANNEL]
|
|
80
|
+
template = body[:channels][0]
|
|
81
|
+
expect(channel).to_be_instance_of ChattyCrow::Response::BatchNotification
|
|
82
|
+
expect(channel.status).to_equal template[:status]
|
|
83
|
+
expect(channel.ok?).to_equal true
|
|
84
|
+
expect(channel.partial_error?).to_equal false
|
|
85
|
+
|
|
86
|
+
# Get message
|
|
87
|
+
message_body = {
|
|
88
|
+
status: :ok,
|
|
89
|
+
notifications: {
|
|
90
|
+
success: 15,
|
|
91
|
+
waiting: 0,
|
|
92
|
+
error: 0
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
mock_message(id: template[:message_id], body: message_body.to_json)
|
|
96
|
+
message = channel.message
|
|
97
|
+
|
|
98
|
+
expect(last_headers['token']).to_equal ChattyCrow.configuration.token
|
|
99
|
+
expect(last_headers['channel']).to_equal FIRST_CHANNEL
|
|
100
|
+
|
|
101
|
+
expect(message.channel).to_equal FIRST_CHANNEL
|
|
102
|
+
expect(message.message_id).to_equal template[:message_id]
|
|
103
|
+
expect(message.token).to_equal ChattyCrow.configuration.token
|
|
104
|
+
expect(message.success).to_equal message_body[:notifications][:success]
|
|
105
|
+
expect(message.waiting).to_equal message_body[:notifications][:waiting]
|
|
106
|
+
expect(message.error).to_equal message_body[:notifications][:error]
|
|
107
|
+
|
|
108
|
+
# Clear mocks
|
|
109
|
+
clear_mock_url
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
data/test/configuration_test.rb
CHANGED
|
@@ -3,9 +3,10 @@ require File.expand_path '../helper', __FILE__
|
|
|
3
3
|
# Test for proper gem configuration
|
|
4
4
|
class ConfigurationTest < MiniTest::Should::TestCase
|
|
5
5
|
should 'provide defaults' do
|
|
6
|
-
assert_config_default :host, 'https://
|
|
7
|
-
assert_config_default :notification_url, 'https://
|
|
8
|
-
assert_config_default :contacts_url, 'https://
|
|
6
|
+
assert_config_default :host, 'https://chattycrow.com/api/v1/'
|
|
7
|
+
assert_config_default :notification_url, 'https://chattycrow.com/api/v1/notification'
|
|
8
|
+
assert_config_default :contacts_url, 'https://chattycrow.com/api/v1/contacts'
|
|
9
|
+
assert_config_default :batch_url, 'https://chattycrow.com/api/v1/batch'
|
|
9
10
|
assert_config_default :token, nil
|
|
10
11
|
assert_config_default :default_channel, nil
|
|
11
12
|
assert_config_default :http_open_timeout, 2
|
|
@@ -19,6 +20,7 @@ class ConfigurationTest < MiniTest::Should::TestCase
|
|
|
19
20
|
assert_equal url, config.host
|
|
20
21
|
assert_equal "#{url}/notification", config.notification_url
|
|
21
22
|
assert_equal "#{url}/contacts", config.contacts_url
|
|
23
|
+
assert_equal "#{url}/batch", config.batch_url
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
should 'use correct url with backslash' do
|
|
@@ -28,6 +30,7 @@ class ConfigurationTest < MiniTest::Should::TestCase
|
|
|
28
30
|
assert_equal url, config.host
|
|
29
31
|
assert_equal "#{url}notification", config.notification_url
|
|
30
32
|
assert_equal "#{url}contacts", config.contacts_url
|
|
33
|
+
assert_equal "#{url}batch", config.batch_url
|
|
31
34
|
end
|
|
32
35
|
|
|
33
36
|
def assert_config_default(option, default_value, config = nil)
|
data/test/helper.rb
CHANGED
|
@@ -35,6 +35,21 @@ module TestHelpers
|
|
|
35
35
|
FakeWeb.register_uri(method, configuration.notification_url, options)
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
# Mock default batch url
|
|
39
|
+
def mock_batch(options)
|
|
40
|
+
method = options.delete(:method) || :post
|
|
41
|
+
options[:status] ||= %w(200 OK)
|
|
42
|
+
|
|
43
|
+
FakeWeb.register_uri(method, configuration.batch_url, options)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Mock messages
|
|
47
|
+
def mock_message(options)
|
|
48
|
+
method = options.delete(:method) || :get
|
|
49
|
+
options[:status] ||= %w(200 OK)
|
|
50
|
+
FakeWeb.register_uri(method, "#{configuration.messages_url}/#{options[:id]}", options)
|
|
51
|
+
end
|
|
52
|
+
|
|
38
53
|
# Mock default URL for contacts
|
|
39
54
|
def mock_contacts(options)
|
|
40
55
|
method = options.delete(:method) || :post
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: chatty_crow
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Netbrick s.r.o.
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2015-01-24 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: multi_json
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1.0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
-
name:
|
|
28
|
+
name: rest-client
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
@@ -184,6 +184,7 @@ files:
|
|
|
184
184
|
- lib/chatty-crow.rb
|
|
185
185
|
- lib/chatty_crow.rb
|
|
186
186
|
- lib/chatty_crow/action_mailer_extension.rb
|
|
187
|
+
- lib/chatty_crow/batch_notification_request.rb
|
|
187
188
|
- lib/chatty_crow/config.rb
|
|
188
189
|
- lib/chatty_crow/contacts_request.rb
|
|
189
190
|
- lib/chatty_crow/error.rb
|
|
@@ -191,16 +192,20 @@ files:
|
|
|
191
192
|
- lib/chatty_crow/error/invalid_attributes.rb
|
|
192
193
|
- lib/chatty_crow/error/invalid_return.rb
|
|
193
194
|
- lib/chatty_crow/error/unauthorized_request.rb
|
|
195
|
+
- lib/chatty_crow/message.rb
|
|
194
196
|
- lib/chatty_crow/notification_request.rb
|
|
195
197
|
- lib/chatty_crow/railtie.rb
|
|
196
198
|
- lib/chatty_crow/request.rb
|
|
197
199
|
- lib/chatty_crow/request/android.rb
|
|
200
|
+
- lib/chatty_crow/request/hipchat.rb
|
|
198
201
|
- lib/chatty_crow/request/ios.rb
|
|
199
202
|
- lib/chatty_crow/request/jabber.rb
|
|
200
203
|
- lib/chatty_crow/request/mail.rb
|
|
201
204
|
- lib/chatty_crow/request/skype.rb
|
|
205
|
+
- lib/chatty_crow/request/slack.rb
|
|
202
206
|
- lib/chatty_crow/request/sms.rb
|
|
203
207
|
- lib/chatty_crow/response.rb
|
|
208
|
+
- lib/chatty_crow/response/batch.rb
|
|
204
209
|
- lib/chatty_crow/response/contacts_add.rb
|
|
205
210
|
- lib/chatty_crow/response/contacts_remove.rb
|
|
206
211
|
- lib/chatty_crow/response/notification.rb
|
|
@@ -209,6 +214,8 @@ files:
|
|
|
209
214
|
- test/android_test.rb
|
|
210
215
|
- test/attachment_test.rb
|
|
211
216
|
- test/base_parser_test.rb
|
|
217
|
+
- test/base_request_test.rb
|
|
218
|
+
- test/batch_test.rb
|
|
212
219
|
- test/configuration_test.rb
|
|
213
220
|
- test/contacts_test.rb
|
|
214
221
|
- test/factories/stewie.jpeg
|
|
@@ -227,7 +234,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
227
234
|
requirements:
|
|
228
235
|
- - ">="
|
|
229
236
|
- !ruby/object:Gem::Version
|
|
230
|
-
version: '
|
|
237
|
+
version: '1.9'
|
|
231
238
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
232
239
|
requirements:
|
|
233
240
|
- - ">="
|
|
@@ -235,7 +242,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
235
242
|
version: '0'
|
|
236
243
|
requirements: []
|
|
237
244
|
rubyforge_project:
|
|
238
|
-
rubygems_version: 2.4.
|
|
245
|
+
rubygems_version: 2.4.3
|
|
239
246
|
signing_key:
|
|
240
247
|
specification_version: 4
|
|
241
248
|
summary: Send your messages to more than 6 comunnication channels.
|
|
@@ -243,9 +250,12 @@ test_files:
|
|
|
243
250
|
- test/android_test.rb
|
|
244
251
|
- test/attachment_test.rb
|
|
245
252
|
- test/base_parser_test.rb
|
|
253
|
+
- test/base_request_test.rb
|
|
254
|
+
- test/batch_test.rb
|
|
246
255
|
- test/configuration_test.rb
|
|
247
256
|
- test/contacts_test.rb
|
|
248
257
|
- test/factories/stewie.jpeg
|
|
249
258
|
- test/helper.rb
|
|
250
259
|
- test/mail_test.rb
|
|
251
260
|
- test/response_test.rb
|
|
261
|
+
has_rdoc:
|