package top.quantic.sentry.discord;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import sx.blah.discord.api.IDiscordClient;
import sx.blah.discord.handle.obj.IMessage;
import sx.blah.discord.util.DiscordException;
import top.quantic.sentry.discord.core.Command;
import top.quantic.sentry.discord.core.CommandBuilder;
import top.quantic.sentry.discord.core.CommandContext;
import top.quantic.sentry.discord.module.CommandSupplier;

import java.util.Collections;
import java.util.List;

import static top.quantic.sentry.config.Constants.INSTANCE_KEY;
import static top.quantic.sentry.discord.util.DiscordUtil.*;

@Component
public class PowerSwitch implements CommandSupplier {

    private static final Logger log = LoggerFactory.getLogger(PowerSwitch.class);

    @Override
    public List<Command> getCommands() {
        return Collections.singletonList(logout());
    }

    private Command logout() {
        return CommandBuilder.of("logout")
            .describedAs("Disconnect from Discord")
            .in("Administrative")
            .nonParsed()
            .secured()
            .onExecute(context -> {
                IMessage message = context.getMessage();
                String[] args = context.getArgs();
                if (args != null) {
                    String id = ourBotId(message.getClient());
                    String[] array = args[0].split(" ");
                    // shutdown if the args match this bot but not this instance
                    if (array.length >= 2 && array[0].equals(id) && !array[1].equals(INSTANCE_KEY)) {
                        deleteMessage(message);
                        doLogout(context);
                    } else {
                        log.debug("Ignoring: Expected args {} and anything but {}", id, INSTANCE_KEY);
                    }
                } else {
                    deleteMessage(message);
                    answer(message, ":wave:");
                    doLogout(context);
                }
            }).build();
    }

    private void doLogout(CommandContext context) {
        IDiscordClient client = context.getMessage().getClient();
        log.info("[{}] Logging out via command", client.getOurUser().getName());
        if (client.isLoggedIn()) {
            try {
                client.logout();
            } catch (DiscordException e) {
                log.warn("Could not logout bot", e);
            }
        }
    }
}

@@ -175,24 +175,106 @@
 cordClient;%0A
+import sx.blah.discord.api.IShard;%0Aimport sx.blah.discord.api.internal.ShardImpl;%0A
 import sx.bl
@@ -589,28 +589,22 @@
 til.
-Collections;
+List;%0A
 %0Aimport 
 java
@@ -591,32 +591,39 @@
 l.List;%0A%0Aimport 
+static 
 java.util.List;%0A
@@ -608,38 +608,99 @@
 tatic java.util.
-List;%0A
+Arrays.asList;%0Aimport static java.util.concurrent.TimeUnit.SECONDS;
 %0Aimport static t
@@ -1033,42 +1033,1188 @@
 urn 
-Collections.singletonList(logout()
+asList(logout(), close());%0A    %7D%0A%0A    private Command close() %7B%0A        return CommandBuilder.of(%22close%22)%0A            .describedAs(%22Send a close code to the bot%22)%0A            .in(%22Administrative%22)%0A            .nonParsed()%0A            .secured()%0A            .onExecute(context -%3E %7B%0A                IMessage message = context.getMessage();%0A                String%5B%5D args = context.getArgs();%0A                int code = 1000;%0A                String reason = null;%0A                if (args != null) %7B%0A                    String%5B%5D array = args%5B0%5D.split(%22 %22, 2);%0A                    if (array.length %3E 0) %7B%0A                        code = Integer.parseInt(array%5B0%5D);%0A                    %7D%0A                    if (array.length %3E 1) %7B%0A                        reason = array%5B1%5D;%0A                    %7D%0A                %7D%0A                try %7B%0A                    SECONDS.sleep(3);%0A                    for (IShard shard : message.getClient().getShards()) %7B%0A                        ((ShardImpl) shard).ws.onWebSocketClose(code, reason);%0A                    %7D%0A                %7D catch (InterruptedException e) %7B%0A                    log.warn(%22Interrupted!%22);%0A                %7D%0A            %7D).build(
 );%0A 

Add a command to issue close codes to ws