|
|
|
@ -16,7 +16,6 @@ import { GoogleChrome } from '../util';
|
|
|
|
|
import { appendFetchAvatarAndProfileJob } from './userProfileImageUpdates';
|
|
|
|
|
import { ConversationTypeEnum } from '../models/conversationAttributes';
|
|
|
|
|
import { getUsBlindedInThatServer } from '../session/apis/open_group_api/sogsv3/knownBlindedkeys';
|
|
|
|
|
import { Action, Reaction } from '../types/Reaction';
|
|
|
|
|
|
|
|
|
|
function contentTypeSupported(type: string): boolean {
|
|
|
|
|
const Chrome = GoogleChrome;
|
|
|
|
@ -339,116 +338,103 @@ export async function handleMessageJob(
|
|
|
|
|
) || messageModel.get('timestamp')} in conversation ${conversation.idForLogging()}`
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (!messageModel.get('isPublic') && regularDataMessage.reaction) {
|
|
|
|
|
if (
|
|
|
|
|
regularDataMessage.reaction.action === Action.REACT &&
|
|
|
|
|
conversation.isPrivate() &&
|
|
|
|
|
messageModel.get('unread')
|
|
|
|
|
) {
|
|
|
|
|
messageModel.set('reaction', regularDataMessage.reaction as Reaction);
|
|
|
|
|
conversation.throttledNotify(messageModel);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
confirm?.();
|
|
|
|
|
} else {
|
|
|
|
|
const sendingDeviceConversation = await getConversationController().getOrCreateAndWait(
|
|
|
|
|
source,
|
|
|
|
|
ConversationTypeEnum.PRIVATE
|
|
|
|
|
);
|
|
|
|
|
try {
|
|
|
|
|
messageModel.set({ flags: regularDataMessage.flags });
|
|
|
|
|
if (messageModel.isExpirationTimerUpdate()) {
|
|
|
|
|
const { expireTimer } = regularDataMessage;
|
|
|
|
|
const oldValue = conversation.get('expireTimer');
|
|
|
|
|
if (expireTimer === oldValue) {
|
|
|
|
|
confirm?.();
|
|
|
|
|
window?.log?.info(
|
|
|
|
|
'Dropping ExpireTimerUpdate message as we already have the same one set.'
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await handleExpirationTimerUpdateNoCommit(conversation, messageModel, source, expireTimer);
|
|
|
|
|
} else {
|
|
|
|
|
// this does not commit to db nor UI unless we need to approve a convo
|
|
|
|
|
await handleRegularMessage(
|
|
|
|
|
conversation,
|
|
|
|
|
sendingDeviceConversation,
|
|
|
|
|
messageModel,
|
|
|
|
|
regularDataMessage,
|
|
|
|
|
source,
|
|
|
|
|
messageHash
|
|
|
|
|
const sendingDeviceConversation = await getConversationController().getOrCreateAndWait(
|
|
|
|
|
source,
|
|
|
|
|
ConversationTypeEnum.PRIVATE
|
|
|
|
|
);
|
|
|
|
|
try {
|
|
|
|
|
messageModel.set({ flags: regularDataMessage.flags });
|
|
|
|
|
if (messageModel.isExpirationTimerUpdate()) {
|
|
|
|
|
const { expireTimer } = regularDataMessage;
|
|
|
|
|
const oldValue = conversation.get('expireTimer');
|
|
|
|
|
if (expireTimer === oldValue) {
|
|
|
|
|
confirm?.();
|
|
|
|
|
window?.log?.info(
|
|
|
|
|
'Dropping ExpireTimerUpdate message as we already have the same one set.'
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
await handleExpirationTimerUpdateNoCommit(conversation, messageModel, source, expireTimer);
|
|
|
|
|
} else {
|
|
|
|
|
// this does not commit to db nor UI unless we need to approve a convo
|
|
|
|
|
await handleRegularMessage(
|
|
|
|
|
conversation,
|
|
|
|
|
sendingDeviceConversation,
|
|
|
|
|
messageModel,
|
|
|
|
|
regularDataMessage,
|
|
|
|
|
source,
|
|
|
|
|
messageHash
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// save the message model to the db and it save the messageId generated to our in-memory copy
|
|
|
|
|
const id = await messageModel.commit();
|
|
|
|
|
messageModel.set({ id });
|
|
|
|
|
|
|
|
|
|
// Note that this can save the message again, if jobs were queued. We need to
|
|
|
|
|
// call it after we have an id for this message, because the jobs refer back
|
|
|
|
|
// to their source message.
|
|
|
|
|
|
|
|
|
|
const unreadCount = await conversation.getUnreadCount();
|
|
|
|
|
conversation.set({ unreadCount });
|
|
|
|
|
conversation.set({
|
|
|
|
|
active_at: Math.max(conversation.attributes.active_at, messageModel.get('sent_at') || 0),
|
|
|
|
|
});
|
|
|
|
|
// this is a throttled call and will only run once every 1 sec at most
|
|
|
|
|
conversation.updateLastMessage();
|
|
|
|
|
await conversation.commit();
|
|
|
|
|
|
|
|
|
|
if (conversation.id !== sendingDeviceConversation.id) {
|
|
|
|
|
await sendingDeviceConversation.commit();
|
|
|
|
|
}
|
|
|
|
|
// save the message model to the db and it save the messageId generated to our in-memory copy
|
|
|
|
|
const id = await messageModel.commit();
|
|
|
|
|
messageModel.set({ id });
|
|
|
|
|
|
|
|
|
|
void queueAttachmentDownloads(messageModel, conversation);
|
|
|
|
|
// Check if we need to update any profile names
|
|
|
|
|
// the only profile we don't update with what is coming here is ours,
|
|
|
|
|
// as our profile is shared accross our devices with a ConfigurationMessage
|
|
|
|
|
if (messageModel.isIncoming() && regularDataMessage.profile) {
|
|
|
|
|
void appendFetchAvatarAndProfileJob(
|
|
|
|
|
sendingDeviceConversation,
|
|
|
|
|
regularDataMessage.profile,
|
|
|
|
|
regularDataMessage.profileKey
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
// Note that this can save the message again, if jobs were queued. We need to
|
|
|
|
|
// call it after we have an id for this message, because the jobs refer back
|
|
|
|
|
// to their source message.
|
|
|
|
|
|
|
|
|
|
// even with all the warnings, I am very sus about if this is usefull or not
|
|
|
|
|
// try {
|
|
|
|
|
// // We go to the database here because, between the message save above and
|
|
|
|
|
// // the previous line's trigger() call, we might have marked all messages
|
|
|
|
|
// // unread in the database. This message might already be read!
|
|
|
|
|
// const fetched = await getMessageById(messageModel.get('id'));
|
|
|
|
|
|
|
|
|
|
// const previousUnread = messageModel.get('unread');
|
|
|
|
|
|
|
|
|
|
// // Important to update message with latest read state from database
|
|
|
|
|
// messageModel.merge(fetched);
|
|
|
|
|
|
|
|
|
|
// if (previousUnread !== messageModel.get('unread')) {
|
|
|
|
|
// window?.log?.warn(
|
|
|
|
|
// 'Caught race condition on new message read state! ' + 'Manually starting timers.'
|
|
|
|
|
// );
|
|
|
|
|
// // We call markRead() even though the message is already
|
|
|
|
|
// // marked read because we need to start expiration
|
|
|
|
|
// // timers, etc.
|
|
|
|
|
// await messageModel.markRead(Date.now());
|
|
|
|
|
// }
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// window?.log?.warn(
|
|
|
|
|
// 'handleMessageJob: Message',
|
|
|
|
|
// messageModel.idForLogging(),
|
|
|
|
|
// 'was deleted'
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (messageModel.get('unread')) {
|
|
|
|
|
conversation.throttledNotify(messageModel);
|
|
|
|
|
}
|
|
|
|
|
confirm?.();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const errorForLog = error && error.stack ? error.stack : error;
|
|
|
|
|
window?.log?.error('handleMessageJob', messageModel.idForLogging(), 'error:', errorForLog);
|
|
|
|
|
const unreadCount = await conversation.getUnreadCount();
|
|
|
|
|
conversation.set({ unreadCount });
|
|
|
|
|
conversation.set({
|
|
|
|
|
active_at: Math.max(conversation.attributes.active_at, messageModel.get('sent_at') || 0),
|
|
|
|
|
});
|
|
|
|
|
// this is a throttled call and will only run once every 1 sec at most
|
|
|
|
|
conversation.updateLastMessage();
|
|
|
|
|
await conversation.commit();
|
|
|
|
|
|
|
|
|
|
if (conversation.id !== sendingDeviceConversation.id) {
|
|
|
|
|
await sendingDeviceConversation.commit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void queueAttachmentDownloads(messageModel, conversation);
|
|
|
|
|
// Check if we need to update any profile names
|
|
|
|
|
// the only profile we don't update with what is coming here is ours,
|
|
|
|
|
// as our profile is shared accross our devices with a ConfigurationMessage
|
|
|
|
|
if (messageModel.isIncoming() && regularDataMessage.profile) {
|
|
|
|
|
void appendFetchAvatarAndProfileJob(
|
|
|
|
|
sendingDeviceConversation,
|
|
|
|
|
regularDataMessage.profile,
|
|
|
|
|
regularDataMessage.profileKey
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// even with all the warnings, I am very sus about if this is usefull or not
|
|
|
|
|
// try {
|
|
|
|
|
// // We go to the database here because, between the message save above and
|
|
|
|
|
// // the previous line's trigger() call, we might have marked all messages
|
|
|
|
|
// // unread in the database. This message might already be read!
|
|
|
|
|
// const fetched = await getMessageById(messageModel.get('id'));
|
|
|
|
|
|
|
|
|
|
// const previousUnread = messageModel.get('unread');
|
|
|
|
|
|
|
|
|
|
// // Important to update message with latest read state from database
|
|
|
|
|
// messageModel.merge(fetched);
|
|
|
|
|
|
|
|
|
|
// if (previousUnread !== messageModel.get('unread')) {
|
|
|
|
|
// window?.log?.warn(
|
|
|
|
|
// 'Caught race condition on new message read state! ' + 'Manually starting timers.'
|
|
|
|
|
// );
|
|
|
|
|
// // We call markRead() even though the message is already
|
|
|
|
|
// // marked read because we need to start expiration
|
|
|
|
|
// // timers, etc.
|
|
|
|
|
// await messageModel.markRead(Date.now());
|
|
|
|
|
// }
|
|
|
|
|
// } catch (error) {
|
|
|
|
|
// window?.log?.warn(
|
|
|
|
|
// 'handleMessageJob: Message',
|
|
|
|
|
// messageModel.idForLogging(),
|
|
|
|
|
// 'was deleted'
|
|
|
|
|
// );
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
if (messageModel.get('unread')) {
|
|
|
|
|
conversation.throttledNotify(messageModel);
|
|
|
|
|
}
|
|
|
|
|
confirm?.();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
const errorForLog = error && error.stack ? error.stack : error;
|
|
|
|
|
window?.log?.error('handleMessageJob', messageModel.idForLogging(), 'error:', errorForLog);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|