mirror of
https://github.com/KokaKiwi/BarInsta
synced 2024-12-23 05:16:58 +00:00
instagram is not returning most data in graphql anymore so mitigation has been implemented, but again they need to stop trampling on the rights of anonymous users
This commit is contained in:
parent
133abcca85
commit
f67d3a023c
@ -10,8 +10,8 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
|
||||
versionCode 52
|
||||
versionName '19.0.0'
|
||||
versionCode 53
|
||||
versionName '19.0.1'
|
||||
|
||||
multiDexEnabled true
|
||||
|
||||
|
@ -64,7 +64,7 @@ public class FeedGridItemViewHolder extends RecyclerView.ViewHolder {
|
||||
binding.postImage.setAspectRatio(1);
|
||||
}
|
||||
if (layoutPreferences.isAvatarVisible()) {
|
||||
binding.profilePic.setVisibility(View.VISIBLE);
|
||||
binding.profilePic.setVisibility(TextUtils.isEmpty(feedModel.getProfileModel().getSdProfilePic()) ? View.GONE : View.VISIBLE);
|
||||
binding.profilePic.setImageURI(feedModel.getProfileModel().getSdProfilePic());
|
||||
final ViewGroup.LayoutParams layoutParams = binding.profilePic.getLayoutParams();
|
||||
@DimenRes final int dimenRes;
|
||||
@ -88,7 +88,7 @@ public class FeedGridItemViewHolder extends RecyclerView.ViewHolder {
|
||||
binding.profilePic.setVisibility(View.GONE);
|
||||
}
|
||||
if (layoutPreferences.isNameVisible()) {
|
||||
binding.name.setVisibility(View.VISIBLE);
|
||||
binding.name.setVisibility(TextUtils.isEmpty(feedModel.getProfileModel().getUsername()) ? View.GONE : View.VISIBLE);
|
||||
binding.name.setText(feedModel.getProfileModel().getUsername());
|
||||
} else {
|
||||
binding.name.setVisibility(View.GONE);
|
||||
|
@ -14,16 +14,36 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService {
|
||||
private final TagsService tagsService;
|
||||
private final HashtagModel hashtagModel;
|
||||
private String nextMaxId;
|
||||
private boolean moreAvailable;
|
||||
private boolean moreAvailable, isLoggedIn;
|
||||
|
||||
public HashtagPostFetchService(final HashtagModel hashtagModel) {
|
||||
public HashtagPostFetchService(final HashtagModel hashtagModel, final boolean isLoggedIn) {
|
||||
this.hashtagModel = hashtagModel;
|
||||
this.isLoggedIn = isLoggedIn;
|
||||
tagsService = TagsService.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fetch(final FetchListener<List<FeedModel>> fetchListener) {
|
||||
tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, new ServiceCallback<TagPostsFetchResponse>() {
|
||||
if (isLoggedIn) tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, new ServiceCallback<TagPostsFetchResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final TagPostsFetchResponse result) {
|
||||
if (result == null) return;
|
||||
nextMaxId = result.getNextMaxId();
|
||||
moreAvailable = result.isMoreAvailable();
|
||||
if (fetchListener != null) {
|
||||
fetchListener.onResult(result.getItems());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(final Throwable t) {
|
||||
// Log.e(TAG, "onFailure: ", t);
|
||||
if (fetchListener != null) {
|
||||
fetchListener.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
else tagsService.fetchGraphQLPosts(hashtagModel.getName().toLowerCase(), nextMaxId, new ServiceCallback<TagPostsFetchResponse>() {
|
||||
@Override
|
||||
public void onSuccess(final TagPostsFetchResponse result) {
|
||||
if (result == null) return;
|
||||
|
@ -352,7 +352,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
|
||||
private void setupPosts() {
|
||||
binding.posts.setViewModelStoreOwner(this)
|
||||
.setLifeCycleOwner(this)
|
||||
.setPostFetchService(new HashtagPostFetchService(hashtagModel))
|
||||
.setPostFetchService(new HashtagPostFetchService(hashtagModel, isLoggedIn))
|
||||
.setLayoutPreferences(PostsLayoutPreferences.fromJson(settingsHelper.getString(Constants.PREF_HASHTAG_POSTS_LAYOUT)))
|
||||
.addFetchStatusChangeListener(fetching -> updateSwipeRefreshState())
|
||||
.setFeedItemCallback(feedItemCallback)
|
||||
|
@ -112,7 +112,7 @@ public class StoryViewerFragment extends Fragment {
|
||||
private StoryModel currentStory;
|
||||
private int slidePos;
|
||||
private int lastSlidePos;
|
||||
private String url, username;
|
||||
private String url;
|
||||
private PollModel poll;
|
||||
private QuestionModel question;
|
||||
private String[] mentions;
|
||||
@ -498,7 +498,7 @@ public class StoryViewerFragment extends Fragment {
|
||||
}
|
||||
} else if (!TextUtils.isEmpty(fragmentArgs.getProfileId()) && !TextUtils.isEmpty(fragmentArgs.getUsername())) {
|
||||
currentStoryMediaId = fragmentArgs.getProfileId();
|
||||
username = fragmentArgs.getUsername();
|
||||
currentStoryUsername = fragmentArgs.getUsername();
|
||||
}
|
||||
isHashtag = fragmentArgs.getIsHashtag();
|
||||
isLoc = fragmentArgs.getIsLoc();
|
||||
@ -534,7 +534,7 @@ public class StoryViewerFragment extends Fragment {
|
||||
}
|
||||
};
|
||||
storiesService.getUserStory(currentStoryMediaId,
|
||||
username,
|
||||
currentStoryUsername,
|
||||
isLoc,
|
||||
isHashtag,
|
||||
isHighlight,
|
||||
|
@ -39,10 +39,10 @@ public class AboutFragment extends BasePreferencesFragment {
|
||||
//thirdPartyCategory.setSummary(R.string.about_category_3pt_summary);
|
||||
thirdPartyCategory.setIconSpaceReserved(false);
|
||||
// alphabetical order!!!
|
||||
thirdPartyCategory.addPreference(getACIPreference());
|
||||
thirdPartyCategory.addPreference(getAutolinkPreference());
|
||||
thirdPartyCategory.addPreference(getExoPlayerPreference());
|
||||
thirdPartyCategory.addPreference(getFrescoPreference());
|
||||
thirdPartyCategory.addPreference(getIcafePreference());
|
||||
thirdPartyCategory.addPreference(getJsoupPreference());
|
||||
thirdPartyCategory.addPreference(getMDIPreference());
|
||||
thirdPartyCategory.addPreference(getRetrofitPreference());
|
||||
@ -101,7 +101,7 @@ public class AboutFragment extends BasePreferencesFragment {
|
||||
if (context == null) return null;
|
||||
final Preference preference = new Preference(context);
|
||||
preference.setTitle("Retrofit");
|
||||
preference.setSummary("Copyright 2013 Square, Inc. Apache Version 2.0.");
|
||||
preference.setSummary("Copyright 2013 Square, Inc. Apache 2.0.");
|
||||
preference.setIconSpaceReserved(false);
|
||||
preference.setOnPreferenceClickListener(p -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
@ -149,7 +149,7 @@ public class AboutFragment extends BasePreferencesFragment {
|
||||
if (context == null) return null;
|
||||
final Preference preference = new Preference(context);
|
||||
preference.setTitle("ExoPlayer");
|
||||
preference.setSummary("Copyright (C) 2016 The Android Open Source Project. Apache Version 2.0.");
|
||||
preference.setSummary("Copyright (C) 2016 The Android Open Source Project. Apache 2.0.");
|
||||
preference.setIconSpaceReserved(false);
|
||||
preference.setOnPreferenceClickListener(p -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
@ -165,7 +165,7 @@ public class AboutFragment extends BasePreferencesFragment {
|
||||
if (context == null) return null;
|
||||
final Preference preference = new Preference(context);
|
||||
preference.setTitle("Material Design Icons");
|
||||
preference.setSummary("Copyright (C) 2014 Austin Andrews & Google LLC. Apache Version 2.0.");
|
||||
preference.setSummary("Copyright (C) 2014 Austin Andrews & Google LLC. Apache 2.0.");
|
||||
preference.setIconSpaceReserved(false);
|
||||
preference.setOnPreferenceClickListener(p -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
@ -181,7 +181,7 @@ public class AboutFragment extends BasePreferencesFragment {
|
||||
if (context == null) return null;
|
||||
final Preference preference = new Preference(context);
|
||||
preference.setTitle("AutoLinkTextViewV2");
|
||||
preference.setSummary("Copyright (C) 2019 Arman Chatikyan. Apache Version 2.0.");
|
||||
preference.setSummary("Copyright (C) 2019 Arman Chatikyan. Apache 2.0.");
|
||||
preference.setIconSpaceReserved(false);
|
||||
preference.setOnPreferenceClickListener(p -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
@ -192,16 +192,16 @@ public class AboutFragment extends BasePreferencesFragment {
|
||||
return preference;
|
||||
}
|
||||
|
||||
private Preference getIcafePreference() {
|
||||
private Preference getACIPreference() {
|
||||
final Context context = getContext();
|
||||
if (context == null) return null;
|
||||
final Preference preference = new Preference(context);
|
||||
preference.setTitle("ICAFE");
|
||||
preference.setSummary("Copyright (C) 2014-2019 Wen Yu. Eclipse Version 2.0.");
|
||||
preference.setTitle("Apache Commons Imaging");
|
||||
preference.setSummary("Copyright 2007-2020 The Apache Software Foundation. Apache 2.0.");
|
||||
preference.setIconSpaceReserved(false);
|
||||
preference.setOnPreferenceClickListener(p -> {
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse("https://github.com/dragon66/icafe"));
|
||||
intent.setData(Uri.parse("https://commons.apache.org/proper/commons-imaging/"));
|
||||
startActivity(intent);
|
||||
return true;
|
||||
});
|
||||
|
@ -24,4 +24,7 @@ public interface TagsRepository {
|
||||
@GET("/api/v1/feed/tag/{tag}/")
|
||||
Call<String> fetchPosts(@Path("tag") final String tag,
|
||||
@QueryMap Map<String, String> queryParams);
|
||||
|
||||
@GET("/graphql/query/")
|
||||
Call<String> fetchGraphQLPosts(@QueryMap(encoded = true) Map<String, String> queryParams);
|
||||
}
|
||||
|
@ -665,6 +665,124 @@ public final class ResponseBodyUtils {
|
||||
return feedModelBuilder.build();
|
||||
}
|
||||
|
||||
public static FeedModel parseGraphQLItem(final JSONObject itemJson) throws JSONException {
|
||||
if (itemJson == null) {
|
||||
return null;
|
||||
}
|
||||
final JSONObject feedItem = itemJson.getJSONObject("node");
|
||||
final String mediaType = feedItem.optString("__typename");
|
||||
if (mediaType.isEmpty() || "GraphSuggestedUserFeedUnit".equals(mediaType))
|
||||
return null;
|
||||
|
||||
final boolean isVideo = feedItem.optBoolean("is_video");
|
||||
final long videoViews = feedItem.optLong("video_view_count", 0);
|
||||
|
||||
final String displayUrl = feedItem.optString("display_url");
|
||||
if (TextUtils.isEmpty(displayUrl)) return null;
|
||||
final String resourceUrl;
|
||||
if (isVideo && feedItem.has("video_url")) {
|
||||
resourceUrl = feedItem.getString("video_url");
|
||||
} else {
|
||||
resourceUrl = feedItem.has("display_resources") ? ResponseBodyUtils.getHighQualityImage(feedItem) : displayUrl;
|
||||
}
|
||||
|
||||
ProfileModel profileModel = null;
|
||||
if (feedItem.has("owner")) {
|
||||
final JSONObject owner = feedItem.getJSONObject("owner");
|
||||
profileModel = new ProfileModel(
|
||||
owner.optBoolean("is_private"),
|
||||
false, // if you can see it then you def follow
|
||||
owner.optBoolean("is_verified"),
|
||||
owner.getString(Constants.EXTRAS_ID),
|
||||
owner.optString(Constants.EXTRAS_USERNAME),
|
||||
owner.optString("full_name"),
|
||||
null,
|
||||
null,
|
||||
owner.optString("profile_pic_url"),
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment");
|
||||
final long commentsCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0;
|
||||
tempJsonObject = feedItem.optJSONObject("edge_media_preview_like");
|
||||
final long likesCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0;
|
||||
tempJsonObject = feedItem.optJSONObject("edge_media_to_caption");
|
||||
final JSONArray captions = tempJsonObject != null ? tempJsonObject.getJSONArray("edges") : null;
|
||||
String captionText = null;
|
||||
if (captions != null && captions.length() > 0) {
|
||||
if ((tempJsonObject = captions.optJSONObject(0)) != null &&
|
||||
(tempJsonObject = tempJsonObject.optJSONObject("node")) != null) {
|
||||
captionText = tempJsonObject.getString("text");
|
||||
}
|
||||
}
|
||||
final JSONObject location = feedItem.optJSONObject("location");
|
||||
// Log.d(TAG, "location: " + (location == null ? null : location.toString()));
|
||||
String locationId = null;
|
||||
String locationName = null;
|
||||
if (location != null) {
|
||||
locationName = location.optString("name");
|
||||
if (location.has("id")) {
|
||||
locationId = location.getString("id");
|
||||
} else if (location.has("pk")) {
|
||||
locationId = location.getString("pk");
|
||||
}
|
||||
// Log.d(TAG, "locationId: " + locationId);
|
||||
}
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
final JSONObject dimensions = feedItem.optJSONObject("dimensions");
|
||||
if (dimensions != null) {
|
||||
height = dimensions.optInt("height");
|
||||
width = dimensions.optInt("width");
|
||||
}
|
||||
String thumbnailUrl = null;
|
||||
try {
|
||||
thumbnailUrl = feedItem.getJSONArray("display_resources")
|
||||
.getJSONObject(0)
|
||||
.getString("src");
|
||||
} catch (JSONException ignored) {}
|
||||
final FeedModel.Builder feedModelBuilder = new FeedModel.Builder()
|
||||
.setProfileModel(profileModel)
|
||||
.setItemType(isVideo ? MediaItemType.MEDIA_TYPE_VIDEO
|
||||
: MediaItemType.MEDIA_TYPE_IMAGE)
|
||||
.setViewCount(videoViews)
|
||||
.setPostId(feedItem.getString(Constants.EXTRAS_ID))
|
||||
.setDisplayUrl(resourceUrl)
|
||||
.setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl : displayUrl)
|
||||
.setShortCode(feedItem.getString(Constants.EXTRAS_SHORTCODE))
|
||||
.setPostCaption(captionText)
|
||||
.setCommentsCount(commentsCount)
|
||||
.setTimestamp(feedItem.optLong("taken_at_timestamp", -1))
|
||||
.setLiked(feedItem.optBoolean("viewer_has_liked"))
|
||||
.setBookmarked(feedItem.optBoolean("viewer_has_saved"))
|
||||
.setLikesCount(likesCount)
|
||||
.setLocationName(locationName)
|
||||
.setLocationId(locationId)
|
||||
.setImageHeight(height)
|
||||
.setImageWidth(width);
|
||||
|
||||
final boolean isSlider = "GraphSidecar".equals(mediaType) && feedItem.has("edge_sidecar_to_children");
|
||||
|
||||
if (isSlider) {
|
||||
feedModelBuilder.setItemType(MediaItemType.MEDIA_TYPE_SLIDER);
|
||||
final JSONObject sidecar = feedItem.optJSONObject("edge_sidecar_to_children");
|
||||
if (sidecar != null) {
|
||||
final JSONArray children = sidecar.optJSONArray("edges");
|
||||
if (children != null) {
|
||||
final List<PostChild> sliderItems = getSliderItems(children);
|
||||
feedModelBuilder.setSliderItems(sliderItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
return feedModelBuilder.build();
|
||||
}
|
||||
|
||||
private static List<PostChild> getChildPosts(final JSONObject mediaJson) throws JSONException {
|
||||
if (mediaJson == null) {
|
||||
return Collections.emptyList();
|
||||
@ -708,4 +826,42 @@ public final class ResponseBodyUtils {
|
||||
.setWidth(childJson.optInt("original_width"))
|
||||
.build();
|
||||
}
|
||||
|
||||
// this is for graphql
|
||||
@NonNull
|
||||
private static List<PostChild> getSliderItems(final JSONArray children) throws JSONException {
|
||||
final List<PostChild> sliderItems = new ArrayList<>();
|
||||
for (int j = 0; j < children.length(); ++j) {
|
||||
final JSONObject childNode = children.optJSONObject(j).getJSONObject("node");
|
||||
final boolean isChildVideo = childNode.optBoolean("is_video");
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
final JSONObject dimensions = childNode.optJSONObject("dimensions");
|
||||
if (dimensions != null) {
|
||||
height = dimensions.optInt("height");
|
||||
width = dimensions.optInt("width");
|
||||
}
|
||||
String thumbnailUrl = null;
|
||||
try {
|
||||
thumbnailUrl = childNode.getJSONArray("display_resources")
|
||||
.getJSONObject(0)
|
||||
.getString("src");
|
||||
} catch (JSONException ignored) {}
|
||||
final PostChild sliderItem = new PostChild.Builder()
|
||||
.setItemType(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO
|
||||
: MediaItemType.MEDIA_TYPE_IMAGE)
|
||||
.setPostId(childNode.getString(Constants.EXTRAS_ID))
|
||||
.setDisplayUrl(isChildVideo ? childNode.getString("video_url")
|
||||
: childNode.getString("display_url"))
|
||||
.setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl
|
||||
: childNode.getString("display_url"))
|
||||
.setVideoViews(childNode.optLong("video_view_count", 0))
|
||||
.setHeight(height)
|
||||
.setWidth(width)
|
||||
.build();
|
||||
// Log.d(TAG, "getSliderItems: sliderItem: " + sliderItem);
|
||||
sliderItems.add(sliderItem);
|
||||
}
|
||||
return sliderItems;
|
||||
}
|
||||
}
|
||||
|
@ -150,157 +150,13 @@ public class FeedService extends BaseService {
|
||||
final JSONArray feedItems = timelineFeed.getJSONArray("edges");
|
||||
|
||||
for (int i = 0; i < feedItems.length(); ++i) {
|
||||
final JSONObject feedItem = feedItems.getJSONObject(i).getJSONObject("node");
|
||||
final String mediaType = feedItem.optString("__typename");
|
||||
if (mediaType.isEmpty() || "GraphSuggestedUserFeedUnit".equals(mediaType))
|
||||
final JSONObject itemJson = feedItems.optJSONObject(i);
|
||||
if (itemJson == null) {
|
||||
continue;
|
||||
|
||||
final boolean isVideo = feedItem.optBoolean("is_video");
|
||||
final long videoViews = feedItem.optLong("video_view_count", 0);
|
||||
|
||||
final String displayUrl = feedItem.optString("display_url");
|
||||
if (TextUtils.isEmpty(displayUrl)) continue;
|
||||
final String resourceUrl;
|
||||
if (isVideo) {
|
||||
resourceUrl = feedItem.getString("video_url");
|
||||
} else {
|
||||
resourceUrl = feedItem.has("display_resources") ? ResponseBodyUtils.getHighQualityImage(feedItem) : displayUrl;
|
||||
}
|
||||
|
||||
ProfileModel profileModel = null;
|
||||
if (feedItem.has("owner")) {
|
||||
final JSONObject owner = feedItem.getJSONObject("owner");
|
||||
profileModel = new ProfileModel(
|
||||
owner.optBoolean("is_private"),
|
||||
false, // if you can see it then you def follow
|
||||
owner.optBoolean("is_verified"),
|
||||
owner.getString(Constants.EXTRAS_ID),
|
||||
owner.getString(Constants.EXTRAS_USERNAME),
|
||||
owner.optString("full_name"),
|
||||
null,
|
||||
null,
|
||||
owner.getString("profile_pic_url"),
|
||||
null,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false);
|
||||
}
|
||||
JSONObject tempJsonObject = feedItem.optJSONObject("edge_media_preview_comment");
|
||||
final long commentsCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0;
|
||||
tempJsonObject = feedItem.optJSONObject("edge_media_preview_like");
|
||||
final long likesCount = tempJsonObject != null ? tempJsonObject.optLong("count") : 0;
|
||||
tempJsonObject = feedItem.optJSONObject("edge_media_to_caption");
|
||||
final JSONArray captions = tempJsonObject != null ? tempJsonObject.getJSONArray("edges") : null;
|
||||
String captionText = null;
|
||||
if (captions != null && captions.length() > 0) {
|
||||
if ((tempJsonObject = captions.optJSONObject(0)) != null &&
|
||||
(tempJsonObject = tempJsonObject.optJSONObject("node")) != null) {
|
||||
captionText = tempJsonObject.getString("text");
|
||||
}
|
||||
}
|
||||
final JSONObject location = feedItem.optJSONObject("location");
|
||||
// Log.d(TAG, "location: " + (location == null ? null : location.toString()));
|
||||
String locationId = null;
|
||||
String locationName = null;
|
||||
if (location != null) {
|
||||
locationName = location.optString("name");
|
||||
if (location.has("id")) {
|
||||
locationId = location.getString("id");
|
||||
} else if (location.has("pk")) {
|
||||
locationId = location.getString("pk");
|
||||
}
|
||||
// Log.d(TAG, "locationId: " + locationId);
|
||||
}
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
final JSONObject dimensions = feedItem.optJSONObject("dimensions");
|
||||
if (dimensions != null) {
|
||||
height = dimensions.optInt("height");
|
||||
width = dimensions.optInt("width");
|
||||
}
|
||||
String thumbnailUrl = null;
|
||||
try {
|
||||
thumbnailUrl = feedItem.getJSONArray("display_resources")
|
||||
.getJSONObject(0)
|
||||
.getString("src");
|
||||
} catch (JSONException ignored) {}
|
||||
final FeedModel.Builder feedModelBuilder = new FeedModel.Builder()
|
||||
.setProfileModel(profileModel)
|
||||
.setItemType(isVideo ? MediaItemType.MEDIA_TYPE_VIDEO
|
||||
: MediaItemType.MEDIA_TYPE_IMAGE)
|
||||
.setViewCount(videoViews)
|
||||
.setPostId(feedItem.getString(Constants.EXTRAS_ID))
|
||||
.setDisplayUrl(resourceUrl)
|
||||
.setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl : displayUrl)
|
||||
.setShortCode(feedItem.getString(Constants.EXTRAS_SHORTCODE))
|
||||
.setPostCaption(captionText)
|
||||
.setCommentsCount(commentsCount)
|
||||
.setTimestamp(feedItem.optLong("taken_at_timestamp", -1))
|
||||
.setLiked(feedItem.getBoolean("viewer_has_liked"))
|
||||
.setBookmarked(feedItem.getBoolean("viewer_has_saved"))
|
||||
.setLikesCount(likesCount)
|
||||
.setLocationName(locationName)
|
||||
.setLocationId(locationId)
|
||||
.setImageHeight(height)
|
||||
.setImageWidth(width);
|
||||
|
||||
final boolean isSlider = "GraphSidecar".equals(mediaType) && feedItem.has("edge_sidecar_to_children");
|
||||
|
||||
if (isSlider) {
|
||||
feedModelBuilder.setItemType(MediaItemType.MEDIA_TYPE_SLIDER);
|
||||
final JSONObject sidecar = feedItem.optJSONObject("edge_sidecar_to_children");
|
||||
if (sidecar != null) {
|
||||
final JSONArray children = sidecar.optJSONArray("edges");
|
||||
if (children != null) {
|
||||
final List<PostChild> sliderItems = getSliderItems(children);
|
||||
feedModelBuilder.setSliderItems(sliderItems);
|
||||
}
|
||||
}
|
||||
}
|
||||
final FeedModel feedModel = feedModelBuilder.build();
|
||||
final FeedModel feedModel = ResponseBodyUtils.parseItem(itemJson);
|
||||
feedModels.add(feedModel);
|
||||
}
|
||||
return new PostsFetchResponse(feedModels, hasNextPage, endCursor);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private List<PostChild> getSliderItems(final JSONArray children) throws JSONException {
|
||||
final List<PostChild> sliderItems = new ArrayList<>();
|
||||
for (int j = 0; j < children.length(); ++j) {
|
||||
final JSONObject childNode = children.optJSONObject(j).getJSONObject("node");
|
||||
final boolean isChildVideo = childNode.optBoolean("is_video");
|
||||
int height = 0;
|
||||
int width = 0;
|
||||
final JSONObject dimensions = childNode.optJSONObject("dimensions");
|
||||
if (dimensions != null) {
|
||||
height = dimensions.optInt("height");
|
||||
width = dimensions.optInt("width");
|
||||
}
|
||||
String thumbnailUrl = null;
|
||||
try {
|
||||
thumbnailUrl = childNode.getJSONArray("display_resources")
|
||||
.getJSONObject(0)
|
||||
.getString("src");
|
||||
} catch (JSONException ignored) {}
|
||||
final PostChild sliderItem = new PostChild.Builder()
|
||||
.setItemType(isChildVideo ? MediaItemType.MEDIA_TYPE_VIDEO
|
||||
: MediaItemType.MEDIA_TYPE_IMAGE)
|
||||
.setPostId(childNode.getString(Constants.EXTRAS_ID))
|
||||
.setDisplayUrl(isChildVideo ? childNode.getString("video_url")
|
||||
: childNode.getString("display_url"))
|
||||
.setThumbnailUrl(thumbnailUrl != null ? thumbnailUrl
|
||||
: childNode.getString("display_url"))
|
||||
.setVideoViews(childNode.optLong("video_view_count", 0))
|
||||
.setHeight(height)
|
||||
.setWidth(width)
|
||||
.build();
|
||||
// Log.d(TAG, "getSliderItems: sliderItem: " + sliderItem);
|
||||
sliderItems.add(sliderItem);
|
||||
}
|
||||
return sliderItems;
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,9 @@ import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import awais.instagrabber.models.FeedModel;
|
||||
@ -186,6 +188,82 @@ public class TagsService extends BaseService {
|
||||
return feedModels;
|
||||
}
|
||||
|
||||
public void fetchGraphQLPosts(@NonNull final String tag,
|
||||
final String maxId,
|
||||
final ServiceCallback<TagPostsFetchResponse> callback) {
|
||||
final Map<String, String> queryMap = new HashMap<>();
|
||||
queryMap.put("query_hash", "9b498c08113f1e09617a1703c22b2f32");
|
||||
queryMap.put("variables", "{" +
|
||||
"\"tag_name\":\"" + tag + "\"," +
|
||||
"\"first\":25," +
|
||||
"\"after\":\"" + (maxId == null ? "" : maxId) + "\"" +
|
||||
"}");
|
||||
final Call<String> request = webRepository.fetchGraphQLPosts(queryMap);
|
||||
request.enqueue(new Callback<String>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) {
|
||||
try {
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
final String body = response.body();
|
||||
if (TextUtils.isEmpty(body)) {
|
||||
callback.onSuccess(null);
|
||||
return;
|
||||
}
|
||||
final TagPostsFetchResponse tagPostsFetchResponse = parseGraphQLResponse(body);
|
||||
callback.onSuccess(tagPostsFetchResponse);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "onResponse", e);
|
||||
callback.onFailure(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) {
|
||||
if (callback != null) {
|
||||
callback.onFailure(t);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private TagPostsFetchResponse parseGraphQLResponse(@NonNull final String body) throws JSONException {
|
||||
final JSONObject rootroot = new JSONObject(body);
|
||||
final JSONObject root = rootroot.getJSONObject("data").getJSONObject("hashtag").getJSONObject("edge_hashtag_to_media");
|
||||
final boolean moreAvailable = root.getJSONObject("page_info").optBoolean("has_next_page");
|
||||
final String nextMaxId = root.getJSONObject("page_info").optString("end_cursor");
|
||||
final int numResults = root.optInt("count");
|
||||
final String status = rootroot.optString("status");
|
||||
final JSONArray itemsJson = root.optJSONArray("edges");
|
||||
final List<FeedModel> items = parseGraphQLItems(itemsJson);
|
||||
return new TagPostsFetchResponse(
|
||||
moreAvailable,
|
||||
nextMaxId,
|
||||
numResults,
|
||||
status,
|
||||
items
|
||||
);
|
||||
}
|
||||
|
||||
private List<FeedModel> parseGraphQLItems(final JSONArray items) throws JSONException {
|
||||
if (items == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<FeedModel> feedModels = new ArrayList<>();
|
||||
for (int i = 0; i < items.length(); i++) {
|
||||
final JSONObject itemJson = items.optJSONObject(i);
|
||||
if (itemJson == null) {
|
||||
continue;
|
||||
}
|
||||
final FeedModel feedModel = ResponseBodyUtils.parseGraphQLItem(itemJson);
|
||||
if (feedModel != null) {
|
||||
feedModels.add(feedModel);
|
||||
}
|
||||
}
|
||||
return feedModels;
|
||||
}
|
||||
|
||||
public static class TagPostsFetchResponse {
|
||||
private boolean moreAvailable;
|
||||
private String nextMaxId;
|
||||
|
Loading…
Reference in New Issue
Block a user