Changeset View
Changeset View
Standalone View
Standalone View
keyserver/src/fetchers/message-fetchers.js
Show All 22 Lines | import { | ||||
type MessageTruncationStatus, | type MessageTruncationStatus, | ||||
messageTruncationStatus, | messageTruncationStatus, | ||||
type FetchMessageInfosResult, | type FetchMessageInfosResult, | ||||
defaultMaxMessageAge, | defaultMaxMessageAge, | ||||
type FetchPinnedMessagesRequest, | type FetchPinnedMessagesRequest, | ||||
type FetchPinnedMessagesResult, | type FetchPinnedMessagesResult, | ||||
isMessageSidebarSourceReactionOrEdit, | isMessageSidebarSourceReactionOrEdit, | ||||
} from 'lib/types/message-types.js'; | } from 'lib/types/message-types.js'; | ||||
import { defaultNumberPerThread } from 'lib/types/message-types.js'; | |||||
import { threadPermissions } from 'lib/types/thread-permission-types.js'; | import { threadPermissions } from 'lib/types/thread-permission-types.js'; | ||||
import { ServerError } from 'lib/utils/errors.js'; | import { ServerError } from 'lib/utils/errors.js'; | ||||
import { | import { | ||||
constructMediaFromMediaMessageContentsAndUploadRows, | constructMediaFromMediaMessageContentsAndUploadRows, | ||||
imagesFromRow, | imagesFromRow, | ||||
} from './upload-fetchers.js'; | } from './upload-fetchers.js'; | ||||
import { | import { | ||||
dbQuery, | dbQuery, | ||||
SQL, | SQL, | ||||
mergeOrConditions, | mergeOrConditions, | ||||
mergeAndConditions, | mergeAndConditions, | ||||
} from '../database/database.js'; | } from '../database/database.js'; | ||||
import { processQueryForSearch } from '../database/search-utils.js'; | |||||
import type { SQLStatementType } from '../database/types.js'; | import type { SQLStatementType } from '../database/types.js'; | ||||
import type { PushInfo } from '../push/send.js'; | import type { PushInfo } from '../push/send.js'; | ||||
import type { Viewer } from '../session/viewer.js'; | import type { Viewer } from '../session/viewer.js'; | ||||
import { | import { | ||||
creationString, | creationString, | ||||
localIDFromCreationString, | localIDFromCreationString, | ||||
} from '../utils/idempotent.js'; | } from '../utils/idempotent.js'; | ||||
▲ Show 20 Lines • Show All 845 Lines • ▼ Show 20 Lines | ): Promise<$ReadOnlyArray<RawMessageInfo>> { | ||||
const rawRelatedMessageInfos = await fetchRelatedMessages( | const rawRelatedMessageInfos = await fetchRelatedMessages( | ||||
viewer, | viewer, | ||||
rawMessageInfoMap, | rawMessageInfoMap, | ||||
); | ); | ||||
return [...rawMessageInfos, ...rawRelatedMessageInfos]; | return [...rawMessageInfos, ...rawRelatedMessageInfos]; | ||||
} | } | ||||
const searchMessagesPageSize: number = defaultNumberPerThread + 1; | |||||
async function searchMessagesInSingleChat( | |||||
inputQuery: string, | |||||
threadID: string, | |||||
viewer?: Viewer, | |||||
cursor?: string, | |||||
): Promise<$ReadOnlyArray<RawMessageInfo>> { | |||||
if (inputQuery === '') { | |||||
console.warn('received empty search query'); | |||||
return []; | |||||
} | |||||
const pattern = processQueryForSearch(inputQuery); | |||||
const query = SQL` | |||||
SELECT m.id, m.thread AS threadID, m.content, m.time, m.type, m.creation, | |||||
m.user AS creatorID, m.target_message as targetMessageID, | |||||
stm.permissions AS subthread_permissions, up.id AS uploadID, | |||||
up.type AS uploadType, up.secret AS uploadSecret, up.extra AS uploadExtra | |||||
FROM message_search s | |||||
LEFT JOIN messages m ON m.id = s.original_message_id | |||||
LEFT JOIN memberships stm ON m.type = ${messageTypes.CREATE_SUB_THREAD} | |||||
AND stm.thread = m.content AND stm.user = m.user | |||||
LEFT JOIN uploads up ON up.container = m.id | |||||
LEFT JOIN messages m2 ON m2.target_message = m.id | |||||
AND m2.type = ${messageTypes.SIDEBAR_SOURCE} AND m2.thread = ${threadID} | |||||
WHERE MATCH(s.processed_content) AGAINST(${pattern} IN BOOLEAN MODE) | |||||
AND (m.thread = ${threadID} OR m2.id IS NOT NULL) | |||||
`; | |||||
if (cursor) { | |||||
query.append(SQL`AND m.id < ${cursor} `); | |||||
} | |||||
query.append(SQL` | |||||
ORDER BY m.time DESC, m.id DESC | |||||
LIMIT ${searchMessagesPageSize} | |||||
`); | |||||
const [results] = await dbQuery(query); | |||||
if (results.length === 0) { | |||||
return []; | |||||
} | |||||
const rawMessageInfos = await rawMessageInfoForRowsAndRelatedMessages( | |||||
results, | |||||
viewer, | |||||
); | |||||
return shimUnsupportedRawMessageInfos( | |||||
rawMessageInfos, | |||||
viewer?.platformDetails, | |||||
); | |||||
} | |||||
export { | export { | ||||
fetchCollapsableNotifs, | fetchCollapsableNotifs, | ||||
fetchMessageInfos, | fetchMessageInfos, | ||||
fetchMessageInfosSince, | fetchMessageInfosSince, | ||||
getMessageFetchResultFromRedisMessages, | getMessageFetchResultFromRedisMessages, | ||||
fetchMessageInfoForLocalID, | fetchMessageInfoForLocalID, | ||||
fetchMessageInfoForEntryAction, | fetchMessageInfoForEntryAction, | ||||
fetchMessageInfoByID, | fetchMessageInfoByID, | ||||
fetchThreadMessagesCount, | fetchThreadMessagesCount, | ||||
fetchLatestEditMessageContentByID, | fetchLatestEditMessageContentByID, | ||||
fetchPinnedMessageInfos, | fetchPinnedMessageInfos, | ||||
fetchRelatedMessages, | fetchRelatedMessages, | ||||
rawMessageInfoForRowsAndRelatedMessages, | rawMessageInfoForRowsAndRelatedMessages, | ||||
searchMessagesInSingleChat, | |||||
searchMessagesPageSize, | |||||
}; | }; |