package activitypub import ( "encoding/json" "errors" "io" "time" "git.mstar.dev/mstar/goutils/other" "git.mstar.dev/mstar/goutils/sliceutils" "github.com/rs/zerolog/log" "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 := GetAccountWebfinger(targetName) if err != nil { return "", other.Error("activitypub", "webfinger request failed", err) } selfLinks := sliceutils.Filter(webfinger.Links, func(t LinkData) bool { return t.Relation == "self" }) if len(selfLinks) == 0 { return "", errors.New("No self link") } APLink := selfLinks[0] req, err := webshared.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() body, _ := io.ReadAll(response.Body) log.Debug(). Int("status", response.StatusCode). Bytes("body", body). Any("headers", response.Header). Msg("Response information") if response.StatusCode != 200 { return "", errors.New("Bad status") } var data InboundUser err = json.Unmarshal(body, &data) if err != nil { return "", err } log.Info().Any("received-data", data).Msg("Response data") return "", nil }