I am trying to deploy a scheduled cloud function to Google Firebase, such as this
https://firebase.google.com/docs/functions/schedule-functions
Anytime I deploy the schedule as "every 1 minutes" it gets deployed fine. However, if I try to do anything else, like "every 60 minutes", "every 8 hours", I get the following error.
I am not even getting information about the error so it is hard to debug.
exports.bookingReminder = functions.pubsub.schedule('every 1 minutes').onRun((context) => {
let today = new Date()
var dateArray = []
let year = (today.getYear() - 100) + 2000
dateArray.push(year.toString())
var month = today.getMonth() + 1
if (month < 10) {
month = "0" + month.toString()
}
dateArray.push(month.toString())
var day = today.getDate()
if (day < 9) {
day = "0" + day.toString()
}
dateArray.push(day.toString())
let fullDate = dateArray.join("-")
console.log(fullDate)
const bookingsRef = admin.firestore().collection("bookings").where("date", "==", fullDate).get().then(snapshot => {
if (snapshot.empty) {
console.log('No matching documents.');
return null;
}
var emails = []
snapshot.forEach(doc => {
console.log("yes found them on this date: " + fullDate)
var booking = doc.data()
var clients = booking.clients
clients.forEach(client => {
emails.push(client.email)
})
console.log(emails);
const serviceRef = admin.firestore().collection("services").doc(booking.serviceId)
let servie = {}
const serviceSnap = serviceRef.get().then(doc2 => {
service = doc2.data()
}).then(() => {
const msg = {
//need client email
to: emails, // Change to your recipient
from: '', // Change to your verified sender
//Booking Reminder
};
console.log("running email send")
sgMail.send(msg);
})
})
return emails;
})
});
Related
I need to calculate the difference in days between two dates in two differente occasions
Occasion 1 - There's a start and an end date
Occasion 2 - There's a start date and a "IN PROGRESS" where the end date should be
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var daTa = ss.getSheetByName("Data");
var daysColumn = daTa.getRange('C2:C' + daTa.getLastRow()).getValues();
var startDate = daTa.getRange('C2:C'+ daTa.getLastRow()).getValues().flat();
var endDate = daTa.getRange('A2:A'+ daTa.getLastRow()).getValues().flat();
var today = new Date().valueOf();
endDate.forEach((finaldate,row) => {
if(finaldate == "IN PROGRESS") {
daysColumn[row][0] = (parseInt(startDate,10)-today);
} else {
daysColumn[row][0] = (parseInt(startDate,10)-parseInt(finaldate,10));
}})
daTa.getRange(2,4,daysColumn.length, 1).setValues(daysColumn)
}
Right now i got this bit of code, and it know what needs to be done, but it returns only "#NUM!" values on the column, where it should print the numbers.
Probably you want this:
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var daTa = ss.getSheetByName("Data");
var daysColumn = daTa.getRange('C2:C' + daTa.getLastRow()).getValues();
var startDate = daTa.getRange('C2:C' + daTa.getLastRow()).getValues().flat()
.map(x => new Date(x).valueOf()); // get milliseconds of the dates
var endDate = daTa.getRange('A2:A' + daTa.getLastRow()).getValues().flat()
.map(x => new Date(x).valueOf()); // get milliseconds of the dates
var today = new Date().valueOf();
var day = 1000 * 60 * 60 * 24; // milliseconds in a day
endDate.forEach((finaldate, row) => {
if (finaldate == "IN PROGRESS") {
daysColumn[row][0] = (startDate[row] - today) / day;
} else {
daysColumn[row][0] = (startDate[row] - finaldate) / day;
}
})
daTa.getRange(2, 4, daysColumn.length, 1).setValues(daysColumn)
}
function DiffInDays(Day1,Day2) {
if(Day1 && Day2 && (Object.prototype.toString.call(Day1) === '[object Date]') && (Object.prototype.toString.call(Day2) === '[object Date]')) {
var day=86400000;
var t1=new Date(Day1).valueOf();
var t2=new Date(Day2).valueOf();
var d=Math.abs(t2-t1);
var days=Math.floor(d/day);
//Logger.log(days);
return days;
} else {
throw 'Invalid Inputs';
}
}
Code below works aside from when Postgres Server is down. After it comes back and socket is available see multiple connections. Normally on clean start of the js it shows only one connection, on a reconnect I'm seeing sometimes more than 5.
Any Ideas why?
var express = require('express');
const app = express();
const fs = require("fs-extra");
const bodyParser = require('body-parser');
const R = require('ramda');
require ('dotenv').config();
var reconnectLoop = 0;
var sleepInterval = 0;
var pg = require('pg');
const pool = {
user: process.env.DB_USER,
host: process.env.DB_SERVER,
database: process.env.DB_NAMESPACE,
password: process.env.DB_PASSWORD,
port: process.env.DB_PORT,
max: 1,
connectionTimeoutMillis: 2000
};
let date_ob = new Date();
// current date
// adjust 0 before single digit date
let date = ("0" + date_ob.getDate()).slice(-2);
// current month
let month = ("0" + (date_ob.getMonth() + 1)).slice(-2);
// current year
let year = date_ob.getFullYear();
// current hours
let hours = date_ob.getHours();
// current minutes
let minutes = date_ob.getMinutes();
// current seconds
let seconds = date_ob.getSeconds();
let client;
const postgresDBConnect = () => {
const startedAt = new Date().getTime();
client = new pg.Client(pool)
client.on('error', (err) => {
console.log('startedAt:-', startedAt);
console.log('crashedAt:-', new Date().getTime());
//Reconnect
reconnectLoop = reconnectLoop + 1;
sleepInterval = reconnectLoop * 1000;
console.log('Trying Reconnect1' + ' Sleep Timeout ' + sleepInterval);
setTimeout(postgresDBConnect,sleepInterval);
});
client.connect(err => {
if (err) {
console.error('Connection issue:', err.stack)
reconnectLoop = reconnectLoop + 1
sleepInterval = 1000 * reconnectLoop
console.log('Trying Reconnect2' + '. Sleep Timeout ' + sleepInterval)
setTimeout(postgresDBConnect,sleepInterval)
} else {
console.log('Connected to Postgres Server')
}
});
};
console.log('Starting UP Postgres Connection');
postgresDBConnect();
var user = {}
app.use(bodyParser.json());
app.post('/post-test', (req, res) => {
console.log('Got body:', req.body);
res.sendStatus(200);
});
app.post('/insertactivity', function (req, res) {
console.log('InsertActivity, Got body:', req.body);
res.sendStatus(200);
var string = JSON.stringify(req.body);
var objectValue = JSON.parse(string);
console.log('currenttime:',objectValue["domain_activity"]["currenttime"]);
console.log('username:',objectValue["domain_activity"]["username"]);
console.log('domain:',objectValue["domain_activity"]["domain"]);
console.log('computer:',objectValue["domain_activity"]["computer"]);
console.log('ipaddr:',objectValue["domain_activity"]["ipaddr"]);
console.log('action:',objectValue["domain_activity"]["action"]);
console.log('macaddr:',objectValue["domain_activity"]["macaddr"]);
console.log('uuid:',objectValue["domain_activity"]["uuid"]);
objdata1 = objectValue["domain_activity"]["currenttime"];
objdata2 = objectValue["domain_activity"]["username"];
objdata3 = objectValue["domain_activity"]["domain"];
objdata4 = objectValue["domain_activity"]["computer"];
objdata5 = objectValue["domain_activity"]["ipaddr"];
objdata6 = objectValue["domain_activity"]["action"];
objdata7 = objectValue["domain_activity"]["macaddr"];
objdata8 = objectValue["domain_activity"]["uuid"];
client.query(`insert into public.authentication_activity (currenttime,username,domain,computer,ipaddr,action,macaddr,uuid) values (
'${objdata1}',
'${objdata2}',
'${objdata3}',
'${objdata4}',
'${objdata5}',
'${objdata6}',
'${objdata7}',
'${objdata8}')`).then(res => {
}).catch(err => {
console.log(err.stack);
})
//.finally(() => {
// client.end()
});
app.post('/updateactivity', function (req, res) {
console.log('UpdateActivity, Got body:', req.body);
res.sendStatus(200);
var string = JSON.stringify(req.body);
var objectValue = JSON.parse(string);
console.log('username:',objectValue["domain_activity"]["username"]);
console.log('uuid:',objectValue["domain_activity"]["uuid"]);
objdata9 = objectValue["domain_activity"]["username"];
objdata10 = objectValue["domain_activity"]["uuid"];
client.query(`select public.sessionduration ('${objdata9}','${objdata10}')`).then(res => {
}).catch(err => {
console.log(err.stack);
})
//.finally(() => {
// client.end()
});
var server = app.listen(8081, function () {
var host = server.address().address
var port = server.address().port
console.log("Server.js app listening at http://%s:%s", host, port)
})
// prints date & time in YYYY-MM-DD HH:MM:SS format
console.log(date + "/" + month + "/" + year + " " + hours + ":" + minutes + ":" + seconds);
Fixed by adding client.end()
Now only see one connection is postgres is restarted
client.connect(err => {
if (err) {
console.error('Connection issue:', err.stack)
reconnectLoop = reconnectLoop + 1
sleepInterval = 1000 * reconnectLoop
console.log('Trying Reconnect2' + '. Sleep Timeout ' + sleepInterval)
client.end()
setTimeout(postgresDBConnect,sleepInterval)
} else {
console.log('Connected to Postgres Server')
}
});
I have 2 actions which are :
This is first
I insert person here :
export const InsertOrUpdate = (person) => {
return (dispatch) => {
var instance = Axios.create({
baseURL: 'url',
// timeout: 1000,
headers: {
"Content-Type": "application/json"
}
});
instance.get("/InsertWorker", {
params: {
Name: person.Name,
Surname: person.Surname,
Duty: person.Duty,
DateOfDay: person.Date.substring(0, person.Date.length - 9),
Shift: person.Shift,
WorkDayCount: person.WorkDayCount,
Equipment: person.Equipment,
Sicil: person.Sicil,
Ship: person.Ship
}
});
}
}
This is second
I call workers here :
export const getSignedWorkers = (collection) => {
return (dispatch) => {
var instance = Axios.create({
baseURL: 'url',
// timeout: 1000,
headers: {
"Content-Type": "application/json"
}
});
instance.get('/GetWorkers', {
params: {
DateOfDay: collection.Tarih,
Shift: collection.Vardiya
}
})
.then((response) => response.data)
.then(x => {
const Signed = str3.filter(x => x.Ship != "" && x.Shift != "H");
console.warn('signed', Signed);
const UnSigned = str3.filter(x => x.Ship == "" || null);
const RemoveOnHolidays = UnSigned.filter(x => x.Shift != "H");
const OnHoliday = str3.filter(x => x.Shift == "H");
const AllWorkers = {};
AllWorkers.signed = Signed;
AllWorkers.Unsigned = RemoveOnHolidays;
AllWorkers.OnHoliday = OnHoliday;
dispatch({ type: FETCH_SIGNED_WORKERS_SIGNED, payload: AllWorkers });
})
.catch((error) => {
console.warn('error', error);
})
}
}
I call this actions here :
_Insert = (person) => {
person.Ship = this.props.gemi_Sefer_No;
this.props.InsertOrUpdate(item); <------- Here I call first action
var date = new Date().getDate(); //Current Date
var month = new Date().getMonth() + 1; //Current Month
var year = new Date().getFullYear(); //Current Year
var tarih = year + "/" + month + "/" + date;
let collection = {};
collection.Tarih = tarih;
collection.Vardiya = this.props.vardiya == 0 ? "S" : this.props.vardiya == 1 ? "A" : this.props.vardiya == 2 ? "G" : null
this.props.getSignedWorkers(collection); <--- Here I call second action
}
I try to insert workers to database then call all workers from database and use another component with redux. However, sometimes it works correctly sometimes not.
I mean , when I insert to database and call back again, insert worker works right however calling all workers come without worker which I insert last one. As I said, it works sometimes right. What should I do ?. Is that wrong to call two actions in same method ? if it is, what should I do ?
What I need to do to circumvent this issue, because when I request data for 2 months I already receive this error, when there is a break per day, I have the following call. With Little data works perfect, but when I increase the period the server brings me
User request limit reached","type":"OAuthException","is_transient":true,"code":17,"error_subcode":2446079,"fbtrace_id":"...
function solicitacaoAssicrona(){
var service = getService()
var batch = [{"method": "GET", "relative_url":"v3.2/act_1125789557444919/insights/impressions,reach,frequency,spend,campaign_name,account_name,clicks,cost_per_10_sec_video_view,cpm,cpp?level=campaign&since=2016-03-03&until=2019-03-04&time_increment=1&limit=100"}]
// var batchUrl = encodeURIComponent(JSON.stringify(batch));
// Logger.log(batchUrl);
var url = "https://graph.facebook.com?include_headers=false&batch=" + encodeURIComponent(JSON.stringify(batch))
var response = UrlFetchApp.fetch(url, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(result)
// response.forEach(function(resp){
// var resp = JSON.parse(resp.body);
// //Logger.log(JSON.stringify(resp, null, 2));
//
//// resp.data[0].values.forEach(function(response){
////
////
//// })
////
// })
}
I'Ve looked at the documentation, but to the moment without success!
https://developers.facebook.com/docs/marketing-api/insights/best-practices/
That's the call I have
var metricas = [
'impressions',
'reach',
'unique_clicks',
'account_currency',
'account_id',
'account_name',
'ad_id',
'ad_name',
'adset_id',
'adset_name',
'buying_type',
'campaign_id',
'campaign_name',
'clicks',
'cost_per_inline_link_click',
'cost_per_inline_post_engagement',
'cost_per_unique_click',
'cost_per_unique_inline_link_click',
'cpc',
'cpm',
'cpp',
'ctr',
'date_start',
//'date_stop',
'frequency',
'inline_link_click_ctr',
'inline_link_clicks',
'inline_post_engagement',
'objective',
'relevance_score',
'social_spend',
'spend',
'unique_ctr',
'unique_inline_link_click_ctr',
'unique_inline_link_clicks',
'unique_link_clicks_ctr',
//'website_ctr',
'video_10_sec_watched_actions',
'cost_per_10_sec_video_view',
'video_30_sec_watched_actions',
'video_avg_percent_watched_actions',
'video_avg_time_watched_actions',
'video_p100_watched_actions',
'video_p25_watched_actions',
'video_p50_watched_actions',
'video_p75_watched_actions',
'video_play_actions',
'video_thruplay_watched_actions',
'video_p95_watched_actions',
]
var parameters = metricas.join(',');
var url = 'https://graph.facebook.com/v3.2/act_xxxxxxxxxx/insights?fields= + parameters + '&level=ad&time_range[since]=2019-02-05&time_range[until]=2019-04-05&time_increment=1&limit=200'
It's to do with how much data you can retrieve with batch requests. For longer periods, you should divide it into smaller chunks, sequential to each other, thus retrieving the data needed in multiple requests. Have a look at this example:
Code.gs
From line 88 of the file, you can see how it can be divided in multiple requests.
https://github.com/halsandr/Facebook_Connector/blob/master/Code.gs
function dateDelta(dObj, num) {
if (isNaN(num)) {
var dateStart = new Date(dObj);
} else {
var dateStart = new Date(dObj);
var dateStart = new Date(dateStart.setDate(dateStart.getDate() + num));
}
var dd = dateStart.getDate();
var mm = dateStart.getMonth()+1; //January is 0!
var yyyy = dateStart.getFullYear();
if(dd<10){
dd='0'+dd;
}
if(mm<10){
mm='0'+mm;
}
var dateStart = yyyy + "-" + mm + "-" + dd;
return dateStart;
}
var gStartDate = new Date(request.dateRange.startDate);
var gStartDate = new Date(dateDelta(gStartDate, -1));
var gEndDate = new Date(request.dateRange.endDate);
var gEndDate = new Date(dateDelta(gEndDate, +1));
var gRange = Math.ceil(Math.abs(gEndDate - gStartDate) / (1000 * 3600 * 24));
var gBatches = Math.ceil(gRange / 92);
if (gBatches < 2) {
var batch = [{"method": "GET", "relative_url": request.configParams.pageID + "/insights/page_fans,page_impressions,page_post_engagements?since=" + dateDelta(gStartDate) + "&until=" + dateDelta(gEndDate)}];
//console.log(batch);
} else {
batch = [];
var iterRanges = gRange / gBatches;
for (i = 0; i < gBatches; i++) {
var iterStart = dateDelta(gStartDate, (iterRanges * i));
if (i == (gBatches - 1)) {
var iterEnd = dateDelta(gEndDate);
} else {
var iterEnd = dateDelta(gStartDate, (iterRanges * (i + 1)) + 1);
}
batch.push({"method": "GET", "relative_url": request.configParams.pageID + "/insights/page_fans,page_impressions,page_post_engagements?since=" + iterStart + "&until=" + iterEnd})
}
//console.log(batch);
}
// Fetch the data with UrlFetchApp
var url = "https://graph.facebook.com?include_headers=false&batch=" + encodeURIComponent(JSON.stringify(batch))
I have a couple of forms on a site I'm working on and the script that controls them doesn't include a success message, so when they're submitted the input data just disappears and the user doesn't know if it's been actually sent or not. I've looked around a bit for answers, but because this file controls an email submission form, a contact form, and a twitter feed, it's a bit much for me to see what's what.
Here's the code, I'd just like to let users know that their message has been sent for both the email input form and the contact form. I appreciate any help that's out there!
$(document).ready(function() {
//Set default hint if nothing is entered
setHints();
//Bind JavaScript event on SignUp Button
$('#signUp').click(function(){
signUp($('#subscribe').val());
});
//Bind JavaScript event on Send Message Button
$('#sendMessage').click(function(){
if(validateInput()){
sendMail();
}else
{
alert('Please fill all fields to send us message.');
}
});
//Load initial site state (countdown, twitts)
initialize();
});
var setHints = function()
{
$('#subscribe').attachHint('Enter your email to be notified when more info is available');
$('[name=contact_name]').attachHint('Name');
$('[name=contact_email]').attachHint('Email');
$('[name=contact_subject]').attachHint('Subject');
$('[name=contact_message]').attachHint('Message');
};
var signUp = function(inputEmail)
{
var isValid = true;
var emailReg = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/;
if(!emailReg.test(inputEmail)){
isValid = false;
alert('Your email is not in valid format');
}
if(isValid){
var params = {
'action' : 'SingUp',
'email' : inputEmail
};
$.ajax({
type: "POST",
url: "php/mainHandler.php",
data: params,
success: function(response){
if(response){
var responseObj = jQuery.parseJSON(response);
if(responseObj.ResponseData)
{
$('#subscribe').val('');
}
}
}
});
}
};
var initialize = function()
{
var params = {
'action' : 'Initialize'
};
$.ajax({
type: "POST",
url: "php/mainHandler.php",
data: params,
success: function(response){
if(response){
var responseObj = jQuery.parseJSON(response);
if(responseObj.ResponseData)
{
$('ul.twitts').empty();
if(responseObj.ResponseData.Twitts){
$('a.followUsURL').attr('href','http://twitter.com/#!/'+responseObj.ResponseData.Twitts[0].Name);
$.each(responseObj.ResponseData.Twitts, function(index, twitt){
var twitterTemplate = '<li>'
+ '#{0}'
+ '{2}'
+ '<span class="time">{3}</span>'
+ '</li>';
$('ul.twitts').append(StringFormat(twitterTemplate, twitt.Name, twitt.StatusID, twitt.Text, twitt.Date));
});
}
if(responseObj.ResponseData.Start_Date)
{
setInterval(function(){
var countDownObj = calculateTimeDifference(responseObj.ResponseData.Start_Date);
if(countDownObj){
$('#days').text(countDownObj.Days);
$('#hours').text(countDownObj.Hours);
$('#minutes').text(countDownObj.Minutes);
$('#seconds').text(countDownObj.Seconds);
}
}, 1000);
}
}
}
}
});
};
var validateInput = function(){
var isValid = true;
$('input, textarea').each(function(){
if($(this).hasClass('required'))
{
if($(this).val()!=''){
if($(this).hasClass('email'))
{
var emailReg = /^([\w-\.]+#([\w-]+\.)+[\w-]{2,4})?$/;
if(!emailReg.test($(this).val())){
isValid = false;
alert('Your email is not in valid format');
}
}
}else
{
isValid = false;
}
}
});
return isValid;
};
var resetInput = function(){
$('input, textarea').each(function() {
$(this).val('').text('');
});
};
var sendMail = function(){
var params = {
'action' : 'SendMessage',
'name' : $('[name=contact_name]').val(),
'email' : $('[name=contact_email]').val(),
'subject' : $('[name=contact_subject]').val(),
'message' : $('[name=contact_message]').val()
};
$.ajax({
type: "POST",
url: "php/mainHandler.php",
data: params,
success: function(response){
if(response){
var responseObj = jQuery.parseJSON(response);
if(responseObj.ResponseData)
$('label.sendingStatus').text(responseObj.ResponseData);
}
resetInput();
$('#sendMail').removeAttr('disabled');
},
error: function (xhr, ajaxOptions, thrownError){
//xhr.status : 404, 303, 501...
var error = null;
switch(xhr.status)
{
case "301":
error = "Redirection Error!";
break;
case "307":
error = "Error, temporary server redirection!";
break;
case "400":
error = "Bad request!";
break;
case "404":
error = "Page not found!";
break;
case "500":
error = "Server is currently unavailable!";
break;
default:
error ="Unespected error, please try again later.";
}
if(error){
$('label.sendingStatus').text(error);
}
}
});
};
var calculateTimeDifference = function(startDate) {
var second = 1000;
var minute = second * 60;
var hour = minute * 60;
var day = hour * 24;
var seconds = 0;
var minutes = 0;
var hours = 0;
var days = 0;
var currentDate = new Date();
startDate = new Date(startDate);
var timeCounter = startDate - currentDate;
if (isNaN(timeCounter))
{
return NaN;
}
else
{
days = Math.floor(timeCounter / day);
timeCounter = timeCounter % day;
hours = Math.floor(timeCounter / hour);
timeCounter = timeCounter % hour;
minutes = Math.floor(timeCounter / minute);
timeCounter = timeCounter % minute;
seconds = Math.floor(timeCounter / second);
}
var tDiffObj = {
"Days" : days,
"Hours" : hours,
"Minutes" : minutes,
"Seconds" : seconds
};
return tDiffObj;
};
var StringFormat = function() {
var s = arguments[0];
for (var i = 0; i < arguments.length - 1; i++) {
var regExpression = new RegExp("\\{" + i + "\\}", "gm");
s = s.replace(regExpression, arguments[i + 1]);
}
return s;
}
You need to hook into the success callbacks of each of the $.ajax calls. You can create a method that will show a message for those:
For example, your signUp function's success callback could look like:
success: function(response){
if(response){
var responseObj = jQuery.parseJSON(response);
if(responseObj.ResponseData)
{
$('#subscribe').val('');
showMessage('Your subscription was received. Thank you!');
}
}
}
And you just create a method that will show the message to the user
var showMessage = function (msg) {
// of course, you wouldn't use alert,
// but would inject the message into the dom somewhere
alert(msg);
}
You would call showMessage anywhere the success callback was fired.
You can add your success notifing code in each of the $.ajax success handlers.