Reaction and forwarded
This commit is contained in:
@@ -3378,16 +3378,37 @@ public class ActionHandler {
|
|||||||
String editedAt = msg.optString("edited_at", "");
|
String editedAt = msg.optString("edited_at", "");
|
||||||
String label = isEdited ? "🖊️ (edited at: " + editedAt + ")" : "";
|
String label = isEdited ? "🖊️ (edited at: " + editedAt + ")" : "";
|
||||||
|
|
||||||
//for reply
|
// ✅ Forwarded info
|
||||||
if (msg.has("reply_to_sender") && msg.has("reply_to_content")) {
|
String forwardLabel = "";
|
||||||
String replySender = msg.optString("reply_to_sender", "Unknown");
|
if (msg.optBoolean("is_forwarded", false)) {
|
||||||
String replyContent = msg.optString("reply_to_content", "(no content)");
|
String forwardFrom = msg.optString("forwarded_from_name", "Unknown");
|
||||||
System.out.printf(" ↪️ Replying to [%s]: %s\n", replySender, replyContent);
|
forwardLabel = "🔁 Forwarded from " + forwardFrom;
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.printf("[%d] [%s] %s: %s %s\n", i + 1, time, senderName, content, label);
|
//for reply
|
||||||
|
String replyLabel = "";
|
||||||
|
if (msg.has("reply_to_id")) {
|
||||||
|
String repliedSender = msg.optString("reply_to_sender", "Unknown");
|
||||||
|
String repliedContent = msg.optString("reply_to_content", "...");
|
||||||
|
replyLabel = "↪️ Reply to " + repliedSender + ": \"" + repliedContent + "\"";
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONArray reactions = msg.optJSONArray("reactions");
|
||||||
|
if (reactions != null && !reactions.isEmpty()) {
|
||||||
|
System.out.print(" 💬 Reactions: ");
|
||||||
|
for (int j = 0; j < reactions.length(); j++) {
|
||||||
|
System.out.print(reactions.getString(j) + " ");
|
||||||
|
}
|
||||||
|
System.out.println();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
System.out.printf("[%d] [%s] %s: \n", i + 1, time, senderName);
|
||||||
|
if (!forwardLabel.isEmpty()) System.out.println(forwardLabel);
|
||||||
|
if (!replyLabel.isEmpty()) System.out.println(replyLabel);
|
||||||
|
System.out.printf("%s %s\n", content, label);
|
||||||
|
System.out.println("─────────────────────────────────────────────");
|
||||||
}
|
}
|
||||||
System.out.println("─────────────────────────────────────────────");
|
|
||||||
|
|
||||||
System.out.print("""
|
System.out.print("""
|
||||||
💬 Options:
|
💬 Options:
|
||||||
@@ -3507,15 +3528,73 @@ public class ActionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String reactToMessage(UUID messageId) {
|
private void reactToMessage(UUID messageId) {
|
||||||
return "not ready";
|
System.out.print("😊 Enter your reaction (e.g., ❤️, 👍, 😂): ");
|
||||||
|
String reaction = scanner.nextLine().trim();
|
||||||
|
|
||||||
|
if (reaction.isEmpty()) {
|
||||||
|
System.out.println("⚠️ Empty reaction discarded.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject req = new JSONObject();
|
||||||
|
req.put("action", "react_to_message");
|
||||||
|
req.put("message_id", messageId.toString());
|
||||||
|
req.put("reaction", reaction);
|
||||||
|
|
||||||
|
JSONObject res = sendWithResponse(req);
|
||||||
|
if (res != null && res.getString("status").equals("success")) {
|
||||||
|
System.out.println("✅ Reaction sent.");
|
||||||
|
} else {
|
||||||
|
System.out.println("❌ Failed to react to message.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String forwardMessage(UUID messageId) {
|
|
||||||
return "not ready";
|
private void forwardMessage(UUID originalMessageId) {
|
||||||
|
System.out.println("\n📤 Select a chat to forward this message to:");
|
||||||
|
|
||||||
|
List<ChatEntry> chatList = Session.chatList;
|
||||||
|
for (int i = 0; i < chatList.size(); i++) {
|
||||||
|
ChatEntry c = chatList.get(i);
|
||||||
|
System.out.printf("%d. [%s] %s\n", i + 1, c.getType(), c.getName());
|
||||||
|
}
|
||||||
|
System.out.println("0. Cancel");
|
||||||
|
|
||||||
|
System.out.print("➤ Enter chat number: ");
|
||||||
|
String input = scanner.nextLine().trim();
|
||||||
|
|
||||||
|
if (input.equals("0")) return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
int choice = Integer.parseInt(input);
|
||||||
|
if (choice < 1 || choice > chatList.size()) {
|
||||||
|
System.out.println("❌ Invalid choice.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChatEntry target = chatList.get(choice - 1);
|
||||||
|
|
||||||
|
JSONObject req = new JSONObject();
|
||||||
|
req.put("action", "forward_message");
|
||||||
|
req.put("target_chat_id", target.getId());
|
||||||
|
req.put("target_chat_type", target.getType());
|
||||||
|
req.put("original_message_id", originalMessageId.toString());
|
||||||
|
req.put("forwarded_by", Session.currentUser.getString("internal_uuid"));
|
||||||
|
|
||||||
|
JSONObject res = sendWithResponse(req);
|
||||||
|
if (res != null && res.getString("status").equals("success")) {
|
||||||
|
System.out.println("✅ Message forwarded successfully.");
|
||||||
|
} else {
|
||||||
|
System.out.println("❌ Failed to forward the message.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.out.println("❌ Invalid input.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void replyToMessage(UUID messageId) {
|
private void replyToMessage(UUID messageId) {
|
||||||
System.out.print("💬 Enter your reply: ");
|
System.out.print("💬 Enter your reply: ");
|
||||||
String content = scanner.nextLine().trim();
|
String content = scanner.nextLine().trim();
|
||||||
|
|||||||
@@ -282,6 +282,42 @@ public class MessageDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean saveForwardedMessage(Message message) {
|
||||||
|
String sql = """
|
||||||
|
INSERT INTO messages (
|
||||||
|
message_id, sender_id, receiver_type, receiver_id,
|
||||||
|
content, message_type, send_at, status,
|
||||||
|
reply_to_id, is_edited, is_deleted_globally,
|
||||||
|
original_message_id, forwarded_by, forwarded_from
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
ps.setObject(1, message.getMessage_id());
|
||||||
|
ps.setObject(2, message.getSender_id());
|
||||||
|
ps.setString(3, message.getReceiver_type());
|
||||||
|
ps.setObject(4, message.getReceiver_id());
|
||||||
|
ps.setString(5, message.getContent());
|
||||||
|
ps.setString(6, message.getMessage_type());
|
||||||
|
ps.setTimestamp(7, Timestamp.valueOf(message.getSend_at()));
|
||||||
|
ps.setString(8, message.getStatus());
|
||||||
|
ps.setObject(9, message.getReply_to_id());
|
||||||
|
ps.setBoolean(10, message.isIs_edited());
|
||||||
|
ps.setBoolean(11, message.isIs_deleted_globally());
|
||||||
|
ps.setObject(12, message.getOriginal_message_id()); //original id
|
||||||
|
ps.setObject(13, message.getForwarded_by()); //forwarded by
|
||||||
|
ps.setObject(14, message.getForwarded_from()); //forwarded from
|
||||||
|
|
||||||
|
return ps.executeUpdate() > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void markMessageAsRead(UUID messageId, UUID userId) {
|
public void markMessageAsRead(UUID messageId, UUID userId) {
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.to.telegramfinalproject.Database;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class MessageReactionDatabase {
|
||||||
|
|
||||||
|
public static boolean saveOrUpdateReaction(UUID messageId, UUID userId, String reaction) {
|
||||||
|
String sql = """
|
||||||
|
INSERT INTO message_reactions (message_id, user_id, emoji)
|
||||||
|
VALUES (?, ?, ?)
|
||||||
|
ON CONFLICT (message_id, user_id)
|
||||||
|
DO UPDATE SET emoji = EXCLUDED.emoji, reacted_at = CURRENT_TIMESTAMP
|
||||||
|
""";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, messageId);
|
||||||
|
ps.setObject(2, userId);
|
||||||
|
ps.setString(3, reaction);
|
||||||
|
return ps.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> getReactions(UUID messageId) {
|
||||||
|
String sql = "SELECT emoji FROM message_reactions WHERE message_id = ?";
|
||||||
|
List<String> reactions = new ArrayList<>();
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||||
|
ps.setObject(1, messageId);
|
||||||
|
ResultSet rs = ps.executeQuery();
|
||||||
|
while (rs.next()) {
|
||||||
|
reactions.add(rs.getString("emoji"));
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return reactions;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2149,7 +2149,7 @@ public class ClientHandler implements Runnable {
|
|||||||
obj.put("is_deleted_globally", m.isIs_deleted_globally());
|
obj.put("is_deleted_globally", m.isIs_deleted_globally());
|
||||||
obj.put("edited_at", m.getEdited_at() != null ? m.getEdited_at().toString() : JSONObject.NULL);
|
obj.put("edited_at", m.getEdited_at() != null ? m.getEdited_at().toString() : JSONObject.NULL);
|
||||||
|
|
||||||
//for reply
|
//For reply messages
|
||||||
if (m.getReply_to_id() != null) {
|
if (m.getReply_to_id() != null) {
|
||||||
Message replied = MessageDatabase.findById(m.getReply_to_id());
|
Message replied = MessageDatabase.findById(m.getReply_to_id());
|
||||||
if (replied != null) {
|
if (replied != null) {
|
||||||
@@ -2160,9 +2160,26 @@ public class ClientHandler implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For forwarded messages
|
||||||
|
if (m.getOriginal_message_id() != null && m.getForwarded_from() != null) {
|
||||||
|
User originalSender = userDatabase.findByInternalUUID(m.getForwarded_from());
|
||||||
|
obj.put("is_forwarded", true);
|
||||||
|
obj.put("forwarded_from_id", m.getForwarded_from().toString());
|
||||||
|
obj.put("forwarded_from_name", originalSender != null ? originalSender.getProfile_name() : "Unknown");
|
||||||
|
} else {
|
||||||
|
obj.put("is_forwarded", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//For reactions
|
||||||
|
List<String> reactions = MessageReactionDatabase.getReactions(m.getMessage_id());
|
||||||
|
obj.put("reactions", new JSONArray(reactions));
|
||||||
|
|
||||||
|
|
||||||
result.put(obj);
|
result.put(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
JSONObject data = new JSONObject();
|
JSONObject data = new JSONObject();
|
||||||
data.put("get_chat_messages", result);
|
data.put("get_chat_messages", result);
|
||||||
|
|
||||||
@@ -2273,6 +2290,58 @@ public class ClientHandler implements Runnable {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case "forward_message" : {
|
||||||
|
UUID originalMessageId = UUID.fromString(requestJson.getString("original_message_id"));
|
||||||
|
UUID targetChatId = UUID.fromString(requestJson.getString("target_chat_id"));
|
||||||
|
String targetChatType = requestJson.getString("target_chat_type");
|
||||||
|
|
||||||
|
// original message
|
||||||
|
Message original = MessageDatabase.findById(originalMessageId);
|
||||||
|
if (original == null) {
|
||||||
|
response = new ResponseModel("error", "Original message not found.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//make forwarded message
|
||||||
|
Message forwarded = new Message(
|
||||||
|
UUID.randomUUID(),
|
||||||
|
currentUser.getInternal_uuid(),
|
||||||
|
targetChatType,
|
||||||
|
targetChatId,
|
||||||
|
original.getContent(),
|
||||||
|
original.getMessage_type(),
|
||||||
|
LocalDateTime.now(),
|
||||||
|
"SEND",
|
||||||
|
null, // reply_to_id
|
||||||
|
false, // is_edited
|
||||||
|
false, // is_deleted_globally
|
||||||
|
original.getMessage_id(), //original message id
|
||||||
|
currentUser.getInternal_uuid(), // forwarded_by
|
||||||
|
original.getSender_id(), // forwarded_from
|
||||||
|
null // edited_at
|
||||||
|
);
|
||||||
|
|
||||||
|
boolean success = MessageDatabase.saveForwardedMessage(forwarded);
|
||||||
|
if (success) {
|
||||||
|
response = new ResponseModel("success", "Message forwarded.");
|
||||||
|
// (اختیاری) ارسال ریل تایم به اعضای چت مقصد
|
||||||
|
} else {
|
||||||
|
response = new ResponseModel("error", "Failed to forward message.");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case "react_to_message": {
|
||||||
|
UUID messageId = UUID.fromString(requestJson.getString("message_id"));
|
||||||
|
String reaction = requestJson.getString("reaction");
|
||||||
|
boolean success = MessageReactionDatabase.saveOrUpdateReaction(messageId, currentUser.getInternal_uuid(), reaction);
|
||||||
|
|
||||||
|
response = success
|
||||||
|
? new ResponseModel("success", "Reaction saved.")
|
||||||
|
: new ResponseModel("error", "Failed to save reaction.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user