mirror of
				https://github.com/KokaKiwi/BarInsta
				synced 2025-11-04 05:25:35 +00:00 
			
		
		
		
	merge discover and feed api's and convert them to kotlin
This commit is contained in:
		
							parent
							
								
									2099aa8676
								
							
						
					
					
						commit
						32fe0edb55
					
				@ -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<List<Media>> fetchListener) {
 | 
			
		||||
        discoverService.topicalExplore(maxId, new ServiceCallback<TopicalExploreFeedResponse>() {
 | 
			
		||||
            @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<WrappedMedia> items = result.getItems();
 | 
			
		||||
                final List<Media> 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<WrappedMedia> items = result.getItems();
 | 
			
		||||
            final List<Media> 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
 | 
			
		||||
 | 
			
		||||
@ -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<PostsFetchResponse>() {
 | 
			
		||||
            @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<Media> 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<Media> mediaResults = result.getFeedModels();
 | 
			
		||||
            feedModels.addAll(mediaResults);
 | 
			
		||||
 | 
			
		||||
            if (fetchListener != null) {
 | 
			
		||||
                fetchListener.onResult(feedModels);
 | 
			
		||||
            }
 | 
			
		||||
        }));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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<FeedFetchResponse> fetch(@FieldMap final Map<String, String> signedForm);
 | 
			
		||||
}
 | 
			
		||||
@ -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<TopicalExploreFeedResponse> topicalExplore(@QueryMap Map<String, String> queryParams);
 | 
			
		||||
}
 | 
			
		||||
    suspend fun topicalExplore(@QueryMap queryParams: Map<String?, String?>?): TopicalExploreFeedResponse?
 | 
			
		||||
 | 
			
		||||
    @FormUrlEncoded
 | 
			
		||||
    @POST("/api/v1/feed/timeline/")
 | 
			
		||||
    suspend fun fetchFeed(@FieldMap signedForm: Map<String?, String?>?): FeedFetchResponse
 | 
			
		||||
}
 | 
			
		||||
@ -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 }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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<TopicalExploreFeedResponse> callback) {
 | 
			
		||||
        final ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String>builder()
 | 
			
		||||
                .put("module", "explore_popular");
 | 
			
		||||
        if (!TextUtils.isEmpty(maxId)) {
 | 
			
		||||
            builder.put("max_id", maxId);
 | 
			
		||||
        }
 | 
			
		||||
        final Call<TopicalExploreFeedResponse> req = repository.topicalExplore(builder.build());
 | 
			
		||||
        req.enqueue(new Callback<TopicalExploreFeedResponse>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onResponse(@NonNull final Call<TopicalExploreFeedResponse> call,
 | 
			
		||||
                                   @NonNull final Response<TopicalExploreFeedResponse> 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<TopicalExploreFeedResponse> call, @NonNull final Throwable t) {
 | 
			
		||||
                callback.onFailure(t);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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<String, String> = 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<String, String>().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<Media> = 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 }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -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<PostsFetchResponse> callback) {
 | 
			
		||||
        final Map<String, String> 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<FeedFetchResponse> request = repository.fetch(form);
 | 
			
		||||
        request.enqueue(new Callback<FeedFetchResponse>() {
 | 
			
		||||
            @Override
 | 
			
		||||
            public void onResponse(@NonNull final Call<FeedFetchResponse> call, @NonNull final Response<FeedFetchResponse> 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<FeedFetchResponse> call, @NonNull final Throwable t) {
 | 
			
		||||
                if (callback != null) {
 | 
			
		||||
                    callback.onFailure(t);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @NonNull
 | 
			
		||||
    private PostsFetchResponse parseResponse(@NonNull final Response<FeedFetchResponse> 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<Media> allPosts = new ArrayList<>();
 | 
			
		||||
        final List<Media> 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<EndOfFeedGroup> 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<Media> 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user