Files
iKeyMon/Sources/Model/API/PingService.swift

77 lines
2.9 KiB
Swift

import Foundation
import UserNotifications
enum PingService {
private static var previousPingStates: [String: Bool] = [:]
private static var suppressedUntil: [String: Date] = [:]
static func suppressChecks(for hostname: String, duration: TimeInterval) {
suppressedUntil[hostname] = Date().addingTimeInterval(duration)
}
static func ping(hostname: String, apiKey: String, notificationsEnabled: Bool = true) async -> Bool {
if let suppressedUntil = suppressedUntil[hostname], suppressedUntil > Date() {
return false
} else {
suppressedUntil.removeValue(forKey: hostname)
}
guard let url = URL(string: "https://\(hostname)/api/v2/ping") else {
print("❌ [PingService] Invalid URL for \(hostname)")
return false
}
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue(apiKey, forHTTPHeaderField: "X-API-KEY")
request.timeoutInterval = 10
do {
let (data, response) = try await URLSession.shared.data(for: request)
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
handlePingFailure(for: hostname, notificationsEnabled: notificationsEnabled)
return false
}
if let result = try? JSONDecoder().decode([String: String].self, from: data), result["response"] == "pong" {
handlePingSuccess(for: hostname, notificationsEnabled: notificationsEnabled)
return true
} else {
handlePingFailure(for: hostname, notificationsEnabled: notificationsEnabled)
return false
}
} catch {
handlePingFailure(for: hostname, notificationsEnabled: notificationsEnabled)
return false
}
}
private static func handlePingSuccess(for hostname: String, notificationsEnabled: Bool) {
let wasPreviouslyDown = previousPingStates[hostname] == false
previousPingStates[hostname] = true
if wasPreviouslyDown && notificationsEnabled {
sendNotification(title: "Server Online", body: "\(hostname) is now online")
}
}
private static func handlePingFailure(for hostname: String, notificationsEnabled: Bool) {
let wasPreviouslyUp = previousPingStates[hostname] != false
previousPingStates[hostname] = false
if wasPreviouslyUp && notificationsEnabled {
sendNotification(title: "Server Offline", body: "\(hostname) is offline")
}
}
private static func sendNotification(title: String, body: String) {
let content = UNMutableNotificationContent()
content.title = title
content.body = body
content.sound = .default
let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil)
UNUserNotificationCenter.current().add(request)
}
}