Favoriting a private track via SoundCloud API - soundcloud

Does anyone know how to favorite a track that is private using the SoundCloud API?
This is what I have so far.
SC.put('/me/favorites/1234567', function(track,error){alert(error.message)})
This works for the track when it's public, but when its private I'm getting a 404/401 error.

As long as you have access to the private track, you should be able to favorite it. Note that this means that either:
The track belongs to the currently authenticated user or..
The track was explicitly shared to the currently authenticated user
As long as either of those two conditions is met, you will be able to favorite a track. Note that of course you also must allow the user to authenticate first:
SC.initialize({
client_id: 'foo',
redirect_uri: 'http://example.com/callback.html'
});
SC.connect(function(me) {
SC.put('/me/favorites/53919056', function(response, error) {
// response.status will equal "201 - Created"
});
});

Related

Facebook Server-side Conversion Tracking

I am wondering if it is possible to track conversions based on the information Facebook provides. (FBID, #facebook.com email)
The only option I see is this
https://developers.facebook.com/docs/marketing-api/app-event-api
And I am still not sure if it would work. If I hashed the #facebook.com email that facebook provides us, would they still be able to associate that with the actual user that clicked the ad?
I am asking this question in relation to facebook message bots. At the moment the only built-in conversion tracking I see is a mutual conversation. I don't see of a way to actually track additional conversions throughout that conversation (for example a successful lead).
Little assistance please :).
Facebook recently added documentation for this
https://developers.facebook.com/docs/messenger-platform/analytics/quickstart#logging-custom-events
var request = require('request');
request.post({
url : "https://graph.facebook.com/your-app-id/activities",
form: {
event: 'CUSTOM_APP_EVENTS',
custom_events: JSON.stringify([{
_eventName: "fb_mobile_purchase",
_valueToSum: 55.22,
fb_currency: 'USD'
}]),
advertiser_tracking_enabled: 1,
application_tracking_enabled: 1,
extinfo: JSON.stringify(['mb1']),
page_id: your-page-id,
page_scoped_user_id: recipientId
}
}, function(err,httpResponse,body){
console.error(err);
console.log(httpResponse.statusCode);
console.log(body);
});
This would allow you to track a custom event, and then use that custom event ad a conversion.

Google Sign-In with Passportjs not getting authenticated

I'm using Sails with Passport for authentication. I'm using passport-google-oauth(OAuth2Strategy) and passport-facebook for enabling Google Sign-in.
I'm not too well-versed with Passport, so pardon me if this is a rookie question. I've set up login via Facebook and it works just fine. With Google, I do receive an authorization code after allowing access to the app, but the I'm eventually not authenticated. I'm guessing the same code should work for both Facebook and Google since the strategies are both based on oauth2.
I'm not even sure what code to share, since I'm using the auto-generated code from sails-generate-auth, but do let me know if there's anything else I can share.
Any ideas on why this might be happening? The app is locally hosted but that's unlikely to be the problem since I am getting to the authorization stage anyway.
I faced the same problem and it was located here in in api/services/passport.js:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
The Google service was not returning a profile.username property.
Because of it, the user is not saved in the database and cannot be authenticated. Then the passport callback receives an empty user, so the function that handles errors is fired and the user is redirected to the login page.
This change allows to use the displayName property as the username:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
/** Content not generated BEGIN */
// If the username property was empty and the profile object
// contains a property "displayName", add it to the user.
if (!user.username && profile.hasOwnProperty('displayName')) {
console.log(profile); // <= Use it to check the content given by Google about the user
user.username = profile.displayName;
}
/** Content not generated END */
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
You could also use the profile.id property because profile.displayName is not necessarily unique (ie: two Google accounts can have an identical displayName). But it is also true accross different services: a Twitter account could also have the same username than a Facebook account. If both register on your application, you will have a bug. This is a problem from the code generated by sails-generate-auth and you should adapt it with the behavior that you want.
I will propose a PR if this solution works for you too.
Alright, so this ultimately turned out to be a known issue with the API.
TL;DR: Enable the Google+ API and the Contacts API as mentioned here. (The Contacts API isn't required, as #AlexisN-o pointed out in the comments. My setup worked as desired with Contacts API disabled. This obviously depends on what scope you're using.)
I believe it's not a nice way of failing since this was an API error that was prevented from bubbling up. Anyway, I dug into passport.authenticate to figure out what was going wrong. This eventually calls the authenticate method defined in the package corresponding to the strategy (oauth2 in this case). In here (passport-google-oauth/lib/passport-google-oauth/oauth2.js) I found that the accessToken was indeed being fetched from Google, so things should be working. This indicated that there was a problem with the requests being made to the token urls. So I ventured a little further into passport-oauth2/lib/strategy.js and finally managed to log this error:
{ [InternalOAuthError: failed to fetch user profile]
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 403,
data: '{
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}],
"code": 403,
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration."
}
}'
} }
This was the end of the hunt for me and the first result for the error search led to the correct answer. Weird fix though.

Loose req.session when trying to get more FB privileges via everyauth

I've been doing user authentication with everyauth and Facebook and all works well. Now, I want to integrate an ability to post to Facebook. Since my app asks only for email scope when users first login, I'll need to get a larger FB scope, and am trying to follow the FB guidelines and only ask for this additional scope when I need it.
I added the following code to my everyauth configuration as per the docs:
everyauth
.facebook
.appId(conf.fb.appId)
.appSecret(conf.fb.appSecret)
//TODO add custom redirect for when authentication is not approved
.scope(function (req, res) {
console.log('Setting FB scope');
console.log('Session: ' + util.inspect(req.session));
var session = req.session;
switch (session.userPhase) {
case 'share-media':
return 'email,user_status';
default:
return 'email';
}
})
All is well when an unauthenticated user logs into the application. The problem is that when I want to "up the ante" on FB scope, which I do by setting req.session.userPhase to 'share-media', and then present a link to /auth/facebook to confirm they want to allow posting to FB. When this happens, I get an error that req.session is undefined from the above code (all of req is undefined).
I assume this is since a previously logged-in user is essentially re-authenticating, but isn't that how I would get more scope from Facebook? Am I going about this the wrong way?
Thanks!!!

In terms of privacy, is it acceptable to extract the user id from a Facebook share response to make use of that user's details?

Using the Facebook API, you can get back the post ID of a Facebook share, even if the user has not authorized your app.
The post ID is prefixed by your user ID, and separated by an underscore.
FB.ui({
method: 'feed',
name: 'People Argue Just to Win',
link: 'http://www.nytimes.com/2011/...',
}, function( response ){
// Response gives you :
// { post_id: "[fbUserId]_346759642059572" }
});
To me it looks like Facebook is using this programmatically, rather than with the idea of providing us the userId out of the kindness of their hearts. But it's extremely tempting to use.
I'm a little rusty on permissions - if there is a way to get back all the users that have liked/shared a specific URL, and not just a count, then this should be okay.
But the question remains, is it acceptable to use?
EDIT:
Now that I think about it, you can access the user ID by making an anonymous call to https://graph.facebook.com/[postId] but ONLY if the post was made public.
If you get a response from FB, it means that you have already ask the user for the required permissions,
so yes you can use the data returned from Facebook as you like, but you always have to inform the users how you use those data.
You can only cache user data if you have permission or it is necessary for the function of your app. Using the like button you can subscribe to edge.create and cache the response from the like.
refer to: http://developers.facebook.com/docs/reference/javascript/FB.Event.subscribe/
II. Storing and Using Data You Receive From Us
You will only request the data you need to operate your application.
You may cache data you receive through use of the Facebook API in
order to improve your application’s user experience, but you should
try to keep the data up to date. This permission does not give you any
rights to such data.
in my app i store the id of every page or user that is viewed to speed up page load times and count page views. Seems with in the scope of Policy as long as i am not sharing the info with 3rd parties or making public what a user has set to non public.

How to publish checkins for a Facebook user

I am building an iOS app using Appcelerator and the build in Facebook API module. I need to find a way to publish checkin on the behalf of the user. The user must be able to checkin at at location and / or a specific FB page. Is this possible? I can publish status messages but I cannot add a location (place).
It is possible - you need to use Facebook's Graph API, which is accessible the Titanium.Facebook.requestWithGraphPath method. This blog post describes how this is done on iOS, but the workflow is the same - although the author says that Facebook's API has changed recently, so YMMV - I couldn't find any explicit documentation in Facebook's developer resources.
To publish a checkin on behalf of the user, you need to have the “publish_checkins” extended permission granted to your app by the user
Get the latitude and longitude of your user’s device
Find a list of places near the user's location by requesting them from the Graph API
Allow the user to pick a place
Send a POST request to the Facebook Graph API with path “me/checkins” containing the PlaceID, user coordinates, and optional tags (friend IDs) and a status message
Here's how you'd request the appropriate permission from the user:
Titanium.Facebook.permissions = ['publish_checkins'];
Titanium.Facebook.authorize();
Here's an example URL that you'd use (using Titanium.Network.createHTTPClient to make a GET request) to find a list of places
https://graph.facebook.com/search?q=coffee&type=place&center=37.76,122.427&distance=1000
Then list those places in a table view, and when the user taps one, you POST to create a checkin, assuming you have the ID of the place, and its coordinates, in appropriately named variables:
var data = {
place: placeID
coordinates: {
latitude: latitude,
longitude: longitude
}
message: message,
tags: [
// tagged users (optional)
]
};
Titanium.Facebook.requestWithGraphPath('me/checkins', data, 'POST', function(e) {
if (e.success) {
alert("Success! Returned from FB: " + e.result);
} else {
if (e.error) {
alert(e.error);
} else {
alert("Unknown result");
}
}
});
You may need to tweak the properties that you send to Facebook if the API has changed, but the general approach is correct.