119 lines
3.6 KiB
Java
119 lines
3.6 KiB
Java
package tc.oc.pgm.listing;
|
|
|
|
import java.security.SecureRandom;
|
|
import javax.annotation.Nullable;
|
|
import javax.inject.Inject;
|
|
import javax.inject.Singleton;
|
|
|
|
import com.google.common.util.concurrent.ListenableFuture;
|
|
import net.md_5.bungee.api.chat.TranslatableComponent;
|
|
import org.apache.commons.codec.binary.Hex;
|
|
import org.apache.commons.codec.digest.DigestUtils;
|
|
import org.bukkit.command.CommandSender;
|
|
import org.bukkit.command.ConsoleCommandSender;
|
|
import tc.oc.api.http.HttpClient;
|
|
import tc.oc.api.http.HttpOption;
|
|
import tc.oc.api.message.types.Reply;
|
|
import tc.oc.commons.bukkit.chat.Audiences;
|
|
import tc.oc.commons.core.commands.CommandFutureCallback;
|
|
import tc.oc.commons.core.concurrent.Flexecutor;
|
|
import tc.oc.minecraft.api.event.Enableable;
|
|
import tc.oc.minecraft.api.server.LocalServer;
|
|
import tc.oc.minecraft.scheduler.Sync;
|
|
|
|
@Singleton
|
|
class ListingServiceImpl implements ListingService, Enableable {
|
|
|
|
private final HttpClient http;
|
|
private final ListingConfiguration config;
|
|
private final LocalServer localServer;
|
|
private final SecureRandom random = new SecureRandom();
|
|
private final Flexecutor executor;
|
|
private final Audiences audiences;
|
|
private final ConsoleCommandSender console;
|
|
|
|
private boolean online;
|
|
private @Nullable String sessionId;
|
|
private @Nullable String sessionDigest;
|
|
|
|
@Inject ListingServiceImpl(HttpClient http, ListingConfiguration config, LocalServer localServer, @Sync(defer = true) Flexecutor executor, Audiences audiences, ConsoleCommandSender console) {
|
|
this.http = http;
|
|
this.config = config;
|
|
this.localServer = localServer;
|
|
this.executor = executor;
|
|
this.audiences = audiences;
|
|
this.console = console;
|
|
}
|
|
|
|
@Override
|
|
public @Nullable String sessionDigest() {
|
|
return sessionDigest;
|
|
}
|
|
|
|
@Override
|
|
public void enable() {
|
|
if(config.enabled()) {
|
|
// Don't announce until we are ready to receive the ping
|
|
executor.execute(() -> update(true));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void disable() {
|
|
if(online) {
|
|
update(false);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public ListenableFuture<Reply> update(boolean online) {
|
|
return update(online, console);
|
|
}
|
|
|
|
@Override
|
|
public ListenableFuture<Reply> update(boolean online, CommandSender sender) {
|
|
this.online = online;
|
|
|
|
if(sessionId == null) {
|
|
final byte[] bytes = new byte[20];
|
|
random.nextBytes(bytes);
|
|
sessionId = Hex.encodeHexString(bytes);
|
|
sessionDigest = DigestUtils.sha1Hex(sessionId);
|
|
}
|
|
|
|
final ListenableFuture<Reply> future = http.post(config.announceUrl().toString(), new ListingUpdate() {
|
|
@Override public @Nullable String host() {
|
|
return config.serverHost();
|
|
}
|
|
|
|
@Override
|
|
public int port() {
|
|
return config.serverPort().orElseGet(localServer::getPort);
|
|
}
|
|
|
|
@Override
|
|
public boolean online() {
|
|
return online;
|
|
}
|
|
|
|
@Override
|
|
public String session() {
|
|
return sessionId;
|
|
}
|
|
}, Reply.class, HttpOption.INFINITE_RETRY);
|
|
|
|
executor.callback(
|
|
future,
|
|
CommandFutureCallback.onSuccess(sender, reply -> {
|
|
if(!online) {
|
|
sessionId = sessionDigest = null;
|
|
}
|
|
|
|
audiences.get(sender).sendMessage(new TranslatableComponent(online ? "announce.online" : "announce.offline"));
|
|
})
|
|
);
|
|
|
|
return future;
|
|
}
|
|
}
|