package activitypub import ( "encoding/json" "errors" "io" "net/http" "time" "git.mstar.dev/mstar/goutils/sliceutils" "github.com/rs/zerolog/log" apshared "git.mstar.dev/mstar/linstrom/activitypub/shared" "git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/storage-new/dbgen" webshared "git.mstar.dev/mstar/linstrom/web/shared" ) func ImportRemoteAccount(targetName string) (string, error) { type InboundUserKey struct { Id string `json:"id"` Owner string `json:"owner"` Pem string `json:"publicKeyPem"` } type InboundUserMedia struct { Type string `json:"type"` Url string `json:"url"` MediaType string `json:"mediaType"` } type InboundUser struct { Id string `json:"id"` Type string `json:"type"` PreferredUsername string `json:"preferredUsername"` Inbox string `json:"inbox"` PublicKey *InboundUserKey `json:"publicKey"` Published *time.Time `json:"published"` DisplayName *string `json:"name"` Description *string `json:"summary,omitempty"` PublicUrl *string `json:"url"` Icon *InboundUserMedia `json:"icon,omitempty"` Banner *InboundUserMedia `json:"image,omitempty"` Discoverable *bool `json:"discoverable"` Location *string `json:"vcard:Address,omitempty"` Birthday *string `json:"vcard:bday,omitempty"` SpeakAsCat bool `json:"speakAsCat"` IsCat bool `json:"isCat"` RestrictedFollow *bool `json:"manuallyApprovesFollowers"` } // Get the target user's link first webfinger, err := apshared.GetAccountWebfinger(targetName) if err != nil { return "", err } selfLinks := sliceutils.Filter(webfinger.Links, func(t apshared.LinkData) bool { return t.Relation == "self" }) if len(selfLinks) == 0 { return "", errors.New("No self link") } APLink := selfLinks[0] req, err := http.NewRequest("GET", *APLink.Href, nil) if err != nil { return "", err } req.Header.Add("Accept", "application/activity+json") // Server actor key for signing linstromActor, err := dbgen.User.Where(dbgen.User.Username.Eq("linstrom")).First() if err != nil { return "", err } var keyBytes []byte if config.GlobalConfig.Experimental.UseEd25519Keys { keyBytes = linstromActor.PrivateKeyEd } else { keyBytes = linstromActor.PrivateKeyRsa } // Sign and send err = webshared.SignRequest(req, linstromActor.ID+"#main-key", keyBytes, nil) if err != nil { return "", err } response, err := webshared.RequestClient.Do(req) if err != nil { return "", err } defer response.Body.Close() if response.StatusCode != 200 { return "", errors.New("Bad status") } var data InboundUser body, _ := io.ReadAll(response.Body) log.Info().Bytes("body", body).Msg("Body from request") err = json.Unmarshal(body, &data) if err != nil { return "", err } log.Info().Any("received-data", data).Msg("Response data") return "", nil }