Начинающий
- Статус
- Оффлайн
- Регистрация
- 6 Дек 2023
- Сообщения
- 522
- Реакции
- 3
- Выберите загрузчик игры
- Vanilla
- Forge
- Fabric
- NeoForge
- OptiFine
- ForgeOptiFine
- Прочие моды
Всем привет! Сливаю телеграм апи, которое писал еще год назад.
Вкратце расскажу что это:
Телеграм апи - система, позволяющая управлять клиентом майнкрафта через телеграм-бота.
Для нее нужна библиотека telegrambots-java, скачать тут -
Стартер апи
Хранилище API-Ключа
Хандлер сообщений внутри бота
Хандлер команд для бота(пока-что есть пару команд, но думаю, что вы сами сможете дописать то, что нужно вам)
Вспомогательный класс для получения баланса
Как инициализировать?
В главном классе вашего проекта
Команда для установки или сброса ключа
Хранилище апи-ключа
Вроде все, есть вопросы - пишите.
Вкратце расскажу что это:
Телеграм апи - система, позволяющая управлять клиентом майнкрафта через телеграм-бота.
Для нее нужна библиотека telegrambots-java, скачать тут -
Пожалуйста, авторизуйтесь для просмотра ссылки.
Стартер апи
Java:
public class TelegramBotStarter {
public static void startBot() {
if (!TelegramApiKeyStorage.isApiKeySet()) {
return;
}
try {
TelegramBotsApi botsApi = new TelegramBotsApi(DefaultBotSession.class);
botsApi.registerBot(new TelegramBotHandler());
} catch (TelegramApiException e) {
}
}
}
Хранилище API-Ключа
Java:
public class TelegramApiKeyStorage {
private static String apiKey = "";
public static void setApiKey(String key) {
apiKey = key;
}
public static String getApiKey() {
return apiKey;
}
public static boolean isApiKeySet() {
return !apiKey.isEmpty();
}
}
Хандлер сообщений внутри бота
Java:
package ru.moyten.telegram.api;
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
import org.telegram.telegrambots.meta.api.objects.Update;
public class TelegramBotHandler extends TelegramLongPollingBot {
@Override
public void onUpdateReceived(Update update) {
if (update.hasMessage() && update.getMessage().hasText()) {
String messageText = update.getMessage().getText();
long chatId = update.getMessage().getChatId();
TelegramCommandHandler.handleCommand(messageText, chatId, this);
}
}
@Override
public String getBotUsername() {
return "bot";
}
@Override
public String getBotToken() {
return TelegramApiKeyStorage.getApiKey();
}
}
Хандлер команд для бота(пока-что есть пару команд, но думаю, что вы сами сможете дописать то, что нужно вам)
Java:
package ru.moyten.telegram.api;
import fgnepasti.wonderful.Wonderful;
import fgnepasti.wonderful.events.EventPacket;
import fgnepasti.wonderful.functions.api.Function;
import com.google.common.eventbus.Subscribe;
import fgnepasti.wonderful.utils.client.BetaAccess;
import fgnepasti.wonderful.utils.client.ClientUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.play.client.CConfirmTransactionPacket;
import net.minecraft.network.play.server.SChatPacket;
import net.minecraft.network.play.server.SConfirmTransactionPacket;
import net.minecraft.util.ScreenShotHelper;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
import org.telegram.telegrambots.meta.api.methods.send.SendPhoto;
import org.telegram.telegrambots.meta.api.objects.InputFile;
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
import java.io.File;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static fgnepasti.wonderful.utils.client.IMinecraft.mc;
public class TelegramCommandHandler {
private final Pattern balPattern = Pattern.compile(".*баланс.*\\$([\\d,]+\\.[\\d]{2})");
private final Pattern balPatternFt = Pattern.compile(".*баланс:.*\\$([\\d,]+\\.[\\d]{2})");
private static final Map<Long, TelegramContext> activeContexts = new ConcurrentHashMap<>();
public static void handleCommand(String message, long chatId, TelegramBotHandler bot) {
if (message.startsWith("/help")) {
StringBuilder builder = new StringBuilder("Помощь по командам\n");
builder.append("/info - Узнать информацию о текущей сессии\n")
.append("/command - Исполнить команду\n")
.append("/command /bal - Узнать баланс игрока(FunTime/Spooky)\n")
.append("/inventory - Получить информацию о инвентаре\n")
.append("/screenshot - Сделать скриншот экрана\n")
.append("/shutdown - Выключить майнкрафт");
sendResponse(bot,chatId, builder.toString());
} else if (message.startsWith("/info")) {
if (mc.player == null) {
sendResponse(bot, chatId, "Игрока нет =(");
return;
}
String playerPos = "X: " + (int) mc.player.getPosX() + " Y: " + (int) mc.player.getPosY() + " Z: " + (int) mc.player.getPosZ();
String server = ((mc.getCurrentServerData() != null && mc.getCurrentServerData().serverIP != null) ? mc.getCurrentServerData().serverIP : "оффлайн");
String anarchy = getAnarchyServerNumber() == -1 ? "Неизвестно" : String.valueOf(getAnarchyServerNumber());
sendResponse(bot, chatId, "Игрок: " + mc.session.getUsername() + "\nПозиция: " + playerPos + "\n" +
"Сервер: " + server + "\n" + "Анархия: " + anarchy);
}
else if (message.startsWith("/command ")) {
String command = message.substring("/command ".length());
if (command.startsWith("/")) {
mc.player.sendChatMessage(command);
if (command.contains("/bal")) {
TelegramContext context = activeContexts.computeIfAbsent(chatId, id -> new TelegramContext(bot, chatId));
context.waitingForBalance = true;
context.lastBalanceResult = null;
sendResponse(bot, chatId, "Получаю информацию о балансе...");
} else {
sendResponse(bot, chatId, "Отправил команду: " + command);
}
} else {
sendResponse(bot,chatId, "Сообщение не является командой");
}
} else if (message.startsWith("/toggle ")) {
String func = message.substring("/toggle ".length());
for (Function f : Wonderful.getInstance().getFunctionRegistry().getFunctions()) {
if (f.getName().toLowerCase().equals(func)) {
f.setState(!f.isState());
sendResponse(bot,chatId, "Состояние функции было изменено на \"" + (f.isState() ? "Включено" : "Выключено") + "\"");
}
}
} else if (message.startsWith("/inventory")) {
if (mc.player == null) {
sendResponse(bot,chatId, "Игрока чучут нет =(");
return;
}
StringBuilder builder = new StringBuilder("Инвентарь:\n");
for (int i = 0; i < mc.player.inventory.getSizeInventory(); i++) {
ItemStack itemStack = mc.player.inventory.getStackInSlot(i);
if (itemStack.getItem() != Items.AIR) {
builder.append(itemStack.getDisplayName().getString()).append(" Кол-во: ").append(itemStack.getCount()).append("\n");
}
}
if (builder.length() > "Инвентарь:\n".length()) {
sendResponse(bot, chatId, builder.toString());
} else {
sendResponse(bot, chatId, "Инвентарь пуст");
}
} else if (message.startsWith("/screenshot")) {
long time = System.currentTimeMillis();
File screenshotsDir = new File(mc.gameDir, "screenshots");
ScreenShotHelper.saveScreenshot(
mc.gameDir,
mc.getMainWindow().getFramebufferWidth(),
mc.getMainWindow().getFramebufferHeight(),
mc.getFramebuffer(),
(messagee) -> mc.execute(() -> {
new Thread(() -> {
try {
File latest = null;
for (int i = 0; i < 30; i++) {
latest = findLastScreenshot(screenshotsDir, time);
if (latest != null) break;
Thread.sleep(100);
}
if (latest != null) {
sendPhoto(bot, chatId, latest);
} else {
sendResponse(bot, chatId, "Скриншот не найден");
}
} catch (Exception e) {
e.printStackTrace();
}
}).start();
})
);
} else if (message.startsWith("/shutdown")) {
mc.shutdownMinecraftApplet();
}
}
private static File findLastScreenshot(File screenshotsDir, long createdAfter) {
File[] files = screenshotsDir.listFiles((dir, name) -> name.toLowerCase().endsWith(".png") && new File(dir, name).lastModified() > createdAfter);
if (files == null || files.length == 0) return null;
return Arrays.stream(files).max(Comparator.comparingLong(File::lastModified)).orElse(null);
}
private static int getAnarchyServerNumber() {
if (mc.ingameGUI.getTabList().header != null) {
String serverHeader = TextFormatting.getTextWithoutFormattingCodes(mc.ingameGUI.getTabList().header.getString());
if (serverHeader != null && serverHeader.contains("Анархия-")) {
return Integer.parseInt(serverHeader.split("Анархия-")[1].trim());
}
}
return -1;
}
private static void sendResponse(TelegramBotHandler bot, long chatId, String text) {
SendMessage message = new SendMessage();
message.setChatId(String.valueOf(chatId));
message.setText(text);
try {
bot.execute(message);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
private static void sendPhoto(TelegramBotHandler bot, long chatId, File photoo) {
SendPhoto photo = new SendPhoto();
photo.setChatId(String.valueOf(chatId));
photo.setPhoto(new InputFile(photoo));
photo.setCaption("Скриншот игры:");
try {
bot.execute(photo);
} catch (TelegramApiException e) {
e.printStackTrace();
}
}
@Subscribe
public void onEvent(EventPacket e) {
if (!(e.getPacket() instanceof SChatPacket)) return;
String raw = ((SChatPacket) e.getPacket()).getChatComponent().getString();
activeContexts.forEach((chatId, context) -> {
if (context.waitingForBalance && raw.contains("баланс")) {
Matcher matcher = balPatternFt.matcher(raw);
if (ClientUtil.onServer("spooky"))
matcher = balPattern.matcher(raw);
if (matcher.find()) {
String balance = matcher.group(1);
context.lastBalanceResult = "Ваш баланс: $" + balance;
context.waitingForBalance = false;
sendResponse(context.bot, context.chatId, context.lastBalanceResult);
activeContexts.remove(chatId);
}
}
});
}
}
Вспомогательный класс для получения баланса
Java:
public class TelegramContext {
public final TelegramBotHandler bot;
public final long chatId;
public String lastBalanceResult;
public boolean waitingForBalance;
public TelegramContext(TelegramBotHandler bot, long chatId) {
this.bot = bot;
this.chatId = chatId;
}
}
Как инициализировать?
В главном классе вашего проекта
Java:
if (TelegramApiKeyStorage.isApiKeySet()) {
new Thread(() -> {
try {
Thread.sleep(2000);
TelegramBotStarter.startBot();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
eventBus.register(new TelegramCommandHandler()); // эта строчка может отличаться в зависимости от вашей системы ивентов, тут мы добавляем TelegramCommandHandler в список листенеров для ивентов
Команда для установки или сброса ключа
Java:
public class TgApiCommand implements Command {
final Logger logger;
final ApiManager manager;
@Override
public void execute(Parameters parameters) {
String keyParam = parameters.asString(0).orElse("");
if (keyParam.isEmpty()) {
logger.log("Укажите аргументы для использования команды");
}
switch (keyParam) {
case "unlink" -> {
TelegramApiKeyStorage.setApiKey("");
logger.log("Отвязали ключ от игры");
}
default -> {
if (keyParam.isEmpty()) {
logger.log("Укажите ключ");
return;
}
manager.updateKey(keyParam);
TelegramApiKeyStorage.setApiKey(keyParam);
logger.log("Ключ установлен на: " + keyParam);
new Thread(() -> {
try {
Thread.sleep(1000);
TelegramBotStarter.startBot();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
}
@Override
public String name() {
return "tgapi";
}
@Override
public String description() {
return "Команда для подключения клиента к телеграму";
}
}
Хранилище апи-ключа
Java:
public class ApiManager {
@Getter
private static String currentKey;
private static final File keyFile = new File(mc.gameDir, separator + "\\assets\\skins\\bb" + separator + "files" + separator + "key.cfg");
@SneakyThrows
public static void load() {
loadKey();
}
@SneakyThrows
public static void loadKey() {
if (!keyFile.exists()) {
currentKey = "";
save();
return;
}
currentKey = Files.readString(keyFile.toPath()).trim();
if (!currentKey.isEmpty()) {
TelegramApiKeyStorage.setApiKey(currentKey);
new Thread(() -> {
try {
Thread.sleep(1000);
TelegramBotStarter.startBot();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}).start();
}
}
public static void updateKey(String newKey) {
currentKey = newKey;
save();
}
@SneakyThrows
private static void save() {
Files.writeString(keyFile.toPath(), currentKey, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
}
@SneakyThrows
public static void refreshKey() {
String newKey = Files.readString(keyFile.toPath()).trim();
if (!newKey.equals(currentKey)) {
currentKey = newKey;
}
}
}
Вроде все, есть вопросы - пишите.
