diff --git a/api/download_subreddit_images.go b/api/download_subreddit_images.go index 955e04a..d16176e 100644 --- a/api/download_subreddit_images.go +++ b/api/download_subreddit_images.go @@ -5,10 +5,12 @@ import ( "errors" "image/jpeg" "io" + "io/fs" "net/http" "net/url" "os" "path" + "path/filepath" "strings" "sync" "time" @@ -185,21 +187,32 @@ func (api *API) downloadSubredditImage(ctx context.Context, post reddit.Post, su return api.saveImageToFSAndDatabase(ctx, tmpImageFile, subreddit, post, devices) } +type stat interface { + Stat() (fs.FileInfo, error) +} + func (api *API) saveImageToFSAndDatabase(ctx context.Context, image io.ReadCloser, subreddit *models.Subreddit, post reddit.Post, devices models.DeviceSlice) (err error) { ctx, span := tracer.Start(ctx, "*API.saveImageToFSAndDatabase") defer span.End() defer image.Close() w, close, err := api.createDeviceImageWriters(post, devices) + defer close() if err != nil { return errs.Wrapw(err, "failed to create image files") } log.New(ctx).Debug("saving image files", "post_id", post.GetID(), "post_url", post.GetImageURL(), "devices", devices) - defer close() - _, err = io.Copy(w, image) + size, err := io.Copy(w, image) if err != nil { return errs.Wrapw(err, "failed to save image files") } + if size == 0 { + if s, ok := image.(stat); ok { + if fi, err := s.Stat(); err == nil { + size = fi.Size() + } + } + } var many []*models.ImageSetter now := time.Now() @@ -209,10 +222,6 @@ func (api *API) saveImageToFSAndDatabase(ctx context.Context, image io.ReadClose nsfw = 1 } width, height := post.GetImageSize() - var size int64 - if fi, err := os.Stat(post.GetImageTargetPath(api.config, device)); err == nil { - size = fi.Size() - } many = append(many, &models.ImageSetter{ Subreddit: omit.From(subreddit.Name), @@ -300,14 +309,14 @@ func (api *API) isImageEntryExists(ctx context.Context, post reddit.Post, device ctx, span := tracer.Start(ctx, "*API.IsImageExists") defer span.End() - _, errQuery := models.Images.Query(ctx, api.db, + exist, errQuery := models.Images.Query(ctx, api.db, models.SelectWhere.Images.Device.EQ(device.Slug), models.SelectWhere.Images.PostName.EQ(post.GetName()), - ).One() + ).Exists() _, errStat := os.Stat(post.GetImageTargetPath(api.config, device)) - return errQuery == nil && errStat == nil + return exist && errQuery == nil && errStat == nil } // findImageFileForDevice finds if any of the image file exists for given devices. @@ -317,16 +326,39 @@ func (api *API) isImageEntryExists(ctx context.Context, post reddit.Post, device // Return nil if no image file exists for the devices. // // Ensure to close the file after use. -func (api *API) findImageFileForDevices(ctx context.Context, post reddit.Post, devices models.DeviceSlice) (file *os.File) { +func (api *API) findImageFileForDevices(ctx context.Context, post reddit.Post, devices models.DeviceSlice) (oldImageFile *os.File) { for _, device := range devices { - _, err := os.Stat(post.GetImageTargetPath(api.config, device)) + stat, err := os.Stat(post.GetImageTargetPath(api.config, device)) if err == nil { - file, err = os.Open(post.GetImageTargetPath(api.config, device)) + oldImageFile, err = os.Open(post.GetImageTargetPath(api.config, device)) if err != nil { log.New(ctx).Err(err).Error("failed to open image file", "filename", post.GetImageTargetPath(api.config, device)) return nil } - return file + defer oldImageFile.Close() + + tempFilename := filepath.Join(os.TempDir(), "redmage", stat.Name()) + + tempFileWrite, err := os.Create(tempFilename) + if err != nil { + log.New(ctx).Err(err).Error("failed to create temp file", "filename", post.GetImageTargetPath(api.config, device)) + return nil + } + defer tempFileWrite.Close() + + _, err = io.Copy(tempFileWrite, oldImageFile) + if err != nil { + log.New(ctx).Err(err).Error("failed to copy image file", "filename", post.GetImageTargetPath(api.config, device)) + return nil + } + + rf, err := os.Open(tempFilename) + if err != nil { + log.New(ctx).Err(err).Error("failed to open temp file", "filename", tempFileWrite.Name()) + return nil + } + + return rf } } diff --git a/rest/subreddits/create.http b/rest/subreddits/create.http index 1297c29..d22a461 100644 --- a/rest/subreddits/create.http +++ b/rest/subreddits/create.http @@ -2,7 +2,7 @@ POST http://localhost:8080/api/v1/subreddits HTTP/1.1 Host: localhost:8080 { - "name": "wallpapers", + "name": "wallpaper", "enable_schedule": 1, "schedule": "@daily", "countback": 300 diff --git a/rest/subreddits/start.http b/rest/subreddits/start.http index 95f0c2b..b0b80f2 100644 --- a/rest/subreddits/start.http +++ b/rest/subreddits/start.http @@ -3,5 +3,5 @@ Host: localhost:8080 Content-Type: application/json { - "subreddit": "wallpapers" + "subreddit": "wallpaper" } diff --git a/views/homeview/homeview.templ b/views/homeview/homeview.templ index 679c238..d4413b5 100644 --- a/views/homeview/homeview.templ +++ b/views/homeview/homeview.templ @@ -39,8 +39,7 @@ templ HomeContent(c *views.Context, data Data) { hx-push-url="true" >