package org.wikipedia.feed.becauseyouread; import android.content.Context; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.google.gson.annotations.SerializedName; import org.wikipedia.Constants; import org.wikipedia.dataclient.WikiSite; import org.wikipedia.dataclient.mwapi.MwException; import org.wikipedia.dataclient.mwapi.MwQueryPage; import org.wikipedia.dataclient.mwapi.MwQueryResponse; import org.wikipedia.dataclient.retrofit.MwCachedService; import org.wikipedia.dataclient.retrofit.WikiCachedService; import org.wikipedia.feed.dataclient.FeedClient; import org.wikipedia.feed.model.Card; import org.wikipedia.history.HistoryEntry; import org.wikipedia.page.bottomcontent.MainPageReadMoreTopicTask; import org.wikipedia.search.SearchResult; import org.wikipedia.search.SearchResults; import org.wikipedia.util.log.L; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import retrofit2.Call; import retrofit2.Response; import retrofit2.http.GET; import retrofit2.http.Query; public class BecauseYouReadClient implements FeedClient { private static final String MORELIKE = "morelike:"; @NonNull private final WikiCachedService<MwApiSearchClient> cachedService = new MwCachedService<>(MwApiSearchClient.class); @Nullable private MainPageReadMoreTopicTask readMoreTopicTask; @Nullable private Call<MwQueryResponse<Pages>> readMoreCall; @Override public void request(@NonNull Context context, @NonNull final WikiSite wiki, int age, @NonNull final FeedClient.Callback cb) { cancel(); readMoreTopicTask = new MainPageReadMoreTopicTask(context, age) { @Override public void onFinish(@Nullable HistoryEntry entry) { if (entry == null) { cb.error(new IOException("Error fetching suggestions")); return; } getSuggestionsForTitle(wiki, entry, cb); } @Override public void onCatch(Throwable caught) { L.w("Error fetching 'because you read' suggestions", caught); cb.error(caught); } }; readMoreTopicTask.execute(); } @Override public void cancel() { if (readMoreTopicTask != null) { readMoreTopicTask.cancel(); readMoreTopicTask = null; } if (readMoreCall != null) { readMoreCall.cancel(); readMoreCall = null; } } private void getSuggestionsForTitle(@NonNull WikiSite wiki, @NonNull final HistoryEntry entry, final FeedClient.Callback cb) { readMoreCall = cachedService.service(wiki).get(MORELIKE + entry.getTitle().getDisplayText()); readMoreCall.enqueue(new retrofit2.Callback<MwQueryResponse<Pages>>() { @Override public void onResponse(Call<MwQueryResponse<Pages>> call, Response<MwQueryResponse<Pages>> response) { MwQueryResponse<Pages> pages = response.body(); if (pages.success() && pages.query().results(entry.getTitle().getWikiSite()) != null) { SearchResults results = SearchResults.filter(pages.query().results(entry.getTitle().getWikiSite()), entry.getTitle().getText(), false); List<BecauseYouReadItemCard> itemCards = new ArrayList<>(); for (SearchResult result : results.getResults()) { itemCards.add(new BecauseYouReadItemCard(result.getPageTitle())); } cb.success(Collections.singletonList((Card) new BecauseYouReadCard(entry, itemCards))); } else if (pages.hasError()) { cb.error(new MwException(pages.getError())); } else { cb.error(new IOException("Error fetching suggestions.")); } } @Override public void onFailure(Call<MwQueryResponse<Pages>> call, Throwable t) { cb.error(t); } }); } static class Pages { @SuppressWarnings("unused") @SerializedName("pages") private List<MwQueryPage> pages; public SearchResults results(WikiSite wiki) { return new SearchResults(pages, wiki); } } private interface MwApiSearchClient { @GET("w/api.php?format=json&formatversion=2&action=query" + "&prop=pageterms|pageimages|pageprops&ppprop=mainpage|disambiguation" + "&wbptterms=description&generator=search&gsrnamespace=0&gsrwhat=text" + "&gsrinfo=&gsrprop=redirecttitle&gsrlimit=" + Constants.SUGGESTION_REQUEST_ITEMS + "&piprop=thumbnail&pilicense=any&pithumbsize=" + Constants.PREFERRED_THUMB_SIZE + "&pilimit=" + Constants.SUGGESTION_REQUEST_ITEMS) @NonNull Call<MwQueryResponse<Pages>> get(@Query("gsrsearch") String morelikeQuery); } }