1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
//! Url parsing.
use regex::Regex;
/// Types of Crunchyroll urls, pointing to media.
#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
#[derive(Clone, Debug)]
pub enum UrlType {
/// The parsed url points to a series. Use [`crate::Series::from_id`] with the value of this
/// field to get a usable struct out of it.
Series(String),
/// The parsed url points to a movie listing. Use [`crate::MovieListing::from_id`] with the
/// value of this field to get a usable struct out of it. This kind of url might not exist in
/// Crunchyroll at all but to be api compatible it's included anyway.
MovieListing(String),
/// The parsed url points to a episode or movie. You can either try
/// [`crate::Episode::from_id`] and [`crate::Movie::from_id`] to guess if it's a episode or
/// movie (in 99.9% of the time it will be a episode, because (at the time of writing)
/// Crunchyroll has only 3 movies which are listed as movies. All other movies are listed as
/// episodes. Makes sense I know) or use [`crate::MediaCollection::from_id`]. The value of this
/// field is the id you have to use in all shown methods.
EpisodeOrMovie(String),
/// The parsed url points to a music video. Use [`crate::MusicVideo::from_id`] with the value of
/// this field to get a usable struct out of it.
MusicVideo(String),
/// The parsed url points to a music video. Use [`crate::Concert::from_id`] with the value of
/// this field to get a usable struct out of it.
Concert(String),
}
/// Extract information out of Crunchyroll urls which are pointing to media.
#[cfg_attr(docsrs, doc(cfg(feature = "parse")))]
pub fn parse_url<S: AsRef<str>>(url: S) -> Option<UrlType> {
lazy_static::lazy_static! {
static ref SERIES_REGEX: Regex = Regex::new(r"^https?://((beta|www)\.)?crunchyroll\.com/([a-zA-Z]{2}/)?(?P<type>series|movie_listing)/(?P<id>.+)/.*$").unwrap();
static ref EPISODE_REGEX: Regex = Regex::new(r"^https?://((beta|www)\.)?crunchyroll\.com/([a-zA-Z]{2}/)?watch/(?P<id>[^/]+)/[^/]*$").unwrap();
static ref MUSIC_REGEX: Regex = Regex::new(r"^https?://((beta|www)\.)?crunchyroll\.com/([a-zA-Z]{2}/)?watch/(?P<music_type>musicvideo|concert)/(?P<id>.+)/.*$").unwrap();
}
#[allow(clippy::manual_map)]
if let Some(capture) = SERIES_REGEX.captures(url.as_ref()) {
let id = capture.name("id").unwrap().as_str().to_string();
match capture.name("type").unwrap().as_str() {
"series" => Some(UrlType::Series(id)),
"movie_listing" => Some(UrlType::MovieListing(id)),
_ => unreachable!(),
}
} else if let Some(capture) = EPISODE_REGEX.captures(url.as_ref()) {
Some(UrlType::EpisodeOrMovie(
capture.name("id").unwrap().as_str().to_string(),
))
} else if let Some(capture) = MUSIC_REGEX.captures(url.as_ref()) {
match capture.name("music_type").unwrap().as_str() {
"musicvideo" => Some(UrlType::MusicVideo(
capture.name("id").unwrap().as_str().to_string(),
)),
"concert" => Some(UrlType::Concert(
capture.name("id").unwrap().as_str().to_string(),
)),
_ => unreachable!(),
}
} else {
None
}
}