Files
chomens-bot-java/src/main/java/me/chayapak1/chomens_bot/plugins/IRCPlugin.java
2024-11-12 16:43:45 +07:00

239 lines
7.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package me.chayapak1.chomens_bot.plugins;
import me.chayapak1.chomens_bot.Bot;
import me.chayapak1.chomens_bot.Configuration;
import me.chayapak1.chomens_bot.Main;
import me.chayapak1.chomens_bot.command.IRCCommandContext;
import me.chayapak1.chomens_bot.util.ColorUtilities;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent;
import org.pircbotx.PircBotX;
import org.pircbotx.User;
import org.pircbotx.cap.SASLCapHandler;
import org.pircbotx.hooks.ListenerAdapter;
import org.pircbotx.hooks.events.MessageEvent;
import javax.net.ssl.SSLSocketFactory;
import java.util.*;
import java.util.concurrent.TimeUnit;
public class IRCPlugin extends ListenerAdapter {
private final Configuration.IRC ircConfig;
private final Map<String, String> servers;
public final Map<String, List<String>> messageQueue = new HashMap<>();
private PircBotX bot;
public IRCPlugin (Configuration config) {
this.ircConfig = config.irc;
this.servers = ircConfig.servers;
if (!ircConfig.enabled) return;
final org.pircbotx.Configuration.Builder builder = new org.pircbotx.Configuration.Builder()
.setName(ircConfig.name)
.setLogin("bot@chomens-bot")
.addServer(ircConfig.host, ircConfig.port)
.setSocketFactory(SSLSocketFactory.getDefault())
.setAutoReconnect(true)
.addListener(this);
if (!ircConfig.password.isEmpty()) builder.addCapHandler(new SASLCapHandler(ircConfig.name, ircConfig.password, true));
for (Map.Entry<String, String> entry : ircConfig.servers.entrySet()) builder.addAutoJoinChannel(entry.getValue());
final org.pircbotx.Configuration configuration = builder.buildConfiguration();
bot = new PircBotX(configuration);
new Thread(() -> {
try {
bot.startBot();
} catch (Exception e) {
e.printStackTrace();
}
}).start();
for (Bot bot : Main.bots) {
bot.addListener(new Bot.Listener() {
@Override
public void connected(ConnectedEvent event) {
IRCPlugin.this.connected(bot);
}
@Override
public void loadedPlugins() {
bot.chat.addListener(new ChatPlugin.Listener() {
@Override
public boolean systemMessageReceived(Component component, String string, String ansi) {
IRCPlugin.this.systemMessageReceived(bot, ansi);
return true;
}
});
}
});
bot.irc = this;
}
Main.executor.scheduleAtFixedRate(this::queueTick, 0, 500, TimeUnit.MILLISECONDS);
}
@Override
public void onMessage(MessageEvent event) {
Bot serverBot = null;
String targetChannel = null;
for (Map.Entry<String, String> entry : servers.entrySet()) {
if (entry.getValue().equals(event.getChannel().getName())) {
serverBot = Main.bots.stream()
.filter(eachBot -> entry.getKey().equals(eachBot.host + ":" + eachBot.port))
.findFirst()
.orElse(null);
targetChannel = entry.getValue();
break;
}
}
if (serverBot == null) return;
final String commandPrefix = ircConfig.prefix;
final User user = event.getUser();
if (user == null) return;
final String name = user.getRealName().isBlank() ? user.getNick() : user.getRealName();
final String message = event.getMessage();
if (message.startsWith(commandPrefix)) {
final String noPrefix = message.substring(commandPrefix.length());
final IRCCommandContext context = new IRCCommandContext(serverBot, commandPrefix, name);
final Component output = serverBot.commandHandler.executeCommand(noPrefix, context, null);
if (output != null) context.sendOutput(output);
return;
}
final Component prefix = Component
.text(targetChannel)
.hoverEvent(
HoverEvent.showText(
Component
.empty()
.append(Component.text("on "))
.append(Component.text(ircConfig.host))
.append(Component.text(":"))
.append(Component.text(ircConfig.port))
.color(NamedTextColor.GRAY)
)
)
.color(NamedTextColor.BLUE);
final Component username = Component
.text(name)
.hoverEvent(HoverEvent.showText(Component.text(event.getUser().getHostname()).color(NamedTextColor.RED)))
.color(NamedTextColor.RED);
final Component messageComponent = Component
.text(message)
.color(NamedTextColor.GRAY);
final Component component = Component.translatable(
"[%s] %s %s",
prefix,
username,
messageComponent
).color(NamedTextColor.DARK_GRAY);
serverBot.chat.tellraw(component);
}
private void systemMessageReceived (Bot bot, String ansi) {
sendMessage(
bot,
ansi
);
}
public void quit (String reason) {
if (bot.isConnected()) bot.sendIRC().quitServer(reason);
}
private void connected (Bot bot) {
sendMessage(
bot,
String.format(
"Successfully connected to: %s:%s",
bot.host,
bot.port
)
);
}
private void queueTick () {
if (!bot.isConnected() || messageQueue.isEmpty()) return;
try {
final Map<String, List<String>> clonedMap = new HashMap<>(messageQueue);
for (Map.Entry<String, List<String>> entry : clonedMap.entrySet()) {
final List<String> logs = entry.getValue();
if (logs.isEmpty()) continue;
final String firstLog = logs.get(0);
logs.remove(0);
final String withIRCColors = ColorUtilities.convertAnsiToIrc(firstLog);
bot.sendIRC().message(entry.getKey(), withIRCColors);
}
} catch (Exception ignored) {}
}
private void addMessageToQueue (Bot bot, String message) {
final String channel = servers.get(bot.host + ":" + bot.port);
addMessageToQueue(channel, message);
}
private void addMessageToQueue (String channel, String message) {
final List<String> split = new ArrayList<>(Arrays.asList(message.split("\n")));
if (!messageQueue.containsKey(channel)) {
messageQueue.put(channel, split);
} else {
if (messageQueue.get(channel).size() > 10) return;
messageQueue.get(channel).addAll(split);
}
}
public void sendMessage (Bot bot, String message) {
final String hostAndPort = bot.host + ":" + bot.port;
final String channel = servers.get(hostAndPort);
if (channel == null) {
bot.logger.error("Channel is not configured for " + hostAndPort);
return;
}
addMessageToQueue(channel, message);
}
}