forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWebSearchService.swift
More file actions
75 lines (63 loc) · 2.1 KB
/
WebSearchService.swift
File metadata and controls
75 lines (63 loc) · 2.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import Foundation
import Preferences
import Keychain
public enum WebSearchProvider {
public enum SerpAPIEngine: String {
case google
case baidu
case bing
case duckDuckGo = "duckduckgo"
}
public enum HeadlessBrowserEngine: String {
case google
case baidu
case bing
case duckDuckGo = "duckduckgo"
}
case serpAPI(SerpAPIEngine, apiKey: String)
case headlessBrowser(HeadlessBrowserEngine)
case appleDocumentation
public static var userPreferred: WebSearchProvider {
switch UserDefaults.shared.value(for: \.searchProvider) {
case .headlessBrowser:
return .headlessBrowser(.init(
rawValue: UserDefaults.shared.value(for: \.headlessBrowserEngine).rawValue
) ?? .google)
case .serpAPI:
let apiKeyName = UserDefaults.shared.value(for: \.serpAPIKeyName)
return .serpAPI(.init(
rawValue: UserDefaults.shared.value(for: \.serpAPIEngine).rawValue
) ?? .google, apiKey: (try? Keychain.apiKey.get(apiKeyName)) ?? "")
}
}
}
public struct WebSearchResult: Equatable {
public struct WebPage: Equatable {
public var urlString: String
public var title: String
public var snippet: String
}
public var webPages: [WebPage]
}
public protocol SearchService {
func search(query: String) async throws -> WebSearchResult
}
public struct WebSearchService {
let service: SearchService
init(service: SearchService) {
self.service = service
}
public init(provider: WebSearchProvider) {
switch provider {
case let .serpAPI(engine, apiKey):
service = SerpAPISearchService(engine: engine, apiKey: apiKey)
case let .headlessBrowser(engine):
service = HeadlessBrowserSearchService(engine: engine)
case .appleDocumentation:
service = AppleDocumentationSearchService()
}
}
public func search(query: String) async throws -> WebSearchResult {
return try await service.search(query: query)
}
}