#include "../../../plugins/utils/EpisodeNameParser.hpp" namespace QuickMedia { static bool has_season_in_name(std::string_view episode_name) { size_t sep_count = 0; size_t index = 0; while(true) { size_t next_index = episode_name.find(" - ", index); if(next_index == std::string_view::npos) break; index = next_index + 3; ++sep_count; } return sep_count >= 2; } static bool is_whitespace(char c) { return c == ' ' || c == '\n' || c == '\t' || c == '\v'; } static std::string_view strip_left(std::string_view str) { size_t i = 0; for(; i < str.size(); ++i) { if(!is_whitespace(str[i])) break; } return str.substr(i); } static std::string_view strip_right(std::string_view str) { long i = (long)str.size() - 1; for(; i >= 0; --i) { if(!is_whitespace(str[i])) break; } return str.substr(0, i + 1); } static std::string_view episode_name_extract_group(std::string_view &episode_name) { episode_name = strip_left(episode_name); if(episode_name[0] == '[') { size_t group_end_index = episode_name.find(']', 1); if(group_end_index == std::string_view::npos) return {}; std::string_view group = episode_name.substr(1, group_end_index - 1); episode_name.remove_prefix(group_end_index + 1); return group; } return {}; } static std::string_view episode_name_extract_anime(std::string_view &episode_name) { episode_name = strip_left(episode_name); size_t episode_or_season_sep_index = episode_name.find(" - "); if(episode_or_season_sep_index == std::string_view::npos) episode_or_season_sep_index = episode_name.size(); std::string_view anime = episode_name.substr(0, episode_or_season_sep_index); anime = strip_right(anime); if(episode_or_season_sep_index + 3 > episode_name.size()) episode_name = {}; else episode_name.remove_prefix(episode_or_season_sep_index + 3); return anime; } static std::string_view episode_name_extract_season(std::string_view &episode_name) { return episode_name_extract_anime(episode_name); } static bool is_real_num(char c) { return (c >= '0' && c <= '9') || c == '.'; } static std::string_view episode_name_extract_episode(std::string_view &episode_name) { episode_name = strip_left(episode_name); size_t i = 0; for(; i < episode_name.size(); ++i) { if(!is_real_num(episode_name[i])) break; } if(i == 0) return {}; std::string_view episode = episode_name.substr(0, i); episode_name.remove_prefix(i + 1); return episode; } static bool ends_with(std::string_view str, std::string_view substr) { return str.size() >= substr.size() && str.substr(str.size() - substr.size()) == substr; } std::optional episode_name_extract_parts(std::string_view episode_name) { EpisodeNameParts name_parts; const bool has_season = 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(episode_name.find("480p") != std::string_view::npos) name_parts.resolution = "480p"; else if(episode_name.find("720p") != std::string_view::npos) name_parts.resolution = "720p"; 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"; else if(episode_name.find("1280x720") != std::string_view::npos) name_parts.resolution = "1280x720"; else if(episode_name.find("1920x1080") != std::string_view::npos) name_parts.resolution = "1920x1080"; else if(episode_name.find("3840x2160") != std::string_view::npos) name_parts.resolution = "3840x2160"; if(ends_with(episode_name, ".mkv")) name_parts.file_ext = ".mkv"; else if(ends_with(episode_name, ".mp4")) name_parts.file_ext = ".mp4"; else if(ends_with(episode_name, ".avi")) name_parts.file_ext = ".avi"; else if(ends_with(episode_name, ".webm")) name_parts.file_ext = ".webm"; else if(ends_with(episode_name, ".wmv")) name_parts.file_ext = ".wmv"; else if(ends_with(episode_name, ".mp3")) name_parts.file_ext = ".mp3"; else if(ends_with(episode_name, ".flac")) name_parts.file_ext = ".flac"; else if(ends_with(episode_name, ".opus")) name_parts.file_ext = ".opus"; else if(ends_with(episode_name, ".wav")) name_parts.file_ext = ".wav"; else if(ends_with(episode_name, ".ogg")) name_parts.file_ext = ".ogg"; return name_parts; } }