Browse Source
Convert GraphQLRepository and GraphQLService to kotlin
renovate/org.robolectric-robolectric-4.x
Convert GraphQLRepository and GraphQLService to kotlin
renovate/org.robolectric-robolectric-4.x
Ammar Githam
4 years ago
12 changed files with 455 additions and 606 deletions
-
45app/src/main/java/awais/instagrabber/activities/MainActivity.kt
-
16app/src/main/java/awais/instagrabber/asyncs/HashtagPostFetchService.java
-
16app/src/main/java/awais/instagrabber/asyncs/LocationPostFetchService.java
-
18app/src/main/java/awais/instagrabber/asyncs/ProfilePostFetchService.java
-
17app/src/main/java/awais/instagrabber/asyncs/SavedPostFetchService.java
-
34app/src/main/java/awais/instagrabber/fragments/HashTagFragment.java
-
29app/src/main/java/awais/instagrabber/fragments/LikesViewerFragment.java
-
41app/src/main/java/awais/instagrabber/fragments/LocationFragment.java
-
34app/src/main/java/awais/instagrabber/fragments/main/ProfileFragment.java
-
25app/src/main/java/awais/instagrabber/repositories/GraphQLRepository.kt
-
99app/src/main/java/awais/instagrabber/viewmodels/CommentsViewerViewModel.java
-
687app/src/main/java/awais/instagrabber/webservices/GraphQLService.kt
@ -1,25 +1,22 @@ |
|||
package awais.instagrabber.repositories; |
|||
package awais.instagrabber.repositories |
|||
|
|||
import java.util.Map; |
|||
import retrofit2.http.GET |
|||
import retrofit2.http.Path |
|||
import retrofit2.http.QueryMap |
|||
|
|||
import retrofit2.Call; |
|||
import retrofit2.http.GET; |
|||
import retrofit2.http.Path; |
|||
import retrofit2.http.QueryMap; |
|||
|
|||
public interface GraphQLRepository { |
|||
interface GraphQLRepository { |
|||
@GET("/graphql/query/") |
|||
Call<String> fetch(@QueryMap(encoded = true) Map<String, String> queryParams); |
|||
suspend fun fetch(@QueryMap(encoded = true) queryParams: Map<String, String>): String |
|||
|
|||
@GET("/{username}/?__a=1") |
|||
Call<String> getUser(@Path("username") String username); |
|||
suspend fun getUser(@Path("username") username: String): String |
|||
|
|||
@GET("/p/{shortcode}/?__a=1") |
|||
Call<String> getPost(@Path("shortcode") String shortcode); |
|||
suspend fun getPost(@Path("shortcode") shortcode: String): String |
|||
|
|||
@GET("/explore/tags/{tag}/?__a=1") |
|||
Call<String> getTag(@Path("tag") String tag); |
|||
suspend fun getTag(@Path("tag") tag: String): String |
|||
|
|||
@GET("/explore/locations/{locationId}/?__a=1") |
|||
Call<String> getLocation(@Path("locationId") long locationId); |
|||
} |
|||
suspend fun getLocation(@Path("locationId") locationId: Long): String |
|||
} |
@ -1,483 +1,266 @@ |
|||
package awais.instagrabber.webservices; |
|||
|
|||
import android.util.Log; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import com.google.common.collect.ImmutableMap; |
|||
|
|||
import org.json.JSONArray; |
|||
import org.json.JSONException; |
|||
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 awais.instagrabber.models.enums.FollowingType; |
|||
import awais.instagrabber.repositories.GraphQLRepository; |
|||
import awais.instagrabber.repositories.responses.FriendshipStatus; |
|||
import awais.instagrabber.repositories.responses.GraphQLUserListFetchResponse; |
|||
import awais.instagrabber.repositories.responses.Hashtag; |
|||
import awais.instagrabber.repositories.responses.Location; |
|||
import awais.instagrabber.repositories.responses.Media; |
|||
import awais.instagrabber.repositories.responses.PostsFetchResponse; |
|||
import awais.instagrabber.repositories.responses.User; |
|||
import awais.instagrabber.utils.Constants; |
|||
import awais.instagrabber.utils.ResponseBodyUtils; |
|||
import awais.instagrabber.utils.TextUtils; |
|||
import retrofit2.Call; |
|||
import retrofit2.Callback; |
|||
import retrofit2.Response; |
|||
|
|||
public class GraphQLService extends BaseService { |
|||
private static final String TAG = "GraphQLService"; |
|||
|
|||
private final GraphQLRepository repository; |
|||
|
|||
private static GraphQLService instance; |
|||
|
|||
private GraphQLService() { |
|||
repository = RetrofitFactory.INSTANCE |
|||
.getRetrofitWeb() |
|||
.create(GraphQLRepository.class); |
|||
} |
|||
|
|||
public static GraphQLService getInstance() { |
|||
if (instance == null) { |
|||
instance = new GraphQLService(); |
|||
} |
|||
return instance; |
|||
} |
|||
package awais.instagrabber.webservices |
|||
|
|||
import android.util.Log |
|||
import awais.instagrabber.models.enums.FollowingType |
|||
import awais.instagrabber.repositories.GraphQLRepository |
|||
import awais.instagrabber.repositories.responses.* |
|||
import awais.instagrabber.utils.Constants |
|||
import awais.instagrabber.utils.ResponseBodyUtils |
|||
import awais.instagrabber.utils.extensions.TAG |
|||
import awais.instagrabber.webservices.RetrofitFactory.retrofitWeb |
|||
import org.json.JSONException |
|||
import org.json.JSONObject |
|||
import java.util.* |
|||
|
|||
object GraphQLService : BaseService() { |
|||
private val repository: GraphQLRepository = retrofitWeb.create(GraphQLRepository::class.java) |
|||
|
|||
// TODO convert string response to a response class |
|||
private void fetch(final String queryHash, |
|||
final String variables, |
|||
final String arg1, |
|||
final String arg2, |
|||
final User backup, |
|||
final ServiceCallback<PostsFetchResponse> callback) { |
|||
final Map<String, String> queryMap = new HashMap<>(); |
|||
queryMap.put("query_hash", queryHash); |
|||
queryMap.put("variables", variables); |
|||
final Call<String> request = repository.fetch(queryMap); |
|||
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 = parsePostResponse(response, arg1, arg2, backup); |
|||
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); |
|||
} |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void fetchLocationPosts(final long locationId, |
|||
final String maxId, |
|||
final ServiceCallback<PostsFetchResponse> callback) { |
|||
fetch("36bd0f2bf5911908de389b8ceaa3be6d", |
|||
"{\"id\":\"" + locationId + "\"," + |
|||
"\"first\":25," + |
|||
"\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |
|||
Constants.EXTRAS_LOCATION, |
|||
"edge_location_to_media", |
|||
null, |
|||
callback); |
|||
} |
|||
|
|||
public void fetchHashtagPosts(@NonNull final String tag, |
|||
final String maxId, |
|||
final ServiceCallback<PostsFetchResponse> callback) { |
|||
fetch("9b498c08113f1e09617a1703c22b2f32", |
|||
"{\"tag_name\":\"" + tag + "\"," + |
|||
"\"first\":25," + |
|||
"\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |
|||
Constants.EXTRAS_HASHTAG, |
|||
"edge_hashtag_to_media", |
|||
null, |
|||
callback); |
|||
} |
|||
|
|||
public void fetchProfilePosts(final long profileId, |
|||
final int postsPerPage, |
|||
final String maxId, |
|||
final User backup, |
|||
final ServiceCallback<PostsFetchResponse> callback) { |
|||
fetch("02e14f6a7812a876f7d133c9555b1151", |
|||
"{\"id\":\"" + profileId + "\"," + |
|||
"\"first\":" + postsPerPage + "," + |
|||
"\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |
|||
Constants.EXTRAS_USER, |
|||
"edge_owner_to_timeline_media", |
|||
backup, |
|||
callback); |
|||
} |
|||
|
|||
public void fetchTaggedPosts(final long profileId, |
|||
final int postsPerPage, |
|||
final String maxId, |
|||
final ServiceCallback<PostsFetchResponse> callback) { |
|||
fetch("31fe64d9463cbbe58319dced405c6206", |
|||
"{\"id\":\"" + profileId + "\"," + |
|||
"\"first\":" + postsPerPage + "," + |
|||
"\"after\":\"" + (maxId == null ? "" : maxId) + "\"}", |
|||
Constants.EXTRAS_USER, |
|||
"edge_user_to_photos_of_you", |
|||
null, |
|||
callback); |
|||
private suspend fun fetch( |
|||
queryHash: String, |
|||
variables: String, |
|||
arg1: String, |
|||
arg2: String, |
|||
backup: User?, |
|||
): PostsFetchResponse { |
|||
val queryMap = mapOf( |
|||
"query_hash" to queryHash, |
|||
"variables" to variables, |
|||
) |
|||
val response = repository.fetch(queryMap) |
|||
return parsePostResponse(response, arg1, arg2, backup) |
|||
} |
|||
|
|||
@NonNull |
|||
private PostsFetchResponse parsePostResponse(@NonNull final Response<String> response, |
|||
@NonNull final String arg1, |
|||
@NonNull final String arg2, |
|||
final User backup) |
|||
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); |
|||
suspend fun fetchLocationPosts( |
|||
locationId: Long, |
|||
maxId: String?, |
|||
): PostsFetchResponse = fetch( |
|||
"36bd0f2bf5911908de389b8ceaa3be6d", |
|||
"{\"id\":\"" + locationId + "\"," + "\"first\":25," + "\"after\":\"" + (maxId ?: "") + "\"}", |
|||
Constants.EXTRAS_LOCATION, |
|||
"edge_location_to_media", |
|||
null |
|||
) |
|||
|
|||
suspend fun fetchHashtagPosts( |
|||
tag: String, |
|||
maxId: String?, |
|||
): PostsFetchResponse = fetch( |
|||
"9b498c08113f1e09617a1703c22b2f32", |
|||
"{\"tag_name\":\"" + tag + "\"," + "\"first\":25," + "\"after\":\"" + (maxId ?: "") + "\"}", |
|||
Constants.EXTRAS_HASHTAG, |
|||
"edge_hashtag_to_media", |
|||
null, |
|||
) |
|||
|
|||
suspend fun fetchProfilePosts( |
|||
profileId: Long, |
|||
postsPerPage: Int, |
|||
maxId: String?, |
|||
backup: User?, |
|||
): PostsFetchResponse = fetch( |
|||
"02e14f6a7812a876f7d133c9555b1151", |
|||
"{\"id\":\"" + profileId + "\"," + "\"first\":" + postsPerPage + "," + "\"after\":\"" + (maxId ?: "") + "\"}", |
|||
Constants.EXTRAS_USER, |
|||
"edge_owner_to_timeline_media", |
|||
backup, |
|||
) |
|||
|
|||
suspend fun fetchTaggedPosts( |
|||
profileId: Long, |
|||
postsPerPage: Int, |
|||
maxId: String?, |
|||
): PostsFetchResponse = fetch( |
|||
"31fe64d9463cbbe58319dced405c6206", |
|||
"{\"id\":\"" + profileId + "\"," + "\"first\":" + postsPerPage + "," + "\"after\":\"" + (maxId ?: "") + "\"}", |
|||
Constants.EXTRAS_USER, |
|||
"edge_user_to_photos_of_you", |
|||
null, |
|||
) |
|||
|
|||
@Throws(JSONException::class) |
|||
private fun parsePostResponse( |
|||
response: String, |
|||
arg1: String, |
|||
arg2: String, |
|||
backup: User?, |
|||
): PostsFetchResponse { |
|||
if (response.isBlank()) { |
|||
Log.e(TAG, "parseResponse: feed response body is empty") |
|||
return PostsFetchResponse(emptyList(), false, null) |
|||
} |
|||
return parseResponseBody(response.body(), arg1, arg2, backup); |
|||
return parseResponseBody(response, arg1, arg2, backup) |
|||
} |
|||
|
|||
@NonNull |
|||
private PostsFetchResponse parseResponseBody(@NonNull final String body, |
|||
@NonNull final String arg1, |
|||
@NonNull final String arg2, |
|||
final User backup) |
|||
throws JSONException { |
|||
final List<Media> items = new ArrayList<>(); |
|||
final JSONObject timelineFeed = new JSONObject(body) |
|||
.getJSONObject("data") |
|||
.getJSONObject(arg1) |
|||
.getJSONObject(arg2); |
|||
final String endCursor; |
|||
final boolean hasNextPage; |
|||
|
|||
final JSONObject pageInfo = timelineFeed.getJSONObject("page_info"); |
|||
@Throws(JSONException::class) |
|||
private fun parseResponseBody( |
|||
body: String, |
|||
arg1: String, |
|||
arg2: String, |
|||
backup: User?, |
|||
): PostsFetchResponse { |
|||
val items: MutableList<Media> = ArrayList() |
|||
val timelineFeed = JSONObject(body) |
|||
.getJSONObject("data") |
|||
.getJSONObject(arg1) |
|||
.getJSONObject(arg2) |
|||
val endCursor: String? |
|||
val hasNextPage: Boolean |
|||
val pageInfo = timelineFeed.getJSONObject("page_info") |
|||
if (pageInfo.has("has_next_page")) { |
|||
hasNextPage = pageInfo.getBoolean("has_next_page"); |
|||
endCursor = hasNextPage ? pageInfo.getString("end_cursor") : null; |
|||
hasNextPage = pageInfo.getBoolean("has_next_page") |
|||
endCursor = if (hasNextPage) pageInfo.getString("end_cursor") else null |
|||
} else { |
|||
hasNextPage = false; |
|||
endCursor = null; |
|||
hasNextPage = false |
|||
endCursor = null |
|||
} |
|||
|
|||
final JSONArray feedItems = timelineFeed.getJSONArray("edges"); |
|||
|
|||
for (int i = 0; i < feedItems.length(); ++i) { |
|||
final JSONObject itemJson = feedItems.optJSONObject(i); |
|||
if (itemJson == null) { |
|||
continue; |
|||
} |
|||
final Media media = ResponseBodyUtils.parseGraphQLItem(itemJson, backup); |
|||
val feedItems = timelineFeed.getJSONArray("edges") |
|||
for (i in 0 until feedItems.length()) { |
|||
val itemJson = feedItems.optJSONObject(i) ?: continue |
|||
val media = ResponseBodyUtils.parseGraphQLItem(itemJson, backup) |
|||
if (media != null) { |
|||
items.add(media); |
|||
items.add(media) |
|||
} |
|||
} |
|||
return new PostsFetchResponse(items, hasNextPage, endCursor); |
|||
return PostsFetchResponse(items, hasNextPage, endCursor) |
|||
} |
|||
|
|||
// TODO convert string response to a response class |
|||
public void fetchCommentLikers(final String commentId, |
|||
final String endCursor, |
|||
final ServiceCallback<GraphQLUserListFetchResponse> callback) { |
|||
final Map<String, String> queryMap = new HashMap<>(); |
|||
queryMap.put("query_hash", "5f0b1f6281e72053cbc07909c8d154ae"); |
|||
queryMap.put("variables", "{\"comment_id\":\"" + commentId + "\"," + |
|||
"\"first\":30," + |
|||
"\"after\":\"" + (endCursor == null ? "" : endCursor) + "\"}"); |
|||
final Call<String> request = repository.fetch(queryMap); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String rawBody = response.body(); |
|||
if (rawBody == null) { |
|||
Log.e(TAG, "Error occurred while fetching gql comment likes of " + commentId); |
|||
callback.onSuccess(null); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject body = new JSONObject(rawBody); |
|||
final String status = body.getString("status"); |
|||
final JSONObject data = body.getJSONObject("data").getJSONObject("comment").getJSONObject("edge_liked_by"); |
|||
final JSONObject pageInfo = data.getJSONObject("page_info"); |
|||
final String endCursor = pageInfo.getBoolean("has_next_page") ? pageInfo.getString("end_cursor") : null; |
|||
final JSONArray users = data.getJSONArray("edges"); |
|||
final int usersLen = users.length(); |
|||
final List<User> userModels = new ArrayList<>(); |
|||
for (int j = 0; j < usersLen; ++j) { |
|||
final JSONObject userObject = users.getJSONObject(j).getJSONObject("node"); |
|||
userModels.add(new User( |
|||
userObject.getLong("id"), |
|||
userObject.getString("username"), |
|||
userObject.optString("full_name"), |
|||
userObject.optBoolean("is_private"), |
|||
userObject.getString("profile_pic_url"), |
|||
userObject.optBoolean("is_verified") |
|||
)); |
|||
// userModels.add(new ProfileModel(userObject.optBoolean("is_private"), |
|||
// false, |
|||
// userObject.optBoolean("is_verified"), |
|||
// userObject.getString("id"), |
|||
// userObject.getString("username"), |
|||
// userObject.optString("full_name"), |
|||
// null, null, |
|||
// userObject.getString("profile_pic_url"), |
|||
// null, 0, 0, 0, false, false, false, false, false)); |
|||
} |
|||
callback.onSuccess(new GraphQLUserListFetchResponse(endCursor, status, userModels)); |
|||
} 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); |
|||
} |
|||
} |
|||
}); |
|||
suspend fun fetchCommentLikers( |
|||
commentId: String, |
|||
endCursor: String?, |
|||
): GraphQLUserListFetchResponse { |
|||
val queryMap = mapOf( |
|||
"query_hash" to "5f0b1f6281e72053cbc07909c8d154ae", |
|||
"variables" to "{\"comment_id\":\"" + commentId + "\"," + "\"first\":30," + "\"after\":\"" + (endCursor ?: "") + "\"}" |
|||
) |
|||
val response = repository.fetch(queryMap) |
|||
val body = JSONObject(response) |
|||
val status = body.getString("status") |
|||
val data = body.getJSONObject("data").getJSONObject("comment").getJSONObject("edge_liked_by") |
|||
val pageInfo = data.getJSONObject("page_info") |
|||
val newEndCursor = if (pageInfo.getBoolean("has_next_page")) pageInfo.getString("end_cursor") else null |
|||
val users = data.getJSONArray("edges") |
|||
val usersLen = users.length() |
|||
val userModels: MutableList<User> = ArrayList() |
|||
for (j in 0 until usersLen) { |
|||
val userObject = users.getJSONObject(j).getJSONObject("node") |
|||
userModels.add(User( |
|||
userObject.getLong("id"), |
|||
userObject.getString("username"), |
|||
userObject.optString("full_name"), |
|||
userObject.optBoolean("is_private"), |
|||
userObject.getString("profile_pic_url"), |
|||
userObject.optBoolean("is_verified") |
|||
)) |
|||
} |
|||
return GraphQLUserListFetchResponse(newEndCursor, status, userModels) |
|||
} |
|||
|
|||
public Call<String> fetchComments(final String shortCodeOrCommentId, |
|||
final boolean root, |
|||
final String cursor) { |
|||
final Map<String, String> queryMap = new HashMap<>(); |
|||
queryMap.put("query_hash", root ? "bc3296d1ce80a24b1b6e40b1e72903f5" : "51fdd02b67508306ad4484ff574a0b62"); |
|||
final Map<String, Object> variables = ImmutableMap.of( |
|||
root ? "shortcode" : "comment_id", shortCodeOrCommentId, |
|||
"first", 50, |
|||
"after", cursor == null ? "" : cursor |
|||
); |
|||
queryMap.put("variables", new JSONObject(variables).toString()); |
|||
return repository.fetch(queryMap); |
|||
suspend fun fetchComments( |
|||
shortCodeOrCommentId: String?, |
|||
root: Boolean, |
|||
cursor: String?, |
|||
): String { |
|||
val variables = mapOf( |
|||
(if (root) "shortcode" else "comment_id") to shortCodeOrCommentId, |
|||
"first" to 50, |
|||
"after" to (cursor ?: "") |
|||
) |
|||
val queryMap = mapOf( |
|||
"query_hash" to if (root) "bc3296d1ce80a24b1b6e40b1e72903f5" else "51fdd02b67508306ad4484ff574a0b62", |
|||
"variables" to JSONObject(variables).toString() |
|||
) |
|||
return repository.fetch(queryMap) |
|||
} |
|||
|
|||
// TODO convert string response to a response class |
|||
public void fetchUser(final String username, |
|||
final ServiceCallback<User> callback) { |
|||
final Call<String> request = repository.getUser(username); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> 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"), |
|||
userJson.getBoolean("is_verified"), |
|||
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 |
|||
), |
|||
false, |
|||
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, |
|||
null, |
|||
null, |
|||
null, |
|||
null, |
|||
null)); |
|||
} 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); |
|||
} |
|||
} |
|||
}); |
|||
suspend fun fetchUser( |
|||
username: String, |
|||
): User { |
|||
val response = repository.getUser(username) |
|||
val body = JSONObject(response) |
|||
val userJson = body.getJSONObject("graphql").getJSONObject(Constants.EXTRAS_USER) |
|||
val isPrivate = userJson.getBoolean("is_private") |
|||
val id = userJson.optLong(Constants.EXTRAS_ID, 0) |
|||
val timelineMedia = userJson.getJSONObject("edge_owner_to_timeline_media") |
|||
// if (timelineMedia.has("edges")) { |
|||
// final JSONArray edges = timelineMedia.getJSONArray("edges"); |
|||
// } |
|||
var url: String? = userJson.optString("external_url") |
|||
if (url.isNullOrBlank()) url = null |
|||
return User( |
|||
id, |
|||
username, |
|||
userJson.getString("full_name"), |
|||
isPrivate, |
|||
userJson.getString("profile_pic_url_hd"), |
|||
userJson.getBoolean("is_verified"), |
|||
friendshipStatus = 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 |
|||
), |
|||
mediaCount = timelineMedia.getLong("count"), |
|||
followerCount = userJson.getJSONObject("edge_followed_by").getLong("count"), |
|||
followingCount = userJson.getJSONObject("edge_follow").getLong("count"), |
|||
biography = userJson.getString("biography"), |
|||
externalUrl = url, |
|||
) |
|||
} |
|||
|
|||
// TODO convert string response to a response class |
|||
public void fetchPost(final String shortcode, |
|||
final ServiceCallback<Media> callback) { |
|||
final Call<String> request = repository.getPost(shortcode); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String rawBody = response.body(); |
|||
if (rawBody == null) { |
|||
Log.e(TAG, "Error occurred while fetching gql post of " + shortcode); |
|||
callback.onSuccess(null); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject body = new JSONObject(rawBody); |
|||
final JSONObject media = body.getJSONObject("graphql") |
|||
.getJSONObject("shortcode_media"); |
|||
callback.onSuccess(ResponseBodyUtils.parseGraphQLItem(media, null)); |
|||
} 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); |
|||
} |
|||
} |
|||
}); |
|||
suspend fun fetchPost( |
|||
shortcode: String, |
|||
): Media { |
|||
val response = repository.getPost(shortcode) |
|||
val body = JSONObject(response) |
|||
val media = body.getJSONObject("graphql").getJSONObject("shortcode_media") |
|||
return ResponseBodyUtils.parseGraphQLItem(media, null) |
|||
} |
|||
|
|||
// TODO convert string response to a response class |
|||
public void fetchTag(final String tag, |
|||
final ServiceCallback<Hashtag> callback) { |
|||
final Call<String> request = repository.getTag(tag); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String rawBody = response.body(); |
|||
if (rawBody == null) { |
|||
Log.e(TAG, "Error occurred while fetching gql tag of " + tag); |
|||
callback.onSuccess(null); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject body = new JSONObject(rawBody) |
|||
.getJSONObject("graphql") |
|||
.getJSONObject(Constants.EXTRAS_HASHTAG); |
|||
final JSONObject timelineMedia = body.getJSONObject("edge_hashtag_to_media"); |
|||
callback.onSuccess(new Hashtag( |
|||
body.getString(Constants.EXTRAS_ID), |
|||
body.getString("name"), |
|||
timelineMedia.getLong("count"), |
|||
body.optBoolean("is_following") ? FollowingType.FOLLOWING : FollowingType.NOT_FOLLOWING, |
|||
null)); |
|||
} 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); |
|||
} |
|||
} |
|||
}); |
|||
suspend fun fetchTag( |
|||
tag: String, |
|||
): Hashtag { |
|||
val response = repository.getTag(tag) |
|||
val body = JSONObject(response) |
|||
.getJSONObject("graphql") |
|||
.getJSONObject(Constants.EXTRAS_HASHTAG) |
|||
val timelineMedia = body.getJSONObject("edge_hashtag_to_media") |
|||
return Hashtag( |
|||
body.getString(Constants.EXTRAS_ID), |
|||
body.getString("name"), |
|||
timelineMedia.getLong("count"), |
|||
if (body.optBoolean("is_following")) FollowingType.FOLLOWING else FollowingType.NOT_FOLLOWING, |
|||
null) |
|||
} |
|||
|
|||
// TODO convert string response to a response class |
|||
public void fetchLocation(final long locationId, |
|||
final ServiceCallback<Location> callback) { |
|||
final Call<String> request = repository.getLocation(locationId); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String rawBody = response.body(); |
|||
if (rawBody == null) { |
|||
Log.e(TAG, "Error occurred while fetching gql location of " + locationId); |
|||
callback.onSuccess(null); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject body = new JSONObject(rawBody) |
|||
.getJSONObject("graphql") |
|||
.getJSONObject(Constants.EXTRAS_LOCATION); |
|||
final JSONObject timelineMedia = body.getJSONObject("edge_location_to_media"); |
|||
final JSONObject address = new JSONObject(body.getString("address_json")); |
|||
callback.onSuccess(new Location( |
|||
body.getLong(Constants.EXTRAS_ID), |
|||
body.getString("slug"), |
|||
body.getString("name"), |
|||
address.optString("street_address"), |
|||
address.optString("city_name"), |
|||
body.optDouble("lng", 0d), |
|||
body.optDouble("lat", 0d) |
|||
)); |
|||
} 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); |
|||
} |
|||
} |
|||
}); |
|||
suspend fun fetchLocation( |
|||
locationId: Long, |
|||
): Location { |
|||
val response = repository.getLocation(locationId) |
|||
val body = JSONObject(response) |
|||
.getJSONObject("graphql") |
|||
.getJSONObject(Constants.EXTRAS_LOCATION) |
|||
// val timelineMedia = body.getJSONObject("edge_location_to_media") |
|||
val address = JSONObject(body.getString("address_json")) |
|||
return Location( |
|||
body.getLong(Constants.EXTRAS_ID), |
|||
body.getString("slug"), |
|||
body.getString("name"), |
|||
address.optString("street_address"), |
|||
address.optString("city_name"), |
|||
body.optDouble("lng", 0.0), |
|||
body.optDouble("lat", 0.0) |
|||
) |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue