Austin Huang
4 years ago
No known key found for this signature in database
GPG Key ID: 84C23AA04587A91F
13 changed files with 590 additions and 363 deletions
-
2app/src/main/java/awais/instagrabber/adapters/CommentsAdapter.java
-
4app/src/main/java/awais/instagrabber/adapters/viewholder/CommentViewHolder.java
-
2app/src/main/java/awais/instagrabber/fragments/LocationFragment.java
-
2app/src/main/java/awais/instagrabber/fragments/comments/Helper.java
-
43app/src/main/java/awais/instagrabber/models/Comment.kt
-
49app/src/main/java/awais/instagrabber/repositories/CommentRepository.java
-
20app/src/main/java/awais/instagrabber/repositories/MediaRepository.java
-
47app/src/main/java/awais/instagrabber/repositories/responses/ChildCommentsFetchResponse.java
-
47app/src/main/java/awais/instagrabber/repositories/responses/CommentsFetchResponse.java
-
51app/src/main/java/awais/instagrabber/repositories/responses/GraphQLCommentsFetchResponse.java
-
169app/src/main/java/awais/instagrabber/viewmodels/CommentsViewerViewModel.java
-
324app/src/main/java/awais/instagrabber/webservices/CommentService.java
-
175app/src/main/java/awais/instagrabber/webservices/MediaService.java
@ -0,0 +1,49 @@ |
|||
package awais.instagrabber.repositories; |
|||
|
|||
import java.util.Map; |
|||
|
|||
import awais.instagrabber.repositories.responses.CommentsFetchResponse; |
|||
import awais.instagrabber.repositories.responses.ChildCommentsFetchResponse; |
|||
import retrofit2.Call; |
|||
import retrofit2.http.FieldMap; |
|||
import retrofit2.http.FormUrlEncoded; |
|||
import retrofit2.http.GET; |
|||
import retrofit2.http.Header; |
|||
import retrofit2.http.POST; |
|||
import retrofit2.http.Path; |
|||
import retrofit2.http.Query; |
|||
import retrofit2.http.QueryMap; |
|||
|
|||
public interface CommentRepository { |
|||
@GET("/api/v1/media/{mediaId}/comments/") |
|||
Call<CommentsFetchResponse> fetchComments(@Path("mediaId") final String mediaId, |
|||
@QueryMap final Map<String, String> queryMap); |
|||
|
|||
@GET("/api/v1/media/{mediaId}/comments/{commentId}/inline_child_comments/") |
|||
Call<ChildCommentsFetchResponse> fetchChildComments(@Path("mediaId") final String mediaId, |
|||
@Path("commentId") final String commentId, |
|||
@QueryMap final Map<String, String> queryMap); |
|||
|
|||
@FormUrlEncoded |
|||
@POST("/api/v1/media/{mediaId}/comment/") |
|||
Call<String> comment(@Path("mediaId") final String mediaId, |
|||
@FieldMap final Map<String, String> signedForm); |
|||
|
|||
@FormUrlEncoded |
|||
@POST("/api/v1/media/{mediaId}/comment/bulk_delete/") |
|||
Call<String> commentsBulkDelete(@Path("mediaId") final String mediaId, |
|||
@FieldMap final Map<String, String> signedForm); |
|||
|
|||
@FormUrlEncoded |
|||
@POST("/api/v1/media/{commentId}/comment_like/") |
|||
Call<String> commentLike(@Path("commentId") final String commentId, |
|||
@FieldMap final Map<String, String> signedForm); |
|||
|
|||
@FormUrlEncoded |
|||
@POST("/api/v1/media/{commentId}/comment_unlike/") |
|||
Call<String> commentUnlike(@Path("commentId") final String commentId, |
|||
@FieldMap final Map<String, String> signedForm); |
|||
|
|||
@GET("/api/v1/language/translate/") |
|||
Call<String> translate(@QueryMap final Map<String, String> form); |
|||
} |
@ -0,0 +1,47 @@ |
|||
package awais.instagrabber.repositories.responses; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import java.util.List; |
|||
|
|||
import awais.instagrabber.models.Comment; |
|||
|
|||
public class ChildCommentsFetchResponse { |
|||
private final int childCommentCount; |
|||
private final String nextMinId; |
|||
private final List<Comment> childComments; |
|||
|
|||
public ChildCommentsFetchResponse(final int childCommentCount, |
|||
final String nextMinId, // unconfirmed |
|||
final List<Comment> childComments) { |
|||
this.childCommentCount = childCommentCount; |
|||
this.nextMinId = nextMinId; |
|||
this.childComments = childComments; |
|||
} |
|||
|
|||
public int getChildCommentCount() { |
|||
return childCommentCount; |
|||
} |
|||
|
|||
public String getNextMinId() { |
|||
return nextMinId; |
|||
} |
|||
|
|||
public boolean hasNext() { |
|||
return nextMinId != null; |
|||
} |
|||
|
|||
public List<Comment> getChildComments() { |
|||
return childComments; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public String toString() { |
|||
return "CommentsFetchResponse{" + |
|||
"childCommentCount=" + childCommentCount + |
|||
", nextMinId='" + nextMinId + '\'' + |
|||
", childComments=" + childComments + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,47 @@ |
|||
package awais.instagrabber.repositories.responses; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import java.util.List; |
|||
|
|||
import awais.instagrabber.models.Comment; |
|||
|
|||
public class CommentsFetchResponse { |
|||
private final int commentCount; |
|||
private final String nextMinId; |
|||
private final List<Comment> comments; |
|||
|
|||
public CommentsFetchResponse(final int commentCount, |
|||
final String nextMinId, |
|||
final List<Comment> comments) { |
|||
this.commentCount = commentCount; |
|||
this.nextMinId = nextMinId; |
|||
this.comments = comments; |
|||
} |
|||
|
|||
public int getCommentCount() { |
|||
return commentCount; |
|||
} |
|||
|
|||
public String getNextMinId() { |
|||
return nextMinId; |
|||
} |
|||
|
|||
public boolean hasNext() { |
|||
return nextMinId != null; |
|||
} |
|||
|
|||
public List<Comment> getComments() { |
|||
return comments; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public String toString() { |
|||
return "CommentsFetchResponse{" + |
|||
"commentCount=" + commentCount + |
|||
", nextMinId='" + nextMinId + '\'' + |
|||
", comments=" + comments + |
|||
'}'; |
|||
} |
|||
} |
@ -1,51 +0,0 @@ |
|||
package awais.instagrabber.repositories.responses; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import java.util.List; |
|||
|
|||
import awais.instagrabber.models.Comment; |
|||
|
|||
public class GraphQLCommentsFetchResponse { |
|||
private final int count; |
|||
private final String cursor; |
|||
private final boolean hasNext; |
|||
private final List<Comment> comments; |
|||
|
|||
public GraphQLCommentsFetchResponse(final int count, |
|||
final String cursor, |
|||
final boolean hasNext, |
|||
final List<Comment> comments) { |
|||
this.count = count; |
|||
this.cursor = cursor; |
|||
this.hasNext = hasNext; |
|||
this.comments = comments; |
|||
} |
|||
|
|||
public int getCount() { |
|||
return count; |
|||
} |
|||
|
|||
public String getCursor() { |
|||
return cursor; |
|||
} |
|||
|
|||
public boolean hasNext() { |
|||
return hasNext; |
|||
} |
|||
|
|||
public List<Comment> getComments() { |
|||
return comments; |
|||
} |
|||
|
|||
@NonNull |
|||
@Override |
|||
public String toString() { |
|||
return "GraphQLCommentsFetchResponse{" + |
|||
"count=" + count + |
|||
", cursor='" + cursor + '\'' + |
|||
", hasNext=" + hasNext + |
|||
", comments=" + comments + |
|||
'}'; |
|||
} |
|||
} |
@ -0,0 +1,324 @@ |
|||
package awais.instagrabber.webservices; |
|||
|
|||
import android.util.Log; |
|||
|
|||
import androidx.annotation.NonNull; |
|||
|
|||
import com.google.gson.Gson; |
|||
|
|||
import org.json.JSONException; |
|||
import org.json.JSONObject; |
|||
|
|||
import java.util.Collections; |
|||
import java.util.HashMap; |
|||
import java.util.List; |
|||
import java.util.Map; |
|||
import java.util.Objects; |
|||
import java.util.UUID; |
|||
|
|||
import awais.instagrabber.models.Comment; |
|||
import awais.instagrabber.repositories.CommentRepository; |
|||
import awais.instagrabber.repositories.responses.ChildCommentsFetchResponse; |
|||
import awais.instagrabber.repositories.responses.CommentsFetchResponse; |
|||
import awais.instagrabber.repositories.responses.User; |
|||
import awais.instagrabber.utils.TextUtils; |
|||
import awais.instagrabber.utils.Utils; |
|||
import retrofit2.Call; |
|||
import retrofit2.Callback; |
|||
import retrofit2.Response; |
|||
|
|||
public class CommentService extends BaseService { |
|||
private static final String TAG = "CommentService"; |
|||
|
|||
private final CommentRepository repository; |
|||
private final String deviceUuid, csrfToken; |
|||
private final long userId; |
|||
|
|||
private static CommentService instance; |
|||
|
|||
private CommentService(final String deviceUuid, |
|||
final String csrfToken, |
|||
final long userId) { |
|||
this.deviceUuid = deviceUuid; |
|||
this.csrfToken = csrfToken; |
|||
this.userId = userId; |
|||
repository = RetrofitFactory.INSTANCE |
|||
.getRetrofit() |
|||
.create(CommentRepository.class); |
|||
} |
|||
|
|||
public String getCsrfToken() { |
|||
return csrfToken; |
|||
} |
|||
|
|||
public String getDeviceUuid() { |
|||
return deviceUuid; |
|||
} |
|||
|
|||
public long getUserId() { |
|||
return userId; |
|||
} |
|||
|
|||
public static CommentService getInstance(final String deviceUuid, final String csrfToken, final long userId) { |
|||
if (instance == null |
|||
|| !Objects.equals(instance.getCsrfToken(), csrfToken) |
|||
|| !Objects.equals(instance.getDeviceUuid(), deviceUuid) |
|||
|| !Objects.equals(instance.getUserId(), userId)) { |
|||
instance = new CommentService(deviceUuid, csrfToken, userId); |
|||
} |
|||
return instance; |
|||
} |
|||
|
|||
public void fetchComments(@NonNull final String mediaId, |
|||
final String maxId, |
|||
@NonNull final ServiceCallback<CommentsFetchResponse> callback) { |
|||
final Map<String, String> form = new HashMap<>(); |
|||
form.put("can_support_threading", "true"); |
|||
if (maxId != null) form.put("max_id", maxId); |
|||
final Call<CommentsFetchResponse> request = repository.fetchComments(mediaId, form); |
|||
request.enqueue(new Callback<CommentsFetchResponse>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<CommentsFetchResponse> call, @NonNull final Response<CommentsFetchResponse> response) { |
|||
if (callback == null) return; |
|||
final CommentsFetchResponse cfr = response.body(); |
|||
if (cfr == null) callback.onFailure(new Exception("response is empty")); |
|||
callback.onSuccess(cfr); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<CommentsFetchResponse> call, @NonNull final Throwable t) { |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void fetchChildComments(@NonNull final String mediaId, |
|||
@NonNull final String commentId, |
|||
final String maxId, |
|||
@NonNull final ServiceCallback<ChildCommentsFetchResponse> callback) { |
|||
final Map<String, String> form = new HashMap<>(); |
|||
if (maxId != null) form.put("max_id", maxId); |
|||
final Call<ChildCommentsFetchResponse> request = repository.fetchChildComments(mediaId, commentId, form); |
|||
request.enqueue(new Callback<ChildCommentsFetchResponse>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<ChildCommentsFetchResponse> call, @NonNull final Response<ChildCommentsFetchResponse> response) { |
|||
if (callback == null) return; |
|||
final ChildCommentsFetchResponse cfr = response.body(); |
|||
if (cfr == null) callback.onFailure(new Exception("response is empty")); |
|||
callback.onSuccess(cfr); |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<ChildCommentsFetchResponse> call, @NonNull final Throwable t) { |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void comment(@NonNull final String mediaId, |
|||
@NonNull final String comment, |
|||
final String replyToCommentId, |
|||
@NonNull final ServiceCallback<Comment> callback) { |
|||
final String module = "self_comments_v2"; |
|||
final Map<String, Object> form = new HashMap<>(); |
|||
// form.put("user_breadcrumb", userBreadcrumb(comment.length())); |
|||
form.put("idempotence_token", UUID.randomUUID().toString()); |
|||
form.put("_csrftoken", csrfToken); |
|||
form.put("_uid", userId); |
|||
form.put("_uuid", deviceUuid); |
|||
form.put("comment_text", comment); |
|||
form.put("containermodule", module); |
|||
if (!TextUtils.isEmpty(replyToCommentId)) { |
|||
form.put("replied_to_comment_id", replyToCommentId); |
|||
} |
|||
final Map<String, String> signedForm = Utils.sign(form); |
|||
final Call<String> commentRequest = repository.comment(mediaId, signedForm); |
|||
commentRequest.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String body = response.body(); |
|||
if (body == null) { |
|||
Log.e(TAG, "Error occurred while creating comment"); |
|||
callback.onSuccess(null); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject jsonObject = new JSONObject(body); |
|||
// final String status = jsonObject.optString("status"); |
|||
final JSONObject commentJsonObject = jsonObject.optJSONObject("comment"); |
|||
Comment comment = null; |
|||
if (commentJsonObject != null) { |
|||
final JSONObject userJsonObject = commentJsonObject.optJSONObject("user"); |
|||
if (userJsonObject != null) { |
|||
final Gson gson = new Gson(); |
|||
final User user = gson.fromJson(userJsonObject.toString(), User.class); |
|||
comment = new Comment( |
|||
commentJsonObject.optString("pk"), |
|||
commentJsonObject.optString("text"), |
|||
commentJsonObject.optLong("created_at"), |
|||
0L, |
|||
false, |
|||
user, |
|||
0 |
|||
); |
|||
} |
|||
} |
|||
callback.onSuccess(comment); |
|||
} catch (Exception e) { |
|||
callback.onFailure(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void deleteComment(final String mediaId, |
|||
final String commentId, |
|||
@NonNull final ServiceCallback<Boolean> callback) { |
|||
deleteComments(mediaId, Collections.singletonList(commentId), callback); |
|||
} |
|||
|
|||
public void deleteComments(final String mediaId, |
|||
final List<String> commentIds, |
|||
@NonNull final ServiceCallback<Boolean> callback) { |
|||
final Map<String, Object> form = new HashMap<>(); |
|||
form.put("comment_ids_to_delete", android.text.TextUtils.join(",", commentIds)); |
|||
form.put("_csrftoken", csrfToken); |
|||
form.put("_uid", userId); |
|||
form.put("_uuid", deviceUuid); |
|||
final Map<String, String> signedForm = Utils.sign(form); |
|||
final Call<String> bulkDeleteRequest = repository.commentsBulkDelete(mediaId, signedForm); |
|||
bulkDeleteRequest.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String body = response.body(); |
|||
if (body == null) { |
|||
Log.e(TAG, "Error occurred while deleting comments"); |
|||
callback.onSuccess(false); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject jsonObject = new JSONObject(body); |
|||
final String status = jsonObject.optString("status"); |
|||
callback.onSuccess(status.equals("ok")); |
|||
} catch (JSONException e) { |
|||
// Log.e(TAG, "Error parsing body", e); |
|||
callback.onFailure(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
// Log.e(TAG, "Error deleting comments", t); |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void commentLike(@NonNull final String commentId, |
|||
@NonNull final ServiceCallback<Boolean> callback) { |
|||
final Map<String, Object> form = new HashMap<>(); |
|||
form.put("_csrftoken", csrfToken); |
|||
// form.put("_uid", userId); |
|||
// form.put("_uuid", deviceUuid); |
|||
final Map<String, String> signedForm = Utils.sign(form); |
|||
final Call<String> commentLikeRequest = repository.commentLike(commentId, signedForm); |
|||
commentLikeRequest.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String body = response.body(); |
|||
if (body == null) { |
|||
Log.e(TAG, "Error occurred while liking comment"); |
|||
callback.onSuccess(false); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject jsonObject = new JSONObject(body); |
|||
final String status = jsonObject.optString("status"); |
|||
callback.onSuccess(status.equals("ok")); |
|||
} catch (JSONException e) { |
|||
// Log.e(TAG, "Error parsing body", e); |
|||
callback.onFailure(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
Log.e(TAG, "Error liking comment", t); |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void commentUnlike(final String commentId, |
|||
@NonNull final ServiceCallback<Boolean> callback) { |
|||
final Map<String, Object> form = new HashMap<>(); |
|||
form.put("_csrftoken", csrfToken); |
|||
// form.put("_uid", userId); |
|||
// form.put("_uuid", deviceUuid); |
|||
final Map<String, String> signedForm = Utils.sign(form); |
|||
final Call<String> commentUnlikeRequest = repository.commentUnlike(commentId, signedForm); |
|||
commentUnlikeRequest.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String body = response.body(); |
|||
if (body == null) { |
|||
Log.e(TAG, "Error occurred while unliking comment"); |
|||
callback.onSuccess(false); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject jsonObject = new JSONObject(body); |
|||
final String status = jsonObject.optString("status"); |
|||
callback.onSuccess(status.equals("ok")); |
|||
} catch (JSONException e) { |
|||
// Log.e(TAG, "Error parsing body", e); |
|||
callback.onFailure(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
Log.e(TAG, "Error unliking comment", t); |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
public void translate(final String id, |
|||
@NonNull final ServiceCallback<String> callback) { |
|||
final Map<String, String> form = new HashMap<>(); |
|||
form.put("id", String.valueOf(id)); |
|||
form.put("type", "2"); |
|||
final Call<String> request = repository.translate(form); |
|||
request.enqueue(new Callback<String>() { |
|||
@Override |
|||
public void onResponse(@NonNull final Call<String> call, @NonNull final Response<String> response) { |
|||
final String body = response.body(); |
|||
if (body == null) { |
|||
Log.e(TAG, "Error occurred while translating"); |
|||
callback.onSuccess(null); |
|||
return; |
|||
} |
|||
try { |
|||
final JSONObject jsonObject = new JSONObject(body); |
|||
final String translation = jsonObject.optString("translation"); |
|||
callback.onSuccess(translation); |
|||
} catch (JSONException e) { |
|||
// Log.e(TAG, "Error parsing body", e); |
|||
callback.onFailure(e); |
|||
} |
|||
} |
|||
|
|||
@Override |
|||
public void onFailure(@NonNull final Call<String> call, @NonNull final Throwable t) { |
|||
Log.e(TAG, "Error translating", t); |
|||
callback.onFailure(t); |
|||
} |
|||
}); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue