151 lines
6.2 KiB
Java
151 lines
6.2 KiB
Java
|
package InnaIrcBot.ProvidersConsumers;
|
||
|
|
||
|
import InnaIrcBot.Commanders.ChanelCommander;
|
||
|
import InnaIrcBot.LogDriver.BotDriver;
|
||
|
import InnaIrcBot.LogDriver.Worker;
|
||
|
|
||
|
import java.io.*;
|
||
|
import java.nio.charset.StandardCharsets;
|
||
|
import java.time.LocalTime;
|
||
|
import java.time.format.DateTimeFormatter;
|
||
|
import java.util.ArrayList;
|
||
|
import java.util.Arrays;
|
||
|
import java.util.Map;
|
||
|
|
||
|
|
||
|
public class ChanConsumer implements Runnable {
|
||
|
private BufferedReader reader;
|
||
|
private String serverName;
|
||
|
private String channelName;
|
||
|
private Worker writerWorker;
|
||
|
private ArrayList<String> userList;
|
||
|
private String nick;
|
||
|
private boolean rejoin;
|
||
|
private Map<String, PrintWriter> chanList;
|
||
|
private String configFilePath;
|
||
|
|
||
|
private PrintWriter chanelCommanderPipe;
|
||
|
|
||
|
private boolean endThread = false;
|
||
|
|
||
|
ChanConsumer(BufferedReader streamReader, String serverName, String channelName, String ownNick, String[] usersOnChan, boolean rejoinAlways, Map<String, PrintWriter> map, String configFilePath){
|
||
|
this.reader = streamReader;
|
||
|
this.serverName = serverName;
|
||
|
this.channelName = channelName;
|
||
|
this.writerWorker = BotDriver.getWorker(serverName, channelName);
|
||
|
this.userList = new ArrayList<>();
|
||
|
this.userList.addAll(Arrays.asList(usersOnChan));
|
||
|
this.nick = ownNick;
|
||
|
this.rejoin = rejoinAlways;
|
||
|
this.chanList = map;
|
||
|
this.configFilePath = configFilePath;
|
||
|
// Create chanel commander thread, get pipe
|
||
|
this.chanelCommanderPipe = getChanelCommander();
|
||
|
}
|
||
|
|
||
|
public void run(){
|
||
|
String data;
|
||
|
String[] dataStrings;
|
||
|
System.out.println("["+LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))+"] THREAD "+serverName+":"+this.channelName +" started"); // TODO:REMOVE DEBUG
|
||
|
try {
|
||
|
while ((data = reader.readLine()) != null) {
|
||
|
dataStrings = data.split(" ",3);
|
||
|
|
||
|
if (!trackUsers(dataStrings[0], dataStrings[1], dataStrings[2]))
|
||
|
continue;
|
||
|
|
||
|
writerWorker.logAdd(dataStrings[0], dataStrings[1], dataStrings[2]);
|
||
|
// Send to chanel commander thread
|
||
|
chanelCommanderPipe.println(data);
|
||
|
chanelCommanderPipe.flush();
|
||
|
//System.out.println("|"+dataStrings[0]+"|"+dataStrings[1]+"|"+dataStrings[2]+"|");
|
||
|
//System.out.println("Thread: "+this.channelName +"\n\tArray:"+ userList);
|
||
|
|
||
|
if (endThread) {
|
||
|
reader.close();
|
||
|
chanList.get(channelName).close();
|
||
|
chanList.remove(channelName);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
} catch (java.io.IOException e){
|
||
|
System.out.println("Internal issue: thread ChanConsumer->run() caused I/O exception:\n\t"+e); // TODO: reconnect
|
||
|
}
|
||
|
writerWorker.close();
|
||
|
//Chanel commander thread's pipe should be closed
|
||
|
chanelCommanderPipe.close();
|
||
|
System.out.println("["+LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))+"] THREAD "+serverName+":"+this.channelName +" ended"); // TODO:REMOVE DEBUG
|
||
|
}
|
||
|
|
||
|
private boolean trackUsers(String event, String initiatorArg, String subjectArg){
|
||
|
switch (event) {
|
||
|
case "PRIVMSG": // most common, we don't have to handle anything else
|
||
|
return true;
|
||
|
case "JOIN":
|
||
|
addUsers(initiatorArg);
|
||
|
return true;
|
||
|
case "PART":
|
||
|
delUsers(initiatorArg);
|
||
|
return true;
|
||
|
case "QUIT": // TODO fix: use regex
|
||
|
if (userList.contains(initiatorArg.replaceAll("!.+$", ""))) {
|
||
|
delUsers(initiatorArg);
|
||
|
return true;
|
||
|
} else
|
||
|
return false; // user quit, but he/she is not in this channel
|
||
|
case "KICK":
|
||
|
if (rejoin && nick.equals(subjectArg.substring(subjectArg.indexOf(" ") + 1, subjectArg.indexOf(" :"))))
|
||
|
StreamProvider.writeToStream(serverName, "JOIN " + channelName);
|
||
|
delUsers(subjectArg.substring(subjectArg.indexOf(" ") + 1, subjectArg.indexOf(" :")));
|
||
|
return true;
|
||
|
case "NICK":
|
||
|
if (userList.contains(initiatorArg.replaceAll("!.+$", ""))) {
|
||
|
swapUsers(initiatorArg, subjectArg);
|
||
|
return true;
|
||
|
} else {
|
||
|
return false; // user changed nick, but he/she is not in this channel
|
||
|
}
|
||
|
default:
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void addUsers(String user){
|
||
|
if (!userList.contains(user.replaceAll("!.+$", "")))
|
||
|
userList.add(user.replaceAll("!.+$", ""));
|
||
|
}
|
||
|
private void delUsers(String user){
|
||
|
if (user.replaceAll("!.+$", "").equals(nick)) {
|
||
|
endThread = true;
|
||
|
}
|
||
|
userList.remove(user.replaceAll("!.+$", ""));
|
||
|
}
|
||
|
private void swapUsers(String userNickOld, String userNickNew){
|
||
|
userList.remove(userNickOld.replaceAll("!.+$", ""));
|
||
|
userList.add(userNickNew);
|
||
|
if (userNickOld.replaceAll("!.+$", "").equals(nick))
|
||
|
this.nick = userNickNew;
|
||
|
}
|
||
|
// Create ChanelCommander
|
||
|
private PrintWriter getChanelCommander(){
|
||
|
PipedOutputStream streamOut = new PipedOutputStream();
|
||
|
try {
|
||
|
BufferedReader streamBufferedReader = new BufferedReader(
|
||
|
new InputStreamReader(
|
||
|
new PipedInputStream(streamOut), StandardCharsets.UTF_8)
|
||
|
);
|
||
|
|
||
|
ChanelCommander commander = new ChanelCommander(streamBufferedReader, serverName, channelName, configFilePath);
|
||
|
|
||
|
new Thread(commander).start();
|
||
|
|
||
|
return new PrintWriter(streamOut);
|
||
|
|
||
|
} catch (IOException e) {
|
||
|
System.out.println("Internal issue: ChanConsumer->getChanelCommander() I/O exception while initialized child objects."); // caused by Socket
|
||
|
endThread = true;
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
}
|