Java tutorial
/* 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) { } }