feat(backend): handle processing errors and add PWA routes

- Block file downloads and previews with a 424 StatusFailedDependency if file processing failed or the box has issues.
- Register routes for `/service-worker.js` and `/share-target` to support PWA features.
- Update README.md with an AI usage disclosure.
This commit is contained in:
2026-06-08 11:53:37 +03:00
parent dbfdacc396
commit d11aec96e5
26 changed files with 1186 additions and 35 deletions

View File

@@ -45,6 +45,10 @@ func GenerateThumbnailsForBoxAsync(uploadService *services.UploadService, logger
logger.Warn("thumbnail box lookup failed", "source", "thumbnail", "severity", "warn", "code", 4204, "box_id", boxID, "error", err.Error())
return
}
if services.BoxHasTrouble(box) {
logger.Warn("thumbnail one-shot skipped trouble box", "source", "thumbnail", "severity", "warn", "code", 4206, "box_id", boxID, "error", services.BoxTroubleReason(box))
return
}
result, err := generateMissingThumbnailsForBox(uploadService, logger, box)
if err != nil {
@@ -91,6 +95,9 @@ func generateMissingThumbnails(uploadService *services.UploadService, logger *sl
if !box.ExpiresAt.After(now) {
continue
}
if services.BoxHasTrouble(box) {
continue
}
boxResult, err := generateMissingThumbnailsForBox(uploadService, logger, box)
result.Scanned += boxResult.Scanned
@@ -109,10 +116,16 @@ func generateMissingThumbnailsForBox(uploadService *services.UploadService, logg
if !box.ExpiresAt.After(time.Now().UTC()) {
return result, nil
}
if services.BoxHasTrouble(box) {
return result, nil
}
changed := false
for i := range box.Files {
file := &box.Files[i]
if file.Processing || services.FileHasTrouble(*file) {
continue
}
needsPrimary := file.Thumbnail == "" && needsThumbnail(*file)
needsScenes := file.SceneThumbnail == "" && needsVideoScenes(*file)
needsArchive := !archiveListingCurrent(*file) && needsArchiveListing(*file)
@@ -206,6 +219,15 @@ func GenerateArchiveListingForFile(uploadService *services.UploadService, box se
}
func generateThumbnail(uploadService *services.UploadService, box services.Box, file services.File) (string, error) {
if services.BoxHasTrouble(box) {
return "", fmt.Errorf("box is marked as trouble: %s", services.BoxTroubleReason(box))
}
if file.Processing {
return "", fmt.Errorf("file is still processing")
}
if services.FileHasTrouble(file) {
return "", fmt.Errorf("file processing failed: %s", file.ProcessingError)
}
thumbnailName := "@thumb@" + file.ID + ".jpg"
object, err := uploadService.OpenFileObject(context.Background(), box, file)
if err != nil {
@@ -244,6 +266,15 @@ func generateVideoScenesThumbnail(uploadService *services.UploadService, box ser
if !needsVideoScenes(file) {
return "", nil
}
if services.BoxHasTrouble(box) {
return "", fmt.Errorf("box is marked as trouble: %s", services.BoxTroubleReason(box))
}
if file.Processing {
return "", fmt.Errorf("file is still processing")
}
if services.FileHasTrouble(file) {
return "", fmt.Errorf("file processing failed: %s", file.ProcessingError)
}
sceneName := "@scene@" + file.ID + ".jpg"
object, err := uploadService.OpenFileObject(context.Background(), box, file)
if err != nil {
@@ -263,6 +294,15 @@ func generateArchiveListing(uploadService *services.UploadService, box services.
if !needsArchiveListing(file) {
return "", nil
}
if services.BoxHasTrouble(box) {
return "", fmt.Errorf("box is marked as trouble: %s", services.BoxTroubleReason(box))
}
if file.Processing {
return "", fmt.Errorf("file is still processing")
}
if services.FileHasTrouble(file) {
return "", fmt.Errorf("file processing failed: %s", file.ProcessingError)
}
listingName := "@archive@" + file.ID + ".json"
object, err := uploadService.OpenFileObject(context.Background(), box, file)
if err != nil {