use of org.javacord.api.entity.DiscordEntity in project Javacord by BtoBastian.
the class ServerUpdaterDelegateImpl method update.
@Override
public CompletableFuture<Void> update() {
// A set with all members that get updates
HashSet<User> members = new HashSet<>(userRoles.keySet());
members.addAll(userNicknames.keySet());
members.addAll(userMuted.keySet());
members.addAll(userDeafened.keySet());
members.addAll(userMoveTargets.keySet());
// A list with all tasks
List<CompletableFuture<?>> tasks = new ArrayList<>();
members.forEach(member -> {
boolean patchMember = false;
ObjectNode updateNode = JsonNodeFactory.instance.objectNode();
Collection<Role> roles = userRoles.get(member);
if (roles != null) {
ArrayNode rolesJson = updateNode.putArray("roles");
roles.stream().map(DiscordEntity::getIdAsString).forEach(rolesJson::add);
patchMember = true;
}
if (userNicknames.containsKey(member)) {
String nickname = userNicknames.get(member);
if (member.isYourself()) {
tasks.add(new RestRequest<Void>(server.getApi(), RestMethod.PATCH, RestEndpoint.OWN_NICKNAME).setUrlParameters(server.getIdAsString()).setBody(JsonNodeFactory.instance.objectNode().put("nick", nickname)).setAuditLogReason(reason).execute(result -> null));
} else {
updateNode.put("nick", (nickname == null) ? "" : nickname);
patchMember = true;
}
}
if (userMuted.containsKey(member)) {
updateNode.put("mute", userMuted.get(member));
patchMember = true;
}
if (userDeafened.containsKey(member)) {
updateNode.put("deaf", userDeafened.get(member));
patchMember = true;
}
if (userMoveTargets.containsKey(member)) {
ServerVoiceChannel channel = userMoveTargets.get(member);
if (member.isYourself()) {
((DiscordApiImpl) server.getApi()).getWebSocketAdapter().sendVoiceStateUpdate(server, channel, null, null);
} else if (channel != null) {
updateNode.put("channel_id", channel.getId());
patchMember = true;
} else {
updateNode.putNull("channel_id");
patchMember = true;
}
}
if (patchMember) {
tasks.add(new RestRequest<Void>(server.getApi(), RestMethod.PATCH, RestEndpoint.SERVER_MEMBER).setUrlParameters(server.getIdAsString(), member.getIdAsString()).setBody(updateNode).setAuditLogReason(reason).execute(result -> null));
}
});
if (newRolesOrder != null) {
tasks.add(server.reorderRoles(newRolesOrder, reason));
}
// Server settings
boolean patchServer = false;
ObjectNode body = JsonNodeFactory.instance.objectNode();
if (name != null) {
body.put("name", name);
patchServer = true;
}
if (region != null) {
body.put("region", region.getKey());
patchServer = true;
}
if (explicitContentFilterLevel != null) {
body.put("explicit_content_filter", explicitContentFilterLevel.getId());
patchServer = true;
}
if (verificationLevel != null) {
body.put("verification_level", verificationLevel.getId());
patchServer = true;
}
if (defaultMessageNotificationLevel != null) {
body.put("default_message_notifications", defaultMessageNotificationLevel.getId());
patchServer = true;
}
if (updateAfkChannel) {
if (afkChannel != null) {
body.put("afk_channel_id", afkChannel.getIdAsString());
} else {
body.putNull("afk_channel_id");
}
patchServer = true;
}
if (afkTimeout != null) {
body.put("afk_timeout", afkTimeout.intValue());
patchServer = true;
}
if (updateIcon) {
if (icon == null) {
body.putNull("icon");
}
patchServer = true;
}
if (updateSplash) {
if (splash == null) {
body.putNull("splash");
}
patchServer = true;
}
if (owner != null) {
body.put("owner_id", owner.getIdAsString());
patchServer = true;
}
if (updateSystemChannel) {
if (systemChannel != null) {
body.put("system_channel_id", systemChannel.getIdAsString());
} else {
body.putNull("system_channel_id");
}
patchServer = true;
}
if (updateModeratorsOnlyChannel) {
if (moderatorsOnlyChannel != null) {
body.put("public_updates_channel_id", moderatorsOnlyChannel.getIdAsString());
} else {
body.putNull("public_updates_channel_id");
}
patchServer = true;
}
if (updateRulesChannel) {
if (rulesChannel != null) {
body.put("rules_channel_id", rulesChannel.getIdAsString());
} else {
body.putNull("rules_channel_id");
}
patchServer = true;
}
if (updateBanner) {
if (banner == null) {
body.putNull("banner");
}
patchServer = true;
}
if (updateLocale) {
if (locale == null) {
body.putNull("preferred_locale");
} else {
body.put("preferred_locale", locale.toLanguageTag());
}
patchServer = true;
}
// Only make a REST call, if we really want to update something
if (patchServer) {
if (icon != null || splash != null || banner != null) {
CompletableFuture<Void> iconFuture = null;
if (icon != null) {
iconFuture = icon.asByteArray(server.getApi()).thenAccept(bytes -> {
String base64Icon = "data:image/" + icon.getFileType() + ";base64," + Base64.getEncoder().encodeToString(bytes);
body.put("icon", base64Icon);
});
}
CompletableFuture<Void> splashFuture = null;
if (splash != null) {
splashFuture = splash.asByteArray(server.getApi()).thenAccept(bytes -> {
String base64Splash = "data:image/" + splash.getFileType() + ";base64," + Base64.getEncoder().encodeToString(bytes);
body.put("splash", base64Splash);
});
}
CompletableFuture<Void> bannerFuture = null;
if (banner != null) {
bannerFuture = banner.asByteArray(server.getApi()).thenAccept(bytes -> {
String base64Banner = "data:image/" + banner.getFileType() + ";base64," + Base64.getEncoder().encodeToString(bytes);
body.put("banner", base64Banner);
});
}
CompletableFuture<Void> future;
List<CompletableFuture<Void>> futureList = new ArrayList<>();
if (iconFuture != null) {
futureList.add(iconFuture);
}
if (splashFuture != null) {
futureList.add(splashFuture);
}
if (bannerFuture != null) {
futureList.add(bannerFuture);
}
future = CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));
tasks.add(future.thenCompose(aVoid -> new RestRequest<Void>(server.getApi(), RestMethod.PATCH, RestEndpoint.SERVER).setUrlParameters(server.getIdAsString()).setBody(body).setAuditLogReason(reason).execute(result -> null)));
} else {
tasks.add(new RestRequest<Void>(server.getApi(), RestMethod.PATCH, RestEndpoint.SERVER).setUrlParameters(server.getIdAsString()).setBody(body).setAuditLogReason(reason).execute(result -> null));
}
}
CompletableFuture<?>[] tasksArray = tasks.toArray(new CompletableFuture<?>[tasks.size()]);
return CompletableFuture.allOf(tasksArray);
}
use of org.javacord.api.entity.DiscordEntity in project Javacord by BtoBastian.
the class AuditLogEntryImpl method iconChange.
private AuditLogChange<?> iconChange(String baseUrl, AuditLogChangeType type, JsonNode oldVal, JsonNode newVal) {
try {
Icon oldIcon = oldVal != null ? new IconImpl(getApi(), new URL(baseUrl + getTarget().map(DiscordEntity::getIdAsString).orElse("0") + "/" + oldVal.asText() + ".png")) : null;
Icon newIcon = newVal != null ? new IconImpl(getApi(), new URL(baseUrl + getTarget().map(DiscordEntity::getIdAsString).orElse("0") + "/" + newVal.asText() + ".png")) : null;
return new AuditLogChangeImpl<>(type, oldIcon, newIcon);
} catch (MalformedURLException e) {
logger.warn("Seems like the icon's url is malformed! Please contact the developer!", e);
return new AuditLogChangeImpl<>(AuditLogChangeType.UNKNOWN, oldVal, newVal);
}
}
use of org.javacord.api.entity.DiscordEntity in project Javacord by BtoBastian.
the class ChannelUpdateHandler method handleRegularServerChannel.
private void handleRegularServerChannel(JsonNode jsonChannel) {
long channelId = jsonChannel.get("id").asLong();
Optional<RegularServerChannel> optionalChannel = api.getRegularServerChannelById(channelId);
if (!optionalChannel.isPresent()) {
LoggerUtil.logMissingChannel(logger, channelId);
return;
}
RegularServerChannelImpl channel = (RegularServerChannelImpl) optionalChannel.get();
ServerImpl server = (ServerImpl) channel.getServer();
final AtomicBoolean areYouAffected = new AtomicBoolean(false);
ChannelCategory oldCategory = channel.asCategorizable().flatMap(Categorizable::getCategory).orElse(null);
ChannelCategory newCategory = jsonChannel.hasNonNull("parent_id") ? channel.getServer().getChannelCategoryById(jsonChannel.get("parent_id").asLong(-1)).orElse(null) : null;
final RegularServerChannelImpl regularServerChannel = (RegularServerChannelImpl) channel;
final int oldRawPosition = regularServerChannel.getRawPosition();
final int newRawPosition = jsonChannel.get("position").asInt();
if (oldRawPosition != newRawPosition || !Objects.deepEquals(oldCategory, newCategory)) {
final int oldPosition = regularServerChannel.getPosition();
if (regularServerChannel instanceof ServerTextChannelImpl) {
((ServerTextChannelImpl) regularServerChannel).setParentId(newCategory == null ? -1 : newCategory.getId());
} else if (regularServerChannel instanceof ServerVoiceChannelImpl) {
((ServerVoiceChannelImpl) regularServerChannel).setParentId(newCategory == null ? -1 : newCategory.getId());
}
regularServerChannel.setRawPosition(newRawPosition);
final int newPosition = regularServerChannel.getPosition();
final ServerChannelChangePositionEvent event = new ServerChannelChangePositionEventImpl(regularServerChannel, newPosition, oldPosition, newRawPosition, oldRawPosition, newCategory, oldCategory);
if (server.isReady()) {
api.getEventDispatcher().dispatchServerChannelChangePositionEvent((DispatchQueueSelector) regularServerChannel.getServer(), regularServerChannel.getServer(), regularServerChannel, event);
}
}
Collection<Long> rolesWithOverwrittenPermissions = new HashSet<>();
Collection<Long> usersWithOverwrittenPermissions = new HashSet<>();
if (jsonChannel.has("permission_overwrites") && !jsonChannel.get("permission_overwrites").isNull()) {
for (JsonNode permissionOverwriteJson : jsonChannel.get("permission_overwrites")) {
Permissions oldOverwrittenPermissions;
ConcurrentHashMap<Long, Permissions> overwrittenPermissions;
long entityId = permissionOverwriteJson.get("id").asLong();
Optional<DiscordEntity> entity;
switch(permissionOverwriteJson.get("type").asInt()) {
case 0:
Role role = server.getRoleById(entityId).orElseThrow(() -> new IllegalStateException("Received channel update event with unknown role!"));
entity = Optional.of(role);
oldOverwrittenPermissions = regularServerChannel.getOverwrittenPermissions(role);
overwrittenPermissions = regularServerChannel.getInternalOverwrittenRolePermissions();
rolesWithOverwrittenPermissions.add(entityId);
break;
case 1:
oldOverwrittenPermissions = regularServerChannel.getOverwrittenUserPermissions().getOrDefault(entityId, PermissionsImpl.EMPTY_PERMISSIONS);
entity = api.getCachedUserById(entityId).map(DiscordEntity.class::cast);
overwrittenPermissions = regularServerChannel.getInternalOverwrittenUserPermissions();
usersWithOverwrittenPermissions.add(entityId);
break;
default:
throw new IllegalStateException("Permission overwrite object with unknown type: " + permissionOverwriteJson);
}
long allow = permissionOverwriteJson.get("allow").asLong(0);
long deny = permissionOverwriteJson.get("deny").asLong(0);
Permissions newOverwrittenPermissions = new PermissionsImpl(allow, deny);
if (!newOverwrittenPermissions.equals(oldOverwrittenPermissions)) {
overwrittenPermissions.put(entityId, newOverwrittenPermissions);
if (server.isReady()) {
dispatchServerChannelChangeOverwrittenPermissionsEvent(channel, newOverwrittenPermissions, oldOverwrittenPermissions, entityId, entity.orElse(null));
areYouAffected.compareAndSet(false, entityId == api.getYourself().getId());
entity.filter(e -> e instanceof Role).map(Role.class::cast).ifPresent(role -> areYouAffected.compareAndSet(false, role.getUsers().stream().anyMatch(User::isYourself)));
}
}
}
}
ConcurrentHashMap<Long, Permissions> overwrittenRolePermissions;
ConcurrentHashMap<Long, Permissions> overwrittenUserPermissions;
overwrittenRolePermissions = regularServerChannel.getInternalOverwrittenRolePermissions();
overwrittenUserPermissions = regularServerChannel.getInternalOverwrittenUserPermissions();
Iterator<Map.Entry<Long, Permissions>> userIt = overwrittenUserPermissions.entrySet().iterator();
while (userIt.hasNext()) {
Map.Entry<Long, Permissions> entry = userIt.next();
if (usersWithOverwrittenPermissions.contains(entry.getKey())) {
continue;
}
Permissions oldPermissions = entry.getValue();
userIt.remove();
if (server.isReady()) {
dispatchServerChannelChangeOverwrittenPermissionsEvent(channel, PermissionsImpl.EMPTY_PERMISSIONS, oldPermissions, entry.getKey(), api.getCachedUserById(entry.getKey()).orElse(null));
areYouAffected.compareAndSet(false, entry.getKey() == api.getYourself().getId());
}
}
Iterator<Map.Entry<Long, Permissions>> roleIt = overwrittenRolePermissions.entrySet().iterator();
while (roleIt.hasNext()) {
Map.Entry<Long, Permissions> entry = roleIt.next();
if (rolesWithOverwrittenPermissions.contains(entry.getKey())) {
continue;
}
api.getRoleById(entry.getKey()).ifPresent(role -> {
Permissions oldPermissions = entry.getValue();
roleIt.remove();
if (server.isReady()) {
dispatchServerChannelChangeOverwrittenPermissionsEvent(channel, PermissionsImpl.EMPTY_PERMISSIONS, oldPermissions, role.getId(), role);
areYouAffected.compareAndSet(false, role.getUsers().stream().anyMatch(User::isYourself));
}
});
}
if (areYouAffected.get() && !channel.canYouSee()) {
api.forEachCachedMessageWhere(msg -> msg.getChannel().getId() == channelId, msg -> {
api.removeMessageFromCache(msg.getId());
((MessageCacheImpl) ((TextChannel) channel).getMessageCache()).removeMessage(msg);
});
}
}
use of org.javacord.api.entity.DiscordEntity in project Javacord by BtoBastian.
the class MessageSetImpl method getMessagesAround.
/**
* Gets up to a given amount of messages in the given channel around a given message in any channel.
* The given message will be part of the result in addition to the messages around if it was sent in the given
* channel and does not count towards the limit.
* Half of the messages will be older than the given message and half of the messages will be newer.
* If there aren't enough older or newer messages, the actual amount of messages will be less than the given limit.
* It's also not guaranteed to be perfectly balanced.
*
* @param channel The channel of the messages.
* @param limit The limit of messages to get.
* @param around Get messages around the message with this id.
* @return The messages.
* @see #getMessagesAroundAsStream(TextChannel, long)
*/
public static CompletableFuture<MessageSet> getMessagesAround(TextChannel channel, int limit, long around) {
CompletableFuture<MessageSet> future = new CompletableFuture<>();
channel.getApi().getThreadPool().getExecutorService().submit(() -> {
try {
// calculate the half limit.
int halfLimit = limit / 2;
// get the newer half
MessageSet newerMessages = getMessagesAfter(channel, halfLimit, around).join();
// get the older half + around message
MessageSet olderMessages = getMessagesBefore(channel, halfLimit + 1, around + 1).join();
// for example because the around message was from a different channel
if (olderMessages.getNewestMessage().map(DiscordEntity::getId).map(id -> id != around).orElse(false)) {
olderMessages = olderMessages.tailSet(olderMessages.getOldestMessage().orElseThrow(AssertionError::new), false);
}
// combine the messages into one collection
Collection<Message> messages = Stream.of(olderMessages, newerMessages).flatMap(Collection::stream).collect(toList());
// we are done
future.complete(new MessageSetImpl(messages));
} catch (Throwable t) {
future.completeExceptionally(t);
}
});
return future;
}
Aggregations