Inhouse type Queue / List commands? Dota 2

Hello NightDev community and @am_1 , I’m trying to make a in-house challenge type of bot based on Queues/lists. I play Dota 2 with my viewers (10 people game, or can vary if its a Arcade game) and want to make an In-house league system. I made a list with the functions/commands I needed, and I need help trying to write them and implementing them on Nightbot.

######Streamer Commands

!queue on/off - Enables or Disables queue functions in your chatroom

######Queue Commands (Streamer/Trusted User)

!start queue - Open your Queue to viewers, they can now self add to your list

!end queue- Stop your Queue, followers can no more self add, however you will keep the record and followers can see their position on your list

!queue view - Shows the entire queue

!queue setsize n - Sets the player group size to n

!queue new - Generates a new group from the queue

!queue remove user - Removes user from the queue. If user is in the current group, removes user from the group and adds another from the queue

!queue clear - Clears the queue and current group

!addviewer viewername - you can add a viewer your self Ex : !addviewer Pepito135

!deleteviewer viewername - Will delete the viewer from the list

!MoveViewer TwitchName Position - Will move follower to the position that you have provided .

Ex : !MoveFollower Pepito135 6

This will move the follower to the postion 6 on your list

######Queue Commands (Viewers)

!queue add - Add yourself to the end of the queue

!queue remove - Remove yourself from the queue or current group

!queue players - Lists the players in the current group

!queue size - Show current size of queue

!queue position - Check your position in the queue

Go to https://beta.nightbot.tv/commands/custom and sign in
Click "Add Command"
In the “Command” field, enter !queue
In the “Message” field, enter this:

$(eval ledger = `$(urlfetch json http://twitch.center/customapi/quote/list?token=FIRSTTOKEN&no_id=1)`.split("|"); privateToken = "SECONDTOKEN"; query = `$(query)`; userName = `$(user)`; userLevel = `$(userlevel)`; $(urlfetch json https://pastebin.com/raw/a7SRP4EP))

Then go to https://twitch.center/customapi/quote/generate. You will see three lines. Your first token is after token= and before &data= on the first line. Your second token is after token= and before &data= on the second and third lines. Use these to replace FIRSTTOKEN and SECONDTOKEN in the command that you just entered into the “Message” field.
In the “Alias” field, enter !queuehelper
Click “Submit”

Now click “Add Command” again.
In the “Command” field, enter !queuehelper
In the “Message” field, enter this:

$(eval r=`$(urlfetch json $(query))`;if(r.startsWith("Successfully added entry #")||r=="All entries have been deleted"){m=`$(query)`.match(/&print=(.+)$/);m?decodeURIComponent(m[1]):"!queue is misconfigured"}else{m=`$(query)`.match(/^\$PRINT\$ (.+)$/);m?m[1]:"Use !queue"})

Click “Submit”

The commands will now work. If they don’t work at all for you, check that you followed all the instructions. There may be some bugs that I didn’t notice, though. Let me know if you find any. And let me know if there’s anything you would like me to change.

Subcommands:

!queue on:
Enable queue subcommands (streamer only)

!queue off:
Disable queue subcommands (streamer only)

!queue start:
Allow viewers to join the queue and leave the group or current queue (trusted users only)

!queue stop:
Prevent viewers from joining the queue and leaving the group or current queue (trusted users only)

!queue view:
Print out the queue and current group (trusted users only)

!queue setsize n:
Change the size of all new groups to n (trusted users only)

!queue new:
Generate a new group of the previously set size or the default size (10). If there aren’t enough users in the queue, then some users from the previous group will be readded. (trusted users only)

!queue clear:
Reset the, queue, current group, and new group size (trusted users only)

!queue add u:
Add user u to the queue if they do not already exist (trusted users only)

!queue remove u:
Remove user u from the group or current group if they exist. If the user was in the current group, then the first person from the queue will replace them. (trusted users only)

!queue move u p:
Move user u to position p if the user is in the queue and the position is valid (trusted users only)

!queue join:
Join the queue if you are not already in the queue or current group

!queue leave:
Leave the queue or current group if you are in either. If you were in the current group, then the first person from the queue will replace you if they exist.

!queue players:
List all players in the current group

!queue size:
Say how many people are in the queue

!queue groupsize:
Say how many people are in the group and the set or default group size

!queue position:
Say what position you are in the queue

In case that PasteBin file expires, here is the main code (you can ignore this):

queue = [];
enabled = true;
open = true;
group = [];
size = 10;

for (i = 0; i < ledger.length; i++)
{
    args = ledger[i].split(",");
    
    if (args.length == 0)
        continue;
    
    switch (args[0])
    {
        case "e": /* Enable queue functions */
            enabled = true;
            break;
        case "d": /* Disable queue functions */
            enabled = false;
            break;
        case "o": /* Open queue to viewers */
            open = true;
            break;
        case "c": /* Close queue to viewers */
            open = false;
            break;
        case "s": /* Set group size to n */
            if (args.length != 2)
                continue;
            
            n = parseInt(args[1]);
            if (isNaN(n) || n <= 0)
                continue;
            
            size = n;
            break;
        case "g": /* Generate a new group from the queue */
            if (group.length + queue.length < size)
                continue;
                
            newPlayers = queue.length > size ? size : queue.length;
            reusedPlayers = size - newPlayers;
            
            group = queue.splice(0, newPlayers).concat(group.splice(0, reusedPlayers));
            break;
        case "r": /* If the user is in the queue, remove them. If the user is in the group, remove them and add another from the queue */
            if (args.length != 2)
                continue;
            
            u = args[1].toLowerCase();
            
            /* Check if the user is in the queue, and if so, remove them */
            for (j = 0; j < queue.length; j++)
            {
                if (u != queue[j].toLowerCase())
                    continue;
                
                queue.splice(j, 1);
                break;
            }
            
            /* Check if the user is in the group, and if so, replace them with the first person in the queue (if they exist) */
            for (j = 0; j < group.length; j++)
            {
                if (u != group[j].toLowerCase())
                    continue;
                
                if (queue.length == 0)
                    group.splice(j, 1);
                else
                    group.splice(j, 1, queue.splice(0, 1)[0]);
                break;
            }
            
            break;
        case "j": /* u joins the queue */
            if (args.length != 2)
                continue;
        
            queue.push(args[1]);
            break;
        case "m": /* Move u to position p */
            if (args.length != 3)
                continue;
            
            u = args[1].toLowerCase();
            p = parseInt(args[2]);
            if (isNaN(p) || p < 0 || p >= queue.length)
                continue;
            
            for (j = 0; j < queue.length; j++)
            {
                if (u != queue[j].toLowerCase())
                    continue;
                
                queue.splice(p, 0, queue.splice(j, 1)[0]);
                break;
            }
            break;
    }
}

streamerUserLevels = ["owner"];
trustedUserLevels = ["owner", "moderator", "regular"];

if (enabled || streamerUserLevels.includes(userLevel))
{
    function makeListString(array)
    {
        string = "";
        
        for (k = 0; k < array.length; k++)
        {
            string += array[k];
            if (array.length > 2 && k != array.length - 1)
                string += ", ";
            if (k == array.length - 2)
                string += " and ";
        }
        
        return string;
    }
    
    args = query.split(" ");
    if (query && args.length >= 1)
    {
        addUrl = `http://twitch.center/customapi/addquote?token=${privateToken}&data=`;
        clearUrl = `http://twitch.center/customapi/delquote?token=${privateToken}&clear=1`;
        
        switch (args[0].toLowerCase())
        {
            case "on":
            case "enable":
                if (streamerUserLevels.includes(userLevel))
                {
                    if (enabled)
                        `$PRINT$ ${userName} -> Queue functions are already enabled`;
                    else
                        addUrl + encodeURIComponent("e|") + "&print=" + encodeURIComponent("Queue functions are now enabled!");
                }
                else
                    `$PRINT$ ${userName} -> You must be the streamer to enable the queue`;
                break;
            case "off":
            case "disable":
                if (streamerUserLevels.includes(userLevel))
                {
                    if (!enabled)
                        `$PRINT$ ${userName} -> Queue functions are already disabled`;
                    else
                        addUrl + encodeURIComponent("d|") + "&print=" + encodeURIComponent("Queue functions are now disabled!");
                }
                else
                    `$PRINT$ ${userName} -> You must be the streamer to disable the queue`;
                break;
            case "start":
            case "begin":
            case "open":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (open)
                        `$PRINT$ ${userName} -> The queue is already open`;
                    else
                        addUrl + encodeURIComponent("o|") + "&print=" + encodeURIComponent("The queue is now open!");
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to start the queue`;
                break;
            case "stop":
            case "end":
            case "close":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (!open)
                        `$PRINT$ ${userName} -> The queue is already closed`;
                    else
                        addUrl + encodeURIComponent("c|") + "&print=" + encodeURIComponent("The queue is now closed!");
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to end the queue`;
                break;
            case "view":
            case "show":
            case "list":
            case "all":
                if (trustedUserLevels.includes(userLevel))
                    `$PRINT$ Current group: ${makeListString(group)} | Queue: ${makeListString(queue)}`.substr(0, 400);
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to view the entire queue`;
                break;
            case "setsize":
            case "changesize":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (args.length == 2)
                    {
                        newSize = parseInt(args[1]);
                        if (isNaN(newSize) || newSize <= 0)
                            `$PRINT$ ${userName} -> Enter a positive integer after "!queue ${args[0]}"`;
                        else
                            if (size == newSize)
                                `$PRINT$ ${userName} -> The player group size is already ${size}`;
                            else
                                addUrl + encodeURIComponent(`s,${newSize}|`) + "&print=" + encodeURIComponent(`The player group size was changed from ${size} to ${newSize}!`);
                    }
                    else
                        `$PRINT$ ${userName} -> Enter a new player group size after "!queue ${args[0]}"`;
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to set the player group size`;
                break;
            case "new":
            case "newgroup":
            case "generate":
            case "generategroup":
            case "next":
            case "nextgroup":
                if (trustedUserLevels.includes(userLevel))
                {
                    availablePlayers = group.length + queue.length;
                    if (availablePlayers < size)
                        `$PRINT$ ${userName} -> The number of players in the queue and current group (${availablePlayers}) isn't high enough to generate a new group of size ${size}`;
                    else
                    {
                        newPlayers = queue.length > size ? size : queue.length;
                        reusedPlayers = size - newPlayers;
                        
                        group = queue.splice(0, newPlayers).concat(group.splice(0, reusedPlayers));
                        
                        (addUrl + encodeURIComponent("g|") + "&print=" + encodeURIComponent(`New group: ${makeListString(group)}`)).substr(0, 400);
                    }
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to generate a new group from the queue`;
                break;
            case "clear":
            case "reset":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (ledger == "There are no quotes added")
                        `$PRINT$ ${userName} -> The queue and current group are already empty`;
                    else
                        clearUrl + "&print=" + encodeURIComponent("The queue and current group are now empty!");
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to clear the queue and current group`;
                break;
            case "add":
            case "addviewer":
            case "adduser":
            case "addfollower":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (args.length >= 2)
                    {
                        user = query.substr(query.indexOf(" ") + 1).replace(/[|,]/g, "");
                        u = user.toLowerCase();
                        
                        currentQueuePosition = -1;
                        for (j = 0; j < queue.length; j++)
                        {
                            if (u != queue[j].toLowerCase())
                                continue;
                            
                            currentQueuePosition = j;
                            break;
                        }
                        
                        foundInGroup = false;
                        for (j = 0; j < group.length; j++)
                        {
                            if (u != group[j].toLowerCase())
                                continue;
                            
                            foundInGroup = true;
                            break;
                        }
                        
                        if (currentQueuePosition != -1)
                            `$PRINT$ ${userName} -> ${user} is already in the queue at position ${currentQueuePosition + 1}`;
                        else if (foundInGroup)
                            `$PRINT$ ${userName} -> ${user} is already in the current group`;
                        else
                            addUrl + encodeURIComponent(`j,${user}|`) + "&print=" + encodeURIComponent(`${user} was added to the queue at position ${queue.length + 1}`);
                    }
                    else
                        `$PRINT$ ${userName} -> Enter the viewer to add after "!queue ${args[0]}"`;
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to add a viewer to the queue`;
                break;
            case "remove":
            case "removeviewer":
            case "removeuser":
            case "removefollower":
            case "delete":
            case "deleteviewer":
            case "deleteuser":
            case "deletefollower":
            case "del":
            case "delviewer":
            case "deluser":
            case "delfollower":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (args.length >= 2)
                    {
                        user = query.substr(query.indexOf(" ") + 1).replace(/[|,]/g, "");
                        u = user.toLowerCase();
                        
                        currentQueuePosition = -1;
                        for (j = 0; j < queue.length; j++)
                        {
                            if (u != queue[j].toLowerCase())
                                continue;
                            
                            currentQueuePosition = j;
                            break;
                        }
                        
                        foundInGroup = false;
                        for (j = 0; j < group.length; j++)
                        {
                            if (u != group[j].toLowerCase())
                                continue;
                            
                            foundInGroup = true;
                            break;
                        }
                        
                        if (currentQueuePosition != -1)
                            addUrl + encodeURIComponent(`r,${user}|`) + "&print=" + encodeURIComponent(`${user} was removed from the queue at position ${currentQueuePosition + 1}`);
                        else if (foundInGroup)
                            addUrl + encodeURIComponent(`r,${user}|`) + "&print=" + encodeURIComponent(`${user} was removed from the current group` + (queue.length == 0 ? "" : ` and was replaced by ${queue[0]}`));
                        else
                            `$PRINT$ ${userName} -> ${user} is not in the queue or current group`;
                    }
                    else
                        `$PRINT$ ${userName} -> Enter the viewer to remove after "!queue ${args[0]}"`;
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to remove a viewer from the queue or current group`;
                break;
            case "move":
            case "moveviewer":
            case "moveuser":
            case "movefollower":
                if (trustedUserLevels.includes(userLevel))
                {
                    if (queue.length == 0)
                        `$PRINT$ ${userName} -> The queue is empty`;
                    else if (queue.length == 1)
                        `$PRINT$ ${userName} -> Because there is only 1 viewer in the queue, it cannot be rearranged`;
                    else
                    {
                        match = query.match(/^[^ ]+ +([^ ].*?) +([^ ]+)$/);
                        if (match)
                        {
                            user = match[1].replace(/[|,]/g, "");
                            u = user.toLowerCase();
                            position = parseInt(match[2]);
                            
                            if (isNaN(position) || position < 1 || position > queue.length)
                                `$PRINT$ ${userName} -> The position must be between 1 and ${queue.length}`;
                            else
                            {
                                position -= 1; /* Remove the visual offset */
                                
                                currentPosition = -1;
                                for (j = 0; j < queue.length; j++)
                                {
                                    if (u != queue[j].toLowerCase())
                                        continue;
                                    
                                    currentPosition = j;
                                    break;
                                }
                                
                                if (currentPosition == -1)
                                    `$PRINT$ ${userName} -> ${user} is not in the queue`;
                                else if (position == currentPosition)
                                    `$PRINT$ ${userName} -> ${user} is already in the queue at position ${currentPosition + 1}`;
                                else
                                    addUrl + encodeURIComponent(`m,${user},${position}|`) + "&print=" + encodeURIComponent(`${user} was moved from position ${currentPosition + 1} to ${position + 1}`);
                            }
                        }
                        else
                            `$PRINT$ ${userName} -> Enter the viewer to move and the new position after "!queue ${args[0]}"`;
                    }
                }
                else
                    `$PRINT$ ${userName} -> You must be a trusted user to move a viewer in the queue`;
                break;
            case "join":
                if (open || trustedUserLevels.includes(userLevel))
                {
                    user = userName.replace(/[|,]/g, "");
                    u = user.toLowerCase();
                        
                    currentQueuePosition = -1;
                    for (j = 0; j < queue.length; j++)
                    {
                        if (u != queue[j].toLowerCase())
                            continue;
                            
                        currentQueuePosition = j;
                        break;
                    }
                    
                    foundInGroup = false;
                    for (j = 0; j < group.length; j++)
                    {
                        if (u != group[j].toLowerCase())
                            continue;
                        
                        foundInGroup = true;
                        break;
                    }
                    
                    if (currentQueuePosition != -1)
                        `$PRINT$ ${userName} -> You are already in the queue at position ${currentQueuePosition + 1}`;
                    else if (foundInGroup)
                        `$PRINT$ ${userName} -> You are already in the current group`;
                    else
                        addUrl + encodeURIComponent(`j,${user}|`) + "&print=" + encodeURIComponent(`${userName} joined the queue at position ${queue.length + 1}`);
                }
                else
                    `$PRINT$ ${userName} -> The queue is closed`;
                break;
            case "leave":
                if (open || trustedUserLevels.includes(userLevel))
                {
                    user = userName.replace(/[|,]/g, "");
                    u = user.toLowerCase();
                    
                    currentQueuePosition = -1;
                    for (j = 0; j < queue.length; j++)
                    {
                        if (u != queue[j].toLowerCase())
                            continue;
                        
                        currentQueuePosition = j;
                        break;
                    }
                    
                    foundInGroup = false;
                    for (j = 0; j < group.length; j++)
                    {
                        if (u != group[j].toLowerCase())
                            continue;
                        
                        foundInGroup = true;
                        break;
                    }
                    
                    if (currentQueuePosition != -1)
                        addUrl + encodeURIComponent(`r,${user}|`) + "&print=" + encodeURIComponent(`${userName} left the queue at position ${currentQueuePosition + 1}`);
                    else if (foundInGroup)
                        addUrl + encodeURIComponent(`r,${user}|`) + "&print=" + encodeURIComponent(`${userName} left the current group` + (queue.length == 0 ? "" : ` and was replaced by ${queue[0]}`));
                    else
                        `$PRINT$ ${userName} -> You are not in the queue or current group`;
                }
                else
                    `$PRINT$ ${userName} -> The queue is closed`;
                break;
            case "players":
            case "currentgroup":
            case "group":
                `$PRINT$ Current group: ${makeListString(group)}`.substr(0, 400);
                break;
            case "size":
            case "length":
                `$PRINT$ Queue length: ${queue.length}`;
                break;
            case "groupsize":
            case "currentgroupsize":
                `$PRINT$ Current group size: ${group.length}/${size}`;
                break;
            case "position":
            case "myposition":
                u = userName.toLowerCase();
                
                positionInQueue = -1;
                for (j = 0; j < queue.length; j++)
                {
                    if (u != queue[j].toLowerCase())
                        continue;
                    
                    positionInQueue = j;
                    break;
                }
                
                if (positionInQueue != -1)
                    `$PRINT$ ${userName}'s queue position is ${positionInQueue + 1}`;
                else
                {
                    foundInGroup = false;
                    for (j = 0; j < group.length; j++)
                    {
                        if (u != group[j].toLowerCase())
                            continue;
                        
                        foundInGroup = true;
                        break;
                    }
                    
                    if (foundInGroup)
                        `$PRINT$ ${userName} -> You are in the current group`;
                    else
                        `$PRINT$ ${userName} -> You are not in the queue or current group`;
                }
                break;
            default:
                `$PRINT$ ${userName} -> That is not a valid subcommand`;
                break;
        }
    }
    else
        `$PRINT$ Current group: ${makeListString(group)} | !queue subcommands: join, leave, players, size, groupsize, and position`.substr(0, 400);
}
else
    `$PRINT$ ${userName} -> Queue functions are disabled`;

Hey man, thanks so much, I didn’t hope this post would get an answer, this is really helpful, would you help me out with some additions and some changes?
Please give me your paypal so I can at least tip you for the help and give back something for you :slight_smile:

An aesthetic change would be changing the all the ‘queue’ words to ‘lobby’.

Before I continue I have a question. How can I add trusted users with a command? Or trusted users are given by giving /mod in my chat. This is important because of how the system works and I proceed to explain it in the following pharagraphs.

I’m gonna explain how a dota 2 in-house league system worked. There is a league admin that vouches (gives trusted users permission) to Captains (Mods/Trusted users). This is where I need help with implementing new functions on how the bot works.

Phase 1 - The Challenge Phase.

The Captains (Trusted users/mods) can challenge themselves (They can accept or decline the challenge), it is usually done with the command !chal.
If the challenge is accepted, Phase 2 starts.

Phase 2 - The Picking Phase

Then the queue starts/opens and the viewers can list up. When the List is filled, the bot selects randomly between the 2 captains and gives them a Side (Team Radiant or Team Dire), and then the player picking phase begings. The picking phase is that the The 2 captains Pick from the listed players in a 1-2-2-2-1 turn order from the pool of players by using the command !pick username123. When a player is picked, the player is removed from the list and can’t be unpicked. I remind that the game is 5vs5, so its the 2 caps plus the 8 people they select from a 10+ users pool.

When the picking phase is finished. It lists the Radiant Team members and Dire Team members and tells them to please Join Discord for Voice Communication and asks them to join the Game Lobby.

Phase 3 - Game Phase

During the game, it’s posible something bad happends (disconnects or trolls) and the game must be aborted. 2 Captains or at least 6 players must type !abort so the match is not counted for points.

Phase 4 - Result Phase.

After the game a winner must be declared. The 2 captains or at least 6 players must type !winner radiant or !winner dire for it to be recorded and declared who was the official winner.

###Information Functions (This is optional since I don’t know if this is posible, and I don’t care much about this, but It would be nice to have)

There is also points given to players given on result of the game and editable info profiles made by the own viewer and trusted users (like !info should display their role and game rank, which is written by them or by a trusted user, that information I don’t know where it could be stored or how could it be made with a bot, only the user themself or a mod/trusted user should be able to edit the user info profile. (This would print like <Username123 is Gold Medal , Role: Carry), so captains in the pick phase have some information about who are they going to pick.

Thanks a lot for help man, in advange thank you so much and please consider giving me your paypal so at least I can give something back.

cheers and have a good weekend <3

Hello @am_1 hope you’re doing well, anything up regarding my last post, np if you don’t have time for help. :slight_smile:

Right now. trusted users are Twitch mods and Nightbot regulars (which are added with !regulars add username.)

I will try to add that functionality.

By what you describe in your second post, it sounds like nobody can join the queue unless the picking phase has just started and hasn’t stopped yet. Is this what you mean? In the first post it sounded like anyone could join the queue unless it was closed. It also sounded like the queue could be infinitely large. Please go into more detail about when the queue is joinable and how large it can be.

How are points distributed after a game?

How is a user’s rank (“Gold Medal”) determined by his points?

If you want a trusted user to ONLY be able to challenge other trusted users, this would require you to add trusted users with a command like !trust name1,name2,name3,name4,name5. Mods and regulars would not automatically be trusted, because AFAIK it’s not possible to check another user’s mod/regular status. Is this what you mean?

Are you aware of Nightbot’s minimum command cooldown of 5 seconds? Will this work for you, considering the pace of the picking phase?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.