Skip to content

Commit

Permalink
refactor: remove Meteor calls for message history methods (#34204)
Browse files Browse the repository at this point in the history
Co-authored-by: Ricardo Garim <[email protected]>
  • Loading branch information
MarcosSpessatto and ricardogarim authored Feb 14, 2025
1 parent 77ba160 commit 1da75e7
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 172 deletions.
6 changes: 4 additions & 2 deletions apps/meteor/app/api/server/v1/channels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { saveRoomSettings } from '../../../channel-settings/server/methods/saveR
import { mountIntegrationQueryBasedOnPermissions } from '../../../integrations/server/lib/mountQueriesBasedOnPermission';
import { addUsersToRoomMethod } from '../../../lib/server/methods/addUsersToRoom';
import { createChannelMethod } from '../../../lib/server/methods/createChannel';
import { getChannelHistory } from '../../../lib/server/methods/getChannelHistory';
import { leaveRoomMethod } from '../../../lib/server/methods/leaveRoom';
import { settings } from '../../../settings/server';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
Expand Down Expand Up @@ -163,10 +164,11 @@ API.v1.addRoute(

const { count = 20, offset = 0 } = await getPaginationItems(this.queryParams);

const result = await Meteor.callAsync('getChannelHistory', {
const result = await getChannelHistory({
rid: findResult._id,
fromUserId: this.userId,
latest: latest ? new Date(latest) : new Date(),
oldest: oldest && new Date(oldest),
oldest: oldest ? new Date(oldest) : undefined,
inclusive: inclusive === 'true',
offset,
count,
Expand Down
9 changes: 5 additions & 4 deletions apps/meteor/app/api/server/v1/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Meteor } from 'meteor/meteor';

import { reportMessage } from '../../../../server/lib/moderation/reportMessage';
import { messageSearch } from '../../../../server/methods/messageSearch';
import { getMessageHistory } from '../../../../server/publications/messages';
import { roomAccessAttributes } from '../../../authorization/server';
import { canAccessRoomAsync, canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom';
import { canSendMessageAsync } from '../../../authorization/server/functions/canSendMessage';
Expand Down Expand Up @@ -101,17 +102,17 @@ API.v1.addRoute(
...(type && { type }),
};

const result = await Meteor.callAsync('messages/get', roomId, getMessagesQuery);
const result = await getMessageHistory(roomId, this.userId, getMessagesQuery);

if (!result) {
return API.v1.failure();
}

return API.v1.success({
result: {
...(result.updated && { updated: await normalizeMessagesForUser(result.updated, this.userId) }),
...(result.deleted && { deleted: result.deleted }),
...(result.cursor && { cursor: result.cursor }),
updated: 'updated' in result ? await normalizeMessagesForUser(result.updated, this.userId) : [],
deleted: 'deleted' in result ? result.deleted : [],
cursor: 'cursor' in result ? result.cursor : undefined,
},
});
},
Expand Down
4 changes: 3 additions & 1 deletion apps/meteor/app/api/server/v1/groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { hasAllPermissionAsync, hasPermissionAsync } from '../../../authorizatio
import { saveRoomSettings } from '../../../channel-settings/server/methods/saveRoomSettings';
import { mountIntegrationQueryBasedOnPermissions } from '../../../integrations/server/lib/mountQueriesBasedOnPermission';
import { createPrivateGroupMethod } from '../../../lib/server/methods/createPrivateGroup';
import { getChannelHistory } from '../../../lib/server/methods/getChannelHistory';
import { leaveRoomMethod } from '../../../lib/server/methods/leaveRoom';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
import { API } from '../api';
Expand Down Expand Up @@ -505,8 +506,9 @@ API.v1.addRoute(

const showThreadMessages = this.queryParams.showThreadMessages !== 'false';

const result = await Meteor.callAsync('getChannelHistory', {
const result = await getChannelHistory({
rid: findResult.rid,
fromUserId: this.userId,
latest: latestDate,
oldest: oldestDate,
inclusive,
Expand Down
6 changes: 4 additions & 2 deletions apps/meteor/app/api/server/v1/im.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { canAccessRoomIdAsync } from '../../../authorization/server/functions/ca
import { hasAtLeastOnePermissionAsync, hasPermissionAsync } from '../../../authorization/server/functions/hasPermission';
import { saveRoomSettings } from '../../../channel-settings/server/methods/saveRoomSettings';
import { getRoomByNameOrIdWithOptionToJoin } from '../../../lib/server/functions/getRoomByNameOrIdWithOptionToJoin';
import { getChannelHistory } from '../../../lib/server/methods/getChannelHistory';
import { settings } from '../../../settings/server';
import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser';
import { API } from '../api';
Expand Down Expand Up @@ -277,16 +278,17 @@ API.v1.addRoute(

const objectParams = {
rid: room._id,
fromUserId: this.userId,
latest: latest ? new Date(latest) : new Date(),
oldest: oldest && new Date(oldest),
oldest: oldest ? new Date(oldest) : undefined,
inclusive: inclusive === 'true',
offset,
count,
unreads: unreads === 'true',
showThreadMessages: showThreadMessages === 'true',
};

const result = await Meteor.callAsync('getChannelHistory', objectParams);
const result = await getChannelHistory(objectParams);

if (!result) {
return API.v1.forbidden();
Expand Down
242 changes: 138 additions & 104 deletions apps/meteor/app/lib/server/methods/getChannelHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,125 +26,159 @@ declare module '@rocket.chat/ddp-client' {
}
}

Meteor.methods<ServerMethods>({
async getChannelHistory({ rid, latest, oldest, inclusive, offset = 0, count = 20, unreads, showThreadMessages = true }) {
check(rid, String);
export const getChannelHistory = async ({
rid,
fromUserId,
latest,
oldest,
inclusive,
offset = 0,
count = 20,
unreads,
showThreadMessages = true,
}: {
rid: string;
fromUserId: string;
latest?: Date;
oldest?: Date;
inclusive?: boolean;
offset?: number;
count?: number;
unreads?: boolean;
showThreadMessages?: boolean;
}): Promise<false | IMessage[] | { messages: IMessage[]; firstUnread?: any; unreadNotLoaded?: number }> => {
check(rid, String);

if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getChannelHistory' });
}

if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getChannelHistory' });
}
if (!fromUserId) {
return false;
}

const fromUserId = Meteor.userId();
if (!fromUserId) {
return false;
}
const room = await Rooms.findOneById(rid);
if (!room) {
return false;
}

const room = await Rooms.findOneById(rid);
if (!room) {
return false;
}
if (!(await canAccessRoomAsync(room, { _id: fromUserId }))) {
return false;
}

if (!(await canAccessRoomAsync(room, { _id: fromUserId }))) {
return false;
}
// Make sure they can access the room
if (
room.t === 'c' &&
!(await hasPermissionAsync(fromUserId, 'preview-c-room')) &&
!(await Subscriptions.findOneByRoomIdAndUserId(rid, fromUserId, { projection: { _id: 1 } }))
) {
return false;
}

// Make sure they can access the room
if (
room.t === 'c' &&
!(await hasPermissionAsync(fromUserId, 'preview-c-room')) &&
!(await Subscriptions.findOneByRoomIdAndUserId(rid, fromUserId, { projection: { _id: 1 } }))
) {
return false;
}
// Ensure latest is always defined.
if (latest === undefined) {
latest = new Date();
}

// Ensure latest is always defined.
if (latest === undefined) {
latest = new Date();
}
// Verify oldest is a date if it exists

// Verify oldest is a date if it exists
if (oldest !== undefined && {}.toString.call(oldest) !== '[object Date]') {
throw new Meteor.Error('error-invalid-date', 'Invalid date', { method: 'getChannelHistory' });
}

if (oldest !== undefined && {}.toString.call(oldest) !== '[object Date]') {
throw new Meteor.Error('error-invalid-date', 'Invalid date', { method: 'getChannelHistory' });
const hiddenSystemMessages = settings.get<MessageTypesValues[]>('Hide_System_Messages');

const hiddenMessageTypes = getHiddenSystemMessages(room, hiddenSystemMessages);

const options: Record<string, unknown> = {
sort: {
ts: -1,
},
skip: offset,
limit: count,
};

const records =
oldest === undefined
? await Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(
rid,
latest,
hiddenMessageTypes,
options,
showThreadMessages,
inclusive,
).toArray()
: await Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
oldest,
latest,
hiddenMessageTypes,
options,
showThreadMessages,
inclusive,
).toArray();

const messages = await normalizeMessagesForUser(records, fromUserId);

if (unreads) {
let unreadNotLoaded = 0;
let firstUnread = undefined;

if (oldest !== undefined) {
const firstMsg = messages[messages.length - 1];
if (firstMsg !== undefined && firstMsg.ts > oldest) {
const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
oldest,
firstMsg.ts,
hiddenMessageTypes,
{
limit: 1,
sort: {
ts: 1,
},
},
showThreadMessages,
);

const totalCursor = await Messages.countVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
oldest,
firstMsg.ts,
hiddenMessageTypes,
showThreadMessages,
);

firstUnread = (await unreadMessages.toArray())[0];
unreadNotLoaded = totalCursor;
}
}

const hiddenSystemMessages = settings.get<MessageTypesValues[]>('Hide_System_Messages');
return {
messages: messages || [],
firstUnread,
unreadNotLoaded,
};
}

const hiddenMessageTypes = getHiddenSystemMessages(room, hiddenSystemMessages);
return {
messages: messages || [],
};
};

const options: Record<string, unknown> = {
sort: {
ts: -1,
},
skip: offset,
limit: count,
};
Meteor.methods<ServerMethods>({
async getChannelHistory({ rid, latest, oldest, inclusive, offset = 0, count = 20, unreads, showThreadMessages = true }) {
check(rid, String);

const records =
oldest === undefined
? await Messages.findVisibleByRoomIdBeforeTimestampNotContainingTypes(
rid,
latest,
hiddenMessageTypes,
options,
showThreadMessages,
inclusive,
).toArray()
: await Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
oldest,
latest,
hiddenMessageTypes,
options,
showThreadMessages,
inclusive,
).toArray();

const messages = await normalizeMessagesForUser(records, fromUserId);

if (unreads) {
let unreadNotLoaded = 0;
let firstUnread = undefined;

if (oldest !== undefined) {
const firstMsg = messages[messages.length - 1];
if (firstMsg !== undefined && firstMsg.ts > oldest) {
const unreadMessages = Messages.findVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
oldest,
firstMsg.ts,
hiddenMessageTypes,
{
limit: 1,
sort: {
ts: 1,
},
},
showThreadMessages,
);

const totalCursor = await Messages.countVisibleByRoomIdBetweenTimestampsNotContainingTypes(
rid,
oldest,
firstMsg.ts,
hiddenMessageTypes,
showThreadMessages,
);

firstUnread = (await unreadMessages.toArray())[0];
unreadNotLoaded = totalCursor;
}
}
if (!Meteor.userId()) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getChannelHistory' });
}

return {
messages: messages || [],
firstUnread,
unreadNotLoaded,
};
const fromUserId = Meteor.userId();
if (!fromUserId) {
return false;
}

return {
messages: messages || [],
};
return getChannelHistory({ rid, fromUserId, latest, oldest, inclusive, offset, count, unreads, showThreadMessages });
},
});
Loading

0 comments on commit 1da75e7

Please sign in to comment.