I'm making a Discord bot, but on the part where the bot determines the Permission of the Author, it does not recognise roles, valuables like "owner" and "admin" are the ID of the role, What is the format for discord.Role?
I've tried making classes with an id and name
perms = 0
if moderator in message.author.roles:
perms = 1
if admin in message.author.roles:
perms = 2
if owner in message.author.roles:
perms = 3
if muted in message.author.roles:
perms = -1
Right now it outputs perms as 0 even though it should be 3 as my role is "owner".
According to the discord.py documentation member.roles (or message.author.roles in your case) returns a list of Role class instances, not role IDs (documentation entry).
You can read about the Role class in the documentation as well.
If you want to check if a member has a role with the specified ID, you can get a list of his role IDs first:
perms = 0
ids = [role.id for role in message.author.roles]
if moderator in ids:
perms = 1
if admin in ids:
perms = 2
if owner in ids:
perms = 3
if muted in ids:
perms = -1
Related
How to add role by name not id. group is string
await message.author.add_roles(message.author, group)
You can use discord.utils.get function for this:
role_name = "role" # specify role name here
role = discord.utils.get(message.guild.roles, name=role_name)
if role is not None:
await message.author.add_roles(role)
I've been banging my head against this. Here's a sample of data frames I have:
df_users:
Email Roles
johndoe0#example.com
johndoe1#example.com
johndoe2#example.com
johndoe3#example.com
johndoe4#example.com
df_groups:
Group1 Group2 Group3
johndoe0#example.com johndoe4#example.com johndoe0#example.com
johndoe1#example.com johndoe1#example.com
johndoe4#example.com johndoe2#example.com
johndoe3#example.com
df_roles:
Group1 Group2 Group3
Role 1 True False False
Role 2 False True True
Role 3 False False True
Here's what I need the output to be:
Email Roles
johndoe0#example.com Role 1
johndoe0#example.com Role 2
johndoe0#example.com Role 3
johndoe1#example.com Role 1
johndoe2#example.com Role 2
johndoe3#example.com Role 3
johndoe2#example.com Role 2
johndoe2#example.com Role 3
johndoe3#example.com Role 2
johndoe3#example.com Role 3
johndoe4#example.com Role 1
I tried doing this in Excel. One of the challenges it that in the actual data, there are hundreds of emails, >100 roles, and dozens of groups.
What I'm thinking of is something like:
# Prepare yourself for bad pseudo-code
for each user in df_users
for each group in in df_groups
if the user is in the group:
if the row value is 'True' in df_roles:
add the value of the first column in df_roles to the 'Roles' column in df_users...
if a role already exists, append it with a ',' delimiter
Hopefully that shows what I'm going for.
Try This:
# data structure that will hold tuple of user and role
users_roles = []
# function that creates sets in order to optimize the search
def create_sets(users_groups):
list_sets = []
for col in list(users_groups.columns):
s = set(list(users_groups[col]))
if '' in s:
s.remove('')
list_sets.append(s)
return list_sets
all_groups_sets = create_sets(df_groups)
for user in list(df_users['Email']):
for idx, group_set in enumerate(all_groups_sets):
if user in group_set:
for i in range(len(df_roles)):
if df_roles.iloc[i][idx]:
users_roles.append((user, 'Role' + ' ' + str(i+1)))
final = pd.DataFrame(users_roles, columns=['Email', 'Role'])
I have two tables
class User(models.Model):
id = fields.BigIntField(pk=True)
name = CharField(max_length=100)
tags: fields.ManyToManyRelation["Tag"] = fields.ManyToManyField(
"models.Tag", related_name="users", through="user_tags"
)
class Tag(models.Model):
id = fields.BigIntField(pk=True)
name = fields.CharField(max_length=100)
value = fields.CharField(max_length=100)
users: fields.ManyToManyRelation[User]
Let's assume this dummy data
#users
bob = await User.create(name="bob")
alice = await User.create(name="alice")
#tags
foo = await Tag.create(name="t1", value="foo")
bar = await Tag.create(name="t2", value="bar")
#m2m
await bob.tags.add(foo)
await alice.tags.add(foo, bar)
Now I want to count users who have both tags foo and bar, which is alice in this case, so it should be 1.
The below query will give me a single level of filtering, but how do I specify that the user should have both foo and bar in their tags ?
u = await User.filter(tags__name="t1", tags__value="foo").count()
Tortoise-ORM provides Q objects for complicated queries with logical operators like |(or) and &(and).
Your query could be made like this:
u = await User.filter(Q(tags__name="t1") &
(Q(tags__value="foo") | Q(tags__value="bar"))).count()
Since you cannot group_by on the annotated field in Tortoise ORM as of now.
Here's the solution using the having clause referred from here
u = await User.filter(Q(tags__value="foo") | Q(tags__value="bar"))
.annotate(count=Count("id"))
.filter(count==2)
The idea is to get the records having a count equal to the number of tags, which is 2 in this case (bar, foo)
I am trying to get a list of all the roles my bot has from top to bottom so I can get the highest role's color.
Not sure what you mean by the "highest role's color", also your post is missing your code.
One way to get the roles the bot has in the guild (via a command) is to get the guild member object and then loop the role objects for that member.
Try this:
#bot.command()
async def list_roles(ctx):
bot_member = ctx.guild.get_member(bot.user.id)
for bot_role in bot_member.roles:
print(f'guild role {bot_role} color {bot_role.color}')
Console output:
guild role #everyone color #000000
guild role masterbot color #2ecc71
guild role winnerPicker color #e67e22
guild role gabAdmin color #ad1457
you can do a loop in all roles like this using Guild.roles
#bot.command()
async def get_roles(ctx):
all_roles = []
for role in ctx.guild.roles:
all_roles.append(role.name)
all_roles.reverse()# to make it higher first
print(all_roles)
you can do with .me in a guild
getting the list:
Guild = THE GUILD YOU WANT TO GET THE ROLES
BotMember = GUILD.members.me
for role in BotMember.roles:
print(f'Role: {role.name} Color: {role.color}')
console log:
Role: #everyone Color: #000000
Role: BaldeGuy Color: #2ecc71
Role: Lorrita Color: #e67e22
Role: Moderator Color: #ad1457
getting the highest role:
Guild = THE GUILD YOU WANT TO GET THE ROLES
BotMember = GUILD.members.me
HighestRole = BotMember.roles.highest.name
print(f'Highest role: {HighestRole}')
console.log:
Highest role: {Moderator}
I'm trying to use lower() so the role names are not case sensitive. So if a user types lol instead of LoL it won't go through the if statement if not role_id:
This is how I'm doing it:
#commands.command()
#commands.check(lambda ctx: ctx.channel.id in [555844758778544160])
async def add(self, ctx, *, rolename):
author = ctx.message.author
role_dict = {
"Members":557212810468392970,
"PS4":568761643916328960,
"LoL":559792606364565505}
role_id = role_dict.get(rolename.lower())
if not role_id:
await ctx.send("I cannot find the role {}.".format(rolename))
return
role = discord.utils.get(ctx.message.guild.roles, id = role_id)
message = '{} added the role **{}**'.format(author.display_name, role.name)
embed = discord.Embed(description=message.format(author.display_name, role.name), colour=0xff0000)
await author.add_roles(role)
await ctx.send("Role Added")
This line here role_id = role_dict.get(rolename.lower()) is the culprit when I add the role !add lol rather than LoL this is what I'm getting:
Help much appreciated.
The problem is that you're comparing a lowercase rolename with dictionary keys that are not in lowercase. For a case-insensitive check, both the rolename and dictionary keys should be lowercase.
Either manually change the dictionary keys to lowercase:
role_dict = {
"members":557212810468392970,
"ps4":568761643916328960,
"lol":559792606364565505}
Or create it programmatically with a dict comprehension, and check if rolename.lower() is in the lowercase dict:
role_dict = {
"Members":557212810468392970,
"PS4":568761643916328960,
"LoL":559792606364565505}
lowercase_dict = {k.lower():v for k,v in role_dict.items()}
role_id = lowercase_dict.get(rolename.lower())
if not role_id:
await ctx.send("I cannot find the role {}.".format(rolename))
return