use of com.battlelancer.seriesguide.sync.SgSyncAdapter.UpdateResult in project SeriesGuide by UweTrottmann.
the class MovieTools method syncMovieListsWithTrakt.
/**
* Updates the local movie database against trakt movie watchlist and collection. Adds, updates
* and removes movies in the database.
*
* <p> When syncing the first time, will upload any local movies missing from trakt collection
* or watchlist instead of removing them locally.
*
* <p> Performs <b>synchronous network access</b>, make sure to run this on a background
* thread.
*/
@SuppressLint("ApplySharedPref")
public UpdateResult syncMovieListsWithTrakt(LastActivityMore activity) {
if (activity.collected_at == null) {
Timber.e("syncMoviesWithTrakt: null collected_at");
return UpdateResult.INCOMPLETE;
}
if (activity.watchlisted_at == null) {
Timber.e("syncMoviesWithTrakt: null watchlisted_at");
return UpdateResult.INCOMPLETE;
}
if (!TraktCredentials.get(context).hasCredentials()) {
return UpdateResult.INCOMPLETE;
}
final boolean merging = !TraktSettings.hasMergedMovies(context);
if (!merging && !TraktSettings.isMovieListsChanged(context, activity.collected_at, activity.watchlisted_at)) {
Timber.d("syncMoviesWithTrakt: no changes");
return UpdateResult.SUCCESS;
}
// download collection
Set<Integer> collection;
try {
Response<List<BaseMovie>> response = traktSync.get().collectionMovies(Extended.DEFAULT_MIN).execute();
if (response.isSuccessful()) {
collection = buildTmdbIdSet(response.body());
} else {
if (SgTrakt.isUnauthorized(context, response)) {
return UpdateResult.INCOMPLETE;
}
SgTrakt.trackFailedRequest(context, "get movie collection", response);
return UpdateResult.INCOMPLETE;
}
} catch (IOException e) {
SgTrakt.trackFailedRequest(context, "get movie collection", e);
return UpdateResult.INCOMPLETE;
}
if (collection == null) {
Timber.e("syncMoviesWithTrakt: null collection response");
return UpdateResult.INCOMPLETE;
}
// download watchlist
Set<Integer> watchlist;
try {
Response<List<BaseMovie>> response = traktSync.get().watchlistMovies(Extended.DEFAULT_MIN).execute();
if (response.isSuccessful()) {
watchlist = buildTmdbIdSet(response.body());
} else {
if (SgTrakt.isUnauthorized(context, response)) {
return UpdateResult.INCOMPLETE;
}
SgTrakt.trackFailedRequest(context, "get movie watchlist", response);
return UpdateResult.INCOMPLETE;
}
} catch (IOException e) {
SgTrakt.trackFailedRequest(context, "get movie watchlist", e);
return UpdateResult.INCOMPLETE;
}
if (watchlist == null) {
Timber.e("syncMoviesWithTrakt: null watchlist response");
return UpdateResult.INCOMPLETE;
}
// build updates
// loop through all local movies
Set<Integer> moviesNotOnTraktCollection = new HashSet<>();
Set<Integer> moviesNotOnTraktWatchlist = new HashSet<>();
ArrayList<ContentProviderOperation> batch = new ArrayList<>();
HashSet<Integer> localMovies = getMovieTmdbIdsAsSet(context);
if (localMovies == null) {
Timber.e("syncMoviesWithTrakt: querying local movies failed");
return UpdateResult.INCOMPLETE;
}
for (Integer tmdbId : localMovies) {
// is local movie in trakt collection or watchlist?
boolean inCollection = collection.remove(tmdbId);
boolean inWatchlist = watchlist.remove(tmdbId);
if (merging) {
// upload movie if missing from trakt collection or watchlist
if (!inCollection) {
moviesNotOnTraktCollection.add(tmdbId);
}
if (!inWatchlist) {
moviesNotOnTraktWatchlist.add(tmdbId);
}
// add to local collection or watchlist, but do NOT remove
if (inCollection || inWatchlist) {
ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(SeriesGuideContract.Movies.buildMovieUri(tmdbId));
if (inCollection) {
builder.withValue(SeriesGuideContract.Movies.IN_COLLECTION, true);
}
if (inWatchlist) {
builder.withValue(SeriesGuideContract.Movies.IN_WATCHLIST, true);
}
batch.add(builder.build());
}
} else {
// mirror trakt collection and watchlist flag
// will take care of removing unneeded (not watched or in any list) movies
// in later sync step
ContentProviderOperation op = ContentProviderOperation.newUpdate(SeriesGuideContract.Movies.buildMovieUri(tmdbId)).withValue(SeriesGuideContract.Movies.IN_COLLECTION, inCollection).withValue(SeriesGuideContract.Movies.IN_WATCHLIST, inWatchlist).build();
batch.add(op);
}
}
// apply collection and watchlist updates to existing movies
try {
DBUtils.applyInSmallBatches(context, batch);
Timber.d("syncMoviesWithTrakt: updated %s", batch.size());
} catch (OperationApplicationException e) {
Timber.e(e, "syncMoviesWithTrakt: database updates failed");
return UpdateResult.INCOMPLETE;
}
batch.clear();
// merge on first run
if (merging) {
// upload movies not in trakt collection or watchlist
if (toTrakt(moviesNotOnTraktCollection, moviesNotOnTraktWatchlist) != UpdateResult.SUCCESS) {
return UpdateResult.INCOMPLETE;
} else {
// set merge successful
PreferenceManager.getDefaultSharedPreferences(context).edit().putBoolean(TraktSettings.KEY_HAS_MERGED_MOVIES, true).commit();
}
}
// add movies from trakt missing locally
// all local movies were removed from trakt collection and watchlist,
// so they only contain movies missing locally
UpdateResult result = addMovies(collection, watchlist);
if (result == UpdateResult.SUCCESS) {
// store last activity timestamps
TraktSettings.storeLastMoviesChangedAt(context, activity.collected_at, activity.watchlisted_at);
// ensure all movie ratings and watched flags are downloaded next
if (collection.size() > 0 || watchlist.size() > 0) {
TraktSettings.resetMoviesLastActivity(context);
}
}
return result;
}
Aggregations