summaryrefslogtreecommitdiff
path: root/moviedbmanager.c
diff options
context:
space:
mode:
authorhorchi <vdr@jwendel.de>2017-03-05 16:39:28 +0100
committerhorchi <vdr@jwendel.de>2017-03-05 16:39:28 +0100
commite2a48d8701f91b8e24fbe9e99e91eb72a87bb749 (patch)
tree726f70554b4ca985a09ef6e30a7fdc8df089993c /moviedbmanager.c
downloadvdr-epg-daemon-e2a48d8701f91b8e24fbe9e99e91eb72a87bb749.tar.gz
vdr-epg-daemon-e2a48d8701f91b8e24fbe9e99e91eb72a87bb749.tar.bz2
git init1.1.103
Diffstat (limited to 'moviedbmanager.c')
-rw-r--r--moviedbmanager.c564
1 files changed, 564 insertions, 0 deletions
diff --git a/moviedbmanager.c b/moviedbmanager.c
new file mode 100644
index 0000000..a47194d
--- /dev/null
+++ b/moviedbmanager.c
@@ -0,0 +1,564 @@
+
+#include "moviedbmanager.h"
+#include "lib/curl.h"
+
+extern const char* confDir;
+
+using namespace std;
+
+cMovieDBManager::cMovieDBManager(void) {
+ connection = NULL;
+ tMovies = NULL;
+ tMoviesActor = NULL;
+ tMoviesActors = NULL;
+ tMovieMedia = NULL;
+ tEvents = NULL;
+ tRecordingList = NULL;
+ movieDbScraper = NULL;
+
+ withutf8 = no;
+ bytesDownloaded = 0;
+ exsltRegisterAll();
+ setlocale(LC_CTYPE, "");
+ char* lang;
+ lang = setlocale(LC_CTYPE, 0);
+ if (lang) {
+ //tell(0, "Set locale to '%s'", lang);
+ if ((strcasestr(lang, "UTF-8") != 0) || (strcasestr(lang, "UTF8") != 0)){
+ //tell(0, "detected UTF-8");
+ withutf8 = yes;
+ }
+ } else {
+ //tell(0, "Reseting locale for LC_CTYPE failed.");
+ }
+ string loc = lang;
+ size_t index = loc.find_first_of("_");
+ string langISO = "";
+ if (index > 0) {
+ langISO = loc.substr(0, index);
+ }
+ if (langISO.size() == 2) {
+ language = langISO.c_str();
+ } else {
+ language = "en";
+ }
+}
+
+cMovieDBManager::~cMovieDBManager() {
+ if (movieDbScraper)
+ delete movieDbScraper;
+ if (tMovies)
+ delete tMovies;
+ if (tMoviesActor)
+ delete tMoviesActor;
+ if (tMoviesActors)
+ delete tMoviesActors;
+ if (tMovieMedia)
+ delete tMovieMedia;
+ if (tEvents)
+ delete tEvents;
+ if (tRecordingList)
+ delete tRecordingList;
+}
+
+int cMovieDBManager::ConnectDatabase(cDbConnection *conn) {
+ int status;
+ connection = conn;
+ if (!connection)
+ return fail;
+ tMovies = new cDbTable(connection, "movie");
+ if ((status = tMovies->open()) != success)
+ return status;
+ tMoviesActor = new cDbTable(connection, "movie_actor");
+ if ((status = tMoviesActor->open()) != success)
+ return status;
+ tMoviesActors = new cDbTable(connection, "movie_actors");
+ if ((status = tMoviesActors->open()) != success)
+ return status;
+ tMovieMedia = new cDbTable(connection, "movie_media");
+ if ((status = tMovieMedia->open()) != success)
+ return status;
+ tEvents = new cDbTable(connection, "events");
+ if ((status = tEvents->open()) != success)
+ return status;
+ tRecordingList = new cDbTable(connection, "recordinglist");
+ if ((status = tRecordingList->open()) != success)
+ return status;
+ return success;
+}
+
+bool cMovieDBManager::ConnectScraper(void) {
+ movieDbScraper = new cMovieDBScraper(language);
+ bool ok = movieDbScraper->Connect();
+ return ok;
+}
+
+bool cMovieDBManager::GetMoviesFromEPG(vector<sMovieResult> *result) {
+ int status = success;
+ cDbStatement *selectMovies = new cDbStatement(tEvents);
+ selectMovies->build("select ");
+ selectMovies->bind("EventId", cDBS::bndOut);
+ selectMovies->bind("Title", cDBS::bndOut, ", ");
+ selectMovies->bind("Year", cDBS::bndOut, ", ");
+ selectMovies->bind("ScrSp", cDBS::bndOut, ", ");
+ selectMovies->build(" from %s where ", tEvents->TableName());
+ selectMovies->build(" category = 'Spielfilm'");
+ selectMovies->build(" and %s is null", tEvents->getField("ScrSp")->getDbName());
+ selectMovies->build(" and updflg in('A','T','C','P')");
+ status += selectMovies->prepare();
+ if (status != success) {
+ delete selectMovies;
+ return false;
+ }
+ for (int found = selectMovies->find(); found; found = selectMovies->fetch()) {
+ sMovieResult res;
+ res.eventId = tEvents->getBigintValue("EventId");
+ res.title = tEvents->getStrValue("Title");
+ res.year = tEvents->getStrValue("Year") ? tEvents->getStrValue("Year") : "";
+ res.lastScraped = tEvents->getIntValue("ScrSp");
+ result->push_back(res);
+ }
+ selectMovies->freeResult();
+ delete selectMovies;
+ return true;
+}
+
+void cMovieDBManager::ProcessMovie(sMovieResult mov) {
+ //tell(0, "Checking eventID: %d, Title: %s, year %s", mov.eventId, mov.title.c_str(), mov.year.c_str());
+
+ map<string, int>::iterator hit = alreadyScraped.find(mov.title);
+ int movieID = 0;
+ if (hit != alreadyScraped.end()) {
+ movieID = (int)hit->second;
+ if (movieID == 0) {
+ //tell(0, "movie %s already scraped and nothing found", mov.title.c_str());
+ return;
+ } else {
+ //tell(0, "found movie %s in cache, id %d", mov.title.c_str(), movieID);
+ }
+ }
+ if (movieID == 0) {
+ //check if movie is in database
+ movieID = LoadMovieFromDB(mov.title);
+ if (movieID != 0) {
+ //tell(0, "movie %s already in db, id %d", mov.title.c_str(), movieID);
+ } else {
+ //scrap movie
+ cMovieDbMovie *movie = movieDbScraper->Scrap(mov.title, mov.year);
+ if (movie) {
+ movieID = movie->id;
+ movie->ReadActors();
+ //tell(0, "movie %s successfully scraped, id %d", mov.title.c_str(), movieID);
+ SaveMovie(movie);
+ delete movie;
+ } else {
+ //tell(0, "movie %s not found at themoviedb.com", mov.title.c_str());
+ }
+ }
+ }
+ alreadyScraped.insert(pair<string, int>(mov.title, movieID));
+ //updating event with movie data
+ UpdateEvent(mov.eventId, movieID);
+}
+
+int cMovieDBManager::LoadMovieFromDB(string title) {
+ int status = success;
+ int movieID = 0;
+ tMovies->clear();
+ tMovies->setValue("Title", title.c_str());
+ cDbStatement *select = new cDbStatement(tMovies);
+ select->build("select ");
+ select->bind("MovieId", cDBS::bndOut);
+ select->build(" from %s where ", tMovies->TableName());
+ select->bind("Title", cDBS::bndIn | cDBS::bndSet);
+ status += select->prepare();
+ if (status != success) {
+ delete select;
+ return movieID;
+ }
+ int res = select->find();
+ if (res) {
+ movieID = tMovies->getIntValue("MovieId");
+ }
+ select->freeResult();
+ delete select;
+ return movieID;
+}
+
+void cMovieDBManager::UpdateEvent(tEventId eventID, int movieID) {
+ stringstream upd;
+ upd << "update " << tEvents->TableName();
+ upd << " set scrsp = " << time(0);
+ upd << ", scrmovieid = " << movieID;
+ upd << " where eventid = " << eventID;
+ cDbStatement updStmt(connection, upd.str().c_str());
+ updStmt.prepare();
+ updStmt.execute();
+}
+
+void cMovieDBManager::SaveMovie(cMovieDbMovie *movie) {
+ SaveMovieBasics(movie);
+ SaveMovieMedia(movie);
+ SaveMovieActors(movie);
+}
+
+void cMovieDBManager::SaveMovieBasics(cMovieDbMovie *movie) {
+ tMovies->clear();
+ tMovies->setValue("MovieId", movie->id);
+ tMovies->setValue("Title", movie->title.c_str());
+ tMovies->setValue("OriginalTitle", movie->originalTitle.c_str());
+ tMovies->setValue("Tagline", movie->tagline.c_str());
+ tMovies->setValue("Overview", movie->overview.c_str());
+ tMovies->setValue("IsAdult", movie->adult?1:0);
+ tMovies->setValue("CollectionId", movie->collectionID);
+ tMovies->setValue("CollectionName", movie->collectionName.c_str());
+ tMovies->setValue("Budget", movie->budget);
+ tMovies->setValue("Revenue", movie->revenue);
+ tMovies->setValue("Genres", movie->genres.c_str());
+ tMovies->setValue("Homepage", movie->homepage.c_str());
+ tMovies->setValue("ReleaaseDate", movie->releaseDate.c_str());
+ tMovies->setValue("Runtime", movie->runtime);
+ tMovies->setValue("Popularity", movie->popularity);
+ tMovies->setValue("VoteAverage", movie->voteAverage);
+ tMovies->store();
+}
+
+void cMovieDBManager::SaveMovieMedia(cMovieDbMovie *movie) {
+ MemoryStruct data;
+ if (movie->posterPath.size() > 10) {
+ tMovieMedia->clear();
+ tMovieMedia->setValue("MovieId", movie->id);
+ tMovieMedia->setValue("ActorId", 0);
+ tMovieMedia->setValue("MediaType", mtPoster);
+ tMovieMedia->setValue("MediaUrl", movie->posterPath.c_str());
+ tMovieMedia->setValue("MediaWidth", movie->posterWidth);
+ tMovieMedia->setValue("MediaHeight", movie->posterHeight);
+ if (GetPicture(movie->posterPath.c_str(), &data) == success) {
+ tMovieMedia->setValue("MediaContent", data.memory, data.size);
+ tMovieMedia->store();
+ }
+ }
+ if (movie->backdropPath.size() > 10) {
+ tMovieMedia->clear();
+ tMovieMedia->setValue("MovieId", movie->id);
+ tMovieMedia->setValue("ActorId", 0);
+ tMovieMedia->setValue("MediaType", mtFanart);
+ tMovieMedia->setValue("MediaUrl", movie->backdropPath.c_str());
+ tMovieMedia->setValue("MediaWidth", movie->backdropWidth);
+ tMovieMedia->setValue("MediaHeight", movie->backdropHeight);
+ if (GetPicture(movie->backdropPath.c_str(), &data) == success) {
+ tMovieMedia->setValue("MediaContent", data.memory, data.size);
+ tMovieMedia->store();
+ }
+ }
+ if (movie->collectionPosterPath.size() > 10) {
+ tMovieMedia->clear();
+ tMovieMedia->setValue("MovieId", movie->id);
+ tMovieMedia->setValue("ActorId", 0);
+ tMovieMedia->setValue("MediaType", mtCollectionPoster);
+ tMovieMedia->setValue("MediaUrl", movie->collectionPosterPath.c_str());
+ tMovieMedia->setValue("MediaWidth", movie->posterWidth);
+ tMovieMedia->setValue("MediaHeight", movie->posterHeight);
+ if (GetPicture(movie->collectionPosterPath.c_str(), &data) == success) {
+ tMovieMedia->setValue("MediaContent", data.memory, data.size);
+ tMovieMedia->store();
+ }
+ }
+ if (movie->collectionBackdropPath.size() > 10) {
+ tMovieMedia->clear();
+ tMovieMedia->setValue("MovieId", movie->id);
+ tMovieMedia->setValue("ActorId", 0);
+ tMovieMedia->setValue("MediaType", mtCollectionFanart);
+ tMovieMedia->setValue("MediaUrl", movie->collectionBackdropPath.c_str());
+ tMovieMedia->setValue("MediaWidth", movie->backdropWidth);
+ tMovieMedia->setValue("MediaHeight", movie->backdropHeight);
+ if (GetPicture(movie->collectionBackdropPath.c_str(), &data) == success) {
+ tMovieMedia->setValue("MediaContent", data.memory, data.size);
+ tMovieMedia->store();
+ }
+ }
+}
+
+void cMovieDBManager::SaveMovieActors(cMovieDbMovie *movie) {
+ cMovieDBActor *actor = NULL;
+ while ((actor = movie->GetActor())) {
+ tMoviesActor->clear();
+ tMoviesActor->setValue("ActorId", actor->id);
+ tMoviesActor->setValue("ActorName", actor->name.c_str());
+ tMoviesActor->store();
+ tMoviesActors->clear();
+ tMoviesActors->setValue("MovieId", movie->id);
+ tMoviesActors->setValue("ActorId", actor->id);
+ tMoviesActors->setValue("Role", actor->role.c_str());
+ tMoviesActors->store();
+ bool mediaExists = LoadMedia(0, actor->id, mtActorThumb);
+ if (!mediaExists) {
+ tMovieMedia->clear();
+ tMovieMedia->setValue("MovieId", 0);
+ tMovieMedia->setValue("ActorId", actor->id);
+ tMovieMedia->setValue("MediaType", mtActorThumb);
+ tMovieMedia->setValue("MediaUrl", actor->thumbUrl.c_str());
+ tMovieMedia->setValue("MediaWidth", actor->width);
+ tMovieMedia->setValue("MediaHeight", actor->height);
+ MemoryStruct data;
+ if (GetPicture(actor->thumbUrl.c_str(), &data) == success) {
+ tMovieMedia->setValue("MediaContent", data.memory, data.size);
+ tMovieMedia->store();
+ }
+ }
+ }
+}
+
+bool cMovieDBManager::LoadMedia(int movieId, int actorId, int mediaType) {
+ tMovieMedia->clear();
+ tMovieMedia->setValue("MovieId", movieId);
+ tMovieMedia->setValue("ActorId", actorId);
+ tMovieMedia->setValue("MediaType", mediaType);
+ int found = tMovieMedia->find();
+ if (found == yes)
+ return true;
+ return false;
+}
+
+int cMovieDBManager::GetPicture(const char* url, MemoryStruct* data) {
+ int maxSize = tMovieMedia->getField("MediaContent")->getSize();
+ data->clear();
+ int fileSize = 0;
+ if (curl.downloadFile(url, fileSize, data) == success) {
+ bytesDownloaded += fileSize;
+ if (fileSize < maxSize)
+ return success;
+ }
+ return fail;
+}
+
+int cMovieDBManager::CleanupMovies(void) {
+ int numDelete = 0;
+ set<int> activeMovieIds;
+ int status = success;
+ //fetching movieIds from current events
+ cDbStatement *selectMovieIds = new cDbStatement(tEvents);
+ selectMovieIds->build("select distinct ");
+ selectMovieIds->bind("ScrMovieId", cDBS::bndOut);
+ selectMovieIds->build(" from %s where ", tEvents->TableName());
+ selectMovieIds->build(" %s is not null ", tEvents->getField("ScrMovieId")->getDbName());
+ selectMovieIds->build(" and %s > 0 ", tEvents->getField("ScrMovieId")->getDbName());
+ status += selectMovieIds->prepare();
+ if (status != success) {
+ delete selectMovieIds;
+ return numDelete;
+ }
+ tEvents->clear();
+
+ for (int res = selectMovieIds->find(); res; res = selectMovieIds->fetch()) {
+ activeMovieIds.insert(tEvents->getIntValue("ScrMovieId"));
+ }
+
+ selectMovieIds->freeResult();
+ delete selectMovieIds;
+
+ //fetching movieIds from recordings
+ cDbStatement *selectMovieIdsRec = new cDbStatement(tRecordingList);
+ selectMovieIdsRec->build("select distinct ");
+ selectMovieIdsRec->bind("SCRMOVIEID", cDBS::bndOut);
+ selectMovieIdsRec->build(" from %s where ", tRecordingList->TableName());
+ selectMovieIdsRec->build(" %s is not null ", tRecordingList->getField("SCRMOVIEID")->getDbName());
+ selectMovieIdsRec->build(" and %s > 0 ", tRecordingList->getField("SCRMOVIEID")->getDbName());
+ status += selectMovieIdsRec->prepare();
+ if (status != success) {
+ delete selectMovieIdsRec;
+ return numDelete;
+ }
+ tRecordingList->clear();
+ for (int res = selectMovieIdsRec->find(); res; res = selectMovieIdsRec->fetch()) {
+ activeMovieIds.insert(tRecordingList->getIntValue("SCRMOVIEID"));
+ }
+ selectMovieIdsRec->freeResult();
+ delete selectMovieIdsRec;
+
+ //fetching all movieIds from movie table
+ vector<int> storedMovieIds;
+ cDbStatement *selectStoredMovieIds = new cDbStatement(tMovies);
+ selectStoredMovieIds->build("select ");
+ selectStoredMovieIds->bind("MovieId", cDBS::bndOut);
+ selectStoredMovieIds->build(" from %s where ", tMovies->TableName());
+ selectStoredMovieIds->build(" %s is not null ", tMovies->getField("MovieId")->getDbName());
+ selectStoredMovieIds->build(" and %s > 0 ", tMovies->getField("MovieId")->getDbName());
+ status += selectStoredMovieIds->prepare();
+ if (status != success) {
+ delete selectStoredMovieIds;
+ return numDelete;
+ }
+ tMovies->clear();
+
+ for (int res = selectStoredMovieIds->find(); res; res = selectStoredMovieIds->fetch()) {
+ storedMovieIds.push_back(tMovies->getIntValue("MovieId"));
+ }
+ selectStoredMovieIds->freeResult();
+ delete selectStoredMovieIds;
+
+ numDelete = storedMovieIds.size() - activeMovieIds.size();
+ if (numDelete < 1)
+ return numDelete;
+ for (vector<int>::iterator mId = storedMovieIds.begin(); mId != storedMovieIds.end(); mId++) {
+ set<int>::iterator hit = activeMovieIds.find(*mId);
+ if (hit == activeMovieIds.end()) {
+ DeleteMovie(*mId);
+ }
+ }
+ return numDelete;
+}
+
+void cMovieDBManager::DeleteMovie(int movieId) {
+ if (movieId < 1)
+ return;
+ stringstream delMovieActors;
+ delMovieActors << "delete from " << tMoviesActors->TableName();
+ delMovieActors << " where " << tMoviesActors->getField("MovieId")->getDbName();
+ delMovieActors << " = " << movieId;
+
+ cDbStatement delActors(connection, delMovieActors.str().c_str());
+ delActors.prepare();
+ delActors.execute();
+
+ stringstream delMovieMedia;
+ delMovieMedia << "delete from " << tMovieMedia->TableName();
+ delMovieMedia << " where " << tMovieMedia->getField("MovieId")->getDbName();
+ delMovieMedia << " = " << movieId;
+
+ cDbStatement delMedia(connection, delMovieMedia.str().c_str());
+ delMedia.prepare();
+ delMedia.execute();
+
+ stringstream delMovie;
+ delMovie << "delete from " << tMovies->TableName();
+ delMovie << " where " << tMovies->getField("MovieId")->getDbName();
+ delMovie << " = " << movieId;
+
+ cDbStatement delMov(connection, delMovie.str().c_str());
+ delMov.prepare();
+ delMov.execute();
+}
+
+bool cMovieDBManager::SearchRecordingDB(string name, int &movieId)
+{
+ int status = success;
+ cDbStatement *select = new cDbStatement(tMovies);
+
+ select->build("select ");
+ select->bind("MovieId", cDBS::bndOut);
+ select->build(" from %s where ", tMovies->TableName());
+ select->bind("Title", cDBS::bndIn | cDBS::bndSet);
+ status += select->prepare();
+
+ if (status != success)
+ {
+ delete select;
+ return false;
+ }
+
+ tMovies->clear();
+ tMovies->setValue("Title", name.c_str());
+ int found = select->find();
+
+ if (found)
+ movieId = tMovies->getIntValue("MovieId");
+
+ select->freeResult();
+ delete select;
+
+ return found;
+}
+
+bool cMovieDBManager::SearchRecordingOnline(string name, int &movieId)
+{
+ cMovieDbMovie *movieRec = movieDbScraper->Scrap(name);
+
+ if (!movieRec)
+ movieRec = SearchRecordingSophisticated(name);
+
+ if (movieRec)
+ {
+ movieRec->ReadActors();
+ SaveMovie(movieRec);
+ movieId = movieRec->id;
+ delete movieRec;
+ return true;
+ }
+
+ return false;
+}
+
+cMovieDbMovie *cMovieDBManager::SearchRecordingSophisticated(string name) {
+ cMovieDbMovie *movieFound = NULL;
+ size_t posHyphen = name.find_first_of("-");
+ size_t posBracket = name.find_first_of("(");
+ bool hasHyphen = (posHyphen != string::npos)?true:false;
+ bool hasBracket = (posBracket != string::npos)?true:false;
+ string nameMod;
+ //first remove all "-"
+ if (hasBracket) {
+ nameMod = str_replace("-", " ", name);
+ movieFound = movieDbScraper->Scrap(nameMod);
+ if (movieFound)
+ return movieFound;
+ }
+ //if both hyphens and brackets found, check what comes first
+ if (hasHyphen && hasBracket) {
+ //if bracket comes after hyphen, remove bracket first
+ if (posBracket > posHyphen) {
+ nameMod = str_cut("(", name);
+ if (nameMod.size() > 3) {
+ movieFound = movieDbScraper->Scrap(nameMod);
+ if (movieFound)
+ return movieFound;
+ }
+ nameMod = str_cut("-", name);
+ if (nameMod.size() > 3) {
+ movieFound = movieDbScraper->Scrap(nameMod);
+ }
+ } else {
+ nameMod = str_cut("-", name);
+ if (nameMod.size() > 3) {
+ movieFound = movieDbScraper->Scrap(nameMod);
+ if (movieFound)
+ return movieFound;
+ }
+ nameMod = str_cut("(", name);
+ if (nameMod.size() > 3) {
+ movieFound = movieDbScraper->Scrap(nameMod);
+ }
+ }
+ } else if (hasHyphen) {
+ nameMod = str_cut("-", name);
+ if (nameMod.size() > 3) {
+ movieFound = movieDbScraper->Scrap(nameMod);
+ }
+ } else if (hasBracket) {
+ nameMod = str_cut("(", name);
+ if (nameMod.size() > 3) {
+ movieFound = movieDbScraper->Scrap(nameMod);
+ }
+ }
+ return movieFound;
+}
+
+bool cMovieDBManager::CheckScrapInfoDB(int scrapMovieId) {
+ //check if movie is in db
+ tMovies->clear();
+ tMovies->setValue("MovieId", scrapMovieId);
+ int found = tMovies->find();
+ if (!found)
+ return false;
+ return true;
+}
+
+bool cMovieDBManager::CheckScrapInfoOnline(int scrapMovieId) {
+ cMovieDbMovie *movieRec = movieDbScraper->ReadMovie(scrapMovieId);
+ if (!movieRec)
+ return false;
+ movieRec->ReadActors();
+ SaveMovie(movieRec);
+ delete movieRec;
+ return true;
+}