From 78e3ffe04af3c40f8f3caba61f7c84b0fb36a701 Mon Sep 17 00:00:00 2001 From: Austin Huang Date: Sat, 23 Jan 2021 14:17:56 -0500 Subject: [PATCH] private api option for profilefetcher --- .../instagrabber/asyncs/ProfileFetcher.java | 156 ++++++------------ .../fragments/main/ProfileFragment.java | 2 +- .../repositories/GraphQLRepository.java | 4 + .../repositories/UserRepository.java | 11 +- .../repositories/responses/User.java | 6 +- .../repositories/responses/WrappedUser.java | 13 ++ .../awais/instagrabber/utils/FlavorTown.java | 3 +- .../viewmodels/AppStateViewModel.java | 1 + .../webservices/GraphQLService.java | 78 +++++++++ .../instagrabber/webservices/UserService.java | 55 +++++- 10 files changed, 214 insertions(+), 115 deletions(-) create mode 100644 app/src/main/java/awais/instagrabber/repositories/responses/WrappedUser.java diff --git a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java index 6218ef8b..46559dfb 100755 --- a/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java +++ b/app/src/main/java/awais/instagrabber/asyncs/ProfileFetcher.java @@ -5,131 +5,81 @@ import android.util.Log; import androidx.annotation.Nullable; -import org.json.JSONObject; +import java.util.ArrayList; +import java.util.List; -import java.net.HttpURLConnection; -import java.net.URL; - -import awais.instagrabber.BuildConfig; import awais.instagrabber.interfaces.FetchListener; import awais.instagrabber.repositories.responses.FriendshipStatus; import awais.instagrabber.repositories.responses.User; -import awais.instagrabber.utils.Constants; -import awais.instagrabber.utils.CookieUtils; -import awais.instagrabber.utils.NetworkUtils; -import awais.instagrabber.utils.TextUtils; -import awaisomereport.LogCollector; +import awais.instagrabber.webservices.GraphQLService; +import awais.instagrabber.webservices.ServiceCallback; +import awais.instagrabber.webservices.UserService; -import static awais.instagrabber.utils.Utils.logCollector; -import static awais.instagrabber.utils.Utils.settingsHelper; - -public final class ProfileFetcher extends AsyncTask { +public final class ProfileFetcher extends AsyncTask { private static final String TAG = ProfileFetcher.class.getSimpleName(); + private final UserService userService; + private final GraphQLService graphQLService; private final FetchListener fetchListener; + private final boolean isLoggedIn; private final String userName; - public ProfileFetcher(String userName, FetchListener fetchListener) { + public ProfileFetcher(final String userName, + final boolean isLoggedIn, + final FetchListener fetchListener) { this.userName = userName; + this.isLoggedIn = isLoggedIn; this.fetchListener = fetchListener; + userService = isLoggedIn ? UserService.getInstance() : null; + graphQLService = isLoggedIn ? null : GraphQLService.getInstance(); } @Nullable @Override - protected User doInBackground(final Void... voids) { - User result = null; + protected String doInBackground(final Void... voids) { + if (isLoggedIn) { + userService.getUsernameInfo(userName, new ServiceCallback() { + @Override + public void onSuccess(final User user) { + Log.d("austin_debug", user.getUsername() + " " + userName); + userService.getUserFriendship(user.getPk(), new ServiceCallback() { + @Override + public void onSuccess(final FriendshipStatus status) { + user.setFriendshipStatus(status); + fetchListener.onResult(user); + } - try { - final HttpURLConnection conn = (HttpURLConnection) new URL("https://www.instagram.com/" + userName + "/?__a=1").openConnection(); - conn.setUseCaches(true); - conn.connect(); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error", t); + } + }); + } - if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - final String json = NetworkUtils.readFromConnection(conn); - // Log.d(TAG, "doInBackground: " + json); - final JSONObject userJson = new JSONObject(json).getJSONObject("graphql") - .getJSONObject(Constants.EXTRAS_USER); - - final String cookie = settingsHelper.getString(Constants.COOKIE); - - boolean isPrivate = userJson.getBoolean("is_private"); - final long id = userJson.optLong(Constants.EXTRAS_ID, 0); - final long uid = CookieUtils.getUserIdFromCookie(cookie); - final JSONObject timelineMedia = userJson.getJSONObject("edge_owner_to_timeline_media"); - // if (timelineMedia.has("edges")) { - // final JSONArray edges = timelineMedia.getJSONArray("edges"); - // } - - String url = userJson.optString("external_url"); - if (TextUtils.isEmpty(url)) url = null; - - return new User( - id, - userName, - userJson.getString("full_name"), - isPrivate, - userJson.getString("profile_pic_url_hd"), - null, - new FriendshipStatus( - userJson.optBoolean("followed_by_viewer"), - userJson.optBoolean("follows_viewer"), - userJson.optBoolean("blocked_by_viewer"), - false, - isPrivate, - userJson.optBoolean("has_requested_viewer"), - userJson.optBoolean("requested_by_viewer"), - false, - userJson.optBoolean("restricted_by_viewer"), - false - ), - userJson.getBoolean("is_verified"), - false, - false, - false, - false, - null, - null, - timelineMedia.getLong("count"), - userJson.getJSONObject("edge_followed_by").getLong("count"), - userJson.getJSONObject("edge_follow").getLong("count"), - 0, - userJson.getString("biography"), - url, - 0, - null); - - // result = new ProfileModel(isPrivate, - // !user.optBoolean("followed_by_viewer") && (id != uid && isPrivate), - // user.getBoolean("is_verified"), - // id, - // userName, - // user.getString("full_name"), - // user.getString("biography"), - // url, - // user.getString("profile_pic_url"), - // user.getString("profile_pic_url_hd"), - // timelineMedia.getLong("count"), - // user.getJSONObject("edge_followed_by").getLong("count"), - // user.getJSONObject("edge_follow").getLong("count"), - // user.optBoolean("followed_by_viewer"), - // user.optBoolean("follows_viewer"), - // user.optBoolean("restricted_by_viewer"), - // user.optBoolean("blocked_by_viewer"), - // user.optBoolean("requested_by_viewer")); - } - - conn.disconnect(); - } catch (final Exception e) { - if (logCollector != null) - logCollector.appendException(e, LogCollector.LogFile.ASYNC_PROFILE_FETCHER, "doInBackground"); - if (BuildConfig.DEBUG) Log.e("AWAISKING_APP", "", e); + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error", t); + } + }); } + else { + graphQLService.fetchUser(userName, new ServiceCallback() { + @Override + public void onSuccess(final User user) { + fetchListener.onResult(user); + } - return result; + @Override + public void onFailure(final Throwable t) { + Log.e(TAG, "Error", t); + } + }); + } + return "yeah"; } @Override - protected void onPostExecute(final User result) { - if (fetchListener != null) fetchListener.onResult(result); + protected void onPreExecute() { + if (fetchListener != null) fetchListener.doBefore(); } } diff --git a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java index b6a80087..d0567bfb 100644 --- a/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java +++ b/app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java @@ -538,7 +538,7 @@ public class ProfileFragment extends Fragment implements SwipeRefreshLayout.OnRe private void fetchProfileDetails() { if (TextUtils.isEmpty(username)) return; - new ProfileFetcher(username.trim().substring(1), profileModel -> { + new ProfileFetcher(username.trim().substring(1), isLoggedIn, profileModel -> { if (getContext() == null) return; this.profileModel = profileModel; setProfileDetails(); diff --git a/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java b/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java index 23020035..0165ad9e 100644 --- a/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java +++ b/app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.java @@ -4,9 +4,13 @@ import java.util.Map; import retrofit2.Call; import retrofit2.http.GET; +import retrofit2.http.Path; import retrofit2.http.QueryMap; public interface GraphQLRepository { @GET("/graphql/query/") Call fetch(@QueryMap(encoded = true) Map queryParams); + + @GET("/{username}/?__a=1") + Call getUser(@Path("username") String username); } diff --git a/app/src/main/java/awais/instagrabber/repositories/UserRepository.java b/app/src/main/java/awais/instagrabber/repositories/UserRepository.java index 5812f5a6..4b14034b 100644 --- a/app/src/main/java/awais/instagrabber/repositories/UserRepository.java +++ b/app/src/main/java/awais/instagrabber/repositories/UserRepository.java @@ -1,7 +1,8 @@ package awais.instagrabber.repositories; -import awais.instagrabber.repositories.responses.User; +import awais.instagrabber.repositories.responses.FriendshipStatus; import awais.instagrabber.repositories.responses.UserSearchResponse; +import awais.instagrabber.repositories.responses.WrappedUser; import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Path; @@ -10,7 +11,13 @@ import retrofit2.http.Query; public interface UserRepository { @GET("/api/v1/users/{uid}/info/") - Call getUserInfo(@Path("uid") final long uid); + Call getUserInfo(@Path("uid") final long uid); + + @GET("/api/v1/users/{username}/usernameinfo/") + Call getUsernameInfo(@Path("username") final String username); + + @GET("/api/v1/friendships/show/{uid}/") + Call getUserFriendship(@Path("uid") final long uid); @GET("/api/v1/users/search/") Call search(@Query("timezone_offset") float timezoneOffset, diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/User.java b/app/src/main/java/awais/instagrabber/repositories/responses/User.java index 65646392..29660685 100644 --- a/app/src/main/java/awais/instagrabber/repositories/responses/User.java +++ b/app/src/main/java/awais/instagrabber/repositories/responses/User.java @@ -10,7 +10,7 @@ public class User implements Serializable { private final boolean isPrivate; private final String profilePicUrl; private final String profilePicId; - private final FriendshipStatus friendshipStatus; + private FriendshipStatus friendshipStatus; private final boolean isVerified; private final boolean hasAnonymousProfilePicture; private final boolean isUnpublished; @@ -102,6 +102,10 @@ public class User implements Serializable { return friendshipStatus; } + public void setFriendshipStatus(final FriendshipStatus friendshipStatus) { + this.friendshipStatus = friendshipStatus; + } + public boolean isVerified() { return isVerified; } diff --git a/app/src/main/java/awais/instagrabber/repositories/responses/WrappedUser.java b/app/src/main/java/awais/instagrabber/repositories/responses/WrappedUser.java new file mode 100644 index 00000000..66a30d88 --- /dev/null +++ b/app/src/main/java/awais/instagrabber/repositories/responses/WrappedUser.java @@ -0,0 +1,13 @@ +package awais.instagrabber.repositories.responses; + +public class WrappedUser { + private final User user; + + public WrappedUser(final User user) { + this.user = user; + } + + public User getUser() { + return user; + } +} diff --git a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java index 85ad0a2f..d37d1ce9 100755 --- a/app/src/main/java/awais/instagrabber/utils/FlavorTown.java +++ b/app/src/main/java/awais/instagrabber/utils/FlavorTown.java @@ -102,8 +102,7 @@ public final class FlavorTown { } public static void changelogCheck(@NonNull final Context context) { -// if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) { - if (true) { + if (settingsHelper.getInteger(Constants.PREV_INSTALL_VERSION) < BuildConfig.VERSION_CODE) { final int appUaCode = settingsHelper.getInteger(Constants.APP_UA_CODE); final String appUa = UserAgentUtils.generateAppUA(appUaCode, LocaleUtils.getCurrentLocale().getLanguage()); settingsHelper.putString(Constants.APP_UA, appUa); diff --git a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java index 37158b60..ce0335eb 100644 --- a/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java +++ b/app/src/main/java/awais/instagrabber/viewmodels/AppStateViewModel.java @@ -83,6 +83,7 @@ public class AppStateViewModel extends AndroidViewModel { if (TextUtils.isEmpty(username)) return; new ProfileFetcher( username.trim().substring(1), + true, currentUser::postValue ).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } diff --git a/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java b/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java index 06a7af8c..4b744ac2 100644 --- a/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java +++ b/app/src/main/java/awais/instagrabber/webservices/GraphQLService.java @@ -271,4 +271,82 @@ public class GraphQLService extends BaseService { } }); } + + public void fetchUser(final String username, + final ServiceCallback callback) { + final Call request = repository.getUser(username); + request.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + final String rawBody = response.body(); + if (rawBody == null) { + Log.e(TAG, "Error occurred while fetching gql user of " + username); + callback.onSuccess(null); + return; + } + try { + final JSONObject body = new JSONObject(rawBody); + final JSONObject userJson = body.getJSONObject("graphql") + .getJSONObject(Constants.EXTRAS_USER); + + boolean isPrivate = userJson.getBoolean("is_private"); + final long id = userJson.optLong(Constants.EXTRAS_ID, 0); + final JSONObject timelineMedia = userJson.getJSONObject("edge_owner_to_timeline_media"); + // if (timelineMedia.has("edges")) { + // final JSONArray edges = timelineMedia.getJSONArray("edges"); + // } + + String url = userJson.optString("external_url"); + if (TextUtils.isEmpty(url)) url = null; + + callback.onSuccess(new User( + id, + username, + userJson.getString("full_name"), + isPrivate, + userJson.getString("profile_pic_url_hd"), + null, + new FriendshipStatus( + userJson.optBoolean("followed_by_viewer"), + userJson.optBoolean("follows_viewer"), + userJson.optBoolean("blocked_by_viewer"), + false, + isPrivate, + userJson.optBoolean("has_requested_viewer"), + userJson.optBoolean("requested_by_viewer"), + false, + userJson.optBoolean("restricted_by_viewer"), + false + ), + userJson.getBoolean("is_verified"), + false, + false, + false, + false, + null, + null, + timelineMedia.getLong("count"), + userJson.getJSONObject("edge_followed_by").getLong("count"), + userJson.getJSONObject("edge_follow").getLong("count"), + 0, + userJson.getString("biography"), + url, + 0, + null)); + } catch (JSONException 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); + } + } + }); + } } diff --git a/app/src/main/java/awais/instagrabber/webservices/UserService.java b/app/src/main/java/awais/instagrabber/webservices/UserService.java index c3b3e9a4..0aff3f32 100644 --- a/app/src/main/java/awais/instagrabber/webservices/UserService.java +++ b/app/src/main/java/awais/instagrabber/webservices/UserService.java @@ -5,8 +5,10 @@ import androidx.annotation.NonNull; import java.util.TimeZone; import awais.instagrabber.repositories.UserRepository; +import awais.instagrabber.repositories.responses.FriendshipStatus; import awais.instagrabber.repositories.responses.User; import awais.instagrabber.repositories.responses.UserSearchResponse; +import awais.instagrabber.repositories.responses.WrappedUser; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -34,25 +36,66 @@ public class UserService extends BaseService { } public void getUserInfo(final long uid, final ServiceCallback callback) { - final Call request = repository.getUserInfo(uid); - request.enqueue(new Callback() { + final Call request = repository.getUserInfo(uid); + request.enqueue(new Callback() { @Override - public void onResponse(@NonNull final Call call, @NonNull final Response response) { - final User user = response.body(); + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + final WrappedUser user = response.body(); if (user == null) { callback.onSuccess(null); return; } - callback.onSuccess(user); + callback.onSuccess(user.getUser()); } @Override - public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { callback.onFailure(t); } }); } + public void getUsernameInfo(final String username, final ServiceCallback callback) { + final Call request = repository.getUsernameInfo(username); + request.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + final WrappedUser user = response.body(); + if (user == null) { + callback.onSuccess(null); + return; + } + callback.onSuccess(user.getUser()); + } + + @Override + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + callback.onFailure(t); + } + }); + } + + public void getUserFriendship(final long uid, final ServiceCallback callback) { + final Call request = repository.getUserFriendship(uid); + request.enqueue(new Callback() { + @Override + public void onResponse(@NonNull final Call call, @NonNull final Response response) { + final FriendshipStatus status = response.body(); + if (status == null) { + callback.onSuccess(null); + return; + } + callback.onSuccess(status); + } + + @Override + public void onFailure(@NonNull final Call call, @NonNull final Throwable t) { + callback.onFailure(t); + } + }); + } + + public Call search(final String query) { final float timezoneOffset = (float) TimeZone.getDefault().getRawOffset() / 1000; return repository.search(timezoneOffset, query);