Search in sources :

Example 1 with DiscordEntity

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);
}
Also used : ServerChannel(org.javacord.api.entity.channel.ServerChannel) URL(java.net.URL) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) RestMethod(org.javacord.core.util.rest.RestMethod) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) FileContainer(org.javacord.core.util.FileContainer) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) DiscordEntity(org.javacord.api.entity.DiscordEntity) Region(org.javacord.api.entity.Region) Locale(java.util.Locale) Map(java.util.Map) Icon(org.javacord.api.entity.Icon) RestRequest(org.javacord.core.util.rest.RestRequest) ServerTextChannel(org.javacord.api.entity.channel.ServerTextChannel) DefaultMessageNotificationLevel(org.javacord.api.entity.server.DefaultMessageNotificationLevel) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) DiscordApiImpl(org.javacord.core.DiscordApiImpl) File(java.io.File) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) ServerVoiceChannel(org.javacord.api.entity.channel.ServerVoiceChannel) ExplicitContentFilterLevel(org.javacord.api.entity.server.ExplicitContentFilterLevel) RestEndpoint(org.javacord.core.util.rest.RestEndpoint) Base64(java.util.Base64) List(java.util.List) User(org.javacord.api.entity.user.User) JsonNodeFactory(com.fasterxml.jackson.databind.node.JsonNodeFactory) Role(org.javacord.api.entity.permission.Role) VerificationLevel(org.javacord.api.entity.server.VerificationLevel) Server(org.javacord.api.entity.server.Server) ServerUpdaterDelegate(org.javacord.api.entity.server.internal.ServerUpdaterDelegate) InputStream(java.io.InputStream) User(org.javacord.api.entity.user.User) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) Role(org.javacord.api.entity.permission.Role) CompletableFuture(java.util.concurrent.CompletableFuture) RestRequest(org.javacord.core.util.rest.RestRequest) ArrayNode(com.fasterxml.jackson.databind.node.ArrayNode) ServerVoiceChannel(org.javacord.api.entity.channel.ServerVoiceChannel) HashSet(java.util.HashSet)

Example 2 with DiscordEntity

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);
    }
}
Also used : IconImpl(org.javacord.core.entity.IconImpl) MalformedURLException(java.net.MalformedURLException) Icon(org.javacord.api.entity.Icon) URL(java.net.URL) DiscordEntity(org.javacord.api.entity.DiscordEntity)

Example 3 with DiscordEntity

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);
        });
    }
}
Also used : User(org.javacord.api.entity.user.User) RegularServerChannel(org.javacord.api.entity.channel.RegularServerChannel) RegularServerChannelImpl(org.javacord.core.entity.channel.RegularServerChannelImpl) JsonNode(com.fasterxml.jackson.databind.JsonNode) ServerChannelChangePositionEvent(org.javacord.api.event.channel.server.ServerChannelChangePositionEvent) ServerImpl(org.javacord.core.entity.server.ServerImpl) PermissionsImpl(org.javacord.core.entity.permission.PermissionsImpl) Permissions(org.javacord.api.entity.permission.Permissions) ServerTextChannelImpl(org.javacord.core.entity.channel.ServerTextChannelImpl) HashSet(java.util.HashSet) ServerVoiceChannelImpl(org.javacord.core.entity.channel.ServerVoiceChannelImpl) Role(org.javacord.api.entity.permission.Role) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) MessageCacheImpl(org.javacord.core.util.cache.MessageCacheImpl) ServerChannelChangePositionEventImpl(org.javacord.core.event.channel.server.ServerChannelChangePositionEventImpl) ChannelCategory(org.javacord.api.entity.channel.ChannelCategory) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) DiscordEntity(org.javacord.api.entity.DiscordEntity)

Example 4 with DiscordEntity

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;
}
Also used : MessageSet(org.javacord.api.entity.message.MessageSet) MessageSet(org.javacord.api.entity.message.MessageSet) Arrays(java.util.Arrays) Spliterators(java.util.Spliterators) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) RestMethod(org.javacord.core.util.rest.RestMethod) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) DiscordEntity(org.javacord.api.entity.DiscordEntity) RestRequest(org.javacord.core.util.rest.RestRequest) TextChannel(org.javacord.api.entity.channel.TextChannel) JsonNode(com.fasterxml.jackson.databind.JsonNode) StreamSupport(java.util.stream.StreamSupport) Iterator(java.util.Iterator) Predicate(java.util.function.Predicate) Collections.emptyList(java.util.Collections.emptyList) Collection(java.util.Collection) NavigableSet(java.util.NavigableSet) DiscordApiImpl(org.javacord.core.DiscordApiImpl) Message(org.javacord.api.entity.message.Message) RestEndpoint(org.javacord.core.util.rest.RestEndpoint) List(java.util.List) Collectors.toList(java.util.stream.Collectors.toList) Stream(java.util.stream.Stream) Comparator(java.util.Comparator) Collections(java.util.Collections) Spliterator(java.util.Spliterator) CompletableFuture(java.util.concurrent.CompletableFuture) Message(org.javacord.api.entity.message.Message) RestEndpoint(org.javacord.core.util.rest.RestEndpoint) DiscordEntity(org.javacord.api.entity.DiscordEntity)

Aggregations

DiscordEntity (org.javacord.api.entity.DiscordEntity)4 JsonNode (com.fasterxml.jackson.databind.JsonNode)2 URL (java.net.URL)2 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Map (java.util.Map)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)2 Icon (org.javacord.api.entity.Icon)2 Role (org.javacord.api.entity.permission.Role)2 User (org.javacord.api.entity.user.User)2 DiscordApiImpl (org.javacord.core.DiscordApiImpl)2 RestEndpoint (org.javacord.core.util.rest.RestEndpoint)2 RestMethod (org.javacord.core.util.rest.RestMethod)2 RestRequest (org.javacord.core.util.rest.RestRequest)2 ArrayNode (com.fasterxml.jackson.databind.node.ArrayNode)1 JsonNodeFactory (com.fasterxml.jackson.databind.node.JsonNodeFactory)1 ObjectNode (com.fasterxml.jackson.databind.node.ObjectNode)1