206 lines
10 KiB
Java
206 lines
10 KiB
Java
package InnaIrcBot.ProvidersConsumers;
|
|
|
|
import InnaIrcBot.Commanders.PrivateMsgCommander;
|
|
import InnaIrcBot.Config.StorageFile;
|
|
import InnaIrcBot.GlobalData;
|
|
import InnaIrcBot.LogDriver.BotDriver;
|
|
import InnaIrcBot.LogDriver.Worker;
|
|
|
|
import java.io.*;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.time.LocalTime;
|
|
import java.time.ZonedDateTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
import java.util.regex.Pattern;
|
|
|
|
public class SystemConsumer implements Runnable{
|
|
private BufferedReader reader;
|
|
private Worker writerWorker;
|
|
private String nick;
|
|
private String serverName;
|
|
private Map<String, PrintWriter> channelsMap;
|
|
private boolean proxyRequired;
|
|
private HashMap<String, ArrayList<String>> proxyAList;
|
|
private StorageFile storageFile;
|
|
|
|
private PrivateMsgCommander commander;
|
|
|
|
SystemConsumer(BufferedReader streamReader, String userNick, Map<String, PrintWriter> map, StorageFile storage) {
|
|
this.writerWorker = BotDriver.getWorker(storage.getServerName(), "system");
|
|
this.nick = userNick;
|
|
this.serverName = storage.getServerName();
|
|
this.channelsMap = map;
|
|
this.reader = streamReader;
|
|
|
|
this.proxyRequired = false;
|
|
this.proxyAList = new HashMap<>();
|
|
this.storageFile = storage;
|
|
|
|
this.commander = new PrivateMsgCommander(serverName, storageFile.getBotAdministratorPassword());
|
|
// Start pre-set channels
|
|
StringBuilder message = new StringBuilder();
|
|
for (String cnl : storageFile.getChannels()) { // TODO: add validation of channels.
|
|
message.append("JOIN ");
|
|
message.append(cnl);
|
|
message.append("\n");
|
|
}
|
|
StreamProvider.writeToStream(serverName,message.toString());
|
|
}
|
|
|
|
@Override
|
|
public void run() {
|
|
System.out.println("["+LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))+"] THREAD "+serverName+":[system] started"); // TODO:REMOVE DEBUG
|
|
|
|
setMainRoutine();
|
|
|
|
for (PrintWriter p :channelsMap.values()) //TODO: check, code duplication. see Data provider constructor
|
|
p.close();
|
|
|
|
writerWorker.close();
|
|
System.out.println("["+LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))+"] THREAD "+serverName+":[system] ended"); // TODO:REMOVE DEBUG
|
|
}
|
|
|
|
private void setMainRoutine(){
|
|
String data;
|
|
String dataStrings[];
|
|
try {
|
|
while ((data = reader.readLine()) != null) {
|
|
dataStrings = data.split(" ",3);
|
|
|
|
if (proxyRequired)
|
|
if (getProxy(dataStrings[0], dataStrings[1], dataStrings[2]))
|
|
continue;
|
|
|
|
if (dataStrings[0].equals("PRIVMSG") && dataStrings[2].indexOf("\u0001") < dataStrings[2].lastIndexOf("\u0001"))
|
|
replyCTCP(dataStrings[1], dataStrings[2].substring(dataStrings[2].indexOf(":")+1));
|
|
else if (Pattern.matches("(^[0-9]{3}$)|(^NICK$)|(^JOIN$)", dataStrings[0])){
|
|
handleNumeric(dataStrings[0], dataStrings[1], dataStrings[2]);
|
|
}
|
|
else if (dataStrings[0].equals("PRIVMSG")) {
|
|
commander.receiver(dataStrings[1], dataStrings[2].replaceAll("^.+?:", "").trim());
|
|
writerWorker.logAdd("[system]", "PRIVMSG sent to", "commander");
|
|
}
|
|
else
|
|
writerWorker.logAdd(dataStrings[0], dataStrings[1], dataStrings[2]); // TODO: Track users
|
|
//System.out.println("System: "+"|"+dataStrings[0]+"|"+dataStrings[1]+"|"+dataStrings[2]+"|");
|
|
}
|
|
} catch (java.io.IOException e){
|
|
System.out.println("Internal issue: thread SystemConsumer->run() caused I/O exception."); // TODO: reconnect
|
|
}
|
|
}
|
|
private boolean getProxy(String eventNum, String sender, String message){ //TODO: if can't join: like channel with password
|
|
if (eventNum.equals("353"))
|
|
return false; // never mind and let it flows as usual.
|
|
else {
|
|
String chan = message.replaceAll("(\\s.?$)|(\\s.+?$)", "");
|
|
|
|
if (eventNum.equals("QUIT") || eventNum.equals("NICK")) {
|
|
for (ArrayList<String> key : proxyAList.values())
|
|
key.add(eventNum + " " + sender + " " + message);
|
|
return false;
|
|
} else if (chan.equals(nick))
|
|
return false;
|
|
else if (proxyAList.keySet().contains(chan)) {
|
|
proxyAList.get(chan).add(eventNum + " " + sender + " " + message);
|
|
return true;
|
|
} else
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private void replyCTCP(String sender, String message){
|
|
if (message.equals("\u0001VERSION\u0001")){
|
|
StreamProvider.writeToStream(serverName,"NOTICE "+simplifyNick(sender)+" :\u0001VERSION "+ GlobalData.getAppVersion()+"\u0001");
|
|
writerWorker.logAdd("[system]", "catch/handled CTCP VERSION from", simplifyNick(sender));
|
|
System.out.println(sender+" "+message);
|
|
System.out.println("NOTICE "+simplifyNick(sender)+" \u0001VERSION "+ GlobalData.getAppVersion()+"\u0001");
|
|
}
|
|
else if (message.startsWith("\u0001PING ") && message.endsWith("\u0001")){
|
|
StreamProvider.writeToStream(serverName,"NOTICE "+simplifyNick(sender)+" :"+message);
|
|
writerWorker.logAdd("[system]", "catch/handled CTCP PING from", simplifyNick(sender));
|
|
//System.out.println(":"+simplifyNick(sender)+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" "+message);
|
|
}
|
|
else if (message.equals("\u0001CLIENTINFO\u0001")){
|
|
StreamProvider.writeToStream(serverName,"NOTICE "+simplifyNick(sender)+" :\u0001CLIENTINFO ACTION PING VERSION TIME CLIENTINFO\u0001");
|
|
writerWorker.logAdd("[system]", "catch/handled CTCP CLIENTINFO from", simplifyNick(sender));
|
|
//System.out.println(":"+simplifyNick(sender)+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" \u0001CLIENTINFO ACTION PING VERSION TIME CLIENTINFO\u0001");
|
|
}
|
|
else if (message.equals("\u0001TIME\u0001")){
|
|
StreamProvider.writeToStream(serverName,"NOTICE "+simplifyNick(sender)+" :\u0001TIME "+ ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME)+"\u0001");
|
|
writerWorker.logAdd("[system]", "catch/handled CTCP TIME from", simplifyNick(sender));
|
|
//System.out.println(":"+simplifyNick(sender)+" NOTICE "+sender.substring(0,sender.indexOf("!"))+" \u0001TIME "+ ZonedDateTime.now().format(DateTimeFormatter.RFC_1123_DATE_TIME)+"\u0001");
|
|
} else
|
|
writerWorker.logAdd("[system]", "catch CTCP request \""+message+"\" from ", simplifyNick(sender));
|
|
}
|
|
private String simplifyNick(String nick){ return nick.replaceAll("!.*$",""); }
|
|
|
|
//todo: nandle nickserv messages
|
|
|
|
private void handleNumeric(String eventNum, String sender, String message){
|
|
switch (eventNum){
|
|
case "433": // TODO: try to use alternative nickname
|
|
writerWorker.logAdd("[system]", "catch/handled:", eventNum+" [nickname already in use]");
|
|
break;
|
|
case "353":
|
|
String chan = message.substring(message.indexOf(" ")+3);
|
|
chan = chan.substring(0, chan.indexOf(" "));
|
|
if (proxyAList.containsKey(chan)) {
|
|
String userOnChanStr = message.substring(message.indexOf(":") + 1);
|
|
userOnChanStr = userOnChanStr.replaceAll("[%@+]", "").trim();
|
|
String[] usersOnChanArr = userOnChanStr.split(" ");
|
|
|
|
PipedOutputStream streamOut = new PipedOutputStream();
|
|
try {
|
|
BufferedReader streamBufferedReader = new BufferedReader(
|
|
new InputStreamReader(
|
|
new PipedInputStream(streamOut), StandardCharsets.UTF_8)
|
|
);
|
|
|
|
channelsMap.put(chan, new PrintWriter(streamOut));
|
|
// % @ +
|
|
ChanConsumer consumer = new ChanConsumer(streamBufferedReader, storageFile.getServerName(), chan, nick, usersOnChanArr, storageFile.getRejoinOnKick(), channelsMap, storageFile.getChanelConfigurationsPath());
|
|
new Thread(consumer).start();
|
|
|
|
|
|
for (String msgStored : proxyAList.get(chan)) {
|
|
channelsMap.get(chan).println(msgStored);
|
|
channelsMap.get(chan).flush();
|
|
}
|
|
|
|
proxyAList.remove(chan);
|
|
if (proxyAList.isEmpty()) {
|
|
proxyRequired = false;
|
|
}
|
|
} catch (IOException e) {
|
|
System.out.println("Internal issue: SystemConsumer->handleNumeric() @ JOIN: I/O exception while initialized child objects."); // caused by Socket
|
|
return; //TODO: QA
|
|
}
|
|
}
|
|
else
|
|
System.out.println("Some internal shit happens that shouldn't happens never ever. Take your cat, call scientists and wait for singularity. Panic allowed.");
|
|
break;
|
|
case "NICK":
|
|
if (sender.startsWith(nick+"!")) {
|
|
String oldNick = nick;
|
|
nick = message.trim();
|
|
|
|
writerWorker.logAdd("[system]", "catch/handled own NICK change from:", sender+" to: "+message);
|
|
}
|
|
break;
|
|
case "JOIN":
|
|
if (sender.startsWith(nick+"!")) {
|
|
proxyAList.put(message, new ArrayList<>()); // Add new channel name to proxy watch-list
|
|
proxyAList.get(message).add(eventNum+" "+sender+" "+message); // Add message to array linked
|
|
this.proxyRequired = true; // Ask for proxy validators
|
|
}
|
|
break;
|
|
default:
|
|
writerWorker.logAdd("[system]", "catch: "+eventNum+" from: "+sender+" :",message);
|
|
break;
|
|
}
|
|
}
|
|
} |