missing permissions in list - node.js

for the command to work it needs 3 permissions, but how could I reduce its size and simplify it for it to identify the missing ones and send a list, and not go from one in one?
e.g.
list = {
USE_EXTERNAL_EMOJIS: 'use external emojis',
EMBED_LINKS: 'embed links',
READ_MESSAGE_HISTORY: 'read message history'
}
CODE:
if (!message.channel.permissionsFor(client.user).has('USE_EXTERNAL_EMOJIS' && 'EMBED_LINKS')) {
return message.channel.send('missing permissions use external emojis and embed links');
}
if (!message.channel.permissionsFor(client.user).has('EMBED_LINKS')) {
return message.channel.send('missing permission embed links');
}
if (!message.channel.permissionsFor(client.user).has('USE_EXTERNAL_EMOJIS')) {
return message.message.channel.send('missing permission use external emojis');
}
if (!message.channel.permissionsFor(client.user).has('READ_MESSAGE_HISTORY')) {
return message.channel.send('missing permission read message history');
}

You can use Object.entries() to get an iterable array of key - value pairs and use a method like this
const neededPermsObj = {
USE_EXTERNAL_EMOJIS: 'use external emojis',
EMBED_LINKS: 'embed links',
READ_MESSAGE_HISTORY: 'read message history'
}
const missingPerms = [];
for (const [key, value] of Object.entries(neededPermsObj)) {
if (!message.channel.permissionsFor(client.user).has(key.toString())) {
missingPerms.push(`${key}: ${value}`)
}
}
if (missingPerms.length != 0) return message.channel.send(missingPerms.join('\n')); // prevent from running cmd
else // execute command code here
This would check if bot has the specified permissions from the object provided, and will return an array with all the missing permissions

Related

Eslint rule is running multiple times

I'm trying to write an eslint rule that enforces making sure the name property is defined on any classes that extend from other Error/Exception named classes (and fixes them).
As far as I can tell, it works in the astexplorer.net individually, but when I'm running it alongside other rules, it ends up getting ran multiple times, so the name property ends up being repeated multiple times in the resulting "fixed" file.
Is there anything in particular I can do to prevent it being run multiple times? I'm assuming what's happening is that it's inserting my name = 'ClassName';, then prettier is needing to reformat the code, which it does, but then maybe it's re-running my rule? I'm not sure.
Rule/fix code shown below. I've tried things like using *fix and yield, but that doesn't seem to help either (see commented code below, based on information in the eslint documentation)
module.exports = {
meta: {
hasSuggestions: true,
type: 'suggestion',
docs: {},
fixable: 'code',
schema: [], // no options,
},
create: function (context) {
return {
ClassDeclaration: function (node) {
const regex = /.*(Error|Exception)$/;
// If the parent/superClass is has "Error" or "Exception" in the name
if (node.superClass && regex.test(node.superClass.name)) {
let name = null;
const className = node.id.name;
// Test class object name
if (!regex.test(className)) {
context.report({
node: node,
message: 'Error extensions must end with "Error" or "Exception".',
});
}
// Find name ClassProperty
node.body.body.some(function (a) {
if (a.type === 'ClassProperty' && a.key.name === 'name') {
name = a.value.value;
return true;
}
});
// Name property is required
if (!name) {
context.report({
node: node,
message: 'Error extensions should have a descriptive name',
fix(fixer) {
return fixer.replaceTextRange(
[node.body.range[0]+1, node.body.range[0]+1],
`name = '${className}';`
);
},
// *fix(fixer) {
// name = className;
// yield fixer.replaceTextRange(
// [node.body.range[0]+1, node.body.range[0]+1],
// `name = '${className}';`
// );
//
// // extend range of the fix to the range of `node.parent`
// yield fixer.insertTextBefore(node.body, '');
// yield fixer.insertTextAfter(node.body, '');
// },
});
}
}
},
};
},
};
Turns out I had the AST Explorer set to the wrong parser, so it was showing me the wrong string name for the ClassProperty node. I should have been using PropertyDefinition instead.

How to return the array after altering it back into json format?

I am making a discord bot where you can use the command tcp freeitem to obtain your free item.
I am trying to alter that value of an Account by adding a new item object into the account. When I map the array to replace a value, it erases the name (allAccounts) of the array of the json. More information below. Here is what I have:
const listOfAllItemNames = require(`C:/Users///censored///OneDrive/Desktop/discord bot/itemsDataList.json`)
const accountList = require(`C:/Users///censored///OneDrive/Desktop/discord bot/account.json`)
const fs = require('fs')
var accountThatWantsFreeItem = accountList.allAccounts.find(user => message.author.id === user.userId);
var randomFreeItem = listOfAllItemNames.allItems[Math.floor(Math.random() * listOfAllItemNames.allItems.length)]
if(accountThatWantsFreeItem === undefined) {message.reply('You need to make an account with tcp create!'); return; }
if(accountThatWantsFreeItem.freeItem === true) {message.reply('You already got your free one item!'); return;}
fs.readFile('C:/Users///censored///OneDrive/Desktop/discord bot/account.json', 'utf8', function readFileCallback(err,data) {
if(err){
console.error(err)
} else {
var accountsArray = JSON.parse(data)
console.log(accountsArray)
var whoSentCommand = accountsArray.allAccounts.find(user => message.author.id === user.userId)
whoSentCommand.Items.push(randomFreeItem)
whoSentCommand.freeItem = true;
var test = accountsArray.allAccounts.map(obj => whoSentCommand === obj.id || obj)
//I believe the issue is trying to map it returns a new array
console.log(test)
test = JSON.stringify(test, null, 5)
//fs.writeFile('C:/Users///censored///OneDrive/Desktop/discord bot/account.json', test, err =>{ console.error(err)} )
}
})
when I write the file back to json file, it removes the "allAccounts" identifier in this file
//json file
//array name "allAccounts" is removed, I need this still here for code to work
{
"allAccounts" : [
{
"userId": "182326315813306368",
"username": "serendipity",
"balanceInHand": 0,
"balanceInBank": 0,
"freeItem": false,
"Items": []
},
(No "allAccounts" array name)
to this: output after writing file
So, the final question is
How would I alter the array so that I only alter the account I want without editing the array name?
Please feel free to ask any questions if I was unclear.
Array.map() method returns the converted array.
So in the below line, map() method takes allAccounts array and perform actions and put the target array (not object) to the test variable.
var test = accountsArray.allAccounts.map(obj => whoSentCommand === obj.id || obj)
So for making code works, please change the code like this:
var test = {
"accountsArray": accountsArray.allAccounts.map(obj => whoSentCommand === obj.id || obj)
}
When posting questions, please please reduce the code to a minimal example that will demonstrate the problem, and use words, not code, to describe the problem.
It looks like you are expecting .map to do something other than what it does.
Please consult the documentation for Array.map().
It takes the array that you pass it (in this case accountsArray.allAccounts) and transforms it, returning the transformed array.
You have essentially done test = accountsArray.allAccounts but for some reason are expecting test to contain an Object with the key allAccounts, when in fact it will only contain an Array, because that is what you have assigned it.

Unban command JDA 4.1.1_101, can't make it work and I don't know why

i'm coding a Discord bot with JDA 4.1.1_101. I created the "ban" command, but i can't make the unban command work. I can't really understand why... Thank you for your help.
if (args[0].equalsIgnoreCase(Main.prefix + "unban")) {
if(event.getGuild().getSelfMember().hasPermission(Permission.BAN_MEMBERS)) {
if (args.length > 0 && args.length < 3) {
try {
event.getMessage().delete().queue();
User member = event.getMessage().getMentionedMembers().get(0).getUser();
String id = member.getId();
event.getGuild().unban(id).queue();
EmbedBuilder ban = new EmbedBuilder();
ban.setColor(Color.GREEN);
ban.setTitle("UnBan");
ban.setDescription("UnBan Report");
ban.addField("Staffer: ", event.getMessage().getAuthor().getName(), true);
ban.addField("Unban: ", member.getName(), true);
logs.sendMessage(ban.build()).queue();
} catch (IndexOutOfBoundsException exx) {
EmbedBuilder error = new EmbedBuilder();
error.setColor(0xff3923);
error.setTitle("Error: User");
error.setDescription("Invalid user.");
event.getChannel().sendMessage(error.build()).queue(message -> {
message.delete().queueAfter(5, TimeUnit.SECONDS);
});
}
} else {
EmbedBuilder error = new EmbedBuilder();
error.setColor(0xff3923);
error.setTitle("Error: Wrong usage.");
error.setDescription("Use: .unban [#user].");
event.getChannel().sendMessage(error.build()).queue(message -> {
message.delete().queueAfter(5, TimeUnit.SECONDS);
});
}
}
}
The problem is, that you are trying to retrieve the user from the mention in the message.
Since the user isn't part of the guild anymore, it seems like this doesn't work.
In order to work around this issue, you have to retrieve the ID manually.
A mention is always in the format <#userid> or <!#userid>.
To get the ID you could just split the message and replace the unnecessary parts, e.g. String id = event.getMessage().getContentRaw().split("<")[1].split(">")[0].replace("!", "").replace("#", "");
I'm sure there are better and smoother ways for doing this. ;)
A better way of retrieving the ID would be using a regex such as <#!?(\d+)> as mentioned by Minn.
In order to get the name of the user, you just need the ID via event.getJDA().getUserById(id).getName().
It's important to mention that you can't properly mention a user who isn't on the server (which is the case when they are banned).
(Addition: I tried using .getMentionedUsers() with the same result as OP.)

node.js - Error: SQLITE_ERROR: near "users": syntax error

I'm trying to put a JSON object "Synced" (Which you will see in the code)
This is the code for a function "addServer(userid, serverid)"
The function is being required from another javascript file
db.all(`SELECT * FROM Users WHERE Tag = ? LIMIT 1`, userid, async(error,element) => {
if(element[0].Synced === '') {
var sJSON = {
users:{
[userid]:4,
},
servers:[`${serverid}`]
}
var serverJSON = JSON.stringify(sJSON)
console.log(serverJSON)
} else {
//Else statement not done yet
}
db.run(`UPDATE Users SET Synced = "${serverJSON}" WHERE Tag = "${userid}"`)
})
Solved. Needed to change quoting.
As Dave Newton said, I had to check my quoting. What I did was change my double quotes to single quotes which solved the problem.

How to delete items attachement from sharepoint List using pnpjs?

Hi Im trying to delete attached item from list items first and then upload new attach file in sharepoint using pnp js (in vuejs)!
i trace the code and delete part is runnging but i dont konw why attached file doesnt delete!!!
this is my code for deleting attached item
public async DeleteItemsAttachment(itemId: number): Promise<any> {
let item = pnp.sp.web.lists.getById('{128EF67A-FDSF-4F42-8E8F-D3FC9523273E}').items.getById(itemId)
return await item.attachmentFiles.deleteMultiple()
}
public async AddanAttachment(itemId: number, fileName: string, arrayBuffer: File): Promise<any> {
let item = pnp.sp.web.lists.getById('{128EF6AA-FD8F-4F42-8E8F-D3FC9523273E}').items.getById(itemId)
return await item.attachmentFiles.add(fileName, arrayBuffer)
}
uploadFile(){
if (this.itemId != null && this.myfiles) {
if (this.HasUploadFile) {
this.spService.DeleteItemsAttachment(this.itemId).then(response => {
this.AddAnAttachmentToRecord()
}).catch(e => {
this.message = ` exception : ${e}`
})
}
else {
this.AddAnAttachmentToRecord()
}
}
How can i solve my problem?
where is wrong area of my code?
According to attachmentfiles.ts deleteMultiple function expects the array of attachment file names, so attachments could be deleted by explicitly providing file names:
item.attachmentFiles.deleteMultiple("{attachment-file-name-1}","{attachment-file-name-2}")
or (more dynamic way) by reading attachment names and specifying it in deleteMultiple function:
let item = sp.web.lists.getByTitle(listTitle).items.getById(itemId);
//1. get all attachments
let attachments = await item.attachmentFiles.get();
let attachmentNames = attachments.map(a => a.FileName);
//2. delete all attachmanents
await item.attachmentFiles.deleteMultiple(...attachmentNames);

Resources