2019-11-23 17:41:13 +00:00
|
|
|
import { RequestHandler } from "../entities/RequestHandler";
|
|
|
|
import { ConversationsHelper } from "../helpers/ConversationsHelper";
|
2019-11-30 09:11:51 +00:00
|
|
|
import { Conversation, BaseConversation } from "../entities/Conversation";
|
|
|
|
import { UserHelper } from "../helpers/UserHelper";
|
2019-11-30 13:03:53 +00:00
|
|
|
import { removeHTMLNodes } from "../utils/StringUtils";
|
2019-11-30 14:17:47 +00:00
|
|
|
import { ConversationMessage } from "../entities/ConversationMessage";
|
2019-12-07 16:35:14 +00:00
|
|
|
import { UnreadConversation } from "../entities/UnreadConversation";
|
2020-04-10 09:05:30 +00:00
|
|
|
import { CallsHelper } from "../helpers/CallsHelper";
|
2020-04-13 12:35:36 +00:00
|
|
|
import { CallsController } from "./CallsController";
|
2019-11-23 17:41:13 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Conversations controller
|
|
|
|
*
|
|
|
|
* @author Pierre HUBERT
|
|
|
|
*/
|
|
|
|
|
|
|
|
export class ConversationsController {
|
|
|
|
|
2019-11-30 09:11:51 +00:00
|
|
|
/**
|
|
|
|
* Create a new conversation
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async CreateConversation(h : RequestHandler) {
|
|
|
|
|
|
|
|
const name = h.postString("name");
|
|
|
|
|
2019-11-30 13:41:34 +00:00
|
|
|
const members = h.postNumbersSet("users");
|
2019-11-30 09:11:51 +00:00
|
|
|
|
|
|
|
// Check if the users exists
|
|
|
|
for (const userID of members) {
|
|
|
|
if(!await UserHelper.Exists(userID))
|
|
|
|
h.error(404, "User " + userID + " not found!");
|
|
|
|
}
|
|
|
|
|
2019-11-30 13:41:34 +00:00
|
|
|
if(!members.has(h.getUserId()))
|
|
|
|
members.add(h.getUserId());
|
2019-11-30 09:11:51 +00:00
|
|
|
|
|
|
|
const conv : BaseConversation = {
|
|
|
|
ownerID: h.getUserId(),
|
2019-11-30 13:03:53 +00:00
|
|
|
name: name == "false" ? "" : removeHTMLNodes(name),
|
2019-11-30 09:11:51 +00:00
|
|
|
following: h.postBool("follow"),
|
|
|
|
members: members,
|
2020-04-26 12:25:20 +00:00
|
|
|
canEveryoneAddMembers: h.postBool("canEveryoneAddMembers", true),
|
2019-11-30 09:11:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const convID = await ConversationsHelper.Create(conv);
|
|
|
|
|
|
|
|
// Success
|
|
|
|
h.send({
|
|
|
|
conversationID: convID,
|
|
|
|
success: "The conversation was successfully created!"
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-11-23 17:41:13 +00:00
|
|
|
/**
|
|
|
|
* Get the list of conversations of the user
|
|
|
|
*
|
|
|
|
* @param handler
|
|
|
|
*/
|
|
|
|
public static async GetList(handler: RequestHandler) {
|
|
|
|
const list = await ConversationsHelper.GetListUser(handler.getUserId());
|
|
|
|
handler.send(list.map(c => this.ConversationToAPI(c)));
|
|
|
|
}
|
|
|
|
|
2019-11-23 19:53:13 +00:00
|
|
|
/**
|
|
|
|
* Get information about a single conversation
|
|
|
|
*
|
|
|
|
* @param handler
|
|
|
|
*/
|
|
|
|
public static async GetInfoSingle(handler: RequestHandler) {
|
2020-04-01 09:11:41 +00:00
|
|
|
const conversationID = await handler.postConversationId("conversationID");
|
2019-11-23 19:54:35 +00:00
|
|
|
const conv = await ConversationsHelper.GetSingle(conversationID, handler.getUserId());
|
2019-11-23 19:53:13 +00:00
|
|
|
|
|
|
|
if(!conv)
|
|
|
|
throw Error("Could not get information about the conversation (but it should have been found though) !!");
|
|
|
|
|
|
|
|
handler.send(this.ConversationToAPI(conv));
|
|
|
|
}
|
|
|
|
|
2019-11-30 11:24:19 +00:00
|
|
|
/**
|
|
|
|
* Update conversation settings
|
|
|
|
*
|
2019-11-30 13:38:49 +00:00
|
|
|
* @param h Request handler
|
2019-11-30 11:24:19 +00:00
|
|
|
*/
|
2019-11-30 13:38:49 +00:00
|
|
|
public static async UpdateSettings(h: RequestHandler) : Promise<void> {
|
2020-04-01 09:11:41 +00:00
|
|
|
const convID = await h.postConversationId("conversationID");
|
2020-04-25 17:03:55 +00:00
|
|
|
const isUserModerator = await ConversationsHelper.IsUserModerator(h.getUserId(), convID);
|
2019-11-30 11:24:19 +00:00
|
|
|
|
|
|
|
// Update following state, if required
|
2019-11-30 13:38:49 +00:00
|
|
|
if(h.hasPostParameter("following")) {
|
2019-11-30 11:24:19 +00:00
|
|
|
await ConversationsHelper.SetFollowing(
|
2019-11-30 13:38:49 +00:00
|
|
|
h.getUserId(),
|
2019-11-30 11:24:19 +00:00
|
|
|
convID,
|
2019-11-30 13:38:49 +00:00
|
|
|
h.postBool("following")
|
2019-11-30 11:24:19 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-04-25 17:03:55 +00:00
|
|
|
// Update members list
|
|
|
|
if(h.hasPostParameter("members")) {
|
|
|
|
|
|
|
|
const members = h.postNumbersSet("members");
|
|
|
|
const canEveryoneAddMembers = await ConversationsHelper.CanEveryoneAddMembers(convID);
|
|
|
|
|
|
|
|
if(!isUserModerator && !canEveryoneAddMembers)
|
|
|
|
h.error(401, "You can not update the list of members of this conversation!");
|
|
|
|
|
|
|
|
// Make sure current user is on the list
|
|
|
|
if(!members.has(h.getUserId()))
|
|
|
|
members.add(h.getUserId());
|
|
|
|
|
|
|
|
await ConversationsHelper.SetMembers(convID, members, isUserModerator);
|
|
|
|
}
|
|
|
|
|
2019-11-30 13:25:06 +00:00
|
|
|
// Change moderator settings
|
2020-04-25 17:03:55 +00:00
|
|
|
if(h.hasPostParameter("name") || h.hasPostParameter("canEveryoneAddMembers")) {
|
2019-11-30 13:25:06 +00:00
|
|
|
|
|
|
|
// Check if user is the moderator of the conversation
|
2020-04-25 17:03:55 +00:00
|
|
|
if(!isUserModerator)
|
2019-11-30 13:38:49 +00:00
|
|
|
h.error(401, "You are not allowed to perform changes on this conversation !");
|
2019-11-30 13:25:06 +00:00
|
|
|
|
|
|
|
// Update conversation name (if required)
|
2019-11-30 13:38:49 +00:00
|
|
|
if(h.hasPostParameter("name")) {
|
2020-04-26 12:11:17 +00:00
|
|
|
const name = h.postString("name", 0);
|
2019-11-30 13:25:06 +00:00
|
|
|
await ConversationsHelper.SetName(convID, name == "false" ? "" : removeHTMLNodes(name));
|
|
|
|
}
|
|
|
|
|
2020-04-25 16:34:31 +00:00
|
|
|
// Update "canEveryoneAddMembers" parameter
|
|
|
|
if(h.hasPostParameter("canEveryoneAddMembers")) {
|
|
|
|
await ConversationsHelper.SetCanEveryoneAddMembers(convID, h.postBool("canEveryoneAddMembers"));
|
|
|
|
}
|
|
|
|
|
2019-11-30 13:25:06 +00:00
|
|
|
}
|
2019-11-30 11:24:19 +00:00
|
|
|
|
2019-11-30 13:38:49 +00:00
|
|
|
h.success("Conversation information successfully updated!");
|
2019-11-30 11:24:19 +00:00
|
|
|
}
|
|
|
|
|
2019-12-07 11:00:28 +00:00
|
|
|
/**
|
|
|
|
* Find, optionally create and return the ID of a privat conversation
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async FindPrivate(h: RequestHandler) {
|
|
|
|
const otherUser = await h.postUserId("otherUser");
|
|
|
|
const allowCreate = h.postBool("allowCreate", false);
|
|
|
|
|
|
|
|
// Query the database
|
|
|
|
const list = await ConversationsHelper.FindPrivate(h.getUserId(), otherUser);
|
|
|
|
|
|
|
|
if(list.length == 0) {
|
|
|
|
|
|
|
|
if(!allowCreate)
|
|
|
|
h.error(404, "Not any private conversation was found. The server was not allowed to create a new one...");
|
|
|
|
|
|
|
|
// Create the conversation
|
|
|
|
const convID = await ConversationsHelper.Create({
|
|
|
|
ownerID: h.getUserId(),
|
|
|
|
name: "",
|
|
|
|
following: true,
|
2020-04-26 12:25:20 +00:00
|
|
|
members: new Set([h.getUserId(), otherUser]),
|
|
|
|
canEveryoneAddMembers: true
|
2019-12-07 11:00:28 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
list.push(convID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
h.send({"conversationsID": list});
|
|
|
|
}
|
|
|
|
|
2019-11-30 14:17:47 +00:00
|
|
|
/**
|
|
|
|
* Refresh current user conversations
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
2020-04-25 16:34:31 +00:00
|
|
|
* @deprecated Only ComunicWeb was using this method until
|
|
|
|
* the introduction of WebSockets...
|
2019-11-30 14:17:47 +00:00
|
|
|
*/
|
|
|
|
public static async RefreshList(h: RequestHandler) {
|
|
|
|
|
|
|
|
const list = {};
|
|
|
|
|
|
|
|
// Check for new conversations
|
|
|
|
if(h.hasPostParameter("newConversations")) {
|
2019-11-30 15:35:32 +00:00
|
|
|
for(const convID of h.postNumbersSet("newConversations", 0)) {
|
2019-11-30 14:17:47 +00:00
|
|
|
if(!ConversationsHelper.DoesUsersBelongsTo(h.getUserId(), convID))
|
|
|
|
h.error(401, "You are not allowed to fetch the messages of this conversation ("+convID+")!");
|
|
|
|
|
|
|
|
list["conversation-" + convID] = (await ConversationsHelper.GetLastMessages(convID, 10))
|
|
|
|
.map(e => this.ConversationMessageToAPI(e));
|
|
|
|
|
2019-11-30 14:22:10 +00:00
|
|
|
// Mark the user has seen the messages
|
|
|
|
await ConversationsHelper.MarkUserSeen(convID, h.getUserId());
|
2019-11-30 14:17:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-30 15:35:32 +00:00
|
|
|
// Check for refresh on some conversations
|
|
|
|
if(h.hasPostParameter("toRefresh")) {
|
|
|
|
const toRefresh = h.postJSON("toRefresh");
|
|
|
|
|
|
|
|
for (const key in toRefresh) {
|
|
|
|
if (toRefresh.hasOwnProperty(key)) {
|
|
|
|
const element = toRefresh[key];
|
|
|
|
|
|
|
|
// Extract conversation ID
|
|
|
|
if(!key.startsWith("conversation-"))
|
|
|
|
h.error(400, "Entries of 'toRefresh' should start with 'conversation-' !");
|
|
|
|
const convID = Number.parseInt(key.replace("conversation-", ""));
|
|
|
|
|
|
|
|
// Extract last message ID
|
|
|
|
if(!element.hasOwnProperty("last_message_id"))
|
|
|
|
h.error(400, "Missing last_message_id for conversation " + convID + "!");
|
|
|
|
const lastMessageID = Number.parseInt(element.last_message_id);
|
|
|
|
|
|
|
|
// Check user rights
|
|
|
|
if(!ConversationsHelper.DoesUsersBelongsTo(h.getUserId(), convID))
|
|
|
|
h.error(401, "You are not allowed to fetch the messages of this conversation ("+convID+")!");
|
|
|
|
|
|
|
|
// Get the messages
|
|
|
|
list["conversation-" + convID] = (await ConversationsHelper.GetNewMessages(convID, lastMessageID))
|
|
|
|
.map(e => this.ConversationMessageToAPI(e));
|
|
|
|
|
|
|
|
// Mark the user has seen the messages
|
|
|
|
await ConversationsHelper.MarkUserSeen(convID, h.getUserId());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-11-30 14:17:47 +00:00
|
|
|
|
|
|
|
h.send(list);
|
|
|
|
}
|
|
|
|
|
2019-11-30 15:44:27 +00:00
|
|
|
/**
|
|
|
|
* Refresh the messages of a single conversation
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async RefreshSingleConversation(h: RequestHandler) {
|
2020-04-01 09:11:41 +00:00
|
|
|
const convID = await h.postConversationId("conversationID");
|
2019-11-30 15:44:27 +00:00
|
|
|
const lastMessageID = h.postInt("last_message_id");
|
|
|
|
|
|
|
|
const messages = lastMessageID == 0 ?
|
|
|
|
|
|
|
|
// Get lastest messages (the user has no message yet)
|
|
|
|
await ConversationsHelper.GetLastMessages(convID, 10) :
|
|
|
|
|
|
|
|
// Get new messages
|
|
|
|
await ConversationsHelper.GetNewMessages(convID, lastMessageID);
|
|
|
|
|
|
|
|
// Specify the user has seen the last message
|
|
|
|
await ConversationsHelper.MarkUserSeen(convID, h.getUserId());
|
|
|
|
|
2019-12-07 11:09:15 +00:00
|
|
|
h.send(messages.map(e => this.ConversationMessageToAPI(e)));
|
2019-11-30 15:44:27 +00:00
|
|
|
}
|
|
|
|
|
2019-11-30 16:13:36 +00:00
|
|
|
/**
|
|
|
|
* Send a new message
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async SendMessage(h: RequestHandler) {
|
2020-04-01 09:11:41 +00:00
|
|
|
const convID = await h.postConversationId("conversationID");
|
2019-11-30 16:13:36 +00:00
|
|
|
const message = removeHTMLNodes(h.postString("message", 0));
|
2019-11-30 18:58:00 +00:00
|
|
|
let imagePath = "";
|
2019-11-30 16:13:36 +00:00
|
|
|
|
2019-11-30 18:58:00 +00:00
|
|
|
// Check for image
|
|
|
|
if(h.hasFile("image")){
|
|
|
|
// Try to save image
|
|
|
|
imagePath = await h.savePostImage("image", "conversations", 1200, 1200);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if(message.length < 3)
|
2019-11-30 16:13:36 +00:00
|
|
|
h.error(401, "Message is empty!");
|
|
|
|
|
|
|
|
// Send message
|
|
|
|
await ConversationsHelper.SendMessage({
|
|
|
|
userID: h.getUserId(),
|
|
|
|
convID: convID,
|
|
|
|
message: message,
|
2019-11-30 18:58:00 +00:00
|
|
|
imagePath: imagePath
|
2019-11-30 16:13:36 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
h.success("Conversation message was sent!");
|
|
|
|
}
|
|
|
|
|
2019-12-07 16:08:53 +00:00
|
|
|
/**
|
|
|
|
* Get the older messages of a conversation
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async GetOlderMessages(h: RequestHandler) {
|
2020-04-01 09:11:41 +00:00
|
|
|
const convID = await h.postConversationId("conversationID");
|
2019-12-07 16:08:53 +00:00
|
|
|
const maxID = h.postInt("oldest_message_id") - 1;
|
|
|
|
|
|
|
|
let limit = h.postInt("limit");
|
|
|
|
if(limit < 1) limit = 1;
|
|
|
|
else if(limit > 30) limit = 30;
|
|
|
|
|
|
|
|
// Get the list of messages
|
|
|
|
const messages = await ConversationsHelper.GetOlderMessage(convID, maxID, limit);
|
|
|
|
|
|
|
|
h.send(messages.map(e => this.ConversationMessageToAPI(e)));
|
|
|
|
}
|
|
|
|
|
2019-12-07 16:15:33 +00:00
|
|
|
/**
|
|
|
|
* Get the number of unread conversations for the user
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async CountUnreadForUser(h: RequestHandler) {
|
|
|
|
h.send({
|
|
|
|
nb_unread: await ConversationsHelper.CountUnreadForUser(h.getUserId())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-12-07 16:35:14 +00:00
|
|
|
/**
|
|
|
|
* Get the list of unread conversations of the user
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async GetListUnread(h: RequestHandler) {
|
|
|
|
const list = await ConversationsHelper.GetListUnread(h.getUserId());
|
|
|
|
|
|
|
|
h.send(list.map(e => this.UnreadConversationToAPI(e)));
|
|
|
|
}
|
|
|
|
|
2019-12-07 17:06:41 +00:00
|
|
|
/**
|
|
|
|
* Request a conversation
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async DeleteConversation(h: RequestHandler) {
|
2020-04-01 09:11:41 +00:00
|
|
|
const convID = await h.postConversationId("conversationID");
|
2019-12-07 17:06:41 +00:00
|
|
|
|
|
|
|
await ConversationsHelper.RemoveUserFromConversation(h.getUserId(), convID);
|
|
|
|
|
|
|
|
h.success("The conversation has been deleted.");
|
|
|
|
}
|
|
|
|
|
2019-12-07 17:39:59 +00:00
|
|
|
/**
|
|
|
|
* Update the content of a conversation message
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async UpdateMessage(h: RequestHandler) {
|
|
|
|
const messageID = h.postInt("messageID");
|
|
|
|
const newContent = h.postString("content");
|
|
|
|
|
|
|
|
if(newContent.length < 3)
|
|
|
|
h.error(401, "Invalid new message content!");
|
|
|
|
|
|
|
|
// Check out whether the user own the message or not
|
|
|
|
if(!await ConversationsHelper.IsUserMessageOwner(h.getUserId(), messageID))
|
|
|
|
h.error(401, "You do not own this conversation message!");
|
|
|
|
|
|
|
|
await ConversationsHelper.UpdateMessageContent(messageID, newContent);
|
|
|
|
|
|
|
|
h.success("Conversation message content successfully update");
|
|
|
|
}
|
|
|
|
|
2019-12-07 17:52:20 +00:00
|
|
|
/**
|
|
|
|
* Delete a conversation message
|
|
|
|
*
|
|
|
|
* @param h Request handler
|
|
|
|
*/
|
|
|
|
public static async DeleteMessage(h: RequestHandler) {
|
|
|
|
const messageID = h.postInt("messageID");
|
|
|
|
|
|
|
|
if(!await ConversationsHelper.IsUserMessageOwner(h.getUserId(), messageID))
|
|
|
|
h.error(401, "You do not own this conversation message!");
|
|
|
|
|
|
|
|
await ConversationsHelper.DeleteMessageById(messageID);
|
|
|
|
|
|
|
|
h.success("Conversation message has been successfully deleted!");
|
|
|
|
}
|
|
|
|
|
2019-11-23 17:41:13 +00:00
|
|
|
/**
|
|
|
|
* Turn a conversation object into an API entry
|
|
|
|
*
|
|
|
|
* @param c
|
|
|
|
*/
|
2020-03-26 12:09:15 +00:00
|
|
|
public static ConversationToAPI(c : Conversation) : any {
|
2019-11-23 17:41:13 +00:00
|
|
|
return {
|
|
|
|
ID: c.id,
|
|
|
|
ID_owner: c.ownerID,
|
|
|
|
last_active: c.lastActive,
|
|
|
|
name: c.name.length > 0 ? c.name : false,
|
|
|
|
following: c.following ? 1 : 0,
|
|
|
|
saw_last_message: c.sawLastMessage ? 1 : 0,
|
2020-04-10 09:05:30 +00:00
|
|
|
members: [...c.members],
|
2020-04-25 16:02:08 +00:00
|
|
|
canEveryoneAddMembers: c.canEveryoneAddMembers,
|
2020-04-10 09:08:18 +00:00
|
|
|
can_have_call: CallsHelper.CanHaveCall(c),
|
2020-04-13 12:35:36 +00:00
|
|
|
can_have_video_call: CallsHelper.CanHaveVideoCAll(c),
|
|
|
|
has_call_now: CallsController.IsHavingCall(c.id)
|
2019-11-23 17:41:13 +00:00
|
|
|
};
|
|
|
|
}
|
2019-11-30 14:17:47 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Turn a conversation message into an API object
|
|
|
|
*
|
|
|
|
* @param c Information about the conversation
|
|
|
|
*/
|
2020-03-26 12:05:14 +00:00
|
|
|
public static ConversationMessageToAPI(c: ConversationMessage) : any {
|
2019-11-30 14:17:47 +00:00
|
|
|
return {
|
|
|
|
ID: c.id,
|
2020-04-01 12:16:26 +00:00
|
|
|
convID: c.convID,
|
2019-11-30 14:17:47 +00:00
|
|
|
ID_user: c.userID,
|
|
|
|
time_insert: c.timeSent,
|
|
|
|
message: c.message,
|
|
|
|
image_path: c.hasImage ? c.imageURL : null
|
|
|
|
};
|
|
|
|
}
|
2019-12-07 16:35:14 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Turn an UnreadConversation object into an API entry
|
|
|
|
*
|
|
|
|
* @param c Target conversation
|
|
|
|
*/
|
|
|
|
private static UnreadConversationToAPI(c: UnreadConversation): any {
|
|
|
|
return {
|
|
|
|
id: c.id,
|
|
|
|
conv_name: c.name,
|
|
|
|
last_active: c.lastActive,
|
|
|
|
userID: c.userID,
|
|
|
|
message: c.message
|
|
|
|
}
|
|
|
|
}
|
2019-11-23 17:41:13 +00:00
|
|
|
}
|