use of com.uwetrottmann.trakt5.entities.Ratings in project SeriesGuide by UweTrottmann.
the class TraktRatingsSync method downloadForMovies.
/**
* 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 boolean downloadForMovies(OffsetDateTime ratedAt) {
if (ratedAt == null) {
Timber.e("downloadForMovies: null rated_at");
return false;
}
long lastRatedAt = TraktSettings.getLastMoviesRatedAt(context);
if (!TimeTools.isAfterMillis(ratedAt, lastRatedAt)) {
// not initial sync, no ratings have changed
Timber.d("downloadForMovies: no changes since %tF %tT", lastRatedAt, lastRatedAt);
return true;
}
if (!TraktCredentials.get(context).hasCredentials()) {
return false;
}
// download rated shows
List<RatedMovie> ratedMovies;
try {
Response<List<RatedMovie>> response = traktSync.ratingsMovies(RatingsFilter.ALL, null, null, null).execute();
if (response.isSuccessful()) {
ratedMovies = response.body();
} else {
if (SgTrakt.isUnauthorized(context, response)) {
return false;
}
Errors.logAndReport("get movie ratings", response);
return false;
}
} catch (Exception e) {
Errors.logAndReport("get movie ratings", e);
return false;
}
if (ratedMovies == null) {
Timber.e("downloadForMovies: null response");
return false;
}
if (ratedMovies.isEmpty()) {
Timber.d("downloadForMovies: no ratings on trakt");
return true;
}
// 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 && TimeTools.isBeforeMillis(movie.rated_at, 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, "downloadForMovies: database update failed");
return false;
}
// save last rated instant
long ratedAtTime = ratedAt.toInstant().toEpochMilli();
PreferenceManager.getDefaultSharedPreferences(context).edit().putLong(TraktSettings.KEY_LAST_MOVIES_RATED_AT, ratedAtTime).apply();
Timber.d("downloadForMovies: success, last rated_at %tF %tT", ratedAtTime, ratedAtTime);
return true;
}
use of com.uwetrottmann.trakt5.entities.Ratings in project SeriesGuide by UweTrottmann.
the class MovieLoader method loadInBackground.
@Override
public MovieDetails loadInBackground() {
// try loading from trakt and tmdb, this might return a cached response
MovieDetails details = app.getMovieTools().getMovieDetails(mTmdbId);
// update local database
updateLocalMovie(getContext(), details, mTmdbId);
// fill in details from local database
Cursor movieQuery = getContext().getContentResolver().query(Movies.buildMovieUri(mTmdbId), MovieQuery.PROJECTION, null, null, null);
if (movieQuery == null || !movieQuery.moveToFirst() || movieQuery.getCount() < 1) {
if (movieQuery != null) {
movieQuery.close();
}
// ensure list flags and watched flag are false on failure
// (assumption: movie not in db, it has the truth, so can't be in any lists or watched)
details.inCollection = false;
details.inWatchlist = false;
details.isWatched = false;
return details;
}
// set local state for watched, collected and watchlist status
// assumption: local db has the truth for these
details.inCollection = DBUtils.restoreBooleanFromInt(movieQuery.getInt(MovieQuery.IN_COLLECTION));
details.inWatchlist = DBUtils.restoreBooleanFromInt(movieQuery.getInt(MovieQuery.IN_WATCHLIST));
details.isWatched = DBUtils.restoreBooleanFromInt(movieQuery.getInt(MovieQuery.WATCHED));
// also use local state of user rating
details.userRating = movieQuery.getInt(MovieQuery.RATING_USER);
// only overwrite other info if remote data failed to load
if (details.traktRatings() == null) {
details.traktRatings(new Ratings());
details.traktRatings().rating = (double) movieQuery.getInt(MovieQuery.RATING_TRAKT);
details.traktRatings().votes = movieQuery.getInt(MovieQuery.RATING_VOTES_TRAKT);
}
if (details.tmdbMovie() == null) {
details.tmdbMovie(new Movie());
details.tmdbMovie().imdb_id = movieQuery.getString(MovieQuery.IMDB_ID);
details.tmdbMovie().title = movieQuery.getString(MovieQuery.TITLE);
details.tmdbMovie().overview = movieQuery.getString(MovieQuery.OVERVIEW);
details.tmdbMovie().poster_path = movieQuery.getString(MovieQuery.POSTER);
details.tmdbMovie().runtime = movieQuery.getInt(MovieQuery.RUNTIME_MIN);
details.tmdbMovie().vote_average = movieQuery.getDouble(MovieQuery.RATING_TMDB);
details.tmdbMovie().vote_count = movieQuery.getInt(MovieQuery.RATING_VOTES_TMDB);
// if stored release date is Long.MAX, movie has no release date
long releaseDateMs = movieQuery.getLong(MovieQuery.RELEASED_UTC_MS);
details.tmdbMovie().release_date = MovieTools.movieReleaseDateFrom(releaseDateMs);
}
// clean up
movieQuery.close();
return details;
}
use of com.uwetrottmann.trakt5.entities.Ratings in project SeriesGuide by UweTrottmann.
the class MovieDetailsFragment method populateMovieViews.
private void populateMovieViews() {
/**
* Get everything from TMDb. Also get additional rating from trakt.
*/
final Ratings traktRatings = movieDetails.traktRatings();
final Movie tmdbMovie = movieDetails.tmdbMovie();
final boolean inCollection = movieDetails.inCollection;
final boolean inWatchlist = movieDetails.inWatchlist;
final boolean isWatched = movieDetails.isWatched;
final int rating = movieDetails.userRating;
textViewMovieTitle.setText(tmdbMovie.title);
getActivity().setTitle(tmdbMovie.title);
textViewMovieDescription.setText(tmdbMovie.overview);
// release date and runtime: "July 17, 2009 | 95 min"
StringBuilder releaseAndRuntime = new StringBuilder();
if (tmdbMovie.release_date != null) {
releaseAndRuntime.append(TimeTools.formatToLocalDate(getContext(), tmdbMovie.release_date));
releaseAndRuntime.append(" | ");
}
releaseAndRuntime.append(getString(R.string.runtime_minutes, String.valueOf(tmdbMovie.runtime)));
textViewMovieDate.setText(releaseAndRuntime.toString());
// check-in button
final String title = tmdbMovie.title;
buttonMovieCheckIn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// display a check-in dialog
MovieCheckInDialogFragment f = MovieCheckInDialogFragment.newInstance(tmdbId, title);
f.show(getFragmentManager(), "checkin-dialog");
Utils.trackAction(getActivity(), TAG, "Check-In");
}
});
CheatSheet.setup(buttonMovieCheckIn);
// hide check-in if not connected to trakt or hexagon is enabled
boolean isConnectedToTrakt = TraktCredentials.get(getActivity()).hasCredentials();
boolean displayCheckIn = isConnectedToTrakt && !HexagonSettings.isEnabled(getActivity());
buttonMovieCheckIn.setVisibility(displayCheckIn ? View.VISIBLE : View.GONE);
dividerMovieButtons.setVisibility(displayCheckIn ? View.VISIBLE : View.GONE);
// watched button (only supported when connected to trakt)
if (isConnectedToTrakt) {
buttonMovieWatched.setText(isWatched ? R.string.action_unwatched : R.string.action_watched);
CheatSheet.setup(buttonMovieWatched, isWatched ? R.string.action_unwatched : R.string.action_watched);
Utils.setCompoundDrawablesRelativeWithIntrinsicBounds(buttonMovieWatched, 0, isWatched ? Utils.resolveAttributeToResourceId(getActivity().getTheme(), R.attr.drawableWatched) : Utils.resolveAttributeToResourceId(getActivity().getTheme(), R.attr.drawableWatch), 0, 0);
buttonMovieWatched.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (isWatched) {
MovieTools.unwatchedMovie(SgApp.from(getActivity()), tmdbId);
Utils.trackAction(getActivity(), TAG, "Unwatched movie");
} else {
MovieTools.watchedMovie(SgApp.from(getActivity()), tmdbId);
Utils.trackAction(getActivity(), TAG, "Watched movie");
}
}
});
buttonMovieWatched.setVisibility(View.VISIBLE);
} else {
buttonMovieWatched.setVisibility(View.GONE);
}
// collected button
Utils.setCompoundDrawablesRelativeWithIntrinsicBounds(buttonMovieCollected, 0, inCollection ? R.drawable.ic_collected : Utils.resolveAttributeToResourceId(getActivity().getTheme(), R.attr.drawableCollect), 0, 0);
buttonMovieCollected.setText(inCollection ? R.string.action_collection_remove : R.string.action_collection_add);
CheatSheet.setup(buttonMovieCollected, inCollection ? R.string.action_collection_remove : R.string.action_collection_add);
buttonMovieCollected.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (inCollection) {
MovieTools.removeFromCollection(SgApp.from(getActivity()), tmdbId);
Utils.trackAction(getActivity(), TAG, "Uncollected movie");
} else {
MovieTools.addToCollection(SgApp.from(getActivity()), tmdbId);
Utils.trackAction(getActivity(), TAG, "Collected movie");
}
}
});
// watchlist button
Utils.setCompoundDrawablesRelativeWithIntrinsicBounds(buttonMovieWatchlisted, 0, inWatchlist ? R.drawable.ic_listed : Utils.resolveAttributeToResourceId(getActivity().getTheme(), R.attr.drawableList), 0, 0);
buttonMovieWatchlisted.setText(inWatchlist ? R.string.watchlist_remove : R.string.watchlist_add);
CheatSheet.setup(buttonMovieWatchlisted, inWatchlist ? R.string.watchlist_remove : R.string.watchlist_add);
buttonMovieWatchlisted.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (inWatchlist) {
MovieTools.removeFromWatchlist(SgApp.from(getActivity()), tmdbId);
Utils.trackAction(getActivity(), TAG, "Unwatchlist movie");
} else {
MovieTools.addToWatchlist(SgApp.from(getActivity()), tmdbId);
Utils.trackAction(getActivity(), TAG, "Watchlist movie");
}
}
});
// show button bar
containerMovieButtons.setVisibility(View.VISIBLE);
// language button
LanguageTools.LanguageData languageData = LanguageTools.getMovieLanguageData(getContext());
if (languageData != null) {
currentLanguageIndex = languageData.languageIndex;
buttonMovieLanguage.setText(languageData.languageString);
} else {
buttonMovieLanguage.setText(null);
}
buttonMovieLanguage.setVisibility(View.VISIBLE);
// ratings
textViewRatingsTmdbValue.setText(TraktTools.buildRatingString(tmdbMovie.vote_average));
textViewRatingsTmdbVotes.setText(TraktTools.buildRatingVotesString(getActivity(), tmdbMovie.vote_count));
if (traktRatings != null) {
textViewRatingsTraktVotes.setText(TraktTools.buildRatingVotesString(getActivity(), traktRatings.votes));
textViewRatingsTraktValue.setText(TraktTools.buildRatingString(traktRatings.rating));
}
// if movie is not in database, can't handle user ratings
if (!inCollection && !inWatchlist && !isWatched) {
textViewRatingsTraktUserLabel.setVisibility(View.GONE);
textViewRatingsTraktUser.setVisibility(View.GONE);
containerRatings.setClickable(false);
// cheat sheet
containerRatings.setLongClickable(false);
} else {
textViewRatingsTraktUserLabel.setVisibility(View.VISIBLE);
textViewRatingsTraktUser.setVisibility(View.VISIBLE);
textViewRatingsTraktUser.setText(TraktTools.buildUserRatingString(getActivity(), rating));
containerRatings.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
rateMovie();
}
});
CheatSheet.setup(containerRatings, R.string.action_rate);
}
containerRatings.setVisibility(View.VISIBLE);
// genres
textViewMovieGenresLabel.setVisibility(View.VISIBLE);
Utils.setValueOrPlaceholder(textViewMovieGenres, TmdbTools.buildGenresString(tmdbMovie.genres));
// trakt comments link
buttonMovieComments.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(getActivity(), TraktCommentsActivity.class);
i.putExtras(TraktCommentsActivity.createInitBundleMovie(title, tmdbId));
Utils.startActivityWithAnimation(getActivity(), i, v);
Utils.trackAction(v.getContext(), TAG, "Comments");
}
});
buttonMovieComments.setVisibility(View.VISIBLE);
// load poster, cache on external storage
if (TextUtils.isEmpty(tmdbMovie.poster_path)) {
frameLayoutMoviePoster.setClickable(false);
frameLayoutMoviePoster.setFocusable(false);
} else {
final String smallImageUrl = TmdbSettings.getImageBaseUrl(getActivity()) + TmdbSettings.POSTER_SIZE_SPEC_W342 + tmdbMovie.poster_path;
ServiceUtils.loadWithPicasso(getActivity(), smallImageUrl).into(imageViewMoviePoster, new Callback.EmptyCallback() {
@Override
public void onSuccess() {
Bitmap bitmap = ((BitmapDrawable) imageViewMoviePoster.getDrawable()).getBitmap();
paletteAsyncTask = Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
int color = palette.getVibrantColor(Color.WHITE);
color = ColorUtils.setAlphaComponent(color, 50);
rootLayoutMovie.setBackgroundColor(color);
}
});
}
});
// click listener for high resolution poster
frameLayoutMoviePoster.setFocusable(true);
frameLayoutMoviePoster.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String largeImageUrl = TmdbSettings.getImageBaseUrl(getActivity()) + TmdbSettings.POSTER_SIZE_SPEC_ORIGINAL + tmdbMovie.poster_path;
Intent intent = new Intent(getActivity(), FullscreenImageActivity.class);
intent.putExtra(FullscreenImageActivity.EXTRA_PREVIEW_IMAGE, smallImageUrl);
intent.putExtra(FullscreenImageActivity.EXTRA_IMAGE, largeImageUrl);
Utils.startActivityWithAnimation(getActivity(), intent, view);
}
});
}
}
use of com.uwetrottmann.trakt5.entities.Ratings in project SeriesGuide by UweTrottmann.
the class SgSyncAdapter method performTraktSync.
private UpdateResult performTraktSync(HashSet<Integer> localShows, long currentTime) {
if (!TraktCredentials.get(getContext()).hasCredentials()) {
Timber.d("performTraktSync: no auth, skip");
return UpdateResult.SUCCESS;
}
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
// get last activity timestamps
TraktTools traktTools = app.getTraktTools();
LastActivities lastActivity = traktTools.getLastActivity();
if (lastActivity == null) {
// trakt is likely offline or busy, try later
Timber.e("performTraktSync: last activity download failed");
return UpdateResult.INCOMPLETE;
}
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
if (localShows.size() == 0) {
Timber.d("performTraktSync: no local shows, skip shows");
} else {
// download and upload episode watched and collected flags
if (performTraktEpisodeSync(localShows, lastActivity.episodes, currentTime) != UpdateResult.SUCCESS) {
return UpdateResult.INCOMPLETE;
}
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
// download show ratings
if (traktTools.downloadShowRatings(lastActivity.shows.rated_at) != UpdateResult.SUCCESS) {
return UpdateResult.INCOMPLETE;
}
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
// download episode ratings
if (traktTools.downloadEpisodeRatings(lastActivity.episodes.rated_at) != UpdateResult.SUCCESS) {
return UpdateResult.INCOMPLETE;
}
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
}
// sync watchlist and collection with trakt
if (app.getMovieTools().syncMovieListsWithTrakt(lastActivity.movies) != UpdateResult.SUCCESS) {
return UpdateResult.INCOMPLETE;
}
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
// download watched movies
if (traktTools.downloadWatchedMovies(lastActivity.movies.watched_at) != UpdateResult.SUCCESS) {
return UpdateResult.INCOMPLETE;
}
// clean up any useless movies (not watched or not in any list)
MovieTools.deleteUnusedMovies(getContext());
if (!AndroidUtils.isNetworkConnected(getContext())) {
return UpdateResult.INCOMPLETE;
}
// download movie ratings
return traktTools.downloadMovieRatings(lastActivity.movies.rated_at);
}
use of com.uwetrottmann.trakt5.entities.Ratings 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;
}
Aggregations