diff options
author | horchi <vdr@jwendel.de> | 2017-03-05 16:39:28 +0100 |
---|---|---|
committer | horchi <vdr@jwendel.de> | 2017-03-05 16:39:28 +0100 |
commit | e2a48d8701f91b8e24fbe9e99e91eb72a87bb749 (patch) | |
tree | 726f70554b4ca985a09ef6e30a7fdc8df089993c /moviedbmanager.c | |
download | vdr-epg-daemon-e2a48d8701f91b8e24fbe9e99e91eb72a87bb749.tar.gz vdr-epg-daemon-e2a48d8701f91b8e24fbe9e99e91eb72a87bb749.tar.bz2 |
git init1.1.103
Diffstat (limited to 'moviedbmanager.c')
-rw-r--r-- | moviedbmanager.c | 564 |
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; +} |