diff --git a/functions.cpp b/functions.cpp index 52dac0c..443148c 100644 --- a/functions.cpp +++ b/functions.cpp @@ -55,6 +55,7 @@ std::wstring utf8_to_wstring( const std::string &utf8 ) { #endif // _WIN32 +// encode url so it's valid even with UTF-8 characters string encodeUrl( const string &url ) { // stolen from here - // https://stackoverflow.com/questions/154536/encode-decode-urls-in-c @@ -439,7 +440,8 @@ void addToDB( string &show, const string &path, const string &language, prepareDB(); #else void addToDB( string &show, const string &path, const string &language, - const string &id, const string &pattern, bool linux, bool dvd ) { + const string &id, const string &pattern, bool linux, bool dvd, + void *progress_ptr ) { if ( !FSLib::exists( getDBName() ) ) prepareDB( pattern ); #endif @@ -460,8 +462,8 @@ void addToDB( string &show, const string &path, const string &language, TEXT( "INSERT OR IGNORE INTO SHOWS ( TVID, SHOW, PATH, LANGUAGE, DVD ) " "VALUES ( '" ) + sanitize( id ) + TEXT( "', '" ) + sanitize( show ) + TEXT( "', '" ) + - sanitize( absolute ) + TEXT( "', '" ) + sanitize( language ) + TEXT( "', " ) + - ( dvd ? TEXT( "1" ) : TEXT( "0" ) ) + TEXT( " );" ) ); + sanitize( absolute ) + TEXT( "', '" ) + sanitize( language ) + + TEXT( "', " ) + ( dvd ? TEXT( "1" ) : TEXT( "0" ) ) + TEXT( " );" ) ); #ifdef _WIN32 string show_id = std::to_wstring( db.lastRowID() ); #else @@ -478,20 +480,20 @@ void addToDB( string &show, const string &path, const string &language, iterateFS( seasons, absolute ); auto size = seasons.size(); size_t i = 0; - cout << "Renaming" << std::endl; -#ifdef _WIN32 - cout << std::endl; -#endif + #ifndef GUI - ProgressBar::print( 0 ); + ProgressBar p; +#else + ProgressBar p( progress_ptr ); #endif + + p.print( TEXT( "Renaming" ) ); + p.print( 0 ); for ( auto &x : seasons ) { singleSeason( absolute, show, x.first, id, language, pattern, linux, true, &x.second, false, dvd ); i++; -#ifndef GUI - ProgressBar::print( ( i * 100 ) / size ); -#endif + p.print( ( i * 100 ) / size ); } #ifndef GUI cout << std::endl; @@ -499,13 +501,8 @@ void addToDB( string &show, const string &path, const string &language, size = seasons.size(); i = 0; - cout << "Adding to database" << std::endl; -#ifdef _WIN32 - cout << std::endl; -#endif -#ifndef GUI - ProgressBar::print( 0 ); -#endif + p.print( TEXT( "Adding to database" ) ); + p.print( 0 ); for ( auto &season : seasons ) { for ( auto &episode : season.second ) { db.exec( TEXT( "INSERT OR IGNORE INTO EPISODES ( SHOWID, PATH ) " @@ -514,9 +511,7 @@ void addToDB( string &show, const string &path, const string &language, TEXT( "' );" ) ); } i++; -#ifndef GUI - ProgressBar::print( ( i * 100 ) / size ); -#endif + p.print( ( i * 100 ) / size ); } #ifndef GUI cout << std::endl; @@ -554,7 +549,13 @@ void cleanUpLine() { } #endif +#ifndef GUI void refreshDB( bool linux ) { +#else +void refreshDB( bool linux, void *progress_ptr ) { +#endif + if ( !FSLib::exists( getDBName() ) ) + return; std::vector< std::unordered_map< string, string > > shows; SQLite::Database db{}; try { @@ -574,26 +575,23 @@ void refreshDB( bool linux ) { db.exec( TEXT( "SELECT PATH FROM SHOWS WHERE TVID == 'pattern';" ), pattern ); - cout << "Refreshing database" << std::endl << std::endl << std::endl; -#ifdef _WIN32 - cout << std::endl; -#endif +#ifndef GUI + ProgressBar p; + p.print( TEXT( "Refreshing database" ) ); + cout << std::endl << std::endl; +#else // GUI + ProgressBar p( progress_ptr ); +#endif // GUI + for ( auto &show : shows ) { if ( FSLib::exists( show[TEXT( "PATH" )] ) ) { cleanUpLine(); - cout << "Refreshing " << show[TEXT( "SHOW" )] << std::endl; -#ifdef _WIN32 - cout << std::endl; -#endif -#ifndef GUI - ProgressBar::print( 0 ); -#endif + p.print( TEXT( "Refreshing " ) + show[TEXT( "SHOW" )] ); + p.print( 0 ); std::map< int, std::map< int, string > > seasons; // get all season number from this directory and subdirectories iterateFS( seasons, show[TEXT( "PATH" )] ); -#ifndef GUI auto size = seasons.size(); -#endif size_t i{}; for ( auto &x : seasons ) { singleSeason( show[TEXT( "PATH" )], show[TEXT( "SHOW" )], @@ -602,27 +600,48 @@ void refreshDB( bool linux ) { &x.second, false, show[TEXT( "DVD" )] == TEXT( "1" ) ); i++; -#ifndef GUI - ProgressBar::print( ( i * 100 ) / size ); -#endif + p.print( ( i * 100 ) / size ); } + p.print( 100 ); #ifndef GUI - ProgressBar::print( 100 ); cout << std::endl; + cleanUpLine(); #endif + p.print( TEXT( "Updating " ) + show[TEXT( "SHOW" )] + + TEXT( " in database" ) ); + p.print( 0 ); + i = 0; + size_t j{}; + size_t addition = 100 / seasons.size(); for ( auto &season : seasons ) { + j = 0; + size_t smalladdition = addition / season.second.size(); for ( auto &episode : season.second ) { db.exec( TEXT( "INSERT INTO EPISODES ( SHOWID, PATH ) " "VALUES ( " ) + show[TEXT( "ID" )] + TEXT( ", '" ) + sanitize( episode.second ) + TEXT( "' );" ) ); + j++; + p.print( i * addition + j * smalladdition ); } + i++; + p.print( i * addition ); } + p.print( 100 ); +#ifndef GUI + cout << std::endl; +#endif } } } +#ifndef GUI void updateDB( bool linux ) { +#else +void updateDB( bool linux, void *progress_ptr ) { +#endif + if ( !FSLib::exists( getDBName() ) ) + return; std::vector< std::unordered_map< string, string > > shows; SQLite::Database db{}; try { @@ -640,19 +659,22 @@ void updateDB( bool linux ) { db.exec( TEXT( "SELECT PATH FROM SHOWS WHERE TVID == 'pattern';" ), pattern ); - cout << "Updating database" << std::endl << std::endl << std::endl; -#ifdef _WIN32 - cout << std::endl; +#ifndef GUI + ProgressBar p; +#else // GUI + ProgressBar p( progress_ptr ); +#endif + p.print( TEXT( "Updating database" ) ); +#ifndef GUI + cout << std::endl << std::endl; #endif for ( auto &show : shows ) { if ( !FSLib::exists( show[TEXT( "PATH" )] ) ) { continue; } cleanUpLine(); - cout << "Updating " << show[TEXT( "SHOW" )] << std::endl; -#ifdef _WIN32 - cout << std::endl; -#endif + p.print( TEXT( "Updating " ) + show[TEXT( "SHOW" )] ); + std::unordered_set< string > episodes; db.exec( TEXT( "SELECT PATH FROM EPISODES WHERE SHOWID == " ) + show[TEXT( "ID" )] + TEXT( ";" ), @@ -668,13 +690,9 @@ void updateDB( bool linux ) { } } } -#ifndef GUI - ProgressBar::print( 0 ); -#endif + p.print( 0 ); if ( !new_eps.empty() ) { -#ifndef GUI auto size = new_eps.size(); -#endif size_t i{}; for ( auto &x : new_eps ) { singleSeason( show[TEXT( "PATH" )], show[TEXT( "SHOW" )], @@ -683,9 +701,7 @@ void updateDB( bool linux ) { &x.second, false, show[TEXT( "DVD" )] == TEXT( "1" ) ); i++; -#ifndef GUI - ProgressBar::print( ( i * 100 ) / size ); -#endif + p.print( ( i * 100 ) / size ); } seasons.clear(); iterateFS( seasons, show[TEXT( "PATH" )] ); @@ -698,14 +714,16 @@ void updateDB( bool linux ) { } } } + p.print( 100 ); #ifndef GUI - ProgressBar::print( 100 ); cout << std::endl; #endif } } void changeDBPattern( const string &pattern ) { + if ( !FSLib::exists( getDBName() ) ) + return; SQLite::Database db{}; try { db.open( getDBName(), SQLite::OPEN_READWRITE ); @@ -718,6 +736,8 @@ void changeDBPattern( const string &pattern ) { } void cleanDB() { + if ( !FSLib::exists( getDBName() ) ) + return; std::vector< std::unordered_map< string, string > > shows; SQLite::Database db{}; try { @@ -754,6 +774,8 @@ void cleanDB() { } void removeFromDB( const string &path ) { + if ( !FSLib::exists( getDBName() ) ) + return; SQLite::Database db{}; try { db.open( getDBName(), SQLite::OPEN_READWRITE ); @@ -771,6 +793,8 @@ void removeFromDB( const string &path ) { } std::vector< std::unordered_map< string, string > > dbGetShows() { + if ( !FSLib::exists( getDBName() ) ) + return {}; SQLite::Database db{}; try { db.open( getDBName(), SQLite::OPEN_READWRITE ); @@ -785,6 +809,8 @@ std::vector< std::unordered_map< string, string > > dbGetShows() { void changeDB( size_t index, const string &path, const string &language, const string &id, bool dvd ) { + if ( !FSLib::exists( getDBName() ) ) + return; SQLite::Database db{}; auto absolute = FSLib::canonical( path ); try { @@ -807,13 +833,22 @@ void changeDB( size_t index, const string &path, const string &language, TEXT( " WHERE ID == " ) + show_id + TEXT( ";" ) ); } -void refreshSingleDB( const size_t &index, bool linux ) { +#ifdef GUI +void refreshSelectDB( std::unordered_set< size_t > &indexes, bool linux, + void *progress_ptr ) { + if ( !FSLib::exists( getDBName() ) ) + return; std::vector< std::unordered_map< string, string > > shows; -#ifdef _WIN32 - string show_id = std::to_wstring( index ); + string index_list{ '(' }; + for ( auto &index : indexes ) { +#ifndef WIN32 + index_list += std::to_string( index ); #else - string show_id = std::to_string( index ); + index_list += std::to_wstring( index ); #endif + index_list += ','; + } + index_list.back() = ')'; SQLite::Database db{}; try { db.open( getDBName(), SQLite::OPEN_READWRITE ); @@ -821,61 +856,63 @@ void refreshSingleDB( const size_t &index, bool linux ) { cerr << "Can't open database, make sure it exists" << std::endl; throw e; } - db.exec( TEXT( "DELETE FROM EPISODES WHERE SHOWID == " ) + show_id + TEXT( ";" ) ); - db.exec( - TEXT( "SELECT TVID, SHOW, PATH, LANGUAGE, DVD FROM SHOWS WHERE ID == " ) + - show_id + TEXT( ";" ), - shows ); - - std::unordered_map< string, string > &show = shows[0]; + db.exec( TEXT( "DELETE FROM EPISODES WHERE SHOWID IN " ) + index_list + + TEXT( ";" ) ); + db.exec( TEXT( "SELECT ID, TVID, SHOW, PATH, LANGUAGE, DVD FROM SHOWS " + "WHERE ID IN " ) + + index_list + TEXT( ";" ), + shows ); string pattern{}; db.exec( TEXT( "SELECT PATH FROM SHOWS WHERE TVID == 'pattern';" ), pattern ); - cout << "Refreshing " << show[TEXT( "SHOW" )] << std::endl - << std::endl - << std::endl; -#ifdef _WIN32 - cout << std::endl; -#endif - if ( FSLib::exists( show[TEXT( "PATH" )] ) ) { -#ifdef _WIN32 - cout << std::endl; -#endif -#ifndef GUI - ProgressBar::print( 0 ); -#endif - std::map< int, std::map< int, string > > seasons; - // get all season number from this directory and subdirectories - iterateFS( seasons, show[TEXT( "PATH" )] ); -#ifndef GUI - auto size = seasons.size(); -#endif - size_t i{}; - for ( auto &x : seasons ) { - singleSeason( show[TEXT( "PATH" )], show[TEXT( "SHOW" )], x.first, - show[TEXT( "TVID" )], show[TEXT( "LANGUAGE" )], - pattern, linux, true, &x.second, false, - show[TEXT( "DVD" )] == TEXT( "1" ) ); - i++; -#ifndef GUI - ProgressBar::print( ( i * 100 ) / size ); -#endif - } -#ifndef GUI - ProgressBar::print( 100 ); - cout << std::endl; -#endif - seasons.clear(); - iterateFS( seasons, show[TEXT( "PATH" )] ); - for ( auto &season : seasons ) { - for ( auto &episode : season.second ) { - db.exec( TEXT( "INSERT INTO EPISODES ( SHOWID, PATH ) " - "VALUES ( " ) + - show_id + TEXT( ", '" ) + sanitize( episode.second ) + - TEXT( "' );" ) ); + ProgressBar p( progress_ptr ); + + for ( auto &show : shows ) { + p.print( TEXT( "Refreshing " ) + show[TEXT( "SHOW" )] ); + if ( FSLib::exists( show[TEXT( "PATH" )] ) ) { + p.print( 0 ); + std::map< int, std::map< int, string > > seasons; + // get all season number from this directory and subdirectories + iterateFS( seasons, show[TEXT( "PATH" )] ); + auto size = seasons.size(); + size_t i{}; + for ( auto &x : seasons ) { + singleSeason( show[TEXT( "PATH" )], show[TEXT( "SHOW" )], + x.first, show[TEXT( "TVID" )], + show[TEXT( "LANGUAGE" )], pattern, linux, true, + &x.second, false, + show[TEXT( "DVD" )] == TEXT( "1" ) ); + i++; + p.print( ( i * 100 ) / size ); + } + p.print( 100 ); + for ( auto &season : seasons ) { + for ( auto &episode : season.second ) { + db.exec( TEXT( "INSERT INTO EPISODES ( SHOWID, PATH ) " + "VALUES ( " ) + + show[TEXT( "ID" )] + TEXT( ", '" ) + + sanitize( episode.second ) + TEXT( "' );" ) ); + } } } } } +#endif + +string getDBPattern() { + if ( !FSLib::exists( getDBName() ) ) + return TEXT( "" ); + SQLite::Database db{}; + try { + db.open( getDBName(), SQLite::OPEN_READONLY ); + } catch ( std::exception &e ) { + cerr << "Can't open database, make sure it exists" << std::endl; + throw e; + } + string pattern{}; + db.exec( TEXT( "SELECT PATH FROM SHOWS WHERE TVID == 'pattern';" ), + pattern ); + return pattern; +} diff --git a/functions.hpp b/functions.hpp index dfcf5d0..e68a85c 100644 --- a/functions.hpp +++ b/functions.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "network.hpp" @@ -30,7 +31,8 @@ using char_t = char; void printHelp(); bool searchSeason( const char_t *const path, size_t &season_pos ); -bool searchSeason( const char_t *const path, size_t &season_pos, size_t &ep_pos ); +bool searchSeason( const char_t *const path, size_t &season_pos, + size_t &ep_pos ); void parseSeasonNumbers( std::set< int > &seasons_num, const char_t *argument ); @@ -45,17 +47,29 @@ void addToDB( string &show, const string &path, const string &language, bool linux, bool dvd ); #else void addToDB( string &show, const string &path, const string &language, - const string &id, const string &pattern, bool linux, bool dvd ); + const string &id, const string &pattern, bool linux, bool dvd, + void *progress_ptr ); std::vector< std::unordered_map< std::string, std::string > > dbGetShows(); #endif void removeFromDB( const string &path ); void changeDBPattern( const string &pattern ); +#ifndef GUI void refreshDB( bool linux ); +#else +void refreshDB( bool linux, void *progress_ptr ); +#endif +#ifndef GUI void updateDB( bool linux ); +#else +void updateDB( bool linux, void *progress_ptr ); +#endif void cleanDB(); void changeDB( size_t index, const string &path, const string &language, - const string &id, bool dvd ); -void refreshSingleDB( const size_t &index, bool linux ); + const string &id, bool dvd ); +#ifdef GUI +void refreshSelectDB( std::unordered_set< size_t > &indexes, bool linux, + void *progress_ptr ); +#endif void iterateFS( std::map< int, std::map< int, string > > &seasons, const string &path ); @@ -63,5 +77,6 @@ void iterateFS( std::map< int, std::map< int, string > > &seasons, string compilePattern( const string &pattern, int season, int episode, const string &filename, const string &episodeName, const string &showName ); +string getDBPattern(); #endif