X is not a function - How to fix - javascript

I'm creating TS3 Query Bot using this
I came up with core.js, register.js and 2 configs for them that are not important in here.
Core.js:
const TeamSpeak3 = require("ts3-nodejs-library")
var config = require("./configs/config.js")
//Create a new Connection
const ts3 = new TeamSpeak3({
host: "localhost",
queryport: 10011,
serverport: 9987,
username: "serveradmin",
password: "",
nickname: "NodeJS Query Framework"
})
/*
Ready gets fired when the Bot has connected to the TeamSpeak Query and
issued login commands (if username and password has been given)
selected the appropriate Server (also if given in the config)
and set the nickname
*/
ts3.on("ready", async () => {
Promise.all([
ts3.registerEvent("server"),
ts3.registerEvent("channel", 0),
ts3.registerEvent("textserver"),
ts3.registerEvent("textchannel"),
ts3.registerEvent("textprivate")
]).then(() => {
console.log("[ JANbot ] Nasluchuje eventow: server, channel (0), textserver, textchannel, textprivate")
}).catch(e => {
console.log("Catched an error!")
console.error(e)
})
})
if(config.registerEnabled = true) {
var register = require("./inc/functions/register.js")
ts3.on("clientmoved", event => {
register.registerUser(event, event.client)
})
}
ts3.on("error", e => console.log("Error", e.message))
ts3.on("close", e => console.log("Connection has been closed!", e))
register.js:
module.exports = function() {
this.registerUser = function(event, client)
{
var register_config = require("/home/node_modules/bot/configs/register_config.js")
if(event.channel.cid == register_config.channelId) {
if(! client.servergroups.includes(register_config.groupId)) {
event.client.addGroups(config.groupId)
event.client.message("You have been successfully registered!")
event.client.kickFromChannel()
return console.log("zarejestrowano " + event.client.nickname)
} else {
event.client.message("You are already registred!")
event.client.kickFromChannel()
return console.log(event.client.nickname + " juz jest zarejestrowany")
}
}
};
}
Main idea is to handle bot and its connection in core.js and just require specific functions to it to make easier updates (you don't need to download whole core.js with many functions, just one file and eventually a config for it)
The error i am getting:
Error register.registerUser is not a function
I'm not advanced in JS so please if I did anything wrong except my problem please tell me that. I have some little thoughts what's wrong but I cannot fix that. I think that registerUser is not function but I don't have any idea how to implement register.js into here:
if(config.registerEnabled = true) {
var register = require("./inc/functions/register.js")
ts3.on("clientmoved", event => {
register.registerUser(event, event.client)
})
}
Btw. I added returns only because I thought it would change registerUser into function.1
//EDIT:
It works, but now I struggle with second problem.
Now the code:
module.exports = {
registerUser: function(event, client)
{
var register_config = require("/home/node_modules/bot/configs/register_config.js")
if(event.channel.cid == register_config.channelId) {
var grupa = register_config.groupId
if(!event.client.servergroups.includes(register_config.groupId)) {
var date = new Date(),
g = date.getHours(),
m = date.getMinutes(),
s = date.getSeconds()
event.client.addGroups(register_config.groupId)
event.client.poke("You have been successfully registered!")
event.client.kickFromChannel()
console.log(" [ " + g + " : " + m + " : " + s + " ] " +'Zarejestronwalem: ' + client.nickname)
} else {
event.client.poke("You are already registered!")
event.client.kickFromChannel()
}
}
}
}
the part:
if(!event.client.servergroups.includes(register_config.groupId)) {
is always true because somehow array servergroups of client doesn't have the number 11 in it so script just thinks it's true. I added console.log(event.client.servergroups) to see if is it problem of register_config.groupId or something else and this shows up in console:
[ 9, 11 ]
So after that I have spotted that it is problem with register_config.groupId because bot with code like this:
(core.js is the same as it was before second problem appeard)
register.js:
module.exports = {
registerUser: function(event, client)
{
var register_config = require("/home/node_modules/bot/configs/register_config.js")
if(event.channel.cid == register_config.channelId) {
var grupa = register_config.groupId
if(!event.client.servergroups.includes(register_config.groupId)) {
var date = new Date(),
g = date.getHours(),
m = date.getMinutes(),
s = date.getSeconds()
event.client.addGroups(register_config.groupId)
event.client.poke("You have been successfully registered!")
event.client.kickFromChannel()
console.log(" [ " + g + " : " + m + " : " + s + " ] " +'Zarejestronwalem: ' + client.nickname)
} else {
event.client.poke("You are already registered!")
event.client.kickFromChannel()
}
}
}
}
register_config.js:
module.exports = {
channelId: 4,
groupdId: 11
}
Bot behaves like here:
client on random channel (not with cid 4)
client joins channel with cid 4
bot kicks him,
pokes him,
doesn't give him server group
Conclusion: register_config.groupId somehow isn't defined as number eleven.
//EDIT #2:
I've done this:
var register_config = {
"groupId": 11,
"channelId": 4
};
module.exports = register_config;
And it works :) Never mind and thank you for help !

In register.js export an object instead of a function:
// module.exports = function() {
module.exports = {
// this.registerUser = function(event, client)
registerUser: function(event, client)
{
var register_config = require("/home/node_modules/bot/configs/register_config.js")
if(event.channel.cid == register_config.channelId) {
if(! client.servergroups.includes(register_config.groupId)) {
event.client.addGroups(config.groupId)
event.client.message("You have been successfully registered!")
event.client.kickFromChannel()
return console.log("zarejestrowano " + event.client.nickname)
} else {
event.client.message("You are already registred!")
event.client.kickFromChannel()
return console.log(event.client.nickname + " juz jest zarejestrowany")
}
}
};
}

Related

How can i edit an embed every 10 seconds in discord.js

So, i am trying to make a bot that pings my minecraft server and shows the players on it. I want to be able to start and stop it with "!" commands. I´ve got the main thing working but i dont really know how i can edit the embed every 10 secs or so. Im using discord.js. I thought about somehow calling the editing function every 10 seconds but i dont really see a function which i could call. Also the discord.js documentation doesnt help really much, because its mostly outdated, and many things changed, from what i could see. Also i should probably say that the codes pretty messy, so sorry for that. Here's my code so far:
const client = new Discord.Client()
const mcping = require('mc-ping-updated');
var server_players_num;
var server_players_name = [];
var server_players_max;
var server_version;
var embed;
var x = 0;
var fields = {};
//INSERT IP AND PORT BELOW
var serverip = "";
var serverport = 16400;
client.on('ready', () => {
console.log("Connected as " + client.user.tag)
})
bot_secret_token = ""
function serverping() {
mcping(serverip, serverport, function(err, res) {
if (err) {
// Some kind of error
console.error(err);
} else {
// Success!
console.log(res);
server_players_num = res.players.online;
console.log(server_players_num);
server_players_max = res.players.max;
if (server_players_num > 0) {
x = 0;
while (x < server_players_num) {
server_players_name.push(res.players.sample[x].name);
console.log(server_players_name[x]);
fields.name = "Spieler:";
if (x == 0) {
//fields.value = server_players_name[x];
fields.value = "[" + server_players_name[x] + "]" + "(https://mcuuid.net/?q=" + res.players.sample[x].id + ")";
} else if (x > 0) {
fields.value = fields.value + '\n' + server_players_name[x];
}
x++
}
};
}
}, 3000);
};
serverping();
client.on('message', async message => {
if (message.content === '!start') {
// inside a command, event listener, etc.
const exampleEmbed = new Discord.MessageEmbed()
.setColor('#d2ff00')
.setTitle('Minecraft Server Status')
.setThumbnail('https://i.ibb.co/hg8nG1s/HTL-PB.png')
.addField("Spieler online:", server_players_num + "/" + server_players_max, true)
.addFields(fields)
.setTimestamp()
embed = await message.channel.send(exampleEmbed);
await embed.edit(exampleEmbed);
}
});
client.login(bot_secret_token)```
Try using setInterval().
client.on('ready', () => {
console.log("Connected as " + client.user.tag)
setInterval(serverping, 10000); //10000ms = 10s
})
A piece of advice, if you want your bot to work asynchronously with other functions, a 10-second delay may be too fast. 1-2 minutes is enough for most occasions.

How to SEND the content when making a GET in Javascript?

I need to GET all the data of a workbook, and I tried one method, but it does not work properly.. The problem is that the Promise is returning the first line of the first worksheet, but it does not continue the process for the rest of the rows of the worksheet, respectively, all the worksheets and I don't know what to do. Maybe you know..
So I wrote this code:
const SheetGet = {
getSheet: (req, res) => {
return new Promise ((resolve, reject) => {
XlsxPopulate.fromFileAsync(filePath)
.then(workbook => {
const wb = xlsx.readFile(filePath, {cellDates: true});
const sheetNames = wb.SheetNames;
sheetNames.forEach(function (element){
let endOfData = false;
let i = 2;
let dataArr = [];
while (endOfData === false){
let taskId = workbook.sheet(element).cell("A" + i.toString()).value();
if (taskId !== undefined){
res.send({
type: 'GET',
list_name: element,
task_id: taskId,
task_name: workbook.sheet(element).cell("B" + i.toString()).value(),
task_description: workbook.sheet(element).cell("C" + i.toString()).value(),
task_due_date: workbook.sheet(element).cell("D" + i.toString()).value(),
task_priority: workbook.sheet(element).cell("E" + i.toString()).value(),
task_status: workbook.sheet(element).cell("F" + i.toString()).value(),
task_notes: workbook.sheet(element).cell("G" + i.toString()).value()
});
i++;
}
else {
endOfData = true;
}
}
})
});
})
}
}
It only gets this an then it stops, and I need to get all of the data from the worksheet.
Do you have any idea on how to resolve this issue? Or the proper way to make it work? Thank you very very much for your time and help!!! Much appreciated every help!!
P.S. I tried this code with "console.log", and it works very well, but the problem is when I changed to res.send, in order to get the info to Postman.
I assume you are using express as the framework, the problem is when you use res.send method, the server already send the data to client, while the rest of the code still running in the background. What I'm gonna do with this case are like this.
const SheetGet = {
getSheet: (req, res) => {
return new Promise ((resolve, reject) => {
XlsxPopulate.fromFileAsync(filePath)
.then(workbook => {
const wb = xlsx.readFile(filePath, {cellDates: true});
const sheetNames = wb.SheetNames;
sheetNames.forEach(function (element){
let endOfData = false;
let i = 2;
let dataArr = [];
while (endOfData === false){
let taskId = workbook.sheet(element).cell("A" + i.toString()).value();
if (taskId !== undefined){
dataArr.push({ // this one
type: 'GET',
list_name: element,
task_id: taskId,
task_name: workbook.sheet(element).cell("B" + i.toString()).value(),
task_description: workbook.sheet(element).cell("C" + i.toString()).value(),
task_due_date: workbook.sheet(element).cell("D" + i.toString()).value(),
task_priority: workbook.sheet(element).cell("E" + i.toString()).value(),
task_status: workbook.sheet(element).cell("F" + i.toString()).value(),
task_notes: workbook.sheet(element).cell("G" + i.toString()).value()
});
i++;
}
else {
endOfData = true;
}
}
})
return res.json({ data: dataArr }); // this one
});
})
}
}
While there is some unnecessary code, the least change you can do to make it works are the code above.
Cheers.

Variable scope; var undefined or same var loop

Meteor.methods({
'list.messages' () {
getTwilioMessages(function(err, data) {
if (err) {
console.warn("There was an error getting data from twilio", err);
return
}
data.messages.forEach(function(message) {
if (SMS.find({
sid: message.sid
}).count() > 0) {
return;
}
var image;
if (message.numMedia > 0) {
var images = [];
Meteor.wrapAsync(client.messages(message.sid).media.list(function(err, data) {
console.log(data)
if (err) throw err;
Meteor.wrapAsync(data.media_list.forEach(function(media, index) {
mediaImage = (function() {
let mediaImg = 'http://api.twilio.com/2010-04-01/Accounts/' + media.account_sid + '/Messages/' + media.parent_sid + '/Media/' + media.sid;
return mediaImg
});
}));
images.push(mediaImage());
console.log("Just One:" + mediaImage())
console.log("IMAGESSSS " + mediaImage())
}));
message.image = mediaImage();
console.log("test" + image)
} else {
message.image = null
}
if (message.from === Meteor.settings.TWILIO.FROM) {
message.type = "outgoing";
} else {
message.type = "incoming";
}
SMS.insert(message)
});
});
getTwilioMessages();
Meteor.setInterval(getTwilioMessages, 60000);
// client.calls.get(function(err, response) {
// response.calls.forEach(function(call) {
// console.log('Received call from: ' + call.from);
// console.log('Call duration (in seconds): ' + call.duration);
// });
// });
},
I expect to see different image URL's in the data.media_list.forEach. But, it returns the same image. In the console I get the desired results.
I want these results:
message.image = 'http://api.twilio.com/2010-04-01/Accounts/3039030393/Messages/303030/media/3kddkdd'
message.image = 'http://api.twilio.com/2010-04-01/Accounts/3039sdfa393/Messages/303030/media/3asdfdfsa' inserted into the correct message.
instead I get the same URl over and over resulting in the same image
for all my messages. I guess my scope is incorrect, but I have
attempted to follow: 2ality guide on scoping and Explaining
JavaScript Scope And Closures with no luck.

Use TripleSec encryption with Node.js Socket.io Chat

I am new to Node.js and I've created a simple chat application using Socket.io. I am trying to encrypt the messages using the triplesec library but I am having some issues. What would be the best approach to add this encryption/decryption:
var triplesec = require('triplesec');
// Encrypt Function
triplesec.encrypt({
key: new triplesec.Buffer('secretkey'),
data: new triplesec.Buffer('secretthings'),
}, function (err, buff) {
if(!err) {
var ciphertext = buff.toString('hex')
console.log(buff.toString('hex'))
}
// Decrypt Function
triplesec.decrypt({
data: new triplesec.Buffer(ciphertext, "hex"),
key: new triplesec.Buffer('secretkey')
}, function (err, buff) {
if(!err) {
console.log(buff.toString());
}
});
});
To this client: (All encryption on the messages coming in and going out will be handled client side, assuming this is the best approach?)
// imports
var readline = require('readline');
var socketio = require('socket.io-client');
var util = require('util');
var clc = require("cli-color");
var async = require("async");
// globals
var nick;
var serverAddress;
var serverPort;
var socket;
var rl = readline.createInterface(process.stdin, process.stdout);
// message types
var chat = clc.green;
var pm = clc.yellow;
var notice = clc.cyan;
var emote = clc.blue;
var error = clc.red;
// function definitions
function consoleOut (msg) {
process.stdout.clearLine();
process.stdout.cursorTo(0);
console.log(msg);
rl.prompt(true);
}
// handle a command that the user has entered
function handleCommand (commandType, arg) {
switch (commandType) {
case 'nick': // set the nickname and send a message with the updated nickname
var notice = nick + " changed their name to " + arg;
nick = arg;
socket.emit('send', { type: 'notice', message: notice });
break;
case 'pm': // private message another user
var to = arg.match(/[a-z]+\b/)[0];
var message = arg.substr(to.length, arg.length);
socket.emit('send', { type: 'pm', message: message, to: to, from: nick });
break;
case 'me': // the user performs some emote
var emote = nick + " " + arg;
socket.emit('send', { type: 'emote', message: emote });
break;
default: // invalid command type
consoleOut(error("That is not a valid command."));
}
}
// start of execution
async.series([
function(callback) {
// get the address
rl.question("Please enter the address of the server, such as 192.168.0.10: ", function(address) {
serverAddress = address;
callback();
});
},
function(callback) {
// get the port
rl.question("Please enter the port the server is listening on, such as 8080: ", function(port) {
serverPort = port;
socket = socketio.connect('http://' + serverAddress + ':' + serverPort);
// register the sockets on message event handler
socket.on('message', function (data) {
var leader;
// process message, these are pretty self explainitory
if (data.type == 'chat' && data.nick != nick) {
leader = chat("<" + data.nick + "> ");
consoleOut(leader + data.message);
}
else if (data.type == "notice") {
consoleOut(notice(data.message));
}
else if (data.type == "pm" && data.to == nick) {
leader = pm("["+data.from+"->"+data.to+"]");
consoleOut(leader + data.message);
}
else if (data.type == "emote") {
consoleOut(emote(data.message));
}
});
callback();
});
},
function(callback) {
// get the users nickname
rl.question("Please enter a nickname: ", function(name) {
nick = name;
var msg = nick + " has joined the chat";
socket.emit('send', { type: 'notice', message: msg });
rl.prompt(true);
callback();
});
}
]);
// called when the user hits enter on the command line
// parses what ever they typed into either a command or a chat message
rl.on('line', function (line) {
if (line[0] == "/" && line.length > 1) {
var cmd = line.match(/[a-z]+\b/)[0];
var arg = line.substr(cmd.length+2, line.length);
handleCommand(cmd, arg);
rl.prompt(true);
} else {
// send chat message
socket.emit('send', { type: 'chat', message: line, nick: nick });
rl.prompt(true);
}
});

Apigee Usergrid: Mass delete option missing

I am using usergrid to store data for a customer project. It's got two collections carShowrooms and cars. So far I am good. But I have a scenario where I have refresh the masterdata of the collection cars. Everytime I do this, I have to delete all the existing data in cars and replace it with incoming cars data from the master inventory system.
Now, with the docu in https://www.npmjs.org/package/usergrid, I see that I can only destroy one car at a time.
car.destroy(function(err){
if (err){
//error - car not deleted
//winston log - tbd
} else {
//success - car deleted
}
});
This is ok for smaller showrooms, but bigger multibrand showrooms have variety of cars - sometimes even upto 50 different varieties (8 car brands * approx. 8 different options).
Is there a mass delete option? can someone please point me to a docu if I am missing something here.
P.S. I am new to usergrid, if this is a repeated question, please mark so and point me to the right url
If you're so inclined, I've written a Node.js bulk deleter that runs delete requests in parallel. It takes approximately 3 minutes to delete 1000 entities.
Here's an always up-to-date gist, and a copy for SO:
// Installation
// 1. Install Node.js http://nodejs.org/download/
// 2. In Terminal, cd (navigate) to the directory where you saved this file
// 3. Run 'npm install request async'
// 4. Edit the script config below with your token, org, app, and collection name.
// 5. To run the script, at the Terminal prompt, run 'node api_baas_deleter.js'
// Config
var access_token = "{token}";
var as_basepath = "http://api.usergrid.com/{org}/{app}/"; // You need the trailing slash!
var collection = "{collection_name}";
// End Config
var request = require('request');
var async = require('async');
var authstring = "access_token=" + access_token;
var total = 0;
var startTime = Date.now();
function deleteRecords(callback) {
request.get({
url: as_basepath + collection + "?" + authstring,
json: true
}, function(e, r, body) {
if (body.count === undefined) {
var err = "Error: invalid endpoint. Check your basepath and collection name.";
console.log(err);
if (typeof(callback) === 'function') {
callback(err)
}
} else {
// console.log("Found " + body.count + " entities");
if (body.count > 0) {
var deletes = [];
for (var i = 0; i < body.count; i++) {
deletes.push({
url: as_basepath + collection + "/" + body.entities[i].uuid + "?" + authstring,
json: true
});
console.log("Deleting " + body.entities[i].uuid)
}
async.each(deletes, function(options, callback) {
request.del(options, function(e, r, body) {
if (r.statusCode === 200) {
total++;
}
callback(e);
});
}, function(err) {
setTimeout(function() {
deleteRecords(collection, function(e) {
callback(e);
});
}, 600); // Mandatory, since it seems to not retrieve entities if you make a request in < 600ms
});
} else {
var timeInMinutes = minutesFromMs(Date.now() - startTime);
console.log("Deleted " + total + " entities in " + timeInMinutes + " minute" + ((timeInMinutes > 1 || timeInMinutes < 1) ? "s" : ""));
if (typeof(callback) === 'function') {
callback()
}
}
}
});
}
function minutesFromMs(time) {
return Math.round(((time % 86400000) % 3600000) / 60000).toString();
}
deleteRecords();
There currently isn't a mass delete function in the Usergrid Node SDK, but you can create one. This is how I added a monkey-patched delete-by-query function into the Node SDK:
Usergrid.client.prototype.delete = function(opts, callback) {
if (_.isFunction(opts)) { callback = opts; opts = undefined; }
if (!opts.qs.q) { opts.qs.q = '*'; }
var options = {
method: 'DELETE',
endpoint: opts.type,
qs: opts.qs
};
var self = this;
this.request(options, function (err, data) {
if (err && self.logging) {
console.log('entities could not be deleted');
}
if (typeof(callback) === 'function') {
callback(err, data);
}
});
};
Hope that helps!
Scott

Categories

Resources