|
|
@ -1,317 +1,202 @@ |
|
|
|
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) + "\"}", |
|
|
|
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) |
|
|
|
} |
|
|
|
|
|
|
|
suspend fun fetchLocationPosts( |
|
|
|
locationId: Long, |
|
|
|
maxId: String?, |
|
|
|
): PostsFetchResponse = fetch( |
|
|
|
"36bd0f2bf5911908de389b8ceaa3be6d", |
|
|
|
"{\"id\":\"" + locationId + "\"," + "\"first\":25," + "\"after\":\"" + (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) + "\"}", |
|
|
|
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, |
|
|
|
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) + "\"}", |
|
|
|
) |
|
|
|
|
|
|
|
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, |
|
|
|
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) + "\"}", |
|
|
|
) |
|
|
|
|
|
|
|
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, |
|
|
|
callback); |
|
|
|
} |
|
|
|
|
|
|
|
@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); |
|
|
|
} |
|
|
|
return parseResponseBody(response.body(), 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) |
|
|
|
) |
|
|
|
|
|
|
|
@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, arg1, arg2, backup) |
|
|
|
} |
|
|
|
|
|
|
|
@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); |
|
|
|
final String endCursor; |
|
|
|
final boolean hasNextPage; |
|
|
|
|
|
|
|
final JSONObject pageInfo = timelineFeed.getJSONObject("page_info"); |
|
|
|
.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; |
|
|
|
} |
|
|
|
|
|
|
|
final JSONArray feedItems = timelineFeed.getJSONArray("edges"); |
|
|
|
|
|
|
|
for (int i = 0; i < feedItems.length(); ++i) { |
|
|
|
final JSONObject itemJson = feedItems.optJSONObject(i); |
|
|
|
if (itemJson == null) { |
|
|
|
continue; |
|
|
|
hasNextPage = false |
|
|
|
endCursor = null |
|
|
|
} |
|
|
|
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( |
|
|
|
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") |
|
|
|
)); |
|
|
|
// 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); |
|
|
|
} |
|
|
|
)) |
|
|
|
} |
|
|
|
}); |
|
|
|
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"); |
|
|
|
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"); |
|
|
|
// } |
|
|
|
|
|
|
|
String url = userJson.optString("external_url"); |
|
|
|
if (TextUtils.isEmpty(url)) url = null; |
|
|
|
|
|
|
|
callback.onSuccess(new User( |
|
|
|
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"), |
|
|
|
null, |
|
|
|
new FriendshipStatus( |
|
|
|
friendshipStatus = FriendshipStatus( |
|
|
|
userJson.optBoolean("followed_by_viewer"), |
|
|
|
userJson.optBoolean("follows_viewer"), |
|
|
|
userJson.optBoolean("blocked_by_viewer"), |
|
|
@ -323,161 +208,59 @@ public class GraphQLService extends BaseService { |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
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) |
|
|
|
suspend fun fetchTag( |
|
|
|
tag: String, |
|
|
|
): Hashtag { |
|
|
|
val response = repository.getTag(tag) |
|
|
|
val body = JSONObject(response) |
|
|
|
.getJSONObject("graphql") |
|
|
|
.getJSONObject(Constants.EXTRAS_HASHTAG); |
|
|
|
final JSONObject timelineMedia = body.getJSONObject("edge_hashtag_to_media"); |
|
|
|
callback.onSuccess(new Hashtag( |
|
|
|
.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"), |
|
|
|
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); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
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) |
|
|
|
suspend fun fetchLocation( |
|
|
|
locationId: Long, |
|
|
|
): Location { |
|
|
|
val response = repository.getLocation(locationId) |
|
|
|
val body = JSONObject(response) |
|
|
|
.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( |
|
|
|
.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", 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); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
body.optDouble("lng", 0.0), |
|
|
|
body.optDouble("lat", 0.0) |
|
|
|
) |
|
|
|
} |
|
|
|
} |