Changing a member's nickname with JDA - discord-jda

I am trying to change someones nickname, but I keep getting this error: net.dv8tion.jda.api.exceptions.HierarchyException: Can't modify a member with higher or equal highest role than yourself!
This is my code:
Member m = e.getMember();
m.modifyNickname(rank.getDisplayName() + " | " + p.getName()).queue();

In the first case, whenever a bot tries to modify the:
Nickname
Role
Or tries to:
Kick
Ban
Timeout
a user, Discord will check if the user is allowed to do so.
This is checked by Discord looking if the bot has a role higher, then the highest role the user it tries to effect has..
In JDA, there should be a util for this. PermissionUtil.canInteract(Member, Member). However, as far as I could find. This is something JDA internal, and should not be used.
In your case, you are either above the bot, or you're the owner. (Whom is always the highest and always has admin)

Related

Discord.py | How do I get a User Tag from an ID?

I am programming an entertainment bot with discord.py, and I want to code a function that allows you to look at other users' in game money and stuff with replit databases. Since making data with a user tag is inefficient since people change their usernames and tags all the time, I am using IDs. I am trying to find a way to get a user tag (eg. Dude#1234) from a user number id (eg. 871954599731396648). I couldn't find a solution. I already know how to use ctx.message.author.id but I can't find a way to make that work with every discord user.
To get the tag you can use the following method
user = await bot.fetch_user(ID) # ID must be an int and this could be could be client for you, be careful as this pings the API and can be abused if not correctly limited.
# user.discriminator will return their tag.
You can check all attributes that user can have here
To get the tag, you first have to get the user object from the id using discord.utils.get:
user_id = #insert the id of the user which you want the tag of
user = await discord.utils.get(client.get_all_members(), id =user_id)#might by something like bot.get_all_members for you
tag = user.name

bot framework and Microsoft teams - how to get all channels associated to a team?

I am trying to get all channels associated with a specific team so that my bot can send proactive messages. Based on the reading I've done, I need to use the FetchChannelList method in the Microsoft.Bot.Connector.Teams namespace, in the TeamsOperationsExtensions class.
If I do this:
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
ConversationList channels = connector.GetTeamsConnectorClient().Teams.FetchChannelList(activity.GetChannelData<TeamsChannelData>().Team.Id);
channels is null. If I break it down to only connector.GetTeamsConnectorClient(), that is not null, but connector.GetTeamsConnectorClient().Teams.FetchChannelList(activity.GetChannelData().Team.Id) is.
To break it down further, I tried to get activity.GetChannelData(). Only the Tenant property is not null. All the others (Channel, Team, EventType and Notification) are null.
I am using tunnelrelay, which forwards messages sent to the bot's public endpoint to a private endpoint, and am using tenant filter authentication in the messages controller. Not sure if that would cause any problems? (When I watch messages coming in through tunnel relay, I see there too that only Tenant is the only channeldata property which is not null. Here's what I see in tunnelrelay:
"entities":[{"locale":"en- US","country":"US","platform":"Windows","type":"clientInfo"}],"channelData":{"tenant":{"id":"our_tenant_id"}}}
Also, regarding the teamID expected as a parameter to the FetchChannelList method, how do I find out what that is for a given team other than the GetChannelData() method? I tried the powershell cmdlet Get-Team (for example: Get-Team -User me#abc.com). It returns a distinct groupId for each team I am a part of, but I'm assuming groupId != TeamId. Is that correct? And, where can I find the teamId that the FetchChannelList is expecting other than the GetChannelData method?
Thanks in advance for any help!
The problem here was that the message to the bot (the activity) was a direct message, not a part of a channel conversation. Apparently, the Channel and Team properties are only available in a channel conversation.
Also, regarding the team ID, one way to get it outside of code is to click the "..." next to the team and click "get link to team". You will see something like:
https://teams.microsoft.com/l/team/19%3a813345c7fafe437e8737057505224dc3%40thread.skype/conversations?groupId=Some_GUID&tenantId=Some_GUID
The line after team/ (19%3a813345c7fafe437e871111115934th3%40thread.skype) contains the teamId, but not exactly. If you replace the first % and the two characters immediately following it with : and the second % and the two characters immediately following it with #, that is your teamid. So, from:
19%3a813345c7fafe437e871111115934th3%40thread.skype
the team ID is:
19:813345c7fafe437e871111115934th3#thread.skype

Discord.js Display Server User Count separately from Server Bot Member Count

I am trying to create a serverinfo command for my Discord.js Bot. I am trying to get the Discord Server User Count separate from the Server's Bot Count. I have been told to use the .filter but I don't understand how to filter the bot count from the user count.
Well from guild.members.cache you'll get a Collection with all the members (users and bots). With .filter you can "exclude" items of a collection if they don't match something. For example:
guild.members.cache.filter(member => !member.user.bot).size;
Should return the number of members that aren't bots on guild.
User filter:
client.guilds.get('Your guild id').members.cache.filter(member => !member.user.bot).size;

use ForceReply option to get input from user without reply interface in telegram

We know that there is ForceReply option to get input from user in telegram api.
Telegram said :
Upon receiving a message with this object, Telegram clients will
display a reply interface to the user (act as if the user has selected
the bot‘s message and tapped ’Reply'). This can be extremely useful if
you want to create user-friendly step-by-step interfaces without
having to sacrifice privacy mode.
Now I used irazasyed/telegram-bot-sdk to make my telegram bot. in that package to create a force_reply interface we should do like this :
$forceReply = Keyboard::forceReply(['force_reply' => true]);
$this->replyWithMessage([
'text' => 'Please enter your name ?',
'reply_markup' => $forceReply
]);
Result is like :
But in usages in other bot for example PollBot that uses this option , when shows a question and want to get answer , reply interface does not show.
I want to do same.I know that if I set value of force_reply to false it done but I do not know after that how can I detect that text that user entered is related to which my question.
what do I do really ?
What I've done for my last bot is:
I created a table for user history which holds some info about users like their username and chat_id, I also keep track of a user's last state in last_state column
So when asking a question from a user, I update her state field in DB with current state, Then upcoming answer is for the question in user's last state, Let me go with a short-simple example.
A:Propmpt question x for user with chat_id n
B:Update state of user whose chat_id is n equal to x in DB
C:Get the answer
D:Get chat_id and then fetch her last_state from DB, the state indicares the question
Now you know which question she's answering to
Check this bot developed by me: #TunnelCSBot

How to work with not (yet) registered devise Users

I have a User model, for login and registration, its email field is used (everything vanilla from the devise gem).
I want (other) users to be able to e.g. add Users to a team, with the email-address as the identifier.
That is fine when the User is already existing (pseudo #team.users.add(User.find_by(email: other_users_email))) but I am unsure how to handle situations where the user does not yet exist (did not [yet] register).
When a (new) User sets up a new account, for the example above after successfull registration current_user.teams should show up correctly.
I do not want to force these potentially new users to use the system (e.g. using devise_invitable) and bother them with an email.
I followed the path of creating the User when a user with the given email does not yet exist, but then when the user actually tries to setup an account, it fails (email not unique).
Alternatively, I could remodel the TeamMember-part and let it optionally either store an email-adress or the reference to an existing User. Then what I would need is to check for "open" TeamMembers directly after User-Account-creation (so, TeamMembers with the given email). I could also do this on each requst, but that looks too expensive to me. There might be race conditions, but I could live with that (and check for the every-now-in-a-millenia-gap with a cron-job).
Any pointers? I am sure this is not that unusual.
I'd do this:
When a user A adds user B to a team by email, create the object for that user B, but set a flag, something like auto_created_and_inactive: true
When user B signs up on the site, you just have to handle this in your users#create: first, try to find an auto-created record and update it (set a password or whatever; also reset the flag). Or otherwise proceed with the usual route of creating a new record.
I have to admit that I did not yet tried #sergio-tulentsevs approach (implement RegistrationController#create). But to complete what I sketched in my question:
User model can define an after_confirmation method, which is called after ... confirmation! So, if I store every information about a potential user with a reference to his/her email-adress, once he/she registered I can query this information and e.g. complete Team-Memberships.
# app/models/user.rb
def after_confirmation
# (pseudo-code, did not try)
self.teams < TeamMembership.open.where(email: self.email)
end

Resources