Remove GSon, add ini4j

Refactor, simplify, change configuration files format
This commit is contained in:
Dmitry Isaenko 2020-10-23 13:43:53 +03:00
parent 89fce149df
commit b3da839bcd
17 changed files with 688 additions and 478 deletions

13
pom.xml
View file

@ -19,18 +19,19 @@
<version>3.23.1</version> <version>3.23.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>org.mongodb</groupId> <groupId>org.mongodb</groupId>
<artifactId>mongodb-driver-sync</artifactId> <artifactId>mongodb-driver-sync</artifactId>
<version>3.9.1</version> <version>3.9.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.ini4j/ini4j -->
<dependency>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
<version>0.5.4</version>
</dependency>
<dependency> <dependency>
<groupId>commons-cli</groupId> <groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId> <artifactId>commons-cli</artifactId>

View file

@ -1,41 +1,36 @@
package InnaIrcBot.Commanders; package InnaIrcBot.Commanders;
import InnaIrcBot.ProvidersConsumers.StreamProvider; import InnaIrcBot.ProvidersConsumers.StreamProvider;
import InnaIrcBot.config.ConfigurationChannel;
import InnaIrcBot.config.ConfigurationManager;
import java.io.*;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.regex.Pattern; import java.util.regex.Pattern;
//TODO: FLOOD, JOIN FLOOD //TODO: FLOOD
// TODO: @ configuration level: if in result we have empty string, no need to pass it to server
public class ChanelCommander implements Runnable { public class ChanelCommander implements Runnable {
private final BlockingQueue<String> streamQueue; private final BlockingQueue<String> streamQueue;
private final String server; private final String server;
private final String channel; private final String channel;
//TODO: add timers //TODO: add timers
private final HashMap<String, String[]> joinMap; // Mask(Pattern) ->, Action | Where Action[0] could be: raw private HashMap<String, String[]> joinMap; // Mask(Pattern) ->, Action | Where Action[0] could be: raw
private final HashMap<String, String[]> msgMap; // Mask(Pattern) ->, Action | Where Action[0] could be: raw private HashMap<String, String[]> msgMap; // Mask(Pattern) ->, Action | Where Action[0] could be: raw
private final HashMap<String, String[]> nickMap; // Mask(Pattern) ->, Action | Where Action[0] could be: raw private HashMap<String, String[]> nickMap; // Mask(Pattern) ->, Action | Where Action[0] could be: raw
private boolean joinFloodTrackNeed = false; private boolean joinFloodTrackNeed = false;
private JoinFloodHandler jfh; private JoinFloodHandler jfh;
private boolean joinCloneTrackNeed = false; // todo:fix private boolean joinCloneTrackNeed = false; // todo:fix
private JoinCloneHandler jch; private JoinCloneHandler jch;
public ChanelCommander(BlockingQueue<String> stream, String serverName, String channel, String configFilePath){ public ChanelCommander(BlockingQueue<String> stream, String serverName, String channel) throws Exception{
this.streamQueue = stream; this.streamQueue = stream;
this.server = serverName; this.server = serverName;
this.channel = channel; this.channel = channel;
readConfing();
this.joinMap = new HashMap<>();
this.msgMap = new HashMap<>();
this.nickMap = new HashMap<>();
readConfing(configFilePath);
} }
@Override @Override
@ -63,15 +58,10 @@ public class ChanelCommander implements Runnable {
break; break;
/* /*
case "PART": // todo: need to track join flood? Fuck that. Track using JOIN case "PART": // todo: need to track join flood? Fuck that. Track using JOIN
break;
case "QUIT": // todo: need this? case "QUIT": // todo: need this?
break;
case "TOPIC": // todo: need this? case "TOPIC": // todo: need this?
break;
case "MODE": // todo: need this? case "MODE": // todo: need this?
break; case "KICK": // todo: need this? */
case "KICK": // todo: need this?
break; */
default: default:
break; break;
} }
@ -240,72 +230,23 @@ public class ChanelCommander implements Runnable {
executiveStr.append(LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss"))); executiveStr.append(LocalTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss")));
} }
StreamProvider.writeToStream(server, executiveStr.toString()); StreamProvider.writeToStream(server, executiveStr.toString());
}
}
// TSV
private void parse(String[] directive){
if (directive.length >= 3 && directive[0] != null && !directive[0].startsWith("#") && directive[1] != null && directive[2] != null){
// System.out.println(Arrays.toString(directive)); // TODO:debug
switch (directive[0].toLowerCase()){
case "join":
joinMap.put(directive[1], Arrays.copyOfRange(directive, 2, directive.length));
break;
case "msg":
msgMap.put(directive[1], Arrays.copyOfRange(directive, 2, directive.length));
break;
case "nick":
nickMap.put(directive[1], Arrays.copyOfRange(directive, 2, directive.length));
break;
case "joinfloodcontrol":
if (!directive[1].isEmpty() && !directive[2].isEmpty() && Pattern.matches("^[0-9]+?$", directive[1].trim()) && Pattern.matches("^[0-9]+?$", directive[2].trim())) {
int events = Integer.parseInt(directive[1].trim());
int timeFrame = Integer.parseInt(directive[2].trim());
if (events > 0 && timeFrame > 0) {
jfh = new JoinFloodHandler(events, timeFrame, server, channel);
joinFloodTrackNeed = true;
}
else {
System.out.println("Internal issue: thread ChanelCommander->parse(): 'Number of events' and/or 'Time Frame in seconds' should be greater than 0");
}
}
else
System.out.println("Internal issue: thread ChanelCommander->parse(): 'Number of events' and/or 'Time Frame in seconds' should be numbers greater than 0");
break;
case "joinclonecontrol":
if (!directive[1].isEmpty() && !directive[2].isEmpty() && Pattern.matches("^[0-9]+?$", directive[1].trim())) {
int events = Integer.parseInt(directive[1].trim());
if (events > 0){
jch = new JoinCloneHandler(directive[2], events, server, channel); // TODO: REMOVE
joinCloneTrackNeed = true;
}
else {
System.out.println("Internal issue: thread ChanelCommander->parse(): 'Number of events' should be greater than 0");
}
} else {
System.out.println("Internal issue: thread ChanelCommander->parse(): 'Number of events' should be greater than 0 and pattern shouldn't be empty.");
}
}
}
}
private String simplifyNick(String nick){ return nick.replaceAll("!.*$",""); } private String simplifyNick(String nick){ return nick.replaceAll("!.*$",""); }
private void readConfing(String confFilesPath){ private void readConfing() throws Exception{
if (!confFilesPath.endsWith(File.separator)) ConfigurationChannel configChannel = ConfigurationManager.getConfiguration(server).getChannelConfig(channel);
confFilesPath += File.separator; joinMap = configChannel.getJoinMap();
msgMap = configChannel.getMsgMap();
nickMap = configChannel.getNickMap();
File file = new File(confFilesPath+server+ channel +".csv"); // TODO: add/search for filename if (configChannel.isJoinFloodControl()) {
jfh = new JoinFloodHandler(configChannel.getJoinFloodControlEvents(), configChannel.getJoinFloodControlTimeframe(), server, channel);
if (!file.exists()) joinFloodTrackNeed = true;
return;
try {
BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
parse(line.split("\t"));
}
} }
catch (Exception e) { if (configChannel.isJoinCloneControl()) {
System.out.println("Internal issue: thread ChanelCommander->readConfig():\t\n"+e.getMessage()); jch = new JoinCloneHandler(configChannel.getJoinCloneControlPattern(), configChannel.getJoinCloneControlTimeframe(), server, channel); // TODO: REMOVE
joinCloneTrackNeed = true;
} }
} }
} }

View file

@ -1,14 +1,12 @@
package InnaIrcBot; package InnaIrcBot;
import InnaIrcBot.logging.LogDriver;
import java.util.ArrayList;
import java.util.List;
public class GlobalData { public class GlobalData {
private static final String version = "InnaIrcBot v0.8 \"Коммунарка\""; private static final String version = "InnaIrcBot v0.8 \"Коммунарка\"";
public static synchronized String getAppVersion(){ public static synchronized String getAppVersion(){
return version; return String.format("%s, %s %s %s", version,
System.getProperty("os.name"),
System.getProperty("os.version"),
System.getProperty("os.arch"));
} }
public static final int CHANNEL_QUEUE_CAPACITY = 500; public static final int CHANNEL_QUEUE_CAPACITY = 500;
} }

View file

@ -6,6 +6,7 @@ import InnaIrcBot.IrcChannel;
import InnaIrcBot.logging.LogDriver; import InnaIrcBot.logging.LogDriver;
import InnaIrcBot.logging.Worker; import InnaIrcBot.logging.Worker;
import InnaIrcBot.config.ConfigurationManager; import InnaIrcBot.config.ConfigurationManager;
import InnaIrcBot.logging.WorkerZero;
import java.time.LocalTime; import java.time.LocalTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -43,15 +44,12 @@ public class ChanConsumer implements Runnable {
this.nick = ownNick; this.nick = ownNick;
this.rejoin = ConfigurationManager.getConfiguration(serverName).getRejoinOnKick(); this.rejoin = ConfigurationManager.getConfiguration(serverName).getRejoinOnKick();
this.channels = channels; this.channels = channels;
// Create chanel commander thread, get pipe getChanelCommander();
getChanelCommander(
ConfigurationManager.getConfiguration(serverName).getChanelConfigurationsPath()
);
} }
// Create ChanelCommander // Create ChanelCommander
private void getChanelCommander(String chanelConfigurationsPath){ private void getChanelCommander() throws Exception{
this.queue = new ArrayBlockingQueue<>(GlobalData.CHANNEL_QUEUE_CAPACITY); this.queue = new ArrayBlockingQueue<>(GlobalData.CHANNEL_QUEUE_CAPACITY);
ChanelCommander commander = new ChanelCommander(queue, serverName, channelName, chanelConfigurationsPath); ChanelCommander commander = new ChanelCommander(queue, serverName, channelName);
this.channelCommanderThread = new Thread(commander); this.channelCommanderThread = new Thread(commander);
this.channelCommanderThread.start(); this.channelCommanderThread.start();
} }
@ -147,7 +145,7 @@ public class ChanConsumer implements Runnable {
System.out.println("ChanConsumer (@"+serverName+"/"+channelName+")->fixLogDriverIssues(): Some issues detected. Trying to fix..."); System.out.println("ChanConsumer (@"+serverName+"/"+channelName+")->fixLogDriverIssues(): Some issues detected. Trying to fix...");
this.writerWorker = LogDriver.getWorker(serverName, channelName); // Reset logDriver and try using the same one this.writerWorker = LogDriver.getWorker(serverName, channelName); // Reset logDriver and try using the same one
if (! writerWorker.logAdd(a, b, c)){ // Write to it what was not written (most likely) and if it's still not consistent: if (! writerWorker.logAdd(a, b, c)){ // Write to it what was not written (most likely) and if it's still not consistent:
this.writerWorker = LogDriver.getZeroWorker(); this.writerWorker = new WorkerZero();
System.out.println("ChanConsumer (@"+serverName+"/"+channelName+")->fixLogDriverIssues(): failed to use defined LogDriver. Using ZeroWorker instead."); System.out.println("ChanConsumer (@"+serverName+"/"+channelName+")->fixLogDriverIssues(): failed to use defined LogDriver. Using ZeroWorker instead.");
} }
} }

View file

@ -42,9 +42,7 @@ public class DataProvider implements Runnable {
ReconnectControl.register(server); ReconnectControl.register(server);
LogDriver.setLogDriver(server, LogDriver.setLogDriver(server);
configurationFile.getLogDriverConfiguration(),
configurationFile.getApplicationLogDir());
/* Used for sending data into consumers objects*/ /* Used for sending data into consumers objects*/
Map<String, IrcChannel> ircChannels = Collections.synchronizedMap(new HashMap<>()); Map<String, IrcChannel> ircChannels = Collections.synchronizedMap(new HashMap<>());
@ -77,8 +75,6 @@ public class DataProvider implements Runnable {
String chan = rawStrings[2].replaceAll("(\\s.?$)|(\\s.+?$)", ""); String chan = rawStrings[2].replaceAll("(\\s.?$)|(\\s.+?$)", "");
//System.out.println("\tChannel: "+chan+"\n\tAction: "+rawStrings[1]+"\n\tSender: "+rawStrings[0]+"\n\tMessage: "+rawStrings[2]+"\n");
if (rawStrings[1].equals("QUIT") || rawStrings[1].equals("NICK")) { // replace regex if (rawStrings[1].equals("QUIT") || rawStrings[1].equals("NICK")) { // replace regex
for (IrcChannel ircChannel : ircChannels.values()) { for (IrcChannel ircChannel : ircChannels.values()) {
ircChannel.getChannelQueue().add(rawStrings[1] + " " + rawStrings[0] + " " + rawStrings[2]); ircChannel.getChannelQueue().add(rawStrings[1] + " " + rawStrings[0] + " " + rawStrings[2]);

View file

@ -0,0 +1,102 @@
package InnaIrcBot.config;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
public class ConfigurationChannel {
private HashMap<String, String[]> joinMap;
private HashMap<String, String[]> msgMap;
private HashMap<String, String[]> nickMap;
private boolean joinFloodControl;
private int joinFloodControlEvents;
private int joinFloodControlTimeframe;
private boolean joinCloneControl;
private int joinCloneControlTimeframe;
private String joinCloneControlPattern;
public ConfigurationChannel(
boolean joinFloodControl,
int joinFloodControlEvents,
int joinFloodControlSeconds,
boolean joinCloneControl,
int joinCloneControlTimeframe,
String joinCloneControlPattern,
List<String> rules){
parseRules(rules);
if (joinFloodControl)
validateJoinFloodControl(joinFloodControlEvents, joinFloodControlSeconds);
if (joinCloneControl)
validateJoinCloneControl(joinCloneControlTimeframe, joinCloneControlPattern);
}
private void parseRules(List<String> rules){
this.joinMap = new HashMap<>();
this.msgMap = new HashMap<>();
this.nickMap = new HashMap<>();
for (String rule : rules){
parseRule(rule);
}
}
private void parseRule(String rule){
String[] directive = rule.split("\t");
if (isNotValidDirective(directive))
return;
switch (directive[0].toLowerCase()){
case "join":
joinMap.put(directive[1], Arrays.copyOfRange(directive, 2, directive.length));
break;
case "msg":
msgMap.put(directive[1], Arrays.copyOfRange(directive, 2, directive.length));
break;
case "nick":
nickMap.put(directive[1], Arrays.copyOfRange(directive, 2, directive.length));
break;
}
}
private boolean isNotValidDirective(String[] directive){
return directive.length < 3 || directive[0] == null || directive[1] == null || directive[2] == null;
}
private void validateJoinFloodControl(int events, int timeFrame){
if (events <= 0 && timeFrame <= 0) {
System.out.println("Join Flood Control configuration issue: 'Join number' and 'time frame' should be greater than 0.");
return;
}
joinFloodControl = true;
joinFloodControlEvents = events;
joinFloodControlTimeframe = timeFrame;
}
private void validateJoinCloneControl(int timeFrame, String pattern){
if (timeFrame < 0) {
System.out.println("Join Clone Control configuration issue: 'time frame' should be greater than 0");
return;
}
joinCloneControl = true;
joinCloneControlTimeframe = timeFrame;
joinCloneControlPattern = pattern;
}
public HashMap<String, String[]> getJoinMap() { return joinMap; }
public HashMap<String, String[]> getMsgMap() { return msgMap; }
public HashMap<String, String[]> getNickMap() { return nickMap; }
public boolean isJoinFloodControl() { return joinFloodControl; }
public int getJoinFloodControlEvents() { return joinFloodControlEvents; }
public int getJoinFloodControlTimeframe() { return joinFloodControlTimeframe; }
public boolean isJoinCloneControl() { return joinCloneControl; }
public int getJoinCloneControlTimeframe() { return joinCloneControlTimeframe; }
public String getJoinCloneControlPattern() { return joinCloneControlPattern; }
}

View file

@ -1,10 +1,19 @@
package InnaIrcBot.config; package InnaIrcBot.config;
import org.ini4j.Config;
import org.ini4j.Ini;
import org.ini4j.Wini;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ConfigurationFile { public class ConfigurationFile {
private String serverName; private String serverName;
private int serverPort; private int serverPort;
private String serverPass; private String serverPass;
private String[] channels;
private String userNick; private String userNick;
private String userIdent; private String userIdent;
private String userRealName; private String userRealName;
@ -12,73 +21,143 @@ public class ConfigurationFile {
private String userNickAuthStyle; private String userNickAuthStyle;
private String userMode; private String userMode;
private boolean rejoinOnKick; private boolean rejoinOnKick;
private String logDriver;
private String[] logDriverParameters;
private String botAdministratorPassword; private String botAdministratorPassword;
private String chanelConfigurationsPath;
private String applicationLogDir; private String applicationLogDir;
private LogDriverConfiguration logDriverConfiguration; private LogDriverConfiguration logDriverConfiguration;
private List<String> channels;
private HashMap<String, ConfigurationChannel> channelConfigs;
public ConfigurationFile(String serverName, public String getServerName() { return serverName; }
int serverPort,
String serverPass,
String[] channels,
String userNick,
String userIdent,
String userRealName,
String userNickPass,
String userNickAuthStyle,
String userMode,
boolean rejoinOnKick,
String logDriver,
String[] logDriverParameters,
String botAdministratorPassword,
String chanelConfigurationsPath,
String applicationLogDir){
this.serverName = serverName;
this.serverPort = serverPort;
this.serverPass = serverPass;
this.channels = channels;
this.userIdent = userIdent;
this.userNick = userNick;
this.userRealName = userRealName;
this.userNickPass = userNickPass;
this.userNickAuthStyle = userNickAuthStyle;
this.userMode = userMode;
this.rejoinOnKick = rejoinOnKick;
this.logDriver = logDriver;
this.logDriverParameters = logDriverParameters;
this.botAdministratorPassword = botAdministratorPassword;
this.chanelConfigurationsPath = chanelConfigurationsPath;
this.applicationLogDir = applicationLogDir;
}
public String getServerName() { return nonNullString(serverName); }
public int getServerPort() { return serverPort; } public int getServerPort() { return serverPort; }
public String getServerPass() { return nonNullString(serverPass); } public String getServerPass() { return serverPass; }
public String[] getChannels() { return channels; } public String getUserNick() { return userNick; }
public String getUserNick() { return nonNullString(userNick); } public String getUserIdent() { return userIdent; }
public String getUserIdent() { return nonNullString(userIdent); } public String getUserRealName() { return userRealName; }
public String getUserRealName() { return nonNullString(userRealName); } public String getUserNickPass() { return userNickPass; }
public String getUserNickPass() { return nonNullString(userNickPass); } public String getUserNickAuthStyle() { return userNickAuthStyle; }
public String getUserNickAuthStyle() { return nonNullString(userNickAuthStyle); } public String getUserMode() { return userMode; }
public String getUserMode() { return nonNullString(userMode); }
public boolean getRejoinOnKick() { return rejoinOnKick; } public boolean getRejoinOnKick() { return rejoinOnKick; }
public String getBotAdministratorPassword() { return botAdministratorPassword; }
public String getApplicationLogDir() { return applicationLogDir; }
public LogDriverConfiguration getLogDriverConfiguration(){ return logDriverConfiguration; }
public List<String> getChannels() { return channels; }
public ConfigurationChannel getChannelConfig(String channel) { return channelConfigs.get(channel); }
public LogDriverConfiguration getLogDriverConfiguration(){ public ConfigurationFile(String pathToConfigurationFile) throws Exception{
return new LogDriverConfiguration(nonNullString(logDriver).toLowerCase(), logDriverParameters); Wini ini = new Wini();
ini.setConfig(getConfig());
ini.load(new File(pathToConfigurationFile));
parseMain(ini);
parseLogging(ini);
parseChannels(ini);
validate();
} }
public String getBotAdministratorPassword() { return nonNullString(botAdministratorPassword); } private Config getConfig(){
public String getChanelConfigurationsPath() { return nonNullString(chanelConfigurationsPath); } Config config = new Config();
public String getApplicationLogDir() { return nonNullString(applicationLogDir); } config.setFileEncoding(StandardCharsets.UTF_8);
config.setMultiOption(true);
public void setUserNickAuthStyle(String userNickAuthStyle) { config.setEscape(true);
this.userNickAuthStyle = userNickAuthStyle; return config;
} }
private String nonNullString(String value){ private void parseMain(Wini ini){
return value == null ? "" : value; Ini.Section mainSection = ini.get("main");
this.serverName = mainSection.getOrDefault("server name", "");
this.serverPort = mainSection.get("server port", int.class);
this.serverPass = mainSection.getOrDefault("server password", "");
this.userNick = mainSection.getOrDefault("nickname", "");
this.userIdent = mainSection.getOrDefault("ident", "");
this.userRealName = mainSection.getOrDefault("real name", "");
this.userNickPass = mainSection.getOrDefault("nickname password", "");
this.userNickAuthStyle = mainSection.getOrDefault("nickserv auth method", "").toLowerCase();
this.userMode = mainSection.getOrDefault("user modes", "");
this.rejoinOnKick = mainSection.get("auto rejoin", boolean.class);
this.botAdministratorPassword = mainSection.getOrDefault("bot administrator password", "");
this.applicationLogDir = mainSection.getOrDefault("application logs", "");
}
private void parseChannels(Wini ini){
Ini.Section channelsSection = ini.get("channels");
this.channels = channelsSection.getAll("channel");
this.channelConfigs = new HashMap<>();
for (String channel: channels){
addNewChannelConfiguration(ini, channel);
}
}
private void addNewChannelConfiguration(Wini ini, String channelName){
Ini.Section channelSection = ini.get(channelName);
if (channelSection == null)
return;
Ini.Section rulesChannelSection = channelSection.getChild("rules");
List<String> channelRules = rulesChannelSection.getAll("rule"); //TODO: check not-null
if (channelRules == null)
channelRules = new ArrayList<>();
Ini.Section joinFloodControlSection = channelSection.getChild("rules");
boolean joinFloodControl = joinFloodControlSection.get("enable", boolean.class);
int joinFloodControlEventsNumber = -1;
int joinFloodControlTimeFrame = -1;
if (joinFloodControl){
joinFloodControlEventsNumber = joinFloodControlSection.get("join number", int.class);
joinFloodControlTimeFrame = joinFloodControlSection.get("time frame", int.class);
}
Ini.Section joinCloneControlSection = channelSection.getChild("rules");
boolean joinCloneControl = joinCloneControlSection.get("enable", boolean.class);;
int joinCloneControlTimeFrame = -1;
String joinCloneControlPattern = "";
if (joinCloneControl){
joinCloneControlTimeFrame = joinCloneControlSection.get("time frame", int.class);
joinCloneControlPattern = joinCloneControlSection.getOrDefault("pattern", "");
}
channelConfigs.put(channelName, new ConfigurationChannel(
joinFloodControl,
joinFloodControlEventsNumber,
joinFloodControlTimeFrame,
joinCloneControl,
joinCloneControlTimeFrame,
joinCloneControlPattern,
channelRules));
}
private void parseLogging(Wini ini){
Ini.Section channelsSection = ini.get("logging");
this.logDriverConfiguration = new LogDriverConfiguration(
channelsSection.getOrDefault("driver", ""),
channelsSection.getOrDefault("file(s) location", ""),
channelsSection.getOrDefault("MongoDB host:port", ""),
channelsSection.getOrDefault("MongoDB DB table", ""),
channelsSection.getOrDefault("MongoDB DB user", ""),
channelsSection.getOrDefault("MongoDB DB password", "")
);
}
//TODO: more validation
private void validate() throws Exception{
if (serverName.isEmpty())
throw new Exception("Server not defined in configuration file.");
if (serverPort <= 0 || serverPort > 65535)
throw new Exception("Server port number cannot be less/equal zero or greater then 65535");
if (userNick.isEmpty())
throw new Exception("Configuration issue: no nickname specified. ");
if (! userNickPass.isEmpty()) {
if (userNickAuthStyle.isEmpty())
throw new Exception("Configuration issue: password specified while auth method is not.");
if ( ! userNickAuthStyle.equals("rusnet") && ! userNickAuthStyle.equals("freenode"))
throw new Exception("Configuration issue: userNickAuthStyle could be freenode or rusnet.");
}
} }
} }

View file

@ -1,13 +1,15 @@
package InnaIrcBot.config; package InnaIrcBot.config;
import com.google.gson.Gson; import org.ini4j.*;
import com.google.gson.GsonBuilder; import org.ini4j.spi.EscapeTool;
import java.io.*; import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
public class ConfigurationFileGenerator { public class ConfigurationFileGenerator {
private String fileLocation; private String fileLocation;
@ -28,7 +30,6 @@ public class ConfigurationFileGenerator {
} }
createConfigurationFile(); createConfigurationFile();
System.out.println("Configuration file created: " + this.fileLocation); // TODO: Move to l4j System.out.println("Configuration file created: " + this.fileLocation); // TODO: Move to l4j
} catch (IOException e){ } catch (IOException e){
System.out.println("Unable to write configuration file: \n\t"+e.getMessage()); System.out.println("Unable to write configuration file: \n\t"+e.getMessage());
@ -38,7 +39,7 @@ public class ConfigurationFileGenerator {
private void setLocationDefault(){ private void setLocationDefault(){
fileLocation = System.getProperty("user.dir") fileLocation = System.getProperty("user.dir")
+ File.separator + File.separator
+ "myBotConfig.conf"; + "innaircbot.conf";
} }
private boolean locationNotDefined(){ private boolean locationNotDefined(){
@ -52,16 +53,17 @@ public class ConfigurationFileGenerator {
private void setLocationInsideFolder() throws IOException{ private void setLocationInsideFolder() throws IOException{
createFoldersIfNeeded(); createFoldersIfNeeded();
if (fileLocation.endsWith(File.separator)) if (fileLocation.endsWith(File.separator))
fileLocation = fileLocation + "myBotConfig.conf"; fileLocation = fileLocation + "innaircbot.conf";
else else
fileLocation = fileLocation + File.separator + "myBotConfig.conf"; fileLocation = fileLocation + File.separator + "innaircbot.conf";
} }
private void createFoldersIfNeeded() throws IOException{ private void createFoldersIfNeeded() throws IOException{
Path folderPath = Paths.get(fileLocation); Path folderPath = Paths.get(fileLocation);
if (! Files.exists(folderPath)) if (! Files.exists(folderPath))
Files.createDirectories(folderPath); Files.createDirectories(folderPath);
} }
private void createConfigurationFile() throws IOException{ /*
private void createConfigurationFileOld() throws IOException{
File configurationFile = new File(this.fileLocation); File configurationFile = new File(this.fileLocation);
Writer writerFile = new OutputStreamWriter(new FileOutputStream(configurationFile.getAbsolutePath()), StandardCharsets.UTF_8); Writer writerFile = new OutputStreamWriter(new FileOutputStream(configurationFile.getAbsolutePath()), StandardCharsets.UTF_8);
@ -78,7 +80,7 @@ public class ConfigurationFileGenerator {
"freenode", "freenode",
"ix", "ix",
true, true,
"Files", "files",
new String[] {System.getProperty("user.home")}, new String[] {System.getProperty("user.home")},
"pswd", "pswd",
System.getProperty("user.home"), System.getProperty("user.home"),
@ -89,4 +91,91 @@ public class ConfigurationFileGenerator {
writingStorageObject.toJson(configurationFileObject, writerFile); writingStorageObject.toJson(configurationFileObject, writerFile);
writerFile.close(); writerFile.close();
} }
*/
private void createConfigurationFile() throws IOException{
final String mainSectionName = "main";
final String channelSectionName = "channels";
List<String> channels = new ArrayList<>();
channels.add("#main");
channels.add("#lpr");
List<String> logDriverPreferences = new ArrayList<>();
logDriverPreferences.add(System.getProperty("user.home"));
File configurationFile = new File(this.fileLocation);
Config myConfig = new Config();
myConfig.setFileEncoding(StandardCharsets.UTF_8);
myConfig.setMultiOption(true);
myConfig.setEscape(true);
//myConfig.setEmptyOption(true);
//myConfig.setComment(true);
Wini ini = new Wini();
ini.setConfig(myConfig);
Ini.Section mainSection = ini.add(mainSectionName);
mainSection.put( "server name", "srv");
mainSection.put( "server port", 6667);
mainSection.put( "server password", "");
mainSection.put( "nickname", "InnaIrcBot");
mainSection.put( "ident", "sweethome");
mainSection.put( "real name", "bot");
mainSection.put( "nickname password", "");
mainSection.put( "nickserv auth method", "freenode");
mainSection.put( "user modes", "i");
mainSection.put( "auto rejoin", true);
mainSection.put( "bot administrator password", "i_pswd");
mainSection.put( "application logs", "/tmp");
Ini.Section loggingSection = ini.add("logging");
loggingSection.put( "driver", "files");
loggingSection.put("file(s) location", "");
loggingSection.put("MongoDB host:port", "");
loggingSection.put("MongoDB DB table", "");
loggingSection.put("MongoDB DB user", "");
loggingSection.put("MongoDB DB password", "");
Ini.Section channelsSection = ini.add(channelSectionName);
channelsSection.putAll("channel", channels);
Ini.Section channelMainSection = ini.add( channels.get(0) );
Ini.Section channelMainRulesSection = channelMainSection.addChild("rules");
channelMainRulesSection.add("rule","join\t^cv.*\t\\cversion\t(^.+(\\s|\\t)+)");
channelMainRulesSection.add("rule","msg\t^cv.*\t\\cversion\t(^.+(\\s|\\t)+)");
channelMainRulesSection.add("rule", "join\t^BadGuy1(.+)?!.*\t\\kickban\trequested\\privmsg\tNever come back");
channelMainRulesSection.add("rule", "join\t^BadGuy2(.+)?!.*\t\\kick\tkick!");
channelMainRulesSection.add("rule", "join\t^BadGuy3(.+)?!.*\t\\ban\tban!");
channelMainRulesSection.add("rule", "nick\t^BadNickname.*\t\\chanmsg\tstop it!\n");
channelMainRulesSection.add("rule", "nick\t^Billilish.*\t\\voice");
channelMainRulesSection.add("rule", "msg\t^cci.*\t\\cclientinfo\t\t(^.+(\\s|\\t)+)\tThere are no ");
channelMainRulesSection.add("rule", "msg\t^cf.*\t\\cfinger\t(^.+(\\s|\\t)+)\tI \t D\t K");
channelMainRulesSection.add("rule", "msg\t^cp.*\t\\cping\t\t(^.+(\\s|\\t)+)\tlol");
channelMainRulesSection.add("rule", "msg\t^cs.*\t\\csource\t(^.+(\\s|\\t)+)\tpiu-\tpiu\t: ");
channelMainRulesSection.add("rule", "msg\t^ct.*\t\\ctime\t\t(^.+(\\s|\\t)+)\tOoops:");
channelMainRulesSection.add("rule", "msg\t^cui.*\t\\cuserinfo\t(^.+(\\s|\\t)+)\tNope: ");
channelMainRulesSection.add("rule", "msg\t^cv.*\t\\cversion\t(^.+(\\s|\\t)+)");
channelMainRulesSection.add("rule", "msg\t^pci.*\t\\pclientinfo\t(^.+(\\s|\\t)+)\tkek: ");
channelMainRulesSection.add("rule", "msg\t^pf.*\t\\pfinger\t(^.+(\\s|\\t)+)\t\tNobody like: ");
channelMainRulesSection.add("rule", "msg\t^pp.*\t\\pping\t\t(^.+(\\s|\\t)+)\tnope: ");
channelMainRulesSection.add("rule", "msg\t^ps.*\t\\psource\t(^.+(\\s|\\t)+)\t\tNooo ");
channelMainRulesSection.add("rule", "msg\t^pt.*\t\\ptime\t\t(^.+(\\s|\\t)+)\tHo-ho-ho: ");
channelMainRulesSection.add("rule", "msg\t^pu.*\t\\puserinfo\t(^.+(\\s|\\t)+)\tSome random text: ");
channelMainRulesSection.add("rule", "msg\t^pv.*\t\\pversion\t(^.+(\\s|\\t)+)\t\\chanmsg\tsent!");
Ini.Section channelMainJoinFloodControlSection = channelMainSection.addChild("JoinFloodControl");
channelMainJoinFloodControlSection.put("enable", true);
channelMainJoinFloodControlSection.put("join number", 3);
channelMainJoinFloodControlSection.put("time frame", 60);
Ini.Section channelMainJoinCloneControlSection = channelMainSection.addChild("JoinCloneControl");
channelMainJoinCloneControlSection.put("enable", false);
channelMainJoinCloneControlSection.put("pattern", "^.+[0-9]+?!.*$");
channelMainJoinFloodControlSection.put("time frame", 0);
ini.store(configurationFile);
}
} }

View file

@ -1,50 +0,0 @@
package InnaIrcBot.config;
import com.google.gson.Gson;
import java.io.*;
public class ConfigurationFileReader {
private ConfigurationFileReader(){}
static ConfigurationFile read(String pathToFile) throws Exception{ // TODO: NULL or object
ConfigurationFile storageObject;
File configFile = new File(pathToFile);
try (Reader fileReader = new InputStreamReader(new FileInputStream(configFile))) {
storageObject = new Gson().fromJson(fileReader, ConfigurationFile.class);
}
validate(storageObject);
return storageObject;
}
private static void validate(ConfigurationFile configurationFile) throws Exception{ //TODO: more validation
if (configurationFile.getServerName().isEmpty())
throw new Exception("Server not defined in configuration file.");
if (configurationFile.getServerPort() <= 0)
throw new Exception("Server port set incorrectly in configuration file.");
String nick = configurationFile.getUserNick();
if (nick.isEmpty())
throw new Exception("Configuration issue: no nickname specified. ");
if (! configurationFile.getUserNickPass().isEmpty()) {
if (configurationFile.getUserNickAuthStyle().isEmpty())
throw new Exception("Configuration issue: password specified while auth method is not.");
configurationFile.setUserNickAuthStyle( configurationFile.getUserNickAuthStyle().toLowerCase() );
if ( ! configurationFile.getUserNickAuthStyle().equals("rusnet") && ! configurationFile.getUserNickAuthStyle().equals("freenode"))
throw new Exception("Configuration issue: userNickAuthStyle could be freenode or rusnet.");
}
if (configurationFile.getServerPort() <= 0 || configurationFile.getServerPort() > 65535)
throw new Exception("Server port number cannot be less/equal zero or greater then 65535");
}
}

View file

@ -8,7 +8,7 @@ public class ConfigurationManager {
private final static Map<String, ConfigurationFile> configurations = Collections.synchronizedMap(new HashMap<>()); private final static Map<String, ConfigurationFile> configurations = Collections.synchronizedMap(new HashMap<>());
public static ConfigurationFile readAndSetConfiguration(String pathToConfigurationFile) throws Exception{ public static ConfigurationFile readAndSetConfiguration(String pathToConfigurationFile) throws Exception{
ConfigurationFile configurationFile = ConfigurationFileReader.read(pathToConfigurationFile); ConfigurationFile configurationFile = new ConfigurationFile(pathToConfigurationFile);
configurations.put(configurationFile.getServerName(), configurationFile); configurations.put(configurationFile.getServerName(), configurationFile);
return configurationFile; return configurationFile;
} }

View file

@ -4,37 +4,81 @@ import InnaIrcBot.logging.SupportedLogDrivers;
public class LogDriverConfiguration { public class LogDriverConfiguration {
private String name; private String name;
private String[] params;
public LogDriverConfiguration(String name, String[] params){ private final String path;
private final String mongoURI;
private final String mongoTable;
private String mongoUser;
private String mongoPassword;
public LogDriverConfiguration(
String name,
String path,
String mongoURI,
String mongoTable,
String mongoUser,
String mongoPassword)
{
this.name = name.toLowerCase(); this.name = name.toLowerCase();
this.params = params; this.path = path;
this.mongoURI = mongoURI;
this.mongoTable = mongoTable;
this.mongoUser = mongoUser;
this.mongoPassword = mongoPassword;
validateName(); validateName();
validateParams(); validateConfiguration();
} }
private void validateName(){ private void validateName(){
if (! SupportedLogDrivers.contains(name)) { if (! SupportedLogDrivers.contains(name)) {
name = SupportedLogDrivers.zero; name = SupportedLogDrivers.zero;
} }
} }
private void validateParams(){
if (params == null) { private void validateConfiguration(){
name = SupportedLogDrivers.zero; switch (this.name){
return; case SupportedLogDrivers.files:
case SupportedLogDrivers.sqlite:
validatePath();
break;
case SupportedLogDrivers.mongodb:
validateMongo();
break;
} }
if (params.length == 0){ }
name = SupportedLogDrivers.zero;
return; private void validatePath(){
try {
checkFieldNotEmpty(path);
} }
if (params[0] == null){ catch (Exception e){
name = SupportedLogDrivers.zero;
return;
}
if (params[0].isEmpty()){
name = SupportedLogDrivers.zero; name = SupportedLogDrivers.zero;
} }
} }
private void validateMongo(){
try {
checkFieldNotEmpty(mongoURI);
checkFieldNotEmpty(mongoTable);
if (mongoUser == null)
mongoUser = "";
if (mongoPassword == null)
mongoPassword = "";
}
catch (Exception e){
name = SupportedLogDrivers.zero;
}
}
private void checkFieldNotEmpty(String field) throws Exception{
if (field == null || field.isEmpty()) {
throw new Exception();
}
}
public String getName() { return name; } public String getName() { return name; }
public String[] getParams() { return params; } public String getPath() { return path; }
public String getMongoURI() { return mongoURI; }
public String getMongoTable() { return mongoTable; }
public String getMongoUser() { return mongoUser; }
public String getMongoPassword() { return mongoPassword; }
} }

View file

@ -1,62 +1,52 @@
package InnaIrcBot.logging; package InnaIrcBot.logging;
import InnaIrcBot.ProvidersConsumers.StreamProvider; import InnaIrcBot.config.ConfigurationFile;
import InnaIrcBot.config.ConfigurationManager;
import InnaIrcBot.config.LogDriverConfiguration; import InnaIrcBot.config.LogDriverConfiguration;
import java.util.HashMap; import java.util.HashMap;
public class LogDriver { public class LogDriver {
private final static HashMap<String, String[][]> serverDriver = new HashMap<>();
private final static HashMap<String, WorkerSystem> systemLogWorkerMap = new HashMap<>(); private final static HashMap<String, WorkerSystem> systemLogWorkerMap = new HashMap<>();
/**
* Define driver for desired server // TODO: add proxy multiple drivers support
* */ public static synchronized void setLogDriver(String server){
// TODO: add proxy worker for using with multiple drivers String applicationLogDir;
public static synchronized void setLogDriver(String server, try {
LogDriverConfiguration logDriverConfiguration, applicationLogDir = ConfigurationManager.getConfiguration(server).getApplicationLogDir();
String applicationLogDir){ }
String[][] drvAndParams = { catch (Exception e){
{logDriverConfiguration.getName()}, applicationLogDir = "";
logDriverConfiguration.getParams() }
};
serverDriver.put(server, drvAndParams);
systemLogWorkerMap.put(server, new WorkerSystem(server, applicationLogDir)); systemLogWorkerMap.put(server, new WorkerSystem(server, applicationLogDir));
} }
public static synchronized Worker getWorker(String server, String channel){ public static synchronized Worker getWorker(String server, String channel){
if (serverDriver.containsKey(server)) { try {
switch (serverDriver.get(server)[0][0]) { ConfigurationFile serverConfiguration = ConfigurationManager.getConfiguration(server);
LogDriverConfiguration logDriverConfiguration = serverConfiguration.getLogDriverConfiguration();
switch (logDriverConfiguration.getName()) {
case "files": case "files":
WorkerFiles workerFiles = new WorkerFiles(server, serverDriver.get(server)[1], channel); return new WorkerFiles(server, logDriverConfiguration, channel);
return validateConsistancy(workerFiles, server, channel);
case "sqlite": case "sqlite":
WorkerSQLite workerSQLite = new WorkerSQLite(server, serverDriver.get(server)[1], channel); return new WorkerSQLite(server, logDriverConfiguration, channel);
return validateConsistancy(workerSQLite, server, channel);
case "mongodb": case "mongodb":
WorkerMongoDB workerMongoDB = new WorkerMongoDB(server, serverDriver.get(server)[1], channel); return new WorkerMongoDB(server, logDriverConfiguration, channel);
return validateConsistancy(workerMongoDB, server, channel);
case "zero": case "zero":
default:
return new WorkerZero(); return new WorkerZero();
} }
} }
System.out.println("Issue on BotDriver->getWorker(): Channel requested for non-existing server?\n" + catch (Exception e){
"\tUsing ZeroWorker."); System.out.println("Issue on BotDriver->getWorker(): Channel requested for non-existing server? "
return new WorkerZero(); + e.getMessage()
+ "\n\tUsing ZeroWorker.");
return new WorkerZero();
}
} }
// If channel found that it's impossible to use defined worker from user settings and asking for use ZeroWorker
public static synchronized Worker getZeroWorker(){ return new WorkerZero(); }
public static synchronized WorkerSystem getSystemWorker(String serverName){ public static synchronized WorkerSystem getSystemWorker(String serverName){
return systemLogWorkerMap.get(serverName); return systemLogWorkerMap.get(serverName);
} }
private static Worker validateConsistancy(Worker worker, String server, String channel){ // synchronized?
if (worker.isConsistent()){
return worker;
}
System.out.println("BotDriver->validateConstancy(): Unable to use "
+worker.getClass().getSimpleName()+" for "+server+"/"+channel
+". Using ZeroWorker instead.");
return new WorkerZero();
}
} }

View file

@ -1,5 +1,7 @@
package InnaIrcBot.logging; package InnaIrcBot.logging;
import InnaIrcBot.config.LogDriverConfiguration;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
@ -17,10 +19,10 @@ public class WorkerFiles implements Worker {
private boolean consistent; private boolean consistent;
public WorkerFiles(String server, String[] driverParameters, String channel){ public WorkerFiles(String server, LogDriverConfiguration logDriverConfiguration, String channel){
this.channel = channel.replaceAll(File.separator, ","); this.channel = channel.replaceAll(File.separator, ",");
formatFilePath(server, driverParameters); formatFilePath(server, logDriverConfiguration.getPath());
try { try {
createServerFolder(); createServerFolder();
@ -31,9 +33,7 @@ public class WorkerFiles implements Worker {
} }
} }
private void formatFilePath(String server, String[] driverParameters){ private void formatFilePath(String server, String dirLocation){
String dirLocation = driverParameters[0].trim(); // TODO: MOVE trim() out of here
if (! dirLocation.endsWith(File.separator)) if (! dirLocation.endsWith(File.separator))
dirLocation += File.separator; dirLocation += File.separator;

View file

@ -1,5 +1,6 @@
package InnaIrcBot.logging; package InnaIrcBot.logging;
import InnaIrcBot.config.LogDriverConfiguration;
import com.mongodb.*; import com.mongodb.*;
import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients; import com.mongodb.client.MongoClients;
@ -24,27 +25,15 @@ public class WorkerMongoDB implements Worker { //TODO consider ski
private MongoCollection<Document> collection; private MongoCollection<Document> collection;
private boolean consistent; private boolean consistent;
public WorkerMongoDB(String server, String[] driverParameters, String channel){ public WorkerMongoDB(String server, LogDriverConfiguration logDriverConfiguration, String channel) throws Exception{
this.server = server; this.server = server;
if (driverParameters.length < 2) String mongoHostAddress = logDriverConfiguration.getMongoURI();
return; String mongoDBName = logDriverConfiguration.getMongoTable();
if (driverParameters[0].isEmpty()) String mongoUser = logDriverConfiguration.getMongoUser();
return; String mongoPass = logDriverConfiguration.getMongoPassword();
if (driverParameters[1].isEmpty())
return;
String mongoHostAddress = driverParameters[0]; if (mongoUser.isEmpty()) {// Consider that DB does not require auth, therefore any credentials are fine, since not null ;)
String mongoDBName = driverParameters[1];
String mongoUser;
String mongoPass;
if (driverParameters.length == 4 && !driverParameters[2].isEmpty() && !driverParameters[3].isEmpty()) {
mongoUser = driverParameters[2];
mongoPass = driverParameters[3];
}
else { // Consider that DB does not require auth, therefore any credentials are fine, since not null ;)
mongoUser = "anon"; mongoUser = "anon";
mongoPass = "anon"; mongoPass = "anon";
} }
@ -108,27 +97,12 @@ public class WorkerMongoDB implements Worker { //TODO consider ski
Document ping = new Document("ping", 1); Document ping = new Document("ping", 1);
// //
try { Document answer = mongoDB.runCommand(ping); // reports to monitor thread if some fuckups happens
Document answer = mongoDB.runCommand(ping); // reports to monitor thread if some fuckups happens if (answer.get("ok") == null || (Double)answer.get("ok") != 1.0d){
if (answer.get("ok") == null || (Double)answer.get("ok") != 1.0d){ close(server);
close(server); return;
return;
}
consistent = true;
} catch (MongoCommandException mce){
System.out.println("BotMongoWorker (@"+this.server +"): Command exception. Check if username/password set correctly.");
close(server); // server received by constructor, not this.server
} catch (MongoTimeoutException mte) {
System.out.println("BotMongoWorker (@"+this.server +"): Timeout exception.");
close(server); // server received by constructor, not this.server
}catch (MongoException me){
System.out.println("BotMongoWorker (@"+this.server +"): MongoDB Exception.");
close(server); // server received by constructor, not this.server
} catch (IllegalStateException ise){
System.out.println("BotMongoWorker (@"+this.server +"): Illegal state exception: MongoDB server already closed (not an issue).");
consistent = false;
// no need to close() obviously
} }
consistent = true;
setClosable(); setClosable();
} }

View file

@ -1,5 +1,6 @@
package InnaIrcBot.logging; package InnaIrcBot.logging;
import InnaIrcBot.config.LogDriverConfiguration;
import org.sqlite.SQLiteConfig; import org.sqlite.SQLiteConfig;
import org.sqlite.SQLiteOpenMode; import org.sqlite.SQLiteOpenMode;
@ -12,139 +13,129 @@ public class WorkerSQLite implements Worker {
private boolean consistent = false; private boolean consistent = false;
private PreparedStatement preparedStatement; private PreparedStatement preparedStatement;
private String ircServer; private final String server;
/** /**
* Don't even think of changing this balalaika. * Don't even think of changing this balalaika.
* */ * */
public WorkerSQLite(String server, String[] driverParameters, String channel){ // TODO: threads on SQLite level // remember: One file one DB public WorkerSQLite(String server, LogDriverConfiguration logDriverConfiguration, String channel) throws Exception{ // TODO: threads on SQLite level // remember: One file one DB
this.ircServer = server; this.server = server;
driverParameters[0] = driverParameters[0].trim(); String dbFileLocation = logDriverConfiguration.getPath();
File dir = new File(driverParameters[0]); File dir = new File(dbFileLocation);
try { dir.mkdirs(); // ignore result, because if it's already exists we're good. Otherwise, it will be created. Only issue that can occur is SecurityException thrown, so let's catch it.
dir.mkdirs(); // ignore result, because if it's already exists we're good. Otherwise, it will be created. Only issue that can occur is SecurityException thrown, so let's catch it.
} catch (Exception e){ if (!dir.exists()) {
System.out.println("BotSQLiteWorker (@"+server+")->constructor(): Failure:\n\tUnable to create directory to store DB file: \n\t" +e); throw new Exception("BotSQLiteWorker (@"+server+")->constructor(): Failure:\n\tUnable to create directory to store DB file: " + dbFileLocation);
return; // consistent = false;
}
if (!dir.exists()) { // probably we might want to try-catch SecurityException, but if it appeared, it has been appeared already in previous block
System.out.println("BotSQLiteWorker (@"+server+")->constructor(): Failure:\n\tUnable to create directory to store DB file: " + driverParameters[0]);
return; // consistent = false;
} }
String connectionURL; String connectionURL;
if (driverParameters[0].endsWith(File.separator)) if (dbFileLocation.endsWith(File.separator))
connectionURL = "jdbc:sqlite:"+driverParameters[0]+server+".db"; connectionURL = "jdbc:sqlite:"+dbFileLocation+server+".db";
else else
connectionURL = "jdbc:sqlite:"+driverParameters[0]+File.separator+server+".db"; connectionURL = "jdbc:sqlite:"+dbFileLocation+File.separator+server+".db";
channel = channel.trim().replaceAll("\"","\\\""); // TODO: use trim in every driver/worker? channel = channel.trim().replaceAll("\"","\\\""); // TODO: use trim in every driver/worker?
try {
SQLiteConfig sqlConfig = new SQLiteConfig();
sqlConfig.setOpenMode(SQLiteOpenMode.NOMUTEX); //SQLITE_OPEN_NOMUTEX : multithreaded mode
this.connection = DriverManager.getConnection(connectionURL, sqlConfig.toProperties()); SQLiteConfig sqlConfig = new SQLiteConfig();
if (connection != null){ sqlConfig.setOpenMode(SQLiteOpenMode.NOMUTEX); //SQLITE_OPEN_NOMUTEX : multithreaded mode
// Create table if not created
Statement statement = connection.createStatement();
String query = "CREATE TABLE IF NOT EXISTS \""+channel+"\" ("
+ " id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+ " unixtime INTEGER,"
+ " event TEXT,"
+ " subject TEXT,"
+ " message TEXT,"
+ " object TEXT"
+");";
statement.executeUpdate(query);
// Check table representation this.connection = DriverManager.getConnection(connectionURL, sqlConfig.toProperties());
ResultSet rs = statement.executeQuery("PRAGMA table_info(\""+channel+"\");"); // executeQuery never null if (connection != null){
boolean[] schemaResultCheck = {false, false, false, false, false, false}; // Create table if not created
Statement statement = connection.createStatement();
String query = "CREATE TABLE IF NOT EXISTS \""+channel+"\" ("
+ " id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
+ " unixtime INTEGER,"
+ " event TEXT,"
+ " subject TEXT,"
+ " message TEXT,"
+ " object TEXT"
+");";
statement.executeUpdate(query);
while (rs.next()) { // Check table representation
switch (rs.getInt("cid")) { ResultSet rs = statement.executeQuery("PRAGMA table_info(\""+channel+"\");"); // executeQuery never null
case 0: boolean[] schemaResultCheck = {false, false, false, false, false, false};
if (rs.getString("name").equals("id")
&& rs.getString("type").equals("INTEGER") while (rs.next()) {
&& (rs.getInt("notnull") == 1) switch (rs.getInt("cid")) {
&& (rs.getString("dflt_value") == null) case 0:
&& (rs.getInt("pk") == 1)) if (rs.getString("name").equals("id")
schemaResultCheck[0] = true; && rs.getString("type").equals("INTEGER")
//System.out.println("Got 0"); && (rs.getInt("notnull") == 1)
break; && (rs.getString("dflt_value") == null)
case 1: && (rs.getInt("pk") == 1))
if (rs.getString("name").equals("unixtime") schemaResultCheck[0] = true;
&& rs.getString("type").equals("INTEGER") //System.out.println("Got 0");
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[1] = true;
//System.out.println("Got 1");
break;
case 2:
if (rs.getString("name").equals("event")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[2] = true;
//System.out.println("Got 2");
break;
case 3:
if (rs.getString("name").equals("subject")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[3] = true;
//System.out.println("Got 3");
break;
case 4:
if (rs.getString("name").equals("message")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[4] = true;
//System.out.println("Got 4");
break;
case 5:
if (rs.getString("name").equals("object")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[5] = true;
//System.out.println("Got 5");
break;
default:
for (int i = 0; i <= 5; i++) {
schemaResultCheck[i] = false; // If more then 5 elements, ruin results
}
}
}
// Validating result: it table in DB have expected schema. If not, removing and recreating table.
for (boolean element: schemaResultCheck) {
if (!element) {
System.out.println("BotSQLiteWorker (@"+server+")->Constructor(): Notice:\n\tFound already existing table for channel with incorrect syntax: removing table and re-creating.");
statement.executeUpdate("DROP TABLE \"" + channel + "\";");
statement.executeUpdate(query);
break; break;
} case 1:
if (rs.getString("name").equals("unixtime")
&& rs.getString("type").equals("INTEGER")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[1] = true;
//System.out.println("Got 1");
break;
case 2:
if (rs.getString("name").equals("event")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[2] = true;
//System.out.println("Got 2");
break;
case 3:
if (rs.getString("name").equals("subject")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[3] = true;
//System.out.println("Got 3");
break;
case 4:
if (rs.getString("name").equals("message")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[4] = true;
//System.out.println("Got 4");
break;
case 5:
if (rs.getString("name").equals("object")
&& rs.getString("type").equals("TEXT")
&& (rs.getInt("notnull") == 0)
&& (rs.getString("dflt_value") == null)
&& (rs.getInt("pk") == 0))
schemaResultCheck[5] = true;
//System.out.println("Got 5");
break;
default:
for (int i = 0; i <= 5; i++) {
schemaResultCheck[i] = false; // If more then 5 elements, ruin results
}
} }
this.consistent = true; }
// Validating result: it table in DB have expected schema. If not, removing and recreating table.
for (boolean element: schemaResultCheck) {
if (!element) {
System.out.println("BotSQLiteWorker (@"+server+")->Constructor(): Notice:\n\tFound already existing table for channel with incorrect syntax: removing table and re-creating.");
statement.executeUpdate("DROP TABLE \"" + channel + "\";");
statement.executeUpdate(query);
break;
}
}
this.consistent = true;
this.preparedStatement = connection.prepareStatement( this.preparedStatement = connection.prepareStatement(
"INSERT INTO \""+channel "INSERT INTO \""+channel
+"\" (unixtime, event, subject, message, object) " +"\" (unixtime, event, subject, message, object) "
+"VALUES (?, ?, ?, ?, ?);"); +"VALUES (?, ?, ?, ?, ?);");
}
else {
System.out.println("BotSQLiteWorker (@"+server+")->constructor() failed:\n\t Connection to SQLite not established.");
this.consistent = false;
}
} }
catch (SQLException e){ else {
System.out.println("BotSQLiteWorker (@"+server+")->constructor() failed:\n\t"+e); System.out.println("BotSQLiteWorker (@"+server+")->constructor() failed:\n\t Connection to SQLite not established.");
this.consistent = false; // this.close(); this.consistent = false;
} }
} }
@ -161,11 +152,6 @@ public class WorkerSQLite implements Worker {
preparedStatement.setString(2, event); preparedStatement.setString(2, event);
preparedStatement.setString(3, initiator); preparedStatement.setString(3, initiator);
switch (event) { switch (event) {
case "NICK":
case "JOIN":
preparedStatement.setString(4, message);
preparedStatement.setString(5, null);
break;
case "PART": case "PART":
case "QUIT": case "QUIT":
case "TOPIC": case "TOPIC":
@ -184,6 +170,8 @@ public class WorkerSQLite implements Worker {
preparedStatement.setString(4, message.replaceAll("^:", "")); preparedStatement.setString(4, message.replaceAll("^:", ""));
preparedStatement.setString(5,null); preparedStatement.setString(5,null);
break; break;
case "NICK":
case "JOIN":
default: default:
preparedStatement.setString(4, message); preparedStatement.setString(4, message);
preparedStatement.setString(5,null); preparedStatement.setString(5,null);
@ -191,12 +179,9 @@ public class WorkerSQLite implements Worker {
} }
preparedStatement.executeUpdate(); preparedStatement.executeUpdate();
} }
catch (SQLException sqle){ catch (Exception e) {
System.out.println("BotSQLiteWorker (@"+ircServer+")->logAdd() failed:\n\t"+sqle); System.out.println("BotSQLiteWorker (@" + server + ")->logAdd() failed:\n\t" + e.getMessage());
this.close(); // consistent will become false. Don't touch this. this.close();
}catch (NullPointerException npe){
System.out.println("BotSQLiteWorker (@"+ircServer+")->logAdd() failed:\n\t"+npe);
this.consistent = false; // most likely closed/non-opened file
} }
return consistent; return consistent;
} }
@ -208,7 +193,7 @@ public class WorkerSQLite implements Worker {
this.connection.close(); this.connection.close();
} }
catch (SQLException | NullPointerException e){ //todo: consider redo catch (SQLException | NullPointerException e){ //todo: consider redo
System.out.println("BotSQLiteWorker (@"+ircServer+")->close() failed:\n\t" + e); // nothing to do here System.out.println("BotSQLiteWorker (@"+ server +")->close() failed:\n\t" + e); // nothing to do here
} }
this.consistent = false; this.consistent = false;
} }

View file

@ -1,38 +1,86 @@
package InnaIrcBot.config; package InnaIrcBot.config;
import InnaIrcBot.logging.SupportedLogDrivers; import InnaIrcBot.logging.SupportedLogDrivers;
import org.ini4j.Config;
import org.ini4j.Ini;
import org.ini4j.Wini;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
class ConfigurationFileTest { class ConfigurationFileTest {
ConfigurationFile config; ConfigurationFile config;
ConfigurationFileTest(){ ConfigurationFileTest() throws Exception{
config = new ConfigurationFile( File file = File.createTempFile("temp", "Ini");
null, /*
-100, List<String> logDriverPreferences = new ArrayList<>();
null, logDriverPreferences.add(System.getProperty("user.home"));
null,
null, List<String> channels = new ArrayList<>();
null, channels.add("#main");
null, channels.add("#lpr");
null,
null, Config myConfig = new Config();
null, myConfig.setFileEncoding(StandardCharsets.UTF_8);
true,
null, Wini ini = new Wini();
new String[]{null}, ini.setConfig(myConfig);
null,
null, Ini.Section mainSection = ini.add("main");
null mainSection.put( "server name", "srv");
); mainSection.put( "server port", 6667);
mainSection.put( "server password", "");
mainSection.put( "channels", channels); //mainSectionName,
mainSection.put( "nickname", "InnaIrcBot");
mainSection.put( "ident", "sweethome");
mainSection.put( "real name", "bot");
mainSection.put( "nickname password", "");
mainSection.put( "nickserv auth method", "freenode");
mainSection.put( "user modes", "i");
mainSection.put( "auto rejoin", true);
mainSection.put( "logging driver", "files");
mainSection.put( "logging driver prefs", logDriverPreferences);
mainSection.put( "bot administrator password", "i_pswd");
mainSection.put( "channels configuration path", "/tmp");
mainSection.put( "application logs", "/tmp");
ini.store(file);
*/
ConfigurationFileGenerator.generate(file.getAbsolutePath());
config = new ConfigurationFile(file.getAbsolutePath());
printAllConfigFields();
}
private String generateFile(){
return "";
}
private void printAllConfigFields(){
System.out.println();
System.out.println(config.getServerName());;
System.out.println(config.getServerPort());;
System.out.println(config.getServerPass());;
System.out.println(config.getUserNick());;
System.out.println(config.getUserIdent());;
System.out.println(config.getUserRealName());;
System.out.println(config.getUserNickPass());;
System.out.println(config.getUserNickAuthStyle());;
System.out.println(config.getUserMode());;
System.out.println(config.getRejoinOnKick());;
System.out.println(config.getBotAdministratorPassword());;
System.out.println(config.getApplicationLogDir());;
} }
@Test @Test
void getServerName() { void getServerName() {
} }
/*
@Test @Test
void getServerPort() { void getServerPort() {
} }
@ -93,4 +141,5 @@ class ConfigurationFileTest {
@Test @Test
void setUserNickAuthStyle() { void setUserNickAuthStyle() {
} }
*/
} }

View file

@ -110,20 +110,34 @@ class LogDriverTest {
} }
private void initializeFilesLogDriver(){ private void initializeFilesLogDriver(){
LogDriver.setLogDriver(serverNameFiles, new LogDriverConfiguration("FileS", new String[]{mainLogsDir.toString()}), ""); LogDriverConfiguration filesDrv = new LogDriverConfiguration("FileS",
mainLogsDir.toString(),
null,
null,
null,
null);
LogDriver.setLogDriver(serverNameFiles);
} }
private void initializeSQLiteLogDriver(){ private void initializeSQLiteLogDriver(){
LogDriver.setLogDriver(serverNameSQLite, new LogDriverConfiguration("SQliTe", new String[]{mainSQLiteLogsDir.toString()}), ""); LogDriverConfiguration sqliteDrv = new LogDriverConfiguration("SQliTe",
mainLogsDir.toString(),
null,
null,
null,
null);
LogDriver.setLogDriver(serverNameSQLite);
} }
private void initializeMongoDBLogDriver(){ private void initializeMongoDBLogDriver(){
String[] params = new String[]{"192.168.1.186:27017", LogDriverConfiguration mongoDrv = new LogDriverConfiguration("MongoDB",
"irc", null,
"loper", "192.168.1.186:27017",
"password"}; "irc",
"loper",
LogDriver.setLogDriver("irc.tomsk.net",new LogDriverConfiguration("MongoDB", params),""); "password");
LogDriver.setLogDriver("irc.tomsk.net");
} }
private void close(){ private void close(){