1use lazy_static::lazy_static;
28
29mod error;
30mod request;
31mod spec;
32
33pub use error::Error;
34pub use request::{fetch, ConsumerRequest};
35pub use spec::*;
36
37lazy_static! {
38 static ref PROVIDERS: Vec<Provider> =
39 serde_json::from_slice(include_bytes!("../providers.json"))
40 .expect("failed to load providers");
41}
42
43pub fn find_provider(url: &str) -> Option<(&Provider, &Endpoint)> {
45 PROVIDERS.iter().find_map(|p| {
46 p.endpoints
47 .iter()
48 .find(|e| e.schemes.iter().any(|s| matches_scheme(s, url)))
49 .map(|e| (p, e))
50 })
51}
52
53pub fn matches_scheme(scheme: &str, mut url: &str) -> bool {
55 let mut fragments = scheme.split('*').filter(|f| !f.is_empty()).peekable();
56
57 while let Some(fragment) = fragments.next() {
58 if !url.starts_with(fragment) {
59 return false;
60 }
61
62 url = &url[fragment.len()..];
63
64 if let Some(fragment) = fragments.peek() {
65 let Some(idx) = url.find(fragment) else {
66 return false;
67 };
68
69 url = &url[idx..];
70 }
71 }
72
73 scheme.ends_with('*') || url.is_empty()
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_twitter_provider() {
82 let url = "https://twitter.com/user/status/1640004220000000000?s=20";
83 let (provider, endpoint) = find_provider(url).unwrap();
84
85 assert_eq!(provider.provider_name, "Twitter");
86 assert_eq!(endpoint.url, "https://publish.twitter.com/oembed");
87 }
88
89 #[test]
90 fn test_youtube_provider() {
91 let url = "https://youtu.be/rAn0MId";
92 let (provider, endpoint) = find_provider(url).unwrap();
93
94 assert_eq!(provider.provider_name, "YouTube");
95 assert_eq!(endpoint.url, "https://www.youtube.com/oembed");
96 }
97
98 #[test]
99 fn test_youtube_provider_with_query() {
100 let url = "https://www.youtube.com/watch?v=rAn0MId";
101 let (provider, endpoint) = find_provider(url).unwrap();
102
103 assert_eq!(provider.provider_name, "YouTube");
104 assert_eq!(endpoint.url, "https://www.youtube.com/oembed");
105 }
106
107 #[test]
108 fn test_spotify() {
109 let url = "https://open.spotify.com/playlist/5R3Pzqu8SLyH9cw9WSXw91";
110 let (provider, endpoint) = find_provider(url).unwrap();
111
112 assert_eq!(provider.provider_name, "Spotify");
113 assert_eq!(endpoint.url, "https://open.spotify.com/oembed");
114 }
115
116 #[test]
117 fn test_invalid() {
118 let url = "https://twitter.nl/user/status/1640004220000000000?s=20";
119 assert!(find_provider(url).is_none());
120
121 let url = "https://www.youtube.com/watcx?v=test";
122 assert!(find_provider(url).is_none());
123 }
124}