package controllers import ( "encoding/json" "fmt" "net/http" "net/url" "strings" "github.com/owncast/owncast/activitypub/webfinger" "github.com/owncast/owncast/core/data" ) // RemoteFollow handles a request to begin the remote follow redirect flow. func RemoteFollow(w http.ResponseWriter, r *http.Request) { type followRequest struct { Account string `json:"account"` } type followResponse struct { RedirectURL string `json:"redirectUrl"` } var request followRequest decoder := json.NewDecoder(r.Body) if err := decoder.Decode(&request); err != nil { WriteSimpleResponse(w, false, "unable to parse request") return } if request.Account == "" { WriteSimpleResponse(w, false, "Remote Fediverse account is required to follow.") return } localActorPath, _ := url.Parse(data.GetServerURL()) localActorPath.Path = fmt.Sprintf("/federation/user/%s", data.GetDefaultFederationUsername()) var template string links, err := webfinger.GetWebfingerLinks(request.Account) if err != nil { WriteSimpleResponse(w, false, err.Error()) return } // Acquire the remote follow redirect template. for _, link := range links { for k, v := range link { if k == "rel" && v == "http://ostatus.org/schema/1.0/subscribe" && link["template"] != nil { template = link["template"].(string) } } } if localActorPath.String() == "" || template == "" { WriteSimpleResponse(w, false, "unable to determine remote follow information for "+request.Account) return } redirectURL := strings.Replace(template, "{uri}", localActorPath.String(), 1) response := followResponse{ RedirectURL: redirectURL, } WriteResponse(w, response) }