Real time
This commit is contained in:
@@ -1627,7 +1627,7 @@ public class ActionHandler {
|
|||||||
|
|
||||||
String input = scanner.nextLine().trim();
|
String input = scanner.nextLine().trim();
|
||||||
switch (input) {
|
switch (input) {
|
||||||
case "1" -> sendMessage(chatId, "private");
|
case "1" -> sendMessageInteractive(chatId, "private");
|
||||||
case "2" -> { viewMessagesInChat(chat); }
|
case "2" -> { viewMessagesInChat(chat); }
|
||||||
case "3" -> { return false; }
|
case "3" -> { return false; }
|
||||||
default -> System.out.println("Invalid choice.");
|
default -> System.out.println("Invalid choice.");
|
||||||
@@ -3543,69 +3543,69 @@ public class ActionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void sendMessage(UUID receiverId, String receiverType) {
|
// public void sendMessage(UUID receiverId, String receiverType) {
|
||||||
Scanner scanner = new Scanner(System.in);
|
// Scanner scanner = new Scanner(System.in);
|
||||||
|
//
|
||||||
System.out.print("Enter your message: ");
|
// System.out.print("Enter your message: ");
|
||||||
String content = scanner.nextLine();
|
// String content = scanner.nextLine();
|
||||||
|
//
|
||||||
System.out.print("Enter message type (TEXT / IMAGE / VIDEO / FILE): ");
|
// System.out.print("Enter message type (TEXT / IMAGE / VIDEO / FILE): ");
|
||||||
String messageType = scanner.nextLine();
|
// String messageType = scanner.nextLine();
|
||||||
Set<String> allowedTypes = Set.of("TEXT", "IMAGE", "VIDEO", "FILE");
|
// Set<String> allowedTypes = Set.of("TEXT", "IMAGE", "VIDEO", "FILE");
|
||||||
while (!allowedTypes.contains(messageType.toUpperCase())) {
|
// while (!allowedTypes.contains(messageType.toUpperCase())) {
|
||||||
System.out.println("❌ Invalid message type. Try again (TEXT / IMAGE / VIDEO / FILE): ");
|
// System.out.println("❌ Invalid message type. Try again (TEXT / IMAGE / VIDEO / FILE): ");
|
||||||
messageType = scanner.nextLine();
|
// messageType = scanner.nextLine();
|
||||||
}
|
// }
|
||||||
messageType = messageType.toUpperCase();
|
// messageType = messageType.toUpperCase();
|
||||||
|
//
|
||||||
JSONArray attachmentsArray = new JSONArray();
|
// JSONArray attachmentsArray = new JSONArray();
|
||||||
|
//
|
||||||
System.out.print("Do you want to attach files? (yes/no): ");
|
// System.out.print("Do you want to attach files? (yes/no): ");
|
||||||
if (scanner.nextLine().equalsIgnoreCase("yes")) {
|
// if (scanner.nextLine().equalsIgnoreCase("yes")) {
|
||||||
while (true) {
|
// while (true) {
|
||||||
System.out.print("File URL: ");
|
// System.out.print("File URL: ");
|
||||||
String fileUrl = scanner.nextLine();
|
// String fileUrl = scanner.nextLine();
|
||||||
|
//
|
||||||
System.out.print("File Type (IMAGE / VIDEO / FILE): ");
|
// System.out.print("File Type (IMAGE / VIDEO / FILE): ");
|
||||||
String fileType = scanner.nextLine();
|
// String fileType = scanner.nextLine();
|
||||||
|
//
|
||||||
JSONObject fileJson = new JSONObject();
|
// JSONObject fileJson = new JSONObject();
|
||||||
fileJson.put("file_url", fileUrl);
|
// fileJson.put("file_url", fileUrl);
|
||||||
fileJson.put("file_type", fileType);
|
// fileJson.put("file_type", fileType);
|
||||||
attachmentsArray.put(fileJson);
|
// attachmentsArray.put(fileJson);
|
||||||
|
//
|
||||||
System.out.print("Add another file? (yes/no): ");
|
// System.out.print("Add another file? (yes/no): ");
|
||||||
if (!scanner.nextLine().equalsIgnoreCase("yes")) {
|
// if (!scanner.nextLine().equalsIgnoreCase("yes")) {
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
JSONObject messageJson = new JSONObject();
|
// JSONObject messageJson = new JSONObject();
|
||||||
messageJson.put("action", "send_message");
|
// messageJson.put("action", "send_message");
|
||||||
messageJson.put("receiver_type", receiverType);
|
// messageJson.put("receiver_type", receiverType);
|
||||||
messageJson.put("content", content);
|
// messageJson.put("content", content);
|
||||||
messageJson.put("message_type", messageType);
|
// messageJson.put("message_type", messageType);
|
||||||
if (receiverType.equals("private")) {
|
// if (receiverType.equals("private")) {
|
||||||
messageJson.put("receiver_user_id", receiverId.toString());
|
// messageJson.put("receiver_user_id", receiverId.toString());
|
||||||
} else {
|
// } else {
|
||||||
messageJson.put("receiver_id", receiverId.toString());
|
// messageJson.put("receiver_id", receiverId.toString());
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (!attachmentsArray.isEmpty()) {
|
// if (!attachmentsArray.isEmpty()) {
|
||||||
messageJson.put("attachments", attachmentsArray);
|
// messageJson.put("attachments", attachmentsArray);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
JSONObject response = sendWithResponse(messageJson);
|
// JSONObject response = sendWithResponse(messageJson);
|
||||||
if (response != null && response.getString("status").equals("success")) {
|
// if (response != null && response.getString("status").equals("success")) {
|
||||||
System.out.println("✅ Message sent successfully! ID: " + response.getJSONObject("data").getString("message_id"));
|
// System.out.println("✅ Message sent successfully! ID: " + response.getJSONObject("data").getString("message_id"));
|
||||||
} else {
|
// } else {
|
||||||
System.out.println("❌ Failed to send message: " + (response != null ? response.getString("message") : "no response"));
|
// System.out.println("❌ Failed to send message: " + (response != null ? response.getString("message") : "no response"));
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3895,7 +3895,7 @@ public class ActionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(input.equalsIgnoreCase("S")){
|
if(input.equalsIgnoreCase("S")){
|
||||||
sendMessage(chat.getId(), chat.getType());
|
sendMessageInteractive(chat.getId(), chat.getType());
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
int index = Integer.parseInt(input);
|
int index = Integer.parseInt(input);
|
||||||
|
|||||||
@@ -5,6 +5,9 @@ import org.to.telegramfinalproject.Models.ChatEntry;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
@@ -117,7 +120,7 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
"removed_from_group", "removed_from_channel",
|
"removed_from_group", "removed_from_channel",
|
||||||
"became_admin", "removed_admin", "ownership_transferred",
|
"became_admin", "removed_admin", "ownership_transferred",
|
||||||
"admin_permissions_updated", "created_private_chat",
|
"admin_permissions_updated", "created_private_chat",
|
||||||
"message_reacted", "message_unreacted" -> true;
|
"message_reacted", "message_unreacted" , "chat_updated"-> true;
|
||||||
default -> false;
|
default -> false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -170,58 +173,125 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
System.out.print(">> ");
|
System.out.print(">> ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private void updateLastMessageTime(JSONObject msg) {
|
||||||
|
// try {
|
||||||
|
// UUID chatUUID = UUID.fromString(msg.getString("chat_id"));
|
||||||
|
// String newTime = msg.optString("last_message_time", null);
|
||||||
|
//
|
||||||
|
// Session.chatList.stream().filter(chat -> chat.getId().equals(chatUUID)).findFirst()
|
||||||
|
// .ifPresent(chat -> {
|
||||||
|
// chat.setLastMessageTime(newTime);
|
||||||
|
// System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Session.activeChats.stream().filter(chat -> chat.getId().equals(chatUUID)).findFirst()
|
||||||
|
// .ifPresent(chat -> {
|
||||||
|
// chat.setLastMessageTime(newTime);
|
||||||
|
// System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Session.archivedChats.stream().filter(chat -> chat.getId().equals(chatUUID)).findFirst()
|
||||||
|
// .ifPresent(chat -> {
|
||||||
|
// chat.setLastMessageTime(newTime);
|
||||||
|
// System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// Session.chatList.sort((c1, c2) -> {
|
||||||
|
// if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0;
|
||||||
|
// if (c1.getLastMessageTime() == null) return 1;
|
||||||
|
// if (c2.getLastMessageTime() == null) return -1;
|
||||||
|
// return c2.getLastMessageTime().compareTo(c1.getLastMessageTime());
|
||||||
|
// });
|
||||||
|
// Session.activeChats.sort((c1, c2) -> {
|
||||||
|
// if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0;
|
||||||
|
// if (c1.getLastMessageTime() == null) return 1;
|
||||||
|
// if (c2.getLastMessageTime() == null) return -1;
|
||||||
|
// return c2.getLastMessageTime().compareTo(c1.getLastMessageTime());
|
||||||
|
// });
|
||||||
|
// Session.archivedChats.sort((c1, c2) -> {
|
||||||
|
// if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0;
|
||||||
|
// if (c1.getLastMessageTime() == null) return 1;
|
||||||
|
// if (c2.getLastMessageTime() == null) return -1;
|
||||||
|
// return c2.getLastMessageTime().compareTo(c1.getLastMessageTime());
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// if (Session.inChatListMenu) {
|
||||||
|
// ActionHandler.displayChatList();
|
||||||
|
// System.out.print("Select a chat by number: ");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } catch (Exception e) {
|
||||||
|
// System.out.println("❌ Failed to update last message time: " + e.getMessage());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
private void updateLastMessageTime(JSONObject msg) {
|
private void updateLastMessageTime(JSONObject msg) {
|
||||||
try {
|
try {
|
||||||
UUID chatUUID = UUID.fromString(msg.getString("chat_id"));
|
UUID chatUUID = UUID.fromString(msg.getString("chat_id"));
|
||||||
String newTime = msg.optString("last_message_time", null);
|
String newTime = msg.optString("last_message_time", null);
|
||||||
|
if (newTime == null || newTime.isBlank()) return;
|
||||||
|
|
||||||
Session.chatList.stream().filter(chat -> chat.getId().equals(chatUUID)).findFirst()
|
updateOneList(Session.chatList, chatUUID, newTime);
|
||||||
.ifPresent(chat -> {
|
updateOneList(Session.activeChats, chatUUID, newTime);
|
||||||
chat.setLastMessageTime(newTime);
|
updateOneList(Session.archivedChats, chatUUID, newTime);
|
||||||
System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
|
||||||
});
|
|
||||||
|
|
||||||
Session.activeChats.stream().filter(chat -> chat.getId().equals(chatUUID)).findFirst()
|
sortByLastMessageTime(Session.chatList);
|
||||||
.ifPresent(chat -> {
|
sortByLastMessageTime(Session.activeChats);
|
||||||
chat.setLastMessageTime(newTime);
|
sortByLastMessageTime(Session.archivedChats);
|
||||||
System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
|
||||||
});
|
|
||||||
|
|
||||||
Session.archivedChats.stream().filter(chat -> chat.getId().equals(chatUUID)).findFirst()
|
|
||||||
.ifPresent(chat -> {
|
|
||||||
chat.setLastMessageTime(newTime);
|
|
||||||
System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
|
||||||
});
|
|
||||||
|
|
||||||
Session.chatList.sort((c1, c2) -> {
|
|
||||||
if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0;
|
|
||||||
if (c1.getLastMessageTime() == null) return 1;
|
|
||||||
if (c2.getLastMessageTime() == null) return -1;
|
|
||||||
return c2.getLastMessageTime().compareTo(c1.getLastMessageTime());
|
|
||||||
});
|
|
||||||
Session.activeChats.sort((c1, c2) -> {
|
|
||||||
if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0;
|
|
||||||
if (c1.getLastMessageTime() == null) return 1;
|
|
||||||
if (c2.getLastMessageTime() == null) return -1;
|
|
||||||
return c2.getLastMessageTime().compareTo(c1.getLastMessageTime());
|
|
||||||
});
|
|
||||||
Session.archivedChats.sort((c1, c2) -> {
|
|
||||||
if (c1.getLastMessageTime() == null && c2.getLastMessageTime() == null) return 0;
|
|
||||||
if (c1.getLastMessageTime() == null) return 1;
|
|
||||||
if (c2.getLastMessageTime() == null) return -1;
|
|
||||||
return c2.getLastMessageTime().compareTo(c1.getLastMessageTime());
|
|
||||||
});
|
|
||||||
|
|
||||||
if (Session.inChatListMenu) {
|
if (Session.inChatListMenu) {
|
||||||
ActionHandler.displayChatList();
|
ActionHandler.displayChatList();
|
||||||
System.out.print("Select a chat by number: ");
|
System.out.print("Select a chat by number: ");
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("❌ Failed to update last message time: " + e.getMessage());
|
System.out.println("❌ Failed to update last message time: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateOneList(List<ChatEntry> list, UUID chatUUID, String newTime) {
|
||||||
|
if (list == null) return;
|
||||||
|
for (ChatEntry chat : list) {
|
||||||
|
if (chatUUID.equals(chat.getId())) { // ✅ internal UUID
|
||||||
|
chat.setLastMessageTime(newTime);
|
||||||
|
System.out.println("✅ Updated last message time for chat: " + chat.getDisplayId());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void sortByLastMessageTime(java.util.List<ChatEntry> list) {
|
||||||
|
if (list == null) return;
|
||||||
|
list.sort((a, b) -> {
|
||||||
|
var ta = parseTs(String.valueOf(a.getLastMessageTime()));
|
||||||
|
var tb = parseTs(String.valueOf(b.getLastMessageTime()));
|
||||||
|
if (ta == null && tb == null) return 0;
|
||||||
|
if (ta == null) return 1; // nullها برن آخر
|
||||||
|
if (tb == null) return -1;
|
||||||
|
return tb.compareTo(ta); // نزولی (جدیدتر بالاتر)
|
||||||
|
});
|
||||||
|
|
||||||
|
// اگر «Saved Messages» رو میخوای همیشه بالا پین کنی، این ۴ خط رو نگه دار؛
|
||||||
|
// اگر نه، حذفش کن.
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
if (list.get(i).isSavedMessages()) {
|
||||||
|
list.add(0, list.remove(i));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static java.time.LocalDateTime parseTs(String s) {
|
||||||
|
if (s == null) return null;
|
||||||
|
s = s.trim();
|
||||||
|
if (s.isEmpty() || s.equalsIgnoreCase("null")) return null;
|
||||||
|
try { return java.time.OffsetDateTime.parse(s).toLocalDateTime(); } catch (Exception ignore) {}
|
||||||
|
try { return java.time.LocalDateTime.parse(s, java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME); } catch (Exception ignore) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void handleAdminRoleChanged(JSONObject data) throws IOException {
|
private void handleAdminRoleChanged(JSONObject data) throws IOException {
|
||||||
String chatType = data.optString("chat_type", "");
|
String chatType = data.optString("chat_type", "");
|
||||||
String chatId = data.optString("group_id",
|
String chatId = data.optString("group_id",
|
||||||
@@ -368,4 +438,7 @@ public class IncomingMessageListener implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3046,6 +3046,59 @@ public class ClientHandler implements Runnable {
|
|||||||
out.println(ack.toString());
|
out.println(ack.toString());
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
|
|
||||||
|
// بعد از out.flush(); و فقط اگر ok==true
|
||||||
|
if (ok) {
|
||||||
|
try {
|
||||||
|
// 1) دریافت پیام از DB تا send_at و... دقیق باشد
|
||||||
|
Message m = MessageDatabase.findById(messageId); // اگر چنین متدی نداری، با پارامترهای همین متد بساز/پر کن
|
||||||
|
|
||||||
|
// 2) لیست دریافتکنندگان بر اساس نوع چت
|
||||||
|
List<UUID> receivers = getReceiversForChat(receiverId, rType.toLowerCase());
|
||||||
|
|
||||||
|
|
||||||
|
// 3) ساخت payload شامل اتچمنت (media)
|
||||||
|
User sender = userDatabase.findByInternalUUID(senderId);
|
||||||
|
JSONObject payload = new JSONObject()
|
||||||
|
.put("action", "new_message")
|
||||||
|
.put("data", new JSONObject()
|
||||||
|
.put("id", m.getMessage_id().toString())
|
||||||
|
.put("chat_id", receiverId.toString())
|
||||||
|
.put("chat_type", rType.toLowerCase())
|
||||||
|
.put("sender_id", senderId.toString())
|
||||||
|
.put("sender_name", sender != null ? sender.getProfile_name() : JSONObject.NULL)
|
||||||
|
.put("message_type", messageType.toLowerCase())
|
||||||
|
.put("text", (text == null || text.isEmpty()) ? JSONObject.NULL : text)
|
||||||
|
.put("media", new JSONObject()
|
||||||
|
.put("media_id", mediaKey != null ? mediaKey.toString() : JSONObject.NULL)
|
||||||
|
.put("file_name", fileName)
|
||||||
|
.put("mime_type", mimeType)
|
||||||
|
.put("size_bytes", fileSize)
|
||||||
|
.put("url", fileUrl)
|
||||||
|
.put("thumbnail_url", JSONObject.NULL)
|
||||||
|
.put("width", safeWidth)
|
||||||
|
.put("height", safeHeight)
|
||||||
|
.put("duration_ms", 0)
|
||||||
|
)
|
||||||
|
.put("send_at", m.getSend_at().toString())
|
||||||
|
.put("status", "SENT")
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4) ارسال به همه اعضا (از جمله خودِ فرستنده اگر میخواهی UI آن هم یکپارچه آپدیت شود)
|
||||||
|
for (UUID uid : receivers) {
|
||||||
|
RealTimeEventDispatcher.sendToUser(uid, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// (اختیاری) رویداد آپدیت چتلیست برای sort بر اساس آخرین پیام
|
||||||
|
RealTimeEventDispatcher.notifyChatUpdated(receiverId, rType, m);
|
||||||
|
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
// اگر ذخیره شد ولی Broadcast شکست خورد، میتوانی Log کنی یا Retry سبک انجام دهی
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
out.println(new JSONObject().put("status","error").put("message","exception").toString());
|
out.println(new JSONObject().put("status","error").put("message","exception").toString());
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package org.to.telegramfinalproject.Server;
|
package org.to.telegramfinalproject.Server;
|
||||||
|
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.to.telegramfinalproject.Database.ChannelDatabase;
|
import org.to.telegramfinalproject.Database.*;
|
||||||
import org.to.telegramfinalproject.Database.ContactDatabase;
|
|
||||||
import org.to.telegramfinalproject.Database.GroupDatabase;
|
|
||||||
import org.to.telegramfinalproject.Database.userDatabase;
|
|
||||||
import org.to.telegramfinalproject.Models.Message;
|
import org.to.telegramfinalproject.Models.Message;
|
||||||
import org.to.telegramfinalproject.Models.User;
|
import org.to.telegramfinalproject.Models.User;
|
||||||
|
|
||||||
@@ -12,7 +9,9 @@ import java.io.IOException;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class RealTimeEventDispatcher {
|
public class RealTimeEventDispatcher {
|
||||||
@@ -425,4 +424,81 @@ public class RealTimeEventDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void notifyChatUpdated(UUID chatId, String chatType, Message lastMsg) {
|
||||||
|
if (chatId == null || chatType == null) return;
|
||||||
|
|
||||||
|
final String type = chatType.toLowerCase(Locale.ROOT);
|
||||||
|
|
||||||
|
List<UUID> receivers;
|
||||||
|
switch (type) {
|
||||||
|
case "private":
|
||||||
|
receivers = PrivateChatDatabase.getMembers(chatId);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "group":
|
||||||
|
receivers = GroupDatabase.getMemberUUIDs(chatId);
|
||||||
|
break;
|
||||||
|
case "channel":
|
||||||
|
receivers = ChannelDatabase.getSubscriberUUIDs(chatId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
receivers = Collections.emptyList();
|
||||||
|
}
|
||||||
|
if (receivers == null || receivers.isEmpty()) return;
|
||||||
|
|
||||||
|
// 2) ساخت خلاصه آخرین پیام برای نمایش در لیست چت
|
||||||
|
String senderName = null;
|
||||||
|
if (lastMsg != null && lastMsg.getSender_id() != null) {
|
||||||
|
User u = userDatabase.findByInternalUUID(lastMsg.getSender_id());
|
||||||
|
if (u != null) senderName = u.getProfile_name();
|
||||||
|
}
|
||||||
|
|
||||||
|
String messageType = lastMsg != null && lastMsg.getMessage_type() != null
|
||||||
|
? lastMsg.getMessage_type().toLowerCase(Locale.ROOT) : "text";
|
||||||
|
|
||||||
|
// preview ساده: برای مدیا، برچسب کوتاه؛ برای متن، کوتاهسازی
|
||||||
|
String preview;
|
||||||
|
if (!"text".equals(messageType)) {
|
||||||
|
switch (messageType) {
|
||||||
|
case "image": preview = "[Photo]"; break;
|
||||||
|
case "video": preview = "[Video]"; break;
|
||||||
|
case "audio": preview = "[Audio]"; break;
|
||||||
|
case "file": preview = "[File]"; break;
|
||||||
|
default: preview = "[Media]";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String t = lastMsg != null ? nullToEmpty(lastMsg.getContent()) : "";
|
||||||
|
preview = t.length() > 80 ? t.substring(0, 80) + "…" : t;
|
||||||
|
}
|
||||||
|
|
||||||
|
String sendAt = (lastMsg != null && lastMsg.getSend_at() != null)
|
||||||
|
? lastMsg.getSend_at().toString()
|
||||||
|
: java.time.OffsetDateTime.now().toString();
|
||||||
|
|
||||||
|
// 3) payload رویداد chat_updated
|
||||||
|
JSONObject payload = new JSONObject()
|
||||||
|
.put("action", "chat_updated")
|
||||||
|
.put("data", new JSONObject()
|
||||||
|
.put("chat_id", chatId.toString())
|
||||||
|
.put("chat_type", type)
|
||||||
|
.put("last_message", new JSONObject()
|
||||||
|
.put("id", lastMsg != null ? lastMsg.getMessage_id().toString() : JSONObject.NULL)
|
||||||
|
.put("sender_id", lastMsg != null ? lastMsg.getSender_id().toString() : JSONObject.NULL)
|
||||||
|
.put("sender_name", senderName != null ? senderName : JSONObject.NULL)
|
||||||
|
.put("message_type", messageType)
|
||||||
|
.put("preview", preview)
|
||||||
|
.put("send_at", sendAt)
|
||||||
|
)
|
||||||
|
.put("last_message_time", sendAt)
|
||||||
|
.put("update_reason", "new_message") // برای کلاینت مفید است
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4) ارسال به همه اعضای چت
|
||||||
|
for (UUID uid : receivers) {
|
||||||
|
sendToUser(uid, payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String nullToEmpty(String s) { return s == null ? "" : s; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user