package protocol import ( "bytes" "fmt" "io/ioutil" "net/http" neturl "net/url" "github.com/keighl/metabolize" "go.uber.org/zap" "github.com/status-im/status-go/images" "github.com/status-im/status-go/protocol/common" "github.com/status-im/status-go/protocol/protobuf" ) type OpenGraphMetadata struct { Title string `json:"title" meta:"og:title"` Description string `json:"description" meta:"og:description"` ThumbnailURL string `json:"thumbnailUrl" meta:"og:image"` } // OpenGraphUnfurler should be preferred over OEmbedUnfurler because oEmbed // gives back a JSON response with a "html" field that's supposed to be embedded // in an iframe (hardly useful for existing Status' clients). type OpenGraphUnfurler struct { url *neturl.URL logger *zap.Logger httpClient *http.Client } func NewOpenGraphUnfurler(URL *neturl.URL, logger *zap.Logger, httpClient *http.Client) *OpenGraphUnfurler { return &OpenGraphUnfurler{ url: URL, logger: logger, httpClient: httpClient, } } func (u *OpenGraphUnfurler) Unfurl() (*common.LinkPreview, error) { preview := newDefaultLinkPreview(u.url) preview.Type = protobuf.UnfurledLink_LINK headers := map[string]string{ "accept": headerAcceptText, "accept-language": headerAcceptLanguage, "user-agent": headerUserAgent, } bodyBytes, err := fetchBody(u.logger, u.httpClient, u.url.String(), headers) if err != nil { return preview, err } var ogMetadata OpenGraphMetadata err = metabolize.Metabolize(ioutil.NopCloser(bytes.NewBuffer(bodyBytes)), &ogMetadata) if err != nil { return preview, fmt.Errorf("failed to parse OpenGraph data") } // There are URLs like https://wikipedia.org/ that don't have an OpenGraph // title tag, but article pages do. In the future, we can fallback to the // website's title by using the