#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 *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::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(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 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 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::iterator mId = storedMovieIds.begin(); mId != storedMovieIds.end(); mId++) { set::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; }