Changeset View
Changeset View
Standalone View
Standalone View
keyserver/src/fetchers/upload-fetchers.js
Show First 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | |||||
): Promise<ThreadFetchMediaResult> { | ): Promise<ThreadFetchMediaResult> { | ||||
const visibleExtractString = `$.${threadPermissions.VISIBLE}.value`; | const visibleExtractString = `$.${threadPermissions.VISIBLE}.value`; | ||||
const query = SQL` | const query = SQL` | ||||
SELECT content.photo AS uploadID, | SELECT content.photo AS uploadID, | ||||
u.secret AS uploadSecret, | u.secret AS uploadSecret, | ||||
u.type AS uploadType, u.extra AS uploadExtra, | u.type AS uploadType, u.extra AS uploadExtra, | ||||
u.container, u.creation_time, | u.container, u.creation_time, | ||||
NULL AS thumbnailID, | NULL AS thumbnailID, | ||||
NULL AS thumbnailUploadSecret | NULL AS thumbnailUploadSecret, | ||||
NULL AS thumbnailUploadExtra | |||||
FROM messages m | FROM messages m | ||||
LEFT JOIN JSON_TABLE( | LEFT JOIN JSON_TABLE( | ||||
m.content, | m.content, | ||||
"$[*]" COLUMNS(photo INT PATH "$") | "$[*]" COLUMNS(photo INT PATH "$") | ||||
) content ON 1 | ) content ON 1 | ||||
LEFT JOIN uploads u ON u.id = content.photo | LEFT JOIN uploads u ON u.id = content.photo | ||||
LEFT JOIN memberships mm ON mm.thread = ${request.threadID} | LEFT JOIN memberships mm ON mm.thread = ${request.threadID} | ||||
AND mm.user = ${viewer.id} | AND mm.user = ${viewer.id} | ||||
WHERE m.thread = ${request.threadID} AND m.type = ${messageTypes.IMAGES} | WHERE m.thread = ${request.threadID} AND m.type = ${messageTypes.IMAGES} | ||||
AND JSON_EXTRACT(mm.permissions, ${visibleExtractString}) IS TRUE | AND JSON_EXTRACT(mm.permissions, ${visibleExtractString}) IS TRUE | ||||
UNION SELECT content.media AS uploadID, | UNION SELECT content.media AS uploadID, | ||||
uv.secret AS uploadSecret, | uv.secret AS uploadSecret, | ||||
uv.type AS uploadType, uv.extra AS uploadExtra, | uv.type AS uploadType, uv.extra AS uploadExtra, | ||||
uv.container, uv.creation_time, | uv.container, uv.creation_time, | ||||
content.thumbnail AS thumbnailID, | content.thumbnail AS thumbnailID, | ||||
ut.secret AS thumbnailUploadSecret | ut.secret AS thumbnailUploadSecret, | ||||
ut.extra AS thumbnailUploadExtra | |||||
FROM messages m | FROM messages m | ||||
LEFT JOIN JSON_TABLE( | LEFT JOIN JSON_TABLE( | ||||
m.content, | m.content, | ||||
"$[*]" COLUMNS( | "$[*]" COLUMNS( | ||||
media INT PATH "$.uploadID", | media INT PATH "$.uploadID", | ||||
thumbnail INT PATH "$.thumbnailUploadID" | thumbnail INT PATH "$.thumbnailUploadID" | ||||
) | ) | ||||
) content ON 1 | ) content ON 1 | ||||
LEFT JOIN uploads uv ON uv.id = content.media | LEFT JOIN uploads uv ON uv.id = content.media | ||||
LEFT JOIN uploads ut ON ut.id = content.thumbnail | LEFT JOIN uploads ut ON ut.id = content.thumbnail | ||||
LEFT JOIN memberships mm ON mm.thread = ${request.threadID} | LEFT JOIN memberships mm ON mm.thread = ${request.threadID} | ||||
AND mm.user = ${viewer.id} | AND mm.user = ${viewer.id} | ||||
WHERE m.thread = ${request.threadID} | WHERE m.thread = ${request.threadID} | ||||
AND m.type = ${messageTypes.MULTIMEDIA} | AND m.type = ${messageTypes.MULTIMEDIA} | ||||
AND JSON_EXTRACT(mm.permissions, ${visibleExtractString}) IS TRUE | AND JSON_EXTRACT(mm.permissions, ${visibleExtractString}) IS TRUE | ||||
ORDER BY creation_time DESC | ORDER BY creation_time DESC | ||||
LIMIT ${request.limit} OFFSET ${request.offset} | LIMIT ${request.limit} OFFSET ${request.offset} | ||||
`; | `; | ||||
const [uploads] = await dbQuery(query); | const [uploads] = await dbQuery(query); | ||||
const media = uploads.map(upload => { | const media = uploads.map(upload => { | ||||
const { uploadID, uploadType, uploadSecret, uploadExtra } = upload; | const { uploadID, uploadType, uploadSecret, uploadExtra } = upload; | ||||
const { width, height } = JSON.parse(uploadExtra); | const { width, height, encryptionKey } = JSON.parse(uploadExtra); | ||||
const dimensions = { width, height }; | const dimensions = { width, height }; | ||||
if (uploadType === 'photo') { | if (uploadType === 'photo') { | ||||
if (encryptionKey) { | |||||
return { | |||||
type: 'encrypted_photo', | |||||
id: uploadID, | |||||
holder: getUploadURL(uploadID, uploadSecret), | |||||
encryptionKey, | |||||
dimensions, | |||||
}; | |||||
} | |||||
return { | return { | ||||
type: 'photo', | type: 'photo', | ||||
id: uploadID, | id: uploadID, | ||||
uri: getUploadURL(uploadID, uploadSecret), | uri: getUploadURL(uploadID, uploadSecret), | ||||
dimensions, | dimensions, | ||||
}; | }; | ||||
} | } | ||||
const { thumbnailID, thumbnailUploadSecret } = upload; | const { thumbnailID, thumbnailUploadSecret, thumbnailUploadExtra } = upload; | ||||
if (encryptionKey) { | |||||
const { encryptionKey: thumbnailEncryptionKey } = | |||||
JSON.parse(thumbnailUploadExtra); | |||||
return { | |||||
type: 'encrypted_video', | |||||
id: uploadID, | |||||
holder: getUploadURL(uploadID, uploadSecret), | |||||
encryptionKey, | |||||
dimensions, | |||||
thumbnailID, | |||||
thumbnailHolder: getUploadURL(thumbnailID, thumbnailUploadSecret), | |||||
thumbnailEncryptionKey, | |||||
}; | |||||
} | |||||
return { | return { | ||||
type: 'video', | type: 'video', | ||||
id: uploadID, | id: uploadID, | ||||
uri: getUploadURL(uploadID, uploadSecret), | uri: getUploadURL(uploadID, uploadSecret), | ||||
dimensions, | dimensions, | ||||
thumbnailID, | thumbnailID, | ||||
thumbnailURI: getUploadURL(thumbnailID, thumbnailUploadSecret), | thumbnailURI: getUploadURL(thumbnailID, thumbnailUploadSecret), | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | ): $ReadOnlyArray<Media> { | ||||
for (const mediaMessageContent of mediaMessageContents) { | for (const mediaMessageContent of mediaMessageContents) { | ||||
const primaryUploadID = mediaMessageContent.uploadID; | const primaryUploadID = mediaMessageContent.uploadID; | ||||
const primaryUpload = uploadMap[primaryUploadID]; | const primaryUpload = uploadMap[primaryUploadID]; | ||||
const primaryUploadSecret = primaryUpload.uploadSecret; | const primaryUploadSecret = primaryUpload.uploadSecret; | ||||
const primaryUploadURI = getUploadURL(primaryUploadID, primaryUploadSecret); | const primaryUploadURI = getUploadURL(primaryUploadID, primaryUploadSecret); | ||||
const uploadExtra = JSON.parse(primaryUpload.uploadExtra); | const uploadExtra = JSON.parse(primaryUpload.uploadExtra); | ||||
const { width, height, loop } = uploadExtra; | const { width, height, loop, encryptionKey } = uploadExtra; | ||||
const dimensions = { width, height }; | const dimensions = { width, height }; | ||||
if (mediaMessageContent.type === 'photo') { | if (mediaMessageContent.type === 'photo') { | ||||
if (encryptionKey) { | |||||
media.push({ | |||||
type: 'encrypted_photo', | |||||
id: primaryUploadID, | |||||
holder: primaryUploadURI, | |||||
encryptionKey, | |||||
dimensions, | |||||
}); | |||||
} else { | |||||
media.push({ | media.push({ | ||||
type: 'photo', | type: 'photo', | ||||
id: primaryUploadID, | id: primaryUploadID, | ||||
uri: primaryUploadURI, | uri: primaryUploadURI, | ||||
dimensions, | dimensions, | ||||
}); | }); | ||||
} | |||||
continue; | continue; | ||||
} | } | ||||
const thumbnailUploadID = mediaMessageContent.thumbnailUploadID; | const thumbnailUploadID = mediaMessageContent.thumbnailUploadID; | ||||
const thumbnailUpload = uploadMap[thumbnailUploadID]; | const thumbnailUpload = uploadMap[thumbnailUploadID]; | ||||
const thumbnailUploadSecret = thumbnailUpload.uploadSecret; | const thumbnailUploadSecret = thumbnailUpload.uploadSecret; | ||||
const thumbnailUploadURI = getUploadURL( | const thumbnailUploadURI = getUploadURL( | ||||
thumbnailUploadID, | thumbnailUploadID, | ||||
thumbnailUploadSecret, | thumbnailUploadSecret, | ||||
); | ); | ||||
const thumbnailUploadExtra = JSON.parse(thumbnailUpload.uploadExtra); | |||||
if (encryptionKey) { | |||||
const video = { | |||||
type: 'encrypted_video', | |||||
id: primaryUploadID, | |||||
holder: primaryUploadURI, | |||||
encryptionKey, | |||||
dimensions, | |||||
thumbnailID: thumbnailUploadID, | |||||
thumbnailHolder: thumbnailUploadURI, | |||||
thumbnailEncryptionKey: thumbnailUploadExtra.encryptionKey, | |||||
}; | |||||
media.push(loop ? { ...video, loop } : video); | |||||
} else { | |||||
const video = { | const video = { | ||||
type: 'video', | type: 'video', | ||||
id: primaryUploadID, | id: primaryUploadID, | ||||
uri: primaryUploadURI, | uri: primaryUploadURI, | ||||
dimensions, | dimensions, | ||||
thumbnailID: thumbnailUploadID, | thumbnailID: thumbnailUploadID, | ||||
thumbnailURI: thumbnailUploadURI, | thumbnailURI: thumbnailUploadURI, | ||||
}; | }; | ||||
media.push(loop ? { ...video, loop } : video); | media.push(loop ? { ...video, loop } : video); | ||||
} | } | ||||
} | |||||
return media; | return media; | ||||
} | } | ||||
export { | export { | ||||
fetchUpload, | fetchUpload, | ||||
fetchUploadChunk, | fetchUploadChunk, | ||||
getUploadSize, | getUploadSize, | ||||
getUploadURL, | getUploadURL, | ||||
mediaFromRow, | mediaFromRow, | ||||
fetchMedia, | fetchMedia, | ||||
fetchMediaForThread, | fetchMediaForThread, | ||||
fetchMediaFromMediaMessageContent, | fetchMediaFromMediaMessageContent, | ||||
constructMediaFromMediaMessageContentsAndUploadRows, | constructMediaFromMediaMessageContentsAndUploadRows, | ||||
}; | }; |