diff --git a/Client/src/main/java/ru/project/ChatClientGUI.java b/Client/src/main/java/ru/project/ChatClientGUI.java new file mode 100644 index 0000000..2f31496 --- /dev/null +++ b/Client/src/main/java/ru/project/ChatClientGUI.java @@ -0,0 +1,27 @@ +package ru.project; +import javafx.application.Application; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.TextField; +import javafx.scene.layout.VBox; +import javafx.stage.Stage; + +public class ChatClientGUI extends Application { + + @Override + public void start(Stage primaryStage) { + TextField inputField = new TextField(); + inputField.setPromptText("Введите сообщение..."); + Button sendButton = new Button("Отправить"); + VBox root = new VBox(10, inputField, sendButton); + Scene scene = new Scene(root, 400, 300); + + primaryStage.setTitle("Чат-клиент"); + primaryStage.setScene(scene); + primaryStage.show(); + } + + public static void main(String[] args) { + launch(args); + } +} diff --git a/Client/src/main/java/ru/project/Client.java b/Client/src/main/java/ru/project/Client.java index 79839de..5d7f515 100644 --- a/Client/src/main/java/ru/project/Client.java +++ b/Client/src/main/java/ru/project/Client.java @@ -12,6 +12,7 @@ public class Client { private DataOutputStream out; private DataInputStream in; private Scanner scanner; + private boolean isBanned = false; public Client() throws IOException { scanner = new Scanner(System.in); @@ -36,7 +37,12 @@ public Client() throws IOException { + message.split(" ")[1]); } if (message.equalsIgnoreCase("/banok")) { - + isBanned = true; + System.out.println("Вы были заблокированы администратором."); + } + if (message.equalsIgnoreCase("/unbanok")) { + isBanned = false; + System.out.println("Теперь вы не заблокированы. Вам доступна отправка сообщений в чат."); } } else { System.out.println(message); @@ -52,7 +58,9 @@ public Client() throws IOException { while (!socket.isClosed()) { String message = scanner.nextLine(); try { - out.writeUTF(message); + if (!isBanned) { + out.writeUTF(message); + } else System.out.println("Вы не можете писать сообщения."); } catch (SocketException e) { System.out.println("Вы были отключены от сервера."); } diff --git a/Server/src/main/java/ru/project/ClientHandler.java b/Server/src/main/java/ru/project/ClientHandler.java index 3ee2899..cdcb595 100644 --- a/Server/src/main/java/ru/project/ClientHandler.java +++ b/Server/src/main/java/ru/project/ClientHandler.java @@ -2,37 +2,38 @@ import java.io.DataInputStream; import java.io.DataOutputStream; -import java.io.EOFException; import java.io.IOException; import java.net.Socket; -import java.net.SocketException; import java.text.SimpleDateFormat; import java.util.Date; public class ClientHandler { - private Socket socket; - private Server server; - private DataInputStream in; - private DataOutputStream out; + private final Socket socket; + private final Server server; + private final DataInputStream in; + private final DataOutputStream out; private String username; private Role role; + private long lastActiveTime; public ClientHandler(Socket socket, Server server) throws IOException { this.socket = socket; this.server = server; this.in = new DataInputStream(socket.getInputStream()); this.out = new DataOutputStream(socket.getOutputStream()); + this.lastActiveTime = System.currentTimeMillis(); new Thread(() -> { try { System.out.println("Клиент подключился " + socket.getPort()); //Цикл логина while (true) { - sendMsg("Для начала работы надо пройти аутентификацию или регистрацию\n" + - "Формат команды для аутентификации: /log\n" + - "Формат команды для регистрации: /reg\n" + - "Для выхода используйте комманду /exit"); + sendMsg(""" + Для начала работы надо пройти аутентификацию или регистрацию + Формат команды для аутентификации: /log + Формат команды для регистрации: /reg + Для выхода используйте комманду /exit"""); String message = in.readUTF(); if (message.startsWith("/")) { if (message.equals("/exit")) { @@ -55,13 +56,15 @@ public ClientHandler(Socket socket, Server server) throws IOException { } if (message.equalsIgnoreCase("/reg")) { String[] regData = new String[3]; - sendMsg("Введите никнейм.\n" + - "Никнейм не должен содержать более 20 символов, и не менее 5 символов\n" + - "Можно использовать цифры, латинские буквы и знаки \"_\" и \"-\""); + sendMsg(""" + Введите никнейм. + Никнейм не должен содержать более 20 символов, и не менее 5 символов + Можно использовать цифры, латинские буквы и знаки "_" и "-\""""); regData[0] = in.readUTF(); - sendMsg("Введите логин.\n" + - "Логин не должен содержать более 20 символов, и не менее 5 символов\n" + - "Можно использовать цифры, латинские буквы и знаки \"_\" и \"-\""); + sendMsg(""" + Введите логин. + Логин не должен содержать более 20 символов, и не менее 5 символов + Можно использовать цифры, латинские буквы и знаки "_" и "-\""""); regData[1] = in.readUTF(); sendMsg("Введите пароль.\n" + "Пароль должен содержать от 5 до 20 символов и обязательно включать в себя любой специальный символ."); @@ -81,6 +84,7 @@ public ClientHandler(Socket socket, Server server) throws IOException { //Цикл работы while (true) { String message = in.readUTF(); + boolean targetUserIsBanned = false; if (message.startsWith("/")) { if (message.equalsIgnoreCase("/exit")) { sendMsg("/exitok"); @@ -101,17 +105,28 @@ public ClientHandler(Socket socket, Server server) throws IOException { continue; } server.kickUser(tokens[1], this); + } else if (message.startsWith("/ban ")) { + String[] tokens = message.split(" ", 2); + if (tokens.length != 2) { + sendMsg("Неверный формат команды /ban"); + continue; + } + server.banUser(tokens[1], this); + targetUserIsBanned = true; + } else if (message.startsWith("/unban ")) { + String[] tokens = message.split(" ", 2); + if (tokens.length != 2) { + sendMsg("Неверный формат комманды /unban"); + continue; + } + if (targetUserIsBanned) { + server.unbanUser(tokens[1], this); + targetUserIsBanned = false; + } else sendMsg("Пользователь " + tokens[1] + " не находится в бане"); + } else if (message.equalsIgnoreCase("/online")) { + sendMsg(server.getOnlineUsers()); } - } else if (message.startsWith("/ban ")) { - String[] tokens = message.split(" ", 2); - if (tokens.length != 2) { - sendMsg("Неверный формат команды /ban"); - continue; } - server.banUser(tokens[1], this); - } - - else { String messageWithTime = "[" + getCurrentTime() + "]" + username + " : " + message; server.broadcastMessage(messageWithTime); @@ -174,4 +189,8 @@ public Role getRole() { private String getCurrentTime() { return new SimpleDateFormat("HH:mm:ss").format(new Date()); } + + public long getLastActiveTime() { + return lastActiveTime; + } } diff --git a/Server/src/main/java/ru/project/Server.java b/Server/src/main/java/ru/project/Server.java index 2d21912..40a4f29 100644 --- a/Server/src/main/java/ru/project/Server.java +++ b/Server/src/main/java/ru/project/Server.java @@ -1,5 +1,6 @@ package ru.project; +import ru.project.checktime.CheckTime; import ru.project.database.DatabaseManager; import javax.xml.crypto.Data; @@ -21,6 +22,8 @@ public Server(int port, DatabaseManager databaseManager) { this.databaseManager = databaseManager; clients = new CopyOnWriteArrayList<>(); authenticator = new inMemoryAuthenticator(this); + + new CheckTime(this).start(); } public void start(){ @@ -88,7 +91,7 @@ public void kickUser(String usernameToKick, ClientHandler adminHandler) { } public void banUser(String usernameToBan, ClientHandler adminHandler) { if (adminHandler.getRole().equals(Role.ADMIN)) { - for (ClientHandler client : client) { + for (ClientHandler client : clients) { if (client.getUsername().equals(usernameToBan)) { client.sendMsg("/banok"); broadcastMessage("Пользователь " + usernameToBan + " был забанен администратором"); @@ -100,8 +103,32 @@ public void banUser(String usernameToBan, ClientHandler adminHandler) { adminHandler.sendMsg("Недостаточно прав"); } } - + public void unbanUser(String usernameToUnban, ClientHandler adminHandler) { + if (adminHandler.getRole().equals(Role.ADMIN)) { + for (ClientHandler client : clients) { + if (client.getUsername().equals(usernameToUnban)) { + client.sendMsg("/unbanok"); + broadcastMessage("Пользователь " + usernameToUnban + " был разбанен администратором"); + return; + } + } + adminHandler.sendMsg("Ошибка. Пользователь с ником " + usernameToUnban + " не найден"); + } else { + adminHandler.sendMsg("Недостаточно прав"); + } + } public DatabaseManager getDatabaseManager() { return databaseManager; } + + public String getOnlineUsers() { + StringBuilder sb = new StringBuilder("Сейчас онлайн:\n"); + for (ClientHandler client : clients) { + sb.append(client.getUsername()).append("\n"); + } + return sb.toString(); + } + public List getClients() { + return this.clients; + } } diff --git a/Server/src/main/java/ru/project/checktime/CheckTime.java b/Server/src/main/java/ru/project/checktime/CheckTime.java new file mode 100644 index 0000000..3af8b5c --- /dev/null +++ b/Server/src/main/java/ru/project/checktime/CheckTime.java @@ -0,0 +1,35 @@ +package ru.project.checktime; + +import ru.project.*; + +import java.util.ArrayList; + +public class CheckTime extends Thread { + private static final long TIMEOUT = 20 * 60 * 1000; + private Server server; + private ClientHandler clientHandler; + + public CheckTime(Server server) { + this.server = server; + } + @Override + public void run() { + while (true) { + try { + Thread.sleep(60*1000); + long currentTime = System.currentTimeMillis(); + + for (ClientHandler client : server.getClients()) { + if (currentTime - client.getLastActiveTime() > TIMEOUT) { + System.out.println("Отключение неактивного клиента: " + client.getUsername()); + client.sendMsg("/exitok"); + server.unsubscribe(client); + client.disconnect(); + } + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/Server/src/main/java/ru/project/database/DatabaseManager.java b/Server/src/main/java/ru/project/database/DatabaseManager.java index 77c1138..a9bb845 100644 --- a/Server/src/main/java/ru/project/database/DatabaseManager.java +++ b/Server/src/main/java/ru/project/database/DatabaseManager.java @@ -4,7 +4,7 @@ import java.sql.*; public class DatabaseManager { - private static final String DB_URL = "jdbc:postgresql://localhost:5432/postgres?currentSchema=public&user=postgres&password=admin"; + private static final String DB_URL = "jdbc:postgresql://localhost:5432/postgres?currentSchema=public&user=postgres&password=postgres"; public DatabaseManager() {