In Hikari (Python API for bots) how do you create and add roles (while specifying permissions)? I've already tried, but to no avail.
perms = (Permissions.READ_MESSAGE_HISTORY
| Permissions.SPEAK
| Permissions.CONNECT
| Permissions.USE_VOICE_ACTIVITY)
muted = Role(name="muted", permissions=perms)
I've tried this, but i get an error saying I need some other kwargs, but i don't understand all of them.
You don't want to create a Role object directly, instead you use the bots rest attribute to create it for you.
This is a working script that creates the a role called custom-role with the permissions you specified when you send a message in the guild with the content $$create-role. Keep in mind this code will error if the bot does not have the MANAGE_ROLES permission, and you'll need to update the admin id's accordingly to be able to use the command youself.
The documentation for the create_role method can be found here.
import os
import hikari
bot = hikari.GatewayBot(os.environ["TOKEN"])
admin_ids = [1234, 5678, 9101] # These should ideally be stored in a database.
#bot.listen()
async def on_message(event: hikari.GuildMessageCreateEvent) -> None:
if event.is_bot or not event.content:
# Ignore bots and empty messages
return None
if event.author_id not in admin_ids:
# Only allow admins to run this command
return None
if event.content.startswith("$$create-role"):
# Create the role, with the permissions
role = await bot.rest.create_role(
event.guild_id,
name="custom-role",
permissions=(
hikari.Permissions.READ_MESSAGE_HISTORY
| hikari.Permissions.SPEAK
| hikari.Permissions.CONNECT
| hikari.Permissions.USE_VOICE_ACTIVITY
)
)
# Send a message to the channel that we created the role
await event.message.respond(f"Created new role <#&{role.id}>")
if __name__ == "__main__":
bot.run()
Related
trying to make a small bot for my server. it kinda works but if the user removes the nickname, the bot returns a None value. how can i fix this?
the goal is to have a bot detect if a user has TBU in the nickname or username, if it does, add him to a role in discord (havnt added this yet, need to look into it) but if the change removes TBU in the name, remove the role.
#client.event
async def on_member_update(before, after):
if before.nick != after.nick: # to only run on status
embed = discord.Embed(title=f"Changed nick")
embed.add_field(name='User', value=before.mention)
embed.add_field(name='Before', value=before.nick)
embed.add_field(name='After', value=after.nick)
# send to admin or channel you choose
channel = client.get_channel(526517582963146762) # notification channel
await channel.send(embed=embed)
admin = client.get_user(174749290902716417) # admin to notify
await admin.send(embed=embed)
if "TBU" in after.nick:
admin = client.get_user(174749290902716417) # admin to notify
await admin.send(embed=embed)
if "TBU" in before.nick and not "TBU" in after.nick:
admin = client.get_user(174749290902716417) # admin to notify
await admin.send(embed=embed)
When a user has no nickname nick returns None.
Change if before.nick != after.nick to if before.nick != after.nick and after.nick is not None, this should work.
I'm trying to get it so a specific role can react to the message to be able to ban the user, I have made the ability to be able to react to the message, and the author of the command can ban the user, but I want to make it so another role can do it as well
Here is what I have currently
def check(rctn, user):
return user.id == ctx.author.id and str(rctn) == '<:tick:837398197931868190>'
reaction, user = await bot.wait_for('reaction_add', check=check)
You can use #commands.has_permissions
For example you could make it:
#bot.command()
#commands.has_permissions(ban_members=True)
# rest of your code
This way only roles with the permissions to ban_members can use the command
I want my bot to change user roles depending on nickname patterns (basically the company ID).
When the user puts his ID in the nickname, on_member_update() is called normally.
In the function, the bot adds roles and changes the nickname again to a specific pattern. This triggers the on_member_update() yet again.
Note that I have the bot in 1 guild only.
I tried to stop it by adding
if before.display_name == after.display_name:
return
But it still enters the function when the nickname is changed. Is there a way to avoid the function triggering itself again?
The code:
#bot.event
async def on_member_update(before, after):
if before.display_name == after.display_name:
return
id = re.findall(r'\d{6,7}', after.display_name)
if not id:
return
else:
# Business logic (changing nickname, adding roles etc...)
This is not an entire answer but it will guide you in the right direction.
You have to keep record of ids of changed users either in a database or using a JSON file. I called it users_changed which should be a list.
Note: that id is reserved in Python you must use another thing maybe even id_
users_changed = [11111,22222,33333] # get this from the db or file.
#bot.event
async def on_member_update(before, after):
if before.id in users_changed:
return
# code here
# then add before.id into the users_changed
I have an application which is school based. Each tenant is a different school and to access the application all users for each school have the same password.
Alongside this each school user has to have a google email if they want access to the application. So the application first checks they are a google user, checks wether they are a school user and finally checks that their google email is in the school user list before they are allowed access to any page.
The school user part is using session data from webapp2 sessions to ensure each request they have appropriate access
class Handler(webapp2.RequestHandler):
def dispatch(self):
# Get a session store for this request.
self.session_store = sessions.get_store(request=self.request)
try:
# Dispatch the request.
webapp2.RequestHandler.dispatch(self)
finally:
# Save all sessions.
self.session_store.save_sessions(self.response)
#webapp2.cached_property
def session(self):
# Returns a session using the default cookie key.
return self.session_store.get_session()
When a user logins I check the password then create a session which checks their password / user combination every request.
def check_u(self):
try:
uid = self.session.get('user')
parent = self.session.get('school-id')
udl = m.models.User.by_id(int(uid),parent)
if uid and udl:
return udl
else:
return False
except (TypeError,AttributeError):
return False
A parent datastore entity for each different school is used called MetaSchool which I have been currently using to ensure that there is no data leak across schools. Each datastore entry uses this parent session key as a way of setting the datastore entry with MetaSchool as parent then using this session key again to read back this data.
This method works but is onerous. I would like to use namespace as a way of separating the data but would like to use the Metaschool id as the name.
def namespace_manager_default_namespace_for_request():
### Here I need to get ------ parent = self.session.get('school-id')
### use this session to gain the MetaSchool key id
### Set this as the namespace name
Basically trying to emulate from the docs the below scenario
from google.appengine.api import users
def namespace_manager_default_namespace_for_request():
# assumes the user is logged in.
return users.get_current_user().user_id()
I am having difficulty getting the session data from Handler object???
Any thoughts
This is what I came up with.
from google.appengine.api import namespace_manager
from webapp2_extras import sessions
def namespace_manager_default_namespace_for_request():
session = sessions.get_store()
s = session.get_session()
name = s.get('key')
if name:
return name
else:
return namespace_manager.set_namespace('string')
I am quite new to this Google app engine. I am learning things every day.
I am have a forum on google app engine.
But I want is to be having private or restricted parts.
Some features should be locked for certain google account users, which are in some sort of access control list.
I plain words I can say, only those user who are in list of access can see the forum rest will be redirect to the "contact to admin" page.
As I am new I wanna know that is it something possible.
if yes, how can I achieve it ?
Thanks,
Alok
If you are using the built-in Users API, you can check users.is_current_user_admin() as an access control mechanism. Administrators can be managed via the dashboard.
If you need more granular, application-specific authorization logic, generally you would create a User model in the datastore that references the built-in UserProperty and also holds a list of roles or whatever else you need to check authorization.
To follow up Drew's reply, I use a similar system in my app, so my server code has something like the following class definition (simplified here for clarity)
class myUser(db.Model):
user = db.UserProperty(required=True)
rights = db.StringProperty(required=True, choices=set(["public", "private"]))
created = db.DateTimeProperty(auto_now_add=True)
lastaccess = db.DateTimeProperty(auto_now=True)
and then I have code like this where I handle queries
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# create a new 'public access' user if we haven't seen this person before
u = myUser(user=user, rights="public")
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
rights = checkUser(users.get_current_user())
if isPrivateArea and rights == "private":
....
This way I create a user for EVERY visitor, and then I have an admin interface to change the rights of selected users - you may decide, for example, to not create a record for every visitor
def checkUserRights(user):
q = db.GqlQuery("SELECT * from myUser WHERE user = :1", user)
u = q.get()
if not u:
# grant default public rights to anyone...
return "public"
# always update the user record after the source is fetched (updates the lastaccess field)
db.put( u )
return u.rights
This is, of course, on a page where the app.yaml specifies "login: required"