RenameServer/themoviedb/moviedb.cpp

291 lines
9.0 KiB
C++
Raw Normal View History

2021-07-08 05:41:34 +00:00
// API - 2ebc8e784a4072da457fae5c0d291e48
2021-07-27 17:40:44 +00:00
// API READ ONLY -
// eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIyZWJjOGU3ODRhNDA3MmRhNDU3ZmFlNWMwZDI5MWU0OCIsInN1YiI6IjYwZTJlNGI5MjJlNDgwMDA2MDJmZDMzMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.c0y7bTCI5KSsfQRw7igPx1FR40mbMF6hGTJTHn0HXH8
2021-07-08 05:41:34 +00:00
#include <algorithm>
#include <iostream>
#include <map>
#include "../filesystem/filesystem.hpp"
#include "functions.hpp"
#include "../library.hpp"
#ifdef _WIN32
#include "rapidjson/document.h"
#else
#include <rapidjson/document.h>
#endif
#include <sstream>
#include <vector>
#ifdef _WIN32
#include <windows.h>
#include <codecvt>
#include <fcntl.h>
#include <io.h>
#include <locale>
constexpr const char_t *_tv_rename_dir_divider = L"\\";
#define toString( a ) utf8_to_wstring( a )
#else
constexpr const char_t *_tv_rename_dir_divider = "/";
#define toString( a ) a
#endif
string _moviedb_api_token{};
Request _moviedb_request;
2021-07-27 17:39:23 +00:00
struct MovieNames {
string name;
string original_name;
};
struct MovieInfo {
string name;
string original_name;
string year;
string id;
};
2021-07-27 17:40:44 +00:00
bool init( const string &config_path ) {
2021-07-08 05:41:34 +00:00
Request &request = _moviedb_request;
#ifdef _WIN32
request.setServer( TEXT( "api.themoviedb.org/3" ) );
#else
request.setServer( "https://api.themoviedb.org/3" );
#endif
2021-07-27 17:40:44 +00:00
_moviedb_api_token =
"eyJhbGciOiJIUzI1NiJ9."
"eyJhdWQiOiIyZWJjOGU3ODRhNDA3MmRhNDU3ZmFlNWMwZDI5MWU0OCIsInN1YiI6IjYwZT"
"JlNGI5MjJlNDgwMDA2MDJmZDMzMyIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9u"
"IjoxfQ.c0y7bTCI5KSsfQRw7igPx1FR40mbMF6hGTJTHn0HXH8";
2021-07-08 05:41:34 +00:00
return true;
}
2021-07-27 17:40:44 +00:00
bool hasKey( const rapidjson::GenericValue< rapidjson::UTF8<> > &object,
const std::string &key ) {
return object.FindMember( key.c_str() ) != object.MemberEnd();
2021-07-10 20:48:31 +00:00
}
2021-07-27 17:39:23 +00:00
std::vector< MovieInfo >
2021-07-08 05:41:34 +00:00
searchMovie( const string &movie, const string &language, const string &year ) {
Request &request = _moviedb_request;
request.addHeader( TEXT( "Accept: application/json" ) );
request.addHeader( TEXT( "Authorization: Bearer " ) + _moviedb_api_token );
auto encoded_show = encodeUrl( movie );
int pages = 0;
int cur_page = 0;
2021-07-27 17:39:23 +00:00
std::vector< MovieInfo > ret;
2021-07-08 05:41:34 +00:00
do {
cur_page++;
rapidjson::Document json;
2021-07-27 17:40:44 +00:00
auto request_uri = TEXT( "/search/movie?query=" ) + encoded_show +
TEXT( "&language=" ) + language + TEXT( "&page=" ) +
toString( std::to_string( cur_page ) );
if ( !year.empty() ) {
request_uri += TEXT( "&year=" ) + year;
2021-07-08 05:41:34 +00:00
}
2021-07-27 17:40:44 +00:00
json.Parse( request.get( request_uri ).c_str() );
2021-07-08 05:41:34 +00:00
if ( json.HasParseError() )
return {};
pages = json["total_pages"].GetInt();
const rapidjson::Value &results = json["results"];
if ( !results.IsArray() ) {
return {};
}
// find all possible movies
for ( size_t i = 0; i < results.Size(); i++ ) {
2021-07-27 17:40:44 +00:00
if ( !hasKey( results[i], "title" ) ||
!hasKey( results[i], "id" ) ||
!hasKey( results[i], "release_date" ) ||
!hasKey( results[i], "original_title" ) ) {
2021-07-10 20:48:31 +00:00
continue;
}
2021-07-08 05:41:34 +00:00
auto movie = toString( results[i]["title"].GetString() );
auto id = toString( std::to_string( results[i]["id"].GetInt() ) );
string year = toString( results[i]["release_date"].GetString() );
2021-07-27 17:40:44 +00:00
string original =
toString( results[i]["original_title"].GetString() );
if ( year.empty() ) {
2021-07-08 05:41:34 +00:00
year = "0000";
} else {
2021-07-27 17:40:44 +00:00
year = year.substr( 0, year.find( '-' ) );
2021-07-08 05:41:34 +00:00
}
2021-07-27 17:39:23 +00:00
MovieInfo tmp;
2021-07-27 17:40:44 +00:00
tmp.name = std::move( movie );
tmp.id = std::move( id );
tmp.original_name = std::move( original );
tmp.year = std::move( year );
ret.push_back( std::move( tmp ) );
2021-07-08 05:41:34 +00:00
}
2021-07-27 17:40:44 +00:00
} while ( cur_page < pages && cur_page < 5 );
2021-07-08 05:41:34 +00:00
request.clearHeader();
return ret;
}
2021-07-27 17:39:23 +00:00
RenameObject movieToRenameObject( const MovieInfo &movie,
2021-07-27 17:40:44 +00:00
const std::string &language ) {
2021-07-08 05:41:34 +00:00
RenameObject result;
2021-07-27 17:39:23 +00:00
result.setPresentedName( movie.name );
result.addCustomField( "id", movie.id );
2021-07-08 05:41:34 +00:00
result.addCustomField( "language", language );
2021-07-27 17:39:23 +00:00
result.addCustomField( "year", movie.year );
result.addCustomField( "original_title", movie.original_name );
2021-07-08 05:41:34 +00:00
result.addCustomField( "use_original", "false" );
return result;
}
std::vector< RenameObject > getOptions( const RenameObject &search ) {
string lang = "en-US";
string year = "";
if ( search.getCustomFields().find( "language" ) !=
search.getCustomFields().end() ) {
lang = search.getCustomFields().at( "language" );
}
if ( search.getCustomFields().find( "year" ) !=
2021-07-27 17:40:44 +00:00
search.getCustomFields().end() ) {
2021-07-08 05:41:34 +00:00
year = search.getCustomFields().at( "year" );
}
string name = search.getPresentedName();
auto possibilities = searchMovie( name, lang, year );
std::vector< RenameObject > result{};
for ( auto &movie : possibilities ) {
result.push_back( movieToRenameObject( movie, lang ) );
}
return result;
}
2021-07-27 17:40:44 +00:00
std::string removeIllegalCharacters( const std::string &input ) {
2021-07-27 17:39:23 +00:00
// replace '/' with '|'
std::string ret = input;
for ( size_t i = 0; i < ret.size(); i++ ) {
if ( ret[i] == '/' ) {
ret[i] = '|';
}
}
// replace characters illegal in windows
ret.erase( std::remove_if( ret.begin(), ret.end(),
2021-07-27 17:40:44 +00:00
[]( char_t x ) {
return x == '?' || x == '"' || x == '\\' ||
x == '*';
} ),
ret.end() );
2021-07-27 17:39:23 +00:00
for ( size_t i = 0; i < ret.size(); i++ ) {
if ( ret[i] == '|' ) {
ret[i] = '-';
} else if ( ret[i] == '<' ) {
ret.erase( i, 1 );
ret.insert( i, TEXT( "" ) );
} else if ( ret[i] == '>' ) {
ret.erase( i, 1 );
ret.insert( i, TEXT( "" ) );
} else if ( ret[i] == ':' ) {
ret[i] = ' ';
ret.insert( i + 1, TEXT( "- " ) );
}
}
for ( size_t i = 0; i < ret.size(); i++ ) {
if ( ret[i] == ' ' && ret[i + 1] == ' ' ) {
ret.erase( i, 1 );
i--;
}
}
return ret;
}
MovieNames movieFromId( const string &id, const string &language ) {
2021-07-08 05:41:34 +00:00
string uri = "/movie/" + id + "?language=" + language;
Request &request = _moviedb_request;
request.addHeader( TEXT( "Accept: application/json" ) );
request.addHeader( TEXT( "Authorization: Bearer " ) + _moviedb_api_token );
rapidjson::Document json;
json.Parse( request.get( uri ).c_str() );
2021-07-27 17:40:44 +00:00
if ( json.HasParseError() ) {
return { "", "" };
2021-07-08 05:41:34 +00:00
}
2021-07-27 17:40:44 +00:00
return { removeIllegalCharacters( json["title"].GetString() ),
removeIllegalCharacters( json["original_title"].GetString() ) };
2021-07-08 05:41:34 +00:00
}
2021-07-27 17:40:44 +00:00
bool renameMovie( const string &path, const string &name, const string &year ) {
return FSLib::rename(
path, FSLib::canonical( FSLib::getContainingDirectory( path ) ) + "/" +
name + " (" + year + ")." + FSLib::getFileExtension( path ) );
2021-07-08 05:41:34 +00:00
}
bool renamePath( const string &path, const RenameObject &renamer ) {
string id = "";
string lang = "en-US";
2021-07-27 17:40:44 +00:00
MovieNames movie = { "", "" };
2021-07-08 05:41:34 +00:00
string year = "";
bool use_original = false;
if ( renamer.getCustomFields().find( "language" ) !=
renamer.getCustomFields().end() ) {
lang = renamer.getCustomFields().at( "language" );
}
if ( renamer.getCustomFields().find( "year" ) !=
renamer.getCustomFields().end() ) {
year = renamer.getCustomFields().at( "year" );
}
if ( renamer.getCustomFields().find( "use_original" ) !=
renamer.getCustomFields().end() ) {
auto use = renamer.getCustomFields().at( "use_original" );
2021-07-27 17:40:44 +00:00
use_original = ( use == "true" || use == "True" || use == "TRUE" );
2021-07-08 05:41:34 +00:00
}
if ( renamer.getCustomFields().find( "id" ) ==
renamer.getCustomFields().end() ||
renamer.getCustomFields().at( "id" ).empty() ) {
auto results = searchMovie( renamer.getPresentedName(), lang, year );
if ( results.empty() )
return false;
2021-07-27 17:39:23 +00:00
id = results[0].id;
2021-07-27 17:40:44 +00:00
movie = { removeIllegalCharacters( results[0].name ),
removeIllegalCharacters( results[0].original_name ) };
2021-07-27 17:39:23 +00:00
year = results[0].year;
2021-07-08 05:41:34 +00:00
} else {
id = renamer.getCustomFields().at( "id" );
movie = movieFromId( id, lang );
}
2021-07-27 17:40:44 +00:00
if ( ( !use_original && movie.name == "" ) ||
( use_original && movie.original_name == "" ) )
2021-07-27 17:39:23 +00:00
return false;
2021-07-27 17:40:44 +00:00
return renameMovie( path, use_original ? movie.original_name : movie.name,
year );
2021-07-08 05:41:34 +00:00
}
std::vector< string > getCustomKeys() {
return { "id", "language", "year", "original_title", "use_original" };
}
const string getName() {
return "TheMovieDB";
}
const bool canRenameMultipleFiles() {
return false;
}