102 lines
2.7 KiB
TypeScript
102 lines
2.7 KiB
TypeScript
import {
|
|
findUserByUsername,
|
|
getUploadSourcesForKeys,
|
|
insertActivityLog
|
|
} from '../db'
|
|
import {
|
|
getImageIndexRow,
|
|
insertImageIndex,
|
|
updateImageThumb,
|
|
updateImageTranscode
|
|
} from '../image-index'
|
|
import { getActiveBackend } from '../storage/resolver'
|
|
import {
|
|
createTag,
|
|
findTagByName,
|
|
setImageTags
|
|
} from '../tags'
|
|
import type { SiteSyncMediaTransfer } from './protocol'
|
|
|
|
export async function applySiteSyncMedia(
|
|
media: SiteSyncMediaTransfer,
|
|
conflictMode: 'skip' | 'overwrite',
|
|
actorUserId: number
|
|
): Promise<{ success: true, skipped: boolean }> {
|
|
if (conflictMode === 'skip' && getImageIndexRow(media.key)) {
|
|
return { success: true, skipped: true }
|
|
}
|
|
|
|
const owner = media.ownerUsername
|
|
? findUserByUsername(media.ownerUsername)
|
|
: null
|
|
if (media.ownerUsername && !owner) {
|
|
throw new Error(`当前站点缺少用户:${media.ownerUsername}`)
|
|
}
|
|
|
|
const backend = await getActiveBackend()
|
|
const requiredKeys = [
|
|
...(!media.sourceDeleted ? [media.key] : []),
|
|
...(media.thumbKey ? [media.thumbKey] : []),
|
|
...(media.hlsKey ? [media.hlsKey] : [])
|
|
]
|
|
for (const key of requiredKeys) {
|
|
if (!await backend.head(key)) {
|
|
throw new Error(`同步对象尚未写入:${key}`)
|
|
}
|
|
}
|
|
|
|
insertImageIndex({
|
|
key: media.key,
|
|
backendId: backend.id,
|
|
userId: owner?.id ?? null,
|
|
originalName: media.originalName,
|
|
contentType: media.contentType,
|
|
size: media.size,
|
|
uploadedAt: media.uploadedAt,
|
|
mediaType: media.mediaType
|
|
})
|
|
|
|
if (
|
|
media.uploadSource
|
|
&& getUploadSourcesForKeys([media.key]).get(media.key) !== media.uploadSource
|
|
) {
|
|
insertActivityLog({
|
|
action: 'upload',
|
|
key: media.key,
|
|
originalName: media.originalName,
|
|
size: media.size,
|
|
contentType: media.contentType,
|
|
source: media.uploadSource,
|
|
userId: owner?.id ?? null,
|
|
backendId: backend.id,
|
|
status: 'success',
|
|
createdAt: media.uploadedAt
|
|
})
|
|
}
|
|
|
|
if (media.thumbKey) updateImageThumb(media.key, media.thumbKey)
|
|
if (media.mediaType === 'video') {
|
|
updateImageTranscode(media.key, {
|
|
status: media.transcodeStatus,
|
|
hlsKey: media.hlsKey,
|
|
progress: media.transcodeProgress,
|
|
preset: media.transcodePreset,
|
|
sourceDeleted: media.sourceDeleted,
|
|
error: media.transcodeError
|
|
})
|
|
}
|
|
|
|
const tagOwnerId = owner?.id ?? actorUserId
|
|
const tagIds: number[] = []
|
|
for (const tag of media.tags) {
|
|
const existing = findTagByName(tagOwnerId, tag.name)
|
|
const item = existing
|
|
? { id: existing.id }
|
|
: createTag(tagOwnerId, tag.name, tag.color)
|
|
tagIds.push(item.id)
|
|
}
|
|
setImageTags(media.key, tagIds, tagOwnerId, true)
|
|
|
|
return { success: true, skipped: false }
|
|
}
|