Skip to content
27 changes: 27 additions & 0 deletions Client/src/main/java/ru/project/ChatClientGUI.java
Original file line number Diff line number Diff line change
@@ -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);
}
}
12 changes: 10 additions & 2 deletions Client/src/main/java/ru/project/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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("Вы были отключены от сервера.");
}
Expand Down
69 changes: 44 additions & 25 deletions Server/src/main/java/ru/project/ClientHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -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")) {
Expand All @@ -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 символов и обязательно включать в себя любой специальный символ.");
Expand All @@ -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");
Expand All @@ -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);
Expand Down Expand Up @@ -174,4 +189,8 @@ public Role getRole() {
private String getCurrentTime() {
return new SimpleDateFormat("HH:mm:ss").format(new Date());
}

public long getLastActiveTime() {
return lastActiveTime;
}
}
31 changes: 29 additions & 2 deletions Server/src/main/java/ru/project/Server.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ru.project;

import ru.project.checktime.CheckTime;
import ru.project.database.DatabaseManager;

import javax.xml.crypto.Data;
Expand All @@ -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(){
Expand Down Expand Up @@ -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 + " был забанен администратором");
Expand All @@ -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<ClientHandler> getClients() {
return this.clients;
}
}
35 changes: 35 additions & 0 deletions Server/src/main/java/ru/project/checktime/CheckTime.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down