Discord DCC_GetRoleName
#1

How can i get the 'rolename'?
pawn Code:
forward DCC_OnMessageCreate(DCC_Message:message);
public DCC_OnMessageCreate(DCC_Message:message)
{
    new realMsg[100];
    DCC_GetMessageContent(message, realMsg, 100);
    new bool:IsBot;
    new DCC_Channel:channel;
    DCC_GetMessageChannel(message, channel);
    new DCC_User:author;
    DCC_GetMessageAuthor(message, author);
    //==================I'm confused with this==================================
    new DCC_Role:role, rolename[128];//<<<<<<<<<<<<<<<<<<<<
    DCC_GetRoleName(role, rolename, 128);//<<<<<<<<<<<<<<<<<<<<
    //==========================================================================
    DCC_IsUserBot(author, IsBot);
    if(IsBot) return 1;
    new discordstr[256];
    new command[32], params[128];
    DCC_GetMessageContent(message, discordstr);
    sscanf(discordstr, "s[32]s[128]", command, params);
    if(channel == g_Discord_Admin_CMD)
    {
        if(!strcmp(command, "!mycommand", true)) {
            if(rolename == g_Role_Level_1 || rolename == g_Role_Level_2 || rolename == g_Role_Level_3 || rolename == g_Role_Level_4) {//<<<<<<<<<<<<<<<<<<<<<<<<
                //My actions
            } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
        }
    }
    return 1;
}
Code:
error 033: array must be indexed (variable "rolename")
I tried it some ways, and still getting errors.
Reply
#2

From what I see, your variable name rolename is an array. So the check should be like this:
Quote:

if(!strcmp(rolename, g_Role_Level_1, false)

Reply
#3

Quote:
Originally Posted by SharpenBlade
View Post
From what I see, your variable name rolename is an array. So the check should be like this:
So, is this already correct? Because i dont even think so.
pawn Code:
new DCC_Role:role, rolename[128];//<<<<<<<<<<<<<<<<<<<<
    DCC_GetRoleName(role, rolename, 128);//<<<<<<<<<<<<<<<<<<<<
I tried to get the 'author's role by this (check the code at the top to see 'author'):
pawn Code:
new rolename[128];
    DCC_GetRoleName(author, rolename, 128);
Which is the correct one? Or how can i make the correct one?

EDIT: This code :
pawn Code:
if(!strcmp(rolename, g_Role_Level_1, false)) {
    //My action
}
Shows this error :
Code:
error 035: argument type mismatch (argument 2)
EDIT: I got this :
pawn Code:
new DCC_Role:g_Role_Level_1;
new DCC_Role:g_Role_Level_2;
new DCC_Role:g_Role_Level_3;
new DCC_Role:g_Role_Level_4;
new DCC_Role:g_Role_Level_5;
new DCC_Role:g_Role_Level_6;
new DCC_Role:g_Role_Level_7;
new DCC_Role:g_Role_Level_8;
And this under OnGameModeInit()

pawn Code:
g_Role_Level_1 = DCC_FindRoleById("myroleid");
g_Role_Level_2 = DCC_FindRoleById("myroleid");
g_Role_Level_3 = DCC_FindRoleById("myroleid");
g_Role_Level_4 = DCC_FindRoleById("myroleid");
g_Role_Level_5 = DCC_FindRoleById("myroleid");
g_Role_Level_6 = DCC_FindRoleById("myroleid");
g_Role_Level_7 = DCC_FindRoleById("myroleid");
g_Role_Level_8 = DCC_FindRoleById("myroleid");
Reply
#4

bump please anyone.. i really need it
Reply
#5

Quote:
Originally Posted by killermvc
View Post
pawn Code:
new DCC_Role:role, rolename[128];//<<<<<<<<<<<<<<<<<<<<
    DCC_GetRoleName(role, rolename, 128);//<<<<<<<<<<<<<<<<<<<<
No this isn't correct.

DCC_GetRoleName will copy the name of the specified role (the variable named 'role') to the array you pass it (rolename in this case) howewer, as you just created the variable 'role' it currently holds the value 'DCC_Role:0', which if you check discord-connector.inc is an invalid role
pawn Code:
#define DCC_INVALID_ROLE DCC_Role:0
You need to retrieve the role(s) of the author of the message, for this, discord-connector has the function
pawn Code:
'native DCC_GetGuildMemberRole(DCC_Guild:guild, DCC_User:user, offset, &DCC_Role:role);'
A bot (and a user) can be in many guilds (discord servers) so you need to specify for which server you want to get that user's roles. To retrieve your guild you may use:
pawn Code:
native DCC_Guild:DCC_FindGuildById(const guild_id[]);
This will return the guild that you should use to call 'DCC_GetGuildMemberRole'
Now, a user may have many roles not just one, so you need to retrieves all of the roles and compare each with the allowed roles for the command.
This is what the third parameter of 'DCC_GetGuildMemberRole' ('offset') is for. If offset is 0 you will get the first role of this user, if is 1 you will get the second role, etc. To know how many roles the user has use:
pawn Code:
native DCC_GetGuildMemberRoleCount(DCC_Guild:guild, DCC_User:user, &count);
Then you just need to loop through each of the user's role
Finally the code would look something like this:
pawn Code:
//optionally you may prefer to make 'DCC_Guild:guild' global and call 'DCC_FindGuildById' in OnGamemodeInit
//so that it only gets called once and not each time someone uses a command
new
    DCC_Guild:guild = DCC_Guild:DCC_FindGuildById("yourGuildId"),
    roleCount,
    DCC_Role:role;

DCC_GetGuildMemberRoleCount(guild, author, roleCount);
if(channel == g_Discord_Admin_CMD) {
    if(!strcmp(command, "!mycommand", true)) {
        //Loop through all roles for this user
        for(new  i = 0; i < roleCount; i++) {
            DCC_GetGuildRole(guild, i, role);
            //you can compare 'role' directly to 'g_Role_Level_X'
            if(role == g_Role_Level_1 || role == g_Role_Level_2 || role == g_Role_Level_3 || role == g_Role_Level_4) {
                    //My actions
            //if you don't break here the command may execute many times. for example if user has both g_Role_Level_1 and g_Role_Level_3
            break;
            } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
        }
    }

    //other commands
}
O ma gad.. i just jumped out of my bed knowing that someone just replied my topic xd... Thanks bud gonna test it

EDIT: I got
Code:
warning 225: unreachable code
for every breaks.. how to fix that?
Reply
#6

pawn Code:
DCC_GetGuildMemberRoleCount(guild, author, roleCount);
if(channel == g_Discord_Admin_CMD) {
    if(!strcmp(command, "!mycommand", true)) {
        //Loop through all roles for this user
        for(new  i = 0; i < roleCount; i++) {
            DCC_GetGuildRole(guild, i, role);
            //you can compare 'role' directly to 'g_Role_Level_X'
            if(role == g_Role_Level_1 || role == g_Role_Level_2 || role == g_Role_Level_3 || role == g_Role_Level_4) {
                    //My actions
            //if you don't break here the command may execute many times. for example if user has both g_Role_Level_1 and g_Role_Level_3
            break;
            } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
        }
    }

    //other commands
}
Let's say there are 5 roles. Level 0 up to 4. Someone with level 0 uses this.
pawn Code:
for (new i; i < roleCount; i++)
{
    //Loop i=0:
    Get user role (role = 0)
    Role is not 1,2,3 or 4.
    Send message: ERROR: You are not a high enough level to use this command.
    Break entire function (not just the loop), return return value of DCC_SendChannelMessage();
}
Now let's say they have level 2.
pawn Code:
for (new i; i < roleCount; i++)
{
    //Loop i=0:
    Get user role (role = 0) //Assuming this role is read before any other role.
    Role is not 1,2,3 or 4
    Send message: ERROR: You are not a high enough level to use this command.
    Break entire function (not just the loop), return return value of DCC_SendChannelMessage();
}
You might wanna use DCC_HasGuildMemberRole(DCC_Guild:guild, DCC_User:user, DCC_Role:role, &bool:has_role); instead. This piece of code (as you can see) is
1- Inefficient because it could loop through all the roles every time someone uses that commands.
2- As seen in a above example, if their first read role is not level 1-4, it would send the error aswell.


As of the unreachable code; make sure you have no code after using return/break/continue in the same level.
Reply
#7

Quote:
Originally Posted by Kwarde
View Post
pawn Code:
DCC_GetGuildMemberRoleCount(guild, author, roleCount);
if(channel == g_Discord_Admin_CMD) {
    if(!strcmp(command, "!mycommand", true)) {
        //Loop through all roles for this user
        for(new  i = 0; i < roleCount; i++) {
            DCC_GetGuildRole(guild, i, role);
            //you can compare 'role' directly to 'g_Role_Level_X'
            if(role == g_Role_Level_1 || role == g_Role_Level_2 || role == g_Role_Level_3 || role == g_Role_Level_4) {
                    //My actions
            //if you don't break here the command may execute many times. for example if user has both g_Role_Level_1 and g_Role_Level_3
            break;
            } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
        }
    }

    //other commands
}
Let's say there are 5 roles. Level 0 up to 4. Someone with level 0 uses this.
pawn Code:
for (new i; i < roleCount; i++)
{
    //Loop i=0:
    Get user role (role = 0)
    Role is not 1,2,3 or 4.
    Send message: ERROR: You are not a high enough level to use this command.
    Break entire function (not just the loop), return return value of DCC_SendChannelMessage();
}
Now let's say they have level 2.
pawn Code:
for (new i; i < roleCount; i++)
{
    //Loop i=0:
    Get user role (role = 0) //Assuming this role is read before any other role.
    Role is not 1,2,3 or 4
    Send message: ERROR: You are not a high enough level to use this command.
    Break entire function (not just the loop), return return value of DCC_SendChannelMessage();
}
You might wanna use DCC_HasGuildMemberRole(DCC_Guild:guild, DCC_User:user, DCC_Role:role, &bool:has_role); instead. This piece of code (as you can see) is
1- Inefficient because it could loop through all the roles every time someone uses that commands.
2- As seen in a above example, if their first read role is not level 1-4, it would send the error aswell.


As of the unreachable code; make sure you have no code after using return/break/continue in the same level.
I have it like this :
pawn Code:
if(!strcmp(command, "!mycommand", true)) {
            for(new  i = 0; i < roleCount; i++) {
                DCC_GetGuildRole(g_Discord_Guild, i, rolename);
                if(rolename == g_Role_Level_1 || rolename == g_Role_Level_2 || rolename == g_Role_Level_3 || rolename == g_Role_Level_4) {
                    //My actions
                    break;
                } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
            }
        }
or should i break it like :
pawn Code:
if(!strcmp(command, "!mycommand", true)) {
            for(new  i = 0; i < roleCount; i++) {
                DCC_GetGuildRole(g_Discord_Guild, i, rolename);
                if(rolename == g_Role_Level_1 || rolename == g_Role_Level_2 || rolename == g_Role_Level_3 || rolename == g_Role_Level_4) {
                    //My actions
                } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
                break;
            }
        }
Reply
#8

Are you sure that there are no more "break"s in the "My actions" part?
The second example should absolutely not be done. break stops a loop and proceeds to code after the loop. If we take this example:

pawn Code:
main()
{
    for (new i; i <= 2; i++)
    {
        if (!i) //Aka "if (i == 0)". !variable equals variable == 0. This statement will only return true if i is 0 (-1 would also return true)
            continue; //If i is 0, cancel the current loop and go to the next loop.
        printf("This is message number %d!", i);
    }
}
This would produce:
Code:
>> Start loop with i, run it as long as i is 2 or less, increase i with every loop
[i = 0]
if (!i) is true: continue to the next loop, increase i with 1 (i++)
[i = 1]
if (!i) is false: do nothing (thus proceeding to the rest of the code)
print: This is message number 1!
Increase i with 1 (i++)
[i = 2]
if (!i) is false: do nothing (thus proceeding to the rest of the code)
print: This is message number 2!
Increase i with 1 (i++)
[i = 3]: Aborting loop
Now if you add a break to it like you did on the second example:
pawn Code:
main()
{
    for (new i; i <= 2; i++)
    {
        if (!i) //Aka "if (i == 0)". !variable equals variable == 0. This statement will only return true if i is 0 (-1 would also return true)
            continue; //If i is 0, cancel the current loop and go to the next loop.
        printf("This is message number %d!", i);
        break;
        print("This code is unreachable!");
    }
}
This would produce (in the runtime):
Code:
>> Start loop with i, run it as long as i is 2 or less, increase i with every loop
[i = 0]
if (!i) is true: continue to the next loop, increase i with 1 (i++)
[i = 1]
if (!i) is false: do nothing (thus proceeding to the rest of the code)
print: This is message number 1!
>BREAK<; Aborting entire loop
As you can see it skips a part that you actually wanted to show. Your code does not use continue so using that second example it will run only once.

However, if we take another look at your code:
pawn Code:
if(!strcmp(command, "!mycommand", true)) {
            for(new  i = 0; i < roleCount; i++) {
                DCC_GetGuildRole(g_Discord_Guild, i, rolename);
                if(rolename == g_Role_Level_1 || rolename == g_Role_Level_2 || rolename == g_Role_Level_3 || rolename == g_Role_Level_4) {
                    //My actions
                    break;
                } else return DCC_SendChannelMessage(g_Discord_Admin_CMD, "```ERROR: You are not a high enough level to use this command```");
            }
        }
Let's assume we have this sitation:

>> We have 5 g_Role_Level_s; g_Role_Level 0 up to g_Role_Level 4. Let's assume they are called this on Discord:
g_Role_Level_0 = User
g_Role_Level_1 = Admin level 1
g_Role_Level_2 = Admin level 2
g_Role_Level_3 = Admin level 3
g_Role_Level_4 = Admin level 4

Let's say that "g_Role_Level_0" is actually called before the other ones in the loop (i = 0 == g_Role_Level_0). In that scenario this would happen:
Code:
command equals "!mycommand"
>> Start loop with i, run it as long as i is less than variable roleCount. Increase i with every loop
[i = 0]
DCC_GetGuildRole on index 0 (i), save outcome to variable rolename
rolename = g_Role_Level_0 (User)
rolename does not equal g_Role_Level_1, g_Role_Level2, g_Role_Level3 or g_Role_Level 4; running the code after else:
>>return<< DCC_SendChannelMessage...
return: break the loop, return the return value of DCC_SendChannelMessage and break the entire function
That's it, the end. No matter if someone is admin or not (assuming the User level is called first), it would never work this way. Hence I recommend using DCC_HasGuildMemberRole()

As for the unreachable code; double check if there are no return, break or continue keywords in the code that should run. Also make sure, if it's used, there is no code in the rest of that level. Eg.

pawn Code:
MyCommand()
{
    //This space is the highest level inside MyCommand()
    new i;
    while (i < 50)
    {
        //Lower level [1]
        i++;
        if (i == 20)
        {
            //Lower level [2]
        }
        else continue; //NOTE: If this was "else return" like you did the print() function below (outside of the loop) would never run!
        //Code placed here would never run anyway
    }
    //Even more code here, back to highest level of MyCommand()
    print("This will not print if else continue is else return");
}
You can see in this example that if you use "else return", the entire function would stop; it does not just stop the code in that specific level.
I hope these examples may clear things out a bit
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)