Add dump command (#808)

* Add dump command
Adds a command to collect and dump infomation about the Geyser install and bootstrap and submit it to a dumps site.

* Finalize URL; misc. fixes; add 'architecture' param

Co-authored-by: DoctorMacc <toy.fighter1@gmail.com>
This commit is contained in:
rtm516 2020-06-27 16:36:48 +01:00 committed by GitHub
parent 75f470cb33
commit 7743f6d718
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 699 additions and 6 deletions

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.platform.bungeecord;
import lombok.Getter;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.plugin.Plugin;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Getter
public class GeyserBungeeDumpInfo extends BootstrapDumpInfo {
private String platformName;
private String platformVersion;
private boolean onlineMode;
private List<ListenerInfo> listeners;
private List<PluginInfo> plugins;
GeyserBungeeDumpInfo(ProxyServer proxy) {
super();
this.platformName = proxy.getName();
this.platformVersion = proxy.getVersion();
this.onlineMode = proxy.getConfig().isOnlineMode();
this.listeners = new ArrayList<>();
this.plugins = new ArrayList<>();
for (net.md_5.bungee.api.config.ListenerInfo listener : proxy.getConfig().getListeners()) {
this.listeners.add(new ListenerInfo(listener.getHost().getHostString(), listener.getHost().getPort()));
}
for (Plugin plugin : proxy.getPluginManager().getPlugins()) {
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), Arrays.asList(plugin.getDescription().getAuthor())));
}
}
}

View file

@ -35,6 +35,7 @@ import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.FileUtils;
@ -140,4 +141,9 @@ public class GeyserBungeePlugin extends Plugin implements GeyserBootstrap {
public Path getConfigFolder() { public Path getConfigFolder() {
return getDataFolder().toPath(); return getDataFolder().toPath();
} }
@Override
public BootstrapDumpInfo getDumpInfo() {
return new GeyserBungeeDumpInfo(getProxy());
}
} }

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.platform.spigot;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import java.util.ArrayList;
import java.util.List;
@Getter
public class GeyserSpigotDumpInfo extends BootstrapDumpInfo {
private String platformName;
private String platformVersion;
private String platformAPIVersion;
private boolean onlineMode;
private String serverIP;
private int serverPort;
private List<PluginInfo> plugins;
GeyserSpigotDumpInfo() {
super();
this.platformName = Bukkit.getName();
this.platformVersion = Bukkit.getVersion();
this.platformAPIVersion = Bukkit.getBukkitVersion();
this.onlineMode = Bukkit.getOnlineMode();
this.serverIP = Bukkit.getIp();
this.serverPort = Bukkit.getPort();
this.plugins = new ArrayList<>();
for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) {
this.plugins.add(new PluginInfo(plugin.isEnabled(), plugin.getName(), plugin.getDescription().getVersion(), plugin.getDescription().getMain(), plugin.getDescription().getAuthors()));
}
}
}

View file

@ -32,6 +32,7 @@ import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.network.translators.world.WorldManager; import org.geysermc.connector.network.translators.world.WorldManager;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough;
@ -192,4 +193,8 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
return temp; return temp;
} }
@Override
public BootstrapDumpInfo getDumpInfo() {
return new GeyserSpigotDumpInfo();
}
} }

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.platform.sponge;
import lombok.Getter;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.spongepowered.api.Platform;
import org.spongepowered.api.Sponge;
import org.spongepowered.api.plugin.PluginContainer;
import java.util.ArrayList;
import java.util.List;
@Getter
public class GeyserSpongeDumpInfo extends BootstrapDumpInfo {
private String platformName;
private String platformVersion;
private boolean onlineMode;
private String serverIP;
private int serverPort;
private List<PluginInfo> plugins;
GeyserSpongeDumpInfo() {
super();
PluginContainer container = Sponge.getPlatform().getContainer(Platform.Component.IMPLEMENTATION);
this.platformName = container.getName();
this.platformVersion = container.getVersion().get();
this.onlineMode = Sponge.getServer().getOnlineMode();
this.serverIP = Sponge.getServer().getBoundAddress().get().getHostString();
this.serverPort = Sponge.getServer().getBoundAddress().get().getPort();
this.plugins = new ArrayList<>();
for (PluginContainer plugin : Sponge.getPluginManager().getPlugins()) {
String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown");
this.plugins.add(new PluginInfo(true, plugin.getName(), plugin.getVersion().get(), pluginClass, plugin.getAuthors()));
}
}
}

View file

@ -34,6 +34,7 @@ import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.FileUtils;
@ -162,4 +163,9 @@ public class GeyserSpongePlugin implements GeyserBootstrap {
public void onServerStop(GameStoppedEvent event) { public void onServerStop(GameStoppedEvent event) {
onDisable(); onDisable();
} }
@Override
public BootstrapDumpInfo getDumpInfo() {
return new GeyserSpongeDumpInfo();
}
} }

View file

@ -30,6 +30,7 @@ import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.command.CommandManager; import org.geysermc.connector.command.CommandManager;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.FileUtils;
@ -108,4 +109,9 @@ public class GeyserStandaloneBootstrap implements GeyserBootstrap {
// Return the current working directory // Return the current working directory
return Paths.get(System.getProperty("user.dir")); return Paths.get(System.getProperty("user.dir"));
} }
@Override
public BootstrapDumpInfo getDumpInfo() {
return new BootstrapDumpInfo();
}
} }

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.platform.velocity;
import com.velocitypowered.api.plugin.PluginContainer;
import com.velocitypowered.api.proxy.ProxyServer;
import lombok.Getter;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import java.util.ArrayList;
import java.util.List;
@Getter
public class GeyserVelocityDumpInfo extends BootstrapDumpInfo {
private String platformName;
private String platformVersion;
private String platformVendor;
private boolean onlineMode;
private String serverIP;
private int serverPort;
private List<PluginInfo> plugins;
GeyserVelocityDumpInfo(ProxyServer proxy) {
super();
this.platformName = proxy.getVersion().getName();
this.platformVersion = proxy.getVersion().getVersion();
this.platformVendor = proxy.getVersion().getVendor();
this.onlineMode = proxy.getConfiguration().isOnlineMode();
this.serverIP = proxy.getBoundAddress().getHostString();
this.serverPort = proxy.getBoundAddress().getPort();
this.plugins = new ArrayList<>();
for (PluginContainer plugin : proxy.getPluginManager().getPlugins()) {
String pluginClass = plugin.getInstance().map((pl) -> pl.getClass().getName()).orElse("unknown");
this.plugins.add(new PluginInfo(true, plugin.getDescription().getName().get(), plugin.getDescription().getVersion().get(), pluginClass, plugin.getDescription().getAuthors()));
}
}
}

View file

@ -39,6 +39,7 @@ import org.geysermc.common.PlatformType;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.bootstrap.GeyserBootstrap; import org.geysermc.connector.bootstrap.GeyserBootstrap;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.GeyserLegacyPingPassthrough; import org.geysermc.connector.ping.GeyserLegacyPingPassthrough;
import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.FileUtils;
@ -153,4 +154,9 @@ public class GeyserVelocityPlugin implements GeyserBootstrap {
public void onShutdown(ProxyShutdownEvent event) { public void onShutdown(ProxyShutdownEvent event) {
onDisable(); onDisable();
} }
@Override
public BootstrapDumpInfo getDumpInfo() {
return new GeyserVelocityDumpInfo(proxyServer);
}
} }

View file

@ -0,0 +1,76 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.common.serializer;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Optional;
public class AsteriskSerializer extends StdSerializer<Object> implements ContextualSerializer {
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = AsteriskSerializer.class)
public @interface Asterisk {
String value() default "***";
}
String asterisk;
public AsteriskSerializer() {
super(Object.class);
}
public AsteriskSerializer(String asterisk) {
super(Object.class);
this.asterisk = asterisk;
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) {
Optional<Asterisk> anno = Optional.ofNullable(property)
.map(prop -> prop.getAnnotation(Asterisk.class));
return new AsteriskSerializer(anno.map(Asterisk::value).orElse(null));
}
@Override
public void serialize(Object obj, JsonGenerator gen, SerializerProvider prov) throws IOException {
gen.writeString(asterisk);
}
}

View file

@ -170,6 +170,11 @@
<skipPoms>false</skipPoms> <skipPoms>false</skipPoms>
<excludeProperties> <excludeProperties>
<excludeProperty>git.user.*</excludeProperty> <excludeProperty>git.user.*</excludeProperty>
<excludeProperty>git.*.user.*</excludeProperty>
<excludeProperty>git.closest.*</excludeProperty>
<excludeProperty>git.commit.id.describe</excludeProperty>
<excludeProperty>git.commit.id.describe-short</excludeProperty>
<excludeProperty>git.commit.message.short</excludeProperty>
</excludeProperties> </excludeProperties>
<commitIdGenerationMode>flat</commitIdGenerationMode> <commitIdGenerationMode>flat</commitIdGenerationMode>
<gitDescribe> <gitDescribe>

View file

@ -26,6 +26,7 @@
package org.geysermc.connector.bootstrap; package org.geysermc.connector.bootstrap;
import org.geysermc.connector.dump.BootstrapDumpInfo;
import org.geysermc.connector.ping.IGeyserPingPassthrough; import org.geysermc.connector.ping.IGeyserPingPassthrough;
import org.geysermc.connector.configuration.GeyserConfiguration; import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.GeyserLogger; import org.geysermc.connector.GeyserLogger;
@ -92,4 +93,11 @@ public interface GeyserBootstrap {
* @return Path location of data folder * @return Path location of data folder
*/ */
Path getConfigFolder(); Path getConfigFolder();
/**
* Information used for the bootstrap section of the debug dump
*
* @return The info about the bootstrap
*/
BootstrapDumpInfo getDumpInfo();
} }

View file

@ -49,6 +49,7 @@ public abstract class CommandManager {
registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload")); registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload"));
registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop")); registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop"));
registerCommand(new OffhandCommand(connector, "offhand", "Puts an items in your offhand.", "geyser.command.offhand")); registerCommand(new OffhandCommand(connector, "offhand", "Puts an items in your offhand.", "geyser.command.offhand"));
registerCommand(new DumpCommand(connector, "dump", "Dumps Geyser debug infomation for bug reports.", "geyser.command.dump"));
} }
public void registerCommand(GeyserCommand command) { public void registerCommand(GeyserCommand command) {

View file

@ -0,0 +1,93 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*/
package org.geysermc.connector.command.defaults;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import org.geysermc.common.ChatColor;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
import org.geysermc.connector.dump.DumpInfo;
import org.geysermc.connector.utils.WebUtils;
import java.io.IOException;
public class DumpCommand extends GeyserCommand {
private final GeyserConnector connector;
private static final ObjectMapper MAPPER = new ObjectMapper();
private static final String DUMP_URL = "https://dump.geysermc.org/";
public DumpCommand(GeyserConnector connector, String name, String description, String permission) {
super(name, description, permission);
this.connector = connector;
final SimpleFilterProvider filter = new SimpleFilterProvider();
filter.addFilter("dump_user_auth", SimpleBeanPropertyFilter.serializeAllExcept(new String[] {"password"}));
MAPPER.setFilterProvider(filter);
}
@Override
public void execute(CommandSender sender, String[] args) {
sender.sendMessage("Collecting dump info");
String dumpData = "";
try {
dumpData = MAPPER.writeValueAsString(new DumpInfo());
} catch (IOException e) {
sender.sendMessage(ChatColor.RED + "Failed to collect dump info, check console for more information");
connector.getLogger().error("Failed to collect dump info", e);
return;
}
sender.sendMessage("Uploading dump");
String response;
JsonNode responseNode;
try {
response = WebUtils.post(DUMP_URL + "documents", dumpData);
responseNode = MAPPER.readTree(response);
} catch (IOException e) {
sender.sendMessage(ChatColor.RED + "Failed to upload dump, check console for more information");
connector.getLogger().error("Failed to upload dump", e);
return;
}
if (!responseNode.has("key")) {
sender.sendMessage(ChatColor.RED + "Failed to upload dump: " + (responseNode.has("message") ? responseNode.get("message").asText() : response));
return;
}
String uploadedDumpUrl = DUMP_URL + responseNode.get("key").asText();
sender.sendMessage("We've made a dump with useful information, report your issue and provide this url: " + ChatColor.DARK_AQUA + uploadedDumpUrl);
if (!sender.isConsole()) {
connector.getLogger().info(sender.getName() + " created a GeyserDump at " + uploadedDumpUrl);
}
}
}

View file

@ -30,6 +30,7 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.geysermc.common.serializer.AsteriskSerializer;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Map; import java.util.Map;
@ -111,16 +112,16 @@ public abstract class GeyserJacksonConfiguration implements GeyserConfiguration
@Setter @Setter
private int port; private int port;
private String motd1;
private String motd2;
@JsonProperty("auth-type") @JsonProperty("auth-type")
private String authType; private String authType;
} }
@Getter @Getter
public static class UserAuthenticationInfo implements IUserAuthenticationInfo { public static class UserAuthenticationInfo implements IUserAuthenticationInfo {
@AsteriskSerializer.Asterisk()
private String email; private String email;
@AsteriskSerializer.Asterisk()
private String password; private String password;
} }

View file

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.connector.dump;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.geysermc.common.PlatformType;
import org.geysermc.connector.GeyserConnector;
import java.util.List;
@Getter
public class BootstrapDumpInfo {
private PlatformType platform;
public BootstrapDumpInfo() {
this.platform = GeyserConnector.getInstance().getPlatformType();
}
@Getter
@AllArgsConstructor
public class PluginInfo {
public boolean enabled;
public String name;
public String version;
public String main;
public List<String> authors;
}
@Getter
@AllArgsConstructor
public class ListenerInfo {
public String ip;
public int port;
}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright (c) 2019-2020 GeyserMC. http://geysermc.org
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* @author GeyserMC
* @link https://github.com/GeyserMC/Geyser
*
*/
package org.geysermc.connector.dump;
import com.github.steveice10.mc.protocol.MinecraftConstants;
import lombok.Getter;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.configuration.GeyserConfiguration;
import org.geysermc.connector.utils.DockerCheck;
import org.geysermc.connector.utils.FileUtils;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;
@Getter
public class DumpInfo {
private final DumpInfo.VersionInfo versionInfo;
private Properties gitInfo;
private final GeyserConfiguration config;
private final BootstrapDumpInfo bootstrapInfo;
public DumpInfo() {
try {
this.gitInfo = new Properties();
this.gitInfo.load(FileUtils.getResource("git.properties"));
} catch (IOException ignored) { }
this.config = GeyserConnector.getInstance().getConfig();
this.versionInfo = new DumpInfo.VersionInfo();
this.bootstrapInfo = GeyserConnector.getInstance().getBootstrap().getDumpInfo();
}
@Getter
public class VersionInfo {
private final String name;
private final String version;
private final String javaVersion;
private final String architecture;
private final String operatingSystem;
private final NetworkInfo network;
private final MCInfo mcInfo;
VersionInfo() {
this.name = GeyserConnector.NAME;
this.version = GeyserConnector.VERSION;
this.javaVersion = System.getProperty("java.version");
this.architecture = System.getProperty("os.arch"); // Usually gives Java architecture but still may be helpful.
this.operatingSystem = System.getProperty("os.name");
this.network = new NetworkInfo();
this.mcInfo = new MCInfo();
}
}
@Getter
public static class NetworkInfo {
private String internalIP;
private final boolean dockerCheck;
NetworkInfo() {
try {
// This is the most reliable for getting the main local IP
Socket socket = new Socket();
socket.connect(new InetSocketAddress("geysermc.org", 80));
this.internalIP = socket.getLocalAddress().getHostAddress();
} catch (IOException e1) {
try {
// Fallback to the normal way of getting the local IP
this.internalIP = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException ignored) { }
}
this.dockerCheck = DockerCheck.checkBasic();
}
}
@Getter
public static class MCInfo {
private final String bedrockVersion;
private final int bedrockProtocol;
private final String javaVersion;
private final int javaProtocol;
MCInfo() {
this.bedrockVersion = GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion();
this.bedrockProtocol = GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion();
this.javaVersion = MinecraftConstants.GAME_VERSION;
this.javaProtocol = MinecraftConstants.PROTOCOL_VERSION;
}
}
}

View file

@ -55,4 +55,19 @@ public class DockerCheck {
} }
} catch (Exception e) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied } catch (Exception e) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied
} }
public static boolean checkBasic() {
try {
String OS = System.getProperty("os.name").toLowerCase();
if (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0) {
String output = new String(Files.readAllBytes(Paths.get("/proc/1/cgroup")));
if (output.contains("docker")) {
return true;
}
}
} catch (Exception ignored) { } // Ignore any errors, inc ip failed to fetch, process could not run or access denied
return false;
}
} }

View file

@ -25,11 +25,10 @@
package org.geysermc.connector.utils; package org.geysermc.connector.utils;
import java.io.BufferedReader; import java.io.*;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
@ -81,4 +80,31 @@ public class WebUtils {
throw new AssertionError("Unable to download and save file: " + fileLocation + " (" + reqURL + ")", e); throw new AssertionError("Unable to download and save file: " + fileLocation + " (" + reqURL + ")", e);
} }
} }
public static String post(String reqURL, String postContent) throws IOException {
URL url = null;
url = new URL(reqURL);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "text/plain");
con.setDoOutput(true);
OutputStream out = con.getOutputStream();
out.write(postContent.getBytes(StandardCharsets.UTF_8));
out.close();
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer content = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
content.append("\n");
}
in.close();
con.disconnect();
return content.toString();
}
} }