import Foundation struct ChatGPTAnalysisParser: ImportParser { func parse(sourceURL: URL, dedupIndex: DedupIndex) throws -> ImportParseResult { let files = try ImportFiles.immediateFiles( at: sourceURL, expected: "eine ChatGPT-Analysis-.json-Datei oder einen Ordner mit .json-Dateien", directFileMatches: { $0.pathExtension.lowercased() == "json" }, directoryFileMatches: { $0.pathExtension.lowercased() == "json" } ) var accumulator = ImportAccumulator( minimumLength: 50, maximumLength: 2_000, dedupIndex: dedupIndex ) for fileURL in files { let root: Any do { root = try ImportJSON.object(from: fileURL) } catch { accumulator.skipMalformed() continue } guard let object = root as? [String: Any] else { accumulator.skipMalformed() continue } let cluster = object["cluster"] as? String ?? fileURL.lastPathComponent guard let quotes = object["quotes_with_source"] as? [Any] else { accumulator.skipMalformed() continue } for quote in quotes { let text: String? if let quote = quote as? String { text = quote } else if let quote = quote as? [String: Any] { text = quote["quote"] as? String ?? quote["text"] as? String } else { text = nil } guard let text else { accumulator.skipMalformed(scanned: true) continue } accumulator.accept( text, sourcePrefix: "chatgpt-import", tags: normalizedClusterTag(cluster) ) } } return accumulator.result() } private func normalizedClusterTag(_ cluster: String) -> String { cluster .lowercased() .replacingOccurrences(of: "/", with: ",") .replacingOccurrences(of: " ", with: "-") } }