networkmanager
unknown
swift
3 years ago
105 kB
9
Indexable
//
// NetworkManager.swift
// eToto
//
// Created by Hristo Hristov on 4.09.20.
// Copyright © 2020 Mobile Wave Solutions. All rights reserved.
//
import UIKit
enum SBBErrorCodes: Int {
case LogoutUser = 421
case SingleSlipToAcceptForTrader = 30
case MultiSlipToAcceptForTrader = 31
}
extension Notification.Name {
static let authenticate = Self.init("authenticate")
}
class NetworkManager: NSObject, NetworkManagerType {
private let cache = ImageCache()
static var shared = NetworkManager()
private var session: URLSession { URLSession.shared }
private lazy var temporarySession = URLSession(configuration: URLSessionConfiguration.default, delegate: self, delegateQueue: nil)
private lazy var logInCompletions: [GetUserCompletion] = []
private(set) lazy var user = Observer<User?>(nil)
private(set) lazy var fastBettingImage = Observer<UIImage?>(nil)
private(set) var lastUser: User? {
didSet {
Storage.etoto.userID = lastUser?.id
}
}
private var keepAliveTimer: Timer?
private var updateBalanceTimer: Timer?
private var updateEventsCacheTimer: Timer?
private var footballEventsCache: [Event]?
private var refreshChatOnChangeTask: URLSessionDataTask?
private var refreshChatTask: URLSessionDataTask?
private(set) var sessionID: String? //TODO: Can I create user property during registration process?
private override init() {
super.init()
NotificationCenter.default.addObserver(self, selector: #selector(sentEvent(_:)),
name: .sentEvent, object: UIApplication.shared)
NotificationCenter.default.addObserver(self, selector: #selector(invalidateFootballCache),
name: UIApplication.willResignActiveNotification, object: nil)
startUpdateEventsCacheTimer()
user.observe { [weak self] (new, _) in
self?.startKeepAliveTimer()
self?.startUpdateBalanceTimer()
if new != nil { self?.lastUser = new }
}
}
deinit {
NotificationCenter.default.removeObserver(self)
}
@objc private func sentEvent(_ notification: Notification) {
guard user.value != nil else {
return
}
startKeepAliveTimer()
}
func invalidateTimers() {
if updateEventsCacheTimer != nil {
updateEventsCacheTimer?.invalidate()
updateEventsCacheTimer = nil
}
}
func initializeTimers() {
startUpdateEventsCacheTimer()
}
private func startKeepAliveTimer() {
DispatchQueue.main.async { [weak self] in
if self?.keepAliveTimer != nil {
self?.keepAliveTimer?.invalidate()
self?.keepAliveTimer = nil
}
guard self?.user.value != nil else {
return
}
self?.keepAliveTimer = Timer.scheduledTimer(withTimeInterval: 60 * 3, repeats: false)
{ (_) in
self?.keepAlive() {
self?.startKeepAliveTimer()
}
}
}
}
private func startUpdateBalanceTimer() {
DispatchQueue.main.async { [weak self] in
if self?.updateBalanceTimer != nil {
self?.updateBalanceTimer?.invalidate()
self?.updateBalanceTimer = nil
}
guard self?.user.value != nil else {
return
}
self?.updateBalanceTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false)
{ (_) in
self?.updateBalance() {
self?.startUpdateBalanceTimer()
}
}
}
}
private func startUpdateEventsCacheTimer() {
DispatchQueue.main.async { [weak self] in
if self?.updateEventsCacheTimer != nil {
self?.updateEventsCacheTimer?.invalidate()
self?.updateEventsCacheTimer = nil
}
self?.updateEventsCacheTimer = Timer.scheduledTimer(withTimeInterval: 60, repeats: true)
{ (_) in
self?.cacheFootballEvents()
}
self?.updateEventsCacheTimer?.fire()
}
}
typealias ResponseBody = (data: Data, json: Any?)
private func handle(request: URLRequest,
data: Data?,
response: URLResponse?,
error: Error?) -> Result<ResponseBody, Error>? {
let successRange = 200...299
if request.allHTTPHeaderFields?.contains(where: { $0.key == User.Key.sessionID.rawValue }) == true {
startKeepAliveTimer()
}
if let code = (error as? URLError)?.code,
case .cancelled = code {
return nil
}
guard let statusCode = (response as? HTTPURLResponse)?.statusCode else {
return .failure(error ?? URLError(.badServerResponse))
}
guard let data = data else {
return .failure(URLError(.badServerResponse))
}
let json = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
switch statusCode {
case 200...299:
if let codeInBody = json?["code"] as? Int, !successRange.contains(codeInBody) {
switch codeInBody {
case SBBErrorCodes.MultiSlipToAcceptForTrader.rawValue,
SBBErrorCodes.SingleSlipToAcceptForTrader.rawValue:
let error = NSError(domain: "", code: codeInBody, userInfo: nil) as Error
return .failure(error)
case SBBErrorCodes.LogoutUser.rawValue:
// Do not logout if there is no valid user
// Otherwise the sessionID after mobile/user-validation/registrations is cleared
// and mobile/user-validation/details fails
if self.user.value?.id != nil {
logoutUser { (_) in }
}
return nil
case 423:
// Password reset returns 423 when the email is invalid or isn't in the system.
// When the email is invalid we get a description: Provided data is invalid. (email)
// When the email isn't in the system we get a description: Provided data is invalid. (customer-not-found)
// Presenting an error for email that isn't in the database would cause a security bridge so we have to handle this error as 'success'
guard let desctiption = json?["description"] as? String else {
return .failure(NSError(domain: "", code: codeInBody, userInfo: nil) as Error)
}
let error = EtotoAPIError(description: desctiption)
return .failure(error)
case 600:
if let jsonData = (json?["data"] as? [[String: Any]]),
let betslipErrorInBody = jsonData[safe: 0]?["betSlipErrorCode"] as? Int {
if betslipErrorInBody == 46 {
let mtsErrorDictionary = (jsonData[safe: 0]?["errorDetails"] as? [String: Any])
let mtsError = mtsErrorDictionary?["mtsErrorCode"] as? String
let error = NSError(domain: "", code: Int(mtsError ?? "0") ?? 0, userInfo: ["type":"MTS"]) as Error
return .failure(error)
}
let error = NSError(domain: "", code: betslipErrorInBody, userInfo: nil) as Error
return .failure(error)
} else {
return .failure(URLError(.badServerResponse))
}
case 200...299:
return .success((data, json?["data"]))
default:
let apiError = try? JSONDecoder().decode(APIError.self, from: data)
return .failure(apiError ?? URLError(.badServerResponse))
}
}
return .success((data, json?["data"]))
case 600:
return .failure(error ?? URLError(.badServerResponse))
case 421:
user.value = nil
return nil
case 401:
return .failure(URLError(.userAuthenticationRequired))
case 400...599:
let apiError = try? JSONDecoder().decode(APIError.self, from: data)
return .failure(apiError ?? URLError(.badServerResponse))
default:
return .failure(error ?? URLError(.badServerResponse))
}
}
//MARK: - Betting
@discardableResult
func checkTradersDecision(completion: @escaping CheckTradersDecision) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.approvedSlips(sessionID: user.value?.sessionID)
) else {
return nil
}
return checkTradersDecision(request: request, completion: completion)
}
private func checkTradersDecision(request: URLRequest, completion: @escaping CheckTradersDecision) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
if let json = body.json as? [String : Any] {
completion(.success(json))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func approveTraderChange(approved: Bool, completion: @escaping ApproveTraderChange) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.approveTraderChange(decision: approved,
sessionID: user.value?.sessionID)
) else {
return nil
}
return approveTraderChange(request: request, completion: completion)
}
private func approveTraderChange(request: URLRequest, completion: @escaping ApproveTraderChange) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(_ ):
completion(.success("newOdds"))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getLiveOdds(odds: [String], completion: @escaping GetLiveOddsCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoLiveBettingAPI(),
endpoint: ETotoLiveBettingAPI.Path.refreshOdds(odds: odds)
) else {
return nil
}
return getLiveOdds(request: request, completion: completion)
}
private func getLiveOdds(request: URLRequest, completion: @escaping GetLiveOddsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
if let newOdds = body.json as? [[String : Any]] {
completion(.success(newOdds))
} else {
completion(.failure(URLError(.cannotParseResponse)))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func virtualsHistory(from: Date,
to: Date,
completion: @escaping (Result<[PlacedBet]?, Error>) -> Void) -> URLSessionWork? {
guard let request =
URLRequest(api: ETotoBetHistoryAPI(),
endpoint: ETotoBetHistoryAPI.Path.virtualsHistory(from: from,
to: to,
sessionID: user.value?.sessionID)) else {
return nil
}
let work = URLSessionWork()
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let json = try? JSONSerialization.jsonObject(with: body.data, options: []) as? [String: Any],
let bodyJson = json["body"] else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
let bets = PlacedBet.virtualPlacedBets(bettingHistory: bodyJson as? [String: [String: Any]])
guard let ids = bets?.compactMap({ $0.id }) else { return completion(.success(bets)) }
work.append(self?.cashoutAmounts(bet: ids) { result in
if case .success(let amounts) = result {
amounts?.forEach({ (id, amount) in
bets?.first(where: { $0.id == id })?.cashout = amount
})
}
completion(.success(bets))
})
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
work.append(task)
task.resume()
return work
}
@discardableResult
func resetPassword(email: String, completion: @escaping ResetPasswordCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.resetPassword(email: email)) else {
return nil
}
return resetPassword(request: request, completion: completion)
}
private func resetPassword(request: URLRequest, completion: @escaping ResetPasswordCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(_):
completion(.success(()))
case .failure(let error):
guard let error = error as? EtotoAPIError else {
completion(.failure(.unknown))
return
}
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func notifyTraderForBetWith(body: [String: Any], completion: @escaping PlaceBetCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoLiveBettingAPI.Path.notifyTraderForBetWith(body: body,
sessionID: user.value?.sessionID)
) else {
return nil
}
return notifyTraderForBetWith(request: request, completion: completion)
}
private func notifyTraderForBetWith(request: URLRequest, completion: @escaping PlaceBetCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
completion(.success(body.json as? [String: Any] ?? [String: Any]()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func placeBet(body: [String: Any], completion: @escaping PlaceBetCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoLiveBettingAPI.Path.placeBet(body: body,
sessionID: user.value?.sessionID)) else {
return nil
}
return placeBet(request: request, completion: completion)
}
private func placeBet(request: URLRequest, completion: @escaping PlaceBetCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
completion(.success(body.json as? [String: Any] ?? [String: Any]()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getFreebets(completion: @escaping FreebetCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID else { return nil }
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.freebets(sessionID: sessionID)) else { return nil }
return getFreebets(request: request, completion: completion)
}
private func getFreebets(request: URLRequest, completion: @escaping FreebetCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
if let bodyJson = body.json as? [String: Any],
let freebetsJson = bodyJson["active"] as? [[String: Any]] {
let freebets = freebetsJson.compactMap { (input: [String: Any] ) in
return Freebet(with: input)
}
completion( .success(freebets) )
} else {
completion(.failure(URLError(.cannotParseResponse)))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func cancelAllCreditBonus(completion: @escaping CancelAllCreditBonusCompletion) -> URLSessionDataTask?
{
guard let sessionID = user.value?.sessionID else { return nil }
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.cancelAllCreditBonus(sessionID: sessionID)) else { return nil }
return cancelAllCreditBonus(request: request, completion: completion)
}
private func cancelAllCreditBonus(request: URLRequest, completion: @escaping CancelAllCreditBonusCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
if let bodyJson = body.json as? [String: Any] {
completion( .success(bodyJson) )
} else {
completion(.failure(URLError(.cannotParseResponse)))
}
case .failure(let error):
completion(.failure(error))
default:
break
}
}
task.resume()
return task
}
@discardableResult
func getCarouselSegments(completion: @escaping GetCarouselSegmentsCompletion) -> URLSessionDataTask?
{
guard let sessionID = user.value?.sessionID else { return nil }
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.carouselSegments(sessionID: sessionID)) else { return nil }
return getCarouselSegments(request: request, completion: completion)
}
private func getCarouselSegments(request: URLRequest, completion: @escaping GetCarouselSegmentsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
guard let model = try? JSONDecoder().decode(GetCarouselSegmentsModel.self, from: body.data) else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(model))
case .failure(let error):
completion(.failure(error))
default:
break
}
}
task.resume()
return task
}
@discardableResult
func getTaxFactor(body: [String: Any], completion: @escaping GetTaxFactorCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoLiveBettingAPI.Path.calculateTaxFactor(body: body, sessionID: user.value?.sessionID)) else {
return nil
}
return getTaxFactor(request: request, completion: completion)
}
private func getTaxFactor(request: URLRequest, completion: @escaping GetTaxFactorCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
if let taxFactor = body.json as? Double {
completion(.success(taxFactor))
} else {
completion(.failure(URLError(.cannotParseResponse)))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getPotentialWinnings(body: [String: Any], completion: @escaping GetPotentialWinningCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoLiveBettingAPI.Path.calculateWinnings(body: body)) else {
return nil
}
return getPotentialWinnings(request: request, completion: completion)
}
private func getPotentialWinnings(request: URLRequest, completion: @escaping GetPotentialWinningCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
completion(.success(body.json as? [String: Any] ?? [String: Any]()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
//MARK: - Categories
@discardableResult
func getCategories(completion: @escaping GetCategoriesCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.categories) else {
return nil
}
return getCategories(request: request, completion: completion)
}
@discardableResult
func getSubCategories(category: Int16, completion: @escaping GetCategoriesCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.subCategories(category: category)) else {
return nil
}
return getCategories(request: request, completion: completion)
}
private func getCategories(request: URLRequest, completion: @escaping GetCategoriesCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
let categories = SportCategory.categories(dictionaries: body.json as? [[String : Any]])
completion(.success(categories))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getEvent(eventID: Int,
completion: @escaping GetEventCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.event(eventID: eventID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let json = body.json as? [String: Any] else {
return completion(.failure(URLError(.cannotParseResponse)))
}
completion(.success(Event(json)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getEvents(category: Int16, completion: @escaping GetEventsCompletion<Event>) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.eventsForCategory(category: category)) else {
return nil
}
return getEvents(request: request, completion: completion)
}
@discardableResult
func getEvents(categories: [Int16], completion: @escaping GetEventsCompletion<Event>) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.eventsForCategories(categories: categories)) else {
return nil
}
return getEvents(request: request, completion: completion)
}
private func getEvents(request: URLRequest,
completion: @escaping GetEventsCompletion<Event>) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
let events = Event.events(dictionaries: body.json as? [[String: Any]])
completion(.success(Filters.filterOutShouldBeHidden(events)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func getImage(categoryID: String, settings: Settings = Settings.etoto, completion: @escaping (UIImage?) -> ()) -> URLSessionDataTask? {
guard let url = settings.categoryIcons[categoryID]?.url else {
completion(UIImage(named: "sportIconsUniversalSport"))
return nil
}
if let image = cache.image(for: url) {
completion(image)
return nil
}
let request = URLRequest(url: url)
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
if let image = UIImage(data: body.data) {
self?.cache.insertImage(image, for: url)
DispatchQueue.main.async {
completion(image)
}
}
case .failure:
DispatchQueue.main.async {
completion(nil)
}
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getEvents(withSearchPattern pattern: String,
completion: @escaping GetOfferEventsCompletion<Event,LiveEvent>) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.quickSearchEvents(searchPattern: pattern)) else {
completion(.failure(CocoaError(.userCancelled)))
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
let events = Event.events(searchResult: body.json as? [[String : Any]])
completion(.success(events))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getPopularCategories(completion: @escaping GetPopularCategoriesCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.popularCategories) else {
return nil
}
return getPopularCategories(request: request, completion: completion)
}
private func getPopularCategories(request: URLRequest, completion: @escaping GetPopularCategoriesCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let model = try? JSONDecoder().decode(PopularCategoryResponseModel.self, from: body.data) else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(model.data))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
//MARK: - Live -
@discardableResult
func getLiveSports(completion: @escaping GetCategoriesCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoLiveBettingAPI(),
endpoint: ETotoLiveBettingAPI.Path.liveBettingCategories) else {
return nil
}
return getLiveSports(request: request, completion: completion)
}
private func getLiveSports(request: URLRequest,
completion: @escaping GetCategoriesCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
let categories = SportCategory.categories(dictionaries: body.json as? [[String : Any]])?
.filter{ $0.level == 1 && ($0.eventsCount ?? 0) > 0}
.sorted(by: { $0.sortOrder < $1.sortOrder })
completion(.success(categories))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getLiveEvents(sportID: Int16, completion: @escaping GetEventsCompletion<LiveEvent>) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoLiveBettingAPI(),
endpoint: ETotoLiveBettingAPI.Path.eventsForCategory(category: sportID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
completion(.success(LiveEvent.events(result: body.json as? [[String : Any]])))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getLiveEventsForDate(dateString: String, completion: @escaping GetEventsCompletion<Event>) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.eventWithDate(date: dateString)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let events = Event.events(dictionaries: body.json as? [[String : Any]]) else { return }
completion(.success(events))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getLiveEvent(eventID: Int, completion: @escaping GetEventCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoLiveBettingAPI(),
endpoint: ETotoLiveBettingAPI.Path.event(event: eventID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let eventDic = (body.json as? [Any])?.first as? [String : AnyObject] else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(LiveEvent(eventDic)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
// MARK: - StatScore -
@discardableResult
func getStatScoreEventMapping(completion: @escaping GetStatScoreEventMappingCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.eventsStatScore) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let dictionaries = body.json as? StatScoreMapping else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(dictionaries))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
//MARK: - User -
// All, when completed, should reset the keep alive timer
private lazy var isUserLoggingIn = false
@discardableResult
func loginUser(name: String?, password: String?,
completion: GetUserCompletion?) -> URLSessionDataTask? {
logInCompletions.appendOptional(completion)
guard !isUserLoggingIn,
let name = name, let password = password,
let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.loginUser(name: name, password: password)) else {
return nil
}
isUserLoggingIn = true
let task = session.dataTask(with: request)
{ [weak self] (data, response, error) in
self?.isUserLoggingIn = false
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
var dictionary = body.json as? [String : Any]
dictionary?[User.Key.sessionID.rawValue] =
(response as? HTTPURLResponse)?.allHeaderFields[User.Key.sessionID.rawValue]
guard let user = User(dictionary: dictionary) else {
self?.logInCompletions.forEach{ $0(.failure(URLError(.cannotParseResponse))) }
self?.logInCompletions.removeAll()
return
}
self?.logInCompletions.forEach{ $0(.success(user)) }
self?.logInCompletions.removeAll()
self?.forceUpdateBalance(force: false, completion: nil)
case .failure(let error):
log.error(error.localizedDescription)
self?.logInCompletions.forEach{ $0(.failure(error)) }
self?.logInCompletions.removeAll()
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func loggedInUser(completion: GetUserCompletion?) -> URLSessionDataTask? {
if let user = user.value {
completion?(.success(user))
return nil
}
//TODO: ("Uncomment for autologin")
return nil
// guard !isUserLoggingIn else {
// logInCompletions.appendOptional(completion)
// return nil
// }
// guard let credentials = KeyChain.rememberedUserCredentials else {
// completion?(.failure(URLError(.userAuthenticationRequired)))
// return nil
// }
// return loginUser(name: credentials.name,
// password: credentials.password,
// completion: completion)
}
@discardableResult
func loggedInUser() -> URLSessionDataTask? {
return loggedInUser(completion: nil)
}
func keepAlive(completion: @escaping () -> ()) {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.keepAlive(sessionID: sessionID)) else {
return
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
if let user = User(dictionary: body.json as? [String : Any]) {
user.sessionID = self?.user.value?.sessionID
self?.user.value = user
}
completion()
case .failure(let error):
print(error.localizedDescription)
case .none:
break
}
}
task.resume()
}
private func updateBalance(completion: @escaping () -> ()) {
updateBalance(force: false, immediately: false, completion: completion)
}
@discardableResult
func forceUpdateBalance(force: Bool, completion: (() -> ())? = nil) -> URLSessionDataTask? {
return updateBalance(force: force, immediately: true, completion: completion)
}
@discardableResult
private func updateBalance(force: Bool, immediately: Bool, completion: (() -> ())? = nil) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID else {
return nil
}
let endpoint: EndPointType
if immediately {
endpoint = ETotoAPI.Path.forceUpdateBalance(force: force, sessionID: sessionID)
} else {
endpoint = ETotoAPI.Path.updateBalance(sessionID: sessionID)
}
guard let request = URLRequest(api: ETotoAPI(), endpoint: endpoint) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
if let data = body.json as? [String : Any],
let bonusData = data["creditBonusBalance"] as? [String : Any],
let balance = data["balance"] as? Double
{
if let bonus = bonusData["amount"] as? Double {
self?.user.value?.bonusAmount = bonus
} else {
self?.user.value?.bonusAmount = 0
}
self?.user.value?.balance.value = balance
}
completion?()
case .failure(let error):
print(error.localizedDescription)
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func logoutUser(completion: @escaping (Result<Bool, Error>) -> ()) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.logoutUser(sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
//TODO: ("Move to the success case once error handling is decided upon")
self?.user.value = nil
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(true))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getUserDetails(completion: @escaping GetUserDetailsCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: UserProfileAPI(),
endpoint: UserProfileAPI.Path.getUserDetails(sessionID: sessionID)) else {
completion(.failure(CustomError(type: .genericError)))
return nil
}
#if RELEASE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success((let data, _)):
let response = try? JSONDecoder().decode(UserDetails.self, from: data)
completion(.success(response))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif APPSTORE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success((let data, _)):
let response = try? JSONDecoder().decode(UserDetails.self, from: data)
completion(.success(response))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif DEBUG
let task = temporarySession.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success((let data, _)):
let response = try? JSONDecoder().decode(UserDetails.self, from: data)
completion(.success(response))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#endif
task.resume()
return task
}
func postUserDetails(userDetails: UserDetails.User, completion: @escaping GetEmptyCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: UserProfileAPI(),
endpoint: UserProfileAPI.Path.postUserDetails(userDetails: userDetails, sessionID: sessionID)) else {
completion(.failure(CustomError(type: .genericError)))
return nil
}
#if RELEASE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif APPSTORE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif DEBUG
let task = temporarySession.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#endif
task.resume()
return task
}
func getDocuments(completion: @escaping GetDocumentsCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: UserProfileAPI(), endpoint: UserProfileAPI.Path.getDocuments(sessionID: sessionID)) else {
completion(.failure(CustomError(type: .genericError)))
return nil
}
#if RELEASE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
do {
let documentList = try JSONDecoder().decode(DocumentList.self, from: body.data)
completion(.success(documentList.receivedUserDocuments))
} catch {
completion(.failure(error))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif APPSTORE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
do {
let documentList = try JSONDecoder().decode(DocumentList.self, from: body.data)
completion(.success(documentList.receivedUserDocuments))
} catch {
completion(.failure(error))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif DEBUG
let task = temporarySession.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
do {
let documentList = try JSONDecoder().decode(DocumentList.self, from: body.data)
completion(.success(documentList.receivedUserDocuments))
} catch {
completion(.failure(error))
}
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#endif
task.resume()
return task
}
func manulalUserConversion(userManualConversion: UserManualConversion, completion: @escaping GetEmptyCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: UserProfileAPI(),
endpoint: UserProfileAPI.Path.manualConversion(userManualConversion: userManualConversion, sessionID: sessionID)) else {
completion(.failure(CustomError(type: .genericError)))
return nil
}
#if RELEASE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif APPSTORE
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#elseif DEBUG
let task = temporarySession.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
#endif
task.resume()
return task
}
@discardableResult
func changePassword(new: String,
old: String,
completion: @escaping (Result<Bool, Error>) -> ()) -> URLSessionDataTask? {
guard let userID = user.value?.id, let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.changePassword(new: new, old: old, userID: userID, sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(true))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func transactions(from: Date, to: Date,
pageSize size: Int?, offset: Int?,
completion: @escaping (Result<[Transaction]?, Error>) -> Void) -> URLSessionDataTask? {
guard let request =
URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.transactions(from: from, to: to, pageSize: size, offset: offset, sessionID: user.value?.sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
completion(.success(Transaction.transactions(dictionaries: body.json as? [[String: Any]])))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func transactionsWithdrawStatus(pageSize size: Int?, offset: Int?,
completion: @escaping (Result<[Transaction]?, Error>) -> Void) -> URLSessionDataTask? {
guard let request =
URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.transactionsWithdrawStatus(pageSize: size, offset: offset, sessionID: user.value?.sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
completion(.success(Transaction.transactions(dictionaries: body.json as? [[String: Any]])))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func cancelTransactionWithdrawal(transactionID: Int?, completion: @escaping (Result<Void, Error>) -> ()) -> URLSessionDataTask? {
guard let request =
URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.cancelTransactionWithdrawal(transactionID: transactionID, sessionID: user.value?.sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func placedBets(from: Date, to: Date, size: Int, status: PlacedBet.Status?, offset: Int,
completion: @escaping (Result<([PlacedBet]?, Int?), Error>) -> Void) -> URLSessionWork? {
guard let request =
URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.bettingHistory(from: from, to: to, size: size, type: status,
offset: offset, sessionID: user.value?.sessionID)) else {
return nil
}
let work = URLSessionWork()
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
let betsAndTheirIDs = PlacedBet.sAndTheirIDs(from: body.json as? [[String: Any]])
let bets = betsAndTheirIDs.bets
var count: Int? = nil
if let responseBody = body.json as? [[String: Any]], responseBody.count > 0, let totalCount = responseBody[0]["transactionsCount"] as? Int {
count = totalCount
}
guard let ids = betsAndTheirIDs.ids else {
return completion(.success((bets,count)))
}
work.append(self?.cashoutAmounts(bet: ids) { result in
if case .success(let amounts) = result {
amounts?.forEach({ (id, amount) in
bets?.first(where: { $0.id == id })?.cashout = amount
})
}
completion(.success((bets,count)))
})
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
work.append(task)
task.resume()
return work
}
@discardableResult
func cashoutAmounts(bet ids: [Int], completion: @escaping (Result<[Int: Double]?, Error>) -> ()) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.cashoutAmounts(betIDs: ids, sessionID: user.value?.sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
var amounts: [Int: Double]?
(body.json as? [String: [String: Any]])?.forEach {
if let value = $0.value["currentCashoutAmount"] as? Double,
let key = Int($0.key) {
if amounts == nil { amounts = [:]}
amounts?[key] = value
}
}
completion(.success(amounts))
return
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func checkAndCashout(betWith id: Int, amount: Double, acceptedChanges: Bool,
completion: @escaping (Result<Double, CashoutError>) -> ()) -> URLSessionWork? {
let endpoint = ETotoAPI.Path.cashoutAmountAndCountdownRequired(
betID: id,
sessionID: user.value?.sessionID
)
guard let request = URLRequest(api: ETotoAPI(),
endpoint: endpoint) else {
return nil
}
let work = URLSessionWork()
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
if let dict = body.json as? [AnyHashable: Any] {
if !acceptedChanges,
let current = dict["amount"] as? Double, current != amount {
return completion(.failure(.changed(amount: current)))
}
else if (dict["countDownRequired"] as? Bool) == true {
work.append(self?.cashoutCountdown(betID: id, amount: amount, acceptedChanges: acceptedChanges) { result in
switch result {
case .success(let countdown):
if let miliseconds = countdown {
DispatchQueue.global(qos: .userInteractive).asyncAfter(deadline: .now() + miliseconds / 1000) {
guard !work.canceled else { return }
work.append(self?.cashout(betWith: id, amount: amount,
acceptedChanges: acceptedChanges, completion: completion))
}
}
else {
work.append(self?.cashout(betWith: id, amount: amount,
acceptedChanges: acceptedChanges, completion: completion))
}
case .failure(let countdownError):
completion(.failure(countdownError))
}
})
}
else {
work.append(self?.cashout(betWith: id, amount: amount,
acceptedChanges: acceptedChanges, completion: completion))
}
}
case .failure(let error):
completion(.failure(.other(error: error)))
case .none:
break
}
}
task.resume()
work.append(task)
return work
}
@discardableResult
private func cashoutCountdown(
betID: Int, amount: Double, acceptedChanges: Bool,
completion: @escaping (Result<Double?, CashoutError>) -> ()) -> URLSessionDataTask? {
let endpoint = ETotoAPI.Path.cashoutCountdown(
betID: betID, amount: amount, acceptedChanges: acceptedChanges,
sessionID: user.value?.sessionID)
guard let request = URLRequest(api: ETotoAPI(),
endpoint: endpoint) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
if let dict = body.json as? [AnyHashable: Any] {
if let miliseconds = dict["value"] as? String {
return completion(.success(Double(miliseconds)))
} else if let changed = dict["amount"] as? Double ??
dict["currentCashoutAmount"] as? Double {
return completion(.failure(.changed(amount: changed)))
}
}
completion(.success(nil))
return
case .failure(let error):
completion(.failure(.other(error: error)))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func cashout(betWith id: Int, amount: Double, acceptedChanges: Bool,
completion: @escaping (Result<Double, CashoutError>) -> ()) -> URLSessionDataTask? {
let endpoint = ETotoAPI.Path.cashoutBet(
id: id, amount: amount, acceptedChanges: acceptedChanges,
sessionID: user.value?.sessionID)
guard let request = URLRequest(api: ETotoAPI(),
endpoint: endpoint) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
if let dict = body.json as? [AnyHashable: Any] {
if dict["success"] as? Bool == true {
return completion(.success(dict["currentCashoutAmount"] as? Double ?? amount))
} else {
if let changed = dict["currentCashoutAmount"] as? Double {
return completion(.failure(.changed(amount: changed)))
}
let error = URLError(
.unknown,
userInfo: [NSLocalizedDescriptionKey: dict["errorMessage"] as? String ?? ""])
return completion(.failure(.other(error: error)))
}
}
completion(.success(amount))
return
case .failure(let error):
completion(.failure(.other(error: error)))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getActivePaymentProviders(completion: @escaping GetActivePaymentProvidersCompletion) -> URLSessionDataTask? {
guard let sessionId = user.value?.sessionID,
let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.activePaymentProviders(sessionID:sessionId )) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let dictionaries = body.json as? [[String : Any]] else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(PaymentProvider.providers(dictionaries)))
return
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func initializePayment(providerId: Int,
transactionAmount: Decimal,
transactionCurrency:String,
completion: @escaping PostInitializePaymentCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID else { return nil }
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.initializePayment(providerId: providerId,
transactionAmount: transactionAmount,
transactionCurrency: transactionCurrency,
sessionID: sessionID)) else { return nil }
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let dictionaries = body.json as? [String:Any],
let success = dictionaries["success"] as? Bool else {
completion(.failure(WithdrawError.processFail))
return
}
if !success {
let code = dictionaries["responseCode"] as? Int
let error = self?.getMappedErrorForPayment(with: code) ?? WithdrawError.processFail
return completion(.failure(error))
}
completion(.success(()))
case .none:
return
case .some(.failure(let error)):
completion(.failure(error))
}
}
task.resume()
return task
}
private func getMappedErrorForPayment(with code: Int?) -> Error {
guard let code = code else {
return WithdrawError.processFail
}
guard let mappedError = Settings.etoto.paymentErrorMessages.first(where: {$0.code == code}) else {
if code == 47 {
return WithdrawError.activeCreditBonus
}
let error: Error
if let firebaseError = Settings.etoto.paymentErrorMessages.first(where: { $0.code == 0 }) {
error = firebaseError
} else {
error = WithdrawError.processFail
}
return error
}
return mappedError
}
//MARK: - Register -
@discardableResult
func baseRegistration(baseRegistration: BaseRegistration, completion: @escaping GetEmptyCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoRegisterAPI(),
endpoint: ETotoRegisterAPI.Path.baseRegistration(baseRegistration: baseRegistration)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(_):
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.allHeaderFields.keys)
if let xOddsSession = httpResponse.allHeaderFields[User.Key.sessionID.rawValue] as? String {
let user = User(dictionary: [:])
user?.sessionID = xOddsSession
self?.user.value = user
}
}
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func detailsRegistration(detailsRegistration: DetailsRegistration, completion: @escaping GetEmptyCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoRegisterAPI(),
endpoint: ETotoRegisterAPI.Path.detailRegistation(detailsRegistration: detailsRegistration,
sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func processPayment(providerId: Int,
transactionAmount: Double,
transactionCurrency: String,
callbackUrl: String,
bankDetail: BankDetail? = nil,
completion: @escaping PostProcessPaymentCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.processPayment(providerId: providerId,
transactionAmount: transactionAmount,
transactionCurrency: transactionCurrency,
callback: callbackUrl,
bankDetail: bankDetail,
sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let dictionaries = body.json as? [String:Any],
let success = dictionaries["success"] as? Bool else {
completion(.failure(WithdrawError.processFail))
return
}
if !success {
let code = dictionaries["responseCode"] as? Int
let error = self?.getMappedErrorForPayment(with: code) ?? WithdrawError.processFail
completion(.failure(error))
}
completion(.success(dictionaries["externalRequestUrl"] as? String ?? ""))
case .none:
return
case .some(.failure(let error)):
completion(.failure(error))
}
}
task.resume()
return task
}
@discardableResult
func customerBanksDetail(_ completion: @escaping GetCustomerBanksDetailCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoAPI(), endpoint: ETotoAPI.Path.customerBanksDetail(sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let dictionaries = body.json as? [[String : Any]]else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(BankDetail.banksDeail(dictionaries)))
return
case .none:
return
case .some(.failure(let error)):
completion(.failure(error))
}
}
task.resume()
return task
}
//TODO: ("Uncomment sessionID after tests")
func dateValidation(date: String, completion: @escaping GetValidationCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoRegisterAPI(baseURL: Settings.etoto.registrationValidationURL),
endpoint: ETotoRegisterAPI.Path.dateValidation(date: date, sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let data):
//TODO: ("Remove force in error casting")
guard let responseArray = try? JSONSerialization.jsonObject(with: data.data, options: []) as? [String] else { return }
if let httpResponse = response as? HTTPURLResponse {
if let xOddsSession = httpResponse.allHeaderFields[User.Key.sessionID.rawValue] as? String {
print(xOddsSession)
}
}
completion(.success((responseArray)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func iDNumberValidation(iDNumber: String, completion: @escaping GetValidationCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoRegisterAPI(baseURL: Settings.etoto.baseRegistrationsURL),
endpoint: ETotoRegisterAPI.Path.iDNumberValidation(iDNumber: iDNumber, sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let data):
guard let responseArray = try? JSONSerialization.jsonObject(with: data.data, options: []) as? [String] else { return }
completion(.success((responseArray)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func personalIDValidation(personalID: String, completion: @escaping GetValidationCompletion) -> URLSessionDataTask? {
guard
let sessionID = user.value?.sessionID,
let request = URLRequest(api: ETotoRegisterAPI(baseURL: Settings.etoto.baseRegistrationsURL),
endpoint: ETotoRegisterAPI.Path.personalIDValidation(personalID: personalID, sessionID: sessionID)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let data):
guard let responseArray = try? JSONSerialization.jsonObject(with: data.data, options: []) as? [String] else { return }
completion(.success((responseArray)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func bonusValidation(completion: @escaping GetValidationCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoRegisterAPI(baseURL: Settings.etoto.baseRegistrationsURL),
endpoint: ETotoRegisterAPI.Path.bonusValidation) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let data):
guard let responseArray = try? JSONSerialization.jsonObject(with: data.data, options: []) as? [String: Any],
let codes = responseArray["codes"] as? [String] else {
return
}
completion(.success((codes)))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func test( _ request: NSMutableURLRequest, completion: @escaping (Result<String?, Error>) -> ()) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID else {
return nil
}
request.addValue(sessionID, forHTTPHeaderField: "X-ODDS-SESSION")
let task = session.dataTask(with: request as URLRequest) { [weak self] (data, response, error) in
switch self?.handle(request: request as URLRequest, data: data, response: response, error: error) {
case .success(let body):
completion(.success(String(data: body.data, encoding: .utf8)))
return
case .none:
return
case .some(.failure(let error)):
completion(.failure(error))
return
}
}
task.resume()
return task
}
// MARK: - Virtuals
@discardableResult
func getVirtualsWebURL(query: [URLQueryItem]?,completion: @escaping GetVirtualsWebURL) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoVirtualsBettingAPI(),
endpoint: ETotoVirtualsBettingAPI.Path.launchGame(sessionID: user.value?.sessionID, query: query)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let json = try? JSONSerialization.jsonObject(with: body.data, options: []) as? [String: Any] else {
completion(.failure(.launchGame(errorMessage: URLError(.cannotParseResponse).localizedDescription)))
return
}
if let errorMessage = json["ErrorMSg"] as? String {
completion(.failure(ETotoVirtualsBettingAPIError.launchGame(errorMessage: errorMessage)))
return
}
guard let urlString = json["url"] as? String else {
completion(.failure(.launchGame(errorMessage: URLError(.cannotParseResponse).localizedDescription)))
return
}
let url = URL(string: urlString)
completion(.success(url))
case .failure(let error):
let virtualsError: ETotoVirtualsBettingAPIError
if let urlError = error as? URLError, urlError.code == .userAuthenticationRequired {
virtualsError = .userAuthenticationRequired(errorMessage: urlError.localizedDescription)
} else {
virtualsError = .launchGame(errorMessage: error.localizedDescription)
}
completion(.failure(virtualsError))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func setLimits(limits: [LimitRequestBody], completion: @escaping LimitCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.setLimits(sessionId: user.value?.sessionID, limits: limits)) else {
return nil
}
return limit(request: request, completion: completion)
}
private func limit(request: URLRequest, completion: @escaping LimitCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
guard let body = body.json as? [[String: Any]] else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(body.compactMap { LimitRequestResponse($0) }))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func acceptRegulations(completion: @escaping AcceptRegulationsCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: ETotoAPI(),
endpoint: ETotoAPI.Path.acceptRegulations(sessionID: user.value?.sessionID)) else {
return nil
}
return acceptRegulations(request: request, completion: completion)
}
private func acceptRegulations(request: URLRequest, completion: @escaping AcceptRegulationsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success:
completion(.success(()))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func limits(completion: @escaping (Result<[Limits]?, Error>) -> Void) -> URLSessionDataTask? {
guard let request = URLRequest(
api: ETotoAPI(),
endpoint: ETotoAPI.Path.limits(sessionID: user.value?.sessionID))
else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
completion(.success(Limits.limits(from: body.json as? [[String: Any]])))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func activate(
_ limitation: Limits.Limitation,
completion: @escaping (Result<[Limits]?, Error>) -> Void) -> URLSessionDataTask?
{
let endpoint = ETotoAPI.Path.activate(
limitation: limitation,
sessionID: user.value?.sessionID)
guard let request = URLRequest(
api: ETotoAPI(),
endpoint: endpoint)
else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
completion(.success(Limits.limits(from: body.json as? [[String: Any]])))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
// MARK: - Football events cache
func cachedFootballEvents() -> [Event]? {
return footballEventsCache
}
func cacheFootballEvents() {
getEvents(category: 1) { result in
switch result {
case .success(let events):
self.footballEventsCache = events
case .failure(_):
break
}
}
}
@objc private func invalidateFootballCache() {
footballEventsCache = nil
}
// MARK: - Notifications Settings
@discardableResult
func getNotificationsSettings(completion: @escaping GetNotificationsSettingsCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: UserProfileAPI(), endpoint: UserProfileAPI.Path.getNotificationsSettings(sessionID: sessionID)) else {
return nil
}
return getNotificationsSettings(request: request, completion: completion)
}
private func getNotificationsSettings(request: URLRequest, completion: @escaping GetNotificationsSettingsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
var string = String(data: body.data, encoding: .utf8)
log.debug(string)
guard let model = try? JSONDecoder().decode(NotificationConfigRequestModel.self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func postNotificationsSettings(model: NotificationConfigRequestModel,completion: @escaping PostNotificationsSettingsCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: UserProfileAPI(), endpoint: UserProfileAPI.Path.postNotificationsSettings(model: model, sessionID: sessionID)) else {
return nil
}
return postNotificationsSettings(request: request, completion: completion)
}
private func postNotificationsSettings(request: URLRequest, completion: @escaping PostNotificationsSettingsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success:
completion(.success(()))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
// MARK: - Chat
@discardableResult
func refreshChat(channelId: Int, completion: @escaping GetChatMessages) -> URLSessionDataTask? {
guard let request = URLRequest(api: ChatAPI(),
endpoint: ChatAPI.Path.refreshChat(channelId: channelId)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
guard let data = data else { return }
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
guard let model = try? JSONDecoder().decode([ChatMessage].self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
completion(.success([]))
}
}
task.resume()
return task
}
@discardableResult
func saveMessage(channelId: Int, completion: @escaping GetChatMessages) -> URLSessionDataTask? {
guard let request = URLRequest(api: ChatAPI(),
endpoint: ChatAPI.Path.refreshChat(channelId: channelId)) else {
return nil
}
refreshChatTask = session.dataTask(with: request) { [weak self] (data, response, error) in
guard let data = data else { return }
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
guard let model = try? JSONDecoder().decode([ChatMessage].self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
refreshChatTask?.resume()
return refreshChatTask
}
@discardableResult
func refreshChatOnChange(channelId: Int, lastId: Int, completion: @escaping GetChatMessages) -> URLSessionDataTask? {
guard let request = URLRequest(api: ChatAPI(),
endpoint: ChatAPI.Path.refreshOnChange(channelId: channelId, lastId: lastId)) else {
return nil
}
refreshChatOnChangeTask = session.dataTask(with: request) { [weak self] (data, response, error) in
guard let data = data else { return }
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
guard let model = try? JSONDecoder().decode([ChatMessage].self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
refreshChatOnChangeTask?.resume()
return refreshChatOnChangeTask
}
@discardableResult
func postChatMessage(messageBody: MessageBody, completion: @escaping GetEmptyCompletion) -> URLSessionDataTask? {
var cleanMessageBody = messageBody
let messageText = messageBody.messageText.literalized()
cleanMessageBody.messageText = messageText
guard
let sessionId = user.value?.sessionID,
let request = URLRequest(api: ChatAPI(),
endpoint: ChatAPI.Path.postMessage(messageBody: cleanMessageBody, sessionId: sessionId)) else {
return nil
}
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(_):
completion(.success(()))
case .failure(let error):
completion(.failure(CustomError(type: .genericError)))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getEventsValidForSubscription(completion: @escaping GetEventsValidForSubscriptionCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: SubscriptionAPI(), endpoint: SubscriptionAPI.Path.allEvents) else {
return nil
}
return getEventsValidForSubscription(request: request, completion: completion)
}
private func getEventsValidForSubscription(request: URLRequest, completion: @escaping GetEventsValidForSubscriptionCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let model = try? JSONDecoder().decode(EventsValidForSubscriptionModel.self, from: body.data) else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(model))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getSubscribedEvents(completion: @escaping GetSubscribedEventsCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: SubscriptionAPI(), endpoint: SubscriptionAPI.Path.customerEvents(sessionId: user.value?.sessionID ?? "")) else {
return nil
}
return getSubscribedEvents(request: request, completion: completion)
}
private func getSubscribedEvents(request: URLRequest, completion: @escaping GetSubscribedEventsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let model = try? JSONDecoder().decode(SubscribedEventsModel.self, from: body.data) else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(model))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func subscribeToEvent(eventId:Int,completion: @escaping SubscribeToEventCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: SubscriptionAPI(), endpoint: SubscriptionAPI.Path.subscribe(eventId: eventId, sessionId: user.value?.sessionID ?? "")) else {
return nil
}
return subscribeToEvent(request: request, completion: completion)
}
private func subscribeToEvent(request: URLRequest, completion: @escaping SubscribeToEventCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let model = try? JSONDecoder().decode(SubscribeToEventModel.self, from: body.data) else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(model))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func unsubscribeFromEvent(eventId:Int,completion: @escaping SubscribeToEventCompletion) -> URLSessionDataTask? {
guard let request = URLRequest(api: SubscriptionAPI(), endpoint: SubscriptionAPI.Path.unsubscribe(eventId: eventId, sessionId: user.value?.sessionID ?? "")) else {
return nil
}
return unsubscribeFromEvent(request: request, completion: completion)
}
private func unsubscribeFromEvent(request: URLRequest, completion: @escaping SubscribeToEventCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
switch self?.handle(request: request, data: data, response: response, error: error) {
case .success(let body):
guard let model = try? JSONDecoder().decode(SubscribeToEventModel.self, from: body.data) else {
completion(.failure(URLError(.cannotParseResponse)))
return
}
completion(.success(model))
case .failure(let error):
completion(.failure(error))
case .none:
break
}
}
task.resume()
return task
}
func cancelRunningChatViewTasks() {
refreshChatOnChangeTask?.cancel()
refreshChatTask?.cancel()
}
//MARK: Deposit
@discardableResult
func getPaymentMethods(completion: @escaping GetPaymentMethodsCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: PaymentsAPI(), endpoint: PaymentsAPI.Path.getPaymentMethods(sessionId: sessionID)) else {
return nil
}
return getPaymentMethods(request: request, completion: completion)
}
private func getPaymentMethods(request: URLRequest, completion: @escaping GetPaymentMethodsCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
let str = String(decoding: body.data, as: UTF8.self)
print(str)
guard var model = try? JSONDecoder().decode(GetPaymentMethodsResponse.self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
model.methods.sort { $0.sortOrder < $1.sortOrder }
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func startPayment(requestModel: PostStartPaymentRequest,completion: @escaping StartPaymentCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: PaymentsAPI(), endpoint: PaymentsAPI.Path.startPayment(sessionId: sessionID, requestModel: requestModel)) else {
return nil
}
return startPayment(request: request, completion: completion)
}
private func startPayment(request: URLRequest, completion: @escaping StartPaymentCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
let str = String(decoding: body.data, as: UTF8.self)
print(str)
guard let model = try? JSONDecoder().decode(PostStartPaymentResponse.self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func removeCardToken(token: String,completion: @escaping RemoveCardTokenCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: PaymentsAPI(), endpoint: PaymentsAPI.Path.removeCardToken(sessionId: sessionID, token: token)) else {
return nil
}
return removeCardToken(request: request, completion: completion)
}
private func removeCardToken(request: URLRequest, completion: @escaping RemoveCardTokenCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
let str = String(decoding: body.data, as: UTF8.self)
print(str)
// guard let model = try? JSONDecoder().decode(PostStartPaymentResponse.self, from: body.data) else {
// completion(.failure(.cannotParseResponse))
// return
// }
completion(.success(()))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
@discardableResult
func getStatus(orderID: String,completion: @escaping GetStatusCompletion) -> URLSessionDataTask? {
guard let sessionID = user.value?.sessionID,
let request = URLRequest(api: PaymentsAPI(), endpoint: PaymentsAPI.Path.getStatus(orderID: orderID)) else {
return nil
}
return getStatus(request: request, completion: completion)
}
private func getStatus(request: URLRequest, completion: @escaping GetStatusCompletion) -> URLSessionDataTask? {
let task = session.dataTask(with: request) { [weak self] (data, response, error) in
let result = self?.handle(request: request, data: data, response: response, error: error)
switch result {
case .success(let body):
let str = String(decoding: body.data, as: UTF8.self)
print(str)
guard let model = try? JSONDecoder().decode(GetPaymentStatusModel.self, from: body.data) else {
completion(.failure(.cannotParseResponse))
return
}
completion(.success(model))
case .failure:
completion(.failure(.unknown))
case .none:
break
}
}
task.resume()
return task
}
}
extension NetworkManager: URLSessionDelegate {
public func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
let urlCredential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, urlCredential)
}
}
Editor is loading...