Skip to content

Commit

Permalink
refactor(MovieScraper): Move to job-based movie loading
Browse files Browse the repository at this point in the history
Just like for TV scrapers

TODO:

 - Custommovie Scraper: Scraping works, but details are lost
  • Loading branch information
bugwelle committed Feb 7, 2023
1 parent ebc6a53 commit 965dd46
Show file tree
Hide file tree
Showing 66 changed files with 1,612 additions and 1,859 deletions.
5 changes: 4 additions & 1 deletion MediaElch.pro
Original file line number Diff line number Diff line change
Expand Up @@ -265,17 +265,18 @@ SOURCES += src/main.cpp \
src/scrapers/movie/aebn/AebnScrapeJob.cpp \
src/scrapers/movie/aebn/AebnSearchJob.cpp \
src/scrapers/movie/custom/CustomMovieScraper.cpp \
src/scrapers/movie/custom/CustomMovieScrapeJob.cpp \
src/scrapers/movie/hotmovies/HotMovies.cpp \
src/scrapers/movie/hotmovies/HotMoviesApi.cpp \
src/scrapers/movie/hotmovies/HotMoviesScrapeJob.cpp \
src/scrapers/movie/hotmovies/HotMoviesSearchJob.cpp \
src/scrapers/movie/imdb/ImdbMovie.cpp \
src/scrapers/movie/imdb/ImdbMovieScraper.cpp \
src/scrapers/movie/imdb/ImdbMovieScrapeJob.cpp \
src/scrapers/movie/imdb/ImdbMovieSearchJob.cpp \
src/scrapers/movie/MovieIdentifier.cpp \
src/scrapers/movie/MovieScraper.cpp \
src/scrapers/movie/MovieSearchJob.cpp \
src/scrapers/movie/MovieMerger.cpp \
src/scrapers/movie/MovieScrapeJob.cpp \
src/scrapers/movie/tmdb/TmdbMovie.cpp \
src/scrapers/movie/tmdb/TmdbMovieSearchJob.cpp \
Expand Down Expand Up @@ -623,6 +624,7 @@ HEADERS += Version.h \
src/scrapers/movie/aebn/AebnSearchJob.h \
src/scrapers/movie/aebn/AebnScrapeJob.h \
src/scrapers/movie/custom/CustomMovieScraper.h \
src/scrapers/movie/custom/CustomMovieScrapeJob.h \
src/scrapers/movie/hotmovies/HotMovies.h \
src/scrapers/movie/hotmovies/HotMoviesApi.h \
src/scrapers/movie/hotmovies/HotMoviesSearchJob.h \
Expand All @@ -633,6 +635,7 @@ HEADERS += Version.h \
src/scrapers/movie/imdb/ImdbMovieScrapeJob.h \
src/scrapers/movie/MovieIdentifier.h \
src/scrapers/movie/MovieScraper.h \
src/scrapers/movie/MovieMerger.h \
src/scrapers/movie/MovieSearchJob.h \
src/scrapers/movie/MovieScrapeJob.h \
src/scrapers/movie/tmdb/TmdbMovie.h \
Expand Down
82 changes: 44 additions & 38 deletions src/data/movie/MovieController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
#include "media/NameFormatter.h"
#include "media_center/MediaCenterInterface.h"
#include "network/DownloadManager.h"
#include "scrapers/movie/MovieMerger.h"
#include "scrapers/movie/MovieScraper.h"
#include "scrapers/movie/custom/CustomMovieScrapeJob.h"
#include "scrapers/movie/custom/CustomMovieScraper.h"
#include "scrapers/movie/imdb/ImdbMovie.h"
#include "scrapers/movie/tmdb/TmdbMovie.h"
Expand Down Expand Up @@ -145,29 +147,52 @@ bool MovieController::loadData(MediaCenterInterface* mediaCenterInterface, bool
}

void MovieController::loadData(QHash<mediaelch::scraper::MovieScraper*, mediaelch::scraper::MovieIdentifier> ids,
mediaelch::scraper::MovieScraper* scraperInterface,
QSet<MovieScraperInfo> infos)
const mediaelch::Locale& locale,
const QSet<MovieScraperInfo>& details)
{
if (ids.isEmpty()) {
return;
}
using namespace mediaelch::scraper;

emit sigLoadStarted(m_movie);

const auto scraper = scraperInterface->meta().identifier;
const auto firstId = ids.constBegin()->str();
const bool isImdbId = ImdbId::isValidFormat(firstId);
m_infosToLoad = details;

const MovieIdentifier id = ids.constBegin().value();

MovieScrapeJob::Config config;
config.details = details;
config.locale = locale;
config.identifier = id;

MovieScraper* scraper = nullptr;
MovieScrapeJob* scrapeJob = nullptr;

m_infosToLoad = infos;
if (ids.size() > 1) {
// Requires custom movie scraper
scraper = CustomMovieScraper::instance();
scrapeJob = scraper->loadMovie(config);
static_cast<CustomMovieScrapeJob*>(scrapeJob)->setScraperMovieIds(std::move(ids));

if (scraper == mediaelch::scraper::TmdbMovie::ID && !isImdbId) {
m_movie->setTmdbId(TmdbId(firstId));
} else {
scraper = ids.constBegin().key();
const auto scraperId = scraper->meta().identifier;
const bool isImdbId = ImdbId::isValidFormat(id.str());

if (scraperId == TmdbMovie::ID && !isImdbId) {
m_movie->setTmdbId(TmdbId(id.str()));

} else if (scraper == mediaelch::scraper::ImdbMovie::ID
|| (scraper == mediaelch::scraper::TmdbMovie::ID && isImdbId)) {
m_movie->setImdbId(ImdbId(firstId));
} else if (scraperId == ImdbMovie::ID || (scraperId == TmdbMovie::ID && isImdbId)) {
m_movie->setImdbId(ImdbId(id.str()));
}

scrapeJob = scraper->loadMovie(config);
}
scraperInterface->loadData(ids, m_movie, infos);

connect(scrapeJob, &MovieScrapeJob::loadFinished, this, [this, scraper](MovieScrapeJob* job) { //
job->deleteLater();
copyDetailsToMovie(*m_movie, job->movie(), job->config().details);
scraperLoadDone(scraper, job);
});
scrapeJob->start();
}

bool MovieController::loadStreamDetailsFromFile()
Expand Down Expand Up @@ -197,19 +222,15 @@ void MovieController::setInfosToLoad(QSet<MovieScraperInfo> infos)
m_infosToLoad = std::move(infos);
}

void MovieController::scraperLoadDone(mediaelch::scraper::MovieScraper* scraper, mediaelch::ScraperError error)
void MovieController::scraperLoadDone(mediaelch::scraper::MovieScraper* scraper,
mediaelch::scraper::MovieScrapeJob* job)
{
using namespace std::chrono_literals;

if (error.hasError() && !error.is404()) {
if (job->hasError() && !job->scraperError().is404()) {
// TODO: 404 not necessary but avoids false positives at the moment.
// TODO: Remove UI dependency
NotificationBox::instance()->showError(error.message, 6s);
}

if (!property("customMovieScraperLoads").isNull() && property("customMovieScraperLoads").toInt() > 1) {
setProperty("customMovieScraperLoads", property("customMovieScraperLoads").toInt() - 1);
return;
NotificationBox::instance()->showError(job->errorString(), 6s);
}

setProperty("customMovieScraperLoads", QVariant());
Expand Down Expand Up @@ -443,21 +464,6 @@ void MovieController::abortDownloads()
emit sigLoadDone(m_movie);
}

void MovieController::setLoadsLeft(QVector<ScraperData> loadsLeft)
{
m_loadDoneFired = false;
m_loadsLeft = loadsLeft;
}

void MovieController::removeFromLoadsLeft(ScraperData load)
{
m_loadsLeft.removeOne(load);
if (m_loadsLeft.isEmpty() && !m_loadDoneFired) {
m_loadDoneFired = true;
scraperLoadDone(Manager::instance()->scrapers().movieScraper(mediaelch::scraper::TmdbMovie::ID), {});
}
}

void MovieController::setForceFanartBackdrop(const bool& force)
{
m_forceFanartBackdrop = force;
Expand Down
18 changes: 7 additions & 11 deletions src/data/movie/MovieController.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#pragma once

#include "data/Locale.h"
#include "data/Poster.h"
#include "network/DownloadManagerElement.h"
#include "scrapers/ScraperError.h"
#include "scrapers/ScraperInfos.h"
#include "scrapers/movie/MovieIdentifier.h"

Expand All @@ -17,7 +17,8 @@ class Movie;
namespace mediaelch {
namespace scraper {
class MovieScraper;
}
class MovieScrapeJob;
} // namespace scraper
} // namespace mediaelch

class MovieController : public QObject
Expand All @@ -37,19 +38,16 @@ class MovieController : public QObject
/// \return Loading was successful or not
bool loadData(MediaCenterInterface* mediaCenterInterface, bool force = false, bool reloadFromNfo = true);

/// \brief Loads the movies info from a scraper
/// \param ids Id of the movie within the given ScraperInterface
/// \param scraperInterface ScraperInterface to use for loading
/// \param infos List of infos to load
/// \brief Loads the movies info from a scraper. If ids has more than one entry, the custom movie scraper is used.
void loadData(QHash<mediaelch::scraper::MovieScraper*, mediaelch::scraper::MovieIdentifier> ids,
mediaelch::scraper::MovieScraper* scraperInterface,
QSet<MovieScraperInfo> infos);
const mediaelch::Locale& locale,
const QSet<MovieScraperInfo>& details);

ELCH_NODISCARD bool loadStreamDetailsFromFile();

/// \brief Called when a ScraperInterface has finished loading
/// Emits the loaded signal
void scraperLoadDone(mediaelch::scraper::MovieScraper* scraper, mediaelch::ScraperError error);
void scraperLoadDone(mediaelch::scraper::MovieScraper* scraper, mediaelch::scraper::MovieScrapeJob* scrapeJob);

QSet<MovieScraperInfo> infosToLoad();

Expand All @@ -64,8 +62,6 @@ class MovieController : public QObject
void loadImage(ImageType type, QUrl url);
void loadImages(ImageType type, QVector<QUrl> urls);
void abortDownloads();
void setLoadsLeft(QVector<ScraperData> loadsLeft);
void removeFromLoadsLeft(ScraperData load);
void setInfosToLoad(QSet<MovieScraperInfo> infos);
void setForceFanartBackdrop(const bool& force);
void setForceFanartPoster(const bool& force);
Expand Down
11 changes: 0 additions & 11 deletions src/globals/ScraperManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,6 @@ const QVector<mediaelch::scraper::MusicScraper*>& ScraperManager::musicScrapers(
return m_musicScrapers;
}

QVector<mediaelch::scraper::MovieScraper*> ScraperManager::constructNativeScrapers(QObject* scraperParent)
{
using namespace mediaelch::scraper;

QVector<MovieScraper*> scrapers;
scrapers.append(new TmdbMovie(scraperParent));
scrapers.append(new ImdbMovie(scraperParent));
scrapers.append(new VideoBuster(scraperParent));
return scrapers;
}

void ScraperManager::initMovieScrapers()
{
using namespace mediaelch::scraper;
Expand Down
2 changes: 0 additions & 2 deletions src/globals/ScraperManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ class ScraperManager : public QObject
ELCH_NODISCARD mediaelch::scraper::ConcertScraper* concertScraper(const QString& identifier);
ELCH_NODISCARD mediaelch::scraper::TvScraper* tvScraper(const QString& identifier);

ELCH_NODISCARD static QVector<mediaelch::scraper::MovieScraper*> constructNativeScrapers(QObject* scraperParent);

private:
void initMovieScrapers();
void initTvScrapers();
Expand Down
1 change: 1 addition & 0 deletions src/scrapers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ add_library(
concert/tmdb/TmdbConcert.cpp
concert/tmdb/TmdbConcertSearchJob.cpp
movie/MovieIdentifier.cpp
movie/MovieMerger.cpp
movie/MovieScraper.cpp
movie/MovieScrapeJob.cpp
movie/MovieSearchJob.cpp
Expand Down
58 changes: 30 additions & 28 deletions src/scrapers/image/TMDbImages.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "TMDbImages.h"

#include "scrapers/movie/MovieMerger.h"
#include "scrapers/movie/tmdb/TmdbMovie.h"
#include "settings/Settings.h"

Expand Down Expand Up @@ -102,9 +103,6 @@ TMDbImages::TMDbImages(QObject* parent) : ImageProvider(parent)

m_searchResultLimit = 0;
m_tmdb = new mediaelch::scraper::TmdbMovie(this);
m_dummyMovie = new Movie({}, this);

connect(m_dummyMovie->controller(), &MovieController::sigInfoLoadDone, this, &TMDbImages::onLoadImagesFinished);
}

const ImageProvider::ScraperMeta& TMDbImages::meta() const
Expand Down Expand Up @@ -160,32 +158,32 @@ void TMDbImages::onSearchMovieFinished(mediaelch::scraper::MovieSearchJob* searc
emit sigSearchDone(results, searchJob->scraperError());
}

/**
* \brief Load movie posters
*/
void TMDbImages::moviePosters(TmdbId tmdbId)
{
m_dummyMovie->clear();
m_imageType = ImageType::MoviePoster;
QSet<MovieScraperInfo> infos;
infos << MovieScraperInfo::Poster;
QHash<mediaelch::scraper::MovieScraper*, mediaelch::scraper::MovieIdentifier> ids;
ids.insert(nullptr, MovieIdentifier(tmdbId));
m_tmdb->loadData(ids, m_dummyMovie, infos);
using namespace mediaelch::scraper;

MovieScrapeJob::Config config;
config.identifier = MovieIdentifier(tmdbId);
config.details = {MovieScraperInfo::Poster};
config.locale = m_tmdb->meta().defaultLocale;

auto* scrapeJob = m_tmdb->loadMovie(config);
connect(scrapeJob, &MovieScrapeJob::loadFinished, this, &TMDbImages::onMovieLoadImagesFinished);
scrapeJob->start();
}

/**
* \brief Load movie backdrops
*/
void TMDbImages::movieBackdrops(TmdbId tmdbId)
{
m_dummyMovie->clear();
m_imageType = ImageType::MovieBackdrop;
QSet<MovieScraperInfo> infos;
infos << MovieScraperInfo::Backdrop;
QHash<mediaelch::scraper::MovieScraper*, mediaelch::scraper::MovieIdentifier> ids;
ids.insert(nullptr, MovieIdentifier(tmdbId));
m_tmdb->loadData(ids, m_dummyMovie, infos);
using namespace mediaelch::scraper;

MovieScrapeJob::Config config;
config.identifier = MovieIdentifier(tmdbId);
config.details = {MovieScraperInfo::Backdrop};
config.locale = m_tmdb->meta().defaultLocale;

auto* scrapeJob = m_tmdb->loadMovie(config);
connect(scrapeJob, &MovieScrapeJob::loadFinished, this, &TMDbImages::onMovieLoadImagesFinished);
scrapeJob->start();
}

void TMDbImages::concertPosters(TmdbId tmdbId)
Expand All @@ -201,13 +199,17 @@ void TMDbImages::concertBackdrops(TmdbId tmdbId)
/**
* \brief Called when the movie images are downloaded
*/
void TMDbImages::onLoadImagesFinished()
void TMDbImages::onMovieLoadImagesFinished(mediaelch::scraper::MovieScrapeJob* job)
{
auto dls = makeDeleteLaterScope(job);

QVector<Poster> posters;
if (m_imageType == ImageType::MovieBackdrop) {
posters = m_dummyMovie->images().backdrops();
} else if (m_imageType == ImageType::MoviePoster) {
posters = m_dummyMovie->images().posters();
const QSet<MovieScraperInfo>& details = job->config().details;
if (details.contains(MovieScraperInfo::Backdrop)) {
posters = job->movie().images().backdrops();

} else if (details.contains(MovieScraperInfo::Poster)) {
posters = job->movie().images().posters();
}

emit sigImagesLoaded(posters, {});
Expand Down
7 changes: 3 additions & 4 deletions src/scrapers/image/TMDbImages.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,14 @@ public slots:

private slots:
void onSearchMovieFinished(mediaelch::scraper::MovieSearchJob* searchJob);
void onLoadImagesFinished();
void onMovieLoadImagesFinished(mediaelch::scraper::MovieScrapeJob* job);

private:
ScraperMeta m_meta;

int m_searchResultLimit = 0;
mediaelch::scraper::TmdbMovie* m_tmdb = nullptr;
Movie* m_dummyMovie = nullptr;
ImageType m_imageType = ImageType::None;

int m_searchResultLimit = 0;
};

} // namespace scraper
Expand Down

0 comments on commit 965dd46

Please sign in to comment.