diff --git a/example/config.yaml b/example/config.yaml index f9572054..5f41952a 100644 --- a/example/config.yaml +++ b/example/config.yaml @@ -400,6 +400,15 @@ instance-expose-public-timeline: false # Default: true instance-deliver-to-shared-inboxes: true +# Bool. This flag will inject a Mastodon version into the version field that +# is included in /api/v1/instance. This version is often used by Mastodon clients +# to do API feature detection. By injecting a Mastodon compatible version, it is +# possible to cajole those clients to behave correctly with GoToSocial. +# +# Options: [true, false] +# Default: false +instance-inject-mastodon-version: false + ########################### ##### ACCOUNTS CONFIG ##### ########################### diff --git a/internal/config/config.go b/internal/config/config.go index 53514e20..cb158cda 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -80,6 +80,7 @@ type Configuration struct { InstanceExposeSuspendedWeb bool `name:"instance-expose-suspended-web" usage:"Expose list of suspended instances as webpage on /about/suspended"` InstanceExposePublicTimeline bool `name:"instance-expose-public-timeline" usage:"Allow unauthenticated users to query /api/v1/timelines/public"` InstanceDeliverToSharedInboxes bool `name:"instance-deliver-to-shared-inboxes" usage:"Deliver federated messages to shared inboxes, if they're available."` + InstanceInjectMastodonVersion bool `name:"instance-inject-mastodon-version" usage:"This injects a Mastodon compatible version in /api/v1/instance to help Mastodon clients that use that version for feature detection"` AccountsRegistrationOpen bool `name:"accounts-registration-open" usage:"Allow anyone to submit an account signup request. If false, server will be invite-only."` AccountsApprovalRequired bool `name:"accounts-approval-required" usage:"Do account signups require approval by an admin or moderator before user can log in? If false, new registrations will be automatically approved."` diff --git a/internal/config/helpers.gen.go b/internal/config/helpers.gen.go index 6cd2d6bd..ceb115bb 100644 --- a/internal/config/helpers.gen.go +++ b/internal/config/helpers.gen.go @@ -849,6 +849,31 @@ func GetInstanceDeliverToSharedInboxes() bool { return global.GetInstanceDeliver // SetInstanceDeliverToSharedInboxes safely sets the value for global configuration 'InstanceDeliverToSharedInboxes' field func SetInstanceDeliverToSharedInboxes(v bool) { global.SetInstanceDeliverToSharedInboxes(v) } +// GetInstanceInjectMastodonVersion safely fetches the Configuration value for state's 'InstanceInjectMastodonVersion' field +func (st *ConfigState) GetInstanceInjectMastodonVersion() (v bool) { + st.mutex.RLock() + v = st.config.InstanceInjectMastodonVersion + st.mutex.RUnlock() + return +} + +// SetInstanceInjectMastodonVersion safely sets the Configuration value for state's 'InstanceInjectMastodonVersion' field +func (st *ConfigState) SetInstanceInjectMastodonVersion(v bool) { + st.mutex.Lock() + defer st.mutex.Unlock() + st.config.InstanceInjectMastodonVersion = v + st.reloadToViper() +} + +// InstanceInjectMastodonVersionFlag returns the flag name for the 'InstanceInjectMastodonVersion' field +func InstanceInjectMastodonVersionFlag() string { return "instance-inject-mastodon-version" } + +// GetInstanceInjectMastodonVersion safely fetches the value for global configuration 'InstanceInjectMastodonVersion' field +func GetInstanceInjectMastodonVersion() bool { return global.GetInstanceInjectMastodonVersion() } + +// SetInstanceInjectMastodonVersion safely sets the value for global configuration 'InstanceInjectMastodonVersion' field +func SetInstanceInjectMastodonVersion(v bool) { global.SetInstanceInjectMastodonVersion(v) } + // GetAccountsRegistrationOpen safely fetches the Configuration value for state's 'AccountsRegistrationOpen' field func (st *ConfigState) GetAccountsRegistrationOpen() (v bool) { st.mutex.RLock() diff --git a/internal/typeutils/internaltofrontend.go b/internal/typeutils/internaltofrontend.go index d6da9493..17b8047e 100644 --- a/internal/typeutils/internaltofrontend.go +++ b/internal/typeutils/internaltofrontend.go @@ -45,6 +45,7 @@ const ( 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{ @@ -52,6 +53,10 @@ var instanceStatusesSupportedMimeTypes = []string{ string(apimodel.StatusContentTypeMarkdown), } +func toMastodonVersion(in string) string { + return instanceMastodonVersion + "+" + strings.ReplaceAll(in, " ", "-") +} + func (c *converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmodel.Account) (*apimodel.Account, error) { // we can build this sensitive account easily by first getting the public account.... apiAccount, err := c.AccountToAPIAccountPublic(ctx, a) @@ -740,6 +745,10 @@ func (c *converter) InstanceToAPIV1Instance(ctx context.Context, i *gtsmodel.Ins MaxTootChars: uint(config.GetStatusesMaxChars()), } + if config.GetInstanceInjectMastodonVersion() { + instance.Version = toMastodonVersion(instance.Version) + } + // configuration instance.Configuration.Statuses.MaxCharacters = config.GetStatusesMaxChars() instance.Configuration.Statuses.MaxMediaAttachments = config.GetStatusesMediaMaxFiles() @@ -839,6 +848,10 @@ func (c *converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins Rules: []interface{}{}, // todo: not implemented } + if config.GetInstanceInjectMastodonVersion() { + instance.Version = toMastodonVersion(instance.Version) + } + // thumbnail thumbnail := apimodel.InstanceV2Thumbnail{} diff --git a/test/envparsing.sh b/test/envparsing.sh index 9b56dd9c..a2ebd6e6 100755 --- a/test/envparsing.sh +++ b/test/envparsing.sh @@ -108,6 +108,7 @@ EXPECT=$(cat <<"EOF" "instance-expose-public-timeline": true, "instance-expose-suspended": true, "instance-expose-suspended-web": true, + "instance-inject-mastodon-version": true, "landing-page-user": "admin", "letsencrypt-cert-dir": "/gotosocial/storage/certs", "letsencrypt-email-address": "", @@ -215,6 +216,7 @@ GTS_INSTANCE_EXPOSE_SUSPENDED=true \ GTS_INSTANCE_EXPOSE_SUSPENDED_WEB=true \ GTS_INSTANCE_EXPOSE_PUBLIC_TIMELINE=true \ GTS_INSTANCE_DELIVER_TO_SHARED_INBOXES=false \ +GTS_INSTANCE_INJECT_MASTODON_VERSION=true \ GTS_ACCOUNTS_ALLOW_CUSTOM_CSS=true \ GTS_ACCOUNTS_CUSTOM_CSS_LENGTH=5000 \ GTS_ACCOUNTS_REGISTRATION_OPEN=true \