Compare commits
No commits in common. "aebff1a12ad6f39e2489075ff868d4f159d888fc" and "d1955da8137496da548071fe97fcf8d7119e8b0e" have entirely different histories.
aebff1a12a
...
d1955da813
1 changed files with 38 additions and 254 deletions
|
@ -4,25 +4,19 @@ import com.google.common.collect.ImmutableList;
|
||||||
import com.pengrad.telegrambot.Callback;
|
import com.pengrad.telegrambot.Callback;
|
||||||
import com.pengrad.telegrambot.TelegramBot;
|
import com.pengrad.telegrambot.TelegramBot;
|
||||||
import com.pengrad.telegrambot.UpdatesListener;
|
import com.pengrad.telegrambot.UpdatesListener;
|
||||||
import com.pengrad.telegrambot.model.Message;
|
|
||||||
import com.pengrad.telegrambot.model.Update;
|
import com.pengrad.telegrambot.model.Update;
|
||||||
import com.pengrad.telegrambot.model.User;
|
import com.pengrad.telegrambot.model.User;
|
||||||
import com.pengrad.telegrambot.request.EditMessageText;
|
|
||||||
import com.pengrad.telegrambot.request.SendMessage;
|
import com.pengrad.telegrambot.request.SendMessage;
|
||||||
import com.pengrad.telegrambot.response.BaseResponse;
|
|
||||||
import com.pengrad.telegrambot.response.SendResponse;
|
import com.pengrad.telegrambot.response.SendResponse;
|
||||||
import com.velocitypowered.api.event.Subscribe;
|
import com.velocitypowered.api.event.Subscribe;
|
||||||
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
import com.velocitypowered.api.event.connection.DisconnectEvent;
|
||||||
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
import com.velocitypowered.api.event.player.ServerConnectedEvent;
|
||||||
import com.velocitypowered.api.event.player.ServerPostConnectEvent;
|
|
||||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||||
import com.velocitypowered.api.proxy.Player;
|
import com.velocitypowered.api.proxy.Player;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
import com.velocitypowered.api.proxy.server.RegisteredServer;
|
||||||
import de.strifel.VTools.VTools;
|
import de.strifel.VTools.VTools;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -33,8 +27,6 @@ import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
|
||||||
import java.util.function.BiConsumer;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TGBridge {
|
public class TGBridge {
|
||||||
|
@ -44,14 +36,11 @@ public class TGBridge {
|
||||||
|
|
||||||
private TelegramBot bot;
|
private TelegramBot bot;
|
||||||
private String TOKEN = "";
|
private String TOKEN = "";
|
||||||
private long BOT_ID = -1;
|
|
||||||
private long CHAT_ID = 0L;
|
private long CHAT_ID = 0L;
|
||||||
|
|
||||||
private int ONLINE_STATUS_MESSAGE_ID = -1;
|
|
||||||
|
|
||||||
private long backoffSec = 1L;
|
private long backoffSec = 1L;
|
||||||
|
|
||||||
public TGBridge(@NotNull VTools plugin) {
|
public TGBridge(VTools plugin) {
|
||||||
INSTANCE = this;
|
INSTANCE = this;
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.server = plugin.getServer();
|
this.server = plugin.getServer();
|
||||||
|
@ -60,7 +49,6 @@ public class TGBridge {
|
||||||
public void register() {
|
public void register() {
|
||||||
server.getEventManager().register(plugin, this);
|
server.getEventManager().register(plugin, this);
|
||||||
botInit();
|
botInit();
|
||||||
initUpdateThread();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadConfig() {
|
private void loadConfig() {
|
||||||
|
@ -79,7 +67,6 @@ public class TGBridge {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
this.CHAT_ID = Long.parseLong(config.getOrDefault("chat_id", "0"));
|
this.CHAT_ID = Long.parseLong(config.getOrDefault("chat_id", "0"));
|
||||||
this.TOKEN = config.getOrDefault("token", "");
|
this.TOKEN = config.getOrDefault("token", "");
|
||||||
this.BOT_ID = Long.parseLong(TOKEN.split(":")[0]);
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
plugin.logger.error("parsing config", e);
|
plugin.logger.error("parsing config", e);
|
||||||
|
@ -95,54 +82,51 @@ public class TGBridge {
|
||||||
for (Update update : updates) {
|
for (Update update : updates) {
|
||||||
try {
|
try {
|
||||||
if (update != null &&
|
if (update != null &&
|
||||||
update.message() != null &&
|
update.message() != null &&
|
||||||
update.message().chat() != null &&
|
update.message().chat() != null &&
|
||||||
update.message().chat().id() == CHAT_ID &&
|
update.message().chat().id() == CHAT_ID &&
|
||||||
update.message().from() != null
|
update.message().from() != null
|
||||||
) {
|
) {
|
||||||
if (update.message().text() != null && !update.message().text().isEmpty()) {
|
if (update.message().text() != null && !update.message().text().isEmpty()) {
|
||||||
String msg = update.message().text();
|
String msg = update.message().text();
|
||||||
switch (msg) {
|
if (msg.equals("/list")) {
|
||||||
case "/list":
|
ArrayList<String> out = new ArrayList<>();
|
||||||
outbound(genOnlineStatus());
|
String fmt = server.getAllPlayers().size() > 1 ? "%d players are currently connected to the proxy." : "%d player is currently connected to the proxy.";
|
||||||
break;
|
out.add(String.format(fmt, server.getAllPlayers().size()));
|
||||||
case "/setpin":
|
List<RegisteredServer> servers = new ArrayList<>(server.getAllServers());
|
||||||
Message replyTo = update.message().replyToMessage();
|
for (RegisteredServer server : servers) {
|
||||||
if (replyTo == null || replyTo.from() == null || replyTo.from().id() != BOT_ID) {
|
List<Player> onServer = ImmutableList.copyOf(server.getPlayersConnected());
|
||||||
outbound("must reply a message that from the bot");
|
if (!onServer.isEmpty()) {
|
||||||
} else {
|
out.add(String.format("[%s] (%d): %s",
|
||||||
int messageId = replyTo.messageId();
|
server.getServerInfo().getName(),
|
||||||
ONLINE_STATUS_MESSAGE_ID = messageId > 0 ? messageId : ONLINE_STATUS_MESSAGE_ID;
|
onServer.size(),
|
||||||
outbound("done");
|
onServer.stream().map(Player::getUsername).collect(Collectors.joining(", ")))
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case "/genpin":
|
outbound(String.join("\n", out));
|
||||||
outbound(genOnlineStatus(),
|
|
||||||
(sendMessage, sendResponse) -> {
|
|
||||||
if (!sendResponse.isOk()) {
|
|
||||||
plugin.logger.error(String.format("sendMessage error %d: %s", sendResponse.errorCode(), sendResponse.description()));
|
|
||||||
} else {
|
|
||||||
int messageId = sendResponse.message().messageId();
|
|
||||||
ONLINE_STATUS_MESSAGE_ID = messageId > 0 ? messageId : ONLINE_STATUS_MESSAGE_ID;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
tgInbound(update.message().from(), msg);
|
tgInbound(update.message().from(), msg);
|
||||||
} else if (update.message().sticker() != null) {
|
}
|
||||||
|
else if (update.message().sticker() != null) {
|
||||||
tgInbound(update.message().from(), "[sticker]");
|
tgInbound(update.message().from(), "[sticker]");
|
||||||
} else if (update.message().photo() != null) {
|
}
|
||||||
|
else if (update.message().photo() != null) {
|
||||||
tgInbound(update.message().from(), "[photo]");
|
tgInbound(update.message().from(), "[photo]");
|
||||||
} else if (update.message().audio() != null) {
|
}
|
||||||
|
else if (update.message().audio() != null) {
|
||||||
tgInbound(update.message().from(), "[audio]");
|
tgInbound(update.message().from(), "[audio]");
|
||||||
} else if (update.message().voice() != null) {
|
}
|
||||||
|
else if (update.message().voice() != null) {
|
||||||
tgInbound(update.message().from(), "[voice]");
|
tgInbound(update.message().from(), "[voice]");
|
||||||
} else if (update.message().document() != null) {
|
}
|
||||||
|
else if (update.message().document() != null) {
|
||||||
tgInbound(update.message().from(), "[document]");
|
tgInbound(update.message().from(), "[document]");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
plugin.logger.error("handling update", e);
|
plugin.logger.error("handling update", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +134,7 @@ public class TGBridge {
|
||||||
}, (e) -> {
|
}, (e) -> {
|
||||||
plugin.logger.error("getting update", e);
|
plugin.logger.error("getting update", e);
|
||||||
plugin.logger.error(String.format("waiting %ds before getting another update", backoffSec));
|
plugin.logger.error(String.format("waiting %ds before getting another update", backoffSec));
|
||||||
try {Thread.sleep(backoffSec * 1000);} catch (InterruptedException ignored) {}
|
try { Thread.sleep(backoffSec * 1000); } catch (InterruptedException ignored) {}
|
||||||
backoffSec *= 2L;
|
backoffSec *= 2L;
|
||||||
if (backoffSec > 3600) {
|
if (backoffSec > 3600) {
|
||||||
backoffSec = 3600;
|
backoffSec = 3600;
|
||||||
|
@ -158,24 +142,6 @@ public class TGBridge {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private String genOnlineStatus() {
|
|
||||||
ArrayList<String> out = new ArrayList<>();
|
|
||||||
String fmt = server.getAllPlayers().size() > 1 ? "%d players are currently connected to the proxy." : "%d player is currently connected to the proxy.";
|
|
||||||
out.add(String.format(fmt, server.getAllPlayers().size()));
|
|
||||||
List<RegisteredServer> registeredServers = new ArrayList<>(server.getAllServers());
|
|
||||||
for (RegisteredServer registeredServer : registeredServers) {
|
|
||||||
List<Player> onServer = ImmutableList.copyOf(registeredServer.getPlayersConnected());
|
|
||||||
if (!onServer.isEmpty()) {
|
|
||||||
out.add(String.format("[%s] (%d): %s",
|
|
||||||
registeredServer.getServerInfo().getName(),
|
|
||||||
onServer.size(),
|
|
||||||
onServer.stream().map(Player::getUsername).collect(Collectors.joining(", ")))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return String.join("\n", out);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void tgInbound(User user, String content) {
|
protected void tgInbound(User user, String content) {
|
||||||
inbound(String.format("[tg] <%s> %s", user.lastName() == null ? user.firstName() : String.format("%s %s", user.firstName(), user.lastName()), content));
|
inbound(String.format("[tg] <%s> %s", user.lastName() == null ? user.firstName() : String.format("%s %s", user.firstName(), user.lastName()), content));
|
||||||
}
|
}
|
||||||
|
@ -189,10 +155,6 @@ public class TGBridge {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void outbound(String content) {
|
protected void outbound(String content) {
|
||||||
outbound(content, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void outbound(String content, @Nullable BiConsumer<SendMessage, SendResponse> onResponse) {
|
|
||||||
if (bot == null) return;
|
if (bot == null) return;
|
||||||
if (content.length() > 4000) {
|
if (content.length() > 4000) {
|
||||||
content = content.substring(0, 4000);
|
content = content.substring(0, 4000);
|
||||||
|
@ -200,12 +162,8 @@ public class TGBridge {
|
||||||
bot.execute(new SendMessage(CHAT_ID, content), new Callback<SendMessage, SendResponse>() {
|
bot.execute(new SendMessage(CHAT_ID, content), new Callback<SendMessage, SendResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(SendMessage sendMessage, SendResponse sendResponse) {
|
public void onResponse(SendMessage sendMessage, SendResponse sendResponse) {
|
||||||
if (onResponse == null) {
|
if (!sendResponse.isOk()) {
|
||||||
if (!sendResponse.isOk()) {
|
plugin.logger.error(String.format("sendMessage error %d: %s", sendResponse.errorCode(), sendResponse.description()));
|
||||||
plugin.logger.error(String.format("sendMessage error %d: %s", sendResponse.errorCode(), sendResponse.description()));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
onResponse.accept(sendMessage, sendResponse);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,195 +179,21 @@ public class TGBridge {
|
||||||
if (bot == null) return;
|
if (bot == null) return;
|
||||||
bot.removeGetUpdatesListener();
|
bot.removeGetUpdatesListener();
|
||||||
bot.shutdown();
|
bot.shutdown();
|
||||||
PROXY_SHUT_DOWN = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onServerConnected(ServerConnectedEvent event) {
|
public void onServerConnected(ServerConnectedEvent event) {
|
||||||
if (event.getPreviousServer().isEmpty()) {
|
if (event.getPreviousServer().isEmpty()) {
|
||||||
if (!event.getPlayer().hasPermission("vtools.globalchat.bypassbridge.join")) {
|
if (!event.getPlayer().hasPermission("vtools.globalchat.bypassbridge.join")) {
|
||||||
joinLeftAnnounce(String.format("%s joined the proxy", event.getPlayer().getUsername()));
|
outbound(String.format("%s joined the proxy", event.getPlayer().getUsername()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateRequests.add(new UpdateRequest());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
public void onDisconnect(DisconnectEvent event) {
|
public void onDisconnect(DisconnectEvent event) {
|
||||||
if (!event.getPlayer().hasPermission("vtools.globalchat.bypassbridge.join")) {
|
if (!event.getPlayer().hasPermission("vtools.globalchat.bypassbridge.join")) {
|
||||||
joinLeftAnnounce(String.format("%s left the proxy", event.getPlayer().getUsername()));
|
outbound(String.format("%s left the proxy", event.getPlayer().getUsername()));
|
||||||
}
|
|
||||||
updateRequests.add(new UpdateRequest(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void onServerPostConnect(ServerPostConnectEvent event){
|
|
||||||
updateRequests.add(new UpdateRequest());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private boolean PROXY_SHUT_DOWN = false;
|
|
||||||
|
|
||||||
private static class UpdateRequest {
|
|
||||||
int updateTimes;
|
|
||||||
|
|
||||||
UpdateRequest() {
|
|
||||||
this(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateRequest(int updateTimes) {
|
|
||||||
this.updateTimes = updateTimes;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private LinkedBlockingQueue<UpdateRequest> updateRequests = new LinkedBlockingQueue<>();
|
|
||||||
|
|
||||||
private void initUpdateThread() {
|
|
||||||
new Thread(() -> {
|
|
||||||
while (true) {
|
|
||||||
if (PROXY_SHUT_DOWN) {
|
|
||||||
setOnlineStatusNotAvailable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int maxiterationNum = 0;
|
|
||||||
UpdateRequest oldestRequest = null;
|
|
||||||
try {
|
|
||||||
oldestRequest = updateRequests.take();
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
if (oldestRequest == null) continue;
|
|
||||||
maxiterationNum = Math.max(maxiterationNum, oldestRequest.updateTimes - 1);
|
|
||||||
while (!updateRequests.isEmpty()){
|
|
||||||
try {
|
|
||||||
maxiterationNum = Math.max(maxiterationNum, updateRequests.take().updateTimes - 1);
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!updateOnlineStatus()) {
|
|
||||||
updateRequests.add(oldestRequest); // 更新失败 回去吧您内
|
|
||||||
}
|
|
||||||
if(maxiterationNum>0){
|
|
||||||
updateRequests.add(new UpdateRequest(maxiterationNum));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
new Thread(()->{
|
|
||||||
while (true) {
|
|
||||||
if (PROXY_SHUT_DOWN) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String oldestMessage = null;
|
|
||||||
try {
|
|
||||||
oldestMessage = announceQueue.take();
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
|
|
||||||
if(!currentAnnounce.isValid()){
|
|
||||||
currentAnnounce = new JoinLeftAnnounceMessage(oldestMessage);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
ArrayList<String> messages = new ArrayList<>(announceQueue.size() + 1);
|
|
||||||
messages.add(oldestMessage);
|
|
||||||
while (!announceQueue.isEmpty()) {
|
|
||||||
try {
|
|
||||||
messages.add(announceQueue.take());
|
|
||||||
} catch (InterruptedException ignored) {}
|
|
||||||
}
|
|
||||||
currentAnnounce.addLines(messages);
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean updateOnlineStatus() {
|
|
||||||
return editOnlineStatusMessage(genOnlineStatus());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean setOnlineStatusNotAvailable() {
|
|
||||||
return editOnlineStatusMessage("(proxy already shutdown)");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean editOnlineStatusMessage(String text) {
|
|
||||||
if (ONLINE_STATUS_MESSAGE_ID < 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
BaseResponse response;
|
|
||||||
try {
|
|
||||||
response = bot.execute(new EditMessageText(CHAT_ID, ONLINE_STATUS_MESSAGE_ID, text));
|
|
||||||
} catch (RuntimeException e) {return false;}
|
|
||||||
return response != null && response.isOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class JoinLeftAnnounceMessage {
|
|
||||||
private int messageId;
|
|
||||||
private long time;
|
|
||||||
|
|
||||||
private StringBuilder text;
|
|
||||||
|
|
||||||
boolean isValid() {
|
|
||||||
if (messageId < 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
long dt = System.currentTimeMillis() - time;
|
|
||||||
return dt <= 60_000 && dt >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JoinLeftAnnounceMessage(String firstMessage) {
|
|
||||||
text = new StringBuilder(firstMessage);
|
|
||||||
time = System.currentTimeMillis();
|
|
||||||
sendAnnounceMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sendAnnounceMessage() {
|
|
||||||
if (bot == null) {
|
|
||||||
messageId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SendResponse response;
|
|
||||||
try {
|
|
||||||
response = bot.execute(new SendMessage(CHAT_ID, text.toString()));
|
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
messageId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(response.isOk() == false){
|
|
||||||
messageId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
messageId = response.message().messageId();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected JoinLeftAnnounceMessage(){
|
|
||||||
messageId = 0;
|
|
||||||
time = 0;
|
|
||||||
text = new StringBuilder();
|
|
||||||
} //dummy
|
|
||||||
private void addLines(List<String> messages) {
|
|
||||||
for (String message : messages) {
|
|
||||||
text.append('\n').append(message);
|
|
||||||
}
|
|
||||||
updateAnnounceMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateAnnounceMessage() {
|
|
||||||
if(!isValid()){
|
|
||||||
plugin.logger.error("message should only push to a valid object");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (bot == null) {
|
|
||||||
messageId = -1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
bot.execute(new EditMessageText(CHAT_ID, messageId, text.toString()));
|
|
||||||
} catch (RuntimeException ignored) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JoinLeftAnnounceMessage currentAnnounce = new JoinLeftAnnounceMessage();
|
|
||||||
private LinkedBlockingQueue<String> announceQueue = new LinkedBlockingQueue<>();
|
|
||||||
|
|
||||||
private void joinLeftAnnounce(String message){
|
|
||||||
announceQueue.add(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue