From 32fe0edb553f56e700a6a3dac4162965b1b0daf2 Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Sun, 25 Jul 2021 17:39:57 -0400 Subject: [PATCH] merge discover and feed api's and convert them to kotlin --- .../asyncs/DiscoverPostFetchService.java | 57 ++++---- .../asyncs/FeedPostFetchService.java | 49 +++---- .../fragments/main/DiscoverFragment.java | 3 - .../repositories/FeedRepository.java | 15 -- .../instagrabber/repositories/FeedService.kt | 22 +-- .../webservices/DiscoverRepository.kt | 22 +++ .../webservices/DiscoverService.java | 64 --------- .../webservices/FeedRepository.kt | 84 +++++++++++ .../instagrabber/webservices/FeedService.java | 133 ------------------ 9 files changed, 166 insertions(+), 283 deletions(-) delete mode 100644 app/src/main/java/awais/instagrabber/repositories/FeedRepository.java create mode 100644 app/src/main/java/awais/instagrabber/webservices/DiscoverRepository.kt delete mode 100644 app/src/main/java/awais/instagrabber/webservices/DiscoverService.java create mode 100644 app/src/main/java/awais/instagrabber/webservices/FeedRepository.kt delete mode 100644 app/src/main/java/awais/instagrabber/webservices/FeedService.java diff --git a/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java index b54b2324..ef817cb2 100644 --- a/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java +++ b/app/src/main/java/awais/instagrabber/asyncs/DiscoverPostFetchService.java @@ -10,52 +10,49 @@ import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse; import awais.instagrabber.repositories.responses.WrappedMedia; -import awais.instagrabber.webservices.DiscoverService; +import awais.instagrabber.utils.CoroutineUtilsKt; +import awais.instagrabber.webservices.FeedRepository; import awais.instagrabber.webservices.ServiceCallback; public class DiscoverPostFetchService implements PostFetcher.PostFetchService { private static final String TAG = "DiscoverPostFetchService"; - private final DiscoverService discoverService; + private final FeedRepository feedRepository; private String maxId; private boolean moreAvailable = false; public DiscoverPostFetchService() { - discoverService = DiscoverService.getInstance(); + feedRepository = FeedRepository.Companion.getInstance(); } @Override public void fetch(final FetchListener> fetchListener) { - discoverService.topicalExplore(maxId, new ServiceCallback() { - @Override - public void onSuccess(final TopicalExploreFeedResponse result) { - if (result == null) { - onFailure(new RuntimeException("result is null")); - return; - } - moreAvailable = result.getMoreAvailable(); - maxId = result.getNextMaxId(); - final List items = result.getItems(); - final List posts; - if (items == null) { - posts = Collections.emptyList(); - } else { - posts = items.stream() - .map(WrappedMedia::getMedia) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - } - if (fetchListener != null) { - fetchListener.onResult(posts); - } - } - - @Override - public void onFailure(final Throwable t) { + feedRepository.topicalExplore(maxId, CoroutineUtilsKt.getContinuation((result, t) -> { + if (t != null) { if (fetchListener != null) { fetchListener.onFailure(t); } + return; } - }); + if (result == null) { + fetchListener.onFailure(new RuntimeException("result is null")); + return; + } + moreAvailable = result.getMoreAvailable(); + maxId = result.getNextMaxId(); + final List items = result.getItems(); + final List posts; + if (items == null) { + posts = Collections.emptyList(); + } else { + posts = items.stream() + .map(WrappedMedia::getMedia) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + if (fetchListener != null) { + fetchListener.onResult(posts); + } + })); } @Override diff --git a/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java b/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java index 96643339..fbc14f3d 100644 --- a/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java +++ b/app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java @@ -9,19 +9,20 @@ import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.PostsFetchResponse; import awais.instagrabber.utils.Constants; import awais.instagrabber.utils.CookieUtils; -import awais.instagrabber.webservices.FeedService; +import awais.instagrabber.utils.CoroutineUtilsKt; +import awais.instagrabber.webservices.FeedRepository; import awais.instagrabber.webservices.ServiceCallback; import static awais.instagrabber.utils.Utils.settingsHelper; public class FeedPostFetchService implements PostFetcher.PostFetchService { private static final String TAG = "FeedPostFetchService"; - private final FeedService feedService; + private final FeedRepository feedRepository; private String nextCursor; private boolean hasNextPage; public FeedPostFetchService() { - feedService = FeedService.getInstance(); + feedRepository = FeedRepository.Companion.getInstance(); } @Override @@ -31,35 +32,27 @@ public class FeedPostFetchService implements PostFetcher.PostFetchService { final String csrfToken = CookieUtils.getCsrfTokenFromCookie(cookie); final String deviceUuid = settingsHelper.getString(Constants.DEVICE_UUID); feedModels.clear(); - feedService.fetch(csrfToken, deviceUuid, nextCursor, new ServiceCallback() { - @Override - public void onSuccess(final PostsFetchResponse result) { - if (result == null && feedModels.size() > 0) { - fetchListener.onResult(feedModels); - return; - } else if (result == null) return; - nextCursor = result.getNextCursor(); - hasNextPage = result.getHasNextPage(); - - final List mediaResults = result.getFeedModels(); - feedModels.addAll(mediaResults); - - if (fetchListener != null) { - // if (feedModels.size() < 15 && hasNextPage) { - // feedService.fetch(csrfToken, nextCursor, this); - // } else { - fetchListener.onResult(feedModels); - // } - } - } - - @Override - public void onFailure(final Throwable t) { + feedRepository.fetchFeed(csrfToken, deviceUuid, nextCursor, CoroutineUtilsKt.getContinuation((result, t) -> { + if (t != null) { if (fetchListener != null) { fetchListener.onFailure(t); } + return; } - }); + if (result == null && feedModels.size() > 0) { + fetchListener.onResult(feedModels); + return; + } else if (result == null) return; + nextCursor = result.getNextCursor(); + hasNextPage = result.getHasNextPage(); + + final List mediaResults = result.getFeedModels(); + feedModels.addAll(mediaResults); + + if (fetchListener != null) { + fetchListener.onResult(feedModels); + } + })); } @Override diff --git a/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java index 1d915d86..aa75f503 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/DiscoverFragment.java @@ -16,7 +16,6 @@ import androidx.activity.OnBackPressedCallback; import androidx.activity.OnBackPressedDispatcher; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.ActionBar; import androidx.fragment.app.Fragment; import androidx.navigation.NavDirections; import androidx.navigation.fragment.NavHostFragment; @@ -34,7 +33,6 @@ import awais.instagrabber.customviews.PrimaryActionModeCallback; import awais.instagrabber.databinding.FragmentDiscoverBinding; import awais.instagrabber.dialogs.PostsLayoutPreferencesDialogFragment; import awais.instagrabber.models.PostsLayoutPreferences; -import awais.instagrabber.models.enums.PostItemType; import awais.instagrabber.repositories.responses.Location; import awais.instagrabber.repositories.responses.Media; import awais.instagrabber.repositories.responses.User; @@ -44,7 +42,6 @@ import awais.instagrabber.utils.CookieUtils; import awais.instagrabber.utils.DownloadUtils; import awais.instagrabber.utils.TextUtils; import awais.instagrabber.utils.Utils; -import awais.instagrabber.webservices.DiscoverService; import static awais.instagrabber.utils.Utils.settingsHelper; diff --git a/app/src/main/java/awais/instagrabber/repositories/FeedRepository.java b/app/src/main/java/awais/instagrabber/repositories/FeedRepository.java deleted file mode 100644 index b5273e35..00000000 --- a/app/src/main/java/awais/instagrabber/repositories/FeedRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package awais.instagrabber.repositories; - -import java.util.Map; - -import awais.instagrabber.repositories.responses.feed.FeedFetchResponse; -import retrofit2.Call; -import retrofit2.http.FieldMap; -import retrofit2.http.FormUrlEncoded; -import retrofit2.http.POST; - -public interface FeedRepository { - @FormUrlEncoded - @POST("/api/v1/feed/timeline/") - Call fetch(@FieldMap final Map signedForm); -} diff --git a/app/src/main/java/awais/instagrabber/repositories/FeedService.kt b/app/src/main/java/awais/instagrabber/repositories/FeedService.kt index aed6d4c2..17c9a8a7 100644 --- a/app/src/main/java/awais/instagrabber/repositories/FeedService.kt +++ b/app/src/main/java/awais/instagrabber/repositories/FeedService.kt @@ -1,13 +1,15 @@ -package awais.instagrabber.repositories; +package awais.instagrabber.repositories -import java.util.Map; +import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse +import awais.instagrabber.repositories.responses.feed.FeedFetchResponse +import retrofit2.Call +import retrofit2.http.* -import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse; -import retrofit2.Call; -import retrofit2.http.GET; -import retrofit2.http.QueryMap; - -public interface DiscoverRepository { +interface FeedService { @GET("/api/v1/discover/topical_explore/") - Call topicalExplore(@QueryMap Map queryParams); -} + suspend fun topicalExplore(@QueryMap queryParams: Map?): TopicalExploreFeedResponse? + + @FormUrlEncoded + @POST("/api/v1/feed/timeline/") + suspend fun fetchFeed(@FieldMap signedForm: Map?): FeedFetchResponse +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/webservices/DiscoverRepository.kt b/app/src/main/java/awais/instagrabber/webservices/DiscoverRepository.kt new file mode 100644 index 00000000..10617aaa --- /dev/null +++ b/app/src/main/java/awais/instagrabber/webservices/DiscoverRepository.kt @@ -0,0 +1,22 @@ +package awais.instagrabber.webservices + +import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse +import awais.instagrabber.utils.TextUtils.isEmpty +import awais.instagrabber.repositories.FeedService +import com.google.common.collect.ImmutableMap + +open class DiscoverRepository(private val repository: FeedService) { + + + companion object { + @Volatile + private var INSTANCE: DiscoverRepository? = null + + fun getInstance(): DiscoverRepository { + return INSTANCE ?: synchronized(this) { + val service = RetrofitFactory.retrofit.create(FeedService::class.java) + DiscoverRepository(service).also { INSTANCE = it } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/webservices/DiscoverService.java b/app/src/main/java/awais/instagrabber/webservices/DiscoverService.java deleted file mode 100644 index 5b275a76..00000000 --- a/app/src/main/java/awais/instagrabber/webservices/DiscoverService.java +++ /dev/null @@ -1,64 +0,0 @@ -package awais.instagrabber.webservices; - -import androidx.annotation.NonNull; - -import com.google.common.collect.ImmutableMap; - -import java.util.Objects; - -import awais.instagrabber.repositories.DiscoverRepository; -import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse; -import awais.instagrabber.utils.TextUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -public class DiscoverService { - - private static final String TAG = "DiscoverService"; - - private final DiscoverRepository repository; - - private static DiscoverService instance; - - private DiscoverService() { - repository = RetrofitFactory.INSTANCE - .getRetrofit() - .create(DiscoverRepository.class); - } - - public static DiscoverService getInstance() { - if (instance == null) { - instance = new DiscoverService(); - } - return instance; - } - - public void topicalExplore(final String maxId, - final ServiceCallback callback) { - final ImmutableMap.Builder builder = ImmutableMap.builder() - .put("module", "explore_popular"); - if (!TextUtils.isEmpty(maxId)) { - builder.put("max_id", maxId); - } - final Call req = repository.topicalExplore(builder.build()); - req.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, - @NonNull final Response response) { - if (callback == null) return; - final TopicalExploreFeedResponse feedResponse = response.body(); - if (feedResponse == null) { - callback.onSuccess(null); - return; - } - callback.onSuccess(feedResponse); - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - callback.onFailure(t); - } - }); - } -} diff --git a/app/src/main/java/awais/instagrabber/webservices/FeedRepository.kt b/app/src/main/java/awais/instagrabber/webservices/FeedRepository.kt new file mode 100644 index 00000000..1abaa7ad --- /dev/null +++ b/app/src/main/java/awais/instagrabber/webservices/FeedRepository.kt @@ -0,0 +1,84 @@ +package awais.instagrabber.webservices + +import android.util.Log +import awais.instagrabber.repositories.FeedService +import awais.instagrabber.repositories.responses.Media +import awais.instagrabber.repositories.responses.PostsFetchResponse +import awais.instagrabber.repositories.responses.discover.TopicalExploreFeedResponse +import awais.instagrabber.repositories.responses.feed.FeedFetchResponse +import awais.instagrabber.utils.TextUtils.isEmpty +import com.google.common.collect.ImmutableMap +import java.util.* + +open class FeedRepository(private val repository: FeedService) { + suspend fun fetchFeed( + csrfToken: String, + deviceUuid: String, + cursor: String + ): PostsFetchResponse { + val form: MutableMap = HashMap() + form["_uuid"] = deviceUuid + form["_csrftoken"] = csrfToken + form["phone_id"] = UUID.randomUUID().toString() + form["device_id"] = UUID.randomUUID().toString() + form["client_session_id"] = UUID.randomUUID().toString() + form["is_prefetch"] = "0" + if (!isEmpty(cursor)) { + form["max_id"] = cursor + form["reason"] = "pagination" + } else { + form["is_pull_to_refresh"] = "1" + form["reason"] = "pull_to_refresh" + } + return parseResponse(repository.fetchFeed(form.toMap())) + } + + suspend fun topicalExplore(maxId: String): TopicalExploreFeedResponse? { + val builder = ImmutableMap.builder().put("module", "explore_popular") + if (!isEmpty(maxId)) { + builder.put("max_id", maxId) + } + return repository.topicalExplore(builder.build()) + } + + private fun parseResponse(feedFetchResponse: FeedFetchResponse): PostsFetchResponse { + val moreAvailable = feedFetchResponse.isMoreAvailable + var nextMaxId = feedFetchResponse.nextMaxId + val needNewMaxId = nextMaxId == "feed_recs_head_load" + val allPosts: MutableList = ArrayList() + val items = feedFetchResponse.items + for (media in items) { + if (needNewMaxId && media!!.endOfFeedDemarcator != null) { + val endOfFeedDemarcator = media.endOfFeedDemarcator + val groupSet = endOfFeedDemarcator!!.groupSet ?: continue + val groups = groupSet.groups ?: continue + for (group in groups) { + val id = group.id + if (id == null || id != "past_posts") continue + nextMaxId = group.nextMaxId + val feedItems = group.feedItems + for (feedItem in feedItems) { + if (feedItem == null || feedItem.isInjected() || feedItem.type == null) continue + allPosts.add(feedItem) + } + } + continue + } + if (media == null || media.isInjected() || media.type == null) continue + allPosts.add(media) + } + return PostsFetchResponse(allPosts, moreAvailable, nextMaxId) + } + + companion object { + @Volatile + private var INSTANCE: FeedRepository? = null + + fun getInstance(): FeedRepository { + return INSTANCE ?: synchronized(this) { + val service = RetrofitFactory.retrofit.create(FeedService::class.java) + FeedRepository(service).also { INSTANCE = it } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/awais/instagrabber/webservices/FeedService.java b/app/src/main/java/awais/instagrabber/webservices/FeedService.java deleted file mode 100644 index 5e6dbf41..00000000 --- a/app/src/main/java/awais/instagrabber/webservices/FeedService.java +++ /dev/null @@ -1,133 +0,0 @@ -package awais.instagrabber.webservices; - -import android.util.Log; - -import androidx.annotation.NonNull; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import awais.instagrabber.repositories.FeedRepository; -import awais.instagrabber.repositories.responses.Media; -import awais.instagrabber.repositories.responses.PostsFetchResponse; -import awais.instagrabber.repositories.responses.feed.EndOfFeedDemarcator; -import awais.instagrabber.repositories.responses.feed.EndOfFeedGroup; -import awais.instagrabber.repositories.responses.feed.EndOfFeedGroupSet; -import awais.instagrabber.repositories.responses.feed.FeedFetchResponse; -import awais.instagrabber.utils.TextUtils; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; - -public class FeedService { - private static final String TAG = "FeedService"; - - private final FeedRepository repository; - - private static FeedService instance; - - private FeedService() { - repository = RetrofitFactory.INSTANCE - .getRetrofit() - .create(FeedRepository.class); - } - - public static FeedService getInstance() { - if (instance == null) { - instance = new FeedService(); - } - return instance; - } - - public void fetch(final String csrfToken, - final String deviceUuid, - final String cursor, - final ServiceCallback callback) { - final Map form = new HashMap<>(); - form.put("_uuid", deviceUuid); - form.put("_csrftoken", csrfToken); - form.put("phone_id", UUID.randomUUID().toString()); - form.put("device_id", UUID.randomUUID().toString()); - form.put("client_session_id", UUID.randomUUID().toString()); - form.put("is_prefetch", "0"); - if (!TextUtils.isEmpty(cursor)) { - form.put("max_id", cursor); - form.put("reason", "pagination"); - } else { - form.put("is_pull_to_refresh", "1"); - form.put("reason", "pull_to_refresh"); - } - final Call request = repository.fetch(form); - request.enqueue(new Callback() { - @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - try { - // Log.d(TAG, "onResponse: body: " + response.body()); - final PostsFetchResponse postsFetchResponse = parseResponse(response); - if (callback != null) { - callback.onSuccess(postsFetchResponse); - } - } catch (Exception e) { - Log.e(TAG, "onResponse", e); - if (callback != null) { - callback.onFailure(e); - } - } - } - - @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { - if (callback != null) { - callback.onFailure(t); - } - } - }); - - } - - @NonNull - private PostsFetchResponse parseResponse(@NonNull final Response response) { - final FeedFetchResponse feedFetchResponse = response.body(); - if (feedFetchResponse == null) { - Log.e(TAG, "parseResponse: feed response body is empty with status code: " + response.code()); - return new PostsFetchResponse(Collections.emptyList(), false, null); - } - return parseResponseBody(feedFetchResponse); - } - - @NonNull - private PostsFetchResponse parseResponseBody(@NonNull final FeedFetchResponse feedFetchResponse) { - final boolean moreAvailable = feedFetchResponse.isMoreAvailable(); - String nextMaxId = feedFetchResponse.getNextMaxId(); - final boolean needNewMaxId = nextMaxId.equals("feed_recs_head_load"); - final List allPosts = new ArrayList<>(); - final List items = feedFetchResponse.getItems(); - for (final Media media : items) { - if (needNewMaxId && media.getEndOfFeedDemarcator() != null) { - final EndOfFeedDemarcator endOfFeedDemarcator = media.getEndOfFeedDemarcator(); - final EndOfFeedGroupSet groupSet = endOfFeedDemarcator.getGroupSet(); - if (groupSet == null) continue; - final List groups = groupSet.getGroups(); - if (groups == null) continue; - for (final EndOfFeedGroup group : groups) { - final String id = group.getId(); - if (id == null || !id.equals("past_posts")) continue; - nextMaxId = group.getNextMaxId(); - final List feedItems = group.getFeedItems(); - for (final Media feedItem : feedItems) { - if (feedItem == null || feedItem.isInjected() || feedItem.getType() == null) continue; - allPosts.add(feedItem); - } - } - continue; - } - if (media == null || media.isInjected() || media.getType() == null) continue; - allPosts.add(media); - } - return new PostsFetchResponse(allPosts, moreAvailable, nextMaxId); - } -} \ No newline at end of file