1
0
Fork 0
mirror of https://github.com/KokaKiwi/BarInsta synced 2026-03-05 12:01:35 +00:00

close #259, release prep, awaiting crowdin

This commit is contained in:
Austin Huang 2020-11-13 17:09:41 -05:00
parent d9c510d9cb
commit f908e7b643
No known key found for this signature in database
GPG key ID: 84C23AA04587A91F
13 changed files with 197 additions and 377 deletions

View file

@ -14,7 +14,8 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService {
private final TagsService tagsService;
private final HashtagModel hashtagModel;
private String nextMaxId;
private boolean moreAvailable, isLoggedIn;
private boolean moreAvailable;
private final boolean isLoggedIn;
public HashtagPostFetchService(final HashtagModel hashtagModel, final boolean isLoggedIn) {
this.hashtagModel = hashtagModel;
@ -24,7 +25,7 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService {
@Override
public void fetch(final FetchListener<List<FeedModel>> fetchListener) {
if (isLoggedIn) tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, new ServiceCallback<TagPostsFetchResponse>() {
final ServiceCallback cb = new ServiceCallback<TagPostsFetchResponse>() {
@Override
public void onSuccess(final TagPostsFetchResponse result) {
if (result == null) return;
@ -42,26 +43,9 @@ public class HashtagPostFetchService implements PostFetcher.PostFetchService {
fetchListener.onFailure(t);
}
}
});
else tagsService.fetchGraphQLPosts(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);
}
}
});
};
if (isLoggedIn) tagsService.fetchPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb);
else tagsService.fetchGraphQLPosts(hashtagModel.getName().toLowerCase(), nextMaxId, cb);
}
@Override

View file

@ -15,15 +15,17 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService {
private final LocationModel locationModel;
private String nextMaxId;
private boolean moreAvailable;
private final boolean isLoggedIn;
public LocationPostFetchService(final LocationModel locationModel) {
public LocationPostFetchService(final LocationModel locationModel, final boolean isLoggedIn) {
this.locationModel = locationModel;
this.isLoggedIn = isLoggedIn;
locationService = LocationService.getInstance();
}
@Override
public void fetch(final FetchListener<List<FeedModel>> fetchListener) {
locationService.fetchPosts(locationModel.getId(), nextMaxId, new ServiceCallback<LocationPostsFetchResponse>() {
final ServiceCallback cb = new ServiceCallback<LocationPostsFetchResponse>() {
@Override
public void onSuccess(final LocationPostsFetchResponse result) {
if (result == null) return;
@ -41,7 +43,9 @@ public class LocationPostFetchService implements PostFetcher.PostFetchService {
fetchListener.onFailure(t);
}
}
});
};
if (isLoggedIn) locationService.fetchPosts(locationModel.getId(), nextMaxId, cb);
else locationService.fetchGraphQLPosts(locationModel.getId(), nextMaxId, cb);
}
@Override

View file

@ -44,6 +44,7 @@ import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.FeedAdapterV2;
import awais.instagrabber.asyncs.HashtagFetcher;
import awais.instagrabber.asyncs.HashtagPostFetchService;
import awais.instagrabber.asyncs.PostFetcher;
import awais.instagrabber.customviews.PrimaryActionModeCallback;
import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout;
import awais.instagrabber.databinding.FragmentHashtagBinding;
@ -81,6 +82,7 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
private NestedCoordinatorLayout root;
private boolean shouldRefresh = true;
private boolean hasStories = false;
private boolean opening = false;
private String hashtag;
private HashtagModel hashtagModel;
private ActionMode actionMode;
@ -199,16 +201,37 @@ public class HashTagFragment extends Fragment implements SwipeRefreshLayout.OnRe
final View profilePicView,
final View mainPostImage,
final int position) {
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(feedModel);
if (position >= 0) {
builder.setPosition(position);
if (opening) return;
else if (TextUtils.isEmpty(feedModel.getProfileModel().getUsername())) {
opening = true;
new PostFetcher(feedModel.getShortCode(), newFeedModel -> {
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(newFeedModel);
if (position >= 0) {
builder.setPosition(position);
}
final PostViewV2Fragment fragment = builder
.setSharedProfilePicElement(profilePicView)
.setSharedMainPostElement(mainPostImage)
.build();
fragment.show(getChildFragmentManager(), "post_view");
opening = false;
}).execute();
}
else {
opening = true;
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(feedModel);
if (position >= 0) {
builder.setPosition(position);
}
final PostViewV2Fragment fragment = builder
.setSharedProfilePicElement(profilePicView)
.setSharedMainPostElement(mainPostImage)
.build();
fragment.show(getChildFragmentManager(), "post_view");
opening = false;
}
final PostViewV2Fragment fragment = builder
.setSharedProfilePicElement(profilePicView)
.setSharedMainPostElement(mainPostImage)
.build();
fragment.show(getChildFragmentManager(), "post_view");
}
};
private final FeedAdapterV2.SelectionModeCallback selectionModeCallback = new FeedAdapterV2.SelectionModeCallback() {

View file

@ -47,6 +47,7 @@ import awais.instagrabber.activities.MainActivity;
import awais.instagrabber.adapters.FeedAdapterV2;
import awais.instagrabber.asyncs.LocationFetcher;
import awais.instagrabber.asyncs.LocationPostFetchService;
import awais.instagrabber.asyncs.PostFetcher;
import awais.instagrabber.customviews.PrimaryActionModeCallback;
import awais.instagrabber.customviews.helpers.NestedCoordinatorLayout;
import awais.instagrabber.databinding.FragmentLocationBinding;
@ -81,6 +82,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
private NestedCoordinatorLayout root;
private boolean shouldRefresh = true;
private boolean hasStories = false;
private boolean opening = false;
private String locationId;
private LocationModel locationModel;
private ActionMode actionMode;
@ -197,16 +199,37 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
final View profilePicView,
final View mainPostImage,
final int position) {
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(feedModel);
if (position >= 0) {
builder.setPosition(position);
if (opening) return;
else if (TextUtils.isEmpty(feedModel.getProfileModel().getUsername())) {
opening = true;
new PostFetcher(feedModel.getShortCode(), newFeedModel -> {
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(newFeedModel);
if (position >= 0) {
builder.setPosition(position);
}
final PostViewV2Fragment fragment = builder
.setSharedProfilePicElement(profilePicView)
.setSharedMainPostElement(mainPostImage)
.build();
fragment.show(getChildFragmentManager(), "post_view");
opening = false;
}).execute();
}
else {
opening = true;
final PostViewV2Fragment.Builder builder = PostViewV2Fragment
.builder(feedModel);
if (position >= 0) {
builder.setPosition(position);
}
final PostViewV2Fragment fragment = builder
.setSharedProfilePicElement(profilePicView)
.setSharedMainPostElement(mainPostImage)
.build();
fragment.show(getChildFragmentManager(), "post_view");
opening = false;
}
final PostViewV2Fragment fragment = builder
.setSharedProfilePicElement(profilePicView)
.setSharedMainPostElement(mainPostImage)
.build();
fragment.show(getChildFragmentManager(), "post_view");
}
};
private final FeedAdapterV2.SelectionModeCallback selectionModeCallback = new FeedAdapterV2.SelectionModeCallback() {
@ -335,7 +358,7 @@ public class LocationFragment extends Fragment implements SwipeRefreshLayout.OnR
private void setupPosts() {
binding.posts.setViewModelStoreOwner(this)
.setLifeCycleOwner(this)
.setPostFetchService(new LocationPostFetchService(locationModel))
.setPostFetchService(new LocationPostFetchService(locationModel, isLoggedIn))
.setLayoutPreferences(PostsLayoutPreferences.fromJson(settingsHelper.getString(Constants.PREF_LOCATION_POSTS_LAYOUT)))
.addFetchStatusChangeListener(fetching -> updateSwipeRefreshState())
.setFeedItemCallback(feedItemCallback)

View file

@ -12,4 +12,7 @@ public interface LocationRepository {
@GET("/api/v1/feed/location/{location}/")
Call<String> fetchPosts(@Path("location") final String locationId,
@QueryMap Map<String, String> queryParams);
@GET("/graphql/query/")
Call<String> fetchGraphQLPosts(@QueryMap(encoded = true) Map<String, String> queryParams);
}

View file

@ -58,9 +58,9 @@ public final class Constants {
// spoof
public static final String USER_AGENT = "Mozilla/5.0 (Linux; Android 8.1.0; motorola one Build/OPKS28.63-18-3; wv) " +
"AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/70.0.3538.80 Mobile Safari/537.36 " +
"Instagram 165.1.0.29.119 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 253447818)";
"Instagram 166.1.0.42.245 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 256099205)";
public static final String I_USER_AGENT =
"Instagram 165.1.0.29.119 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 253447818)";
"Instagram 166.1.0.42.245 Android (27/8.1.0; 320dpi; 720x1362; motorola; motorola one; deen_sprout; qcom; pt_BR; 256099205)";
public static final String A_USER_AGENT = "https://Barinsta.AustinHuang.me / mailto:Barinsta@AustinHuang.me";
// see https://github.com/dilame/instagram-private-api/blob/master/src/core/constants.ts
public static final String SUPPORTED_CAPABILITIES = "[ { \"name\": \"SUPPORTED_SDK_VERSIONS\", \"value\":" +

View file

@ -62,7 +62,7 @@ public final class LocaleUtils {
if (appLanguageIndex == 1) return "en";
if (appLanguageIndex == 2) return "fr";
if (appLanguageIndex == 3) return "es";
if (appLanguageIndex == 4) return "zh";
if (appLanguageIndex == 4) return "zh-rCN";
if (appLanguageIndex == 5) return "in";
if (appLanguageIndex == 6) return "it";
if (appLanguageIndex == 7) return "de";
@ -72,7 +72,9 @@ public final class LocaleUtils {
if (appLanguageIndex == 11) return "fa";
if (appLanguageIndex == 12) return "mk";
if (appLanguageIndex == 13) return "vi";
if (appLanguageIndex == 14) return "hi";
if (appLanguageIndex == 14) return "zh-rTW";
if (appLanguageIndex == 15) return "hi";
if (appLanguageIndex == 16) return "cs";
return null;
}

View file

@ -671,8 +671,6 @@ public final class ResponseBodyUtils {
}
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);

View file

@ -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;
@ -27,7 +29,7 @@ import retrofit2.Retrofit;
public class LocationService extends BaseService {
private static final String TAG = "LocationService";
private final LocationRepository repository;
private final LocationRepository repository, webRepository;
private static LocationService instance;
@ -36,6 +38,10 @@ public class LocationService extends BaseService {
.baseUrl("https://i.instagram.com")
.build();
repository = retrofit.create(LocationRepository.class);
final Retrofit webRetrofit = getRetrofitBuilder()
.baseUrl("https://www.instagram.com")
.build();
webRepository = webRetrofit.create(LocationRepository.class);
}
public static LocationService getInstance() {
@ -48,7 +54,7 @@ public class LocationService extends BaseService {
public void fetchPosts(@NonNull final String locationId,
final String maxId,
final ServiceCallback<LocationPostsFetchResponse> callback) {
final ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String>builder();
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
if (!TextUtils.isEmpty(maxId)) {
builder.put("max_id", maxId);
}
@ -117,6 +123,82 @@ public class LocationService extends BaseService {
return feedModels;
}
public void fetchGraphQLPosts(@NonNull final String locationId,
final String maxId,
final ServiceCallback<LocationPostsFetchResponse> callback) {
final Map<String, String> queryMap = new HashMap<>();
queryMap.put("query_hash", "36bd0f2bf5911908de389b8ceaa3be6d");
queryMap.put("variables", "{" +
"\"id\":\"" + locationId + "\"," +
"\"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 LocationPostsFetchResponse 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 LocationPostsFetchResponse parseGraphQLResponse(@NonNull final String body) throws JSONException {
final JSONObject rootroot = new JSONObject(body);
final JSONObject root = rootroot.getJSONObject("data").getJSONObject("location").getJSONObject("edge_location_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 LocationPostsFetchResponse(
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 LocationPostsFetchResponse {
private boolean moreAvailable;
private String nextMaxId;