bot.addListener('message', function (from, channel, message) {
IRClog.write("[" + (new Date()).toJSON() + "] [" + channel + "] <" + from + ">" + message + "\n");
// ============= PLAYER COMMANDS ============= //
if (logMessages){
util.log("[" + channel + "] <" + from + ">" + message);
}
console.log(message)// the message is logged
bot.whois(from,function(WHOIS){
if(typeof WHOIS.account == 'undefined'){
var isAuthed = false;
} else {
var isAuthed = true;
}
if (message.indexOf("!") === 0){//now the message is undefined
...
As described in the code, the var message is a string, and then, I don't know why, it becomes an undefined variable. Why is that happening? I didn't assign it to another value.
Depending on the execution context the function that the bot.whois executes may not have message defined in scope. You can use a closure to ensure the scope by passing in the message.
(function (msg) {
console.log(msg)// the message is logged
bot.whois(from, function(WHOIS){
var isAuthed = typeof WHOIS.account !== 'undefined';
if (msg.indexOf("!") === 0) {
...
}
})(message);
Your code is incomplete, obviously, and the actual bug probably resides somewhere below your cutoff point as you've put in your question:
bot.addListener('message', function (from, channel, message) {
IRClog.write("[" + (new Date()).toJSON() + "] [" + channel + "] <" + from + ">" + message + "\n");
// ============= PLAYER COMMANDS ============= //
if (logMessages){
util.log("[" + channel + "] <" + from + ">" + message);
}
console.log(message)// the message is logged
bot.whois(from,function(WHOIS){
if(typeof WHOIS.account == 'undefined'){
var isAuthed = false;
} else {
var isAuthed = true;
}
if (message.indexOf("!") === 0){//now the message is undefined
...
}); // end of the whois block, which is asynchronous
/* somewhere down here, message probably gets set to undefined
like this:
message = undefined; // this would run before bot.whois(from, cb); finishes
*/
}); // end of addListener
You either need to make sure that you're not messing with the message below your whois call, or you need to create a copy that you don't mess with, or you need to follow #Romoku's advice and wrap your whois call in a properly formatted closure (like the following) and pass message in to a strictly local scope:
bot.addListener('message', function (from, channel, message) {
IRClog.write("[" + (new Date()).toJSON() + "] [" + channel + "] <" + from + ">" + message + "\n");
// ============= PLAYER COMMANDS ============= //
if (logMessages){
util.log("[" + channel + "] <" + from + ">" + message);
}
console.log(message)// the message is logged
(function (msg) {
bot.whois(from,function(WHOIS){
if(typeof WHOIS.account == 'undefined'){
var isAuthed = false;
} else {
var isAuthed = true;
}
if (msg.indexOf("!") === 0){//now the message is undefined
...
}); // end of the whois block, which is asynchronous
})(message);
/* now you can do whatever you want to the message variable and bot.whois will
be able to operate on its independent, unmolested copy
*/
}); // end of addListener
Please note how in my example, and #Romoku's, message has been explicitly renamed (to msg and m, respectively), to make it clear that you're working with in a different scope with a different copy of the data.
Related
(node:9436) UnhandledPromiseRejectionWarning: TypeError: makeUser is not a function
Hello I tried to make a command for when the person does the command automatically adds 1 line in a cfg called users.json but this gives me this error.
Again, as I was updating my bot to discord.js V12 I got an error:
TypeError: makeUser is not a function
Here is a part the code:
if (!config.servers.servidores.includes(args[4])) {
console.log(yellow + "[" + moment.tz("America/Sao_Paulo").format('HH:mm A') + "] " + red + `[DB]` + reset + ` ${msg.author.username} ` + l7yellow + `->` + lightred + ` Configuração Errada` + reset + ` Status: ` + red + `Servidor` + reset)
const metodoembed = new Discord.RichEmbed()
.setColor("#ff0000")
.setTitle("Database Editor -> Atom")
.setDescription("An `error` was identified when\nmodifying the database.")
.addField('**Type:**', '```http\n' + 'Server' + '```', true)
.addField('Solution:', 'Check the available\nservers in the database', true)
.setThumbnail(`${msg.author.displayAvatarURL}`)
.setTimestamp()
.setFooter(`${msg.author.username}`, `${msg.author.displayAvatarURL}`);
return msg.channel.send(metodoembed); }
//
function updategive(file, json) {
fs.writeFile(file, JSON.stringify(json, null, 2), "utf8", function(err) {
console.log(purple + "[" + reset + moment.tz("America/Sao_Paulo").format('HH:mm A') + purple + "] " + `[🧮] Banco de Dados atualizado.`);
});
}
if (!users[person]) {
makeUser(person);
}
users[person].attackTime = time;
users[person].concurrents = conc;
users[person].servers = servers;
users[person].expire = moment(expire).unix();
updategive("users.json", users);
return msg.channel.send(responsegive);
}
The error is occuring in this line:
if (!users[person]) {
makeUser(person);
}
Hello seems like you are using a function that is not existing. Create a function with the name makeUser and the parameter user. So it should look like this function makeUser(user) {...}.
Also if you are using discord.js v12, make sure you replace RichEmbed with MessageEmbed.
I've been working on a script which collates the scores for a list of user from a website. One problem is though, I'm trying to load the next page in the while loop, but the function is not being loaded...
casper.then(function () {
var fs = require('fs');
json = require('usernames.json');
var length = json.username.length;
leaderboard = {};
for (var ii = 0; ii < length; ii++) {
var currentName = json.username[ii];
this.thenOpen("http://www.url.com?ul=" + currentName + "&sortdir=desc&sort=lastfound", function (id) {
return function () {
this.capture("Screenshots/" + json.username[id] + ".png");
if (!casper.exists(x("//*[contains(text(), 'That username does not exist in the system')]"))) {
if (casper.exists(x('//*[#id="ctl00_ContentBody_ResultsPanel"]/table[2]'))) {
this.thenEvaluate(tgsagc.tagNextLink);
tgsagc.cacheCount = 0;
tgsagc.
continue = true;
this.echo("------------ " + json.username[id] + " ------------");
while (tgsagc.
continue) {
this.then(function () {
this.evaluate(tgsagc.tagNextLink);
var findDates, pageNumber;
pageNumber = this.evaluate(tgsagc.pageNumber);
findDates = this.evaluate(tgsagc.getFindDates);
this.echo("Found " + findDates.length + " on page " + pageNumber);
tgsagc.checkFinds(findDates);
this.echo(tgsagc.cacheCount + " Caches for " + json.username[id]);
this.echo("Continue? " + tgsagc["continue"]);
this.click("#tgsagc-link-next");
});
}
leaderboard[json.username[id]] = tgsagc.cacheCount;
console.log("Final Count: " + leaderboard[json.username[id]]);
console.log(JSON.stringify(leaderboard));
} else {
this.echo("------------ " + json.username[id] + " ------------");
this.echo("0 Caches Found");
leaderboard[json.username[id]] = 0;
console.log(JSON.stringify(leaderboard));
}
} else {
this.echo("------------ " + json.username[id] + " ------------");
this.echo("No User found with that Username");
leaderboard[json.username[id]] = null;
console.log(JSON.stringify(leaderboard));
}
});
while (tgsagc.continue) {
this.then(function(){
this.evaluate(tgsagc.tagNextLink);
var findDates, pageNumber;
pageNumber = this.evaluate(tgsagc.pageNumber);
findDates = this.evaluate(tgsagc.getFindDates);
this.echo("Found " + findDates.length + " on page " + pageNumber);
tgsagc.checkFinds(findDates);
this.echo(tgsagc.cacheCount + " Caches for " + json.username[id]);
this.echo("Continue? " + tgsagc["continue"]);
return this.click("#tgsagc-link-next");
});
}
Ok, looking at this code I can suggest a couple of changes you should make:
I don't think you should be calling return from within your function within then(). This maybe terminating the function prematurely. Looking at the casperjs documentation, the examples don't return anything either.
Within your while loop, what sets "tgsagc.continue" to false?
Don't use "continue" as a variable name. It is a reserved word in Javascript used for terminating an iteration of a loop. In your case this shouldn't be a problem, but its bad practice anyhow.
Don't continually re-define the method within your call to the then() function. Refactor your code so that it is defined once elsewhere.
We ended up having to scope the function, so it loads the next page in the loop.
This is mainly because CasperJS is not designed to calculate scores, and it tries to asynchronously do the calculation, missing the required functions
I'm writing a script that stores database backup files to multiple locations. In addition, the data is stored on a NAS, which is normally accessible. If this is not the case, the error message is to be intercepted.
I tried it this way:
wshshell = WScript.CreateObject("WScript.Shell");
fso = WScript.CreateObject("Scripting.FileSystemObject");
SetupPath = WScript.arguments(0);
if (fso.FileExists(SetupPath))
{
//Load setup JSON
SetupFile = fso.OpenTextFile(SetupPath, 1, true, 0);
eval(SetupFile.ReadAll());
// Parse setup configuration from JSON
...
BackupPath = Setup["BackupPath"];
FilesForBackup = Setup["FilesForBackup"];
NASBackupPath = Setup["NASBackupPath"];
...
CreateNewBackupFiles();
Log("Script was successfully executed.");
}
else
{
Log("Script was not successfully executed.");
}
/* Creates a new compressed database backup */
function CreateNewBackupFiles()
{
tempfile = fso.GetTempName();
file = fso.GetFile("C:\\Program\\7-Zip\\7z.exe");
rarexe = file.ShortPath;
script = rarexe + " a -r " + tempfile + " " + FilesForBackup;
wshshell.Run(script, 0, true);
fso.CopyFile(tempfile, BackupPath + PrefixBackupFile + "backup.7z");
//Save to NAS
if(NASBackupPath!="")
{
try
{
fso.CopyFile(tempfile, NASBackupPath);
}
catch(err)
{
Log("Path \"" + NASBackupPath + "\" not available.");
}
}
fso.DeleteFile(tempfile, true); //delete tempfile
}
/* Saves a log in "Debug.Log" */
function Log(msg)
{
fs = WScript.CreateObject("Scripting.FileSystemObject");
a = fs.OpenTextFile("Debug.log", 8, true, 0);
line = "[" + CurrentTime()+ "] ";
line += "[" + WScript.ScriptName + "] ";
line += "[" + msg + "]";
a.WriteLine(line);
}
Nevertheless, errors continue to be issued. I´m using the Script on Windows XP SP3. Is there a possibility to catch this error with javascript?
thanks
I have found the error. The error came from the "Log". First, not every time a new "File System object" must be created. It can be simply used the object "fso". In addition, the open text file must be closed at the end of the function. Here is the correction:
function Log(msg)
{
a = fso.OpenTextFile("Debug.log", 8, true, 0);
line = "[" + CurrentTime()+ "] ";
line += "[" + WScript.ScriptName + "] ";
line += "[" + msg + "]";
a.WriteLine(line);
a.Close();
}
Attached is the code in question.
var http = require("http");
var i = 0;
var hostNames = ['www.1800autoland.com','www.youtube.com','www.1800contacts.com'];
for(i;i<hostNames.length;i++){
var options = {
host: hostNames[i],
path: '/'
};
http.get(options, function(res){
console.log("url: " + hostNames[i]);
console.log("status: " + res.statusCode);
for(var item in res.headers){
if(item == "server"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-powered-by"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-aspnet-version"){
console.log(item + ": " + res.headers[item]);
}
}
console.log("\n");
})
};
I have an array of URLs, and the issue I came to consult the site is that in my code, hostNames[i] does not display the n-th (or "i" in this case) index as a string. The output in console would always be "undefined." I have tried String(), toString(), and a number of different methods to no avail. Could someone point me to the right direction? What is the conversion I need to do?
This is a typical closure problem that occurs because of asynchronousness. When your callback fires the value of i will always be hostNames.length.
To fix it close around the value of i:
http.get(options, (function(res) { // '(' before function is optional, I use it to indicate immediate invocation
return function (i) { // this is the closed value for i
console.log("url: " + hostNames[i]);
console.log("status: " + res.statusCode);
// .. etc
};
}(i))); // immediate invocation with i
What's important to realize about using closures like this, is that you're making a number of anonymous functions, not just one. Each function is bound to its own value of i.
The easiest way to avoid having to write these strange bits of code is to not use for loops directly, but use a map function. Like:
function array_map(array, callback) {
var i, len = array.length;
for (i = 0; i < len; i += 1) {
callback(i, array[i]);
}
}
This makes it so you automatically close the value of i. Your loop will look like:
array_map(hostNames, function(i, hostname) { // i and hostname have the closed value
// .. etc
});
It's the closure problem, try this:
(function (i) {
http.get(options, function(res){
console.log("url: " + hostNames[i]);
console.log("status: " + res.statusCode);
for(var item in res.headers){
if(item == "server"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-powered-by"){
console.log(item + ": " + res.headers[item]);
}
if(item == "x-aspnet-version"){
console.log(item + ": " + res.headers[item]);
}
}
console.log("\n");
})
})(i);
You should use the .get(i) method to retrieve the item. You do not need to initialize the counter in the array, as others have stated.
This is just freakin weird to me. So if I don't
function BindAlbumAndPhotoData()
{
// Get an array of all the user's Albums
var aAlbums = GetAllAlbums(userID, token);
alert("aAlbums: " + aAlbums);
if (aAlbums == null || aAlbums == "undefined")
return;
// Set the default albumID
var defaultAlbumID = aAlbums[0].id;
};
So I get an undefined error on the line var defaultAlbumID = aAlbums[0].id; if I don't uncomment the alert("aAlbums: " + aAlbums);
what the heck? If I comment out alert("aAlbums: " + aAlbums); then I get an undefined for the var defaultAlbumID = aAlbums[0].id;
This is so weird. I've been working all night to figure out why I kept getting an undefined for the aAlbum[0] and as soon as I add back an alert that I used to have above it, all is fine...makes no sense to me.
Here's the full code of GetAllAlbums:
function GetAllAlbums(userID, accessToken)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
alert("uri: " + uri);
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++)
{
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
});
return aAlbums;
}
so I'm not returning the array until I hit the callback of the FB.api async call so I don't see how my defaultAlbumID = aAlbums[0].id; line of code is executing before I have a valid array of data back. When I put in the alert, ovbvioulsly it's delaying before it hits my line defaultAlbumID = aAlbums[0].id; causing it to I guess luckily have data beacuse the async FB.api call is done but again I don't see how that's even possible to have an issue like this when I'm waiting for the call before proceeding on and returning the array to aAlbums in my BindAlbumAndPhotoData() method.
UPDATE #3
function BindAlbumAndPhotoData()
{
GetAllAlbums(userID, accessToken, function (aAlbums)
{
alert("we're back and should have data");
if (aAlbums === null || aAlbums === undefined) {
alert("array is empty");
return false;
}
var defaultAlbumID = aAlbums[0].id;
// Set the default albumID
var defaultAlbumID = aAlbums[0].id;
// Bind the album dropdown
alert(" defaultAlbumID: " + defaultAlbumID);
});
};
function GetAllAlbums(userID, accessToken, callbackFunctionSuccess)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++)
{
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
// pass the array back to the callback function sent as a param to the GetAllAlbums method here
callbackFunctionSuccess(aAlbums);
});
}
It's not hitting my alert in the callback. I must still be doing something wrong here.
UPDATE #4 - for some reason it's not hitting my FB.api callback now.
function GetAllAlbums(userID, accessToken, callbackFunctionSuccess)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
alert("uri: " + uri);
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++) {
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
alert("about to pass back the array to the callback function");
// pass the array back to the callback function sent as a param to the GetAllAlbums method here
callbackFunctionSuccess(aAlbums);
});
}
function BindAlbumAndPhotoData()
{
// Get an array of all the user's Albums
GetAllAlbums(userID, token, function(aAlbums){
// Set the default albumID
var defaultAlbumID = aAlbums[0].id;
});
};
and then in the GetAllAlbums function call the success function when you have the data back
//********* AFTER THE BREAK *******//
In response to the updated question: The FB API is mostly asynchronous, and will keep executing other code while it waits. So using your code, all I have done is passed in the function, and then call the function you've passed it at the end
function GetAllAlbums(userID, accessToken, funcSuccess)
{
var aAlbums = []; // array
var uri = "/" + userID + "/albums?access_token=" + accessToken;
alert("uri: " + uri);
FB.api(uri, function (response)
{
// check for a valid response
if (!response || response.error)
{
alert("error occured");
return;
}
for (var i = 0, l = response.data.length; i < l; i++)
{
alert("Album #: " + i + "\r\n" +
"response.data[i].id: " + response.data[i].id + "\r\n" +
"response.data[i].name: " + response.data[i].name + "\r\n" +
"response.data[i].count: " + response.data[i].count + "\r\n" +
"response.data[i].link: " + response.data[i].link
);
aAlbums[i] = new Album(
response.data[i].id,
response.data[i].name,
response.data[i].count,
response.data[i].link
);
alert("aAlbums[" + i + "].id : " + aAlbums[i].id);
}
funcSuccess(aAlbums);
});
}
Is your function GetAllAlbums() doing some HTTP requests? If so then you need to either make that call synchronous or you need to put your code into a function and pass that as a callback to the Ajax request.
Try three equals signs instead of two, and also... return false rather than nothing at all.
if (aAlbums === null || aAlbums === undefined)
return false;
Also, undefined doesn't need to be in quotes, otherwise, it's just considered a string with a value of "undefined"
On an added note, it's probably better to ALSO check if aAlbums is actually an array before you decide to return a key from it.
if ( aAlbums === null
|| aAlbums === undefined
|| (typeof(aAlbums)=='object'&& !(aAlbums instanceof Array))
} return false;
Try modifying your condition like this:
if (typeof aAlbums == 'undefined')
return;
Also make sure that aAlbums has values and is an array:
alert(aAlbums.length);
Or:
for(var i = 0; i < aAlbums.length; i++)
{
alert(aAlbums[i].id);
}