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