// Package media holds shared media size/resolution policy (no I/O). // Client App compresses user uploads; bots must compress server-side via infrastructure/media. package media // Default limits aligned with App frontend (image ≤1080p, video ≤720p ≤100MB, avatar ≤200×200). const ( DefaultImageMaxEdge = 1080 DefaultVideoMaxEdge = 720 DefaultAvatarMaxEdge = 200 DefaultImageMaxBytes = 10 << 20 // 10 MiB (square/moment image purpose) DefaultVideoMaxBytes = 100 << 20 // 100 MiB DefaultAvatarMaxBytes = 2 << 20 // 2 MiB (upload purpose hard cap) DefaultJPEGQuality = 85 DefaultVideoCRF = 23 ) // Limits is the resolution/size policy shared by user checks and bot compress. type Limits struct { ImageMaxEdge int VideoMaxEdge int AvatarMaxEdge int ImageMaxBytes int64 VideoMaxBytes int64 AvatarMaxBytes int64 } // DefaultLimits returns client-aligned defaults. func DefaultLimits() Limits { return Limits{ ImageMaxEdge: DefaultImageMaxEdge, VideoMaxEdge: DefaultVideoMaxEdge, AvatarMaxEdge: DefaultAvatarMaxEdge, ImageMaxBytes: DefaultImageMaxBytes, VideoMaxBytes: DefaultVideoMaxBytes, AvatarMaxBytes: DefaultAvatarMaxBytes, } } // Normalize fills zero fields with defaults. func (l Limits) Normalize() Limits { d := DefaultLimits() if l.ImageMaxEdge <= 0 { l.ImageMaxEdge = d.ImageMaxEdge } if l.VideoMaxEdge <= 0 { l.VideoMaxEdge = d.VideoMaxEdge } if l.AvatarMaxEdge <= 0 { l.AvatarMaxEdge = d.AvatarMaxEdge } if l.ImageMaxBytes <= 0 { l.ImageMaxBytes = d.ImageMaxBytes } if l.VideoMaxBytes <= 0 { l.VideoMaxBytes = d.VideoMaxBytes } if l.AvatarMaxBytes <= 0 { l.AvatarMaxBytes = d.AvatarMaxBytes } return l } // LongestEdge returns max(w, h). func LongestEdge(w, h int) int { if w > h { return w } return h } // NeedsResize reports whether the frame exceeds maxEdge (already-smaller is kept as-is). func NeedsResize(w, h, maxEdge int) bool { if maxEdge <= 0 || w <= 0 || h <= 0 { return false } return LongestEdge(w, h) > maxEdge }