mirror of https://github.com/bvn13/JIrcBot.git
calculator bot implemented
parent
87d16a1fe4
commit
340a9296c7
|
@ -0,0 +1,21 @@
|
|||
package ru.bvn13.jircbot;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import ru.bvn13.jircbot.bot.JircBot;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@ComponentScan("ru.bvn13.jircbot")
|
||||
public class MainApp {
|
||||
|
||||
@Autowired
|
||||
private JircBot bot;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(MainApp.class, args);
|
||||
System.out.println("==============> STARTING <==============");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package ru.bvn13.jircbot.bot;
|
||||
|
||||
|
||||
import org.pircbotx.Configuration;
|
||||
import org.pircbotx.PircBotX;
|
||||
import org.pircbotx.UtilSSLSocketFactory;
|
||||
import org.pircbotx.cap.TLSCapHandler;
|
||||
import org.pircbotx.hooks.ListenerAdapter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import ru.bvn13.jircbot.config.JircBotConfiguration;
|
||||
import ru.bvn13.jircbot.listeners.CalculatorListener;
|
||||
import ru.bvn13.jircbot.listeners.TestListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@Component
|
||||
public class JircBot extends ListenerAdapter {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(JircBot.class);
|
||||
|
||||
|
||||
private JircBotConfiguration config;
|
||||
|
||||
private Map<String, PircBotX> bots = new HashMap<>();
|
||||
|
||||
|
||||
@Autowired
|
||||
public JircBot(JircBotConfiguration config) {
|
||||
this.config = config;
|
||||
this.start();
|
||||
}
|
||||
|
||||
|
||||
public void start() {
|
||||
|
||||
//Setup this bot
|
||||
Configuration.Builder templateConfig = new Configuration.Builder()
|
||||
.setLogin("JIrcBot") //login part of hostmask, eg name:login@host
|
||||
.setAutoNickChange(true) //Automatically change nick when the current one is in use
|
||||
.setCapEnabled(true) //Enable CAP features
|
||||
.addCapHandler(new TLSCapHandler(new UtilSSLSocketFactory().trustAllCertificates(), true));
|
||||
|
||||
this.config.getConnections().forEach(c -> {
|
||||
List<Configuration.ServerEntry> servers = new ArrayList<>();
|
||||
servers.add(new Configuration.ServerEntry(c.getServer(), c.getPort()));
|
||||
this.bots.put(
|
||||
String.format("%s/%s", c.getServer(), c.getChannelName()),
|
||||
new PircBotX(templateConfig
|
||||
.setName(c.getBotName())
|
||||
.addListener(new CalculatorListener()) //This class is a listener, so add it to the bots known listeners
|
||||
.setServers(servers)
|
||||
.setAutoReconnect(true)
|
||||
.addAutoJoinChannel(c.getChannelName()) //Join the official #pircbotx channel
|
||||
.buildForServer(c.getServer())
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
//bot.connect throws various exceptions for failures
|
||||
this.bots.forEach((id, b) -> {
|
||||
try {
|
||||
b.startBot();
|
||||
} catch (Exception ex) {
|
||||
logger.error("ERROR STARTING BOT: "+id);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package ru.bvn13.jircbot.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.bvn13.jircbot.model.Config;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
public class JircBotConfiguration {
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(JircBotConfiguration.class);
|
||||
|
||||
|
||||
@Value("${config}")
|
||||
private String configFileName;
|
||||
|
||||
@Getter
|
||||
private List<Config> connections = new ArrayList<>();
|
||||
|
||||
|
||||
@PostConstruct
|
||||
public void readConfigFile() {
|
||||
logger.debug("Start reading configuration file: "+this.configFileName);
|
||||
|
||||
JSONParser parser = new JSONParser();
|
||||
Reader reader = null;
|
||||
try {
|
||||
reader = new FileReader(this.configFileName);
|
||||
Object jsonObj = parser.parse(reader);
|
||||
JSONObject jsonObject = (JSONObject) jsonObj;
|
||||
|
||||
logger.debug("CONFIG VERSION: "+jsonObject.get("version"));
|
||||
|
||||
JSONArray settings = (JSONArray) jsonObject.get("connections");
|
||||
|
||||
Iterator<JSONObject> iterator = settings.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Config config = this.parseConfig(iterator.next());
|
||||
if (config.getEnabled())
|
||||
this.connections.add(config);
|
||||
}
|
||||
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
throw new InternalError("Config file not found: "+this.configFileName);
|
||||
} catch (ParseException e) {
|
||||
e.printStackTrace();
|
||||
throw new InternalError("Wrong config file format. JSON is expected.");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new InternalError("Config is not readable.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Config parseConfig(JSONObject data) {
|
||||
Config config = new Config();
|
||||
config.setEnabled((Boolean)data.get("enabled"));
|
||||
config.setServer((String)data.get("server"));
|
||||
config.setPort(Integer.parseInt(data.get("port").toString()));
|
||||
config.setChannelName((String)data.get("channelName"));
|
||||
config.setBotName((String)data.get("botName"));
|
||||
return config;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package ru.bvn13.jircbot.listeners;
|
||||
|
||||
import net.objecthunter.exp4j.Expression;
|
||||
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||
import org.pircbotx.hooks.ListenerAdapter;
|
||||
import org.pircbotx.hooks.WaitForQueue;
|
||||
import org.pircbotx.hooks.events.MessageEvent;
|
||||
import org.pircbotx.hooks.types.GenericMessageEvent;
|
||||
|
||||
|
||||
|
||||
public class CalculatorListener extends ListenerAdapter {
|
||||
|
||||
private static final String COMMAND = "?calc";
|
||||
|
||||
|
||||
@Override
|
||||
public void onGenericMessage(final GenericMessageEvent event) throws Exception {
|
||||
|
||||
if (event.getUser().getNick().equals(event.getBot().getNick())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.getMessage().startsWith(COMMAND)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String message = event.getMessage().replace(COMMAND, "").trim();
|
||||
String[] commands = message.split(" ", 2);
|
||||
|
||||
if (commands.length == 0 || commands[0].isEmpty() || commands[0].trim().equalsIgnoreCase("help")) {
|
||||
event.respond(this.helpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.checkComand(commands[0].trim())) {
|
||||
return;
|
||||
}
|
||||
|
||||
String expressionString = message;
|
||||
event.respond("EXPRESSION: "+expressionString);
|
||||
ExpressionBuilder expressionBuilder = new ExpressionBuilder(expressionString);
|
||||
Expression exp = null;
|
||||
|
||||
WaitForQueue queue = new WaitForQueue(event.getBot());
|
||||
while (true) {
|
||||
|
||||
MessageEvent currentEvent = queue.waitFor(MessageEvent.class);
|
||||
|
||||
if (currentEvent.getMessage().startsWith(COMMAND)) {
|
||||
message = currentEvent.getMessage().replace(COMMAND, "").trim();
|
||||
commands = message.split(" ", 2);
|
||||
if (commands.length == 0 || commands[0].isEmpty()) {
|
||||
currentEvent.respond("Command is expected.");
|
||||
currentEvent.respond(this.helpMessage());
|
||||
} else if (commands[0].trim().equalsIgnoreCase("vars")) {
|
||||
exp = expressionBuilder.variables(commands[1].trim()).build();
|
||||
currentEvent.respond("VARIABLES: "+commands[1].trim());
|
||||
} else if (commands[0].trim().equalsIgnoreCase("set")) {
|
||||
String[] variableData = commands[1].trim().split("=", 2);
|
||||
if (variableData.length < 2 || variableData[0].isEmpty() || variableData[1].isEmpty()) {
|
||||
currentEvent.respond("FORMAT: variable = value");
|
||||
} else {
|
||||
if (exp == null) {
|
||||
//currentEvent.respond("Variables are not set!");
|
||||
exp = expressionBuilder.build();
|
||||
} else {
|
||||
Double value = Double.parseDouble(variableData[1].trim());
|
||||
exp = exp.setVariable(variableData[0].trim(), value);
|
||||
currentEvent.respond(String.format("VARIABLE SET: %s = %f", variableData[0].trim(), value));
|
||||
}
|
||||
}
|
||||
} else if (commands[0].trim().equalsIgnoreCase("done")) {
|
||||
if (exp == null) {
|
||||
exp = expressionBuilder.build();
|
||||
}
|
||||
Double result = exp.evaluate();
|
||||
currentEvent.respond(String.format("%s = %f", expressionString, result));
|
||||
expressionBuilder = null;
|
||||
exp = null;
|
||||
queue.close();
|
||||
return;
|
||||
} else {
|
||||
currentEvent.respond(this.helpMessage());
|
||||
}
|
||||
} else {
|
||||
currentEvent.respond("Command must be started with: "+COMMAND);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Boolean checkComand(String command) {
|
||||
return command.equalsIgnoreCase("vars")
|
||||
|| command.equalsIgnoreCase("set")
|
||||
|| command.equalsIgnoreCase("done");
|
||||
}
|
||||
|
||||
private String helpMessage() {
|
||||
return "CALCULATOR (powered by Exp4J) | "+
|
||||
"Commands: | "+
|
||||
"vars - set variables names delimetered by comma, i.e.: a, b | "+
|
||||
"set - set variable, i.e.: a = 2 | "+
|
||||
"done - evaluate expression";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package ru.bvn13.jircbot.listeners;
|
||||
|
||||
import org.pircbotx.dcc.ReceiveChat;
|
||||
import org.pircbotx.hooks.ListenerAdapter;
|
||||
import org.pircbotx.hooks.WaitForQueue;
|
||||
import org.pircbotx.hooks.events.IncomingChatRequestEvent;
|
||||
import org.pircbotx.hooks.events.MessageEvent;
|
||||
import org.pircbotx.hooks.types.GenericMessageEvent;
|
||||
|
||||
public class TestListener extends ListenerAdapter {
|
||||
|
||||
@Override
|
||||
public void onGenericMessage(final GenericMessageEvent event) throws Exception {
|
||||
//Hello world
|
||||
//This way to handle commands is useful for listeners that listen for multiple commands
|
||||
if (event.getMessage().startsWith("?hello"))
|
||||
event.respond("Hello World!");
|
||||
|
||||
//If this isn't a waittest, ignore
|
||||
//This way to handle commands is useful for listers that only listen for one command
|
||||
if (!event.getMessage().startsWith("?waitTest start"))
|
||||
return;
|
||||
|
||||
//WaitTest has started
|
||||
event.respond("Started...");
|
||||
WaitForQueue queue = new WaitForQueue(event.getBot());
|
||||
//Infinate loop since we might recieve messages that aren't WaitTest's.
|
||||
while (true) {
|
||||
//Use the waitFor() method to wait for a MessageEvent.
|
||||
//This will block (wait) until a message event comes in, ignoring
|
||||
//everything else
|
||||
MessageEvent currentEvent = queue.waitFor(MessageEvent.class);
|
||||
//Check if this message is the "ping" command
|
||||
if (currentEvent.getMessage().startsWith("?waitTest ping"))
|
||||
event.respond("pong");
|
||||
//Check if this message is the "end" command
|
||||
else if (currentEvent.getMessage().startsWith("?waitTest end")) {
|
||||
event.respond("Stopping");
|
||||
queue.close();
|
||||
//Very important that we end the infinate loop or else the test
|
||||
//will continue forever!
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onIncomingChatRequest(IncomingChatRequestEvent event) throws Exception {
|
||||
//Accept the incoming chat request. If it fails it will throw an exception
|
||||
ReceiveChat chat = event.accept();
|
||||
//Read lines from the server
|
||||
String line;
|
||||
while ((line = chat.readLine()) != null)
|
||||
if (line.equalsIgnoreCase("done")) {
|
||||
//Shut down the chat
|
||||
chat.close();
|
||||
break;
|
||||
} else {
|
||||
//Fun example
|
||||
int lineLength = line.length();
|
||||
chat.sendLine("Line '" + line + "' contains " + lineLength + " characters");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package ru.bvn13.jircbot.model;
|
||||
|
||||
import com.sun.istack.internal.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Config {
|
||||
|
||||
@NotNull
|
||||
private Boolean enabled = false;
|
||||
|
||||
@NotNull
|
||||
private String server;
|
||||
|
||||
@NotNull
|
||||
private Integer port = 6667;
|
||||
|
||||
@NotNull
|
||||
private String botName;
|
||||
|
||||
private String channelName;
|
||||
|
||||
}
|
Loading…
Reference in New Issue