mirror of
https://github.com/Miasmusa/Shadow.git
synced 2024-11-14 19:04:54 -05:00
api
This commit is contained in:
parent
4d10a1c9ce
commit
c0de23593f
6 changed files with 185 additions and 23 deletions
|
@ -43,6 +43,7 @@ import net.shadow.client.feature.command.impl.Kill;
|
|||
import net.shadow.client.feature.command.impl.LinkWolf;
|
||||
import net.shadow.client.feature.command.impl.LogFlood;
|
||||
import net.shadow.client.feature.command.impl.MessageSpam;
|
||||
import net.shadow.client.feature.command.impl.OnlineAPI;
|
||||
import net.shadow.client.feature.command.impl.Panic;
|
||||
import net.shadow.client.feature.command.impl.PermissionLevel;
|
||||
import net.shadow.client.feature.command.impl.Poof;
|
||||
|
@ -153,6 +154,7 @@ public class CommandRegistry {
|
|||
vanillaCommands.add(new ForceOP());
|
||||
vanillaCommands.add(new ServerCrash());
|
||||
vanillaCommands.add(new RandomBook());
|
||||
vanillaCommands.add(new OnlineAPI());
|
||||
|
||||
rebuildSharedCommands();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
|
||||
*/
|
||||
|
||||
package net.shadow.client.feature.command.impl;
|
||||
|
||||
import net.shadow.client.ShadowMain;
|
||||
import net.shadow.client.feature.command.Command;
|
||||
import net.shadow.client.feature.command.coloring.ArgumentType;
|
||||
import net.shadow.client.feature.command.coloring.PossibleArgument;
|
||||
import net.shadow.client.feature.command.coloring.StaticArgumentServer;
|
||||
import net.shadow.client.feature.command.exception.CommandException;
|
||||
import net.shadow.client.feature.module.ModuleRegistry;
|
||||
import net.shadow.client.feature.module.impl.misc.IRC;
|
||||
import net.shadow.client.helper.ShadowAPIWrapper;
|
||||
import net.shadow.client.helper.event.EventType;
|
||||
import net.shadow.client.helper.event.Events;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class OnlineAPI extends Command {
|
||||
static final File SESSION_KEY_FILE = new File(ShadowMain.BASE, "session.sip");
|
||||
public OnlineAPI() {
|
||||
super("OnlineAPI", "Manage your API connection to the mothership","onlineapi","shadowapi","onlineservices");
|
||||
tryToRecoverSession();
|
||||
Events.registerEventHandler(EventType.CONFIG_SAVE, event -> {
|
||||
String authKey = ShadowAPIWrapper.getAuthKey();
|
||||
if (authKey != null) {
|
||||
try {
|
||||
FileUtils.write(SESSION_KEY_FILE,authKey,StandardCharsets.UTF_8);
|
||||
} catch (Exception e) {
|
||||
System.out.println("failed to save session :(");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
void tryToRecoverSession() {
|
||||
if (SESSION_KEY_FILE.exists()) {
|
||||
try {
|
||||
String session = FileUtils.readFileToString(SESSION_KEY_FILE, StandardCharsets.UTF_8);
|
||||
if (!session.isEmpty()) {
|
||||
if (ShadowAPIWrapper.loginWithKey(session)) {
|
||||
System.out.println("recovered previous session from backup file");
|
||||
} else {
|
||||
System.out.println("server said no to session recovery, moving on");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("failed to recover session :(");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public PossibleArgument getSuggestionsWithType(int index, String[] args) {
|
||||
if (index == 0) return new PossibleArgument(ArgumentType.STRING, "login", "logout");
|
||||
if (args[0].equalsIgnoreCase("login")) {
|
||||
return StaticArgumentServer.serveFromStatic(index-1,new PossibleArgument(ArgumentType.STRING, "(username)"), new PossibleArgument(ArgumentType.STRING, "(password)"));
|
||||
}
|
||||
return super.getSuggestionsWithType(index, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecute(String[] args) throws CommandException {
|
||||
validateArgumentsLength(args,1, "Need an action");
|
||||
switch(args[0].toLowerCase()) {
|
||||
case "login" -> {
|
||||
if (ShadowAPIWrapper.getAuthKey() != null) {
|
||||
error("You're already logged in!");
|
||||
return;
|
||||
}
|
||||
validateArgumentsLength(args, 3, "Need action, username and password");
|
||||
if (ShadowAPIWrapper.attemptLogin(args[1], args[2])) {
|
||||
success("You're now logged in as "+args[1]+". Try using IRC or the item market ;)");
|
||||
} else {
|
||||
error("Failed to login. Check if username and password are correct");
|
||||
}
|
||||
}
|
||||
case "logout" -> {
|
||||
IRC irc = ModuleRegistry.getByClass(IRC.class);
|
||||
if (irc.isEnabled()) irc.setEnabled(false);
|
||||
ShadowAPIWrapper.logout();
|
||||
success("Logged you out");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,13 +5,6 @@
|
|||
package net.shadow.client.feature.command.impl;
|
||||
|
||||
import net.shadow.client.feature.command.Command;
|
||||
import net.shadow.client.feature.module.AddonModule;
|
||||
import net.shadow.client.feature.module.Module;
|
||||
import net.shadow.client.feature.module.ModuleRegistry;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
|
||||
public class Test extends Command {
|
||||
public Test() {
|
||||
|
@ -20,16 +13,6 @@ public class Test extends Command {
|
|||
|
||||
@Override
|
||||
public void onExecute(String[] args) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Module module : ModuleRegistry.getModules()) {
|
||||
if (module instanceof AddonModule) continue;
|
||||
String cname = module.getClass().getSimpleName();
|
||||
sb.append(String.format("registerModule(%s.class);", cname)).append("\n");
|
||||
}
|
||||
try {
|
||||
Files.writeString(new File("bruh.txt").toPath(), sb.toString(), StandardOpenOption.CREATE);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import net.minecraft.network.packet.c2s.play.ChatMessageC2SPacket;
|
|||
import net.shadow.client.feature.module.Module;
|
||||
import net.shadow.client.feature.module.ModuleType;
|
||||
import net.shadow.client.helper.IRCWebSocket;
|
||||
import net.shadow.client.helper.ShadowAPIWrapper;
|
||||
import net.shadow.client.helper.event.EventListener;
|
||||
import net.shadow.client.helper.event.EventType;
|
||||
import net.shadow.client.helper.event.events.PacketEvent;
|
||||
|
@ -17,10 +18,8 @@ import net.shadow.client.helper.util.Utils;
|
|||
import java.net.URI;
|
||||
|
||||
public class IRC extends Module {
|
||||
static final String websocketUrl = "ws://localhost:8080/irc";
|
||||
static String ircPrefix = "#";
|
||||
IRCWebSocket wsS;
|
||||
static String authToken = System.getenv("SHADOW_API_KEY");
|
||||
public IRC() {
|
||||
super("IRC", "Chat with others using the client", ModuleType.MISC);
|
||||
}
|
||||
|
@ -42,12 +41,12 @@ public class IRC extends Module {
|
|||
|
||||
@Override
|
||||
public void enable() {
|
||||
if (authToken == null) {
|
||||
if (ShadowAPIWrapper.getAuthKey() == null) {
|
||||
Utils.Logging.error("Cannot use IRC because you didn't use the launcher to launch shadow.");
|
||||
setEnabled(false);
|
||||
return;
|
||||
}
|
||||
this.wsS = new IRCWebSocket(URI.create(websocketUrl),authToken,()-> {
|
||||
this.wsS = new IRCWebSocket(URI.create(ShadowAPIWrapper.BASE_WS+"/irc"),ShadowAPIWrapper.getAuthKey(),()-> {
|
||||
this.wsS = null;
|
||||
this.setEnabled(false);
|
||||
});
|
||||
|
|
|
@ -80,6 +80,6 @@ public class IRCWebSocket extends WebSocketClient {
|
|||
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
|
88
src/main/java/net/shadow/client/helper/ShadowAPIWrapper.java
Normal file
88
src/main/java/net/shadow/client/helper/ShadowAPIWrapper.java
Normal file
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) Shadow client, 0x150, Saturn5VFive 2022. All rights reserved.
|
||||
*/
|
||||
|
||||
package net.shadow.client.helper;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
import java.util.Map;
|
||||
|
||||
public class ShadowAPIWrapper {
|
||||
public static final String BASE_DOMAIN = "api.shadowclient.cf";
|
||||
public static final String BASE_URL = "https://"+BASE_DOMAIN;
|
||||
public static final String BASE_WS = "wss://"+BASE_DOMAIN;
|
||||
static String authKey = "";
|
||||
static HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.ALWAYS).build();
|
||||
static Gson gson = new Gson();
|
||||
static boolean currentUserIsAdmin = false;
|
||||
|
||||
public static String getAuthKey() {
|
||||
if (authKey.isEmpty()) return null;
|
||||
return authKey;
|
||||
}
|
||||
|
||||
public static boolean isCurrentUserAdmin() {
|
||||
return currentUserIsAdmin;
|
||||
}
|
||||
|
||||
static HttpResponse<String> get(String path) {
|
||||
return request(path, "GET", HttpRequest.BodyPublishers.noBody());
|
||||
}
|
||||
static HttpResponse<String> request(String path, String method, HttpRequest.BodyPublisher publisher) {
|
||||
URI u = URI.create(BASE_URL+path);
|
||||
HttpRequest request = HttpRequest.newBuilder().method(method, publisher).uri(u).header("Authorization", authKey).build();
|
||||
try {
|
||||
return client.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
static HttpResponse<String> post(String path, String data) {
|
||||
return request(path, "POST", HttpRequest.BodyPublishers.ofString(data));
|
||||
}
|
||||
public static void logout() {
|
||||
authKey = "";
|
||||
}
|
||||
public static boolean loginWithKey(String session) {
|
||||
String prevAuthKey = authKey;
|
||||
authKey = session;
|
||||
HttpResponse<String> resp = get("/users/current");
|
||||
if (resp.statusCode() != 200) {
|
||||
authKey = prevAuthKey;
|
||||
return false;
|
||||
}
|
||||
Map<String, Object> info = gson.fromJson(resp.body(),Map.class);
|
||||
currentUserIsAdmin = (boolean) info.getOrDefault("isAdmin", false);
|
||||
return true;
|
||||
}
|
||||
public static boolean attemptLogin(String username, String password) {
|
||||
String d = gson.toJson(Map.of(
|
||||
"username", username,
|
||||
"password", password
|
||||
));
|
||||
HttpResponse<String> uResp = post("/users/apiKeyForCreds", d);
|
||||
if (uResp == null) return false;
|
||||
System.out.println(uResp.body()+": "+d);
|
||||
if (uResp.statusCode() != 200) return false;
|
||||
return loginWithKey(uResp.body());
|
||||
}
|
||||
public static boolean putItem(ItemStack stack) {
|
||||
HttpResponse<String> a = request("/items","PUT", HttpRequest.BodyPublishers.ofString(gson.toJson(Map.of(
|
||||
"itemName", Registry.ITEM.getId(stack.getItem()).getPath(),
|
||||
"itemNbt", new String(Base64.getEncoder().encode(stack.getOrCreateNbt().toString().getBytes(StandardCharsets.UTF_8)))
|
||||
))));
|
||||
if (a == null) return false;
|
||||
System.out.println(a.body());
|
||||
return a.statusCode() == 200;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue