mirror of https://gitlab.com/ngerakines/tavern.git
73 lines
2.1 KiB
Go
73 lines
2.1 KiB
Go
package fed
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"github.com/ngerakines/tavern/common"
|
|
"github.com/ngerakines/tavern/errors"
|
|
"github.com/ngerakines/tavern/storage"
|
|
)
|
|
|
|
type WebFingerClient struct {
|
|
HTTPClient common.HTTPClient
|
|
Logger *zap.Logger
|
|
}
|
|
|
|
var invalidWebFingerResource = fmt.Errorf("invalid webfinger resource")
|
|
|
|
func (client WebFingerClient) Fetch(location string) (storage.Payload, error) {
|
|
destination, err := BuildWebFingerURL(location)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
client.Logger.Debug("Sending webfinger request", zap.String("url", destination))
|
|
_, payload, err := JRDJsonGet(client.HTTPClient, destination)
|
|
return payload, err
|
|
}
|
|
|
|
func BuildWebFingerURL(location string) (string, error) {
|
|
// example: https://webfinger.net/lookup/?resource=https%3A%2F%2Fmastodon.social%2F%40ngerakines
|
|
if strings.HasPrefix(location, "https://") {
|
|
u, err := url.Parse(location)
|
|
if err != nil {
|
|
return "", fmt.Errorf("%w: %s", invalidWebFingerResource, location)
|
|
}
|
|
domain := u.Hostname()
|
|
return fmt.Sprintf("https://%s/.well-known/webfinger?resource=%s", domain, url.QueryEscape(location)), nil
|
|
}
|
|
// Some acct lookups may have a prefix from user input.
|
|
location = strings.TrimPrefix(location, "@")
|
|
|
|
subjectParts := strings.FieldsFunc(location, func(r rune) bool { return r == '@' })
|
|
if len(subjectParts) != 2 {
|
|
return "", fmt.Errorf("%w: %s", invalidWebFingerResource, location)
|
|
}
|
|
|
|
return fmt.Sprintf("https://%s/.well-known/webfinger?resource=acct:%s", subjectParts[1], url.QueryEscape(location)), nil
|
|
}
|
|
|
|
func ActorIDFromWebFingerPayload(wfp storage.Payload) (string, string, error) {
|
|
subject, _ := storage.JSONString(wfp, "subject")
|
|
|
|
links, ok := storage.JSONMapList(wfp, "links")
|
|
if ok {
|
|
for _, link := range links {
|
|
rel, hasRel := storage.JSONString(link, "rel")
|
|
linkType, hasType := storage.JSONString(link, "type")
|
|
href, hasHref := storage.JSONString(link, "href")
|
|
if !hasRel || !hasType || !hasHref {
|
|
continue
|
|
}
|
|
if rel == "self" && linkType == "application/activity+json" {
|
|
return href, subject, nil
|
|
}
|
|
}
|
|
}
|
|
return "", "", errors.NewNotFoundError(nil)
|
|
}
|