net.issarlk.androbunny.inkbunny.API.java Source code

Java tutorial

Introduction

Here is the source code for net.issarlk.androbunny.inkbunny.API.java

Source

/*
Copyright 2011 Gilbert Roulot.
    
This file is part of Androbunny.
    
Androbunny 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 3 of the License, or
(at your option) any later version.
    
Androbunny 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 Androbunny.  If not, see <http://www.gnu.org/licenses/>.
       
*/
package net.issarlk.androbunny.inkbunny;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.issarlk.androbunny.AndrobunnyAppSingleton;
import net.issarlk.androbunny.utils.SimpleObservable;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import android.os.Parcel;
import android.util.Log;

/**
 * @author g-roulot
 *
 */

public class API {
    /**
     * 
     */
    private static final long serialVersionUID = -5706275778291461485L;
    private static String TAG = "InkbunnyAPI";
    public final SimpleObservable<String> sid = new SimpleObservable<String>(null);
    public String ratingsmask;
    public final static int RATING_GENERAL = 1;
    public final static int RATING_MATURE = 2;
    public final static int RATING_ADULT = 4;
    public final static int SEARCH_KEYWORDS = 1;
    public final static int SEARCH_TITLES = 2;
    public final static int SEARCH_DESCRIPTIONS = 4;

    public void login(String username, String password) throws IOException, InkbunnyAPIException {
        JSONObject json = null;
        try {
            //Log in and read SID
            String tmps = AndrobunnyAppSingleton.androbunnyapp.readUri(
                    new URI("https://inkbunny.net/api_login.php?username=" + username + "&password=" + password));
            json = (JSONObject) new JSONTokener(tmps).nextValue();
            this.sid.set(json.getString("sid"));
            this.ratingsmask = json.getString("ratingsmask");
        } catch (JSONException e) {
            if (json != null && json.has("error_code")) {
                throw InkbunnyAPIException.from(json);
            } else {
                throw (new InkbunnyAPIException(e));
            }
        } catch (URISyntaxException e) {
            throw (new InkbunnyAPIException(e));
        } catch (ClientProtocolException e) {
            throw (new InkbunnyAPIException(e));
        }
    }

    public void logout() {
        this.sid.set(null);
        this.ratingsmask = null;
    }

    public Search getLatest() throws InkbunnyAPIException {
        Search result = new Search(this.sid, "");
        result.description = "Recent submissions";
        return result;
    }

    public Search getPopular() throws InkbunnyAPIException {
        Search result = new Search(this.sid,
                "dayslimit=3&orderby=views&count_limit=100&submissions_per_page=100&random=yes&scraps=no",
                Search.NO_PAGES);
        result.description = "Recent popular submissions";
        return result;
    }

    public Search getLatestWritings() throws InkbunnyAPIException {
        Search result = new Search(this.sid, "type=12");
        result.description = "Recent written submissions";
        return result;
    }

    public Search getLatestMusics() throws InkbunnyAPIException {
        Search result = new Search(this.sid, "type=10,11");
        result.description = "Recent musics";
        return result;
    }

    public Search getNew() throws InkbunnyAPIException {
        Search result = new Search(this.sid, "unread_submissions=yes");
        result.description = "New submissions";
        return result;
    }

    public Search getUserGallery(User argUser) throws InkbunnyAPIException {
        Search result = new Search(this.sid, "user_id=" + argUser.id + "&scraps=no");
        result.description = argUser.name + "'s gallery";
        return result;
    }

    public Search getUserScraps(User argUser) throws InkbunnyAPIException {
        Search result = new Search(this.sid, "user_id=" + argUser.id + "&scraps=only");
        result.description = argUser.name + "'s scraps";
        return result;
    }

    public Search getUserFavorites(User argUser) throws InkbunnyAPIException {
        Search result = new Search(this.sid, "favs_user_id=" + argUser.id);
        result.description = argUser.name + "'s favorites";
        return result;
    }

    public Search getPool(int id) throws InkbunnyAPIException {
        Search result = new Search(this.sid, "pool_id=" + id + "&orderby=pool_order");
        result.description = "Pool";
        return result;
    }

    public Search searchText(String text, int fields, int dayslimit) throws InkbunnyAPIException {
        Search result;
        try {
            result = new Search(this.sid,
                    "text=" + URLEncoder.encode(text, "UTF-8") + "&keywords="
                            + (((fields & SEARCH_KEYWORDS) != 0) ? "yes" : "no") + "&title="
                            + (((fields & SEARCH_TITLES) != 0) ? "yes" : "no") + "&description="
                            + (((fields & SEARCH_DESCRIPTIONS) != 0) ? "yes" : "no")
                            + ((dayslimit > 0) ? "&dayslimit=" + dayslimit : ""));
            result.description = "Search results for " + text;
            return result;
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, e.toString());
            return null;
        }
    }

    public static String extractTree(Pattern pattern, String data) {
        Matcher matches = pattern.matcher(data);
        if (matches.matches()) {
            data = matches.group(1);
            StringBuilder result = new StringBuilder();
            //Extract
            int taglevel = 0;

            CharacterIterator it = new StringCharacterIterator(data);
            int mode = 0;
            int inparamname = 0;
            int inparamvalue = 0;
            int outsidetags = 0;
            int intagname = 0;
            char paramvaluechar = '"';
            HashMap<String, String> params = new HashMap<String, String>();
            StringBuilder tagname = new StringBuilder();
            StringBuilder paramname = new StringBuilder();
            StringBuilder paramvalue = new StringBuilder();
            StringBuilder text = new StringBuilder();
            for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {

                if (c == '<') {
                    //start of tag
                    c = it.next();
                    params.clear();
                    outsidetags = 0;
                    //Output text
                    //Log.d(TAG, repeat(' ', taglevel) + text.toString());
                    result.append(text);
                    if (c == '/') {
                        //Start of closing tag
                        mode = 3;
                        intagname = 1;
                        c = it.next();
                    } else {
                        //Start of openning tag
                        mode = 2;
                        intagname = 1;
                    }
                    tagname = new StringBuilder();
                }
                if (intagname == 1) {
                    if (c < 'a' || c > 'z') {
                        intagname = 0;
                    } else {
                        tagname.append(c);
                    }
                }
                if ((mode == 2 || mode == 3) && intagname == 0 && inparamname == 0 && inparamvalue == 0 && c >= 'a'
                        && c <= 'z') {
                    inparamname = 1;
                    paramname = new StringBuilder();
                }
                if (inparamname == 1) {
                    if (c == '=') {
                        inparamname = 0;
                        inparamvalue = 1;
                        paramvaluechar = it.next();
                        paramvalue = new StringBuilder();
                        continue;
                    } else if (c != ' ') {
                        paramname.append(c);
                    }
                }
                if (inparamvalue == 1) {
                    if (c == paramvaluechar) {
                        //End of value
                        inparamvalue = 0;
                        params.put(paramname.toString(), paramvalue.toString());
                    } else {
                        paramvalue.append(c);
                    }
                }
                if (mode == 2 && inparamvalue == 0 && c == '/') {
                    c = it.next();
                    if (c == '>') {
                        //tag closed at its end
                        mode = 4;
                        if (tagname.toString().equals("br")) {
                            result.append("<br/>");
                        }
                    } else {
                        c = it.previous();
                    }
                }
                if (c == '>') {
                    if (mode == 2) {
                        //openning
                        taglevel += 1;
                        outsidetags = 1;
                        text = new StringBuilder();
                        String paramstr = "";
                        for (String key : params.keySet()) {
                            paramstr += " " + key + "=\"" + params.get(key) + "\"";
                        }
                        //Log.d(TAG, repeat(' ', taglevel - 1) + "<" + tagname.toString() + paramstr + ">");
                        result.append("<" + tagname.toString() + paramstr + ">");
                        mode = 0;
                        continue;
                    } else if (mode == 3) {
                        //Closing
                        taglevel -= 1;
                        outsidetags = 1;
                        text = new StringBuilder();
                        //Log.d(TAG, repeat(' ', taglevel) + "</" + tagname.toString() + ">");
                        result.append("</" + tagname.toString() + ">\n");
                        mode = 0;
                        if (taglevel <= 0) {
                            break;
                        }
                        continue;
                    } else if (mode == 4) {
                        //closed at end
                        outsidetags = 1;
                        text = new StringBuilder();
                        //Log.d(TAG, repeat(' ', taglevel) + "<" + tagname.toString() + "/>");
                        result.append("<" + tagname.toString() + "/>\n");
                        mode = 0;
                        continue;
                    }
                }
                if (outsidetags == 1) {
                    //Append char
                    text.append(c);
                }
            }

            String res = result.toString();
            return res;
        }
        return null;
    }

    public void scrapeUserPage(User argUser) throws IOException {
        argUser.profile = "Couldn't read user profile";
        String data = "";
        try {
            data = AndrobunnyAppSingleton.androbunnyapp.readUri(new URI("https://inkbunny.net/" + argUser.name));
        } catch (URISyntaxException e2) {
            Log.e(TAG, e2.toString());
        }
        // Extract profile
        Pattern pattern = Pattern.compile(".*<div class='title'>Profile</div>.*?(<.*)",
                Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        argUser.profile = extractTree(pattern, data);
        // Extract user icon
        pattern = Pattern.compile(
                "<img [^>]*? src='([^']*)' [^>]*? alt='" + argUser.name + "' title='" + argUser.name + "'[^>]*?/>",
                Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher matcher = pattern.matcher(data);
        if (matcher.find()) {
            //Found the user icon
            try {
                argUser.icons[0] = new Icon(Icon.LARGE, new URI(matcher.group(1)));
            } catch (URISyntaxException e) {
                Log.e(TAG, e.toString());
            }
        }
    }

    public static String repeat(char c, int i) {
        StringBuilder tst = new StringBuilder();
        for (int j = 0; j < i; j++) {
            tst.append(c);
        }
        return tst.toString();
    }

    public User getUserFromName(String username) {
        String tmps = "";
        try {
            //Use the user autocomplete API to retrieve user
            tmps = AndrobunnyAppSingleton.androbunnyapp
                    .readUri(new URI("https://inkbunny.net/api_username_autosuggest.php?username="
                            + URLEncoder.encode(username, "UTF-8")));
        } catch (ClientProtocolException e) {
            Log.e(TAG, e.toString());
            return null;
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, e.toString());
            return null;
        } catch (IOException e) {
            Log.e(TAG, e.toString());
            return null;
        } catch (URISyntaxException e) {
            Log.e(TAG, e.toString());
            return null;
        }
        try {
            JSONObject json_response;
            json_response = (JSONObject) new JSONTokener(tmps).nextValue();
            JSONArray suggestions = json_response.getJSONArray("results");
            //Use first suggestion
            JSONObject suggestion = suggestions.getJSONObject(0);
            return new User(suggestion.getInt("id"), suggestion.getString("singleword"));
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            return null;
        }
    }

    public Submission getSubmissionByID(int id) throws IOException {
        try {
            //Load submission details         
            String tmps = AndrobunnyAppSingleton.androbunnyapp
                    .readUri(new URI("https://inkbunny.net/api_submissions.php?sid=" + this.sid.get()
                            + "&show_description_bbcode_parsed=yes&show_writing_bbcode_parsed=yes&submission_ids="
                            + id));
            JSONObject json = (JSONObject) new JSONTokener(tmps).nextValue();
            JSONArray submissions = json.getJSONArray("submissions");
            //There should only be one submission in the array, the one we are looking for
            json = submissions.getJSONObject(0);
            return new Submission(json);
        } catch (ClientProtocolException e) {
            Log.e(TAG, "Exception: " + e.toString());
            return null;
        } catch (URISyntaxException e) {
            Log.e(TAG, "Exception: " + e.toString());
            return null;
        } catch (JSONException e) {
            Log.e(TAG, "Exception: " + e.toString());
            return null;
        }
    }

    public Submission getHeavySubmission(Submission light_submission) throws IOException {
        return this.getSubmissionByID(light_submission.id);
    }

    public static int getBool(JSONObject json, String field) throws JSONException {
        String tmp = json.getString(field);
        if (tmp.equals("f")) {
            return 0;
        } else {
            return 1;
        }
    }

    public boolean isLoggedIn() throws InkbunnyAPIException {
        //return true if there is a still valid sid
        if (this.sid.get() == null) {
            return false;
        }
        try {
            //Perform a simple search         
            String tmps = AndrobunnyAppSingleton.androbunnyapp
                    .readUri(new URI("https://inkbunny.net/api_search.php?sid=" + this.sid.get()
                            + "&dayslimit=1&count_limit=1&no_submissions=yes"));
            JSONObject json_response = (JSONObject) new JSONTokener(tmps).nextValue();
            json_response.get("sid");
            return true;
        } catch (ClientProtocolException e) {
            throw new InkbunnyAPIException(e);
        } catch (URISyntaxException e) {
            throw new InkbunnyAPIException(e);
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            return false;
        } catch (IOException e) {
            throw new InkbunnyAPIException(e);
        }
    }

    public String[] getKeywords(String text) {
        //Search keywords starting with text
        String tmps;
        try {
            tmps = AndrobunnyAppSingleton.androbunnyapp
                    .readUri(new URI("https://inkbunny.net/api_search_autosuggest.php?ratingsmask="
                            + this.ratingsmask + "&keyword=" + URLEncoder.encode(text, "UTF-8")));
        } catch (ClientProtocolException e) {
            Log.e(TAG, e.toString());
            return null;
        } catch (UnsupportedEncodingException e) {
            Log.e(TAG, e.toString());
            return null;
        } catch (IOException e) {
            Log.e(TAG, e.toString());
            return null;
        } catch (URISyntaxException e) {
            Log.e(TAG, e.toString());
            return null;
        }
        try {
            JSONObject json_response;
            json_response = (JSONObject) new JSONTokener(tmps).nextValue();
            JSONArray suggestions = json_response.getJSONArray("results");
            int l = suggestions.length();
            String[] result = new String[l];
            for (int i = 0; i < l; i++) {
                JSONObject suggestion;
                suggestion = suggestions.getJSONObject(i);
                result[i] = suggestion.getString("singleword");
            }
            return result;
        } catch (JSONException e) {
            Log.e(TAG, e.toString());
            return null;
        }
    }

    public int describeContents() {
        return 0;
    }

    public void writeToParcel(Parcel arg0, int arg1) {

    }
}