How to update user permission discord js - node.js

So, I want to update a permission for some users.
First, I tried to create a text channel and overwrite a user Permission. Then I do a for loop to update the permission, but I dont know how.
Things I've tried to update the permission :
channel.overwritePermissions({
permissionOverwrites: [
{
id: guild.id,
deny: ['VIEW_CHANNEL'],
},
{
id: playerData[i],
allow: ['VIEW_CHANNEL'],
},
],
});
//it said channel not defined?
message.guild.channels.cache.find('🐺werewolves').overwritePermissions({
permissionOverwrites: [
{
id: playerData[i],
allow:['VIEW_CHANNEL'],
}
]
})
//it said : fn is not a function
I've I have seen this solution and read the documentation, but the instruction isn't clear.
PS : The permission update must be a loop because the number of users who get the permission always changing.

Regarding first codeblock
channel is not defined, because it's not defined. You cannot use variables without defining them, that's how JavaScript works. To solve it, you would have to define it using for example const channel = ..., or access it from other variables you have, just like you are trying to use find in your second codeblock - you access it from message, as you're most likely in the message event.
Regarding second codeblock
This is not a proper way to use find, neither in old - removed in your version - way, nor the new way. The old way was to do find(property, value), to which you wouldn't provide a value ('🐺werewolves' would be treated as property you're trying to search by). New way you have to use, allows way more flexibility by requiring to pass it a function, just like in the example for the method. Since what you passed was a string and not a function, internal code throws an error fn is not a function.
For your example above, correct way to use that find would be
message.guild.channels.cache.find(channel => channel.name === '🐺werewolves');
Additionally, note that ideally you shouldn't try to call any methods on that directly, as in case when no channel with that name would be found, your code will throw an error. Snippet below should avoid that possibility.
const channel = message.guild.channels.cache.find(channel => channel.name === '🐺werewolves');
if (channel) channel.overwritePermissions(...)

Related

Lighthouse GraphQL - How to return current_user in mutation resolver?

I have a situation where I'm writing a custom mutation resolver, and currently have to pass the current_user's ID from my frontend to be able to then perform a ::find on the User model. What would be ideal however, is to be able to use an instance of current_user so that I don't have to rely on passing over an ID to my GraphQL server.
I'm still fairly new to the world of Laravel and GraphQL in general, however I've been reading up on the Lighthouse docs that mention the #auth directive, and other StackOverflow answers that mention using auth('api')->user(), however that returns NULL for me. I should also mention that I'm using the lighthouse-graphql-passport-auth library for dealing with user authentication, if that makes any difference. Does anybody know how to access current_user?
public function __invoke($_, array $args)
{
// $user = \App\Models\User::find($args['id']); <--- not ideal
$user = auth('api')->user(); <--- returns NULL
var_dump($user);
foreach ($user->notifications as $notification) {
$notification->viewed = true;
$notification->save();
}
$notifications = $user->notifications->toArray();
return [
'status' => 'Success',
'notifications' => $notifications
];
}
I found an interesting part in the lighthouse-graphql-passport-auth docs that discuss setting a [global middleware][3] to insert the logged in user into the $context. This was exactly like what I needed, and after adding the line into the middleware section of lighthouse.php config as mentioned in the docs, I was able to use $context->user() to return the currently logged in user.

Firestore security rules with set {merge}

In my Firestore data I have the following
ItemID
amountOfItemsToPurchase: 1
itemsLeft: 3
If a user wants to update the items to purchase for the same ItemID or create the document if the ItemID is not present, I use set(, {merge:true}, however in terms of the Firestore Security rules things get complicated.
I've written the following test:
const initialUserDoc = adminFirestore.collection("Users").doc(VALID_USER_ID).collection("Cart").doc(documentID);
await initialUserDoc.set({
"amountOfItemsToPurchase": 1,
"itemsLeft": 3
});
// Get the user's node and grab the example user
const userTestRef = db.collection("Users").doc(VALID_USER_ID).collection("Cart").doc(documentID);
await firebase.assertFails(userTestRef.set({
"amountOfItemsToPurchase": firebase.firestore.FieldValue.increment(1000),
}, {merge: true}));
This test results in the following: Error: Expected request to fail, but it succeeded
What I want for every scenario (update or create), to avoid that the amountOfItemsToPurchase exceeds the itemsLeft, for that I use the following:
request.resource.data.amountOfItemsToPurchase <= request.resource.data.itemsLeft => This will be in the allow create portion.
This rises the following:
Does the allow create or the allow update** will be called? and also why is not taking into account the itemsLeft variable
From your description and the comments, your security rule looks OK.
Let me write it for futher discussion:
match /items/{id} {
allow create, update:
if request.resource.data.amountOfItemsToPurchase < request.resource.data.itemsLeft;
}
First gotcha: use request.resource to be able to read the value of the field after the update.
Second gotcha: when using set, the FieldValue.increment sentinel does not increment but sets the value. You should use the update function to actually increment the value.
Third gotcha: FieldValue.increment with set function and {merge: true} does increment the value!
So in the end the rule works fine as is, I can confirm it works for me.

Remove a users reaction from fetchMessage? - Discord JS

I have a question for Discord.js.
How would I remove a specific user's reaction from a message?
I have tried to do so with this code:
// Now known as 'messages.fetch'.
message.channel.fetchMessage(MessageID).then(m => {
m.reactions.remove(UserID);
});
But it doesn't remove the user's reaction at all. Am I doing something wrong?
Any help would be appreciated.
Since this question is getting a lot of attraction, I decided to post what worked for me
Remove Specific User's Specific Reaction
// Channel = the channel object of the message's original channel
// MessageID = ID of the message, if hard coding, put around quotations eg: "1234"
const msg = await channel.messages.fetch(MessageID);
msg.reactions.resolve("REACTION EMOJI,
REACTION OBJECT OR REACTION ID").users.remove("ID OR OBJECT OF USER TO REMOVE");
Note: If using an older version of discord.js, simply replace channel.messages.fetch with channel.fetchMessage
The chosen option works, I would like to explain it. You need to grab the MessageReaction object from the message for the reaction you want to remove. How you do that depends on your code, in my case I was working with a reaction collector so on my collect call I already had the MessageReaction.
You then need to access the users property (a ReactionUserManager object). With this object, you can call .remove().
Code is below:
collector.on('collect', async (reaction, user) => {
...
// delete the reaciton
reaction.users.remove(user.id);
});
message.reactions is a collection of messageReactions. I think you need to loop through the collection and then remove the messageReaction required.
message.channel.fetchMessage(messageID).map(r => r).then(message => {
message.reactions.forEach(reaction => reaction.remove(UserID))
})
If you look at the documentation for reactions you can see it is a Collection, and it mentions that they are mapped by reaction ID's , and not the user ID's. The way you could remove them is get the reaction, filter the users and then maybe do something with that? I'm not sure how to remove those specifically, but that should get you the users, then filter that to the ID you want.
message.channel.fetchMessage(messageID).then(msg = m.reactions.get(reactionID).users); // Gets the users that reacted to a certain emote, I think.

Announce a members role ADDED to a specific role in a specific channel

I'd like to have my bot announce in our specific channel called family-talk, which I do have the channel ID of as well but not sure where to put it, but I'd want this to only happen when a role has been added to a member, is my below code correct or wrong? I don't have a lot of good ways of testing this so i'm hoping for some big help here. I also would like to know where the best place would be to place the code. Thank you!
if(!oldMember.roles.has('539208166563643407') && newMember.roles.has('561773668439687179'))
client.channels.get("550197572178935809").send("This member got the special role!");
Your code should work, BUT you have 2 diffrent IDs in the if, so to make this a bit cleaner just do:
const roleID = '539208166563643407';
const channelID = '550197572178935809';
client.on('guildMemberUpdate', (oldMember, newMember) => {
if(!oldMember.roles.has(roleID) && newMember.roles.has(roleID)) {
client.channels.get(channelID).send(newMember.displayName + ' got the special role!');
}
});

How can i pass input argument when writing loopback-testing

I am writing a test driven development for my strongloop API code with the help of loopback-testing .
Here they do not have any detailed document on this, so i am stuck with case of argument passing with the API call
Example i have a below case,
Method : PUT
URL : /api/admin/vineyard/<vineyard_id>
i need to pass the below arguments with this URL
1. 'vineyard_id' is a id of vine, it should be an integer .
2. in header = 'token'
3. in body = '{'name':'tastyWine','price':200}'
How can i pass these three arguments with this API ?
I can easily handle ,if there is only two types of arguments
Example :
Method : POST
`/api/user/members/<test_username>/auth'`
arguments : test_username and password
I can handle this like this ,
lt.describe.whenCalledRemotely('POST',
'/api/user/members/'+test_username+'/auth', {
'password': test_passwords
},
But how can i handle the above case , Many thanks for your answers for this example.
I'm not entirely sure what your specific problem is, but I will attempt to walk through everything you should need.
I am assuming you are using the predefined prototype.updateAttributes() method for your model as described here.
Next assumption is that you want to use the built-in authentication and authorization to allow the user to call this method. Given that assumption, you need something like this in your test code:
var vineyard_id = 123; //the id of the test item you want to change
var testUser = {email: 'test#test.com',password: 'test'};
lt.describe.whenCalledByUser(testUser, 'PUT', '/api/admin/vineyard/'+vineyard_id,
{
'name':'tastyWine',
'price':200
},
function () {
it('should update the record and return ok', function() {
assert.equal(this.res.statusCode, 200);
});
}
);
If you are using the out-of-the-box user model, you should be fine, but if you extended the model as is commonly done, you may need something like this early on in your test file:
lt.beforeEach.withUserModel('user');
Also, be aware of a few (currently incomplete) updates to will allow for better handling of built-in model extensions: Suggestions #56, Add support for non-default models #57, and givenLoggedInUser() function throws error #59.

Resources