expo-server-sdk 0.1.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/.gitattributes +1 -0
- data/.github/workflows/main.yml +18 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +18 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +68 -0
- data/LICENSE.txt +21 -0
- data/README.md +252 -0
- data/Rakefile +16 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/expo-server-sdk.gemspec +41 -0
- data/lib/expo/server/sdk/version.rb +15 -0
- data/lib/expo/server/sdk.rb +14 -0
- data/lib/push/chunk.rb +58 -0
- data/lib/push/client.rb +292 -0
- data/lib/push/notification.rb +348 -0
- data/lib/push/receipts.rb +98 -0
- data/lib/push/tickets.rb +118 -0
- metadata +96 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Expo
|
4
|
+
module Push
|
5
|
+
##
|
6
|
+
# A single receipt for a single notification.
|
7
|
+
#
|
8
|
+
# - In case of an #ok? receipt, no action need be taken
|
9
|
+
# - In case of an #error? receipt, holds the #message, #explain
|
10
|
+
#
|
11
|
+
# Some failed receipts may expose which push token is not or no longer
|
12
|
+
# valid. This is exposed via #original_push_token.
|
13
|
+
#
|
14
|
+
class Receipt
|
15
|
+
attr_reader :data, :receipt_id
|
16
|
+
|
17
|
+
def initialize(data:, receipt_id:)
|
18
|
+
self.data = data
|
19
|
+
self.receipt_id = receipt_id
|
20
|
+
end
|
21
|
+
|
22
|
+
def original_push_token
|
23
|
+
return nil if ok?
|
24
|
+
|
25
|
+
if message.include?('PushToken[')
|
26
|
+
return /Expo(?:nent)?PushToken\[(?:[^\]]+?)\]/.match(message) { |match| match[0] }
|
27
|
+
end
|
28
|
+
|
29
|
+
/\A[a-z\d]{8}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{12}\z/i.match(message) { |match| match[0] }
|
30
|
+
end
|
31
|
+
|
32
|
+
def message
|
33
|
+
data.fetch('message')
|
34
|
+
end
|
35
|
+
|
36
|
+
def explain
|
37
|
+
Expo::Push::Error.explain((data['details'] || {})['error'])
|
38
|
+
end
|
39
|
+
|
40
|
+
def ok?
|
41
|
+
data['status'] == 'ok'
|
42
|
+
end
|
43
|
+
|
44
|
+
def error?
|
45
|
+
data['status'] == 'error'
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
attr_writer :data, :receipt_id
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# Receipts represent a single call to the receipts endpoint. It holds both
|
55
|
+
# the successfully retrieved receipts, as well as the still unresolved IDs.
|
56
|
+
#
|
57
|
+
# You MUST iterate #each_error and first check if its an Error, which would
|
58
|
+
# be the case if the entire call failed. Otherwise, it will iterate through
|
59
|
+
# each receipt that indicates a failed push.
|
60
|
+
#
|
61
|
+
# Keep calling the receipts endpoint until #unresolved_ids is empty, or a
|
62
|
+
# day has passed at least.
|
63
|
+
#
|
64
|
+
# @see Receipt
|
65
|
+
#
|
66
|
+
class Receipts
|
67
|
+
def initialize(results:, requested_ids:)
|
68
|
+
self.results = results
|
69
|
+
self.requested_ids = requested_ids
|
70
|
+
end
|
71
|
+
|
72
|
+
def each
|
73
|
+
receipts.each do |receipt|
|
74
|
+
next unless receipt.ok?
|
75
|
+
|
76
|
+
yield receipt
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def each_error
|
81
|
+
results.each do |receipt|
|
82
|
+
next yield receipt if receipt.is_a?(Error)
|
83
|
+
next unless receipt.error?
|
84
|
+
|
85
|
+
yield receipt
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def unresolved_ids
|
90
|
+
requested_ids - results.keys
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
attr_accessor :results, :requested_ids
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/push/tickets.rb
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Expo
|
4
|
+
module Push
|
5
|
+
##
|
6
|
+
# A ticket represents a single receipt ticket.
|
7
|
+
#
|
8
|
+
# - In case of an #ok? ticket, holds the receipt id in #id
|
9
|
+
# - In case of an #error? ticket, holds the #message, #explain
|
10
|
+
#
|
11
|
+
# Some failed tickets may expose which push token is not or no longer
|
12
|
+
# valid. This is exposed via #original_push_token.
|
13
|
+
#
|
14
|
+
class Ticket
|
15
|
+
attr_reader :data
|
16
|
+
|
17
|
+
def initialize(data)
|
18
|
+
self.data = data
|
19
|
+
end
|
20
|
+
|
21
|
+
def id
|
22
|
+
data.fetch('id')
|
23
|
+
end
|
24
|
+
|
25
|
+
def original_push_token
|
26
|
+
return nil if ok?
|
27
|
+
|
28
|
+
if message.include?('PushToken[')
|
29
|
+
return /Expo(?:nent)?PushToken\[(?:[^\]]+?)\]/.match(message) { |match| match[0] }
|
30
|
+
end
|
31
|
+
|
32
|
+
/\A[a-z\d]{8}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{4}-[a-z\d]{12}\z/i.match(message) { |match| match[0] }
|
33
|
+
end
|
34
|
+
|
35
|
+
def message
|
36
|
+
data.fetch('message')
|
37
|
+
end
|
38
|
+
|
39
|
+
def explain
|
40
|
+
Expo::Push::Error.explain((data['details'] || {})['error'])
|
41
|
+
end
|
42
|
+
|
43
|
+
def ok?
|
44
|
+
data['status'] == 'ok'
|
45
|
+
end
|
46
|
+
|
47
|
+
def error?
|
48
|
+
data['status'] == 'error'
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
attr_writer :data
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Tickets are paged: each batch when sending the notifications is one
|
58
|
+
# tickets entry. Each tickets entry has many tickets.
|
59
|
+
#
|
60
|
+
# To ease exploration and continuation of the tickets, use the
|
61
|
+
# folowing methods:
|
62
|
+
#
|
63
|
+
# - #batch_ids: slices all the receipts into chunks
|
64
|
+
# - #each: iterates over each single ticket that is NOT an error
|
65
|
+
# - #each_error: iterates over each errorered batch and failed ticket
|
66
|
+
#
|
67
|
+
# You MUST handle each error, and you MUST first check if its an Error
|
68
|
+
# or not, because of the way an entire batch call can fail.
|
69
|
+
#
|
70
|
+
# @see Ticket
|
71
|
+
#
|
72
|
+
class Tickets
|
73
|
+
def initialize(results)
|
74
|
+
self.results = results
|
75
|
+
end
|
76
|
+
|
77
|
+
def ids
|
78
|
+
[].tap do |ids|
|
79
|
+
each { |ticket| ids << ticket.id }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def batch_ids
|
84
|
+
ids.each_slice(PUSH_NOTIFICATION_RECEIPT_CHUNK_LIMIT).to_a
|
85
|
+
end
|
86
|
+
|
87
|
+
def each
|
88
|
+
results.each do |tickets|
|
89
|
+
next if tickets.is_a?(Error)
|
90
|
+
|
91
|
+
tickets.each do |ticket|
|
92
|
+
next unless ticket.ok?
|
93
|
+
|
94
|
+
yield ticket
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def each_error
|
100
|
+
results.each do |tickets|
|
101
|
+
if tickets.is_a?(Error)
|
102
|
+
yield tickets
|
103
|
+
else
|
104
|
+
tickets.each do |ticket|
|
105
|
+
next unless ticket.error?
|
106
|
+
|
107
|
+
yield ticket
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
attr_accessor :results
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
metadata
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: expo-server-sdk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Derk-Jan Karrenbeld
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-10-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: connection_pool
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: http
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5.0'
|
41
|
+
description: This gem has been written to fix shortcomings with the current community
|
42
|
+
provided gem, which has many outstanding issues and open pull requests.
|
43
|
+
email:
|
44
|
+
- derk-jan+github@karrenbeld.info
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- ".gitattributes"
|
50
|
+
- ".github/workflows/main.yml"
|
51
|
+
- ".gitignore"
|
52
|
+
- ".rubocop.yml"
|
53
|
+
- CODE_OF_CONDUCT.md
|
54
|
+
- Gemfile
|
55
|
+
- Gemfile.lock
|
56
|
+
- LICENSE.txt
|
57
|
+
- README.md
|
58
|
+
- Rakefile
|
59
|
+
- bin/console
|
60
|
+
- bin/setup
|
61
|
+
- expo-server-sdk.gemspec
|
62
|
+
- lib/expo/server/sdk.rb
|
63
|
+
- lib/expo/server/sdk/version.rb
|
64
|
+
- lib/push/chunk.rb
|
65
|
+
- lib/push/client.rb
|
66
|
+
- lib/push/notification.rb
|
67
|
+
- lib/push/receipts.rb
|
68
|
+
- lib/push/tickets.rb
|
69
|
+
homepage: https://github.com/sleeplessbyte/expo-server-sdk-ruby
|
70
|
+
licenses:
|
71
|
+
- MIT
|
72
|
+
metadata:
|
73
|
+
homepage_uri: https://github.com/sleeplessbyte/expo-server-sdk-ruby
|
74
|
+
source_code_uri: https://github.com/sleeplessbyte/expo-server-sdk-ruby
|
75
|
+
bug_tracker_uri: https://github.com/sleeplessbyte/expo-server-sdk-ruby/issues
|
76
|
+
changelog_uri: https://github.com/sleeplessbyte/expo-server-sdk-ruby/blob/main/CHANGELOG.md
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.6.8
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubygems_version: 3.1.6
|
93
|
+
signing_key:
|
94
|
+
specification_version: 4
|
95
|
+
summary: Modern replacement for exponent-server-sdk
|
96
|
+
test_files: []
|