fix: resolved missing reactions in open groups, fixed mutation cache logic

pull/2650/head
William Grant 2 years ago
parent dd37133fcc
commit 504f60cb97

@ -446,10 +446,11 @@ async function getMessageBySenderAndSentAt({
} }
async function getMessageByServerId( async function getMessageByServerId(
conversationId: string,
serverId: number, serverId: number,
skipTimerInit: boolean = false skipTimerInit: boolean = false
): Promise<MessageModel | null> { ): Promise<MessageModel | null> {
const message = await channels.getMessageByServerId(serverId); const message = await channels.getMessageByServerId(conversationId, serverId);
if (!message) { if (!message) {
return null; return null;
} }

@ -735,7 +735,6 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
reaction, reaction,
sender: UserUtils.getOurPubKeyStrFromCache(), sender: UserUtils.getOurPubKeyStrFromCache(),
you: true, you: true,
isOpenGroup: false,
}); });
return; return;
} }
@ -752,7 +751,6 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
reaction, reaction,
sender: UserUtils.getOurPubKeyStrFromCache(), sender: UserUtils.getOurPubKeyStrFromCache(),
you: true, you: true,
isOpenGroup: false,
}); });
return; return;
} }

@ -1040,10 +1040,14 @@ function getMessageBySenderAndSentAt({ source, sentAt }: { source: string; sentA
return map(rows, row => jsonToObject(row.json)); return map(rows, row => jsonToObject(row.json));
} }
function getMessageByServerId(serverId: number) { // serverIds are not unique so we need the conversationId
function getMessageByServerId(conversationId: string, serverId: number) {
const row = assertGlobalInstance() const row = assertGlobalInstance()
.prepare(`SELECT * FROM ${MESSAGES_TABLE} WHERE serverId = $serverId;`) .prepare(
`SELECT * FROM ${MESSAGES_TABLE} WHERE conversationId = $conversationId AND serverId = $serverId;`
)
.get({ .get({
conversationId,
serverId, serverId,
}); });

@ -309,7 +309,6 @@ async function handleSwarmMessage(
reaction: rawDataMessage.reaction, reaction: rawDataMessage.reaction,
sender: msgModel.get('source'), sender: msgModel.get('source'),
you: isUsFromCache(msgModel.get('source')), you: isUsFromCache(msgModel.get('source')),
isOpenGroup: false,
}); });
if ( if (
convoToAddMessageTo.isPrivate() && convoToAddMessageTo.isPrivate() &&

@ -2,6 +2,7 @@ import AbortController from 'abort-controller';
import { OpenGroupReactionResponse } from '../../../../types/Reaction'; import { OpenGroupReactionResponse } from '../../../../types/Reaction';
import { Reactions } from '../../../../util/reactions'; import { Reactions } from '../../../../util/reactions';
import { OpenGroupRequestCommonType } from '../opengroupV2/ApiUtil'; import { OpenGroupRequestCommonType } from '../opengroupV2/ApiUtil';
import { getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils';
import { import {
batchFirstSubIsSuccess, batchFirstSubIsSuccess,
batchGlobalIsSuccess, batchGlobalIsSuccess,
@ -26,7 +27,8 @@ export const clearSogsReactionByServerId = async (
serverId: number, serverId: number,
roomInfos: OpenGroupRequestCommonType roomInfos: OpenGroupRequestCommonType
): Promise<boolean> => { ): Promise<boolean> => {
const { supported, conversation } = await hasReactionSupport(serverId); const converationId = getOpenGroupV2ConversationId(roomInfos.serverUrl, roomInfos.roomId);
const { supported, conversation } = await hasReactionSupport(converationId, serverId);
if (!supported) { if (!supported) {
return false; return false;
} }
@ -51,7 +53,7 @@ export const clearSogsReactionByServerId = async (
addToMutationCache(cacheEntry); addToMutationCache(cacheEntry);
// Since responses can take a long time we immediately update the moderators's UI and if there is a problem it is overwritten by handleOpenGroupMessageReactions later. // Since responses can take a long time we immediately update the moderators's UI and if there is a problem it is overwritten by handleOpenGroupMessageReactions later.
await Reactions.handleClearReaction(serverId, reaction); await Reactions.handleClearReaction(converationId, serverId, reaction);
const options: Array<OpenGroupBatchRow> = [ const options: Array<OpenGroupBatchRow> = [
{ {

@ -6,6 +6,7 @@
import { filter, findIndex, remove } from 'lodash'; import { filter, findIndex, remove } from 'lodash';
import { Reactions } from '../../../../util/reactions'; import { Reactions } from '../../../../util/reactions';
import { OpenGroupReactionMessageV4 } from '../opengroupV2/OpenGroupServerPoller'; import { OpenGroupReactionMessageV4 } from '../opengroupV2/OpenGroupServerPoller';
import { getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils';
export enum ChangeType { export enum ChangeType {
REACTIONS = 0, REACTIONS = 0,
@ -143,6 +144,10 @@ export async function processMessagesUsingCache(
} }
message.reactions = updatedReactions; message.reactions = updatedReactions;
await Reactions.handleOpenGroupMessageReactions(message.reactions, message.id); await Reactions.handleOpenGroupMessageReactions(
getOpenGroupV2ConversationId(server, room),
message.id,
message.reactions
);
return message; return message;
} }

@ -12,19 +12,15 @@ import { Reactions } from '../../../../util/reactions';
import { OnionSending } from '../../../onions/onionSend'; import { OnionSending } from '../../../onions/onionSend';
import { ToastUtils, UserUtils } from '../../../utils'; import { ToastUtils, UserUtils } from '../../../utils';
import { OpenGroupPollingUtils } from '../opengroupV2/OpenGroupPollingUtils'; import { OpenGroupPollingUtils } from '../opengroupV2/OpenGroupPollingUtils';
import { getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils';
import { getUsBlindedInThatServer } from './knownBlindedkeys'; import { getUsBlindedInThatServer } from './knownBlindedkeys';
import { batchGlobalIsSuccess, parseBatchGlobalStatusCode } from './sogsV3BatchPoll'; import { batchGlobalIsSuccess, parseBatchGlobalStatusCode } from './sogsV3BatchPoll';
import {
addToMutationCache,
ChangeType,
SogsV3Mutation,
updateMutationCache,
} from './sogsV3MutationCache';
export const hasReactionSupport = async ( export const hasReactionSupport = async (
conversationId: string,
serverId: number serverId: number
): Promise<{ supported: boolean; conversation: ConversationModel | null }> => { ): Promise<{ supported: boolean; conversation: ConversationModel | null }> => {
const found = await Data.getMessageByServerId(serverId); const found = await Data.getMessageByServerId(conversationId, serverId);
if (!found) { if (!found) {
window.log.warn(`Open Group Message ${serverId} not found in db`); window.log.warn(`Open Group Message ${serverId} not found in db`);
return { supported: false, conversation: null }; return { supported: false, conversation: null };
@ -57,7 +53,10 @@ export const sendSogsReactionOnionV4 = async (
throw new Error(`Could not find sogs pubkey of url:${serverUrl}`); throw new Error(`Could not find sogs pubkey of url:${serverUrl}`);
} }
const { supported, conversation } = await hasReactionSupport(reaction.id); const { supported, conversation } = await hasReactionSupport(
getOpenGroupV2ConversationId(serverUrl, room),
reaction.id
);
if (!supported) { if (!supported) {
return false; return false;
} }
@ -82,27 +81,13 @@ export const sendSogsReactionOnionV4 = async (
const method = reaction.action === Action.REACT ? 'PUT' : 'DELETE'; const method = reaction.action === Action.REACT ? 'PUT' : 'DELETE';
const serverPubkey = allValidRoomInfos[0].serverPublicKey; const serverPubkey = allValidRoomInfos[0].serverPublicKey;
const cacheEntry: SogsV3Mutation = {
server: serverUrl,
room: room,
changeType: ChangeType.REACTIONS,
seqno: null,
metadata: {
messageId: reaction.id,
emoji,
action: reaction.action === Action.REACT ? 'ADD' : 'REMOVE',
},
};
addToMutationCache(cacheEntry);
// Since responses can take a long time we immediately update the sender's UI and if there is a problem it is overwritten by handleOpenGroupMessageReactions later. // Since responses can take a long time we immediately update the sender's UI and if there is a problem it is overwritten by handleOpenGroupMessageReactions later.
const me = UserUtils.getOurPubKeyStrFromCache(); const me = UserUtils.getOurPubKeyStrFromCache();
await Reactions.handleMessageReaction({ await Reactions.handleMessageReaction({
reaction, reaction,
sender: blinded ? getUsBlindedInThatServer(conversation) || me : me, sender: blinded ? getUsBlindedInThatServer(conversation) || me : me,
you: true, you: true,
isOpenGroup: true, openGroupConversationId: getOpenGroupV2ConversationId(serverUrl, room),
}); });
// reaction endpoint requires an empty dict {} // reaction endpoint requires an empty dict {}
@ -137,9 +122,5 @@ export const sendSogsReactionOnionV4 = async (
const success = Boolean(reaction.action === Action.REACT ? rawMessage.added : rawMessage.removed); const success = Boolean(reaction.action === Action.REACT ? rawMessage.added : rawMessage.removed);
if (success) {
updateMutationCache(cacheEntry, rawMessage.seqno);
}
return success; return success;
}; };

@ -56,7 +56,6 @@ describe('ReactionMessage', () => {
reaction: reaction as SignalService.DataMessage.IReaction, reaction: reaction as SignalService.DataMessage.IReaction,
sender: ourNumber, sender: ourNumber,
you: true, you: true,
isOpenGroup: false,
}); });
expect(updatedMessage?.get('reacts'), 'original message should have reacts').to.not.be expect(updatedMessage?.get('reacts'), 'original message should have reacts').to.not.be
@ -89,7 +88,6 @@ describe('ReactionMessage', () => {
reaction: reaction as SignalService.DataMessage.IReaction, reaction: reaction as SignalService.DataMessage.IReaction,
sender: ourNumber, sender: ourNumber,
you: true, you: true,
isOpenGroup: false,
}); });
expect(updatedMessage?.get('reacts'), 'original message reacts should be undefined').to.be expect(updatedMessage?.get('reacts'), 'original message reacts should be undefined').to.be

@ -38,14 +38,14 @@ function hitRateLimit(): boolean {
*/ */
const getMessageByReaction = async ( const getMessageByReaction = async (
reaction: SignalService.DataMessage.IReaction, reaction: SignalService.DataMessage.IReaction,
isOpenGroup: boolean openGroupConversationId?: string
): Promise<MessageModel | null> => { ): Promise<MessageModel | null> => {
let originalMessage = null; let originalMessage = null;
const originalMessageId = Number(reaction.id); const originalMessageId = Number(reaction.id);
const originalMessageAuthor = reaction.author; const originalMessageAuthor = reaction.author;
if (isOpenGroup) { if (openGroupConversationId && !isEmpty(openGroupConversationId)) {
originalMessage = await Data.getMessageByServerId(originalMessageId); originalMessage = await Data.getMessageByServerId(openGroupConversationId, originalMessageId);
} else { } else {
const collection = await Data.getMessagesBySentAt(originalMessageId); const collection = await Data.getMessagesBySentAt(originalMessageId);
originalMessage = collection.find((item: MessageModel) => { originalMessage = collection.find((item: MessageModel) => {
@ -152,19 +152,19 @@ const handleMessageReaction = async ({
reaction, reaction,
sender, sender,
you, you,
isOpenGroup, openGroupConversationId,
}: { }: {
reaction: SignalService.DataMessage.IReaction; reaction: SignalService.DataMessage.IReaction;
sender: string; sender: string;
you: boolean; you: boolean;
isOpenGroup: boolean; openGroupConversationId?: string;
}) => { }) => {
if (!reaction.emoji) { if (!reaction.emoji) {
window?.log?.warn(`There is no emoji for the reaction ${reaction}.`); window?.log?.warn(`There is no emoji for the reaction ${reaction}.`);
return; return;
} }
const originalMessage = await getMessageByReaction(reaction, isOpenGroup); const originalMessage = await getMessageByReaction(reaction, openGroupConversationId);
if (!originalMessage) { if (!originalMessage) {
return; return;
} }
@ -240,10 +240,12 @@ const handleMessageReaction = async ({
* Handles updating the UI when clearing all reactions for a certain emoji * Handles updating the UI when clearing all reactions for a certain emoji
* Only usable by moderators in opengroups and runs on their client * Only usable by moderators in opengroups and runs on their client
*/ */
const handleClearReaction = async (serverId: number, emoji: string) => { const handleClearReaction = async (conversationId: string, serverId: number, emoji: string) => {
const originalMessage = await Data.getMessageByServerId(serverId); const originalMessage = await Data.getMessageByServerId(conversationId, serverId);
if (!originalMessage) { if (!originalMessage) {
window?.log?.warn(`Cannot find the original reacted message ${serverId}.`); window?.log?.warn(
`Cannot find the original reacted message ${serverId} in conversation ${conversationId}.`
);
return; return;
} }
@ -265,14 +267,18 @@ const handleClearReaction = async (serverId: number, emoji: string) => {
/** /**
* Handles all message reaction updates/responses for opengroups * Handles all message reaction updates/responses for opengroups
* serverIds are not unique so we need the conversationId
*/ */
const handleOpenGroupMessageReactions = async ( const handleOpenGroupMessageReactions = async (
reactions: OpenGroupReactionList, conversationId: string,
serverId: number serverId: number,
reactions: OpenGroupReactionList
) => { ) => {
const originalMessage = await Data.getMessageByServerId(serverId); const originalMessage = await Data.getMessageByServerId(conversationId, serverId);
if (!originalMessage) { if (!originalMessage) {
window?.log?.warn(`Cannot find the original reacted message ${serverId}.`); window?.log?.warn(
`Cannot find the original reacted message ${serverId} in conversation ${conversationId}.`
);
return; return;
} }

Loading…
Cancel
Save