I run game servers and wrote a Node.js bot to send/receive chat messages from/to Discord to enable communication between them.
Now I want to integrate it's functionality to receive the latest logs from the game to Discord.
I have managed to make it work for a single player but now I want to make it work for several players.
I have three variables: channelID, server, playerID.
So, my question is what's the best method to have multiple arrays of ChannelID which will contain multiple server values and playerID values to be processed by a single function?
My current working code:
var channelID = "channel1";
var server = "server1";
var playerID = "player1";
//Last log message is stored in Webdis
var webdisURL = "http://127.0.0.1:7379/GET/" + server + playerID;
setInterval(() => lastLog(webdisURL, function(body) {
Object.keys(body).forEach(e => result = `${body[e]}`);
client.channels.cache.get(channelID).send(result);
}), 3000);
function lastLog(webdisURL, callback) {
request({
url: webdisURL,
json: true
}, function(error, response, body) {
if (!error && response.statusCode === 200) {
callback(body);
}
});
}
So I have managed to do it like this:
var webdisURL = "http://127.0.0.1:7379/GET/";
class Players {
constructor(players, channelID) {
players = players.split(',');
players.forEach(getPlayers);
function getPlayers(value) {
var playerName = value.split(":")[0];
var playerSRV = value.split(":")[1];
var playerID = value.split(":")[2];
var getLogURL = webdisURL + playerSRV + playerID;
var result;
var previousResult;
setInterval(() => lastLog(getLogURL, function (body) {
Object.keys(body).forEach(e => result = `${body[e]}`);
if (result !== previousResult) {
client.channels.cache.get(channelID).send("[" + playerName + "] - [" + playerSRV + "]: " + result);
previousResult = result;
}
}), 3000);
function lastLog(getLogURL, callback) {
request({
url: getLogURL,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
callback(body);
}
});
}
}
}
}
// "playerName1:playerSRV1:playerID1,playerName2:playerSRV2:playerID2", "channelID"
let playerTeam1 = new Players("Perseus:myServer1:ID1", "channel1");
let playerTeam2 = new Players("Another Player:myServer2:ID1,Another Player2:myServer3:ID1", "channel2");
Example Output:
[Perseus] - [myServer1]: Day 153, 11:59:43: Your 'Campfire' was auto-decay destroyed!
[Another Player] - [myServer2]: Day 153, 11:59:43: Your 'Campfire' was auto-decay destroyed!
[Another Player2] - [myServer3]: Day 153, 11:59:43: Your 'Campfire' was auto-decay destroyed!
Does it look OK? I'll appreciate any suggestions for improvement.
Related
When I am calling one API from the nodejs it is giving proper reply. But when I am adding one more call it is giving 401 error. I dont know if I have to close some parameter before calling another request.
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
var request = require('request')
var username = "shruti111";
var password = 'Welcome1';
var planId;
baseUrl = 'https://50d5a18993c046e585b90bc8cc5e1f80-jcs.oci.cloudonline.ml:443';
var baseUrlwoHttps = baseUrl.substring(8);
process.env["NO_PROXY"] = baseUrlwoHttps;
var getUrl = baseUrl + '/IMCMCSREST/rest/v1/PlannedCosts';
var options = {
url: getUrl,
auth: {
user: username,
password: password
}
}
request(options, function (err, res, body) {
if (err) {
console.dir(err)
return
}
var json = JSON.parse(body);
var arr = [];
for (i = 0; i < json.items.length; i++) {
if (json.items[i].PlanCode == 'Material Cost Planning - PO')
planId = json.items[i].PlanId;
//arr.push(json.items[i].PlanId, json.items[i].PlanCode);
}
console.log(planId);
})
Upto this point it is working properly. If I add below code in the same file it gives 401 error for both call. Otherwise it runs properly.
var getUrl = baseUrl + 'IMCMCSREST/rest/v1/PlannedCosts/' + planId + '/ child / CmiCpPlanCostTypesView';
var options = {
url: getUrl,
auth: {
user: username,
password: password
}
}
request(options, function (err, res, body) {
if (err) {
console.dir(err)
return
}
console.log(body);
var json = JSON.parse(body);
console.log(json);
var arr = [];
var x;
for (i = 0; i < json.items.length; i++) {
arr[i] = json.items[i].CostTypeId;
//arr.push(json.items[i].PlanId, json.items[i].PlanCode);
}
console.log(arr[i]);
})
I think the first problem here is the plandId variable you're using on second request does not have a value. What you can try is calling the second request on the callback of first request.
Another problem seems to be you are redefining existing variables, though its not fully clear as you didn't show the file as a whole.
I have to make a load of subsequent http requests to load product images into the app as it has to function in an offline mode.
Around 2000 calls.
The http client seems toi have a memory leak which causes the persistent mbytes in "instruments" to rise to around 200 without being garbaged.
After use of the http client it is being set to null.
I have tried setting the file property of the httpclient without any success
I have set the unload function to only call the callback function which in turn calls the http send function again (thus looping through the 2000 products to get the respective pictures)
I changed from SDK 7.5.0.v20180824022007 to SDK 8.1.0.v20190423134840 and even SDK 9.0.0.v20181031080737 but the problem remains
the code of my http common module:
function HttpClient(options = {}) {
this.root = options.root || "ROOT_OF_API";
this.endpoint = options.endpoint || false;
this.needsChecksum = options.needsChecksum || false;
this.data = {};
this.method = options.method || "Post";
this.timeout = options.timeout || 5000;
this.calculateChecksum = function () {
var moment = require('alloy/moment');
if (!Alloy.Models.user.authenticated()) {
return false;
}
var sp = (moment().unix() - Alloy.Models.meta.get("timeDiff"))
var hash = Ti.Utils.md5HexDigest("nX" + sp + "FossilSFAapp" + Alloy.Models.user.get('token').substring(10, 14) + "CS")
var checksum = sp + "-" + hash.substring(4, 8)
this.data.checksum = checksum
}
};
HttpClient.prototype.setData = function (data) {
this.data = data
};
HttpClient.prototype.send = function (callback) {
// set new checksum for request if is needed
if (this.needsChecksum) {
this.calculateChecksum()
}
// add app version
if (this.method === "POST") {
this.data.appversion = Ti.App.version;
}
// send
var client = Ti.Network.createHTTPClient({
onload: function () {
callback({
success: true
})
},
onerror: function(e) {
callback({
message: e.messgae,
success: false
})
},
timeout: this.timeout
});
client.open(this.method, this.root + this.endpoint);
if (this.setFile) {
client.file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, this.fileName);
}
client.setRequestHeader('Content-Type', 'application/json');
client.send(JSON.stringify(this.data));
client = null;
};
module.exports = HttpClient;
and then the module is used in the product model like so:
var HttpClient = require('./HttpClient');
var httpClient = new HttpClient();
function getImage (i) {
if (collection.at(i) && collection.at(i).get('iimage0') && collection.at(i).needsImageUpdate()) {
httpClient.endpoint = collection.at(i).get('acarticlenumber') +".jpg";
httpClient.fileName = 'productImages/' + collection.at(i).get('acarticlenumber') + '.jpg'
httpClient.send(function(e){
if (i < collection.length) {
i++
getImage(i)
} else {
finished()
}
});
} else {
if (i < collection.length) {
i++
getImage(i)
} else {
finished()
}
}
}
// start getting images at index 0
getImage(0)
anyone have an idea why these memory leaks appear ?
It only ever occurs when actually sending the http request.
Hi Im working on a scraper script so far Ive been able scrape from 2 elements . At this testing state I do not have a database setup thus far. So I thought Id just Sort this straight to my server page. This is my working code
var http = require('http');
var request = require('request');
var cheerio = require('cheerio');
http.createServer(function (req, res) {
request('http://www.xscores.com/soccer', function (error, response,
html) {
if (!error && response.statusCode == 200) {
var $ = cheerio.load(html);
var HomeTeam = "";
var AwayTeam = "";
$('div.score_home_txt.score_cell.wrap').each(function (i, element) {
var a = $(this).text();
var a = a.toLowerCase();
HomeTeam += "<tr><td>" + a + "</td>";
//console.log(a);
});
$('div.score_away_txt.score_cell.wrap').each(function (i, element) {
var b = $(this).text();
var b = b.toLowerCase();
AwayTeam += "<td>" + b + "</td><tr>";
//console.log(b);
});
var html = "<table><th>" + "HomeTeam</th><th>AwayTeam</th>" + HomeTeam + AwayTeam + "</table>"
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end(html);
}
});
}).listen(8080);
console.log('Server is running at http://178.62.253.206:8080/');
The plan was to sort this in a table with 2 Columns Home in Col A and Away in ColB, But im a little unsure how to write this so it gets sorted correctly.
The code above sort this into a single row. Ive tried a few different approaches but haven figured out the correct way yet :/
Any help would be much appreciated
Frederik
You need to find a common parent, looking at the website you are scraping .score_line looks like a reasonable option
// assume we're always going to return html
res.set('Content-Type', 'text/html');
// hit API
request('http://www.xscores.com/soccer', (err, response, html) => {
if (err || response.statusCode !== 200) {
// log error internally
console.error(err ? err.message : `API status code: ${response.statusCode}`);
// return client response
return res.status(500).send('<b>Internal Server Error</b>');
}
const $ = cheerio.load(html);
const rows = [];
// find each row
$('.score_line').each((i, el) => {
// extract each column
const homeScore = el.find('.score_home.score_cell.wrap').text().toLowerCase();
const awayScore = el.find('.score_away.score_cell.wrap').text().toLowerCase();
// build row
rows.push(`<tr><td>${homeScore}</td><td>${awayScore}</td></tr>`);
});
// build & send table
res.send(`<table>${rows.join('')}</table>`);
});
var getMatches = function(){
var sait = 'https://www.website.com'
request({ url: sait, jar: true}, function(error, response, html){
if(!error){
var $ = cheerio.load(html)
var count = ($('.TheMatch').length)
for(var i = 2; i< count + 2 ; i++){
var live = ($('.TheMatch:nth-child('+i+') .LiveStatus').text())
var nameMatch = ($('.TheMatch:nth-child('+i+') .MDxEventName').text())
var time = ($('.TheMatch:nth-child('+i+') .DateTime').text().substring(8))
var websiteCount = ($('.TheMatch:nth-child('+i+') .TotalBookies').text())
if((websiteCount >= 25) && (live.length === 0) ){
console.log('match ' + nameMatch)
console.log('count Websites ' + websiteCount)
}
}}})}
i want to make auth on this website and save the cookie how can i do it ? and save the cookie so everytime i parse dont gonna need to log in ?
Well, I did similar task. But problem is that it is always site specific. Anyway, the way to do it is to use request library to make a post request to website's auth endpoint. Then response object will contain appropriate cookies like sessionID or something. Then you save this cookie and do a new request to page you wanted from the beginning. Here is documentation about cookies in request module: https://github.com/request/request#requestcookie. That worked for me fine.
How to get:
request.post({ url: "website/signin",
form: {
login: 'login',
password: "password",
remember: 1
}
}, function(err, httpResponse, body) {
var cooka = false;
var cookies = httpResponse.headers['set-cookie'];
if (typeof cookies != "undefined") cooka = cookies[0];
if (typeof cooka != "undefined" && cooka != false) {
self.sessionId = cooka.substring(10, cooka.indexOf(";"));
} else {
return self.emit("error", "Can't get session id");
}
});
How to set:
var options = { uri: "desired url" };
var j = request.jar();
if (worker.source == "coquette") {
var cookie = request.cookie('PHPSESSID=' + worker.sessionId);
j.setCookie(cookie, url);
options.jar = j;
}
request.get(options, function(error, response, body) {
if (error || response.statusCode != 200) {
} else {
// work with body body
}
});
app.getImage = function() {
var image = Meteor.http.get("https://turtlerock-discourse.global.ssl.fastly.net/user_avatar/talk.turtlerockstudios.com/takran/45/879.png", {
});
var prefix = "data:image/png;base64,";
var imagebase64 = new Buffer(image.content, 'binary').toString('base64');
imagebase64 = prefix + imagebase64;
console.log(imagebase64);
return imagebase64;
}
but I am not seeing results,
any help?
This is a dummy text for the error.
a pure Meteor solutions:
var response = HTTP.call('GET', url,{npmRequestOptions: { encoding: null }})
var data = "data:" + response.headers["content-type"] + ";base64," + new Buffer(response.content).toString('base64');
This is how I fixed this issue.
app.getImage = function(){
var myrequest = request.defaults({ encoding: null });
var fut = new Future();
var options = {
"url" : "https://any.domain.com/any.png"
}
myrequest.get(options, function (error, response, body) {
if (!error && response.statusCode == 200) {
var data = "data:" + response.headers["content-type"] + ";base64," + new Buffer(body).toString('base64');
fut.return(data);
}
else
fut.return(null);
});
return fut.wait();
}
I was assuming this solution should have come with meteor code itself,
but it doesn't,
I had to use nodejs way to do it.
I will still be waiting for someone to post an answer based on pure meteor way.