/* GoToSocial Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package typeutils import ( "errors" "fmt" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" ) func (c *converter) ASRepresentationToAccount(accountable Accountable) (*gtsmodel.Account, error) { // first check if we actually already know this account uriProp := accountable.GetJSONLDId() if uriProp == nil || !uriProp.IsIRI() { return nil, errors.New("no id property found on person, or id was not an iri") } uri := uriProp.GetIRI() acct := >smodel.Account{} err := c.db.GetWhere("uri", uri.String(), acct) if err == nil { // we already know this account so we can skip generating it return acct, nil } if _, ok := err.(db.ErrNoEntries); !ok { // we don't know the account and there's been a real error return nil, fmt.Errorf("error getting account with uri %s from the database: %s", uri.String(), err) } // we don't know the account so we need to generate it from the person -- at least we already have the URI! acct = >smodel.Account{} acct.URI = uri.String() // Username aka preferredUsername // We need this one so bail if it's not set. username, err := extractPreferredUsername(accountable) if err != nil { return nil, fmt.Errorf("couldn't extract username: %s", err) } acct.Username = username // Domain acct.Domain = uri.Host // avatar aka icon // if this one isn't extractable in a format we recognise we'll just skip it if avatarURL, err := extractIconURL(accountable); err == nil { acct.AvatarRemoteURL = avatarURL.String() } // header aka image // if this one isn't extractable in a format we recognise we'll just skip it if headerURL, err := extractImageURL(accountable); err == nil { acct.HeaderRemoteURL = headerURL.String() } // display name aka name // we default to the username, but take the more nuanced name property if it exists acct.DisplayName = username if displayName, err := extractName(accountable); err == nil { acct.DisplayName = displayName } // TODO: fields aka attachment array // note aka summary note, err := extractSummary(accountable) if err == nil && note != "" { acct.Note = note } // check for bot and actor type switch gtsmodel.ActivityStreamsActor(accountable.GetTypeName()) { case gtsmodel.ActivityStreamsPerson, gtsmodel.ActivityStreamsGroup, gtsmodel.ActivityStreamsOrganization: // people, groups, and organizations aren't bots acct.Bot = false // apps and services are case gtsmodel.ActivityStreamsApplication, gtsmodel.ActivityStreamsService: acct.Bot = true default: // we don't know what this is! return nil, fmt.Errorf("type name %s not recognised or not convertible to gtsmodel.ActivityStreamsActor", accountable.GetTypeName()) } acct.ActorType = gtsmodel.ActivityStreamsActor(accountable.GetTypeName()) // TODO: locked aka manuallyApprovesFollowers // discoverable // default to false -- take custom value if it's set though acct.Discoverable = false discoverable, err := extractDiscoverable(accountable) if err == nil { acct.Discoverable = discoverable } // url property url, err := extractURL(accountable) if err != nil { return nil, fmt.Errorf("could not extract url for person with id %s: %s", uri.String(), err) } acct.URL = url.String() // InboxURI if accountable.GetActivityStreamsInbox() == nil || accountable.GetActivityStreamsInbox().GetIRI() == nil { return nil, fmt.Errorf("person with id %s had no inbox uri", uri.String()) } acct.InboxURI = accountable.GetActivityStreamsInbox().GetIRI().String() // OutboxURI if accountable.GetActivityStreamsOutbox() == nil || accountable.GetActivityStreamsOutbox().GetIRI() == nil { return nil, fmt.Errorf("person with id %s had no outbox uri", uri.String()) } acct.OutboxURI = accountable.GetActivityStreamsOutbox().GetIRI().String() // FollowingURI if accountable.GetActivityStreamsFollowing() == nil || accountable.GetActivityStreamsFollowing().GetIRI() == nil { return nil, fmt.Errorf("person with id %s had no following uri", uri.String()) } acct.FollowingURI = accountable.GetActivityStreamsFollowing().GetIRI().String() // FollowersURI if accountable.GetActivityStreamsFollowers() == nil || accountable.GetActivityStreamsFollowers().GetIRI() == nil { return nil, fmt.Errorf("person with id %s had no followers uri", uri.String()) } acct.FollowersURI = accountable.GetActivityStreamsFollowers().GetIRI().String() // FeaturedURI // very much optional if accountable.GetTootFeatured() != nil && accountable.GetTootFeatured().GetIRI() != nil { acct.FeaturedCollectionURI = accountable.GetTootFeatured().GetIRI().String() } // TODO: FeaturedTagsURI // TODO: alsoKnownAs // publicKey pkey, pkeyURL, err := extractPublicKeyForOwner(accountable, uri) if err != nil { return nil, fmt.Errorf("couldn't get public key for person %s: %s", uri.String(), err) } acct.PublicKey = pkey acct.PublicKeyURI = pkeyURL.String() return acct, nil }