tmi.js message with input/argument? - node.js

Im am working on a twitch-bot using the tmi.js-npm and got a question about that.
I want to make a command like - "!giveaway" with an input, which could be anything. eg. "!giveaway pg". Then it should return "!pg". So the keyword "!giveaway" should be fixed, but the part after the blank, could be anything that is typed in.
My script looks like this:
client.on("chat", function (channel, user, message, self) {
if (message === "!Giveaway" + " " + "input"){
if(user["display-name"] === "username"){
client.say("channel", "!" + "input");
} else {
client.say("channel", "No permissions");
}
};
});
Thanks :)

Something like this is most commonly used, adding more checks is advised, but depends on your needs.
Checking the incoming message to see if it starts with a specific command, like so:
message.startsWith("!giveaway")
and with other logic
if (message.startsWith("!giveaway")) {
var input = message.split(' ')[1];
if (input.count < 2) return;
if (user["display-name"] === "username") {
client.say("channel", "!" + input);
} else {
client.say("channel", "No permissions");
}
}

Related

Node.js: Multiple inputs from user in an interactive CLI

I'm trying to create a simple interactive CLI with Node.js, that collects input from the user by "talking" to them asking questions.
I'm working with the 'readline' module that forces me to use the callback mechanism, currently results in the weird cascade below.
As I'm new to Node.js and to the callback idea, I really feel I'm doing something wrong but not sure how to make it better.
How can I reformat my function so it will be more elegant?
(I know the function below won't return anything, it's just for my temp debugging)
function getUserInput(dbData) {
readline.question('What would you like to edit?\n\n\t(1) Cars\t(2) Data owners\n', choice => {
if (choice == 1) {
readline.question('Choose operation:\n\n\t(1) Add new\n', op => {
if (op == 1) {
let newCar = {};
console.log("--> Please fill in the required details (with Capital First Letter):\n\n");
readline.question("Car name: ", carName => {
newCar.name = carName;
readline.question("Car make: ", carMake => {
newCar.make = carMake;
readline.question("Team (DC/CSF): ", team => {
newCar.team = team;
readline.question("TC (1/2): ", tc => {
newCar.tc = tc;
readline.close();
console.log(newCar);
});
});
});
});
}
else {
console.log("Invalid choice!\n");
getUserInput(dbData);
}
});
}
else {
console.log("Invalid choice!\n");
getUserInput(dbData);
};
});

Discord.js-commando: Stopping all commands if not in a specific channel

For testing I am trying to stop all commands, unless in a certain channel. I know how to do this for each command specifically, but I am trying to catch it inside of the main bot file, and return a message. I have tried two ways so far:
bot.on('command', async m => { (Also tried 'commandmessage')
console.log('COMMAND');
if (m.channel != 'bot-testing') {
return m.channel.send('You can\'t use commands here!');
}
});
Which doesn't work at all. Then I tried this:
bot.on('message', async m => {
m.isDM = (m.guild ? false : true);
if (m.content[0] != bot.commandPrefix) {
return;
} else {
if (m.channel != 'bot-testing') {
m.channel.send('You can\'t use commands here!');
}
}
});
Which kind of works, but doesn't stop the command.
It looks like you were super close - you just need to look at m.channel.name in your second if-statement (using method #2):
bot.on('message', async m => {
// ...
if (m.content[0] != bot.commandPrefix) {
return;
} else {
// [NEW: add .name prop here]
if (m.channel.name != 'bot-testing') {
m.channel.send('You can\'t use commands here!');
}
}
});

Node.js message.split returns undefined

So I want to create a bot command that when i type
-say Something Here it returns someone says: Something here But all it does is returns someone says: undefined Btw i'm using tmi.js
bot.on("chat", function (channel, user, message, self) {
if(message === "-say")
var code = message.split(' ')[1];
bot.action("stankotomic", "someone says: " + code);
});
I am not really sure, but i think you meant something else. Tell me if i got you wrong. but as I've understood your question, that is the correct way to do it.
considering that message = "-say Something Here";
and your result should be: "Someone says: Something Here"
Lets look at your code line by line:
if(message === "-say") // I am 100% sure "-say" and
//"-say something here" are different. correct me if i am wrong.
//so we need to check for the first word, or first element in our array of words.
//lets first create array than check: if(message.split(" ")[0] == "-say")
var code = message.split(' ')[1]; //now, we don't have 2 spaces together
//anywhere in our message, so array == nothing.
//I guess it should be more like: message.split(" ").shift().join(" ");
// this will return you: "Something Here".
bot.action("stankotomic", "someone says: " + code);
Your final code:
bot.on("chat", function (channel, user, message, self) {
if(message.split(" ")[0] == "-say")
var code = message.split(" ").shift().join(" ");
bot.action("stankotomic", "someone says: " + code);
});
PS:
Split documentation.
Join documentation.
Shift documentation.
If you take the following line:
var code = message.split(' ')[1];
...and change it to the following, it should help:
var code = message.split(' ')[1];
You had two spaces as the separator argument to split() where you should have only had one.
See here for documentation for String.prototype.split()

Parse.com set class default attributes

I have been working with Parse Cloud Code, and I have not achieved setting default values for my classes. Right now I am doing this:
Parse.Cloud.beforeSave('MyClass',function(request, response){
//The description should only have 200 characters
if(request.object.get('description')){
var des = request.object.get('description');
if(des.length>200){
request.object.set("description", des.substring(0, 197) + "...");
}
}
//let's make a default value
if(typeof request.object.get('active') === 'undefined'){
request.object.set('active',false);
}
response.success();
});
When I upload this function to the Cloud Code, and try to create a new object from the dashboard it wont have the default value active = false.
I don't know what's going on. Has somebody achieved this before?
My code is very similar to the one in the Parse docs. They say this could be done like this:
Parse.Cloud.beforeSave("Review", function(request, response) {
var comment = request.object.get("comment");
if (comment.length > 140) {
// Truncate and add a ...
request.object.set("comment", comment.substring(0, 137) + "...");
}
response.success();
});
However, for me it doesn't want to work.
Wohoo! I did it!
Nowhere in the documentation is said that if you want to do so, you must return the object you edited in the response.success().
Solution:
Parse.Cloud.beforeSave('MyClass',function(request, response){
//The description should only have 200 characters
if(request.object.get('description')){
var des = request.object.get('description');
if(des.length>200){
request.object.set("description", des.substring(0, 197) + "...");
}
}
//let's make a default value
if(typeof request.object.get('active') === 'undefined'){
request.object.set('active',false);
}
response.success(request.object); //this is the line that changes
});

How do I stop a table script from processing?

I am creating an insert script that does some business logic.
Basically, I want to check to see if a value in the inserted item exists in a table. But, it seems like if I find a problem Request.Send() doesn't stop execution and get an error.
I think there is an async issue here. I'm not 100% sure how to solve.
Is there a way to stop execution of the script?
if (item.memberType === 'Family' && item.primaryFamilyMember) {
table
.where({
memberNumber: item.primaryFamilyMember,
memberType: 'Family',
primaryFamilyMember: null })
.read({
success: function(results) {
if (results.length == 0) {
request.respond(statusCodes.BAD_REQUEST,
'Invalid Primary Family Member specified.');
console.error('Invalid Primary Family Member specified:' + item.primaryFamilyMember);
validInsert = false;
} else {
item.memberType = results[0].memberType;
item.memberLevel = results[0].memberLevel;
item.dateOfExpiry = results[0].dateOfExpiry;
}
}
});
}
if (validInsert) {
var today = new Date();
var prefix = today.getFullYear().toString().substr(2,2) + ('0' + (today.getMonth() + 1)).slice(-2);
table.includeTotalCount().where(function(prefix){
return this.memberNumber.substring(0, 4) === prefix;
}, prefix)
.take(0).read({
success: function (results) {
if (isNaN(results.totalCount)) {
results.totalCount = 0;
}
item.memberNumber = prefix + ('00' + (results.totalCount + 1)).slice(-3);
request.execute();
}
});
}
Yes, validInsert is declared at the top of the insert function.
I assume what's happening is the if(validInsert) runs before the read callback. But if so, i'm not sure why I'm getting "Error: Execute cannot be called after respond has been called." That implies the callback is running first.
Also, the record is being inserted when it shouldn't be even though the 400 error is sent back to the client.
This is an express app right? Should I just call response.end() after the error occurs?
Yes, there are definitely asyn issues in that code. To solve get rid of your validInsert flag and simply move the if (validInsert) section into the success callback (or make it a function called from the success callback). For example:
success: function(results) {
if (results.length == 0) {
request.respond(statusCodes.BAD_REQUEST,
'Invalid Primary Family Member specified.');
console.error('Invalid Primary Family Member specified:' + item.primaryFamilyMember);
} else {
item.memberType = results[0].memberType;
item.memberLevel = results[0].memberLevel;
item.dateOfExpiry = results[0].dateOfExpiry;
var today = new Date();
var prefix = today.getFullYear().toString().substr(2,2) + ('0' + (today.getMonth() + 1)).slice(-2);
...
//respond successfully
}
}

Resources