diff --git a/pom.xml b/pom.xml index 429ce0f7..e3794548 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.namelessmc - NamelessAPI + java-api canary diff --git a/src/com/namelessmc/NamelessAPI/NamelessAPI.java b/src/com/namelessmc/NamelessAPI/NamelessAPI.java deleted file mode 100644 index dfbf3a06..00000000 --- a/src/com/namelessmc/NamelessAPI/NamelessAPI.java +++ /dev/null @@ -1,280 +0,0 @@ -package com.namelessmc.NamelessAPI; - -import java.io.UnsupportedEncodingException; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import com.namelessmc.NamelessAPI.Request.Action; -import com.namelessmc.NamelessAPI.Website.Update; - -public final class NamelessAPI { - - private static final String DEFAULT_USER_AGENT = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"; - - public static boolean DEBUG_MODE = false; - - private final URL apiUrl; - - private String userAgent = null; - - /** - * @param apiUrl URL of API to connect to, in the format http(s)://yoursite.com/index.php?route=/api/v2/API_KEY - * @param debug If debug is set to true, debug messages are enabled for every NamelessAPI instance. - */ - public NamelessAPI(final URL apiUrl, final boolean debug) { - if (debug) { - DEBUG_MODE = true; - } - this.apiUrl = apiUrl; - this.userAgent = DEFAULT_USER_AGENT; - } - - /** - * @param host URL of your website, in the format http(s)://yoursite.com - * @param apiKey API key - * @param debug If debug is set to true, debug messages are enabled for every NamelessAPI instance. - * @throws MalformedURLException - */ - public NamelessAPI(final String host, final String apiKey, final boolean debug) throws MalformedURLException { - if (debug) { - DEBUG_MODE = true; - } - - this.apiUrl = new URL(host + "/index.php?route=/api/v2/" + apiKey); - this.userAgent = DEFAULT_USER_AGENT; - } - - /** - * Checks if a web API connection can be established - * @return - * - */ - public NamelessException checkWebAPIConnection() { - try { - final Request request = new Request(this.apiUrl, this.userAgent, Action.INFO); - request.connect(); - - if (request.hasError()) { - throw new ApiError(request.getError()); - } - - final JsonObject response = request.getResponse(); - if (response.has("nameless_version")) { - return null; - } else { - return new NamelessException("Invalid respose: " + response.getAsString()); - } - } catch (final NamelessException e) { - return e; - } - } - - /** - * Get all announcements - * @return list of current announcements - * @throws NamelessException if there is an error in the request - */ - public List getAnnouncements() throws NamelessException { - final Request request = new Request(this.apiUrl, this.userAgent, Action.GET_ANNOUNCEMENTS); - request.connect(); - - if (request.hasError()) { - throw new ApiError(request.getError()); - } - - final List announcements = new ArrayList<>(); - - final JsonObject object = request.getResponse(); - object.getAsJsonArray().forEach((element) -> { - final JsonObject announcementJson = element.getAsJsonObject(); - final String content = announcementJson.get("content").getAsString(); - final String[] display = jsonToArray(announcementJson.get("display").getAsJsonArray()); - final String[] permissions = jsonToArray(announcementJson.get("permissions").getAsJsonArray()); - announcements.add(new Announcement(content, display, permissions)); - }); - - return announcements; - } - - /** - * Get all announcements visible for the player with the specified uuid - * @param uuid UUID of player to get visibile announcements for - * @return list of current announcements visible to the player - * @throws NamelessException if there is an error in the request - */ - public List getAnnouncements(final UUID uuid) throws NamelessException { - final Request request = new Request(this.apiUrl, this.userAgent, Action.GET_ANNOUNCEMENTS, new ParameterBuilder().add("uuid", uuid).build()); - request.connect(); - - if (request.hasError()) { - throw new ApiError(request.getError()); - } - - final List announcements = new ArrayList<>(); - - request.getResponse().get("announcements").getAsJsonArray().forEach((element) -> { - final JsonObject announcementJson = element.getAsJsonObject(); - final String content = announcementJson.get("content").getAsString(); - final String[] display = jsonToArray(announcementJson.get("display").getAsJsonArray()); - final String[] permissions = jsonToArray(announcementJson.get("permissions").getAsJsonArray()); - announcements.add(new Announcement(content, display, permissions)); - }); - - return announcements; - } - - public void submitServerInfo(final String jsonData) throws NamelessException { - final Request request = new Request(this.apiUrl, this.userAgent, Action.SERVER_INFO, new ParameterBuilder().add("info", jsonData).build()); - request.connect(); - if (request.hasError()) { - throw new ApiError(request.getError()); - } - } - - public Website getWebsite() throws NamelessException { - final Request request = new Request(this.apiUrl, this.userAgent, Action.INFO); - request.connect(); - - if (request.hasError()) { - throw new ApiError(request.getError()); - } - - final JsonObject json = request.getResponse(); - - final String version = json.get("nameless_version").getAsString(); - - final String[] modules = jsonToArray(json.get("modules").getAsJsonArray()); - - final JsonObject updateJson = json.get("version_update").getAsJsonObject(); - final boolean updateAvailable = updateJson.get("update").getAsBoolean(); - Update update; - if (updateAvailable) { - final String updateVersion = updateJson.get("version").getAsString(); - final boolean isUrgent = updateJson.get("urgent").getAsBoolean(); - update = new Update(isUrgent, updateVersion); - } else { - update = null; - } - - return new Website(version, update, modules); - - } - - public boolean validateUser(final UUID uuid, final String code) throws NamelessException { - final String[] parameters = new ParameterBuilder().add("uuid", uuid.toString()).add("code", code).build(); - final Request request = new Request(this.apiUrl, this.userAgent, Action.VALIDATE_USER, parameters); - request.connect(); - if (request.hasError()) { - final int errorCode = request.getError(); - if (errorCode == 28) { - return false; - } - throw new ApiError(errorCode); - } - return true; - } - - public NamelessPlayer getPlayer(final UUID uuid) throws NamelessException { - return new NamelessPlayer(uuid, this.apiUrl, this.userAgent); - } - - public Map getRegisteredUsers(final boolean hideInactive, final boolean hideBanned) throws NamelessException { - final Request request = new Request(this.apiUrl, this.userAgent, Action.LIST_USERS); - request.connect(); - if (request.hasError()) { - throw new ApiError(request.getError()); - } - - final Map users = new HashMap<>(); - - request.getResponse().get("users").getAsJsonArray().forEach(userJsonElement -> { - final String uuid = userJsonElement.getAsJsonObject().get("uuid").getAsString(); - final String username = userJsonElement.getAsJsonObject().get("username").getAsString(); - final String active = userJsonElement.getAsJsonObject().get("active").getAsString(); - final String banned = userJsonElement.getAsJsonObject().get("banned").getAsString(); - - if (!( - uuid.equals("none") || - hideInactive && active.equals("0") || - hideBanned && banned.equals("1") - )) { - try { - users.put(websiteUuidToJavaUuid(uuid), username); - } catch (final StringIndexOutOfBoundsException e) { - System.err.println("NamelessMC API - Skipped user with invalid UUID '" + uuid + "' (username: '" + username + "')"); - } - } - }); - - return users; - } - - public List getRegisteredUsersAsNamelessPlayerList(final boolean hideInactive, final boolean hideBanned) throws NamelessException { - final Map users = this.getRegisteredUsers(hideInactive, hideBanned); - final List namelessPlayers = new ArrayList<>(); - - for (final UUID userUuid : users.keySet()) { - namelessPlayers.add(this.getPlayer(userUuid)); - } - - return namelessPlayers; - } - - public void setUserAgent(final String userAgent) { - this.userAgent = userAgent; - } - - /** - * - * @return Configured user agent or {@code null} if not configured. - */ - public String getUserAgent() { - return this.userAgent; - } - - static String encode(final Object object) { - try { - return URLEncoder.encode(object.toString(), "UTF-8"); - } catch (final UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage()); - } - } - - static String[] jsonToArray(final JsonArray jsonArray) { - final List list = new ArrayList<>(); - jsonArray.iterator().forEachRemaining((element) -> list.add(element.getAsString())); - return list.toArray(new String[] {}); - } - - static UUID websiteUuidToJavaUuid(final String uuid) { - // Add dashes to uuid - // https://bukkit.org/threads/java-adding-dashes-back-to-minecrafts-uuids.272746/ - StringBuffer sb = new StringBuffer(uuid); - sb.insert(8, "-"); - - sb = new StringBuffer(sb.toString()); - sb.insert(13, "-"); - - sb = new StringBuffer(sb.toString()); - sb.insert(18, "-"); - - sb = new StringBuffer(sb.toString()); - sb.insert(23, "-"); - - return UUID.fromString(sb.toString()); - } - - -} \ No newline at end of file diff --git a/src/com/namelessmc/NamelessAPI/NamelessPlayer.java b/src/com/namelessmc/NamelessAPI/NamelessPlayer.java deleted file mode 100644 index 450c35cb..00000000 --- a/src/com/namelessmc/NamelessAPI/NamelessPlayer.java +++ /dev/null @@ -1,281 +0,0 @@ -package com.namelessmc.NamelessAPI; - -import java.net.URL; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.UUID; - -import com.google.gson.JsonObject; -import com.namelessmc.NamelessAPI.Notification.NotificationType; -import com.namelessmc.NamelessAPI.Request.Action; - -public final class NamelessPlayer { - - private String userName; - private String displayName; - private final UUID uuid; - private int groupID; - private int reputation; - private Date registeredDate; - private boolean exists; - private boolean validated; - private boolean banned; - private String groupName; - - private final URL baseUrl; - private final String userAgent; - - /** - * Creates a new NamelessPlayer object. This constructor should not be called in the main server thread. - * @param uuid - * @param baseUrl Base API URL: http(s)://yoursite.com/api/v2/API_KEY - * @throws NamelessException - */ - NamelessPlayer(final UUID uuid, final URL baseUrl, final String userAgent) throws NamelessException { - this.uuid = uuid; - this.baseUrl = baseUrl; - this.userAgent = userAgent; - - final Request request = new Request(baseUrl, userAgent, Action.USER_INFO, new ParameterBuilder().add("uuid", uuid).build()); - this.init(request); - } - - private void init(final Request request) throws NamelessException { - request.connect(); - - if (request.hasError()) throw new ApiError(request.getError()); - - final JsonObject response = request.getResponse(); - - this.exists = response.get("exists").getAsBoolean(); - - if (!this.exists) - return; - - // Convert UNIX timestamp to date - final Date registered = new Date(Long.parseLong(response.get("registered").toString().replaceAll("^\"|\"$", "")) * 1000); - - this.userName = response.get("username").getAsString(); - this.displayName = response.get("displayname").getAsString(); - //uuid = UUID.fromString(addDashesToUUID(response.get("uuid").getAsString())); - this.groupName = response.get("group_name").getAsString(); - this.groupID = response.get("group_id").getAsInt(); - this.registeredDate = registered; - this.validated = response.get("validated").getAsBoolean(); - //reputation = response.get("reputation").getAsInt(); - this.reputation = 0; // temp until reputation is added to API - this.banned = response.get("banned").getAsBoolean(); - } - - /*public static String addDashesToUUID(String uuid) { - // https://bukkit.org/threads/java-adding-dashes-back-to-minecrafts-uuids.272746/ - StringBuffer sb = new StringBuffer(uuid); - sb.insert(8, "-"); - - sb = new StringBuffer(sb.toString()); - sb.insert(13, "-"); - - sb = new StringBuffer(sb.toString()); - sb.insert(18, "-"); - - sb = new StringBuffer(sb.toString()); - sb.insert(23, "-"); - - return sb.toString(); - }*/ - - /** - * @return The Minecraft username associated with the provided UUID. This is not always the name displayed on the website. - * @see #getDisplayName() - */ - public String getUsername() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.userName; - } - - /** - * @return The name this player uses on the website. This is not always the same as their Minecraft username. - * @see #getUsername() - */ - public String getDisplayName() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.displayName; - } - - /** - * @return Minecraft UUID of this player. - * @see #getUsername() - */ - public UUID getUniqueId() { - return this.uuid; - } - - /** - * @return A numerical group id. - */ - public int getGroupID() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.groupID; - } - - /** - * @return The user's primary group name - */ - public String getGroupName() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.groupName; - } - - /** - * @return The user's site reputation. - */ - public int getReputation() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.reputation; - } - - /** - * @return The date the user registered on the website. - */ - public Date getRegisteredDate() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.registeredDate; - } - - /** - * @return Whether an account associated with the UUID exists. - * @see #getUniqueId() - */ - public boolean exists() { - return this.exists; - } - - /** - * @return Whether this account has been validated. An account is validated when a password is set. - */ - public boolean isValidated() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.validated; - } - - /** - * @return Whether this account is banned from the website. - */ - public boolean isBanned() { - if (!this.exists) - throw new UnsupportedOperationException("This player does not exist."); - - return this.banned; - } - - /** - * @param code - * @return True if the user could be validated successfully, false if the provided code is wrong - * @throws NamelessException - * @throws - */ - public boolean validate(final String code) throws NamelessException { - final String[] params = new ParameterBuilder() - .add("uuid", this.uuid) - .add("code", code).build(); - final Request request = new Request(this.baseUrl, this.userAgent, Action.VALIDATE_USER, params); - request.connect(); - - if (request.hasError()) { - if (request.getError() == ApiError.INVALID_VALIDATE_CODE) - return false; - else - throw new ApiError(request.getError()); - } else - return true; - } - - public List getNotifications() throws NamelessException { - final Request request = new Request(this.baseUrl, this.userAgent, Action.GET_NOTIFICATIONS, new ParameterBuilder().add("uuid", this.uuid).build()); - request.connect(); - - if (request.hasError()) throw new ApiError(request.getError()); - - final List notifications = new ArrayList<>(); - - final JsonObject object = request.getResponse(); - object.getAsJsonArray("notifications").forEach((element) -> { - final String message = element.getAsJsonObject().get("message").getAsString(); - final String url = element.getAsJsonObject().get("url").getAsString(); - final NotificationType type = NotificationType.fromString(element.getAsJsonObject().get("type").getAsString()); - notifications.add(new Notification(message, url, type)); - }); - - return notifications; - } - - /** - * Sets the players group - * @param groupId Numerical ID associated with a group - * @throws NamelessException - */ - public void setGroup(final int groupId) throws NamelessException { - final String[] parameters = new ParameterBuilder().add("uuid", this.uuid).add("group_id", groupId).build(); - final Request request = new Request(this.baseUrl, this.userAgent, Action.SET_GROUP, parameters); - request.connect(); - if (request.hasError()) throw new ApiError(request.getError()); - } - - /** - * Registers a new account. The player will be sent an email to set a password. - * @param minecraftName In-game name for this player - * @param email Email address - * @return Email verification disabled: A link which the user needs to click to complete registration - *
Email verification enabled: An empty string (the user needs to check their email to complete registration) - * @throws NamelessException - */ - public String register(final String minecraftName, final String email) throws NamelessException { - final String[] parameters = new ParameterBuilder().add("username", minecraftName).add("uuid", this.uuid).add("email", email).build(); - final Request request = new Request(this.baseUrl, this.userAgent, Action.REGISTER, parameters); - request.connect(); - - if (request.hasError()) throw new ApiError(request.getError()); - - final JsonObject response = request.getResponse(); - - if (response.has("link")) - return response.get("link").getAsString(); - else - return ""; - } - - /** - * Reports a player - * @param reportedUuid UUID of the reported player - * @param reportedUsername In-game name of the reported player - * @param reason Reason why this player has been reported - * @throws NamelessException - */ - public void createReport(final UUID reportedUuid, final String reportedUsername, final String reason) throws NamelessException { - final String[] parameters = new ParameterBuilder() - .add("reporter_uuid", this.uuid) - .add("reported_uuid", reportedUuid) - .add("reported_username", reportedUsername) - .add("content", reason) - .build(); - final Request request = new Request(this.baseUrl, this.userAgent, Action.CREATE_REPORT, parameters); - request.connect(); - if (request.hasError()) throw new ApiError(request.getError()); - } - -} \ No newline at end of file diff --git a/src/com/namelessmc/NamelessAPI/ParameterBuilder.java b/src/com/namelessmc/NamelessAPI/ParameterBuilder.java deleted file mode 100644 index e06bbf19..00000000 --- a/src/com/namelessmc/NamelessAPI/ParameterBuilder.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.namelessmc.NamelessAPI; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class ParameterBuilder { - - private Map parameters; - - public ParameterBuilder() { - parameters = new HashMap<>(); - } - - public ParameterBuilder add(String key, Object value) { - parameters.put(key, value.toString()); - return this; - } - - public String[] build() { - List parameterStrings = new ArrayList<>(); - - parameters.entrySet().forEach((entry) -> { - parameterStrings.add(entry.getKey() + "=" + encode(entry.getValue())); - }); - - return parameterStrings.toArray(new String[] {}); - } - - private static String encode(Object object) { - try { - return URLEncoder.encode(object.toString(), "UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException(e.getMessage()); - } - } - -} diff --git a/src/com/namelessmc/NamelessAPI/Request.java b/src/com/namelessmc/NamelessAPI/Request.java deleted file mode 100644 index f109065c..00000000 --- a/src/com/namelessmc/NamelessAPI/Request.java +++ /dev/null @@ -1,144 +0,0 @@ -package com.namelessmc.NamelessAPI; - -import static com.namelessmc.NamelessAPI.Request.RequestMethod.GET; -import static com.namelessmc.NamelessAPI.Request.RequestMethod.POST; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.Reader; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.charset.Charset; - -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; - -public class Request { - - private URL url; - private final RequestMethod method; - private final String parameters; - private final Action action; - private final String userAgent; - - private JsonObject response; - private boolean hasError; - private int errorCode = -1; - - public Request(final URL baseUrl, final String userAgent, final Action action, final String... parameters) { - this.userAgent = userAgent; - this.action = action; - this.method = action.method; - this.parameters = String.join("&", parameters); - - try { - final String base = baseUrl.toString() + "/" + action.toString(); - - if (action.method == RequestMethod.GET && parameters.length > 0) { - this.url = new URL(base + "&" + this.parameters); - } else { - this.url = new URL(base); - } - } catch (final MalformedURLException e) { - final IllegalArgumentException ex = new IllegalArgumentException("URL is malformed (" + e.getMessage() + ")"); - ex.initCause(e); - throw ex; - } - } - - public boolean hasError() { - return this.hasError; - } - - public int getError() throws NamelessException { - if (!this.hasError) { - throw new NamelessException("Requested error code but there is no error."); - } - - return this.errorCode; - } - - public JsonObject getResponse() throws NamelessException { - return this.response; - } - - public void connect() throws NamelessException { - if (NamelessAPI.DEBUG_MODE) { - System.out.println(String.format("NamelessAPI > Making %s request (%s", this.action.toString(), this.method.toString())); - System.out.println(String.format("NamelessAPI > URL: %s", this.url)); - System.out.println(String.format("NamelessAPI > Parameters: %s", this.parameters)); - } - - try { - final HttpURLConnection connection = (HttpURLConnection) this.url.openConnection(); - - connection.setRequestMethod(this.method.toString()); - connection.addRequestProperty("User-Agent", this.userAgent); - - - if (this.method == RequestMethod.POST) { - final byte[] encodedMessage = this.parameters.getBytes(Charset.forName("UTF-8")); - connection.setRequestProperty("Content-Length", encodedMessage.length + ""); - connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); - connection.setDoOutput(true); - try (OutputStream out = connection.getOutputStream()){ - out.write(encodedMessage); - } - } - - try (InputStream in = connection.getInputStream(); - Reader reader = new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8"))){ - JsonParser.parseReader(reader).getAsJsonObject(); - } - - connection.disconnect(); - - this.hasError = this.response.get("error").getAsBoolean(); - if (this.hasError) { - this.errorCode = this.response.get("code").getAsInt(); - } - } catch (final IOException e) { - throw new NamelessException(e); - } - } - - public enum Action { - - INFO("info", GET), - GET_ANNOUNCEMENTS("getAnnouncements", GET), - REGISTER("register", POST), - USER_INFO("userInfo", GET), - SET_GROUP("setGroup", POST), - CREATE_REPORT("createReport", POST), - GET_NOTIFICATIONS("getNotifications", GET), - SERVER_INFO("serverInfo", POST), - VALIDATE_USER("validateUser", POST), - LIST_USERS("listUsers", GET), - - ; - - RequestMethod method; - String name; - - Action(final String name, final RequestMethod method){ - this.name = name; - this.method = method; - } - - @Override - public String toString() { - return this.name; - } - - } - - public enum RequestMethod { - - GET, POST - - } - -} diff --git a/src/com/namelessmc/NamelessAPI/Announcement.java b/src/com/namelessmc/java_api/Announcement.java similarity index 93% rename from src/com/namelessmc/NamelessAPI/Announcement.java rename to src/com/namelessmc/java_api/Announcement.java index 92b00168..c64c8d8c 100644 --- a/src/com/namelessmc/NamelessAPI/Announcement.java +++ b/src/com/namelessmc/java_api/Announcement.java @@ -1,4 +1,4 @@ -package com.namelessmc.NamelessAPI; +package com.namelessmc.java_api; public class Announcement { diff --git a/src/com/namelessmc/NamelessAPI/ApiError.java b/src/com/namelessmc/java_api/ApiError.java similarity index 92% rename from src/com/namelessmc/NamelessAPI/ApiError.java rename to src/com/namelessmc/java_api/ApiError.java index dd7bacaa..58c008ce 100644 --- a/src/com/namelessmc/NamelessAPI/ApiError.java +++ b/src/com/namelessmc/java_api/ApiError.java @@ -1,4 +1,4 @@ -package com.namelessmc.NamelessAPI; +package com.namelessmc.java_api; public class ApiError extends NamelessException { @@ -34,15 +34,15 @@ public class ApiError extends NamelessException { private static final long serialVersionUID = 3093028909912281912L; - private int code; + private final int code; - public ApiError(int code) { + public ApiError(final int code) { super("An API error occured with error code " + code); this.code = code; } - public int getErrorCode() { - return code; + public int getError() { + return this.code; } } diff --git a/src/com/namelessmc/java_api/Group.java b/src/com/namelessmc/java_api/Group.java new file mode 100644 index 00000000..b3672700 --- /dev/null +++ b/src/com/namelessmc/java_api/Group.java @@ -0,0 +1,35 @@ +package com.namelessmc.java_api; + +import com.google.gson.JsonObject; + +public class Group { + + private final int id; + private final String name; + private final boolean primary; + + Group(final int id, final String name, final boolean primary) { + this.id = id; + this.name = name; + this.primary = primary; + } + + Group(final JsonObject group) { + this.id = group.get("id").getAsInt(); + this.name = group.get("name").getAsString(); + this.primary = group.has("primary") ? group.get("primary").getAsBoolean() : false; + } + + public int getId() { + return this.id; + } + + public String getName() { + return this.name; + } + + public boolean isPrimary() { + return this.primary; + } + +} diff --git a/src/com/namelessmc/java_api/NamelessAPI.java b/src/com/namelessmc/java_api/NamelessAPI.java new file mode 100644 index 00000000..47359f2e --- /dev/null +++ b/src/com/namelessmc/java_api/NamelessAPI.java @@ -0,0 +1,320 @@ +package com.namelessmc.java_api; + +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.namelessmc.java_api.RequestHandler.Action; +import com.namelessmc.java_api.Website.Update; + +public final class NamelessAPI { + + private static final String DEFAULT_USER_AGENT = "Nameless-Java-API/beta"; // TODO include mavenversion string + + private final RequestHandler requests; + + public NamelessAPI(final URL apiUrl) { + this(apiUrl, DEFAULT_USER_AGENT); + } + + /** + * @param apiUrl URL of API to connect to, in the format http(s)://yoursite.com/index.php?route=/api/v2/API_KEY + * @param debug + */ + public NamelessAPI(final URL apiUrl, final boolean debug) { + this(apiUrl, DEFAULT_USER_AGENT, debug); + } + + public NamelessAPI(final URL apiUrl, final String userAgent) { + this(apiUrl, userAgent, false); + } + + /** + * @param host URL of your website, in the format http(s)://yoursite.com + * @param apiKey API key + * @param debug + * @throws MalformedURLException + */ + public NamelessAPI(final String host, final String apiKey, final String userAgent, final boolean debug) throws MalformedURLException { + this(new URL(host + "/index.php?route=/api/v2/" + apiKey), userAgent, debug); + } + + public NamelessAPI(final String host, final String apiKey, final boolean debug) throws MalformedURLException { + this(host, apiKey, DEFAULT_USER_AGENT, debug); + } + + public NamelessAPI(final String host, final String apiKey, final String userAgent) throws MalformedURLException { + this(host, apiKey, userAgent, false); + } + + public NamelessAPI(final String host, final String apiKey) throws MalformedURLException { + this(host, apiKey, DEFAULT_USER_AGENT); + } + + public NamelessAPI(final URL apiUrl, final String userAgent, final boolean debug) { + this.requests = new RequestHandler(apiUrl, userAgent, debug); + } + + RequestHandler getRequestHandler() { + return this.requests; + } + + /** + * Checks if a web API connection can be established + * throws {@link NamelessException} if the connection was unsuccessful + */ + public void checkWebAPIConnection() throws NamelessException { + final JsonObject response = this.requests.get(Action.INFO); + if (!response.has("nameless_version")) { + throw new NamelessException("Invalid respose: " + response.getAsString()); + } + } + + /** + * Get all announcements + * @return list of current announcements + * @throws NamelessException if there is an error in the request + */ + public List getAnnouncements() throws NamelessException { + final JsonObject response = this.requests.get(Action.GET_ANNOUNCEMENTS); + + final List announcements = new ArrayList<>(); + + response.getAsJsonArray().forEach((element) -> { + final JsonObject announcementJson = element.getAsJsonObject(); + final String content = announcementJson.get("content").getAsString(); + final String[] display = jsonToArray(announcementJson.get("display").getAsJsonArray()); + final String[] permissions = jsonToArray(announcementJson.get("permissions").getAsJsonArray()); + announcements.add(new Announcement(content, display, permissions)); + }); + + return announcements; + } + + /** + * Get all announcements visible for the player with the specified uuid + * @param uuid UUID of player to get visibile announcements for + * @return list of current announcements visible to the player + * @throws NamelessException if there is an error in the request + */ + public List getAnnouncements(final NamelessUser user) throws NamelessException { + final JsonObject response = this.requests.get(Action.GET_ANNOUNCEMENTS, "id", user.getId()); + + final List announcements = new ArrayList<>(); + + response.get("announcements").getAsJsonArray().forEach((element) -> { + final JsonObject announcementJson = element.getAsJsonObject(); + final String content = announcementJson.get("content").getAsString(); + final String[] display = jsonToArray(announcementJson.get("display").getAsJsonArray()); + final String[] permissions = jsonToArray(announcementJson.get("permissions").getAsJsonArray()); + announcements.add(new Announcement(content, display, permissions)); + }); + + return announcements; + } + + public void submitServerInfo(final String jsonData) throws NamelessException { + this.requests.post(Action.SERVER_INFO, jsonData); + } + + public Website getWebsite() throws NamelessException { + final JsonObject json = this.requests.get(Action.INFO); + + final String version = json.get("nameless_version").getAsString(); + + final String[] modules = jsonToArray(json.get("modules").getAsJsonArray()); + + final JsonObject updateJson = json.get("version_update").getAsJsonObject(); + final boolean updateAvailable = updateJson.get("update").getAsBoolean(); + Update update; + if (updateAvailable) { + final String updateVersion = updateJson.get("version").getAsString(); + final boolean isUrgent = updateJson.get("urgent").getAsBoolean(); + update = new Update(isUrgent, updateVersion); + } else { + update = null; + } + + return new Website(version, update, modules); + + } + + public List getRegisteredUsers(final UserFilter... filters) throws NamelessException { + final List parameters = new ArrayList<>(); + for (final UserFilter filter : filters) { + parameters.add(filter.getName()); + parameters.add(filter.getValue().toString()); + } + final JsonObject response = this.requests.get(Action.LIST_USERS, parameters); + final JsonArray array = response.getAsJsonArray("users"); + final List users = new ArrayList<>(array.size()); + for (final JsonElement e : array) { + final JsonObject o = e.getAsJsonObject(); + final int id = o.get("id").getAsInt(); + final String username = o.get("username").getAsString(); + Optional uuid; + if (o.has("uuid")) { + uuid = Optional.of(NamelessAPI.websiteUuidToJavaUuid(o.get("uuid").getAsString())); + } else { + uuid = Optional.empty(); + } + users.add(new NamelessUser(this, id, username, uuid)); + }; + return Collections.unmodifiableList(users); + } + + public Optional getUser(final int id) throws NamelessException { + final NamelessUser user = getUserLazy(id); + if (user.exists()) { + return Optional.of(user); + } else { + return Optional.empty(); + } + } + + public Optional getUser(final String username) throws NamelessException { + final NamelessUser user = getUserLazy(username); + if (user.exists()) { + return Optional.of(user); + } else { + return Optional.empty(); + } + } + + public Optional getUser(final UUID uuid) throws NamelessException { + final NamelessUser user = getUserLazy(uuid); + if (user.exists()) { + return Optional.of(user); + } else { + return Optional.empty(); + } + } + + public NamelessUser getUserLazy(final int id) throws NamelessException { + return new NamelessUser(this, id, null, null); + } + + public NamelessUser getUserLazy(final String username) throws NamelessException { + return new NamelessUser(this, null, username, null); + } + + public NamelessUser getUserLazy(final UUID uuid) throws NamelessException { + return new NamelessUser(this, null, null, Optional.of(uuid)); + } + + public NamelessUser getUserLazy(final String username, final UUID uuid) throws NamelessException { + return new NamelessUser(this, null, null, Optional.of(uuid)); + } + + public NamelessUser getUserLazy(final int id, final String username, final UUID uuid) throws NamelessException { + return new NamelessUser(this, id, username, Optional.of(uuid)); + } + + public Optional getUserByDiscordId(final long id) throws NamelessException { + try { + final JsonObject response = this.requests.get(Action.GET_USER_BY_DISCORD_ID, "discord_id", id); + return Optional.of(new NamelessUser(this, response.get("id").getAsInt(), null, null)); + } catch (final ApiError e) { + if (e.getError() == ApiError.UNABLE_TO_FIND_USER) { + return Optional.empty(); + } else { + throw e; + } + } + } + + public void submitRankList(final List rankNames) { + + } + + public Optional getGroup(final int id) throws NamelessException { + final JsonObject response = this.requests.get(Action.GROUP_INFO, "id", id); + if (!response.has("group")) { + return Optional.empty(); + } else { + return Optional.of(new Group(response.getAsJsonObject("group"))); + } + } + + public Optional getGroup(final String name) throws NamelessException { + final JsonObject response = this.requests.get(Action.GROUP_INFO, "name", name); + if (!response.has("group")) { + return Optional.empty(); + } else { + return Optional.of(new Group(response.getAsJsonObject("group"))); + } + } + + /** + * Registers a new account. The user will be sent an email to set a password. + * @param username Username + * @param email Email address + * @return Email verification disabled: A link which the user needs to click to complete registration + *
Email verification enabled: An empty string (the user needs to check their email to complete registration) + * @throws NamelessException + */ + public Optional registerUser(final String username, final String email, final UUID uuid) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("username", username); + post.addProperty("email", email); + if (uuid != null) { + post.addProperty("uuid", uuid.toString()); + } + + final JsonObject response = this.requests.post(Action.REGISTER, post.toString()); + + if (response.has("link")) { + return Optional.of(response.get("link").getAsString()); + } else { + return Optional.empty(); + } + } + + public Optional registerUser(final String username, final String email) throws NamelessException { + return registerUser(username, email, null); + } + + static String encode(final Object object) { + try { + return URLEncoder.encode(object.toString(), "UTF-8"); + } catch (final UnsupportedEncodingException e) { + throw new RuntimeException(e.getMessage()); + } + } + + @Deprecated + static String[] jsonToArray(final JsonArray jsonArray) { + final List list = new ArrayList<>(); + jsonArray.iterator().forEachRemaining((element) -> list.add(element.getAsString())); + return list.toArray(new String[] {}); + } + + static UUID websiteUuidToJavaUuid(final String uuid) { + // Add dashes to uuid + // https://bukkit.org/threads/java-adding-dashes-back-to-minecrafts-uuids.272746/ + StringBuffer sb = new StringBuffer(uuid); + sb.insert(8, "-"); + + sb = new StringBuffer(sb.toString()); + sb.insert(13, "-"); + + sb = new StringBuffer(sb.toString()); + sb.insert(18, "-"); + + sb = new StringBuffer(sb.toString()); + sb.insert(23, "-"); + + return UUID.fromString(sb.toString()); + } + + +} \ No newline at end of file diff --git a/src/com/namelessmc/NamelessAPI/NamelessException.java b/src/com/namelessmc/java_api/NamelessException.java similarity index 93% rename from src/com/namelessmc/NamelessAPI/NamelessException.java rename to src/com/namelessmc/java_api/NamelessException.java index c94becb5..d0a4e778 100644 --- a/src/com/namelessmc/NamelessAPI/NamelessException.java +++ b/src/com/namelessmc/java_api/NamelessException.java @@ -1,4 +1,4 @@ -package com.namelessmc.NamelessAPI; +package com.namelessmc.java_api; /** * Generic exception thrown by many methods in the Nameless API diff --git a/src/com/namelessmc/java_api/NamelessUser.java b/src/com/namelessmc/java_api/NamelessUser.java new file mode 100644 index 00000000..0c8d5a4e --- /dev/null +++ b/src/com/namelessmc/java_api/NamelessUser.java @@ -0,0 +1,311 @@ +package com.namelessmc.java_api; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.UUID; +import java.util.stream.StreamSupport; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.namelessmc.java_api.Notification.NotificationType; +import com.namelessmc.java_api.RequestHandler.Action; + +public final class NamelessUser { + + private final NamelessAPI api; + private final RequestHandler requests; + + private Integer id; + private String username; + private Optional uuid; + + private JsonObject userInfo; + + // only one of id, username, uuid has to be provided + NamelessUser(final NamelessAPI api, final Integer id, final String username, final Optional uuid) throws NamelessException { + this.api = api; + this.requests = api.getRequestHandler(); + + if (id == null && username == null && uuid == null) { + throw new IllegalArgumentException("You must specify at least one of ID, uuid, username"); + } + + this.id = id; + this.username = username; + this.uuid = uuid; + } + + private void loadUserInfo() throws NamelessException { + final JsonObject response; + if (this.id != null) { + response = this.requests.get(Action.USER_INFO, "id", this.id); + } else if (this.uuid != null && this.uuid.isPresent()) { + response = this.requests.get(Action.USER_INFO, "uuid", this.uuid.get()); + } else if (this.username != null) { + response = this.requests.get(Action.USER_INFO, "username", this.username); + } else { + throw new IllegalStateException("ID, uuid, and username not known for this player."); + } + + if (!response.get("exists").getAsBoolean()) { + throw new UserNotExistException(); + } + + this.userInfo = response; + } + + public NamelessAPI getApi() { + return this.api; + } + + public int getId() throws NamelessException { + if (this.id == null) { + this.loadUserInfo(); + this.id = this.userInfo.get("id").getAsInt(); + } + + return this.id; + } + + public String getUsername() throws NamelessException { + if (this.username == null) { + this.loadUserInfo(); + this.username = this.userInfo.get("username").getAsString(); + } + + return this.username; + } + + public Optional getUniqueId() throws NamelessException { + if (this.uuid == null) { + this.loadUserInfo(); + if (this.userInfo.has("uuid")) { + this.uuid = Optional.of(NamelessAPI.websiteUuidToJavaUuid(this.userInfo.get("uuid").getAsString())); + } else { + this.uuid = Optional.empty(); + } + } + + return this.uuid; + } + + public boolean exists() throws NamelessException { + if (this.userInfo == null) { + try { + loadUserInfo(); + } catch (final UserNotExistException e) { + return false; + } + } + + return true; + } + + public String getDisplayName() throws NamelessException { + if (this.userInfo == null) { + this.loadUserInfo(); + } + + return this.userInfo.get("displayname").getAsString(); + } + + + /** + * @return The date the user registered on the website. + * @throws NamelessException + */ + public Date getRegisteredDate() throws NamelessException { + if (this.userInfo == null) { + this.loadUserInfo(); + } + + return new Date(Long.parseLong(this.userInfo.get("registered").toString().replaceAll("^\"|\"$", "")) * 1000); + } + + /** + * @return Whether this account is banned from the website. + * @throws NamelessException + */ + public boolean isBanned() throws NamelessException { + if (this.userInfo == null) { + this.loadUserInfo(); + } + + return this.userInfo.get("banned").getAsBoolean(); + } + + public boolean isVerified() throws NamelessException { + if (this.userInfo == null) { + this.loadUserInfo(); + } + + return this.userInfo.get("verified").getAsBoolean(); + } + + public VerificationInfo getVerificationInfo() throws NamelessException { + final boolean verified = isVerified(); + final JsonObject verification = this.userInfo.getAsJsonObject("verification"); + return new VerificationInfo(verified, verification); + } + + public Group getPrimaryGroup() throws NamelessException { + if (this.userInfo == null) { + this.loadUserInfo(); + } + + final JsonObject groups = this.userInfo.getAsJsonObject("groups"); + final JsonObject primary = groups.getAsJsonObject("primary"); + return new Group(primary.get("id").getAsInt(), primary.get("name").getAsString(), true); + } + + public List getSecondaryGroups() throws NamelessException { + if (this.userInfo == null) { + this.loadUserInfo(); + } + + final JsonObject groups = this.userInfo.getAsJsonObject("groups"); + final List secondaryGroups = new ArrayList<>(); + groups.getAsJsonArray("secondary").forEach(e -> { + final JsonObject group = e.getAsJsonObject(); + secondaryGroups.add(new Group(group.get("id").getAsInt(), group.get("name").getAsString(), false)); + }); + return Collections.unmodifiableList(secondaryGroups); + } + + public List getGroups() throws NamelessException { + final List secondaryGroups = this.getSecondaryGroups(); + final List list = new ArrayList<>(secondaryGroups.size() + 1); + list.add(this.getPrimaryGroup()); + list.addAll(this.getSecondaryGroups()); + return Collections.unmodifiableList(list); + } + + public void setPrimaryGroup(final Group group) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.addProperty("group", group.getId()); + this.requests.post(Action.SET_PRIMARY_GROUP, post.toString()); + } + + public void addSecondaryGroups(final Group... groups) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.add("groups", new Gson().toJsonTree(Arrays.stream(groups).mapToInt(Group::getId).toArray())); + this.requests.post(Action.ADD_SECONDARY_GROUPS, post.toString()); + } + + public void removeSecondaryGroups(final Group... groups) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.add("groups", new Gson().toJsonTree(Arrays.stream(groups).mapToInt(Group::getId).toArray())); + this.requests.post(Action.REMOVE_SECONDARY_GROUPS, post.toString()); + } + + public int getNotificationCount() throws NamelessException { + return getNotifications().size(); // TODO more efficient method + } + + public List getNotifications() throws NamelessException { + final JsonObject response = this.requests.get(Action.GET_NOTIFICATIONS, "id", this.id); + + final List notifications = new ArrayList<>(); + response.getAsJsonArray("notifications").forEach((element) -> { + final String message = element.getAsJsonObject().get("message").getAsString(); + final String url = element.getAsJsonObject().get("url").getAsString(); + final NotificationType type = NotificationType.fromString(element.getAsJsonObject().get("type").getAsString()); + notifications.add(new Notification(message, url, type)); + }); + + return notifications; + } + + /** + * Reports a player + * @param username Username of the player or user to report + * @param reason Reason why this player has been reported + * @throws NamelessException + */ + public void createReport(final String username, final String reason) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("reporter", this.id); + post.addProperty("reported", username); + post.addProperty("content", reason); + this.requests.post(Action.CREATE_REPORT, post.toString()); + } + + /** + * @param code + * @return True if the user could be validated successfully, false if the provided code is wrong + * @throws NamelessException + * @throws + */ + public boolean verifyMinecraft(final String code) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.addProperty("code", code); + try { + this.requests.post(Action.VERIFY_MINECRAFT, post.toString()); + return true; + } catch (final ApiError e) { + if (e.getError() == ApiError.INVALID_VALIDATE_CODE) { + return false; + } else { + throw e; + } + } + } + + public void verifyDiscord(final String verificationToken) throws NamelessException { + this.requests.post(Action.VERIFY_DISCORD, verificationToken); + } + + public Optional getDiscordId() throws NamelessException { + final JsonObject response = this.requests.get(Action.GET_DISCORD_ID, "id", this.id); + if (response.has("discord_id")) { + return Optional.of(response.get("discord_id").getAsInt()); + } else { + return Optional.empty(); + } + } + + public long[] getDiscordRoles() throws NamelessException { + final JsonObject response = this.requests.get(Action.GET_DISCORD_ROLES, "id", this.id); + return StreamSupport.stream(response.getAsJsonArray("roles").spliterator(), false) + .mapToLong(JsonElement::getAsLong).toArray(); + } + + public void setDiscordRoles(final long[] roleIds) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.add("roles", new Gson().toJsonTree(roleIds)); + this.requests.post(Action.SET_DISCORD_ROLES, post.toString()); + } + + public void addDiscordRole(final long roleId) throws NamelessException { + addDiscordRoles(new long[] {roleId}); + } + + public void addDiscordRoles(final long[] roleIds) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.add("roles", new Gson().toJsonTree(roleIds)); + this.requests.post(Action.ADD_DISCORD_ROLES, post.toString()); + } + + public void removeDiscordRole(final long roleId) throws NamelessException { + removeDiscordRole(new long[] {roleId}); + } + + public void removeDiscordRole(final long[] roleIds) throws NamelessException { + final JsonObject post = new JsonObject(); + post.addProperty("id", this.id); + post.add("roles", new Gson().toJsonTree(roleIds)); + this.requests.post(Action.REMOVE_DISCORD_ROLES, post.toString()); + } + +} \ No newline at end of file diff --git a/src/com/namelessmc/NamelessAPI/Notification.java b/src/com/namelessmc/java_api/Notification.java similarity index 95% rename from src/com/namelessmc/NamelessAPI/Notification.java rename to src/com/namelessmc/java_api/Notification.java index 96f75945..2ecd44cc 100644 --- a/src/com/namelessmc/NamelessAPI/Notification.java +++ b/src/com/namelessmc/java_api/Notification.java @@ -1,4 +1,4 @@ -package com.namelessmc.NamelessAPI; +package com.namelessmc.java_api; public class Notification { diff --git a/src/com/namelessmc/java_api/RequestHandler.java b/src/com/namelessmc/java_api/RequestHandler.java new file mode 100644 index 00000000..4a4a1deb --- /dev/null +++ b/src/com/namelessmc/java_api/RequestHandler.java @@ -0,0 +1,176 @@ +package com.namelessmc.java_api; + +import static com.namelessmc.java_api.RequestHandler.RequestMethod.GET; +import static com.namelessmc.java_api.RequestHandler.RequestMethod.POST; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.Reader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +public class RequestHandler { + + private final URL baseUrl; + private final String userAgent; + + RequestHandler(final URL baseUrl, final String userAgent, final boolean debug) { + this.baseUrl = baseUrl; + this.userAgent = userAgent; + } + + public JsonObject post(final Action action, final String postData) throws NamelessException { + if (action.method != RequestMethod.POST) { + throw new IllegalArgumentException("Cannot POST to a GET API method"); + } + + URL url; + try { + url = new URL(this.baseUrl.toString() + "/" + action); + } catch (final MalformedURLException e) { + throw new NamelessException("Invalid URL or parameter string"); + } + + try { + return makeConnection(url, postData); + } catch (final IOException e) { + throw new NamelessException(e); + } + } + + public JsonObject get(final Action action, final Object... parameters) throws NamelessException { + if (action.method != RequestMethod.GET) { + throw new IllegalArgumentException("Cannot GET a POST API method"); + } + + final StringBuilder urlBuilder = new StringBuilder(this.baseUrl.toString()); + urlBuilder.append("/"); + urlBuilder.append(action); + + if (parameters.length > 0) { + if (parameters.length % 2 != 0) { + throw new IllegalArgumentException("Parameter string varargs array length must be even"); + } + + for (int i = 0; i < parameters.length; i++) { + if (i % 2 == 0) { + urlBuilder.append("&"); + urlBuilder.append(parameters[i]); + } else { + urlBuilder.append("="); + urlBuilder.append(URLEncoder.encode(parameters[i].toString(), StandardCharsets.UTF_8)); + } + } + } + + URL url; + try { + url = new URL(urlBuilder.toString()); + } catch (final MalformedURLException e) { + throw new NamelessException("Error while building request URL: " + urlBuilder); + } + + try { + return makeConnection(url, null); + } catch (final IOException e) { + throw new NamelessException(e); + } + } + + private JsonObject makeConnection(final URL url, final String postBody) throws NamelessException, IOException { + final HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.addRequestProperty("User-Agent", this.userAgent); + + if (postBody != null) { + connection.setRequestMethod("POST"); + final String contentType = postBody.startsWith("[") || postBody.startsWith("{") ? "application/json" : "text/plain"; + final byte[] encodedMessage = postBody.getBytes(StandardCharsets.UTF_8); + connection.setRequestProperty("Content-Length", encodedMessage.length + ""); + connection.setRequestProperty("Content-Type", contentType); + connection.setDoOutput(true); + try (OutputStream out = connection.getOutputStream()){ + out.write(encodedMessage); + } + } + + JsonObject response; + + try (InputStream in = connection.getInputStream(); + Reader reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8)){ + response = JsonParser.parseReader(reader).getAsJsonObject(); + } + + connection.disconnect(); + + if (!response.has("error")) { + throw new NamelessException("Unexpected response from website (missing json key 'error')"); + } + + if (response.get("error").getAsBoolean()) { + throw new ApiError(response.get("code").getAsInt()); + } + + return response; + } + + public enum Action { + + INFO("info", GET), + GET_ANNOUNCEMENTS("getAnnouncements", GET), + REGISTER("register", POST), + USER_INFO("userInfo", GET), + LIST_GROUPS("listGroups", GET), + GROUP_INFO("groupInfo", GET), + SET_PRIMARY_GROUP("setPrimaryGroup", POST), + ADD_SECONDARY_GROUPS("addSecondaryGroups", POST), + REMOVE_SECONDARY_GROUPS("setSecondaryGroups", POST), + SET_GROUP("setGroup", POST), + CREATE_REPORT("createReport", POST), + GET_NOTIFICATIONS("getNotifications", GET), + SERVER_INFO("serverInfo", POST), + UPDATE_USERNAME("updateUsername", POST), + VERIFY_MINECRAFT("verifyMinecraft", POST), + LIST_USERS("listUsers", GET), + INGAME_RANKS("ingameRanks", POST), + VERIFY_DISCORD("verifyDiscord", POST), + GET_DISCORD_ID("getDiscordId", GET), + GET_DISCORD_ROLES("getDiscordRoles", GET), + GET_USER_BY_DISCORD_ID("getUserByDiscordId", GET), + SET_DISCORD_ROLES("setDiscordRoles", POST), + ADD_DISCORD_ROLES("addDiscordRoles", POST), + REMOVE_DISCORD_ROLES("removeDiscordRoles", POST), + + ; + + RequestMethod method; + String name; + + Action(final String name, final RequestMethod post){ + this.name = name; + this.method = post; + } + + @Override + public String toString() { + return this.name; + } + + } + + + public enum RequestMethod { + + GET, POST + + } + +} diff --git a/src/com/namelessmc/java_api/UserFilter.java b/src/com/namelessmc/java_api/UserFilter.java new file mode 100644 index 00000000..1245540a --- /dev/null +++ b/src/com/namelessmc/java_api/UserFilter.java @@ -0,0 +1,30 @@ +package com.namelessmc.java_api; + +public class UserFilter { + + public static UserFilter BANNED = new UserFilter<>("banned", true); + public static UserFilter UNBANNED = new UserFilter<>("banned", true); + public static UserFilter VERIFIED = new UserFilter<>("verified", false); + public static UserFilter UNVERIFIED = new UserFilter<>("verified", false); + + private final String filterName; + private FilterValue value; + + public UserFilter(final String filterName, final FilterValue defaultValue) { + this.filterName = filterName; + this.value = defaultValue; + } + + public void value(final FilterValue value) { + this.value = value; + } + + public String getName() { + return this.filterName; + } + + public FilterValue getValue() { + return this.value; + } + +} diff --git a/src/com/namelessmc/java_api/UserNotExistException.java b/src/com/namelessmc/java_api/UserNotExistException.java new file mode 100644 index 00000000..88ce6ed5 --- /dev/null +++ b/src/com/namelessmc/java_api/UserNotExistException.java @@ -0,0 +1,7 @@ +package com.namelessmc.java_api; + +public class UserNotExistException extends NamelessException { + + private static final long serialVersionUID = 1L; + +} diff --git a/src/com/namelessmc/java_api/VerificationInfo.java b/src/com/namelessmc/java_api/VerificationInfo.java new file mode 100644 index 00000000..dbfaaaaf --- /dev/null +++ b/src/com/namelessmc/java_api/VerificationInfo.java @@ -0,0 +1,41 @@ +package com.namelessmc.java_api; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class VerificationInfo { + + private final boolean verified; + private final JsonObject json; + + VerificationInfo(final boolean verified, final JsonObject json) { + this.verified = verified; + this.json = json; + } + + public boolean isVerified() { + return this.verified; + } + + public boolean isVerifiedCustom(final String name) { + final JsonElement e = this.json.get(name); + if (e == null) { + throw new UnsupportedOperationException("The API did not return verification for '" + name + "'"); + } else { + return e.getAsBoolean(); + } + } + + public boolean isVerifiedEmail() { + return isVerifiedCustom("email"); + } + + public boolean isVerifiedMinecraft() { + return isVerifiedCustom("minecraft"); + } + + public boolean isVerifiedDiscord() { + return isVerifiedCustom("discord"); + } + +} diff --git a/src/com/namelessmc/NamelessAPI/Website.java b/src/com/namelessmc/java_api/Website.java similarity index 95% rename from src/com/namelessmc/NamelessAPI/Website.java rename to src/com/namelessmc/java_api/Website.java index 8f80ed54..6f4f4f76 100644 --- a/src/com/namelessmc/NamelessAPI/Website.java +++ b/src/com/namelessmc/java_api/Website.java @@ -1,4 +1,4 @@ -package com.namelessmc.NamelessAPI; +package com.namelessmc.java_api; public class Website {