mypackage.FeedlyAPI.java Source code

Java tutorial

Introduction

Here is the source code for mypackage.FeedlyAPI.java

Source

/*
   FeedlyAPI.java
       
   Copyright (C) 2014 Shun ITO <movingentity@gmail.com>
       
   This file is part of Green Feed Reader.
    
   Green Feed Reader is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public License
   as published by the Free Software Foundation; either version 2
   of the License, or (at your option) any later version.
       
   Green Feed Reader is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
       
   You should have received a copy of the GNU General Public License
   along with Green Feed Reader.  If not, see <http://www.gnu.org/licenses/>.
*/

package mypackage;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;

import org.json.me.JSONArray;
import org.json.me.JSONException;
import org.json.me.JSONObject;

public class FeedlyAPI {
    private FeedlyClient _feedlyclient = null;

    private String client_id = "";
    private String client_secret = "";
    private String service_host = "";

    private static final int NUM_OF_TRIALS = 3;

    public FeedlyAPI(FeedlyClient _feedlyclient, String client_id, String client_secret, boolean sandbox) {
        this._feedlyclient = _feedlyclient;

        this.client_id = client_id;
        this.client_secret = client_secret;

        if (sandbox) {
            this.service_host = "sandbox.feedly.com";
        } else {
            this.service_host = "cloud.feedly.com";
        }
    }

    //
    //-- Authentication -------------------------------------------------------//
    //
    public String get_code_url(String callback_url) {
        // Authenticating a user and obtaining a code
        //
        // The authentication scenario begins by redirecting a browser (full page or popup)
        // to a feedly cloud URL with a set of query parameters that indicate
        // the type of cloud API access the application requires.
        // feedly handles the user authentication and consent,
        // and the result is authorization code. feedly returns the code on the redirect of the response.
        //
        // GET /v3/auth/auth

        final String SCOPE = "https://cloud.feedly.com/subscriptions";
        final String RESPONSE_TYPE = "code";

        String request_url = "";
        request_url += getEndpoint("/v3/auth/auth") + "?";
        request_url += "client_id=" + client_id + "&";
        request_url += "redirect_uri=" + callback_url + "&";
        request_url += "scope=" + SCOPE + "&";
        request_url += "response_type=" + RESPONSE_TYPE;

        return request_url;
    }

    public JSONObject getAccessToken(String redirect_uri, String code) throws Exception {
        // Exchanging a code for a refresh token and an access token
        // After you received the code, you may exchange it for an access token and a refresh token.
        // This request is an HTTPs post, and includes the following parameters:
        //
        // POST /v3/auth/token

        JSONObject body = new JSONObject();
        try {
            body.put("client_id", client_id);
            body.put("client_secret", client_secret);
            body.put("grant_type", "authorization_code");
            body.put("redirect_uri", redirect_uri);
            body.put("code", code);
        } catch (JSONException e) {
            throw new Exception("FeedlyAPI::getAccessToken()0");
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                return new JSONObject(doPostNOCheck(getEndpoint("/v3/auth/token"), body));
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::getAccessToken()1");
    }

    public JSONObject refreshAccessToken() throws IOException, Exception {
        // Using a refresh token
        //
        // Your application may obtain a new access token by sending a refresh token
        // to the feedly Authorization server.
        //
        // POST /v3/auth/token

        JSONObject body = new JSONObject();
        try {
            body.put("refresh_token", _feedlyclient.getRefreshToken());
            body.put("client_id", client_id);
            body.put("client_secret", client_secret);
            body.put("grant_type", "refresh_token");
        } catch (JSONException e) {
            throw new Exception("FeedlyAPI::refreshAccessToken()0");
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                return new JSONObject(doPostNOCheck(getEndpoint("/v3/auth/token"), body));
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::refreshAccessToken()1");
    } //refreshAccessToken()

    public JSONObject revokeRefreshToken() throws Exception {
        // Revoking a refresh token
        // 
        // This is a logout operation:
        // the refresh token passed cannot be reused to generate new access tokens.
        //
        // POST /v3/auth/token

        JSONObject body = new JSONObject();
        try {
            body.put("refresh_token", _feedlyclient.getRefreshToken());
            body.put("client_id", client_id);
            body.put("client_secret", client_secret);
            body.put("grant_type", "revoke_token");
        } catch (JSONException e) {
            throw new Exception("FeedlyAPI::revokeRefreshToken()0");
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                return new JSONObject(doPost(getEndpoint("/v3/auth/token"), body));
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::revokeRefreshToken()1");
    }

    //
    //-- Feeds ----------------------------------------------------------------//
    //
    /*public JSONArray getMetadataForListOfFeeds(Vector feedIds) throws JSONException, IOException, Exception
    {
       // Get the metadata for a list of feeds
       //
       // POST /v3/feeds/.mget
           
       String url = getEndpoint("/v3/feeds/.mget");
       JSONArray body = new JSONArray(feedIds);
           
        return new JSONArray(doPostJSONArray(url, body));
    }*/

    //
    //-- Markers --------------------------------------------------------------//
    //
    public JSONObject getListOfUnreadCounts() throws Exception {
        // Get the list of unread counts
        //
        // GET /v3/markers/counts

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                return new JSONObject(doGet(getEndpoint("/v3/markers/counts")));
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::getListOfUnreadCounts()");
    }

    public void markOneOrMultipleArticlesAsRead(Vector entryIds) throws Exception {
        // Mark one or multiple articles as read
        // POST /v3/markers

        if (entryIds.size() == 0) {
            throw new Exception("FeedlyAPI::markOneOrMultipleArticlesAsRead()0");
        }

        //
        JSONObject body = new JSONObject();
        try {
            body.put("action", "markAsRead");
            body.put("type", "entries");
            body.put("entryIds", entryIds);
        } catch (JSONException e) {
            throw new Exception("FeedlyAPI::markOneOrMultipleArticlesAsRead()1");
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                doPost(getEndpoint("/v3/markers"), body);
                return;
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::markOneOrMultipleArticlesAsRead()2");
    }

    public void keepOneOrMultipleArticlesAsUnread(Vector entryIds) throws IOException, Exception {
        // Keep one or multiple articles as unread
        // POST /v3/markers

        if (entryIds.size() == 0) {
            throw new Exception("FeedlyAPI::keepOneOrMultipleArticlesAsUnread()0");
        }

        //
        JSONObject json = new JSONObject();
        try {
            json.put("action", "keepUnread");
            json.put("type", "entries");
            json.put("entryIds", entryIds);
        } catch (JSONException e) {
            throw new Exception("FeedlyAPI::keepOneOrMultipleArticlesAsUnread()1");
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                doPost(getEndpoint("/v3/markers"), json);
                return;
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::keepOneOrMultipleArticlesAsUnread()2");
    }

    //
    //-- Streams --------------------------------------------------------------//
    //
    public JSONObject getTheContentOfaStream(String streamId) throws Exception {
        // GET /v3/streams/:streamId/contents <- NOT WORK
        // or
        // GET /v3/streams/contents?streamId=:streamId
        //
        // [streamId]
        // Feed Id
        // feed/:url example: feed/http://feeds.engadget.com/weblogsinc/engadget
        // Category Id
        // user/:userId/category/:label example: user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/tech
        // Tag Id
        // user/:userId/tag/:label example: user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/tag/inspiration

        //return new JSONObject(doGet(getEndpoint("/v3/streams/contents?streamId=" + streamId)));

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                String raw = doGet(getEndpoint("/v3/streams/contents?streamId=" + streamId));
                JSONObject out = new JSONObject(raw);
                return out;
            } catch (JSONException e) {
                continue;
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::getTheContentOfaStream()");
    }

    //
    //-- Subscriptions --------------------------------------------------------//
    //
    public JSONArray getUserSubscriptions() throws Exception {
        // Get the user?fs subscriptions
        //
        // GET /v3/subscriptions

        String error = "\n->";

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                return new JSONArray(doGet(getEndpoint("/v3/subscriptions")));
            } catch (JSONException e) {
                error += "\n->" + e.toString();
                continue;
            } catch (IOException e) {
                error += "\n->" + e.toString();
                continue;
            } catch (Exception e) {
                error += "\n->" + e.toString();
                continue;
            }
        }
        throw new Exception("FeedlyAPI::getUserSubscriptions()" + error);
    }

    //
    //-- Tags -----------------------------------------------------------------//
    //
    /*public JSONArray getListOfTags() throws IOException, Exception
    {
       // Get the list of tags created by the user.
       //
       // GET /v3/tags
           
       // O???Aw???s?B
       for(int i=0; i<NUM_OF_TRIALS; i++)
       {
     try {
        return new JSONArray(doGet(getEndpoint("/v3/tags")));
     } catch (IOException e) {
        continue;
     } catch (Exception e) {
        continue;
     }
       }
       throw new Exception("FeedlyAPI::getListOfUnreadCounts()");
    }*/

    public void tagEntry(String tagId, String feedId) throws Exception {
        // Tag an existing entry
        //
        // PUT /v3/tags/:tagId1,:tagId2

        // !!!!!!! tagId'/'URLGR?[h !!!!!!!
        String url = getEndpoint("/v3/tags/") + encode(tagId);

        //
        JSONObject body = new JSONObject();
        try {
            body.put("entryId", feedId);
        } catch (JSONException e) {
            throw new Exception("FeedlyAPI::tagEntry()0");
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                doPut(url, body);
                return;
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::tagEntry()1");
    }

    /*public void tagMultipleEntries(String tagId, Vector entryIds) throws Exception
    {
       //    Tag multiple entries
       //
       // PUT /v3/tags/:tagId1,:tagId2
           
       // Some info about some api - Google O?[v
       // https://groups.google.com/forum/#!searchin/feedly-cloud/tag/feedly-cloud/Py15TGUVAyA/pIn7kWwKCRoJ
           
       if(entryIds.size() == 0)
       {
     throw new Exception("FeedlyAPI::tagMultipleEntries()0");
       }
           
       // !!!!!!! tagId'/'URLGR?[h !!!!!!!
       String url = getEndpoint("/v3/tags/") + encode(tagId);
           
       //
       JSONObject json = new JSONObject();
       try {
     json.put("entryIds", entryIds);
       } catch (JSONException e) {
     throw new Exception("FeedlyAPI::tagMultipleEntries()1");
       }
           
       // O???Aw???s?B
       for(int i=0; i<NUM_OF_TRIALS; i++)
       {
     try {
        doPut(url, json);
        return;
     } catch (IOException e) {
        continue;
     } catch (Exception e) {
        continue;
     }
       }
       throw new Exception("FeedlyAPI::tagMultipleEntries()2");
    }*/

    public void untagMultipleEntries(String tagId, Vector entryIds) throws Exception {
        // Untag multiple entries
        //
        // DELETE /v3/tags/:tagId1,tagId2/:entryId1,entryId2

        // Some info about some api - Google O?[v
        // https://groups.google.com/forum/#!searchin/feedly-cloud/tag/feedly-cloud/Py15TGUVAyA/pIn7kWwKCRoJ

        if (entryIds.size() == 0) {
            throw new Exception("FeedlyAPI::untagMultipleEntries()0");
        }

        String url = getEndpoint("/v3/tags/");

        // tagID
        url += encode(tagId);

        // Separater
        url += "/";

        // entryIds
        for (Enumeration e = entryIds.elements(); e.hasMoreElements();) {
            // URLGR?[hentryId?B
            url += encode((String) e.nextElement());

            // Separater
            if (e.hasMoreElements()) {
                url += ",";
            }
        }

        // O???Aw???s?B
        for (int i = 0; i < NUM_OF_TRIALS; i++) {
            try {
                doDelete(url);
                return;
            } catch (IOException e) {
                continue;
            } catch (Exception e) {
                continue;
            }
        }
        throw new Exception("FeedlyAPI::untagMultipleEntries()1");
    }

    //
    //-- Utilities ------------------------------------------------------------//
    //
    private String doDelete(String url) throws IOException, Exception {
        return _feedlyclient.doDelete(url);
    }

    private String doGet(String url) throws IOException, Exception {
        return _feedlyclient.doGet(url);
    }

    private String doPost(String url, JSONObject body) throws IOException, Exception {
        return _feedlyclient.doPost(url, body, true);
    }

    /*private String doPostJSONArray(String url, JSONArray body) throws IOException, Exception
    {
       return _feedlyclient.doPostJSONArray(url, body, true);
    }*/

    private String doPostNOCheck(String url, JSONObject body) throws IOException, Exception {
        return _feedlyclient.doPost(url, body, false);
    }

    private String doPut(String url, JSONObject body) throws IOException, Exception {
        return _feedlyclient.doPut(url, body, true);
    }

    private String getEndpoint(String path) {
        String url = "https://" + service_host;

        // URLGR?[h?B
        path = urlEncode(path);

        if (path != "") {
            //url += "/" + path;
            url += path;
        }

        return url;
    }

    public String getTime(long time_ms) {
        long diffInSeconds = (System.currentTimeMillis() - time_ms) / 1000;

        long diff[] = new long[] { 0, 0, 0, 0 };
        // sec
        diff[3] = (diffInSeconds >= 60 ? diffInSeconds % 60 : diffInSeconds);
        // min
        diff[2] = (diffInSeconds = (diffInSeconds / 60)) >= 60 ? diffInSeconds % 60 : diffInSeconds;
        // hours
        diff[1] = (diffInSeconds = (diffInSeconds / 60)) >= 24 ? diffInSeconds % 24 : diffInSeconds;
        // days
        diff[0] = (diffInSeconds = (diffInSeconds / 24));

        if (diff[0] > 0) {
            if (diff[0] == 1) {
                return String.valueOf(diff[0]) + " day ago";
            } else {
                return String.valueOf(diff[0]) + " days ago";
            }
        } else if (diff[1] > 0) {
            if (diff[1] == 1) {
                return String.valueOf(diff[1]) + " hour ago";
            } else {
                return String.valueOf(diff[1]) + " hours ago";
            }
        } else if (diff[2] > 0) {
            if (diff[2] == 1) {
                return String.valueOf(diff[2]) + " minute ago";
            } else {
                return String.valueOf(diff[2]) + " minutes ago";
            }
        } else {
            return String.valueOf(diff[3]) + " seconds ago";
        }

        //e.g. 2008-06-03T12:15:03Z
        //DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        //DateFormat dateFormat = new SimpleDateFormat("HH' hours ago'");
        //return dateFormat.formatLocal(System.currentTimeMillis() - time_ms);
    }

    //
    // java.net.URLDecoder like? - BlackBerry Support Community Forums
    // http://supportforums.blackberry.com/t5/Java-Development/java-net-URLDecoder-like/td-p/435842
    // Thanks fwest!!
    //
    public static String urlEncode(String s) {
        StringBuffer sbuf = new StringBuffer();
        int len = s.length();
        for (int i = 0; i < len; i++) {
            int ch = s.charAt(i);
            if ('A' <= ch && ch <= 'Z') { // 'A'..'Z'
                sbuf.append((char) ch);
            } else if ('a' <= ch && ch <= 'z') { // 'a'..'z'
                sbuf.append((char) ch);
            } else if ('0' <= ch && ch <= '9') { // '0'..'9'
                sbuf.append((char) ch);
            } else if (ch == ' ') { // space
                sbuf.append('+');
            } else if (ch == '-' || ch == '_' // unreserved
                    || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\\' || ch == '(' || ch == ')'
                    || ch == '/' || ch == '&' || ch == '=' || ch == '?') {
                sbuf.append((char) ch);
            } else if (ch <= 0x007f) { // other ASCII
                sbuf.append(hex[ch]);
            } else if (ch <= 0x07FF) { // non-ASCII <= 0x7FF
                sbuf.append(hex[0xc0 | (ch >> 6)]);
                sbuf.append(hex[0x80 | (ch & 0x3F)]);
            } else { // 0x7FF < ch <= 0xFFFF
                sbuf.append(hex[0xe0 | (ch >> 12)]);
                sbuf.append(hex[0x80 | ((ch >> 6) & 0x3F)]);
                sbuf.append(hex[0x80 | (ch & 0x3F)]);
            }
        }
        return sbuf.toString();
    }

    // Hex constants.
    private final static String[] hex = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09",
            "%0a", "%0b", "%0c", "%0d", "%0e", "%0f", "%10", "%11", "%12", "%13", "%14", "%15", "%16", "%17", "%18",
            "%19", "%1a", "%1b", "%1c", "%1d", "%1e", "%1f", "%20", "%21", "%22", "%23", "%24", "%25", "%26", "%27",
            "%28", "%29", "%2a", "%2b", "%2c", "%2d", "%2e", "%2f", "%30", "%31", "%32", "%33", "%34", "%35", "%36",
            "%37", "%38", "%39", "%3a", "%3b", "%3c", "%3d", "%3e", "%3f", "%40", "%41", "%42", "%43", "%44", "%45",
            "%46", "%47", "%48", "%49", "%4a", "%4b", "%4c", "%4d", "%4e", "%4f", "%50", "%51", "%52", "%53", "%54",
            "%55", "%56", "%57", "%58", "%59", "%5a", "%5b", "%5c", "%5d", "%5e", "%5f", "%60", "%61", "%62", "%63",
            "%64", "%65", "%66", "%67", "%68", "%69", "%6a", "%6b", "%6c", "%6d", "%6e", "%6f", "%70", "%71", "%72",
            "%73", "%74", "%75", "%76", "%77", "%78", "%79", "%7a", "%7b", "%7c", "%7d", "%7e", "%7f", "%80", "%81",
            "%82", "%83", "%84", "%85", "%86", "%87", "%88", "%89", "%8a", "%8b", "%8c", "%8d", "%8e", "%8f", "%90",
            "%91", "%92", "%93", "%94", "%95", "%96", "%97", "%98", "%99", "%9a", "%9b", "%9c", "%9d", "%9e", "%9f",
            "%a0", "%a1", "%a2", "%a3", "%a4", "%a5", "%a6", "%a7", "%a8", "%a9", "%aa", "%ab", "%ac", "%ad", "%ae",
            "%af", "%b0", "%b1", "%b2", "%b3", "%b4", "%b5", "%b6", "%b7", "%b8", "%b9", "%ba", "%bb", "%bc", "%bd",
            "%be", "%bf", "%c0", "%c1", "%c2", "%c3", "%c4", "%c5", "%c6", "%c7", "%c8", "%c9", "%ca", "%cb", "%cc",
            "%cd", "%ce", "%cf", "%d0", "%d1", "%d2", "%d3", "%d4", "%d5", "%d6", "%d7", "%d8", "%d9", "%da", "%db",
            "%dc", "%dd", "%de", "%df", "%e0", "%e1", "%e2", "%e3", "%e4", "%e5", "%e6", "%e7", "%e8", "%e9", "%ea",
            "%eb", "%ec", "%ed", "%ee", "%ef", "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7", "%f8", "%f9",
            "%fa", "%fb", "%fc", "%fd", "%fe", "%ff" };

    public static String encode(String s) {
        StringBuffer sbuf = new StringBuffer();
        int len = s.length();
        for (int i = 0; i < len; i++) {
            int ch = s.charAt(i);
            if ('A' <= ch && ch <= 'Z') { // 'A'..'Z'
                sbuf.append((char) ch);
            } else if ('a' <= ch && ch <= 'z') { // 'a'..'z'
                sbuf.append((char) ch);
            } else if ('0' <= ch && ch <= '9') { // '0'..'9'
                sbuf.append((char) ch);
            } else if (ch == ' ') { // space
                sbuf.append('+');
            } else if (ch == '-' || ch == '_' // unreserved
                    || ch == '.' || ch == '!' || ch == '~' || ch == '*' || ch == '\'' || ch == '(' || ch == ')') {
                sbuf.append((char) ch);
            } else if (ch <= 0x007f) { // other ASCII
                sbuf.append(hex[ch]);
            } else if (ch <= 0x07FF) { // non-ASCII <= 0x7FF
                sbuf.append(hex[0xc0 | (ch >> 6)]);
                sbuf.append(hex[0x80 | (ch & 0x3F)]);
            } else { // 0x7FF < ch <= 0xFFFF
                sbuf.append(hex[0xe0 | (ch >> 12)]);
                sbuf.append(hex[0x80 | ((ch >> 6) & 0x3F)]);
                sbuf.append(hex[0x80 | (ch & 0x3F)]);
            }
        }
        return sbuf.toString();
    }

}