diff --git a/lib/pangea/config/environment.dart b/lib/pangea/config/environment.dart index 4d4378999..c9069e183 100644 --- a/lib/pangea/config/environment.dart +++ b/lib/pangea/config/environment.dart @@ -56,6 +56,7 @@ class Environment { return dotenv.env["RC_IOS_KEY"] ?? 'appl_DUPqnxuLjkBLzhBPTWeDjqNENuv'; } + // This is a public key static String get rcStripeKey { return dotenv.env["RC_STRIPE_KEY"] ?? 'strp_YWZxWUeEfvagiefDNoofinaRCOl'; } diff --git a/lib/pangea/controllers/subscription_controller.dart b/lib/pangea/controllers/subscription_controller.dart index cffd64748..d9b720129 100644 --- a/lib/pangea/controllers/subscription_controller.dart +++ b/lib/pangea/controllers/subscription_controller.dart @@ -327,7 +327,10 @@ class SubscriptionController extends BaseController { SubscriptionDuration duration, { bool isPromo = false, }) async { - final Requests req = Requests(baseUrl: PApiUrls.baseAPI); + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: _pangeaController.userController.accessToken, + ); final String reqUrl = Uri.encodeFull( "${PApiUrls.paymentLink}?pangea_user_id=$userID&duration=${duration.value}&redeem=$isPromo", ); diff --git a/lib/pangea/controllers/user_controller.dart b/lib/pangea/controllers/user_controller.dart index 381c08c4d..53893cb7b 100644 --- a/lib/pangea/controllers/user_controller.dart +++ b/lib/pangea/controllers/user_controller.dart @@ -10,7 +10,6 @@ import 'package:jwt_decode/jwt_decode.dart'; import 'package:matrix/matrix.dart' as matrix; import '../models/user_model.dart'; -import '../repo/user_repo.dart'; /// Controller that manages saving and reading of user/profile information class UserController extends BaseController { @@ -124,26 +123,6 @@ class UserController extends BaseController { // wait for account data to load // as long as it's not null, then this we've already migrated the profile await _pangeaController.matrixState.client.waitForAccountData(); - if (profile.userSettings.dateOfBirth != null) { - return; - } - - // we used to store the user's profile in the pangea server - // we now store it in the matrix account data - final PangeaProfileResponse? resp = await PUserRepo.fetchPangeaUserInfo( - userID: userId!, - matrixAccessToken: _matrixAccessToken!, - ); - - // if it's null, we don't have a profile in the pangea server - if (resp?.profile == null) { - return; - } - - // if we have a profile in the pangea server, we need to migrate it to the matrix account data - final userSetting = UserSettings.fromJson(resp!.profile.toJson()); - final newProfile = Profile(userSettings: userSetting); - await newProfile.saveProfileData(waitForDataInSync: true); } /// Reinitializes the user's profile diff --git a/lib/pangea/network/urls.dart b/lib/pangea/network/urls.dart index 9a8421d83..6a4ba5607 100644 --- a/lib/pangea/network/urls.dart +++ b/lib/pangea/network/urls.dart @@ -9,58 +9,65 @@ import 'package:fluffychat/pangea/config/environment.dart'; /// /// https://api.staging.pangea.chat/api/v1/ class PApiUrls { - static String baseAPI = Environment.baseAPI; + static String choreoPrefix = "/choreo"; + static String subscriptionPrefix = "/subscription"; + static String accountPrefix = "/account"; + + static String choreoEndpoint = + "${Environment.choreoApi}${PApiUrls.choreoPrefix}"; + static String subscriptionEndpoint = + "${Environment.choreoApi}${PApiUrls.subscriptionPrefix}"; + static String accountEndpoint = + "${Environment.choreoApi}${PApiUrls.accountPrefix}"; /// ---------------------- Languages -------------------------------------- - static String getLanguages = "/languages"; + static String getLanguages = "${PApiUrls.choreoEndpoint}/languages"; /// ---------------------- Users -------------------------------------- - static String createUser = "/account/create"; - static String userDetails = "/account/get_user_access_token?pangea_user_id="; - static String updateUserProfile = "/account/update"; - static String paymentLink = "/account/payment_link"; - static String subscriptionExpiration = "/account/premium_expires_date"; + static String paymentLink = "${PApiUrls.subscriptionEndpoint}/payment_link"; /// ---------------------- Conversation Partner ------------------------- - static String searchUserProfiles = "/account/search"; + /// PTODO: Migrate or remove + static String searchUserProfiles = "${PApiUrls.accountEndpoint}/search"; ///-------------------------------- choreo -------------------------- - static String igc = "${Environment.choreoApi}/grammar"; + static String igc = "${PApiUrls.choreoEndpoint}/grammar"; static String languageDetection = - "${Environment.choreoApi}/language_detection"; + "${PApiUrls.choreoEndpoint}/language_detection"; - static String igcLite = "${Environment.choreoApi}/grammar_lite"; - static String spanDetails = "${Environment.choreoApi}/span_details"; + static String igcLite = "${PApiUrls.choreoEndpoint}/grammar_lite"; + static String spanDetails = "${PApiUrls.choreoEndpoint}/span_details"; - static String wordNet = "${Environment.choreoApi}/wordnet"; + static String wordNet = "${PApiUrls.choreoEndpoint}/wordnet"; static String contextualizedTranslation = - "${Environment.choreoApi}/translation/contextual"; + "${PApiUrls.choreoEndpoint}/translation/contextual"; static String simpleTranslation = - "${Environment.choreoApi}/translation/direct"; - static String tokenize = "${Environment.choreoApi}/tokenize"; + "${PApiUrls.choreoEndpoint}/translation/direct"; + static String tokenize = "${PApiUrls.choreoEndpoint}/tokenize"; static String contextualDefinition = - "${Environment.choreoApi}/contextual_definition"; - static String similarity = "${Environment.choreoApi}/similarity"; - static String topicInfo = "${Environment.choreoApi}/vocab_list"; + "${PApiUrls.choreoEndpoint}/contextual_definition"; + static String similarity = "${PApiUrls.choreoEndpoint}/similarity"; + static String topicInfo = "${PApiUrls.choreoEndpoint}/vocab_list"; - static String itFeedback = "${Environment.choreoApi}/translation/feedback"; + static String itFeedback = "${PApiUrls.choreoEndpoint}/translation/feedback"; - static String firstStep = "/it_initialstep"; - static String subseqStep = "/it_step"; + static String firstStep = "${PApiUrls.choreoEndpoint}/it_initialstep"; + static String subseqStep = "${PApiUrls.choreoEndpoint}/it_step"; - static String textToSpeech = "${Environment.choreoApi}/text_to_speech"; - static String speechToText = "${Environment.choreoApi}/speech_to_text"; + static String textToSpeech = "${PApiUrls.choreoEndpoint}/text_to_speech"; + static String speechToText = "${PApiUrls.choreoEndpoint}/speech_to_text"; static String messageActivityGeneration = - "${Environment.choreoApi}/practice/message"; + "${PApiUrls.choreoEndpoint}/practice/message"; ///-------------------------------- revenue cat -------------------------- + static String rcApiV1 = "https://api.revenuecat.com/v1"; - static String rcApiV2 = - "https://api.revenuecat.com/v2/projects/${Environment.rcProjectId}"; - static String rcApps = "$rcApiV2/apps"; - static String rcProducts = "$rcApiV2/offerings?expand=items.package.product"; - static String rcSubscribers = "$rcApiV1/subscribers"; + static String rcAppsChoreo = "${PApiUrls.subscriptionEndpoint}/app_ids"; + static String rcProductsChoreo = + "${PApiUrls.subscriptionEndpoint}/all_products"; + + static String rcSubscription = "$rcApiV1/subscribers"; } diff --git a/lib/pangea/repo/image_repo.dart b/lib/pangea/repo/image_repo.dart index 624e06e22..d12f02975 100644 --- a/lib/pangea/repo/image_repo.dart +++ b/lib/pangea/repo/image_repo.dart @@ -2,6 +2,7 @@ import 'dart:convert'; import 'dart:developer'; import 'package:fluffychat/pangea/utils/error_handler.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; @@ -44,9 +45,12 @@ class GenerateImageRequest { class ImageRepo { static Future fetchImage( - GenerateImageRequest request) async { - final Requests req = - Requests(baseUrl: Environment.choreoApi); // Set your API base URL + GenerateImageRequest request, + ) async { + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, + ); // Set your API base URL final requestBody = request.toJson(); try { @@ -58,7 +62,8 @@ class ImageRepo { if (res.statusCode == 200) { final decodedBody = jsonDecode(utf8.decode(res.bodyBytes)); return GenerateImageeResponse.fromJson( - decodedBody); // Convert response to ImageModel + decodedBody, + ); // Convert response to ImageModel } else { throw Exception('Failed to load image'); } diff --git a/lib/pangea/repo/interactive_translation_repo.dart b/lib/pangea/repo/interactive_translation_repo.dart index ab5d3b1d6..6e1739ecf 100644 --- a/lib/pangea/repo/interactive_translation_repo.dart +++ b/lib/pangea/repo/interactive_translation_repo.dart @@ -1,8 +1,9 @@ import 'dart:convert'; +import 'package:fluffychat/pangea/config/environment.dart'; +import 'package:fluffychat/widgets/matrix.dart'; import 'package:http/http.dart'; -import 'package:fluffychat/pangea/config/environment.dart'; import '../models/custom_input_translation_model.dart'; import '../models/it_response_model.dart'; import '../models/system_choice_translation_model.dart'; @@ -14,8 +15,8 @@ class ITRepo { CustomInputRequestModel initalText, ) async { final Requests req = Requests( - baseUrl: Environment.choreoApi, choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, ); final Response res = await req.post(url: PApiUrls.firstStep, body: initalText.toJson()); @@ -29,8 +30,8 @@ class ITRepo { SystemChoiceRequestModel subseqText, ) async { final Requests req = Requests( - baseUrl: Environment.choreoApi, choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, ); final Response res = diff --git a/lib/pangea/repo/language_repo.dart b/lib/pangea/repo/language_repo.dart index 9ca12b25e..4c0589750 100644 --- a/lib/pangea/repo/language_repo.dart +++ b/lib/pangea/repo/language_repo.dart @@ -1,18 +1,20 @@ import 'dart:convert'; import 'dart:developer'; +import 'package:fluffychat/pangea/config/environment.dart'; import 'package:fluffychat/pangea/models/language_model.dart'; import 'package:fluffychat/pangea/network/urls.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart'; -import '../config/environment.dart'; import '../network/requests.dart'; class LanguageRepo { static Future> fetchLanguages() async { - final Requests req = Requests(baseUrl: Environment.choreoApi); + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + ); final Response res = await req.get(url: PApiUrls.getLanguages); final decodedBody = diff --git a/lib/pangea/repo/subscription_repo.dart b/lib/pangea/repo/subscription_repo.dart index 293977921..d50cd1c6f 100644 --- a/lib/pangea/repo/subscription_repo.dart +++ b/lib/pangea/repo/subscription_repo.dart @@ -3,28 +3,30 @@ import 'dart:convert'; import 'package:collection/collection.dart'; import 'package:fluffychat/pangea/config/environment.dart'; import 'package:fluffychat/pangea/controllers/subscription_controller.dart'; +import 'package:fluffychat/pangea/network/requests.dart'; import 'package:fluffychat/pangea/utils/error_handler.dart'; import 'package:fluffychat/pangea/utils/subscription_app_id.dart'; +import 'package:fluffychat/widgets/matrix.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import '../network/urls.dart'; class SubscriptionRepo { - static final Map requestHeaders = { - 'Content-type': 'application/json', - 'Accept': 'application/json', - 'Authorization': 'Bearer ${Environment.rcKey}', - }; - static Future getAppIds() async { try { - final http.Response res = await http.get( - Uri.parse(PApiUrls.rcApps), - headers: SubscriptionRepo.requestHeaders, + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, + ); + final http.Response res = await req.get( + url: PApiUrls.rcAppsChoreo, + ); + + return SubscriptionAppIds.fromJson( + jsonDecode(res.body), ); - final json = jsonDecode(res.body); - return SubscriptionAppIds.fromJson(json); } catch (err) { ErrorHandler.logError( m: "Failed to fetch app information for revenuecat API", @@ -36,19 +38,19 @@ class SubscriptionRepo { static Future?> getAllProducts() async { try { - final http.Response res = await http.get( - Uri.parse(PApiUrls.rcProducts), - headers: SubscriptionRepo.requestHeaders, + final Requests req = Requests( + choreoApiKey: Environment.choreoApiKey, + accessToken: MatrixState.pangeaController.userController.accessToken, + ); + final http.Response res = await req.get( + url: PApiUrls.rcProductsChoreo, ); final Map json = jsonDecode(res.body); final RCProductsResponseModel resp = RCProductsResponseModel.fromJson(json); return resp.allProducts; - } catch (err) { - ErrorHandler.logError( - m: "Failed to fetch entitlement information for revenuecat API", - s: StackTrace.current, - ); + } catch (err, s) { + ErrorHandler.logError(e: err, s: s); return null; } } @@ -62,7 +64,7 @@ class SubscriptionRepo { 'Accept': 'application/json', 'Authorization': 'Bearer ${Environment.rcStripeKey}', }; - final String url = "${PApiUrls.rcSubscribers}/$userId"; + final String url = "${PApiUrls.rcSubscription}/$userId"; final http.Response res = await http.get( Uri.parse(url), headers: stripeHeaders, @@ -88,26 +90,20 @@ class RCProductsResponseModel { Map json, ) { final List offerings = json["items"] as List; - final offering = offerings.firstWhereOrNull( - Environment.isStaging - ? (offering) => !(offering['is_current'] as bool) - : (offering) => offering['is_current'] as bool, - ); - final Map metadata = offering['metadata']; - - final List allProducts = []; - for (final packageDetails in offering['packages']['items']) { - final String packageId = packageDetails['id']; - final List products = - RCProductsResponseModel.productsFromPackageDetails( - packageDetails, - packageId, - metadata, - ); - allProducts.addAll(products); - } - - return RCProductsResponseModel(allProducts: allProducts); + final res = offerings + .map( + (offering) => SubscriptionDetails( + price: offering['price'], + duration: SubscriptionDuration.values.firstWhereOrNull( + (duration) => duration.value == offering['duration'], + ), + id: offering['id'], + appId: offering['appId'], + ), + ) + .toList() + .cast(); + return RCProductsResponseModel(allProducts: res); } static List productsFromPackageDetails( diff --git a/lib/pangea/repo/user_repo.dart b/lib/pangea/repo/user_repo.dart index 7f3efc48f..ec6f29c01 100644 --- a/lib/pangea/repo/user_repo.dart +++ b/lib/pangea/repo/user_repo.dart @@ -1,66 +1,14 @@ import 'dart:convert'; -import 'dart:developer'; +import 'package:fluffychat/pangea/config/environment.dart'; import 'package:fluffychat/pangea/constants/model_keys.dart'; import 'package:http/http.dart'; -import '../models/user_model.dart'; import '../models/user_profile_search_model.dart'; import '../network/requests.dart'; import '../network/urls.dart'; class PUserRepo { - // static Future repoCreatePangeaUser({ - // required String userID, - // required String dob, - // required fullName, - // required String matrixAccessToken, - // }) async { - // try { - // final Requests req = Requests( - // baseUrl: PApiUrls.baseAPI, - // matrixAccessToken: matrixAccessToken, - // ); - - // final Map body = { - // ModelKey.userFullName: fullName, - // ModelKey.userPangeaUserId: userID, - // ModelKey.userDateOfBirth: dob, - // }; - // final resp = await req.post( - // url: PApiUrls.createUser, - // body: body, - // ); - // return PangeaProfileResponse.fromJson(jsonDecode(resp.body)); - // } catch (err, s) { - // ErrorHandler.logError(e: err, s: s); - // return null; - // } - // } - - static Future fetchPangeaUserInfo({ - required String userID, - required String matrixAccessToken, - }) async { - Response res; - try { - final Requests req = Requests( - baseUrl: PApiUrls.baseAPI, - matrixAccessToken: matrixAccessToken, - ); - res = await req.get( - url: PApiUrls.userDetails, - objectId: userID, - ); - - return PangeaProfileResponse.fromJson(jsonDecode(res.body)); - } catch (err) { - //status code should be 400 - PTODO - check ffor this. - log("Most likely a first signup and needs to make an account"); - return null; - } - } - static Future searchUserProfiles({ // List? interests, String? targetLanguage, @@ -72,8 +20,8 @@ class PUserRepo { required int limit, }) async { final Requests req = Requests( - baseUrl: PApiUrls.baseAPI, accessToken: accessToken, + choreoApiKey: Environment.choreoApiKey, ); final Map body = {}; // if (interests != null) body[ModelKey.userInterests] = interests.toString(); diff --git a/lib/pangea/utils/subscription_app_id.dart b/lib/pangea/utils/subscription_app_id.dart index c6de8867c..de2332ed3 100644 --- a/lib/pangea/utils/subscription_app_id.dart +++ b/lib/pangea/utils/subscription_app_id.dart @@ -22,24 +22,11 @@ class SubscriptionAppIds { return null; } - factory SubscriptionAppIds.fromJson(json) { - final SubscriptionAppIds appIds = SubscriptionAppIds(); - for (final appInfo in (json['items'] as List)) { - final String platform = appInfo['type']; - final String appId = appInfo['id']; - switch (platform) { - case 'stripe': - appIds.stripeId = appId; - continue; - case 'app_store': - appIds.appleId = appId; - continue; - case 'play_store': - appIds.androidId = appId; - continue; - } - } - return appIds; + factory SubscriptionAppIds.fromJson(Map json) { + return SubscriptionAppIds() + ..stripeId = json['stripe_id'] + ..androidId = json['android_id'] + ..appleId = json['apple_id']; } }