package ml.docilealligator.infinityforreddit.message; import android.os.AsyncTask; import androidx.annotation.Nullable; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Locale; import ml.docilealligator.infinityforreddit.utils.JSONUtils; import ml.docilealligator.infinityforreddit.utils.Utils; public class ParseMessage { public static void parseMessage(String response, Locale locale, int messageType, ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) { new ParseMessageAsnycTask(response, locale, messageType, parseMessageAsnycTaskListener).execute(); } public static ArrayList parseMessages(JSONArray messageArray, Locale locale, int messageType) { ArrayList messages = new ArrayList<>(); for (int i = 0; i < messageArray.length(); i++) { try { Message message = parseSingleMessage(messageArray.getJSONObject(i), locale, messageType); if (message != null) { messages.add(message); } } catch (JSONException e) { e.printStackTrace(); } } return messages; } public static void parseRepliedMessage(String response, Locale locale, ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener) { new ParseSentMessageAsnycTask(response, locale, parseSentMessageAsyncTaskListener).execute(); } public static void parseComposedMessageError(String response, ParseComposedMessageErrorListener parseComposedMessageErrorListener) { new ParseComposedMessageErrorAsncTask(response, parseComposedMessageErrorListener).execute(); } @Nullable private static Message parseSingleMessage(JSONObject messageJSON, Locale locale, int messageType) throws JSONException { String kind = messageJSON.getString(JSONUtils.KIND_KEY); if ((messageType == FetchMessage.MESSAGE_TYPE_INBOX && kind.equals("t4")) || (messageType == FetchMessage.MESSAGE_TYPE_PRIVATE_MESSAGE && !kind.equals("t4"))) { return null; } JSONObject rawMessageJSON = messageJSON.getJSONObject(JSONUtils.DATA_KEY); String subredditName = rawMessageJSON.getString(JSONUtils.SUBREDDIT_KEY); String subredditNamePrefixed = rawMessageJSON.getString(JSONUtils.SUBREDDIT_NAME_PREFIX_KEY); String id = rawMessageJSON.getString(JSONUtils.ID_KEY); String fullname = rawMessageJSON.getString(JSONUtils.NAME_KEY); String subject = rawMessageJSON.getString(JSONUtils.SUBJECT_KEY); String author = rawMessageJSON.getString(JSONUtils.AUTHOR_KEY); String destination = rawMessageJSON.getString(JSONUtils.DEST_KEY); String parentFullname = rawMessageJSON.getString(JSONUtils.PARENT_ID_KEY); String title = rawMessageJSON.has(JSONUtils.LINK_TITLE_KEY) ? rawMessageJSON.getString(JSONUtils.LINK_TITLE_KEY) : null; String body = Utils.modifyMarkdown(rawMessageJSON.getString(JSONUtils.BODY_KEY)); String context = rawMessageJSON.getString(JSONUtils.CONTEXT_KEY); String distinguished = rawMessageJSON.getString(JSONUtils.DISTINGUISHED_KEY); boolean wasComment = rawMessageJSON.getBoolean(JSONUtils.WAS_COMMENT_KEY); boolean isNew = rawMessageJSON.getBoolean(JSONUtils.NEW_KEY); int score = rawMessageJSON.getInt(JSONUtils.SCORE_KEY); int nComments = rawMessageJSON.isNull(JSONUtils.NUM_COMMENTS_KEY) ? -1 : rawMessageJSON.getInt(JSONUtils.NUM_COMMENTS_KEY); long timeUTC = rawMessageJSON.getLong(JSONUtils.CREATED_UTC_KEY) * 1000; Calendar submitTimeCalendar = Calendar.getInstance(); submitTimeCalendar.setTimeInMillis(timeUTC); String formattedTime = new SimpleDateFormat("MMM d, yyyy, HH:mm", locale).format(submitTimeCalendar.getTime()); ArrayList replies = null; if (!rawMessageJSON.isNull(JSONUtils.REPLIES_KEY) && rawMessageJSON.get(JSONUtils.REPLIES_KEY) instanceof JSONObject) { JSONArray repliesArray = rawMessageJSON.getJSONObject(JSONUtils.REPLIES_KEY).getJSONObject(JSONUtils.DATA_KEY) .getJSONArray(JSONUtils.CHILDREN_KEY); replies = parseMessages(repliesArray, locale, messageType); } Message message = new Message(kind, subredditName, subredditNamePrefixed, id, fullname, subject, author, destination, parentFullname, title, body, context, distinguished, formattedTime, wasComment, isNew, score, nComments, timeUTC); if (replies != null) { message.setReplies(replies); } return message; } private static class ParseMessageAsnycTask extends AsyncTask { private final String response; private final Locale locale; private ArrayList messages; private String after; private final int messageType; private final ParseMessageAsyncTaskListener parseMessageAsyncTaskListener; ParseMessageAsnycTask(String response, Locale locale, int messageType, ParseMessageAsyncTaskListener parseMessageAsnycTaskListener) { this.response = response; this.locale = locale; this.messageType = messageType; messages = new ArrayList<>(); this.parseMessageAsyncTaskListener = parseMessageAsnycTaskListener; } @Override protected Void doInBackground(Void... voids) { try { JSONArray messageArray = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.CHILDREN_KEY); messages = parseMessages(messageArray, locale, messageType); after = new JSONObject(response).getJSONObject(JSONUtils.DATA_KEY).getString(JSONUtils.AFTER_KEY); } catch (JSONException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); parseMessageAsyncTaskListener.parseSuccess(messages, after); } } private static class ParseSentMessageAsnycTask extends AsyncTask { private final String response; private final Locale locale; private Message message; private String errorMessage; private boolean parseFailed = false; private final ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener; ParseSentMessageAsnycTask(String response, Locale locale, ParseSentMessageAsyncTaskListener parseSentMessageAsyncTaskListener) { this.response = response; this.locale = locale; this.parseSentMessageAsyncTaskListener = parseSentMessageAsyncTaskListener; } @Override protected Void doInBackground(Void... voids) { try { JSONObject messageJSON = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY) .getJSONObject(JSONUtils.DATA_KEY).getJSONArray(JSONUtils.THINGS_KEY).getJSONObject(0); message = parseSingleMessage(messageJSON, locale, FetchMessage.MESSAGE_TYPE_PRIVATE_MESSAGE); } catch (JSONException e) { e.printStackTrace(); errorMessage = parseRepliedMessageErrorMessage(response); parseFailed = true; } return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (parseFailed) { parseSentMessageAsyncTaskListener.parseFailed(errorMessage); } else { parseSentMessageAsyncTaskListener.parseSuccess(message); } } } private static class ParseComposedMessageErrorAsncTask extends AsyncTask { private final String response; private final ParseComposedMessageErrorListener parseComposedMessageErrorListener; private String errorMessage; ParseComposedMessageErrorAsncTask(String response, ParseComposedMessageErrorListener parseComposedMessageErrorListener) { this.response = response; this.parseComposedMessageErrorListener = parseComposedMessageErrorListener; } @Override protected Void doInBackground(Void... voids) { errorMessage = parseRepliedMessageErrorMessage(response); return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (errorMessage == null) { parseComposedMessageErrorListener.noError(); } else { parseComposedMessageErrorListener.error(errorMessage); } } } @Nullable private static String parseRepliedMessageErrorMessage(String response) { try { JSONObject responseObject = new JSONObject(response).getJSONObject(JSONUtils.JSON_KEY); if (responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() != 0) { JSONArray error = responseObject.getJSONArray(JSONUtils.ERRORS_KEY) .getJSONArray(responseObject.getJSONArray(JSONUtils.ERRORS_KEY).length() - 1); if (error.length() != 0) { String errorString; if (error.length() >= 2) { errorString = error.getString(1); } else { errorString = error.getString(0); } return errorString.substring(0, 1).toUpperCase() + errorString.substring(1); } else { return null; } } else { return null; } } catch (JSONException e) { e.printStackTrace(); } return null; } public interface ParseMessageAsyncTaskListener { void parseSuccess(ArrayList messages, @Nullable String after); } public interface ParseSentMessageAsyncTaskListener { void parseSuccess(Message message); void parseFailed(String errorMessage); } public interface ParseComposedMessageErrorListener { void noError(); void error(String errorMessage); } }