video_url_validator/
lib.rs

1//! # Video URL Validator
2//!
3//! A Rust crate for validating video URLs from popular platforms including:
4//! - YouTube
5//! - Facebook
6//! - Vimeo
7//! - DailyMotion
8//! - Wistia
9//!
10//! ## Example
11//!
12//! ```rust
13//! use video_url_validator::VideoUrlValidator;
14//!
15//! let validator = VideoUrlValidator::new();
16//!
17//! // Validate YouTube URL
18//! assert!(validator.validate_youtube_video_url("https://youtube.com/watch?v=23433"));
19//!
20//! // Validate any supported platform
21//! assert!(validator.is_valid_video_url("https://vimeo.com/12343432"));
22//! `
23
24pub mod error;
25pub mod utils;
26
27pub use error::ValidationError;
28pub use utils::*;
29
30use regex::Regex;
31use std::collections::HashMap;
32
33/// Supported video platforms
34#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub enum VideoPlatform {
36    YouTube,
37    Facebook,
38    Vimeo,
39    DailyMotion,
40    Wistia,
41}
42
43impl VideoPlatform {
44    /// Get the platform name as a string
45    pub fn as_str(&self) -> &'static str {
46        match self {
47            VideoPlatform::YouTube => "YouTube",
48            VideoPlatform::Facebook => "Facebook",
49            VideoPlatform::Vimeo => "Vimeo",
50            VideoPlatform::DailyMotion => "DailyMotion",
51            VideoPlatform::Wistia => "Wistia",
52        }
53    }
54}
55
56/// Main validator struct for video URLs
57pub struct VideoUrlValidator {
58    patterns: HashMap<VideoPlatform, Regex>,
59}
60
61impl VideoUrlValidator {
62    /// Create a new VideoUrlValidator instance
63    pub fn new() -> Self {
64        let mut patterns = HashMap::new();
65
66        // YouTube patterns - supports multiple URL formats
67        let youtube_pattern = Regex::new(
68            r"^https?://(www\.)?(youtube\.com/(watch\?v=|embed/|v/)|youtu\.be/)[\w-]+(&[\w=&-]*)?$",
69        )
70        .expect("Invalid YouTube regex pattern");
71        patterns.insert(VideoPlatform::YouTube, youtube_pattern);
72
73        // Facebook video patterns
74        let facebook_pattern = Regex::new(
75            r"^https?://(www\.)?facebook\.com/(.*/)?(video\.php\?v=|videos/)[\d]+/?(\?.*)?$",
76        )
77        .expect("Invalid Facebook regex pattern");
78        patterns.insert(VideoPlatform::Facebook, facebook_pattern);
79
80        // Vimeo patterns
81        let vimeo_pattern = Regex::new(r"^https?://(www\.)?vimeo\.com/[\d]+/?(\?.*)?$")
82            .expect("Invalid Vimeo regex pattern");
83        patterns.insert(VideoPlatform::Vimeo, vimeo_pattern);
84
85        // DailyMotion patterns
86        let dailymotion_pattern =
87            Regex::new(r"^https?://(www\.)?(dailymotion\.com/video/|dai\.ly/)[\w-]+/?(\?.*)?$")
88                .expect("Invalid DailyMotion regex pattern");
89        patterns.insert(VideoPlatform::DailyMotion, dailymotion_pattern);
90
91        // Wistia patterns
92        let wistia_pattern =
93            Regex::new(r"^https?://([^.]+\.)?wistia\.com/(medias|embed)/[\w-]+/?(\?.*)?$")
94                .expect("Invalid Wistia regex pattern");
95        patterns.insert(VideoPlatform::Wistia, wistia_pattern);
96
97        Self { patterns }
98    }
99
100    /// Validate a YouTube video URL
101    pub fn validate_youtube_video_url(&self, url: &str) -> bool {
102        self.patterns
103            .get(&VideoPlatform::YouTube)
104            .map(|regex| regex.is_match(url))
105            .unwrap_or(false)
106    }
107
108    /// Validate a Facebook video URL
109    pub fn validate_facebook_video_url(&self, url: &str) -> bool {
110        self.patterns
111            .get(&VideoPlatform::Facebook)
112            .map(|regex| regex.is_match(url))
113            .unwrap_or(false)
114    }
115
116    /// Validate a Vimeo video URL
117    pub fn validate_vimeo_video_url(&self, url: &str) -> bool {
118        self.patterns
119            .get(&VideoPlatform::Vimeo)
120            .map(|regex| regex.is_match(url))
121            .unwrap_or(false)
122    }
123
124    /// Validate a DailyMotion video URL
125    pub fn validate_dailymotion_video_url(&self, url: &str) -> bool {
126        self.patterns
127            .get(&VideoPlatform::DailyMotion)
128            .map(|regex| regex.is_match(url))
129            .unwrap_or(false)
130    }
131
132    /// Validate a Wistia video URL
133    pub fn validate_wistia_video_url(&self, url: &str) -> bool {
134        self.patterns
135            .get(&VideoPlatform::Wistia)
136            .map(|regex| regex.is_match(url))
137            .unwrap_or(false)
138    }
139
140    /// Validate any video URL and return the detected platform
141    pub fn validate_video_url(&self, url: &str) -> Option<VideoPlatform> {
142        for (platform, regex) in &self.patterns {
143            if regex.is_match(url) {
144                return Some(platform.clone());
145            }
146        }
147        None
148    }
149
150    /// Check if a URL is a valid video URL from any supported platform
151    pub fn is_valid_video_url(&self, url: &str) -> bool {
152        self.validate_video_url(url).is_some()
153    }
154
155    /// Get all supported platforms
156    pub fn supported_platforms(&self) -> Vec<VideoPlatform> {
157        self.patterns.keys().cloned().collect()
158    }
159
160    /// Validate multiple URLs at once
161    pub fn validate_multiple(&self, urls: &[&str]) -> Vec<(String, Option<VideoPlatform>)> {
162        urls.iter()
163            .map(|url| (url.to_string(), self.validate_video_url(url)))
164            .collect()
165    }
166}
167
168impl Default for VideoUrlValidator {
169    fn default() -> Self {
170        Self::new()
171    }
172}