import 'package:comunic/enums/user_page_visibility.dart'; import 'package:comunic/helpers/serialization/user_list_serialization_helper.dart'; import 'package:comunic/lists/custom_emojies_list.dart'; import 'package:comunic/lists/users_list.dart'; import 'package:comunic/models/advanced_user_info.dart'; import 'package:comunic/models/api_request.dart'; import 'package:comunic/models/custom_emoji.dart'; import 'package:comunic/models/user.dart'; /// User helper /// /// Helper used to get information about the users of Comunic /// /// @author Pierre HUBERT /// Handle advanced information error enum GetUserAdvancedInformationErrorCause { NOT_FOUND, NETWORK_ERROR, NOT_AUTHORIZED } class GetUserAdvancedUserError extends Error { final GetUserAdvancedInformationErrorCause cause; GetUserAdvancedUserError(this.cause) : assert(cause != null); } class UsersHelper { /// Download information about some given users ID /// /// Return the list of users information in case of success, null in case of /// failure Future _downloadInfo(List users) async { // Execute the request final response = await APIRequest( uri: "user/getInfoMultiple", needLogin: true, args: {"usersID": users.join(",")}).exec(); // Check if the request did not execute correctly if (response.code != 200) return null; final list = UsersList(); response.getObject()!.forEach( (k, v) => list.add( User( id: v["userID"], firstName: v["firstName"], lastName: v["lastName"], pageVisibility: v["publicPage"] == "false" ? UserPageVisibility.PRIVATE : (v["openPage"] == "false" ? UserPageVisibility.PRIVATE : UserPageVisibility.OPEN), virtualDirectory: v["virtualDirectory"] == "" ? null : v["virtualDirectory"], accountImageURL: v["accountImage"], customEmojies: _parseCustomEmojies(v["customEmojis"]), ), ), ); // Save the list await UsersListSerialisationHelper().insertOrReplaceElements(list); return list; } /// Get users information from a given [Set]. Throws an exception in case /// of failure Future getListWithThrow(Set users, {bool forceDownload = false}) async { final list = await getUsersInfo(users.toList(), forceDownload: forceDownload); if (list == null) throw Exception( "Could not get information about the given list of users!"); return list; } /// Get information about a single user. Throws in case of failure Future getSingleWithThrow(int? user, {bool forceDownload = false}) async { return (await getListWithThrow(Set()..add(user), forceDownload: forceDownload))[0]; } /// Get users information from a given [Set] /// /// Throws in case of failure Future getList(Set users, {bool forceDownload = false}) async { final list = await getUsersInfo(users.toList()); if (list == null) throw Exception("Failed to get the list of users!"); return list; } /// Get users information /// /// If [forceDownload] is set to true, the data will always be retrieved from /// the server, otherwise cached data will be used if available Future getUsersInfo(List users, {bool forceDownload = false}) async { List toDownload = []; UsersList list = UsersList(); // Check cache for (int? userID in users) { if (!forceDownload && await UsersListSerialisationHelper().any((u) => u.id == userID)) list.add( await UsersListSerialisationHelper().first((u) => u.id == userID)); else toDownload.add(userID); } // Process download if required if (toDownload.length > 0) { final downloadedList = await _downloadInfo(toDownload); if (downloadedList == null) return null; list.addAll(downloadedList); } return list; } /// Try to fetch advanced information about a user Future getAdvancedInfo(int id) async { final response = await APIRequest( uri: "user/getAdvancedUserInfo", needLogin: true, args: {"userID": id.toString()}).exec(); // Handle exceptions if (response.code != 200) { var cause = GetUserAdvancedInformationErrorCause.NETWORK_ERROR; if (response.code == 404) cause = GetUserAdvancedInformationErrorCause.NOT_FOUND; if (response.code == 401) cause = GetUserAdvancedInformationErrorCause.NOT_AUTHORIZED; throw new GetUserAdvancedUserError(cause); } return apiToAdvancedUserInfo(response.getObject()!); } /// Parse the list of custom emojies static CustomEmojiesList _parseCustomEmojies(List list) { final l = list.cast>(); return CustomEmojiesList() ..addAll(l .map((f) => CustomEmoji( id: f["id"], userID: f["userID"], shortcut: f["shortcut"], url: f["url"], )) .toList()); } static AdvancedUserInfo apiToAdvancedUserInfo(Map data) => AdvancedUserInfo( id: data["userID"], firstName: data["firstName"], lastName: data["lastName"], pageVisibility: data["publicPage"] == "false" ? UserPageVisibility.PRIVATE : (data["openPage"] == "false" ? UserPageVisibility.PRIVATE : UserPageVisibility.OPEN), virtualDirectory: data["virtualDirectory"] == "" ? null : data["virtualDirectory"], accountImageURL: data["accountImage"], emailAddress: data["email_address"], customEmojies: _parseCustomEmojies(data["customEmojis"]), publicNote: data["publicNote"], canPostTexts: data["can_post_texts"], isFriendsListPublic: data["friend_list_public"], numberFriends: data["number_friends"], accountCreationTime: data["account_creation_time"], personalWebsite: data["personnalWebsite"], location: data["location"], likes: data["pageLikes"], userLike: data["user_like_page"], ); }