package app.fedilab.android.client; import android.content.Context; import android.content.SharedPreferences; import android.database.sqlite.SQLiteDatabase; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Objects; import app.fedilab.android.R; import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Error; import app.fedilab.android.client.Entities.PixelFedStory; import app.fedilab.android.client.Entities.PixelFedStoryItem; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.helper.Helper; import app.fedilab.android.sqlite.AccountDAO; import app.fedilab.android.sqlite.Sqlite; @SuppressWarnings("unused") public class PixelfedAPI { private final Context context; private List pixelFedStories; private String instance; private String prefKeyOauthTokenT; private APIResponse apiResponse; private Error APIError; private int actionCode; public PixelfedAPI(Context context) { this.context = context; if (context == null) { APIError = new Error(); return; } SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); this.prefKeyOauthTokenT = sharedpreferences.getString(Helper.PREF_KEY_OAUTH_TOKEN, null); if (Helper.getLiveInstance(context) != null) this.instance = Helper.getLiveInstance(context); else { SQLiteDatabase db = Sqlite.getInstance(context.getApplicationContext(), Sqlite.DB_NAME, null, Sqlite.DB_VERSION).open(); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); String instance = sharedpreferences.getString(Helper.PREF_INSTANCE, Helper.getLiveInstance(context)); Account account = new AccountDAO(context, db).getUniqAccount(userId, instance); if (account == null) { APIError = new Error(); APIError.setError(context.getString(R.string.toast_error)); return; } this.instance = account.getInstance().trim(); } apiResponse = new APIResponse(); APIError = null; } /** * Parse json response for several stories * * @param jsonArray JSONArray * @return List */ private static List parseStories(JSONArray jsonArray) { List pixelFedStories = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); PixelFedStory pixelFedStory = parseStory(resobj); i++; pixelFedStories.add(pixelFedStory); } } catch (JSONException e) { e.printStackTrace(); } return pixelFedStories; } /** * Parse a single item for stories * * @param jsonObject JSONObject * @return PixelFedStoryItem */ private static PixelFedStory parseStory(JSONObject jsonObject) { PixelFedStory pixelFedStory = new PixelFedStory(); try { pixelFedStory.setId(jsonObject.getString("id")); pixelFedStory.setPhoto(jsonObject.getString("photo")); pixelFedStory.setName(jsonObject.getString("name")); pixelFedStory.setLink(jsonObject.getString("link")); pixelFedStory.setLastUpdated(new Date(jsonObject.getLong("lastUpdated"))); if (jsonObject.has("seen") && !jsonObject.isNull("seen")) { pixelFedStory.setSeen(jsonObject.getBoolean("seen")); } else { pixelFedStory.setSeen(false); } pixelFedStory.setPixelFedStoryItems(parseStoryItems(jsonObject.getJSONArray("items"))); } catch (JSONException ignored) { ignored.printStackTrace(); } return pixelFedStory; } /** * Parse json response for several items for stories * * @param jsonArray JSONArray * @return List */ private static List parseStoryItems(JSONArray jsonArray) { List pixelFedStoryItems = new ArrayList<>(); try { int i = 0; while (i < jsonArray.length()) { JSONObject resobj = jsonArray.getJSONObject(i); PixelFedStoryItem pixelFedStoryItem = parseStoryItem(resobj); i++; pixelFedStoryItems.add(pixelFedStoryItem); } } catch (JSONException e) { e.printStackTrace(); } return pixelFedStoryItems; } /** * Parse a single item for stories * * @param jsonObject JSONObject * @return PixelFedStoryItem */ private static PixelFedStoryItem parseStoryItem(JSONObject jsonObject) { PixelFedStoryItem pixelFedStoryItem = new PixelFedStoryItem(); try { pixelFedStoryItem.setId(jsonObject.getString("id")); pixelFedStoryItem.setType(jsonObject.getString("type")); pixelFedStoryItem.setLength(jsonObject.getInt("length")); pixelFedStoryItem.setSrc(jsonObject.getString("src")); pixelFedStoryItem.setPreview(jsonObject.getString("preview")); pixelFedStoryItem.setLink(jsonObject.getString("link")); pixelFedStoryItem.setLinkText(jsonObject.getString("linkText")); pixelFedStoryItem.setTime(new Date(jsonObject.getLong("time"))); pixelFedStoryItem.setExpires_at(new Date(jsonObject.getLong("expires_at"))); pixelFedStoryItem.setSeen(jsonObject.getBoolean("seen")); } catch (JSONException ignored) { ignored.printStackTrace(); } return pixelFedStoryItem; } /** * Retrieves Pixelfed Own Stories *synchronously* * * @return APIResponse */ /* public APIResponse getMyStories() { pixelFedStories = new ArrayList<>(); PixelFedStory pixelFedStory; try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/me"), 10, null, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); pixelFedStory = parseStory(new JSONObject(response)); pixelFedStories.add(pixelFedStory); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } if (apiResponse == null) apiResponse = new APIResponse(); apiResponse.setPixelFedStories(pixelFedStories); return apiResponse; }*/ /** * Retrieves Pixelfed Own Stories *synchronously* * * @return APIResponse */ public JSONObject getPostDetails(String username, String targertedId) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(Helper.getLiveInstanceWithProtocol(context) + String.format("/api/v2/profile/%s/status/%s/state", username, targertedId), 10, null, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); return new JSONObject(response).getJSONObject("reactions"); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } return null; } /** * Retrieves Pixelfed Own Stories *synchronously* * * @return APIResponse */ public APIResponse getFriendStories(String userId, String max_id) { pixelFedStories = new ArrayList<>(); HashMap params = new HashMap<>(); if (max_id != null) params.put("max_id", max_id); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl("/profile/" + userId), 10, params, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); pixelFedStories = parseStories(new JSONArray(response)); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } if (apiResponse == null) apiResponse = new APIResponse(); apiResponse.setPixelFedStories(pixelFedStories); return apiResponse; } /** * Delete a media in story * * @param id String id of the object */ public void deleteStory(String id) { try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); httpsConnection.delete(getAbsoluteUrl("/delete/" + id), 30, null, prefKeyOauthTokenT); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException e) { e.printStackTrace(); } } /** * Posts a story * * @param status Status object related to the status * @return APIResponse */ public APIResponse postStory(Status status) { JsonObject jsonObject = new JsonObject(); if (status.getMedia_attachments() != null && status.getMedia_attachments().size() > 0) { JsonArray mediaArray = new JsonArray(); for (Attachment attachment : status.getMedia_attachments()) mediaArray.add(attachment.getId()); jsonObject.add("media_ids", mediaArray); } ArrayList statuses = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.postJson(getAbsoluteUrl("/add"), 30, jsonObject, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); PixelFedStory statusreturned = parseStory(new JSONObject(response)); statuses.add(statusreturned); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); e.printStackTrace(); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } apiResponse.setPixelFedStories(statuses); return apiResponse; } /** * Retrieves an item from its ID * * @return APIResponse */ public APIResponse getStoryItem(String id) { List pixelFedStoryItems = new ArrayList<>(); try { HttpsConnection httpsConnection = new HttpsConnection(context, this.instance); String response = httpsConnection.get(getAbsoluteUrl(String.format("/item/%s", id)), 10, null, prefKeyOauthTokenT); apiResponse.setSince_id(httpsConnection.getSince_id()); apiResponse.setMax_id(httpsConnection.getMax_id()); PixelFedStoryItem pixelFedStoryItem = parseStoryItem(new JSONObject(response)); pixelFedStoryItems.add(pixelFedStoryItem); } catch (HttpsConnection.HttpsConnectionException e) { setError(e.getStatusCode(), e); } catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) { e.printStackTrace(); } if (apiResponse == null) apiResponse = new APIResponse(); apiResponse.setPixelFedStoryItems(pixelFedStoryItems); return apiResponse; } /** * Set the error message * * @param statusCode int code * @param error Throwable error */ public void setError(int statusCode, Throwable error) { APIError = new Error(); APIError.setStatusCode(statusCode); String message = statusCode + " - " + error.getMessage(); try { JSONObject jsonObject = new JSONObject(Objects.requireNonNull(error.getMessage())); String errorM = jsonObject.get("error").toString(); message = "Error " + statusCode + " : " + errorM; } catch (JSONException e) { if (error.getMessage().split(".").length > 0) { String errorM = error.getMessage().split(".")[0]; message = "Error " + statusCode + " : " + errorM; } } APIError.setError(message); apiResponse.setError(APIError); } private void setDefaultError(Exception e) { APIError = new Error(); if (apiResponse == null) { apiResponse = new APIResponse(); } if (e.getLocalizedMessage() != null && e.getLocalizedMessage().trim().length() > 0) APIError.setError(e.getLocalizedMessage()); else if (e.getMessage() != null && e.getMessage().trim().length() > 0) APIError.setError(e.getMessage()); else APIError.setError(context.getString(R.string.toast_error)); apiResponse.setError(APIError); } public Error getError() { return APIError; } private String getAbsoluteUrl(String action) { return Helper.instanceWithProtocol(this.context, this.instance) + "/api/stories/v0" + action; } }