1
0
mirror of https://gitlab.com/comunic/comunicmobile synced 2024-11-22 12:59:21 +00:00
comunicmobile/lib/helpers/posts_helper.dart

287 lines
8.2 KiB
Dart

import 'package:comunic/enums/post_kind.dart';
import 'package:comunic/enums/post_target.dart';
import 'package:comunic/enums/post_visibility_level.dart';
import 'package:comunic/enums/user_access_levels.dart';
import 'package:comunic/helpers/comments_helper.dart';
import 'package:comunic/helpers/survey_helper.dart';
import 'package:comunic/helpers/websocket_helper.dart';
import 'package:comunic/lists/comments_list.dart';
import 'package:comunic/lists/posts_list.dart';
import 'package:comunic/models/api_request.dart';
import 'package:comunic/models/displayed_content.dart';
import 'package:comunic/models/new_post.dart';
import 'package:comunic/models/post.dart';
import 'package:http_parser/http_parser.dart';
/// Posts helper
///
/// @author Pierre HUBERT
const _APIPostsVisibilityLevelMap = {
"public": PostVisibilityLevel.PUBLIC,
"friends": PostVisibilityLevel.FRIENDS,
"private": PostVisibilityLevel.USER,
"members": PostVisibilityLevel.GROUP_MEMBERS
};
const _APIPostsKindsMap = {
"text": PostKind.TEXT,
"image": PostKind.IMAGE,
"weblink": PostKind.WEB_LINK,
"pdf": PostKind.PDF,
"countdown": PostKind.COUNTDOWN,
"survey": PostKind.SURVEY,
"youtube": PostKind.YOUTUBE
};
const _APIUserAccessMap = {
"no-access": UserAccessLevels.NONE,
"basic": UserAccessLevels.BASIC,
"intermediate": UserAccessLevels.INTERMEDIATE,
"full": UserAccessLevels.FULL
};
const _APIPostsTargetKindsMap = {
PostTarget.USER_PAGE: "user",
PostTarget.GROUP_PAGE: "group"
};
class PostsHelper {
/// Stores the list of posts we are registered to
///
/// First int = post ID
/// Second int = number of registered people
static final _registeredPosts = Map<int, int>();
/// Get the list of latest posts. Return the list of posts or null in case of
/// failure
Future<PostsList?> getLatest({int from = 0}) async {
final response =
await APIRequest(uri: "posts/get_latest", needLogin: true, args: {
"include_groups": true.toString(),
"startFrom": from.toString(),
}).exec();
if (response.code != 200) return null;
try {
// Parse & return the list of posts
return PostsList()
..addAll(response.getArray()!.map((f) => _apiToPost(f)));
} catch (e) {
print(e.toString());
return null;
}
}
/// Get the list of posts of a user
Future<PostsList?> getUserPosts(int? userID, {int from = 0}) async {
final response = await (APIRequest(uri: "posts/get_user", needLogin: true)
..addInt("userID", userID)
..addInt("startFrom", from == 0 ? 0 : from - 1))
.exec();
if (response.code != 200) return null;
try {
// Parse & return the list of posts
return PostsList()
..addAll(response.getArray()!.map((f) => _apiToPost(f)));
} catch (e) {
print(e.toString());
return null;
}
}
/// Get the list of posts of a group
Future<PostsList?> getGroupPosts(int groupID, {int from = 0}) async {
final response = await (APIRequest(uri: "posts/get_group", needLogin: true)
..addInt("groupID", groupID)
..addInt("startFrom", from == 0 ? 0 : from - 1))
.exec();
if (response.code != 200) return null;
try {
// Parse & return the list of posts
return PostsList()
..addAll(response.getArray()!.map((f) => _apiToPost(f)));
} catch (e) {
print(e.toString());
return null;
}
}
/// Get a single post information
Future<Post> getSingle(int postID) async {
final response = await APIRequest(
uri: "posts/get_single",
args: {"postID": postID.toString()},
needLogin: true,
).exec();
if (!response.isOK)
throw Exception("Could not get information about the post!");
return _apiToPost(response.getObject());
}
/// Create a new post
///
/// This function crash in case of error
Future<void> createPost(NewPost post) async {
APIRequest request =
APIRequest(uri: "posts/create", needLogin: true, args: {
"kind-page": _APIPostsTargetKindsMap[post.target],
"kind-id": post.targetID.toString(),
"visibility": _APIPostsVisibilityLevelMap.map(
(s, v) => MapEntry(v, s))[post.visibility],
"kind": _APIPostsKindsMap.map((s, k) => MapEntry(k, s))[post.kind],
"content": post.content
});
switch (post.kind) {
case PostKind.TEXT:
break;
case PostKind.IMAGE:
request.addBytesFile("image", post.image);
break;
case PostKind.WEB_LINK:
request.addString("url", post.url);
break;
case PostKind.PDF:
request.addBytesFile(
"pdf",
BytesFile("file.pdf", post.pdf,
type: MediaType.parse("application/pdf")));
break;
case PostKind.COUNTDOWN:
request.addInt(
"time-end", (post.timeEnd!.millisecondsSinceEpoch / 1000).floor());
break;
case PostKind.SURVEY:
request.addString("question", post.survey!.question);
request.addString("answers", post.survey!.answers.join("<>"));
request.addBool(
"allowNewAnswers", post.survey!.allowNewChoicesCreation);
break;
case PostKind.YOUTUBE:
request.addString("youtube_id", post.youtubeId);
break;
default:
throw Exception("Unsupported post type :" + post.kind.toString());
}
final response = await request.execWithFiles();
if (!response.isOK) throw Exception("Could not create the post !");
}
/// Update a post content
Future<bool> updateContent(int id, String newContent) async {
return (await APIRequest(
uri: "posts/update_content",
needLogin: true,
args: {
"postID": id.toString(),
"new_content": newContent,
},
).exec())
.isOK;
}
/// Update a post visibility
Future<bool> setVisibility(int id, PostVisibilityLevel level) async {
return (await APIRequest(
uri: "posts/set_visibility_level",
needLogin: true,
args: {
"postID": id.toString(),
"new_level":
_APIPostsVisibilityLevelMap.map((k, v) => MapEntry(v, k))[level]
},
).exec())
.isOK;
}
/// Delete a post
Future<bool> delete(int id) async {
return (await APIRequest(
uri: "posts/delete",
needLogin: true,
args: {"postID": id.toString()},
).exec())
.isOK;
}
/// Register to a post events
Future<void> registerPostEvents(int id) async {
if (_registeredPosts.containsKey(id))
_registeredPosts.update(id, (v) => v + 1);
else {
_registeredPosts[id] = 1;
await ws("\$main/register_post", {"postID": id});
}
}
/// Un-register to post events
Future<void> unregisterPostEvents(int id) async {
if (!_registeredPosts.containsKey(id)) return;
_registeredPosts.update(id, (v) => v - 1);
if (_registeredPosts[id]! <= 0) {
_registeredPosts.remove(id);
await ws("\$main/unregister_post", {"postID": id});
}
}
/// Turn an API entry into a [Post] object
Post _apiToPost(Map<String, dynamic> map) {
final postKind = _APIPostsKindsMap[map["kind"]]!;
// Parse comments
CommentsList? comments;
if (map["comments"] != null) {
comments = CommentsList();
map["comments"]
.forEach((v) => comments!.add(CommentsHelper.apiToComment(v)));
}
final survey = postKind == PostKind.SURVEY
? SurveyHelper.apiToSurvey(map["data_survey"])
: null;
return Post(
id: map["ID"],
userID: map["userID"],
userPageID: map["user_page_id"],
groupID: map["group_id"],
timeSent: map["post_time"],
content: DisplayedString(map["content"]),
visibilityLevel: _APIPostsVisibilityLevelMap[map["visibility_level"]]!,
kind: postKind,
fileSize: map["file_size"],
fileType: map["file_type"],
filePath: map["file_path"],
fileURL: map["file_path_url"],
timeEnd: map["time_end"],
linkURL: map["link_url"],
linkTitle: map["link_title"],
linkDescription: map["link_description"],
linkImage: map["link_image"],
likes: map["likes"],
userLike: map["userlike"],
access: _APIUserAccessMap[map["user_access"]]!,
comments: comments,
survey: survey);
}
}