Search in sources :

Example 1 with BaseShow

use of com.uwetrottmann.trakt5.entities.BaseShow in project SeriesGuide by UweTrottmann.

the class TvdbTools method addShow.

/**
     * Adds a show and its episodes to the database. If the show already exists, does nothing.
     *
     * <p> If signed in to Hexagon, gets show properties and episode flags.
     *
     * <p> If connected to trakt, but not signed in to Hexagon, gets episode flags from trakt
     * instead.
     *
     * @return True, if the show and its episodes were added to the database.
     */
public boolean addShow(int showTvdbId, @Nullable String language, @Nullable HashMap<Integer, BaseShow> traktCollection, @Nullable HashMap<Integer, BaseShow> traktWatched) throws TvdbException {
    boolean isShowExists = DBUtils.isShowExists(app, showTvdbId);
    if (isShowExists) {
        return false;
    }
    // get show and determine the language to use
    Show show = getShowDetailsWithHexagon(showTvdbId, language);
    language = show.language;
    // get episodes and store everything to the database
    final ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    batch.add(DBUtils.buildShowOp(app, show, true));
    getEpisodesAndUpdateDatabase(batch, show, language);
    // restore episode flags...
    if (HexagonSettings.isEnabled(app)) {
        // ...from Hexagon
        boolean success = EpisodeTools.Download.flagsFromHexagon(app, showTvdbId);
        if (!success) {
            // failed to download episode flags
            // flag show as needing an episode merge
            ContentValues values = new ContentValues();
            values.put(Shows.HEXAGON_MERGE_COMPLETE, false);
            app.getContentResolver().update(Shows.buildShowUri(showTvdbId), values, null, null);
        }
        // flag show to be auto-added (again), send (new) language to Hexagon
        app.getShowTools().sendIsAdded(showTvdbId, language);
    } else {
        // ...from trakt
        TraktTools traktTools = app.getTraktTools();
        if (!traktTools.storeEpisodeFlags(traktWatched, showTvdbId, TraktTools.Flag.WATCHED)) {
            throw new TvdbDataException("addShow: storing trakt watched episodes failed.");
        }
        if (!traktTools.storeEpisodeFlags(traktCollection, showTvdbId, TraktTools.Flag.COLLECTED)) {
            throw new TvdbDataException("addShow: storing trakt collected episodes failed.");
        }
    }
    // calculate next episode
    DBUtils.updateLatestEpisode(app, showTvdbId);
    return true;
}
Also used : ContentValues(android.content.ContentValues) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) BaseShow(com.uwetrottmann.trakt5.entities.BaseShow) Show(com.battlelancer.seriesguide.dataliberation.model.Show) TraktTools(com.battlelancer.seriesguide.util.TraktTools)

Example 2 with BaseShow

use of com.uwetrottmann.trakt5.entities.BaseShow in project SeriesGuide by UweTrottmann.

the class TraktTools method processTraktSeasons.

/**
     * Sync the watched/collected episodes of the given trakt show with the local episodes. The
     * given show has to be watched/collected on trakt.
     *
     * @param isInitialSync If {@code true}, will upload watched/collected episodes that are not
     * watched/collected on trakt. If {@code false}, will set them not watched/collected (if not
     * skipped) to mirror the trakt episode.
     */
public int processTraktSeasons(boolean isInitialSync, int localShow, @NonNull BaseShow traktShow, @NonNull Flag flag) {
    HashMap<Integer, BaseSeason> traktSeasons = buildTraktSeasonsMap(traktShow.seasons);
    Cursor localSeasonsQuery = context.getContentResolver().query(SeriesGuideContract.Seasons.buildSeasonsOfShowUri(localShow), new String[] { SeriesGuideContract.Seasons._ID, SeriesGuideContract.Seasons.COMBINED }, null, null, null);
    if (localSeasonsQuery == null) {
        return FAILED;
    }
    final ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    List<SyncSeason> syncSeasons = new ArrayList<>();
    while (localSeasonsQuery.moveToNext()) {
        String seasonId = localSeasonsQuery.getString(0);
        int seasonNumber = localSeasonsQuery.getInt(1);
        if (traktSeasons.containsKey(seasonNumber)) {
            // season watched/collected on trakt
            if (!processTraktEpisodes(isInitialSync, seasonId, traktSeasons.get(seasonNumber), syncSeasons, flag)) {
                return FAILED;
            }
        } else {
            // season not watched/collected on trakt
            if (isInitialSync) {
                // schedule all watched/collected episodes of this season for upload
                SyncSeason syncSeason = buildSyncSeason(seasonId, seasonNumber, flag);
                if (syncSeason != null) {
                    syncSeasons.add(syncSeason);
                }
            } else {
                // set all watched/collected episodes of season not watched/collected
                batch.add(ContentProviderOperation.newUpdate(SeriesGuideContract.Episodes.buildEpisodesOfSeasonUri(seasonId)).withSelection(flag.clearFlagSelection, null).withValue(flag.databaseColumn, flag.notFlaggedValue).build());
            }
        }
    }
    localSeasonsQuery.close();
    try {
        DBUtils.applyInSmallBatches(context, batch);
    } catch (OperationApplicationException e) {
        Timber.e(e, "Setting seasons unwatched failed.");
    }
    if (syncSeasons.size() > 0) {
        // upload watched/collected episodes for this show
        Integer showTraktId = ShowTools.getShowTraktId(context, localShow);
        if (showTraktId == null) {
            // show should have a trakt id, give up
            return FAILED;
        }
        return uploadEpisodes(showTraktId, syncSeasons, flag);
    } else {
        return SUCCESS;
    }
}
Also used : ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) BaseSeason(com.uwetrottmann.trakt5.entities.BaseSeason) OperationApplicationException(android.content.OperationApplicationException) SyncSeason(com.uwetrottmann.trakt5.entities.SyncSeason)

Example 3 with BaseShow

use of com.uwetrottmann.trakt5.entities.BaseShow in project SeriesGuide by UweTrottmann.

the class AddShowTask method doInBackground.

@Override
protected Void doInBackground(Void... params) {
    Timber.d("Starting to add shows...");
    SearchResult firstShow = addQueue.peek();
    if (firstShow == null) {
        Timber.d("Finished. Queue was empty.");
        return null;
    }
    if (!AndroidUtils.isNetworkConnected(context)) {
        Timber.d("Finished. No internet connection.");
        publishProgress(RESULT_OFFLINE, firstShow.getTmdbId(), firstShow.getTitle());
        return null;
    }
    if (isCancelled()) {
        Timber.d("Finished. Cancelled.");
        return null;
    }
    // if not connected to Hexagon, get episodes from trakt
    Map<Integer, BaseShow> traktCollection = null;
    Map<Integer, BaseShow> traktWatched = null;
    if (!HexagonSettings.isEnabled(context) && TraktCredentials.get(context).hasCredentials()) {
        Timber.d("Getting watched and collected episodes from trakt.");
        // get collection
        Map<Integer, BaseShow> traktShows = getTraktShows(true);
        if (traktShows == null) {
            // can not get collected state from trakt, give up.
            return null;
        }
        traktCollection = traktShows;
        // get watched
        traktShows = getTraktShows(false);
        if (traktShows == null) {
            // can not get watched state from trakt, give up.
            return null;
        }
        traktWatched = traktShows;
    }
    HexagonEpisodeSync hexagonEpisodeSync = new HexagonEpisodeSync(context, SgApp.getServicesComponent(context).hexagonTools());
    int result;
    boolean addedAtLeastOneShow = false;
    boolean failedMergingShows = false;
    while (!addQueue.isEmpty()) {
        Timber.d("Starting to add next show...");
        if (isCancelled()) {
            Timber.d("Finished. Cancelled.");
            // table yet
            return null;
        }
        SearchResult nextShow = addQueue.removeFirst();
        // set values required for progress update
        String currentShowName = nextShow.getTitle();
        int currentShowTmdbId = nextShow.getTmdbId();
        if (currentShowTmdbId <= 0) {
            // Invalid ID, should never have been passed, report.
            // Background: Hexagon gets requests with ID 0.
            IllegalStateException invalidIdException = new IllegalStateException("Show id invalid: " + currentShowTmdbId + ", silentMode=" + isSilentMode + ", merging=" + isMergingShows);
            Errors.logAndReport("Add show", invalidIdException);
            continue;
        }
        if (!AndroidUtils.isNetworkConnected(context)) {
            Timber.d("Finished. No connection.");
            publishProgress(RESULT_OFFLINE, currentShowTmdbId, currentShowName);
            failedMergingShows = true;
            break;
        }
        ShowResult addResult = SgApp.getServicesComponent(context).showTools().addShow(nextShow.getTmdbId(), nextShow.getLanguage(), traktCollection, traktWatched, hexagonEpisodeSync);
        if (addResult == ShowResult.SUCCESS) {
            result = PROGRESS_SUCCESS;
            addedAtLeastOneShow = true;
        } else if (addResult == ShowResult.IN_DATABASE) {
            result = PROGRESS_EXISTS;
        } else {
            Timber.e("Adding show failed: %s", addResult);
            // not because it does not (longer) exist.
            if (isMergingShows && addResult != ShowResult.DOES_NOT_EXIST) {
                failedMergingShows = true;
            }
            switch(addResult) {
                case DOES_NOT_EXIST:
                    result = PROGRESS_ERROR_TVDB_NOT_EXISTS;
                    break;
                case TMDB_ERROR:
                    result = PROGRESS_ERROR_TVDB;
                    break;
                case TRAKT_ERROR:
                    result = PROGRESS_ERROR_TRAKT;
                    break;
                case HEXAGON_ERROR:
                    result = PROGRESS_ERROR_HEXAGON;
                    break;
                case DATABASE_ERROR:
                    result = PROGRESS_ERROR_DATA;
                    break;
                default:
                    result = PROGRESS_ERROR;
                    break;
            }
        }
        publishProgress(result, currentShowTmdbId, currentShowName);
        Timber.d("Finished adding show. (Result code: %s)", result);
    }
    isFinishedAddingShows = true;
    // when merging shows down from Hexagon, set success flag
    if (isMergingShows && !failedMergingShows) {
        HexagonSettings.setHasMergedShows(context, true);
    }
    if (addedAtLeastOneShow) {
        // make sure the next sync will download all ratings
        PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(TraktSettings.KEY_LAST_SHOWS_RATED_AT, 0).putLong(TraktSettings.KEY_LAST_EPISODES_RATED_AT, 0).apply();
        // renew FTS3 table
        Timber.d("Renewing search table.");
        SeriesGuideDatabase.rebuildFtsTable(context);
    }
    Timber.d("Finished adding shows.");
    return null;
}
Also used : BaseShow(com.uwetrottmann.trakt5.entities.BaseShow) HexagonEpisodeSync(com.battlelancer.seriesguide.sync.HexagonEpisodeSync) ShowResult(com.battlelancer.seriesguide.ui.shows.ShowTools2.ShowResult) SuppressLint(android.annotation.SuppressLint)

Example 4 with BaseShow

use of com.uwetrottmann.trakt5.entities.BaseShow in project SeriesGuide by UweTrottmann.

the class TraktAddLoader method parseTraktShowsToSearchResults.

/**
 * Transforms a list of trakt shows to a list of {@link SearchResult}, marks shows already in
 * the local database as added.
 */
static List<SearchResult> parseTraktShowsToSearchResults(Context context, @NonNull List<BaseShow> traktShows, @Nullable String overrideLanguage) {
    List<SearchResult> results = new ArrayList<>();
    // build list
    SparseArrayCompat<String> existingPosterPaths = SgApp.getServicesComponent(context).showTools().getTmdbIdsToPoster();
    for (BaseShow baseShow : traktShows) {
        if (baseShow == null) {
            continue;
        }
        Show show = baseShow.show;
        if (show == null || show.ids == null || show.ids.tmdb == null) {
            // has no TMDB id
            continue;
        }
        SearchResult result = new SearchResult();
        result.setTmdbId(show.ids.tmdb);
        result.setTitle(show.title);
        // search results return an overview, while trending and other lists do not
        result.setOverview(!TextUtils.isEmpty(show.overview) ? show.overview : show.year != null ? String.valueOf(show.year) : "");
        if (existingPosterPaths.indexOfKey(show.ids.tmdb) >= 0) {
            // is already in local database
            result.setState(SearchResult.STATE_ADDED);
            // use the poster fetched for it (or null if there is none)
            result.setPosterPath(existingPosterPaths.get(show.ids.tmdb));
        }
        if (overrideLanguage != null) {
            result.setLanguage(overrideLanguage);
        }
        results.add(result);
    }
    return results;
}
Also used : BaseShow(com.uwetrottmann.trakt5.entities.BaseShow) ArrayList(java.util.ArrayList) Show(com.uwetrottmann.trakt5.entities.Show) BaseShow(com.uwetrottmann.trakt5.entities.BaseShow)

Example 5 with BaseShow

use of com.uwetrottmann.trakt5.entities.BaseShow in project SeriesGuide by UweTrottmann.

the class AddShowTask method doInBackground.

@Override
protected Void doInBackground(Void... params) {
    Timber.d("Starting to add shows...");
    // don't even get started
    if (addQueue.isEmpty()) {
        Timber.d("Finished. Queue was empty.");
        return null;
    }
    // set values required for progress update
    SearchResult nextShow = addQueue.peek();
    currentShowName = nextShow.title;
    currentShowTvdbId = nextShow.tvdbid;
    if (!AndroidUtils.isNetworkConnected(app)) {
        Timber.d("Finished. No internet connection.");
        publishProgress(RESULT_OFFLINE);
        return null;
    }
    if (isCancelled()) {
        Timber.d("Finished. Cancelled.");
        return null;
    }
    // if not connected to Hexagon, get episodes from trakt
    HashMap<Integer, BaseShow> traktCollection = null;
    HashMap<Integer, BaseShow> traktWatched = null;
    if (!HexagonSettings.isEnabled(app) && TraktCredentials.get(app).hasCredentials()) {
        Timber.d("Getting watched and collected episodes from trakt.");
        // get collection
        HashMap<Integer, BaseShow> traktShows = getTraktShows("get collection", true);
        if (traktShows == null) {
            // can not get collected state from trakt, give up.
            return null;
        }
        traktCollection = traktShows;
        // get watched
        traktShows = getTraktShows("get watched", false);
        if (traktShows == null) {
            // can not get watched state from trakt, give up.
            return null;
        }
        traktWatched = traktShows;
    }
    int result;
    boolean addedAtLeastOneShow = false;
    boolean failedMergingShows = false;
    while (!addQueue.isEmpty()) {
        Timber.d("Starting to add next show...");
        if (isCancelled()) {
            Timber.d("Finished. Cancelled.");
            // table yet
            return null;
        }
        nextShow = addQueue.removeFirst();
        // set values required for progress update
        currentShowName = nextShow.title;
        currentShowTvdbId = nextShow.tvdbid;
        if (!AndroidUtils.isNetworkConnected(app)) {
            Timber.d("Finished. No connection.");
            publishProgress(RESULT_OFFLINE);
            failedMergingShows = true;
            break;
        }
        try {
            boolean addedShow = TvdbTools.getInstance(app).addShow(nextShow.tvdbid, nextShow.language, traktCollection, traktWatched);
            result = addedShow ? PROGRESS_SUCCESS : PROGRESS_EXISTS;
            addedAtLeastOneShow = addedShow || // do not overwrite previous success
            addedAtLeastOneShow;
        } catch (TvdbException e) {
            // because it does not exist (any longer)
            if (!(isMergingShows && e.itemDoesNotExist())) {
                failedMergingShows = true;
            }
            if (e.service() == TvdbException.Service.TVDB) {
                if (e.itemDoesNotExist()) {
                    result = PROGRESS_ERROR_TVDB_NOT_EXISTS;
                } else {
                    result = PROGRESS_ERROR_TVDB;
                }
            } else if (e.service() == TvdbException.Service.HEXAGON) {
                result = PROGRESS_ERROR_HEXAGON;
            } else if (e.service() == TvdbException.Service.DATA) {
                result = PROGRESS_ERROR_DATA;
            } else {
                result = PROGRESS_ERROR;
            }
            Timber.e(e, "Adding show failed");
        }
        publishProgress(result);
        Timber.d("Finished adding show. (Result code: %s)", result);
    }
    isFinishedAddingShows = true;
    // when merging shows down from Hexagon, set success flag
    if (isMergingShows && !failedMergingShows) {
        HexagonSettings.setHasMergedShows(app, true);
    }
    if (addedAtLeastOneShow) {
        // make sure the next sync will download all ratings
        PreferenceManager.getDefaultSharedPreferences(app).edit().putLong(TraktSettings.KEY_LAST_SHOWS_RATED_AT, 0).putLong(TraktSettings.KEY_LAST_EPISODES_RATED_AT, 0).apply();
        // renew FTS3 table
        Timber.d("Renewing search table.");
        DBUtils.rebuildFtsTable(app);
    }
    Timber.d("Finished adding shows.");
    return null;
}
Also used : BaseShow(com.uwetrottmann.trakt5.entities.BaseShow) SearchResult(com.battlelancer.seriesguide.items.SearchResult) TvdbException(com.battlelancer.seriesguide.thetvdbapi.TvdbException)

Aggregations

BaseShow (com.uwetrottmann.trakt5.entities.BaseShow)5 ArrayList (java.util.ArrayList)4 ContentProviderOperation (android.content.ContentProviderOperation)3 OperationApplicationException (android.content.OperationApplicationException)2 SuppressLint (android.annotation.SuppressLint)1 ContentValues (android.content.ContentValues)1 Cursor (android.database.Cursor)1 Show (com.battlelancer.seriesguide.dataliberation.model.Show)1 SearchResult (com.battlelancer.seriesguide.items.SearchResult)1 HexagonEpisodeSync (com.battlelancer.seriesguide.sync.HexagonEpisodeSync)1 TvdbException (com.battlelancer.seriesguide.thetvdbapi.TvdbException)1 ShowResult (com.battlelancer.seriesguide.ui.shows.ShowTools2.ShowResult)1 TraktTools (com.battlelancer.seriesguide.util.TraktTools)1 BaseSeason (com.uwetrottmann.trakt5.entities.BaseSeason)1 Show (com.uwetrottmann.trakt5.entities.Show)1 SyncSeason (com.uwetrottmann.trakt5.entities.SyncSeason)1