mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 06:12:25 -05:00 
			
		
		
		
	add api/v1/instance info handler + instance model (#18)
This commit is contained in:
		
					parent
					
						
							
								0cbab627c7
							
						
					
				
			
			
				commit
				
					
						3363e0ebdd
					
				
			
		
					 11 changed files with 222 additions and 22 deletions
				
			
		
							
								
								
									
										38
									
								
								internal/api/client/instance/instance.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								internal/api/client/instance/instance.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | package instance | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"github.com/sirupsen/logrus" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/api" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/config" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/message" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/router" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	// InstanceInformationPath | ||||||
|  | 	InstanceInformationPath = "api/v1/instance" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Module implements the ClientModule interface | ||||||
|  | type Module struct { | ||||||
|  | 	config    *config.Config | ||||||
|  | 	processor message.Processor | ||||||
|  | 	log       *logrus.Logger | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // New returns a new instance information module | ||||||
|  | func New(config *config.Config, processor message.Processor, log *logrus.Logger) api.ClientModule { | ||||||
|  | 	return &Module{ | ||||||
|  | 		config:    config, | ||||||
|  | 		processor: processor, | ||||||
|  | 		log:       log, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Route satisfies the ClientModule interface | ||||||
|  | func (m *Module) Route(s router.Router) error { | ||||||
|  | 	s.AttachHandler(http.MethodGet, InstanceInformationPath, m.InstanceInformationGETHandler) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								internal/api/client/instance/instanceget.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								internal/api/client/instance/instanceget.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | package instance | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"net/http" | ||||||
|  | 
 | ||||||
|  | 	"github.com/gin-gonic/gin" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func (m *Module) InstanceInformationGETHandler(c *gin.Context) { | ||||||
|  | 	l := m.log.WithField("func", "InstanceInformationGETHandler") | ||||||
|  | 
 | ||||||
|  | 	instance, err := m.processor.InstanceGet(m.config.Host) | ||||||
|  | 	if err != nil { | ||||||
|  | 		l.Debugf("error getting instance from processor: %s", err) | ||||||
|  | 		c.JSON(http.StatusInternalServerError, gin.H{"error": "internal server error"}) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	c.JSON(http.StatusOK, instance) | ||||||
|  | } | ||||||
|  | @ -23,9 +23,9 @@ type Instance struct { | ||||||
| 	// REQUIRED | 	// REQUIRED | ||||||
| 
 | 
 | ||||||
| 	// The domain name of the instance. | 	// The domain name of the instance. | ||||||
| 	URI string `json:"uri"` | 	URI string `json:"uri,omitempty"` | ||||||
| 	// The title of the website. | 	// The title of the website. | ||||||
| 	Title string `json:"title"` | 	Title string `json:"title,omitempty"` | ||||||
| 	// Admin-defined description of the Mastodon site. | 	// Admin-defined description of the Mastodon site. | ||||||
| 	Description string `json:"description"` | 	Description string `json:"description"` | ||||||
| 	// A shorter description defined by the admin. | 	// A shorter description defined by the admin. | ||||||
|  | @ -33,9 +33,9 @@ type Instance struct { | ||||||
| 	// An email that may be contacted for any inquiries. | 	// An email that may be contacted for any inquiries. | ||||||
| 	Email string `json:"email"` | 	Email string `json:"email"` | ||||||
| 	// The version of Mastodon installed on the instance. | 	// The version of Mastodon installed on the instance. | ||||||
| 	Version string `json:"version"` | 	Version string `json:"version,omitempty"` | ||||||
| 	// Primary langauges of the website and its staff. | 	// Primary langauges of the website and its staff. | ||||||
| 	Languages []string `json:"languages"` | 	Languages []string `json:"languages,omitempty"` | ||||||
| 	// Whether registrations are enabled. | 	// Whether registrations are enabled. | ||||||
| 	Registrations bool `json:"registrations"` | 	Registrations bool `json:"registrations"` | ||||||
| 	// Whether registrations require moderator approval. | 	// Whether registrations require moderator approval. | ||||||
|  | @ -43,16 +43,16 @@ type Instance struct { | ||||||
| 	// Whether invites are enabled. | 	// Whether invites are enabled. | ||||||
| 	InvitesEnabled bool `json:"invites_enabled"` | 	InvitesEnabled bool `json:"invites_enabled"` | ||||||
| 	// URLs of interest for clients apps. | 	// URLs of interest for clients apps. | ||||||
| 	URLS *InstanceURLs `json:"urls"` | 	URLS *InstanceURLs `json:"urls,omitempty"` | ||||||
| 	// Statistics about how much information the instance contains. | 	// Statistics about how much information the instance contains. | ||||||
| 	Stats *InstanceStats `json:"stats"` | 	Stats *InstanceStats `json:"stats,omitempty"` | ||||||
| 
 |  | ||||||
| 	// OPTIONAL |  | ||||||
| 
 |  | ||||||
| 	// Banner image for the website. | 	// Banner image for the website. | ||||||
| 	Thumbnail string `json:"thumbnail,omitempty"` | 	Thumbnail string `json:"thumbnail"` | ||||||
| 	// A user that can be contacted, as an alternative to email. | 	// A user that can be contacted, as an alternative to email. | ||||||
| 	ContactAccount *Account `json:"contact_account,omitempty"` | 	ContactAccount *Account `json:"contact_account,omitempty"` | ||||||
|  | 	// What's the maximum allowed length of a post on this instance? | ||||||
|  | 	// This is provided for compatibility with Tusky. | ||||||
|  | 	MaxTootChars uint `json:"max_toot_chars"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // InstanceURLs represents URLs necessary for successfully connecting to the instance as a user. See https://docs.joinmastodon.org/entities/instance/ | // InstanceURLs represents URLs necessary for successfully connecting to the instance as a user. See https://docs.joinmastodon.org/entities/instance/ | ||||||
|  |  | ||||||
|  | @ -117,6 +117,11 @@ type DB interface { | ||||||
| 	// This is needed for things like serving files that belong to the instance and not an individual user/account. | 	// This is needed for things like serving files that belong to the instance and not an individual user/account. | ||||||
| 	CreateInstanceAccount() error | 	CreateInstanceAccount() error | ||||||
| 
 | 
 | ||||||
|  | 	// CreateInstanceInstance creates an instance in the database with the same domain as the instance host value. | ||||||
|  | 	// Ie., if the instance is hosted at 'example.org' the instance will have a domain of 'example.org'. | ||||||
|  | 	// This is needed for things like serving instance information through /api/v1/instance | ||||||
|  | 	CreateInstanceInstance() error | ||||||
|  | 
 | ||||||
| 	// GetAccountByUserID is a shortcut for the common action of fetching an account corresponding to a user ID. | 	// GetAccountByUserID is a shortcut for the common action of fetching an account corresponding to a user ID. | ||||||
| 	// The given account pointer will be set to the result of the query, whatever it is. | 	// The given account pointer will be set to the result of the query, whatever it is. | ||||||
| 	// In case of no entries, a 'no entries' error will be returned | 	// In case of no entries, a 'no entries' error will be returned | ||||||
|  |  | ||||||
|  | @ -307,17 +307,54 @@ func (ps *postgresService) DeleteWhere(key string, value interface{}, i interfac | ||||||
| 
 | 
 | ||||||
| func (ps *postgresService) CreateInstanceAccount() error { | func (ps *postgresService) CreateInstanceAccount() error { | ||||||
| 	username := ps.config.Host | 	username := ps.config.Host | ||||||
| 	instanceAccount := >smodel.Account{ | 	key, err := rsa.GenerateKey(rand.Reader, 2048) | ||||||
| 		Username: username, | 	if err != nil { | ||||||
|  | 		ps.log.Errorf("error creating new rsa key: %s", err) | ||||||
|  | 		return err | ||||||
| 	} | 	} | ||||||
| 	inserted, err := ps.conn.Model(instanceAccount).Where("username = ?", username).SelectOrInsert() | 
 | ||||||
|  | 	newAccountURIs := util.GenerateURIsForAccount(username, ps.config.Protocol, ps.config.Host) | ||||||
|  | 	a := >smodel.Account{ | ||||||
|  | 		Username:              ps.config.Host, | ||||||
|  | 		DisplayName:           username, | ||||||
|  | 		URL:                   newAccountURIs.UserURL, | ||||||
|  | 		PrivateKey:            key, | ||||||
|  | 		PublicKey:             &key.PublicKey, | ||||||
|  | 		PublicKeyURI:          newAccountURIs.PublicKeyURI, | ||||||
|  | 		ActorType:             gtsmodel.ActivityStreamsPerson, | ||||||
|  | 		URI:                   newAccountURIs.UserURI, | ||||||
|  | 		InboxURI:              newAccountURIs.InboxURI, | ||||||
|  | 		OutboxURI:             newAccountURIs.OutboxURI, | ||||||
|  | 		FollowersURI:          newAccountURIs.FollowersURI, | ||||||
|  | 		FollowingURI:          newAccountURIs.FollowingURI, | ||||||
|  | 		FeaturedCollectionURI: newAccountURIs.CollectionURI, | ||||||
|  | 	} | ||||||
|  | 	inserted, err := ps.conn.Model(a).Where("username = ?", username).SelectOrInsert() | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	if inserted { | 	if inserted { | ||||||
| 		ps.log.Infof("created instance account %s with id %s", username, instanceAccount.ID) | 		ps.log.Infof("created instance account %s with id %s", username, a.ID) | ||||||
| 	} else { | 	} else { | ||||||
| 		ps.log.Infof("instance account %s already exists with id %s", username, instanceAccount.ID) | 		ps.log.Infof("instance account %s already exists with id %s", username, a.ID) | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (ps *postgresService) CreateInstanceInstance() error { | ||||||
|  | 	i := >smodel.Instance{ | ||||||
|  | 		Domain: ps.config.Host, | ||||||
|  | 		Title: ps.config.Host, | ||||||
|  | 		URI: fmt.Sprintf("%s://%s", ps.config.Protocol, ps.config.Host), | ||||||
|  | 	} | ||||||
|  | 	inserted, err := ps.conn.Model(i).Where("domain = ?", ps.config.Host).SelectOrInsert() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if inserted { | ||||||
|  | 		ps.log.Infof("created instance instance %s with id %s", ps.config.Host, i.ID) | ||||||
|  | 	} else { | ||||||
|  | 		ps.log.Infof("instance instance %s already exists with id %s",  ps.config.Host, i.ID) | ||||||
| 	} | 	} | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -34,6 +34,7 @@ import ( | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/api/client/app" | 	"github.com/superseriousbusiness/gotosocial/internal/api/client/app" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/api/client/auth" | 	"github.com/superseriousbusiness/gotosocial/internal/api/client/auth" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/api/client/fileserver" | 	"github.com/superseriousbusiness/gotosocial/internal/api/client/fileserver" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/api/client/instance" | ||||||
| 	mediaModule "github.com/superseriousbusiness/gotosocial/internal/api/client/media" | 	mediaModule "github.com/superseriousbusiness/gotosocial/internal/api/client/media" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/api/client/status" | 	"github.com/superseriousbusiness/gotosocial/internal/api/client/status" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/api/security" | 	"github.com/superseriousbusiness/gotosocial/internal/api/security" | ||||||
|  | @ -68,6 +69,7 @@ var models []interface{} = []interface{}{ | ||||||
| 	>smodel.Tag{}, | 	>smodel.Tag{}, | ||||||
| 	>smodel.User{}, | 	>smodel.User{}, | ||||||
| 	>smodel.Emoji{}, | 	>smodel.Emoji{}, | ||||||
|  | 	>smodel.Instance{}, | ||||||
| 	&oauth.Token{}, | 	&oauth.Token{}, | ||||||
| 	&oauth.Client{}, | 	&oauth.Client{}, | ||||||
| } | } | ||||||
|  | @ -105,6 +107,7 @@ var Run action.GTSAction = func(ctx context.Context, c *config.Config, log *logr | ||||||
| 	// build client api modules | 	// build client api modules | ||||||
| 	authModule := auth.New(c, dbService, oauthServer, log) | 	authModule := auth.New(c, dbService, oauthServer, log) | ||||||
| 	accountModule := account.New(c, processor, log) | 	accountModule := account.New(c, processor, log) | ||||||
|  | 	instanceModule := instance.New(c, processor, log) | ||||||
| 	appsModule := app.New(c, processor, log) | 	appsModule := app.New(c, processor, log) | ||||||
| 	mm := mediaModule.New(c, processor, log) | 	mm := mediaModule.New(c, processor, log) | ||||||
| 	fileServerModule := fileserver.New(c, processor, log) | 	fileServerModule := fileserver.New(c, processor, log) | ||||||
|  | @ -119,6 +122,7 @@ var Run action.GTSAction = func(ctx context.Context, c *config.Config, log *logr | ||||||
| 
 | 
 | ||||||
| 		// now everything else | 		// now everything else | ||||||
| 		accountModule, | 		accountModule, | ||||||
|  | 		instanceModule, | ||||||
| 		appsModule, | 		appsModule, | ||||||
| 		mm, | 		mm, | ||||||
| 		fileServerModule, | 		fileServerModule, | ||||||
|  | @ -142,6 +146,10 @@ var Run action.GTSAction = func(ctx context.Context, c *config.Config, log *logr | ||||||
| 		return fmt.Errorf("error creating instance account: %s", err) | 		return fmt.Errorf("error creating instance account: %s", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if err := dbService.CreateInstanceInstance(); err != nil { | ||||||
|  | 		return fmt.Errorf("error creating instance instance: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	gts, err := New(dbService, router, federator, c) | 	gts, err := New(dbService, router, federator, c) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return fmt.Errorf("error creating gotosocial service: %s", err) | 		return fmt.Errorf("error creating gotosocial service: %s", err) | ||||||
|  |  | ||||||
							
								
								
									
										33
									
								
								internal/gtsmodel/instance.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								internal/gtsmodel/instance.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | package gtsmodel | ||||||
|  | 
 | ||||||
|  | import "time" | ||||||
|  | 
 | ||||||
|  | // Instance represents a federated instance, either local or remote. | ||||||
|  | type Instance struct { | ||||||
|  | 	// ID of this instance in the database | ||||||
|  | 	ID string `pg:"type:uuid,default:gen_random_uuid(),pk,notnull,unique"` | ||||||
|  | 	// Instance domain eg example.org | ||||||
|  | 	Domain string `pg:",notnull,unique"` | ||||||
|  | 	// Title of this instance as it would like to be displayed. | ||||||
|  | 	Title string | ||||||
|  | 	// base URI of this instance eg https://example.org | ||||||
|  | 	URI string `pg:",notnull,unique"` | ||||||
|  | 	// When was this instance created in the db? | ||||||
|  | 	CreatedAt time.Time `pg:"type:timestamp,notnull,default:now()"` | ||||||
|  | 	// When was this instance last updated in the db? | ||||||
|  | 	UpdatedAt   time.Time `pg:"type:timestamp,notnull,default:now()"` | ||||||
|  | 	// When was this instance suspended, if at all? | ||||||
|  | 	SuspendedAt time.Time | ||||||
|  | 	// ID of any existing domain block for this instance in the database | ||||||
|  | 	DomainBlockID string | ||||||
|  | 	// Short description of this instance | ||||||
|  | 	ShortDescription string | ||||||
|  | 	// Longer description of this instance | ||||||
|  | 	Description string | ||||||
|  | 	// Contact email address for this instance | ||||||
|  | 	ContactEmail string | ||||||
|  | 	// Contact account ID in the database for this instance | ||||||
|  | 	ContactAccountID string | ||||||
|  | 	// Reputation score of this instance | ||||||
|  | 	Reputation int64 `pg:",notnull,default:0"` | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								internal/message/instanceprocess.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								internal/message/instanceprocess.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | package message | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 
 | ||||||
|  | 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func (p *processor) InstanceGet(domain string) (*apimodel.Instance, ErrorWithCode) { | ||||||
|  | 	i := >smodel.Instance{} | ||||||
|  | 	if err := p.db.GetWhere("domain", domain, i); err != nil { | ||||||
|  | 		return nil, NewErrorInternalError(fmt.Errorf("db error fetching instance %s: %s", p.config.Host, err)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	ai, err := p.tc.InstanceToMasto(i) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, NewErrorInternalError(fmt.Errorf("error converting instance to api representation: %s", err)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return  ai, nil | ||||||
|  | } | ||||||
|  | @ -68,9 +68,20 @@ type Processor interface { | ||||||
| 	// AccountUpdate processes the update of an account with the given form | 	// AccountUpdate processes the update of an account with the given form | ||||||
| 	AccountUpdate(authed *oauth.Auth, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error) | 	AccountUpdate(authed *oauth.Auth, form *apimodel.UpdateCredentialsRequest) (*apimodel.Account, error) | ||||||
| 
 | 
 | ||||||
|  | 	// AdminEmojiCreate handles the creation of a new instance emoji by an admin, using the given form. | ||||||
|  | 	AdminEmojiCreate(authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error) | ||||||
|  | 
 | ||||||
| 	// AppCreate processes the creation of a new API application | 	// AppCreate processes the creation of a new API application | ||||||
| 	AppCreate(authed *oauth.Auth, form *apimodel.ApplicationCreateRequest) (*apimodel.Application, error) | 	AppCreate(authed *oauth.Auth, form *apimodel.ApplicationCreateRequest) (*apimodel.Application, error) | ||||||
| 
 | 
 | ||||||
|  | 	// InstanceGet retrieves instance information for serving at api/v1/instance | ||||||
|  | 	InstanceGet(domain string) (*apimodel.Instance, ErrorWithCode) | ||||||
|  | 
 | ||||||
|  | 	// MediaCreate handles the creation of a media attachment, using the given form. | ||||||
|  | 	MediaCreate(authed *oauth.Auth, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error) | ||||||
|  | 	// MediaGet handles the fetching of a media attachment, using the given request form. | ||||||
|  | 	MediaGet(authed *oauth.Auth, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) | ||||||
|  | 
 | ||||||
| 	// StatusCreate processes the given form to create a new status, returning the api model representation of that status if it's OK. | 	// StatusCreate processes the given form to create a new status, returning the api model representation of that status if it's OK. | ||||||
| 	StatusCreate(authed *oauth.Auth, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, error) | 	StatusCreate(authed *oauth.Auth, form *apimodel.AdvancedStatusCreateForm) (*apimodel.Status, error) | ||||||
| 	// StatusDelete processes the delete of a given status, returning the deleted status if the delete goes through. | 	// StatusDelete processes the delete of a given status, returning the deleted status if the delete goes through. | ||||||
|  | @ -86,13 +97,6 @@ type Processor interface { | ||||||
| 	// StatusUnfave processes the unfaving of a given status, returning the updated status if the fave goes through. | 	// StatusUnfave processes the unfaving of a given status, returning the updated status if the fave goes through. | ||||||
| 	StatusUnfave(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) | 	StatusUnfave(authed *oauth.Auth, targetStatusID string) (*apimodel.Status, error) | ||||||
| 
 | 
 | ||||||
| 	// MediaCreate handles the creation of a media attachment, using the given form. |  | ||||||
| 	MediaCreate(authed *oauth.Auth, form *apimodel.AttachmentRequest) (*apimodel.Attachment, error) |  | ||||||
| 	// MediaGet handles the fetching of a media attachment, using the given request form. |  | ||||||
| 	MediaGet(authed *oauth.Auth, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) |  | ||||||
| 	// AdminEmojiCreate handles the creation of a new instance emoji by an admin, using the given form. |  | ||||||
| 	AdminEmojiCreate(authed *oauth.Auth, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error) |  | ||||||
| 
 |  | ||||||
| 	/* | 	/* | ||||||
| 		FEDERATION API-FACING PROCESSING FUNCTIONS | 		FEDERATION API-FACING PROCESSING FUNCTIONS | ||||||
| 		These functions are intended to be called when the federating client needs an immediate (ie., synchronous) reply | 		These functions are intended to be called when the federating client needs an immediate (ie., synchronous) reply | ||||||
|  |  | ||||||
|  | @ -74,6 +74,9 @@ type TypeConverter interface { | ||||||
| 	// VisToMasto converts a gts visibility into its mastodon equivalent | 	// VisToMasto converts a gts visibility into its mastodon equivalent | ||||||
| 	VisToMasto(m gtsmodel.Visibility) model.Visibility | 	VisToMasto(m gtsmodel.Visibility) model.Visibility | ||||||
| 
 | 
 | ||||||
|  | 	// InstanceToMasto converts a gts instance into its mastodon equivalent for serving at /api/v1/instance | ||||||
|  | 	InstanceToMasto(i *gtsmodel.Instance) (*model.Instance, error) | ||||||
|  | 
 | ||||||
| 	/* | 	/* | ||||||
| 		FRONTEND (mastodon) MODEL TO INTERNAL (gts) MODEL | 		FRONTEND (mastodon) MODEL TO INTERNAL (gts) MODEL | ||||||
| 	*/ | 	*/ | ||||||
|  |  | ||||||
|  | @ -551,3 +551,33 @@ func (c *converter) VisToMasto(m gtsmodel.Visibility) model.Visibility { | ||||||
| 	} | 	} | ||||||
| 	return "" | 	return "" | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func (c *converter) InstanceToMasto(i *gtsmodel.Instance) (*model.Instance, error) { | ||||||
|  | 	mi := &model.Instance{ | ||||||
|  | 		URI: i.URI, | ||||||
|  | 		Title: i.Title, | ||||||
|  | 		Description: i.Description, | ||||||
|  | 		ShortDescription: i.ShortDescription, | ||||||
|  | 		Email: i.ContactEmail, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if i.Domain == c.config.Host { | ||||||
|  | 		mi.Registrations = c.config.AccountsConfig.OpenRegistration | ||||||
|  | 		mi.ApprovalRequired = c.config.AccountsConfig.RequireApproval | ||||||
|  | 		mi.InvitesEnabled = false // TODO | ||||||
|  | 		mi.MaxTootChars = uint(c.config.StatusesConfig.MaxChars) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// contact account is optional but let's try to get it | ||||||
|  | 	if i.ContactAccountID != "" { | ||||||
|  | 		ia := >smodel.Account{} | ||||||
|  | 		if err := c.db.GetByID(i.ContactAccountID, ia); err == nil { | ||||||
|  | 			ma, err := c.AccountToMastoPublic(ia) | ||||||
|  | 			if err == nil { | ||||||
|  | 				mi.ContactAccount = ma | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return mi, nil | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue