package media import ( "context" "fmt" "strings" pkgmedia "spark-server/internal/pkg/media" ) // BotAsset is compressed media ready for objectstore.Put / PutLarge. type BotAsset struct { Data []byte Width int Height int MIME string Size int64 } // PrepareBotImage compresses RSS/downloaded image bytes to ≤1080p before object storage write. // Call this after HTTP download and before PutLarge. func PrepareBotImage(src []byte, opt Options) (*BotAsset, error) { res, err := CompressImage(src, opt) if err != nil { return nil, err } return &BotAsset{ Data: res.Data, Width: res.Width, Height: res.Height, MIME: res.MIME, Size: int64(len(res.Data)), }, nil } // PrepareBotAvatar compresses bot avatar to ≤200×200. func PrepareBotAvatar(src []byte, opt Options) (*BotAsset, error) { res, err := CompressAvatar(src, opt) if err != nil { return nil, err } return &BotAsset{ Data: res.Data, Width: res.Width, Height: res.Height, MIME: res.MIME, Size: int64(len(res.Data)), }, nil } // PrepareBotVideo compresses downloaded video to ≤720p (requires ffmpeg). func PrepareBotVideo(ctx context.Context, src []byte, opt Options) (*BotAsset, error) { res, err := CompressVideoBytes(ctx, src, opt) if err != nil { return nil, err } return &BotAsset{ Data: res.Data, Width: res.Width, Height: res.Height, MIME: res.MIME, Size: int64(len(res.Data)), }, nil } // OptionsFromLimits builds compressor options from shared policy limits. func OptionsFromLimits(lim pkgmedia.Limits, jpegQuality, videoCRF int, ffmpegPath string) Options { return Options{ Limits: lim.Normalize(), JPEGQuality: jpegQuality, VideoCRF: videoCRF, FFmpegPath: strings.TrimSpace(ffmpegPath), } } // MustCompressBotImage is PrepareBotImage with a clearer error prefix for callers. func MustCompressBotImage(src []byte, opt Options) (*BotAsset, error) { a, err := PrepareBotImage(src, opt) if err != nil { return nil, fmt.Errorf("bot image compress: %w", err) } return a, nil }