use crate::episode::regexes;
pub fn validate_before_parsing(title: &str) -> bool {
if title.is_empty() {
return false;
}
let lower = title.to_ascii_lowercase();
if lower.contains("password") && lower.contains("yenc") {
return false;
}
if !title.chars().any(|c| c.is_alphanumeric()) {
return false;
}
let without_ext = remove_file_extension(title);
for re in regexes::REJECT_HASHED_REGEXES.iter() {
if re.is_match(&without_ext) {
return false;
}
}
for re in regexes::SEASON_FOLDER_REGEXES.iter() {
if re.is_match(&without_ext) {
return false;
}
}
true
}
pub fn remove_file_extension(title: &str) -> String {
const MEDIA_EXTENSIONS: &[&str] = &[
".3g2", ".3gp", ".3gp2", ".asf", ".avi", ".divx", ".flv", ".m4v", ".mk3d", ".mka", ".mkv",
".mov", ".mp4", ".mpa", ".mpeg", ".mpg", ".ogg", ".ogm", ".ogv", ".qt", ".rm", ".rmvb",
".tp", ".ts", ".vob", ".w64", ".wav", ".webm", ".wmv", ".srt", ".sub", ".idx", ".ssa",
".ass", ".nfo", ".txt", ".par2", ".nzb",
];
if let Some(m) = regexes::FILE_EXTENSION_REGEX.find(title) {
let ext = &title[m.start()..];
if MEDIA_EXTENSIONS.iter().any(|e| e.eq_ignore_ascii_case(ext)) {
return title[..m.start()].to_string();
}
}
title.to_string()
}
pub fn preprocess_title(title: &str) -> Option<String> {
if !validate_before_parsing(title) {
return None;
}
let mut release_title = if regexes::REVERSED_TITLE_REGEX.is_match(title) {
let without_ext = remove_file_extension(title);
without_ext.chars().rev().collect::<String>()
} else {
remove_file_extension(title)
};
if release_title.starts_with("@\"") {
release_title = release_title.strip_prefix("@\"").unwrap().to_string();
if release_title.ends_with('"') {
release_title.pop();
}
}
release_title = release_title.replace('【', "[").replace('】', "]");
if let Some(caps) = regexes::PRE_SUB_SPANISH_REGEX.captures(&release_title)
&& let (Some(t), Some(y), Some(info)) =
(caps.name("title"), caps.name("year"), caps.name("info"))
{
release_title = format!("{} ({}) - {} ", t.as_str(), y.as_str(), info.as_str());
}
let simple_title = regexes::SIMPLE_TITLE_REGEX
.replace_all(&release_title, "")
.to_string();
let simple_title = if let Some(m) = regexes::WEBSITE_PREFIX_REGEX.find(&simple_title) {
let matched = &simple_title[m.start()..m.end()];
let lower = matched.to_ascii_lowercase();
if lower.contains("naruto-kun.") {
simple_title
} else {
regexes::WEBSITE_PREFIX_REGEX
.replace(&simple_title, "")
.to_string()
}
} else {
simple_title
};
let simple_title = regexes::WEBSITE_POSTFIX_REGEX
.replace(&simple_title, "")
.to_string();
let simple_title = regexes::CLEAN_TORRENT_SUFFIX_REGEX
.replace(&simple_title, "")
.to_string();
let simple_title = simple_title.replace("[]", "").replace("()", "");
let simple_title = simple_title.trim().to_string();
let simple_title = if let Some(m) = regexes::CLEAN_QUALITY_BRACKETS_REGEX.find(&simple_title) {
let bracket_content = &simple_title[m.start()..];
let quality = crate::parse_quality_name(bracket_content);
if quality.quality != crate::Quality::Unknown {
simple_title[..m.start()].to_string()
} else {
simple_title
}
} else {
simple_title
};
let simple_title = expand_six_digit_airdate(&simple_title);
Some(simple_title)
}
fn expand_six_digit_airdate(title: &str) -> String {
if let Some(caps) = regexes::SIX_DIGIT_AIR_DATE_REGEX.captures(title)
&& let (Some(prefix), Some(year), Some(month), Some(day), Some(suffix)) = (
caps.name("prefix"),
caps.name("airyear"),
caps.name("airmonth"),
caps.name("airday"),
caps.name("suffix"),
)
{
let full_year = format!("20{}", year.as_str());
let replacement = format!(
"{}{}.{}.{}{}",
prefix.as_str(),
full_year,
month.as_str(),
day.as_str(),
suffix.as_str()
);
return format!(
"{}{}{}",
&title[..caps.get(0).unwrap().start()],
replacement,
&title[caps.get(0).unwrap().end()..]
);
}
title.to_string()
}
pub fn digit_boundary_ok(input: &str, start: usize, end: usize) -> bool {
let bytes = input.as_bytes();
let no_before = start == 0 || !bytes[start - 1].is_ascii_digit();
let no_after = end >= bytes.len() || !bytes[end].is_ascii_digit();
no_before && no_after
}
pub fn clean_series_title(raw: &str) -> String {
let mut title = regexes::REQUEST_INFO_REGEX.replace(raw, "").to_string();
title = title.replace(['.', '_'], " ");
title = title.trim().trim_end_matches(['-', '/']).trim().to_string();
close_trailing_year_paren(&mut title);
title
}
fn close_trailing_year_paren(title: &mut String) {
let mut rchars = title.chars().rev();
let last4: Vec<char> = rchars.by_ref().take(4).collect();
if last4.len() == 4 && last4.iter().all(|c| c.is_ascii_digit()) && rchars.next() == Some('(') {
title.push(')');
}
}