Support flix collections

This commit is contained in:
2025-12-08 20:33:13 -08:00
parent c2fb43de30
commit dd2cf5c942
15 changed files with 277 additions and 137 deletions
+5 -4
View File
@@ -215,18 +215,19 @@ impl Scanner {
for await dir in ReadDirStream::new(dirs) {
match dir {
Ok(dir) => {
let path = dir.path();
let filetype = match dir.file_type().await {
Ok(filetype) => filetype,
Err(err) => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::FileType(err)),
};
continue;
}
};
let path = dir.path();
if filetype.is_dir() {
subdirs_to_scan.push(path);
continue;
@@ -236,7 +237,7 @@ impl Scanner {
is_image_extension!() => {
if poster_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicatePosterFile),
};
continue;
@@ -248,7 +249,7 @@ impl Scanner {
}
Some(_) | None => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedFile),
};
}
+7 -6
View File
@@ -60,11 +60,13 @@ impl Scanner {
for await dir in ReadDirStream::new(dirs) {
match dir {
Ok(dir) => {
let path = dir.path();
let filetype = match dir.file_type().await {
Ok(filetype) => filetype,
Err(err) => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::FileType(err)),
};
continue;
@@ -72,18 +74,17 @@ impl Scanner {
};
if !filetype.is_file() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedNonFile),
};
continue;
}
let path = dir.path();
match path.extension().and_then(OsStr::to_str) {
is_media_extension!() => {
if media_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicateMediaFile),
};
continue;
@@ -97,7 +98,7 @@ impl Scanner {
is_image_extension!() => {
if poster_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicatePosterFile),
};
continue;
@@ -109,7 +110,7 @@ impl Scanner {
}
Some(_) | None => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedFile),
};
}
+6 -6
View File
@@ -211,7 +211,7 @@ impl Scanner {
}
let media_folder_re = MEDIA_FOLDER_REGEX.get_or_init(|| {
Regex::new(r"^[[[:alnum:]] -]+ \([[:digit:]]+\) \[[[:digit:]]+\]$")
Regex::new(r"^[[[:alnum:]]' -]+ \([[:digit:]]+\) \[[[:digit:]]+\]$")
.unwrap_or_else(|err| panic!("regex is invalid: {err}"))
});
let season_folder_re = SEASON_FOLDER_REGEX.get_or_init(|| {
@@ -257,11 +257,13 @@ impl Scanner {
for await dir in ReadDirStream::new(dirs) {
match dir {
Ok(dir) => {
let path = dir.path();
let filetype = match dir.file_type().await {
Ok(filetype) => filetype,
Err(err) => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::FileType(err)),
};
continue;
@@ -271,11 +273,9 @@ impl Scanner {
continue;
}
let dir_path = dir.path();
let Some(folder_name) = dir_path.file_name().and_then(OsStr::to_str)
else {
let Some(folder_name) = path.file_name().and_then(OsStr::to_str) else {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedFolder),
};
continue;
+7 -6
View File
@@ -56,11 +56,13 @@ impl Scanner {
for await dir in ReadDirStream::new(dirs) {
match dir {
Ok(dir) => {
let path = dir.path();
let filetype = match dir.file_type().await {
Ok(filetype) => filetype,
Err(err) => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::FileType(err)),
};
continue;
@@ -68,18 +70,17 @@ impl Scanner {
};
if !filetype.is_file() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedNonFile),
};
continue;
}
let path = dir.path();
match path.extension().and_then(OsStr::to_str) {
is_media_extension!() => {
if media_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicateMediaFile),
};
continue;
@@ -93,7 +94,7 @@ impl Scanner {
is_image_extension!() => {
if poster_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicatePosterFile),
};
continue;
@@ -105,7 +106,7 @@ impl Scanner {
}
Some(_) | None => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedFile),
};
}
+12 -11
View File
@@ -89,18 +89,19 @@ impl Scanner {
for await dir in ReadDirStream::new(dirs) {
match dir {
Ok(dir) => {
let path = dir.path();
let filetype = match dir.file_type().await {
Ok(filetype) => filetype,
Err(err) => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::FileType(err)),
};
continue;
}
};
let path = dir.path();
if filetype.is_dir() {
episode_dirs_to_scan.push(path);
continue;
@@ -110,7 +111,7 @@ impl Scanner {
is_image_extension!() => {
if poster_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicatePosterFile),
};
continue;
@@ -122,7 +123,7 @@ impl Scanner {
}
Some(_) | None => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedFile),
};
}
@@ -149,7 +150,7 @@ impl Scanner {
for episode_dir in episode_dirs_to_scan {
let Some(episode_dir_name) = episode_dir.file_name().and_then(OsStr::to_str) else {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
@@ -157,14 +158,14 @@ impl Scanner {
let Some((_, s_e_str)) = episode_dir_name.split_once('S') else {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
};
let Some((s_str, e_str)) = s_e_str.split_once('E') else {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
@@ -172,14 +173,14 @@ impl Scanner {
let Ok(season_number) = s_str.parse::<SeasonNumber>() else {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
};
if season_number != season {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::Inconsistent),
};
continue;
@@ -191,14 +192,14 @@ impl Scanner {
.collect::<Result<Vec<_>, _>>()
else {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
};
let Ok(episode_numbers) = EpisodeNumbers::try_from(episode_numbers.as_ref()) else {
yield Item {
path: path.to_owned(),
path: episode_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
+7 -6
View File
@@ -107,18 +107,19 @@ impl Scanner {
for await dir in ReadDirStream::new(dirs) {
match dir {
Ok(dir) => {
let path = dir.path();
let filetype = match dir.file_type().await {
Ok(filetype) => filetype,
Err(err) => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::FileType(err)),
};
continue;
}
};
let path = dir.path();
if filetype.is_dir() {
season_dirs_to_scan.push(path);
continue;
@@ -128,7 +129,7 @@ impl Scanner {
is_image_extension!() => {
if poster_file_name.is_some() {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::DuplicatePosterFile),
};
continue;
@@ -140,7 +141,7 @@ impl Scanner {
}
Some(_) | None => {
yield Item {
path: path.to_owned(),
path,
event: Err(Error::UnexpectedFile),
};
}
@@ -167,7 +168,7 @@ impl Scanner {
for season_dir in season_dirs_to_scan {
let Some(season_dir_name) = season_dir.file_name().and_then(OsStr::to_str) else {
yield Item {
path: path.to_owned(),
path: season_dir,
event: Err(Error::UnexpectedFolder),
};
continue;
@@ -178,7 +179,7 @@ impl Scanner {
.map(|(_, s)| s.parse::<SeasonNumber>())
else {
yield Item {
path: path.to_owned(),
path: season_dir,
event: Err(Error::UnexpectedFolder),
};
continue;