@@ -13,36 +13,45 @@ class MessageAPI {
13
13
14
14
static let keyLastApiUpdate = " keyLastApiUpdate "
15
15
static let keyLastVersionChecked = " keyLastVersionChecked "
16
-
17
- static func getMessagesIfNeeded( completion: @escaping ( MessageResponse ? , Swift . Error ? ) -> Void ) {
16
+
17
+ static func getMessagesIfNeeded( completion: @escaping ( MessageResponse ? , MessageAPIError ? ) -> Void ) {
18
18
if shouldGetMessages ( ) {
19
- guard let token = UserDefaults . standard. string ( forKey: " deviceTokenForAPN " ) else {
20
- return
21
- }
22
- //Get relevat encounter data
23
- guard let persistentContainer =
24
- EncounterDB . shared. persistentContainer else {
25
- return
26
- }
27
- let managedContext = persistentContainer. newBackgroundContext ( )
28
- guard let encounterLastWeekRequest = Encounter . fetchEncountersInLast ( days: 7 ) else {
19
+ getMessages ( completion: completion)
20
+ }
21
+ }
22
+
23
+ static func getMessages( completion: @escaping ( MessageResponse ? , MessageAPIError ? ) -> Void ) {
24
+ guard let token = UserDefaults . standard. string ( forKey: " deviceTokenForAPN " ) else {
25
+ completion ( nil , . RequestError)
26
+ return
27
+ }
28
+ //Get relevat encounter data
29
+ guard let persistentContainer =
30
+ EncounterDB . shared. persistentContainer else {
31
+ completion ( nil , . RequestError)
29
32
return
30
- }
33
+ }
34
+ let managedContext = persistentContainer. newBackgroundContext ( )
35
+ guard let encounterLastWeekRequest = Encounter . fetchEncountersInLast ( days: 7 ) else {
36
+ completion ( nil , . RequestError)
37
+ return
38
+ }
39
+
40
+ do {
41
+ //fetch last week encounters count
42
+ let weekEncounters = try managedContext. count ( for: encounterLastWeekRequest)
43
+ let healthcheck = BluetraceManager . shared. isBluetoothOn ( ) && BluetraceManager . shared. isBluetoothAuthorized ( ) ?
44
+ healthCheckParamValue. OK :
45
+ healthCheckParamValue. POSSIBLE_ERROR
46
+ let encounterCheck = weekEncounters > 0 ? healthCheckParamValue. OK : healthCheckParamValue. POSSIBLE_ERROR
31
47
32
- do {
33
- //fetch last week encounters count
34
- let weekEncounters = try managedContext. count ( for: encounterLastWeekRequest)
35
- let healthcheck = ( BluetraceManager . shared. isBluetoothOn ( ) &&
36
- BluetraceManager . shared. isBluetoothAuthorized ( ) &&
37
- weekEncounters > 0 ? healthCheckParamValue. OK : healthCheckParamValue. POSSIBLE_ERROR)
38
-
39
- // Make API call to get messages
40
- let messageRequest = MessageRequest ( remotePushToken: token, healthcheck: healthcheck)
41
- getMessages ( msgRequest: messageRequest, completion: completion)
42
-
43
- } catch let error as NSError {
44
- DLog ( " Could not fetch encounter(s) from db. \( error) , \( error. userInfo) " )
45
- }
48
+ // Make API call to get messages
49
+ let messageRequest = MessageRequest ( remotePushToken: token, healthcheck: healthcheck, encountershealth: encounterCheck)
50
+ getMessages ( msgRequest: messageRequest, completion: completion)
51
+
52
+ } catch let error as NSError {
53
+ completion ( nil , . RequestError)
54
+ DLog ( " Could not fetch encounter(s) from db. \( error) , \( error. userInfo) " )
46
55
}
47
56
}
48
57
@@ -62,36 +71,40 @@ class MessageAPI {
62
71
63
72
if lastChecked > 0 {
64
73
let lastCheckedDate = Date ( timeIntervalSince1970: lastChecked)
65
- let components = calendar. dateComponents ( [ . day ] , from: lastCheckedDate, to: currentDate)
74
+ let components = calendar. dateComponents ( [ . hour ] , from: lastCheckedDate, to: currentDate)
66
75
67
- if let numDays = components. day {
68
- shouldGetMessages = numDays > 0
76
+ if let numHours = components. hour {
77
+ shouldGetMessages = numHours > 4
69
78
}
70
79
}
71
80
72
81
return shouldGetMessages
73
82
}
74
83
75
84
private static func getMessages( msgRequest: MessageRequest ,
76
- completion: @escaping ( MessageResponse ? , Swift . Error ? ) -> Void ) {
85
+ completion: @escaping ( MessageResponse ? , MessageAPIError ? ) -> Void ) {
77
86
let keychain = KeychainSwift ( )
78
87
guard let apiHost = PlistHelper . getvalueFromInfoPlist ( withKey: " API_Host " , plistName: " CovidSafe-config " ) else {
88
+ completion ( nil , . RequestError)
79
89
return
80
90
}
81
91
82
92
guard let token = keychain. get ( " JWT_TOKEN " ) else {
83
- completion ( nil , nil )
93
+ completion ( nil , . RequestError )
84
94
return
85
95
}
86
96
let headers : HTTPHeaders = [
87
97
" Authorization " : " Bearer \( token) "
88
98
]
89
99
100
+ let preferredLanguages = Locale . preferredLanguages. count > 5 ? Locale . preferredLanguages [ 0 ... 5 ] . joined ( separator: " , " ) : Locale . preferredLanguages. joined ( separator: " , " )
101
+
90
102
var params : [ String : Any ] = [
91
103
" os " : " ios- \( UIDevice . current. systemVersion) " ,
92
104
" healthcheck " : msgRequest. healthcheck. rawValue,
93
- " preferredlanguages " : Locale . preferredLanguages
94
- ]
105
+ " encountershealth " : msgRequest. encountershealth. rawValue,
106
+ " preferredlanguages " : preferredLanguages
107
+ ]
95
108
96
109
if let buildString = Bundle . main. version {
97
110
params [ " appversion " ] = " \( buildString) "
@@ -104,20 +117,35 @@ class MessageAPI {
104
117
parameters: params,
105
118
headers: headers
106
119
) . validate ( ) . responseDecodable ( of: MessageResponse . self) { ( response) in
107
- switch response. result {
108
- case . success:
109
- guard let messageResponse = response. value else { return }
110
-
111
- // save successful timestamp
112
- let calendar = NSCalendar . current
113
- let currentDate = calendar. startOfDay ( for: Date ( ) )
120
+ switch response. result {
121
+ case . success:
122
+ guard let messageResponse = response. value else { return }
123
+
124
+ // save successful timestamp
125
+ let minutesToDefer = Int . random ( in: 0 ..< 10 )
126
+ let calendar = NSCalendar . current
127
+ let currentDate = Date ( )
128
+ if let deferredDate = calendar. date ( byAdding: . minute, value: minutesToDefer, to: currentDate) {
129
+ UserDefaults . standard. set ( deferredDate. timeIntervalSince1970, forKey: keyLastApiUpdate)
130
+ } else {
114
131
UserDefaults . standard. set ( currentDate. timeIntervalSince1970, forKey: keyLastApiUpdate)
115
- UserDefaults . standard. set ( Bundle . main. version, forKey: keyLastVersionChecked)
116
-
117
- completion ( messageResponse, nil )
118
- case let . failure( error) :
119
- completion ( nil , error)
120
132
}
133
+ UserDefaults . standard. set ( Bundle . main. version, forKey: keyLastVersionChecked)
134
+
135
+ completion ( messageResponse, nil )
136
+ case . failure( _) :
137
+ guard let statusCode = response. response? . statusCode else {
138
+ completion ( nil , . UnknownError)
139
+ return
140
+ }
141
+ if ( statusCode == 200 ) {
142
+ completion ( nil , . ResponseError)
143
+ }
144
+ if ( statusCode >= 400 && statusCode < 500 ) {
145
+ completion ( nil , . RequestError)
146
+ }
147
+ completion ( nil , . ServerError)
148
+ }
121
149
}
122
150
}
123
151
}
@@ -131,6 +159,7 @@ enum healthCheckParamValue: String {
131
159
struct MessageRequest {
132
160
var remotePushToken : String ?
133
161
var healthcheck : healthCheckParamValue
162
+ var encountershealth : healthCheckParamValue
134
163
}
135
164
136
165
struct MessageResponse : Decodable {
@@ -154,3 +183,10 @@ struct Message: Decodable {
154
183
case destination
155
184
}
156
185
}
186
+
187
+ enum MessageAPIError : Error {
188
+ case RequestError
189
+ case ResponseError
190
+ case ServerError
191
+ case UnknownError
192
+ }
0 commit comments