damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

commit 6ac68b5a737cdabb4e2c6c15dfabc620cadaa532
parent 2048e68d67d6efa219ece0c20fa6fb37d8ac02f7
Author: symbsrcool <nostr9779@pm.me>
Date:   Sun, 16 Apr 2023 22:29:40 -0400

Add nokyctranslate translation option

Changelog-Added: Add nokyctranslate translation option
Closes: #946

Diffstat:
Mdamus/Models/TranslationService.swift | 3+++
Mdamus/Models/UserSettingsStore.swift | 38+++++++++++++++++++++++++++++++++++++-
Mdamus/Util/Translator.swift | 25+++++++++++++++++++++++++
Mdamus/Views/Settings/TranslationSettingsView.swift | 11+++++++++++
4 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/damus/Models/TranslationService.swift b/damus/Models/TranslationService.swift @@ -31,6 +31,7 @@ enum TranslationService: String, CaseIterable, Identifiable, StringCodable { case none case libretranslate case deepl + case nokyctranslate var model: Model { switch self { @@ -40,6 +41,8 @@ enum TranslationService: String, CaseIterable, Identifiable, StringCodable { return .init(tag: self.rawValue, displayName: NSLocalizedString("LibreTranslate (Open Source)", comment: "Dropdown option for selecting LibreTranslate as the translation service.")) case .deepl: return .init(tag: self.rawValue, displayName: NSLocalizedString("DeepL (Proprietary, Higher Accuracy)", comment: "Dropdown option for selecting DeepL as the translation service.")) + case .nokyctranslate: + return .init(tag: self.rawValue, displayName: NSLocalizedString("NoKYCTranslate.com (Prepay with BTC)", comment: "Dropdown option for selecting NoKYCTranslate.com as the translation service.")) } } diff --git a/damus/Models/UserSettingsStore.swift b/damus/Models/UserSettingsStore.swift @@ -196,6 +196,20 @@ class UserSettingsStore: ObservableObject { } } } + + @Published var nokyctranslate_api_key: String { + didSet { + do { + if nokyctranslate_api_key == "" { + try clearNoKYCTranslateApiKey() + } else { + try saveNoKYCTranslateApiKey(nokyctranslate_api_key) + } + } catch { + // No-op. + } + } + } init() { do { @@ -203,6 +217,13 @@ class UserSettingsStore: ObservableObject { } catch { deepl_api_key = "" } + + do { + nokyctranslate_api_key = try Vault.getPrivateKey(keychainConfiguration: DamusNoKYCTranslateKeychainConfiguration()) + } catch { + nokyctranslate_api_key = "" + } + } private func saveLibreTranslateApiKey(_ apiKey: String) throws { @@ -213,6 +234,14 @@ class UserSettingsStore: ObservableObject { try Vault.deletePrivateKey(keychainConfiguration: DamusLibreTranslateKeychainConfiguration()) } + private func saveNoKYCTranslateApiKey(_ apiKey: String) throws { + try Vault.savePrivateKey(apiKey, keychainConfiguration: DamusNoKYCTranslateKeychainConfiguration()) + } + + private func clearNoKYCTranslateApiKey() throws { + try Vault.deletePrivateKey(keychainConfiguration: DamusNoKYCTranslateKeychainConfiguration()) + } + private func saveDeepLApiKey(_ apiKey: String) throws { try Vault.savePrivateKey(apiKey, keychainConfiguration: DamusDeepLKeychainConfiguration()) } @@ -229,6 +258,8 @@ class UserSettingsStore: ObservableObject { return URLComponents(string: libretranslate_url) != nil case .deepl: return deepl_api_key != "" + case .nokyctranslate: + return nokyctranslate_api_key != "" } } } @@ -245,7 +276,12 @@ struct DamusDeepLKeychainConfiguration: KeychainConfiguration { var accountName = "deepl_apikey" } +struct DamusNoKYCTranslateKeychainConfiguration: KeychainConfiguration { + var serviceName = "damus" + var accessGroup: String? = nil + var accountName = "nokyctranslate_apikey" +} + func pk_setting_key(_ pubkey: String, key: String) -> String { return "\(pubkey)_\(key)" } - diff --git a/damus/Util/Translator.swift b/damus/Util/Translator.swift @@ -24,6 +24,8 @@ public struct Translator { switch userSettingsStore.translation_service { case .libretranslate: return try await translateWithLibreTranslate(text, from: sourceLanguage, to: targetLanguage) + case .nokyctranslate: + return try await translateWithNoKYCTranslate(text, from: sourceLanguage, to: targetLanguage) case .deepl: return try await translateWithDeepL(text, from: sourceLanguage, to: targetLanguage) case .none: @@ -85,6 +87,29 @@ public struct Translator { let response: Response = try await decodedData(for: request) return response.translations.map { $0.text }.joined(separator: " ") } + + private func translateWithNoKYCTranslate(_ text: String, from sourceLanguage: String, to targetLanguage: String) async throws -> String? { + let url = try makeURL("https://translate.nokyctranslate.com", path: "/translate") + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + + struct RequestBody: Encodable { + let q: String + let source: String + let target: String + let api_key: String? + } + let body = RequestBody(q: text, source: sourceLanguage, target: targetLanguage, api_key: userSettingsStore.nokyctranslate_api_key) + request.httpBody = try encoder.encode(body) + + struct Response: Decodable { + let translatedText: String + } + let response: Response = try await decodedData(for: request) + return response.translatedText + } private func makeURL(_ baseUrl: String, path: String) throws -> URL { guard var components = URLComponents(string: baseUrl) else { diff --git a/damus/Views/Settings/TranslationSettingsView.swift b/damus/Views/Settings/TranslationSettingsView.swift @@ -65,6 +65,17 @@ struct TranslationSettingsView: View { } } + if settings.translation_service == .nokyctranslate { + SecureField(NSLocalizedString("API Key (required)", comment: "Prompt for optional entry of API Key to use translation server."), text: $settings.nokyctranslate_api_key) + .disableAutocorrection(true) + .disabled(settings.translation_service != .nokyctranslate) + .autocapitalization(UITextAutocapitalizationType.none) + + if settings.nokyctranslate_api_key == "" { + Link(NSLocalizedString("Get API Key with BTC/Lightning", comment: "Button to navigate to nokyctranslate website to get a translation API key."), destination: URL(string: "https://nokyctranslate.com")!) + } + } + if settings.translation_service != .none { Toggle(NSLocalizedString("Automatically translate notes", comment: "Toggle to automatically translate notes."), isOn: $settings.auto_translate) .toggleStyle(.switch)