diff --git a/CHANGELOG.md b/CHANGELOG.md index c536d89..e07063f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Changes + +- Add Apple Photos as a coming-soon built-in crawler with read-only status, refresh, search, platform-native storage paths, and configurable library selection. + ### Fixes - Install OpenClaw crawler apps from the current Homebrew tap instead of legacy formulas that lag released versions. diff --git a/README.md b/README.md index 2a70b64..2a576ef 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Built-in manifests ship for: - `discrawl` - `telecrawl` - `imsgcrawl` +- `photoscrawl` (coming soon) - `notcrawl` - `gogcli` through the `gog` executable - `wacli` diff --git a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift new file mode 100644 index 0000000..3cbff62 --- /dev/null +++ b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps+Photoscrawl.swift @@ -0,0 +1,48 @@ +import Foundation + +public extension BuiltInCrawlApps { + static let photoscrawl = CrawlAppManifest( + id: Self.photoscrawlID, + displayName: "Apple Photos", + description: "Local-first, read-only Apple Photos archive crawler", + availability: .comingSoon, + binary: .init(name: "photoscrawl"), + branding: .init( + symbolName: "photo.on.rectangle.angled", + accentColor: "#FF2D55", + bundleIdentifier: "com.apple.Photos"), + paths: .init( + defaultConfig: "~/Library/Application Support/photoscrawl/config.toml", + defaultDatabase: "~/Library/Application Support/photoscrawl/photos.sqlite", + defaultCache: "~/Library/Caches/photoscrawl", + defaultLogs: "~/Library/Application Support/photoscrawl/logs", + defaultShare: "~/Library/Application Support/photoscrawl/share"), + commands: [ + "metadata": ["metadata", "--json"], + "status": ["status", "--json"], + "refresh": ["crawl", "--library", "{config:library_path}", "--json"], + "query": ["search", "--json", "--query"], + ], + capabilities: [.status, .refresh, .search], + statusRequiresSecrets: false, + privacy: .init( + exportsSecrets: false, + localOnlyScopes: [ + "apple-photos", + "sqlite", + "media-metadata", + "location-observations", + "local-model-observations", + ]), + configOptions: [ + .init( + id: "library_path", + label: "Photos library", + help: "Photos Library package read by refresh; photoscrawl expands a leading ~/ path.", + defaultValue: "~/Pictures/Photos Library.photoslibrary"), + ], + configSections: [ + .init(id: "photos", title: "Photos Library", optionIDs: ["library_path"]), + ]) + .withSuggestion(Self.appSuggest("Photos", ["com.apple.Photos"])) +} diff --git a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift index d92e410..ce16f50 100644 --- a/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift +++ b/Sources/CrawlBarCore/BuiltInApps/BuiltInCrawlApps.swift @@ -6,6 +6,7 @@ public enum BuiltInCrawlApps { public static let discrawlID = CrawlAppID(rawValue: "discrawl") public static let telecrawlID = CrawlAppID(rawValue: "telecrawl") public static let imsgcrawlID = CrawlAppID(rawValue: "imsgcrawl") + public static let photoscrawlID = CrawlAppID(rawValue: "photoscrawl") public static let notcrawlID = CrawlAppID(rawValue: "notcrawl") public static let gogcliID = CrawlAppID(rawValue: "gogcli") public static let wacliID = CrawlAppID(rawValue: "wacli") @@ -18,6 +19,7 @@ public enum BuiltInCrawlApps { Self.discrawl, Self.telecrawl, Self.imsgcrawl, + Self.photoscrawl, Self.notcrawl, Self.gogcli, Self.wacli, diff --git a/Sources/CrawlBarSelfTest/SelfTestConfig.swift b/Sources/CrawlBarSelfTest/SelfTestConfig.swift index f9b1b6e..5ae6a1a 100644 --- a/Sources/CrawlBarSelfTest/SelfTestConfig.swift +++ b/Sources/CrawlBarSelfTest/SelfTestConfig.swift @@ -14,6 +14,11 @@ extension CrawlBarSelfTest { try Self.expect(config.apps.map(\.id) == BuiltInCrawlApps.all.map(\.id), "built-in apps are present") try Self.expect(config.appConfig(for: BuiltInCrawlApps.gogcliID)?.enabled == true, "new Google app normalizes enabled") try Self.expect(config.appConfig(for: BuiltInCrawlApps.gogcliID)?.showInMenuBar == true, "new Google app appears in menu bar") + try Self.expect(config.appConfig(for: BuiltInCrawlApps.photoscrawlID)?.enabled == false, "coming-soon Photos crawler normalizes disabled") + try Self.expect(BuiltInCrawlApps.photoscrawl.availability == .comingSoon, "Photos crawler remains coming soon without an installer") + try Self.expect( + BuiltInCrawlApps.photoscrawl.commands["refresh"] == ["crawl", "--library", "{config:library_path}", "--json"], + "Photos refresh uses the configured library path") let oldConfig = CrawlBarConfig( version: 1, apps: [CrawlBarAppConfig(id: BuiltInCrawlApps.wacliID, enabled: false, showInMenuBar: false)]).normalized()