(ctx context.Context, urlStr string)
| 691 | return "", fmt.Errorf("failed to decrypt: %w", err) |
| 692 | } |
| 693 | |
| 694 | return string(plaintext), nil |
| 695 | } |
| 696 | |
| 697 | func extractFirstURL(text string) string { |
| 698 | match := urlRegex.FindString(text) |
| 699 | if match == "" { |
| 700 | return "" |
| 701 | } |
| 702 | |
| 703 | return match |
| 704 | } |
| 705 | func fetchOpenGraphData(ctx context.Context, urlStr string) openGraphResult { |
| 706 | pageData, _, err := fetchURLBytes(ctx, urlStr, openGraphPageMaxBytes) |
| 707 | if err != nil { |
| 708 | log.Warn().Err(err).Str("url", urlStr).Msg("Failed to fetch URL for Open Graph data") |
| 709 | return openGraphResult{} |
| 710 | } |
| 711 | |
| 712 | doc, err := goquery.NewDocumentFromReader(bytes.NewReader(pageData)) |
| 713 | if err != nil { |
| 714 | log.Warn().Err(err).Str("url", urlStr).Msg("Failed to parse HTML for Open Graph data") |
| 715 | return openGraphResult{} |
| 716 | } |
| 717 | |
| 718 | title := doc.Find(`meta[property="og:title"]`).AttrOr("content", "") |
| 719 | if title == "" { |
| 720 | title = strings.TrimSpace(doc.Find("title").Text()) |
| 721 | } |
| 722 | |
| 723 | description := doc.Find(`meta[property="og:description"]`).AttrOr("content", "") |
| 724 | if description == "" { |
| 725 | description = doc.Find(`meta[name="description"]`).AttrOr("content", "") |
| 726 | } |
| 727 | |
| 728 | var imageURLStr string |
| 729 | selectors := []struct { |
| 730 | selector string |
| 731 | attr string |
| 732 | }{ |
| 733 | {`meta[property="og:image"]`, "content"}, |
| 734 | {`meta[property="twitter:image"]`, "content"}, |
| 735 | {`link[rel="apple-touch-icon"]`, "href"}, |
| 736 | {`link[rel="icon"]`, "href"}, |
| 737 | } |
| 738 | |
| 739 | for _, s := range selectors { |
| 740 | imageURLStr, _ = doc.Find(s.selector).Attr(s.attr) |
| 741 | if imageURLStr != "" { |
| 742 | break |
| 743 | } |
| 744 | } |
| 745 |
no test coverage detected