NodeJS, DiscordJS. Split arguments by {} - javascript

How can I get this working, I am not sure what I am doing wrong here.
let args = message.content.substring(PREFIX.length).split(" ");
const a = args;
const items = a.slice(a.indexOf('{') + 1, a.lastIndexOf('}')).split('}{')
switch(args[0]) {
case 'status':
message.channel.send("**Current Status:**");
con.query("SELECT * FROM games", function(err, result, fields) {
if(err) throw err;
Object.keys(result).forEach(function(key) {
var row = result[key];
message.channel.send('**' + row.name + '**' + ' - ' + '(' + row.description + ')' + ' - ' + '**' + row.status + '**');
});
});
break;
case 'add':
let name = items[1];
let desc = items[2];
let status = items[3];
console.log(items);
break;
I am trying to split the !ADD commands arguments by {} so this system knows that every other string inside of {} is the next command
!add {this is a argument}{another argument}{another argument sitting here}

I think the issue is that you are splitting the message to parse out the initial command (add), but not joining it back together before doing the next split. I think you want to change the second line to:
const a = args.slice(1).join(' ');
That should make the items array ['this is a argument', 'another argument', 'another argument sitting here']
When you access the items array, make sure you are using the correct indices as well. In this example there are only 3 items, so valid indexes would be (0, 1, 2). (In your code you are accessing 3)

A light regexp-using approach could be:
let line="!add {this is a argument}{another argument}{another argument sitting here}"
let [command,argumentlist]=line.match(/!([^\s]+)\s+\{(.*)\}/).splice(1);
let arguments=argumentlist.split("}{");
console.log(command);
console.log(arguments);
The match() thing strips the ! from the beginning and the outermost {} pair, and then the split() is the same as it was in your code.

Related

JavaScript output of a string instead of undefined?

I'm getting undefined instead of a String on return of the answer - though it is the right correct characters being logged. How do I get it to output a definite string?
var greet = function(name) {
let first = String(name. charAt(0). toUpperCase());
let second = String(name.slice(1));
console.log('Hello ' + first + second + '!');
}
You forgot to return a value, so the return-value is undefined.
var greet = function(name) {
let first = String(name. charAt(0). toUpperCase());
let second = String(name.slice(1));
return 'Hello ' + first + second + '!';
}
console.log(greet('Gemma'));
The console will print the result of evaluating an expression. You can notice if you set
let name = 'john'
it will print undefined in the very next line.
That is also happening here. First it is printing your value, then it print undefined.
Your function is working fine - you just need to invoke it and feed its argument with a name...
[for the result look in the console]
var greet = function(name) {
let first = String(name.charAt(0).toUpperCase());
let second = String(name.slice(1));
console.log('Hello ' + first + second + '!');
}
;
greet("henky");

QZ Tray raw Printing

This is my very first question.
How can i run an "IF STATEMENT" in side the raw code of QZ tray where Var = print data [];
The below code works wonderful without IF STATEMENT, but the codes cannot parse once i use it.
var printData = [
'<xpml><page quantity="0" pitch="127.0 mm"></xpml>^AD\n',
'^O0\n'
'<xpml></page></xpml><xpml><page quantity="9" pitch="127.0 mm"></xpml>~MDELF,FORMAT_0\n',
'^E10.0\n',
'^L\n',
'C0,0000000000000000,+1,prompt_C0\n',
'C1,0000000000000000,+1,prompt_C1\n',
'C2,000,+1,prompt_C2\n',
'Lo,51,438,761,440\n',
'Lo,51,678,761,680\n',
'Lo,51,558,761,560\n',
'Lo,51,158,761,160\n',
'AH,320,31,1,1,0,0,'+ acs +'\n',
'BQ2,160,742,4,8,156,0,0,C^C0\n',
'AD,254,900,1,1,0,0,^C1\n',
'AA,439,440,1,1,0,0,Service\n',
'Lo,425,440,427,678\n',
'AA,442,560,1,1,0,0,Total No of Pieces\n',
'AA,439,684,1,1,0,0,Origin\n',
'AB,511,684,1,1,0,0,' + origin +'\n',
'AF,182,590,1,1,0,0,'+ destination+'\n',
'R49,13,762,999,3,3\n',
'E\n',
'^KFORMAT_0\n',
if (pcstart.length ==1)
{
premawb + postmawb +'0000'+ pcstart +'\n',
}
else {
premawb + postmawb +'000'+ pcstart +'\n',
}
pcstart + '\n',
'E\n',
'~P'+ copyPrint+'\n',
qz.print(config, printData).catch(displayError);
}
How can i run an "IF STATEMENT" in side the raw code of QZ tray
You can't mid-array, but you can add a ternary operator which does the same thing for a simple if/else statement:
pcstart.length == 1 ? '0000' : '000'
... and in context...
var printData = [
'<xpml><page quantity="0" pitch="127.0 mm"></xpml>^AD\n',
'...',
'^KFORMAT_0\n',
premawb + postmawb + (pcstart.length == 1 ? '0000' : '000') + pcstart + '\n',
pcstart + '\n',
'E\n',
'~P'+ copyPrint + '\n'
];
qz.print(config, printData).catch(displayError);
You can also call a function on the array element, so you may find it more desirable to roll your own pad(...) function and then call pad on the entire number or concatenated string... e.g:
premawb + postmawb + pad(pcstart, 4) +' \n',
I the above example, pad(...) is a function you make that can contain all the if/else statements you need and returns the formatted value.

Give my javascript array access to includes()

Before everything, I have been making a word filter program for my discord.js bot so excuse me for the bad words!
Since you can't add extra parameters in includes() I decided to make a var line:
var filteredwords = ['asshole', 'fuck']
But now I want to place these words (further more will be added) in the following code line:
if (message.content.includes('asshole'));
So instead of 'asshole' I want to place the array? How can I do that? Since I'm a beginner in JS I could not understand the other topics with a similar question. It would be fine if you explain it in noob language. :)
If useful, this is my full code:
const Discord = require('discord.js');
const client = new Discord.Client();
var filteredwords = ['asshole', 'fuck']
function commandIs(str, msg) {
return msg.content.toLowerCase().startsWith('--' + str);
}
client.on('ready', () => {
console.log('The bot is started succesfully')
});
client.on('message', message => {
if (commandIs('trump', message)) {
message.reply('He is the president of the United States of America!');
}
if (commandIs('putin', message)) {
message.reply('He is the president of Russia!');
}
if (commandIs('spacetaco', message)) {
message.reply('He is the first user who joined Arcanews!');
}
if (message.content.includes('asshole')); {
message.reply('Do not swear please');
message.delete();
var colors = require('colors/safe');
console.log(colors.red(`The following message got deleted:
${message.content}`));
}
});
if(filterwords.some(badword=>message.content.includes(badword))){
alert("BAD!");
}
Array.prototype.some iterates over the array and returns true if one of the given function called with the array elem as argument is true, therefore if it contains at least one bad word...
Because of the "includes" method you used, I think the type of "message.content" is an array.
Therefore, the problem can be regard as compare two arrays. You can simply apply two loops for checking, or you can use reduce method for checking.
var messageA = {
content: "Here is a asshole in it.".split(" "),
};
var messageB = {
content: "Here is a hole in it.".split(" "),
};
var filteredwords = ['asshole', 'fuck'];
var isValidA = messageA.content.reduce(function(pre, cur) {
if (pre) return !!filteredwords.indexOf(cur);
return pre;
}, true);
var isValidB = messageB.content.reduce(function(pre, cur) {
if (pre) return !!filteredwords.indexOf(cur);
return pre;
}, true);
console.log(isValidA); // false
console.log(isValidB); // true
You can use regex matching here. A much faster implementation
var filteredwords = ['bad-word', 'another-bad-word']
var message = 'Hello this string has a bad-word in it'; // Use your messsage.content here
// In a regex - '\b' start or end of a word
// " .join('\\b|\\b') " - gives me a regex string with each of the values from filteredwords array concatinated to for a 'OR' expression
// Here is th regex exp taht is generated `\basshole\b|\bfuck\b`
if( (new RegExp( '\\b' + filteredwords.join('\\b|\\b') + '\\b') ).test(message) ){
alert('match'); // Here the word were matched
}else{
alert('no match'); // Wooho, a safe message
}
Pro tip :
RegEx solution stands out in a way that you do the match that are case-insensitive and for bad-words that appear as a part of another word eg 'dambad-Word' would give a match for bad-word
EDIT: Updating answer to the full-code posted by const Discord = require('discord.js');
const client = new Discord.Client();
var filteredwords = ['asshole', 'fuck']
function commandIs(str, msg) {
return msg.content.toLowerCase().startsWith('--' + str);
}
client.on('ready', () => {
console.log('The bot is started succesfully')
});
client.on('message', message => {
if (commandIs('trump', message)) {
message.reply('He is the president of the United States of America!');
}
if (commandIs('putin', message)) {
message.reply('He is the president of Russia!');
}
if (commandIs('spacetaco', message)) {
message.reply('He is the first user who joined Arcanews!');
}
if ( (new RegExp('\\b' + filteredwords.join('\\b|\\b') + '\\b')).test(message.content ) ) {
message.reply('Do not swear please');
message.delete();
var colors = require('colors/safe');
console.log(colors.red(`The following message got deleted:${message.content}`));
}
});
If you want to do the matching for not whole words like say curseWord should be detected in the sentence hello there youcurseword (case insensitive as well), you can replace the last IF condition with :
// We can get rid of '\b' to make the search not limited to whole-word matching
if ((new RegExp(filteredwords.join('|'))).test(message.content))
// We can use 'i' flag to make the matching case insensitive
if ((new RegExp(filteredwords.join('|') , 'i')).test(message.content))

mongoose 'or' and 'like' operators node.js

I wan to implement search for my page. So from frontEnd I got search value from user's input, and I need search at my db with 3 rows limit.
So I need sql query like that:
SELECT * FROM PRODUCTS p WHERE p.title like '%user_value%' or p.sku like '%user_value%'
I try to do it like that:
router.get('/search', function(req, res, next) {
var value = req.query.val;
var query = Product.find({"title": new RegExp('/' + value+'/')}).limit(3);
query.exec(function(err, products) {
if (!err) {
// Method to construct the json result set
var result = JSON.stringify(products);
log.info(products);
res.send(result, {
'Content-Type': 'application/json'
}, 200);
} else {
res.send(JSON.stringify(err), {
'Content-Type': 'application/json'
}, 404);
}
});
But I always got empty results. Its seems to me that RegExp path invalid.
UPDATE1:
'like' operator fixed like that:
Product.find({"title": new RegExp(".*" + value + ".*")}).limit(3);
But "or p.sku like '%user_value%'" problem still take a place
You need to pass modifiers as second parameter in RegExp constructor.
var query = Product.find({"title": new RegExp(".*" + value.replace(/(\W)/g, "\\$1") + ".*", "i")}).limit(3);
Example:
> var value = 'SNR-SFP+W73-60'
> console.log(new RegExp(".*" + value.replace(/(\W)/g, "\\$1") + ".*", "i"))
/.*SNR\-SFP\+W73\-60.*/i
In your RegExp object you should do this:
new RegExp(value)
instead of this:
new RegExp('/' + value + '/')
Refer this link:
RegExp

Parse semi-structured values

it's my first question here. I tried to find an answer but couldn't, honestly, figure out which terms should I use, so sorry if it has been asked before.
Here it goes:
I have thousands of records in a .txt file, in this format:
(1, 3, 2, 1, 'John (Finances)'),
(2, 7, 2, 1, 'Mary Jane'),
(3, 7, 3, 2, 'Gerald (Janitor), Broflowski'),
... and so on. The first value is the PK, the other 3 are Foreign Keys, the 5th is a string.
I need to parse them as JSON (or something) in Javascript, but I'm having troubles because some strings have parentheses+comma (on 3rd record, "Janitor", e.g.), so I can't use substring... maybe trimming the right part, but I was wondering if there is some smarter way to parse it.
Any help would be really appreciated.
Thanks!
You can't (read probably shouldn't) use a regular expression for this. What if the parentheses contain another pair or one is mismatched?
The good news is that you can easily construct a tokenizer/parser for this.
The idea is to keep track of your current state and act accordingly.
Here is a sketch for a parser I've just written here, the point is to show you the general idea. Let me know if you have any conceptual questions about it.
It works demo here but I beg you not to use it in production before understanding and patching it.
How it works
So, how do we build a parser:
var State = { // remember which state the parser is at.
BeforeRecord:0, // at the (
DuringInts:1, // at one of the integers
DuringString:2, // reading the name string
AfterRecord:3 // after the )
};
We'll need to keep track of the output, and the current working object since we'll parse these one at a time.
var records = []; // to contain the results
var state = State.BeforeRecord;
Now, we iterate the string, keep progressing in it and read the next character
for(var i = 0;i < input.length; i++){
if(state === State.BeforeRecord){
// handle logic when in (
}
...
if(state === State.AfterRecord){
// handle that state
}
}
Now, all that's left is to consume it into the object at each state:
If it's at ( we start parsing and skip any whitespaces
Read all the integers and ditch the ,
After four integers, read the string from ' to the next ' reaching the end of it
After the string, read until the ) , store the object, and start the cycle again.
The implementation is not very difficult too.
The parser
var State = { // keep track of the state
BeforeRecord:0,
DuringInts:1,
DuringString:2,
AfterRecord:3
};
var records = []; // to contain the results
var state = State.BeforeRecord;
var input = " (1, 3, 2, 1, 'John (Finances)'), (2, 7, 2, 1, 'Mary Jane'), (3, 7, 3, 2, 'Gerald (Janitor), Broflowski')," // sample input
var workingRecord = {}; // what we're reading into.
for(var i = 0;i < input.length; i++){
var token = input[i]; // read the current input
if(state === State.BeforeRecord){ // before reading a record
if(token === ' ') continue; // ignore whitespaces between records
if(token === '('){ state = State.DuringInts; continue; }
throw new Error("Expected ( before new record");
}
if(state === State.DuringInts){
if(token === ' ') continue; // ignore whitespace
for(var j = 0; j < 4; j++){
if(token === ' ') {token = input[++i]; j--; continue;} // ignore whitespace
var curNum = '';
while(token != ","){
if(!/[0-9]/.test(token)) throw new Error("Expected number, got " + token);
curNum += token;
token = input[++i]; // get the next token
}
workingRecord[j] = Number(curNum); // set the data on the record
token = input[++i]; // remove the comma
}
state = State.DuringString;
continue; // progress the loop
}
if(state === State.DuringString){
if(token === ' ') continue; // skip whitespace
if(token === "'"){
var str = "";
token = input[++i];
var lenGuard = 1000;
while(token !== "'"){
str+=token;
if(lenGuard-- === 0) throw new Error("Error, string length bounded by 1000");
token = input[++i];
}
workingRecord.str = str;
token = input[++i]; // remove )
state = State.AfterRecord;
continue;
}
}
if(state === State.AfterRecord){
if(token === ' ') continue; // ignore whitespace
if(token === ',') { // got the "," between records
state = State.BeforeRecord;
records.push(workingRecord);
workingRecord = {}; // new record;
continue;
}
throw new Error("Invalid token found " + token);
}
}
console.log(records); // logs [Object, Object, Object]
// each object has four numbers and a string, for example
// records[0][0] is 1, records[0][1] is 3 and so on,
// records[0].str is "John (Finances)"
I echo Ben's sentiments about regular expressions usually being bad for this, and I completely agree with him that tokenizers are the best tool here.
However, given a few caveats, you can use a regular expression here. This is because any ambiguities in your (, ), , and ' can be attributed (AFAIK) to your final column; as all of the other columns will always be integers.
So, given:
The input is perfectly formed (with no unexpected (, ), , or ').
Each record is on a new line, per your edit
The only new lines in your input will be to break to the next record
... the following should work (Note "new lines" here are \n. If they're \r\n, change them accordingly):
var input = /* Your input */;
var output = input.split(/\n/g).map(function (cols) {
cols = cols.match(/^\((\d+), (\d+), (\d+), (\d+), '(.*)'\)/).slice(1);
return cols.slice(0, 4).map(Number).concat(cols[4]);
});
The code splits on new lines, then goes through row by row and splits into cells using a regular expression, which greedily attributes as much as it can to the final cell. It then turns the first 4 elements into integers, and sticks the 5th element (the string) onto the end.
This gives you an array of records, where each record is itself an array. The first 4 elements are your PK's (as integers) and your 5th element is the string.
For example, given your input, use output[0][4] to get "Gerald (Janitor), Broflowski", and output[1][0] to get the first PK 2 for the second record (don't forget JavaScript arrays are zero-indexed).
You can see it working here: http://jsfiddle.net/56ThR/
Another option would be to convert it into something that looks like an Array and eval it. I know it is not recommended to use eval, but it's a cool solution :)
var lines = input.split("\n");
var output = [];
for(var v in lines){
// Remove opening (
lines[v] = lines[v].slice(1);
// Remove closing ) and what is after
lines[v] = lines[v].slice(0, lines[v].lastIndexOf(')'));
output[v] = eval("[" + lines[v] + "]");
}
So, the eval parameter would look like: [1, 3, 2, 1, 'John (Finances)'], which is indeed an Array.
Demo: http://jsfiddle.net/56ThR/3/
And, it can also be written shorter like this:
var lines = input.split("\n");
var output = lines.map( function(el) {
return eval("[" + el.slice(1).slice(0, el.lastIndexOf(')') - 1) + "]");
});
Demo: http://jsfiddle.net/56ThR/4/
You can always do it "manually" :)
var lines = input.split("\n");
var output = [];
for(var v in lines){
output[v] = [];
// Remove opening (
lines[v] = lines[v].slice(1);
// Get integers
for(var i = 0; i < 4; ++i){
var pos = lines[v].indexOf(',');
output[v][i] = parseInt(lines[v].slice(0, pos));
lines[v] = lines[v].slice(pos+1);
}
// Get string betwen apostrophes
lines[v] = lines[v].slice(lines[v].indexOf("'") + 1);
output[v][4] = lines[v].slice(0, lines[v].indexOf("'"));
}
Demo: http://jsfiddle.net/56ThR/2/
What you have here is basically a csv (comma separated value) file which you wish to parse.
The easiest way would be to use an wxternal library that will take care of most of the issues you have
Example: jquery csv library is a good one. https://code.google.com/p/jquery-csv/

Categories