diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..e30701e --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + theoni.vkbot + vkbot + VkBot + 1.0 + + + + maven-shade-plugin + 2.1 + + + package + + shade + + + + + theoni.vkbot.Bot + + + + + + + + + + + org.projectlombok + lombok + 1.18.20 + provided + + + org.jetbrains + annotations + 24.0.0 + provided + + + + 17 + 17 + UTF-8 + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..af69e68 --- /dev/null +++ b/pom.xml @@ -0,0 +1,68 @@ + + + 4.0.0 + + theoni.vkbot + vkbot + 1.0 + jar + + VkBot + + + UTF-8 + 17 + 17 + + + + + org.projectlombok + lombok + 1.18.20 + provided + + + com.vk.api + sdk + 1.0.14 + + + org.yaml + snakeyaml + 1.21 + + + com.github.t9t.minecraft-rcon-client + minecraft-rcon-client + 1.0.0 + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 2.1 + + + package + + shade + + + + + theoni.vkbot.Bot + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/theoni/vkbot/Bot.java b/src/main/java/theoni/vkbot/Bot.java new file mode 100644 index 0000000..d39b4e5 --- /dev/null +++ b/src/main/java/theoni/vkbot/Bot.java @@ -0,0 +1,40 @@ +package theoni.vkbot; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class Bot { + + public static void main(String[] args) throws InterruptedException { + Path currentPath = Paths.get("").toAbsolutePath(); + String configPath = "/config.yml"; + File file = new File(currentPath.toString(), "config.yml"); + + if (!file.exists()) { + try { + + InputStream inputStream = Bot.class.getResourceAsStream(configPath); + OutputStream outputStream = new FileOutputStream(file); + + byte[] buffer = new byte[1024]; + int bytesRead; + while ((bytesRead = inputStream.read(buffer)) != -1) { + outputStream.write(buffer, 0, bytesRead); + } + + inputStream.close(); + outputStream.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + new BotHandler().startBot(); + } +} diff --git a/src/main/java/theoni/vkbot/BotHandler.java b/src/main/java/theoni/vkbot/BotHandler.java new file mode 100644 index 0000000..42b9855 --- /dev/null +++ b/src/main/java/theoni/vkbot/BotHandler.java @@ -0,0 +1,85 @@ +package theoni.vkbot; + +import com.vk.api.sdk.client.actors.GroupActor; +import com.vk.api.sdk.exceptions.ApiException; +import com.vk.api.sdk.exceptions.ClientException; +import com.vk.api.sdk.objects.messages.*; +import com.vk.api.sdk.queries.messages.MessagesGetLongPollHistoryQuery; + +import theoni.vkbot.managers.BotManager; +import theoni.vkbot.managers.ConfigManager; +import theoni.vkbot.utils.Keyboards; +import theoni.vkbot.utils.Rcon; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +public class BotHandler { + + private ConfigManager config; + private List rconUsers = new ArrayList<>(); + + public BotHandler() { + this.config = new ConfigManager(new File("config.yml")); + } + + public void startBot() { + + Thread thread = new Thread(new Runnable() { + + public void run() { + + GroupActor actor = new GroupActor(config.getInt("groupId"), config.getString("token")); + BotManager manager = new BotManager(actor); + + Integer ts = manager.getTs(); + + while (true){ + try { + + MessagesGetLongPollHistoryQuery historyQuery = manager.getHistoryQuery(ts); + List messages = historyQuery.execute().getMessages().getItems(); + + if (!messages.isEmpty()){ + messages.forEach(message -> { + + String text = message.getText().replace("/", ""); + + if (text.equalsIgnoreCase("Начать")){ + manager.sendMessage(Messages.START.getText(), message, Keyboards.rconKeyboard()); + } + + else if (text.equalsIgnoreCase("Rcon")){ + if (config.getList("allowed-users").contains(message.getFromId())) { + if (config.getList("fast-commands").size() != 0) { + manager.sendMessage(Messages.RCON_WITH_COMMANDS.getText(), message, Keyboards.commandsKeyboard()); + } else { + manager.sendMessage(Messages.RCON.getText(), message, Keyboards.commandsKeyboard()); + } + rconUsers.add(message.getFromId()); + } + } + + else if (rconUsers.contains(message.getFromId())) { + if (config.getList("blocked-commands").contains(text)) { + manager.sendMessage(Messages.COMMAND_BLOCKED.getText(), message); + return; + } + manager.sendMessage("Команда отправлена.\nОтвет сервера: " + Rcon.command(text), message); + } + }); + } + + ts = manager.getTs(); + Thread.sleep(500); + + } catch (InterruptedException | ClientException | ApiException e) { + e.printStackTrace(); + } + } + } + }); + thread.start(); + } +} diff --git a/src/main/java/theoni/vkbot/Messages.java b/src/main/java/theoni/vkbot/Messages.java new file mode 100644 index 0000000..5d2fdb7 --- /dev/null +++ b/src/main/java/theoni/vkbot/Messages.java @@ -0,0 +1,17 @@ +package theoni.vkbot; + +import lombok.Getter; + +public enum Messages { + START("Введите Rcon или используйте кнопку ниже."), + RCON("Ведите команду для отправки на сервер."), + RCON_WITH_COMMANDS("Ведите команду для отправки на сервер.\n\nБыстрые команды:"), + COMMAND_BLOCKED("Данная команда заблокирована."); + + @Getter private String text; + + Messages(String text) { + this.text = text; + } + +} diff --git a/src/main/java/theoni/vkbot/managers/BotManager.java b/src/main/java/theoni/vkbot/managers/BotManager.java new file mode 100644 index 0000000..d0129f9 --- /dev/null +++ b/src/main/java/theoni/vkbot/managers/BotManager.java @@ -0,0 +1,71 @@ +package theoni.vkbot.managers; + +import java.util.Random; +import com.vk.api.sdk.client.VkApiClient; +import com.vk.api.sdk.client.actors.GroupActor; +import com.vk.api.sdk.exceptions.ApiException; +import com.vk.api.sdk.exceptions.ClientException; +import com.vk.api.sdk.httpclient.HttpTransportClient; +import com.vk.api.sdk.objects.messages.*; +import com.vk.api.sdk.queries.messages.MessagesGetLongPollHistoryQuery; + +public class BotManager { + + private VkApiClient vk; + private GroupActor actor; + private Random random; + + public BotManager(GroupActor actor) { + this.vk = new VkApiClient(new HttpTransportClient()); + this.actor = actor; + this.random = new Random(); + } + + public void sendMessage(String text, Message message, Keyboard keyboard) { + try { + vk.messages().send(actor).message(text).userId(message.getFromId()).randomId(random.nextInt(10000)).keyboard(keyboard).execute(); + } catch (ApiException | ClientException e) { + e.printStackTrace(); + } + } + + public void sendMessage(String text, Message message) { + try { + vk.messages().send(actor).message(text).userId(message.getFromId()).randomId(random.nextInt(10000)).execute(); + } catch (ApiException | ClientException e) { + e.printStackTrace(); + } + } + + public void sendMessage(String text, Integer id, Keyboard keyboard) { + try { + vk.messages().send(actor).message(text).userId(id).randomId(random.nextInt(10000)).keyboard(keyboard).execute(); + } catch (ApiException | ClientException e) { + e.printStackTrace(); + } + } + + public void sendMessage(String text, Integer id) { + try { + vk.messages().send(actor).message(text).userId(id).randomId(random.nextInt(10000)).execute(); + } catch (ApiException | ClientException e) { + e.printStackTrace(); + } + } + + public Integer getTs() { + try { + Integer ts = vk.messages().getLongPollServer(actor).execute().getTs(); + return ts; + } catch (ApiException | ClientException e) { + e.printStackTrace(); + } + return 0; + } + + public MessagesGetLongPollHistoryQuery getHistoryQuery(Integer ts) { + MessagesGetLongPollHistoryQuery historyQuery = vk.messages().getLongPollHistory(actor).ts(ts); + return historyQuery; + } + +} diff --git a/src/main/java/theoni/vkbot/managers/ConfigManager.java b/src/main/java/theoni/vkbot/managers/ConfigManager.java new file mode 100644 index 0000000..8495924 --- /dev/null +++ b/src/main/java/theoni/vkbot/managers/ConfigManager.java @@ -0,0 +1,47 @@ +package theoni.vkbot.managers; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.List; +import java.util.Map; + +import org.yaml.snakeyaml.Yaml; + +public class ConfigManager { + + private Yaml yaml; + private Map config; + + public ConfigManager(File configFile) { + try { + this.yaml = new Yaml(); + this.config = yaml.load(new FileInputStream(configFile)); + } catch(FileNotFoundException e) {} + } + + public String getString(String key) { + return (String) getValue(key); + } + + public int getInt(String key) { + return (int) getValue(key); + } + + public boolean getBoolean(String key) { + return (boolean) getValue(key); + } + + public List getList(String key) { + return (List) getValue(key); + } + + private Object getValue(String key) { + String[] keys = key.split("\\."); + Map value = config; + for (int i = 0; i < keys.length - 1; i++) { + value = (Map) value.get(keys[i]); + } + return value.get(keys[keys.length - 1]); + } +} \ No newline at end of file diff --git a/src/main/java/theoni/vkbot/utils/Keyboards.java b/src/main/java/theoni/vkbot/utils/Keyboards.java new file mode 100644 index 0000000..50e7c64 --- /dev/null +++ b/src/main/java/theoni/vkbot/utils/Keyboards.java @@ -0,0 +1,55 @@ +package theoni.vkbot.utils; + +import com.vk.api.sdk.objects.messages.Keyboard; +import com.vk.api.sdk.objects.messages.KeyboardButton; +import com.vk.api.sdk.objects.messages.KeyboardButtonAction; +import com.vk.api.sdk.objects.messages.KeyboardButtonColor; +import com.vk.api.sdk.objects.messages.TemplateActionTypeNames; + +import theoni.vkbot.managers.ConfigManager; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Keyboards { + + public static Keyboard rconKeyboard() { + Keyboard keyboard = new Keyboard(); + + keyboard.setButtons(Arrays.asList( + Arrays.asList( + new KeyboardButton() + .setColor(KeyboardButtonColor.POSITIVE) + .setAction(new KeyboardButtonAction() + .setLabel("Rcon") + .setType(TemplateActionTypeNames.TEXT)) + ) + )); + keyboard.setInline(true); + + return keyboard; + } + + public static Keyboard commandsKeyboard() { + Keyboard keyboard = new Keyboard(); + ConfigManager config = new ConfigManager(new File("config.yml")); + + List list = new ArrayList<>(); + for (Object command : config.getList("fast-commands")) { + list.add( + new KeyboardButton() + .setColor(KeyboardButtonColor.POSITIVE) + .setAction(new KeyboardButtonAction() + .setLabel("/" + command) + .setType(TemplateActionTypeNames.TEXT)) + ); + } + + keyboard.setButtons(Arrays.asList(list)); + keyboard.setInline(true); + + return keyboard; + } +} diff --git a/src/main/java/theoni/vkbot/utils/Rcon.java b/src/main/java/theoni/vkbot/utils/Rcon.java new file mode 100644 index 0000000..873fcae --- /dev/null +++ b/src/main/java/theoni/vkbot/utils/Rcon.java @@ -0,0 +1,21 @@ +package theoni.vkbot.utils; + +import java.io.File; + +import com.github.t9t.minecraftrconclient.RconClient; +import com.github.t9t.minecraftrconclient.RconClientException; + +import theoni.vkbot.managers.ConfigManager; + +public class Rcon { + + public static String command(String name) { + ConfigManager config = new ConfigManager(new File("config.yml")); + try { + RconClient client = RconClient.open(config.getString("rcon.host"), config.getInt("rcon.port"), config.getString("rcon.password")); + return client.sendCommand(name); + } catch(RconClientException e) {} + return ""; + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..d7e9d7d --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,20 @@ +groupId: 123 # ID группы вк +token: "" # Токен группы ВК + +rcon: + host: "localhost" # Адрес RCON + port: 19132 # Порт RCON + password: "5YzNmYjUyM" # Пароль RCON + +allowed-users: + - 1 # Цифровые ID + +# Быстрые команды, будут отображатся при вводе Rcon +fast-commands: + - "ver" + - "status" + - "stop" + +# Заблокированные команды +blocked-commands: + - "stop" \ No newline at end of file