package ap import ( "errors" "fmt" "io" "net/http" "time" "gitlab.com/mstarongitlab/goap" ) var ErrNoApUrl = errors.New("no Activitypub url in webfinger") func GetRemoteUser(fullHandle string) (goap.BaseApChain, error) { webfinger, err := GetAccountWebfinger(fullHandle) if err != nil { return nil, err } apUrl := "" for _, link := range webfinger.Links { if link.Relation == "self" { apUrl = *link.Href } } if apUrl == "" { return nil, ErrNoApUrl } apRequest, err := http.NewRequest("GET", apUrl, nil) if err != nil { return nil, err } apRequest.Header.Add("Accept", "application/activity+json,application/ld+json,application/json") client := http.Client{Timeout: time.Second * 30} res, err := client.Do(apRequest) if err != nil { return nil, err } if res.StatusCode != 200 { return nil, fmt.Errorf("bad status code: %d", res.StatusCode) } body, err := io.ReadAll(res.Body) if err != nil { return nil, err } apObject, _ := goap.Unmarshal(body, nil, nil) // Check if Id exists if _, ok := goap.FindAttribute[*goap.UDIdData](apObject); !ok { return nil, fmt.Errorf("missing attribute for account: Id") } // Check that it has the correct object type for an account if objTypePtr, ok := goap.FindAttribute[*goap.UDTypeData](apObject); !ok { return nil, fmt.Errorf("missing attribute for account: Type") } else if objType := *objTypePtr; objType.Type != goap.KEY_ACTIVITYSTREAMS_ACTOR { return nil, fmt.Errorf("wrong ap object type: %s", objType.Type) } // And finally check for inbox if _, ok := goap.FindAttribute[*goap.W3InboxData](apObject); !ok { return nil, fmt.Errorf("missing attribute for account: Inbox") } return apObject, nil } func GetRemoteObject(target string) (goap.BaseApChain, error) { apRequest, err := http.NewRequest("GET", target, nil) if err != nil { return nil, err } apRequest.Header.Add("Accept", "application/activity+json,application/ld+json,application/json") client := http.Client{Timeout: time.Second * 30} res, err := client.Do(apRequest) if err != nil { return nil, err } if res.StatusCode != 200 { return nil, fmt.Errorf("bad status code: %d", res.StatusCode) } body, err := io.ReadAll(res.Body) if err != nil { return nil, err } apObject, _ := goap.Unmarshal(body, nil, nil) return apObject, nil }