From c596acb2be9ec196616f6134c95d80db4e866868 Mon Sep 17 00:00:00 2001 From: zvon Date: Wed, 15 Jan 2020 22:20:44 +0100 Subject: [PATCH] TV_Rename: refactor --- tv_rename.cpp | 218 ++++++++++++++++++++++++++------------------------ tv_rename.hpp | 22 +++-- 2 files changed, 130 insertions(+), 110 deletions(-) diff --git a/tv_rename.cpp b/tv_rename.cpp index 198c21c..f333834 100644 --- a/tv_rename.cpp +++ b/tv_rename.cpp @@ -1,17 +1,12 @@ #include #include -#ifdef _WIN32 - -#include -#include -#include -#include -#include - -#endif - #include "filesystem.hpp" +#include "functions.hpp" +#include "tv_rename.hpp" + +#include "json.hpp" +using json = nlohmann::json; #ifndef GUI @@ -21,20 +16,22 @@ #endif -#include "functions.hpp" -#include "tv_rename.hpp" - -#include "json.hpp" -using json = nlohmann::json; - #ifdef _WIN32 +#include +#include +#include +#include +#include + constexpr const char_t *dir_divider = L"\\"; #define cout std::wcout #define cerr std::wcerr #define cin std::wcin +#define toString( a ) utf8_to_wstring( a ) + #else constexpr const char_t *dir_divider = "/"; @@ -44,22 +41,24 @@ constexpr const char_t *dir_divider = "/"; #define cin std::cin #define TEXT( a ) a +#define toString( a ) a #endif + std::string api_token = ""; -Curl c; +Request r; std::vector< std::pair< string, string > > searchShow( const string &show, const string &language ) { - c.addHeader( "Accept: application/json" ); - c.addHeader( "Authorization: Bearer " + api_token ); - c.addHeader( "Accept-Language: " + language ); + r.addHeader( TEXT( "Accept: application/json" ) ); + r.addHeader( TEXT( "Authorization: Bearer " ) + api_token ); + r.addHeader( TEXT( "Accept-Language: " ) + language ); auto encoded_show = encodeUrl( show ); auto j = json::parse( - c.get( "https://api.thetvdb.com/search/series?name=" + encoded_show ) ); + r.get( TEXT( "/search/series?name=" ) + encoded_show ) ); std::vector< json > results; if( j["data"].is_array() ) { @@ -73,10 +72,11 @@ searchShow( const string &show, const string &language ) { // find all possible shows for ( auto &x : results ) { - ret.emplace_back( x["seriesName"].get< string >(), - std::to_string( x["id"].get< int >() ) ); + auto show = toString( x["seriesName"].get< std::string >() ); + auto id = toString( std::to_string( x["id"].get< int >() ) ); + ret.emplace_back( show, id ); } - c.clearHeader(); + r.clearHeader(); return ret; } @@ -95,31 +95,33 @@ string getShowId( string &show, const string &language ) { } string showNameFromId( const string &id, const string &language ) { - c.addHeader( "Accept: application/json" ); - c.addHeader( "Authorization: Bearer " + api_token ); - c.addHeader( "Accept-Language: " + language ); + r.addHeader( TEXT( "Accept: application/json" ) ); + r.addHeader( TEXT( "Authorization: Bearer " ) + api_token ); + r.addHeader( TEXT( "Accept-Language: " ) + language ); - auto j = json::parse( c.get( "https://api.thetvdb.com/series/" + id ) ); + auto j = json::parse( r.get( TEXT( "/series/" ) + id ) ); - return j["data"].get< json >()["seriesName"].get< string >(); + // TODO check if got json + std::string show = j["data"].get< json >()["seriesName"].get< std::string >(); + return toString( show ); } // get names for all episodes for a given season std::vector< string > getEpisodeNames( const string &id, const string &season, const string &language, bool dvd = false ) { - c.addHeader( "Accept: application/json" ); - c.addHeader( "Authorization: Bearer " + api_token ); - c.addHeader( "Accept-Language: " + language ); - string page = "1"; - string season_query = "airedSeason="; + r.addHeader( TEXT( "Accept: application/json" ) ); + r.addHeader( TEXT( "Authorization: Bearer " ) + api_token ); + r.addHeader( TEXT( "Accept-Language: " ) + language ); + string page = TEXT( "1" ); + string season_query = TEXT( "airedSeason=" ); if( dvd ) - season_query = "dvdSeason="; + season_query = TEXT( "dvdSeason=" ); std::vector< string > episodes; do { episodes.resize( episodes.size() * 2 ); - auto j = json::parse( c.get( "https://api.thetvdb.com/series/" + id + - "/episodes/query?" + season_query + season - + "&page=" + page ) ); + auto j = json::parse( r.get( TEXT( "/series/" ) + id + + TEXT( "/episodes/query?" ) + season_query + season + + TEXT( "&page=" ) + page ) ); if( j["data"].is_array() ) { auto epdata = j["data"].get< std::vector< json > >(); if( episodes.size() < epdata.size() ) @@ -131,13 +133,13 @@ std::vector< string > getEpisodeNames( const string &id, const string &season, if( index > episodes.size() ) episodes.resize( index ); index--; - episodes[index] = x["episodeName"].get< string >(); + episodes[index] = toString( x["episodeName"].get< string >() ); } else { size_t index = x["airedEpisodeNumber"].get< size_t >(); if( index > episodes.size() ) episodes.resize( index ); index--; - episodes[index] = x["episodeName"].get(); + episodes[index] = toString( x["episodeName"].get() ); } } } @@ -146,24 +148,18 @@ std::vector< string > getEpisodeNames( const string &id, const string &season, } if( j["links"]["next"].is_null() ) break; - page = std::to_string( j["links"]["next"].get< size_t >() ); + page = toString( std::to_string( j["links"]["next"].get< size_t >() ) ); } while( 1 ); - c.clearHeader(); + r.clearHeader(); return episodes; } -std::vector< std::pair< string, std::pair< string, string > > > +std::vector< std::pair< std::pair< int, string >, std::pair< string, string > > > getRenamedFiles( const string &show, int season, const string id, const string &language, const string &pattern, - const bool &linux, const std::set< string > &files, bool dvd = false ) { -#ifdef _WIN32 - auto season_num = std::to_wstring( season ); - auto episodes = - parseEpisodeNames( utf8_to_wstring( season_code ), language ); -#else - auto season_num = std::to_string( season ); + const bool &linux, const std::map< int, string > &files, bool dvd ) { + auto season_num = toString( std::to_string( season ) ); auto episodes = getEpisodeNames( id, season_num, language, dvd ); -#endif if ( episodes.empty() ) return {}; @@ -171,35 +167,27 @@ getRenamedFiles( const string &show, int season, const string id, if ( files.empty() ) return {}; - std::vector< std::pair< string, std::pair< string, string > > > + std::vector< std::pair< std::pair< int, string >, std::pair< string, string > > > renamed_files; - size_t pos = 0; for ( const auto &x : files ) { - auto last = x.find_last_of( dir_divider ); + auto last = x.second.find_last_of( dir_divider ); string og_name; string dir; if ( last == string::npos ) { - og_name = x; + og_name = x.second; dir = TEXT( "." ); } else { - og_name = x.substr( last + 1 ); - dir = x.substr( 0, last ); + og_name = x.second.substr( last + 1 ); + dir = x.second.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--; + unsigned long ep_num = x.first - 1; - if ( num < episodes.size() ) { + if ( ep_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], + auto name = compilePattern( pattern, season, x.first, + og_name.substr( 0, pos ), episodes[ep_num], show ) + og_name.substr( pos ); // replace '/' with '|' @@ -243,7 +231,7 @@ getRenamedFiles( const string &show, int season, const string id, } } renamed_files.emplace_back( - dir, std::pair< string, string >( og_name, name ) ); + std::pair< int, string >( x.first, dir ), std::pair< string, string >( og_name, name ) ); } } return renamed_files; @@ -252,16 +240,22 @@ getRenamedFiles( const string &show, int season, const string id, void singleSeason( const string &path, string &show, int season, string id, const string &language, const string &pattern, const bool &linux, const bool &trust, - std::set< string > const *files_ptr, bool print, bool dvd ) { + std::map< int, string > *files_ptr, bool print, bool dvd ) { if ( id.empty() ) id = getShowId( show, language ); - std::set< string > *found_files = nullptr; + std::map< int, std::map< int, string > > *found_files = nullptr; if ( files_ptr == nullptr ) { - found_files = new std::set< string >; - findSeason( *found_files, season, path ); - files_ptr = found_files; + found_files = new std::map< int, std::map< int, string > >; + iterateFS( *found_files, path ); + if( found_files->find( season ) != found_files->end() ) + files_ptr = &(*found_files)[season]; + } + + if( files_ptr == nullptr ) { + cerr << "Couldn't find episodes with season " << season << std::endl; + return; } auto renamed_files = getRenamedFiles( show, season, id, language, pattern, @@ -287,8 +281,11 @@ void singleSeason( const string &path, string &show, int season, string id, 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 ); + FSLib::rename( renamed->first.second + dir_divider + renamed->second.first, + renamed->first.second + dir_divider + renamed->second.second ); + if( found_files == nullptr ) { + files_ptr[0][renamed->first.first] = renamed->first.second + dir_divider + renamed->second.second; + } } if ( found_files != nullptr ) { @@ -296,46 +293,52 @@ void singleSeason( const string &path, string &show, int season, string id, } } +void singleSeason( const string &path, string &show, int season, string id, + const string &language, const string &pattern, + const size_t &flags, std::map< int, string > *files_ptr, + bool print ) { + singleSeason( path, show, season, id, language, pattern, flags & TV_LINUX, + flags & TV_TRUST, files_ptr, print, flags & TV_DVD ); +} + #ifndef GUI 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, bool dvd ) { + const std::set< int > seasons, const string &language, + const string &pattern, const size_t &flags ) { + std::map< int, std::map< int, string > > season_map; + iterateFS( season_map, path ); auto id = getShowId( show, language ); - for ( const auto &x : seasons ) { - singleSeason( path, show, x.first, id, language, pattern, linux, trust, - &x.second, dvd ); + for( auto &x : season_map ) { + if( seasons.find( x.first ) != seasons.end() ) { + singleSeason( path, show, x.first, id, language, pattern, flags & TV_LINUX, flags & TV_TRUST, + &x.second, flags & TV_DVD ); + } } } -void multipleSeasons( const string &path, string &show, - const std::set< int > seasons, const string &language, - const string &pattern, const bool &linux, - const bool &trust, bool dvd ) { - std::map< int, std::set< string > > season_map; - findSeasons( season_map, path, seasons ); - multipleSeasons( path, show, season_map, language, pattern, linux, trust, dvd ); -} - void allSeasons( const string &path, string &show, const string &language, - const string &pattern, const bool &linux, const bool &trust, bool dvd ) { - std::map< int, std::set< string > > seasons; + const string &pattern, const size_t &flags ) { + std::map< int, std::map< int, string > > seasons; // get all season number from this directory and subdirectories iterateFS( seasons, path ); - multipleSeasons( path, show, seasons, language, pattern, linux, trust, dvd ); + auto id = getShowId( show, language ); + for( auto &x : seasons ) { + singleSeason( path, show, x.first, id, language, pattern, flags & TV_LINUX, flags & TV_TRUST, + &x.second, flags & TV_DVD ); + } } std::vector< std::pair< std::string, std::string > > getLangs() { std::vector< std::pair< std::string, std::string > > langs; - c.addHeader( "Accept: application/json" ); - c.addHeader( "Authorization: Bearer " + api_token ); - auto j = json::parse( c.get( "https://api.thetvdb.com/languages" ) ); - c.clearHeader(); + r.addHeader( TEXT( "Accept: application/json" ) ); + r.addHeader( TEXT( "Authorization: Bearer " ) + api_token ); + auto j = json::parse( r.get( TEXT( "/languages" ) ) ); + r.clearHeader(); auto langs_json = j["data"].get< std::vector< json > >(); for ( auto &x : langs_json ) { - langs.emplace_back( x["abbreviation"].get< std::string >(), - x["name"].get< std::string >() ); + langs.emplace_back( toString( x["abbreviation"].get< std::string >() ), + toString( x["name"].get< std::string >() ) ); } return langs; } @@ -354,12 +357,17 @@ bool findLanguage( const char_t *language ) { } bool authenticate( const std::string &api_key ) { - c.addHeader( "Accept: application/json" ); - c.addHeader( "Content-Type: application/json" ); - auto j = json::parse( c.post( "https://api.thetvdb.com/login", +#ifdef _WIN32 + r.setServer( "api.thetvdb.com" ); +#else + r.setServer( "https://api.thetvdb.com" ); +#endif + r.addHeader( TEXT( "Accept: application/json" ) ); + r.addHeader( TEXT( "Content-Type: application/json" ) ); + auto j = json::parse( r.post( TEXT( "/login" ), "{ \"apikey\": \"" + api_key + "\" }" ) ); - api_token = j["token"].get< std::string >(); - c.clearHeader(); + api_token = toString( j["token"].get< std::string >() ); + r.clearHeader(); // TODO check return code return true; } diff --git a/tv_rename.hpp b/tv_rename.hpp index 899f2a1..05baa7c 100644 --- a/tv_rename.hpp +++ b/tv_rename.hpp @@ -1,11 +1,18 @@ #ifndef TV_RENAME_HPP #define TV_RENAME_HPP +#include #include #include #include "network.hpp" +// TV flags +#define TV_CHDIR 0x0100 +#define TV_TRUST 0x0200 +#define TV_LINUX 0x0400 +#define TV_DVD 0x0800 + #ifdef _WIN32 using string = std::wstring; @@ -18,27 +25,32 @@ using char_t = char; #endif +// TODO change files_ptr contents to new file names void singleSeason( const string &path, string &show, int season, string id, const string &language, const string &pattern, const bool &linux, const bool &trust, - std::set< string > const *files_ptr = nullptr, + std::map< int, string > *files_ptr = nullptr, bool print = true, bool dvd = false ); +void singleSeason( const string &path, string &show, int season, string id, + const string &language, const string &pattern, + const size_t &flags, std::map< int, string > *files_ptr = nullptr, + bool print = true ); + #ifdef GUI 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 ); + const bool &linux, Curl &c, const std::map< int, string > &files, bool dvd = false ); #else void multipleSeasons( const string &path, string &show, const std::set< int > seasons, const string &language, - const string &pattern, const bool &linux, - const bool &trust, bool dvd = false ); + const string &pattern, const size_t &flags ); void allSeasons( const string &path, string &show, const string &language, - const string &pattern, const bool &linux, const bool &trust, bool dvd = false ); + const string &pattern, const size_t &flags ); #endif