com.moviejukebox.plugin.FanartTvPlugin.java Source code

Java tutorial

Introduction

Here is the source code for com.moviejukebox.plugin.FanartTvPlugin.java

Source

/*
 *      Copyright (c) 2004-2016 YAMJ Members
 *      https://github.com/orgs/YAMJ/people
 *
 *      This file is part of the Yet Another Movie Jukebox (YAMJ) project.
 *
 *      YAMJ is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      any later version.
 *
 *      YAMJ is distributed in the hope that it will be useful,
 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *      GNU General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with YAMJ.  If not, see <http://www.gnu.org/licenses/>.
 *
 *      Web: https://github.com/YAMJ/yamj-v2
 *
 */
package com.moviejukebox.plugin;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.moviejukebox.model.Movie;
import com.moviejukebox.tools.PropertiesUtil;
import com.moviejukebox.tools.StringTools;
import com.moviejukebox.tools.YamjHttpClientBuilder;
import com.moviejukebox.tools.cache.CacheMemory;
import com.omertron.fanarttvapi.FanartTvApi;
import com.omertron.fanarttvapi.FanartTvException;
import com.omertron.fanarttvapi.enumeration.FTArtworkType;
import com.omertron.fanarttvapi.enumeration.FTSourceType;
import com.omertron.fanarttvapi.model.ArtworkList;
import com.omertron.fanarttvapi.model.FTArtwork;
import com.omertron.fanarttvapi.model.FTMovie;
import com.omertron.fanarttvapi.model.FTSeries;

public class FanartTvPlugin {

    private static final Logger LOG = LoggerFactory.getLogger(FanartTvPlugin.class);
    public static final String FANARTTV_PLUGIN_ID = "fanarttv";
    private static final String API_KEY = PropertiesUtil.getProperty("API_KEY_FanartTv");
    private FanartTvApi ft;
    private static final Map<FTArtworkType, Integer> ARTWORK_TYPES = new EnumMap<>(FTArtworkType.class);
    private int totalRequiredTv = 0;
    private int totalRequireMovie = 0;
    private static final String DEFAULT_LANGUAGE = "en";
    private static final String LANG_MOVIE = getMovieLanguage();
    private static final String LANG_TV = getTvLanguage();

    static {
        // Read the properties for the artwork required and the quantities

        // The propery name should be named like: "{artworkType}.{artworkSource}.download", e.g. clearart.tv.download
        StringBuilder artworkPropertyName;
        for (FTArtworkType artworkType : EnumSet.allOf(FTArtworkType.class)) {
            artworkPropertyName = new StringBuilder(artworkType.toString().toLowerCase());
            artworkPropertyName.append('.');
            artworkPropertyName.append(artworkType.getSourceType().toString().toLowerCase());
            artworkPropertyName.append(".download");

            if (PropertiesUtil.getBooleanProperty(artworkPropertyName.toString(), Boolean.FALSE)) {
                ARTWORK_TYPES.put(artworkType, 1);
                LOG.debug("{} required", artworkPropertyName);
            } else {
                LOG.debug("{} not required", artworkPropertyName);
            }
        }

        if (ARTWORK_TYPES.isEmpty()) {
            LOG.debug("No Fanart.TV artwork required.");
        } else {
            LOG.debug("Looking for {} Fanart.TV Types", ARTWORK_TYPES.toString());
        }
    }

    public FanartTvPlugin() {
        try {
            this.ft = new FanartTvApi(API_KEY, null, YamjHttpClientBuilder.getHttpClient());
        } catch (FanartTvException ex) {
            LOG.warn("Failed to initialise FanartTV API: {}", ex.getMessage(), ex);
            return;
        }

        // Calculate the required number of artworks (Only do it once though)
        if (totalRequireMovie + totalRequiredTv == 0) {
            for (FTArtworkType key : ARTWORK_TYPES.keySet()) {
                if (key.getSourceType() == FTSourceType.MOVIE) {
                    totalRequireMovie += ARTWORK_TYPES.get(key);
                } else if (key.getSourceType() == FTSourceType.TV) {
                    totalRequiredTv += ARTWORK_TYPES.get(key);
                } else {
                    LOG.trace("Skipped artwork type '{}' as its source type is '{}' and not required", key,
                            key.getSourceType());
                }
            }
        }
    }

    /**
     * Scan and return all artwork types (Defaults type to null)
     *
     * @param movie
     * @return
     */
    public boolean scan(Movie movie) {
        return scan(movie, null);
    }

    /**
     * Scan and return the artwork type requested (or all if type is null)
     *
     * @param movie
     * @param artworkType Artwork type required (null is all)
     * @return
     */
    public boolean scan(Movie movie, final FTArtworkType artworkType) {
        if (artworkType != null && !ARTWORK_TYPES.containsKey(artworkType)) {
            LOG.debug("{} not required", artworkType.toString().toLowerCase());
            return true;
        }

        ArtworkList ftArtwork;
        String requiredLanguage;

        Map<FTArtworkType, Integer> requiredArtworkTypes = new EnumMap<>(ARTWORK_TYPES);

        if (movie.isTVShow()) {
            int tvdbid = NumberUtils.toInt(movie.getId(TheTvDBPlugin.THETVDB_PLUGIN_ID), 0);

            // Remove the non-TV types
            for (FTArtworkType at : requiredArtworkTypes.keySet()) {
                if (at.getSourceType() != FTSourceType.TV) {
                    requiredArtworkTypes.remove(at);
                }
            }

            // Get all the artwork to speed up any subsequent requests
            ftArtwork = getTvArtwork(tvdbid);
            requiredLanguage = LANG_TV;
        } else {
            int tmdbId = NumberUtils.toInt(movie.getId(TheMovieDbPlugin.TMDB_PLUGIN_ID), 0);

            // Remove the non-Movie types
            for (FTArtworkType at : requiredArtworkTypes.keySet()) {
                if (at.getSourceType() != FTSourceType.MOVIE) {
                    requiredArtworkTypes.remove(at);
                }
            }

            // Get all the artwork to speed up any subsequent requests
            ftArtwork = getMovieArtwork(tmdbId, movie.getId(ImdbPlugin.IMDB_PLUGIN_ID));
            requiredLanguage = LANG_MOVIE;
        }

        if (ftArtwork.hasArtwork()) {
            LOG.debug("Found {} artwork items", ftArtwork.getArtwork().size());

            FTArtworkType ftType;

            for (Map.Entry<FTArtworkType, List<FTArtwork>> entry : ftArtwork.getArtwork().entrySet()) {
                LOG.trace("Found '{}' with {} items", entry.getKey(), entry.getValue().size());
                ftType = entry.getKey();

                if (requiredArtworkTypes.containsKey(ftType) && requiredArtworkTypes.get(ftType) > 0) {
                    LOG.trace("Processing '{}' artwork, {} are requried", entry.getKey(),
                            requiredArtworkTypes.get(ftType));
                    int left = processArtworkToMovie(movie, ftType, requiredLanguage,
                            requiredArtworkTypes.get(ftType), entry.getValue());
                    // Update the required artwork counter
                    requiredArtworkTypes.put(ftType, left);
                    // remove the count from the requiredQuantity
                }
            }

            int requiredQuantity = 0;
            for (Map.Entry<FTArtworkType, Integer> entry : requiredArtworkTypes.entrySet()) {
                requiredQuantity += entry.getValue();
            }

            if (requiredQuantity > 0) {
                LOG.debug("Not all required artwork was found for '{}' - {}", movie.getBaseName(),
                        requiredArtworkTypes.toString());
                return false;
            }
            LOG.debug("All required artwork was found for '{}'", movie.getBaseName());
            return true;
        }
        LOG.debug("No artwork found for {}", movie.getBaseName());
        return false;
    }

    /**
     * Process the artwork into the movie URLs
     *
     * @param movie Movie to add the artwork to
     * @param ftType Type of the artwork
     * @param reqAmount Number of items required
     * @param artworkList List of the artwork found on Fanart.TV
     * @return artwork remaining to be found
     */
    private static int processArtworkToMovie(Movie movie, FTArtworkType ftType, final String reqLanguage,
            int reqAmount, final List<FTArtwork> artworkList) {
        LOG.trace("Getting {} of '{}' artwork, there are {} available, looking for '{}' language", reqAmount,
                ftType, artworkList.size(), reqLanguage);

        int remaining = reqAmount;

        for (FTArtwork artwork : artworkList) {
            LOG.trace("Artwork: {}", artwork);
            // send to function to add to movie
            if (reqLanguage.equalsIgnoreCase(artwork.getLanguage()) && addArtworkToMovie(movie, ftType, artwork)) {
                remaining--;
                if (remaining > 0) {
                    LOG.trace("{} has {} remaining", ftType, remaining);
                } else {
                    LOG.trace("All artwork for {} found.", ftType);
                    break;
                }
            }
        }

        return remaining;
    }

    /**
     * Add the artwork URL to the movie
     *
     * @param movie
     * @param ftType
     * @param artwork
     * @return
     */
    private static boolean addArtworkToMovie(Movie movie, FTArtworkType ftType, FTArtwork artwork) {
        boolean success;
        LOG.debug("Adding {} to movie '{}' with URL {}", ftType, movie.getBaseName(), artwork.getUrl());

        switch (ftType) {
        case CLEARART:
            movie.setClearArtURL(artwork.getUrl());
            success = true;
            break;
        case CLEARLOGO:
            movie.setClearLogoURL(artwork.getUrl());
            success = true;
            break;
        case SEASONTHUMB:
            success = checkSeason(artwork, movie);
            break;
        case TVTHUMB:
            movie.setTvThumbURL(artwork.getUrl());
            success = true;
            break;
        case MOVIEART:
            movie.setClearArtURL(artwork.getUrl());
            success = true;
            break;
        case MOVIEDISC:
            movie.setMovieDiscURL(artwork.getUrl());
            success = true;
            break;
        case MOVIELOGO:
            movie.setClearLogoURL(artwork.getUrl());
            success = true;
            break;
        default:
            LOG.trace("Unrecognised artwork type '{}', ignoring.", ftType.toString().toLowerCase());
            success = false;
        }

        return success;
    }

    /**
     * Check the artwork is for the correct season and update it if necessary
     *
     * @param artwork
     * @param movie
     * @return
     */
    private static boolean checkSeason(FTArtwork artwork, Movie movie) {
        boolean success;
        // Check this is the right season
        if (NumberUtils.toInt(artwork.getSeason(), -1) == movie.getSeason()) {
            movie.setSeasonThumbURL(artwork.getUrl());
            success = true;
        } else {
            success = false;
        }
        return success;
    }

    /**
     * Get artwork for the TV
     *
     * @param tvdbId
     * @return
     */
    public FTSeries getTvArtwork(int tvdbId) {
        String key = CacheMemory.generateCacheKey(FANARTTV_PLUGIN_ID, String.valueOf(tvdbId));

        FTSeries ftArtwork = (FTSeries) CacheMemory.getFromCache(key);
        if (ftArtwork == null || ftArtwork.hasArtwork()) {
            try {
                ftArtwork = ft.getTvArtwork(Integer.toString(tvdbId));

                if (ftArtwork != null && ftArtwork.hasArtwork()) {
                    CacheMemory.addToCache(key, ftArtwork);
                }

                return ftArtwork;
            } catch (FanartTvException ex) {
                LOG.warn("Failed to get fanart information for TVDB ID: {}. Error: {}", tvdbId, ex.getMessage(),
                        ex);
                return new FTSeries();
            }
        }
        return ftArtwork;
    }

    /**
     * Get artwork for the Movie
     *
     * @param tmdbId
     * @param imdbId
     * @return
     */
    public FTMovie getMovieArtwork(int tmdbId, String imdbId) {
        String key;

        if (StringTools.isValidString(imdbId)) {
            key = CacheMemory.generateCacheKey(FANARTTV_PLUGIN_ID, imdbId);
        } else if (tmdbId > 0) {
            key = CacheMemory.generateCacheKey(FANARTTV_PLUGIN_ID, Integer.toString(tmdbId));
        } else {
            // No valid ID provided, so quit.
            return new FTMovie();
        }

        FTMovie ftArtwork = (FTMovie) CacheMemory.getFromCache(key);

        // If we get nothing back from the cache or it's empty, check for artwork
        if (ftArtwork == null || !ftArtwork.hasArtwork()) {
            try {
                if (StringTools.isValidString(imdbId)) {
                    ftArtwork = ft.getMovieArtwork(imdbId);
                } else {
                    ftArtwork = ft.getMovieArtwork(Integer.toString(tmdbId));
                }

                if (ftArtwork != null && ftArtwork.hasArtwork()) {
                    CacheMemory.addToCache(key, ftArtwork);
                }

                return ftArtwork;
            } catch (FanartTvException ex) {
                LOG.warn("Failed to get fanart information for IMDB ID: {} / TMDB ID: {}. Error: {}", imdbId,
                        tmdbId, ex.getMessage(), ex);
                return new FTMovie();
            }
        }
        return ftArtwork;
    }

    /**
     * Determine if artwork is required
     *
     * @param requiredType
     * @return
     */
    public static boolean isArtworkRequired(FTArtworkType requiredType) {
        if (ARTWORK_TYPES.containsKey(requiredType)) {
            return ARTWORK_TYPES.get(requiredType) > 0;
        }
        // Not found, so not required
        LOG.warn("{} is not a valid Fanart.TV type", requiredType);
        return false;
    }

    /**
     * Determine if artwork is required
     *
     * @param artworkType
     * @return
     */
    public static boolean isArtworkRequired(String artworkType) {
        FTArtworkType requiredType;
        try {
            requiredType = FTArtworkType.fromString(artworkType);
        } catch (IllegalArgumentException ex) {
            LOG.warn("{} is not a valid Fanart.TV type", artworkType);
            return false;
        }

        return isArtworkRequired(requiredType);
    }

    /**
     * Get the language for the Movie search.
     *
     * Default to the fanart.tv setting and then try themoviedb setting
     *
     * @return
     */
    private static String getMovieLanguage() {
        String language = PropertiesUtil.getProperty("fanarttv.movie.language", "");
        if (StringUtils.isBlank(language)) {
            language = PropertiesUtil.getProperty("themoviedb.language", DEFAULT_LANGUAGE);
        }
        return language;
    }

    /**
     * Get the kanguage for the TV Search
     *
     * Default to the fanart.tv setting and then try thetvdb setting
     *
     * @return
     */
    private static String getTvLanguage() {
        String language = PropertiesUtil.getProperty("fanarttv.tv.language", "");
        if (StringUtils.isBlank(language)) {
            language = PropertiesUtil.getProperty("thetvdb.language", DEFAULT_LANGUAGE);
        }
        return language;
    }
}