Java tutorial
/* * Copyright (C) 2017 Bastian Oppermann * * This file is part of Javacord. * * Javacord is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * Javacord is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see <http://www.gnu.org/licenses/>. */ package de.btobastian.javacord.entities.permissions.impl; import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.JsonNode; import com.mashape.unirest.http.Unirest; import de.btobastian.javacord.ImplDiscordAPI; import de.btobastian.javacord.entities.Channel; import de.btobastian.javacord.entities.Server; import de.btobastian.javacord.entities.User; import de.btobastian.javacord.entities.VoiceChannel; import de.btobastian.javacord.entities.impl.ImplServer; import de.btobastian.javacord.entities.permissions.Permissions; import de.btobastian.javacord.entities.permissions.Role; import de.btobastian.javacord.listener.role.*; import de.btobastian.javacord.utils.LoggerUtil; import de.btobastian.javacord.utils.ratelimits.RateLimitType; import org.json.JSONObject; import org.slf4j.Logger; import java.awt.*; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; /** * The implementation of the role interface. */ public class ImplRole implements Role { /** * The logger of this class. */ private static final Logger logger = LoggerUtil.getLogger(ImplRole.class); private static final Permissions emptyPermissions = new ImplPermissions(0, 0); // key = channelId private final ConcurrentHashMap<String, Permissions> overwrittenPermissions = new ConcurrentHashMap<>(); private final ImplDiscordAPI api; private final String id; private String name; private final ImplServer server; private ImplPermissions permissions; private int position; private Color color; private boolean hoist; private boolean mentionable; private boolean managed; private final List<User> users = new ArrayList<>(); /** * Creates a new instance of this class. * * @param data A JSONObject containing all necessary data. * @param server The server of the role. * @param api The api of this server. */ public ImplRole(JSONObject data, ImplServer server, ImplDiscordAPI api) { this.server = server; this.api = api; id = data.getString("id"); name = data.getString("name"); permissions = new ImplPermissions(data.getInt("permissions")); position = data.getInt("position"); color = new Color(data.getInt("color")); hoist = data.getBoolean("hoist"); mentionable = data.getBoolean("mentionable"); managed = data.getBoolean("managed"); server.addRole(this); } @Override public String getId() { return id; } @Override public String getName() { return name; } @Override public Server getServer() { return server; } @Override public Permissions getPermissions() { return permissions; } @Override public Permissions getOverwrittenPermissions(Channel channel) { Permissions overwrittenPermissions = this.overwrittenPermissions.get(channel.getId()); if (overwrittenPermissions == null) { overwrittenPermissions = emptyPermissions; } return overwrittenPermissions; } @Override public Permissions getOverwrittenPermissions(VoiceChannel channel) { Permissions overwrittenPermissions = this.overwrittenPermissions.get(channel.getId()); if (overwrittenPermissions == null) { overwrittenPermissions = emptyPermissions; } return overwrittenPermissions; } @Override public List<User> getUsers() { return new ArrayList<>(users); } @Override public int getPosition() { return position; } @Override public boolean getHoist() { return hoist; } @Override public Color getColor() { return color; } @Override public boolean isMentionable() { return mentionable; } @Override public boolean isManaged() { return managed; } @Override public String getMentionTag() { return "<@&" + getId() + ">"; } @Override public Future<Void> updatePermissions(Permissions permissions) { return update(name, color, hoist, permissions); } @Override public Future<Void> updateName(String name) { return update(name, color, hoist, permissions); } @Override public Future<Void> updateColor(Color color) { return update(name, color, hoist, permissions); } @Override public Future<Void> updateHoist(boolean hoist) { return update(name, color, hoist, permissions); } @Override public Future<Void> update(String name, Color color, boolean hoist, Permissions permissions) { if (name == null) { name = getName(); } if (color == null) { color = getColor(); } if (permissions == null) { permissions = getPermissions(); } return update(name, color.getRGB(), hoist, ((ImplPermissions) permissions).getAllowed()); } /** * Updates the role. * * @param name The new name of the role. * @param color The new color of the role. * @param hoist The new hoist of the role. * @param allow The new permissions of the role. * @return A future. */ private Future<Void> update(final String name, final int color, final boolean hoist, final int allow) { return api.getThreadPool().getExecutorService().submit(new Callable<Void>() { @Override public Void call() throws Exception { logger.debug( "Trying to update role {} (new name: {}, old name: {}, new color: {}, old color: {}," + " new hoist: {}, old hoist: {}, new allow: {}, old allow: {})", ImplRole.this, name, getName(), color & 0xFFFFFF, getColor().getRGB() & 0xFFFFFF, hoist, getHoist(), allow, permissions.getAllowed()); HttpResponse<JsonNode> response = Unirest .patch("https://discordapp.com/api/guilds/" + server.getId() + "/roles/" + id) .header("authorization", api.getToken()).header("Content-Type", "application/json") .body(new JSONObject().put("name", name).put("color", color & 0xFFFFFF).put("hoist", hoist) .put("permissions", allow).toString()) .asJson(); api.checkResponse(response); api.checkRateLimit(response, RateLimitType.UNKNOWN, null, null); logger.info( "Updated role {} (new name: {}, old name: {}, new color: {}, old color: {}," + " new hoist: {}, old hoist: {}, new allow: {}, old allow: {})", ImplRole.this, name, getName(), color & 0xFFFFFF, getColor().getRGB() & 0xFFFFFF, hoist, getHoist(), allow, permissions.getAllowed()); // update permissions if (ImplRole.this.permissions.getAllowed() != allow) { final ImplPermissions oldPermissions = ImplRole.this.permissions; ImplRole.this.permissions = new ImplPermissions(allow); // call listener api.getThreadPool().getSingleThreadExecutorService("listeners").submit(new Runnable() { @Override public void run() { List<RoleChangePermissionsListener> listeners = api .getListeners(RoleChangePermissionsListener.class); synchronized (listeners) { for (RoleChangePermissionsListener listener : listeners) { try { listener.onRoleChangePermissions(api, ImplRole.this, oldPermissions); } catch (Throwable t) { logger.warn("Uncaught exception in RoleChangePermissionsListener!", t); } } } } }); } // update name if (ImplRole.this.name.equals(name)) { final String oldName = ImplRole.this.name; ImplRole.this.name = name; // call listener api.getThreadPool().getSingleThreadExecutorService("listeners").submit(new Runnable() { @Override public void run() { List<RoleChangeNameListener> listeners = api.getListeners(RoleChangeNameListener.class); synchronized (listeners) { for (RoleChangeNameListener listener : listeners) { try { listener.onRoleChangeName(api, ImplRole.this, oldName); } catch (Throwable t) { logger.warn("Uncaught exception in RoleChangeNameListener!", t); } } } } }); } // update color if (ImplRole.this.color.getRGB() != new Color(color).getRGB()) { final Color oldColor = ImplRole.this.color; ImplRole.this.color = new Color(color); // call listener api.getThreadPool().getSingleThreadExecutorService("listeners").submit(new Runnable() { @Override public void run() { List<RoleChangeColorListener> listeners = api .getListeners(RoleChangeColorListener.class); synchronized (listeners) { for (RoleChangeColorListener listener : listeners) { try { listener.onRoleChangeColor(api, ImplRole.this, oldColor); } catch (Throwable t) { logger.warn("Uncaught exception in RoleChangeColorListener!", t); } } } } }); } // update hoist if (ImplRole.this.hoist != hoist) { ImplRole.this.hoist = hoist; // call listener api.getThreadPool().getSingleThreadExecutorService("listeners").submit(new Runnable() { @Override public void run() { List<RoleChangeHoistListener> listeners = api .getListeners(RoleChangeHoistListener.class); synchronized (listeners) { for (RoleChangeHoistListener listener : listeners) { try { listener.onRoleChangeHoist(api, ImplRole.this, !ImplRole.this.hoist); } catch (Throwable t) { logger.warn("Uncaught exception in RoleChangeHoistListener!", t); } } } } }); } return null; } }); } @Override public Future<Void> delete() { return api.getThreadPool().getExecutorService().submit(new Callable<Void>() { @Override public Void call() throws Exception { logger.debug("Trying to delete role {}", ImplRole.this); HttpResponse<JsonNode> response = Unirest .delete("https://discordapp.com/api/guilds/" + getServer().getId() + "/roles/" + getId()) .header("authorization", api.getToken()).asJson(); api.checkResponse(response); server.removeRole(ImplRole.this); logger.info("Deleted role {}", ImplRole.this); api.getThreadPool().getSingleThreadExecutorService("listeners").submit(new Runnable() { @Override public void run() { List<RoleDeleteListener> listeners = api.getListeners(RoleDeleteListener.class); synchronized (listeners) { for (RoleDeleteListener listener : listeners) { try { listener.onRoleDelete(api, ImplRole.this); } catch (Throwable t) { logger.warn("Uncaught exception in RoleDeleteListener!", t); } } } } }); return null; } }); } @Override public Future<Void> removeUser(User user) { List<Role> roles = new ArrayList<>(user.getRoles(getServer())); roles.remove(this); return getServer().updateRoles(user, roles.toArray(new Role[roles.size()])); } @Override public Future<Void> addUser(User user) { List<Role> roles = new ArrayList<>(user.getRoles(getServer())); roles.add(this); return getServer().updateRoles(user, roles.toArray(new Role[roles.size()])); } /** * Adds an user. * * @param user The user to add. */ public void addUserNoUpdate(User user) { synchronized (users) { users.add(user); } } /** * Removes an user. * * @param user The user to remove. */ public void removeUserNoUpdate(User user) { synchronized (users) { users.remove(user); } } /** * Sets the name of the channel. * * @param name The name to set. */ public void setName(String name) { this.name = name; } /** * Sets the permissions of the channel. * * @param permissions The permissions to set. */ public void setPermissions(ImplPermissions permissions) { this.permissions = permissions; } /** * Sets the position of the channel. * * @param position The position to set. */ public void setPosition(int position) { this.position = position; } /** * Sets overwritten permissions. * * @param channel The channel which overwrites the permissions. * @param permissions The overwritten permissions to set. */ public void setOverwrittenPermissions(Channel channel, Permissions permissions) { overwrittenPermissions.put(channel.getId(), permissions); } /** * Sets overwritten permissions. * * @param channel The voice channel which overwrites the permissions. * @param permissions The overwritten permissions to set. */ public void setOverwrittenPermissions(VoiceChannel channel, Permissions permissions) { overwrittenPermissions.put(channel.getId(), permissions); } /** * Sets the color of the channel. * * @param color The color to set. */ public void setColor(Color color) { this.color = color; } /** * Sets the hoist of the channel. * * @param hoist The hoist to set. */ public void setHoist(boolean hoist) { this.hoist = hoist; } @Override public String toString() { return getName() + " (id: " + getId() + ")"; } }