pushradar 0.9.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 +7 -0
- data/.gitignore +9 -0
- data/.idea/PushRadarRuby.iml +14 -0
- data/.idea/inspectionProfiles/Project_Default.xml +6 -0
- data/.idea/misc.xml +4 -0
- data/.idea/modules.xml +8 -0
- data/.idea/vcs.xml +6 -0
- data/.idea/workspace.xml +714 -0
- data/Gemfile +5 -0
- data/LICENSE +21 -0
- data/PushRadar.gemspec +25 -0
- data/README.in_progress.md +23 -0
- data/Rakefile +1 -0
- data/bin/console +6 -0
- data/bin/setup +6 -0
- data/lib/PushRadar.rb +386 -0
- data/lib/PushRadar/APIClient.rb +50 -0
- data/lib/PushRadar/Targeting.rb +201 -0
- data/lib/PushRadar/Utils.rb +570 -0
- data/lib/PushRadar/version.rb +3 -0
- metadata +91 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017. PushRadar
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/PushRadar.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'PushRadar/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'pushradar'
|
8
|
+
spec.version = PushRadar::VERSION
|
9
|
+
spec.authors = ['PushRadar']
|
10
|
+
spec.email = ['contact@pushradar.com']
|
11
|
+
|
12
|
+
spec.summary = %q{PushRadar's official Ruby library, wrapping the PushRadar API.}
|
13
|
+
spec.homepage = 'https://github.com/pushradar/pushradar-ruby'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = 'exe'
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.15'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# PushRadarRuby
|
2
|
+
|
3
|
+
TODO: Describe the gem
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'pushradar'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install pushradar
|
20
|
+
|
21
|
+
## Other Sections
|
22
|
+
|
23
|
+
TODO: Write the other sections
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/console
ADDED
data/bin/setup
ADDED
data/lib/PushRadar.rb
ADDED
@@ -0,0 +1,386 @@
|
|
1
|
+
require 'PushRadar/version'
|
2
|
+
require 'PushRadar/Targeting'
|
3
|
+
require 'PushRadar/APIClient'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module PushRadar
|
7
|
+
|
8
|
+
# A realtime push notifications API service for the web, featuring advanced targeting
|
9
|
+
class Radar
|
10
|
+
|
11
|
+
# ------------------------------
|
12
|
+
# Initialisation & configuration
|
13
|
+
# ------------------------------
|
14
|
+
|
15
|
+
# Creates a new instance of PushRadar with the specified API secret
|
16
|
+
def initialize(api_secret)
|
17
|
+
|
18
|
+
# Initialize data
|
19
|
+
@data = {}
|
20
|
+
|
21
|
+
# Reset the targeting options
|
22
|
+
reset_targeting
|
23
|
+
|
24
|
+
# Check that the API secret is a string
|
25
|
+
unless api_secret.is_a?(String)
|
26
|
+
raise 'The API secret must be a string value.'
|
27
|
+
end
|
28
|
+
|
29
|
+
# Trim the API secret
|
30
|
+
api_secret.strip!
|
31
|
+
|
32
|
+
# If we are running unit tests, set the unit test mode flag and skip the PushRadar API client initialisation
|
33
|
+
@is_unit_test_mode = (api_secret == 'test-secret')
|
34
|
+
|
35
|
+
# Check that the API secret starts with sk_
|
36
|
+
unless api_secret.start_with?('sk_')
|
37
|
+
raise 'API secret invalid. You can view your PushRadar API secret at https://dashboard.pushradar.com/api'
|
38
|
+
end
|
39
|
+
|
40
|
+
# Make a new instance of a PushRadar API client with the specified API secret
|
41
|
+
@api_client = APIClient.new(api_secret)
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# ------------------------------
|
46
|
+
# Browser targeting
|
47
|
+
# ------------------------------
|
48
|
+
|
49
|
+
# Targets the notification to clients currently using the given browser
|
50
|
+
def target_browser(browser)
|
51
|
+
|
52
|
+
# Add the browser to the list of target browsers
|
53
|
+
@targeting.target_browser browser
|
54
|
+
|
55
|
+
# Allow method chaining
|
56
|
+
self
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
# Targets the notification to clients currently using any of the given browsers
|
61
|
+
def target_browsers(*browsers)
|
62
|
+
|
63
|
+
# Target each browser
|
64
|
+
browsers.each {|x|
|
65
|
+
target_browser x
|
66
|
+
}
|
67
|
+
|
68
|
+
# Allow method chaining
|
69
|
+
self
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
# ------------------------------
|
74
|
+
# Country targeting
|
75
|
+
# ------------------------------
|
76
|
+
|
77
|
+
# Targets the notification to clients currently located in the given country
|
78
|
+
def target_country(country_code)
|
79
|
+
|
80
|
+
# Add the country to the list of target countries
|
81
|
+
@targeting.target_country country_code
|
82
|
+
|
83
|
+
# Allow method chaining
|
84
|
+
self
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
# Targets the notification to clients currently located in any of the given countries
|
89
|
+
def target_countries(*country_codes)
|
90
|
+
|
91
|
+
# Target each country
|
92
|
+
country_codes.each {|x|
|
93
|
+
target_country x
|
94
|
+
}
|
95
|
+
|
96
|
+
# Allow method chaining
|
97
|
+
self
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# ------------------------------
|
102
|
+
# Continent targeting
|
103
|
+
# ------------------------------
|
104
|
+
|
105
|
+
# Targets the notification to clients currently located in Asia
|
106
|
+
def target_asia
|
107
|
+
|
108
|
+
# Target the continent
|
109
|
+
@targeting.target_continent('AS')
|
110
|
+
|
111
|
+
# Allow method chaining
|
112
|
+
self
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
# Targets the notification to clients currently located in Africa
|
117
|
+
def target_africa
|
118
|
+
|
119
|
+
# Target the continent
|
120
|
+
@targeting.target_continent('AF')
|
121
|
+
|
122
|
+
# Allow method chaining
|
123
|
+
self
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
# Targets the notification to clients currently located in Antarctica
|
128
|
+
def target_antarctica
|
129
|
+
|
130
|
+
# Target the continent
|
131
|
+
@targeting.target_continent('AN')
|
132
|
+
|
133
|
+
# Allow method chaining
|
134
|
+
self
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
# Targets the notification to clients currently located in Europe
|
139
|
+
def target_europe
|
140
|
+
|
141
|
+
# Target the continent
|
142
|
+
@targeting.target_continent('EU')
|
143
|
+
|
144
|
+
# Allow method chaining
|
145
|
+
self
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
# Targets the notification to clients currently located in North America
|
150
|
+
def target_north_america
|
151
|
+
|
152
|
+
# Target the continent
|
153
|
+
@targeting.target_continent('NA')
|
154
|
+
|
155
|
+
# Allow method chaining
|
156
|
+
self
|
157
|
+
|
158
|
+
end
|
159
|
+
|
160
|
+
# Targets the notification to clients currently located in South America
|
161
|
+
def target_south_america
|
162
|
+
|
163
|
+
# Target the continent
|
164
|
+
@targeting.target_continent('SA')
|
165
|
+
|
166
|
+
# Allow method chaining
|
167
|
+
self
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
# Targets the notification to clients currently located in Oceania
|
172
|
+
def target_oceania
|
173
|
+
|
174
|
+
# Target the continent
|
175
|
+
@targeting.target_continent('OC')
|
176
|
+
|
177
|
+
# Allow method chaining
|
178
|
+
self
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
# ------------------------------
|
183
|
+
# IP address targeting
|
184
|
+
# ------------------------------
|
185
|
+
|
186
|
+
# Targets the notification to clients with the given IP address
|
187
|
+
def target_ip(ip_address)
|
188
|
+
|
189
|
+
# Add the IP address to the list of target IP addresses
|
190
|
+
@targeting.target_ip ip_address
|
191
|
+
|
192
|
+
# Allow method chaining
|
193
|
+
self
|
194
|
+
|
195
|
+
end
|
196
|
+
|
197
|
+
# Targets the notification to clients with any of the given IP addresses
|
198
|
+
def target_ips(*ip_addresses)
|
199
|
+
|
200
|
+
# Target each IP address
|
201
|
+
ip_addresses.each {|x|
|
202
|
+
target_ip x
|
203
|
+
}
|
204
|
+
|
205
|
+
# Allow method chaining
|
206
|
+
self
|
207
|
+
|
208
|
+
end
|
209
|
+
|
210
|
+
# ------------------------------
|
211
|
+
# Action targeting
|
212
|
+
# ------------------------------
|
213
|
+
|
214
|
+
# Targets the notification to clients who have taken the given action
|
215
|
+
def target_action(action_identifier)
|
216
|
+
|
217
|
+
# Add the action to the list of target actions
|
218
|
+
@targeting.target_action action_identifier
|
219
|
+
|
220
|
+
# Allow method chaining
|
221
|
+
self
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
# Targets the notification to clients who have taken any of the given actions
|
226
|
+
def target_actions(*action_identifiers)
|
227
|
+
|
228
|
+
# Target each action
|
229
|
+
action_identifiers.each {|x|
|
230
|
+
target_action x
|
231
|
+
}
|
232
|
+
|
233
|
+
# Allow method chaining
|
234
|
+
self
|
235
|
+
|
236
|
+
end
|
237
|
+
|
238
|
+
# Targets the notification to clients who have not taken the given action
|
239
|
+
def target_not_action(action_identifier)
|
240
|
+
|
241
|
+
# Add the action to the list of target "not" actions
|
242
|
+
@targeting.target_not_action action_identifier
|
243
|
+
|
244
|
+
# Allow method chaining
|
245
|
+
self
|
246
|
+
|
247
|
+
end
|
248
|
+
|
249
|
+
# Targets the notification to clients who have not taken any of the given actions
|
250
|
+
def target_not_actions(*action_identifiers)
|
251
|
+
|
252
|
+
# Target each action
|
253
|
+
action_identifiers.each {|x|
|
254
|
+
target_not_action x
|
255
|
+
}
|
256
|
+
|
257
|
+
# Allow method chaining
|
258
|
+
self
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
# ------------------------------
|
263
|
+
# User targeting
|
264
|
+
# ------------------------------
|
265
|
+
|
266
|
+
# Targets the notification to a specific user (identifier by their user ID)
|
267
|
+
def target_user(user_id)
|
268
|
+
|
269
|
+
# Target the user
|
270
|
+
@targeting.target_user user_id
|
271
|
+
|
272
|
+
# Allow method chaining
|
273
|
+
self
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
# Targets the notification to specific users (identifier by their user IDs)
|
278
|
+
def target_users(user_ids)
|
279
|
+
|
280
|
+
# Target the user IDs
|
281
|
+
user_ids.each {|x|
|
282
|
+
target_user x
|
283
|
+
}
|
284
|
+
|
285
|
+
# Allow method chaining
|
286
|
+
self
|
287
|
+
|
288
|
+
end
|
289
|
+
|
290
|
+
# ------------------------------
|
291
|
+
# Adding data
|
292
|
+
# ------------------------------
|
293
|
+
|
294
|
+
# Adds a data item to the list of data items
|
295
|
+
def add_data_item(key, value)
|
296
|
+
|
297
|
+
# Make sure the key is not empty
|
298
|
+
if key == ''
|
299
|
+
raise 'The key provided cannot be empty.'
|
300
|
+
end
|
301
|
+
|
302
|
+
# Add the data item
|
303
|
+
unless @data.keys.include?(key)
|
304
|
+
@data[key] = value
|
305
|
+
end
|
306
|
+
|
307
|
+
# Allow method chaining
|
308
|
+
self
|
309
|
+
|
310
|
+
end
|
311
|
+
|
312
|
+
# Adds multiple data items to the list of data items
|
313
|
+
def add_data_items(data = {})
|
314
|
+
|
315
|
+
# Add the data items
|
316
|
+
data.keys.each {|x|
|
317
|
+
add_data_item x, data[x]
|
318
|
+
}
|
319
|
+
|
320
|
+
# Allow method chaining
|
321
|
+
self
|
322
|
+
|
323
|
+
end
|
324
|
+
|
325
|
+
# ------------------------------
|
326
|
+
# Broadcast method
|
327
|
+
# ------------------------------
|
328
|
+
|
329
|
+
# Broadcasts data on the channel specified
|
330
|
+
def broadcast(channel, data = {})
|
331
|
+
|
332
|
+
# If we are running unit tests, throw an exception
|
333
|
+
if @is_unit_test_mode
|
334
|
+
raise 'Unit testing of the broadcast() method is not supported.'
|
335
|
+
end
|
336
|
+
|
337
|
+
# Trim the channel name
|
338
|
+
channel.strip!
|
339
|
+
|
340
|
+
# Check whether data has been provided
|
341
|
+
if data.length == 0 && @data.length == 0
|
342
|
+
raise 'There is no data to broadcast.'
|
343
|
+
end
|
344
|
+
|
345
|
+
# Check whether the channel name contains spaces
|
346
|
+
if channel.include? ' '
|
347
|
+
raise "The channel name cannot contain spaces. By convention, channel names are alphanumerical and lowercase, with optional dashes (e.g. 'test-channel')."
|
348
|
+
end
|
349
|
+
|
350
|
+
# Use the stored data if the data parameter is empty
|
351
|
+
if data.length == 0
|
352
|
+
data = @data
|
353
|
+
end
|
354
|
+
|
355
|
+
# Initialize the hash of data to send to the server
|
356
|
+
data_to_send = {
|
357
|
+
channel: channel,
|
358
|
+
notification: data.to_json,
|
359
|
+
target_user_ids: @targeting.instance_variable_get('@target_user_ids').to_json,
|
360
|
+
target_actions: @targeting.instance_variable_get('@target_actions').to_json,
|
361
|
+
target_not_actions: @targeting.instance_variable_get('@target_not_actions').to_json,
|
362
|
+
target_continents: @targeting.instance_variable_get('@target_continents').to_json,
|
363
|
+
target_countries: @targeting.instance_variable_get('@target_countries').to_json,
|
364
|
+
target_ips: @targeting.instance_variable_get('@target_ips').to_json,
|
365
|
+
target_browsers: @targeting.instance_variable_get('@target_browsers').to_json
|
366
|
+
}
|
367
|
+
|
368
|
+
# Broadcast the notification
|
369
|
+
@api_client.post('/broadcast', data_to_send)
|
370
|
+
|
371
|
+
# Reset the targeting options
|
372
|
+
reset_targeting
|
373
|
+
|
374
|
+
end
|
375
|
+
|
376
|
+
# Resets the targeting options
|
377
|
+
def reset_targeting
|
378
|
+
@targeting = Targeting.new
|
379
|
+
end
|
380
|
+
|
381
|
+
# Set which methods are private
|
382
|
+
private :reset_targeting
|
383
|
+
|
384
|
+
end
|
385
|
+
|
386
|
+
end
|