ones-ruby-msm 0.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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +42 -0
  3. data/.editorconfig +14 -0
  4. data/.gitignore +17 -0
  5. data/.rspec +3 -0
  6. data/.rubocop.yml +182 -0
  7. data/CODEOWNERS +1 -0
  8. data/CODE_OF_CONDUCT.md +74 -0
  9. data/Gemfile +14 -0
  10. data/Gemfile.lock +87 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +226 -0
  13. data/Rakefile +8 -0
  14. data/bin/console +15 -0
  15. data/bin/setup +8 -0
  16. data/fixtures/vcr_cassettes/os-csv-export.yml +135 -0
  17. data/fixtures/vcr_cassettes/os-fetch-noti.yml +76 -0
  18. data/fixtures/vcr_cassettes/os-fetch-notifications.yml +237 -0
  19. data/fixtures/vcr_cassettes/os-fetch-player.yml +72 -0
  20. data/fixtures/vcr_cassettes/os-fetch-players.yml +72 -0
  21. data/fixtures/vcr_cassettes/os-send-noti.yml +145 -0
  22. data/lib/onesignal.rb +85 -0
  23. data/lib/onesignal/attachments.rb +27 -0
  24. data/lib/onesignal/auto_map.rb +13 -0
  25. data/lib/onesignal/autoloader.rb +7 -0
  26. data/lib/onesignal/buttons.rb +17 -0
  27. data/lib/onesignal/client.rb +87 -0
  28. data/lib/onesignal/commands.rb +7 -0
  29. data/lib/onesignal/commands/autoloader.rb +7 -0
  30. data/lib/onesignal/commands/base_command.rb +23 -0
  31. data/lib/onesignal/commands/create_notification.rb +15 -0
  32. data/lib/onesignal/commands/csv_export.rb +15 -0
  33. data/lib/onesignal/commands/fetch_notification.rb +15 -0
  34. data/lib/onesignal/commands/fetch_notifications.rb +17 -0
  35. data/lib/onesignal/commands/fetch_player.rb +15 -0
  36. data/lib/onesignal/commands/fetch_players.rb +11 -0
  37. data/lib/onesignal/configuration.rb +19 -0
  38. data/lib/onesignal/filter.rb +140 -0
  39. data/lib/onesignal/included_targets.rb +47 -0
  40. data/lib/onesignal/notification.rb +39 -0
  41. data/lib/onesignal/notification/contents.rb +17 -0
  42. data/lib/onesignal/notification/headings.rb +17 -0
  43. data/lib/onesignal/responses.rb +7 -0
  44. data/lib/onesignal/responses/autoloader.rb +7 -0
  45. data/lib/onesignal/responses/base_response.rb +18 -0
  46. data/lib/onesignal/responses/csv_export.rb +18 -0
  47. data/lib/onesignal/responses/notification.rb +45 -0
  48. data/lib/onesignal/responses/player.rb +21 -0
  49. data/lib/onesignal/segment.rb +23 -0
  50. data/lib/onesignal/sounds.rb +39 -0
  51. data/lib/onesignal/version.rb +6 -0
  52. data/onesignal-ruby.gemspec +48 -0
  53. metadata +268 -0
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/core_ext/string'
4
+ require 'active_support/json'
5
+ require 'onesignal/version'
6
+ require 'onesignal/commands'
7
+
8
+ ActiveSupport.escape_html_entities_in_json = false
9
+
10
+ module OneSignal
11
+ class << self
12
+ def configure
13
+ yield config
14
+ end
15
+
16
+ def send_notification notification
17
+ return unless OneSignal.config.active
18
+
19
+ created = Commands::CreateNotification.call notification
20
+ fetch_notification(JSON.parse(created.body)['id'])
21
+ end
22
+
23
+ def fetch_notification notification_id
24
+ return unless OneSignal.config.active
25
+
26
+ fetched = Commands::FetchNotification.call notification_id
27
+ Responses::Notification.from_json fetched.body
28
+ end
29
+
30
+ def fetch_notifications(page_limit: 50, page_offset: 0, kind: nil)
31
+ return unless OneSignal.config.active
32
+
33
+ Enumerator.new() do |yielder|
34
+ limit = page_limit
35
+ offset = page_offset
36
+
37
+ fetched = Commands::FetchNotifications.call limit, offset, kind
38
+ parsed = JSON.parse(fetched.body)
39
+
40
+ total_count = parsed["total_count"]
41
+ max_pages = (total_count / limit.to_f).ceil
42
+
43
+ loop do
44
+ parsed['notifications'].each do |notification|
45
+ yielder << Responses::Notification.from_json(notification)
46
+ end
47
+ offset += 1
48
+ break if offset >= max_pages
49
+ fetched = Commands::FetchNotifications.call limit, offset*limit, kind
50
+ parsed = JSON.parse(fetched.body)
51
+ end
52
+ end
53
+ end
54
+
55
+ def fetch_player player_id
56
+ return unless OneSignal.config.active
57
+
58
+ fetched = Commands::FetchPlayer.call player_id
59
+ Responses::Player.from_json fetched.body
60
+ end
61
+
62
+ def fetch_players
63
+ return unless OneSignal.config.active
64
+
65
+ fetched = Commands::FetchPlayers.call
66
+ JSON.parse(fetched.body)['players'].map { |player| Responses::Player.from_json player }
67
+ end
68
+
69
+ def csv_export params = {}
70
+ return unless OneSignal.config.active
71
+
72
+ fetched = Commands::CsvExport.call params
73
+ Responses::CsvExport.from_json fetched.body
74
+ end
75
+
76
+ def config
77
+ @config ||= Configuration.new
78
+ end
79
+
80
+ alias define configure
81
+ end
82
+ end
83
+
84
+ require 'onesignal/autoloader'
85
+ require 'onesignal/responses'
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ class Attachments
5
+ attr_reader :data, :url, :ios_attachments, :android_picture, :amazon_picture, :chrome_picture
6
+
7
+ def initialize data: nil, url: nil, ios_attachments: nil, android_picture: nil, amazon_picture: nil, chrome_picture: nil
8
+ @data = data
9
+ @url = url
10
+ @ios_attachments = ios_attachments
11
+ @android_picture = android_picture
12
+ @amazon_picture = amazon_picture
13
+ @chrome_picture = chrome_picture
14
+ end
15
+
16
+ def as_json options = nil
17
+ {
18
+ 'data' => @data.as_json(options),
19
+ 'url' => @url,
20
+ 'ios_attachments' => @ios_attachments.as_json(options),
21
+ 'big_picture' => @android_picture,
22
+ 'adm_big_picture' => @amazon_picture,
23
+ 'chrome_big_picture' => @chrome_picture
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module AutoMap
5
+ def create_readers **attributes
6
+ attributes.keys.each do |k|
7
+ self.class.define_method k do
8
+ attributes[k]
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.expand_path(__dir__)}/*.rb"].each do |file|
4
+ filename = File.basename file
5
+ classname = filename.split('.rb').first.camelize
6
+ OneSignal.autoload classname, File.expand_path("../#{filename}", __FILE__)
7
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ class Buttons
5
+ attr_reader :buttons
6
+
7
+ def initialize buttons: nil
8
+ @buttons = buttons
9
+ end
10
+
11
+ def as_json options = nil
12
+ {
13
+ 'buttons' => @buttons.as_json(options),
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module OneSignal
6
+ class Client
7
+ class ApiError < RuntimeError; end
8
+
9
+ def initialize app_id, api_key, api_url
10
+ @app_id = app_id
11
+ @api_key = api_key
12
+ @api_url = api_url
13
+ @conn = ::Faraday.new(url: api_url) do |faraday|
14
+ # faraday.response :logger do |logger|
15
+ # logger.filter(/(api_key=)(\w+)/, '\1[REMOVED]')
16
+ # logger.filter(/(Basic )(\w+)/, '\1[REMOVED]')
17
+ # end
18
+ faraday.adapter Faraday.default_adapter
19
+ end
20
+ end
21
+
22
+ def create_notification notification
23
+ post 'notifications', notification
24
+ end
25
+
26
+ def fetch_notification notification_id
27
+ get "notifications/#{notification_id}"
28
+ end
29
+
30
+ def fetch_notifications page_limit: 50, page_offset: 0, kind: nil
31
+ url = "notifications?limit=#{page_limit}&offset=#{page_offset}"
32
+ url = kind ? "#{url}&kind=#{kind}" : url
33
+ get url
34
+ end
35
+
36
+ def fetch_players
37
+ get 'players'
38
+ end
39
+
40
+ def fetch_player player_id
41
+ get "players/#{player_id}"
42
+ end
43
+
44
+ def csv_export extra_fields: nil, last_active_since: nil, segment_name: nil
45
+ post "players/csv_export?app_id=#{@app_id}",
46
+ extra_fields: extra_fields,
47
+ last_active_since: last_active_since&.to_i&.to_s,
48
+ segment_name: segment_name
49
+ end
50
+
51
+ private
52
+
53
+ def create_body payload
54
+ body = payload.as_json.delete_if { |_, v| v.nil? }
55
+ body['app_id'] = @app_id
56
+ body
57
+ end
58
+
59
+ def post url, body
60
+ res = @conn.post do |req|
61
+ req.url url
62
+ req.body = create_body(body).to_json
63
+ req.headers['Content-Type'] = 'application/json'
64
+ req.headers['Authorization'] = "Basic #{@api_key}"
65
+ end
66
+
67
+ handle_errors res
68
+ end
69
+
70
+ def get url
71
+ res = @conn.get do |req|
72
+ req.url url, app_id: @app_id
73
+ req.headers['Content-Type'] = 'application/json'
74
+ req.headers['Authorization'] = "Basic #{@api_key}"
75
+ end
76
+
77
+ handle_errors res
78
+ end
79
+
80
+ def handle_errors res
81
+ errors = JSON.parse(res.body).fetch 'errors', []
82
+ raise ApiError, (errors.first || "Error code #{res.status}") if res.status > 399 || errors.any?
83
+
84
+ res
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ require 'onesignal/commands/autoloader'
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Dir["#{File.expand_path(__dir__)}/*.rb"].each do |file|
4
+ filename = File.basename file
5
+ classname = filename.split('.rb').first.camelize
6
+ OneSignal::Commands.autoload classname, File.expand_path("../#{filename}", __FILE__)
7
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simple_command'
4
+
5
+ module OneSignal
6
+ module Commands
7
+ class BaseCommand
8
+ prepend ::SimpleCommand
9
+
10
+ def call
11
+ raise NotImplementedError, 'this is an abstract class'
12
+ end
13
+
14
+ def client
15
+ @client ||= OneSignal::Client.new(config.app_id, config.api_key, config.api_url)
16
+ end
17
+
18
+ def config
19
+ OneSignal.config
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ class CreateNotification < BaseCommand
6
+ def initialize notification
7
+ @notification = notification
8
+ end
9
+
10
+ def call
11
+ client.create_notification @notification
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ class CsvExport < BaseCommand
6
+ def initialize params
7
+ @params = params || {}
8
+ end
9
+
10
+ def call
11
+ client.csv_export @params
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ class FetchNotification < BaseCommand
6
+ def initialize notification_id
7
+ @notification_id = notification_id
8
+ end
9
+
10
+ def call
11
+ client.fetch_notification @notification_id
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ class FetchNotifications < BaseCommand
6
+ def initialize page_limit, page_offset, kind
7
+ @page_limit = page_limit
8
+ @page_offset = page_offset
9
+ @kind = kind
10
+ end
11
+
12
+ def call
13
+ client.fetch_notifications page_limit: @page_limit, page_offset: @page_offset, kind: @kind
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ class FetchPlayer < BaseCommand
6
+ def initialize player_id
7
+ @player_id = player_id
8
+ end
9
+
10
+ def call
11
+ client.fetch_player @player_id
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ module Commands
5
+ class FetchPlayers < BaseCommand
6
+ def call
7
+ client.fetch_players
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module OneSignal
6
+ class Configuration
7
+ attr_accessor :app_id, :api_key, :api_url, :active, :logger
8
+
9
+ def initialize
10
+ @app_id = ENV['ONESIGNAL_APP_ID']
11
+ @api_key = ENV['ONESIGNAL_API_KEY']
12
+ @api_url = "https://onesignal.com/api/#{OneSignal::API_VERSION}"
13
+ @active = true
14
+ @logger = Logger.new(STDOUT).tap do |logger|
15
+ logger.level = Logger::INFO
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OneSignal
4
+ class Filter
5
+ OR = { operator: 'OR' }.freeze
6
+
7
+ attr_reader :field, :key, :relation, :value, :hours_ago, :location
8
+
9
+ class << self
10
+ def last_session
11
+ FilterBuilder.new 'last_session'
12
+ end
13
+
14
+ def first_session
15
+ FilterBuilder.new 'first_session'
16
+ end
17
+
18
+ def session_count
19
+ FilterBuilder.new 'session_count'
20
+ end
21
+
22
+ def session_time
23
+ FilterBuilder.new 'session_time'
24
+ end
25
+
26
+ def amount_spent
27
+ FilterBuilder.new 'amount_spent'
28
+ end
29
+
30
+ def bought_sku sku
31
+ FilterBuilder.new 'bought_sku', key: sku
32
+ end
33
+
34
+ def tag tag
35
+ FilterBuilder.new 'tag', key: tag
36
+ end
37
+
38
+ def language
39
+ FilterBuilder.new 'language'
40
+ end
41
+
42
+ def app_version
43
+ FilterBuilder.new 'app_version'
44
+ end
45
+
46
+ def country
47
+ FilterBuilder.new 'country'
48
+ end
49
+
50
+ def location radius:, lat:, long:
51
+ location = OpenStruct.new radius: radius, latitude: lat, longitude: long
52
+ new FilterBuilder.new('location', location: location)
53
+ end
54
+
55
+ def email email
56
+ new(FilterBuilder.new('email', value: email))
57
+ end
58
+ end
59
+
60
+ def hours_ago!
61
+ @hours_ago ||= @value
62
+ @value = nil
63
+ self
64
+ end
65
+
66
+ def as_json options = nil
67
+ super(options).select { |_k, v| v.present? }
68
+ end
69
+
70
+ private
71
+
72
+ def initialize builder
73
+ @field = builder.b_field
74
+ @key = builder.b_key
75
+ @relation = builder.b_relation
76
+ @value = builder.b_value
77
+ @hours_ago = builder.b_hours_ago
78
+ @location = builder.b_location
79
+ end
80
+
81
+ class FilterBuilder
82
+ attr_reader :b_field, :b_key, :b_relation, :b_value, :b_hours_ago, :b_location
83
+
84
+ def initialize field, params = {}
85
+ @b_field = field
86
+ @b_key = params[:key]
87
+ @b_location = params[:location]
88
+ @b_value = params[:value]
89
+ end
90
+
91
+ def lesser_than value
92
+ @b_relation = '<'
93
+ @b_value = value.to_s
94
+ build
95
+ end
96
+
97
+ alias < lesser_than
98
+
99
+ def greater_than value
100
+ @b_relation = '>'
101
+ @b_value = value.to_s
102
+ build
103
+ end
104
+
105
+ alias > greater_than
106
+
107
+ def equals value
108
+ @b_relation = '='
109
+ @b_value = value.to_s
110
+ build
111
+ end
112
+
113
+ alias == equals
114
+
115
+ def not_equals value
116
+ @b_relation = '!='
117
+ @b_value = value.to_s
118
+ build
119
+ end
120
+
121
+ alias != not_equals
122
+
123
+ def exists
124
+ @b_relation = 'exists'
125
+ build
126
+ end
127
+
128
+ def not_exists
129
+ @b_relation = 'not_exists'
130
+ build
131
+ end
132
+
133
+ private
134
+
135
+ def build
136
+ Filter.new self
137
+ end
138
+ end
139
+ end
140
+ end