DnsUpdater/Sources/App/Model/Files.swift
Christoph Hagen 9b6fd627ac First version
2024-11-15 10:46:29 +01:00

114 lines
3.3 KiB
Swift

import Foundation
struct Files {
let configuration: DnsConfiguration
var lastDataURL: URL {
.init(fileURLWithPath: configuration.lastUpdateFilePath)
}
var logFileURL: URL {
.init(fileURLWithPath: configuration.logFilePath)
}
var domainConfigurationURL: URL {
.init(fileURLWithPath: configuration.domainConfigFilePath)
}
init(configurationFileURL: URL) throws {
let data: Data
do {
data = try Data(contentsOf: configurationFileURL)
} catch {
throw DNSError.failedToReadLogFile(error)
}
do {
self.configuration = try JSONDecoder().decode(DnsConfiguration.self, from: data)
} catch {
throw DNSError.failedToDecodeLogFile(error)
}
}
func loadDomainConfiguration() throws -> DomainConfiguration {
let data: Data
do {
data = try Data(contentsOf: domainConfigurationURL)
} catch {
throw DNSError.failedToReadDomainConfiguration(error)
}
do {
return try JSONDecoder().decode(DomainConfiguration.self, from: data)
} catch {
throw DNSError.failedToDecodeDomainConfiguration(error)
}
}
func loadLastState() throws -> AppState {
guard FileManager.default.fileExists(atPath: configuration.lastUpdateFilePath) else {
return .init(date: Date(), state: .nominal, domainStates: [:])
}
let data: Data
do {
data = try Data(contentsOf: lastDataURL)
} catch {
throw DNSError.failedToReadLastState(error)
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
let state: AppState
do {
state = try decoder.decode(AppState.self, from: data)
} catch {
throw DNSError.failedToDecodeLastState(error)
}
return state
}
func save(lastState: AppState) throws {
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .secondsSince1970
encoder.outputFormatting = .prettyPrinted
let data: Data
do {
data = try encoder.encode(lastState)
} catch {
throw DNSError.failedToEncodeState(error)
}
do {
try data.write(to: lastDataURL)
} catch {
throw DNSError.failedToWriteState(error)
}
}
func addLogEntry(changedDomains: [String : DomainState]) throws {
if !FileManager.default.fileExists(atPath: configuration.logFilePath) {
do {
try Data().write(to: logFileURL)
} catch {
throw DNSError.failedToCreateDNSLog(error)
}
}
guard let handle = FileHandle(forUpdatingAtPath: logFileURL.path) else {
throw DNSError.failedToOpenDNSLogForWriting
}
let entry = changedDomains.map {
$1.logEntry(domain: $0)
}
.joined(separator: "\n") + "\n"
let entryData = entry.data(using: .utf8)!
do {
try handle.seekToEnd()
try handle.write(contentsOf: entryData)
try handle.close()
} catch {
throw DNSError.failedToWriteDNSLog(error)
}
}
}