github.com/status-im/status-go@v1.1.0/protocol/linkpreview_unfurler_oembed.go (about) 1 package protocol 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "net/http" 7 neturl "net/url" 8 9 "go.uber.org/zap" 10 11 "github.com/status-im/status-go/protocol/common" 12 "github.com/status-im/status-go/protocol/protobuf" 13 ) 14 15 type OEmbedUnfurler struct { 16 logger *zap.Logger 17 httpClient *http.Client 18 // oembedEndpoint describes where the consumer may request representations for 19 // the supported URL scheme. For example, for YouTube, it is 20 // https://www.youtube.com/oembed. 21 oembedEndpoint string 22 // url is the actual URL to be unfurled. 23 url *neturl.URL 24 } 25 26 func NewOEmbedUnfurler(oembedEndpoint string, 27 url *neturl.URL, 28 logger *zap.Logger, 29 httpClient *http.Client) *OEmbedUnfurler { 30 return &OEmbedUnfurler{ 31 oembedEndpoint: oembedEndpoint, 32 url: url, 33 logger: logger, 34 httpClient: httpClient, 35 } 36 } 37 38 type OEmbedResponse struct { 39 Title string `json:"title"` 40 ThumbnailURL string `json:"thumbnail_url"` 41 } 42 43 func (u *OEmbedUnfurler) newOEmbedURL() (*neturl.URL, error) { 44 oembedURL, err := neturl.Parse(u.oembedEndpoint) 45 if err != nil { 46 return nil, err 47 } 48 49 // When format is specified, the provider MUST return data in the requested 50 // format, else return an error. 51 oembedURL.RawQuery = neturl.Values{ 52 "url": {u.url.String()}, 53 "format": {"json"}, 54 }.Encode() 55 56 return oembedURL, nil 57 } 58 59 func (u OEmbedUnfurler) Unfurl() (*common.LinkPreview, error) { 60 preview := newDefaultLinkPreview(u.url) 61 preview.Type = protobuf.UnfurledLink_LINK 62 63 oembedURL, err := u.newOEmbedURL() 64 if err != nil { 65 return preview, err 66 } 67 68 headers := map[string]string{ 69 "accept": headerAcceptJSON, 70 "accept-language": headerAcceptLanguage, 71 "user-agent": headerUserAgent, 72 } 73 oembedBytes, err := fetchBody(u.logger, u.httpClient, oembedURL.String(), headers) 74 if err != nil { 75 return preview, err 76 } 77 78 var oembedResponse OEmbedResponse 79 if err != nil { 80 return preview, err 81 } 82 err = json.Unmarshal(oembedBytes, &oembedResponse) 83 if err != nil { 84 return preview, err 85 } 86 87 if oembedResponse.Title == "" { 88 return preview, fmt.Errorf("missing required title in oEmbed response") 89 } 90 91 preview.Title = oembedResponse.Title 92 return preview, nil 93 }