Facebook API - How to get user's nationality (location)? - facebook

I'm using Facebook Phonegap plugin for my mobile game project. My problem is I can't get user's location after call facebookConnectPlugin:
facebookConnectPlugin.login(["email"], function(response) {
console.log(JSON.stringify(response.authResponse.userID));
sessionStorage.setItem("userID", JSON.stringify(response.authResponse.userID));
facebookConnectPlugin.api(
"me/?fields=id,email,first_name,last_name,location", ["user_birthday"],
function(response) {
alert(JSON.stringify(response))
}, function(response) {
alert(JSON.stringify(response))
});
$state.transitionTo('app.home');
}, function(response) {
alert(JSON.stringify(response))
});
facebookConnectPlugin.js
/*
* #author Ally Ogilvie
* #copyright Wizcorp Inc. [ Incorporated Wizards ] 2014
* #file - facebookConnectPlugin.js
* #about - JavaScript interface for PhoneGap bridge to Facebook Connect SDK
*
*
*/
if (!window.cordova) {
// This should override the existing facebookConnectPlugin object created from cordova_plugins.js
var facebookConnectPlugin = {
getLoginStatus: function (s, f) {
// Try will catch errors when SDK has not been init
try {
FB.getLoginStatus(function (response) {
s(response);
});
} catch (error) {
if (!f) {
console.error(error.message);
} else {
f(error.message);
}
}
},
showDialog: function (options, s, f) {
if (!options.name) {
options.name = "";
}
if (!options.message) {
options.message = "";
}
if (!options.caption) {
options.caption = "";
}
if (!options.description) {
options.description = "";
}
if (!options.link) {
options.link = "";
}
if (!options.picture) {
options.picture = "";
}
// Try will catch errors when SDK has not been init
try {
FB.ui({
method: options.method,
message: options.message,
name: options.name,
caption: options.caption,
description: (
options.description
),
link: options.link,
picture: options.picture
},
function (response) {
if (response && response.request) {
s(response);
} else {
f(response);
}
});
} catch (error) {
if (!f) {
console.error(error.message);
} else {
f(error.message);
}
}
},
// Attach this to a UI element, this requires user interaction.
login: function (permissions, s, f) {
// JS SDK takes an object here but the native SDKs use array.
var permissionObj = {};
if (permissions && permissions.length > 0) {
permissionObj.scope = permissions.toString();
}
FB.login(function (response) {
if (response.authResponse) {
s(response);
} else {
f(response.status);
}
}, permissionObj);
},
getAccessToken: function (s, f) {
var response = FB.getAccessToken();
if (!response) {
if (!f) {
console.error("NO_TOKEN");
} else {
f("NO_TOKEN");
}
} else {
s(response);
}
},
logEvent: function (eventName, params, valueToSum, s, f) {
// AppEvents are not avaliable in JS.
s();
},
logPurchase: function (value, currency, s, f) {
// AppEvents are not avaliable in JS.
s();
},
logout: function (s, f) {
// Try will catch errors when SDK has not been init
try {
FB.logout( function (response) {
s(response);
})
} catch (error) {
if (!f) {
console.error(error.message);
} else {
f(error.message);
}
}
},
api: function (graphPath, permissions, s, f) {
// JS API does not take additional permissions
// Try will catch errors when SDK has not been init
try {
FB.api(graphPath, function (response) {
if (response.error) {
f(response);
} else {
s(response);
}
});
} catch (error) {
if (!f) {
console.error(error.message);
} else {
f(error.message);
}
}
},
// Browser wrapper API ONLY
browserInit: function (appId, version) {
if (!version) {
version = "v2.0";
}
FB.init({
appId : appId,
cookie : true,
xfbml : true,
version : version
})
}
};
// Bake in the JS SDK
(function () {
console.log("launching FB SDK")
var e = document.createElement('script');
e.src = document.location.protocol + '//connect.facebook.net/en_US/sdk.js';
e.async = true;
document.getElementById('fb-root').appendChild(e);
}());
}

You don't ask for the appropriate permission user_location, and if you don't, you can't get access to the data. That's plain simple.
See https://developers.facebook.com/docs/graph-api/reference/v2.1/user/#readperms

Related

Problem with facebook login from the facebook application

I also encounter a problem with a project, login with facebook works on absolutely any browser, even those on mobile, but in the integrated browser in the facebook application it doesn't work, it just doesn't connect me, it sends me back to login ... can you help me with a piece of advice please? Thank you.
I used this script:
<script>
(function(){
var body = $('body');
var socialLoginErrorElm = $('#loginError');
var loginModal = $('#loginModal');
body.on('social-login:error', function(e, error) {
socialLoginErrorElm.removeClass('hide').html('<div class="alert alert-danger">' + error + '</div>');
loginModal.removeClass("logging-in");
});
window.loginWithFb = function(){
FB.login(function(response) {
if (response.authResponse) {
if(response.authResponse.grantedScopes.split(',').indexOf('email') < 0) {
//If email permission not granted
body.trigger('social-login:error', (__('fbNoEmailError')));
return;
}
FB.api('/me', {fields: 'id,name,email'}, function(response) {
console.log('Logged in as ' + response.name + '.');
//Dual check email - needed to if check if the user has a verified email ID
if(!response.email) {
body.trigger('social-login:error', (__('fbNoEmailError')));
return;
}
body.trigger('loggedIn:fb');
});
} else {
body.trigger('social-login:error', (__('fbPermissionError')));
}
}, {
scope: 'email',
auth_type: 'rerequest',
'return_scopes': true
});
}
var body = $('body');
body.on('click', '[data-action="loginWithFB"]', function(e){
loginWithFb();
e.preventDefault();
});
body.on('loggedIn', function(){
loginModal.modal('hide');
});
body.on('loggedIn:fb', function(){
if(!User.isLoggedIn()) {
$.get(BASE_PATH + '/login/fb').success(function(response){
User.setData(response.user);
}).fail(function(jqXHR, textStatus, errorThrown){
body.trigger('social-login:error', jqXHR.responseText);
}).always(function(){
loginModal.removeClass("logging-in");
});
}
});
body.on('prompt-login', function(e, message){
loginModal.find('.login-prompt-message').html(message);
loginModal.modal('show');
});
})();
function showNewPointsAlert(addedPoints) {
var alertOptions = {
title: "+"+ addedPoints +" " + __('points'),
text: __('earnedNewPointsMessage'),
imageUrl: "{{LeaderboardHelpers::getPointsIcon()}}",
confirmButtonText: __('earnedNewPointsOkayBtnText'),
allowEscapeKey: true,
allowOutsideClick: true,
customClass: 'new-points-alert'
}
#if(!empty($mainBtnColor))
alertOptions.confirmButtonColor = '{{{$mainBtnColor}}}';
#endif
swal(alertOptions);
}
$('body').on('user-activity-recorded', function() {
$.get('{{route('getMyPoints')}}').success(function(response) {
if(response && response.points) {
var oldPoints = parseInt(User.data.points);
var newPoints = parseInt(response.points);
User.data.points = newPoints;
User.setData(User.data);
if(oldPoints != newPoints) {
var animateClass = 'animated bounceIn';
$('#headerUserMenu').removeClass(animateClass).addClass(animateClass);
var addedPoints = parseInt(newPoints) - parseInt(oldPoints);
#if(MyConfig::isTrue('leaderboard.showNewPointsAlert'))
showNewPointsAlert(addedPoints);
#endif
}
}
}).fail(function() {
});
});
</script>

Callback is not a function NODEJS

I am trying learn nodejs and stumble upon this error
callback(null, removed);
TypeError: callback is not a function
It is a Steam trade bot, so when it send me an offer, I accept it but after that it crashes. What is wrong?
exports.removeOweNoTitle = (user, callback) => {
let file = 'data/users/' + user + '.json';
if(fs.existsSync(file)) {
let read = fs.createReadStream(file);
let data = "";
read.on('data', (chunk) => {
data += chunk;
});
read.on('end', () => {
let json;
try {
json = JSON.parse(data);
} catch(error) {
return callback(error);
}
let owe = {};
if(json.owe)
owe = json.owe;
else {
callback(null, 0);
return;
}
let removed = 0;
for(let game in owe) {
if(owe[game]) {
removed += owe[game];
owe[game] = 0;
}
}
let write = fs.createWriteStream(file, {flags: 'w'});
exports.clearNotifications(user, () => {
write.write(JSON.stringify(json), (error) => {
if(error)
return callback(error);
write.end();
});
return;
});
write.write(JSON.stringify(json), (error) => {
if(error)
return callback(error);
write.end();
});
write.on("finish", (callback, error) => {
callback(null, removed); //tady nebyl deklarován callback chyběl
});
});
} else {
generateUserFile(user);
callback(new Error('User\'s file is not defined!'), null);
}
}

react-native-fbsdk - how to get user profile?

onLoginFinished's result just tells me the granted permissions. From the repo, not clear how to get the user profile. Seems like react-native-fbsdkcore should wrap FBSDKProfile.h but don't see where it does.
var FBSDKLogin = require('react-native-fbsdklogin');
var {
FBSDKLoginButton,
} = FBSDKLogin;
var Login = React.createClass({
render: function() {
return (
<View>
<FBSDKLoginButton
onLoginFinished={(error, result) => {
if (error) {
alert('Error logging in.');
} else {
if (result.isCanceled) {
alert('Login cancelled.');
} else {
alert('Logged in.');
}
}
}}
onLogoutFinished={() => alert('Logged out.')}
readPermissions={[]}
publishPermissions={['publish_actions']}/>
</View>
);
}
});
Found out you can get logged in user's profile with Graph API.
// Create a graph request asking for user's profile
var fetchProfileRequest = new FBSDKGraphRequest((error, result) => {
if (error) {
alert('Error making request.');
} else {
// Data from request is in result
}
}, '/me');
// Start the graph request.
fetchProfileRequest.start();
There is an easier way to do it. Rather than manually making the graph request yourself, 'react-native-fbsdkcore' package to get the data associated with the logged in user (if there is one)
var
FBSDKCore = require('react-native-fbsdkcore');
var {
FBSDKAccessToken,
} = FBSDKCore;
FBSDKAccessToken.getCurrentAccessToken((token) => {
// token will be null if no user is logged in,
// or will contain the data associated with the logged in user
});
cphackm address is that in this issue #2
Using #flow, here is a full example:
FbLogin.js
// #flow
import * as React from 'react';
import { View } from 'react-native';
import { LoginButton, AccessToken } from 'react-native-fbsdk';
import { FbService } from '#services';
import { toast } from '#libs/helpers';
type LoginResult = {
isCancelled: boolean,
grantedPermissions?: Array<string>,
declinedPermissions?: Array<string>
};
type Props = {
store: {
Account: Object
}
};
type State = {
token?: string
};
export default class Login extends React.Component<Props, State> {
componentDidMount() {
AccessToken.getCurrentAccessToken().then(tokenData => {
if (tokenData) {
console.log('[-- tokenData --]', tokenData);
const { accessToken, userID } = tokenData;
if (accessToken) {
console.log('[-- accessToken, userID --]', accessToken, userID);
this.setState({ token: accessToken });
// this._getUserInformation();
}
}
});
}
_getUserInformation = () => {
const { token } = this.state;
const { Account } = this.props.store;
if (token) {
FbService.getFbUserData(token, (error, result) => {
if (error) {
console.log('[-- error --]', error);
} else {
Account.provider = 'facebook';
Account.authorized = true;
Account.current = { password: '', token, ...result };
console.log('[-- responseFbUserData --]', result);
}
});
}
};
render() {
return (
<View>
<LoginButton
readPermissions={['public_profile']}
onLoginFinished={(error: Object, result: LoginResult) => {
if (error) {
alert('Login failed with error: ' + error.toString());
} else if (result.isCancelled) {
alert('Login was cancelled');
} else {
if (result) {
this._getUserInformation();
}
}
}}
onLogoutFinished={() => toast('User logged out', 'info')}
/>
</View>
);
}
}
/* AccessToken
accessToken: string,
applicationID: string,
userID: string,
permissions: Array<string>,
declinedPermissions: Array<string>,
accessTokenSource?: string,
expirationTime: number,
lastRefreshTime: number,
*/
FbService.js
// #flow
import * as React from 'react';
import { GraphRequestManager, GraphRequest, AccessToken } from 'react-native-fbsdk';
export function getFbUserData(token: string, callBack: Function) {
const profileRequestConfig = {
httpMethod: 'GET',
version: 'v2.12',
parameters: {
fields: {
string: 'id, name, email'
}
},
accessToken: token
};
const profileRequest = new GraphRequest('/me', profileRequestConfig, callBack);
new GraphRequestManager().addRequest(profileRequest).start();
}

hash format error! using routing

I have developed an OpenUI5 app ant it works fine!
But every time that I invoke the routing I have this message:
2015-07-15 16:15:45 hash format error! The current Hash: /line/01 -
log
error
onHashChange
detectHashChange
jQuery.event.dispatch
jQuery.event.add.elemData.handle
It is not a blocking problem but it is annoying because it dirty and fills thi debug console..!
To call the router I write:
this.router = sap.ui.core.UIComponent.getRouterFor(this);
this.router.navTo("activities", {
"id_line": '01'
});
and this is the routing file:
routes: [
...
{
pattern: "line/{id_line}",
name: "activities",
target: ["master_search", "detail_activities"]
},
...
],
targets: {
master_search: {
viewName: "UniversalMenu",
viewLevel: 1,
controlAggregation: "masterPages"
}
,
detail_activities: {
viewName: "DetailActivity",
viewLevel: 4
}
...
}
Edit: this is a snippet where I use jQuery.sap.history
jQuery.sap.require("jquery.sap.history");
jQuery.sap.require("sap.m.InstanceManager");
sap.ui.controller("ui5bp.view.App", {
getDefaultPage : function () {
return "Menu";
},
onInit : function () {
var historyDefaultHandler = function (navType) {
if (navType === jQuery.sap.history.NavType.Back) {
//this.navBack(this.getDefaultPage());
} else {
this.navTo(this.getDefaultPage(), null, false);
}
};
var historyPageHandler = function (params, navType) {
if (!params || !params.id) {
jQuery.sap.log.error("invalid parameter: " + params);
} else {
if (navType === jQuery.sap.history.NavType.Back) {
this.navBack(params.id);
} else {
this.navTo(params.id, params.data, false);
}
}
};
jQuery.sap.history({
routes: [{
// This handler is executed when you navigate back to the history state on the path "page"
path : "page",
handler : jQuery.proxy(historyPageHandler, this)
}],
// The default handler is executed when you navigate back to the history state with an empty hash
defaultHandler: jQuery.proxy(historyDefaultHandler, this)
});
// subscribe to event bus
var bus = sap.ui.getCore().getEventBus();
bus.subscribe("nav", "to", this.navHandler, this);
bus.subscribe("nav", "back", this.navHandler, this);
bus.subscribe("nav", "virtual", this.navHandler, this);
},
navHandler: function (channelId, eventId, data) {
if (eventId === "to") {
this.navTo(data.id, data.data, true);
} else if (eventId === "back") {
//**************************************************
// if(data && data.id){
// this.navBack(data.id);
// } else {
// jQuery.sap.history.back();
// }
var app = this.getView().app;
if(data.type==="master"){
app.backMaster();
}else if(data.type==="detail"){
app.backDetail();
}else{alert("back to master o detail?");};
//**************************************************
} else if (eventId === "virtual") {
jQuery.sap.history.addVirtualHistory();
} else {
jQuery.sap.log.error("'nav' event cannot be processed. There's no handler registered for event with id: " + eventId);
}
},
navTo : function (id, data, writeHistory) {
if (id === undefined) {
// invalid parameter
jQuery.sap.log.error("navTo failed due to missing id");
} else {
var app = this.getView().app;
// navigate in the app control
app.to(id, "slide", data);
}
},
/*
navBack : function (id) {
if (!id) {
// invalid parameter
jQuery.sap.log.error("navBack - parameters id must be given");
} else {
// close open popovers
if (sap.m.InstanceManager.hasOpenPopover()) {
sap.m.InstanceManager.closeAllPopovers();
}
// close open dialogs
if (sap.m.InstanceManager.hasOpenDialog()) {
sap.m.InstanceManager.closeAllDialogs();
jQuery.sap.log.info("navBack - closed dialog(s)");
}
// ... and navigate back
var app = this.getView().app;
var currentId = (app.getCurrentPage()) ? app.getCurrentPage().getId() : null;
if (currentId !== id) {
app.backToPage(id);
jQuery.sap.log.info("navBack - back to page: " + id);
}
}
}
*/
});
In Component.js I had 2 rows where I set up custom myNavBack and myNavToWithoutHash functions:
// 3a. monkey patch the router
var oRouter = this.getRouter();
oRouter.myNavBack = ui5bp.MyRouter.myNavBack; //to comment
oRouter.myNavToWithoutHash = ui5bp.MyRouter.myNavToWithoutHash; //to comment
I have started from an example of app skeleton for my app and then I have implemented the routing with the logic suggested from the framework.
This coexistence of two different methods to navigate produced the error in console. Tahnkyou #TimGerlach
After the comment of the two rows errors have vanished.

smart way to rewrite this function

I have this, and I am showing a div if user clicked one button and not showing it if the user clicked other. Its working but its dumb to do this way with repeatition
$j(document).ready(function() {
$j('#Button1').click( function () {
var data = $j("form").serialize();
$j.post('file.php', data, function(response){
$j("#Response").show();
});
});
$j('#Button21').click( function () {
var data = $j("form").serialize();
$j.post('file.php', data, function(response){
//do something else
});
});
});
I'd do it by adding a class to the selected buttons and then pull the event.target id from the click function:
$j('.buttons').click(function(e) {
var buttonId = e.target.id,
data = $j("form").serialize();
$j.post('file.php', data, function(response) {
switch (buttonId) {
case "Button1":
$j("#Response").show();
break;
case "Button21":
//do something else
break;
}
});
});
You need to abstract the data from the functionality.
sendClick('#Button1', function() {
$j('#Response').show();
});
sendClick('#Button21', function() {
// do something
});
sendClick function
function sendClick(selector, callback)
{
$j(selector).click( function () {
var data = $j("form").serialize();
$j.post('file.php', data, callback);
});
}
This way you can repeat the same functionality over and over by changing the selector and the callback. You could customise this even further by:
function sendClick(selector, options, callback)
{
// handle arguments
if(typeof options == 'function') {
callback = options;
options = {};
} else {
options = options || {};
}
$j.extend({
form: 'form',
file: 'file.php'
}, options);
// abstracted logic
$j(selector).click(function() {
var data = $j(options.form).serialize();
$j.post(options.file, data, callback);
});
}
then use like
sendClick('#select', {form: '#anotherForm'}, function() {
// do something
});
or
sendClick('#another', function(response) {
// something else
});
You can attach the event to both, and then, when you need to check which element triggered the event, use event.target.
$j(function() {
$j('#Button1, #Button2').click( function (event) {
var data = $j("form").serialize();
$j.post('file.php', data, function(response){
if ($(event.target).is('#Button1')) {
$j("#Response").show();
} else {
// Do something else
}
});
});
});
Here are two different ways:
You can combine the two handlers into one handler:
$j(document).ready(function () {
$j('#Button1, #Button21').click(function() {
var id = this.id;
var data = $j("form").serialize();
$j.post('file.php', data, function(response) {
if (id == 'Button1') {
// Show
} else {
// Do something else
}
});
});
});
Or write a special kind of handler:
$j.fn.clickAndPost = function (handler) {
this.click(function () {
var me = this;
var data = $j("form").serialize();
$j.post('file.php', data, function(response) {
handler.call(me);
});
});
});
...and attach two of them:
$j(document).ready(function () {
$j('#Button1').clickAndPost(function () {
// Show
});
$j('#Button21').clickAndPost(function () {
// Do something else
});
});
$j(function($) {
$('#Button1', '#Button21').click(function() {
var that = this,
data = $('form').serialize();
$.post('file.php', data, function(response) {
if ( that.id === 'Button1' ) {
$('#Response').show();
} else {
//do something else
}
});
});
});
$(document).ready(function() {
$('#Button1 #Button21').click(function() {
var that = this.attr("id");
data = $('form').serialize();
$.post('file.php', data, function(response) {
if ( that === 'Button1' ) {
$('#Response').show();
} else {
//do something else
}
});
});
});
Let me know if it's not working.