Browse Source
implement app feed endpoint instead of browser
renovate/org.robolectric-robolectric-4.x
implement app feed endpoint instead of browser
renovate/org.robolectric-robolectric-4.x
Austin Huang
4 years ago
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
7 changed files with 178 additions and 48 deletions
-
33app/src/main/java/awais/instagrabber/asyncs/FeedPostFetchService.java
-
14app/src/main/java/awais/instagrabber/repositories/FeedRepository.java
-
137app/src/main/java/awais/instagrabber/webservices/FeedService.java
-
36app/src/main/java/awais/instagrabber/webservices/GraphQLService.java
-
2app/src/main/java/awais/instagrabber/webservices/LocationService.java
-
2app/src/main/java/awais/instagrabber/webservices/ProfileService.java
-
2app/src/main/java/awais/instagrabber/webservices/TagsService.java
@ -0,0 +1,14 @@ |
|||
package awais.instagrabber.repositories; |
|||
|
|||
import java.util.Map; |
|||
|
|||
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<String> fetch(@FieldMap final Map<String, String> signedForm); |
|||
} |
@ -0,0 +1,137 @@ |
|||
package awais.instagrabber.webservices; |
|||
|
|||
import android.os.Handler; |
|||
import android.util.Log; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import org.json.JSONArray; |
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
|
|||
import java.io.IOException; |
|||
import java.io.InputStream; |
|||
import java.io.InputStreamReader; |
|||
import java.io.Reader; |
|||
import java.nio.charset.StandardCharsets; |
|||
import java.util.ArrayList; |
|||
import java.util.Collections; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.TimeZone; |
|||
import java.util.UUID; |
|||
|
|||
import awais.instagrabber.models.FeedModel; |
|||
import awais.instagrabber.models.PostChild; |
|||
import awais.instagrabber.models.ProfileModel; |
|||
import awais.instagrabber.models.enums.MediaItemType; |
|||
import awais.instagrabber.repositories.FeedRepository; |
|||
import awais.instagrabber.repositories.responses.PostsFetchResponse; |
|||
import awais.instagrabber.utils.Constants; |
|||
import awais.instagrabber.utils.ResponseBodyUtils; |
|||
import awais.instagrabber.utils.TextUtils; |
|||
import retrofit2.Call; |
|||
import retrofit2.Callback; |
|||
import retrofit2.Response; |
|||
import retrofit2.Retrofit; |
|||
|
|||
public class FeedService extends BaseService { |
|||
private static final String TAG = "FeedService"; |
|||
|
|||
private final FeedRepository repository; |
|||
|
|||
private static FeedService instance; |
|||
|
|||
private FeedService() { |
|||
final Retrofit retrofit = getRetrofitBuilder() |
|||
.baseUrl("https://i.instagram.com") |
|||
.build(); |
|||
repository = retrofit.create(FeedRepository.class); |
|||
} |
|||
|
|||
public static FeedService getInstance() { |
|||
if (instance == null) { |
|||
instance = new FeedService(); |
|||
} |
|||
return instance; |
|||
} |
|||
|
|||
public void fetch(final String csrfToken, |
|||
final String cursor, |
|||
final ServiceCallback<PostsFetchResponse> callback) { |
|||
final Map<String, String> form = new HashMap<>(); |
|||
form.put("_uuid", UUID.randomUUID().toString()); |
|||
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"); |
|||
form.put("timezone_offset", String.valueOf(TimeZone.getDefault().getRawOffset() / 1000)); |
|||
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<String> request = repository.fetch(form); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
try { |
|||
// Log.d(TAG, "onResponse: body: " + response.body()); |
|||
final PostsFetchResponse postsFetchResponse = parseResponse(response); |
|||
if (callback != null) { |
|||
callback.onSuccess(postsFetchResponse); |
|||
} |
|||
} catch (JSONException e) { |
|||
Log.e(TAG, "onResponse", e); |
|||
if (callback != null) { |
|||
callback.onFailure(e); |
|||
} |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
if (callback != null) { |
|||
callback.onFailure(t); |
|||
} |
|||
} |
|||
}); |
|||
|
|||
} |
|||
|
|||
@NonNull |
|||
private PostsFetchResponse parseResponse(@NonNull final Response<String> response) throws JSONException { |
|||
if (TextUtils.isEmpty(response.body())) { |
|||
Log.e(TAG, "parseResponse: feed response body is empty with status code: " + response.code()); |
|||
return new PostsFetchResponse(Collections.emptyList(), false, null); |
|||
} |
|||
return parseResponseBody(response.body()); |
|||
} |
|||
|
|||
@NonNull |
|||
private PostsFetchResponse parseResponseBody(@NonNull final String body) |
|||
throws JSONException { |
|||
final JSONObject root = new JSONObject(body); |
|||
final boolean moreAvailable = root.optBoolean("more_available"); |
|||
final String nextMaxId = root.optString("next_max_id"); |
|||
final JSONArray feedItems = root.optJSONArray("items"); |
|||
final List<FeedModel> feedModels = new ArrayList<>(); |
|||
for (int i = 0; i < feedItems.length(); ++i) { |
|||
final JSONObject itemJson = feedItems.optJSONObject(i); |
|||
if (itemJson == null || itemJson.has("injected") |
|||
) { |
|||
continue; |
|||
} |
|||
final FeedModel feedModel = ResponseBodyUtils.parseItem(itemJson); |
|||
if (feedModel != null) { |
|||
feedModels.add(feedModel); |
|||
} |
|||
} |
|||
return new PostsFetchResponse(feedModels, moreAvailable, nextMaxId); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue