From 52dfa42283541ff48cce3a6cbdf4e2e2e8567a30 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 9 Dec 2023 14:21:21 +0100 Subject: Local anime: parse SXXEXX pattern --- src/plugins/utils/EpisodeNameParser.cpp | 65 +++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/plugins/utils/EpisodeNameParser.cpp b/src/plugins/utils/EpisodeNameParser.cpp index e314953..8610ab0 100644 --- a/src/plugins/utils/EpisodeNameParser.cpp +++ b/src/plugins/utils/EpisodeNameParser.cpp @@ -1,6 +1,39 @@ #include "../../../plugins/utils/EpisodeNameParser.hpp" namespace QuickMedia { + static bool is_num(char c) { + return c >= '0' && c <= '9'; + } + + static bool char_to_num(char c) { + return c - '0'; + } + + // Finds and parses SXXEXX where X is a number, returns the index to after the pattern or std::string_view::npos + static size_t parse_season_episode_pattern(std::string_view episode_name, int *season, int *episode) { + *season = 0; + *episode = 0; + + size_t index = 0; + while(true) { + index = episode_name.find('S', index); + if(index == std::string_view::npos) + return std::string_view::npos; + + if(index + 6 >= episode_name.size()) + return std::string_view::npos; + + if(is_num(episode_name[index + 1]) && is_num(episode_name[index + 2]) && episode_name[index + 3] == 'E' + && is_num(episode_name[index + 4]) && is_num(episode_name[index + 5])) + { + *season = char_to_num(episode_name[index + 1]) * 10 + char_to_num(episode_name[index + 2]); + *episode = char_to_num(episode_name[index + 4]) * 10 + char_to_num(episode_name[index + 5]); + return index + 6; + } + ++index; + } + } + static bool has_season_in_name(std::string_view episode_name) { size_t sep_count = 0; size_t index = 0; @@ -96,20 +129,30 @@ namespace QuickMedia { } std::optional episode_name_extract_parts(std::string_view episode_name) { + const std::string_view full_episode_name = episode_name; EpisodeNameParts name_parts; - const bool has_season = has_season_in_name(episode_name); + + int season = 0; + int episode = 0; + size_t after_season_episode_pattern = parse_season_episode_pattern(episode_name, &season, &episode); + const bool has_season = after_season_episode_pattern != std::string_view::npos || has_season_in_name(episode_name); name_parts.group = episode_name_extract_group(episode_name); name_parts.anime = episode_name_extract_anime(episode_name); if(name_parts.anime.empty()) return std::nullopt; - if(has_season) - name_parts.season = episode_name_extract_season(episode_name); - - name_parts.episode = episode_name_extract_episode(episode_name); - if(name_parts.episode.empty()) - return std::nullopt; + if(after_season_episode_pattern == std::string_view::npos) { + if(has_season) + name_parts.season = episode_name_extract_season(episode_name); + + name_parts.episode = episode_name_extract_episode(episode_name); + if(name_parts.episode.empty()) + return std::nullopt; + } else { + name_parts.season = full_episode_name.substr(after_season_episode_pattern - 5, 2); + name_parts.episode = full_episode_name.substr(after_season_episode_pattern - 2, 2); + } if(episode_name.find("480p") != std::string_view::npos) name_parts.resolution = "480p"; @@ -118,13 +161,13 @@ namespace QuickMedia { else if(episode_name.find("1080p") != std::string_view::npos) name_parts.resolution = "1080p"; else if(episode_name.find("2160p") != std::string_view::npos) - name_parts.resolution = "2160p"; + name_parts.resolution = "4k"; else if(episode_name.find("1280x720") != std::string_view::npos) - name_parts.resolution = "1280x720"; + name_parts.resolution = "720p"; else if(episode_name.find("1920x1080") != std::string_view::npos) - name_parts.resolution = "1920x1080"; + name_parts.resolution = "1080p"; else if(episode_name.find("3840x2160") != std::string_view::npos) - name_parts.resolution = "3840x2160"; + name_parts.resolution = "4k"; if(ends_with(episode_name, ".mkv")) name_parts.file_ext = ".mkv"; -- cgit v1.2.3