123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- package controllers
- import (
- "encoding/json"
- "fmt"
- "net/http"
- "net/url"
- "strings"
- "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 := 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)
- }
- func getWebfingerLinks(account string) ([]map[string]interface{}, error) {
- type webfingerResponse struct {
- Links []map[string]interface{} `json:"links"`
- }
- account = strings.TrimLeft(account, "@") // remove any leading @
- accountComponents := strings.Split(account, "@")
- fediverseServer := accountComponents[1]
- // HTTPS is required.
- requestURL, err := url.Parse("https://" + fediverseServer)
- if err != nil {
- return nil, fmt.Errorf("unable to parse fediverse server host %s", fediverseServer)
- }
- requestURL.Path = "/.well-known/webfinger"
- query := requestURL.Query()
- query.Add("resource", fmt.Sprintf("acct:%s", account))
- requestURL.RawQuery = query.Encode()
- response, err := http.DefaultClient.Get(requestURL.String())
- if err != nil {
- return nil, err
- }
- defer response.Body.Close()
- var links webfingerResponse
- decoder := json.NewDecoder(response.Body)
- if err := decoder.Decode(&links); err != nil {
- return nil, err
- }
- return links.Links, nil
- }
|