Update: I successfully got it to post events between two dates. The problem is I set the two dates to year-month-dayT00:00:00.000Z and year-month-dayT23:59:59.999Z. but it sends events from the previous day and the day I set it to. See code snippets after everything else.
Original:
I use discord a lot in communications and now I am part of a robotics team that would like to use it as well. The only problem is, it doesn't work with Google calendar. So I looked around a bit to see if i could find a bot that i could use. There are a few out there but non of them are that great. So I decided to make my own. I am using node.js and the google calendar api.
So far I have gotten the authentication of the calendar down so that works. But now I am trying to figure out how to get daily updates in a discord channel. This is the default example Google gives you on doing this. Only problem is all it does is just give the next 10 events on your calendar, not just for the day.
if anyone could help me figure out how to go about doing this it would be much apreciated.
function getEvents(auth) {
var calendar = google.calendar('v3');
calendar.events.list({
auth: auth,
calendarId: 'primary',
timeMin: (new Date()).toISOString(),
maxResults: 10,
singleEvents: true,
orderBy: 'startTime'
}, , function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var events = response.items;
if (events.length == 0) {
console.log('No upcoming events found.');
} else {
console.log('Upcoming 10 events:');
for (var i = 0; i < events.length; i++) {
var event = events[i];
var start = event.start.dateTime || event.start.date;
console.log('%s - %s', start, event.summary);
}
}
});
}
Here is what I have to run it everyday:
var datetime = new Date();
datetime.getHours('newlistener', (event, addEventListener) => {
if (datetime.getHours == 24) {
getEventsForDay();
}
else {
return;
}
});
Updated code:
var datetime = new Date();
function getCurrentDayList() {
var year = ('0' + datetime.getUTCFullYear()).slice(-4);
var month = ('0' + (datetime.getUTCMonth() + 1)).slice(-2);
var day = ('0' + (datetime.getUTCDate())).slice(-2);
return (year + '-' + month + '-' + day + 'T00:00:00.000Z');
}
function getNextDayList() {
var year = ('0' + datetime.getUTCFullYear()).slice(-4);
var month = ('0' + (datetime.getUTCMonth() + 1)).slice(-2);
var day = ('0' + (datetime.getUTCDate())).slice(-2);
return (year + '-' + month + '-' + day + 'T23:59:59.999Z');
}
function listEvents(auth) {
var calendar = google.calendar('v3');
calendar.events.list({
auth: auth,
calendarId: 'primary',
timeMin: getCurrentDayList(),
timeMax: getNextDayList(),
maxResults: 10,
singleEvents: true,
orderBy: 'startTime'
}, function(err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
var events = response.items;
if (events.length == 0) {
console.log('No upcoming events found.');
} else {
console.log('Upcoming 10 events:');
for (var i = 0; i < events.length; i++) {
var event = events[i];
var start = event.start.dateTime || event.start.date;
console.log('%s - %s', start, event.summary);
}
}
});
}
Try adding timeMax and timeMin.
timeMax
Upper bound (exclusive) for an event's start time to filter by. Optional. The default is not to filter by start time. Must be an RFC3339 timestamp with mandatory time zone offset, e.g., 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but will be ignored. If timeMin is set, timeMax must be greater than timeMin.
TimeMin
Lower bound (inclusive) for an event's end time to filter by. Optional. The default is not to filter by end time. Must be an RFC3339 timestamp with mandatory time zone offset, e.g., 2011-06-03T10:00:00-07:00, 2011-06-03T10:00:00Z. Milliseconds may be provided but will be ignored. If timeMax is set, timeMin must be smaller than timeMax.
timeMax 2018-01-06T00:00:00-08:00
timeMin 2018-01-05T00:00:00-08:00
Also there is a tutorial on "Retrieve events occuring between a date range."
Hope this helps.
Related
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.
I have a node.js app consisting of a timer calling a user defined function made up of a bunch of functions in node language. The calling script has a timer calling function mybuy() every 10 seconds; mybuy() buys crypto currencies using Binance api according trigger prices contained in a mySQL table (alarms). I would like to start mysell() (not shown , but similar to myBuy()) right after mybuy() has run its course.
How to make mysell() the callback function of mybuy()?
This the calling script:
var fs = require('fs');
var sl = require('alberto/buy');
var loop = 0;
setImmediate(() => {
// start the log
fs.appendFile('./log.txt', "\n Loop-> " + loop + "\n", function (err) {
if (err) { console.log(err); }
})
//execute the function
sl.mybuy(); // USD function; everything happens here.Can take long to finish
var myInt = setInterval(function () {
loop++;
fs.appendFile('./log.txt', "Loop-> " + loop + "\n", function (err) {
if (err) { console.log(err); }
})
//execute every 10 secs
sl.mybuy();
if (loop > 5) { clearInterval(myInt); } // max 6 loops for testing
}, 10000);
});
the UDF id here
exports.mybuy = function () {
var fs = require('fs'); // I keep a log.txt
process.stdout.write("\u001b[2J\u001b[0;0H");// clear screen
aww = (new Date()).toJSON().slice(0, 19).replace(/[-T]/, '-');
aww = aww.replace(/T/, ' ');
console.log(aww, '\n\n'); // practicing with dates
var mysql = require('mysql');
var con = mysql.createConnection({
host: "www.photobangkok.com",
user: "photoban_user",
password: "xxxxxxxx",
database: "photoban_datab"
});
// 'added' is for never processed entries in alarms table.It will change to BOUGHT or SOLD
sql = "SELECT rec, id,coin,buy,amount_b,stat FROM alarms where stat='added' AND buy>0 order by coin";
var cnt = 0; // not used, perhaps an idea to emit an event when cnt reaches the number of rows
con.query(sql, function (err, result) {
if (err) throw err;
str = "";
for (var index in result) {
str = result[index].rec + "-" + result[index].id + "-" + result[index].coin + "-" + result[index].buy + "-" + result[index].amount_b + "-" + result[index].stat;
// set up variables
coin = result[index].coin;
buy = result[index].buy;
rec = result[index].rec;
id = result[index].id;
amount = result[index].amount_b;
console.log('\x1b[36m%s\x1b[0m', str); // set color green. Display str
checkprice(coin, buy, rec, id, amount); //check Binance today price for the coin.The function will execute sometimes
} // end of loop
console.log('\x1b[36m%s\x1b[0m', str); // set color green. Display str
});
//check single coin price using binance api
function checkprice(coin, buy, rec, id, amount) {
const binance = require('node-binance-api')().options({
APIKEY: '<key>',
APISECRET: '<secret>',
useServerTime: true,
test: true //sandbox does not work
});
binance.prices(coin, (error, ticker) => {
act = "Nothing"; // default value
pricenow = ticker[coin]; // note ticker[coin]
if (pricenow < buy) {
show(id, rec, coin, buy, amount, pricenow);// Display sometimes then call book()
} else { console.log(coin, pricenow, buy, act, '\n'); }
});
}
function show(id, rec, coin, buy, amount, pricenow) {
delta = buy - pricenow; // posted trigger - today price
delta = delta.toFixed(8);
console.log('\x1b[31m%s\x1b[0m', coin, buy, amount, id, rec, ">BUY", delta); //display entries from alarms higher that today price
book(id, rec, coin, buy, amount, pricenow);
}
// dummy function to be replaced with a buy api order
function book(id, rec, coin, buy, amount, pricenow) {
const binance = require('node-binance-api')().options({
APIKEY: '<key>',
APISECRET: '<secret>',
useServerTime: true,
test: true //sandbox
});
console.log("Order:buy what??", coin, "amount:", amount, '\n');
/* binance.prices(coin, (error, ticker) => {
console.log("booking",coin, ticker[coin]);
update(id,rec);
}); */
update(id, rec, amount); // update mySql table. Slow but sure
}
function update(id, rec, amount) {
var sql = "UPDATE alarms SET stat = 'BOUGHT' ,today =
CONVERT_TZ(now(), '+00:00', '+7:00') WHERE id = "+id+" AND rec = "+rec;
con.query(sql, function (err, result) {
if (err) throw err;
console.log(result.affectedRows + " record updated");
// keep a log.tx
fs.appendFile('./log.txt', aww + " bought " + id + "-" + rec + "-" + amount + "\n",
function (err) {
if (err) { console.log(err); }
})
});
}
// I could check if all rows are done and raise an event? (how to do it)
} // end
To make mySell as the callback method of myBuy, invoke the myBuy method using the following structure.
myBuy(() => {
// operation of mySell method
});
And your myBuy method should return the callback, after perform its own operation.
exports.myBuy = function(cb) {
// operation of myBuy method
return cb; // return to the mySell method
}
For example clinic working hours on specific date are as follow:
var workingStartTime = 2018-05-12T08:00:00.000Z;
var workingEndTime = 2018-05-12T22:00:00.000Z;
Doctor's already scheduled appointments on the same date are as follow:
var busySlots =
[ {
start_time: '2018-05-12T14:30:00.000Z',end_time:'2018-05-12T17:45:00.000Z'
},
{
start_time: '2018-05-12T20:30:00.000Z',end_time: '2018-05-12T21:45:00.000Z'
}]
I need to fetch available time slots of doctor which are greater than 60 minutes starting from 2018-05-12T08:00:00.000Z to 2018-05-12T22:00:00.000Z
timings of a day with minimum line of code in nodejs.
Following problem is similar to my query:
How to find free time slot based on available time slot and booked time slot?
But above code is in php and i need code written in nodejs.
Below code might be not optimized but it works for me:
function (cb){
var duration = 60;
var freeSlots = [];
var workingStartTime = 2018-05-12T08:00:00.000Z;
var workingEndTime = 2018-05-12T22:00:00.000Z;
var busySlots = [];
busySlots.push({ start_time: "2018-05-12T14:30:00.000Z",end_time: "2018-05-12T17:45:00.000Z" }) ;
busySlots.push({ start_time: "2018-05-12T20:30:00.000Z",end_time: "2018-05-12T21:45:00.000Z" }) ;
var beginAt = workingStartTime;
var overAt = workingEndTime;
var count = 0;
var last = busySlots.length;
async.forEach(busySlots, function (item, callback){
/*** Library funcition to gind difference between two dates (Minutes) ***/
var diff = libFunc.getRange(beginAt, item.start_time,TIME_UNITS.MINUTES);
if(diff > duration){
let free = {"start_time":beginAt , "end_time":item.start_time};
freeSlots.push(free);
beginAt = item.end_time;
count += 1;
/** Process for end slot **/
if(last == count){
var diff = libFunc.getRange(item.end_time, overAt, TIME_UNITS.MINUTES);
if(diff > duration){
let free = {"start_time":item.end_time , "end_time":overAt};
freeSlots.push(free);
callback();
}else{
callback();
}
}else{
callback();
}
/** Process for end slot **/
}else{
beginAt = item.end_time;
count += 1;
/** Process for end slot **/
if(last == count){
var diff = libFunc.getRange(item.end_time, overAt, TIME_UNITS.MINUTES);
if(diff > duration){
let free = {"start_time":item.end_time , "end_time":overAt};
freeSlots.push(free);
callback();
}else{
callback();
}
}else{
callback();
}
/** Process for end slot **/
}
}, function(err) {
// console.log(freeSlots);
cb(null);
});
},
I'm using Express & Node.js.
router.get('/:year?/:month?/:day?', function(req, res) {
var date = moment();
if (req.params.year && req.params.month && req.params.day) {
var dateString = req.params.year + " " + req.params.month + " " + req.params.day;
var tempDate = moment(dateString, "DD MM YYYY");
if (tempDate.isValid()) {
date = tempDate;
}
}
.catch(function (err) {
console.error(err);
res.send("Error");
});
});
The above isn't my full code for my route. But I need some pointers. I'm using Moment.js(http://momentjs.com/) to grab the current date, format it and pass it through the url in the route.get request.
However, I don't want the user to be able to go to a past date. So if the date has already been and the user tries to navigate too it I want to redirect them back to the current date.
.then (function(){
var pastDate = function(req, res) {
if (req.query.[pastDate]) {
res.redirect('/');
} else {}
}
})
I don't think the the syntax is correct. But not sure if i'm looking on the right lines in how I'd do this.
Thanks for help.
I looked through your code and it looks really inconsisten and I don't fully understand what you're trying to do, but you can probably narrow it down to something like this:
router.get('/:year?/:month?/:day?', function (req, res) {
var year = req.params.year;
var month = req.params.month;
var day = req.params.day;
if (year && month && day) {
var requestDate = moment(day + ' ' + month + ' ' + year);
var today = moment();
if (requestDate.isValid() && !requestDate.isBefore(today)) {
// All set and valid, do stuff with the request
} else {
// Invalid date or the requested date is before today
// Redirecting to /year/month/day of this day, e.g /2015/04/31
return res.redirect('/' + today.year() + '/' + today.month() + '/' + today.date());
}
}
});
Moment has an isBefore method that is really handy for these kind of tasks.
You should use a bit more variables in your code so it's easier to work with! :)
You should be able to just do a less than comparison.
var goodDate = function() {
var now = moment();
if (this < now) {
return false
}
return true
}
How would you go about applying a time limit to a series of callbacks in node.js?
Would this be easier using the async library?
Thankyou, as you can see I'm struggling with asynchronous javascript.
Instead of calling the next step directly, call the below function with
doNext : your actual next step
stepData : your parameters plus an execution time limit in miliseconds
unDoThis : the function to run if the work just done ever must be undone
function nextStep(doNext, stepData, unDoThis) {
The first time, set the time out
if (!stepData.expireAt) {
var currentDate = new Date();
stepData.expireAt = currentDate.setMilliseconds(currentDate.getMilliseconds() + stepData.runMiliseconds);
console.log(new Date().toISOString() +" We will expire at "
+ new Date(stepData.expireAt).toISOString());
};
Remember how to undo the last completed step
if (!stepData.unDoAll) stepData.unDoAll = [];
if (unDoThis) stepData.unDoAll.push(unDoThis);
If time is expired, undo all completed steps
if (new Date(stepData.expireAt) < new Date().getTime()) {
while (stepData.unDoAll.length) {
var unDoOne = stepData.unDoAll.pop();
unDoOne();
}
console.log(new Date().toISOString() +' That was it!');
else perform the next step
} else {
doNext(stepData, Array.prototype.slice.call(arguments, 2));
}
}
From the below worker functions we will build the chain that we will interupt
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}
function oneStep(stepData) {
console.log (new Date().toISOString() +' ('+ stepData.nrIterations +') I do some stuff ');
sleep(100);
var myIteration = stepData.nrIterations--;
if (stepData.nrIterations) {
nextStep(otherStep, stepData);
}
}
function otherStep(stepData) {
console.log (new Date().toISOString() +' ('+ stepData.nrIterations +') I do more stuff, leaving a trace');
sleep(100);
var myIteration = stepData.nrIterations--;
if (stepData.nrIterations) {
nextStep(oneStep, stepData, function () {
console.log(new Date().toISOString() +' ('+ myIteration +') I clean some trace ');
});
}
}
And now we use it.
Play around with runMiliseconds and nrIterations to see the effect
console.log (new Date().toISOString() + ' About to start ');
var currentDate = new Date();
nextStep(oneStep, {
runMiliseconds : 250,
nrIterations: 22
});