Skip to content

Commit a2b6a8b

Browse files
authoredSep 14, 2020
COVIDSafe code from version 1.11 (AU-COVIDSafe#22)
1 parent 746841a commit a2b6a8b

File tree

65 files changed

+4396
-2212
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

65 files changed

+4396
-2212
lines changed
 

‎CovidSafe.xcodeproj/project.pbxproj

+97-23
Large diffs are not rendered by default.

‎CovidSafe/API/MessageAPI.swift

+82-46
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,45 @@ class MessageAPI {
1313

1414
static let keyLastApiUpdate = "keyLastApiUpdate"
1515
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) {
1818
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)
2932
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
3147

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)")
4655
}
4756
}
4857

@@ -62,36 +71,40 @@ class MessageAPI {
6271

6372
if lastChecked > 0 {
6473
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)
6675

67-
if let numDays = components.day {
68-
shouldGetMessages = numDays > 0
76+
if let numHours = components.hour {
77+
shouldGetMessages = numHours > 4
6978
}
7079
}
7180

7281
return shouldGetMessages
7382
}
7483

7584
private static func getMessages(msgRequest: MessageRequest,
76-
completion: @escaping (MessageResponse?, Swift.Error?) -> Void) {
85+
completion: @escaping (MessageResponse?, MessageAPIError?) -> Void) {
7786
let keychain = KeychainSwift()
7887
guard let apiHost = PlistHelper.getvalueFromInfoPlist(withKey: "API_Host", plistName: "CovidSafe-config") else {
88+
completion(nil, .RequestError)
7989
return
8090
}
8191

8292
guard let token = keychain.get("JWT_TOKEN") else {
83-
completion(nil, nil)
93+
completion(nil, .RequestError)
8494
return
8595
}
8696
let headers: HTTPHeaders = [
8797
"Authorization": "Bearer \(token)"
8898
]
8999

100+
let preferredLanguages = Locale.preferredLanguages.count > 5 ? Locale.preferredLanguages[0...5].joined(separator: ",") : Locale.preferredLanguages.joined(separator: ",")
101+
90102
var params: [String : Any] = [
91103
"os" : "ios-\(UIDevice.current.systemVersion)",
92104
"healthcheck" : msgRequest.healthcheck.rawValue,
93-
"preferredlanguages": Locale.preferredLanguages
94-
]
105+
"encountershealth" : msgRequest.encountershealth.rawValue,
106+
"preferredlanguages": preferredLanguages
107+
]
95108

96109
if let buildString = Bundle.main.version {
97110
params["appversion"] = "\(buildString)"
@@ -104,20 +117,35 @@ class MessageAPI {
104117
parameters: params,
105118
headers: headers
106119
).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 {
114131
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)
120132
}
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+
}
121149
}
122150
}
123151
}
@@ -131,6 +159,7 @@ enum healthCheckParamValue: String {
131159
struct MessageRequest {
132160
var remotePushToken: String?
133161
var healthcheck: healthCheckParamValue
162+
var encountershealth: healthCheckParamValue
134163
}
135164

136165
struct MessageResponse: Decodable {
@@ -154,3 +183,10 @@ struct Message: Decodable {
154183
case destination
155184
}
156185
}
186+
187+
enum MessageAPIError: Error {
188+
case RequestError
189+
case ResponseError
190+
case ServerError
191+
case UnknownError
192+
}

0 commit comments

Comments
 (0)
Please sign in to comment.