summaryrefslogtreecommitdiff
path: root/themoviedbscraper
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2013-08-23 17:11:38 +0200
committerlouis <louis.braun@gmx.de>2013-08-23 17:11:38 +0200
commit21c1ad1005e3415f8448a21f17ed3ba3be9715b8 (patch)
treee8cae7353b6047d1d1bd104ad54e5b15d0c85260 /themoviedbscraper
downloadvdr-plugin-tvscraper-21c1ad1005e3415f8448a21f17ed3ba3be9715b8.tar.gz
vdr-plugin-tvscraper-21c1ad1005e3415f8448a21f17ed3ba3be9715b8.tar.bz2
Initial Push Version 0.0.1
Diffstat (limited to 'themoviedbscraper')
-rw-r--r--themoviedbscraper/moviedbactors.c83
-rw-r--r--themoviedbscraper/moviedbactors.h37
-rw-r--r--themoviedbscraper/moviedbmovie.c140
-rw-r--r--themoviedbscraper/moviedbmovie.h37
-rw-r--r--themoviedbscraper/themoviedbscraper.c151
-rw-r--r--themoviedbscraper/themoviedbscraper.h32
6 files changed, 480 insertions, 0 deletions
diff --git a/themoviedbscraper/moviedbactors.c b/themoviedbscraper/moviedbactors.c
new file mode 100644
index 0000000..b3880f3
--- /dev/null
+++ b/themoviedbscraper/moviedbactors.c
@@ -0,0 +1,83 @@
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <jansson.h>
+#include "moviedbactors.h"
+
+using namespace std;
+
+cMovieDbActors::cMovieDbActors(string json) {
+ this->json = json;
+}
+
+cMovieDbActors::~cMovieDbActors() {
+ actors.clear();
+}
+
+void cMovieDbActors::ParseJSON(void) {
+ json_t *jActors;
+ json_error_t error;
+ jActors = json_loads(json.c_str(), 0, &error);
+ if (!jActors) {
+ return;
+ }
+ if(!json_is_object(jActors)) {
+ return;
+ }
+ json_t *cast = json_object_get(jActors, "cast");
+ if(!json_is_array(cast)) {
+ return;
+ }
+ size_t numActors = json_array_size(cast);
+ for (size_t i = 0; i < numActors; i++) {
+ json_t *jActor = json_array_get(cast, i);
+ if (!json_is_object(jActor)) {
+ return;
+ }
+ json_t *jId = json_object_get(jActor, "id");
+ json_t *jName = json_object_get(jActor, "name");
+ json_t *jRole = json_object_get(jActor, "character");
+ json_t *jPath = json_object_get(jActor, "profile_path");
+ if (!json_is_integer(jId) || !json_is_string(jName) || !json_is_string(jRole) || !json_is_string(jPath))
+ return;
+ cMovieDBActor *actor = new cMovieDBActor();
+ actor->id = json_integer_value(jId);
+ actor->name = json_string_value(jName);
+ actor->role = json_string_value(jRole);
+ actor->path = json_string_value(jPath);
+ actors.push_back(actor);
+ }
+}
+
+void cMovieDbActors::StoreDB(cTVScraperDB *db, int movieID) {
+ int numActors = actors.size();
+ for (int i=0; i<numActors; i++) {
+ db->InsertMovieActor(movieID, actors[i]->id, actors[i]->name, actors[i]->role);
+ }
+}
+
+void cMovieDbActors::Store(string baseUrl, string destDir) {
+ int size = actors.size();
+ string path;
+ string url;
+ for (int i=0; i<size; i++) {
+ stringstream strUrl;
+ strUrl << baseUrl << actors[i]->path;
+ url = strUrl.str();
+ stringstream fullPath;
+ fullPath << destDir << "/actor_" << actors[i]->id << ".jpg";
+ path = fullPath.str();
+ if (!FileExists(path)) {
+ CurlGetUrlFile(url.c_str(), path.c_str());
+ }
+ }
+}
+
+void cMovieDbActors::Dump(void) {
+ int numActors = actors.size();
+ esyslog("tvscraper: %d Actors:", numActors);
+ for (int i=0; i<numActors; i++) {
+ esyslog("tvscraper: id %d, name %s, role %s, path %s", actors[i]->id, actors[i]->name.c_str(), actors[i]->role.c_str(), actors[i]->path.c_str());
+ }
+} \ No newline at end of file
diff --git a/themoviedbscraper/moviedbactors.h b/themoviedbscraper/moviedbactors.h
new file mode 100644
index 0000000..1169b85
--- /dev/null
+++ b/themoviedbscraper/moviedbactors.h
@@ -0,0 +1,37 @@
+#ifndef __TVSCRAPER_MOVIEDBACTORS_H
+#define __TVSCRAPER_MOVIEDBACTORS_H
+
+using namespace std;
+
+// --- cMovieDBActor -------------------------------------------------------------
+class cMovieDBActor {
+public:
+ cMovieDBActor(void) {
+ id = 0;
+ path = "";
+ name = "";
+ role = "";
+ };
+ int id;
+ string path;
+ string name;
+ string role;
+};
+
+// --- cMovieDBActors -------------------------------------------------------------
+
+class cMovieDbActors {
+private:
+ string json;
+ vector<cMovieDBActor*> actors;
+public:
+ cMovieDbActors(string json);
+ virtual ~cMovieDbActors(void);
+ void ParseJSON(void);
+ void StoreDB(cTVScraperDB *db, int movieID);
+ void Store(string baseUrl, string destDir);
+ void Dump(void);
+};
+
+
+#endif //__TVSCRAPER_MOVIEDBACTORS_H
diff --git a/themoviedbscraper/moviedbmovie.c b/themoviedbscraper/moviedbmovie.c
new file mode 100644
index 0000000..26aee7f
--- /dev/null
+++ b/themoviedbscraper/moviedbmovie.c
@@ -0,0 +1,140 @@
+#include <string>
+#include <sstream>
+#include <vector>
+#include <algorithm>
+#include <jansson.h>
+#include "moviedbmovie.h"
+
+using namespace std;
+
+cMovieDbMovie::cMovieDbMovie(string json) {
+ this->json = json;
+ title = "";
+ originalTitle = "";
+ overview = "";
+ backdropPath = "";
+ posterPath = "";
+}
+
+cMovieDbMovie::~cMovieDbMovie() {
+
+}
+
+void cMovieDbMovie::ParseJSON(void) {
+ json_t *movie;
+ json_error_t error;
+ movie = json_loads(json.c_str(), 0, &error);
+ if (!movie) {
+ return;
+ }
+ if(!json_is_object(movie)) {
+ return;
+ }
+ json_t *jTitle = json_object_get(movie, "title");
+ if(json_is_string(jTitle)) {
+ title = json_string_value(jTitle);;
+ }
+ json_t *jOriginalTitle = json_object_get(movie, "original_title");
+ if(json_is_string(jOriginalTitle)) {
+ originalTitle = json_string_value(jOriginalTitle);
+ }
+ json_t *jOverview = json_object_get(movie, "overview");
+ if(json_is_string(jOverview)) {
+ overview = json_string_value(jOverview);
+ }
+ json_t *jBackdrop = json_object_get(movie, "backdrop_path");
+ if(json_is_string(jBackdrop)) {
+ backdropPath = json_string_value(jBackdrop);
+ }
+ json_t *jPoster = json_object_get(movie, "poster_path");
+ if(json_is_string(jPoster)) {
+ posterPath = json_string_value(jPoster);
+ }
+}
+
+int cMovieDbMovie::ParseJSONForMovieId(string movieSearchString) {
+ //convert searchstring to lower case
+ transform(movieSearchString.begin(), movieSearchString.end(), movieSearchString.begin(), ::tolower);
+ json_t *root;
+ json_error_t error;
+ root = json_loads(json.c_str(), 0, &error);
+ if (!root) {
+ return -1;
+ }
+ if(!json_is_object(root)) {
+ return -1;
+ }
+ json_t *results = json_object_get(root, "results");
+ if(!json_is_array(results)) {
+ return -1;
+ }
+ size_t numResults = json_array_size(results);
+ for (size_t res = 0; res < numResults; res++) {
+ json_t *result = json_array_get(results, res);
+ if (!json_is_object(result)) {
+ return -1;
+ }
+ json_t *title = json_object_get(result, "title");
+ if (!json_is_string(title)) {
+ return -1;
+ }
+ string resultTitle = json_string_value(title);
+ //convert result to lower case
+ transform(resultTitle.begin(), resultTitle.end(), resultTitle.begin(), ::tolower);
+ json_t *jId = json_object_get(result, "id");
+ if (json_is_integer(jId)) {
+ int id = (int)json_integer_value(jId);
+ searchResult sRes;
+ sRes.id = id;
+ sRes.distance = sentence_distance(resultTitle, movieSearchString);
+ resultSet.push_back(sRes);
+ }
+ }
+ return FindBestResult();
+}
+
+int cMovieDbMovie::FindBestResult(void) {
+ int resID = -1;
+ int bestMatch = -1;
+ int numResults = resultSet.size();
+ for (int i=0; i<numResults; i++) {
+ if (i == 0) {
+ bestMatch = resultSet[i].distance;
+ resID = resultSet[i].id;
+ } else if (resultSet[i].distance < bestMatch) {
+ bestMatch = resultSet[i].distance;
+ resID = resultSet[i].id;
+ }
+ }
+ return resID;
+}
+
+void cMovieDbMovie::StoreMedia(string posterBaseUrl, string backdropBaseUrl, string destDir) {
+ stringstream pathPoster;
+ pathPoster << destDir << id << "_poster.jpg";
+ stringstream posterUrl;
+ posterUrl << posterBaseUrl << posterPath;
+ if (!FileExists(pathPoster.str())) {
+ CurlGetUrlFile(posterUrl.str().c_str(), pathPoster.str().c_str());
+ }
+ stringstream pathBackdrop;
+ pathBackdrop << destDir << id << "_backdrop.jpg";
+ stringstream backdropUrl;
+ backdropUrl << backdropBaseUrl << backdropPath;
+ if (!FileExists(pathBackdrop.str())) {
+ CurlGetUrlFile(backdropUrl.str().c_str(), pathBackdrop.str().c_str());
+ }
+}
+
+void cMovieDbMovie::StoreDB(cTVScraperDB *db) {
+ db->InsertMovie(id, title, originalTitle, overview);
+}
+
+void cMovieDbMovie::Dump(void) {
+ esyslog("tvscraper: -------------- MOVIE DUMP ---------------");
+ esyslog("tvscraper: title %s", title.c_str());
+ esyslog("tvscraper: originalTitle %s", originalTitle.c_str());
+ esyslog("tvscraper: overview %s", overview.c_str());
+ esyslog("tvscraper: backdropPath %s", backdropPath.c_str());
+ esyslog("tvscraper: posterPath %s", posterPath.c_str());
+} \ No newline at end of file
diff --git a/themoviedbscraper/moviedbmovie.h b/themoviedbscraper/moviedbmovie.h
new file mode 100644
index 0000000..e1bd6d9
--- /dev/null
+++ b/themoviedbscraper/moviedbmovie.h
@@ -0,0 +1,37 @@
+#ifndef __TVSCRAPER_MOVIEDBMOVIE_H
+#define __TVSCRAPER_MOVIEDBMOVIE_H
+
+using namespace std;
+
+struct searchResult {
+ int id;
+ int distance;
+};
+
+// --- cMovieDbMovie -------------------------------------------------------------
+
+class cMovieDbMovie {
+private:
+ int id;
+ string json;
+ string title;
+ string originalTitle;
+ string overview;
+ string backdropPath;
+ string posterPath;
+ vector<searchResult> resultSet;
+ int FindBestResult(void);
+public:
+ cMovieDbMovie(string json);
+ virtual ~cMovieDbMovie(void);
+ int ParseJSONForMovieId(string movieSearchString);
+ void ParseJSON(void);
+ void SetID(int movieID) { id = movieID; };
+ int ID(void) { return id; };
+ void StoreDB(cTVScraperDB *db);
+ void StoreMedia(string posterBaseUrl, string backdropBaseUrl, string destDir);
+ void Dump();
+};
+
+
+#endif //__TVSCRAPER_TVDBSERIES_H
diff --git a/themoviedbscraper/themoviedbscraper.c b/themoviedbscraper/themoviedbscraper.c
new file mode 100644
index 0000000..2f9e7e9
--- /dev/null
+++ b/themoviedbscraper/themoviedbscraper.c
@@ -0,0 +1,151 @@
+#include <string>
+#include <sstream>
+#include <vector>
+#include <jansson.h>
+#include "themoviedbscraper.h"
+
+using namespace std;
+
+cMovieDBScraper::cMovieDBScraper(string baseDir, cTVScraperDB *db, string language) {
+ apiKey = "abb01b5a277b9c2c60ec0302d83c5ee9";
+ //TODO: use language from VDR settings
+ this->language = language;
+ baseURL = "api.themoviedb.org/3";
+ this->baseDir = baseDir;
+ this->db = db;
+ posterSize = "w500";
+ backdropSize = "w1280";
+ actorthumbSize = "h632";
+}
+
+cMovieDBScraper::~cMovieDBScraper() {
+}
+
+void cMovieDBScraper::Scrap(const cEvent *event, int recordingID) {
+ string movieName = event->Title();
+ int eventID = (int)event->EventID();
+ if (config.enableDebug)
+ esyslog("tvscraper: scrapping movie \"%s\"", movieName.c_str());
+ int movieID = SearchMovie(movieName);
+ if (movieID < 1) {
+ if (config.enableDebug)
+ esyslog("tvscraper: nothing found for \"%s\"", movieName.c_str());
+ return;
+ }
+ if (!recordingID) {
+ time_t validTill = event->EndTime();
+ db->InsertEventMovie(eventID, validTill, movieID);
+ } else {
+ db->InsertRecording(recordingID, 0, movieID);
+ }
+ if (db->MovieExists(movieID)) {
+ return;
+ }
+ cMovieDbMovie *movie = ReadMovie(movieID);
+ if (!movie)
+ return;
+ movie->StoreDB(db);
+ cMovieDbActors *actors = ReadActors(movieID);
+ if (!actors) {
+ delete movie;
+ return;
+ }
+ actors->StoreDB(db, movieID);
+ StoreMedia(movie, actors);
+ delete movie;
+ delete actors;
+ if (config.enableDebug)
+ esyslog("tvscraper: \"%s\" successfully scrapped, id %d", movieName.c_str(), movieID);
+}
+
+bool cMovieDBScraper::Connect(void) {
+ stringstream url;
+ url << baseURL << "/configuration?api_key=" << apiKey;
+ string configJSON;
+ if (CurlGetUrl(url.str().c_str(), &configJSON)) {
+ return parseJSON(configJSON);
+ }
+ return false;
+}
+
+bool cMovieDBScraper::parseJSON(string jsonString) {
+ json_t *root;
+ json_error_t error;
+
+ root = json_loads(jsonString.c_str(), 0, &error);
+ if (!root) {
+ return false;
+ }
+ if(!json_is_object(root)) {
+ return false;
+ }
+ json_t *images;
+ images = json_object_get(root, "images");
+ if(!json_is_object(images)) {
+ return false;
+ }
+
+ json_t *imgUrl;
+ imgUrl = json_object_get(images, "base_url");
+ if(!json_is_string(imgUrl)) {
+ return false;
+ }
+ imageUrl = json_string_value(imgUrl);
+ return true;
+}
+
+int cMovieDBScraper::SearchMovie(string movieName) {
+ stringstream movieEscaped;
+ movieEscaped << "\"" << movieName << "\"";
+ stringstream url;
+ url << baseURL << "/search/movie?api_key=" << apiKey << "&query=" << CurlEscape(movieEscaped.str().c_str()) << "&language=" << language.c_str();
+ string movieJSON;
+ int movieID = -1;
+ if (CurlGetUrl(url.str().c_str(), &movieJSON)) {
+ cMovieDbMovie *movie = new cMovieDbMovie(movieJSON);
+ movieID = movie->ParseJSONForMovieId(movieName);
+ delete movie;
+ }
+ return movieID;
+}
+
+cMovieDbMovie *cMovieDBScraper::ReadMovie(int movieID) {
+ stringstream url;
+ url << baseURL << "/movie/" << movieID << "?api_key=" << apiKey << "&language=" << language.c_str();
+ string movieJSON;
+ cMovieDbMovie *movie = NULL;
+ if (CurlGetUrl(url.str().c_str(), &movieJSON)) {
+ movie = new cMovieDbMovie(movieJSON);
+ movie->SetID(movieID);
+ movie->ParseJSON();
+ }
+ return movie;
+}
+
+cMovieDbActors *cMovieDBScraper::ReadActors(int movieID) {
+ stringstream url;
+ url << baseURL << "/movie/" << movieID << "/casts?api_key=" << apiKey;
+ string actorsJSON;
+ cMovieDbActors *actors = NULL;
+ if (CurlGetUrl(url.str().c_str(), &actorsJSON)) {
+ actors = new cMovieDbActors(actorsJSON);
+ actors->ParseJSON();
+ }
+ return actors;
+}
+
+void cMovieDBScraper::StoreMedia(cMovieDbMovie *movie, cMovieDbActors *actors) {
+ stringstream posterUrl;
+ posterUrl << imageUrl << posterSize;
+ stringstream backdropUrl;
+ backdropUrl << imageUrl << backdropSize;
+ stringstream destDir;
+ destDir << baseDir << "/";
+ movie->StoreMedia(posterUrl.str(), backdropUrl.str(), destDir.str());
+ stringstream actorsUrl;
+ actorsUrl << imageUrl << actorthumbSize;
+ stringstream actorsDestDir;
+ actorsDestDir << baseDir << "/actors";
+ CreateDirectory(actorsDestDir.str());
+ actors->Store(actorsUrl.str(), actorsDestDir.str());
+}
diff --git a/themoviedbscraper/themoviedbscraper.h b/themoviedbscraper/themoviedbscraper.h
new file mode 100644
index 0000000..54d463b
--- /dev/null
+++ b/themoviedbscraper/themoviedbscraper.h
@@ -0,0 +1,32 @@
+#ifndef __TVSCRAPER_MOVIEDBSCRAPER_H
+#define __TVSCRAPER_MOVIEDBSCRAPER_H
+
+using namespace std;
+
+// --- cMovieDBScraper -------------------------------------------------------------
+
+class cMovieDBScraper {
+private:
+ string apiKey;
+ string language;
+ string baseURL;
+ string baseDir;
+ string imageUrl;
+ string posterSize;
+ string backdropSize;
+ string actorthumbSize;
+ cTVScraperDB *db;
+ bool parseJSON(string jsonString);
+ int SearchMovie(string movieName);
+ cMovieDbMovie *ReadMovie(int movieID);
+ cMovieDbActors *ReadActors(int movieID);
+ void StoreMedia(cMovieDbMovie *movie, cMovieDbActors *actors);
+public:
+ cMovieDBScraper(string baseDir, cTVScraperDB *db, string language);
+ virtual ~cMovieDBScraper(void);
+ bool Connect(void);
+ void Scrap(const cEvent *event, int recordingID = 0);
+};
+
+
+#endif //__TVSCRAPER_MOVIEDBSCRAPER_H