FaceBook API: Get the Request Object for a request Id - logged into the account that sent the request. Using the "Requests Dialog" API - facebook

I am using the "Requests Dialog" to create Facebook requests. Inorder to get the user that the requests were sent to I need to access the Request object using the graph API. I have tried most of the permissions settings that seemed appropriate (read_requests and user_about_me) to get the request object, but instead I get a false in the response. Am I using the wrong permissions?
I am able to access the request object using the graph API from the account that the request was sent to.
http://developers.facebook.com/docs/reference/dialogs/requests/
Return Data - A comma-separated list
of the request_ids that were created.
To learn who the requests were sent
to, you should loop through the
information for each request object
identified by a request id.

I've been asking myself this question a while ago:
How to retrieve all the requests sent by me?
The answer: you can't!
You have two options:
Store the request_id returned when the user sent the request, so you can later access them and get the data you need
Knowing the receiver!
Proof of the above, you can check the friend_request table. The indexable field is the uid_to field!

This is if you want it in know Iframe mode as you don't need Iframe mode any more
function sendRequest() {
FB.ui({
method: 'apprequests',
title: 'Invite friends to join you',
message: 'Come play with me.'
},
function (res) {
if (res && res.request_ids) {
var requests = res.request_ids.join(',');
$.post('FBRequest.ashx',
{ request_ids: requests },
function (resp) { });
}
});
return false;
}

If you want to find out the user ids of the people you just sent a request to. Then this code is what you need:
var request = {
message: msg,
method: 'apprequests',
title: 'Select some of your friends'
};
FB.ui(request, function (data) {
if (data && data.request_ids) {
// Get the uid of the person(s) who was/were invited
var uids = new Array();
FB.api("/?ids=" + data.request_ids.join(), function(data2) {
for (i = 0; i<data.request_ids.length; i++) {
uids[i] = data2[data.request_ids[i]]['to']['id'];
}
# do something with uids here
});
}
});

Don't know if this helps, but here's how I handle it.
Javascript:
function sendRequest() {
FB.ui({
display: 'iframe',
method: 'apprequests',
title: 'Invite friends to join you',
message: 'Come play with me.'
},
function (res) {
if (res && res.request_ids) {
var requests = res.request_ids.join(',');
$.post('FBRequest.ashx',
{ request_ids: requests },
function (resp) { });
}
});
return false;
}
Server side (FBRequest.ashx):
// get operation and data
var ids = HttpContext.Current.Request["request_ids"];
// if we have data
if(ids != null) {
// make batch graph request for request details
var requestIds = ids.Split(',').Select(i => long.Parse(i)).ToList();
var fbApp = new FacebookWebClient([AppId],[AppSecret]);
dynamic parameters = new ExpandoObject();
parameters.ids = ids;
dynamic requests = fbApp.Get(parameters);
// cycle through graph results and do stuff
dynamic req = null;
for(int i=0;i<requestIds.Count;i++) {
try {
req = requests[requestIds[i].ToString()];
// do stuff with request, save to DB, etc.
} catch (Exception ex) {
// error in finding request, continue...
}
}
}

You can access the list of user id's as part of the return data
FB.ui({
method: 'apprequest',
message: 'Use this thing',
}, function(result){
//a list of ids are in here
result.to;
});

Related

Google Action Webhook Inline Editor Returns Before the API call

This is my first Google Action project. I have a simple slot after the invocation. User enters the value on prompt and slot invokes the webhook and make a call to API using the user input. All works fine. However the webhook returns to users even before the API call finish processing and returns the value (line 1 conv.add). I do see in the logs that everything from API is logged fine after the webhook returns to user. Below is the code I am using. I am using inline editor. What am I missing? Thanks for help in advance.
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
var https = require('https');
const fetch = require('node-fetch');
const app = conversation({debug: true});
app.handle('SearchData', conv => {
const body = JSON.stringify({
val: "this is my body"
});
// prepare the header
var postheaders = {
'Content-Type' : 'application/json',
'Auth' : 'MyAuthCreds'
};
fetch('https://host.domain.com/data', {
method: 'post',
body: body,
headers: postheaders,
})
.then(res => res.json())
.then(d => {
console.log(d);
var profile = d;//JSON.parse(d);
console.log(d.entries);
console.log("Length: "+ d.entries.length);
if(d.entries.length > 0)
{
console.log("Data found");
conv.add("Data found"); //line 1
}
else
{
console.log("no data found");
conv.add("no data found"); //line 1
}
})
.catch(function (err) {
// POST failed...
console.log(err);
});
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
Your issue is that your handler is making API calls which are asynchronous, but the Assistant Conversation library doesn't know that you're doing so. So as soon as the handler finishes, it tries to send back a response, but your asynchronous responses (the stuff in the then() blocks) haven't executed yet.
To address this, you need to return a Promise object so the library knows to wait till the Promise is fulfilled before it returns.
Fortunately, in your case, this should be pretty straightforward. fetch and all the .then() blocks return a Promise. So all you need to do is add a return statement in front of the call to fetch. So something like this:
return fetch('https://host.domain.com/data', {

Add a user manually on server side and set their session

I can't seem to understand the relation between Accounts.createUser() and Accounts.onCreateUser(). I have an external api that validates the users' login credentials. Once the api sends me a positive response, I need to add the user in MongoDB and start its session so it can be considered as a logged in user. Accounts.createUser() is creating a user on server side, but I need Accounts.onCreateUser() because I need to add custom fields like user's token that is being generated from the external api.
This is the code I have right now (which doesn't add a user at all):
server-side code:
var request = {
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
},
'params': user
};
try {
var response = HTTP.call('POST', url, request); //send call to the external api
var token = response.data.token;
//decode the token and add the user in the database
var userInfo = Base64.decode(token.split('.')[1]);
var options = {
email: user._username,
profile: {
name: user._username
},
token: token
};
var user = Accounts.onCreateUser(function(options, user) {
if (options.token)
user.token = options.token;
if (options.profile)
user.profile = options.profile;
return user;
});
console.log(user); //this returns undefined
return JSON.stringify({
'code': 200,
'token': userInfo
});
} catch (error) {
console.log(error);
//console.log(error.response);
var body = error.response.content;
return body;
}
Okay. So I finally found what I had been looking for. The relation between Accounts.createUser and Accounts.onCreateUser is that Accounts.onCreateUser is a hook and adds extended functionality to the original Accounts.createUser function. What is the extended functionality? It lets you create additional fields prior to actually inserting your user in the database. You have to write this hook in your main.js (server side) in the startup code snippet:
Meteor.startup(() => {
Accounts.onCreateUser(function(options, user) {
if (options.token)
user.token = options.token;
if (options.profile)
user.profile = options.profile;
return user;
});
})
And wherever you want to add the user, simply call Accounts.createUser() and this hook will be called automatically prior to the createUser call

Facebook api multiple request

I am creating a facebook application generator. And I need to check if the user has currently added the application on this facebook page or not.
In order to do that, i first request facebook api to give a list of his pages. Then i loop through all the pages. And request for apps on each of these pages.
Lastly i compare the appId with the one user just created and displays the display the warning accordingly.
The problem is , when i loop through each of the pageId and request FbApi for subpages, the request response is delayed and the for each loop completes its cycle before the results are fetched from facebook.
Here is my code, which is quite complex... Any ideas to fix the issue is highly appreciated.
FB.login(function (response) {
FB.api('/me/accounts', function (apiresponse) {
var totalPages = apiresponse.data.length;
var pageIndex = 0;
$.each(apiresponse.data, function (pageNumber, pageData) {
var pageAccessToken = pageData.access_token;
var tabPageName = pageData.name;
var tabPageId = pageData.id;
FB.api("/" + tabPageId + "/tabs", function (response) {
var foundApp = false
$.each(response.data, function (index, value) {
var exsistingAppId = (value.id).split("app_").pop();
if (exsistingAppId == fbAppId) {
foundApp = true;
}
});
if (foundApp === true) {
var data = {
PageId: tabPageId,
Url: window.location.href.split("/").pop()
}
$.ajax({
type: "POST",
url: '/facebook/Match',
contentType: "application/json",
data: JSON.stringify(data),
success: function (data) {
if (data == "True") {
$("#addToFacebookModal ul").append("<li><span class='pageTab'><a class='pageTabName' target='_blank' href='https://facebook.com/profile.php?id=" +tabPageId + "'>" +tabPageName + "</a></span><a class='deleteAppFromPageTab' data-id='" +tabPageId + "' data-accessToken='" +pageAccessToken + "'>[x]</a></li>");
alreadyAdded.push(true);
} else {
alreadyAdded.push(false);
}
pageIndex++;
if (pageIndex == totalPages) {
console.log("Total Pages = " + totalPages + ", Looped through = " + alreadyAdded.length);
if (alreadyAdded.indexOf(true) >= 0) {
$("#addToFacebookModal").modal();
} else {
addToFacebook();
}
}
}
});
}
else {
pageIndex++;
}
});
});
});
}, { scope: 'manage_pages' });
Here is pseudocode of what i am doing
var myVariable
-Fb.Api Callback function returns response array
-Loop through the response array
-Get new Response array based on the previous response in that array
-Loop through each item of the new response array and compare it with myVariable.
The problem is that responses are delayed while the loop finishes up before the responses arrive. As i result i cant compare the nested Item with myVariable.
If by "facebook page" you mean a business page / organization page (not a profile), you can get the same information more easily by checking the endpoint '/{{page_id}}/tabs/{{app_id}}.
Replace page_id with the ID of the page you want to check and app_id similarly with your app ID. I don't have working code at the moment, but something like this:
FB.api(
'/' + checkPageID + '/tabs/{{app_id}}',
function (response) {
// Do console.log(response) to figure out how to see if installed or not
}
)
YOu can use fields expansion:
https://developers.facebook.com/docs/graph-api/using-graph-api/v2.3#fieldexpansion
FB.api('/me/accounts', {fields: 'name, address{city}'},function (response)
{
//do something here.
}

fb 'apprequests' redirect to new url or send additional parameter to url

I need to pass additional parameter to redirect url when the user accept fb app request or need to redirect user to a custom url. How can I do this?...Please see the following code.
$('#sendRequest').click(function() {
FB.ui(
{
method : 'apprequests',
message : $(this).attr('data-message')
},
function (response) {
// If response is null the user canceled the dialog
if (response != null) {
logResponse(response);
}
}
);
});
I have used "data" parameter to send information while sending the request and accessed it in the other end using the "request id".
$('#sendRequest').click(function() {
FB.ui(
{
method : 'apprequests',
message : $(this).attr('data-message'),
data: sessionId,
max_recipients:1
},
function (response) {
// If response is null the user canceled the dialog
if (response != null) {
logResponse(response);
}
}
);
});
There is nothing that you can add in the code you’ve shown.
If you need to combine any data with a request, than you’ll have to save this data to your own database, so you can look it up again when receiving the request id(s) send to you when a user accepts requests.

How should I retrieve original pictures included with the Facebook posts?

My application uses the Facebook Javascript SDK to add wall posts to the feed of a community's page, and to retrieve them again. Pictures included with the posts are processed and placed somewhere on the Facebook servers.
When these posts are retrieved the links to the pictures turn out to be links pointing to the fbcdn.net server.
Is there a way to access the original links?
Update:
Here is my code posting a post:
// The "params" variable contains a field called "picture"
// (which is a link pointing to my picture)
FB.addWallPost = function (params, pageId, token, complete) {
var fbApiParams = {
access_token: token
};
$.extend(fbApiParams, params);
FB.api(pageId + '/feed', 'post', fbApiParams, function (response) {
// FB.apiCallDone is a function checking if there's any positive response
if (FB.apiCallDone(response)) {
complete(response.id);
}
else {
complete(null);
}
});
}
And these lines retrieve the posts:
FB.getWallPosts = function (wallPostsIds, token, complete) {
if (wallPostsIds && wallPostsIds != null && wallPostsIds.length) {
var wallPostsIdsStr = wallPostsIds.join(',');
var fbApiParams = {
ids: wallPostsIdsStr,
access_token: token
};
FB.api('/', fbApiParams, function (response) {
if (FB.apiCallDone(response)) {
var wallPosts = dictElemsToArr(response);
complete(wallPosts);
}
else {
complete([]);
}
});
}
else {
complete([]);
}
}
If you're posting pictures to Facebook, they will be stored locally by Facebook.
It is up to your application to store the path of the original images if your application requires this information.