From 0af876979b9e2f781822770a24c93c229e3f1fa8 Mon Sep 17 00:00:00 2001 From: Xeronith Date: Thu, 15 Sep 2022 18:33:28 +0430 Subject: [PATCH] feat(app): :sparkles: resolve federated actors --- greataped/app/routes/user.go | 18 ++++++++++++++++++ greataped/contracts/utility.go | 13 +++++++++++++ greataped/server/http_context.go | 20 +++++++++++++++++--- greataped/utility/strings.go | 16 ++++++++++++++++ 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/greataped/app/routes/user.go b/greataped/app/routes/user.go index 4a4f0b7..3cc8e20 100644 --- a/greataped/app/routes/user.go +++ b/greataped/app/routes/user.go @@ -1,6 +1,7 @@ package routes import ( + "activitypub" "app/models/repos" "config" . "contracts" @@ -19,6 +20,23 @@ var User = route.New(HttpGet, "/u/:username", func(x IContext) error { return x.BadRequest("Bad request") } + if x.StringUtil().Contains(username, "@") { + parts := x.StringUtil().Split(username, "@") + url := x.StringUtil().Format("https://%s/.well-known/webfinger?resource=acct:%s", parts[1], username) + + webfinger := activitypub.Webfinger{} + if err := x.GetActivityStream(url, "", "", nil, &webfinger); err != nil { + return x.InternalServerError(err.Error()) + } + + actor := activitypub.Actor{} + if err := x.GetActivityStream(webfinger.Aliases[0], "activitystream", "", nil, &actor); err != nil { + return x.InternalServerError(err.Error()) + } + + return x.Activity(actor) + } + user := &repos.User{} err := repos.FindUserByUsername(user, username).Error if errors.Is(err, gorm.ErrRecordNotFound) { diff --git a/greataped/contracts/utility.go b/greataped/contracts/utility.go index cc4c4c1..0916bea 100644 --- a/greataped/contracts/utility.go +++ b/greataped/contracts/utility.go @@ -12,4 +12,17 @@ type IStringUtil interface { Replace(s, old, new string, n int) string // Format formats according to a format specifier and returns the resulting string. Format(format string, a ...any) string + // Split slices s into all substrings separated by sep and returns a slice of + // the substrings between those separators. + // + // If s does not contain sep and sep is not empty, Split returns a + // slice of length 1 whose only element is s. + // + // If sep is empty, Split splits after each UTF-8 sequence. If both s + // and sep are empty, Split returns an empty slice. + // + // It is equivalent to SplitN with a count of -1. + // + // To split around the first instance of a separator, see Cut. + Split(s, sep string) []string } diff --git a/greataped/server/http_context.go b/greataped/server/http_context.go index bc10a7d..d411e8c 100644 --- a/greataped/server/http_context.go +++ b/greataped/server/http_context.go @@ -184,8 +184,14 @@ func (context *httpServerContext) requestActivityStream(method, url, keyId, priv return err } - if err := context.signRequest(keyId, privateKey, data, req); err != nil { - return err + if privateKey != "" { + if err := context.signRequest(keyId, privateKey, data, req); err != nil { + return err + } + } + + if keyId == "activitystream" { + req.Header.Add("Accept", "application/activity+json") } res, err := context.httpClient.Do(req) @@ -202,10 +208,18 @@ func (context *httpServerContext) requestActivityStream(method, url, keyId, priv return fmt.Errorf("%s", res.Status) } + j, err := io.ReadAll(res.Body) + if err != nil { + return err + } + + fmt.Println(string(j)) + if output != nil { - if err := json.NewDecoder(res.Body).Decode(output); err != nil { + if err := json.Unmarshal(j, output); err != nil { return err } + } return nil diff --git a/greataped/utility/strings.go b/greataped/utility/strings.go index 4e9d249..acbed5b 100644 --- a/greataped/utility/strings.go +++ b/greataped/utility/strings.go @@ -31,3 +31,19 @@ func (util *stringUtil) Replace(s, old, new string, n int) string { func (util *stringUtil) Format(format string, a ...any) string { return fmt.Sprintf(format, a...) } + +// Split slices s into all substrings separated by sep and returns a slice of +// the substrings between those separators. +// +// If s does not contain sep and sep is not empty, Split returns a +// slice of length 1 whose only element is s. +// +// If sep is empty, Split splits after each UTF-8 sequence. If both s +// and sep are empty, Split returns an empty slice. +// +// It is equivalent to SplitN with a count of -1. +// +// To split around the first instance of a separator, see Cut. +func (util *stringUtil) Split(s, sep string) []string { + return strings.Split(s, sep) +}