Search in sources :

Example 1 with TvdbException

use of com.battlelancer.seriesguide.thetvdbapi.TvdbException in project SeriesGuide by UweTrottmann.

the class AnalyticsTree method log.

@Override
protected void log(int priority, String tag, String message, Throwable t) {
    if (priority == Log.ERROR) {
        // remove any stack trace attached by Timber
        if (message != null) {
            int newLine = message.indexOf('\n');
            if (newLine > 0) {
                message = message.substring(0, newLine);
            }
        }
        // special treatment for some exceptions
        if (t instanceof TvdbException) {
            TvdbException e = (TvdbException) t;
            Utils.trackCustomEvent(context, CATEGORY_THETVDB_ERROR, tag + ": " + message, e.getMessage());
            return;
        } else if (t instanceof OAuthProblemException) {
            // log trakt OAuth failures
            OAuthProblemException e = (OAuthProblemException) t;
            StringBuilder exceptionMessage = new StringBuilder();
            if (!TextUtils.isEmpty(e.getError())) {
                exceptionMessage.append(e.getError());
            }
            if (!TextUtils.isEmpty(e.getDescription())) {
                exceptionMessage.append(", ").append(e.getDescription());
            }
            if (!TextUtils.isEmpty(e.getUri())) {
                exceptionMessage.append(", ").append(e.getUri());
            }
            Utils.trackCustomEvent(context, "OAuth Error", tag + ": " + message, exceptionMessage.toString());
            return;
        } else if (t instanceof OAuthSystemException) {
            // log trakt OAuth failures
            OAuthSystemException e = (OAuthSystemException) t;
            Utils.trackCustomEvent(context, "OAuth Error", tag + ": " + message, e.getMessage());
            return;
        }
    }
    // drop empty messages
    if (message == null) {
        return;
    }
    // drop debug and verbose logs
    if (priority == Log.DEBUG || priority == Log.VERBOSE) {
        return;
    }
    // transform priority into string
    String level = null;
    switch(priority) {
        case Log.INFO:
            level = "INFO";
            break;
        case Log.WARN:
            level = "WARN";
            break;
        case Log.ERROR:
            level = "ERROR";
            break;
    }
    // finally log to crashlytics
    Crashlytics.log(level + "/" + tag + ": " + message);
    // track some non-fatal exceptions with crashlytics
    if (priority == Log.ERROR) {
        if (t instanceof SQLiteException) {
            Crashlytics.logException(t);
        }
    }
}
Also used : OAuthProblemException(org.apache.oltu.oauth2.common.exception.OAuthProblemException) OAuthSystemException(org.apache.oltu.oauth2.common.exception.OAuthSystemException) TvdbException(com.battlelancer.seriesguide.thetvdbapi.TvdbException) SQLiteException(android.database.sqlite.SQLiteException)

Example 2 with TvdbException

use of com.battlelancer.seriesguide.thetvdbapi.TvdbException in project SeriesGuide by UweTrottmann.

the class TvdbAddLoader method loadInBackground.

@Override
public Result loadInBackground() {
    List<SearchResult> results;
    if (TextUtils.isEmpty(query)) {
        // no query? load a list of trending shows from trakt
        List<TrendingShow> trendingShows = SgTrakt.executeCall(app, traktShows.get().trending(1, 35, Extended.FULL), "get trending shows");
        if (trendingShows != null) {
            List<Show> shows = new LinkedList<>();
            for (TrendingShow show : trendingShows) {
                if (show.show == null || show.show.ids == null || show.show.ids.tvdb == null) {
                    // skip if required values are missing
                    continue;
                }
                shows.add(show.show);
            }
            // manually set the language to the current search language
            results = TraktAddLoader.parseTraktShowsToSearchResults(getContext(), shows, language);
            return buildResultSuccess(results, R.string.add_empty);
        } else {
            return buildResultFailure(R.string.trakt);
        }
    } else {
        // use TheTVDB search for all other (or any) languages
        if (DisplaySettings.LANGUAGE_EN.equals(language)) {
            List<com.uwetrottmann.trakt5.entities.SearchResult> searchResults = SgTrakt.executeCall(app, traktSearch.get().textQueryShow(query, null, null, null, null, null, null, null, null, null, Extended.FULL, 1, 30), "search shows");
            if (searchResults != null) {
                List<Show> shows = new LinkedList<>();
                for (com.uwetrottmann.trakt5.entities.SearchResult result : searchResults) {
                    if (result.show == null || result.show.ids == null || result.show.ids.tvdb == null) {
                        // skip, TVDB id required
                        continue;
                    }
                    shows.add(result.show);
                }
                // manually set the language to English
                results = TraktAddLoader.parseTraktShowsToSearchResults(getContext(), shows, DisplaySettings.LANGUAGE_EN);
                return buildResultSuccess(results, R.string.no_results);
            } else {
                return buildResultFailure(R.string.trakt);
            }
        } else {
            try {
                if (TextUtils.isEmpty(language)) {
                    // use the v1 API to do an any language search not supported by v2
                    results = TvdbTools.getInstance(app).searchShow(query, null);
                } else {
                    results = TvdbTools.getInstance(app).searchSeries(query, language);
                }
                markLocalShows(results);
                return buildResultSuccess(results, R.string.no_results);
            } catch (TvdbException e) {
                Timber.e(e, "Searching show failed");
            }
            return buildResultFailure(R.string.tvdb);
        }
    }
}
Also used : SearchResult(com.battlelancer.seriesguide.items.SearchResult) TrendingShow(com.uwetrottmann.trakt5.entities.TrendingShow) LinkedList(java.util.LinkedList) Show(com.uwetrottmann.trakt5.entities.Show) TrendingShow(com.uwetrottmann.trakt5.entities.TrendingShow) TvdbException(com.battlelancer.seriesguide.thetvdbapi.TvdbException)

Example 3 with TvdbException

use of com.battlelancer.seriesguide.thetvdbapi.TvdbException in project SeriesGuide by UweTrottmann.

the class SgSyncAdapter method onPerformSync.

@SuppressLint("CommitPrefEdits")
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
    // determine type of sync
    final boolean syncImmediately = extras.getBoolean(SyncInitBundle.SYNC_IMMEDIATE, false);
    final SyncType syncType = SyncType.from(extras.getInt(SyncInitBundle.SYNC_TYPE, SyncType.DELTA.id));
    Timber.i("Syncing...%s%s", syncType, (syncImmediately ? "_IMMEDIATE" : "_REGULAR"));
    // should we sync?
    final long currentTime = System.currentTimeMillis();
    if (!syncImmediately && syncType != SyncType.SINGLE) {
        if (!isTimeForSync(getContext(), currentTime)) {
            Timber.d("Syncing...ABORT_DID_JUST_SYNC");
            return;
        }
    }
    // build a list of shows to update
    int[] showsToUpdate;
    if (syncType == SyncType.SINGLE) {
        int showTvdbId = extras.getInt(SyncInitBundle.SYNC_SHOW_TVDB_ID, 0);
        if (showTvdbId == 0) {
            Timber.e("Syncing...ABORT_INVALID_SHOW_TVDB_ID");
            return;
        }
        showsToUpdate = new int[] { showTvdbId };
    } else {
        showsToUpdate = getShowsToUpdate(syncType, currentTime);
        if (showsToUpdate == null) {
            Timber.e("Syncing...ABORT_SHOW_QUERY_FAILED");
            return;
        }
    }
    // from here on we need more sophisticated abort handling, so keep track of errors
    UpdateResult resultCode = UpdateResult.SUCCESS;
    // loop through shows and download latest data from TVDb
    Timber.d("Syncing...TVDb");
    final AtomicInteger updateCount = new AtomicInteger();
    final ContentResolver resolver = getContext().getContentResolver();
    for (int i = updateCount.get(); i < showsToUpdate.length; i++) {
        int id = showsToUpdate[i];
        // stop sync if connectivity is lost
        if (!AndroidUtils.isNetworkConnected(getContext())) {
            resultCode = UpdateResult.INCOMPLETE;
            break;
        }
        try {
            TvdbTools.getInstance(app).updateShow(id);
            // make sure other loaders (activity, overview, details) are notified
            resolver.notifyChange(Episodes.CONTENT_URI_WITHSHOW, null);
        } catch (TvdbException e) {
            // failed, continue with other shows
            resultCode = UpdateResult.INCOMPLETE;
            Timber.e(e, "Updating show failed");
        }
        updateCount.incrementAndGet();
    }
    // do some more things if this is not a quick update
    if (syncType != SyncType.SINGLE) {
        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
        // get latest TMDb configuration
        Timber.d("Syncing...TMDb config");
        getTmdbConfiguration(prefs);
        // sync with Hexagon or trakt
        final HashSet<Integer> showsExisting = ShowTools.getShowTvdbIdsAsSet(getContext());
        @SuppressLint("UseSparseArrays") final HashMap<Integer, SearchResult> showsNew = new HashMap<>();
        if (showsExisting == null) {
            resultCode = UpdateResult.INCOMPLETE;
        } else {
            if (HexagonSettings.isEnabled(getContext())) {
                // sync with hexagon...
                Timber.d("Syncing...Hexagon");
                boolean success = HexagonTools.syncWithHexagon(app, showsExisting, showsNew);
                // don't overwrite failure
                if (resultCode == UpdateResult.SUCCESS) {
                    resultCode = success ? UpdateResult.SUCCESS : UpdateResult.INCOMPLETE;
                }
            } else {
                // ...OR sync with trakt
                Timber.d("Syncing...trakt");
                UpdateResult resultTrakt = performTraktSync(showsExisting, currentTime);
                // don't overwrite failure
                if (resultCode == UpdateResult.SUCCESS) {
                    resultCode = resultTrakt;
                }
                // add shows newly discovered on trakt
                if (showsNew.size() > 0) {
                    List<SearchResult> showsNewList = new LinkedList<>(showsNew.values());
                    TaskManager.getInstance(getContext()).performAddTask(app, showsNewList, true, false);
                }
            }
            // make sure other loaders (activity, overview, details) are notified of changes
            resolver.notifyChange(Episodes.CONTENT_URI_WITHSHOW, null);
        }
        // renew search table if shows were updated and it will not be renewed by add task
        if (updateCount.get() > 0 && showsToUpdate.length > 0 && showsNew.size() == 0) {
            DBUtils.rebuildFtsTable(getContext());
        }
        // update next episodes for all shows
        TaskManager.getInstance(getContext()).tryNextEpisodeUpdateTask();
        // store time of update, set retry counter on failure
        if (resultCode == UpdateResult.SUCCESS) {
            // we were successful, reset failed counter
            prefs.edit().putLong(UpdateSettings.KEY_LASTUPDATE, currentTime).putInt(UpdateSettings.KEY_FAILED_COUNTER, 0).commit();
        } else {
            int failed = UpdateSettings.getFailedNumberOfUpdates(getContext());
            /*
                 * Back off by 2**(failure + 2) * minutes. Purposely set a fake
                 * last update time, because the next update will be triggered
                 * UPDATE_INTERVAL minutes after the last update time. This way
                 * we can trigger it earlier (4min up to 32min).
                 */
            long fakeLastUpdateTime;
            if (failed < 4) {
                fakeLastUpdateTime = currentTime - ((SYNC_INTERVAL_MINIMUM_MINUTES - (int) Math.pow(2, failed + 2)) * DateUtils.MINUTE_IN_MILLIS);
            } else {
                fakeLastUpdateTime = currentTime;
            }
            failed += 1;
            prefs.edit().putLong(UpdateSettings.KEY_LASTUPDATE, fakeLastUpdateTime).putInt(UpdateSettings.KEY_FAILED_COUNTER, failed).commit();
        }
    }
    // There could have been new episodes added after an update
    Utils.runNotificationService(getContext());
    Timber.i("Syncing...%s", resultCode.toString());
}
Also used : SharedPreferences(android.content.SharedPreferences) HashMap(java.util.HashMap) SearchResult(com.battlelancer.seriesguide.items.SearchResult) SuppressLint(android.annotation.SuppressLint) LinkedList(java.util.LinkedList) ContentResolver(android.content.ContentResolver) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) SuppressLint(android.annotation.SuppressLint) TvdbException(com.battlelancer.seriesguide.thetvdbapi.TvdbException) SuppressLint(android.annotation.SuppressLint)

Example 4 with TvdbException

use of com.battlelancer.seriesguide.thetvdbapi.TvdbException 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

TvdbException (com.battlelancer.seriesguide.thetvdbapi.TvdbException)4 SearchResult (com.battlelancer.seriesguide.items.SearchResult)3 LinkedList (java.util.LinkedList)2 SuppressLint (android.annotation.SuppressLint)1 ContentResolver (android.content.ContentResolver)1 SharedPreferences (android.content.SharedPreferences)1 SQLiteException (android.database.sqlite.SQLiteException)1 BaseShow (com.uwetrottmann.trakt5.entities.BaseShow)1 Show (com.uwetrottmann.trakt5.entities.Show)1 TrendingShow (com.uwetrottmann.trakt5.entities.TrendingShow)1 HashMap (java.util.HashMap)1 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 OAuthProblemException (org.apache.oltu.oauth2.common.exception.OAuthProblemException)1 OAuthSystemException (org.apache.oltu.oauth2.common.exception.OAuthSystemException)1