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.
- checksums.yaml +7 -0
- data/.circleci/config.yml +42 -0
- data/.editorconfig +14 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.rubocop.yml +182 -0
- data/CODEOWNERS +1 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +87 -0
- data/LICENSE.txt +21 -0
- data/README.md +226 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/fixtures/vcr_cassettes/os-csv-export.yml +135 -0
- data/fixtures/vcr_cassettes/os-fetch-noti.yml +76 -0
- data/fixtures/vcr_cassettes/os-fetch-notifications.yml +237 -0
- data/fixtures/vcr_cassettes/os-fetch-player.yml +72 -0
- data/fixtures/vcr_cassettes/os-fetch-players.yml +72 -0
- data/fixtures/vcr_cassettes/os-send-noti.yml +145 -0
- data/lib/onesignal.rb +85 -0
- data/lib/onesignal/attachments.rb +27 -0
- data/lib/onesignal/auto_map.rb +13 -0
- data/lib/onesignal/autoloader.rb +7 -0
- data/lib/onesignal/buttons.rb +17 -0
- data/lib/onesignal/client.rb +87 -0
- data/lib/onesignal/commands.rb +7 -0
- data/lib/onesignal/commands/autoloader.rb +7 -0
- data/lib/onesignal/commands/base_command.rb +23 -0
- data/lib/onesignal/commands/create_notification.rb +15 -0
- data/lib/onesignal/commands/csv_export.rb +15 -0
- data/lib/onesignal/commands/fetch_notification.rb +15 -0
- data/lib/onesignal/commands/fetch_notifications.rb +17 -0
- data/lib/onesignal/commands/fetch_player.rb +15 -0
- data/lib/onesignal/commands/fetch_players.rb +11 -0
- data/lib/onesignal/configuration.rb +19 -0
- data/lib/onesignal/filter.rb +140 -0
- data/lib/onesignal/included_targets.rb +47 -0
- data/lib/onesignal/notification.rb +39 -0
- data/lib/onesignal/notification/contents.rb +17 -0
- data/lib/onesignal/notification/headings.rb +17 -0
- data/lib/onesignal/responses.rb +7 -0
- data/lib/onesignal/responses/autoloader.rb +7 -0
- data/lib/onesignal/responses/base_response.rb +18 -0
- data/lib/onesignal/responses/csv_export.rb +18 -0
- data/lib/onesignal/responses/notification.rb +45 -0
- data/lib/onesignal/responses/player.rb +21 -0
- data/lib/onesignal/segment.rb +23 -0
- data/lib/onesignal/sounds.rb +39 -0
- data/lib/onesignal/version.rb +6 -0
- data/onesignal-ruby.gemspec +48 -0
- metadata +268 -0
data/lib/onesignal.rb
ADDED
@@ -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,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,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 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,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
|