Repository: usememos/memos
File: server/router/api/v1/resource_service.go (Go)

Code before:
		if atomic.LoadInt32(&availableGeneratorAmount) <= 0 {
			return nil, errors.New("not enough available generator amount")
		}
		atomic.AddInt32(&availableGeneratorAmount, -1)
		defer func() {
			atomic.AddInt32(&availableGeneratorAmount, 1)
		}()

		// Otherwise, generate and save the thumbnail image.
		blob, err := s.GetResourceBlob(resource)
		if err != nil {
			return nil, errors.Wrap(err, "failed to get resource blob")
		}
		img, err := imaging.Decode(bytes.NewReader(blob), imaging.AutoOrientation(true))
		if err != nil {
			return nil, errors.Wrap(err, "failed to decode thumbnail image")
		}

		thumbnailMaxWidth := 700 // equal to home/explore screen image max width
		var thumbnailImage image.Image

		if img.Bounds().Max.X > thumbnailMaxWidth {
			thumbnailImage = imaging.Resize(img, thumbnailMaxWidth, 0, imaging.Lanczos)
		} else {
			thumbnailImage = img
		}

		if err := imaging.Save(thumbnailImage, filePath); err != nil {
			return nil, errors.Wrap(err, "failed to save thumbnail file")
		}
	}

	dstFile, err := os.Open(filePath)
	if err != nil {
		return nil, errors.Wrap(err, "failed to open thumbnail file")
	}
	defer dstFile.Close()
	dstBlob, err := io.ReadAll(dstFile)
	if err != nil {
		return nil, errors.Wrap(err, "failed to read thumbnail file")
	}
	return dstBlob, nil
}

var fileKeyPattern = regexp.MustCompile(`\{[a-z]{1,9}\}`)

func replaceFilenameWithPathTemplate(path, filename string) string {
	t := time.Now()
	path = fileKeyPattern.ReplaceAllStringFunc(path, func(s string) string {
		switch s {
		case "{filename}":

Review comment (suggestion):
```suggestion
		var thumbnailImage image.Image
		if img.Bounds().Max.X > thumbnailMaxWidth {
			thumbnailImage = imaging.Resize(img, thumbnailMaxWidth, 0, imaging.Lanczos)
		} else {
			thumbnailImage = img
		}
```

Code after:
		if atomic.LoadInt32(&availableGeneratorAmount) <= 0 {
			return nil, errors.New("not enough available generator amount")
		}
		atomic.AddInt32(&availableGeneratorAmount, -1)
		defer func() {
			atomic.AddInt32(&availableGeneratorAmount, 1)
		}()

		// Otherwise, generate and save the thumbnail image.
		blob, err := s.GetResourceBlob(resource)
		if err != nil {
			return nil, errors.Wrap(err, "failed to get resource blob")
		}
		img, err := imaging.Decode(bytes.NewReader(blob), imaging.AutoOrientation(true))
		if err != nil {
			return nil, errors.Wrap(err, "failed to decode thumbnail image")
		}

		thumbnailMaxWidth := 700 // equal to home/explore screen image max width
		var thumbnailImage image.Image
		if img.Bounds().Max.X > thumbnailMaxWidth {
			thumbnailImage = imaging.Resize(img, thumbnailMaxWidth, 0, imaging.Lanczos)
		} else {
			thumbnailImage = img
		}

		if err := imaging.Save(thumbnailImage, filePath); err != nil {
			return nil, errors.Wrap(err, "failed to save thumbnail file")
		}
	}

	dstFile, err := os.Open(filePath)
	if err != nil {
		return nil, errors.Wrap(err, "failed to open thumbnail file")
	}
	defer dstFile.Close()
	dstBlob, err := io.ReadAll(dstFile)
	if err != nil {
		return nil, errors.Wrap(err, "failed to read thumbnail file")
	}
	return dstBlob, nil
}

var fileKeyPattern = regexp.MustCompile(`\{[a-z]{1,9}\}`)

func replaceFilenameWithPathTemplate(path, filename string) string {
	t := time.Now()
	path = fileKeyPattern.ReplaceAllStringFunc(path, func(s string) string {
		switch s {
		case "{filename}":
			return filename