mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
121 lines
2.5 KiB
Swift
121 lines
2.5 KiB
Swift
//
|
|
// OPMLFile.swift
|
|
// Account
|
|
//
|
|
// Created by Maurice Parker on 9/12/19.
|
|
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import os
|
|
import Parser
|
|
import Core
|
|
|
|
@MainActor final class OPMLFile {
|
|
|
|
private let fileURL: URL
|
|
private let account: Account
|
|
private let dataFile: DataFile
|
|
|
|
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "OPMLFile")
|
|
|
|
init(filename: String, account: Account) {
|
|
|
|
self.account = account
|
|
self.fileURL = URL(fileURLWithPath: filename)
|
|
self.dataFile = DataFile(fileURL: self.fileURL)
|
|
|
|
self.dataFile.delegate = self
|
|
}
|
|
|
|
func markAsDirty() {
|
|
|
|
dataFile.markAsDirty()
|
|
}
|
|
|
|
func opmlItems() -> [OPMLItem]? {
|
|
guard let fileData = opmlFileData() else {
|
|
return nil
|
|
}
|
|
|
|
return parsedOPMLItems(fileData: fileData)
|
|
}
|
|
|
|
func save() {
|
|
|
|
dataFile.save()
|
|
}
|
|
}
|
|
|
|
private extension OPMLFile {
|
|
|
|
func opmlFileData() -> Data? {
|
|
var fileData: Data? = nil
|
|
|
|
do {
|
|
fileData = try Data(contentsOf: fileURL)
|
|
} catch {
|
|
logger.error("OPML read from disk failed for \(self.fileURL): \(error.localizedDescription)")
|
|
}
|
|
|
|
return fileData
|
|
}
|
|
|
|
func parsedOPMLItems(fileData: Data) -> [OPMLItem]? {
|
|
let parserData = ParserData(url: fileURL.absoluteString, data: fileData)
|
|
let opmlDocument = OPMLParser.document(with: parserData)
|
|
return opmlDocument?.items
|
|
}
|
|
|
|
func opmlDocument() -> String {
|
|
let escapedTitle = account.nameForDisplay.escapingSpecialXMLCharacters
|
|
let openingText =
|
|
"""
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!-- OPML generated by NetNewsWire -->
|
|
<opml version="1.1">
|
|
<head>
|
|
<title>\(escapedTitle)</title>
|
|
</head>
|
|
<body>
|
|
|
|
"""
|
|
|
|
let middleText = account.OPMLString(indentLevel: 0, allowCustomAttributes: true)
|
|
|
|
let closingText =
|
|
"""
|
|
</body>
|
|
</opml>
|
|
"""
|
|
|
|
let opml = openingText + middleText + closingText
|
|
return opml
|
|
}
|
|
}
|
|
|
|
extension OPMLFile: DataFileDelegate {
|
|
|
|
func data(for dataFile: DataFile) -> Data? {
|
|
|
|
guard !account.isDeleted else {
|
|
return nil
|
|
}
|
|
|
|
let opmlDocumentString = opmlDocument()
|
|
guard let data = opmlDocumentString.data(using: .utf8, allowLossyConversion: true) else {
|
|
|
|
assertionFailure("OPML String conversion to Data failed for \(self.fileURL).")
|
|
logger.error("OPML String conversion to Data failed for \(self.fileURL)")
|
|
return nil
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
func dataFileWriteToDiskDidFail(for dataFile: DataFile, error: Error) {
|
|
|
|
logger.error("OPML save to disk failed for \(self.fileURL): \(error.localizedDescription)")
|
|
}
|
|
}
|