package kr.kdev.dg1s.biowiki.ui.comments; import android.os.Handler; import android.text.TextUtils; import com.android.volley.VolleyError; import com.wordpress.rest.RestRequest; import org.json.JSONObject; import org.xmlpull.v1.XmlPullParserException; import org.xmlrpc.android.XMLRPCClientInterface; import org.xmlrpc.android.XMLRPCException; import org.xmlrpc.android.XMLRPCFactory; import java.io.IOException; import java.util.HashMap; import java.util.Map; import kr.kdev.dg1s.biowiki.BioWiki; import kr.kdev.dg1s.biowiki.datasets.CommentTable; import kr.kdev.dg1s.biowiki.models.Blog; import kr.kdev.dg1s.biowiki.models.Comment; import kr.kdev.dg1s.biowiki.models.CommentList; import kr.kdev.dg1s.biowiki.models.CommentStatus; import kr.kdev.dg1s.biowiki.models.Note; import kr.kdev.dg1s.biowiki.util.AppLog; /** * Created by nbradbury on 11/8/13. * actions related to comments - replies, moderating, etc. * methods below do network calls in the background & update local DB upon success * all methods below MUST be called from UI thread */ public class CommentActions { private CommentActions() { throw new AssertionError(); } /* * add a comment for the passed post */ public static void addComment(final int accountId, final String postID, final String commentText, final CommentActionListener actionListener) { final Blog blog = BioWiki.getBlog(accountId); if (blog == null || TextUtils.isEmpty(commentText)) { if (actionListener != null) actionListener.onActionResult(false); return; } final Handler handler = new Handler(); new Thread() { @Override public void run() { XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword()); Map<String, Object> commentHash = new HashMap<String, Object>(); commentHash.put("content", commentText); commentHash.put("author", ""); commentHash.put("author_url", ""); commentHash.put("author_email", ""); Object[] params = { blog.getRemoteBlogId(), blog.getUsername(), blog.getPassword(), postID, commentHash}; int newCommentID; try { newCommentID = (Integer) client.call("wp.newComment", params); } catch (XMLRPCException e) { AppLog.e(AppLog.T.COMMENTS, "Error while sending new comment", e); newCommentID = -1; } catch (IOException e) { AppLog.e(AppLog.T.COMMENTS, "Error while sending new comment", e); newCommentID = -1; } catch (XmlPullParserException e) { AppLog.e(AppLog.T.COMMENTS, "Error while sending new comment", e); newCommentID = -1; } final boolean succeeded = (newCommentID >= 0); if (actionListener != null) { handler.post(new Runnable() { @Override public void run() { actionListener.onActionResult(succeeded); } }); } } }.start(); } /** * reply to an individual comment */ static void submitReplyToComment(final int accountId, final Comment comment, final String replyText, final CommentActionListener actionListener) { final Blog blog = BioWiki.getBlog(accountId); if (blog == null || comment == null || TextUtils.isEmpty(replyText)) { if (actionListener != null) actionListener.onActionResult(false); return; } final Handler handler = new Handler(); new Thread() { @Override public void run() { XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword()); Map<String, Object> replyHash = new HashMap<String, Object>(); replyHash.put("comment_parent", Long.toString(comment.commentID)); replyHash.put("content", replyText); replyHash.put("author", ""); replyHash.put("author_url", ""); replyHash.put("author_email", ""); Object[] params = { blog.getRemoteBlogId(), blog.getUsername(), blog.getPassword(), Long.toString(comment.postID), replyHash}; long newCommentID; try { Object newCommentIDObject = client.call("wp.newComment", params); if (newCommentIDObject instanceof Integer) { newCommentID = ((Integer) newCommentIDObject).longValue(); } else if (newCommentIDObject instanceof Long) { newCommentID = (Long) newCommentIDObject; } else { AppLog.e(AppLog.T.COMMENTS, "wp.newComment returned the wrong data type"); newCommentID = -1; } } catch (XMLRPCException e) { AppLog.e(AppLog.T.COMMENTS, "Error while sending the new comment", e); newCommentID = -1; } catch (IOException e) { AppLog.e(AppLog.T.COMMENTS, "Error while sending the new comment", e); newCommentID = -1; } catch (XmlPullParserException e) { AppLog.e(AppLog.T.COMMENTS, "Error while sending the new comment", e); newCommentID = -1; } final boolean succeeded = (newCommentID >= 0); if (actionListener != null) { handler.post(new Runnable() { @Override public void run() { actionListener.onActionResult(succeeded); } }); } } }.start(); } /** * reply to an individual comment that came from a notification - this differs from * submitReplyToComment() in that it enables responding to a reply to a comment this * user made on someone else's blog */ static void submitReplyToCommentNote(final Note note, final String replyText, final CommentActionListener actionListener) { if (note == null || TextUtils.isEmpty(replyText)) { if (actionListener != null) actionListener.onActionResult(false); return; } RestRequest.Listener listener = new RestRequest.Listener() { @Override public void onResponse(JSONObject jsonObject) { if (actionListener != null) actionListener.onActionResult(true); } }; RestRequest.ErrorListener errorListener = new RestRequest.ErrorListener() { @Override public void onErrorResponse(VolleyError volleyError) { if (volleyError != null) AppLog.e(AppLog.T.COMMENTS, volleyError.getMessage(), volleyError); if (actionListener != null) actionListener.onActionResult(false); } }; Note.Reply reply = note.buildReply(replyText); BioWiki.getRestClientUtils().replyToComment(reply, listener, errorListener); } /** * change the status of a single comment */ static void moderateComment(final int accountId, final Comment comment, final CommentStatus newStatus, final CommentActionListener actionListener) { // deletion is handled separately if (newStatus != null && newStatus.equals(CommentStatus.TRASH)) { deleteComment(accountId, comment, actionListener); return; } final Blog blog = BioWiki.getBlog(accountId); if (blog == null || comment == null || newStatus == null || newStatus == CommentStatus.UNKNOWN) { if (actionListener != null) actionListener.onActionResult(false); return; } final Handler handler = new Handler(); new Thread() { @Override public void run() { XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword()); Map<String, String> postHash = new HashMap<String, String>(); postHash.put("status", CommentStatus.toString(newStatus)); postHash.put("content", comment.getCommentText()); postHash.put("author", comment.getAuthorName()); postHash.put("author_url", comment.getAuthorUrl()); postHash.put("author_email", comment.getAuthorEmail()); Object[] params = {blog.getRemoteBlogId(), blog.getUsername(), blog.getPassword(), Long.toString(comment.commentID), postHash}; Object result; try { result = client.call("wp.editComment", params); } catch (XMLRPCException e) { AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e); result = null; } catch (IOException e) { AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e); result = null; } catch (XmlPullParserException e) { AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e); result = null; } final boolean success = (result != null && Boolean.parseBoolean(result.toString())); if (success) CommentTable.updateCommentStatus(blog.getLocalTableBlogId(), comment.commentID, CommentStatus.toString(newStatus)); if (actionListener != null) { handler.post(new Runnable() { @Override public void run() { actionListener.onActionResult(success); } }); } } }.start(); } /** * change the status of multiple comments * TODO: investigate using system.multiCall to perform a single call to moderate the list */ static void moderateComments(final int accountId, final CommentList comments, final CommentStatus newStatus, final OnCommentsModeratedListener actionListener) { // deletion is handled separately if (newStatus != null && newStatus.equals(CommentStatus.TRASH)) { deleteComments(accountId, comments, actionListener); return; } final Blog blog = BioWiki.getBlog(accountId); if (blog == null || comments == null || comments.size() == 0 || newStatus == null || newStatus == CommentStatus.UNKNOWN) { if (actionListener != null) actionListener.onCommentsModerated(new CommentList()); return; } final CommentList moderatedComments = new CommentList(); final String newStatusStr = CommentStatus.toString(newStatus); final int localBlogId = blog.getLocalTableBlogId(); final int remoteBlogId = blog.getRemoteBlogId(); final Handler handler = new Handler(); new Thread() { @Override public void run() { XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword()); for (Comment comment : comments) { Map<String, String> postHash = new HashMap<String, String>(); postHash.put("status", newStatusStr); postHash.put("content", comment.getCommentText()); postHash.put("author", comment.getAuthorName()); postHash.put("author_url", comment.getAuthorUrl()); postHash.put("author_email", comment.getAuthorEmail()); Object[] params = { remoteBlogId, blog.getUsername(), blog.getPassword(), Long.toString(comment.commentID), postHash}; Object result; try { result = client.call("wp.editComment", params); boolean success = (result != null && Boolean.parseBoolean(result.toString())); if (success) { comment.setStatus(newStatusStr); moderatedComments.add(comment); } } catch (XMLRPCException e) { AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e); } catch (IOException e) { AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e); } catch (XmlPullParserException e) { AppLog.e(AppLog.T.COMMENTS, "Error while editing comment", e); } } // update status in SQLite of successfully moderated comments CommentTable.updateCommentsStatus(localBlogId, moderatedComments, newStatusStr); if (actionListener != null) { handler.post(new Runnable() { @Override public void run() { actionListener.onCommentsModerated(moderatedComments); } }); } } }.start(); } /** * delete (trash) a single comment */ private static void deleteComment(final int accountId, final Comment comment, final CommentActionListener actionListener) { final Blog blog = BioWiki.getBlog(accountId); if (blog == null || comment == null) { if (actionListener != null) actionListener.onActionResult(false); return; } final Handler handler = new Handler(); new Thread() { @Override public void run() { XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword()); Object[] params = { blog.getRemoteBlogId(), blog.getUsername(), blog.getPassword(), comment.commentID}; Object result; try { result = client.call("wp.deleteComment", params); } catch (final XMLRPCException e) { AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e); result = null; } catch (IOException e) { AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e); result = null; } catch (XmlPullParserException e) { AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e); result = null; } final boolean success = (result != null && Boolean.parseBoolean(result.toString())); if (success) CommentTable.deleteComment(accountId, comment.commentID); if (actionListener != null) { handler.post(new Runnable() { @Override public void run() { actionListener.onActionResult(success); } }); } } }.start(); } /** * delete multiple comments */ private static void deleteComments(final int accountId, final CommentList comments, final OnCommentsModeratedListener actionListener) { final Blog blog = BioWiki.getBlog(accountId); if (blog == null || comments == null || comments.size() == 0) { if (actionListener != null) actionListener.onCommentsModerated(new CommentList()); return; } final CommentList deletedComments = new CommentList(); final int localBlogId = blog.getLocalTableBlogId(); final int remoteBlogId = blog.getRemoteBlogId(); final Handler handler = new Handler(); new Thread() { @Override public void run() { XMLRPCClientInterface client = XMLRPCFactory.instantiate(blog.getUri(), blog.getHttpuser(), blog.getHttppassword()); for (Comment comment : comments) { Object[] params = { remoteBlogId, blog.getUsername(), blog.getPassword(), comment.commentID}; Object result; try { result = client.call("wp.deleteComment", params); boolean success = (result != null && Boolean.parseBoolean(result.toString())); if (success) deletedComments.add(comment); } catch (XMLRPCException e) { AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e); } catch (IOException e) { AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e); } catch (XmlPullParserException e) { AppLog.e(AppLog.T.COMMENTS, "Error while deleting comment", e); } } // remove successfully deleted comments from SQLite CommentTable.deleteComments(localBlogId, deletedComments); if (actionListener != null) { handler.post(new Runnable() { @Override public void run() { actionListener.onCommentsModerated(deletedComments); } }); } } }.start(); } /* * used by comment fragments to alert container activity of a change to one or more * comments (moderated, deleted, added, etc.) */ public static enum ChangedFrom { COMMENT_LIST, COMMENT_DETAIL } public static enum ChangeType {EDITED, STATUS, REPLIED, TRASHED} /* * listener when a comment action is performed */ public interface CommentActionListener { public void onActionResult(boolean succeeded); } /* * listener when comments are moderated or deleted */ public interface OnCommentsModeratedListener { public void onCommentsModerated(final CommentList moderatedComments); } public static interface OnCommentChangeListener { public void onCommentChanged(ChangedFrom changedFrom, ChangeType changeType); } }