2020-10-31 01:20:17 +03:00
|
|
|
package InnaIrcBot.Commanders.flood;
|
2018-12-16 17:27:44 +03:00
|
|
|
|
2020-11-01 18:35:14 +03:00
|
|
|
import InnaIrcBot.Commanders.EventHandler;
|
2018-12-16 17:27:44 +03:00
|
|
|
import InnaIrcBot.ProvidersConsumers.StreamProvider;
|
|
|
|
|
|
|
|
import java.time.LocalDateTime;
|
2020-10-20 03:37:20 +03:00
|
|
|
import java.util.*;
|
|
|
|
|
2020-10-31 01:20:17 +03:00
|
|
|
public class JoinFloodHandler implements EventHandler {
|
2020-10-20 03:37:20 +03:00
|
|
|
private final int joinMaxNumber; // How many events should happens before we start validation
|
|
|
|
private final int timeFrameInSeconds; // For which period critical amount of events should happens
|
|
|
|
private final String server;
|
|
|
|
private final String channel;
|
|
|
|
protected final HashMap<String, LinkedList<LocalDateTime>> users;
|
|
|
|
|
2020-10-31 01:20:17 +03:00
|
|
|
public JoinFloodHandler(String server, String channel, int joinMaxNumber, int timeFrameInSeconds){
|
|
|
|
this.server = server;
|
|
|
|
this.channel = channel;
|
2020-10-20 03:37:20 +03:00
|
|
|
this.joinMaxNumber = joinMaxNumber;
|
2018-12-16 17:27:44 +03:00
|
|
|
this.timeFrameInSeconds = timeFrameInSeconds;
|
2020-10-20 03:37:20 +03:00
|
|
|
this.users = new HashMap<>();
|
2018-12-16 17:27:44 +03:00
|
|
|
}
|
2020-10-31 01:20:17 +03:00
|
|
|
@Override
|
|
|
|
public void track(String nick){
|
|
|
|
nick = simplifyNick(nick);
|
2018-12-16 17:27:44 +03:00
|
|
|
|
2020-10-31 01:20:17 +03:00
|
|
|
if (isNewcomer(nick)) {
|
|
|
|
registerNewUser(nick);
|
2020-10-20 03:37:20 +03:00
|
|
|
return;
|
2018-12-16 17:27:44 +03:00
|
|
|
}
|
2020-10-20 03:37:20 +03:00
|
|
|
|
2020-10-31 01:20:17 +03:00
|
|
|
if(isJoinFlooder(nick)){
|
|
|
|
kickBanUser(nick);
|
|
|
|
users.remove(nick);
|
2018-12-16 17:27:44 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-20 03:37:20 +03:00
|
|
|
private boolean isNewcomer(String user){
|
|
|
|
return ! users.containsKey(user);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void registerNewUser(String user){
|
|
|
|
users.put(user, new LinkedList<>());
|
|
|
|
users.get(user).addFirst(LocalDateTime.now());
|
|
|
|
}
|
2018-12-16 17:27:44 +03:00
|
|
|
|
2020-10-20 03:37:20 +03:00
|
|
|
private boolean isJoinFlooder(String user){
|
|
|
|
final LocalDateTime firstJoinTime = getFirstJoinTimeAndUpdate(user);
|
|
|
|
return firstJoinTime.isAfter(LocalDateTime.now().minusSeconds(timeFrameInSeconds));
|
2018-12-16 17:27:44 +03:00
|
|
|
}
|
|
|
|
|
2020-10-20 03:37:20 +03:00
|
|
|
private LocalDateTime getFirstJoinTimeAndUpdate(String user){
|
|
|
|
LinkedList<LocalDateTime> userJoinHistory = users.get(user);
|
|
|
|
LocalDateTime fistJoinTime;
|
|
|
|
|
|
|
|
userJoinHistory.addLast(LocalDateTime.now());
|
|
|
|
|
|
|
|
if (userJoinHistory.size() > joinMaxNumber){
|
|
|
|
fistJoinTime = userJoinHistory.getFirst();
|
|
|
|
userJoinHistory.removeFirst();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
fistJoinTime = LocalDateTime.MIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
return fistJoinTime;
|
|
|
|
}
|
|
|
|
private void kickBanUser(String user){
|
|
|
|
StreamProvider.writeToStream(server,
|
|
|
|
"PRIVMSG "+ channel +" :"+user+": join flood ("+ joinMaxNumber +" connections in "+timeFrameInSeconds+" seconds).\n"+
|
|
|
|
"MODE "+ channel +" +b "+user+"!*@*"); // TODO: consider other ban methods
|
2018-12-16 17:27:44 +03:00
|
|
|
}
|
2020-10-31 01:20:17 +03:00
|
|
|
|
|
|
|
private String simplifyNick(String nick){ return nick.replaceAll("!.*$",""); }
|
2018-12-16 17:27:44 +03:00
|
|
|
}
|