link_preview/providers/
twitter.rs

1use scraper::{Html, Selector};
2
3/// Twittet meta tags.
4pub enum TwitterMetaTag {
5    /// Title for the Twitter card
6    Title,
7    /// The card type, which will be one of “summary”, “summary_large_image”,
8    /// “app”, or “player”.
9    Card,
10    /// @username for the website used in the card footer.
11    /// This tag is not required, make sure the `Option::None` variant is handled.
12    Site,
13    /// @username for the content creator / author.
14    /// This tag is not required, make sure the `Option::None` variant is handled.
15    Creator,
16    /// Twitter Card Image
17    Image,
18    /// Card description
19    Description,
20}
21
22impl TwitterMetaTag {
23    fn str(&self) -> &str {
24        match self {
25            TwitterMetaTag::Title => "title",
26            TwitterMetaTag::Card => "card",
27            TwitterMetaTag::Site => "site",
28            TwitterMetaTag::Creator => "creator",
29            TwitterMetaTag::Image => "image",
30            TwitterMetaTag::Description => "description",
31        }
32    }
33}
34
35/// Finds the Twitter tag specified in the provided `Html` instance
36pub fn find_twitter_tag(html: &Html, tag: TwitterMetaTag) -> Option<String> {
37    let selector = Selector::parse(&format!("meta[name=\"twitter:{}\"]", tag.str())).unwrap();
38
39    if let Some(element) = html.select(&selector).next() {
40        if let Some(value) = element.value().attr("content") {
41            return Some(value.to_string());
42        }
43    }
44
45    None
46}
47
48#[cfg(test)]
49mod tests {
50    use crate::html_from_bytes;
51    use crate::tests::TWITTER_COMPLIANT_HTML;
52
53    use super::{find_twitter_tag, TwitterMetaTag};
54
55    #[test]
56    fn retrieves_card() {
57        let html = html_from_bytes(TWITTER_COMPLIANT_HTML).unwrap();
58        let value = find_twitter_tag(&html, TwitterMetaTag::Card).unwrap();
59
60        assert_eq!(value, "summary_large_image");
61    }
62
63    #[test]
64    fn retrieves_title() {
65        let html = html_from_bytes(TWITTER_COMPLIANT_HTML).unwrap();
66        let value = find_twitter_tag(&html, TwitterMetaTag::Title).unwrap();
67
68        assert_eq!(value, "SEO Strategies for a better web");
69    }
70
71    #[test]
72    fn retrieves_image() {
73        let html = html_from_bytes(TWITTER_COMPLIANT_HTML).unwrap();
74        let value = find_twitter_tag(&html, TwitterMetaTag::Image).unwrap();
75
76        assert_eq!(value, "https://linktoyourimage");
77    }
78
79    #[test]
80    fn retrieves_description() {
81        let html = html_from_bytes(TWITTER_COMPLIANT_HTML).unwrap();
82        let value = find_twitter_tag(&html, TwitterMetaTag::Description).unwrap();
83
84        assert_eq!(value, "John Appleseed tells you his secrets on SEO for a better web experience by taking advantage of OpenGraph's Tags!");
85    }
86
87    #[test]
88    fn retrieves_tweet_site_name() {
89        let html = html_from_bytes(TWITTER_COMPLIANT_HTML).unwrap();
90        let value = find_twitter_tag(&html, TwitterMetaTag::Site).unwrap();
91
92        assert_eq!(value, "@nytimes");
93    }
94
95    #[test]
96    fn retrieves_tweet_creator_username() {
97        let html = html_from_bytes(TWITTER_COMPLIANT_HTML).unwrap();
98        let value = find_twitter_tag(&html, TwitterMetaTag::Creator).unwrap();
99
100        assert_eq!(value, "@EstebanBorai");
101    }
102}