/* Movie Database - TMDb Copyright (C) 2015-2020 TangoCash License: GPLv2 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "mdb-tmdb.h" CTMDB *CTMDB::getInstance() { static CTMDB *tmdb = NULL; if (!tmdb) tmdb = new CTMDB(); return tmdb; } CTMDB::CTMDB() { key = g_settings.tmdb_api_key; posterfile = "/tmp/tmdb.jpg"; hintbox = NULL; } CTMDB::~CTMDB() { cleanup(); } void CTMDB::setTitle(std::string epgtitle) { minfo.epgtitle = epgtitle; hintbox = new CHintBox(LOCALE_MESSAGEBOX_INFO, LOCALE_TMDB_READ_DATA); hintbox->paint(); std::string lang = Lang2ISO639_1(g_settings.language); getMovieDetails(lang); if ((minfo.result < 1 || minfo.overview.empty()) && lang != "en") getMovieDetails("en", true); if (hintbox) { hintbox->hide(); delete hintbox; hintbox = NULL; } } bool CTMDB::getData(std::string url, Json::Value *root) { std::string answer; if (!getUrl(url, answer)) return false; std::string errMsg = ""; bool ok = parseJsonFromString(answer, root, &errMsg); if (!ok) { printf("Failed to parse JSON\n"); printf("%s\n", errMsg.c_str()); return false; } return true; } bool CTMDB::getMovieDetails(std::string lang, bool second) { printf("[TMDB]: %s\n", __func__); Json::Value root; const std::string urlapi = "http://api.themoviedb.org/3/"; std::string url = urlapi + "search/multi?api_key=" + key + "&language=" + lang + "&query=" + encodeUrl(minfo.epgtitle); if (!(getData(url, &root))) return false; minfo.result = root.get("total_results", 0).asInt(); if (minfo.result == 0) { std::string title = minfo.epgtitle; size_t pos1 = title.find_last_of("("); size_t pos2 = title.find_last_of(")"); if (pos1 != std::string::npos && pos2 != std::string::npos && pos2 > pos1) { printf("[TMDB]: second try\n"); title.replace(pos1, pos2 - pos1 + 1, ""); url = urlapi + "search/multi?api_key=" + key + "&language=" + lang + "&query=" + encodeUrl(title); if (!(getData(url, &root))) return false; minfo.result = root.get("total_results", 0).asInt(); } } printf("[TMDB]: results: %d\n", minfo.result); if (minfo.result > 0) { Json::Value elements = root["results"]; int use_result = 0; if ((minfo.result > 1) && (!second)) selectResult(elements, minfo.result, use_result); if (!second) { minfo.id = elements[use_result].get("id", -1).asInt(); minfo.media_type = elements[use_result].get("media_type", "").asString(); } if (minfo.id > -1) { url = urlapi + minfo.media_type + "/" + to_string(minfo.id) + "?api_key=" + key + "&language=" + lang + "&append_to_response=credits"; if (!(getData(url, &root))) return false; minfo.overview = root.get("overview", "").asString(); minfo.poster_path = root.get("poster_path", "").asString(); minfo.original_title = root.get("original_title", "").asString();; minfo.release_date = root.get("release_date", "").asString();; minfo.vote_average = root.get("vote_average", "").asString();; minfo.vote_count = root.get("vote_count", 0).asInt();; minfo.runtime = root.get("runtime", 0).asInt();; if (minfo.media_type == "tv") { minfo.original_title = root.get("original_name", "").asString();; minfo.episodes = root.get("number_of_episodes", 0).asInt();; minfo.seasons = root.get("number_of_seasons", 0).asInt();; minfo.release_date = root.get("first_air_date", "").asString();; elements = root["episode_run_time"]; minfo.runtimes = elements[0].asString(); for (unsigned int i = 1; i < elements.size(); i++) { minfo.runtimes += + ", " + elements[i].asString(); } } elements = root["genres"]; minfo.genres = elements[0].get("name", "").asString(); for (unsigned int i = 1; i < elements.size(); i++) { minfo.genres += ", " + elements[i].get("name", "").asString(); } elements = root["credits"]["cast"]; minfo.cast.clear(); for (unsigned int i = 0; i < elements.size() && i < 10; i++) { minfo.cast += " " + elements[i].get("character", "").asString() + " (" + elements[i].get("name", "").asString() + ")\n"; //printf("test: %s (%s)\n",elements[i].get("character","").asString().c_str(),elements[i].get("name","").asString().c_str()); } unlink(posterfile.c_str()); if (hasPoster()) getBigPoster(posterfile.c_str()); //printf("[TMDB]: %s (%s) %s\n %s\n %d\n",minfo.epgtitle.c_str(),minfo.original_title.c_str(),minfo.release_date.c_str(),minfo.overview.c_str(),minfo.found); return true; } } else return false; return false; } std::string CTMDB::getEPGText() { std::string epgtext(""); epgtext += "Vote: " + minfo.vote_average.substr(0, 3) + "/10; Votecount: " + to_string(minfo.vote_count) + "\n"; epgtext += "\n"; epgtext += minfo.overview + "\n"; epgtext += "\n"; if (minfo.media_type == "tv") epgtext += g_Locale->getString(LOCALE_EPGVIEWER_LENGTH) + ": " + minfo.runtimes + "\n"; else epgtext += g_Locale->getString(LOCALE_EPGVIEWER_LENGTH) + ": " + to_string(minfo.runtime) + "\n"; epgtext += g_Locale->getString(LOCALE_EPGVIEWER_GENRE) + ": " + minfo.genres + "\n"; epgtext += g_Locale->getString(LOCALE_EPGEXTENDED_ORIGINAL_TITLE) + ": " + minfo.original_title + "\n"; epgtext += g_Locale->getString(LOCALE_EPGEXTENDED_YEAR_OF_PRODUCTION) + ": " + minfo.release_date.substr(0, 4) + "\n"; if (minfo.media_type == "tv") epgtext += "Seasons/Episodes: " + to_string(minfo.seasons) + "/" + to_string(minfo.episodes) + "\n"; if (!minfo.cast.empty()) epgtext += g_Locale->getString(LOCALE_EPGEXTENDED_ACTORS) + ":\n" + minfo.cast + "\n"; return epgtext; } std::string CTMDB::getMovieText() { std::string movietext(""); if (!minfo.overview.empty()) { movietext = minfo.overview + "\n"; if (!minfo.cast.empty()) { movietext += "\n"; movietext += g_Locale->getString(LOCALE_EPGEXTENDED_ACTORS) + ":\n"; movietext += minfo.cast; } } return movietext; } void CTMDB::cleanup() { if (access(posterfile.c_str(), F_OK) == 0) unlink(posterfile.c_str()); } void CTMDB::selectResult(Json::Value elements, int results, int &use_result) { if (hintbox) { hintbox->hide(); delete hintbox; hintbox = NULL; } int select = 0; CMenuWidget *m = new CMenuWidget(LOCALE_TMDB_READ_DATA, NEUTRINO_ICON_SETTINGS); CMenuSelectorTarget *selector = new CMenuSelectorTarget(&select); // we don't show introitems, so we add a separator for a smoother view m->addItem(GenericMenuSeparator); CMenuForwarder *mf; int counter = std::min(results, 10); for (int i = 0; i != counter; i++) { if (elements[i].get("media_type", "").asString() == "movie") mf = new CMenuForwarder(elements[i].get("title", "").asString(), true, NULL, selector, to_string(i).c_str()); else mf = new CMenuForwarder(elements[i].get("name", "").asString(), true, NULL, selector, to_string(i).c_str()); m->addItem(mf); } m->enableSaveScreen(); m->exec(NULL, ""); if (!m->gotAction()) return; delete selector; delete m; use_result = select; }