pub use zantetsu_core::error::{Result, ZantetsuError};
pub use zantetsu_core::parser::{HeuristicParser, NeuralParser};
pub use zantetsu_core::scoring::{QualityProfile, QualityScores};
pub use zantetsu_core::types::{
AudioCodec, EpisodeSpec, MediaSource, ParseMode, ParseResult, Resolution, VideoCodec,
};
pub use zantetsu_vecdb::{
AnimeIds, AnimeTitleMatch, MatchProvider, MatchSource, MatchResult, MatcherError,
TitleMatcher, default_kitsu_dump_dir,
};
pub struct Zantetsu {
heuristic: HeuristicParser,
neural: Option<NeuralParser>,
}
impl Zantetsu {
pub fn new() -> Result<Self> {
let heuristic = HeuristicParser::new()?;
let neural = NeuralParser::new().ok();
Ok(Self { heuristic, neural })
}
pub fn parse(&self, input: &str) -> Result<ParseResult> {
let heuristic_result = self.heuristic.parse(input)?;
if heuristic_result.confidence >= 0.8 {
return Ok(heuristic_result);
}
if let Some(ref neural) = self.neural {
if let Ok(neural_result) = neural.parse(input) {
if neural_result.confidence > heuristic_result.confidence {
return Ok(neural_result);
}
}
}
Ok(heuristic_result)
}
pub fn parse_heuristic(&self, input: &str) -> Result<ParseResult> {
self.heuristic.parse(input)
}
pub fn parse_neural(&self, input: &str) -> Result<ParseResult> {
match &self.neural {
Some(neural) => neural.parse(input),
None => Err(ZantetsuError::NeuralParser(
"Neural parser not available".into(),
)),
}
}
pub fn score(&self, result: &ParseResult, _profile: &QualityProfile) -> QualityScores {
QualityScores::from_metadata(
result.resolution,
result.video_codec,
result.audio_codec,
result.source,
result.confidence,
)
}
pub fn has_neural_parser(&self) -> bool {
self.neural.is_some()
}
}
impl Default for Zantetsu {
fn default() -> Self {
Self::new().expect("Failed to create Zantetsu engine")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_standard() {
let engine = Zantetsu::new().unwrap();
let result = engine
.parse("[SubsPlease] Cowboy Bebop - 01 [1080p][HEVC].mkv")
.unwrap();
assert_eq!(result.group.as_deref(), Some("SubsPlease"));
assert_eq!(result.title.as_deref(), Some("Cowboy Bebop"));
assert_eq!(result.episode, Some(EpisodeSpec::Single(1)));
}
#[test]
fn test_parse_empty_input() {
let engine = Zantetsu::new().unwrap();
let result = engine.parse("");
assert!(result.is_err());
}
#[test]
fn test_heuristic_only() {
let engine = Zantetsu::new().unwrap();
let result = engine.parse_heuristic("[Erai-raws] One Piece - 1071 [720p].mkv");
assert!(result.is_ok());
}
}