Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Read your Safari Reading List and dump to plain text
import Foundation
func fatalerror(_ text : String) {
fputs(text, __stderrp)
exit(-1)
}
struct ReadingListItem {
init(title: String?, previewText: String?, url: URL, dateAdded: Date) {
self.title = title
self.previewText = previewText
self.url = url
self.dateAdded = dateAdded
}
let title : String?
let previewText : String?
let url : URL
let dateAdded : Date
}
var items = [ReadingListItem]()
let outputPath = "/Users/yaakov/Sync/Personal/readinglist"
let libraryDirectory = NSSearchPathForDirectoriesInDomains(.libraryDirectory, .userDomainMask, true)[0]
if let
bookmarks = NSDictionary(contentsOfFile: "\(outputPath)/Bookmarks.plist"),
let children = bookmarks["Children"] as? [NSDictionary] {
for var item in children {
if item["WebBookmarkType"] as? String != "WebBookmarkTypeList" || item["Title"] as? String != "com.apple.ReadingList" {
continue
}
let readingListItems = item["Children"] as? [NSDictionary]
if let readingListItems = readingListItems {
for var currentItem in readingListItems {
let title = (currentItem["URIDictionary"] as? NSDictionary)?["title"] as? String
let uri = currentItem["URLString"] as? String
let rldata = currentItem["ReadingList"] as? NSDictionary
let preview = rldata?["PreviewText"] as? String
let date = rldata?["DateAdded"] as? Date
if let _ = title, let _ = uri {
print()
} else {
fatalerror("Missing title or uri for item.")
}
if date == nil {
fatalerror("Missing date for item.")
}
if let urlText = uri, let url = URL(string: urlText) {
let item = ReadingListItem(title: title, previewText: preview, url: url, dateAdded: date!)
items.append(item)
}
}
} else {
fatalerror("Could not find a Reading List bookmarks set.")
}
}
} else {
fatalerror("Unable to load Safari Bookmarks.")
}
let itemsByDomain = Dictionary(grouping: items, by: { $0.url.host?.lowercased() ?? "unknown" })
print("Found \(itemsByDomain.values.count) items across \(itemsByDomain.keys.count) domains.")
var domains = Array(itemsByDomain.keys)
for var domain in domains {
let domainItems = itemsByDomain[domain]!.sorted(by: { $0.dateAdded < $1.dateAdded })
var text = ""
for var item in domainItems {
text += item.dateAdded.description + "\n"
if let title = item.title {
text += title + "\n"
}
text += item.url.absoluteString + "\n"
if let preview = item.previewText {
text += preview + "\n"
}
text += "\n----\n\n"
}
try text.write(toFile: outputPath + "/" + domain + ".txt", atomically: true, encoding: .utf8)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment