Merge pull request #5 from PartowRoshani/Real-Time-update
Real-Time-update
This commit is contained in:
@@ -13,4 +13,6 @@ module org.to.telegramfinalproject {
|
|||||||
requires java.sql;
|
requires java.sql;
|
||||||
opens org.to.telegramfinalproject to javafx.fxml;
|
opens org.to.telegramfinalproject to javafx.fxml;
|
||||||
exports org.to.telegramfinalproject;
|
exports org.to.telegramfinalproject;
|
||||||
|
exports org.to.telegramfinalproject.Client;
|
||||||
|
opens org.to.telegramfinalproject.Client to javafx.fxml;
|
||||||
}
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
|||||||
|
package org.to.telegramfinalproject.Client;
|
||||||
|
|
||||||
|
public class EventProcessorThread extends Thread {
|
||||||
|
private final ActionHandler handler;
|
||||||
|
|
||||||
|
public EventProcessorThread(ActionHandler handler) {
|
||||||
|
this.handler = handler;
|
||||||
|
setDaemon(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(2000);
|
||||||
|
handler.processIncomingEvents();
|
||||||
|
} catch (InterruptedException ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
package org.to.telegramfinalproject.Client;
|
||||||
|
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
|
||||||
|
public class IncomingMessageListener implements Runnable {
|
||||||
|
private final BufferedReader in;
|
||||||
|
|
||||||
|
public IncomingMessageListener(BufferedReader in) {
|
||||||
|
this.in = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
System.out.println("👂 Real-Time Listener started.");
|
||||||
|
|
||||||
|
String line;
|
||||||
|
while ((line = in.readLine()) != null) {
|
||||||
|
JSONObject response = new JSONObject(line);
|
||||||
|
System.out.println("📥 Received raw line: " + line);
|
||||||
|
|
||||||
|
if (response.has("action")) {
|
||||||
|
String action = response.getString("action");
|
||||||
|
if (isRealTimeEvent(action)) {
|
||||||
|
handleRealTimeEvent(response);
|
||||||
|
} else {
|
||||||
|
TelegramClient.responseQueue.put(response);
|
||||||
|
}
|
||||||
|
} else if (response.has("status") && response.has("message")) {
|
||||||
|
TelegramClient.responseQueue.put(response);
|
||||||
|
} else {
|
||||||
|
TelegramClient.responseQueue.put(response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("🔴 Listener stopped: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRealTimeEvent(String action) {
|
||||||
|
return switch (action) {
|
||||||
|
case "new_message", "message_edited", "message_deleted",
|
||||||
|
"user_status_changed", "added_to_group", "added_to_channel",
|
||||||
|
"update_group_or_channel", "chat_deleted",
|
||||||
|
"blocked_by_user", "unblocked_by_user", "message_seen" -> true;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleRealTimeEvent(JSONObject response) {
|
||||||
|
String action = response.getString("action");
|
||||||
|
JSONObject msg = response.getJSONObject("data");
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case "new_message" -> {
|
||||||
|
System.out.println("\n🔔 New Message:");
|
||||||
|
System.out.println("From: " + msg.getString("sender"));
|
||||||
|
System.out.println("Time: " + msg.getString("time"));
|
||||||
|
System.out.println("Content: " + msg.getString("content"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "message_edited" -> {
|
||||||
|
System.out.println("\n✏️ Message Edited:");
|
||||||
|
System.out.println("ID: " + msg.getString("message_id"));
|
||||||
|
System.out.println("New Content: " + msg.getString("new_content"));
|
||||||
|
System.out.println("Edit Time: " + msg.getString("edited_at"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "message_deleted" -> {
|
||||||
|
System.out.println("\n🗑️ Message Deleted:");
|
||||||
|
System.out.println("Message ID: " + msg.getString("message_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "user_status_changed" -> {
|
||||||
|
System.out.println("\n🔄 User Status Changed:");
|
||||||
|
System.out.println("User: " + msg.getString("user_id"));
|
||||||
|
System.out.println("Status: " + msg.getString("status"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "added_to_group" -> {
|
||||||
|
System.out.println("\n👥 You were added to a group: " + msg.getString("chat_name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "added_to_channel" -> {
|
||||||
|
System.out.println("\n📢 You were added to a channel: " + msg.getString("chat_name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "update_group_or_channel" -> {
|
||||||
|
System.out.println("\n🔄 Group/Channel updated: " + msg.getString("new_name"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "chat_deleted" -> {
|
||||||
|
System.out.println("\n🗑️ Chat deleted: " + msg.getString("chat_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "blocked_by_user" -> {
|
||||||
|
System.out.println("\n⛔ You were blocked by user: " + msg.getString("blocker_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "unblocked_by_user" -> {
|
||||||
|
System.out.println("\n✅ You were unblocked by user: " + msg.getString("unblocker_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
case "message_seen" -> {
|
||||||
|
System.out.println("\n👁️ Your message was seen:");
|
||||||
|
System.out.println("Message ID: " + msg.getString("message_id"));
|
||||||
|
System.out.println("Seen at: " + msg.getString("seen_at"));
|
||||||
|
}
|
||||||
|
|
||||||
|
default -> {
|
||||||
|
System.out.println("\n❓ Unknown real-time action: " + action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.print(">> ");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package org.to.telegramfinalproject.Client;
|
||||||
|
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
public class RealTimeBuffer {
|
||||||
|
public static final BlockingQueue<JSONObject> incomingEvents = new LinkedBlockingQueue<>();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -10,4 +10,12 @@ import java.util.List;
|
|||||||
public class Session {
|
public class Session {
|
||||||
public static JSONObject currentUser;
|
public static JSONObject currentUser;
|
||||||
public static List<ChatEntry> chatList;
|
public static List<ChatEntry> 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!");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -8,15 +8,19 @@ import java.io.InputStreamReader;
|
|||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
public class TelegramClient {
|
public class TelegramClient {
|
||||||
private static final String SERVER_HOST = "localhost";
|
private static final String SERVER_HOST = "localhost";
|
||||||
private static final int SERVER_PORT = 12345;
|
private static final int SERVER_PORT = 8000;
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
private BufferedReader in;
|
private BufferedReader in;
|
||||||
private PrintWriter out;
|
private PrintWriter out;
|
||||||
private final Scanner scanner;
|
private final Scanner scanner;
|
||||||
ActionHandler handler = null;
|
ActionHandler handler = null;
|
||||||
|
public static BlockingQueue<JSONObject> responseQueue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
public TelegramClient() {
|
public TelegramClient() {
|
||||||
this.scanner = new Scanner(System.in);
|
this.scanner = new Scanner(System.in);
|
||||||
@@ -27,72 +31,51 @@ public class TelegramClient {
|
|||||||
this.socket = new Socket(SERVER_HOST, SERVER_PORT);
|
this.socket = new Socket(SERVER_HOST, SERVER_PORT);
|
||||||
this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
|
this.in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
|
||||||
this.out = new PrintWriter(this.socket.getOutputStream(), true);
|
this.out = new PrintWriter(this.socket.getOutputStream(), true);
|
||||||
System.out.println(" Connected to Telegram Server");
|
System.out.println("✅ Connected to Telegram Server");
|
||||||
this.handler = new ActionHandler(this.out, this.in, this.scanner);
|
this.handler = new ActionHandler(this.out, this.in, this.scanner);
|
||||||
this.showMainMenu();
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Error connecting to server: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Thread listenerThread = new Thread(new IncomingMessageListener(in));
|
||||||
|
listenerThread.setDaemon(true);
|
||||||
|
listenerThread.start();
|
||||||
|
|
||||||
|
showMainMenu();
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("❌ Error connecting to server: " + e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showMainMenu() {
|
private void showMainMenu() {
|
||||||
while(true) {
|
while (true) {
|
||||||
System.out.println("Main Menu:");
|
System.out.println("Main Menu:");
|
||||||
System.out.println("1. Register");
|
System.out.println("1. Register");
|
||||||
System.out.println("2. Login");
|
System.out.println("2. Login");
|
||||||
System.out.println("3. Exit");
|
System.out.println("3. Exit");
|
||||||
System.out.print("Choose an option: ");
|
System.out.print("Choose an option: ");
|
||||||
switch (this.scanner.nextLine()) {
|
String choice = scanner.nextLine();
|
||||||
case "1":
|
|
||||||
this.handler.register();
|
switch (choice) {
|
||||||
break;
|
case "1" -> handler.register();
|
||||||
case "2":
|
case "2" -> {
|
||||||
this.handler.loginHandler();
|
handler.loginHandler();
|
||||||
if (Session.currentUser != null) {
|
if (Session.currentUser != null) {
|
||||||
System.out.println("Login successful.");
|
System.out.println("✅ Login successful.");
|
||||||
this.handler.userMenu();
|
UUID internalId = UUID.fromString(Session.currentUser.getString("internal_uuid"));
|
||||||
|
handler.userMenu(internalId);
|
||||||
} else {
|
} else {
|
||||||
System.out.println("Login failed.");
|
System.out.println("❌ Login failed.");
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case "3":
|
case "3" -> {
|
||||||
System.out.println("Disconnecting...");
|
System.out.println("Exiting...");
|
||||||
|
|
||||||
if (Session.currentUser != null && Session.currentUser.has("internalUUID")) {
|
|
||||||
try {
|
|
||||||
JSONObject logoutRequest = new JSONObject();
|
|
||||||
logoutRequest.put("action", "logout");
|
|
||||||
logoutRequest.put("user_id", Session.currentUser.getString("internalUUID"));
|
|
||||||
out.println(logoutRequest.toString());
|
|
||||||
in.readLine();
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("Failed to notify server on logout: " + e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (socket != null) socket.close();
|
|
||||||
if (in != null) in.close();
|
|
||||||
if (out != null) out.close();
|
|
||||||
System.out.println("Disconnected.");
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println("Error closing connection: " + e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
default -> System.out.println("Invalid choice.");
|
||||||
default:
|
|
||||||
System.out.println("Invalid choice. Please try again.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
TelegramClient client = new TelegramClient();
|
new TelegramClient().start();
|
||||||
client.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.to.telegramfinalproject.Database;
|
package org.to.telegramfinalproject.Database;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
import org.to.telegramfinalproject.Models.Channel;
|
import org.to.telegramfinalproject.Models.Channel;
|
||||||
import org.to.telegramfinalproject.Models.Group;
|
import org.to.telegramfinalproject.Models.Group;
|
||||||
|
|
||||||
@@ -7,6 +9,7 @@ import java.sql.Connection;
|
|||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -75,4 +78,527 @@ public class ChannelDatabase {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<UUID> getSubscriberUUIDs(UUID channelInternalUUID) {
|
||||||
|
List<UUID> subscriberIds = new ArrayList<>();
|
||||||
|
String sql = "SELECT user_id FROM channel_subscribers WHERE channel_id = ?";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelInternalUUID);
|
||||||
|
|
||||||
|
try (ResultSet rs = stmt.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
subscriberIds.add((UUID) rs.getObject("user_id"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscriberIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Channel findByChannelId(String channelId) {
|
||||||
|
String sql = "SELECT * FROM channels WHERE channel_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setString(1, channelId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
if (rs.next()) {
|
||||||
|
Channel channel = new Channel();
|
||||||
|
channel.setInternal_uuid(UUID.fromString(rs.getString("internal_uuid")));
|
||||||
|
channel.setChannel_id(rs.getString("channel_id"));
|
||||||
|
channel.setChannel_name(rs.getString("channel_name"));
|
||||||
|
channel.setImage_url(rs.getString("image_url"));
|
||||||
|
channel.setCreator_id(UUID.fromString(rs.getString("creator_id")));
|
||||||
|
channel.setDescription(rs.getString("description"));
|
||||||
|
channel.setCreated_at(rs.getTimestamp("created_at").toLocalDateTime());
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isUserSubscribed(UUID userId, UUID channelInternalId) {
|
||||||
|
String sql = "SELECT * FROM channel_subscribers WHERE user_id = ? AND channel_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, userId);
|
||||||
|
stmt.setObject(2, channelInternalId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
return rs.next();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static UUID findInternalUUIDByChannelId(String channelId) {
|
||||||
|
String sql = "SELECT internal_uuid FROM channels WHERE channel_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, channelId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return (UUID) rs.getObject("internal_uuid");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean addSubscriberToChannel(UUID userId, UUID channelUUID) {
|
||||||
|
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, channelUUID);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 role) {
|
||||||
|
String sql = "INSERT INTO channel_subscribers (channel_id, user_id, role) VALUES (?, ?, ?) ON CONFLICT DO NOTHING";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
stmt.setString(3, role);
|
||||||
|
|
||||||
|
stmt.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Channel findByInternalUUID(UUID internalUUID) {
|
||||||
|
String sql = "SELECT * FROM channels WHERE internal_uuid = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, internalUUID);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
if (rs.next()) {
|
||||||
|
Channel channel = new Channel();
|
||||||
|
channel.setInternal_uuid(UUID.fromString(rs.getString("internal_uuid")));
|
||||||
|
channel.setChannel_id(rs.getString("channel_id"));
|
||||||
|
channel.setChannel_name(rs.getString("channel_name"));
|
||||||
|
channel.setImage_url(rs.getString("image_url"));
|
||||||
|
channel.setCreator_id(UUID.fromString(rs.getString("creator_id")));
|
||||||
|
channel.setDescription(rs.getString("description"));
|
||||||
|
channel.setCreated_at(rs.getTimestamp("created_at").toLocalDateTime());
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean addOwnerToChannel(UUID channelId, UUID userId) {
|
||||||
|
String sql = "INSERT INTO channel_subscribers (channel_id, user_id, role) VALUES (?, ?, 'owner')";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean addAdminToChannel(UUID channelId, UUID userId, JSONObject permissions) {
|
||||||
|
String sql = "UPDATE channel_subscribers SET role = 'admin', permissions = ?::jsonb WHERE channel_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, permissions.toString());
|
||||||
|
stmt.setObject(2, channelId);
|
||||||
|
stmt.setObject(3, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getChannelRole(UUID channelId, UUID userId) {
|
||||||
|
String sql = "SELECT role FROM channel_subscribers WHERE channel_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return rs.getString("role");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "subscriber"; // پیشفرض
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static JSONObject getChannelPermissions(UUID channelId, UUID userId) {
|
||||||
|
String sql = "SELECT permissions FROM channel_subscribers WHERE channel_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return new JSONObject(rs.getString("permissions"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return new JSONObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean updateChannelAdminPermissions(UUID channelId, UUID userId, JSONObject permissions) {
|
||||||
|
String sql = "UPDATE channel_subscribers SET permissions = ?::jsonb WHERE channel_id = ? AND user_id = ? AND role = 'admin'";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, permissions.toString());
|
||||||
|
stmt.setObject(2, channelId);
|
||||||
|
stmt.setObject(3, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<JSONObject> getChannelAdminsAndOwner(UUID channelId) {
|
||||||
|
List<JSONObject> admins = new ArrayList<>();
|
||||||
|
|
||||||
|
String sql = """
|
||||||
|
SELECT u.internal_uuid, u.profile_name, u.user_id, cs.role, cs.permissions
|
||||||
|
FROM channel_subscribers cs
|
||||||
|
JOIN users u ON cs.user_id = u.internal_uuid
|
||||||
|
WHERE cs.channel_id = ? AND (cs.role = 'owner' OR cs.role = 'admin')
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
|
||||||
|
try (ResultSet rs = stmt.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put("internal_uuid", rs.getObject("internal_uuid").toString());
|
||||||
|
obj.put("profile_name", rs.getString("profile_name"));
|
||||||
|
obj.put("user_id", rs.getString("user_id"));
|
||||||
|
obj.put("role", rs.getString("role"));
|
||||||
|
obj.put("permissions", new JSONObject(rs.getString("permissions")));
|
||||||
|
admins.add(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return admins;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isOwner(UUID channelId, UUID userId) {
|
||||||
|
String sql = "SELECT role FROM channel_subscribers WHERE channel_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return "owner".equals(rs.getString("role"));
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isAdmin(UUID channelId, UUID userId) {
|
||||||
|
String sql = "SELECT role FROM channel_subscribers WHERE channel_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
String role = rs.getString("role");
|
||||||
|
return "admin".equals(role) || "owner".equals(role); // owner هم admin هست
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isUserInChannel(UUID userId, UUID channelId) {
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(
|
||||||
|
"SELECT 1 FROM channel_subscribers WHERE channel_id = ? AND user_id = ?")) {
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
return rs.next();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean removeSubscriberFromChannel(UUID channelId, UUID userId) {
|
||||||
|
String sql = "DELETE FROM channel_subscribers WHERE channel_id = ? AND user_id = ?";
|
||||||
|
|
||||||
|
try (Connection conn =ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
|
||||||
|
int affectedRows = stmt.executeUpdate();
|
||||||
|
return affectedRows > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
System.err.println("Error removing subscriber from channel: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static JSONArray getChannelSubscribers(UUID channelId) {
|
||||||
|
JSONArray subscribers = new JSONArray();
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(
|
||||||
|
"SELECT u.internal_uuid, u.user_id, u.profile_name, " +
|
||||||
|
"CASE WHEN cs.role = 'owner' THEN 'owner' " +
|
||||||
|
" WHEN cs.role = 'admin' THEN 'admin' " +
|
||||||
|
" ELSE 'subscriber' END AS role " +
|
||||||
|
"FROM channel_subscribers cs " +
|
||||||
|
"JOIN users u ON cs.user_id = u.internal_uuid " +
|
||||||
|
"WHERE cs.channel_id = ?")) {
|
||||||
|
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put("internal_uuid", rs.getObject("internal_uuid").toString());
|
||||||
|
obj.put("user_id", rs.getString("user_id"));
|
||||||
|
obj.put("profile_name", rs.getString("profile_name"));
|
||||||
|
obj.put("role", rs.getString("role"));
|
||||||
|
subscribers.put(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscribers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean updateChannelInfo(UUID channelId, String newId, String name, String description, String imageUrl) {
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(
|
||||||
|
"UPDATE channels SET channel_id = ?, channel_name = ?, description = ?, image_url = ? WHERE internal_uuid = ?")) {
|
||||||
|
|
||||||
|
stmt.setString(1, newId);
|
||||||
|
stmt.setString(2, name);
|
||||||
|
stmt.setString(3, description);
|
||||||
|
stmt.setString(4, imageUrl);
|
||||||
|
stmt.setObject(5, channelId);
|
||||||
|
|
||||||
|
int rows = stmt.executeUpdate();
|
||||||
|
return rows > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isChannelIdUnique(String channelId, UUID excludeChannelUUID) {
|
||||||
|
String query = "SELECT COUNT(*) FROM channels WHERE channel_id = ? AND internal_uuid != ?";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(query)) {
|
||||||
|
|
||||||
|
stmt.setString(1, channelId);
|
||||||
|
stmt.setObject(2, excludeChannelUUID);
|
||||||
|
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
int count = rs.getInt(1);
|
||||||
|
return count == 0;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean demoteAdminToSubscriber(UUID channelId, UUID userId) {
|
||||||
|
String sql = "UPDATE channel_subscribers SET role = 'member', permissions = '{}'::jsonb WHERE channel_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
|
||||||
|
int affected = stmt.executeUpdate();
|
||||||
|
return affected > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean deleteChannel(UUID channelId) {
|
||||||
|
String sql = "DELETE FROM channels WHERE internal_uuid = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, channelId);
|
||||||
|
int affected = stmt.executeUpdate();
|
||||||
|
return affected > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean transferOwnership(UUID channelId, UUID newOwnerUUID) {
|
||||||
|
String sql = """
|
||||||
|
UPDATE channel_subscribers
|
||||||
|
SET role = CASE
|
||||||
|
WHEN user_id = ? THEN 'owner'
|
||||||
|
WHEN role = 'owner' THEN 'admin'
|
||||||
|
ELSE role
|
||||||
|
END
|
||||||
|
WHERE channel_id = ?
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, newOwnerUUID);
|
||||||
|
stmt.setObject(2, channelId);
|
||||||
|
|
||||||
|
stmt.executeUpdate();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,13 +16,17 @@ public class ContactDatabase {
|
|||||||
return ConnectionDb.connect();
|
return ConnectionDb.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean addContact(UUID userId, UUID contactId) {
|
||||||
|
String sql = """
|
||||||
|
INSERT INTO contacts (user_id, contact_id)
|
||||||
|
VALUES (?, ?)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
""";
|
||||||
|
|
||||||
public boolean addContact(UUID user_id, UUID contact_id) {
|
try (Connection conn = ConnectionDb.connect();
|
||||||
String sql = "INSERT INTO contacts (user_id, contact_id) VALUES (?, ?) ON CONFLICT DO NOTHING";
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
try (Connection connection = getConnection()) {
|
stmt.setObject(1, userId);
|
||||||
PreparedStatement stmt = connection.prepareStatement(sql);
|
stmt.setObject(2, contactId);
|
||||||
stmt.setObject(1, user_id);
|
|
||||||
stmt.setObject(2,contact_id);
|
|
||||||
return stmt.executeUpdate() > 0;
|
return stmt.executeUpdate() > 0;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@@ -31,6 +35,7 @@ public class ContactDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean removeContact(UUID user_id, UUID contact_id) {
|
public boolean removeContact(UUID user_id, UUID contact_id) {
|
||||||
String sql = "DELETE FROM contacts WHERE user_id = ? AND contact_id = ?";
|
String sql = "DELETE FROM contacts WHERE user_id = ? AND contact_id = ?";
|
||||||
try (Connection connection = getConnection()) {
|
try (Connection connection = getConnection()) {
|
||||||
@@ -44,19 +49,47 @@ public class ContactDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean blockContact(UUID user_id, UUID contact_id) {
|
public static boolean toggleBlock(UUID userId, UUID targetId) {
|
||||||
String sql = "UPDATE contacts SET is_blocked = TRUE WHERE user_id = ? AND contact_id = ?";
|
String selectSql = "SELECT is_blocked FROM contacts WHERE user_id = ? AND contact_id = ?";
|
||||||
try (Connection connection = getConnection()) {
|
String updateSql = "UPDATE contacts SET is_blocked = ? WHERE user_id = ? AND contact_id = ?";
|
||||||
PreparedStatement stmt = connection.prepareStatement(sql);
|
|
||||||
stmt.setObject(1, user_id);
|
try (Connection conn = getConnection();
|
||||||
stmt.setObject(2, contact_id);
|
PreparedStatement selectStmt = conn.prepareStatement(selectSql)) {
|
||||||
return stmt.executeUpdate() > 0;
|
|
||||||
|
selectStmt.setObject(1, userId);
|
||||||
|
selectStmt.setObject(2, targetId);
|
||||||
|
|
||||||
|
ResultSet rs = selectStmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
boolean currentlyBlocked = rs.getBoolean("is_blocked");
|
||||||
|
|
||||||
|
try (PreparedStatement updateStmt = conn.prepareStatement(updateSql)) {
|
||||||
|
updateStmt.setBoolean(1, !currentlyBlocked);
|
||||||
|
updateStmt.setObject(2, userId);
|
||||||
|
updateStmt.setObject(3, targetId);
|
||||||
|
updateStmt.executeUpdate();
|
||||||
|
}
|
||||||
|
return !currentlyBlocked;
|
||||||
|
} else {
|
||||||
|
// اگر رابطه وجود نداره، اول باید کاربر رو به contact ها اضافه کنیم
|
||||||
|
String insertSql = "INSERT INTO contacts (user_id, contact_id, is_blocked) VALUES (?, ?, ?)";
|
||||||
|
try (PreparedStatement insertStmt = conn.prepareStatement(insertSql)) {
|
||||||
|
insertStmt.setObject(1, userId);
|
||||||
|
insertStmt.setObject(2, targetId);
|
||||||
|
insertStmt.setBoolean(3, true);
|
||||||
|
insertStmt.executeUpdate();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public boolean unblockContact(UUID user_id, UUID contact_id) {
|
public boolean unblockContact(UUID user_id, UUID contact_id) {
|
||||||
String sql = "UPDATE contacts SET is_blocked = FALSE WHERE user_id = ? AND contact_id = ?";
|
String sql = "UPDATE contacts SET is_blocked = FALSE WHERE user_id = ? AND contact_id = ?";
|
||||||
try (Connection connection = getConnection()) {
|
try (Connection connection = getConnection()) {
|
||||||
@@ -94,7 +127,7 @@ public class ContactDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean existsContact(UUID user_id, UUID contact_id) {
|
public static boolean existsContact(UUID user_id, UUID contact_id) {
|
||||||
String sql = "SELECT 1 FROM contacts WHERE user_id = ? AND contact_id = ? LIMIT 1"; // stop searching when find the first item in DB(LIMIT 1)
|
String sql = "SELECT 1 FROM contacts WHERE user_id = ? AND contact_id = ? LIMIT 1"; // stop searching when find the first item in DB(LIMIT 1)
|
||||||
try (Connection connection = getConnection()) {
|
try (Connection connection = getConnection()) {
|
||||||
PreparedStatement stmt = connection.prepareStatement(sql);
|
PreparedStatement stmt = connection.prepareStatement(sql);
|
||||||
@@ -155,4 +188,76 @@ public class ContactDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean deleteChatOneSide(UUID currentUserId, UUID otherUserId) {
|
||||||
|
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 (user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = getConnection();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, currentUserId);
|
||||||
|
stmt.setObject(2, currentUserId);
|
||||||
|
stmt.setObject(3, currentUserId);
|
||||||
|
stmt.setObject(4, otherUserId);
|
||||||
|
stmt.setObject(5, otherUserId);
|
||||||
|
stmt.setObject(6, currentUserId);
|
||||||
|
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean deleteChatBoth(UUID currentUserId, UUID otherUserId) {
|
||||||
|
String sqlDeleteMessages = """
|
||||||
|
DELETE FROM messages
|
||||||
|
WHERE receiver_type = 'private' AND (
|
||||||
|
(sender_id = ? AND receiver_id = ?) OR
|
||||||
|
(sender_id = ? AND receiver_id = ?)
|
||||||
|
)
|
||||||
|
""";
|
||||||
|
|
||||||
|
String sqlDeleteChat = """
|
||||||
|
DELETE FROM private_chat
|
||||||
|
WHERE (user1_id = ? AND user2_id = ?) OR (user1_id = ? AND user2_id = ?)
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = getConnection()) {
|
||||||
|
conn.setAutoCommit(false);
|
||||||
|
|
||||||
|
try (PreparedStatement stmtMsg = conn.prepareStatement(sqlDeleteMessages);
|
||||||
|
PreparedStatement stmtChat = conn.prepareStatement(sqlDeleteChat)) {
|
||||||
|
|
||||||
|
stmtMsg.setObject(1, currentUserId);
|
||||||
|
stmtMsg.setObject(2, otherUserId);
|
||||||
|
stmtMsg.setObject(3, otherUserId);
|
||||||
|
stmtMsg.setObject(4, currentUserId);
|
||||||
|
stmtMsg.executeUpdate();
|
||||||
|
|
||||||
|
stmtChat.setObject(1, currentUserId);
|
||||||
|
stmtChat.setObject(2, otherUserId);
|
||||||
|
stmtChat.setObject(3, otherUserId);
|
||||||
|
stmtChat.setObject(4, currentUserId);
|
||||||
|
stmtChat.executeUpdate();
|
||||||
|
|
||||||
|
conn.commit();
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
conn.rollback();
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package org.to.telegramfinalproject.Database;
|
package org.to.telegramfinalproject.Database;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
import org.to.telegramfinalproject.Models.Group;
|
import org.to.telegramfinalproject.Models.Group;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.*;
|
||||||
import java.sql.PreparedStatement;
|
import java.time.LocalDateTime;
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@@ -76,5 +76,528 @@ public class GroupDatabase {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<UUID> getMemberUUIDs(UUID groupInternalUUID) {
|
||||||
|
List<UUID> memberIds = new ArrayList<>();
|
||||||
|
String sql = "SELECT user_id FROM group_members WHERE group_id = ?";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupInternalUUID);
|
||||||
|
|
||||||
|
try (ResultSet rs = stmt.executeQuery()) {
|
||||||
|
while (rs.next()) {
|
||||||
|
memberIds.add((UUID) rs.getObject("user_id"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return memberIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Group findByGroupId(String groupId) {
|
||||||
|
String sql = "SELECT * FROM groups WHERE group_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setString(1, groupId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
if (rs.next()) {
|
||||||
|
Group group = new Group();
|
||||||
|
group.setInternal_uuid(UUID.fromString(rs.getString("internal_uuid")));
|
||||||
|
group.setGroup_id(rs.getString("group_id"));
|
||||||
|
group.setGroup_name(rs.getString("group_name"));
|
||||||
|
group.setImage_url(rs.getString("image_url"));
|
||||||
|
group.setCreator_id(UUID.fromString(rs.getString("creator_id")));
|
||||||
|
group.setDescription(rs.getString("description"));
|
||||||
|
group.setCreated_at(rs.getTimestamp("created_at").toLocalDateTime());
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isUserInGroup(UUID userId, UUID groupInternalId) {
|
||||||
|
String sql = "SELECT * FROM group_members WHERE user_id = ? AND group_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, userId);
|
||||||
|
stmt.setObject(2, groupInternalId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
return rs.next();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean updateGroupInfo(UUID internalUUID, String newGroupId, String name, String description, String imageUrl) {
|
||||||
|
String sql = "UPDATE groups SET group_id = ?, group_name = ?, description = ?, image_url = ? WHERE internal_uuid = ?";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, newGroupId);
|
||||||
|
stmt.setString(2, name);
|
||||||
|
stmt.setString(3, description);
|
||||||
|
if (imageUrl == null) {
|
||||||
|
stmt.setNull(4, Types.VARCHAR);
|
||||||
|
} else {
|
||||||
|
stmt.setString(4, imageUrl);
|
||||||
|
}
|
||||||
|
stmt.setObject(5, internalUUID);
|
||||||
|
|
||||||
|
int affectedRows = stmt.executeUpdate();
|
||||||
|
return affectedRows > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isGroupIdUnique(String groupId, UUID excludeUUID) {
|
||||||
|
String sql = "SELECT COUNT(*) FROM groups WHERE group_id = ? AND internal_uuid != ?";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, groupId);
|
||||||
|
stmt.setObject(2, excludeUUID);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return rs.getInt(1) == 0;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void addMember(UUID groupInternalId, UUID userId) {
|
||||||
|
String sql = "INSERT INTO group_members (group_id, user_id) VALUES (?, ?) ON CONFLICT DO NOTHING";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupInternalId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
stmt.executeUpdate();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static UUID findInternalUUIDByGroupId(String groupId) {
|
||||||
|
String sql = "SELECT internal_uuid FROM groups WHERE group_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, groupId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return (UUID) rs.getObject("internal_uuid");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean addMemberToGroup(UUID userId, UUID groupUUID) {
|
||||||
|
String sql = """
|
||||||
|
INSERT INTO group_members (group_id, user_id)
|
||||||
|
VALUES (?, ?)
|
||||||
|
ON CONFLICT DO NOTHING
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupUUID);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Group findByInternalUUID(UUID internalUUID) {
|
||||||
|
String sql = "SELECT * FROM groups WHERE internal_uuid = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, internalUUID);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
if (rs.next()) {
|
||||||
|
Group group = new Group();
|
||||||
|
group.setInternal_uuid(UUID.fromString(rs.getString("internal_uuid")));
|
||||||
|
group.setGroup_id(rs.getString("group_id"));
|
||||||
|
group.setGroup_name(rs.getString("group_name"));
|
||||||
|
group.setImage_url(rs.getString("image_url"));
|
||||||
|
group.setCreator_id(UUID.fromString(rs.getString("creator_id")));
|
||||||
|
group.setDescription(rs.getString("description"));
|
||||||
|
group.setCreated_at(rs.getTimestamp("created_at").toLocalDateTime());
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean addOwnerToGroup(UUID groupId, UUID userId) {
|
||||||
|
String sql = "INSERT INTO group_members (group_id, user_id, role) VALUES (?, ?, 'owner')";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean addAdminToGroup(UUID groupId, UUID userId, JSONObject permissions) {
|
||||||
|
String sql = """
|
||||||
|
UPDATE group_members
|
||||||
|
SET role = 'admin',
|
||||||
|
permissions = ?::jsonb
|
||||||
|
WHERE group_id = ? AND user_id = ? AND role = 'member'
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setString(1, permissions.toString());
|
||||||
|
stmt.setObject(2, groupId);
|
||||||
|
stmt.setObject(3, userId);
|
||||||
|
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static String getGroupRole(UUID groupId, UUID userId) {
|
||||||
|
String sql = "SELECT role FROM group_members WHERE group_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
return rs.getString("role");
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return "member"; // پیشفرض
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean updateGroupAdminPermissions(UUID groupId, UUID userId, JSONObject permissions) {
|
||||||
|
String sql = """
|
||||||
|
UPDATE group_members
|
||||||
|
SET permissions = ?::jsonb
|
||||||
|
WHERE group_id = ? AND user_id = ? AND role = 'admin'
|
||||||
|
""";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setString(1, permissions.toString());
|
||||||
|
stmt.setObject(2, groupId);
|
||||||
|
stmt.setObject(3, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static List<JSONObject> getGroupAdminsAndOwner(UUID groupId) {
|
||||||
|
List<JSONObject> admins = new ArrayList<>();
|
||||||
|
|
||||||
|
String sql = "SELECT gm.user_id, gm.role, gm.permissions, u.profile_name " +
|
||||||
|
"FROM group_members gm " +
|
||||||
|
"JOIN users u ON gm.user_id = u.internal_uuid " +
|
||||||
|
"WHERE gm.group_id = ? AND gm.role IN ('owner', 'admin')";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
JSONObject obj = new JSONObject();
|
||||||
|
obj.put("user_id", rs.getObject("user_id").toString());
|
||||||
|
obj.put("role", rs.getString("role"));
|
||||||
|
obj.put("permissions", new JSONObject(rs.getString("permissions")));
|
||||||
|
obj.put("profile_name", rs.getString("profile_name"));
|
||||||
|
admins.add(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return admins;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isOwner(UUID groupId, UUID userId) {
|
||||||
|
String sql = "SELECT 1 FROM group_members WHERE group_id = ? AND user_id = ? AND role = 'owner'";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
return rs.next(); // اگر رکوردی پیدا شد یعنی owner است
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAdmin(UUID groupId, UUID userId) {
|
||||||
|
String sql = "SELECT role FROM group_members WHERE group_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
String role = rs.getString("role");
|
||||||
|
return "admin".equals(role) || "owner".equals(role); // owner هم admin هست
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONObject getGroupPermissions(UUID groupId, UUID userId) {
|
||||||
|
String sql = "SELECT permissions FROM group_members WHERE group_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
if (rs.next()) {
|
||||||
|
String permissions = rs.getString("permissions");
|
||||||
|
if (permissions != null && !permissions.isBlank()) {
|
||||||
|
return new JSONObject(permissions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return new JSONObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static JSONArray getGroupMembers(UUID groupId) {
|
||||||
|
String sql = """
|
||||||
|
SELECT u.profile_name, u.user_id, u.internal_uuid, gm.role, gm.permissions
|
||||||
|
FROM group_members gm
|
||||||
|
JOIN users u ON gm.user_id = u.internal_uuid
|
||||||
|
WHERE gm.group_id = ?
|
||||||
|
""";
|
||||||
|
|
||||||
|
JSONArray members = new JSONArray();
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
while (rs.next()) {
|
||||||
|
JSONObject member = new JSONObject();
|
||||||
|
member.put("profile_name", rs.getString("profile_name"));
|
||||||
|
member.put("user_id", rs.getString("user_id")); // آیدی قابل نمایش
|
||||||
|
member.put("internal_uuid", rs.getObject("internal_uuid").toString());
|
||||||
|
member.put("role", rs.getString("role"));
|
||||||
|
|
||||||
|
String permissions = rs.getString("permissions");
|
||||||
|
if (permissions != null && !permissions.isBlank()) {
|
||||||
|
member.put("permissions", new JSONObject(permissions));
|
||||||
|
}
|
||||||
|
|
||||||
|
members.put(member);
|
||||||
|
}
|
||||||
|
|
||||||
|
return members;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean demoteAdminToMember(UUID groupId, UUID userId) {
|
||||||
|
String sql = "UPDATE group_members SET role = 'member', permissions = '{}'::jsonb WHERE group_id = ? AND user_id = ? AND role = 'admin'";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean removeMemberFromGroup(UUID groupId, UUID userId) {
|
||||||
|
String sql = "DELETE FROM group_members WHERE group_id = ? AND user_id = ?";
|
||||||
|
try (Connection conn = ConnectionDb.connect(); PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
stmt.setObject(2, userId);
|
||||||
|
return stmt.executeUpdate() > 0;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean transferOwnership(UUID groupId, UUID newOwnerId) {
|
||||||
|
String demoteOldOwner = "UPDATE group_members SET role = 'admin' WHERE group_id = ? AND role = 'owner'";
|
||||||
|
String promoteNewOwner = "UPDATE group_members SET role = 'owner' WHERE group_id = ? AND user_id = ?";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect()) {
|
||||||
|
conn.setAutoCommit(false);
|
||||||
|
|
||||||
|
try (PreparedStatement demoteStmt = conn.prepareStatement(demoteOldOwner);
|
||||||
|
PreparedStatement promoteStmt = conn.prepareStatement(promoteNewOwner)) {
|
||||||
|
|
||||||
|
demoteStmt.setObject(1, groupId);
|
||||||
|
demoteStmt.executeUpdate();
|
||||||
|
|
||||||
|
promoteStmt.setObject(1, groupId);
|
||||||
|
promoteStmt.setObject(2, newOwnerId);
|
||||||
|
promoteStmt.executeUpdate();
|
||||||
|
|
||||||
|
conn.commit();
|
||||||
|
return true;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
conn.rollback();
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean deleteGroup(UUID groupId) {
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement("DELETE FROM groups WHERE internal_uuid = ?")) {
|
||||||
|
|
||||||
|
stmt.setObject(1, groupId);
|
||||||
|
int affectedRows = stmt.executeUpdate();
|
||||||
|
|
||||||
|
return affectedRows > 0;
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,41 @@ import java.util.stream.Collectors;
|
|||||||
public class MessageDatabase {
|
public class MessageDatabase {
|
||||||
|
|
||||||
|
|
||||||
|
public static void save(Message message) {
|
||||||
|
String sql = """
|
||||||
|
INSERT INTO messages (
|
||||||
|
message_id, sender_id, receiver_type, receiver_id, content,
|
||||||
|
message_type, file_url, send_at, status,
|
||||||
|
reply_to_id, is_edited, original_message_id, forwarded_by, forwarded_from
|
||||||
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
|
||||||
|
stmt.setObject(1, message.getMessage_id());
|
||||||
|
stmt.setObject(2, message.getSender_id());
|
||||||
|
stmt.setString(3, message.getReceiver_type());
|
||||||
|
stmt.setObject(4, message.getReceiver_id());
|
||||||
|
stmt.setString(5, message.getContent());
|
||||||
|
stmt.setString(6, message.getMessage_type());
|
||||||
|
stmt.setString(7, message.getFile_url());
|
||||||
|
stmt.setObject(8, message.getSend_at());
|
||||||
|
stmt.setString(9, message.getStatus());
|
||||||
|
stmt.setObject(10, message.getReply_to_id());
|
||||||
|
stmt.setBoolean(11, message.isIs_edited());
|
||||||
|
stmt.setObject(12, message.getOriginal_message_id());
|
||||||
|
stmt.setObject(13, message.getForwarded_by());
|
||||||
|
stmt.setObject(14, message.getForwarded_from());
|
||||||
|
|
||||||
|
stmt.executeUpdate();
|
||||||
|
|
||||||
|
} catch (SQLException e) {
|
||||||
|
System.err.println("❌ Error saving message: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
@@ -182,6 +217,80 @@ public class MessageDatabase {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Message> privateChatHistory(UUID user1, UUID user2) {
|
||||||
|
List<Message> result = new ArrayList<>();
|
||||||
|
String sql = """
|
||||||
|
SELECT * FROM messages
|
||||||
|
WHERE receiver_type = 'private'
|
||||||
|
AND (
|
||||||
|
(sender_id = ? AND receiver_id = ?)
|
||||||
|
OR (sender_id = ? AND receiver_id = ?)
|
||||||
|
)
|
||||||
|
ORDER BY send_at
|
||||||
|
""";
|
||||||
|
|
||||||
|
try (Connection conn = ConnectionDb.connect();
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql)) {
|
||||||
|
stmt.setObject(1, user1);
|
||||||
|
stmt.setObject(2, user2);
|
||||||
|
stmt.setObject(3, user2);
|
||||||
|
stmt.setObject(4, user1);
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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> 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> searchMessagesInGroups(List<UUID> groupIds, String keyword) {
|
public static List<Message> searchMessagesInGroups(List<UUID> groupIds, String keyword) {
|
||||||
List<Message> result = new ArrayList<>();
|
List<Message> result = new ArrayList<>();
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class userDatabase {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
User var6;
|
User var6;
|
||||||
try (Connection conn = this.getConnection()) {
|
try (Connection conn = ConnectionDb.connect()) {
|
||||||
try (PreparedStatement stmt = conn.prepareStatement(query)) {
|
try (PreparedStatement stmt = conn.prepareStatement(query)) {
|
||||||
stmt.setString(1, userId);
|
stmt.setString(1, userId);
|
||||||
ResultSet rs = stmt.executeQuery();
|
ResultSet rs = stmt.executeQuery();
|
||||||
@@ -228,7 +228,6 @@ public class userDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static User findByInternalUUID(UUID internalUuid) {
|
public static User findByInternalUUID(UUID internalUuid) {
|
||||||
String sql = "SELECT * FROM users WHERE internal_uuid = ?";
|
String sql = "SELECT * FROM users WHERE internal_uuid = ?";
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,70 @@
|
|||||||
package org.to.telegramfinalproject.Models;
|
package org.to.telegramfinalproject.Models;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
public class ChatEntry {
|
public class ChatEntry {
|
||||||
private final String name;
|
private UUID internalId;
|
||||||
private final String id;
|
private String displayId;
|
||||||
private final String imageUrl;
|
private String name;
|
||||||
private final String type; // "private", "group", "channel"
|
private String imageUrl;
|
||||||
private final LocalDateTime lastMessageTime;
|
private String type;
|
||||||
|
private LocalDateTime lastMessageTime;
|
||||||
|
|
||||||
public ChatEntry(String name, String id, String imageUrl, String type, LocalDateTime lastMessageTime) {
|
// 🔹 نقشها
|
||||||
|
private boolean isOwner = false;
|
||||||
|
private boolean isAdmin = false;
|
||||||
|
private JSONObject permissions;
|
||||||
|
|
||||||
|
|
||||||
|
public ChatEntry(UUID internalId, String displayId, String name, String imageUrl, String type, LocalDateTime lastMessageTime) {
|
||||||
|
this.internalId = internalId;
|
||||||
|
this.displayId = displayId;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.id = id;
|
|
||||||
this.imageUrl = imageUrl;
|
this.imageUrl = imageUrl;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.lastMessageTime = lastMessageTime;
|
this.lastMessageTime = lastMessageTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
// ✅ کانستراکتور اضافهشده برای پشتیبانی از نقشها (اختیاری، برای استفادههای جدید)
|
||||||
return name;
|
public ChatEntry(UUID internalId, String displayId, String name, String imageUrl, String type, LocalDateTime lastMessageTime, boolean isOwner, boolean isAdmin) {
|
||||||
|
this(internalId, displayId, name, imageUrl, type, lastMessageTime);
|
||||||
|
this.isOwner = isOwner;
|
||||||
|
this.isAdmin = isAdmin;
|
||||||
|
this.permissions = permissions;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
// 🟩 گتر و ستر جدید
|
||||||
return id;
|
public boolean isOwner() {
|
||||||
|
return isOwner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(boolean owner) {
|
||||||
|
isOwner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAdmin() {
|
||||||
|
return isAdmin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdmin(boolean admin) {
|
||||||
|
isAdmin = admin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// سایر گترها
|
||||||
|
public UUID getId() {
|
||||||
|
return internalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayId() {
|
||||||
|
return displayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getImageUrl() {
|
public String getImageUrl() {
|
||||||
@@ -36,4 +78,13 @@ public class ChatEntry {
|
|||||||
public LocalDateTime getLastMessageTime() {
|
public LocalDateTime getLastMessageTime() {
|
||||||
return lastMessageTime;
|
return lastMessageTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public JSONObject getPermissions() {
|
||||||
|
return permissions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPermissions(JSONObject permissions) {
|
||||||
|
this.permissions = permissions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package org.to.telegramfinalproject.Models;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
public class ContactRequestModel {
|
||||||
|
private String event;
|
||||||
|
private String contactId;
|
||||||
|
private String userId;
|
||||||
|
|
||||||
|
public ContactRequestModel(String event, String contactId, String userId) {
|
||||||
|
this.event = event;
|
||||||
|
this.contactId = contactId;
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject toJson() {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("event", event);
|
||||||
|
json.put("contact_id", contactId);
|
||||||
|
json.put("user_id", userId);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,7 +28,7 @@ public class JsonUtil {
|
|||||||
|
|
||||||
public static JSONObject userToJson(User user) {
|
public static JSONObject userToJson(User user) {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("internalUUID", user.getInternal_uuid().toString());
|
obj.put("internal_uuid", user.getInternal_uuid().toString());
|
||||||
obj.put("user_id", user.getUser_id() != null ?user.getUser_id().toString() :JSONObject.NULL);
|
obj.put("user_id", user.getUser_id() != null ?user.getUser_id().toString() :JSONObject.NULL);
|
||||||
obj.put("username", user.getUsername());
|
obj.put("username", user.getUsername());
|
||||||
obj.put("profile_name", user.getProfile_name());
|
obj.put("profile_name", user.getProfile_name());
|
||||||
@@ -109,9 +109,13 @@ public class JsonUtil {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static JSONArray groupMemberListToJson(List<GroupMember> members) {
|
public static JSONArray groupMemberListToJson(List<GroupMember> members) {
|
||||||
JSONArray array = new JSONArray();
|
JSONArray array = new JSONArray();
|
||||||
|
|
||||||
|
if (members == null) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
for (GroupMember m : members) {
|
for (GroupMember m : members) {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("group_id", m.getGroup_id().toString());
|
obj.put("group_id", m.getGroup_id().toString());
|
||||||
@@ -120,32 +124,45 @@ public class JsonUtil {
|
|||||||
obj.put("role", m.getRole());
|
obj.put("role", m.getRole());
|
||||||
array.put(obj);
|
array.put(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSONArray channelSubscribeToJson(List<ChannelSubscribe> subscribes){
|
|
||||||
|
public static JSONArray channelSubscribeToJson(List<ChannelSubscribe> subscribes) {
|
||||||
JSONArray array = new JSONArray();
|
JSONArray array = new JSONArray();
|
||||||
for(ChannelSubscribe s :subscribes ){
|
|
||||||
|
if (subscribes == null) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChannelSubscribe s : subscribes) {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("channel_id",s.getChannel_id().toString());
|
obj.put("channel_id", s.getChannel_id().toString());
|
||||||
obj.put("user_id", s.getUser_id().toString());
|
obj.put("user_id", s.getUser_id().toString());
|
||||||
obj.put("Subscribed_at", s.getJoin_at().toString());
|
obj.put("Subscribed_at", s.getJoin_at().toString());
|
||||||
|
array.put(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static JSONArray chatListToJson(List<ChatEntry> chatList) {
|
public static JSONArray chatListToJson(List<ChatEntry> chatList) {
|
||||||
JSONArray jsonArray = new JSONArray();
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
|
||||||
for (ChatEntry entry : chatList) {
|
for (ChatEntry entry : chatList) {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("id", entry.getId() != null ?entry.getId() :JSONObject.NULL);
|
obj.put("internal_id", entry.getId().toString());
|
||||||
|
obj.put("id", entry.getDisplayId());
|
||||||
obj.put("name", entry.getName());
|
obj.put("name", entry.getName());
|
||||||
obj.put("image_url", entry.getImageUrl() != null ?entry.getImageUrl() :JSONObject.NULL);
|
obj.put("image_url", entry.getImageUrl());
|
||||||
obj.put("type", entry.getType());
|
obj.put("type", entry.getType());
|
||||||
obj.put("last_message_time", entry.getLastMessageTime() != null ? entry.getLastMessageTime().toString() : JSONObject.NULL);
|
obj.put("last_message_time", entry.getLastMessageTime() == null ? JSONObject.NULL : entry.getLastMessageTime().toString());
|
||||||
|
obj.put("is_owner", entry.isOwner());
|
||||||
|
obj.put("is_admin", entry.isAdmin());
|
||||||
|
|
||||||
|
|
||||||
jsonArray.put(obj);
|
jsonArray.put(obj);
|
||||||
}
|
}
|
||||||
@@ -154,4 +171,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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
public class PrivateChat {
|
public class PrivateChat {
|
||||||
private UUID chat_id;
|
private final UUID chat_id;
|
||||||
private UUID user1_id;
|
private UUID user1_id;
|
||||||
private UUID user2_id;
|
private UUID user2_id;
|
||||||
private LocalDateTime created_at;
|
private LocalDateTime created_at;
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.to.telegramfinalproject.Models;
|
||||||
|
|
||||||
|
public class SearchResultModel {
|
||||||
|
private final String type;
|
||||||
|
private final String id; // ← UUID واقعی برای عملیات
|
||||||
|
private final String displayId; // ← user_id یا group_id برای نمایش
|
||||||
|
private String name;
|
||||||
|
private final String content;
|
||||||
|
private final String sender;
|
||||||
|
private final String time;
|
||||||
|
|
||||||
|
public SearchResultModel(String type, String id, String displayId,
|
||||||
|
String content, String sender, String time) {
|
||||||
|
this.type = type;
|
||||||
|
this.id = id;
|
||||||
|
this.displayId = displayId;
|
||||||
|
this.content = content;
|
||||||
|
this.sender = sender;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
// فقط در صورت نیاز برای user/group/channel
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDisplayId() {
|
||||||
|
return displayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSender() {
|
||||||
|
return sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTime() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "[" + type.toUpperCase() + "] " + name + " (ID: " + displayId + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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,"owner");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
|||||||
|
package org.to.telegramfinalproject.Server;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import org.to.telegramfinalproject.Database.userDatabase;
|
||||||
|
import org.to.telegramfinalproject.Database.ContactDatabase;
|
||||||
|
public class ContactService {
|
||||||
|
public static boolean addContact(UUID userId, UUID contactId) {
|
||||||
|
if (userId.equals(contactId)) return false;
|
||||||
|
if (userDatabase.findByInternalUUID(contactId) == null) return false;
|
||||||
|
if (userDatabase.findByInternalUUID(userId) == null) return false;
|
||||||
|
if (ContactDatabase.existsContact(userId, contactId)) return false;
|
||||||
|
|
||||||
|
return ContactDatabase.addContact(userId, contactId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
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");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import java.net.ServerSocket;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
|
|
||||||
public class MainServer {
|
public class MainServer {
|
||||||
private static final int PORT = 12345;
|
private static final int PORT = 8000;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
try (ServerSocket serverSocket = new ServerSocket(PORT)) {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package org.to.telegramfinalproject.Server;
|
||||||
|
|
||||||
|
|
||||||
|
import org.to.telegramfinalproject.Database.ContactDatabase;
|
||||||
|
import org.to.telegramfinalproject.Models.ResponseModel;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PrivateChatService {
|
||||||
|
|
||||||
|
public static ResponseModel deletePrivateChat(UUID currentUserId, UUID targetUserId, boolean both) {
|
||||||
|
boolean success = both ?
|
||||||
|
ContactDatabase.deleteChatBoth(currentUserId, targetUserId) :
|
||||||
|
ContactDatabase.deleteChatOneSide(currentUserId, targetUserId);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
return new ResponseModel("success", "Chat deleted successfully");
|
||||||
|
} else {
|
||||||
|
return new ResponseModel("error", "Chat not found or failed to delete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,250 @@
|
|||||||
|
package org.to.telegramfinalproject.Server;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.to.telegramfinalproject.Database.ChannelDatabase;
|
||||||
|
import org.to.telegramfinalproject.Database.GroupDatabase;
|
||||||
|
import org.to.telegramfinalproject.Models.Message;
|
||||||
|
import org.to.telegramfinalproject.Models.User;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class RealTimeEventDispatcher {
|
||||||
|
|
||||||
|
public static void sendToUser(UUID userId, JSONObject data) {
|
||||||
|
Socket socket = SessionManager.getUserSocket(userId);
|
||||||
|
|
||||||
|
|
||||||
|
if (socket != null && !socket.isClosed()) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
|
||||||
|
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
|
||||||
|
System.out.println("🚀 Sending to user: " + userId + " → " + data);
|
||||||
|
|
||||||
|
out.println(data.toString());
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("❌ Error sending to user: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println("⚠️ User " + userId + " is offline. Skipping real-time send.");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void broadcastToUsers(List<UUID> userIds, JSONObject data) {
|
||||||
|
for (UUID userId : userIds) {
|
||||||
|
sendToUser(userId, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONObject buildEvent(String action, JSONObject payload) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("action", action);
|
||||||
|
json.put("data", payload);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void notifyNewMessage(Message msg, User sender) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("sender", sender.getUser_id());
|
||||||
|
data.put("receiver_type", msg.getReceiver_type());
|
||||||
|
data.put("receiver_id", msg.getReceiver_id());
|
||||||
|
data.put("content", msg.getContent());
|
||||||
|
data.put("time", msg.getSend_at().toString());
|
||||||
|
|
||||||
|
JSONObject event = buildEvent("new_message", data);
|
||||||
|
|
||||||
|
switch (msg.getReceiver_type()) {
|
||||||
|
case "private" -> RealTimeEventDispatcher.sendToUser(msg.getReceiver_id(), event);
|
||||||
|
case "group" -> {
|
||||||
|
List<UUID> memberIds = GroupDatabase.getMemberUUIDs(msg.getReceiver_id());
|
||||||
|
memberIds.remove(sender.getInternal_uuid());
|
||||||
|
RealTimeEventDispatcher.broadcastToUsers(memberIds, event);
|
||||||
|
}
|
||||||
|
case "channel" -> {
|
||||||
|
List<UUID> subscriberIds = ChannelDatabase.getSubscriberUUIDs(msg.getReceiver_id());
|
||||||
|
subscriberIds.remove(sender.getInternal_uuid());
|
||||||
|
subscriberIds.remove(sender.getInternal_uuid());
|
||||||
|
RealTimeEventDispatcher.broadcastToUsers(subscriberIds, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void notifyMessageEdited(UUID messageId, String newContent, List<UUID> receivers) {
|
||||||
|
|
||||||
|
String editTime = LocalDateTime.now().toString();
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("message_id", messageId.toString());
|
||||||
|
data.put("new_content", newContent);
|
||||||
|
data.put("edited_at", editTime);
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "edit_message");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
broadcastToUsers(receivers, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void notifyMessageDeleted(UUID messageId, List<UUID> receivers) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("message_id", messageId.toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "delete_message");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
broadcastToUsers(receivers, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyUserUpdated(UUID userId, String newProfileName, String newImageUrl, List<UUID> contactIds) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("user_id", userId.toString());
|
||||||
|
data.put("new_name", newProfileName);
|
||||||
|
data.put("new_image_url", newImageUrl);
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "update_user");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
broadcastToUsers(contactIds, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyChatDeleted(String type, UUID id, List<UUID> affectedUsers) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("chat_type", type); // private, group, channel
|
||||||
|
data.put("chat_id", id.toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "chat_deleted");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
broadcastToUsers(affectedUsers, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyGroupOrChannelUpdated(String type, UUID id, String newName, String newImageUrl, List<UUID> affectedUsers) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("chat_type", type); // "group" or "channel"
|
||||||
|
data.put("chat_id", id.toString());
|
||||||
|
data.put("new_name", newName);
|
||||||
|
data.put("new_image_url", newImageUrl);
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "update_group_or_channel");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
broadcastToUsers(affectedUsers, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyMediaMessage(Message msg, User sender) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("sender", sender.getUser_id());
|
||||||
|
data.put("receiver_type", msg.getReceiver_type());
|
||||||
|
data.put("receiver_id", msg.getReceiver_id());
|
||||||
|
data.put("file_url", msg.getFile_url());
|
||||||
|
data.put("file_type", msg.getMessage_type()); // IMAGE, FILE, VIDEO...
|
||||||
|
data.put("time", msg.getSend_at().toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "new_media");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
switch (msg.getReceiver_type()) {
|
||||||
|
case "private" -> sendToUser(msg.getReceiver_id(), event);
|
||||||
|
case "group" -> {
|
||||||
|
List<UUID> members = GroupDatabase.getMemberUUIDs(msg.getReceiver_id());
|
||||||
|
members.remove(sender.getInternal_uuid());
|
||||||
|
broadcastToUsers(members, event);
|
||||||
|
}
|
||||||
|
case "channel" -> {
|
||||||
|
List<UUID> subs = ChannelDatabase.getSubscriberUUIDs(msg.getReceiver_id());
|
||||||
|
subs.remove(sender.getInternal_uuid());
|
||||||
|
broadcastToUsers(subs, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyAddedToChat(String type, UUID chatId, String chatName, String imageUrl, UUID userId) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("chat_type", type); // group یا channel
|
||||||
|
data.put("chat_id", chatId.toString());
|
||||||
|
data.put("chat_name", chatName);
|
||||||
|
data.put("image_url", imageUrl);
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", type.equals("group") ? "added_to_group" : "added_to_channel");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
sendToUser(userId, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyRemovedFromChat(String type, UUID chatId, UUID userId) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("chat_type", type);
|
||||||
|
data.put("chat_id", chatId.toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", type.equals("group") ? "removed_from_group" : "removed_from_channel");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
sendToUser(userId, event);
|
||||||
|
}
|
||||||
|
public static void notifyMessageSeen(UUID messageId, UUID senderId) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("message_id", messageId.toString());
|
||||||
|
data.put("seen_at", LocalDateTime.now().toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "message_seen");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
sendToUser(senderId, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void notifyBlocked(UUID blockerId, UUID blockedUserId) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("blocker_id", blockerId.toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "blocked_by_user");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
sendToUser(blockedUserId, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void notifyUnblocked(UUID unblockerId, UUID unblockedUserId) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("unblocker_id", unblockerId.toString());
|
||||||
|
|
||||||
|
JSONObject event = new JSONObject();
|
||||||
|
event.put("action", "unblocked_by_user");
|
||||||
|
event.put("data", data);
|
||||||
|
|
||||||
|
sendToUser(unblockedUserId, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void notifyUserStatusChanged(UUID userId, String status, List<UUID> contacts) {
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.put("user_id", userId.toString());
|
||||||
|
data.put("status", status); // online | offline
|
||||||
|
data.put("time", LocalDateTime.now().toString());
|
||||||
|
|
||||||
|
JSONObject event = buildEvent("user_status_changed", data);
|
||||||
|
|
||||||
|
broadcastToUsers(contacts, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package org.to.telegramfinalproject.Utils;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.to.telegramfinalproject.Database.ChannelDatabase;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class ChannelPermissionUtil {
|
||||||
|
|
||||||
|
public static boolean canAddSubscribers(UUID channelId, UUID userId) {
|
||||||
|
if (ChannelDatabase.isOwner(channelId, userId)) return true;
|
||||||
|
if (ChannelDatabase.isAdmin(channelId, userId)) {
|
||||||
|
JSONObject perms = ChannelDatabase.getChannelPermissions(channelId, userId);
|
||||||
|
return perms.optBoolean("can_add_members", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canAddAdmins(UUID channelId, UUID userId) {
|
||||||
|
if (ChannelDatabase.isOwner(channelId, userId)) return true;
|
||||||
|
if (ChannelDatabase.isAdmin(channelId, userId)) {
|
||||||
|
JSONObject perms = ChannelDatabase.getChannelPermissions(channelId, userId);
|
||||||
|
return perms.optBoolean("can_add_admins", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canEditChannel(UUID channelId, UUID userId) {
|
||||||
|
if (ChannelDatabase.isOwner(channelId, userId)) return true;
|
||||||
|
if (ChannelDatabase.isAdmin(channelId, userId)) {
|
||||||
|
JSONObject perms = ChannelDatabase.getChannelPermissions(channelId, userId);
|
||||||
|
return perms.optBoolean("can_edit_channel", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canRemoveAdmins(UUID channelId, UUID userId) {
|
||||||
|
if (ChannelDatabase.isOwner(channelId, userId)) return true;
|
||||||
|
if (ChannelDatabase.isAdmin(channelId, userId)) {
|
||||||
|
JSONObject perms = ChannelDatabase.getChannelPermissions(channelId, userId);
|
||||||
|
return perms.optBoolean("can_remove_admins", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canRemoveSubscribers(UUID channelId, UUID userId) {
|
||||||
|
if (ChannelDatabase.isOwner(channelId, userId)) return true;
|
||||||
|
if (ChannelDatabase.isAdmin(channelId, userId)) {
|
||||||
|
JSONObject perms = ChannelDatabase.getChannelPermissions(channelId, userId);
|
||||||
|
return perms.optBoolean("can_remove_members", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.to.telegramfinalproject.Utils;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.to.telegramfinalproject.Database.GroupDatabase;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class GroupPermissionUtil {
|
||||||
|
|
||||||
|
public static boolean canAddMembers(UUID groupId, UUID userId) {
|
||||||
|
String role = GroupDatabase.getGroupRole(groupId, userId);
|
||||||
|
if (role.equals("owner")) return true;
|
||||||
|
if (role.equals("admin")) {
|
||||||
|
JSONObject permissions = GroupDatabase.getGroupPermissions(groupId, userId);
|
||||||
|
return permissions.optBoolean("can_add_members", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canRemoveMembers(UUID groupId, UUID userId) {
|
||||||
|
String role = GroupDatabase.getGroupRole(groupId, userId);
|
||||||
|
if (role.equals("owner")) return true;
|
||||||
|
if (role.equals("admin")) {
|
||||||
|
JSONObject permissions = GroupDatabase.getGroupPermissions(groupId, userId);
|
||||||
|
return permissions.optBoolean("can_remove_members", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canAddAdmins(UUID groupId, UUID userId) {
|
||||||
|
String role = GroupDatabase.getGroupRole(groupId, userId);
|
||||||
|
if (role.equals("owner")) return true;
|
||||||
|
if (role.equals("admin")) {
|
||||||
|
JSONObject permissions = GroupDatabase.getGroupPermissions(groupId, userId);
|
||||||
|
return permissions.optBoolean("can_add_admins", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canRemoveAdmins(UUID groupId, UUID userId) {
|
||||||
|
String role = GroupDatabase.getGroupRole(groupId, userId);
|
||||||
|
if (role.equals("owner")) return true;
|
||||||
|
if (role.equals("admin")) {
|
||||||
|
JSONObject permissions = GroupDatabase.getGroupPermissions(groupId, userId);
|
||||||
|
return permissions.optBoolean("can_remove_admins", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canEditGroup(UUID groupId, UUID userId) {
|
||||||
|
String role = GroupDatabase.getGroupRole(groupId, userId);
|
||||||
|
if (role.equals("owner")) return true;
|
||||||
|
if (role.equals("admin")) {
|
||||||
|
JSONObject permissions = GroupDatabase.getGroupPermissions(groupId, userId);
|
||||||
|
return permissions.optBoolean("can_edit_group", false);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.image.Image?>
|
||||||
|
<?import javafx.scene.image.ImageView?>
|
||||||
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.layout.HBox?>
|
||||||
|
<?import javafx.scene.layout.VBox?>
|
||||||
|
|
||||||
|
<HBox xmlns="http://javafx.com/javafx"
|
||||||
|
xmlns:fx="http://javafx.com/fxml"
|
||||||
|
fx:controller="org.to.telegramfinalproject.ContactCell"
|
||||||
|
spacing="10.0" alignment="CENTER_LEFT"
|
||||||
|
prefHeight="60.0" style="-fx-padding: 10;">
|
||||||
|
|
||||||
|
<ImageView fx:id="profileImage" fitHeight="40.0" fitWidth="40.0" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@/Icons/default_user.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
|
||||||
|
<VBox spacing="4.0">
|
||||||
|
<Label fx:id="nameLabel" text="profile_name"
|
||||||
|
style="-fx-font-size: 14px; -fx-font-weight: bold;" />
|
||||||
|
<Label fx:id="statusLabel" text="● Online"
|
||||||
|
style="-fx-font-size: 12px; -fx-text-fill: green;" />
|
||||||
|
</VBox>
|
||||||
|
</HBox>
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.scene.image.*?>
|
||||||
|
<?import javafx.scene.text.*?>
|
||||||
|
<?import java.lang.*?>
|
||||||
|
<?import java.util.*?>
|
||||||
|
<?import javafx.scene.*?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
|
||||||
|
<ScrollPane prefHeight="983.0" prefWidth="859.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.to.telegramfinalproject.MainPage">
|
||||||
|
<content>
|
||||||
|
<AnchorPane prefHeight="977.0" prefWidth="845.0">
|
||||||
|
<children>
|
||||||
|
<AnchorPane layoutX="7.0" layoutY="-8.0" prefHeight="977.0" prefWidth="845.0">
|
||||||
|
<children>
|
||||||
|
<Label layoutX="-7.0" layoutY="-6.0" prefHeight="78.0" prefWidth="859.0" style="-fx-background-color: #1882da;" text=" Telegram" textFill="WHITE">
|
||||||
|
<font>
|
||||||
|
<Font name="Arial Bold" size="36.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Button contentDisplay="GRAPHIC_ONLY" layoutX="6.0" layoutY="10.0" mnemonicParsing="false" style="-fx-background-color: #1882da;">
|
||||||
|
<graphic>
|
||||||
|
<ImageView fitHeight="39.0" fitWidth="63.0" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../../../Icons/menu.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
|
<Button contentDisplay="GRAPHIC_ONLY" layoutX="703.0" layoutY="9.0" mnemonicParsing="false" prefHeight="54.0" prefWidth="135.0" style="-fx-background-color: #1882da;" text="" textFill="#d6d6d6">
|
||||||
|
<graphic>
|
||||||
|
<ImageView fitHeight="47.0" fitWidth="54.0" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../../../Icons/search.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
|
<Button contentDisplay="GRAPHIC_ONLY" layoutX="547.0" mnemonicParsing="false" prefHeight="66.0" prefWidth="114.0" style="-fx-background-color: #1882da;" text="" />
|
||||||
|
<ImageView fitHeight="50.0" fitWidth="110.0" layoutX="586.0" layoutY="14.0" pickOnBounds="true" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@../../../Icons/time.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
<ListView fx:id="contactListView" layoutX="1.0" layoutY="73.0" prefHeight="907.0" prefWidth="851.0" />
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
|
</content>
|
||||||
|
</ScrollPane>
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<?import javafx.geometry.Insets?>
|
||||||
|
<?import javafx.scene.control.*?>
|
||||||
|
<?import javafx.scene.image.*?>
|
||||||
|
<?import javafx.scene.layout.*?>
|
||||||
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
|
<AnchorPane prefHeight="800.0" prefWidth="802.0"
|
||||||
|
xmlns="http://javafx.com/javafx/8"
|
||||||
|
xmlns:fx="http://javafx.com/fxml/1"
|
||||||
|
fx:controller="org.to.telegramfinalproject.SearchingView">
|
||||||
|
|
||||||
|
<children>
|
||||||
|
|
||||||
|
<StackPane alignment="CENTER_LEFT" layoutX="0" layoutY="0" prefHeight="90.0" prefWidth="802.0">
|
||||||
|
<children>
|
||||||
|
|
||||||
|
<Label prefHeight="90.0" prefWidth="802.0"
|
||||||
|
style="-fx-background-color: #1882da;"
|
||||||
|
text=" Search" textFill="#c9c9c9">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="24.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
|
||||||
|
<HBox spacing="5.0" alignment="CENTER_LEFT">
|
||||||
|
<StackPane.margin>
|
||||||
|
<Insets left="100.0" />
|
||||||
|
</StackPane.margin>
|
||||||
|
|
||||||
|
<TextField fx:id="searchField"
|
||||||
|
promptText="Search..."
|
||||||
|
prefHeight="40.0" prefWidth="250.0"
|
||||||
|
style="-fx-background-color: #ffffff; -fx-background-radius: 20; -fx-border-radius: 20; -fx-border-color: transparent; -fx-font-size: 14;" />
|
||||||
|
|
||||||
|
<Button fx:id="searchButton"
|
||||||
|
contentDisplay="GRAPHIC_ONLY"
|
||||||
|
prefWidth="32.0" prefHeight="32.0"
|
||||||
|
style="-fx-background-color: #ffffff; -fx-background-radius: 50; -fx-border-color: transparent;">
|
||||||
|
<graphic>
|
||||||
|
<ImageView fitHeight="16.0" fitWidth="16.0" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@/Icons/search.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button fx:id="exitButton"
|
||||||
|
contentDisplay="GRAPHIC_ONLY"
|
||||||
|
prefWidth="32.0" prefHeight="32.0"
|
||||||
|
style="-fx-background-color: #ffffff; -fx-background-radius: 50; -fx-border-color: transparent;">
|
||||||
|
<graphic>
|
||||||
|
<ImageView fitHeight="16.0" fitWidth="16.0" preserveRatio="true">
|
||||||
|
<image>
|
||||||
|
<Image url="@/Icons/remove.png" />
|
||||||
|
</image>
|
||||||
|
</ImageView>
|
||||||
|
</graphic>
|
||||||
|
</Button>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
</children>
|
||||||
|
</StackPane>
|
||||||
|
|
||||||
|
</children>
|
||||||
|
</AnchorPane>
|
||||||
Reference in New Issue
Block a user