From 12c01133e121f618a1d8e6a211908c71d5632115 Mon Sep 17 00:00:00 2001 From: Erik Kiznov <46452865+k1zn@users.noreply.github.com> Date: Fri, 26 Aug 2022 01:13:20 +0500 Subject: [PATCH] msg downloader: update - fix photo attach size - replace mentions to links - add sticker support - add reply support - add forward messages support - add chat actions support --- .../lite/downloaders/MessagesDownloader.java | 222 +++++++++++++++++- 1 file changed, 210 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/ru/vtosters/lite/downloaders/MessagesDownloader.java b/app/src/main/java/ru/vtosters/lite/downloaders/MessagesDownloader.java index 2c96b77f1..c867a9f4e 100644 --- a/app/src/main/java/ru/vtosters/lite/downloaders/MessagesDownloader.java +++ b/app/src/main/java/ru/vtosters/lite/downloaders/MessagesDownloader.java @@ -25,10 +25,13 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Objects; +import java.util.regex.Pattern; public class MessagesDownloader{ private static SimpleDateFormat sdformat; + private static SparseArray usersArray; + public static String formatTime(long now){ return sdformat.format(new Date(now)); } @@ -82,6 +85,8 @@ public class MessagesDownloader{ List msgs = parseMessages(obj.getJSONArray("items")); + usersArray = users; + fl.onReceive(users, msgs); } catch (JSONException e) { e.printStackTrace(); @@ -114,12 +119,12 @@ public class MessagesDownloader{ } static class MiniUser{ + public String firstName; + public String lastName; int id; - String firstName; - String lastName; String photo100; - public MiniUser(JSONObject obj) throws JSONException{ + public MiniUser(JSONObject obj) throws JSONException { id = obj.getInt("id"); firstName = obj.optString("first_name", obj.optString("name")); lastName = obj.optString("last_name", ""); @@ -129,20 +134,32 @@ public class MessagesDownloader{ static class MiniMsg{ long date; - String text; int fromId; + int id; // message id + String text; List attachments; + List fwd_messages; + JSONObject reply_message; // one reply + JSONObject chat_action; public MiniMsg(JSONObject obj) throws JSONException{ date = obj.getLong("date") * 1000; fromId = obj.getInt("from_id"); + id = obj.getInt("id"); text = decryptMessage(obj.getString("text"), obj.getInt("peer_id")); + reply_message = obj.optJSONObject("reply_message"); + chat_action = obj.optJSONObject("action"); attachments = new ArrayList<>(); + fwd_messages = new ArrayList<>(); JSONArray arr = obj.optJSONArray("attachments"); if (arr == null) return; for (int i = 0; i < arr.length(); i++) attachments.add(arr.getJSONObject(i)); + + JSONArray fwdArr = obj.optJSONArray("fwd_messages"); + if (fwdArr == null) return; + for (int i = 0; i < fwdArr.length(); i++) fwd_messages.add(fwdArr.getJSONObject(i)); } } @@ -185,6 +202,9 @@ public class MessagesDownloader{ " margin-top: 8px;\n" + " font-style: italic;\n" + "}\n" + + "p.chat-action {\n" + + " font-style: italic;\n" + + "}\n" + "\n" + ".vtex-milk-header {\n" + " border-radius: 8px;\n" + @@ -224,6 +244,20 @@ public class MessagesDownloader{ ".msg-body {\n" + " padding-top: 4px;\n" + "}\n" + + ".msg-reply {\n" + + " border-left: 3px solid #7aa7f6;\n" + + " margin-top: 5px;\n" + + " padding-left: 3px;\n" + + "}\n\n" + + ".msg-reply p {\n" + + " padding-left: 5px;\n" + + "}\n\n" + + ".msg-reply p.reply-header {\n" + + " color: #5181B8;\n" + + "}\n\n" + + ".msg-reply p.reply-content {\n" + + " color: #000000;\n" + + "}\n" + "\n" + ""; @@ -242,16 +276,174 @@ public class MessagesDownloader{ @Override String provideMessage(MiniMsg message, MiniUser user) throws JSONException{ - String isOut = (user.id == getUserId()) ? "vtex-milk-msg-out" : ""; + String isOut = (user.id == getUserId()) ? " vtex-milk-msg-out" : ""; + String chatAction = (message.chat_action != null) ? getHtmlForChatAction(message.chat_action) : ""; String attaches = (message.attachments.size() > 0) ? "

Вложения: " + getHtmlForAttach(message.attachments) + "

" : ""; + String reply = (message.reply_message != null) ? provideReply(message.reply_message) : ""; + String fwdMessages = (message.fwd_messages.size() > 0) ? provideForwardMessages(message.fwd_messages) : ""; - return "
" + - "

от " + user.firstName + " " + user.lastName + " " + formatTime(message.date) + "

" + // TODO photo100 - "

" + message.text + "

" + - attaches + + return "
" + + "

от " + user.firstName + " " + user.lastName + " " + formatTime(message.date) + "

" + // TODO photo100 + "

" + mentionsReplace(message.text) + "

" + + chatAction + + attaches + + reply + + fwdMessages + "
"; } + private String provideReply(JSONObject replyMessage) throws JSONException { + var messageId = replyMessage.getInt("id"); + var userId = replyMessage.getInt("from_id"); + var text = mentionsReplace(replyMessage.getString("text")); + var fwdMessages = replyMessage.optJSONArray("fwd_messages"); + + var user = usersArray.get(userId); + + if (text.isEmpty()) { + if (fwdMessages != null) { + var length = fwdMessages.length(); + if (length > 0) text = length + " " + pluralMsg(length); + } else text = "Вложение"; + } + + return "" + + "
" + + "

Пересланное сообщение

" + + "

" + user.firstName + " " + user.lastName + ": " + text + "

" + + "
" + + "
"; + } + + private String provideForwardMessages(List fwd_messages) throws JSONException { + StringBuilder fwdmsgs = new StringBuilder("
"); + + for (JSONObject fwd_message : fwd_messages) { + List attaches = new ArrayList<>(); + + JSONArray arr = fwd_message.optJSONArray("attachments"); + if (arr != null) { + for (int i = 0; i < arr.length(); i++) { + try { + attaches.add(arr.getJSONObject(i)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + List fwdsMsg = new ArrayList<>(); + + JSONArray fwd_msgs = fwd_message.optJSONArray("fwd_messages"); + if (fwd_msgs != null) { + for (int i = 0; i < fwd_msgs.length(); i++) { + try { + fwdsMsg.add(fwd_msgs.getJSONObject(i)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + } + + JSONObject reply_message = fwd_message.optJSONObject("reply_message"); + + var attachesHtml = (attaches.size() > 0) ? "Вложения: " + getHtmlForAttach(attaches) : ""; + var replyHtml = (reply_message != null) ? provideReply(reply_message) : ""; + var fwdsHtml = (fwdsMsg.size() > 0) ? provideForwardMessages(fwdsMsg) : ""; // recursion XD :> + + var userId = fwd_message.getInt("from_id"); + var text = mentionsReplace(fwd_message.getString("text")); + + var userLink = ((userId < 0) ? "club" : "id") + Math.abs(userId); + + fwdmsgs.append("

@").append(userLink).append(": ").append(text).append(attachesHtml).append(replyHtml).append(fwdsHtml); + } + + return fwdmsgs.append("

").toString(); + } + + private String mentionsReplace(String text) { + var matcher = Pattern.compile("\\[((?:club|id|public)\\d+)\\|([^]]+)\\]").matcher(text); + + return matcher.replaceAll("$2"); + } + + private String pluralMsg(int count) { + String[] plurals = {"сообщение", "сообщения", "сообщений"}; + + var hundredModulo = count % 100; + var tenModulo = count % 10; + + if (hundredModulo > 10 && hundredModulo < 20) return plurals[2]; + else if (tenModulo > 1 && tenModulo < 5) return plurals[1]; + else if (tenModulo == 1) return plurals[0]; + + return plurals[2]; + } + + private String getHtmlForChatAction(JSONObject action) { + var type = action.optString("type"); + + StringBuilder htmlAction = new StringBuilder("

"); + + switch(type) { + case "chat_photo_update": + htmlAction.append("Обновил фотографию беседы"); + break; + case "chat_photo_remove": + htmlAction.append("Удалил фотографию беседы"); + break; + case "chat_create": + var name = action.optString("text"); + htmlAction.append("Создал беседу").append((!name.isEmpty()) ? " с названием \"" + name + "\"" : ""); + break; + case "chat_title_update": + var newName = action.optString("text"); + htmlAction.append("Сменил название беседы").append((!newName.isEmpty()) ? " на \"" + newName : "\""); + break; + case "chat_invite_user": + var newUserId = action.optInt("member_id"); + htmlAction.append("Добавил " + ((newUserId > 0) ? "пользователя" : "группу")); + if (newUserId != 0) { + var userLink = ((newUserId < 0) ? "club" : "id") + Math.abs(newUserId); + htmlAction.append(" @").append(userLink).append(""); + } + break; + case "chat_kick_user": + var removedUserId = action.optInt("member_id"); + htmlAction.append("Исключил " + ((removedUserId > 0) ? "пользователя" : "группу")); + if (removedUserId != 0) { + var userLink = ((removedUserId < 0) ? "club" : "id") + Math.abs(removedUserId); + htmlAction.append(" @").append(userLink).append(""); + } + break; + case "chat_pin_message": + var message = action.optString("message"); + htmlAction.append("Закрепил сообщение").append((!message.isEmpty()) ? (" с текстом: \"" + message + "\"") : ""); + break; + case "chat_unpin_message": + htmlAction.append("Открепил сообщение"); + break; + case "chat_invite_user_by_link": + htmlAction.append("Вступил в беседу по ссылке"); + break; + default: + htmlAction.append("Действие не поддерживается (").append(type).append(")"); + break; + } + + return htmlAction.append("

").toString(); + } + + /* + TODO: + 1) poll (опросы) + 2) audio (аудио) + 3) audio_message (голосовое сообщение) + 4) "geo" в объекте сообщения (геометка) + 5) video (видео) + */ + private String getHtmlForAttach(List attaches) throws JSONException{ StringBuilder rs = new StringBuilder(); @@ -259,9 +451,12 @@ public class MessagesDownloader{ String type = attach.getString("type"); JSONObject item = attach.optJSONObject(type); + if (item == null) continue; + switch(type) { case "photo": - rs.append("фотография"); + var sizes = item.getJSONArray("sizes"); + rs.append("фотография"); break; case "doc": rs.append("документ"); @@ -270,10 +465,13 @@ public class MessagesDownloader{ rs.append("ссылка"); break; case "wall": - rs.append("запись на стене"); + rs.append("запись на стене"); + break; + case "sticker": + rs.append(""); break; default: - rs.append("unsupported (").append(type).append(")"); + rs.append("Вложение не поддерживается (").append(type).append(")"); break; }