diff --git a/keyserver/src/endpoints.js b/keyserver/src/endpoints.js --- a/keyserver/src/endpoints.js +++ b/keyserver/src/endpoints.js @@ -41,6 +41,7 @@ threadLeaveResponder, threadUpdateResponder, threadCreationResponder, + threadFetchMediaResponder, threadJoinResponder, } from './responders/thread-responders.js'; import { @@ -133,6 +134,10 @@ responder: messageFetchResponder, requiredPolicies: baseLegalPolicies, }, + fetch_thread_media: { + responder: threadFetchMediaResponder, + requiredPolicies: baseLegalPolicies, + }, get_session_public_keys: { responder: getSessionPublicKeysResponder, requiredPolicies: baseLegalPolicies, diff --git a/keyserver/src/fetchers/upload-fetchers.js b/keyserver/src/fetchers/upload-fetchers.js --- a/keyserver/src/fetchers/upload-fetchers.js +++ b/keyserver/src/fetchers/upload-fetchers.js @@ -5,6 +5,10 @@ import type { Media } from 'lib/types/media-types.js'; import type { MediaMessageServerDBContent } from 'lib/types/messages/media.js'; import { getUploadIDsFromMediaMessageServerDBContents } from 'lib/types/messages/media.js'; +import type { + ThreadFetchMediaResult, + ThreadFetchMediaRequest, +} from 'lib/types/thread-types.js'; import { ServerError } from 'lib/utils/errors.js'; import { dbQuery, SQL } from '../database/database.js'; @@ -116,7 +120,9 @@ return result.map(mediaFromRow); } -async function fetchMediaForThread(request: any): Promise { +async function fetchMediaForThread( + request: ThreadFetchMediaRequest, +): Promise { // Fetch the uploads used for the uploadsMap containing the thread media const query = SQL` SELECT id AS uploadID, secret AS uploadSecret, diff --git a/keyserver/src/responders/thread-responders.js b/keyserver/src/responders/thread-responders.js --- a/keyserver/src/responders/thread-responders.js +++ b/keyserver/src/responders/thread-responders.js @@ -15,6 +15,8 @@ type NewThreadResponse, type ServerThreadJoinRequest, type ThreadJoinResult, + type ThreadFetchMediaResult, + type ThreadFetchMediaRequest, threadTypes, } from 'lib/types/thread-types.js'; import { values } from 'lib/utils/objects.js'; @@ -31,6 +33,7 @@ } from './entry-responders.js'; import { createThread } from '../creators/thread-creator.js'; import { deleteThread } from '../deleters/thread-deleters.js'; +import { fetchMediaForThread } from '../fetchers/upload-fetchers.js'; import type { Viewer } from '../session/viewer.js'; import { updateRole, @@ -176,6 +179,21 @@ return await joinThread(viewer, request); } +const threadFetchMediaRequestInputValidator = tShape({ + threadID: t.String, + limit: t.Number, + offset: t.Number, + currentMediaIDs: t.list(t.String), +}); +async function threadFetchMediaResponder( + viewer: Viewer, + input: any, +): Promise { + const request: ThreadFetchMediaRequest = input; + await validateInput(viewer, threadFetchMediaRequestInputValidator, request); + return await fetchMediaForThread(request); +} + export { threadDeletionResponder, roleUpdateResponder, @@ -184,5 +202,6 @@ threadUpdateResponder, threadCreationResponder, threadJoinResponder, + threadFetchMediaResponder, newThreadRequestInputValidator, }; diff --git a/lib/actions/thread-actions.js b/lib/actions/thread-actions.js --- a/lib/actions/thread-actions.js +++ b/lib/actions/thread-actions.js @@ -10,6 +10,8 @@ NewThreadResult, ClientThreadJoinRequest, ThreadJoinPayload, + ThreadFetchMediaRequest, + ThreadFetchMediaResult, } from '../types/thread-types.js'; import type { CallServerEndpoint } from '../utils/call-server-endpoint.js'; import { values } from '../utils/objects.js'; @@ -162,6 +164,15 @@ }; }; +const fetchThreadMedia = ( + callServerEndpoint: CallServerEndpoint, +): (( + request: ThreadFetchMediaRequest, +) => Promise) => async request => { + const response = await callServerEndpoint('fetch_thread_media', request); + return response; +}; + export { deleteThreadActionTypes, deleteThread, @@ -177,4 +188,5 @@ joinThread, leaveThreadActionTypes, leaveThread, + fetchThreadMedia, }; diff --git a/lib/types/endpoints.js b/lib/types/endpoints.js --- a/lib/types/endpoints.js +++ b/lib/types/endpoints.js @@ -61,6 +61,7 @@ FETCH_ENTRY_REVISIONS: 'fetch_entry_revisions', FETCH_ERROR_REPORT_INFOS: 'fetch_error_report_infos', FETCH_MESSAGES: 'fetch_messages', + FETCH_THREAD_MEDIA: 'fetch_thread_media', GET_SESSION_PUBLIC_KEYS: 'get_session_public_keys', JOIN_THREAD: 'join_thread', LEAVE_THREAD: 'leave_thread', diff --git a/lib/types/thread-types.js b/lib/types/thread-types.js --- a/lib/types/thread-types.js +++ b/lib/types/thread-types.js @@ -4,6 +4,7 @@ import type { Shape } from './core.js'; import type { CalendarQuery, RawEntryInfo } from './entry-types.js'; +import type { Media } from './media-types.js'; import type { RawMessageInfo, MessageTruncationStatuses, @@ -453,6 +454,17 @@ +userInfos: $ReadOnlyArray, }; +export type ThreadFetchMediaResult = { + +media: $ReadOnlyArray, + +adjustedOffset: number, +}; +export type ThreadFetchMediaRequest = { + +threadID: string, + +limit: number, + +offset: number, + +currentMediaIDs: $ReadOnlyArray, +}; + export type SidebarInfo = { +threadInfo: ThreadInfo, +lastUpdatedTime: number,