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.
@@ -0,0 +1,50 @@
1
+ require 'PushRadar/version'
2
+ require 'PushRadar/Targeting'
3
+ require 'net/http'
4
+ require 'json'
5
+
6
+ module PushRadar
7
+
8
+ # A client that interacts with PushRadar's API
9
+ class APIClient
10
+
11
+ # Creates a new instance of the PushRadar API client with the specified API secret
12
+ def initialize(api_secret)
13
+
14
+ # Set the API secret
15
+ api_secret.strip!
16
+ @api_secret = api_secret
17
+
18
+ # Set the API endpoint
19
+ @api_endpoint = 'https://api.pushradar.com/v1'
20
+
21
+ end
22
+
23
+ # Performs a POST request to the API destination specified
24
+ def post(destination, data)
25
+
26
+ # Add in the fields that should be sent with each request
27
+ data['api_secret'] = @api_secret
28
+ data['client_platform'] = 'ruby'
29
+ data['request_sent_at'] = Time.now.to_i
30
+
31
+ # Make sure the destination does not contain the base URL or forward slash characters
32
+ destination = destination.gsub('/', '')
33
+ destination.sub! @api_endpoint, ''
34
+
35
+ # Construct the actual URL to POST the data to
36
+ url = @api_endpoint + '/' + destination
37
+
38
+ # Send a POST request to the server
39
+ uri = URI(url)
40
+ req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
41
+ req.body = data.to_json
42
+ Net::HTTP.start(uri.hostname, uri.port) do |http|
43
+ http.request(req)
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,201 @@
1
+ require 'PushRadar/version'
2
+ require 'PushRadar/Utils'
3
+ require 'ipaddr'
4
+
5
+ module PushRadar
6
+
7
+ # Specifies the target audience of a PushRadar notification
8
+ class Targeting
9
+
10
+ # ------------------------------
11
+ # Initialization & configuration
12
+ # ------------------------------
13
+
14
+ # Creates a new notification targeting object
15
+ def initialize
16
+
17
+ # Initialize variables
18
+ @target_user_ids = []
19
+ @target_actions = []
20
+ @target_not_actions = []
21
+ @target_browsers = []
22
+ @target_continents = []
23
+ @target_countries = []
24
+ @target_ips = []
25
+
26
+ end
27
+
28
+ # ------------------------------
29
+ # Browser targeting
30
+ # ------------------------------
31
+
32
+ # Adds a browser to the list of target browsers
33
+ def target_browser(browser)
34
+
35
+ # Trim the browser and convert it to lowercase
36
+ browser.strip!
37
+ browser.downcase
38
+
39
+ # Validate the browser for being one of the supported types
40
+ unless %w(chrome ie edge safari opera firefox).include? browser
41
+ raise "The browser must be one of the following: 'chrome', 'ie', 'edge', 'safari', 'opera', 'firefox'."
42
+ end
43
+
44
+ # Add the browser to the list of target browser
45
+ unless @target_browsers.include? browser
46
+ @target_browsers.push browser
47
+ end
48
+
49
+ end
50
+
51
+ # ------------------------------
52
+ # Country targeting
53
+ # ------------------------------
54
+
55
+ # Adds a country to the list of target countries
56
+ def target_country(country_code)
57
+
58
+ # Trim the country code and convert it to uppercase
59
+ country_code.strip!
60
+ country_code.upcase
61
+
62
+ # Ensure that the country code is not empty
63
+ if country_code == ''
64
+ raise 'The country code provided cannot be empty.'
65
+ end
66
+
67
+ # Validate the country code
68
+ unless Utils.get_countries.keys.include? country_code.to_sym
69
+ raise 'The country code provided must be a valid two-letter (ISO 3166-1 alpha-2) code.'
70
+ end
71
+
72
+ # Add the country to the list
73
+ unless @target_countries.include? country_code
74
+ @target_countries.push country_code
75
+ end
76
+
77
+ end
78
+
79
+ # ------------------------------
80
+ # Continent targeting
81
+ # ------------------------------
82
+
83
+ # Targets a continent by its continent code
84
+ def target_continent(continent_code)
85
+
86
+ # Target the countries located in this continent
87
+ Utils.get_countries_from_continent(continent_code).each {|country|
88
+ target_country country
89
+ }
90
+
91
+ # Add the continent code to the list
92
+ unless @target_continents.include? continent_code
93
+ @target_continents.push continent_code
94
+ end
95
+
96
+ end
97
+
98
+ # ------------------------------
99
+ # IP address targeting
100
+ # ------------------------------
101
+
102
+ # Targets the notification to clients with the given IP address
103
+ def target_ip(ip_address)
104
+
105
+ # Trim the IP address
106
+ ip_address.strip!
107
+
108
+ # Make sure that the IP address is not empty
109
+ if ip_address == ''
110
+ raise 'The IP address provided cannot be empty.'
111
+ end
112
+
113
+ # Check for wildcard IPs
114
+ if ip_address.include? '*'
115
+ raise 'Wildcard IP address targeting is not supported.'
116
+ end
117
+
118
+ # Validate the IP address
119
+ unless Utils.is_valid_ip ip_address
120
+ raise 'The IP address provided must be a valid IPv4 or IPv6 address.'
121
+ end
122
+
123
+ # Add the IP address to the list
124
+ unless @target_ips.include? ip_address
125
+ @target_ips.push ip_address
126
+ end
127
+
128
+ end
129
+
130
+ # ------------------------------
131
+ # Action targeting
132
+ # ------------------------------
133
+
134
+ # Targets the notification to clients who have taken the given action
135
+ def target_action(action_identifier)
136
+
137
+ # Trim the action identifier
138
+ action_identifier.strip!
139
+
140
+ # Make sure the action identifier is not empty
141
+ if action_identifier == ''
142
+ raise 'The action identifier cannot be empty'
143
+ end
144
+
145
+ # Make sure that the action is not in the target "not" actions list
146
+ if @target_not_actions.include? action_identifier
147
+ raise "Action '" + action_identifier + "' is already in the 'not' actions list."
148
+ end
149
+
150
+ # Add the action to the list
151
+ unless @target_actions.include? action_identifier
152
+ @target_actions.push action_identifier
153
+ end
154
+
155
+ end
156
+
157
+ # Targets the notification to clients who have not taken the given action
158
+ def target_not_action(action_identifier)
159
+
160
+ # Trim the action identifier
161
+ action_identifier.strip!
162
+
163
+ # Make sure the action identifier is not empty
164
+ if action_identifier == ''
165
+ raise 'The action identifier cannot be empty'
166
+ end
167
+
168
+ # Make sure that the action is not in the target actions list
169
+ if @target_actions.include? action_identifier
170
+ raise "Action '" + action_identifier + "' is already in the actions list."
171
+ end
172
+
173
+ # Add the action to the list
174
+ unless @target_not_actions.include? action_identifier
175
+ @target_not_actions.push action_identifier
176
+ end
177
+
178
+ end
179
+
180
+ # ------------------------------
181
+ # User targeting
182
+ # ------------------------------
183
+
184
+ # Targets the notification to a specific user (identifier by their user ID)
185
+ def target_user(user_id)
186
+
187
+ # Make sure that the user ID is not empty
188
+ if user_id == nil
189
+ raise 'The user ID cannot be nil.'
190
+ end
191
+
192
+ # Add the user ID to the list
193
+ unless @target_user_ids.include? user_id
194
+ @target_user_ids.push user_id
195
+ end
196
+
197
+ end
198
+
199
+ end
200
+
201
+ end
@@ -0,0 +1,570 @@
1
+ require 'PushRadar/version'
2
+ require 'resolv'
3
+
4
+ module PushRadar
5
+
6
+ # Contains helpful methods that are used throughout the library
7
+ class Utils
8
+
9
+ # ------------------------------
10
+ # Collection utilities
11
+ # ------------------------------
12
+
13
+ # Searches the given dictionary for values matching the value provided, and returns the keys of those elements
14
+ def self.keys_where_value(dictionary, value)
15
+
16
+ # Select the keys
17
+ keys = []
18
+ dictionary.each {|x|
19
+ if dictionary[x] == value
20
+ keys.push value
21
+ end
22
+ }
23
+
24
+ # Return the keys
25
+ keys
26
+
27
+ end
28
+
29
+ # ------------------------------
30
+ # Location utilities
31
+ # ------------------------------
32
+
33
+ # Gets a hash that associates ISO 3166-1 alpha-2 country codes with country names
34
+ def self.get_countries
35
+
36
+ {AD: 'Andorra',
37
+ AE: 'United Arab Emirates',
38
+ AF: 'Afghanistan',
39
+ AG: 'Antigua and Barbuda',
40
+ AI: 'Anguilla',
41
+ AL: 'Albania',
42
+ AM: 'Armenia',
43
+ AO: 'Angola',
44
+ AQ: 'Antarctica',
45
+ AR: 'Argentina',
46
+ AS: 'American Samoa',
47
+ AT: 'Austria',
48
+ AU: 'Australia',
49
+ AW: 'Aruba',
50
+ AX: 'Åland Islands',
51
+ AZ: 'Azerbaijan',
52
+ BA: 'Bosnia and Herzegovina',
53
+ BB: 'Barbados',
54
+ BD: 'Bangladesh',
55
+ BE: 'Belgium',
56
+ BF: 'Burkina Faso',
57
+ BG: 'Bulgaria',
58
+ BH: 'Bahrain',
59
+ BI: 'Burundi',
60
+ BJ: 'Benin',
61
+ BL: 'Saint Barthélemy',
62
+ BM: 'Bermuda',
63
+ BN: 'Brunei Darussalam',
64
+ BO: 'Bolivia, Plurinational State of',
65
+ BQ: 'Bonaire, Sint Eustatius and Saba',
66
+ BR: 'Brazil',
67
+ BS: 'Bahamas',
68
+ BT: 'Bhutan',
69
+ BV: 'Bouvet Island',
70
+ BW: 'Botswana',
71
+ BY: 'Belarus',
72
+ BZ: 'Belize',
73
+ CA: 'Canada',
74
+ CC: 'Cocos (Keeling) Islands',
75
+ CD: 'Congo, the Democratic Republic of the',
76
+ CF: 'Central African Republic',
77
+ CG: 'Congo',
78
+ CH: 'Switzerland',
79
+ CI: 'Côte d\'Ivoire',
80
+ CK: 'Cook Islands',
81
+ CL: 'Chile',
82
+ CM: 'Cameroon',
83
+ CN: 'China',
84
+ CO: 'Colombia',
85
+ CR: 'Costa Rica',
86
+ CU: 'Cuba',
87
+ CV: 'Cabo Verde',
88
+ CW: 'Curaçao',
89
+ CX: 'Christmas Island',
90
+ CY: 'Cyprus',
91
+ CZ: 'Czechia',
92
+ DE: 'Germany',
93
+ DJ: 'Djibouti',
94
+ DK: 'Denmark',
95
+ DM: 'Dominica',
96
+ DO: 'Dominican Republic',
97
+ DZ: 'Algeria',
98
+ EC: 'Ecuador',
99
+ EE: 'Estonia',
100
+ EG: 'Egypt',
101
+ EH: 'Western Sahara',
102
+ ER: 'Eritrea',
103
+ ES: 'Spain',
104
+ ET: 'Ethiopia',
105
+ FI: 'Finland',
106
+ FJ: 'Fiji',
107
+ FK: 'Falkland Islands (Malvinas)',
108
+ FM: 'Micronesia, Federated States of',
109
+ FO: 'Faroe Islands',
110
+ FR: 'France',
111
+ GA: 'Gabon',
112
+ GB: 'United Kingdom of Great Britain and Northern Ireland',
113
+ GD: 'Grenada',
114
+ GE: 'Georgia',
115
+ GF: 'French Guiana',
116
+ GG: 'Guernsey',
117
+ GH: 'Ghana',
118
+ GI: 'Gibraltar',
119
+ GL: 'Greenland',
120
+ GM: 'Gambia',
121
+ GN: 'Guinea',
122
+ GP: 'Guadeloupe',
123
+ GQ: 'Equatorial Guinea',
124
+ GR: 'Greece',
125
+ GS: 'South Georgia and the South Sandwich Islands',
126
+ GT: 'Guatemala',
127
+ GU: 'Guam',
128
+ GW: 'Guinea-Bissau',
129
+ GY: 'Guyana',
130
+ HK: 'Hong Kong',
131
+ HM: 'Heard Island and McDonald Islands',
132
+ HN: 'Honduras',
133
+ HR: 'Croatia',
134
+ HT: 'Haiti',
135
+ HU: 'Hungary',
136
+ ID: 'Indonesia',
137
+ IE: 'Ireland',
138
+ IL: 'Israel',
139
+ IM: 'Isle of Man',
140
+ IN: 'India',
141
+ IO: 'British Indian Ocean Territory',
142
+ IQ: 'Iraq',
143
+ IR: 'Iran, Islamic Republic of',
144
+ IS: 'Iceland',
145
+ IT: 'Italy',
146
+ JE: 'Jersey',
147
+ JM: 'Jamaica',
148
+ JO: 'Jordan',
149
+ JP: 'Japan',
150
+ KE: 'Kenya',
151
+ KG: 'Kyrgyzstan',
152
+ KH: 'Cambodia',
153
+ KI: 'Kiribati',
154
+ KM: 'Comoros',
155
+ KN: 'Saint Kitts and Nevis',
156
+ KP: 'Korea, Democratic People\'s Republic of',
157
+ KR: 'Korea, Republic of',
158
+ KW: 'Kuwait',
159
+ KY: 'Cayman Islands',
160
+ KZ: 'Kazakhstan',
161
+ LA: 'Lao People\'s Democratic Republic',
162
+ LB: 'Lebanon',
163
+ LC: 'Saint Lucia',
164
+ LI: 'Liechtenstein',
165
+ LK: 'Sri Lanka',
166
+ LR: 'Liberia',
167
+ LS: 'Lesotho',
168
+ LT: 'Lithuania',
169
+ LU: 'Luxembourg',
170
+ LV: 'Latvia',
171
+ LY: 'Libya',
172
+ MA: 'Morocco',
173
+ MC: 'Monaco',
174
+ MD: 'Moldova, Republic of',
175
+ ME: 'Montenegro',
176
+ MF: 'Saint Martin (French part)',
177
+ MG: 'Madagascar',
178
+ MH: 'Marshall Islands',
179
+ MK: 'Macedonia, the former Yugoslav Republic of',
180
+ ML: 'Mali',
181
+ MM: 'Myanmar',
182
+ MN: 'Mongolia',
183
+ MO: 'Macao',
184
+ MP: 'Northern Mariana Islands',
185
+ MQ: 'Martinique',
186
+ MR: 'Mauritania',
187
+ MS: 'Montserrat',
188
+ MT: 'Malta',
189
+ MU: 'Mauritius',
190
+ MV: 'Maldives',
191
+ MW: 'Malawi',
192
+ MX: 'Mexico',
193
+ MY: 'Malaysia',
194
+ MZ: 'Mozambique',
195
+ NA: 'Namibia',
196
+ NC: 'New Caledonia',
197
+ NE: 'Niger',
198
+ NF: 'Norfolk Island',
199
+ NG: 'Nigeria',
200
+ NI: 'Nicaragua',
201
+ NL: 'Netherlands',
202
+ NO: 'Norway',
203
+ NP: 'Nepal',
204
+ NR: 'Nauru',
205
+ NU: 'Niue',
206
+ NZ: 'New Zealand',
207
+ OM: 'Oman',
208
+ PA: 'Panama',
209
+ PE: 'Peru',
210
+ PF: 'French Polynesia',
211
+ PG: 'Papua New Guinea',
212
+ PH: 'Philippines',
213
+ PK: 'Pakistan',
214
+ PL: 'Poland',
215
+ PM: 'Saint Pierre and Miquelon',
216
+ PN: 'Pitcairn',
217
+ PR: 'Puerto Rico',
218
+ PS: 'Palestine, State of',
219
+ PT: 'Portugal',
220
+ PW: 'Palau',
221
+ PY: 'Paraguay',
222
+ QA: 'Qatar',
223
+ RE: 'Réunion',
224
+ RO: 'Romania',
225
+ RS: 'Serbia',
226
+ RU: 'Russian Federation',
227
+ RW: 'Rwanda',
228
+ SA: 'Saudi Arabia',
229
+ SB: 'Solomon Islands',
230
+ SC: 'Seychelles',
231
+ SD: 'Sudan',
232
+ SE: 'Sweden',
233
+ SG: 'Singapore',
234
+ SH: 'Saint Helena, Ascension and Tristan da Cunha',
235
+ SI: 'Slovenia',
236
+ SJ: 'Svalbard and Jan Mayen',
237
+ SK: 'Slovakia',
238
+ SL: 'Sierra Leone',
239
+ SM: 'San Marino',
240
+ SN: 'Senegal',
241
+ SO: 'Somalia',
242
+ SR: 'Suriname',
243
+ SS: 'South Sudan',
244
+ ST: 'Sao Tome and Principe',
245
+ SV: 'El Salvador',
246
+ SX: 'Sint Maarten (Dutch part)',
247
+ SY: 'Syrian Arab Republic',
248
+ SZ: 'Swaziland',
249
+ TC: 'Turks and Caicos Islands',
250
+ TD: 'Chad',
251
+ TF: 'French Southern Territories',
252
+ TG: 'Togo',
253
+ TH: 'Thailand',
254
+ TJ: 'Tajikistan',
255
+ TK: 'Tokelau',
256
+ TL: 'Timor-Leste',
257
+ TM: 'Turkmenistan',
258
+ TN: 'Tunisia',
259
+ TO: 'Tonga',
260
+ TR: 'Turkey',
261
+ TT: 'Trinidad and Tobago',
262
+ TV: 'Tuvalu',
263
+ TW: 'Taiwan, Province of China',
264
+ TZ: 'Tanzania, United Republic of',
265
+ UA: 'Ukraine',
266
+ UG: 'Uganda',
267
+ UM: 'United States Minor Outlying Islands',
268
+ US: 'United States of America',
269
+ UY: 'Uruguay',
270
+ UZ: 'Uzbekistan',
271
+ VA: 'Holy See',
272
+ VC: 'Saint Vincent and the Grenadines',
273
+ VE: 'Venezuela, Bolivarian Republic of',
274
+ VG: 'Virgin Islands, British',
275
+ VI: 'Virgin Islands, U.S.',
276
+ VN: 'Viet Nam',
277
+ VU: 'Vanuatu',
278
+ WF: 'Wallis and Futuna',
279
+ WS: 'Samoa',
280
+ YE: 'Yemen',
281
+ YT: 'Mayotte',
282
+ ZA: 'South Africa',
283
+ ZM: 'Zambia',
284
+ ZW: 'Zimbabwe'}
285
+
286
+ end
287
+
288
+ # Gets a hash that associates ISO 3166-1 alpha-2 country codes with two-letter continent codes
289
+ def self.get_country_continent_hash
290
+
291
+ # Return the hash
292
+ {AD: 'EU',
293
+ AE: 'AS',
294
+ AF: 'AS',
295
+ AG: 'NA',
296
+ AI: 'NA',
297
+ AL: 'EU',
298
+ AM: 'AS',
299
+ AO: 'AF',
300
+ AQ: 'AN',
301
+ AR: 'SA',
302
+ AS: 'OC',
303
+ AT: 'EU',
304
+ AU: 'OC',
305
+ AW: 'NA',
306
+ AX: 'EU',
307
+ AZ: 'AS',
308
+ BA: 'EU',
309
+ BB: 'NA',
310
+ BD: 'AS',
311
+ BE: 'EU',
312
+ BF: 'AF',
313
+ BG: 'EU',
314
+ BH: 'AS',
315
+ BI: 'AF',
316
+ BJ: 'AF',
317
+ BL: 'NA',
318
+ BM: 'NA',
319
+ BN: 'AS',
320
+ BO: 'SA',
321
+ BR: 'SA',
322
+ BS: 'NA',
323
+ BT: 'AS',
324
+ BV: 'AN',
325
+ BW: 'AF',
326
+ BY: 'EU',
327
+ BZ: 'NA',
328
+ CA: 'NA',
329
+ CC: 'AS',
330
+ CD: 'AF',
331
+ CF: 'AF',
332
+ CG: 'AF',
333
+ CH: 'EU',
334
+ CI: 'AF',
335
+ CK: 'OC',
336
+ CL: 'SA',
337
+ CM: 'AF',
338
+ CN: 'AS',
339
+ CO: 'SA',
340
+ CR: 'NA',
341
+ CU: 'NA',
342
+ CV: 'AF',
343
+ CX: 'AS',
344
+ CY: 'AS',
345
+ CZ: 'EU',
346
+ DE: 'EU',
347
+ DJ: 'AF',
348
+ DK: 'EU',
349
+ DM: 'NA',
350
+ DO: 'NA',
351
+ DZ: 'AF',
352
+ EC: 'SA',
353
+ EE: 'EU',
354
+ EG: 'AF',
355
+ EH: 'AF',
356
+ ER: 'AF',
357
+ ES: 'EU',
358
+ ET: 'AF',
359
+ FI: 'EU',
360
+ FJ: 'OC',
361
+ FK: 'SA',
362
+ FM: 'OC',
363
+ FO: 'EU',
364
+ FR: 'EU',
365
+ GA: 'AF',
366
+ GB: 'EU',
367
+ GD: 'NA',
368
+ GE: 'AS',
369
+ GF: 'SA',
370
+ GG: 'EU',
371
+ GH: 'AF',
372
+ GI: 'EU',
373
+ GL: 'NA',
374
+ GM: 'AF',
375
+ GN: 'AF',
376
+ GP: 'NA',
377
+ GQ: 'AF',
378
+ GR: 'EU',
379
+ GS: 'AN',
380
+ GT: 'NA',
381
+ GU: 'OC',
382
+ GW: 'AF',
383
+ GY: 'SA',
384
+ HK: 'AS',
385
+ HM: 'AN',
386
+ HN: 'NA',
387
+ HR: 'EU',
388
+ HT: 'NA',
389
+ HU: 'EU',
390
+ ID: 'AS',
391
+ IE: 'EU',
392
+ IL: 'AS',
393
+ IM: 'EU',
394
+ IN: 'AS',
395
+ IO: 'AS',
396
+ IQ: 'AS',
397
+ IR: 'AS',
398
+ IS: 'EU',
399
+ IT: 'EU',
400
+ JE: 'EU',
401
+ JM: 'NA',
402
+ JO: 'AS',
403
+ JP: 'AS',
404
+ KE: 'AF',
405
+ KG: 'AS',
406
+ KH: 'AS',
407
+ KI: 'OC',
408
+ KM: 'AF',
409
+ KN: 'NA',
410
+ KP: 'AS',
411
+ KR: 'AS',
412
+ KW: 'AS',
413
+ KY: 'NA',
414
+ KZ: 'AS',
415
+ LA: 'AS',
416
+ LB: 'AS',
417
+ LC: 'NA',
418
+ LI: 'EU',
419
+ LK: 'AS',
420
+ LR: 'AF',
421
+ LS: 'AF',
422
+ LT: 'EU',
423
+ LU: 'EU',
424
+ LV: 'EU',
425
+ LY: 'AF',
426
+ MA: 'AF',
427
+ MC: 'EU',
428
+ MD: 'EU',
429
+ ME: 'EU',
430
+ MF: 'NA',
431
+ MG: 'AF',
432
+ MH: 'OC',
433
+ MK: 'EU',
434
+ ML: 'AF',
435
+ MM: 'AS',
436
+ MN: 'AS',
437
+ MO: 'AS',
438
+ MP: 'OC',
439
+ MQ: 'NA',
440
+ MR: 'AF',
441
+ MS: 'NA',
442
+ MT: 'EU',
443
+ MU: 'AF',
444
+ MV: 'AS',
445
+ MW: 'AF',
446
+ MX: 'NA',
447
+ MY: 'AS',
448
+ MZ: 'AF',
449
+ NA: 'AF',
450
+ NC: 'OC',
451
+ NE: 'AF',
452
+ NF: 'OC',
453
+ NG: 'AF',
454
+ NI: 'NA',
455
+ NL: 'EU',
456
+ NO: 'EU',
457
+ NP: 'AS',
458
+ NR: 'OC',
459
+ NU: 'OC',
460
+ NZ: 'OC',
461
+ OM: 'AS',
462
+ PA: 'NA',
463
+ PE: 'SA',
464
+ PF: 'OC',
465
+ PG: 'OC',
466
+ PH: 'AS',
467
+ PK: 'AS',
468
+ PL: 'EU',
469
+ PM: 'NA',
470
+ PN: 'OC',
471
+ PR: 'NA',
472
+ PS: 'AS',
473
+ PT: 'EU',
474
+ PW: 'OC',
475
+ PY: 'SA',
476
+ QA: 'AS',
477
+ RE: 'AF',
478
+ RO: 'EU',
479
+ RS: 'EU',
480
+ RU: 'EU',
481
+ RW: 'AF',
482
+ SA: 'AS',
483
+ SB: 'OC',
484
+ SC: 'AF',
485
+ SD: 'AF',
486
+ SE: 'EU',
487
+ SG: 'AS',
488
+ SH: 'AF',
489
+ SI: 'EU',
490
+ SJ: 'EU',
491
+ SK: 'EU',
492
+ SL: 'AF',
493
+ SM: 'EU',
494
+ SN: 'AF',
495
+ SO: 'AF',
496
+ SR: 'SA',
497
+ ST: 'AF',
498
+ SV: 'NA',
499
+ SY: 'AS',
500
+ SZ: 'AF',
501
+ TC: 'NA',
502
+ TD: 'AF',
503
+ TF: 'AN',
504
+ TG: 'AF',
505
+ TH: 'AS',
506
+ TJ: 'AS',
507
+ TK: 'OC',
508
+ TL: 'AS',
509
+ TM: 'AS',
510
+ TN: 'AF',
511
+ TO: 'OC',
512
+ TR: 'EU',
513
+ TT: 'NA',
514
+ TV: 'OC',
515
+ TW: 'AS',
516
+ TZ: 'AF',
517
+ UA: 'EU',
518
+ UG: 'AF',
519
+ UM: 'OC',
520
+ US: 'NA',
521
+ UY: 'SA',
522
+ UZ: 'AS',
523
+ VA: 'EU',
524
+ VC: 'NA',
525
+ VE: 'SA',
526
+ VG: 'NA',
527
+ VI: 'NA',
528
+ VN: 'AS',
529
+ VU: 'OC',
530
+ WF: 'OC',
531
+ WS: 'OC',
532
+ YE: 'AS',
533
+ YT: 'AF',
534
+ ZA: 'AF',
535
+ ZM: 'AF',
536
+ ZW: 'AF'}
537
+
538
+ end
539
+
540
+ # Gets a list of ISO 3166-1 alpha-2 country codes, corresponding to countries located within the given continent
541
+ def self.get_countries_from_continent(continent_code)
542
+
543
+ # Convert the continent code to uppercase
544
+ continent_code.strip!
545
+ continent_code.upcase
546
+
547
+ # Get the country codes where the value equals the continent code
548
+ keys_where_value(get_country_continent_hash, continent_code)
549
+
550
+ end
551
+
552
+ # ------------------------------
553
+ # IP address utilities
554
+ # ------------------------------
555
+
556
+ # Checks whether the given IP address is valid
557
+ def self.is_valid_ip(addr)
558
+ case addr
559
+ when Resolv::IPv4::Regex
560
+ return true
561
+ when Resolv::IPv6::Regex
562
+ return true
563
+ else
564
+ return false
565
+ end
566
+ end
567
+
568
+ end
569
+
570
+ end