Trying to GET from api after posting API issues - javascript

Hi developers I am back again with a question,
I am trying to get some data from this website https://www.iamsterdam.com/nl/uit-in-amsterdam/uit/agenda. First did I crawl the website but when doing that it came to mind that they have a api and that will be a lot faster. So I tried to get the data from the api I tried this:
get-website.js:
var webPage = require('webpage');
var page = webPage.create();
var settings = {
operation: "POST",
encoding: "utf8",
headers: {
"Content-Type": "application/json"
},
data: JSON.stringify({
DateFilter: 03112016,
PageId: "3418a37d-b907-4c80-9d67-9fec68d96568",
Take: 2,
Skip: 12,
ViewMode: 1
})
};
page.open('https://www.iamsterdam.com/api/AgendaApi/', settings, function(status) {
console.log(page.content);
phantom.exit();
});
get-website.php
$phantom_script= 'get-website.js';
$response = exec ('phantomjs ' . $phantom_script);
echo $response;
But what I get back doesn't look good:
Message":"An error has occurred.","ExceptionMessage":"Page could not be found","ExceptionType":"System.ApplicationException","StackTrace":" at Axendo.SC.AM.Iamsterdam.Controllers.Api.AgendaApiController.GetResultsInternal(RequestModel requestModel)\r\n at lambda_method(Closure , Object , Object[] )\r\n
etc.
Here is a picture of firebug:
I hope someone can help me.

Interesting question. I was a bit surprised that the site would honor AJAX-request in a browser and even in cURL, but not in PhantomJS. In such cases you have to study and replicate request very carefully, because one of little details probably greatly affects the server's response.
Turned out, it was a cookie and form content-type that had to be set accordingly.
var webPage = require('webpage');
var page = webPage.create();
// courtesy of http://stackoverflow.com/a/1714899/2715393
var serialize = function(obj) {
var str = [];
for(var p in obj)
if (obj.hasOwnProperty(p)) {
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
}
return str.join("&");
}
var settings = {
operation: "POST",
encoding: "utf8",
headers: {
"accept-encoding" : "identity", // https://github.com/ariya/phantomjs/issues/10930#issuecomment-81541618
"x-requested-with" : "XMLHttpRequest",
"accept-language" : "en;q=0.8,en-US;q=0.6",
"authority" : "www.iamsterdam.com",
"accept":"application/json, text/javascript, */*; q=0.01",
"content-type" : "application/x-www-form-urlencoded; charset=UTF-8",
"cookie" : "website#lang=nl"
},
data: serialize({
Genre: '',
DateFilter: '03112016',
DayPart: '',
SearchTerm: '',
Neighbourhoud: '',
DayRange: '',
ViewMode: 1,
LastMinuteTickets : '',
PageId: '3418a37d-b907-4c80-9d67-9fec68d96568',
Skip: 0,
Take: 12
})
};
page.open('https://www.iamsterdam.com/api/AgendaApi/', settings, function(status) {
console.log(page.content);
phantom.exit();
});

Related

Trying to create multisig account for NEM on local machine but getting error

Hello Everyone I am trying to make plugin from Buildfire to be bale to create NEM account and to change it into multisig account using local network (ei localhost)
Here are the code snippets for the required things I would like to ask weather there is an issue in making of JSON missing bits in the json or any other errors I need to look up, I have tried to look up error and it's solution but met with no results. The error I get is :
"error: "Internal Server Error" message: "expected value for property
transaction, but none was found" status: 500"
let done = $.ajax({
url: "http://127.0.0.1:7890/account/generate"
}).done(function (data) {
/// check you have data to report on
///if (data && data.list && data.list.length) {
/// fill in the UI with the new data
var report = data;
PubKey = report.publicKey;
PKey = report.privateKey;
$('#address').text("Created Account");
$('#balance').text(report.address);
$('#summary').text(report.privateKey);
$('#vested').text(report.publicKey)
///}
});
var date = new Date();
var TS = date.getTime();
var xyz = {
xyz: JSON.stringify({
"transaction":
{
"timeStamp": TS, ///needs to be changed to current timestamp from creating of account
"fee": 20, ///have to check
"type": 4097,
"deadline": TS + 30000, ///need to be changed
"version": -1744830462, /// main(real) network 1744830465,
"signer": PubKey,
"modifications": [
{
"modificationType": 1,
"cosignatoryAccount": PbKey
}
],
"minCosignatories" : {
"relativeChange": 1
}
},
"privateKey": PKey
})
};
fetch("http://127.0.0.1:7890/transaction/prepare-announce",{
method : 'POST',
headers : {
'Accept': 'application/json, text/plain, */*',
'Content-Type': 'application/json'
},
body : JSON.stringify(xyz)
}).then(function (response) {
return response.json();
})
.then(function (result) {
alert(result);
}).catch (function (error) {
console.log('Request failed', error);
});
did you try normal transaction?
It looks you don't sign your transaction.
and DON'T FETCH YOUR PRIVATE KEY ON NETWORK.

jQuery ajax base auth working only from external websites but not from local request

This code works when used on external websites (e.g. jsfiddle.net)
but not when used on my website itself:
var $ = jQuery;
var makeBaseAuth = function(user, pswd){
var token = user + ":" + pswd;
var hash = "";
if (btoa) {
hash = btoa(token);
}
return "Basic " + hash;
};
var settings = {
"crossDomain": true,
"url": "http://mywebsite.org/wp-json/wp/v2/settings",
"method": "GET",
"headers": {
"authorization": makeBaseAuth("admin", "mypassword")
}
}
$.ajax(settings)
.done(function(response){
console.log(response);
})
.error(function(err){
console.log(err);
});
I get this error
responseText: "{"code":"rest_forbidden","message":"You do not have permissions to do it.","data":{"status":401}}"
statusText: "Unauthorized"
I've tried to use "crossDomain": false but without success...
Why it's not working? How can I make it working also from local request?
Update: Thanks to your suggestions I solved by adding this header:
"X-WP-NONCE": "<?php echo wp_create_nonce( 'wp_rest' ); ?>"
Thanks a lot! :)

Posting multiple Photos to one post

I have been trying to create an application which needs multiple photos to be attached to one post. These are the following attempts i tried,
First i used facebook-node-sdk which JS SDK to achieve different functionality, but Official Js Sdk does't have option for file to upload, when then i moved to attaching/inserting photo itself to HTTP POST with the help of form-data, with the following code-
var form = new FormData();
form.append('file', fs.createReadStream(picPaths[0]));
form.append('message', "Hello"); //Put message
var ACCESS_TOKEN = "ACCESS_TOKEN";
var options = {
method: 'post',
host: 'graph.facebook.com',
path: '{Object-ID}/photos' + '?access_token=' + ACCESS_TOKEN,
headers: form.getHeaders(),
}
var request = https.request(options, function(res) {
console.log(res, false, null);
});
form.pipe(request);
request.on('error', function(error) {
console.log(error);
});
This works with one photo.
But as you can see in this github.com/Thuzi/facebook-node-sdk/issues/113 which i started, it is not possible to attach more than one photo.
So as mentioned by dantman i stated looking in batch process, which can be found developers.facebook.com/docs/graph-api/making-multiple-requests titled under Uploading binary data. The one thing that hits and give me hope is this one statement.
The attached_files property can take a comma separated list of attachment names in its value.
Note That (batching with photos) also is not possible with this library or JS SDK (Please correct me if i am wrong)
You can do post images with curl like this,
curl -F 'access_token=ACCESS_TOKEN' -F 'batch=[{"method":"POST","relative_url":"{Object-Id}/photos","body":"message=Test Post","attached_files":"file1"}]' -F 'file1=#image1' -F 'file2=#image2' https://graph.facebook.com
The above code posts with one image
So my question is this, it possible to attach multiple images/binary_files to the post with the help of curl, something like ..."attached_files":"file1,file2"... as suggested by docs, please help me with this problem and if you have already done this can you please post the snapshot of your code.
Thanks, Ravi
I finally figured out how.
So first, read the section here titled "Publishing a multi-photo post with uploaded photos": https://developers.facebook.com/docs/graph-api/reference/page/photos/#Creating
What it says is basically correct, however, it is not in JavaScript. Also, they don't emphasize enough an important step: You have to set "published" to "false" for the image you upload, for it to then be attachable to the post that gets created.
So anyway, here is the working code -- in JavaScript, and with "published" correctly set to false:
async function PostImageToFacebook(token, filename, mimeType, imageDataBlob, message) {
var fd = new FormData();
fd.append("access_token", token);
fd.append("source", imageDataBlob);
//fd.append("message", "photo message for " + filename);
fd.append("no_story", "true");
//fd.append("privacy", "SELF");
fd.append("published", "false");
// Upload image to facebook without story(post to feed)
let uploadPhotoResponse = await $.ajax({
url: "https://graph.facebook.com/me/photos?access_token=" + token,
type: "POST",
data: fd,
processData: false,
contentType: false,
cache: false
});
console.log(`Uploaded photo "${filename}": `, uploadPhotoResponse);
let uploadPhotoResponse2 = await $.ajax({
url: "https://graph.facebook.com/me/photos?access_token=" + token,
type: "POST",
data: fd,
processData: false,
contentType: false,
cache: false
});
console.log(`Uploaded photo "${filename}": `, uploadPhotoResponse2);
let makePostResponse = await $.ajax({
"async": true,
"crossDomain": true,
"url": "https://graph.facebook.com/v2.11/me/feed",
"method": "POST",
"headers": {
"cache-control": "no-cache",
"content-type": "application/x-www-form-urlencoded"
},
"data": {
"message": "Testing multi-photo post2!",
"attached_media[0]": `{"media_fbid":${uploadPhotoResponse.id}}`,
"attached_media[1]": `{"media_fbid":${uploadPhotoResponse2.id}}`,
"access_token": token
}
});
console.log(`Made post: `, makePostResponse);
}
The code above currently just uploads the same image twice, then attaches both to the new post. Obviously, in real world usage you would replace the data in the second photo-upload with a different image.
Anyway, to use the function, just call it like so:
function dataURItoBlob(dataURI) {
var byteString = atob(dataURI.split(",")[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ab], {type: "image/png"});
}
let imageDataURI = GetImageDataURIFromSomewhere();
let imageBlob = dataURItoBlob(imageDataURI);
PostImageToFacebook(fbToken, "some_filename", "image/png", imageBlob, window.location.href);
this is possible.
Note: This one is not an efficient way to do this but just for explaining purpose i am doing here,
The first hint that i got that it may be possible is from this post
Steps that i used:
Follow the doc to create custom open graph stories
Let's suppose you four image to attach (pic[1, 2, 3, 4])
First i staged them with the help of new facebook-node-sdk v1.1.0-alpha1 with the code something like this (with batch process).
FB.api( "", "post", {
batch: [
{
method: "POST",
relative_url: "me/staging_resources",
attached_files: "file1",
type:"image/png"
}, {
method: "POST",
relative_url: "me/staging_resources",
attached_files: "file2",
type:"image/png"
}, {
method: "POST",
relative_url: "me/staging_resources",
attached_files: "file3",
type:"image/png"
}, {
method: "POST",
relative_url: "me/staging_resources",
attached_files: "file4",
type:"image/png"
}],
file1: fs.createReadStream(picPaths[0]),
file2: fs.createReadStream(picPaths[1]),
file3: fs.createReadStream(picPaths[2]),
file4: fs.createReadStream(picPaths[3])
},
function(response) {
console.log(response);
});
Now from the response part get the url and dis the post with the same library. With the code something like this.
FB.api(
"me/objects/{app-namespace}:{custom-object}",
"post", {
"object": {
"og:title": "Sample Post",
"og:image[0]": {
"url": "fbstaging:{...}",
"user_generated": true
},
"og:image[1]": {
"url": "fbstaging:{...}",
"user_generated": true
},
"og:image[2]": {
"url": "fbstaging:{...}",
"user_generated": true
},
"og:image[3]": {
"url": "fbstaging:{...}",
"user_generated": true
}
}
},
function(response) {
console.log(response);
}
);
Now, with these two piece of code you will be able to push multiple images/photo to the single post.
Note: this can make more sense or can be done with the help of named batch process which is being described here.
Thanks,
Ravi

div only showing up when debugging

I got a piece of code which drives me insane.
I am loading some Data from the server which takes some time, therefore I would like to display a "loading-icon". But the icon is not showing up, so I debugged the code in Chrome and then it is working.
$(".k-loading-mask").show();
//loading the data from the server
var purchaseInvoiceItems = getOpenPurchaseInvoiceItems(id);
viewmodel.Items = ko.mapping.fromJS(purchaseInvoiceItems, {}, viewmodel.Items);
var prepaymentableOrders = getPrepaymentableOrders(id);
viewmodel.PrepaymentableOrders = ko.mapping.fromJS(prepaymentableOrders, {}, viewmodel.PrepaymentableOrders);
//loading done... hide the loading-icon.
$("div.k-loading-mask").hide();
EDIT:
function getOpenPurchaseInvoiceItems(id) {
var result = jQuery.ajax({
url: '/purchaseinvoices/getopenpurchaseinvoiceitems',
data: JSON.stringify({ supplierId: id }),
async: false,
type: 'POST',
contentType: "application/json"
});
var json = result.responseText;
var purchaseInvoiceItems = eval("(" + json + ")");
return purchaseInvoiceItems;
}
function getPrepaymentableOrders(id) {
var result = jQuery.ajax({
url: '/purchaseinvoices/getprepaymentableorders',
data: JSON.stringify({ supplierId: id }),
async: false,
type: 'POST',
contentType: "application/json"
});
var json = result.responseText;
var purchaseInvoiceItems = eval("(" + json + ")");
return purchaseInvoiceItems;
}
EDIT2
After refactoring the calls to async ajax I ran into the problem, that the done() of getOpenPurchaseInvoiceItems is never called. The done() of getPrepaymentableOrders is called when I call the function directly.
But Chrome Networkanalysis tells me the networktransaction is finished after ~3 seconds.
Maris answer is also not working for me, done() is never called.
function getOpenPurchaseInvoiceItems(id) {
$(".k-loading-mask").show();
jQuery.ajax({
url: '/purchaseinvoices/getopenpurchaseinvoiceitems',
data: JSON.stringify({ supplierId: id }),
type: 'POST',
contentType: "application/json"
}).done(function (data) { //This done is never called.
viewmodel.Items = ko.mapping.fromJS(data, {}, viewmodel.Items);
getPrepaymentableOrders(id);
});
}
//This one works like a charm when called directly
function getPrepaymentableOrders(id) {
jQuery.ajax({
url: '/purchaseinvoices/getprepaymentableorders',
data: JSON.stringify({ supplierId: id }),
type: 'POST',
contentType: "application/json",
}).done(function (data) {
viewmodel.PrepaymentableOrders = ko.mapping.fromJS(data, {}, viewmodel.PrepaymentableOrders);
$("div.k-loading-mask").hide();
});
}
EDIT 3
Added an error-callback, which actually gets fired.
status 200
statusText OK
responseText (The Json of the result-items)
I don't quiet get why the result has an error ...
Fun-Fact:
This works, and it seems that my predecessor had the same problems, because this code is a modified version of my predecessors code.
.error(function (data) {
var json = data.responseText;
var purchaseInvoiceItems = eval("(" + json + ")");
viewmodel.Items = ko.mapping.fromJS(purchaseInvoiceItems, {}, viewmodel.Items);
getPrepaymentableOrders(id);
});
Seems like the result cannot be parsed directly?!
Fiddler Response
HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Mon, 28 Sep 2015 11:29:15 GMT
X-AspNet-Version: 4.0.30319
X-AspNetMvc-Version: 3.0
Cache-Control: private, s-maxage=0
Content-Type: application/json; charset=utf-8
Content-Length: 126537
Connection: Close
[{"GoodsReceiptItemId":311360,"PurchaseOrderNumber":"BE0010018","SupplierProductNumber":"205.00-122","ProductNumber":"205.00-122","SupplierDeliveryNumber":"5503","GoodsReceiptDate":new Date(1442527200000),"Description":"001-4631-00, \"L-A-EE\"","ShouldBePayed":false,"Amount":500.00000,"Price":2.66000,"PriceUnit":1.00000,"TotalPrice":1330.00000,"PurchaseOrderId":309360,"ProductId":4792,"GoodsReceiptId":299080,"Id":0,"HasBeenSaved":false,"Errors":{"Errors":[],"HasAnyError":false,"HasSumError":false},....]
Since in the javascript there is only one thread and you are running sync calls to the api, UI is getting freezed until the requests is done. That is why you don't see the loading bar at all. So, you have to use async calls and promises to achieve what you want.
The next code should work.
function getOpenPurchaseInvoiceItems(id) {
return $.post('/purchaseinvoices/getopenpurchaseinvoiceitems', { supplierId: id });
}
function getPrepaymentableOrders(id) {
return $.post('/purchaseinvoices/getprepaymentableorders', { supplierId: id });
}
$(".k-loading-mask").show();
//loading the data from the server
var purchaseInvoiceItemsPromise = getOpenPurchaseInvoiceItems(id);
var prepaymentableOrdersPromise = getPrepaymentableOrders(id);
$.when(purchaseInvoiceItemsPromise, prepaymentableOrdersPromise ).done(function(purchaseInvoiceItems, prepaymentableOrders){
viewmodel.Items = ko.mapping.fromJS(purchaseInvoiceItems, {}, viewmodel.Items);
viewmodel.PrepaymentableOrders = ko.mapping.fromJS(prepaymentableOrders, {}, viewmodel.PrepaymentableOrders);
$("div.k-loading-mask").hide();
})
Never use the synchronous ajax calls. If you for some reason want to use synchronous calls then you definitely doing something wrong.
Try using asynchronous calls, like so:
jQuery.ajax({
url: '/purchaseinvoices/getopenpurchaseinvoiceitems',
data: JSON.stringify({ supplierId: id }),
type: 'POST',
contentType: "application/json"
}).done(function(purchaseInvoiceItems){
//.....
})
PS: never use "eval". If you're getting JSON, and the headers say that it's JSON, jquery is smart enough to transform the result to the actual object.
If however you need to convert a JSON string to object, use JSON.parse

Using Facebook's Mobile Hosting API with Parse Cloud Code for App Links

I am having trouble getting App Links working with Parse.
Since my App is mobile only i wanted to use Facebook's Mobile Hosting API.
And since you need to send your Facebook App Secret with the request i wanted to do it with Parse Cloud Code.
All i coud find on the Facebook documentation was how to do it with cURL:
curl https://graph.facebook.com/app/app_link_hosts \
-F access_token="APP_ACCESS_TOKEN" \
-F name="iOS App Link Object Example" \
-F ios=' [
{
"url" : "sharesample://story/1234",
"app_store_id" : 12345,
"app_name" : "ShareSample",
}, ]' \
-F web=' {
"should_fallback" : false, }'
so this is what i came up with in cloud code
Parse.Cloud.httpRequest({
method: 'POST',
url: 'https://graph.facebook.com/app/app_link_hosts',
headers: {
'Content-Type': 'multipart/form-data'
},
body: {
access_token : "APP_ACCESS_TOKEN",
name : "iOS App Link Object Example",
ios : '[{"url" : "sharesample://story/1234","app_store_id" : 12345,"app_name" : "ShareSample",},]',
web : '{"should_fallback" : false,}'
}
the response i get is: Request failed with response code 400
now i just read that multipart/form-data is not supported withParse.Cloud.httpRequest
so is there another way to do this?
update: just found out that you can send multipart data with a Buffer,
so this is my code now
var Buffer = require('buffer').Buffer;
var access_token = new Buffer('APP_ACCESS_TOKEN','utf8');
var name = new Buffer('iOS App Link Object Example','utf8');
var ios = new Buffer('[{"url" : "sharesample://story/1234","app_store_id" : 12345,"app_name" : "ShareSample",},]','utf8');
var web = new Buffer('{"should_fallback" : false,}','utf8');
var contentBuffer = Buffer.concat([access_token, name, ios, web]);
Parse.Cloud.httpRequest({
url: 'https://graph.facebook.com/app/app_link_hosts',
method: 'POST',
headers: {
'Content-Type': 'text/html; charset=utf-8'
},
body: contentBuffer
}
however i am still getting the same result :(
update2: got it working with content type application/x-www-form-urlencoded and normal body. But i think the error was somewhere in my parameters since i tested it with curl and got the same response
It took me a few hours, but I finally got it working:
// Returns the canonical url, like https://fb.me/....
Parse.Cloud.define("createAppLink", function(request, response) {
// see https://developers.facebook.com/docs/graph-api/reference/v2.5/app/app_link_hosts
var storyId = request.params.storyId + ''; // param identifying a single "post"
var appId = 'APP_ID';
var appSec = 'APP_SECRET';
var appToken = appId + '|' + appSec; // your app token
Parse.Cloud.httpRequest({
url: 'https://graph.facebook.com/app/app_link_hosts',
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ // you need to stringify it
access_token: appToken,
name: 'LINK TO ' + storyId, // it is needed but not public
android: [{
url: 'app://story/' + storyId, // deep link url
package: 'com.package', // your package name
app_name: 'APP' // your app name
}],
web: { should_fallback: 'false' }
})
}).then(function(httpResponse) {
// We get an id, by which we can fetch
// the canonical url with a get request
var data = JSON.parse(httpResponse.text);
var id = data.id;
return Parse.Cloud.httpRequest({
url: 'https://graph.facebook.com/' + id,
method: 'GET',
headers: {
'Content-Type': 'application/json'
},
params: {
access_token: appToken,
fields: 'canonical_url',
pretty: 'true'
}
});
}).then(function(httpResponse) {
var data = JSON.parse(httpResponse.text);
var canonicalUrl = data.canonical_url;
response.success(canonicalUrl);
}, function(error) {
response.error(error);
})
});

Categories

Resources