mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-23 20:26:39 +00:00
Compare commits
4 commits
c80ef9330a
...
33d3219ebb
Author | SHA1 | Date | |
---|---|---|---|
33d3219ebb | |||
d2820a1470 | |||
a1966f723d | |||
36409a4ac0 |
3
go.mod
3
go.mod
|
@ -17,7 +17,6 @@ require (
|
||||||
codeberg.org/gruf/go-kv v1.6.5
|
codeberg.org/gruf/go-kv v1.6.5
|
||||||
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
codeberg.org/gruf/go-list v0.0.0-20240425093752-494db03d641f
|
||||||
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
|
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
|
||||||
codeberg.org/gruf/go-mimetypes v1.2.0
|
|
||||||
codeberg.org/gruf/go-mutexes v1.5.1
|
codeberg.org/gruf/go-mutexes v1.5.1
|
||||||
codeberg.org/gruf/go-runners v1.6.3
|
codeberg.org/gruf/go-runners v1.6.3
|
||||||
codeberg.org/gruf/go-sched v1.2.4
|
codeberg.org/gruf/go-sched v1.2.4
|
||||||
|
@ -42,7 +41,7 @@ require (
|
||||||
github.com/k3a/html2text v1.2.1
|
github.com/k3a/html2text v1.2.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.27
|
github.com/microcosm-cc/bluemonday v1.0.27
|
||||||
github.com/miekg/dns v1.1.62
|
github.com/miekg/dns v1.1.62
|
||||||
github.com/minio/minio-go/v7 v7.0.79
|
github.com/minio/minio-go/v7 v7.0.80
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/ncruces/go-sqlite3 v0.20.0
|
github.com/ncruces/go-sqlite3 v0.20.0
|
||||||
github.com/oklog/ulid v1.3.1
|
github.com/oklog/ulid v1.3.1
|
||||||
|
|
6
go.sum
generated
6
go.sum
generated
|
@ -62,8 +62,6 @@ codeberg.org/gruf/go-maps v1.0.4 h1:K+Ww4vvR3TZqm5jqrKVirmguZwa3v1VUvmig2SE8uxY=
|
||||||
codeberg.org/gruf/go-maps v1.0.4/go.mod h1:ASX7osM7kFwt5O8GfGflcFjrwYGD8eIuRLl/oMjhEi8=
|
codeberg.org/gruf/go-maps v1.0.4/go.mod h1:ASX7osM7kFwt5O8GfGflcFjrwYGD8eIuRLl/oMjhEi8=
|
||||||
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760 h1:m2/UCRXhjDwAg4vyji6iKCpomKw6P4PmBOUi5DvAMH4=
|
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760 h1:m2/UCRXhjDwAg4vyji6iKCpomKw6P4PmBOUi5DvAMH4=
|
||||||
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760/go.mod h1:E3RcaCFNq4zXpvaJb8lfpPqdUAmSkP5F1VmMiEUYTEk=
|
codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760/go.mod h1:E3RcaCFNq4zXpvaJb8lfpPqdUAmSkP5F1VmMiEUYTEk=
|
||||||
codeberg.org/gruf/go-mimetypes v1.2.0 h1:3rZGXY/SkNYbamiddWXs2gETXIBkGIeWYnbWpp2OEbc=
|
|
||||||
codeberg.org/gruf/go-mimetypes v1.2.0/go.mod h1:YiUWRj/nAdJQc+UFRvcsL6xXZsbc6b6Ic739ycEO8Yg=
|
|
||||||
codeberg.org/gruf/go-mutexes v1.5.1 h1:xICU0WXhWr6wf+Iror4eE3xT+xnXNPrO6o77D/G6QuY=
|
codeberg.org/gruf/go-mutexes v1.5.1 h1:xICU0WXhWr6wf+Iror4eE3xT+xnXNPrO6o77D/G6QuY=
|
||||||
codeberg.org/gruf/go-mutexes v1.5.1/go.mod h1:rPEqQ/y6CmGITaZ3GPTMQVsoZAOzbsAHyIaLsJcOqVE=
|
codeberg.org/gruf/go-mutexes v1.5.1/go.mod h1:rPEqQ/y6CmGITaZ3GPTMQVsoZAOzbsAHyIaLsJcOqVE=
|
||||||
codeberg.org/gruf/go-runners v1.6.3 h1:To/AX7eTrWuXrTkA3RA01YTP5zha1VZ68LQ+0D4RY7E=
|
codeberg.org/gruf/go-runners v1.6.3 h1:To/AX7eTrWuXrTkA3RA01YTP5zha1VZ68LQ+0D4RY7E=
|
||||||
|
@ -413,8 +411,8 @@ github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||||
github.com/minio/minio-go/v7 v7.0.79 h1:SvJZpj3hT0RN+4KiuX/FxLfPZdsuegy6d/2PiemM/bM=
|
github.com/minio/minio-go/v7 v7.0.80 h1:2mdUHXEykRdY/BigLt3Iuu1otL0JTogT0Nmltg0wujk=
|
||||||
github.com/minio/minio-go/v7 v7.0.79/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
|
github.com/minio/minio-go/v7 v7.0.80/go.mod h1:84gmIilaX4zcvAWWzJ5Z1WI5axN+hAbM5w25xf8xvC0=
|
||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||||
|
|
|
@ -323,14 +323,14 @@ type videoStream struct {
|
||||||
//
|
//
|
||||||
// Note the checks for (len(res.video) > 0) may catch some audio files with embedded
|
// Note the checks for (len(res.video) > 0) may catch some audio files with embedded
|
||||||
// album art as video, but i blame that on the hellscape that is media filetypes.
|
// album art as video, but i blame that on the hellscape that is media filetypes.
|
||||||
//
|
func (res *result) GetFileType() (gtsmodel.FileType, string, string) {
|
||||||
// TODO: we can update this code to also return a mimetype and avoid later parsing!
|
|
||||||
func (res *result) GetFileType() (gtsmodel.FileType, string) {
|
|
||||||
switch res.format {
|
switch res.format {
|
||||||
case "mpeg":
|
case "mpeg":
|
||||||
return gtsmodel.FileTypeVideo, "mpeg"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/mpeg", "mpeg"
|
||||||
case "mjpeg":
|
case "mjpeg":
|
||||||
return gtsmodel.FileTypeVideo, "mjpeg"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/x-motion-jpeg", "mjpeg"
|
||||||
case "mov,mp4,m4a,3gp,3g2,mj2":
|
case "mov,mp4,m4a,3gp,3g2,mj2":
|
||||||
switch {
|
switch {
|
||||||
case len(res.video) > 0:
|
case len(res.video) > 0:
|
||||||
|
@ -338,55 +338,70 @@ func (res *result) GetFileType() (gtsmodel.FileType, string) {
|
||||||
res.duration <= 30 {
|
res.duration <= 30 {
|
||||||
// Short, soundless
|
// Short, soundless
|
||||||
// video file aka gifv.
|
// video file aka gifv.
|
||||||
return gtsmodel.FileTypeGifv, "mp4"
|
return gtsmodel.FileTypeGifv,
|
||||||
|
"video/mp4", "mp4"
|
||||||
} else {
|
} else {
|
||||||
// Video file (with or without audio).
|
// Video file (with or without audio).
|
||||||
return gtsmodel.FileTypeVideo, "mp4"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/mp4", "mp4"
|
||||||
}
|
}
|
||||||
case len(res.audio) > 0 &&
|
case len(res.audio) > 0 &&
|
||||||
res.audio[0].codec == "aac":
|
res.audio[0].codec == "aac":
|
||||||
// m4a only supports [aac] audio.
|
// m4a only supports [aac] audio.
|
||||||
return gtsmodel.FileTypeAudio, "m4a"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/mp4", "m4a"
|
||||||
}
|
}
|
||||||
case "apng":
|
case "apng":
|
||||||
return gtsmodel.FileTypeImage, "apng"
|
return gtsmodel.FileTypeImage,
|
||||||
|
"image/apng", "apng"
|
||||||
case "png_pipe":
|
case "png_pipe":
|
||||||
return gtsmodel.FileTypeImage, "png"
|
return gtsmodel.FileTypeImage,
|
||||||
|
"image/png", "png"
|
||||||
case "image2", "image2pipe", "jpeg_pipe":
|
case "image2", "image2pipe", "jpeg_pipe":
|
||||||
return gtsmodel.FileTypeImage, "jpeg"
|
return gtsmodel.FileTypeImage,
|
||||||
|
"image/jpeg", "jpeg"
|
||||||
case "webp", "webp_pipe":
|
case "webp", "webp_pipe":
|
||||||
return gtsmodel.FileTypeImage, "webp"
|
return gtsmodel.FileTypeImage,
|
||||||
|
"image/webp", "webp"
|
||||||
case "gif":
|
case "gif":
|
||||||
return gtsmodel.FileTypeImage, "gif"
|
return gtsmodel.FileTypeImage,
|
||||||
|
"image/gif", "gif"
|
||||||
case "mp3":
|
case "mp3":
|
||||||
if len(res.audio) > 0 {
|
if len(res.audio) > 0 {
|
||||||
switch res.audio[0].codec {
|
switch res.audio[0].codec {
|
||||||
case "mp2":
|
case "mp2":
|
||||||
return gtsmodel.FileTypeAudio, "mp2"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/mp2", "mp2"
|
||||||
case "mp3":
|
case "mp3":
|
||||||
return gtsmodel.FileTypeAudio, "mp3"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/mp3", "mp3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "asf":
|
case "asf":
|
||||||
switch {
|
switch {
|
||||||
case len(res.video) > 0:
|
case len(res.video) > 0:
|
||||||
return gtsmodel.FileTypeVideo, "wmv"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/x-ms-wmv", "wmv"
|
||||||
case len(res.audio) > 0:
|
case len(res.audio) > 0:
|
||||||
return gtsmodel.FileTypeAudio, "wma"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/x-ms-wma", "wma"
|
||||||
}
|
}
|
||||||
case "ogg":
|
case "ogg":
|
||||||
if len(res.video) > 0 {
|
if len(res.video) > 0 {
|
||||||
switch res.video[0].codec {
|
switch res.video[0].codec {
|
||||||
case "theora", "dirac": // daala, tarkin
|
case "theora", "dirac": // daala, tarkin
|
||||||
return gtsmodel.FileTypeVideo, "ogv"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/ogg", "ogv"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(res.audio) > 0 {
|
if len(res.audio) > 0 {
|
||||||
switch res.audio[0].codec {
|
switch res.audio[0].codec {
|
||||||
case "opus", "libopus":
|
case "opus", "libopus":
|
||||||
return gtsmodel.FileTypeAudio, "opus"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/opus", "opus"
|
||||||
default:
|
default:
|
||||||
return gtsmodel.FileTypeAudio, "ogg"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/ogg", "ogg"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "matroska,webm":
|
case "matroska,webm":
|
||||||
|
@ -411,21 +426,27 @@ func (res *result) GetFileType() (gtsmodel.FileType, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if isWebm {
|
if isWebm {
|
||||||
// Check for valid webm codec config.
|
// Check valid webm codec config.
|
||||||
return gtsmodel.FileTypeVideo, "webm"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/webm", "webm"
|
||||||
}
|
}
|
||||||
|
|
||||||
// All else falls under generic mkv.
|
// All else falls under generic mkv.
|
||||||
return gtsmodel.FileTypeVideo, "mkv"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/x-matroska", "mkv"
|
||||||
case len(res.audio) > 0:
|
case len(res.audio) > 0:
|
||||||
return gtsmodel.FileTypeAudio, "mka"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/x-matroska", "mka"
|
||||||
}
|
}
|
||||||
case "avi":
|
case "avi":
|
||||||
return gtsmodel.FileTypeVideo, "avi"
|
return gtsmodel.FileTypeVideo,
|
||||||
|
"video/x-msvideo", "avi"
|
||||||
case "flac":
|
case "flac":
|
||||||
return gtsmodel.FileTypeAudio, "flac"
|
return gtsmodel.FileTypeAudio,
|
||||||
|
"audio/flac", "flac"
|
||||||
}
|
}
|
||||||
return gtsmodel.FileTypeUnknown, res.format
|
return gtsmodel.FileTypeUnknown,
|
||||||
|
"", res.format
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageMeta extracts image metadata contained within ffprobe'd media result streams.
|
// ImageMeta extracts image metadata contained within ffprobe'd media result streams.
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"video/ogg", // .ogv
|
"video/ogg", // .ogv
|
||||||
|
|
||||||
// mpeg4 types
|
// mpeg4 types
|
||||||
"audio/x-m4a", // .m4a
|
"audio/mp4", // .m4a
|
||||||
"video/mp4", // .mp4
|
"video/mp4", // .mp4
|
||||||
"video/quicktime", // .mov
|
"video/quicktime", // .mov
|
||||||
|
|
||||||
|
|
|
@ -163,9 +163,10 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var ext string
|
var ext string
|
||||||
|
var fileType gtsmodel.FileType
|
||||||
|
|
||||||
// Get type from ffprobe format data.
|
// Get abstract file type, mimetype and ext from ffprobe data.
|
||||||
fileType, ext := result.GetFileType()
|
fileType, p.emoji.ImageContentType, ext = result.GetFileType()
|
||||||
if fileType != gtsmodel.FileTypeImage {
|
if fileType != gtsmodel.FileTypeImage {
|
||||||
return gtserror.Newf("unsupported emoji filetype: %s (%s)", fileType, ext)
|
return gtserror.Newf("unsupported emoji filetype: %s (%s)", fileType, ext)
|
||||||
}
|
}
|
||||||
|
@ -216,10 +217,6 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
|
||||||
"png",
|
"png",
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get mimetype for the file container
|
|
||||||
// type, falling back to generic data.
|
|
||||||
p.emoji.ImageContentType = getMimeType(ext)
|
|
||||||
|
|
||||||
// Set the known emoji static content type.
|
// Set the known emoji static content type.
|
||||||
p.emoji.ImageStaticContentType = "image/png"
|
p.emoji.ImageStaticContentType = "image/png"
|
||||||
|
|
||||||
|
|
|
@ -186,8 +186,8 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
p.media.FileMeta.Original.Duration = util.PtrIf(float32(result.duration))
|
p.media.FileMeta.Original.Duration = util.PtrIf(float32(result.duration))
|
||||||
p.media.FileMeta.Original.Bitrate = util.PtrIf(result.bitrate)
|
p.media.FileMeta.Original.Bitrate = util.PtrIf(result.bitrate)
|
||||||
|
|
||||||
// Set media type from ffprobe format data.
|
// Set generic media type and mimetype from ffprobe format data.
|
||||||
p.media.Type, ext = result.GetFileType()
|
p.media.Type, p.media.File.ContentType, ext = result.GetFileType()
|
||||||
|
|
||||||
// Add file extension to path.
|
// Add file extension to path.
|
||||||
newpath := temppath + "." + ext
|
newpath := temppath + "." + ext
|
||||||
|
@ -236,10 +236,10 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
|
|
||||||
// Determine if blurhash needs generating.
|
// Determine if blurhash needs generating.
|
||||||
needBlurhash := (p.media.Blurhash == "")
|
needBlurhash := (p.media.Blurhash == "")
|
||||||
var newBlurhash string
|
var newBlurhash, mimeType string
|
||||||
|
|
||||||
// Generate thumbnail, and new blurhash if need from media.
|
// Generate thumbnail, and new blurhash if needed from temp media.
|
||||||
thumbpath, newBlurhash, err = generateThumb(ctx, temppath,
|
thumbpath, mimeType, newBlurhash, err = generateThumb(ctx, temppath,
|
||||||
thumbWidth,
|
thumbWidth,
|
||||||
thumbHeight,
|
thumbHeight,
|
||||||
result.orientation,
|
result.orientation,
|
||||||
|
@ -250,6 +250,9 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
return gtserror.Newf("error generating image thumb: %w", err)
|
return gtserror.Newf("error generating image thumb: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set generated thumbnail's mimetype.
|
||||||
|
p.media.Thumbnail.ContentType = mimeType
|
||||||
|
|
||||||
if needBlurhash {
|
if needBlurhash {
|
||||||
// Set newly determined blurhash.
|
// Set newly determined blurhash.
|
||||||
p.media.Blurhash = newBlurhash
|
p.media.Blurhash = newBlurhash
|
||||||
|
@ -265,10 +268,6 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
ext,
|
ext,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get mimetype for the file container
|
|
||||||
// type, falling back to generic data.
|
|
||||||
p.media.File.ContentType = getMimeType(ext)
|
|
||||||
|
|
||||||
// Copy temporary file into storage at path.
|
// Copy temporary file into storage at path.
|
||||||
filesz, err := p.mgr.state.Storage.PutFile(ctx,
|
filesz, err := p.mgr.state.Storage.PutFile(ctx,
|
||||||
p.media.File.Path,
|
p.media.File.Path,
|
||||||
|
@ -295,9 +294,6 @@ func (p *ProcessingMedia) store(ctx context.Context) error {
|
||||||
thumbExt,
|
thumbExt,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Determine thumbnail content-type from thumb ext.
|
|
||||||
p.media.Thumbnail.ContentType = getMimeType(thumbExt)
|
|
||||||
|
|
||||||
// Copy thumbnail file into storage at path.
|
// Copy thumbnail file into storage at path.
|
||||||
thumbsz, err := p.mgr.state.Storage.PutFile(ctx,
|
thumbsz, err := p.mgr.state.Storage.PutFile(ctx,
|
||||||
p.media.Thumbnail.Path,
|
p.media.Thumbnail.Path,
|
||||||
|
|
|
@ -84,17 +84,21 @@ func generateThumb(
|
||||||
needBlurhash bool,
|
needBlurhash bool,
|
||||||
) (
|
) (
|
||||||
outpath string,
|
outpath string,
|
||||||
|
mimeType string,
|
||||||
blurhash string,
|
blurhash string,
|
||||||
err error,
|
err error,
|
||||||
) {
|
) {
|
||||||
var ext string
|
var ext string
|
||||||
|
|
||||||
|
// Default type is webp.
|
||||||
|
mimeType = "image/webp"
|
||||||
|
|
||||||
// Generate thumb output path REPLACING extension.
|
// Generate thumb output path REPLACING extension.
|
||||||
if i := strings.IndexByte(filepath, '.'); i != -1 {
|
if i := strings.IndexByte(filepath, '.'); i != -1 {
|
||||||
outpath = filepath[:i] + "_thumb.webp"
|
outpath = filepath[:i] + "_thumb.webp"
|
||||||
ext = filepath[i+1:] // old extension
|
ext = filepath[i+1:] // old extension
|
||||||
} else {
|
} else {
|
||||||
return "", "", gtserror.New("input file missing extension")
|
return "", "", "", gtserror.New("input file missing extension")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for the few media types we
|
// Check for the few media types we
|
||||||
|
@ -106,6 +110,7 @@ func generateThumb(
|
||||||
// Replace the "webp" with "jpeg", as we'll
|
// Replace the "webp" with "jpeg", as we'll
|
||||||
// use our native Go thumbnailing generation.
|
// use our native Go thumbnailing generation.
|
||||||
outpath = outpath[:len(outpath)-4] + "jpeg"
|
outpath = outpath[:len(outpath)-4] + "jpeg"
|
||||||
|
mimeType = "image/jpeg"
|
||||||
|
|
||||||
log.Debug(ctx, "generating thumb from jpeg")
|
log.Debug(ctx, "generating thumb from jpeg")
|
||||||
blurhash, err := generateNativeThumb(
|
blurhash, err := generateNativeThumb(
|
||||||
|
@ -117,7 +122,7 @@ func generateThumb(
|
||||||
jpeg.Decode,
|
jpeg.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, blurhash, err
|
return outpath, mimeType, blurhash, err
|
||||||
|
|
||||||
// We specifically only allow generating native
|
// We specifically only allow generating native
|
||||||
// thumbnails from gif IF it doesn't contain an
|
// thumbnails from gif IF it doesn't contain an
|
||||||
|
@ -128,6 +133,7 @@ func generateThumb(
|
||||||
// Replace the "webp" with "jpeg", as we'll
|
// Replace the "webp" with "jpeg", as we'll
|
||||||
// use our native Go thumbnailing generation.
|
// use our native Go thumbnailing generation.
|
||||||
outpath = outpath[:len(outpath)-4] + "jpeg"
|
outpath = outpath[:len(outpath)-4] + "jpeg"
|
||||||
|
mimeType = "image/jpeg"
|
||||||
|
|
||||||
log.Debug(ctx, "generating thumb from gif")
|
log.Debug(ctx, "generating thumb from gif")
|
||||||
blurhash, err := generateNativeThumb(
|
blurhash, err := generateNativeThumb(
|
||||||
|
@ -139,7 +145,7 @@ func generateThumb(
|
||||||
gif.Decode,
|
gif.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, blurhash, err
|
return outpath, mimeType, blurhash, err
|
||||||
|
|
||||||
// We specifically only allow generating native
|
// We specifically only allow generating native
|
||||||
// thumbnails from png IF it doesn't contain an
|
// thumbnails from png IF it doesn't contain an
|
||||||
|
@ -150,6 +156,7 @@ func generateThumb(
|
||||||
// Replace the "webp" with "jpeg", as we'll
|
// Replace the "webp" with "jpeg", as we'll
|
||||||
// use our native Go thumbnailing generation.
|
// use our native Go thumbnailing generation.
|
||||||
outpath = outpath[:len(outpath)-4] + "jpeg"
|
outpath = outpath[:len(outpath)-4] + "jpeg"
|
||||||
|
mimeType = "image/jpeg"
|
||||||
|
|
||||||
log.Debug(ctx, "generating thumb from png")
|
log.Debug(ctx, "generating thumb from png")
|
||||||
blurhash, err := generateNativeThumb(
|
blurhash, err := generateNativeThumb(
|
||||||
|
@ -161,7 +168,7 @@ func generateThumb(
|
||||||
png.Decode,
|
png.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, blurhash, err
|
return outpath, mimeType, blurhash, err
|
||||||
|
|
||||||
// We specifically only allow generating native
|
// We specifically only allow generating native
|
||||||
// thumbnails from webp IF it doesn't contain an
|
// thumbnails from webp IF it doesn't contain an
|
||||||
|
@ -172,6 +179,7 @@ func generateThumb(
|
||||||
// Replace the "webp" with "jpeg", as we'll
|
// Replace the "webp" with "jpeg", as we'll
|
||||||
// use our native Go thumbnailing generation.
|
// use our native Go thumbnailing generation.
|
||||||
outpath = outpath[:len(outpath)-4] + "jpeg"
|
outpath = outpath[:len(outpath)-4] + "jpeg"
|
||||||
|
mimeType = "image/jpeg"
|
||||||
|
|
||||||
log.Debug(ctx, "generating thumb from webp")
|
log.Debug(ctx, "generating thumb from webp")
|
||||||
blurhash, err := generateNativeThumb(
|
blurhash, err := generateNativeThumb(
|
||||||
|
@ -183,7 +191,7 @@ func generateThumb(
|
||||||
webp.Decode,
|
webp.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, blurhash, err
|
return outpath, mimeType, blurhash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The fallback for thumbnail generation, which
|
// The fallback for thumbnail generation, which
|
||||||
|
@ -196,18 +204,18 @@ func generateThumb(
|
||||||
height,
|
height,
|
||||||
pixfmt,
|
pixfmt,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return outpath, "", err
|
return outpath, "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if needBlurhash {
|
if needBlurhash {
|
||||||
// Generate new blurhash from webp output thumb.
|
// Generate new blurhash from webp output thumb.
|
||||||
blurhash, err = generateWebpBlurhash(outpath)
|
blurhash, err = generateWebpBlurhash(outpath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return outpath, "", gtserror.Newf("error generating blurhash: %w", err)
|
return outpath, "", "", gtserror.Newf("error generating blurhash: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return outpath, blurhash, err
|
return outpath, mimeType, blurhash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateNativeThumb generates a thumbnail
|
// generateNativeThumb generates a thumbnail
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
package media
|
package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmp"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -28,7 +27,6 @@
|
||||||
|
|
||||||
"codeberg.org/gruf/go-bytesize"
|
"codeberg.org/gruf/go-bytesize"
|
||||||
"codeberg.org/gruf/go-iotools"
|
"codeberg.org/gruf/go-iotools"
|
||||||
"codeberg.org/gruf/go-mimetypes"
|
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -87,12 +85,6 @@ func getExtension(path string) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// getMimeType returns a suitable mimetype for file extension.
|
|
||||||
func getMimeType(ext string) string {
|
|
||||||
const defaultType = "application/octet-stream"
|
|
||||||
return cmp.Or(mimetypes.MimeTypes[ext], defaultType)
|
|
||||||
}
|
|
||||||
|
|
||||||
// drainToTmp drains data from given reader into a new temp file
|
// drainToTmp drains data from given reader into a new temp file
|
||||||
// and closes it, returning the path of the resulting temp file.
|
// and closes it, returning the path of the resulting temp file.
|
||||||
//
|
//
|
||||||
|
|
5
vendor/codeberg.org/gruf/go-mimetypes/README.md
generated
vendored
5
vendor/codeberg.org/gruf/go-mimetypes/README.md
generated
vendored
|
@ -1,5 +0,0 @@
|
||||||
# go-mimetypes
|
|
||||||
|
|
||||||
A generated lookup map of file extensions to mimetypes, from data provided at: https://raw.githubusercontent.com/micnic/mime.json/master/index.json
|
|
||||||
|
|
||||||
This allows determining mimetype without relying on OS mimetype lookups.
|
|
42
vendor/codeberg.org/gruf/go-mimetypes/get-mime-types.sh
generated
vendored
42
vendor/codeberg.org/gruf/go-mimetypes/get-mime-types.sh
generated
vendored
|
@ -1,42 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Mime types JSON source
|
|
||||||
URL='https://raw.githubusercontent.com/micnic/mime.json/master/index.json'
|
|
||||||
|
|
||||||
# Define intro to file
|
|
||||||
FILE='
|
|
||||||
// This is an automatically generated file, do not edit
|
|
||||||
package mimetypes
|
|
||||||
|
|
||||||
|
|
||||||
// MimeTypes is a map of file extensions to mime types.
|
|
||||||
var MimeTypes = map[string]string{
|
|
||||||
'
|
|
||||||
|
|
||||||
# Set break on new-line
|
|
||||||
IFS='
|
|
||||||
'
|
|
||||||
|
|
||||||
for line in $(curl -fL "$URL" | grep -E '".+"\s*:\s*".+"'); do
|
|
||||||
# Trim final whitespace
|
|
||||||
line=$(echo "$line" | sed -e 's|\s*$||')
|
|
||||||
|
|
||||||
# Ensure it ends in a comma
|
|
||||||
[ "${line%,}" = "$line" ] && line="${line},"
|
|
||||||
|
|
||||||
# Add to file
|
|
||||||
FILE="${FILE}${line}
|
|
||||||
"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Add final statement to file
|
|
||||||
FILE="${FILE}
|
|
||||||
}
|
|
||||||
|
|
||||||
"
|
|
||||||
|
|
||||||
# Write to file
|
|
||||||
echo "$FILE" > 'mime.gen.go'
|
|
||||||
|
|
||||||
# Check for valid go
|
|
||||||
gofumpt -w 'mime.gen.go'
|
|
1207
vendor/codeberg.org/gruf/go-mimetypes/mime.gen.go
generated
vendored
1207
vendor/codeberg.org/gruf/go-mimetypes/mime.gen.go
generated
vendored
File diff suppressed because it is too large
Load diff
47
vendor/codeberg.org/gruf/go-mimetypes/mime.go
generated
vendored
47
vendor/codeberg.org/gruf/go-mimetypes/mime.go
generated
vendored
|
@ -1,47 +0,0 @@
|
||||||
package mimetypes
|
|
||||||
|
|
||||||
import "path"
|
|
||||||
|
|
||||||
// PreferredExts defines preferred file
|
|
||||||
// extensions for input mime types (as there
|
|
||||||
// can be multiple extensions per mime type).
|
|
||||||
var PreferredExts = map[string]string{
|
|
||||||
MimeTypes["mp3"]: "mp3", // audio/mpeg
|
|
||||||
MimeTypes["mpeg"]: "mpeg", // video/mpeg
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetForFilename returns mimetype for given filename.
|
|
||||||
func GetForFilename(filename string) (string, bool) {
|
|
||||||
ext := path.Ext(filename)
|
|
||||||
if len(ext) < 1 {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
mime, ok := MimeTypes[ext[1:]]
|
|
||||||
return mime, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFileExt returns the file extension to use for mimetype. Relying first upon
|
|
||||||
// the 'PreferredExts' map. It simply returns the first match there may multiple.
|
|
||||||
func GetFileExt(mimeType string) (string, bool) {
|
|
||||||
ext, ok := PreferredExts[mimeType]
|
|
||||||
if ok {
|
|
||||||
return ext, true
|
|
||||||
}
|
|
||||||
for ext, mime := range MimeTypes {
|
|
||||||
if mime == mimeType {
|
|
||||||
return ext, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetFileExts returns known file extensions used for mimetype.
|
|
||||||
func GetFileExts(mimeType string) []string {
|
|
||||||
var exts []string
|
|
||||||
for ext, mime := range MimeTypes {
|
|
||||||
if mime == mimeType {
|
|
||||||
exts = append(exts, ext)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exts
|
|
||||||
}
|
|
18
vendor/github.com/minio/minio-go/v7/api.go
generated
vendored
18
vendor/github.com/minio/minio-go/v7/api.go
generated
vendored
|
@ -99,6 +99,7 @@ type Client struct {
|
||||||
healthStatus int32
|
healthStatus int32
|
||||||
|
|
||||||
trailingHeaderSupport bool
|
trailingHeaderSupport bool
|
||||||
|
maxRetries int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options for New method
|
// Options for New method
|
||||||
|
@ -123,12 +124,16 @@ type Options struct {
|
||||||
// Custom hash routines. Leave nil to use standard.
|
// Custom hash routines. Leave nil to use standard.
|
||||||
CustomMD5 func() md5simd.Hasher
|
CustomMD5 func() md5simd.Hasher
|
||||||
CustomSHA256 func() md5simd.Hasher
|
CustomSHA256 func() md5simd.Hasher
|
||||||
|
|
||||||
|
// Number of times a request is retried. Defaults to 10 retries if this option is not configured.
|
||||||
|
// Set to 1 to disable retries.
|
||||||
|
MaxRetries int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global constants.
|
// Global constants.
|
||||||
const (
|
const (
|
||||||
libraryName = "minio-go"
|
libraryName = "minio-go"
|
||||||
libraryVersion = "v7.0.79"
|
libraryVersion = "v7.0.80"
|
||||||
)
|
)
|
||||||
|
|
||||||
// User Agent should always following the below style.
|
// User Agent should always following the below style.
|
||||||
|
@ -278,6 +283,11 @@ func privateNew(endpoint string, opts *Options) (*Client, error) {
|
||||||
// healthcheck is not initialized
|
// healthcheck is not initialized
|
||||||
clnt.healthStatus = unknown
|
clnt.healthStatus = unknown
|
||||||
|
|
||||||
|
clnt.maxRetries = MaxRetry
|
||||||
|
if opts.MaxRetries > 0 {
|
||||||
|
clnt.maxRetries = opts.MaxRetries
|
||||||
|
}
|
||||||
|
|
||||||
// Return.
|
// Return.
|
||||||
return clnt, nil
|
return clnt, nil
|
||||||
}
|
}
|
||||||
|
@ -590,9 +600,9 @@ func (c *Client) executeMethod(ctx context.Context, method string, metadata requ
|
||||||
return nil, errors.New(c.endpointURL.String() + " is offline.")
|
return nil, errors.New(c.endpointURL.String() + " is offline.")
|
||||||
}
|
}
|
||||||
|
|
||||||
var retryable bool // Indicates if request can be retried.
|
var retryable bool // Indicates if request can be retried.
|
||||||
var bodySeeker io.Seeker // Extracted seeker from io.Reader.
|
var bodySeeker io.Seeker // Extracted seeker from io.Reader.
|
||||||
reqRetry := MaxRetry // Indicates how many times we can retry the request
|
var reqRetry = c.maxRetries // Indicates how many times we can retry the request
|
||||||
|
|
||||||
if metadata.contentBody != nil {
|
if metadata.contentBody != nil {
|
||||||
// Check if body is seekable then it is retryable.
|
// Check if body is seekable then it is retryable.
|
||||||
|
|
26
vendor/github.com/minio/minio-go/v7/pkg/lifecycle/lifecycle.go
generated
vendored
26
vendor/github.com/minio/minio-go/v7/pkg/lifecycle/lifecycle.go
generated
vendored
|
@ -434,12 +434,34 @@ func (de DelMarkerExpiration) MarshalXML(enc *xml.Encoder, start xml.StartElemen
|
||||||
return enc.EncodeElement(delMarkerExp(de), start)
|
return enc.EncodeElement(delMarkerExp(de), start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AllVersionsExpiration represents AllVersionsExpiration actions element in an ILM policy
|
||||||
|
type AllVersionsExpiration struct {
|
||||||
|
XMLName xml.Name `xml:"AllVersionsExpiration" json:"-"`
|
||||||
|
Days int `xml:"Days,omitempty" json:"Days,omitempty"`
|
||||||
|
DeleteMarker ExpireDeleteMarker `xml:"DeleteMarker,omitempty" json:"DeleteMarker,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsNull returns true if days field is 0
|
||||||
|
func (e AllVersionsExpiration) IsNull() bool {
|
||||||
|
return e.Days == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalXML satisfies xml.Marshaler to provide custom encoding
|
||||||
|
func (e AllVersionsExpiration) MarshalXML(enc *xml.Encoder, start xml.StartElement) error {
|
||||||
|
if e.IsNull() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
type allVersionsExp AllVersionsExpiration
|
||||||
|
return enc.EncodeElement(allVersionsExp(e), start)
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalJSON customizes json encoding by omitting empty values
|
// MarshalJSON customizes json encoding by omitting empty values
|
||||||
func (r Rule) MarshalJSON() ([]byte, error) {
|
func (r Rule) MarshalJSON() ([]byte, error) {
|
||||||
type rule struct {
|
type rule struct {
|
||||||
AbortIncompleteMultipartUpload *AbortIncompleteMultipartUpload `json:"AbortIncompleteMultipartUpload,omitempty"`
|
AbortIncompleteMultipartUpload *AbortIncompleteMultipartUpload `json:"AbortIncompleteMultipartUpload,omitempty"`
|
||||||
Expiration *Expiration `json:"Expiration,omitempty"`
|
Expiration *Expiration `json:"Expiration,omitempty"`
|
||||||
DelMarkerExpiration *DelMarkerExpiration `json:"DelMarkerExpiration,omitempty"`
|
DelMarkerExpiration *DelMarkerExpiration `json:"DelMarkerExpiration,omitempty"`
|
||||||
|
AllVersionsExpiration *AllVersionsExpiration `json:"AllVersionsExpiration,omitempty"`
|
||||||
ID string `json:"ID"`
|
ID string `json:"ID"`
|
||||||
RuleFilter *Filter `json:"Filter,omitempty"`
|
RuleFilter *Filter `json:"Filter,omitempty"`
|
||||||
NoncurrentVersionExpiration *NoncurrentVersionExpiration `json:"NoncurrentVersionExpiration,omitempty"`
|
NoncurrentVersionExpiration *NoncurrentVersionExpiration `json:"NoncurrentVersionExpiration,omitempty"`
|
||||||
|
@ -475,6 +497,9 @@ type rule struct {
|
||||||
if !r.NoncurrentVersionTransition.isNull() {
|
if !r.NoncurrentVersionTransition.isNull() {
|
||||||
newr.NoncurrentVersionTransition = &r.NoncurrentVersionTransition
|
newr.NoncurrentVersionTransition = &r.NoncurrentVersionTransition
|
||||||
}
|
}
|
||||||
|
if !r.AllVersionsExpiration.IsNull() {
|
||||||
|
newr.AllVersionsExpiration = &r.AllVersionsExpiration
|
||||||
|
}
|
||||||
|
|
||||||
return json.Marshal(newr)
|
return json.Marshal(newr)
|
||||||
}
|
}
|
||||||
|
@ -485,6 +510,7 @@ type Rule struct {
|
||||||
AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload `xml:"AbortIncompleteMultipartUpload,omitempty" json:"AbortIncompleteMultipartUpload,omitempty"`
|
AbortIncompleteMultipartUpload AbortIncompleteMultipartUpload `xml:"AbortIncompleteMultipartUpload,omitempty" json:"AbortIncompleteMultipartUpload,omitempty"`
|
||||||
Expiration Expiration `xml:"Expiration,omitempty" json:"Expiration,omitempty"`
|
Expiration Expiration `xml:"Expiration,omitempty" json:"Expiration,omitempty"`
|
||||||
DelMarkerExpiration DelMarkerExpiration `xml:"DelMarkerExpiration,omitempty" json:"DelMarkerExpiration,omitempty"`
|
DelMarkerExpiration DelMarkerExpiration `xml:"DelMarkerExpiration,omitempty" json:"DelMarkerExpiration,omitempty"`
|
||||||
|
AllVersionsExpiration AllVersionsExpiration `xml:"AllVersionsExpiration,omitempty" json:"AllVersionsExpiration,omitempty"`
|
||||||
ID string `xml:"ID" json:"ID"`
|
ID string `xml:"ID" json:"ID"`
|
||||||
RuleFilter Filter `xml:"Filter,omitempty" json:"Filter,omitempty"`
|
RuleFilter Filter `xml:"Filter,omitempty" json:"Filter,omitempty"`
|
||||||
NoncurrentVersionExpiration NoncurrentVersionExpiration `xml:"NoncurrentVersionExpiration,omitempty" json:"NoncurrentVersionExpiration,omitempty"`
|
NoncurrentVersionExpiration NoncurrentVersionExpiration `xml:"NoncurrentVersionExpiration,omitempty" json:"NoncurrentVersionExpiration,omitempty"`
|
||||||
|
|
5
vendor/modules.txt
vendored
5
vendor/modules.txt
vendored
|
@ -48,9 +48,6 @@ codeberg.org/gruf/go-maps
|
||||||
# codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
|
# codeberg.org/gruf/go-mempool v0.0.0-20240507125005-cef10d64a760
|
||||||
## explicit; go 1.22.2
|
## explicit; go 1.22.2
|
||||||
codeberg.org/gruf/go-mempool
|
codeberg.org/gruf/go-mempool
|
||||||
# codeberg.org/gruf/go-mimetypes v1.2.0
|
|
||||||
## explicit; go 1.17
|
|
||||||
codeberg.org/gruf/go-mimetypes
|
|
||||||
# codeberg.org/gruf/go-mutexes v1.5.1
|
# codeberg.org/gruf/go-mutexes v1.5.1
|
||||||
## explicit; go 1.22.2
|
## explicit; go 1.22.2
|
||||||
codeberg.org/gruf/go-mutexes
|
codeberg.org/gruf/go-mutexes
|
||||||
|
@ -486,7 +483,7 @@ github.com/miekg/dns
|
||||||
# github.com/minio/md5-simd v1.1.2
|
# github.com/minio/md5-simd v1.1.2
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
github.com/minio/md5-simd
|
github.com/minio/md5-simd
|
||||||
# github.com/minio/minio-go/v7 v7.0.79
|
# github.com/minio/minio-go/v7 v7.0.80
|
||||||
## explicit; go 1.22
|
## explicit; go 1.22
|
||||||
github.com/minio/minio-go/v7
|
github.com/minio/minio-go/v7
|
||||||
github.com/minio/minio-go/v7/pkg/cors
|
github.com/minio/minio-go/v7/pkg/cors
|
||||||
|
|
Loading…
Reference in a new issue