spotlight.swift

 1import Foundation
 2import CoreSpotlight
 3import MobileCoreServices
 4
 5// Compilation: swiftc spotlight.swift -o spotlight
 6// Usage: ./spotlight <json_of_emails>
 7
 8struct EmailToIndex: Codable {
 9    let id: String
10    let subject: String
11    let sender: String
12    let body: String
13    let date: Date
14}
15
16func indexEmails(jsonString: String) {
17    guard let data = jsonString.data(using: .utf8),
18          let emails = try? JSONDecoder().decode([EmailToIndex].self, from: data) else {
19        print("Error: Invalid JSON")
20        exit(1)
21    }
22    
23    var searchableItems: [CSSearchableItem] = []
24    
25    for email in emails {
26        let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeEmailMessage as String)
27        attributeSet.title = email.subject
28        attributeSet.contentDescription = email.body
29        attributeSet.authorNames = [email.sender]
30        attributeSet.contentCreationDate = email.date
31        
32        let item = CSSearchableItem(
33            uniqueIdentifier: email.id,
34            domainIdentifier: "com.floatpane.matcha.emails",
35            attributeSet: attributeSet
36        )
37        searchableItems.append(item)
38    }
39    
40    CSSearchableIndex.default().indexSearchableItems(searchableItems) { error in
41        if let error = error {
42            print("Error indexing items: \(error.localizedDescription)")
43            exit(1)
44        } else {
45            print("Successfully indexed \(searchableItems.count) emails")
46            exit(0)
47        }
48    }
49}
50
51let args = ProcessInfo.processInfo.arguments
52if args.count > 1 {
53    indexEmails(jsonString: args[1])
54} else {
55    let input = FileHandle.standardInput.readDataToEndOfFile()
56    if let text = String(data: input, encoding: .utf8) {
57        indexEmails(jsonString: text)
58    }
59}
60
61RunLoop.main.run()