Work on delete chat
This commit is contained in:
@@ -1237,6 +1237,7 @@ public class ActionHandler {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private JSONObject getGroupPermissions(UUID groupId) {
|
private JSONObject getGroupPermissions(UUID groupId) {
|
||||||
JSONObject req = new JSONObject();
|
JSONObject req = new JSONObject();
|
||||||
req.put("action", "get_group_permissions");
|
req.put("action", "get_group_permissions");
|
||||||
@@ -2013,7 +2014,7 @@ public class ActionHandler {
|
|||||||
private void deleteChat(UUID targetId, boolean both) {
|
private void deleteChat(UUID targetId, boolean both) {
|
||||||
JSONObject req = new JSONObject();
|
JSONObject req = new JSONObject();
|
||||||
req.put("action", "delete_private_chat");
|
req.put("action", "delete_private_chat");
|
||||||
req.put("target_id", targetId.toString());
|
req.put("chat_id", targetId.toString());
|
||||||
req.put("both", both);
|
req.put("both", both);
|
||||||
send(req);
|
send(req);
|
||||||
|
|
||||||
|
|||||||
@@ -65,6 +65,54 @@ public class MessageDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void markGloballyDeleted(UUID chatId) {
|
||||||
|
String sql = "UPDATE messages SET deleted_globally = true WHERE receiver_id = ? AND receiver_type = 'private'";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, chatId);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logDeletedMessagesFor(UUID chatId, UUID userId) {
|
||||||
|
List<Message> messages = MessageDatabase.privateChatHistory(chatId);
|
||||||
|
for (Message message : messages) {
|
||||||
|
if (!isMessageDeleted(message.getMessage_id(), userId)) {
|
||||||
|
String sql = """
|
||||||
|
INSERT INTO deleted_messages (message_id, user_id)
|
||||||
|
VALUES (?, ?)
|
||||||
|
ON CONFLICT (message_id, user_id) DO NOTHING
|
||||||
|
""";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, message.getMessage_id());
|
||||||
|
ps.setObject(2, userId);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isMessageDeleted(UUID messageId, UUID userId) {
|
||||||
|
String sql = "SELECT 1 FROM deleted_messages WHERE message_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, messageId);
|
||||||
|
ps.setObject(2, userId);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
return rs.next();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void markMessageAsRead(UUID messageId, UUID userId) {
|
public void markMessageAsRead(UUID messageId, UUID userId) {
|
||||||
String sql = "INSERT INTO message_receipts (message_id, user_id) VALUES (?, ?) ON CONFLICT DO NOTHING";
|
String sql = "INSERT INTO message_receipts (message_id, user_id) VALUES (?, ?) ON CONFLICT DO NOTHING";
|
||||||
try (Connection conn = ConnectionDb.connect();
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ package org.to.telegramfinalproject.Database;
|
|||||||
|
|
||||||
import org.to.telegramfinalproject.Models.PrivateChat;
|
import org.to.telegramfinalproject.Models.PrivateChat;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.*;
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -133,4 +130,129 @@ public class PrivateChatDatabase {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static PrivateChat extractPrivateChat(ResultSet rs) throws SQLException {
|
||||||
|
UUID chatId = UUID.fromString(rs.getString("chat_id"));
|
||||||
|
UUID user1 = rs.getObject("user1_id", UUID.class);
|
||||||
|
UUID user2 = rs.getObject("user2_id", UUID.class);
|
||||||
|
boolean user1Deleted = rs.getBoolean("user1_deleted");
|
||||||
|
boolean user2Deleted = rs.getBoolean("user2_deleted");
|
||||||
|
LocalDateTime createdAt = rs.getTimestamp("created_at").toLocalDateTime();
|
||||||
|
|
||||||
|
return new PrivateChat(chatId, user1, user2, user1Deleted, user2Deleted, createdAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markChatDeleted(UUID userId, UUID chatId) {
|
||||||
|
String sql = """
|
||||||
|
UPDATE private_chat
|
||||||
|
SET user1_deleted = CASE WHEN user1_id = ? THEN true ELSE user1_deleted END,
|
||||||
|
user2_deleted = CASE WHEN user2_id = ? THEN true ELSE user2_deleted END
|
||||||
|
WHERE chat_id = ?
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, userId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
stmt.setObject(3, chatId);
|
||||||
|
stmt.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void unmarkChatDeleted(UUID userId, UUID chatId) {
|
||||||
|
String sql = """
|
||||||
|
UPDATE private_chat
|
||||||
|
SET user1_deleted = CASE WHEN user1_id = ? THEN false ELSE user1_deleted END,
|
||||||
|
user2_deleted = CASE WHEN user2_id = ? THEN false ELSE user2_deleted END
|
||||||
|
WHERE chat_id = ?
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, userId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
stmt.setObject(3, chatId);
|
||||||
|
stmt.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markUser1Deleted(UUID chatId) {
|
||||||
|
updateBoolField(chatId, "user1_deleted", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markUser2Deleted(UUID chatId) {
|
||||||
|
updateBoolField(chatId, "user2_deleted", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void markBothDeleted(UUID chatId) {
|
||||||
|
String sql = "UPDATE private_chat SET user1_deleted = true, user2_deleted = true WHERE chat_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, chatId);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void updateBoolField(UUID chatId, String field, boolean value) {
|
||||||
|
String sql = "UPDATE private_chat SET " + field + " = ? WHERE chat_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setBoolean(1, value);
|
||||||
|
ps.setObject(2, chatId);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static PrivateChat findById(UUID chatId) {
|
||||||
|
String sql = "SELECT * FROM private_chat WHERE chat_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, chatId);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
UUID user1_id = (UUID) rs.getObject("user1_id");
|
||||||
|
UUID user2_id = (UUID) rs.getObject("user2_id");
|
||||||
|
boolean user1_deleted = rs.getBoolean("user1_deleted");
|
||||||
|
boolean user2_deleted = rs.getBoolean("user2_deleted");
|
||||||
|
LocalDateTime created_at = rs.getTimestamp("created_at").toLocalDateTime();
|
||||||
|
|
||||||
|
return new PrivateChat(chatId, user1_id, user2_id, user1_deleted, user2_deleted, created_at);
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void clearDeletedFlag(UUID senderId, UUID receiverId) {
|
||||||
|
String sql = """
|
||||||
|
UPDATE private_chat
|
||||||
|
SET user1_deleted = CASE WHEN user1_id = ? THEN false ELSE user1_deleted END,
|
||||||
|
user2_deleted = CASE WHEN user2_id = ? THEN false ELSE user2_deleted END
|
||||||
|
WHERE (user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, senderId);
|
||||||
|
ps.setObject(2, senderId);
|
||||||
|
ps.setObject(3, senderId);
|
||||||
|
ps.setObject(4, receiverId);
|
||||||
|
ps.setObject(5, receiverId);
|
||||||
|
ps.setObject(6, senderId);
|
||||||
|
ps.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class PrivateChat {
|
public class PrivateChat {
|
||||||
private final UUID chat_id;
|
private final UUID chat_id;
|
||||||
|
private boolean user1_deleted;
|
||||||
|
private boolean user2_deleted;
|
||||||
private UUID user1_id;
|
private UUID user1_id;
|
||||||
private UUID user2_id;
|
private UUID user2_id;
|
||||||
private LocalDateTime created_at;
|
private LocalDateTime created_at;
|
||||||
@@ -16,6 +18,16 @@ public class PrivateChat {
|
|||||||
this.created_at =created_at;
|
this.created_at =created_at;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PrivateChat(UUID chatId, UUID user1, UUID user2, boolean user1Deleted, boolean user2Deleted, LocalDateTime createdAt) {
|
||||||
|
this.chat_id = chatId;
|
||||||
|
this.user1_id = user1;
|
||||||
|
this.user2_id = user2;
|
||||||
|
this.user1_deleted = user1Deleted;
|
||||||
|
this.user2_deleted = user2Deleted;
|
||||||
|
this.created_at = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setUser1_id(UUID user1_id){this.user1_id =user1_id;}
|
public void setUser1_id(UUID user1_id){this.user1_id =user1_id;}
|
||||||
public void setUser2_id(UUID user2_id){this.user2_id =user2_id;}
|
public void setUser2_id(UUID user2_id){this.user2_id =user2_id;}
|
||||||
public void setCreated_at(LocalDateTime created_at){this.created_at = created_at;}
|
public void setCreated_at(LocalDateTime created_at){this.created_at = created_at;}
|
||||||
|
|||||||
@@ -1432,26 +1432,33 @@ public class ClientHandler implements Runnable {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "delete_private_chat" : {
|
case "delete_private_chat": {
|
||||||
if (currentUser == null) {
|
if (currentUser == null) {
|
||||||
response = new ResponseModel("error", "Unauthorized. Please login first.");
|
response = new ResponseModel("error", "Unauthorized. Please login first.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
UUID targetId = UUID.fromString(requestJson.getString("target_id"));
|
|
||||||
|
// دریافت شناسه چت و نوع حذف (یکطرفه یا دوطرفه)
|
||||||
|
UUID targetId = UUID.fromString(requestJson.getString("chat_id"));
|
||||||
boolean both = requestJson.getBoolean("both");
|
boolean both = requestJson.getBoolean("both");
|
||||||
|
|
||||||
//RealTime
|
// Real-Time Event Dispatch (اطلاعرسانی ریل تایم)
|
||||||
if (both) {
|
if (both) {
|
||||||
|
// حذف دوطرفه
|
||||||
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
||||||
RealTimeEventDispatcher.notifyChatDeleted("private", currentUser.getInternal_uuid(), List.of(targetId));
|
RealTimeEventDispatcher.notifyChatDeleted("private", currentUser.getInternal_uuid(), List.of(targetId));
|
||||||
} else {
|
} else {
|
||||||
|
// حذف یکطرفه
|
||||||
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
RealTimeEventDispatcher.notifyChatDeleted("private", targetId, List.of(currentUser.getInternal_uuid()));
|
||||||
}
|
}
|
||||||
response = PrivateChatService.deletePrivateChat(currentUser.getInternal_uuid(), targetId, both);
|
|
||||||
|
// فراخوانی متد حذف چت
|
||||||
|
response = handleDeleteChat(requestJson);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case "get_group_permissions": {
|
case "get_group_permissions": {
|
||||||
if (currentUser == null) {
|
if (currentUser == null) {
|
||||||
response = new ResponseModel("error", "Unauthorized. Please login first.");
|
response = new ResponseModel("error", "Unauthorized. Please login first.");
|
||||||
@@ -2025,8 +2032,6 @@ public class ClientHandler implements Runnable {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
response = new ResponseModel("error", "Unknown action: " + action);
|
response = new ResponseModel("error", "Unknown action: " + action);
|
||||||
}
|
}
|
||||||
@@ -2085,6 +2090,7 @@ public class ClientHandler implements Runnable {
|
|||||||
|
|
||||||
|
|
||||||
private ResponseModel handleSendMessage(JSONObject json) {
|
private ResponseModel handleSendMessage(JSONObject json) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (currentUser == null)
|
if (currentUser == null)
|
||||||
return new ResponseModel("error", "Unauthorized. Please login first.");
|
return new ResponseModel("error", "Unauthorized. Please login first.");
|
||||||
@@ -2093,9 +2099,13 @@ public class ClientHandler implements Runnable {
|
|||||||
UUID senderId = currentUser.getInternal_uuid();
|
UUID senderId = currentUser.getInternal_uuid();
|
||||||
String receiverType = json.getString("receiver_type");
|
String receiverType = json.getString("receiver_type");
|
||||||
UUID receiverId;
|
UUID receiverId;
|
||||||
|
|
||||||
receiverId = UUID.fromString(json.getString("receiver_id"));
|
receiverId = UUID.fromString(json.getString("receiver_id"));
|
||||||
|
|
||||||
|
if(Objects.equals(receiverType, "private")){
|
||||||
|
PrivateChatDatabase.clearDeletedFlag(senderId, receiverId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String content = json.optString("content", "");
|
String content = json.optString("content", "");
|
||||||
String messageType = json.optString("message_type", "TEXT");
|
String messageType = json.optString("message_type", "TEXT");
|
||||||
|
|
||||||
@@ -2165,5 +2175,42 @@ public class ClientHandler implements Runnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private ResponseModel handleDeleteChat(JSONObject json) {
|
||||||
|
try {
|
||||||
|
if (currentUser == null)
|
||||||
|
return new ResponseModel("error", "Unauthorized");
|
||||||
|
|
||||||
|
UUID chatId = UUID.fromString(json.getString("chat_id"));
|
||||||
|
boolean bothSides = json.optBoolean("both_sides", false);
|
||||||
|
|
||||||
|
PrivateChat chat = PrivateChatDatabase.findById(chatId);
|
||||||
|
if (chat == null) return new ResponseModel("error", "Chat not found.");
|
||||||
|
|
||||||
|
UUID self = currentUser.getInternal_uuid();
|
||||||
|
UUID other = chat.getUser1_id().equals(self) ? chat.getUser2_id() : chat.getUser1_id();
|
||||||
|
|
||||||
|
if (bothSides) {
|
||||||
|
PrivateChatDatabase.markBothDeleted(chatId);
|
||||||
|
MessageDatabase.markGloballyDeleted(chatId);
|
||||||
|
MessageDatabase.logDeletedMessagesFor(chatId, self);
|
||||||
|
MessageDatabase.logDeletedMessagesFor(chatId, other);
|
||||||
|
return new ResponseModel("success", "Chat deleted for both sides.");
|
||||||
|
} else {
|
||||||
|
if (chat.getUser1_id().equals(self))
|
||||||
|
PrivateChatDatabase.markUser1Deleted(chatId);
|
||||||
|
else
|
||||||
|
PrivateChatDatabase.markUser2Deleted(chatId);
|
||||||
|
|
||||||
|
MessageDatabase.logDeletedMessagesFor(chatId, self);
|
||||||
|
return new ResponseModel("success", "Chat deleted (one-sided).");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return new ResponseModel("error", "Exception while deleting chat.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user