I am trying to call some Parse CloudCode that I wrote for Mailgun, but when I call it from my iOS app this is what I get:
E2015-09-16T05:52:37.410Z]v4 after_save triggered for EmailConfirmations for user HjHSYVX56t:
Input: {"object":{"createdAt":"2015-09-
16T05:52:37.399Z","email1":"test#trever.me","email2":"test#trever.me","name1":"Test Test","name2":"Test Test","objectId":"KPLpKdZqSO","updatedAt":"2015-09-16T05:52:37.399Z"}}
Result: Uncaught Error: Can't form encode an Object
I get this from the Parse Console, does anyone know what that means exactly?
Thank you!
Here is my CloudCode:
// bring in Mailgun
var Mailgun = require('mailgun');
// init Mailgun
Mailgun.initialize('sandboxcf52f1abbe6f4bbe80c055aecc31f58f.mailgun.org', 'key-b29acfb8411921998764456e247c30fa');
Parse.Cloud.afterSave("EmailConfirmations", function(request) {
// This function runs on INSERT and DELETE operations.
// Check to ensure account is new.
if (!request.object.existed()) {
var email1 = request.object.get("email1");
var email2 = request.object.get("email2");
var name1 = request.object.get("name1");
var name2 = request.object.get("name2");
var tradeDateTime = request.object.get("tradeDateTime");
var body = "Hello " + name1 + "&" + name2 + ",\n\n Your trade on" + tradeDateTime +
"has been approved, and will need to be processed in Empower, or via an Expresso ticket. " +
"Please process as soon as possible to ensure a successful trade.";
var sender = "test#test.com";
var subject = "Trade Confirmation";
}
Mailgun.sendEmail(
{
to: [email1, email2],
from: sender,
subject: subject,
text: body
}, onMailComplete, onMailError);
function onMailComplete (httpResponse) {
console.log(httpResponse);
console.log("Email sent to " + email1 + "and" + email2);
}
function onMailError (httpResponse) {
console.error(httpResponse);
console.error("Uh oh, something went wrong");
}
} /* eo func def */
);
And this is the code where I'm calling the cloud function:
PFCloud.callFunctionInBackground("EmailConfirmations", withParameters: ["objectId": objectID, "email1" : emailCurrentUser, "email2" : emailCurrentUser, "name1" : fullnameCurrentUser, "name2" : fullnameCurrentUser])
I guess you tried to send an HTTP request passing object as parameter where it expected string. Use JSON.stringify(object) before passing it.
For more info see: https://parse.com/questions/result-uncaught-error-cant-form-encode-an-object
EDIT:
Now i totally.. don't understand what's going on. You should re-read the Parse Cloud guide because you are mixing afterSave hooks with cloud function calls and those are different things.
I guess your cloud code should look like this:
// bring in Mailgun
var Mailgun = require('mailgun');
// init Mailgun
Mailgun.initialize('sandboxcf52f1abbe6f4bbe80c055aecc31f58f.mailgun.org', 'key-b29acfb8411921998764456e247c30fa');
Parse.Cloud.define("EmailConfirmations", function(request) {
var email1 = request.params.email1;
var email2 = request.params.email2;
var name1 = request.params.name1;
var name2 = request.params.name2;
var tradeDateTime = request.params.tradeDateTime;
var body = "Hello " + name1 + "&" + name2 + ",\n\n Your trade on" + tradeDateTime +
"has been approved, and will need to be processed in Empower, or via an Expresso ticket. " +
"Please process as soon as possible to ensure a successful trade.";
var sender = "test#test.com";
var subject = "Trade Confirmation";
Mailgun.sendEmail({
to: [email1, email2],
from: sender,
subject: subject,
text: body
}, onMailComplete, onMailError);
function onMailComplete (httpResponse) {
console.log(httpResponse);
console.log("Email sent to " + email1 + "and" + email2);
}
function onMailError (httpResponse) {
console.error(httpResponse);
console.error("Uh oh, something went wrong");
}
} /* eo func def */
);
And in the swift function call you can skip the objectID but you should add tradeDateTime of type NSDate
Related
I am making a Telegram bot using Appscript and I want to copy/send message with an inline_keyboard but when I send the URL I get an invalid parameter error and I don't know what is wrong, because everything worked until I add the reply_markup parameter.
function enviarMnesjePruebaCanal() {//ENVIAR MENSAJE
var urlusuarioconid = "tg://userid?=" + miID
var keyboard = {
"inline_keyboard": [
[
{
"text": "Usuario",
"url": urlusuarioconid
}
]
]
};
var url = telegramUrl + '/sendMessage?chat_id=' + miID + '&text=' + "texto" + "&reply_markup=" + JSON.stringify(keyboard);
Logger.log(url);
UrlFetchApp.fetch(url);
}
`
This is my code and this is what I send to telegram and what I get back:
(I have deleted the data of my bot and my id for obvious reasons, but that part is ok because when I run it without the last part it sends me the message)
I have already tried several things and they all give the same problem, I don't know if anyone can help me or see what could be happening. Thanks!
The issue is caused by the reply_markup containing non-url tokens.
You should encode that part of the url using encodeURIComponent()
Change the code to:
function enviarMnesjePruebaCanal() {
var myID = 123456;
var urlusuarioconid = "tg://userid?=" + myID
var keyboard = {
"inline_keyboard": [
[
{
"text": "Usuario",
"url": urlusuarioconid
}
]
]
};
var url = telegramUrl + '/sendMessage?chat_id=' + myID + '&text=' + "texto" + "&reply_markup=" + encodeURIComponent(JSON.stringify(keyboard));
Logger.log(url);
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
The important change here is adding the encodeURIComponent:
encodeURIComponent(JSON.stringify(keyboard))
I have some problem with parse cloud js.
After I save ParseMessage object, I want to check 3 pointer (product, sender and recipient) in other class (MessageTracker). With the base 3 query there is no problem, but when I call insideQuery.notEqualTo("sender", result.get("owner")); I got an error:
102 : pointer field sender needs a pointer value
This "owner" also a pointer to user class, like the others (sender and recipient), but this time parse cloud send an error.
(On console I see, that the object ids are valid values, so I have the right objects)
Parse.Cloud.afterSave("ParseMessage", function(request) {
var message = request.object;
var product = message.get("product");
var sender = message.get("sender");
var recipient = message.get("recipient");
var query = new Parse.Query("Product");
query.get(product.id, {
success: function(result) {
console.error("prod owner: " + result.get("owner").id + " sender: " + sender.id + " reciever: " + recipient.id);
var insideQuery = new Parse.Query("MessageTracker");
insideQuery.equalTo("product", product);
insideQuery.equalTo("sender", sender);
insideQuery.equalTo("recipient", recipient);
insideQuery.notEqualTo("sender", result.get("owner"));
insideQuery.find({
success: function(results) {
console.error("count: " + results.length);
},
error: function(error) {
console.error("Got an error " + error.code + " : " + error.message);
}
});
},
error: function(object, error) {
}
});
});
Any good advice?
UPDATE
I maybe found the problem. Parse do not let us check equalTo and notEqualTo for the same pointer in the query. Is there any other way to do that?
Try building out the pointer:
var ownerPointer = {
__type: 'Pointer',
className: <className>,
objectId: result.get("owner").id
};
insideQuery.notEqualTo("sender", ownerPointer);
I want to develop an app for Pebble. This app is going to tell you how long it takes from one place you set in options to another one taking in account traffic jams and stuff.
To achieve this I need to make a page that will return JSON. Pebble retrieves information using code like that:
var cityName = 'London';
var URL = 'http://api.openweathermap.org/data/2.5/weather?q=' + cityName;
ajax(
{
url: URL,
type: 'json'
},
function(data) {
// Success!
console.log('Successfully fetched weather data!');
},
function(error) {
// Failure!
console.log('Failed fetching weather data: ' + error);
}
);
I created a small page with a js script that gets needed information from Yandex API:
var route;
ymaps.ready(init);
var myMap;
function init(){
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
var time = 0;
var home = getParameterByName("h");
var work = getParameterByName("w");
ymaps.route([home, work],{avoidTrafficJams: true}).then(
function (router) {
route=router;
time = ((route.getTime())/60).toFixed(2);
var info = new Object;
info["home"] = home;
info["work"] = work;
info["time"] = ~~time+"m"+~~((time%1)*60)+"s";
JSON.stringify(info);
},
function (error) {
alert('Возникла ошибка: ' + error.message);
}
);
}
As you can see I can get a JSON string in the end. But how do I send it to clients when a request with right parameters is made?
I ended up using phantomjs and executing this js script on my php page.
How do I save a user pointer to an object when i have the object id of the user.
I am able to save the object to the class in Parse but the assignee is always 'Undefined' in Parse.
e.g. I have retrieved the user object and can get the username / object id etc through:
function getUserFromUsername(username) {
Parse.initialize("...", "...");
console.log('The username passed in is: ' + username);
var User = Parse.Object.extend("_User");
var query = new Parse.Query(User);
query.equalTo("username", username);
query.first({
success : function(result) {
// Do something with the returned Parse.Object values
var userPointer = new Parse.User();
userPointer = result;
console.log(userPointer.get('username')); // this returns the correct username
return userPointer;
},
error : function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
Which is called from my save task function below: (Note, I've logged all relevant fields and they return as expected.
function saveNewTask(clientName, taskTitle, taskDue, assigneeArray) {
Parse.initialize("...", "...");
var x;
for (x in assigneeArray) {
var Task = Parse.Object.extend("Tasks");
var task = new Task();
task.set("title", taskTitle);
task.set("date", taskDue);
var thisAssignee = GetUserFromUsername(assigneeArray[x]);
task.set('assignee', thisAssignee);
task.save(null, {
success : function(task) {
// Execute any logic that should take place after the object is saved.
console.log('New object created with objectId: ' + task.id);
},
error : function(gameScore, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
console.log('Failed to create new object, with error code: ' + error.message);
}
});
}
}
So you should save a pointer to the user to the task.
var Task = Parse.Object.extend("Tasks");
var task = new Task();
task.set("user", user);
task.set("title", "taskTitle");
task.set("date", taskDue);
task.save(null, {
success : function(task) {
// Execute any logic that should take place after the object is saved.
console.log('New object created with objectId: ' + task.id);
},
error : function(gameScore, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
console.log('Failed to create new object, with error code: ' + error.message);
}
});
By default, when fetching an object, related Parse.Objects are not fetched. These objects' values cannot be retrieved until they have been fetched like so:
var user = task.get("user");
user.fetch({
success: function(user) {
//fetch user is here
}
});
This is explained here: https://parse.com/docs/js_guide#objects-pointers
The problem with your script is when you are querying in Parse it is done asynchronously so you can't return the user immediately. Instead you need to return the promise and then handle it when you call getUserFromUsername:
function getUserFromUsername(username) {
var User = Parse.Object.extend("_User");
var query = new Parse.Query(User);
query.equalTo("username", username);
return query.first();
}
getUserFromUsername('testUsername').then(function(result) {
//use User here
}, function(error) {
alert("Error: " + error.code + " " + error.message);
});
Take a look at this document on promise chaining for more information about promises:
I created a simple Google form with the fields:
Name, E-mail, Salary and Request.
When the user completes the form, I want to send him/her an e-mail with the info. However, I want to use the "Request" field to plug in a unique number that the user can refer to if they need further correspondence. If the user enters anything in the 'Request' field, I want to discard it and use the number that I generate (both in the response and in the spreadsheet).
I've been able to piece together the script using other info I've found. It seems to work for everything except the e-mail response going back to the user.- It does not contain the number that I want to use in the 'Request' field, but instead sends back any input that the user puts in the 'Request' field. The spreadsheet looks ok (it has my number in the 'Request' field.)
Here's my script:
function sendFormByEmail(e) {
var capsht = SpreadsheetApp.getActiveSheet();
var caprow = SpreadsheetApp.getActiveSheet().getLastRow();
capsht.getRange(caprow,5).setValue("Cap-"+caprow);
var admin = "admin#xxx.com";
try {
var recipient = e.namedValues["Email"];
var subject = "Capacity Request Form Received";
var s = SpreadsheetApp.getActiveSheet();
var headers = s.getRange(1,1,1,s.getLastColumn()).getValues()[0];
var message = "";
for (var i in headers)
message += headers[i] + ' = '+ e.namedValues[headers[i]].toString() + "\n\n";
MailApp.sendEmail(recipient, subject, message);
}
catch (error) {
MailApp.sendEmail(admin, "Error with form submission response email", error.message);
}
}
try it like this :
(added comment in code and deleted repetitions)
function sendFormByEmail(e)
{
var capsht = SpreadsheetApp.getActiveSheet();
var caprow = capsht.getLastRow();
var codenumber = "Cap-"+caprow
capsht.getRange(caprow,5).setValue(codenumber);
var admin = "admin#xxx.com";
try {
var recipient = e.namedValues["Email"];
var subject = "Capacity Request Form Received";
var headers = capsht.getRange(1,1,1,capsht.getLastColumn()).getValues()[0];
var message = "";
for(var i in headers)
if(i!=4){
message += headers[i] + ' = '+ e.namedValues[headers[i]].toString() + "\n\n";
}else{ // if i==4 (column nr5)then use your code number
message += headers[i] + ' = '+ codenumber + "\n\n";
}
MailApp.sendEmail(recipient, subject, message);
}
catch (error)
{
MailApp.sendEmail(admin, "Error with form submission response email", error.message);
}
}