Firebase setWithPriority results in Firebase.update failed - javascript

I'm trying to write data to the Firebase Database with a given Priority, in order to then retrieve the childs in reversed order than they are currently in. The following I got from the answer of another question regarding this issue:
var postData = {
url: urlvar
};
// Get a key for a new Post.
var newPostKey = firebase.database().ref().push();//.key;
newPostKey.setWithPriority(postData, 0 - Date.now());
var updates = {};
updates['/user-posts/' + uid + '/' + '/urls/' + newPostKey] = postData;
return firebase.database().ref().update(updates);
However, when trying to trigger this, I'm getting (from the extensions popup console):
Error: Firebase.update failed: First argument contains an invalid key
Which argument is meant by that, what exactly is wrong here?
What did work, before I tried to set a priority, was simply the code above but newPostKey was attached a key:
var newPostKey = firebase.database().ref().push().key;

After trying around different approaches I have found a solution where I can just add the priority to the postData, and then write it to the DB:
var postData = {
url: urlvar,
".priority": 0 - Date.now()
};
var newPostKey = firebase.database().ref().push().key;

Related

Unexpected token u in JSON at position 0 not working for async

I am fairly new to js and node.js but I have managed to get the calls going to the API and getting the necessary information. However when I was attempting to continue to raise the batter id to get the next information available. I have successfully gotten the undefined error check to work as well. But I was unable to loop through because I was trying to perform something immediately on an async function. I am now trying to make the entire function async with a 2 second delay after each run, but it is returning the following error (i'm assuming because something is undefined)
**Note: When I just get the value for i=4 and p=1 the value does exist in the API data. However it gives this error when I attempt to start with those values using this code.
error:
Unexpected token u in JSON at position 0
this is my code:
request('API Info redacted',
setTimeout (function (err, response, body) {
//do stuff below
//to get the first play of the game, set i=1 and p=0
var i = 4;
var p = 1;
// ************
var boolIn = 1;
// parse the body as JSON
var parsedBody = JSON.parse(body);
var apiResults = parsedBody.apiResults;
if( typeof(apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p]) == 'undefined') {
//sets the variables to the first batter of the next inning
p=0;
i = i+1;
}
//below pulls the apiResults from the body of the API request
var sportId = apiResults.sportId;
var hitName = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].name;
var fname = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].batter.firstName;
var lname = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].batter.lastName;
var outsB = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].outs.before;
var outsA = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].outs.after;
var rbis = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].runsBattedIn;
var outDifference = (outsA - outsB);
var hitB = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].baseSituation.beforeId;
var hitA = apiResults[0].league.season.eventType[0].events[0].pbp[i].pbpDetails[p].baseSituation.afterId;
var baseDifference = (hitA - hitB);
//prints the details pulled above
res.json("First Name: " + fname + ", Last Name: " + lname + ", Hit name: " + hitName + ", Outs on the play: " + outDifference + ", Rbi's: " + rbis +
", Base Sit: " + baseDifference);
//increases the batter call
p = p+1;
//below ends the setTimeout
}, 2000));
//ended request
});
setTimeout will not pass arguments to the function it calls, so body is undefined. When you pass that to JSON.parse, it will be converted to the string "undefined", which isn't a valid JSON text.
Nowhere is your code do you show any JSON coming into your program (or embedded into it). You need to have some JSON to parse before you try to parse it.

ServiceNow UI Page GlideAjax

I created a form using UI Page and am trying to have some fields autopopulated onChange. I have a client script that works for the most part, but the issue arises when certain fields need to be dot-walked in order to be autopopulated. I've read that dot-walking will not work in client scripts for scoped applications and that a GlideAjax code will need to be used instead. I'm not familiar with GlideAjax and Script Includes, can someone help me with transitioning my code?
My current client script looks like this:
function beneficiary_1(){
var usr = g_user.userID;
var related = $('family_member_1').value;
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee',usr);
rec.addQuery('sys_id',related);
rec.query(dataReturned);
}
function dataReturned(rec){
//autopopulate the beneficiary fields pending on the user selection
if(rec.next()) {
$('fm1_ssn').value = rec.ssn;
$('fm1_address').value = rec.beneficiary_contact.address;
$('fm1_email').value = rec.beneficiary_contact.email;
$('fm1_phone').value = rec.beneficiary_contact.mobile_phone;
var dob = rec.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0] ;
$('fm1_date_of_birth').value = date;
}
}
fm1_address, fm1_email, and fm1_phone do not auto populate because the value is dot walking from the HR_Beneficiary table to the HR_Emergency_Contact table.
How can I transform the above code to GlideAjax format?
I haven't tested this code so you may need to debug it, but hopefully gets you on the right track. However there are a couple of steps for this.
Create a script include that pull the data and send a response to an ajax call.
Call this script include from a client script using GlideAjax.
Handle the AJAX response and populate the form.
This is part of the client script in #2
A couple of good websites to look at for this
GlideAjax documentation for reference
Returning multiple values with GlideAjax
1. Script Include - Here you will create your method to pull the data and respond to an ajax call.
This script include object has the following details
Name: BeneficiaryContact
Parateters:
sysparm_my_userid - user ID of the employee
sysparm_my_relativeid - relative sys_id
Make certain to check "Client callable" in the script include options.
var BeneficiaryContact = Class.create();
BeneficiaryContact.prototype = Object.extendsObject(AbstractAjaxProcessor, {
getContact : function() {
// parameters
var userID = this.getParameter('sysparm_my_userid');
var relativeID = this.getParameter('sysparm_my_relativeid');
// query
var rec = new GlideRecord('hr_beneficiary');
rec.addQuery('employee', userID);
rec.addQuery('sys_id', relativeID);
rec.query();
// build object
var obj = {};
obj.has_value = rec.hasNext(); // set if a record was found
// populate object
if(rec.next()) {
obj.ssn = rec.ssn;
obj.date_of_birth = rec.date_of_birth.toString();
obj.address = rec.beneficiary_contact.address.toString();
obj.email = rec.beneficiary_contact.email.toString();
obj.mobile_phone = rec.beneficiary_contact.mobile_phone.toString();
}
// encode to json
var json = new JSON();
var data = json.encode(obj);
return data;
},
type : "BeneficiaryContact"
});
2. Client Script - Here you will call BeneficiaryContact from #1 with a client script
function onChange(control, oldValue, newValue, isLoading, isTemplate) {
if (isLoading || newValue === '') {
return;
}
var usr = g_user.userID;
var related = $('family_member_1').value;
var ga = new GlideAjax('BeneficiaryContact'); // call the object
ga.addParam('sysparm_name', 'getContact'); // call the function
ga.addParam('sysparm_my_userid', usr); // pass in userID
ga.addParam('sysparm_my_relativeid', related); // pass in relative sys_id
ga.getXML(populateBeneficiary);
}
3. Handle AJAX response - Deal with the response from #2
This is part of your client script
Here I put in the answer.has_value check as an example, but you may want to remove that until this works and you're done debugging.
function populateBeneficiary(response) {
var answer = response.responseXML.documentElement.getAttribute("answer");
answer = answer.evalJSON(); // convert json in to an object
// check if a value was found
if (answer.has_value) {
var dob = answer.date_of_birth;
var arr = dob.split("-");
var date = arr[1] + "/"+ arr[2] + "/" + arr[0];
$('fm1_ssn').value = answer.ssn;
$('fm1_address').value = answer.address;
$('fm1_email').value = answer.email;
$('fm1_phone').value = answer.mobile_phone;
$('fm1_date_of_birth').value = date;
}
else {
g_form.addErrorMessage('A beneficiary was not found.');
}
}

Mailchimp Google sheet issue with the api key

All the variables are returning correct values but the the urlfetch response returns 403 or 401 (access denied).
First log output:
var payload = {
"apikey": API_KEY,
"filters": {
"sendtime_start": REPORT_START_DATE,
"sendtime_end": REPORT_END_DATE
}
};
Logger.log(payload );
Second log output:
var params = {
"method": "POST", //what MC specifies
"muteHttpExceptions": true,
"payload": payload,
"limit": 100
};
Logger.log(params);
Third log output:
var apiCall = function(endpoint) {
//issue with syntax here?
var apiResponse = UrlFetchApp.fetch(automationsList, params);
var json = JSON.parse(apiResponse);
Logger.log(apiResponse);
return json;
};
Automation API Call that is not working:
var automations = apiCall(automationsList);
var automationsData = automations.data;
for (var i = 0; i < automationsData.length; i++) {
// are these response parameters? are these specific values getting pulled from MC - these are the type of values i want?
var a = automationsData[i];
var aid = a.id; // identifies unique campaign *** does this have anything to do with the call function above - it used to be as cid b/c this was for campaigns before??
var emails_sent = a.emails_sent;
var recipients = a.recipients;
var report_summary = a.report_summary;
var settings = a.settings;
if (send_time) {
var r = apiCall(reports, cid); // why does this have cid? but the other one didn't??
var emails_sent = r.emails_sent;
var opens = r.opens;
var unique_opens = r.unique_opens;
var clicks = r.clicks;
var unique_clicks = r.unique_clicks;
var open_rate = (unique_opens / emails_sent).toFixed(4);
var click_rate = (unique_clicks / emails_sent).toFixed(4);
}
The for loop is not even gets executed because I get following error for automationsData:
TypeError: Cannot read property "data" from undefined. (line 82, file "Code")
The apiResponse there is somehow not working, any help is appreciated.
The problem is in how you set up your project in the Developers Console. Try to follow again the process here for you to verify if you already do it in the correct way.
You can also check the solution here in this SO question, he/she explained it here, why he/she get the same 401 and 403 error that you get.
As it turns out, I was using v3.0 for the Mailchimp api whereas I needed to use 2.0.

Authenticating with Last.fm in Jquery - Invalid method signature supplied

I'm trying to auth a Last.fm session and am struggling to sign a request for a session key correctly.
I keep receiving Invalid method signature supplied However when I md5 hash what i believe the query should consist of outside of JS, I get the same signature. I must be including the wrong data in the string I guess, but can't figure out what.
I know there are a few other questions and i've ran through them all to see what's going wrong here, but I swear it looks right to me.
This is the signing algorithm and Ajax call. I've tried to leave enough sample data too.
// Set elsewhere but hacked into this example:
var last_fm_data = {
'last_token':'TOKEN876234876',
'user': 'bob',
'secret': 'SECRET348264386'
};
// Kick it off.
last_fm_call('auth.getSession', {'token': last_fm_data['last_token']});
// Low level API call, purely builds a POSTable object and calls it.
function last_fm_call(method, data){
// param data - dictionary.
last_fm_data[method] = false;
// Somewhere to put the result after callback.
// Append some static variables
data['api_key'] = "APIKEY1323454";
data['format'] = 'json';
data['method'] = method;
post_data = last_fm_sign(data);
$.ajax({
type: "post",
url: last_url,
data: post_data,
success: function(res){
last_fm_data[method] = res;
console.log(res['key'])// Should return session key.
},
dataType: 'json'
});
}
function last_fm_sign(params){
ss = "";
st = [];
so = {};
Object.keys(params).forEach(function(key){
st.push(key); // Get list of object keys
});
st.sort(); // Alphabetise it
st.forEach(function(std){
ss = ss + std + params[std]; // build string
so[std] = params[std]; // return object in exact same order JIC
});
// console.log(ss + last_fm_data['secret']);
// api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386
hashed_sec = unescape(encodeURIComponent($.md5(ss + last_fm_data['secret'])));
so['signature'] = hashed_sec; // Correct when calculated elsewhere.
return so; // Returns signed POSTable object
}
Anything anyone can see that i'm missing here? I'm absolutely stumped why this isn't returning a correctly signed POSTable object in the format requested here. Thanks for your time.
Edit: can't thank anyone for their time if i don't get any advice! No one had any experience with last.fm?
After investigating your code and other posts related to last.fm api call, I found that #george lee in fact is correct. You don't need to provide format while generating the auth_sign.
Apart from that you need to apply $.md5() to auth_sign string after applying encodeURIComponent() and unescape() functions. Like this.
hashed_sec = $.md5(unescape(encodeURIComponent(ss + last_fm_data['secret'])));
Also while making ajax call you need to pass api_key, token & api_sig as data. But seeing your code, reveals that you are passing api_key, token, format, method & signature.
So you need to remove format, method & signature from the data field of ajax call.
Instead you need to pass api_key, token & api_sig to the data field.
So the final code after commenting the data['format'] = 'json'; line will look like this.
// Set elsewhere but hacked into this example:
var last_fm_data = {
'last_token':'TOKEN876234876',
'user': 'bob',
'secret': 'SECRET348264386'
};
// Kick it off.
last_fm_call('auth.getSession', {'token': last_fm_data['last_token']});
// Low level API call, purely builds a POSTable object and calls it.
function last_fm_call(method, data){
// param data - dictionary.
last_fm_data[method] = false;
// Somewhere to put the result after callback.
// Append some static variables
data['api_key'] = "APIKEY1323454";
//data['format'] = 'json';
data['method'] = method;
post_data = last_fm_sign(data);
$.ajax({
type: "POST",
url: last_url,
data: post_data,
success: function(res){
last_fm_data[method] = res;
console.log(res['key'])// Should return session key.
},
dataType: 'json'
});
}
function last_fm_sign(params){
ss = "";
st = [];
so = {};
so['api_key'] = params['api_key'];
so['token'] = params['token'];
Object.keys(params).forEach(function(key){
st.push(key); // Get list of object keys
});
st.sort(); // Alphabetise it
st.forEach(function(std){
ss = ss + std + params[std]; // build string
});
ss += last_fm_data['secret'];
// console.log(ss + last_fm_data['secret']);
// api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386
hashed_sec = $.md5(unescape(encodeURIComponent(ss)));
so['api_sig'] = hashed_sec; // Correct when calculated elsewhere.
return so; // Returns signed POSTable object
}
Please refer to this link.
So on testing some of the responses, I found the solution. There were 2 issues.
EDITED see below (
The first was needing to remove
data['format'] = 'json';
as George Lee pointed out. Thanks George.
)
The other issue was that I'd named a variable incorrectly so was being POSTed with the wrong name. The line
so['signature'] = hashed_sec;
should have been
so['api_sig'] = hashed_sec;
I noticed this in Pankaj's answer but unfortunately the rest of his answer (i.e. including the method) was incorrect. Making these 2 changes resolved the call and signed it correctly.
Thanks for all the suggestions!
EDIT:
After some more playing, i've found that
data['format'] = 'json';
IS correct, however it DOESN'T get hashed with the signature.
Adding data['format'] = 'json'; to the POST object after hashing works, and in this instance will return JSON as opposed to XML - which was the preferred method. Adding after hashing is not documented anywhere that I can find, so there you go.
The new working code is as follows, and this shows the 2 lines indicated with --------------------
// Set elsewhere but hacked into this example:
var last_fm_data = {
'last_token':'TOKEN876234876',
'user': 'bob',
'secret': 'SECRET348264386'
};
// Kick it off.
last_fm_call('auth.getSession', {'token': last_fm_data['last_token']});
// Low level API call, purely builds a POSTable object and calls it.
function last_fm_call(method, data){
// param data - dictionary.
last_fm_data[method] = false;
// Somewhere to put the result after callback.
// Append some static variables
data['api_key'] = "APIKEY1323454";
data['method'] = method;
post_data = last_fm_sign(data);
// THEN ADD THE FORMAT ---------------------------------------
post_data['format'] = 'json';
$.ajax({
type: "post",
url: last_url,
data: post_data,
success: function(res){
last_fm_data[method] = res;
console.log(res['key'])// Should return session key.
},
dataType: 'json'
});
}
function last_fm_sign(params){
ss = "";
st = [];
so = {};
Object.keys(params).forEach(function(key){
st.push(key); // Get list of object keys
});
st.sort(); // Alphabetise it
st.forEach(function(std){
ss = ss + std + params[std]; // build string
so[std] = params[std]; // return object in exact same order JIC
});
// console.log(ss + last_fm_data['secret']);
// api_keyAPIKEY1323454formatjsonmethodauth.getSessiontokenTOKEN876234876SECRET348264386
hashed_sec = unescape(encodeURIComponent($.md5(ss + last_fm_data['secret'])));
so['api_sig'] = hashed_sec; // RENAMED THIS ----------------------------
return so; // Returns signed POSTable object
}

Twitter OAuth1.0A Javascript Error

I'm currently working on incorporating an authorization feature for Twitter following the approach described here: https://dev.twitter.com/docs/auth/implementing-sign-twitter. I'm using Ajax to send my POST 'http' request, but I've been constantly running into a '401: Unauthorized' error. My code is below:
function getTweets() {
var time = generateTimestamp();
var nonce = generateNonce();
var signature = generateSignature(time, nonce);
var headers = {
"Authorization": 'OAuth oauth_callback="http%3A%2F%2Fwww.google.com%2F", oauth_consumer_key="eEeAAz9fakedtAOlIUhPgQ", oauth_nonce="bbc34b2ca6faabogus6dfc025907fa334", oauth_signature="' + signature + '", oauth_signature_method="HMAC-SHA1", oauth_timestamp="' + time + '", oauth_version="1.0"'
};
$.ajax({
type: "POST",
url: "https://api.twitter.com/oauth/request_token",
dataType: "text",
headers: headers,
success: function(data) {
alert("Success!");
console.log(data);
},
error: function(jq) {
alert("Request Failed.");
console.log(jq.statusText);
}
});
}
function generateTimestamp() {
var currentTime = new Date;
currentTime = Math.floor(currentTime.getTime() / 1000);
return currentTime;
}
function generateNonce() {
var code = "";
for (var i = 0; i < 20; i++) {
code += Math.floor(Math.random() * 9).toString();
}
return code;
}
function generateSignature(timestamp, nonce) {
var http_method = "POST";
var base_url = "https://api.twitter.com/oauth/request_token";
var consumer_key = "eEeAAz9hUKtdjunkeIUhPgQ";
var consumer_secret = "c7wHxnjubxVDcc5hYFqnotactuallymysecretWs2XazUFde0lPRBtBQ";
var signature_method = "HMAC-SHA1";
var token = "609493744-kNPzLKSI4Hg9NWQnopeFPb91eXFUutFm1nZ2hDk2";
var token_secret = "15WOJS9Ji1AXsKRkyAZrxKdsalted5Gj5ZyEAb9aVrJxI";
var version = "1.0";
var parameter_string = "oauth_callback=" + encodeURIComponent(base_url) + "&oauth_consumer_key=" + consumer_key + "&oauth_nonce=" + nonce + "&oauth_consumer_key=" + consumer_key + "&oauth_signature_method=" + signature_method + "&oauth_timestamp=" + timestamp +"&oauth_version=" + version;
var base_string = http_method + "&" + encodeURIComponent(base_url) + "&" + encodeURIComponent(parameter_string);
var signing_key = encodeURIComponent(consumer_secret) + "&";
var signature = encodeURIComponent(window.btoa(CryptoJS.HmacSHA1(base_string, signing_key)));
alert(signature);
return signature;
}
Feel free to post below if there's any other information that would make this error clearer. Thanks.
I created a node.js library to mess around with the Twitter OAuth dance and API. Code is here, tweeter.js
You're welcome to walk through the logic for creating the header and signature (starting at line 348 )
One thing I don't see in the code you've posted and which will make a huge difference is that the signature string must be generated to include the original header, then the header must be rebuilt with the generated string. It's a huge pain and it took me a while to figure it out.
Although the code I wrote is geared toward node.js, you should be able to reuse a lot of the logic to meet your needs.
EDIT
I found a site called hueniverse documented OAuth very well. In fact, there is a utility here to build your own headers for validating your logic (select the 'Create your own' radio button).
EDIT 2
To better explain including the oauth_signature value in the header, suppose you have all of the data up to this point:
var headerObj = {
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0"
};
You create the HMAC-SHA1 signature and receive: "jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
You would then add that return value to headerObj, giving you:
headerObj = {
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0",
oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
};
And this modified version of headerObj is what you build your HTTP headers from.
GET / HTTP/1.1
Host: api.twitter.com:443
Authorization: OAuth realm="https://api.twitter.com/",
oauth_consumer_key="123456789",
oauth_token="11111",
oauth_nonce="asdfghjkl%3B",
oauth_timestamp="1341852000",
oauth_signature_method="HMAC-SHA1",
oauth_version="1.0",
oauth_signature="jBpoONisOt5kFYOrQ5fHCSZBGkI%3D"
NOTE: I didn't verify the host/realm/port, so these are probably wrong. Check the API for those.
The reason this is done is that on Twitter's side (this is an OAuth implementation detail), the oauth_signature value is removed and the rest of the header is hashed and its return value is compared to the value sent in oauth_signature. It's sort of like a wax seal on an envelope... if the hash of the rest of the header doesn't match the hash value you sent in oauth_signature, Twitter knows not to trust the sender or the contents.
EDIT 2.5
I'm moving this from the comment to the answer.
If you check out this line in tweeter.js, you'll see the logic.
var signature = self.oauthSignature(method, path, headerObj, query);
headerObj.oauth_signature = qs.escape(signature);
// concat the header object into a csv string
var header = 'OAuth realm="Twitter API",';
var oauthParts = [];
for (var h in headerObj) {
oauthParts.push(h + '="'+headerObj[h]+'"');
}
header+= oauthParts.join(',');
//...
return header;
This bit of code does as I've explained in EDIT 2, by converting a JSON object into key="value" strings stored in oauthParts[], then joins each element in that array into a single comma-separated string which begins with OAuth realm="Twitter API",

Categories

Resources