2444 lines
91 KiB
Java
2444 lines
91 KiB
Java
package org.to.telegramfinalproject.Client;
|
||
|
||
import org.json.JSONArray;
|
||
import org.json.JSONObject;
|
||
import org.to.telegramfinalproject.Models.ChatEntry;
|
||
import org.to.telegramfinalproject.Models.SearchRequestModel;
|
||
|
||
import java.io.BufferedReader;
|
||
import java.io.IOException;
|
||
import java.io.PrintWriter;
|
||
import java.time.LocalDateTime;
|
||
import java.util.*;
|
||
import java.util.concurrent.ArrayBlockingQueue;
|
||
import java.util.concurrent.BlockingQueue;
|
||
import java.util.concurrent.LinkedBlockingQueue;
|
||
import java.util.concurrent.TimeUnit;
|
||
|
||
|
||
public class ActionHandler {
|
||
private final PrintWriter out;
|
||
private final BufferedReader in;
|
||
private final Scanner scanner;
|
||
public static volatile boolean forceExitChat = false;
|
||
public static ActionHandler instance;
|
||
|
||
|
||
private void handleRealTime(JSONObject json) throws IOException {
|
||
IncomingMessageListener listener = new IncomingMessageListener(this.in);
|
||
listener.handleRealTimeEvent (json);
|
||
}
|
||
public ActionHandler(PrintWriter out, BufferedReader in, Scanner scanner) {
|
||
this.out = out;
|
||
this.in = in;
|
||
this.scanner = scanner;
|
||
ActionHandler.instance = this;
|
||
|
||
}
|
||
|
||
public void loginHandler() {
|
||
System.out.println("Login form: \n");
|
||
System.out.print("Username: ");
|
||
String username = this.scanner.nextLine();
|
||
System.out.print("Password: ");
|
||
String password = this.scanner.nextLine();
|
||
|
||
JSONObject request = new JSONObject();
|
||
request.put("action", "login");
|
||
request.put("user_id", JSONObject.NULL);
|
||
request.put("username", username);
|
||
request.put("password", password);
|
||
request.put("profile_name", JSONObject.NULL);
|
||
|
||
this.send(request);
|
||
|
||
}
|
||
|
||
public void register() {
|
||
System.out.println("Register form: \n");
|
||
System.out.print("Username: ");
|
||
String username = this.scanner.nextLine();
|
||
System.out.print("User id: ");
|
||
String user_id = this.scanner.nextLine();
|
||
System.out.print("Password: ");
|
||
String password = this.scanner.nextLine();
|
||
System.out.print("Profile name: ");
|
||
String profile_name = this.scanner.nextLine();
|
||
|
||
JSONObject request = new JSONObject();
|
||
request.put("action", "register");
|
||
request.put("user_id", user_id);
|
||
request.put("username", username);
|
||
request.put("password", password);
|
||
request.put("profile_name", profile_name);
|
||
|
||
this.send(request);
|
||
}
|
||
|
||
public void search() {
|
||
System.out.print("Enter keyword to search: ");
|
||
String keyword = scanner.nextLine();
|
||
|
||
if (Session.currentUser == null || !Session.currentUser.has("user_id")) {
|
||
System.out.println("You must be logged in to search.");
|
||
return;
|
||
}
|
||
|
||
String userId = Session.currentUser.getString("user_id");
|
||
SearchRequestModel model = new SearchRequestModel("search", keyword, userId);
|
||
send(model.toJson());
|
||
}
|
||
|
||
|
||
public void searchInUsers(){
|
||
System.out.println("Enter keyword to search: ");
|
||
String keyword = scanner.nextLine();
|
||
if (Session.currentUser == null || !Session.currentUser.has("user_id")) {
|
||
System.out.println("You must be logged in to search.");
|
||
return;
|
||
}
|
||
String userId = Session.currentUser.getString("user_id");
|
||
SearchRequestModel model = new SearchRequestModel("searchInUsers", keyword, userId);
|
||
send(model.toJson());
|
||
|
||
}
|
||
|
||
|
||
public void searchEligibleUsers(String entityType, UUID entityId) {
|
||
System.out.print("Enter keyword to search: ");
|
||
String keyword = scanner.nextLine().trim();
|
||
|
||
if (Session.currentUser == null || !Session.currentUser.has("user_id")) {
|
||
System.out.println("You must be logged in to search.");
|
||
return;
|
||
}
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "searchEligibleUsers");
|
||
req.put("keyword", keyword);
|
||
req.put("user_id", Session.currentUser.getString("user_id"));
|
||
req.put("entity_id", entityId.toString());
|
||
req.put("entity_type", entityType); // group یا channel
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ " + (res != null ? res.getString("message") : "No response received."));
|
||
return;
|
||
}
|
||
|
||
JSONArray results = res.getJSONObject("data").getJSONArray("results");
|
||
if (results.isEmpty()) {
|
||
System.out.println("⚠️ No eligible users found.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("\nEligible Users:");
|
||
for (int i = 0; i < results.length(); i++) {
|
||
JSONObject user = results.getJSONObject(i);
|
||
System.out.println((i + 1) + ". " + user.getString("name") + " (ID: " + user.getString("id") + ")");
|
||
}
|
||
|
||
System.out.print("Select a user to add (or 0 to cancel): ");
|
||
int choice;
|
||
try {
|
||
choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
} catch (Exception e) {
|
||
System.out.println("❌ Invalid input.");
|
||
return;
|
||
}
|
||
|
||
if (choice < 0 || choice >= results.length()) {
|
||
System.out.println("Cancelled.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = results.getJSONObject(choice);
|
||
UUID targetUUID = UUID.fromString(selected.getString("uuid"));
|
||
|
||
if (entityType.equals("group")) {
|
||
addMemberToGroup(entityId, targetUUID);
|
||
} else if (entityType.equals("channel")) {
|
||
addSubscriberToChannel(entityId, targetUUID);
|
||
}
|
||
}
|
||
|
||
|
||
private void addContact(UUID contactId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "add_contact");
|
||
req.put("user_id", Session.currentUser.getString("user_id"));
|
||
req.put("contact_id", contactId.toString());
|
||
send(req);
|
||
}
|
||
|
||
|
||
private void joinGroupOrChannel(String type, String uuid) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "join_" + type);
|
||
req.put("user_id", Session.getUserUUID());
|
||
req.put("id", uuid);
|
||
send(req);
|
||
}
|
||
|
||
|
||
|
||
private ChatEntry fetchChatInfo(String receiverId, String receiverType) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_info");
|
||
req.put("receiver_id", receiverId);
|
||
req.put("receiver_type", receiverType);
|
||
out.println(req.toString());
|
||
|
||
try {
|
||
JSONObject response = TelegramClient.responseQueue.take();
|
||
if (response != null && response.getString("status").equals("success")) {
|
||
JSONObject data = response.getJSONObject("data");
|
||
|
||
return new ChatEntry(
|
||
UUID.fromString(data.getString("internal_id")),
|
||
receiverId,
|
||
data.getString("name"),
|
||
data.optString("image_url", ""),
|
||
receiverType,
|
||
null,
|
||
data.optBoolean("is_owner", false),
|
||
data.optBoolean("is_admin", false)
|
||
);
|
||
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("Error fetching chat info: " + e.getMessage());
|
||
}
|
||
|
||
// اگر شکست خورد، internalId نامعتبر میسازیم (برای جلوگیری از null)
|
||
return new ChatEntry(
|
||
UUID.randomUUID(), // ساخت یک UUID موقت (ولی اشتباه)
|
||
receiverId,
|
||
"[Unknown " + receiverType + "]",
|
||
"",
|
||
receiverType,
|
||
null
|
||
);
|
||
}
|
||
|
||
|
||
private void refreshChatList() {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_list");
|
||
req.put("user_id", Session.currentUser.getString("user_id"));
|
||
out.println(req.toString());
|
||
|
||
try {
|
||
JSONObject response = TelegramClient.responseQueue.take();
|
||
|
||
if (response != null && response.getString("status").equals("success")) {
|
||
if (response.has("data") && !response.isNull("data")) {
|
||
JSONObject data = response.getJSONObject("data");
|
||
|
||
// ❗ چک کن که chat_list وجود داره
|
||
if (!data.has("chat_list") || data.isNull("chat_list")) {
|
||
System.out.println("❌ chat_list not found in response data.");
|
||
return;
|
||
}
|
||
|
||
JSONArray chatListJson = data.getJSONArray("chat_list");
|
||
List<ChatEntry> chatList = new ArrayList<>();
|
||
|
||
for (Object obj : chatListJson) {
|
||
JSONObject chat = (JSONObject) obj;
|
||
|
||
ChatEntry entry = new ChatEntry(
|
||
UUID.fromString(chat.getString("internal_id")),
|
||
chat.getString("id"),
|
||
chat.getString("name"),
|
||
chat.optString("image_url", ""),
|
||
chat.getString("type"),
|
||
chat.isNull("last_message_time") ? null : LocalDateTime.parse(chat.getString("last_message_time")),
|
||
chat.optBoolean("is_owner", false),
|
||
chat.optBoolean("is_admin", false)
|
||
);
|
||
|
||
chatList.add(entry);
|
||
}
|
||
|
||
Session.chatList = chatList;
|
||
System.out.println("✅ Chat list updated. Total: " + chatList.size());
|
||
} else {
|
||
System.out.println("⚠️ Response has no data object.");
|
||
}
|
||
} else {
|
||
if (response.has("message") && !response.isNull("message")) {
|
||
System.out.println("❌ Failed to refresh chat list: " + response.getString("message"));
|
||
} else {
|
||
System.out.println("❌ Failed to refresh chat list.");
|
||
}
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("❌ Error during refreshChatList: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
|
||
public void createGroup() {
|
||
System.out.print("Enter group ID: ");
|
||
String groupId = scanner.nextLine();
|
||
String groupName = null;
|
||
while (groupName == null) {
|
||
System.out.print("Enter group name: ");
|
||
String input = scanner.nextLine();
|
||
if (!input.trim().isEmpty()) {
|
||
groupName = input;
|
||
} else {
|
||
System.out.println("Group name can't be empty.");
|
||
}
|
||
}
|
||
System.out.print("Enter image URL (optional): ");
|
||
String imageUrl = scanner.nextLine();
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "create_group");
|
||
req.put("user_id", Session.getUserUUID());
|
||
req.put("group_id", groupId);
|
||
req.put("group_name", groupName);
|
||
req.put("image_url", imageUrl.isBlank() ? JSONObject.NULL : imageUrl);
|
||
|
||
send(req);
|
||
}
|
||
|
||
|
||
|
||
public void createChannel() {
|
||
System.out.print("Enter channel ID: ");
|
||
String channelId = scanner.nextLine();
|
||
String channelName = null;
|
||
while (channelName == null) {
|
||
System.out.print("Enter channel name: ");
|
||
String input = scanner.nextLine();
|
||
if (!input.trim().isEmpty()) {
|
||
channelName = input;
|
||
} else {
|
||
System.out.println("Channel name can't be empty.");
|
||
}
|
||
}
|
||
System.out.print("Enter image URL (optional): ");
|
||
String imageUrl = scanner.nextLine();
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "create_channel");
|
||
req.put("user_id", Session.getUserUUID());
|
||
req.put("channel_id", channelId);
|
||
req.put("channel_name", channelName);
|
||
req.put("image_url", imageUrl.isBlank() ? JSONObject.NULL : imageUrl);
|
||
|
||
send(req);
|
||
}
|
||
|
||
public void addMember(UUID memberId){
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "add_member");
|
||
req.put("user_id", Session.currentUser.getString("user_id"));
|
||
//req.put("group/channel",)
|
||
req.put("member_id", memberId.toString());
|
||
send(req);
|
||
}
|
||
|
||
|
||
|
||
|
||
private void send(JSONObject request) {
|
||
try {
|
||
if (!request.has("action") || request.isNull("action")) {
|
||
System.err.println("❌ Invalid request: missing action.");
|
||
return;
|
||
}
|
||
|
||
String action = request.getString("action");
|
||
this.out.println(request.toString());
|
||
|
||
JSONObject response = null;
|
||
|
||
// منتظر بمون تا پاسخ واقعی (یعنی status داشته باشه) بیاد
|
||
while (true) {
|
||
JSONObject incoming = TelegramClient.responseQueue.take();
|
||
|
||
if (incoming.has("status")) {
|
||
response = incoming;
|
||
break;
|
||
} else {
|
||
// این یک پیام Real-Time است
|
||
handleRealTime(incoming); // ✅
|
||
}
|
||
}
|
||
|
||
if (response == null) {
|
||
System.out.println("⚠️ No usable response received.");
|
||
return;
|
||
}
|
||
|
||
if (response.has("message") && !response.isNull("message")) {
|
||
System.out.println("✅ Server Response: " + response.getString("message"));
|
||
}
|
||
|
||
String status = response.optString("status", "error");
|
||
if (!"success".equals(status) || !response.has("data") || response.isNull("data"))
|
||
return;
|
||
|
||
|
||
switch (action) {
|
||
case "login":
|
||
case "register":
|
||
Session.currentUser = response.getJSONObject("data");
|
||
|
||
JSONArray chatListJson = Session.currentUser.getJSONArray("chat_list");
|
||
List<ChatEntry> chatList = new ArrayList<>();
|
||
|
||
for (Object obj : chatListJson) {
|
||
JSONObject chat = (JSONObject) obj;
|
||
|
||
ChatEntry entry = new ChatEntry(
|
||
UUID.fromString(chat.getString("internal_id")),
|
||
chat.getString("id"),
|
||
chat.getString("name"),
|
||
chat.optString("image_url", ""),
|
||
chat.getString("type"),
|
||
chat.isNull("last_message_time") ? null : LocalDateTime.parse(chat.getString("last_message_time")),
|
||
chat.optBoolean("is_owner", false),
|
||
chat.optBoolean("is_admin", false)
|
||
);
|
||
|
||
|
||
|
||
chatList.add(entry);
|
||
|
||
}
|
||
|
||
|
||
Session.chatList = chatList;
|
||
break;
|
||
|
||
case "searchInUsers":
|
||
JSONArray result = response.getJSONObject("data").getJSONArray("results");
|
||
if (result.isEmpty()){
|
||
System.out.println("No results found.");
|
||
}
|
||
else{
|
||
System.out.println("Search Results:");
|
||
for (int i = 0 ; i < result.length(); i++){
|
||
JSONObject item = result.getJSONObject(i);
|
||
String type = item.getString("type");
|
||
if(type.equals("user")){
|
||
System.out.println((i + 1) + ". [" + type + "] "
|
||
+ item.getString("name") + " (ID: " + item.getString("id") + ")");
|
||
}
|
||
}
|
||
System.out.print("Select a result number to interact(0 for return): ");
|
||
int index = Integer.parseInt(scanner.nextLine()) - 1;
|
||
if (index < 0 || index >= result.length()) return;
|
||
JSONObject selected = result.getJSONObject(index);
|
||
String userId = selected.getString("id");
|
||
String uuid = selected.getString("uuid");
|
||
UUID memberId = UUID.fromString(uuid);
|
||
addMember(memberId);
|
||
}
|
||
break;
|
||
case "search" :
|
||
JSONArray results = response.getJSONObject("data").getJSONArray("results");
|
||
|
||
if (results.isEmpty()) {
|
||
System.out.println("No results found.");
|
||
} else {
|
||
System.out.println("\nSearch Results:");
|
||
for (int i = 0; i < results.length(); i++) {
|
||
JSONObject item = results.getJSONObject(i);
|
||
String type = item.getString("type");
|
||
|
||
if (type.equals("message")) {
|
||
System.out.println((i + 1) + ". [message] \"" + item.getString("content") + "\""
|
||
+ " (from: " + item.optString("sender", "N/A") + ", at: " + item.getString("time") + ")");
|
||
} else {
|
||
System.out.println((i + 1) + ". [" + type + "] "
|
||
+ item.getString("name") + " (ID: " + item.getString("id") + ")");
|
||
}
|
||
}
|
||
|
||
System.out.print("Select a result number to interact (or 0 to exit): ");
|
||
int index = Integer.parseInt(scanner.nextLine()) - 1;
|
||
if (index == -1) {
|
||
System.out.println("Exit...");
|
||
return;
|
||
}
|
||
if (index < -1 || index >= results.length()) return;
|
||
|
||
JSONObject selected = results.getJSONObject(index);
|
||
String type = selected.getString("type");
|
||
|
||
switch (type) {
|
||
case "user" -> {
|
||
String uuidStr = selected.getString("uuid");
|
||
UUID uuid = UUID.fromString(uuidStr);
|
||
|
||
System.out.println("🔍 Looking for chat with internal_id='" + uuid + "' type='private'");
|
||
|
||
ChatEntry existing = Session.chatList.stream()
|
||
.filter(c -> c.getId().equals(uuid) && c.getType().equals("private"))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
if (existing != null) {
|
||
openChat(existing);
|
||
} else {
|
||
System.out.println("ℹ Trying to add contact...");
|
||
addContact(uuid);
|
||
|
||
refreshChatList();
|
||
System.out.println("🔄 Rechecking chat list...");
|
||
|
||
existing = Session.chatList.stream()
|
||
.filter(c -> c.getId().equals(uuid) && c.getType().equals("private"))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
if (existing != null) {
|
||
openChat(existing);
|
||
} else {
|
||
System.out.println("❌ Failed to open chat. Try again later.");
|
||
}
|
||
}
|
||
}
|
||
|
||
case "group", "channel" -> {
|
||
String uuidStr = selected.getString("uuid");
|
||
UUID uuid = UUID.fromString(uuidStr);
|
||
|
||
System.out.println("🔍 Looking for chat with internal_id='" + uuid + "' type='" + type + "'");
|
||
|
||
ChatEntry existing = Session.chatList.stream()
|
||
.filter(c -> c.getId().equals(uuid) && c.getType().equals(type))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
if (existing != null) {
|
||
openChat(existing);
|
||
} else {
|
||
System.out.println("ℹ Trying to join " + type + "...");
|
||
joinGroupOrChannel(type, uuidStr);
|
||
|
||
refreshChatList();
|
||
System.out.println("🔄 Rechecking chat list...");
|
||
|
||
existing = Session.chatList.stream()
|
||
.filter(c -> c.getId().equals(uuid) && c.getType().equals(type))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
if (existing != null) {
|
||
openChat(existing);
|
||
} else {
|
||
System.out.println("❌ Failed to open " + type + ". Try again later.");
|
||
}
|
||
}
|
||
}
|
||
|
||
case "message" -> {
|
||
String receiverId = selected.getString("receiver_id");
|
||
String receiverType = selected.getString("receiver_type");
|
||
|
||
System.out.println("🔍 Looking for chat with displayId='" + receiverId + "' type='" + receiverType + "'");
|
||
|
||
ChatEntry chat = Session.chatList.stream()
|
||
.filter(c -> c.getDisplayId().equals(receiverId) && c.getType().equals(receiverType))
|
||
.findFirst()
|
||
.orElseGet(() -> fetchChatInfo(receiverId, receiverType));
|
||
|
||
openChat(chat);
|
||
}
|
||
|
||
default -> System.out.println("No interaction available for type: " + type);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
break;
|
||
|
||
|
||
case "create_group":
|
||
case "create_channel":
|
||
if (response.has("data")) {
|
||
JSONObject chatJson = response.getJSONObject("data");
|
||
|
||
ChatEntry chat = new ChatEntry(
|
||
UUID.fromString(chatJson.getString("internal_id")),
|
||
chatJson.getString("id"),
|
||
chatJson.getString("name"),
|
||
chatJson.optString("image_url", ""),
|
||
chatJson.getString("type"),
|
||
null,
|
||
chatJson.optBoolean("is_owner", false),
|
||
chatJson.optBoolean("is_admin", false)
|
||
);
|
||
|
||
|
||
refreshChatList();
|
||
System.out.println("✅ Created and opening chat...");
|
||
refreshChatList();
|
||
openChat(chat);
|
||
}
|
||
|
||
break;
|
||
|
||
case "get_messages":
|
||
JSONArray messages = response.getJSONObject("data").getJSONArray("messages");
|
||
System.out.println("\n🔓 Messages fetched:");
|
||
System.out.println("─────────────────────────────────────────────");
|
||
for (int i = 0; i < messages.length(); i++) {
|
||
JSONObject m = messages.getJSONObject(i);
|
||
String senderId = m.getString("sender_id");
|
||
String content = m.getString("content");
|
||
String time = m.getString("send_at");
|
||
|
||
String label = senderId.equals(Session.currentUser.getString("internal_uuid")) ? "You" : "Other";
|
||
System.out.println("[" + time + "] " + label + ": " + content);
|
||
}
|
||
System.out.println("─────────────────────────────────────────────");
|
||
break;
|
||
|
||
|
||
case "logout":
|
||
Session.currentUser = null;
|
||
Session.chatList = null;
|
||
break;
|
||
}
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("❌ Error during send(): " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
|
||
public void userMenu(UUID internal_uuid) throws IOException {
|
||
while (true) {
|
||
|
||
|
||
if (Session.backToChatList) {
|
||
Session.backToChatList = false;
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
System.out.println("\nUser Menu:");
|
||
System.out.println("1. Show chat list");
|
||
System.out.println("2. Search");
|
||
System.out.println("3. Create Channel");
|
||
System.out.println("4. Create group");
|
||
System.out.println("5. Logout");
|
||
System.out.print("Choose an option: ");
|
||
String choice = scanner.nextLine();
|
||
|
||
switch (choice) {
|
||
case "1" -> {
|
||
Session.inChatListMenu = true;
|
||
showChatListAndSelect();
|
||
Session.inChatListMenu = false;
|
||
}
|
||
case "2" -> search();
|
||
case "3" -> createChannel();
|
||
case "4" -> createGroup();
|
||
case "5" -> {
|
||
logout();
|
||
return;
|
||
}
|
||
default -> System.out.println("Invalid choice.");
|
||
}
|
||
}
|
||
}
|
||
|
||
public void showChatListAndSelect() {
|
||
|
||
|
||
List<ChatEntry> chatList = Session.getChatList();
|
||
if (chatList.isEmpty()) {
|
||
System.out.println("📭 You have no chats.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("\nYour Chats:");
|
||
for (int i = 0; i < chatList.size(); i++) {
|
||
ChatEntry entry = chatList.get(i);
|
||
String last = entry.getLastMessageTime() == null ? "No messages yet" : entry.getLastMessageTime().toString();
|
||
System.out.printf("%d. [%s] %s - Last: %s\n", i + 1, entry.getType(), entry.getName(), last);
|
||
}
|
||
|
||
System.out.print("Select a chat by number: ");
|
||
int choice = Integer.parseInt(scanner.nextLine());
|
||
if (choice < 1 || choice > chatList.size()) {
|
||
System.out.println("❌ Invalid choice.");
|
||
return;
|
||
}
|
||
|
||
openChat(chatList.get(choice - 1));
|
||
}
|
||
|
||
|
||
|
||
private void openChat(ChatEntry chat) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_messages");
|
||
req.put("receiver_id", chat.getId());
|
||
req.put("receiver_type", chat.getType());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch messages.");
|
||
return;
|
||
}
|
||
|
||
JSONArray messages = res.getJSONObject("data").getJSONArray("messages");
|
||
System.out.println("\n🔓 Messages fetched:");
|
||
System.out.println("─────────────────────────────────────────────");
|
||
for (int i = 0; i < messages.length(); i++) {
|
||
JSONObject m = messages.getJSONObject(i);
|
||
String senderId = m.getString("sender_id");
|
||
String content = m.getString("content");
|
||
String time = m.getString("send_at");
|
||
|
||
String label = senderId.equals(Session.currentUser.getString("internal_uuid")) ? "You" : "Other";
|
||
System.out.println("[" + time + "] " + label + ": " + content);
|
||
}
|
||
System.out.println("─────────────────────────────────────────────");
|
||
|
||
boolean stayInChat = true;
|
||
|
||
|
||
Session.currentChatId = chat.getId().toString();
|
||
Session.currentChatEntry = chat;
|
||
Session.currentChatType = chat.getType().toLowerCase();
|
||
Session.inChatMenu = true;
|
||
startMenuRefresherThread();
|
||
|
||
|
||
while (stayInChat) {
|
||
if (forceExitChat) {
|
||
System.out.println("⚠️ You have been removed from this chat or chat was deleted. Returning to chat list...");
|
||
forceExitChat = false;
|
||
break;
|
||
}
|
||
|
||
System.out.println("\n📍 Entered Chat:");
|
||
System.out.println("🔷 Name: " + chat.getName());
|
||
System.out.println("────────────────────────────────────────────");
|
||
|
||
switch (chat.getType().trim().toLowerCase()) {
|
||
case "private" -> stayInChat = showPrivateChatMenu(chat);
|
||
case "group" -> stayInChat = showGroupChatMenu(chat);
|
||
case "channel" -> stayInChat = showChannelChatMenu(chat);
|
||
default -> {
|
||
System.out.println("❗ Unknown chat type: " + chat.getType());
|
||
stayInChat = false;
|
||
}
|
||
}
|
||
}
|
||
|
||
Session.inChatMenu = false;
|
||
Session.currentChatId = null;
|
||
Session.currentChatEntry = null;
|
||
Session.currentChatType = null;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private boolean showPrivateChatMenu(ChatEntry chat) {
|
||
|
||
if (forceExitChat) {
|
||
forceExitChat = false;
|
||
System.out.println("🚪 Exiting chat due to real-time update.");
|
||
return false;
|
||
}
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_profile");
|
||
req.put("target_id", chat.getId()); // internal UUID
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
|
||
if (res.getString("status").equals("success")) {
|
||
JSONObject data = res.getJSONObject("data");
|
||
|
||
System.out.println("\n💬 Private Chat with: " + data.getString("profile_name"));
|
||
|
||
if (data.getBoolean("is_online")) {
|
||
System.out.println("✅ Status: Online");
|
||
} else {
|
||
System.out.println("📅 Last seen: " + data.getString("last_seen"));
|
||
}
|
||
|
||
System.out.println("────────────────────────────────────────────");
|
||
}
|
||
|
||
|
||
System.out.println("1. Send message");
|
||
System.out.println("2. Block/Unblock");
|
||
System.out.println("3. Delete chat (one-sided)");
|
||
System.out.println("4. Delete chat (both sides)");
|
||
System.out.println("5. View profile");
|
||
System.out.println("6. Back");
|
||
|
||
|
||
String input = scanner.nextLine();
|
||
switch (input) {
|
||
case "1" -> sendMessageTo(chat.getId(), "private");
|
||
case "2" -> toggleBlock(chat.getId());
|
||
case "3" -> {
|
||
deleteChat(chat.getId(), false);
|
||
return false;
|
||
}
|
||
case "4" -> {
|
||
deleteChat(chat.getId(), true);
|
||
return false;
|
||
}
|
||
case "5" -> {
|
||
JSONObject reqProfile = new JSONObject();
|
||
reqProfile.put("action", "view_profile");
|
||
reqProfile.put("target_id", chat.getId());
|
||
|
||
JSONObject resProfile = sendWithResponse(reqProfile);
|
||
|
||
if (resProfile.getString("status").equals("success")) {
|
||
JSONObject profile = resProfile.getJSONObject("data");
|
||
System.out.println("\n👤 Profile Info:");
|
||
System.out.println("🔷 Name: " + profile.optString("profile_name", "Unknown"));
|
||
System.out.println("📄 Bio: " + profile.optString("bio", "No bio set"));
|
||
System.out.println("🖼️ Image URL: " + profile.optString("image_url", "N/A"));
|
||
|
||
if (profile.getBoolean("is_online")) {
|
||
System.out.println("✅ Status: Online");
|
||
} else {
|
||
System.out.println("📅 Last seen: " + profile.optString("last_seen", "Unknown"));
|
||
}
|
||
System.out.println("────────────────────────────────────────────");
|
||
} else {
|
||
System.out.println("❌ Could not load profile.");
|
||
}
|
||
return true;
|
||
}
|
||
|
||
case "6" -> {
|
||
return false;
|
||
}
|
||
default -> System.out.println("Invalid choice.");
|
||
}
|
||
return true;
|
||
}
|
||
|
||
private JSONObject getGroupPermissions(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_group_permissions");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
return new JSONObject();
|
||
}
|
||
return res.getJSONObject("data");
|
||
}
|
||
|
||
|
||
|
||
private boolean showGroupChatMenu(ChatEntry chat) {
|
||
if (forceExitChat) {
|
||
forceExitChat = false;
|
||
System.out.println("🚪 Exiting chat due to real-time update.");
|
||
return false;
|
||
}
|
||
|
||
boolean isAdmin = chat.isAdmin();
|
||
boolean isOwner = chat.isOwner();
|
||
JSONObject perms = getGroupPermissions(chat.getId());
|
||
|
||
System.out.println("\n--- Group Chat Menu ---");
|
||
System.out.println("1. Send Message");
|
||
System.out.println("2. View Members");
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_members", false))) {
|
||
System.out.println("3. Add Member");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_edit_group", false))) {
|
||
System.out.println("4. Edit Group Info");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_admins", false))) {
|
||
System.out.println("5. Add Admin");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_admins", false))) {
|
||
System.out.println("6. Remove Admin");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_members", false))) {
|
||
System.out.println("7. Remove member");
|
||
}
|
||
if (isOwner) {
|
||
System.out.println("8. Delete Group");
|
||
System.out.println("9. Leave Group (Transfer ownership required)");
|
||
} else {
|
||
System.out.println("9. Leave Group");
|
||
}
|
||
System.out.println("10. View Profile");
|
||
|
||
System.out.println("0. Back to Chat List");
|
||
|
||
String input = scanner.nextLine();
|
||
switch (input) {
|
||
case "1" -> sendMessageTo(chat.getId(), "group");
|
||
case "2" -> viewGroupMembers(chat.getId());
|
||
case "3" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_members", false)))
|
||
searchEligibleUsers("group", chat.getId());
|
||
else System.out.println("❌ You don't have permission.");
|
||
}
|
||
case "4" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_edit_group", false))) editGroupInfo(chat.getId());
|
||
else System.out.println("❌ You don't have permission.");
|
||
}
|
||
case "5" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_admins", false))) addAdminToGroup(chat.getId());
|
||
else System.out.println("❌ You don't have permission.");
|
||
}
|
||
case "6" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_admins", false))) removeAdminFromGroup(chat.getId());
|
||
else System.out.println("❌ You don't have permission.");
|
||
}
|
||
case "7" ->{
|
||
if(isOwner || (isAdmin && perms.optBoolean("can_remove_members",false))) removeMemberFromGroup(chat.getId());
|
||
}
|
||
case "8" -> {
|
||
if (isOwner) deleteGroup(chat.getId());
|
||
else System.out.println("❌ You don't have permission.");
|
||
return false;
|
||
}
|
||
case "9" -> {
|
||
if (isOwner) {
|
||
transferOwnershipAndLeave(chat.getId());
|
||
} else {
|
||
leaveChat(chat.getId(), "group");
|
||
// refreshChatList();
|
||
}
|
||
return false;
|
||
}
|
||
case "10" ->{
|
||
GroupInfo(chat.getId());
|
||
}
|
||
|
||
case "0" -> {
|
||
return false;
|
||
}
|
||
default -> System.out.println("Invalid choice.");
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
|
||
private boolean showChannelChatMenu(ChatEntry chat) {
|
||
if (forceExitChat) {
|
||
forceExitChat = false;
|
||
System.out.println("🚪 Exiting chat due to real-time update.");
|
||
return false;
|
||
}
|
||
|
||
chat = fetchChatInfo(chat.getId().toString(), chat.getType());
|
||
boolean isAdmin = chat.isAdmin();
|
||
boolean isOwner = chat.isOwner();
|
||
|
||
JSONObject perms = getChannelPermissions(chat.getId());
|
||
|
||
System.out.println("\n--- Channel Menu ---");
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_post", false))) {
|
||
System.out.println("1. Send Post");
|
||
}
|
||
|
||
if (isOwner || isAdmin) {
|
||
System.out.println("2. View Subscribers");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_members", false))) {
|
||
System.out.println("3. Add Subscriber");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_members", false))) {
|
||
System.out.println("4. Remove Subscriber");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_edit_channel", false))) {
|
||
System.out.println("5. Edit Channel Info");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_admins", false))) {
|
||
System.out.println("6. Add Admin");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_admins", false))) {
|
||
System.out.println("7. Remove Admin");
|
||
}
|
||
|
||
if (isOwner) {
|
||
System.out.println("8. Delete Channel");
|
||
System.out.println("9. Leave Channel (Transfer ownership required)");
|
||
} else {
|
||
System.out.println("8. Leave Channel");
|
||
}
|
||
|
||
System.out.println("10. View Profile");
|
||
System.out.println("0. Back to Chat List");
|
||
|
||
String input = scanner.nextLine();
|
||
switch (input) {
|
||
case "1" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_post", false))) {
|
||
sendMessageTo(chat.getId(), "channel");
|
||
} else {
|
||
System.out.println("❌ You don't have permission to post.");
|
||
}
|
||
}
|
||
case "2" -> {
|
||
if (isOwner || isAdmin) {
|
||
viewChannelSubscribers(chat.getId());
|
||
} else {
|
||
System.out.println("❌ You don't have permission to view subscribers.");
|
||
}
|
||
}
|
||
case "3" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_members", false))) {
|
||
searchEligibleUsers("channel", chat.getId());
|
||
} else {
|
||
System.out.println("❌ You don't have permission to add subscribers.");
|
||
}
|
||
}
|
||
case "4" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_members", false))) {
|
||
removeSubscriberFromChannel(chat.getId());
|
||
} else {
|
||
System.out.println("❌ You don't have permission to remove subscribers.");
|
||
}
|
||
}
|
||
case "5" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_edit_channel", false))) {
|
||
editChannelInfo(chat.getId());
|
||
} else {
|
||
System.out.println("❌ You don't have permission to edit channel info.");
|
||
}
|
||
}
|
||
case "6" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_admins", false))) {
|
||
addAdminToChannel(chat.getId());
|
||
} else {
|
||
System.out.println("❌ You don't have permission to add admins.");
|
||
}
|
||
}
|
||
case "7" -> {
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_admins", false))) {
|
||
removeAdminFromChannel(chat.getId());
|
||
} else {
|
||
System.out.println("❌ You don't have permission to remove admins.");
|
||
}
|
||
}
|
||
case "8" -> {
|
||
if (isOwner) {
|
||
deleteChannel(chat.getId());
|
||
return false;
|
||
} else {
|
||
leaveChat(chat.getId(), "channel");
|
||
return false;
|
||
}
|
||
}
|
||
case "9" -> {
|
||
if (isOwner) {
|
||
transferChannelOwnershipAndLeave(chat.getId());
|
||
return false;
|
||
} else {
|
||
System.out.println("❌ You don't have permission.");
|
||
}
|
||
}
|
||
case "10"->{
|
||
ChannelInfo(chat.getId());
|
||
}
|
||
case "0" -> {
|
||
return false;
|
||
}
|
||
default -> System.out.println("Invalid choice.");
|
||
}
|
||
return true;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
private void transferOwnershipAndLeave(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_group_admins");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch admins.");
|
||
return;
|
||
}
|
||
|
||
JSONArray admins = res.getJSONObject("data").getJSONArray("admins");
|
||
|
||
if (admins.length() == 0) {
|
||
System.out.println("⚠️ No other admins available. You cannot leave without promoting someone to owner.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("--- Admins List ---");
|
||
for (int i = 0; i < admins.length(); i++) {
|
||
JSONObject admin = admins.getJSONObject(i);
|
||
System.out.printf("%d. %s (%s)\n", i + 1, admin.getString("profile_name"), admin.getString("user_id"));
|
||
}
|
||
|
||
System.out.print("Select a new owner by number: ");
|
||
int choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
|
||
if (choice < 0 || choice >= admins.length()) {
|
||
System.out.println("Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = admins.getJSONObject(choice);
|
||
String newOwnerId = selected.getString("user_id");
|
||
|
||
JSONObject promoteReq = new JSONObject();
|
||
promoteReq.put("action", "transfer_group_ownership");
|
||
promoteReq.put("group_id", groupId.toString());
|
||
promoteReq.put("new_owner_user_id", newOwnerId);
|
||
|
||
JSONObject promoteRes = sendWithResponse(promoteReq);
|
||
if (promoteRes == null || !promoteRes.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to transfer ownership.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("✅ Ownership transferred successfully.");
|
||
leaveChat(groupId, "group");
|
||
}
|
||
|
||
private void removeMemberFromGroup(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_group_members");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch members.");
|
||
return;
|
||
}
|
||
|
||
JSONArray members = res.getJSONObject("data").getJSONArray("members");
|
||
List<JSONObject> eligible = new ArrayList<>();
|
||
|
||
System.out.println("\n--- Members List ---");
|
||
for (int i = 0; i < members.length(); i++) {
|
||
JSONObject m = members.getJSONObject(i);
|
||
String role = m.getString("role");
|
||
String profileName = m.getString("profile_name");
|
||
String userId = m.getString("user_id");
|
||
|
||
if (role.equals("owner")) continue;
|
||
|
||
eligible.add(m);
|
||
System.out.println((eligible.size()) + ". " + profileName + " (" + userId + ") [" + role + "]");
|
||
}
|
||
|
||
if (eligible.isEmpty()) {
|
||
System.out.println("⚠️ No removable members.");
|
||
return;
|
||
}
|
||
|
||
System.out.print("Select a member to remove: ");
|
||
int choice;
|
||
try {
|
||
choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
} catch (Exception e) {
|
||
System.out.println("❌ Invalid input.");
|
||
return;
|
||
}
|
||
|
||
if (choice < 0 || choice >= eligible.size()) {
|
||
System.out.println("❌ Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = eligible.get(choice);
|
||
String targetInternalUUID = selected.getString("internal_uuid");
|
||
|
||
JSONObject removeReq = new JSONObject();
|
||
removeReq.put("action", "remove_member_from_group");
|
||
removeReq.put("group_id", groupId.toString());
|
||
removeReq.put("user_id", targetInternalUUID);
|
||
|
||
JSONObject removeRes = sendWithResponse(removeReq);
|
||
if (removeRes != null)
|
||
System.out.println(removeRes.getString("message"));
|
||
}
|
||
|
||
|
||
|
||
private void addAdminToChannel(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_channel_subscribers");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch subscribers.");
|
||
return;
|
||
}
|
||
|
||
JSONArray subscribers = res.getJSONObject("data").getJSONArray("subscribers");
|
||
List<JSONObject> eligible = new ArrayList<>();
|
||
|
||
System.out.println("\n--- Subscribers List ---");
|
||
for (int i = 0; i < subscribers.length(); i++) {
|
||
JSONObject s = subscribers.getJSONObject(i);
|
||
String role = s.getString("role");
|
||
String profileName = s.getString("profile_name");
|
||
String userId = s.getString("user_id");
|
||
|
||
if (role.equals("subscriber")) {
|
||
eligible.add(s);
|
||
System.out.printf("%d. %s (%s)\n", eligible.size(), profileName, userId);
|
||
}
|
||
}
|
||
|
||
if (eligible.isEmpty()) {
|
||
System.out.println("⚠️ No eligible subscribers to promote.");
|
||
return;
|
||
}
|
||
|
||
System.out.print("Select a subscriber to promote to admin: ");
|
||
int choice;
|
||
try {
|
||
choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
} catch (Exception e) {
|
||
System.out.println("❌ Invalid input.");
|
||
return;
|
||
}
|
||
|
||
if (choice < 0 || choice >= eligible.size()) {
|
||
System.out.println("❌ Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = eligible.get(choice);
|
||
String targetInternalUUID = selected.getString("internal_uuid");
|
||
|
||
JSONObject permissions = new JSONObject();
|
||
System.out.print("Can post? (true/false): ");
|
||
permissions.put("can_post", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can edit channel info? (true/false): ");
|
||
permissions.put("can_edit_channel", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can add members? (true/false): ");
|
||
permissions.put("can_add_members", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can remove members? (true/false): ");
|
||
permissions.put("can_remove_members", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can add admins? (true/false): ");
|
||
permissions.put("can_add_admins", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can remove admins? (true/false): ");
|
||
permissions.put("can_remove_admins", Boolean.parseBoolean(scanner.nextLine()));
|
||
|
||
JSONObject promoteReq = new JSONObject();
|
||
promoteReq.put("action", "add_admin_to_channel");
|
||
promoteReq.put("channel_id", channelId.toString());
|
||
promoteReq.put("target_user_id", targetInternalUUID);
|
||
promoteReq.put("permissions", permissions);
|
||
|
||
JSONObject promoteRes = sendWithResponse(promoteReq);
|
||
if (promoteRes != null)
|
||
System.out.println(promoteRes.getString("message"));
|
||
}
|
||
|
||
|
||
|
||
|
||
private void addAdminToGroup(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_group_members");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch members.");
|
||
return;
|
||
}
|
||
|
||
JSONArray members = res.getJSONObject("data").getJSONArray("members");
|
||
List<JSONObject> eligible = new ArrayList<>();
|
||
|
||
System.out.println("\n--- Members List ---");
|
||
for (int i = 0; i < members.length(); i++) {
|
||
JSONObject m = members.getJSONObject(i);
|
||
if (m.getString("role").equals("member")) {
|
||
eligible.add(m);
|
||
System.out.println((eligible.size()) + ". " + m.getString("profile_name") + " (" + m.getString("user_id") + ")");
|
||
}
|
||
}
|
||
|
||
if (eligible.isEmpty()) {
|
||
System.out.println("⚠️ No eligible members.");
|
||
return;
|
||
}
|
||
|
||
System.out.print("Select a member to promote: ");
|
||
int choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
if (choice < 0 || choice >= eligible.size()) {
|
||
System.out.println("❌ Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = eligible.get(choice);
|
||
String targetInternalUUID = selected.getString("internal_uuid"); // دقت کن internal_uuid
|
||
|
||
JSONObject permissions = new JSONObject();
|
||
System.out.print("Can add members? (true/false): ");
|
||
permissions.put("can_add_members", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can remove members? (true/false): ");
|
||
permissions.put("can_remove_members", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can add admins? (true/false): ");
|
||
permissions.put("can_add_admins", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can remove admins? (true/false): ");
|
||
permissions.put("can_remove_admins", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can edit group info? (true/false): ");
|
||
permissions.put("can_edit_group", Boolean.parseBoolean(scanner.nextLine()));
|
||
|
||
JSONObject promoteReq = new JSONObject();
|
||
promoteReq.put("action", "add_admin_to_group");
|
||
promoteReq.put("group_id", groupId.toString());
|
||
promoteReq.put("user_id", targetInternalUUID); // ارسال internal_uuid واقعی
|
||
promoteReq.put("permissions", permissions);
|
||
|
||
JSONObject promoteRes = sendWithResponse(promoteReq);
|
||
if (promoteRes != null)
|
||
System.out.println(promoteRes.getString("message"));
|
||
}
|
||
|
||
|
||
private void viewGroupMembers(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_group_members");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
if (res.getString("status").equals("success")) {
|
||
JSONArray members = res.getJSONObject("data").getJSONArray("members");
|
||
|
||
System.out.println("\n--- Group Members ---");
|
||
for (int i = 0; i < members.length(); i++) {
|
||
JSONObject m = members.getJSONObject(i);
|
||
String name = m.getString("profile_name");
|
||
String userId = m.getString("user_id");
|
||
String role = m.getString("role");
|
||
System.out.printf("- %s (ID: %s) [%s]\n", name, userId, role);
|
||
}
|
||
} else {
|
||
System.out.println("❌ Failed to fetch members.");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
private void removeSubscriberFromChannel(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_channel_subscribers");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch subscribers.");
|
||
return;
|
||
}
|
||
|
||
JSONArray subscribers = res.getJSONObject("data").getJSONArray("subscribers");
|
||
List<JSONObject> eligible = new ArrayList<>();
|
||
|
||
System.out.println("\n--- Subscribers List ---");
|
||
for (int i = 0; i < subscribers.length(); i++) {
|
||
JSONObject s = subscribers.getJSONObject(i);
|
||
String role = s.getString("role");
|
||
String profileName = s.getString("profile_name");
|
||
String userId = s.getString("user_id");
|
||
|
||
if (role.equals("owner")) continue;
|
||
|
||
eligible.add(s);
|
||
System.out.println((eligible.size()) + ". " + profileName + " (" + userId + ") [" + role + "]");
|
||
}
|
||
|
||
if (eligible.isEmpty()) {
|
||
System.out.println("⚠️ No removable subscribers.");
|
||
return;
|
||
}
|
||
|
||
System.out.print("Select a subscriber to remove: ");
|
||
int choice;
|
||
try {
|
||
choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
} catch (Exception e) {
|
||
System.out.println("❌ Invalid input.");
|
||
return;
|
||
}
|
||
|
||
if (choice < 0 || choice >= eligible.size()) {
|
||
System.out.println("❌ Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = eligible.get(choice);
|
||
String targetInternalUUID = selected.getString("internal_uuid");
|
||
|
||
JSONObject removeReq = new JSONObject();
|
||
removeReq.put("action", "remove_subscriber_from_channel");
|
||
removeReq.put("channel_id", channelId.toString());
|
||
removeReq.put("user_id", targetInternalUUID);
|
||
|
||
JSONObject removeRes = sendWithResponse(removeReq);
|
||
if (removeRes != null)
|
||
System.out.println(removeRes.getString("message"));
|
||
}
|
||
|
||
|
||
private void transferChannelOwnershipAndLeave(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_channel_admins");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch admins.");
|
||
return;
|
||
}
|
||
|
||
JSONArray admins = res.getJSONObject("data").getJSONArray("admins");
|
||
|
||
if (admins.length() == 0) {
|
||
System.out.println("⚠️ No other admins available. You cannot leave without promoting someone to owner.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("\n--- Admins List ---");
|
||
for (int i = 0; i < admins.length(); i++) {
|
||
JSONObject admin = admins.getJSONObject(i);
|
||
System.out.printf("%d. %s (%s)\n", i + 1, admin.getString("profile_name"), admin.getString("user_id"));
|
||
}
|
||
|
||
System.out.print("Select a new owner by number: ");
|
||
int choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
|
||
if (choice < 0 || choice >= admins.length()) {
|
||
System.out.println("Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = admins.getJSONObject(choice);
|
||
String newOwnerId = selected.getString("internal_id");
|
||
|
||
JSONObject promoteReq = new JSONObject();
|
||
promoteReq.put("action", "transfer_channel_ownership");
|
||
promoteReq.put("channel_id", channelId.toString());
|
||
promoteReq.put("new_owner_user_id", newOwnerId);
|
||
|
||
JSONObject promoteRes = sendWithResponse(promoteReq);
|
||
if (promoteRes == null || !promoteRes.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to transfer ownership.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("✅ Ownership transferred successfully.");
|
||
leaveChat(channelId, "channel");
|
||
}
|
||
|
||
|
||
|
||
private void deleteChannel(UUID channelId) {
|
||
System.out.print("Are you sure you want to delete the channel? (yes/no): ");
|
||
String confirm = scanner.nextLine().trim().toLowerCase();
|
||
|
||
if (!confirm.equals("yes")) {
|
||
System.out.println("❌ Delete cancelled.");
|
||
return;
|
||
}
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "delete_channel");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res != null && res.getString("status").equals("success")) {
|
||
System.out.println("✅ Channel deleted successfully.");
|
||
refreshChatList();
|
||
} else {
|
||
System.out.println("❌ Failed to delete channel.");
|
||
}
|
||
}
|
||
|
||
|
||
private void deleteGroup(UUID groupId) {
|
||
System.out.print("Are you sure you want to delete the group? (yes/no): ");
|
||
String confirm = scanner.nextLine().trim().toLowerCase();
|
||
|
||
if (!confirm.equals("yes")) {
|
||
System.out.println("❌ Delete cancelled.");
|
||
return;
|
||
}
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "delete_group");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res != null && res.getString("status").equals("success")) {
|
||
System.out.println("✅ Group deleted successfully.");
|
||
refreshChatList();
|
||
} else {
|
||
System.out.println("❌ Failed to delete group.");
|
||
}
|
||
}
|
||
|
||
private void deleteChat(UUID targetId, boolean both) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "delete_private_chat");
|
||
req.put("target_id", targetId.toString());
|
||
req.put("both", both);
|
||
send(req);
|
||
|
||
JSONObject resp = sendWithResponse(req);
|
||
if (resp.getString("status").equals("success")) {
|
||
System.out.println("✅ Chat deleted successfully.");
|
||
} else {
|
||
System.out.println("⚠️ Failed to delete chat.");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
private void toggleBlock(UUID userId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "toggle_block");
|
||
req.put("user_id", Session.getUserUUID());
|
||
req.put("target_id", userId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
String status = res.getString("status");
|
||
String message = res.getString("message");
|
||
|
||
if (status.equals("success")) {
|
||
System.out.println("🔒 " + message);
|
||
} else {
|
||
System.out.println("❌ " + message);
|
||
}
|
||
}
|
||
|
||
|
||
private void leaveChat(UUID id, String type) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "leave_chat");
|
||
req.put("user_id", Session.getUserUUID());
|
||
req.put("chat_id", id.toString());
|
||
req.put("chat_type", type);
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
String status = res.getString("status");
|
||
String message = res.getString("message");
|
||
|
||
if (status.equals("success")) {
|
||
System.out.println("✅ You left the chat.");
|
||
} else {
|
||
System.out.println("❌ " + message);
|
||
}
|
||
}
|
||
|
||
|
||
private void removeAdminFromGroup(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_group_admins");
|
||
req.put("group_id", groupId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch admins.");
|
||
return;
|
||
}
|
||
|
||
JSONArray admins = res.getJSONObject("data").getJSONArray("admins");
|
||
List<JSONObject> eligible = new ArrayList<>();
|
||
|
||
System.out.println("\n--- Admins List ---");
|
||
for (int i = 0; i < admins.length(); i++) {
|
||
JSONObject admin = admins.getJSONObject(i);
|
||
String role = admin.getString("role");
|
||
String profileName = admin.getString("profile_name");
|
||
String userId = admin.getString("user_id");
|
||
|
||
if (!role.equals("owner")) {
|
||
eligible.add(admin);
|
||
System.out.printf("%d. %s (%s)\n", eligible.size(), profileName, userId);
|
||
}
|
||
}
|
||
|
||
if (eligible.isEmpty()) {
|
||
System.out.println("⚠️ No removable admins.");
|
||
return;
|
||
}
|
||
|
||
System.out.print("Select an admin to remove: ");
|
||
int choice;
|
||
try {
|
||
choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
} catch (Exception e) {
|
||
System.out.println("❌ Invalid input.");
|
||
return;
|
||
}
|
||
|
||
if (choice < 0 || choice >= eligible.size()) {
|
||
System.out.println("❌ Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = eligible.get(choice);
|
||
String targetInternalUUID = selected.getString("user_id");
|
||
|
||
JSONObject removeReq = new JSONObject();
|
||
removeReq.put("action", "remove_admin_from_group");
|
||
removeReq.put("group_id", groupId.toString());
|
||
removeReq.put("target_user_id", targetInternalUUID);
|
||
|
||
JSONObject removeRes = sendWithResponse(removeReq);
|
||
if (removeRes != null)
|
||
System.out.println(removeRes.getString("message"));
|
||
}
|
||
|
||
|
||
private void removeAdminFromChannel(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_channel_admins");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch admins.");
|
||
return;
|
||
}
|
||
|
||
JSONArray admins = res.getJSONObject("data").getJSONArray("admins");
|
||
List<JSONObject> eligible = new ArrayList<>();
|
||
|
||
System.out.println("\n--- Admins List ---");
|
||
for (int i = 0; i < admins.length(); i++) {
|
||
JSONObject admin = admins.getJSONObject(i);
|
||
String role = admin.getString("role");
|
||
String profileName = admin.getString("profile_name");
|
||
String userId = admin.getString("user_id");
|
||
|
||
if (!role.equals("owner")) {
|
||
eligible.add(admin);
|
||
System.out.printf("%d. %s (%s)\n", eligible.size(), profileName, userId);
|
||
}
|
||
}
|
||
|
||
if (eligible.isEmpty()) {
|
||
System.out.println("⚠️ No removable admins.");
|
||
return;
|
||
}
|
||
|
||
System.out.print("Select an admin to remove: ");
|
||
int choice;
|
||
try {
|
||
choice = Integer.parseInt(scanner.nextLine()) - 1;
|
||
} catch (Exception e) {
|
||
System.out.println("❌ Invalid input.");
|
||
return;
|
||
}
|
||
|
||
if (choice < 0 || choice >= eligible.size()) {
|
||
System.out.println("❌ Invalid selection.");
|
||
return;
|
||
}
|
||
|
||
JSONObject selected = eligible.get(choice);
|
||
String targetInternalUUID = selected.getString("internal_uuid");
|
||
|
||
JSONObject removeReq = new JSONObject();
|
||
removeReq.put("action", "remove_admin_from_channel");
|
||
removeReq.put("channel_id", channelId.toString());
|
||
removeReq.put("target_user_id", targetInternalUUID);
|
||
|
||
JSONObject removeRes = sendWithResponse(removeReq);
|
||
if (removeRes != null)
|
||
System.out.println(removeRes.getString("message"));
|
||
}
|
||
|
||
|
||
|
||
|
||
private void sendMessageTo(UUID id, String type) {
|
||
System.out.print("Enter message: ");
|
||
String text = scanner.nextLine().trim();
|
||
|
||
if (text.isEmpty()) {
|
||
System.out.println("Message cannot be empty.");
|
||
return;
|
||
}
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "send_message");
|
||
req.put("sender_id", Session.getUserUUID());
|
||
req.put("receiver_id", id.toString());
|
||
req.put("receiver_type", type);
|
||
req.put("text", text);
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
if (res.getBoolean("success")) {
|
||
System.out.println("✅ Message sent.");
|
||
} else {
|
||
System.out.println("❌ Failed to send message.");
|
||
}
|
||
}
|
||
|
||
private void addMemberToGroup(UUID groupId, UUID userId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "add_member_to_group");
|
||
req.put("group_id", groupId.toString());
|
||
req.put("user_id", userId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res != null) {
|
||
System.out.println(res.getString("message"));
|
||
}
|
||
}
|
||
|
||
private void addSubscriberToChannel(UUID channelId, UUID targetUserId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "add_subscriber_to_channel");
|
||
req.put("channel_id", channelId.toString());
|
||
req.put("user_id", targetUserId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
if (res.getString("status").equals("success")) {
|
||
System.out.println("✅ Subscriber added successfully.");
|
||
} else {
|
||
System.out.println("❌ " + res.getString("message"));
|
||
}
|
||
}
|
||
|
||
private void GroupInfo(UUID groupId){
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_info");
|
||
req.put("receiver_id", groupId.toString());
|
||
req.put("receiver_type", "group");
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch group info.");
|
||
return;
|
||
}
|
||
|
||
JSONObject data = res.getJSONObject("data");
|
||
|
||
String currentId = data.getString("id");
|
||
String currentName = data.getString("name");
|
||
String currentDesc = data.optString("description", null);
|
||
String currentImage = data.optString("image_url", null);
|
||
|
||
System.out.println("\n--- Group Info ---");
|
||
System.out.println("1. Group ID: " + currentId);
|
||
System.out.println("2. Name: " + currentName);
|
||
System.out.println("3. Description: " + currentDesc);
|
||
System.out.println("4. Image URL: " + currentImage);
|
||
System.out.println("────────────────────────────────────────────");
|
||
|
||
|
||
}
|
||
|
||
private void editGroupInfo(UUID groupId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_info");
|
||
req.put("receiver_id", groupId.toString());
|
||
req.put("receiver_type", "group");
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch group info.");
|
||
return;
|
||
}
|
||
|
||
JSONObject data = res.getJSONObject("data");
|
||
|
||
String currentId = data.getString("id");
|
||
String currentName = data.getString("name");
|
||
String currentDesc = data.optString("description", null);
|
||
String currentImage = data.optString("image_url", null);
|
||
|
||
System.out.println("\n--- Current Group Info ---");
|
||
System.out.println("1. Group ID: " + currentId);
|
||
System.out.println("2. Name: " + currentName);
|
||
System.out.println("3. Description: " + currentDesc);
|
||
System.out.println("4. Image URL: " + currentImage);
|
||
System.out.println("0. Cancel");
|
||
|
||
System.out.print("Select the field you want to edit (0-4): ");
|
||
String choice = scanner.nextLine().trim();
|
||
|
||
String newGroupId = currentId;
|
||
String newName = currentName;
|
||
String newDesc = currentDesc;
|
||
String newImage = currentImage;
|
||
|
||
switch (choice) {
|
||
case "1" -> {
|
||
System.out.print("Enter new Group ID: ");
|
||
newGroupId = scanner.nextLine().trim();
|
||
}
|
||
case "2" -> {
|
||
System.out.print("Enter new Group Name: ");
|
||
newName = scanner.nextLine().trim();
|
||
}
|
||
case "3" -> {
|
||
System.out.print("Enter new Description: ");
|
||
newDesc = scanner.nextLine().trim();
|
||
}
|
||
case "4" -> {
|
||
System.out.print("Enter new Image URL: ");
|
||
newImage = scanner.nextLine().trim();
|
||
}
|
||
case "0" -> {
|
||
System.out.println("Cancelled.");
|
||
return;
|
||
}
|
||
default -> {
|
||
System.out.println("Invalid choice.");
|
||
return;
|
||
}
|
||
}
|
||
|
||
JSONObject editReq = new JSONObject();
|
||
editReq.put("action", "edit_group_info");
|
||
editReq.put("group_id", groupId.toString()); // internal_uuid
|
||
editReq.put("new_group_id", newGroupId);
|
||
editReq.put("name", newName);
|
||
editReq.put("description", newDesc);
|
||
editReq.put("image_url", newImage);
|
||
|
||
JSONObject editRes = sendWithResponse(editReq);
|
||
if (editRes != null)
|
||
System.out.println(editRes.getString("message"));
|
||
}
|
||
|
||
|
||
|
||
private void viewChannelSubscribers(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_channel_subscribers");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
if (res.getString("status").equals("success")) {
|
||
JSONObject data = res.getJSONObject("data");
|
||
JSONArray subs = data.getJSONArray("subscribers");
|
||
|
||
System.out.println("--- Subscribers ---");
|
||
for (int i = 0; i < subs.length(); i++) {
|
||
JSONObject s = subs.getJSONObject(i);
|
||
System.out.println("- " + s.getString("profile_name"));
|
||
}
|
||
} else {
|
||
System.out.println("❌ Failed to load subscribers.");
|
||
}
|
||
}
|
||
|
||
private void ChannelInfo(UUID channelInternalId){
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_info");
|
||
req.put("receiver_id", channelInternalId.toString());
|
||
req.put("receiver_type", "channel");
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch channel info.");
|
||
return;
|
||
}
|
||
|
||
JSONObject data = res.getJSONObject("data");
|
||
|
||
String currentId = data.getString("id");
|
||
String currentName = data.getString("name");
|
||
String currentDesc = data.optString("description", null);
|
||
String currentImage = data.optString("image_url", null);
|
||
|
||
System.out.println("\n--- Channel Info ---");
|
||
System.out.println("1. Channel ID: " + currentId);
|
||
System.out.println("2. Name: " + currentName);
|
||
System.out.println("3. Description: " + currentDesc);
|
||
System.out.println("4. Image URL: " + currentImage);
|
||
System.out.println("────────────────────────────────────────────");
|
||
|
||
}
|
||
|
||
|
||
private void editChannelInfo(UUID channelInternalId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_info");
|
||
req.put("receiver_id", channelInternalId.toString());
|
||
req.put("receiver_type", "channel");
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
System.out.println("❌ Failed to fetch channel info.");
|
||
return;
|
||
}
|
||
|
||
JSONObject data = res.getJSONObject("data");
|
||
|
||
String currentId = data.getString("id");
|
||
String currentName = data.getString("name");
|
||
String currentDesc = data.optString("description", null);
|
||
String currentImage = data.optString("image_url", null);
|
||
|
||
System.out.println("\n--- Current Channel Info ---");
|
||
System.out.println("1. Channel ID: " + currentId);
|
||
System.out.println("2. Name: " + currentName);
|
||
System.out.println("3. Description: " + currentDesc);
|
||
System.out.println("4. Image URL: " + currentImage);
|
||
System.out.println("0. Cancel");
|
||
|
||
System.out.print("Select the field you want to edit (0-4): ");
|
||
String choice = scanner.nextLine().trim();
|
||
|
||
String newChannelId = currentId;
|
||
String newName = currentName;
|
||
String newDesc = currentDesc;
|
||
String newImage = currentImage;
|
||
|
||
switch (choice) {
|
||
case "1" -> {
|
||
System.out.print("Enter new Channel ID: ");
|
||
newChannelId = scanner.nextLine().trim();
|
||
}
|
||
case "2" -> {
|
||
System.out.print("Enter new Channel Name: ");
|
||
newName = scanner.nextLine().trim();
|
||
}
|
||
case "3" -> {
|
||
System.out.print("Enter new Description: ");
|
||
newDesc = scanner.nextLine().trim();
|
||
}
|
||
case "4" -> {
|
||
System.out.print("Enter new Image URL: ");
|
||
newImage = scanner.nextLine().trim();
|
||
}
|
||
case "0" -> {
|
||
System.out.println("Cancelled.");
|
||
return;
|
||
}
|
||
default -> {
|
||
System.out.println("Invalid choice.");
|
||
return;
|
||
}
|
||
}
|
||
|
||
JSONObject editReq = new JSONObject();
|
||
editReq.put("action", "edit_channel_info");
|
||
editReq.put("channel_id", channelInternalId.toString()); // internal_uuid
|
||
editReq.put("new_channel_id", newChannelId);
|
||
editReq.put("name", newName);
|
||
editReq.put("description", newDesc);
|
||
editReq.put("image_url", newImage);
|
||
|
||
JSONObject editRes = sendWithResponse(editReq);
|
||
if (editRes != null)
|
||
System.out.println(editRes.getString("message"));
|
||
}
|
||
|
||
|
||
private JSONObject getResponse() {
|
||
try {
|
||
return TelegramClient.responseQueue.take();
|
||
|
||
} catch (InterruptedException e) {
|
||
throw new RuntimeException("Failed to get server response");
|
||
}
|
||
}
|
||
|
||
|
||
public void logout() {
|
||
if (Session.currentUser != null && Session.currentUser.has("user_id")) {
|
||
JSONObject request = new JSONObject();
|
||
request.put("action", "logout");
|
||
request.put("user_id", Session.currentUser.getString("internal_uuid"));
|
||
|
||
send(request);
|
||
Session.currentUser = null;
|
||
Session.chatList = null;
|
||
} else {
|
||
System.out.println("Not logged in.");
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
public void addAdminToEntity(String type, UUID entityId) {
|
||
System.out.print("Enter user ID to promote to admin: ");
|
||
String targetUserId = scanner.nextLine().trim();
|
||
|
||
JSONObject permissions = new JSONObject();
|
||
System.out.print("Can send messages? (true/false): ");
|
||
permissions.put("can_send", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can edit info? (true/false): ");
|
||
permissions.put("can_edit", Boolean.parseBoolean(scanner.nextLine()));
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", type.equals("group") ? "add_admin_to_group" : "add_admin_to_channel");
|
||
req.put(type + "_id", entityId.toString());
|
||
req.put("target_user_id", targetUserId);
|
||
req.put("permissions", permissions);
|
||
|
||
send(req);
|
||
JSONObject res = getResponse();
|
||
System.out.println(res.getString("message"));
|
||
}
|
||
|
||
|
||
private void editChannelAdminPermissions(UUID channelId) {
|
||
System.out.print("Enter user_id of the admin to edit: ");
|
||
String userId = scanner.nextLine().trim();
|
||
|
||
JSONObject permissions = new JSONObject();
|
||
System.out.print("Can post? (true/false): ");
|
||
permissions.put("can_post", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can edit channel info? (true/false): ");
|
||
permissions.put("can_edit_channel", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can add members? (true/false): ");
|
||
permissions.put("can_add_members", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can remove members? (true/false): ");
|
||
permissions.put("can_remove_members", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can add admins? (true/false): ");
|
||
permissions.put("can_add_admins", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can remove admins? (true/false): ");
|
||
permissions.put("can_remove_admins", Boolean.parseBoolean(scanner.nextLine()));
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "edit_channel_admin_permissions");
|
||
req.put("channel_id", channelId.toString());
|
||
req.put("user_id", userId);
|
||
req.put("permissions", permissions);
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res != null)
|
||
System.out.println(res.getString("message"));
|
||
}
|
||
|
||
|
||
private void viewChannelAdmins(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "view_channel_admins");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null) return;
|
||
|
||
if (res.getString("status").equals("success")) {
|
||
JSONArray admins = res.getJSONObject("data").getJSONArray("admins");
|
||
|
||
System.out.println("\n--- Channel Admins ---");
|
||
for (int i = 0; i < admins.length(); i++) {
|
||
JSONObject a = admins.getJSONObject(i);
|
||
System.out.printf("- %s (%s) [%s]\n",
|
||
a.getString("profile_name"),
|
||
a.getString("user_id"),
|
||
a.getString("role"));
|
||
}
|
||
} else {
|
||
System.out.println("❌ Failed to fetch admins.");
|
||
}
|
||
}
|
||
|
||
|
||
private JSONObject getChannelPermissions(UUID channelId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_channel_permissions");
|
||
req.put("channel_id", channelId.toString());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res == null || !res.getString("status").equals("success")) {
|
||
return new JSONObject();
|
||
}
|
||
return res.getJSONObject("data");
|
||
}
|
||
|
||
|
||
public void editAdminPermissions(String type, UUID entityId) {
|
||
System.out.print("Enter user ID of the admin to edit: ");
|
||
String targetUserId = scanner.nextLine().trim();
|
||
|
||
JSONObject permissions = new JSONObject();
|
||
System.out.print("Can send messages? (true/false): ");
|
||
permissions.put("can_send", Boolean.parseBoolean(scanner.nextLine()));
|
||
System.out.print("Can edit info? (true/false): ");
|
||
permissions.put("can_edit", Boolean.parseBoolean(scanner.nextLine()));
|
||
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", type.equals("group") ? "edit_group_admin_permissions" : "edit_channel_admin_permissions");
|
||
req.put(type + "_id", entityId.toString());
|
||
req.put("target_user_id", targetUserId);
|
||
req.put("permissions", permissions);
|
||
|
||
send(req);
|
||
JSONObject res = getResponse();
|
||
System.out.println(res.getString("message"));
|
||
}
|
||
|
||
|
||
public void viewAdmins(String type, UUID entityId) {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", type.equals("group") ? "view_group_admins" : "view_channel_admins");
|
||
req.put(type + "_id", entityId.toString());
|
||
|
||
send(req);
|
||
JSONObject res = getResponse();
|
||
if (res.getString("status").equals("success")) {
|
||
JSONArray admins = res.getJSONObject("data").getJSONArray("admins");
|
||
System.out.println("📋 Admins in this " + type + ":");
|
||
for (int i = 0; i < admins.length(); i++) {
|
||
JSONObject admin = admins.getJSONObject(i);
|
||
System.out.printf("- %s (%s)\n", admin.getString("name"), admin.getString("role"));
|
||
}
|
||
} else {
|
||
System.out.println("❌ " + res.getString("message"));
|
||
}
|
||
}
|
||
|
||
|
||
public static JSONObject sendWithResponse(JSONObject request) {
|
||
try {
|
||
if (!request.has("action") || request.isNull("action")) {
|
||
System.err.println("❌ Invalid request: missing action.");
|
||
return null;
|
||
}
|
||
|
||
String requestId = UUID.randomUUID().toString();
|
||
request.put("request_id", requestId);
|
||
|
||
BlockingQueue<JSONObject> queue = new LinkedBlockingQueue<>();
|
||
TelegramClient.pendingResponses.put(requestId, queue);
|
||
|
||
TelegramClient.getInstance().getOut().println(request.toString());
|
||
|
||
// Wait for response
|
||
JSONObject response = queue.take();
|
||
|
||
TelegramClient.pendingResponses.remove(requestId);
|
||
|
||
if (response == null) {
|
||
System.out.println("⚠️ No response received.");
|
||
return null;
|
||
}
|
||
|
||
System.out.println("✅ Server Response: " + response.getString("message"));
|
||
return response;
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("❌ Error during sendWithResponse(): " + e.getMessage());
|
||
e.printStackTrace();
|
||
return null;
|
||
}
|
||
}
|
||
|
||
|
||
public static void requestChatList() {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_list");
|
||
req.put("user_id", Session.getUserUUID());
|
||
|
||
JSONObject res = sendWithResponse(req);
|
||
if (res.getString("status").equals("success")) {
|
||
JSONArray chats = res.getJSONObject("data").getJSONArray("chat_list");
|
||
Session.updateChatList(chats);
|
||
System.out.println("✅ Chat list updated.");
|
||
} else {
|
||
System.out.println("❌ Failed to update chat list.");
|
||
}
|
||
}
|
||
|
||
|
||
public static void requestChatInfo(String chatId, String chatType) throws IOException {
|
||
JSONObject req = new JSONObject();
|
||
req.put("action", "get_chat_info");
|
||
req.put("receiver_id", chatId);
|
||
req.put("receiver_type", chatType);
|
||
TelegramClient.send(req);
|
||
}
|
||
|
||
|
||
|
||
|
||
public static void displayChatList() {
|
||
if (Session.chatList == null || Session.chatList.isEmpty()) {
|
||
System.out.println("\n📭 No chats available.");
|
||
return;
|
||
}
|
||
|
||
System.out.println("\n💬 Your Chats:");
|
||
int index = 1;
|
||
for (ChatEntry chat : Session.chatList) {
|
||
System.out.printf("%d. [%s] %s (%s)\n", index++, chat.getType(), chat.getName(), chat.getDisplayId());
|
||
}
|
||
}
|
||
|
||
public static class ChatStateMonitor implements Runnable {
|
||
private final PrintWriter out;
|
||
|
||
public ChatStateMonitor(PrintWriter out) {
|
||
this.out = out;
|
||
}
|
||
|
||
@Override
|
||
public void run() {
|
||
while (true) {
|
||
try {
|
||
if (forceExitChat) {
|
||
System.out.println("🚪 You were removed from the chat. Returning to chat list...");
|
||
forceExitChat = false;
|
||
Session.backToChatList = true;
|
||
}
|
||
|
||
if (Session.forceRefreshChatList) {
|
||
Session.forceRefreshChatList = false;
|
||
System.out.println("🔁 Refresh triggered by real-time event.");
|
||
ActionHandler.requestChatList();
|
||
if (Session.inChatListMenu) {
|
||
System.out.println("\n📬 Updated Chat List:");
|
||
ActionHandler.displayChatList(); // این متدی باشه که چتها رو نمایش بده
|
||
System.out.print("Select a chat by number: ");
|
||
}
|
||
}
|
||
|
||
Thread.sleep(300); // جلوگیری از مصرف بیمورد CPU
|
||
} catch (Exception e) {
|
||
System.out.println("❌ ChatStateMonitor crashed: " + e.getMessage());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
public static class CurrentChatMenuRefresher implements Runnable {
|
||
private final ActionHandler handler;
|
||
|
||
public CurrentChatMenuRefresher(ActionHandler handler) {
|
||
this.handler = handler;
|
||
}
|
||
|
||
@Override
|
||
public void run() {
|
||
System.out.println("🔁 Menu refresher thread running...");
|
||
|
||
while (true) {
|
||
try {
|
||
if (Session.refreshCurrentChatMenu && Session.inChatMenu && Session.currentChatId != null) {
|
||
System.out.println("🔁 [Refresher] Refresh requested. Searching for chat...");
|
||
|
||
// جستجو در لیست چتها با استفاده از currentChatId
|
||
ChatEntry chat = Session.chatList.stream()
|
||
.filter(e -> e.getId().toString().equals(Session.currentChatId))
|
||
.findFirst()
|
||
.orElse(null);
|
||
|
||
if (chat != null) {
|
||
Session.currentChatEntry = chat;
|
||
Session.refreshCurrentChatMenu = false;
|
||
|
||
String type = chat.getType().toLowerCase();
|
||
System.out.println("\n🔁 Your permissions have changed. Menu updated:");
|
||
|
||
if (type.equals("group")) {
|
||
handler.printGroupMenuOnly(chat);
|
||
} else if (type.equals("channel")) {
|
||
handler.printChannelMenuOnly(chat);
|
||
}
|
||
|
||
System.out.print("Select an option: ");
|
||
} else {
|
||
System.out.println("⚠️ No matching chat found for ID: " + Session.currentChatId);
|
||
}
|
||
}
|
||
|
||
Thread.sleep(200);
|
||
} catch (Exception e) {
|
||
System.out.println("❌ CurrentChatMenuRefresher crashed: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
public void printGroupMenuOnly(ChatEntry chat) {
|
||
boolean isAdmin = chat.isAdmin();
|
||
boolean isOwner = chat.isOwner();
|
||
JSONObject perms = getGroupPermissions(chat.getId());
|
||
|
||
System.out.println("\n--- Group Chat Menu (Auto-refreshed) ---");
|
||
System.out.println("1. Send Message");
|
||
System.out.println("2. View Members");
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_members", false))) {
|
||
System.out.println("3. Add Member");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_edit_group", false))) {
|
||
System.out.println("4. Edit Group Info");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_admins", false))) {
|
||
System.out.println("5. Add Admin");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_admins", false))) {
|
||
System.out.println("6. Remove Admin");
|
||
}
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_members", false))) {
|
||
System.out.println("7. Remove member");
|
||
}
|
||
if (isOwner) {
|
||
System.out.println("8. Delete Group");
|
||
System.out.println("9. Leave Group (Transfer ownership required)");
|
||
} else {
|
||
System.out.println("9. Leave Group");
|
||
}
|
||
|
||
System.out.println("0. Back to Chat List");
|
||
}
|
||
|
||
|
||
public void printChannelMenuOnly(ChatEntry chat) {
|
||
boolean isAdmin = chat.isAdmin();
|
||
boolean isOwner = chat.isOwner();
|
||
JSONObject perms = getChannelPermissions(chat.getId());
|
||
|
||
System.out.println("\n--- Channel Menu (Auto-refreshed) ---");
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_post", false))) {
|
||
System.out.println("1. Send Post");
|
||
}
|
||
|
||
if (isOwner || isAdmin) {
|
||
System.out.println("2. View Subscribers");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_members", false))) {
|
||
System.out.println("3. Add Subscriber");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_members", false))) {
|
||
System.out.println("4. Remove Subscriber");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_edit_channel", false))) {
|
||
System.out.println("5. Edit Channel Info");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_add_admins", false))) {
|
||
System.out.println("6. Add Admin");
|
||
}
|
||
|
||
if (isOwner || (isAdmin && perms.optBoolean("can_remove_admins", false))) {
|
||
System.out.println("7. Remove Admin");
|
||
}
|
||
|
||
if (isOwner) {
|
||
System.out.println("8. Delete Channel");
|
||
System.out.println("9. Leave Channel (Transfer ownership required)");
|
||
} else {
|
||
System.out.println("8. Leave Channel");
|
||
}
|
||
|
||
System.out.println("0. Back to Chat List");
|
||
}
|
||
|
||
|
||
|
||
public static void requestPermissions(String chatId, String chatType) {
|
||
JSONObject permissionReq = new JSONObject();
|
||
permissionReq.put("action", "get_permissions");
|
||
permissionReq.put("receiver_id", chatId);
|
||
permissionReq.put("receiver_type", chatType);
|
||
TelegramClient.send(permissionReq);
|
||
}
|
||
|
||
public void refreshCurrentChat() {
|
||
switch (Session.currentChatType.toLowerCase()) {
|
||
case "group" -> showGroupChatMenu(Session.currentChatEntry);
|
||
case "channel" -> showChannelChatMenu(Session.currentChatEntry);
|
||
}
|
||
}
|
||
|
||
|
||
private void startMenuRefresherThread() {
|
||
Thread refresher = new Thread(() -> {
|
||
System.out.println("🟡 Refresher tick. refreshCurrentChatMenu = " + Session.refreshCurrentChatMenu);
|
||
|
||
while (true) {
|
||
try {
|
||
Thread.sleep(500);
|
||
if (Session.refreshCurrentChatMenu) {
|
||
Session.refreshCurrentChatMenu = false;
|
||
if (Session.currentChatEntry == null) {
|
||
System.out.println("⚠️ currentChatEntry is null. Skipping...");
|
||
continue; // ❗ اینجا بجای return باید continue باشه
|
||
}
|
||
|
||
|
||
switch (Session.currentChatEntry.getType()) {
|
||
case "group" -> showGroupChatMenu(Session.currentChatEntry);
|
||
case "channel" -> showChannelChatMenu(Session.currentChatEntry);
|
||
}
|
||
}
|
||
} catch (Exception ignored) {}
|
||
}
|
||
});
|
||
refresher.setDaemon(true);
|
||
refresher.start();
|
||
}
|
||
|
||
|
||
|
||
}
|
||
|
||
|