Home Manual Reference Source Test Repository

src/providers/helpers/moviehelper.js

// Import the neccesary modules.
import asyncq from "async-q";

import Movie from "../../models/Movie";
import Util from "../../util";
import { fanart, omdb, tmdb, trakt } from "../../config/constants";

/** Class for saving movies. */
export default class Helper {

  /**
   * Create an helper object for movie content.
   * @param {String} name - The name of the content provider.
   */
  constructor(name) {
    /**
     * The name of the torrent provider.
     * @type {String}
     */
    this.name = name;

    /**
     * The util object with general functions.
     * @type {Util}
     */
    this._util = new Util();
  }

  /**
   * Update the torrents for an existing movie.
   * @param {Movie} movie - The new movie.
   * @param {Movie} found - The existing movie.
   * @param {String} language - The language of the torrent.
   * @param {String} quality - The quality of the torrent.
   * @return {Movie} - A movie with merged torrents.
   */
  _updateTorrent(movie, found, language, quality) {
    let update = false;

    if (found.torrents[language] && movie.torrents[language]) {
      if (found.torrents[language][quality] && movie.torrents[language][quality]) {
        if (found.torrents[language][quality].seed > movie.torrents[language][quality].seed) {
          update = true;
        } else if (movie.torrents[language][quality].seed > found.torrents[language][quality].seed) {
          update = false;
        } else if (found.torrents[language][quality].url === movie.torrents[language][quality].url) {
          update = true;
        }
      } else if (found.torrents[language][quality] && !movie.torrents[language][quality]) {
        update = true;
      }
    } else if (found.torrents[language] && !movie.torrents[language]) {
      if (found.torrents[language][quality]) {
        movie.torrents[language] = {};
        update = true;
      }
    }

    if (update) movie.torrents[language][quality] = found.torrents[language][quality];
    return movie;
  }

  /**
   * @description Update a given movie.
   * @function Helper#updateMovie
   * @memberof module:providers/movie/helper
   * @param {Movie} movie - The movie to update its torrent.
   * @returns {Movie} - A newly updated movie.
   */
  async _updateMovie(movie) {
    try {
      const found = await Movie.findOne({
        _id: movie._id
      }).exec();
      if (found) {
        logger.info(`${this.name}: '${found.title}' is an existing movie.`);

        if (found.torrents) {
          Object.keys(found.torrents).forEach(language => {
            movie = this._updateTorrent(movie, found, language, "720p");
            movie = this._updateTorrent(movie, found, language, "1080p");
          });
        }

        return await Movie.findOneAndUpdate({
          _id: movie._id
        }, movie).exec();
      } else {
        logger.info(`${this.name}: '${movie.title}' is a new movie!`);
        return await new Movie(movie).save();
      }
    } catch (err) {
      return this._util.onError(err);
    }
  }

  /**
   * Adds torrents to a movie.
   * @param {Movie} movie - The movie to add the torrents to.
   * @param {Object} torrents - The torrents to add to the movie.
   * @returns {Movie} - A movie with torrents attached.
   */
  addTorrents(movie, torrents) {
    return asyncq.each(Object.keys(torrents), torrent => movie.torrents[torrent] = torrents[torrent])
      .then(() => this._updateMovie(movie));
  }

  /**
   * Get images from themoviedb.org or omdbapi.com.
   * @param {Integer} tmdb_id - The tmdb id of the movie you want the images from.
   * @param {String} imdb_id - The imdb id of the movie you want the images from.
   * @returns {Object} - Object with a banner, fanart and poster images.
   */
  async _getImages(tmdb_id, imdb_id) {
    const holder = "images/posterholder.png"
    const images = {
      banner: holder,
      fanart: holder,
      poster: holder
    };

    try {
      const tmdbData = await tmdb.call(`/movie/${tmdb_id}/images`, {});

      let tmdbPoster = tmdbData['posters'].filter(poster => poster.iso_639_1 === "en" || poster.iso_639_1 === null)[0]
      tmdbPoster = tmdb.getImageUrl(tmdbPoster.file_path, 'w500');

      let tmdbBackdrop = tmdbData['backdrops'].filter(backdrop => backdrop.iso_639_1 === "en" || backdrop.iso_639_1 === null)[0];
      tmdbBackdrop = tmdb.getImageUrl(tmdbBackdrop.file_path, 'w500');

      images.banner = tmdbPoster ? tmdbPoster : holder;
      images.fanart = tmdbBackdrop ? tmdbBackdrop : holder;
      images.poster = tmdbPoster ? tmdbPoster : holder;
    } catch (err) {
      try {
        const omdbImages = await omdb.byID({
          imdb: imdb_id,
          type: "movie"
        });
        images.banner = omdbImages.Poster ? omdbImages.Poster : holder;
        images.fanart = omdbImages.Poster? omdbImages.Poster : holder;
        images.poster = omdbImages.Poster ? omdbImages.Poster : holder;
      } catch (err) {
        try {
          const fanartImages = await fanart.getMovieImages(tmdb_id);
          images.banner = fanartImages.moviebanner ? fanartImages.moviebanner[0].url : holder;
          images.fanart = fanartImages.moviebackground ? fanartImages.moviebackground[0].url : fanartImages.hdmovieclearart ? fanartImages.hdmovieclearart[0].url : holder;
          images.poster = fanartImages.movieposter ? fanartImages.movieposter[0].url : holder;
        } catch (err) {
          return this._util.onError(`Images: Could not find images on: ${err.path || err} with id: '${tmdb_id || imdb_id}'`);
        }
      }
    }

    return images;
  }

  /**
   * Get info from Trakt and make a new movie object.
   * @param {String} slug - The slug to query trakt.tv.
   * @returns {Movie} - A new movie.
   */
  async getTraktInfo(slug) {
    try {
      const traktMovie = await trakt.movies.summary({
        id: slug,
        extended: "full"
      });
      const traktWatchers = await trakt.movies.watching({id: slug});

      let watching = 0;
      if (traktWatchers !== null) watching = traktWatchers.length;

      if (traktMovie && traktMovie.ids["imdb"] && traktMovie.ids["tmdb"]) {
        return {
          _id: traktMovie.ids["imdb"],
          imdb_id: traktMovie.ids["imdb"],
          title: traktMovie.title,
          year: traktMovie.year,
          slug: traktMovie.ids["slug"],
          synopsis: traktMovie.overview,
          runtime: traktMovie.runtime,
          rating: {
            hated: 100,
            loved: 100,
            votes: traktMovie.votes,
            watching: watching,
            percentage: Math.round(traktMovie.rating * 10)
          },
          country: traktMovie.language,
          last_updated: Number(new Date()),
          images: await this._getImages(traktMovie.ids["tmdb"], traktMovie.ids["imdb"]),
          genres: traktMovie.genres !== null ? traktMovie.genres : ["unknown"],
          released: new Date(traktMovie.released).getTime() / 1000.0,
          trailer: traktMovie.trailer || null,
          certification: traktMovie.certification,
          torrents: {}
        };
      }
    } catch (err) {
      return this._util.onError(`Trakt: Could not find any data on: ${err.path || err} with slug: '${slug}'`);
    }
  }

}