mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2024-11-24 12:46:38 +00:00
Compare commits
No commits in common. "372d040d90ce878126e6618feb8735ca9a0fcf8a" and "4f8542914e2da35e5812f9e00b215a7f1116ffbd" have entirely different histories.
372d040d90
...
4f8542914e
|
@ -18,24 +18,6 @@
|
||||||
# Default: 40MiB (41943040 bytes)
|
# Default: 40MiB (41943040 bytes)
|
||||||
media-local-max-size: 40MiB
|
media-local-max-size: 40MiB
|
||||||
|
|
||||||
# Size. Size in bytes of max image size referred to on /api/v_/instance endpoints,
|
|
||||||
# used by applications like Tusky to automatically scale locally uploaded media.
|
|
||||||
#
|
|
||||||
# Leaving this unset will default to media-local-max-size.
|
|
||||||
#
|
|
||||||
# Examples: [64, 500, 5MiB, 5MB, 50M]
|
|
||||||
# Default: unset
|
|
||||||
media-image-size-hint: 5MiB
|
|
||||||
|
|
||||||
# Size. Size in bytes of max video size referred to on /api/v_/instance endpoints,
|
|
||||||
# used by applications like Tusky to automatically scale locally uploaded media.
|
|
||||||
#
|
|
||||||
# Leaving this unset will default to media-local-max-size.
|
|
||||||
#
|
|
||||||
# Examples: [64, 4096, 4MiB, 4MB, 40M]
|
|
||||||
# Default: unset
|
|
||||||
media-video-size-hint: 40MiB
|
|
||||||
|
|
||||||
# Size. Max size in bytes of media to download from other instances.
|
# Size. Max size in bytes of media to download from other instances.
|
||||||
#
|
#
|
||||||
# Lowering this limit may cause your instance not to fetch post media.
|
# Lowering this limit may cause your instance not to fetch post media.
|
||||||
|
|
|
@ -471,24 +471,6 @@ accounts-custom-css-length: 10000
|
||||||
# Default: 40MiB (41943040 bytes)
|
# Default: 40MiB (41943040 bytes)
|
||||||
media-local-max-size: 40MiB
|
media-local-max-size: 40MiB
|
||||||
|
|
||||||
# Size. Size in bytes of max image size referred to on /api/v_/instance endpoints,
|
|
||||||
# used by applications like Tusky to automatically scale locally uploaded media.
|
|
||||||
#
|
|
||||||
# Leaving this unset will default to media-local-max-size.
|
|
||||||
#
|
|
||||||
# Examples: [64, 500, 5MiB, 5MB, 50M]
|
|
||||||
# Default: unset
|
|
||||||
media-image-size-hint: 5MiB
|
|
||||||
|
|
||||||
# Size. Size in bytes of max video size referred to on /api/v_/instance endpoints,
|
|
||||||
# used by applications like Tusky to automatically scale locally uploaded media.
|
|
||||||
#
|
|
||||||
# Leaving this unset will default to media-local-max-size.
|
|
||||||
#
|
|
||||||
# Examples: [64, 4096, 4MiB, 4MB, 40M]
|
|
||||||
# Default: unset
|
|
||||||
media-video-size-hint: 40MiB
|
|
||||||
|
|
||||||
# Size. Max size in bytes of media to download from other instances.
|
# Size. Max size in bytes of media to download from other instances.
|
||||||
#
|
#
|
||||||
# Lowering this limit may cause your instance not to fetch post media.
|
# Lowering this limit may cause your instance not to fetch post media.
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -17,6 +17,7 @@ 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
|
||||||
|
|
2
go.sum
generated
2
go.sum
generated
|
@ -62,6 +62,8 @@ 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=
|
||||||
|
|
|
@ -120,7 +120,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -130,10 +130,10 @@ func (suite *InstancePatchTestSuite) TestInstancePatch1() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
@ -261,7 +261,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -271,10 +271,10 @@ func (suite *InstancePatchTestSuite) TestInstancePatch2() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
@ -402,7 +402,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -412,10 +412,10 @@ func (suite *InstancePatchTestSuite) TestInstancePatch3() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
@ -594,7 +594,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -604,10 +604,10 @@ func (suite *InstancePatchTestSuite) TestInstancePatch6() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
@ -757,7 +757,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -767,10 +767,10 @@ func (suite *InstancePatchTestSuite) TestInstancePatch8() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
@ -939,7 +939,7 @@ func (suite *InstancePatchTestSuite) TestInstancePatch9() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -949,10 +949,10 @@ func (suite *InstancePatchTestSuite) TestInstancePatch9() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
|
|
@ -98,8 +98,6 @@ type Configuration struct {
|
||||||
MediaRemoteCacheDays int `name:"media-remote-cache-days" usage:"Number of days to locally cache media from remote instances. If set to 0, remote media will be kept indefinitely."`
|
MediaRemoteCacheDays int `name:"media-remote-cache-days" usage:"Number of days to locally cache media from remote instances. If set to 0, remote media will be kept indefinitely."`
|
||||||
MediaEmojiLocalMaxSize bytesize.Size `name:"media-emoji-local-max-size" usage:"Max size in bytes of emojis uploaded to this instance via the admin API."`
|
MediaEmojiLocalMaxSize bytesize.Size `name:"media-emoji-local-max-size" usage:"Max size in bytes of emojis uploaded to this instance via the admin API."`
|
||||||
MediaEmojiRemoteMaxSize bytesize.Size `name:"media-emoji-remote-max-size" usage:"Max size in bytes of emojis to download from other instances."`
|
MediaEmojiRemoteMaxSize bytesize.Size `name:"media-emoji-remote-max-size" usage:"Max size in bytes of emojis to download from other instances."`
|
||||||
MediaImageSizeHint bytesize.Size `name:"media-image-size-hint" usage:"Size in bytes of max image size referred to on /api/v_/instance endpoints (else, local max size)"`
|
|
||||||
MediaVideoSizeHint bytesize.Size `name:"media-video-size-hint" usage:"Size in bytes of max video size referred to on /api/v_/instance endpoints (else, local max size)"`
|
|
||||||
MediaLocalMaxSize bytesize.Size `name:"media-local-max-size" usage:"Max size in bytes of media uploaded to this instance via API"`
|
MediaLocalMaxSize bytesize.Size `name:"media-local-max-size" usage:"Max size in bytes of media uploaded to this instance via API"`
|
||||||
MediaRemoteMaxSize bytesize.Size `name:"media-remote-max-size" usage:"Max size in bytes of media to download from other instances"`
|
MediaRemoteMaxSize bytesize.Size `name:"media-remote-max-size" usage:"Max size in bytes of media to download from other instances"`
|
||||||
MediaCleanupFrom string `name:"media-cleanup-from" usage:"Time of day from which to start running media cleanup/prune jobs. Should be in the format 'hh:mm:ss', eg., '15:04:05'."`
|
MediaCleanupFrom string `name:"media-cleanup-from" usage:"Time of day from which to start running media cleanup/prune jobs. Should be in the format 'hh:mm:ss', eg., '15:04:05'."`
|
||||||
|
|
|
@ -1225,56 +1225,6 @@ func GetMediaEmojiRemoteMaxSize() bytesize.Size { return global.GetMediaEmojiRem
|
||||||
// SetMediaEmojiRemoteMaxSize safely sets the value for global configuration 'MediaEmojiRemoteMaxSize' field
|
// SetMediaEmojiRemoteMaxSize safely sets the value for global configuration 'MediaEmojiRemoteMaxSize' field
|
||||||
func SetMediaEmojiRemoteMaxSize(v bytesize.Size) { global.SetMediaEmojiRemoteMaxSize(v) }
|
func SetMediaEmojiRemoteMaxSize(v bytesize.Size) { global.SetMediaEmojiRemoteMaxSize(v) }
|
||||||
|
|
||||||
// GetMediaImageSizeHint safely fetches the Configuration value for state's 'MediaImageSizeHint' field
|
|
||||||
func (st *ConfigState) GetMediaImageSizeHint() (v bytesize.Size) {
|
|
||||||
st.mutex.RLock()
|
|
||||||
v = st.config.MediaImageSizeHint
|
|
||||||
st.mutex.RUnlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetMediaImageSizeHint safely sets the Configuration value for state's 'MediaImageSizeHint' field
|
|
||||||
func (st *ConfigState) SetMediaImageSizeHint(v bytesize.Size) {
|
|
||||||
st.mutex.Lock()
|
|
||||||
defer st.mutex.Unlock()
|
|
||||||
st.config.MediaImageSizeHint = v
|
|
||||||
st.reloadToViper()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MediaImageSizeHintFlag returns the flag name for the 'MediaImageSizeHint' field
|
|
||||||
func MediaImageSizeHintFlag() string { return "media-image-size-hint" }
|
|
||||||
|
|
||||||
// GetMediaImageSizeHint safely fetches the value for global configuration 'MediaImageSizeHint' field
|
|
||||||
func GetMediaImageSizeHint() bytesize.Size { return global.GetMediaImageSizeHint() }
|
|
||||||
|
|
||||||
// SetMediaImageSizeHint safely sets the value for global configuration 'MediaImageSizeHint' field
|
|
||||||
func SetMediaImageSizeHint(v bytesize.Size) { global.SetMediaImageSizeHint(v) }
|
|
||||||
|
|
||||||
// GetMediaVideoSizeHint safely fetches the Configuration value for state's 'MediaVideoSizeHint' field
|
|
||||||
func (st *ConfigState) GetMediaVideoSizeHint() (v bytesize.Size) {
|
|
||||||
st.mutex.RLock()
|
|
||||||
v = st.config.MediaVideoSizeHint
|
|
||||||
st.mutex.RUnlock()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetMediaVideoSizeHint safely sets the Configuration value for state's 'MediaVideoSizeHint' field
|
|
||||||
func (st *ConfigState) SetMediaVideoSizeHint(v bytesize.Size) {
|
|
||||||
st.mutex.Lock()
|
|
||||||
defer st.mutex.Unlock()
|
|
||||||
st.config.MediaVideoSizeHint = v
|
|
||||||
st.reloadToViper()
|
|
||||||
}
|
|
||||||
|
|
||||||
// MediaVideoSizeHintFlag returns the flag name for the 'MediaVideoSizeHint' field
|
|
||||||
func MediaVideoSizeHintFlag() string { return "media-video-size-hint" }
|
|
||||||
|
|
||||||
// GetMediaVideoSizeHint safely fetches the value for global configuration 'MediaVideoSizeHint' field
|
|
||||||
func GetMediaVideoSizeHint() bytesize.Size { return global.GetMediaVideoSizeHint() }
|
|
||||||
|
|
||||||
// SetMediaVideoSizeHint safely sets the value for global configuration 'MediaVideoSizeHint' field
|
|
||||||
func SetMediaVideoSizeHint(v bytesize.Size) { global.SetMediaVideoSizeHint(v) }
|
|
||||||
|
|
||||||
// GetMediaLocalMaxSize safely fetches the Configuration value for state's 'MediaLocalMaxSize' field
|
// GetMediaLocalMaxSize safely fetches the Configuration value for state's 'MediaLocalMaxSize' field
|
||||||
func (st *ConfigState) GetMediaLocalMaxSize() (v bytesize.Size) {
|
func (st *ConfigState) GetMediaLocalMaxSize() (v bytesize.Size) {
|
||||||
st.mutex.RLock()
|
st.mutex.RLock()
|
||||||
|
|
|
@ -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,
|
return gtsmodel.FileTypeVideo, "mpeg"
|
||||||
"video/mpeg", "mpeg"
|
|
||||||
case "mjpeg":
|
case "mjpeg":
|
||||||
return gtsmodel.FileTypeVideo,
|
return gtsmodel.FileTypeVideo, "mjpeg"
|
||||||
"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,70 +338,55 @@ func (res *result) GetFileType() (gtsmodel.FileType, string, string) {
|
||||||
res.duration <= 30 {
|
res.duration <= 30 {
|
||||||
// Short, soundless
|
// Short, soundless
|
||||||
// video file aka gifv.
|
// video file aka gifv.
|
||||||
return gtsmodel.FileTypeGifv,
|
return gtsmodel.FileTypeGifv, "mp4"
|
||||||
"video/mp4", "mp4"
|
|
||||||
} else {
|
} else {
|
||||||
// Video file (with or without audio).
|
// Video file (with or without audio).
|
||||||
return gtsmodel.FileTypeVideo,
|
return gtsmodel.FileTypeVideo, "mp4"
|
||||||
"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,
|
return gtsmodel.FileTypeAudio, "m4a"
|
||||||
"audio/mp4", "m4a"
|
|
||||||
}
|
}
|
||||||
case "apng":
|
case "apng":
|
||||||
return gtsmodel.FileTypeImage,
|
return gtsmodel.FileTypeImage, "apng"
|
||||||
"image/apng", "apng"
|
|
||||||
case "png_pipe":
|
case "png_pipe":
|
||||||
return gtsmodel.FileTypeImage,
|
return gtsmodel.FileTypeImage, "png"
|
||||||
"image/png", "png"
|
|
||||||
case "image2", "image2pipe", "jpeg_pipe":
|
case "image2", "image2pipe", "jpeg_pipe":
|
||||||
return gtsmodel.FileTypeImage,
|
return gtsmodel.FileTypeImage, "jpeg"
|
||||||
"image/jpeg", "jpeg"
|
|
||||||
case "webp", "webp_pipe":
|
case "webp", "webp_pipe":
|
||||||
return gtsmodel.FileTypeImage,
|
return gtsmodel.FileTypeImage, "webp"
|
||||||
"image/webp", "webp"
|
|
||||||
case "gif":
|
case "gif":
|
||||||
return gtsmodel.FileTypeImage,
|
return gtsmodel.FileTypeImage, "gif"
|
||||||
"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,
|
return gtsmodel.FileTypeAudio, "mp2"
|
||||||
"audio/mp2", "mp2"
|
|
||||||
case "mp3":
|
case "mp3":
|
||||||
return gtsmodel.FileTypeAudio,
|
return gtsmodel.FileTypeAudio, "mp3"
|
||||||
"audio/mp3", "mp3"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "asf":
|
case "asf":
|
||||||
switch {
|
switch {
|
||||||
case len(res.video) > 0:
|
case len(res.video) > 0:
|
||||||
return gtsmodel.FileTypeVideo,
|
return gtsmodel.FileTypeVideo, "wmv"
|
||||||
"video/x-ms-wmv", "wmv"
|
|
||||||
case len(res.audio) > 0:
|
case len(res.audio) > 0:
|
||||||
return gtsmodel.FileTypeAudio,
|
return gtsmodel.FileTypeAudio, "wma"
|
||||||
"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,
|
return gtsmodel.FileTypeVideo, "ogv"
|
||||||
"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,
|
return gtsmodel.FileTypeAudio, "opus"
|
||||||
"audio/opus", "opus"
|
|
||||||
default:
|
default:
|
||||||
return gtsmodel.FileTypeAudio,
|
return gtsmodel.FileTypeAudio, "ogg"
|
||||||
"audio/ogg", "ogg"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "matroska,webm":
|
case "matroska,webm":
|
||||||
|
@ -426,27 +411,21 @@ func (res *result) GetFileType() (gtsmodel.FileType, string, string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if isWebm {
|
if isWebm {
|
||||||
// Check valid webm codec config.
|
// Check for valid webm codec config.
|
||||||
return gtsmodel.FileTypeVideo,
|
return gtsmodel.FileTypeVideo, "webm"
|
||||||
"video/webm", "webm"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All else falls under generic mkv.
|
// All else falls under generic mkv.
|
||||||
return gtsmodel.FileTypeVideo,
|
return gtsmodel.FileTypeVideo, "mkv"
|
||||||
"video/x-matroska", "mkv"
|
|
||||||
case len(res.audio) > 0:
|
case len(res.audio) > 0:
|
||||||
return gtsmodel.FileTypeAudio,
|
return gtsmodel.FileTypeAudio, "mka"
|
||||||
"audio/x-matroska", "mka"
|
|
||||||
}
|
}
|
||||||
case "avi":
|
case "avi":
|
||||||
return gtsmodel.FileTypeVideo,
|
return gtsmodel.FileTypeVideo, "avi"
|
||||||
"video/x-msvideo", "avi"
|
|
||||||
case "flac":
|
case "flac":
|
||||||
return gtsmodel.FileTypeAudio,
|
return gtsmodel.FileTypeAudio, "flac"
|
||||||
"audio/flac", "flac"
|
|
||||||
}
|
}
|
||||||
return gtsmodel.FileTypeUnknown,
|
return gtsmodel.FileTypeUnknown, res.format
|
||||||
"", res.format
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImageMeta extracts image metadata contained within ffprobe'd media result streams.
|
// ImageMeta extracts image metadata contained within ffprobe'd media result streams.
|
||||||
|
|
|
@ -40,7 +40,7 @@ func InitFfprobe(ctx context.Context, max int) error {
|
||||||
|
|
||||||
// Ffprobe runs the given arguments with an instance of ffprobe.
|
// Ffprobe runs the given arguments with an instance of ffprobe.
|
||||||
func Ffprobe(ctx context.Context, args Args) (uint32, error) {
|
func Ffprobe(ctx context.Context, args Args) (uint32, error) {
|
||||||
return ffprobeRunner.Run(ctx, func() (uint32, error) {
|
return ffmpegRunner.Run(ctx, func() (uint32, error) {
|
||||||
return wasm.Run(ctx, runtime, ffprobe, args)
|
return wasm.Run(ctx, runtime, ffprobe, args)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
"video/ogg", // .ogv
|
"video/ogg", // .ogv
|
||||||
|
|
||||||
// mpeg4 types
|
// mpeg4 types
|
||||||
"audio/mp4", // .m4a
|
"audio/x-m4a", // .m4a
|
||||||
"video/mp4", // .mp4
|
"video/mp4", // .mp4
|
||||||
"video/quicktime", // .mov
|
"video/quicktime", // .mov
|
||||||
|
|
||||||
|
|
|
@ -664,7 +664,7 @@ func (suite *ManagerTestSuite) TestOpusProcess() {
|
||||||
Duration: util.Ptr(float32(122.10006)),
|
Duration: util.Ptr(float32(122.10006)),
|
||||||
Bitrate: util.Ptr(uint64(116426)),
|
Bitrate: util.Ptr(uint64(116426)),
|
||||||
}, attachment.FileMeta.Original)
|
}, attachment.FileMeta.Original)
|
||||||
suite.Equal("audio/opus", attachment.File.ContentType)
|
suite.Equal("audio/ogg", attachment.File.ContentType)
|
||||||
suite.Equal(1776956, attachment.File.FileSize)
|
suite.Equal(1776956, attachment.File.FileSize)
|
||||||
suite.Empty(attachment.Blurhash)
|
suite.Empty(attachment.Blurhash)
|
||||||
|
|
||||||
|
|
|
@ -163,10 +163,9 @@ func (p *ProcessingEmoji) store(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
var ext string
|
var ext string
|
||||||
var fileType gtsmodel.FileType
|
|
||||||
|
|
||||||
// Get abstract file type, mimetype and ext from ffprobe data.
|
// Get type from ffprobe format data.
|
||||||
fileType, p.emoji.ImageContentType, ext = result.GetFileType()
|
fileType, 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)
|
||||||
}
|
}
|
||||||
|
@ -217,6 +216,10 @@ 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 generic media type and mimetype from ffprobe format data.
|
// Set media type from ffprobe format data.
|
||||||
p.media.Type, p.media.File.ContentType, ext = result.GetFileType()
|
p.media.Type, 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, mimeType string
|
var newBlurhash string
|
||||||
|
|
||||||
// Generate thumbnail, and new blurhash if needed from temp media.
|
// Generate thumbnail, and new blurhash if need from media.
|
||||||
thumbpath, mimeType, newBlurhash, err = generateThumb(ctx, temppath,
|
thumbpath, newBlurhash, err = generateThumb(ctx, temppath,
|
||||||
thumbWidth,
|
thumbWidth,
|
||||||
thumbHeight,
|
thumbHeight,
|
||||||
result.orientation,
|
result.orientation,
|
||||||
|
@ -250,9 +250,6 @@ 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
|
||||||
|
@ -268,6 +265,10 @@ 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,
|
||||||
|
@ -294,6 +295,9 @@ 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,21 +84,17 @@ 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
|
||||||
|
@ -110,7 +106,6 @@ 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(
|
||||||
|
@ -122,7 +117,7 @@ func generateThumb(
|
||||||
jpeg.Decode,
|
jpeg.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, mimeType, blurhash, err
|
return outpath, 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
|
||||||
|
@ -133,7 +128,6 @@ 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(
|
||||||
|
@ -145,7 +139,7 @@ func generateThumb(
|
||||||
gif.Decode,
|
gif.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, mimeType, blurhash, err
|
return outpath, 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
|
||||||
|
@ -156,7 +150,6 @@ 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(
|
||||||
|
@ -168,7 +161,7 @@ func generateThumb(
|
||||||
png.Decode,
|
png.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, mimeType, blurhash, err
|
return outpath, 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
|
||||||
|
@ -179,7 +172,6 @@ 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(
|
||||||
|
@ -191,7 +183,7 @@ func generateThumb(
|
||||||
webp.Decode,
|
webp.Decode,
|
||||||
needBlurhash,
|
needBlurhash,
|
||||||
)
|
)
|
||||||
return outpath, mimeType, blurhash, err
|
return outpath, blurhash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// The fallback for thumbnail generation, which
|
// The fallback for thumbnail generation, which
|
||||||
|
@ -204,18 +196,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, mimeType, blurhash, nil
|
return outpath, blurhash, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateNativeThumb generates a thumbnail
|
// generateNativeThumb generates a thumbnail
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package media
|
package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"cmp"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
|
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -85,6 +87,12 @@ 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.
|
||||||
//
|
//
|
||||||
|
|
|
@ -18,11 +18,9 @@
|
||||||
package typeutils
|
package typeutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmp"
|
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -44,13 +42,16 @@
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
instanceStatusesCharactersReservedPerURL = 25
|
instanceStatusesCharactersReservedPerURL = 25
|
||||||
instancePollsMinExpiration = 300 // seconds
|
instanceMediaAttachmentsImageMatrixLimit = 16777216 // width * height
|
||||||
instancePollsMaxExpiration = 2629746 // seconds
|
instanceMediaAttachmentsVideoMatrixLimit = 16777216 // width * height
|
||||||
instanceAccountsMaxFeaturedTags = 10
|
instanceMediaAttachmentsVideoFrameRateLimit = 60
|
||||||
instanceAccountsMaxProfileFields = 6 // FIXME: https://github.com/superseriousbusiness/gotosocial/issues/1876
|
instancePollsMinExpiration = 300 // seconds
|
||||||
instanceSourceURL = "https://github.com/superseriousbusiness/gotosocial"
|
instancePollsMaxExpiration = 2629746 // seconds
|
||||||
instanceMastodonVersion = "3.5.3"
|
instanceAccountsMaxFeaturedTags = 10
|
||||||
|
instanceAccountsMaxProfileFields = 6 // FIXME: https://github.com/superseriousbusiness/gotosocial/issues/1876
|
||||||
|
instanceSourceURL = "https://github.com/superseriousbusiness/gotosocial"
|
||||||
|
instanceMastodonVersion = "3.5.3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var instanceStatusesSupportedMimeTypes = []string{
|
var instanceStatusesSupportedMimeTypes = []string{
|
||||||
|
@ -1562,24 +1563,11 @@ func (c *Converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins
|
||||||
instance.Configuration.Statuses.CharactersReservedPerURL = instanceStatusesCharactersReservedPerURL
|
instance.Configuration.Statuses.CharactersReservedPerURL = instanceStatusesCharactersReservedPerURL
|
||||||
instance.Configuration.Statuses.SupportedMimeTypes = instanceStatusesSupportedMimeTypes
|
instance.Configuration.Statuses.SupportedMimeTypes = instanceStatusesSupportedMimeTypes
|
||||||
instance.Configuration.MediaAttachments.SupportedMimeTypes = media.SupportedMIMETypes
|
instance.Configuration.MediaAttachments.SupportedMimeTypes = media.SupportedMIMETypes
|
||||||
|
instance.Configuration.MediaAttachments.ImageSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated.
|
||||||
// NOTE: we use the local max sizes here
|
instance.Configuration.MediaAttachments.ImageMatrixLimit = instanceMediaAttachmentsImageMatrixLimit
|
||||||
// as it hints to apps like Tusky for image
|
instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated.
|
||||||
// compression of locally uploaded media.
|
instance.Configuration.MediaAttachments.VideoFrameRateLimit = instanceMediaAttachmentsVideoFrameRateLimit
|
||||||
//
|
instance.Configuration.MediaAttachments.VideoMatrixLimit = instanceMediaAttachmentsVideoMatrixLimit
|
||||||
// TODO: return local / remote depending
|
|
||||||
// on authorized endpoint user (if any)?
|
|
||||||
localMax := config.GetMediaLocalMaxSize()
|
|
||||||
imageSz := cmp.Or(config.GetMediaImageSizeHint(), localMax)
|
|
||||||
videoSz := cmp.Or(config.GetMediaVideoSizeHint(), localMax)
|
|
||||||
instance.Configuration.MediaAttachments.ImageSizeLimit = int(imageSz) // #nosec G115 -- Already validated.
|
|
||||||
instance.Configuration.MediaAttachments.VideoSizeLimit = int(videoSz) // #nosec G115 -- Already validated.
|
|
||||||
|
|
||||||
// we don't actually set any limits on these. set to max possible.
|
|
||||||
instance.Configuration.MediaAttachments.ImageMatrixLimit = math.MaxInt
|
|
||||||
instance.Configuration.MediaAttachments.VideoFrameRateLimit = math.MaxInt
|
|
||||||
instance.Configuration.MediaAttachments.VideoMatrixLimit = math.MaxInt
|
|
||||||
|
|
||||||
instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions()
|
instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions()
|
||||||
instance.Configuration.Polls.MaxCharactersPerOption = config.GetStatusesPollOptionMaxChars()
|
instance.Configuration.Polls.MaxCharactersPerOption = config.GetStatusesPollOptionMaxChars()
|
||||||
instance.Configuration.Polls.MinExpiration = instancePollsMinExpiration
|
instance.Configuration.Polls.MinExpiration = instancePollsMinExpiration
|
||||||
|
@ -1725,24 +1713,11 @@ func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins
|
||||||
instance.Configuration.Statuses.CharactersReservedPerURL = instanceStatusesCharactersReservedPerURL
|
instance.Configuration.Statuses.CharactersReservedPerURL = instanceStatusesCharactersReservedPerURL
|
||||||
instance.Configuration.Statuses.SupportedMimeTypes = instanceStatusesSupportedMimeTypes
|
instance.Configuration.Statuses.SupportedMimeTypes = instanceStatusesSupportedMimeTypes
|
||||||
instance.Configuration.MediaAttachments.SupportedMimeTypes = media.SupportedMIMETypes
|
instance.Configuration.MediaAttachments.SupportedMimeTypes = media.SupportedMIMETypes
|
||||||
|
instance.Configuration.MediaAttachments.ImageSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated.
|
||||||
// NOTE: we use the local max sizes here
|
instance.Configuration.MediaAttachments.ImageMatrixLimit = instanceMediaAttachmentsImageMatrixLimit
|
||||||
// as it hints to apps like Tusky for image
|
instance.Configuration.MediaAttachments.VideoSizeLimit = int(config.GetMediaRemoteMaxSize()) // #nosec G115 -- Already validated.
|
||||||
// compression of locally uploaded media.
|
instance.Configuration.MediaAttachments.VideoFrameRateLimit = instanceMediaAttachmentsVideoFrameRateLimit
|
||||||
//
|
instance.Configuration.MediaAttachments.VideoMatrixLimit = instanceMediaAttachmentsVideoMatrixLimit
|
||||||
// TODO: return local / remote depending
|
|
||||||
// on authorized endpoint user (if any)?
|
|
||||||
localMax := config.GetMediaLocalMaxSize()
|
|
||||||
imageSz := cmp.Or(config.GetMediaImageSizeHint(), localMax)
|
|
||||||
videoSz := cmp.Or(config.GetMediaVideoSizeHint(), localMax)
|
|
||||||
instance.Configuration.MediaAttachments.ImageSizeLimit = int(imageSz) // #nosec G115 -- Already validated.
|
|
||||||
instance.Configuration.MediaAttachments.VideoSizeLimit = int(videoSz) // #nosec G115 -- Already validated.
|
|
||||||
|
|
||||||
// we don't actually set any limits on these. set to max possible.
|
|
||||||
instance.Configuration.MediaAttachments.ImageMatrixLimit = math.MaxInt
|
|
||||||
instance.Configuration.MediaAttachments.VideoFrameRateLimit = math.MaxInt
|
|
||||||
instance.Configuration.MediaAttachments.VideoMatrixLimit = math.MaxInt
|
|
||||||
|
|
||||||
instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions()
|
instance.Configuration.Polls.MaxOptions = config.GetStatusesPollMaxOptions()
|
||||||
instance.Configuration.Polls.MaxCharactersPerOption = config.GetStatusesPollOptionMaxChars()
|
instance.Configuration.Polls.MaxCharactersPerOption = config.GetStatusesPollOptionMaxChars()
|
||||||
instance.Configuration.Polls.MinExpiration = instancePollsMinExpiration
|
instance.Configuration.Polls.MinExpiration = instancePollsMinExpiration
|
||||||
|
|
|
@ -1958,7 +1958,7 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV1ToFrontend() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -1968,10 +1968,10 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV1ToFrontend() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
@ -2103,7 +2103,7 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV2ToFrontend() {
|
||||||
"image/apng",
|
"image/apng",
|
||||||
"audio/ogg",
|
"audio/ogg",
|
||||||
"video/ogg",
|
"video/ogg",
|
||||||
"audio/mp4",
|
"audio/x-m4a",
|
||||||
"video/mp4",
|
"video/mp4",
|
||||||
"video/quicktime",
|
"video/quicktime",
|
||||||
"audio/x-ms-wma",
|
"audio/x-ms-wma",
|
||||||
|
@ -2113,10 +2113,10 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV2ToFrontend() {
|
||||||
"video/x-matroska"
|
"video/x-matroska"
|
||||||
],
|
],
|
||||||
"image_size_limit": 41943040,
|
"image_size_limit": 41943040,
|
||||||
"image_matrix_limit": 9223372036854775807,
|
"image_matrix_limit": 16777216,
|
||||||
"video_size_limit": 41943040,
|
"video_size_limit": 41943040,
|
||||||
"video_frame_rate_limit": 9223372036854775807,
|
"video_frame_rate_limit": 60,
|
||||||
"video_matrix_limit": 9223372036854775807
|
"video_matrix_limit": 16777216
|
||||||
},
|
},
|
||||||
"polls": {
|
"polls": {
|
||||||
"max_options": 6,
|
"max_options": 6,
|
||||||
|
|
|
@ -129,11 +129,9 @@ EXPECT=$(cat << "EOF"
|
||||||
"media-emoji-local-max-size": 420,
|
"media-emoji-local-max-size": 420,
|
||||||
"media-emoji-remote-max-size": 420,
|
"media-emoji-remote-max-size": 420,
|
||||||
"media-ffmpeg-pool-size": 8,
|
"media-ffmpeg-pool-size": 8,
|
||||||
"media-image-size-hint": 5242880,
|
|
||||||
"media-local-max-size": 420,
|
"media-local-max-size": 420,
|
||||||
"media-remote-cache-days": 30,
|
"media-remote-cache-days": 30,
|
||||||
"media-remote-max-size": 420,
|
"media-remote-max-size": 420,
|
||||||
"media-video-size-hint": 41943040,
|
|
||||||
"metrics-auth-enabled": false,
|
"metrics-auth-enabled": false,
|
||||||
"metrics-auth-password": "",
|
"metrics-auth-password": "",
|
||||||
"metrics-auth-username": "",
|
"metrics-auth-username": "",
|
||||||
|
@ -246,14 +244,12 @@ GTS_ACCOUNTS_REGISTRATION_OPEN=true \
|
||||||
GTS_ACCOUNTS_REASON_REQUIRED=false \
|
GTS_ACCOUNTS_REASON_REQUIRED=false \
|
||||||
GTS_MEDIA_DESCRIPTION_MIN_CHARS=69 \
|
GTS_MEDIA_DESCRIPTION_MIN_CHARS=69 \
|
||||||
GTS_MEDIA_DESCRIPTION_MAX_CHARS=5000 \
|
GTS_MEDIA_DESCRIPTION_MAX_CHARS=5000 \
|
||||||
GTS_MEDIA_IMAGE_SIZE_HINT='5MiB' \
|
|
||||||
GTS_MEDIA_LOCAL_MAX_SIZE=420 \
|
GTS_MEDIA_LOCAL_MAX_SIZE=420 \
|
||||||
GTS_MEDIA_REMOTE_MAX_SIZE=420 \
|
GTS_MEDIA_REMOTE_MAX_SIZE=420 \
|
||||||
GTS_MEDIA_REMOTE_CACHE_DAYS=30 \
|
GTS_MEDIA_REMOTE_CACHE_DAYS=30 \
|
||||||
GTS_MEDIA_EMOJI_LOCAL_MAX_SIZE=420 \
|
GTS_MEDIA_EMOJI_LOCAL_MAX_SIZE=420 \
|
||||||
GTS_MEDIA_EMOJI_REMOTE_MAX_SIZE=420 \
|
GTS_MEDIA_EMOJI_REMOTE_MAX_SIZE=420 \
|
||||||
GTS_MEDIA_FFMPEG_POOL_SIZE=8 \
|
GTS_MEDIA_FFMPEG_POOL_SIZE=8 \
|
||||||
GTS_MEDIA_VIDEO_SIZE_HINT='40MiB' \
|
|
||||||
GTS_METRICS_AUTH_ENABLED=false \
|
GTS_METRICS_AUTH_ENABLED=false \
|
||||||
GTS_METRICS_ENABLED=false \
|
GTS_METRICS_ENABLED=false \
|
||||||
GTS_STORAGE_BACKEND='local' \
|
GTS_STORAGE_BACKEND='local' \
|
||||||
|
|
5
vendor/codeberg.org/gruf/go-mimetypes/README.md
generated
vendored
Normal file
5
vendor/codeberg.org/gruf/go-mimetypes/README.md
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# 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
Normal file
42
vendor/codeberg.org/gruf/go-mimetypes/get-mime-types.sh
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#!/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
Normal file
1207
vendor/codeberg.org/gruf/go-mimetypes/mime.gen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
47
vendor/codeberg.org/gruf/go-mimetypes/mime.go
generated
vendored
Normal file
47
vendor/codeberg.org/gruf/go-mimetypes/mime.go
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
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
|
||||||
|
}
|
3
vendor/modules.txt
vendored
3
vendor/modules.txt
vendored
|
@ -48,6 +48,9 @@ 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
|
||||||
|
|
Loading…
Reference in a new issue