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;
}
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;
}
}
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;
}
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;
}
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;
}
Aggregations