Files
Telegram-Final-Project/src/main/java/org/to/telegramfinalproject/Client/SidebarHandler.java
T
2025-08-12 16:28:59 +03:30

580 lines
21 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package org.to.telegramfinalproject.Client;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.to.telegramfinalproject.Models.ChatEntry;
import org.to.telegramfinalproject.Models.FileAttachment;
import org.to.telegramfinalproject.Models.Message;
import java.time.LocalDateTime;
import java.util.*;
import static org.to.telegramfinalproject.Client.ActionHandler.sendWithResponse;
public class SidebarHandler {
private final Scanner scanner;
private ActionHandler actionHandler ;
private final String userUUID;
public SidebarHandler(Scanner scanner, ActionHandler actionHandler, ActionHandler action) {
this.scanner = scanner;
this.actionHandler = action;
this.userUUID = Session.getUserUUID();
}
public SidebarHandler(Scanner scanner, ActionHandler actionHandler) {
this.scanner = scanner;
this.actionHandler = actionHandler;
this.userUUID = Session.getUserUUID();
}
public void handleSidebarAction(SidebarAction action) {
switch (action) {
case MY_PROFILE:
openUserProfile();
break;
case NEW_GROUP:
createNewGroup();
break;
case NEW_CHANNEL:
createNewChannel();
break;
case CONTACTS:
showContacts();
break;
case SAVED_MESSAGES:
ensureSavedMessagesCreated();
break;
case SETTINGS:
openSettings();
break;
case FEATURES:
showTelegramFeatures();
break;
case Q_AND_A:
showTelegramQA();
break;
}
}
private void openUserProfile() {
// Step 1: Request profile info from the server
JSONObject request = new JSONObject();
request.put("action", "get_user_profile");
JSONObject response = sendWithResponse(request);
if (response == null || !response.optString("status", "fail").equals("success")) {
System.out.println("Failed to load profile information.");
return;
}
JSONObject profile;
try {
profile = response.getJSONObject("data");
} catch (JSONException e) {
System.out.println("Received malformed profile data from server.");
return;
}
String profileName = profile.optString("profile_name", "NOT-AVAILABLE");
String userId = profile.optString("user_id", "NOT-AVAILABLE");
String status = profile.optString("status", "NOT-AVAILABLE");
String bio = profile.optString("bio", "NOT-AVAILABLE");
String profilePictureUrl = profile.optString("profile_picture_url", "NOT-AVAILABLE");
// Step 2: Show profile info
System.out.println("===== My Profile =====");
System.out.println("Profile Picture URL : " + profilePictureUrl);
System.out.println("Profile Name : " + profileName);
System.out.println("User ID : @" + userId);
System.out.println("Status : " + status);
System.out.println("Bio : " + bio);
System.out.println("======================");
// Step 3: Ask if user wants to edit anything
System.out.println("Do you want to edit any of these? (yes/no)");
while (true) {
String choice = scanner.nextLine().trim().toLowerCase();
if (choice.equals("no")) return;
if (!choice.equals("yes")) {
System.out.println("Invalid input. Please enter 'yes' or 'no'.");
continue;
}
// Step 4: Show editable fields
System.out.println("Which field do you want to edit?");
System.out.println("1. Profile Name");
System.out.println("2. User ID");
System.out.println("3. Bio");
System.out.println("4. Profile Picture URL");
System.out.println("0. Cancel");
String option = scanner.nextLine().trim();
switch (option) {
case "1" -> editProfileName();
case "2" -> editUserId();
case "3" -> editBio();
case "4" -> editProfilePictureUrl();
case "0" -> { return; }
default -> System.out.println("Invalid choice. Try again.");
}
// Re-fetch and re-display profile after editing
openUserProfile();
return;
}
}
private void editProfileName() {
System.out.println("Enter your new profile name:");
String newProfileName = scanner.nextLine().trim();
// Step 1: Validate input
while (newProfileName.trim().isEmpty()) {
System.out.println("Profile name cannot be empty. Enter another name.");
newProfileName = scanner.nextLine().trim();
}
// Step 2: Create request
JSONObject request = new JSONObject();
request.put("action", "edit_profile_name");
request.put("new_profile_name", newProfileName);
// Step 3: Send request and receive response
JSONObject response = sendWithResponse(request);
// Step 4: Handle response
if (response == null || !response.optString("status", "fail").equals("success")) {
System.out.println("Failed to update profile name.");
} else {
System.out.println("Profile name updated successfully!");
}
}
private void editUserId() {
while (true) {
System.out.println("Enter your new user ID: ");
String newUserId = scanner.nextLine().trim();
if (newUserId.isEmpty()) {
System.out.println("User ID cannot be empty.");
continue;
}
if (newUserId.contains(" ")) {
System.out.println("User ID cannot contain spaces.");
continue;
}
if (!newUserId.matches("^[a-zA-Z0-9_]+$")) {
System.out.println("User ID can only contain letters, digits, and underscores.");
continue;
}
// Send to server
JSONObject request = new JSONObject();
request.put("action", "edit_user_id");
request.put("new_user_id", newUserId);
JSONObject response = sendWithResponse(request);
if (response.getString("status").equals("success")) {
System.out.println("User ID updated successfully.");
break;
} else {
// Server-side error message (e.g., ID already exists)
System.out.println(response.getString("message"));
}
}
}
private void editBio() {
System.out.println("Enter your new bio:");
String newBio = scanner.nextLine().trim();
// Limit the bio length
if (newBio.length() > 70) {
System.out.println("Bio cannot be more than 70 characters.");
return;
}
JSONObject request = new JSONObject();
request.put("action", "edit_bio");
request.put("new_bio", newBio);
JSONObject response = sendWithResponse(request);
if (response.getString("status").equals("success")) {
System.out.println("Bio updated successfully.");
} else {
System.out.println(response.getString("message"));
}
}
private void editProfilePictureUrl() {
while (true) {
System.out.println("Enter new profile picture URL (or leave empty to remove):");
String newImageUrl = scanner.nextLine().trim();
// URL validation
if (newImageUrl.contains(" ")) {
System.out.println("URL cannot contain spaces.");
continue;
}
if (!newImageUrl.isEmpty() && !newImageUrl.matches("^(http|https)://.*$")) {
System.out.println("Invalid URL format. Please enter a valid HTTP/HTTPS link.");
continue;
}
JSONObject request = new JSONObject();
request.put("action", "edit_profile_picture");
request.put("new_image_url", newImageUrl);
JSONObject response = sendWithResponse(request);
if (response.getString("status").equals("success")) {
System.out.println("Bio updated successfully.");
} else {
System.out.println(response.getString("message"));
}
break;
}
}
private void createNewGroup() {
actionHandler.createGroup();
}
private void createNewChannel() {
actionHandler.createChannel();
}
private void showContacts() {
actionHandler.showContactList();
}
public void ensureSavedMessagesCreated() {
// 1) Client-side quick check
boolean alreadyExists = false;
if (Session.activeChats != null) {
for (ChatEntry e : Session.activeChats) {
if (e != null && e.isSavedMessages()) { alreadyExists = true; break; }
}
}
if (alreadyExists) {
System.out.println("️ Saved Messages already exists.");
return;
}
// 2) Ask server to get or create the self-chat
JSONObject res = sendWithResponse(new JSONObject().put("action", "get_or_create_saved_messages"));
if (res == null || !"success".equals(res.optString("status"))) {
System.out.println("❌ Failed to create/open Saved Messages: " + (res != null ? res.optString("message","") : ""));
return;
}
JSONObject data = res.optJSONObject("data");
if (data == null) {
System.out.println("❌ Invalid server response for Saved Messages.");
return;
}
boolean created = data.optBoolean("created", true); // if server sends it
String chatId = data.optString("chat_id", null);
if (created) {
System.out.println("✅ Saved Messages created." + (chatId != null ? " chat_id=" + chatId : ""));
try {
UUID cid = UUID.fromString(chatId);
ChatEntry saved = new ChatEntry(cid, "Saved Messages", "Saved Messages", "", "private", null, true, false);
saved.setSavedMessages(true);
if (Session.activeChats == null) Session.activeChats = new ArrayList<>();
Session.activeChats.add(0, saved);
} catch (Exception ignore) {}
} else {
System.out.println("️ Saved Messages already exists." + (chatId != null ? " chat_id=" + chatId : ""));
}
}
private void openSettings() {
while (true) {
System.out.println("⚙️ Settings\n");
String imageUrl = Session.currentUser.optString("image_url", "—");
String profileName = Session.currentUser.optString("profile_name", "—");
String userId = Session.currentUser.optString("user_id", "—");
renderUserCard(imageUrl, profileName, userId);
System.out.println();
renderMenu();
System.out.print("\nChoose an option (0-4): ");
String pick = scanner.nextLine().trim();
switch (pick) {
case "1": openUserProfile(); break;
case "2": showPrivacySettings(); break;
case "3": showTelegramQA(); break;
case "4": showTelegramFeatures(); break;
case "0": return;
default:
System.out.println("❌ Invalid choice. Press Enter to continue...");
scanner.nextLine();
}
}
}
private void showPrivacySettings() {
while (true) {
System.out.println("🔒 Privacy\n");
System.out.println("1) Blocked users");
System.out.println("2) Change username / password");
System.out.println("0) Back");
System.out.print("\nChoose: ");
String pick = scanner.nextLine().trim();
switch (pick) {
case "1": viewBlockedUsers(); break;
case "2": changeCredentialsFlow(); break;
case "0": return;
default:
System.out.println("❌ Invalid choice. Press Enter...");
scanner.nextLine();
}
}
}
private void viewBlockedUsers() {
System.out.println("🚫 Blocked Users\n");
org.json.JSONObject req = new org.json.JSONObject();
req.put("action", "get_blocked_users");
org.json.JSONObject res = sendWithResponse(req);
if (res == null || !res.optString("status","error").equals("success")) {
System.out.println("❌ Failed to fetch blocked users. Press Enter...");
scanner.nextLine();
return;
}
org.json.JSONArray arr = res.getJSONObject("data").optJSONArray("blocked_users");
if (arr == null || arr.isEmpty()) {
System.out.println("📭 No blocked users.");
System.out.println("\nPress Enter...");
scanner.nextLine();
return;
}
for (int i = 0; i < arr.length(); i++) {
org.json.JSONObject u = arr.getJSONObject(i);
String profileName = u.optString("profile_name", "—");
String userId = u.optString("user_id", "—");
System.out.printf("%d) %s (@%s)\n", i + 1, profileName, userId);
}
System.out.println("\n0) Back");
System.out.print("\nChoose a user to UNBLOCK (number): ");
String pick = scanner.nextLine().trim();
if (pick.equals("0")) return;
int idx;
try { idx = Integer.parseInt(pick) - 1; } catch (Exception e) { idx = -1; }
if (idx < 0 || idx >= arr.length()) {
System.out.println("❌ Invalid index. Press Enter...");
scanner.nextLine();
return;
}
org.json.JSONObject target = arr.getJSONObject(idx);
String targetDisplayId = target.optString("user_id", "");
java.util.UUID targetInternalId = java.util.UUID.fromString(target.getString("internal_uuid"));
System.out.printf("Unblock %s (@%s)? (yes/no): ", target.optString("profile_name","—"), targetDisplayId);
if (!scanner.nextLine().trim().equalsIgnoreCase("yes")) return;
org.json.JSONObject unReq = new org.json.JSONObject();
unReq.put("action", "toggle_block");
unReq.put("user_id",Session.getUserUUID());
unReq.put("target_id", targetInternalId.toString());
org.json.JSONObject unRes = sendWithResponse(unReq);
if (unRes != null && unRes.optString("status","error").equals("success")) {
System.out.println("✅ User unblocked.");
} else {
System.out.println("❌ Failed to unblock.");
}
System.out.println("Press Enter...");
scanner.nextLine();
}
private void changeCredentialsFlow() {
System.out.println("🛡️ Change Username / Password\n");
System.out.print("Enter current password: ");
String currentPassword = scanner.nextLine();
org.json.JSONObject verReq = new org.json.JSONObject();
verReq.put("action", "verify_password");
verReq.put("current_password", currentPassword);
org.json.JSONObject verRes = sendWithResponse(verReq);
if (verRes == null || !verRes.optString("status","error").equals("success")) {
System.out.println("❌ Current password is incorrect.");
System.out.println("Press Enter...");
scanner.nextLine();
return;
}
String currentUsername = Session.currentUser.optString("username", "—");
System.out.println("\n✅ Verified.");
System.out.println("Current username: " + currentUsername);
System.out.println("Current password: ******** (hidden)");
System.out.println("\nWhat do you want to change?");
System.out.println("1) Username");
System.out.println("2) Password");
System.out.println("3) Both");
System.out.println("0) Back");
System.out.print("\nChoose: ");
String pick = scanner.nextLine().trim();
switch (pick) {
case "1":
changeUsername(currentPassword);
break;
case "2":
changePassword(currentPassword);
break;
case "3":
boolean uOk = changeUsername(currentPassword);
boolean pOk = changePassword(currentPassword);
if (uOk && pOk) System.out.println("✅ Username and password updated.");
System.out.println("Press Enter...");
scanner.nextLine();
break;
case "0":
return;
default:
System.out.println("❌ Invalid choice. Press Enter...");
scanner.nextLine();
}
}
private boolean changeUsername(String currentPassword) {
System.out.print("\nNew username: ");
String newUsername = scanner.nextLine().trim();
if (!isValidUsername(newUsername)) {
System.out.println("❌ Invalid username. Use 432 chars: letters, digits, underscore.");
return false;
}
org.json.JSONObject req = new org.json.JSONObject();
req.put("action", "update_username");
req.put("current_password", currentPassword);
req.put("new_username", newUsername);
org.json.JSONObject res = sendWithResponse(req);
if (res != null && res.optString("status","error").equals("success")) {
Session.currentUser.put("username", newUsername);
System.out.println("✅ Username updated.");
return true;
} else {
String msg = (res == null) ? "No response." : res.optString("message","Update failed.");
System.out.println("❌ " + msg);
return false;
}
}
private boolean isValidUsername(String s) {
//4-32 char
return s != null && s.matches("^[A-Za-z0-9_]{4,32}$");
}
private boolean changePassword(String currentPassword) {
System.out.print("\nNew password: ");
String newPassword = scanner.nextLine();
System.out.print("Repeat new password: ");
String repeat = scanner.nextLine();
if (!newPassword.equals(repeat)) {
System.out.println("❌ Passwords do not match.");
return false;
}
if (!isStrongPassword(newPassword)) {
System.out.println("❌ Weak password. Min 8 chars, include letters and digits.");
return false;
}
org.json.JSONObject req = new org.json.JSONObject();
req.put("action", "update_password");
req.put("current_password", currentPassword);
req.put("new_password", newPassword);
org.json.JSONObject res = sendWithResponse(req);
if (res != null && res.optString("status","error").equals("success")) {
System.out.println("✅ Password updated.");
return true;
} else {
String msg = (res == null) ? "No response." : res.optString("message","Update failed.");
System.out.println("❌ " + msg);
return false;
}
}
private void renderUserCard(String imageUrl, String profileName, String userId) {
int w = 60;
String top = "┌" + "─".repeat(w - 2) + "┐";
String bot = "└" + "─".repeat(w - 2) + "┘";
System.out.println(top);
System.out.println(padBoxLine("Profile", w));
System.out.println("├" + "─".repeat(w - 2) + "┤");
System.out.println(padBoxLine("Image URL: " + imageUrl, w));
System.out.println(padBoxLine("Profile Name: "+ profileName, w));
System.out.println(padBoxLine("User ID: " + userId, w));
System.out.println(bot);
}
private String padBoxLine(String text, int width) {
final int inner = width - 2;
if (text.length() > inner) {
text = text.substring(0, inner - 1) + "…";
}
int spaces = inner - text.length();
return "│" + text + " ".repeat(Math.max(0, spaces)) + "│";
}
private void renderMenu() {
System.out.println("1) My Account");
System.out.println("2) Privacy");
System.out.println("3) Telegram Q&A");
System.out.println("4) Telegram Features");
System.out.println("0) Back");
}
private void showTelegramFeatures() {
System.out.println("🌟 Showing Telegram features...");
}
private void showTelegramQA() {
System.out.println("❓ Showing Q&A...");
}
private boolean isStrongPassword(String s) {
boolean approved = s.matches("\\b(?=[^\\s]*[A-Z])(?=[^\\s]*[a-z])(?=[^\\s]*\\d)(?=[^\\s]*[!@#$%^&*])[^\\s]{8,}\\b");
return approved ;
}
}