diff --git a/lib/pangea/common/network/urls.dart b/lib/pangea/common/network/urls.dart index a667066c8..5bb4f2c86 100644 --- a/lib/pangea/common/network/urls.dart +++ b/lib/pangea/common/network/urls.dart @@ -86,4 +86,7 @@ class PApiUrls { static String rcProductsTrial = "${PApiUrls.subscriptionEndpoint}/free_trial"; static String rcSubscription = PApiUrls.subscriptionEndpoint; + + static String phoneticTranscription = + "${PApiUrls.choreoEndpoint}/phonetic_transcription"; } diff --git a/lib/pangea/phonetic_transcription/phonetic_transcription_repo.dart b/lib/pangea/phonetic_transcription/phonetic_transcription_repo.dart new file mode 100644 index 000000000..30eac8302 --- /dev/null +++ b/lib/pangea/phonetic_transcription/phonetic_transcription_repo.dart @@ -0,0 +1,66 @@ +import 'dart:convert'; +import 'dart:developer'; + +import 'package:fluffychat/pangea/common/config/environment.dart'; +import 'package:fluffychat/pangea/common/network/requests.dart'; +import 'package:fluffychat/pangea/common/network/urls.dart'; +import 'package:fluffychat/pangea/common/utils/error_handler.dart'; +import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_request.dart'; +import 'package:fluffychat/pangea/phonetic_transcription/phonetic_transcription_response.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/foundation.dart'; +import 'package:get_storage/get_storage.dart'; +import 'package:http/http.dart'; + +class PhoneticTranscriptionRepo { + static final GetStorage _storage = + GetStorage('phonetic_transcription_storage'); + + static void set(PhoneticTranscriptionRequest request, + PhoneticTranscriptionResponse response) { + response.expireAt ??= DateTime.now().add(const Duration(days: 100)); + _storage.write(request.storageKey, response.toJson()); + } + + static Future _fetch( + PhoneticTranscriptionRequest request) async { + final cachedJson = _storage.read(request.storageKey); + final cached = cachedJson == null + ? null + : PhoneticTranscriptionResponse.fromJson(cachedJson); + + if (cached != null) { + if (DateTime.now().isBefore(cached.expireAt!)) { + return cached; + } else { + _storage.remove(request.storageKey); + } + } + + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, + ); + + final Response res = await req.post( + url: PApiUrls.phoneticTranscription, + body: request.toJson(), + ); + + final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); + final response = PhoneticTranscriptionResponse.fromJson(decodedBody); + set(request, response); + return response; + } + + static Future get( + PhoneticTranscriptionRequest request) async { + try { + return await _fetch(request); + } catch (e) { + debugger(when: kDebugMode); + ErrorHandler.logError(e: e, data: request.toJson()); + rethrow; + } + } +} diff --git a/lib/pangea/phonetic_transcription/phonetic_transcription_request.dart b/lib/pangea/phonetic_transcription/phonetic_transcription_request.dart new file mode 100644 index 000000000..02dfcb7c7 --- /dev/null +++ b/lib/pangea/phonetic_transcription/phonetic_transcription_request.dart @@ -0,0 +1,33 @@ +class PhoneticTranscriptionRequest { + final String l1; + final String l2; + final String content; + final bool requiresTokenization; + + PhoneticTranscriptionRequest({ + required this.l1, + required this.l2, + required this.content, + this.requiresTokenization = true, + }); + + factory PhoneticTranscriptionRequest.fromJson(Map json) { + return PhoneticTranscriptionRequest( + l1: json['l1'] as String, + l2: json['l2'] as String, + content: json['content'] as String, + requiresTokenization: json['requires_tokenization'] ?? true, + ); + } + + Map toJson() { + return { + 'l1': l1, + 'l2': l2, + 'content': content, + 'requires_tokenization': requiresTokenization, + }; + } + + String get storageKey => 'l1:$l1,l2:$l2,content:$content'; +} diff --git a/lib/pangea/phonetic_transcription/phonetic_transcription_response.dart b/lib/pangea/phonetic_transcription/phonetic_transcription_response.dart new file mode 100644 index 000000000..9efce60d4 --- /dev/null +++ b/lib/pangea/phonetic_transcription/phonetic_transcription_response.dart @@ -0,0 +1,55 @@ +class PhoneticTranscriptionResponse { + final Map arc; + final Map content; + final Map tokenization; + final Map phoneticTranscriptionResult; + DateTime? expireAt; + + PhoneticTranscriptionResponse({ + required this.arc, + required this.content, + required this.tokenization, + required this.phoneticTranscriptionResult, + this.expireAt, + }); + + factory PhoneticTranscriptionResponse.fromJson(Map json) { + return PhoneticTranscriptionResponse( + arc: Map.from(json['arc'] as Map), + content: Map.from(json['content'] as Map), + tokenization: Map.from(json['tokenization'] as Map), + phoneticTranscriptionResult: Map.from( + json['phonetic_transcription_result'] as Map), + expireAt: json['expireAt'] == null + ? null + : DateTime.parse(json['expireAt'] as String), + ); + } + + Map toJson() { + return { + 'arc': arc, + 'content': content, + 'tokenization': tokenization, + 'phonetic_transcription_result': phoneticTranscriptionResult, + 'expireAt': expireAt?.toIso8601String(), + }; + } + + @override + bool operator ==(Object other) => + identical(this, other) || + other is PhoneticTranscriptionResponse && + runtimeType == other.runtimeType && + arc == other.arc && + content == other.content && + tokenization == other.tokenization && + phoneticTranscriptionResult == other.phoneticTranscriptionResult; + + @override + int get hashCode => + arc.hashCode ^ + content.hashCode ^ + tokenization.hashCode ^ + phoneticTranscriptionResult.hashCode; +} diff --git a/lib/pangea/phonetic_transcription/test_phonetic_transcription_api.dart b/lib/pangea/phonetic_transcription/test_phonetic_transcription_api.dart new file mode 100644 index 000000000..e69de29bb