update contact list

This commit is contained in:
2025-08-04 16:41:23 +03:30
parent 83a29d5ea1
commit 96fa7264cf
10 changed files with 309 additions and 30 deletions
@@ -2959,7 +2959,7 @@ public class ActionHandler {
}
case "2" -> {
addContact(chat.getId());
refreshChatList();
refreshContactList();
}
default -> System.out.println("Back...");
}
@@ -3213,6 +3213,59 @@ public class ActionHandler {
}
}
private void refreshContactList() {
JSONObject req = new JSONObject();
req.put("action", "get_contact_list");
req.put("user_id", Session.currentUser.getString("user_id"));
out.println(req.toString());
try {
JSONObject response = TelegramClient.responseQueue.take();
if (response != null && response.getString("status").equals("success")) {
if (response.has("data") && !response.isNull("data")) {
JSONObject data = response.getJSONObject("data");
if (!data.has("contact_list") || data.isNull("contact_list")) {
System.out.println("❌ contact_list not found in response data.");
return;
}
JSONArray contactListJson = data.getJSONArray("contact_list");
List<ContactEntry> contactList = new ArrayList<>();
for (Object obj : contactListJson) {
JSONObject c = (JSONObject) obj;
ContactEntry entry = new ContactEntry(
UUID.fromString(c.getString("contact_id")),
c.getString("user_id"),
c.getString("profile_name"),
c.optString("image_url", ""),
c.optBoolean("is_blocked", false)
);
contactList.add(entry);
}
Session.contactEntries = contactList;
System.out.println("✅ Contact list updated. Total: " + contactList.size());
} else {
System.out.println("⚠️ Response has no data object.");
}
} else {
if (response.has("message") && !response.isNull("message")) {
System.out.println("❌ Failed to refresh contact list: " + response.getString("message"));
} else {
System.out.println("❌ Failed to refresh contact list.");
}
}
} catch (Exception e) {
System.err.println("❌ Error during refreshContactList: " + e.getMessage());
e.printStackTrace();
}
}
@@ -79,19 +79,19 @@ public class IncomingMessageListener implements Runnable {
"update_group_or_channel", "chat_deleted",
"blocked_by_user", "unblocked_by_user", "message_seen",
"removed_from_group", "removed_from_channel",
"became_admin", "removed_admin", "ownership_transferred","admin_permissions_updated" -> true;
"became_admin", "removed_admin", "ownership_transferred","admin_permissions_updated","created_private_chat" -> true;
default -> false;
};
}
void handleRealTimeEvent(JSONObject response) throws IOException {
String action = response.getString("action");
JSONObject msg = response.getJSONObject("data");
JSONObject msg = response.has("data") ? response.getJSONObject("data") : new JSONObject();
switch (action) {
case "added_to_group", "added_to_channel",
"removed_from_group", "removed_from_channel", "chat_deleted" -> {
"removed_from_group", "removed_from_channel", "chat_deleted","created_private_chat" -> {
System.out.println("🔄 Chat list changed. Updating...");
Session.forceRefreshChatList = true;
System.out.println("🧪 Calling requestChatList() after being added");
@@ -135,10 +135,6 @@ public class IncomingMessageListener implements Runnable {
}
//
default -> displayRealTimeMessage(action, msg);
}
@@ -27,8 +27,7 @@ public class Session {
public static String currentChatId = null;
public static ChatEntry currentChatEntry = null;
public static List<ContactEntry> contactEntries = new ArrayList<>();
public static boolean inContactListMenu = false;
public static String getUserUUID() {
@@ -1,6 +1,7 @@
package org.to.telegramfinalproject.Database;
import org.to.telegramfinalproject.Models.Contact;
import org.to.telegramfinalproject.Models.ContactEntry;
import org.to.telegramfinalproject.Models.User;
import java.sql.*;
@@ -268,5 +269,39 @@ public class ContactDatabase {
}
}
public static List<ContactEntry> getContactEntries(UUID userId) {
List<ContactEntry> entries = new ArrayList<>();
String sql = """
SELECT c.contact_id, c.is_blocked, u.user_id, u.profile_name, u.image_url
FROM contacts c
JOIN users u ON c.contact_id = u.internal_uuid
WHERE c.user_id = ?
""";
try (Connection conn = ConnectionDb.connect();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setObject(1, userId);
ResultSet rs = ps.executeQuery();
while (rs.next()) {
UUID contactId = UUID.fromString(rs.getString("contact_id"));
boolean isBlocked = rs.getBoolean("is_blocked");
String userIdStr = rs.getString("user_id");
String profileName = rs.getString("profile_name");
String imageUrl = rs.getString("image_url");
ContactEntry entry = new ContactEntry(contactId, userIdStr, profileName, imageUrl, isBlocked);
entries.add(entry);
}
} catch (SQLException e) {
e.printStackTrace();
}
return entries;
}
}
@@ -76,7 +76,7 @@ public class MessageDatabase {
}
public static void logDeletedMessagesFor(UUID chatId, UUID userId) {
List<Message> messages = MessageDatabase.privateChatHistory(chatId);
List<Message> messages = MessageDatabase.privateChatHistory(chatId, userId);
for (Message message : messages) {
if (!isMessageDeleted(message.getMessage_id(), userId)) {
String sql = """
@@ -306,18 +306,45 @@ public class MessageDatabase {
return result;
}
public static List<Message> privateChatHistory(UUID chatId) {
// public static List<Message> privateChatHistory(UUID chatId) {
// List<Message> result = new ArrayList<>();
// String sql = """
// SELECT * FROM messages
// WHERE receiver_type = 'private'
// AND receiver_id = ?
// ORDER BY send_at
// """;
//
// try (Connection conn = ConnectionDb.connect();
// PreparedStatement stmt = conn.prepareStatement(sql)) {
// stmt.setObject(1, chatId);
// ResultSet rs = stmt.executeQuery();
// while (rs.next()) {
// result.add(extractMessage(rs));
// }
// } catch (SQLException e) {
// e.printStackTrace();
// }
// return result;
// }
public static List<Message> privateChatHistory(UUID chatId, UUID userId) {
List<Message> result = new ArrayList<>();
String sql = """
SELECT * FROM messages
WHERE receiver_type = 'private'
AND receiver_id = ?
AND receiver_id = ?
AND is_deleted_globally = FALSE
AND message_id NOT IN (
SELECT message_id FROM deleted_messages WHERE user_id = ?
)
ORDER BY send_at
""";
try (Connection conn = ConnectionDb.connect();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setObject(1, chatId);
stmt.setObject(2, userId);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
result.add(extractMessage(rs));
@@ -331,11 +358,39 @@ public class MessageDatabase {
public static List<Message> groupChatHistory(UUID groupId) {
// public static List<Message> groupChatHistory(UUID groupId) {
// List<Message> result = new ArrayList<>();
// String sql = """
// SELECT * FROM messages
// WHERE receiver_type = 'group' AND receiver_id = ?
// ORDER BY send_at
// """;
//
// try (Connection conn = ConnectionDb.connect();
// PreparedStatement stmt = conn.prepareStatement(sql)) {
// stmt.setObject(1, groupId);
// ResultSet rs = stmt.executeQuery();
// while (rs.next()) {
// result.add(extractMessage(rs));
// }
// } catch (SQLException e) {
// e.printStackTrace();
// }
// return result;
// }
public static List<Message> groupChatHistory(UUID groupId,UUID userId) {
List<Message> result = new ArrayList<>();
String sql = """
SELECT * FROM messages
WHERE receiver_type = 'group' AND receiver_id = ?
WHERE receiver_type = 'group'
AND receiver_id = ?
AND is_deleted_globally = FALSE
AND message_id NOT IN (
SELECT message_id FROM deleted_messages WHERE user_id = ?
)
ORDER BY send_at
""";
@@ -353,11 +408,39 @@ public class MessageDatabase {
}
public static List<Message> channelChatHistory(UUID channelId) {
// public static List<Message> channelChatHistory(UUID channelId) {
// List<Message> result = new ArrayList<>();
// String sql = """
// SELECT * FROM messages
// WHERE receiver_type = 'channel' AND receiver_id = ?
// ORDER BY send_at
// """;
//
// try (Connection conn = ConnectionDb.connect();
// PreparedStatement stmt = conn.prepareStatement(sql)) {
// stmt.setObject(1, channelId);
// ResultSet rs = stmt.executeQuery();
// while (rs.next()) {
// result.add(extractMessage(rs));
// }
// } catch (SQLException e) {
// e.printStackTrace();
// }
// return result;
// }
public static List<Message> channelChatHistory(UUID channelId,UUID userId) {
List<Message> result = new ArrayList<>();
String sql = """
SELECT * FROM messages
WHERE receiver_type = 'channel' AND receiver_id = ?
WHERE receiver_type = 'channel'
AND receiver_id = ?
AND is_deleted_globally = FALSE
AND message_id NOT IN (
SELECT message_id FROM deleted_messages WHERE user_id = ?
)
ORDER BY send_at
""";
@@ -375,6 +458,7 @@ public class MessageDatabase {
}
public static List<Message> searchMessagesInGroups(List<UUID> groupIds, String keyword) {
List<Message> result = new ArrayList<>();
if (groupIds.isEmpty()) return result;
@@ -251,7 +251,28 @@ public class PrivateChatDatabase {
}
public static UUID findChatBetween(UUID user1, UUID user2) {
String sql = """
SELECT chat_id FROM private_chat
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, user1);
ps.setObject(2, user2);
ps.setObject(3, user2);
ps.setObject(4, user1);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return (UUID) rs.getObject("chat_id");
}
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
}
@@ -40,5 +40,4 @@ public class Contact {
}
@@ -1,5 +1,7 @@
package org.to.telegramfinalproject.Models;
import org.json.JSONObject;
import java.util.UUID;
public class ContactEntry {
@@ -41,4 +43,16 @@ public class ContactEntry {
public String toString() {
return profileName + " (" + userId + ")" + (isBlocked ? " [Blocked]" : "");
}
public JSONObject toJson() {
JSONObject obj = new JSONObject();
obj.put("contact_id", contactId.toString());
obj.put("user_id", userId);
obj.put("profile_name", profileName);
obj.put("image_url", imageUrl);
obj.put("is_blocked", isBlocked);
return obj;
}
}
@@ -2,6 +2,7 @@ package org.to.telegramfinalproject.Models;
import org.json.JSONArray;
import org.json.JSONObject;
import org.to.telegramfinalproject.Database.userDatabase;
import java.time.LocalDateTime;
import java.util.List;
@@ -9,20 +10,43 @@ import java.util.UUID;
public class JsonUtil {
public static JSONArray contactListToJson(List<Contact> contacts) {
JSONArray array = new JSONArray();
for (Contact contact : contacts) {
UUID contactId = contact.getContact_id();
User contactUser = userDatabase.findByInternalUUID(contactId);
if (contactUser == null) continue;
JSONObject obj = new JSONObject();
obj.put("user_id", contact.getUser_id().toString());
obj.put("contact_id", contact.getContact_id().toString());
obj.put("contact_id", contactId.toString()); // UUID
obj.put("user_id", contactUser.getUser_id()); // public ID
obj.put("profile_name", contactUser.getProfile_name());
obj.put("image_url", contactUser.getImage_url());
obj.put("is_blocked", contact.getIs_blocked());
obj.put("added_at", contact.getAdd_at().toString());
array.put(obj);
}
return array;
}
public static JSONArray contactEntryListToJson(List<ContactEntry> contactEntries) {
JSONArray array = new JSONArray();
for (ContactEntry entry : contactEntries) {
JSONObject obj = new JSONObject();
obj.put("contact_id", entry.getContactId().toString());
obj.put("user_id", entry.getUserId());
obj.put("profile_name", entry.getProfileName());
obj.put("image_url", entry.getImageUrl());
obj.put("is_blocked", entry.isBlocked());
array.put(obj);
}
return array;
}
@@ -486,6 +486,7 @@ public class ClientHandler implements Runnable {
currentUser.getImage_url(),
contactUUID
);
}
response = success
@@ -1265,7 +1266,7 @@ public class ClientHandler implements Runnable {
break;
}
messages = MessageDatabase.privateChatHistory(chatId);
messages = MessageDatabase.privateChatHistory(chatId, currentUser.getInternal_uuid());
}
@@ -1275,7 +1276,7 @@ public class ClientHandler implements Runnable {
response = new ResponseModel("error", "Group not found.");
break;
}
messages = MessageDatabase.groupChatHistory(group.getInternal_uuid());
messages = MessageDatabase.groupChatHistory(group.getInternal_uuid(),currentUser.getInternal_uuid());
}
@@ -1285,7 +1286,7 @@ public class ClientHandler implements Runnable {
response = new ResponseModel("error", "Channel not found.");
break;
}
messages = MessageDatabase.channelChatHistory(channel.getInternal_uuid());
messages = MessageDatabase.channelChatHistory(channel.getInternal_uuid(),currentUser.getInternal_uuid());
}
default -> {
response = new ResponseModel("error", "Invalid receiver type.");
@@ -1988,7 +1989,6 @@ public class ClientHandler implements Runnable {
}
break;
case "get_or_create_private_chat": {
if (currentUser == null) {
response = new ResponseModel("error", "Unauthorized. Please login first.");
@@ -1999,7 +1999,23 @@ public class ClientHandler implements Runnable {
UUID user1 = UUID.fromString(requestJson.getString("user1"));
UUID user2 = UUID.fromString(requestJson.getString("user2"));
UUID oldChat = PrivateChatDatabase.findChatBetween(user1, user2);
UUID chatId = PrivateChatDatabase.getOrCreateChat(user1, user2);
boolean isNew = oldChat == null;
if (isNew) {
JSONObject chatPayload = new JSONObject();
chatPayload.put("action", "created_private_chat");
JSONObject chatData = new JSONObject();
chatData.put("chat_id", chatId.toString());
chatData.put("chat_type", "private");
chatData.put("last_message_time", LocalDateTime.now().toString());
chatPayload.put("data", chatData);
RealTimeEventDispatcher.sendToUser(user1, chatPayload);
RealTimeEventDispatcher.sendToUser(user2, chatPayload);
}
JSONObject data = new JSONObject();
data.put("chat_id", chatId.toString());
@@ -2014,6 +2030,7 @@ public class ClientHandler implements Runnable {
case "get_private_chat_target": {
UUID chatId = UUID.fromString(requestJson.getString("chat_id"));
userId = currentUser.getInternal_uuid();
@@ -2029,6 +2046,43 @@ public class ClientHandler implements Runnable {
break;
}
case "get_contact_list": {
if (currentUser == null) {
response = new ResponseModel("error", "Unauthorized. Please login first.");
break;
}
List<Contact> contacts = ContactDatabase.getContacts(currentUser.getInternal_uuid());
List<ContactEntry> contactEntries = new ArrayList<>();
for (Contact contact : contacts) {
UUID contactId = contact.getContact_id();
User contactUser = userDatabase.findByInternalUUID(contactId);
if (contactUser == null) continue;
ContactEntry entry = new ContactEntry(
contactId,
contactUser.getUser_id(),
contactUser.getProfile_name(),
contactUser.getImage_url(),
contact.getIs_blocked()
);
contactEntries.add(entry);
}
// Optional: sort alphabetically
contactEntries.sort(Comparator.comparing(ContactEntry::getProfileName, String.CASE_INSENSITIVE_ORDER));
JSONObject data = new JSONObject();
data.put("contact_list", JsonUtil.contactEntryListToJson(contactEntries));
response = new ResponseModel("success", "Contact list refreshed", data);
break;
}