站点同步

This commit is contained in:
tianmo committed 2026-10-17 14:41:32 +08:00
1 parent a64be50b73
commit 9cb8552a99
28 files changed
+1683 -18

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
import { findUserByUsername } 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.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 }
}