/** * Interface to the WordPress.com REST API. */ package org.wordpress.android.util; import java.util.HashMap; import java.util.Map; import com.android.volley.DefaultRetryPolicy; import com.android.volley.Request.Method; import com.android.volley.RequestQueue; import com.android.volley.RetryPolicy; import com.android.volley.VolleyError; import com.wordpress.rest.Oauth; import com.wordpress.rest.RestClient; import com.wordpress.rest.RestRequest; import com.wordpress.rest.RestRequest.ErrorListener; import com.wordpress.rest.RestRequest.Listener; import org.wordpress.android.WordPress; import org.wordpress.android.models.Note; public class WPRestClient { private static final String NOTIFICATION_FIELDS = "id,type,unread,body,subject,timestamp"; private static final String COMMENT_REPLY_CONTENT_FIELD = "content"; private RestClient mRestClient; private Authenticator mAuthenticator; /** Socket timeout in milliseconds for rest requests */ public static final int REST_TIMEOUT_MS = 30000; /** Default number of retries for POST rest requests */ public static final int REST_MAX_RETRIES_POST = 0; /** Default number of retries for GET rest requests */ public static final int REST_MAX_RETRIES_GET = 3; /** Default backoff multiplier for rest requests */ public static final float REST_BACKOFF_MULT = 2f; public WPRestClient(RequestQueue queue, Authenticator authenticator, String accessToken) { // load an existing access token from prefs if we have one mAuthenticator = authenticator; mRestClient = new RestClient(queue, accessToken); if (DeviceUtils.isBlackBerry()) { mRestClient.setUserAgent(DeviceUtils.getBlackBerryUserAgent()); } else { mRestClient.setUserAgent("wp-android/" + WordPress.versionName); } } /** * Remove the current access token */ public void clearAccessToken() { mRestClient.setAccessToken(null); } /** * Sets the access token for all future requests */ public void setAccessToken(String token) { mRestClient.setAccessToken(token); } /** * Reply to a comment using a Note.Reply object. * * https://developer.wordpress.com/docs/api/1/post/sites/%24site/posts/%24 * post_ID/replies/new/ */ public void replyToComment(Note.Reply reply, Listener listener, ErrorListener errorListener) { Map<String, String> params = new HashMap<String, String>(); params.put(COMMENT_REPLY_CONTENT_FIELD, reply.getContent()); post(reply.getRestPath(), params, null, listener, errorListener); } /** * Reply to a comment. * * https://developer.wordpress.com/docs/api/1/post/sites/%24site/posts/%24 * post_ID/replies/new/ */ public void replyToComment(String siteId, String commentId, String content, Listener listener, ErrorListener errorListener) { Map<String, String> params = new HashMap<String, String>(); params.put(COMMENT_REPLY_CONTENT_FIELD, content); String path = String.format("sites/%s/comments/%s/replies/new", siteId, commentId); post(path, params, null, listener, errorListener); } /** * Follow a site given an ID or domain * * https://developer.wordpress.com/docs/api/1/post/sites/%24site/follows/new * / */ public void followSite(String siteId, Listener listener, ErrorListener errorListener) { String path = String.format("sites/%s/follows/new", siteId); post(path, listener, errorListener); } /** * Unfollow a site given an ID or domain * * https://developer.wordpress.com/docs/api/1/post/sites/%24site/follows/ * mine/delete/ */ public void unfollowSite(String siteId, Listener listener, ErrorListener errorListener) { String path = String.format("sites/%s/follows/mine/delete", siteId); post(path, listener, errorListener); } /** * Get a single notification. * * https://developer.wordpress.com/docs/api/1/get/notifications/ */ public void getNotification(String noteId, Listener listener, ErrorListener errorListener) { get(String.format("notifications/%s", noteId), listener, errorListener); } /** * Mark a notification as read * * https://developer.wordpress.com/docs/api/1/post/notifications/read/ */ public void markNoteAsRead(Note note, Listener listener, ErrorListener errorListener) { String path = "notifications/read"; Map<String, String> params = new HashMap<String, String>(); params.put(String.format("counts[%s]", note.getId()), note.getUnreadCount()); post(path, params, null, listener, errorListener); } /** * Get notifications with the provided params. * * https://developer.wordpress.com/docs/api/1/get/notifications/ */ public void getNotifications(Map<String, String> params, Listener listener, ErrorListener errorListener) { params.put("number", "40"); params.put("num_note_items", "20"); params.put("fields", NOTIFICATION_FIELDS); get("notifications", params, null, listener, errorListener); } /** * Get notifications with default params. * * https://developer.wordpress.com/docs/api/1/get/notifications/ */ public void getNotifications(Listener listener, ErrorListener errorListener) { getNotifications(new HashMap<String, String>(), listener, errorListener); } /** * Update the seen timestamp. * * https://developer.wordpress.com/docs/api/1/post/notifications/seen */ public void markNotificationsSeen(String timestamp, Listener listener, ErrorListener errorListener) { Map<String, String> params = new HashMap<String, String>(); params.put("time", timestamp); post("notifications/seen", params, null, listener, errorListener); } /** * Moderate a comment. * * http://developer.wordpress.com/docs/api/1/sites/%24site/comments/%24 * comment_ID/ */ public void moderateComment(String siteId, String commentId, String status, Listener listener, ErrorListener errorListener) { Map<String, String> params = new HashMap<String, String>(); params.put("status", status); String path = String.format("sites/%s/comments/%s/", siteId, commentId); post(path, params, null, listener, errorListener); } /** * Make GET request */ public void get(String path, Listener listener, ErrorListener errorListener) { get(path, null, null, listener, errorListener); } /** * Make GET request with params */ public void get(String path, Map<String, String> params, RetryPolicy retryPolicy, Listener listener, ErrorListener errorListener) { // turn params into querystring RestRequest request = mRestClient.makeRequest(Method.GET, RestClient.getAbsoluteURL(path, params), null, listener, errorListener); if (retryPolicy == null) { retryPolicy = new DefaultRetryPolicy(REST_TIMEOUT_MS, REST_MAX_RETRIES_GET, REST_BACKOFF_MULT); } request.setRetryPolicy(retryPolicy); Request authCheck = new Request(request, errorListener); authCheck.send(); } /** * Make POST request */ public void post(String path, Listener listener, ErrorListener errorListener) { post(path, null, null, listener, errorListener); } /** * Make POST request with params */ public void post(final String path, Map<String, String> params, RetryPolicy retryPolicy, Listener listener, ErrorListener errorListener) { final RestRequest request = mRestClient.makeRequest(Method.POST, RestClient.getAbsoluteURL(path), params, listener, errorListener); if (retryPolicy == null) { retryPolicy = new DefaultRetryPolicy(REST_TIMEOUT_MS, REST_MAX_RETRIES_POST, REST_BACKOFF_MULT); //Do not retry on failure } request.setRetryPolicy(retryPolicy); Request authCheck = new Request(request, errorListener); authCheck.send(); } /** * Interface that provides a method that should perform the necessary task * to make sure the provided Request will be authenticated. * * The Authenticator must call Request.send() when it has completed its * operations. For convenience the Request class provides * Request.setAccessToken so the Authenticator can easily update the access * token. */ public interface Authenticator { void authenticate(Request request); } /** * Encapsulates the behaviour for asking the Authenticator for an access * token. This allows the request maker to disregard the authentication * state when making requests. */ public class Request { RestRequest mRequest; RestRequest.ErrorListener mListener; protected Request(RestRequest request, ErrorListener listener) { mRequest = request; mListener = listener; } /** * Attempt to send the request, checks to see if we have an access token * and if not asks the Authenticator to authenticate the request. * * If no Authenticator is provided the request is always sent. */ public void send() { if (mRestClient.isAuthenticated() || mAuthenticator == null) { makeRequest(); } else { mAuthenticator.authenticate(this); } } /** * Method to set the acces token for current and future requests */ public void setAccessToken(Oauth.Token token) { mRestClient.setAccessToken(token.toString()); mRequest.setAccessToken(token.toString()); } /** * If an access token cannot be obtained the request can be aborted and * the handler's onFailure method is called */ public void abort(VolleyError error) { if (mListener != null) { mListener.onErrorResponse(error); } } /** * Implement this method to perform the request that should be * authenticated */ public void makeRequest() { mRestClient.send(mRequest); } } }