#include #include #ifdef _WIN32 #include #include #include #include #include #endif #ifndef GUI #include "filesystem.hpp" #include #include #include #endif #include "functions.hpp" #include "tv_rename.hpp" #ifdef _WIN32 constexpr const char_t *dir_divider = L"\\"; #define cout std::wcout #define cerr std::wcerr #define cin std::wcin #else constexpr const char_t *dir_divider = "/"; #define cout std::cout #define cerr std::cerr #define cin std::cin #define TEXT( a ) a #endif // get names for all episodes for a given season std::vector< string > parseEpisodeNames( const string &season_code, const string &language ) { std::vector< string > episodes; size_t pos = 0; while ( true ) { pos = season_code.find( TEXT( "ge=\"" ) + language + TEXT( "\" " ), pos ); if ( pos != string::npos ) { if ( language == TEXT( "en" ) ) pos += 17; else pos += 29; while ( iswspace( season_code[pos] ) ) pos++; auto end = season_code.find( TEXT( "<" ), pos ); end--; while ( iswspace( season_code[end] ) ) end--; end++; episodes.push_back( season_code.substr( pos, end - pos ) ); } else { break; } } return episodes; } std::vector< std::pair< string, std::pair< string, string > > > getRenamedFiles( const string &show, int season, string url, const string &language, const string &pattern, const bool &linux, Curl &c, const std::set< string > &files ) { #ifdef _WIN32 auto season_num = std::to_wstring( season ); #else auto season_num = std::to_string( season ); #endif url += TEXT( "/seasons/" ); url += season_num; // get source code of season's page auto season_code = c.execute( url ); // remove newlines season_code.erase( std::remove_if( season_code.begin(), season_code.end(), []( char x ) { return x == '\r' || x == '\n'; } ), season_code.end() ); // first 900 chars or so are useless to us season_code = season_code.substr( 900 ); // get only the episode names auto pos = season_code.find( "\"translations\"" ); if ( pos != string::npos ) { season_code = season_code.substr( pos ); pos = season_code.find( "" ); if ( pos != string::npos ) season_code = season_code.substr( 0, pos ); else return {}; } else { return {}; } #ifdef _WIN32 auto episodes = parseEpisodeNames( utf8_to_wstring( season_code ), language ); #else auto episodes = parseEpisodeNames( season_code, language ); #endif if ( episodes.empty() ) return {}; if ( files.empty() ) return {}; std::vector< std::pair< string, std::pair< string, string > > > renamed_files; for ( const auto &x : files ) { auto last = x.find_last_of( dir_divider ); string og_name; string dir; if ( last == string::npos ) { og_name = x; dir = TEXT( "." ); } else { og_name = x.substr( last + 1 ); dir = x.substr( 0, last ); } unsigned long num; // get file's episode number if ( searchSpecificSeason( x.c_str(), pos, season_num ) ) { num = std::stoi( x.c_str() + pos ); } else { continue; } num -= 1; if ( num < episodes.size() ) { auto pos = og_name.find_last_of( TEXT( "." ) ); // get desired filename auto name = compilePattern( pattern, season, num + 1, og_name.substr( 0, pos ), episodes[num], show ) + og_name.substr( pos ); // replace '/' with '|' for ( size_t i = 0; i < name.size(); i++ ) { if ( name[i] == '/' ) { name[i] = '|'; } } // replace characters illegal in windows if desired if ( !linux ) { name.erase( std::remove_if( name.begin(), name.end(), []( char_t x ) { return x == '?' || x == '"' || x == '\\' || x == '*'; } ), name.end() ); size_t max{ name.size() }; for ( size_t i = 0; i < max; i++ ) { if ( name[i] == '|' ) { name[i] = '-'; } else if ( name[i] == '<' ) { name[i] = 'i'; name.insert( i + 1, TEXT( "s less than" ) ); max += 11; } else if ( name[i] == '>' ) { name[i] = 'i'; name.insert( i + 1, TEXT( "s more than" ) ); max += 11; } else if ( name[i] == ':' ) { name[i] = ' '; name.insert( i + 1, 1, '-' ); max++; } } for ( size_t i = 0; i < max; i++ ) { if ( name[i] == ' ' && name[i + 1] == ' ' ) { name.erase( i, 1 ); max--; i--; } } } renamed_files.emplace_back( dir, std::pair< string, string >( og_name, name ) ); } } return renamed_files; } #ifndef GUI void singleSeason( const string &path, string &show, int season, string url, const string &language, const string &pattern, const bool &linux, const bool &trust, Curl &c, std::set< string > const *files_ptr, bool print ) { if ( url.empty() ) url = getDefUrl( show, language, c ); std::set< string > *found_files = nullptr; if ( files_ptr == nullptr ) { found_files = new std::set< string >; findSeason( *found_files, season, path ); files_ptr = found_files; } auto renamed_files = getRenamedFiles( show, season, std::move( url ), language, pattern, linux, c, *files_ptr ); if ( print ) { for ( auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed ) { cout << renamed->second.first << " --> " << renamed->second.second << std::endl; } if ( !trust ) { cout << "Does this seem ok? (y/n) "; string response; cin >> response; cin.clear(); cin.ignore( 1, '\n' ); if ( response[0] != 'y' && response[0] != 'Y' ) return; } } for ( auto renamed = renamed_files.begin(); renamed != renamed_files.end(); ++renamed ) { FSLib::rename( renamed->first + dir_divider + renamed->second.first, renamed->first + dir_divider + renamed->second.second ); } if ( found_files != nullptr ) { delete found_files; } } void multipleSeasons( const string &path, string &show, const std::map< int, std::set< string > > &seasons, const string &language, const string &pattern, const bool &linux, const bool &trust, Curl &c ) { auto url = getDefUrl( show, language, c ); for ( const auto &x : seasons ) { singleSeason( path, show, x.first, url, language, pattern, linux, trust, c, &x.second ); } } void multipleSeasons( const string &path, string &show, const std::set< int > seasons, const string &language, const string &pattern, const bool &linux, const bool &trust, Curl &c ) { std::map< int, std::set< string > > season_map; findSeasons( season_map, path, seasons ); multipleSeasons( path, show, season_map, language, pattern, linux, trust, c ); } void allSeasons( const string &path, string &show, const string &language, const string &pattern, const bool &linux, const bool &trust, Curl &c ) { std::map< int, std::set< string > > seasons; // get all season number from this directory and subdirectories iterateFS( seasons, path ); multipleSeasons( path, show, seasons, language, pattern, linux, trust, c ); } #endif