Search in sources :

Example 11 with Sync

use of com.uwetrottmann.trakt5.services.Sync in project SeriesGuide by UweTrottmann.

the class TraktTools method downloadEpisodeRatings.

/**
     * Downloads trakt episode ratings and applies the latest ones to the database.
     *
     * <p> To apply all ratings, set {@link TraktSettings#KEY_LAST_EPISODES_RATED_AT} to 0.
     */
public UpdateResult downloadEpisodeRatings(@Nullable DateTime ratedAt) {
    if (ratedAt == null) {
        Timber.e("downloadEpisodeRatings: null rated_at");
        return UpdateResult.INCOMPLETE;
    }
    long lastRatedAt = TraktSettings.getLastEpisodesRatedAt(context);
    if (!ratedAt.isAfter(lastRatedAt)) {
        // not initial sync, no ratings have changed
        Timber.d("downloadEpisodeRatings: no changes since %tF %tT", lastRatedAt, lastRatedAt);
        return UpdateResult.SUCCESS;
    }
    if (!TraktCredentials.get(context).hasCredentials()) {
        return UpdateResult.INCOMPLETE;
    }
    // download rated episodes
    List<RatedEpisode> ratedEpisodes;
    try {
        Response<List<RatedEpisode>> response = traktSync.get().ratingsEpisodes(RatingsFilter.ALL, Extended.DEFAULT_MIN).execute();
        if (response.isSuccessful()) {
            ratedEpisodes = response.body();
        } else {
            if (SgTrakt.isUnauthorized(context, response)) {
                return UpdateResult.INCOMPLETE;
            }
            SgTrakt.trackFailedRequest(context, "get episode ratings", response);
            return UpdateResult.INCOMPLETE;
        }
    } catch (IOException e) {
        SgTrakt.trackFailedRequest(context, "get episode ratings", e);
        return UpdateResult.INCOMPLETE;
    }
    if (ratedEpisodes == null) {
        Timber.e("downloadEpisodeRatings: null response");
        return UpdateResult.INCOMPLETE;
    }
    if (ratedEpisodes.isEmpty()) {
        Timber.d("downloadEpisodeRatings: no ratings on trakt");
        return UpdateResult.SUCCESS;
    }
    // trakt last activity rated_at timestamp is set after the rating timestamp
    // so include ratings that are a little older
    long ratedAtThreshold = lastRatedAt - 5 * DateUtils.MINUTE_IN_MILLIS;
    ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    for (RatedEpisode episode : ratedEpisodes) {
        if (episode.rating == null || episode.episode == null || episode.episode.ids == null || episode.episode.ids.tvdb == null) {
            // skip, can't handle
            continue;
        }
        if (episode.rated_at != null && episode.rated_at.isBefore(ratedAtThreshold)) {
            // no need to apply older ratings again
            break;
        }
        // if an episode does not exist, this update will do nothing
        ContentProviderOperation op = ContentProviderOperation.newUpdate(SeriesGuideContract.Episodes.buildEpisodeUri(episode.episode.ids.tvdb)).withValue(SeriesGuideContract.Episodes.RATING_USER, episode.rating.value).build();
        batch.add(op);
    }
    // apply database updates
    try {
        DBUtils.applyInSmallBatches(context, batch);
    } catch (OperationApplicationException e) {
        Timber.e(e, "downloadEpisodeRatings: database update failed");
        return UpdateResult.INCOMPLETE;
    }
    // save last rated instant
    PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(TraktSettings.KEY_LAST_EPISODES_RATED_AT, ratedAt.getMillis()).commit();
    Timber.d("downloadEpisodeRatings: success, last rated_at %tF %tT", ratedAt.getMillis(), ratedAt.getMillis());
    return UpdateResult.SUCCESS;
}
Also used : RatedEpisode(com.uwetrottmann.trakt5.entities.RatedEpisode) ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) IOException(java.io.IOException) OperationApplicationException(android.content.OperationApplicationException)

Example 12 with Sync

use of com.uwetrottmann.trakt5.services.Sync in project SeriesGuide by UweTrottmann.

the class TraktTools method downloadMovieRatings.

/**
     * Downloads trakt movie ratings and applies the latest ones to the database.
     *
     * <p> To apply all ratings, set {@link TraktSettings#KEY_LAST_MOVIES_RATED_AT} to 0.
     */
public UpdateResult downloadMovieRatings(DateTime ratedAt) {
    if (ratedAt == null) {
        Timber.e("downloadMovieRatings: null rated_at");
        return UpdateResult.INCOMPLETE;
    }
    long lastRatedAt = TraktSettings.getLastMoviesRatedAt(context);
    if (!ratedAt.isAfter(lastRatedAt)) {
        // not initial sync, no ratings have changed
        Timber.d("downloadMovieRatings: no changes since %tF %tT", lastRatedAt, lastRatedAt);
        return UpdateResult.SUCCESS;
    }
    if (!TraktCredentials.get(context).hasCredentials()) {
        return UpdateResult.INCOMPLETE;
    }
    // download rated shows
    List<RatedMovie> ratedMovies;
    try {
        Response<List<RatedMovie>> response = traktSync.get().ratingsMovies(RatingsFilter.ALL, Extended.DEFAULT_MIN).execute();
        if (response.isSuccessful()) {
            ratedMovies = response.body();
        } else {
            if (SgTrakt.isUnauthorized(context, response)) {
                return UpdateResult.INCOMPLETE;
            }
            SgTrakt.trackFailedRequest(context, "get movie ratings", response);
            return UpdateResult.INCOMPLETE;
        }
    } catch (IOException e) {
        SgTrakt.trackFailedRequest(context, "get movie ratings", e);
        return UpdateResult.INCOMPLETE;
    }
    if (ratedMovies == null) {
        Timber.e("downloadMovieRatings: null response");
        return UpdateResult.INCOMPLETE;
    }
    if (ratedMovies.isEmpty()) {
        Timber.d("downloadMovieRatings: no ratings on trakt");
        return UpdateResult.SUCCESS;
    }
    // trakt last activity rated_at timestamp is set after the rating timestamp
    // so include ratings that are a little older
    long ratedAtThreshold = lastRatedAt - 5 * DateUtils.MINUTE_IN_MILLIS;
    // go through ratings, latest first (trakt sends in that order)
    ArrayList<ContentProviderOperation> batch = new ArrayList<>();
    for (RatedMovie movie : ratedMovies) {
        if (movie.rating == null || movie.movie == null || movie.movie.ids == null || movie.movie.ids.tmdb == null) {
            // skip, can't handle
            continue;
        }
        if (movie.rated_at != null && movie.rated_at.isBefore(ratedAtThreshold)) {
            // no need to apply older ratings again
            break;
        }
        // if a movie does not exist, this update will do nothing
        ContentProviderOperation op = ContentProviderOperation.newUpdate(SeriesGuideContract.Movies.buildMovieUri(movie.movie.ids.tmdb)).withValue(SeriesGuideContract.Movies.RATING_USER, movie.rating.value).build();
        batch.add(op);
    }
    // apply database updates
    try {
        DBUtils.applyInSmallBatches(context, batch);
    } catch (OperationApplicationException e) {
        Timber.e(e, "downloadMovieRatings: database update failed");
        return UpdateResult.INCOMPLETE;
    }
    // save last rated instant
    PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(TraktSettings.KEY_LAST_MOVIES_RATED_AT, ratedAt.getMillis()).commit();
    Timber.d("downloadMovieRatings: success, last rated_at %tF %tT", ratedAt.getMillis(), ratedAt.getMillis());
    return UpdateResult.SUCCESS;
}
Also used : ContentProviderOperation(android.content.ContentProviderOperation) ArrayList(java.util.ArrayList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) RatedMovie(com.uwetrottmann.trakt5.entities.RatedMovie) IOException(java.io.IOException) OperationApplicationException(android.content.OperationApplicationException)

Example 13 with Sync

use of com.uwetrottmann.trakt5.services.Sync in project SeriesGuide by UweTrottmann.

the class TraktSync method sync.

/**
 * @param onlyRatings To not conflict with Hexagon sync, can turn on so only
 *                    ratings are synced.
 */
public SgSyncAdapter.UpdateResult sync(long currentTime, boolean onlyRatings) {
    // get last activity timestamps
    progress.publish(SyncProgress.Step.TRAKT);
    if (!AndroidUtils.isNetworkConnected(context)) {
        progress.recordError();
        return SgSyncAdapter.UpdateResult.INCOMPLETE;
    }
    LastActivities lastActivity = getLastActivity();
    if (lastActivity == null || lastActivity.episodes == null || lastActivity.shows == null || lastActivity.movies == null) {
        // trakt is offline or busy, or there are server errors, try later.
        progress.recordError();
        Timber.e("performTraktSync: last activity download failed");
        return SgSyncAdapter.UpdateResult.INCOMPLETE;
    }
    TraktRatingsSync ratingsSync = new TraktRatingsSync(context, traktSync);
    Map<Integer, Long> tmdbIdsToShowIds = SgApp.getServicesComponent(context).showTools().getTmdbIdsToShowIds();
    if (tmdbIdsToShowIds.size() == 0) {
        Timber.d("performTraktSync: no local shows, skip shows");
    } else {
        if (!onlyRatings) {
            // EPISODES
            // download and upload episode watched and collected flags
            progress.publish(SyncProgress.Step.TRAKT_EPISODES);
            if (!AndroidUtils.isNetworkConnected(context)) {
                progress.recordError();
                return SgSyncAdapter.UpdateResult.INCOMPLETE;
            }
            if (!syncEpisodes(tmdbIdsToShowIds, lastActivity.episodes, currentTime)) {
                progress.recordError();
                return SgSyncAdapter.UpdateResult.INCOMPLETE;
            }
        }
        // download ratings
        progress.publish(SyncProgress.Step.TRAKT_RATINGS);
        if (!AndroidUtils.isNetworkConnected(context)) {
            progress.recordError();
            return SgSyncAdapter.UpdateResult.INCOMPLETE;
        }
        if (!ratingsSync.downloadForEpisodes(lastActivity.episodes.rated_at)) {
            progress.recordError();
            return SgSyncAdapter.UpdateResult.INCOMPLETE;
        }
        // download ratings
        if (!AndroidUtils.isNetworkConnected(context)) {
            progress.recordError();
            return SgSyncAdapter.UpdateResult.INCOMPLETE;
        }
        if (!ratingsSync.downloadForShows(lastActivity.shows.rated_at)) {
            progress.recordError();
            return SgSyncAdapter.UpdateResult.INCOMPLETE;
        }
    }
    // MOVIES
    progress.publish(SyncProgress.Step.TRAKT_MOVIES);
    TraktMovieSync movieSync = new TraktMovieSync(context, movieTools, traktSync);
    // sync watchlist, collection and watched movies with trakt
    if (!onlyRatings) {
        if (!AndroidUtils.isNetworkConnected(context)) {
            progress.recordError();
            return SgSyncAdapter.UpdateResult.INCOMPLETE;
        }
        if (!movieSync.syncLists(lastActivity.movies)) {
            progress.recordError();
            return SgSyncAdapter.UpdateResult.INCOMPLETE;
        }
        // clean up any useless movies (not watched or not in any list)
        MovieTools.deleteUnusedMovies(context);
    }
    // download movie ratings
    progress.publish(SyncProgress.Step.TRAKT_RATINGS);
    if (!AndroidUtils.isNetworkConnected(context)) {
        progress.recordError();
        return SgSyncAdapter.UpdateResult.INCOMPLETE;
    }
    if (!ratingsSync.downloadForMovies(lastActivity.movies.rated_at)) {
        progress.recordError();
        return SgSyncAdapter.UpdateResult.INCOMPLETE;
    }
    return SgSyncAdapter.UpdateResult.SUCCESS;
}
Also used : LastActivities(com.uwetrottmann.trakt5.entities.LastActivities)

Example 14 with Sync

use of com.uwetrottmann.trakt5.services.Sync in project SeriesGuide by UweTrottmann.

the class BaseRateItemTask method doBackgroundAction.

@Override
protected Integer doBackgroundAction(Void... params) {
    if (isSendingToTrakt()) {
        if (!TraktCredentials.get(getContext()).hasCredentials()) {
            return ERROR_TRAKT_AUTH;
        }
        SyncItems ratedItems = buildTraktSyncItems();
        if (ratedItems == null) {
            return ERROR_TRAKT_API;
        }
        SyncErrors notFound;
        try {
            Sync traktSync = SgApp.getServicesComponent(getContext()).traktSync();
            Response<SyncResponse> response = traktSync.addRatings(ratedItems).execute();
            if (response.isSuccessful()) {
                notFound = response.body().not_found;
            } else {
                if (SgTrakt.isUnauthorized(getContext(), response)) {
                    return ERROR_TRAKT_AUTH;
                }
                Errors.logAndReport(getTraktAction(), response);
                return ERROR_TRAKT_API;
            }
        } catch (Exception e) {
            Errors.logAndReport(getTraktAction(), e);
            return ERROR_TRAKT_API;
        }
        if (notFound != null) {
            if ((notFound.movies != null && notFound.movies.size() != 0) || (notFound.shows != null && notFound.shows.size() != 0) || (notFound.episodes != null && notFound.episodes.size() != 0)) {
                // movie, show or episode not found on trakt
                return ERROR_TRAKT_API_NOT_FOUND;
            }
        }
    }
    if (!doDatabaseUpdate()) {
        return ERROR_DATABASE;
    }
    return SUCCESS;
}
Also used : SyncItems(com.uwetrottmann.trakt5.entities.SyncItems) SyncResponse(com.uwetrottmann.trakt5.entities.SyncResponse) SyncErrors(com.uwetrottmann.trakt5.entities.SyncErrors) Sync(com.uwetrottmann.trakt5.services.Sync)

Aggregations

OperationApplicationException (android.content.OperationApplicationException)8 ArrayList (java.util.ArrayList)8 List (java.util.List)7 ContentProviderOperation (android.content.ContentProviderOperation)6 IOException (java.io.IOException)4 LinkedList (java.util.LinkedList)4 BaseShow (com.uwetrottmann.trakt5.entities.BaseShow)2 LastActivities (com.uwetrottmann.trakt5.entities.LastActivities)2 RatedEpisode (com.uwetrottmann.trakt5.entities.RatedEpisode)2 RatedMovie (com.uwetrottmann.trakt5.entities.RatedMovie)2 RatedShow (com.uwetrottmann.trakt5.entities.RatedShow)2 SyncItems (com.uwetrottmann.trakt5.entities.SyncItems)2 SyncResponse (com.uwetrottmann.trakt5.entities.SyncResponse)2 Sync (com.uwetrottmann.trakt5.services.Sync)2 HashMap (java.util.HashMap)2 SuppressLint (android.annotation.SuppressLint)1 Cursor (android.database.Cursor)1 SearchResult (com.battlelancer.seriesguide.items.SearchResult)1 HexagonEpisodeSync (com.battlelancer.seriesguide.sync.HexagonEpisodeSync)1 TvdbException (com.battlelancer.seriesguide.thetvdbapi.TvdbException)1