8f8f8b2755
macOS menu bar app providing NHL game situational awareness with league-wide scoreboard, dynamic polling, notifications with team logos, and configurable display options.
46 lines
1.3 KiB
Swift
46 lines
1.3 KiB
Swift
//
|
|
// ApiService.swift
|
|
// IceGlass
|
|
//
|
|
// Copyright 2026 Rouslan Zenetl. All Rights Reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
typealias ApiServiceCallback = (_ jsonData: Data, _ response: URLResponse) -> Void
|
|
|
|
class ApiService: @unchecked Sendable {
|
|
private let logger = IceGlassLogger(
|
|
subsystem: Bundle.main.bundleIdentifier ?? "dev.rzen.indie.IceGlass",
|
|
category: "ApiService"
|
|
)
|
|
|
|
let url: URL
|
|
let callback: ApiServiceCallback
|
|
|
|
var previousFetchTime: Date = .distantPast
|
|
|
|
init(url: URL?, callback: @escaping ApiServiceCallback) {
|
|
guard let url = url else {
|
|
AppTerminator.terminate()
|
|
self.url = URL(string: "")!
|
|
self.callback = { (_: Data, _: URLResponse) in }
|
|
return
|
|
}
|
|
self.url = url
|
|
self.callback = callback
|
|
}
|
|
|
|
func fetch() async {
|
|
do {
|
|
let (data, response) = try await URLSession.shared.data(from: url)
|
|
logger.info("Polling: \(self.url)")
|
|
logger.debug("Previous: \(Date.now.timeIntervalSince(previousFetchTime).humanReadableTime())")
|
|
previousFetchTime = Date.now
|
|
callback(data, response)
|
|
} catch {
|
|
logger.error("Invalid response from \(self.url) \(error)")
|
|
}
|
|
}
|
|
}
|