linstrom/activitypub/import.go
mStar f4e876a4b1
All checks were successful
/ docker (push) Successful in 4m7s
Current state
2025-04-13 20:10:19 +02:00

105 lines
3.2 KiB
Go

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)
// err = webshared.SignWithHttpsig(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
}