From 2b972c4b7cef7067bba670fd441989441a86656f Mon Sep 17 00:00:00 2001 From: Partow Roshani Date: Thu, 12 Jun 2025 12:25:28 +0330 Subject: [PATCH] Create groups an channels --- .../Client/ActionHandler.java | 193 +++++++++++++++++- .../telegramfinalproject/Client/Session.java | 8 + .../Database/ChannelDatabase.java | 86 +++++++- .../Database/GroupDatabase.java | 73 +++++++ .../telegramfinalproject/Models/JsonUtil.java | 12 ++ .../Server/ChannelService.java | 23 +++ .../Server/ClientHandler.java | 152 +++++++++++++- .../Server/GroupService.java | 23 +++ 8 files changed, 547 insertions(+), 23 deletions(-) create mode 100644 src/main/java/org/to/telegramfinalproject/Server/ChannelService.java create mode 100644 src/main/java/org/to/telegramfinalproject/Server/GroupService.java diff --git a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java index 4ba057c..e2db742 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Client/ActionHandler.java @@ -94,6 +94,117 @@ public class ActionHandler { } + private ChatEntry fetchChatInfo(String receiverId, String receiverType) { + JSONObject req = new JSONObject(); + req.put("action", "get_chat_info"); + req.put("receiver_id", receiverId); + req.put("receiver_type", receiverType); + out.println(req.toString()); + + try { + String responseText = in.readLine(); + if (responseText != null) { + JSONObject response = new JSONObject(responseText); + if (response.getString("status").equals("success")) { + JSONObject data = response.getJSONObject("data"); + return new ChatEntry( + receiverId, + data.getString("name"), + data.optString("image_url", ""), + receiverType, + null + ); + } + } + } catch (Exception e) { + System.err.println("Error fetching chat info: " + e.getMessage()); + } + + return new ChatEntry(receiverId, "[Unknown " + receiverType + "]", "", receiverType, null); + } + + + private void refreshChatList() { + JSONObject req = new JSONObject(); + req.put("action", "get_chat_list"); + req.put("user_id", Session.currentUser.getString("user_id")); + out.println(req.toString()); + + try { + String responseText = in.readLine(); + if (responseText != null) { + JSONObject response = new JSONObject(responseText); + if (response.getString("status").equals("success")) { + JSONArray chatListJson = response.getJSONObject("data").getJSONArray("chat_list"); + List chatList = new ArrayList<>(); + + for (Object obj : chatListJson) { + JSONObject chat = (JSONObject) obj; + ChatEntry entry = new ChatEntry( + chat.getString("id"), + chat.getString("name"), + chat.optString("image_url", ""), + chat.getString("type"), + chat.isNull("last_message_time") + ? null + : LocalDateTime.parse(chat.getString("last_message_time")) + ); + chatList.add(entry); + } + + Session.chatList = chatList; + System.out.println("✅ Chat list updated."); + } + } + } catch (Exception e) { + System.err.println("❌ Failed to refresh chat list: " + e.getMessage()); + } + } + + + public void createGroup() { + System.out.print("Enter group ID: "); + String groupId = scanner.nextLine(); + System.out.print("Enter group name: "); + String groupName = scanner.nextLine(); + System.out.print("Enter image URL (optional): "); + String imageUrl = scanner.nextLine(); + + JSONObject req = new JSONObject(); + req.put("action", "create_group"); + req.put("user_id", Session.getUserUUID()); + req.put("group_id", groupId); // ID قابل نمایش + req.put("group_name", groupName); + req.put("image_url", imageUrl.isBlank() ? JSONObject.NULL : imageUrl); + + send(req); + } + + + + public void createChannel() { + System.out.print("Enter channel ID: "); + String channelId = scanner.nextLine(); + System.out.print("Enter channel name: "); + String channelName = scanner.nextLine(); + System.out.print("Enter image URL (optional): "); + String imageUrl = scanner.nextLine(); + + JSONObject req = new JSONObject(); + req.put("action", "create_channel"); + req.put("user_id", Session.getUserUUID()); + req.put("channel_id", channelId); + req.put("channel_name", channelName); + req.put("image_url", imageUrl.isBlank() ? JSONObject.NULL : imageUrl); + + send(req); + } + + + + + + private void send(JSONObject request) { try { if (!request.has("action") || request.isNull("action")) { @@ -129,7 +240,7 @@ public class ActionHandler { ChatEntry entry = new ChatEntry( chat.getString("id"), chat.getString("name"), - chat.getString("image_url"), + chat.optString("image_url", ""), chat.getString("type"), chat.isNull("last_message_time") ? null : LocalDateTime.parse(chat.getString("last_message_time")) @@ -165,22 +276,86 @@ public class ActionHandler { JSONObject selected = results.getJSONObject(index); String type = selected.getString("type"); + switch (type) { case "user" -> { - UUID contactId = UUID.fromString(selected.getString("uuid")); // ✅ درست - addContact(contactId); + String userId = selected.getString("id"); + String uuid = selected.getString("uuid"); + + ChatEntry existing = Session.chatList.stream() + .filter(c -> c.getId().equals(userId) && c.getType().equals("private")) + .findFirst() + .orElse(null); + + if (existing != null) { + openChat(existing); + } else { + UUID contactId = UUID.fromString(uuid); + addContact(contactId); + ChatEntry newChat = fetchChatInfo(contactId.toString(), "private"); + refreshChatList(); + openChat(newChat); + } } case "group", "channel" -> { - joinGroupOrChannel(selected.getString("type"), selected.getString("uuid")); // ✅ + String id = selected.getString("id"); + String uuid = selected.getString("uuid"); + + ChatEntry existing = Session.chatList.stream() + .filter(c -> c.getId().equals(id) && c.getType().equals(type)) + .findFirst() + .orElse(null); + + if (existing != null) { + openChat(existing); + } else { + joinGroupOrChannel(type, uuid); + + ChatEntry newChat = fetchChatInfo(uuid, type); + refreshChatList(); + openChat(newChat); + } + } + + case "message" -> { + String receiverId = selected.getString("receiver_id"); + String receiverType = selected.getString("receiver_type"); + + ChatEntry chat = Session.chatList.stream() + .filter(c -> c.getId().equals(receiverId) && c.getType().equals(receiverType)) + .findFirst() + .orElseGet(() -> fetchChatInfo(receiverId, receiverType)); + + openChat(chat); } default -> System.out.println("No interaction available for type: " + type); } + } break; + case "create_group": + case "create_channel": + if (status.equals("success") && response.has("data")) { + JSONObject chatJson = response.getJSONObject("data"); + ChatEntry chat = new ChatEntry( + chatJson.getString("id"), + chatJson.getString("name"), + chatJson.optString("image_url", ""), + chatJson.getString("type"), + null + ); + refreshChatList(); + System.out.println("✅ Created and opening chat..."); + openChat(chat); + } + break; + + + case "get_messages": // Optional: handle later @@ -200,16 +375,18 @@ public class ActionHandler { System.out.println("\nUser Menu:"); System.out.println("1. Show chat list"); System.out.println("2. Search"); - System.out.println("3. Add contact"); - System.out.println("4. Logout"); + System.out.println("3. Create Channel"); + System.out.println("4. Create group"); + System.out.println("5. Logout"); System.out.print("Choose an option: "); String choice = scanner.nextLine(); switch (choice) { case "1" -> showChatListAndSelect(); case "2" -> search(); - case "3" -> addContact(internal_uuid); - case "4" -> { + case "3" -> createChannel(); + case "4" -> createGroup(); + case "5" -> { logout(); return; } diff --git a/src/main/java/org/to/telegramfinalproject/Client/Session.java b/src/main/java/org/to/telegramfinalproject/Client/Session.java index 9bf0d73..64270a1 100644 --- a/src/main/java/org/to/telegramfinalproject/Client/Session.java +++ b/src/main/java/org/to/telegramfinalproject/Client/Session.java @@ -10,4 +10,12 @@ import java.util.List; public class Session { public static JSONObject currentUser; public static List chatList; + + public static String getUserUUID() { + if (currentUser.has("uuid")) return currentUser.getString("uuid"); + if (currentUser.has("internal_uuid")) return currentUser.getString("internal_uuid"); + if (currentUser.has("internalUUID")) return currentUser.getString("internalUUID"); + throw new RuntimeException("❌ No UUID found in currentUser!"); + } + } \ No newline at end of file diff --git a/src/main/java/org/to/telegramfinalproject/Database/ChannelDatabase.java b/src/main/java/org/to/telegramfinalproject/Database/ChannelDatabase.java index 426c2c0..e6ca149 100644 --- a/src/main/java/org/to/telegramfinalproject/Database/ChannelDatabase.java +++ b/src/main/java/org/to/telegramfinalproject/Database/ChannelDatabase.java @@ -7,6 +7,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -139,16 +140,7 @@ public class ChannelDatabase { return false; } - public static void addSubscriber(UUID channelInternalId, UUID userId) { - String sql = "INSERT INTO channel_subscribe (channel_id, user_id) VALUES (?, ?) ON CONFLICT DO NOTHING"; - try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) { - stmt.setObject(1, channelInternalId); - stmt.setObject(2, userId); - stmt.executeUpdate(); - } catch (SQLException e) { - e.printStackTrace(); - } - } + public static UUID findInternalUUIDByChannelId(String channelId) { @@ -186,4 +178,78 @@ public class ChannelDatabase { } + public static boolean createChannel(Channel channel, UUID creatorId) { + String sql = """ + INSERT INTO channels ( + internal_uuid, channel_id, channel_name, + creator_id, image_url, description, created_at + ) + VALUES (gen_random_uuid(), ?, ?, ?, ?, ?, ?) + RETURNING internal_uuid + """; + + String subscriberSql = """ + INSERT INTO channel_subscribers (channel_id, user_id) VALUES (?, ?) + """; + + try (Connection conn = ConnectionDb.connect()) { + // مرحله اول: ساخت کانال + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, channel.getChannel_id()); + stmt.setString(2, channel.getChannel_name()); + stmt.setObject(3, creatorId); + stmt.setString(4, channel.getImage_url()); + stmt.setString(5, channel.getDescription()); + stmt.setObject(6, channel.getCreated_at()); + + ResultSet rs = stmt.executeQuery(); + if (!rs.next()) return false; + + UUID internalUUID = (UUID) rs.getObject("internal_uuid"); + channel.setInternal_uuid(internalUUID); // اختیاری برای پیگیری بعدی + + // مرحله دوم: افزودن کاربر به لیست سابسکرایبرها + PreparedStatement subStmt = conn.prepareStatement(subscriberSql); + subStmt.setObject(1, internalUUID); + subStmt.setObject(2, creatorId); + subStmt.executeUpdate(); + + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + + public static boolean insertChannel(UUID internalUUID, String channelId, String channelName, UUID creatorId, String imageUrl, LocalDateTime createdAt) { + String sql = "INSERT INTO channels (internal_uuid, channel_id, channel_name, creator_id, image_url, created_at) VALUES (?, ?, ?, ?, ?, ?)"; + + try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setObject(1, internalUUID); + stmt.setString(2, channelId); + stmt.setString(3, channelName); + stmt.setObject(4, creatorId); + stmt.setString(5, imageUrl); + stmt.setObject(6, createdAt); + stmt.executeUpdate(); + return true; + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + public static void addSubscriber(UUID channelId, UUID userId) { + String sql = "INSERT INTO channel_subscribers (channel_id, user_id) VALUES (?, ?) ON CONFLICT DO NOTHING"; + + try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setObject(1, channelId); + stmt.setObject(2, userId); + stmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + } diff --git a/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java b/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java index b05abb5..88fcae7 100644 --- a/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java +++ b/src/main/java/org/to/telegramfinalproject/Database/GroupDatabase.java @@ -6,6 +6,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -182,5 +183,77 @@ public class GroupDatabase { return false; } } + public static boolean createGroup(Group group, UUID creatorId) { + String sql = """ + INSERT INTO groups ( + internal_uuid, group_id, group_name, + creator_id, image_url, description, created_at + ) + VALUES (gen_random_uuid(), ?, ?, ?, ?, ?, ?) + RETURNING internal_uuid + """; + + String memberSql = """ + INSERT INTO group_members (group_id, user_id) VALUES (?, ?) + """; + + try (Connection conn = ConnectionDb.connect()) { + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, group.getGroup_id()); + stmt.setString(2, group.getGroup_name()); + stmt.setObject(3, creatorId); + stmt.setString(4, group.getImage_url()); + stmt.setString(5, group.getDescription()); + stmt.setObject(6, group.getCreated_at()); + + ResultSet rs = stmt.executeQuery(); + if (!rs.next()) return false; + + UUID internalUUID = (UUID) rs.getObject("internal_uuid"); + group.setInternal_uuid(internalUUID); + + PreparedStatement memberStmt = conn.prepareStatement(memberSql); + memberStmt.setObject(1, internalUUID); + memberStmt.setObject(2, creatorId); + memberStmt.executeUpdate(); + + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + + public static boolean insertGroup(UUID internalUUID, String groupId, String groupName, UUID creatorId, String imageUrl, LocalDateTime createdAt) { + String sql = "INSERT INTO groups (internal_uuid, group_id, group_name, creator_id, image_url, created_at) VALUES (?, ?, ?, ?, ?, ?)"; + + try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setObject(1, internalUUID); + stmt.setString(2, groupId); + stmt.setString(3, groupName); + stmt.setObject(4, creatorId); + stmt.setString(5, imageUrl); + stmt.setObject(6, createdAt); + stmt.executeUpdate(); + return true; + } catch (SQLException e) { + e.printStackTrace(); + return false; + } + } + + public static void addMember(UUID groupId, UUID userId, String role) { + String sql = "INSERT INTO group_members (group_id, user_id, role) VALUES (?, ?, ?) ON CONFLICT DO NOTHING"; + + try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setObject(1, groupId); + stmt.setObject(2, userId); + stmt.setString(3, role); + stmt.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/org/to/telegramfinalproject/Models/JsonUtil.java b/src/main/java/org/to/telegramfinalproject/Models/JsonUtil.java index 4e3a37f..f56159a 100644 --- a/src/main/java/org/to/telegramfinalproject/Models/JsonUtil.java +++ b/src/main/java/org/to/telegramfinalproject/Models/JsonUtil.java @@ -154,4 +154,16 @@ public class JsonUtil { } + public static JSONObject chatToJson(ChatEntry chat) { + JSONObject obj = new JSONObject(); + obj.put("id", chat.getId()); + obj.put("name", chat.getName()); + obj.put("image_url", chat.getImageUrl() != null ? chat.getImageUrl() : JSONObject.NULL); + obj.put("type", chat.getType()); + obj.put("last_message_time", chat.getLastMessageTime() != null ? chat.getLastMessageTime().toString() : JSONObject.NULL); + return obj; + } + + + } diff --git a/src/main/java/org/to/telegramfinalproject/Server/ChannelService.java b/src/main/java/org/to/telegramfinalproject/Server/ChannelService.java new file mode 100644 index 0000000..a8f7a33 --- /dev/null +++ b/src/main/java/org/to/telegramfinalproject/Server/ChannelService.java @@ -0,0 +1,23 @@ +package org.to.telegramfinalproject.Server; + +import org.to.telegramfinalproject.Models.Channel; +import org.to.telegramfinalproject.Database.ChannelDatabase; + +import java.time.LocalDateTime; +import java.util.UUID; + +public class ChannelService { + public static boolean createChannel(String channelId, String channelName, UUID creatorUUID, String imageUrl) { + UUID internalUUID = UUID.randomUUID(); + LocalDateTime now = LocalDateTime.now(); + + boolean inserted = ChannelDatabase.insertChannel(internalUUID, channelId, channelName, creatorUUID, imageUrl, now); + + if (inserted) { + ChannelDatabase.addSubscriber(internalUUID, creatorUUID); // اضافه کردن سازنده + return true; + } + return false; + } + +} diff --git a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java index adabffe..a6347ce 100644 --- a/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java +++ b/src/main/java/org/to/telegramfinalproject/Server/ClientHandler.java @@ -141,7 +141,7 @@ public class ClientHandler implements Runnable { JSONObject obj = new JSONObject(); obj.put("type", "user"); obj.put("id", u.getUser_id()); - obj.put("uuid", u.getInternal_uuid().toString()); // ✅ اضافه شود + obj.put("uuid", u.getInternal_uuid().toString()); obj.put("name", u.getProfile_name()); results.add(obj); } @@ -149,8 +149,8 @@ public class ClientHandler implements Runnable { for (Group g : GroupDatabase.searchGroups(keyword)) { JSONObject obj = new JSONObject(); obj.put("type", "group"); - obj.put("id", g.getGroup_id()); // قابل نمایش - obj.put("uuid", g.getInternal_uuid().toString()); // برای عملیات + obj.put("id", g.getGroup_id()); + obj.put("uuid", g.getInternal_uuid().toString()); obj.put("name", g.getGroup_name()); results.add(obj); } @@ -158,8 +158,8 @@ public class ClientHandler implements Runnable { for (Channel c : ChannelDatabase.searchChannels(keyword)) { JSONObject obj = new JSONObject(); obj.put("type", "channel"); - obj.put("id", c.getChannel_id()); // قابل نمایش - obj.put("uuid", c.getInternal_uuid().toString()); // برای عملیات + obj.put("id", c.getChannel_id()); + obj.put("uuid", c.getInternal_uuid().toString()); obj.put("name", c.getChannel_name()); results.add(obj); } @@ -171,6 +171,8 @@ public class ClientHandler implements Runnable { obj.put("content", m.getContent()); obj.put("sender", m.getSender_id().toString()); obj.put("time", m.getSend_at().toString()); + obj.put("receiver_id", m.getReceiver_id().toString()); + obj.put("receiver_type", m.getReceiver_type()); results.add(obj); } @@ -248,6 +250,146 @@ public class ClientHandler implements Runnable { } + case "get_chat_info": { + String id = requestJson.getString("receiver_id"); + String type = requestJson.getString("receiver_type"); + JSONObject data = new JSONObject(); + + switch (type) { + case "private" -> { + User u = new userDatabase().findByUserId(id); + if (u != null) { + data.put("name", u.getProfile_name()); + data.put("image_url", u.getImage_url()); + } else { + response = new ResponseModel("error", "User not found."); + break; + } + + } + case "group" -> { + Group g = GroupDatabase.findByGroupId(id); + if (g != null) { + data.put("name", g.getGroup_name()); + data.put("image_url", g.getImage_url()); + } else { + response = new ResponseModel("error", "Group not found."); + break; + } + } + case "channel" -> { + Channel c = ChannelDatabase.findByChannelId(id); + if (c != null) { + data.put("name", c.getChannel_name()); + data.put("image_url", c.getImage_url()); + } else { + response = new ResponseModel("error", "Channel not found."); + break; + } + } + + default -> { + response = new ResponseModel("error", "Unknown type."); + break; + } + } + + if (data.has("name")) { + response = new ResponseModel("success", "Chat info fetched", data); + } + + break; + } + + + case "get_chat_list": { + String userIdStr = requestJson.getString("user_id"); + User user = new userDatabase().findByUserId(userIdStr); + + List contacts = ContactDatabase.getContacts(user.getInternal_uuid()); + List groups = GroupDatabase.getGroupsByUser(user.getInternal_uuid()); + List channels = ChannelDatabase.getChannelsByUser(user.getInternal_uuid()); + + List chatList = new ArrayList<>(); + + for (Contact contact : contacts) { + User target = userDatabase.findByInternalUUID(contact.getContact_id()); + if (target == null) continue; + LocalDateTime last = MessageDatabase.getLastMessageTimeBetween(user.getInternal_uuid(), target.getInternal_uuid(), "private"); + + chatList.add(new ChatEntry(target.getUser_id(), target.getProfile_name(), target.getImage_url(), "private", last)); + } + + for (Group group : groups) { + LocalDateTime last = MessageDatabase.getLastMessageTime(group.getInternal_uuid(), "group"); + chatList.add(new ChatEntry(group.getGroup_id(), group.getGroup_name(), group.getImage_url(), "group", last)); + } + + for (Channel channel : channels) { + LocalDateTime last = MessageDatabase.getLastMessageTime(channel.getInternal_uuid(), "channel"); + chatList.add(new ChatEntry(channel.getChannel_id(), channel.getChannel_name(), channel.getImage_url(), "channel", last)); + } + + chatList.sort((a, b) -> { + if (a.getLastMessageTime() == null) return 1; + if (b.getLastMessageTime() == null) return -1; + return b.getLastMessageTime().compareTo(a.getLastMessageTime()); + }); + + JSONObject data = new JSONObject(); + data.put("chat_list", JsonUtil.chatListToJson(chatList)); + + response = new ResponseModel("success", "Chat list updated.", data); + break; + } + case "create_group": { + try { + String groupId = requestJson.getString("group_id"); // ID نمایشی + String groupName = requestJson.getString("group_name"); + String userIdStr = requestJson.getString("user_id"); + String imageUrl = requestJson.optString("image_url", null); + + UUID creatorUUID = UUID.fromString(userIdStr); + + boolean created = GroupService.createGroup(groupId, groupName, creatorUUID, imageUrl); + + response = created + ? new ResponseModel("success", "Group created.") + : new ResponseModel("error", "Group creation failed."); + + } catch (Exception e) { + response = new ResponseModel("error", "Error creating group: " + e.getMessage()); + } + break; + } + + case "create_channel": { + try { + String channelId = requestJson.getString("channel_id"); + String channelName = requestJson.getString("channel_name"); + String userIdStr = requestJson.getString("user_id"); + String imageUrl = requestJson.optString("image_url", null); + + UUID creatorUUID = UUID.fromString(userIdStr); + + boolean created = ChannelService.createChannel(channelId, channelName, creatorUUID, imageUrl); + + response = created + ? new ResponseModel("success", "Channel created.") + : new ResponseModel("error", "Channel creation failed."); + + } catch (Exception e) { + response = new ResponseModel("error", "Error creating channel: " + e.getMessage()); + } + break; + } + + + + + + + default: response = new ResponseModel("error", "Unknown action: " + action); } diff --git a/src/main/java/org/to/telegramfinalproject/Server/GroupService.java b/src/main/java/org/to/telegramfinalproject/Server/GroupService.java new file mode 100644 index 0000000..31da28b --- /dev/null +++ b/src/main/java/org/to/telegramfinalproject/Server/GroupService.java @@ -0,0 +1,23 @@ +package org.to.telegramfinalproject.Server; + +import org.to.telegramfinalproject.Models.Group; +import org.to.telegramfinalproject.Database.GroupDatabase; + +import java.time.LocalDateTime; +import java.util.UUID; + +public class GroupService { + public static boolean createGroup(String groupId, String groupName, UUID creatorUUID, String imageUrl) { + UUID internalUUID = UUID.randomUUID(); + LocalDateTime now = LocalDateTime.now(); + + boolean inserted = GroupDatabase.insertGroup(internalUUID, groupId, groupName, creatorUUID, imageUrl, now); + + if (inserted) { + GroupDatabase.addMember(internalUUID, creatorUUID, "owner"); // سازنده owner می‌شود + return true; + } + return false; + } + +}