Search code examples
discorddiscord-jda

Discord Bot (JDA) is not modifying my Roles


I Programmed an Discord Bot to make an Time Role (a Role that Changes its name every second to: "{UserName} --D --H --min --sec).

It worked Fine, but after an hour it does not worked anymore, but I did not change anything in the Code.

I have an Command ("{prefix} shutdown"), it basicly do ShardManager.shutdown(); and than I get an error.

Code for the Command:

package Discord.Commands.TimeRank;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ThreadPoolExecutor.DiscardOldestPolicy;

import Discord.Bot;
import Discord.Commands.Command;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.exceptions.RateLimitedException;

public class startTimeRole extends Command {
    public static Server server;

    public Timer timer;
    public static boolean isRunning = false;

    @Override
    public void set(String prefix, String help) {

        prefix = "timeRole";
        help = Bot.prefix + " timeRole <STATE> -> STATE = start, pause";

        super.set(prefix, help);
    }

    @Override
    public void Execute(MessageReceivedEvent event, String[] args) {
        super.Execute(event, args);

        server = server.get(event.getGuild());

        if (args.length <= 1) {
            event.getTextChannel().sendMessage("Please give at least one **Argument**!").queue();
            help(event);
            return;
        } else {
            if (args[1].equals("start")) {
                if (!isRunning) {
                    timer = new Timer();
                    event.getTextChannel().sendMessage("Activated timeRole!").queue();
                    isRunning = true;
                    timer.scheduleAtFixedRate(new TimerTask() {
                        public void run() {

                            for (Client client : server.onlineClients) {
                                Role timeRole = null;

                                for (Role role : client.member.getRoles()) {
                                    if (timeRole != null) {
                                        break;
                                    }
                                    if (role.getName().startsWith(client.member.getUser().getName())) {
                                        
                                        client.onlineTime.setTime(role.getName().substring(client.member.getUser().getName().length() + 1));
                                        
                                        client.onlineTime.plus(10);

                                        timeRole = role;
                                    }
                                }
                                if (timeRole != null) {
                                    timeRole.getManager()
                                            .setName(client.member.getUser().getName() + " " + client.onlineTime.get())
                                            .queue();
                                } else {
                                    try {
                                        server.guild
                                                .addRoleToMember(client.member,
                                                        server.guild.createRole()
                                                                .setName(client.member.getUser().getName() + " "
                                                                        + client.onlineTime.get())
                                                                .complete(true))
                                                .queue();
                                    } catch (RateLimitedException e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                    }, 0, 10000);
                    return;
                } else {
                    event.getTextChannel().sendMessage("timeRole is Active!").queue();
                    help(event);
                    return;
                }
            } else if (args[1].equals("pause")) {
                if (isRunning) {
                    timer.cancel();
                    event.getTextChannel().sendMessage("Paused timeRole").queue();
                    ;
                    isRunning = false;
                } else {
                    event.getTextChannel().sendMessage("timeRole is Paused!").queue();
                    help(event);
                    return;
                }
                return;
            } else {
                event.getTextChannel().sendMessage("Please give one **Argument**").queue();
                help(event);
                return;
            }
        }
    }
}

Code for the "Server" Class:

package Discord.Commands.TimeRank;

import java.util.ArrayList;

import net.dv8tion.jda.api.OnlineStatus;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;

public class Server {
    public ArrayList<Client> clients = new ArrayList<Client>();
    public ArrayList<Client> onlineClients = new ArrayList<Client>();

    public Guild guild;

    private Server(Guild guild) {
        this.guild = guild;
    }

    public static Server get(Guild guild) {
        Server server = new Server(guild);

        server.clients = server.getMembersAsClients();
        server.onlineClients = server.getOnlineMembersAsClients();
        
        return server;
    }

    public ArrayList<Client> getMembersAsClients() {
        ArrayList<Client> clients = new ArrayList<Client>();

        System.out.println(guild.getMembers().size());

        for (Member member : guild.getMembers()) {
            if (!member.getUser().isBot()) {
                clients.add(new Client(member));
            }
        }

        return clients;
    }

    public ArrayList<Client> getOnlineMembersAsClients() {
        ArrayList<Client> onlineClients = new ArrayList<Client>();

        for (Client client : clients) {
            if (!client.member.getUser().isBot()) {
                if (client.member.getOnlineStatus() == OnlineStatus.ONLINE) {
                    onlineClients.add(client);
                }
            }
        }
        return onlineClients;
    }
}

and Time Class:

package Discord.Commands.TimeRank;

public class Time {
    public int Days, Hours, Minutes, Seconds;

    public Time() {
    }

    public String get() {
        return Days + "D " + Hours + "H " + Minutes + "min " + Seconds + "sec ";
    }

    public void plus(int plus) {
        Seconds += plus;
        if (Seconds >= 60) {
            Seconds = 0;
            Minutes++;
            if (Minutes >= 60) {
                Minutes = 0;
                Hours++;
                if (Hours >= 24) {
                    Hours = 0;
                    Days++;
                    return;
                }
            }
        }
    }

    public void setTime(String Time) {
        String[] Time_ = Time.split(" ");

        int Days = Integer.parseInt(Time_[0].split("D")[0]);
        int Hours = Integer.parseInt(Time_[1].split("H")[0]);
        int Minutes = Integer.parseInt(Time_[2].split("min")[0]);
        int Seconds = Integer.parseInt(Time_[3].split("sec")[0]);

        this.Days = Days;
        this.Hours = Hours;
        this.Minutes = Minutes;
        this.Seconds = Seconds;
    }
}

And the Error:

[DefaultShardManager] INFO RateLimiter - Waiting for 1 bucket(s) to finish. Average queue size of 2 requests
Exception in thread "Timer-0" java.util.concurrent.RejectedExecutionException: The Requester has been stopped! No new requests can be requested!
    at net.dv8tion.jda.internal.requests.Requester.request(Requester.java:107)
    at net.dv8tion.jda.internal.requests.RestActionImpl.queue(RestActionImpl.java:189)
    at net.dv8tion.jda.internal.managers.ManagerBase.queue(ManagerBase.java:121)
    at net.dv8tion.jda.api.requests.RestAction.queue(RestAction.java:411)
    at net.dv8tion.jda.api.requests.RestAction.queue(RestAction.java:377)
    at Discord.Commands.TimeRank.startTimeRole$1.run(startTimeRole.java:67)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)

Sorry for that much Code but I just thoght that you could need it to know what, what is.

If you have some questions Just ask them. :D


Solution

  • You are being rate limited. Different requests to the api have different limits on how often you are allowed to perform them. When spamming a request you can easily hit such a limit.

    Switching the bot works because every new bot starts at zero until you hit the limit again.

    My advice is to decrease the number of requests. Trying to circumvent the limit it therefore abusing the api is against TOS.