facebook api graph not search users - facebook

I'm trying to find users but it throws me an authentication error
import requests
from urllib.parse import urlencode
token = 'my-token'
graph_url = 'https://graph.facebook.com/v3.2/search?'
params = {
'q':'francisco',
'type':'user',
'method':'get',
'format':'json',
'access_token':token
}
url = graph_url+urlencode(params)
resp = requests.get(url)
print(resp.json())
error:
{'error': {'message': 'Unsupported operation', 'type': 'OAuthException', 'code': 100, 'fbtrace_id': 'Dao1UbelGkF'}}
It seems that something I'm not doing well or that searches are no longer allowed

https://developers.facebook.com/docs/graph-api/changelog/breaking-changes#search-4-4
Searching for users is not available anymore since 2018. It would not make any sense anyway, you would only be able to get users who authorized your App.

Related

How to fetch page list from Facebook Graph API?

I can download user events but not user managed pages. Why? What is the difference?
Using react-facebook-login to get user access token
import FacebookLogin from "react-facebook-login";
Adding Facebook login to the screen, it has the pages_show_list permission:
<FacebookLogin
appId={fbAppId}
autoLoad={true}
fields="name,email,picture"
scope="public_profile,pages_show_list"
onClick={this.componentClicked}
callback={this.responseFacebook}
And here is the handler:
responseFacebook = response => {
this.setState({
accessToken: response.accessToken,
isLoggedIn: true,
userID: response.userID,
name: response.name,
email: response.email,
picture: response.picture.data.url
});
axios.get('https://graph.facebook.com/v5.0/me/accounts&access_token='+response.accessToken)
.then(response => {
console.log("aaa " + response);
console.log("bbb ");
})
};
Second breakpoint will not be reached.
But get a lot of strange error:
Facebook API Explorer returns the data
Code is here: https://gitlab.com/j4nos/ticket-portal/blob/master/src/App.js
But get a lot oof strange error:
Focus.
The main part of importance here is that it shows that you are getting a 400 Bad Request response from the API, with that URL you tried to request there.
https://graph.facebook.com/v5.0/me/accounts&access_token=...
How does the query string portion of a URL start again ...?
Question mark, not ampersand.

Google Cloud Storage upload file to Facebook Attachment API

I have an app that I am trying to create a Facebook bot for and it needs to send photo cards to users. However, to do so I need to get a Facebook attachment_id because I can't upload my files directly from the web. (https://developers.facebook.com/docs/messenger-platform/reference/attachment-upload-api/)
My app is on Firebase, for some reason when I try the URL it gives me this error:
{
"error": {
"message": "(#546) The type of file you're trying to attach isn't allowed. Please try again with a different format.",
"type": "OAuthException",
"code": 546,
"error_subcode": 1545026,
"fbtrace_id": "H8qfi28cNvp"
}
}
That happens with any URL I try but here is a test https://memes-dev.mymemestore.com/mms-tp1pESD7hgWWLiOUziHz.jpg
So I try to use the Google Cloud Storage nodejs api to get a readstream and send that like so
const stream = gcs().bucket('my bucket').file('mms-tp1pESD7hgWWLiOUziHz.jpg').createReadStream();
const message = new formdata();
message.append('message', '{"attachment":{"type":"image", "payload":{"is_reusable":true}}}');
message.append('filedata', stream);
fetch('https://graph.facebook.com/v2.6/me/message_attachments?access_token=<PAGE ACCESS TOKEN>',
{
method: 'POST',
headers: message.getHeaders(),
body: message
})
.then(res => {
console.log(res);
return res.json();
})
.then(json => {
console.log(json);
});
but that gives me the following error
(#100) Incorrect number of files uploaded. Must upload exactly one file.
Does anyone know what is going on?
Thanks
One thing I forgot to mention was that this all had to be done serverless. But I got around it by downloading the image to a tmpdir using tmpdir = path.join(os.tmpdir(), filename) and then fs.createReadStream(tmpdir) and that is working.

How to access a secret group's posts using facebook-api?

I am a part of a secret group. I want to get all of the posts and their metadata. I use the following code:
import facebook
if __name__ == '__main__':
APP_SECRET = ""
APP_ID = ""
PAGE_ID = "" ## Page ID of the secret group
access_token = facebook.get_app_access_token(APP_ID, APP_SECRET)
graph = facebook.GraphAPI(access_token)
resp = graph.get_object('me/accounts')
page_access_token = None
for page in resp['data']:
if page['id'] == PAGE_ID:
page_access_token = page['access_token']
graph = facebook.GraphAPI(page_access_token)
but I get this error:
facebook.GraphAPIError: An active access token must be used to query information about the current user.
on line resp = graph.get_object('me/accounts').
Where am I going wrong?
The error message means that you did not authorize the user. How to do that: https://developers.facebook.com/docs/facebook-login/
/me/accounts is the endpoint to get access to pages, for groups you need the user_managed_groups permission and the /me/groups endpoint. You need to use an active User Token for that, of course.
More information: https://developers.facebook.com/docs/graph-api/reference/v2.4/user/groups

Facebook Auth with AngularJS and Django REST Framework

I am developing a SPA application with AngularJS which uses Django backend for the server. The way that I communicate with the server from the SPA is with django-rest-framework. So now I want to make authentication with facebook (google and twitter too) and I read a lot on this topic and found OAuth.io which is making the authetication on the client SPA side and python-social-auth which is doing the same thing but on the server side.
So currently I have only the client auth, my app is connecting to facebook (with OAuth.io) and login successfully. This process is returning access_token and then I am making a request to my API which have to login this user or create account for this user by given token and this part is not working. So I am not sure where I am wrong, maybe because there isn't a full tutorial about using python-social-auth so maybe I am missing something or.. I don't know..
So some code of this what I have:
On the SPA side: This is the connection with OAuth.io and is working because I am getting the access token. Then I have to make a request to my rest API. backend is 'facebook', 'google' or 'twitter'
OAuth.initialize('my-auth-code-for-oauthio');
OAuth.popup(backend, function(error, result) {
//handle error with error
//use result.access_token in your API request
var token = 'Token ' + result.access_token;
var loginPromise = $http({
method:'POST',
url: 'api-token/login/' + backend + '/',
headers: {'Authorization': token}});
loginPromise.success(function () {
console.log('Succeess');
});
loginPromise.error(function (result) {
console.log('error');
});
});
On the server in my settings.py I have added social plugin to the installed apps, template context preprocessors, some auth backends and that is my file:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
...,
'rest_framework',
'rest_framework.authtoken',
'api',
'social.apps.django_app.default',
'social'
)
TEMPLATE_CONTEXT_PROCESSORS = ("django.contrib.auth.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"django.core.context_processors.request",
"django.contrib.messages.context_processors.messages",
'social.apps.django_app.context_processors.backends',
'social.apps.django_app.context_processors.login_redirect',)
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
)
}
SOCIAL_AUTH_FACEBOOK_KEY = 'key'
SOCIAL_AUTH_FACEBOOK_SECRET = 'secret'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
AUTHENTICATION_BACKENDS = (
'social.backends.open_id.OpenIdAuth',
'social.backends.facebook.FacebookOAuth2',
'social.backends.facebook.FacebookAppOAuth',
'social.backends.google.GoogleOpenId',
'social.backends.google.GoogleOAuth2',
'social.backends.google.GoogleOAuth',
'social.backends.twitter.TwitterOAuth',
'django.contrib.auth.backends.ModelBackend',
)
In my views.py of the API I have the following (I found it here):
from django.contrib.auth.models import User, Group
from rest_framework import viewsets, generics
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, parsers, renderers
from rest_framework.authtoken.serializers import AuthTokenSerializer
from rest_framework.decorators import api_view, throttle_classes
from social.apps.django_app.utils import strategy
from rest_framework.permissions import IsAuthenticated, IsAuthenticatedOrReadOnly
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
class ObtainAuthToken(APIView):
throttle_classes = ()
permission_classes = ()
parser_classes = (parsers.FormParser, parsers.MultiPartParser, parsers.JSONParser,)
renderer_classes = (renderers.JSONRenderer,)
serializer_class = AuthTokenSerializer
model = Token
# Accept backend as a parameter and 'auth' for a login / pass
def post(self, request, backend):
serializer = self.serializer_class(data=request.DATA)
if backend == 'auth':
if serializer.is_valid():
token, created = Token.objects.get_or_create(user=serializer.object['user'])
return Response({'token': token.key})
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
# Here we call PSA to authenticate like we would if we used PSA on server side.
user = register_by_access_token(request, backend)
# If user is active we get or create the REST token and send it back with user data
if user and user.is_active:
token, created = Token.objects.get_or_create(user=user)
return Response({'id': user.id , 'name': user.username, 'userRole': 'user','token': token.key})
#strategy()
def register_by_access_token(request, backend):
backend = request.strategy.backend
user = request.user
user = backend._do_auth(
access_token=request.GET.get('access_token'),
user=user.is_authenticated() and user or None
)
return user
And finally I have these routes in urls.py:
...
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api-token-auth/', 'rest_framework.authtoken.views.obtain_auth_token'),
url(r'^api-token/login/(?P<backend>[^/]+)/$', views.ObtainAuthToken.as_view()),
url(r'^register/(?P<backend>[^/]+)/', views.register_by_access_token),
...
Everytime when I try to do auth, OAuth.io is working and the rqest to api returns
detail: "Invalid token"
I think that I missed something in the configuration of python-social-auth or I am doing everything wrong. So I will be glad if anyone has some ideas and want to help :)
Add the following line to your ObtainAuthToken class
authentication_classes = ()
and your error {"detail": "Invalid token"} will go away.
Here's why...
Your request contains the following header
Authorization: Token yourAccessToken
yet you have defined rest_framework.authentication.TokenAuthentication in DEFAULT_AUTHENTICATION_CLASSES.
Based on this Django thinks you want to perform token authentication as you have passed a Token in. It fails because this is an access token for facebook and doesn't exist in your django *_token database, hence the invalid token error. In your case all you need to do is tell Django not to use TokenAuthentication for this view.
FYI
Keep in mind you may encounter further errors as your code execution was halted before the post method of ObtainAuthToken executed. Personally when trying to step through your code I got the error
'DjangoStrategy' object has no attribute 'backend'
on
backend = request.strategy.backend
and resolved it by changing to
uri = ''
strategy = load_strategy(request)
backend = load_backend(strategy, backend, uri)
Additionally you should update your you register_by_access_token function as it doesn't line up with the working code from the blog you referenced. The blog author posted his latest code here. Your version doesn't pull the token out of the auth header which is required if you want to use it to auth with a third party like facebook.
Yea. Solved. The settings are not right and you need to add permissions.
REST_FRAMEWORK = {
# Use hyperlinked styles by default.
# Only used if the `serializer_class` attribute is not set on a view.
'DEFAULT_MODEL_SERIALIZER_CLASS':
'rest_framework.serializers.HyperlinkedModelSerializer',
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
and some info about pipeline:
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'social.pipeline.social_auth.associate_by_email',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details'
)
I'm using tools just like you, but I provide my login/register/.... with
django-allauth package, and then use django-rest-auth for API handling.
You just need follow the installation instruction, then use them for your rest APIs.
Adding allauth and rest-auth to your INSTALLED_APPS:
INSTALLED_APPS = (
...,
'rest_framework',
'rest_framework.authtoken',
'rest_auth'
...,
'allauth',
'allauth.account',
'rest_auth.registration',
...,
'allauth.socialaccount',
'allauth.socialaccount.providers.facebook',
)
Then add your custom urls:
urlpatterns = patterns('',
...,
(r'^auth/', include('rest_auth.urls')),
(r'^auth/registration/', include('rest_auth.registration.urls'))
)
Finally, add this line:
TEMPLATE_CONTEXT_PROCESSORS = (
...,
'allauth.account.context_processors.account',
'allauth.socialaccount.context_processors.socialaccount',
...
)
These two packages works like a charm, and you don't need to have concern about any type of login.registration, because allauth package handles both django model login and oAuth login.
I hope it helps

Upload video to Facebook from the server

I have a problem when uploading videos to Facebook.
I use Facebook SDK for Android: https://github.com/facebook/facebook-android-sdk to get the access token with the following permissions: "publish_stream","email","video_upload","publish_actions"
Then I send token to the server, which should upload the video. The server tries to upload video using following code:
string fullurl = string.Format("https://graph-video.facebook.com/me/videos?title={0}&description={1}&access_token={2}", HttpUtility.UrlEncode(fileName), HttpUtility.UrlEncode(description), token);
Facebook returns an error:
System.Net.WebException: The remote server returned an error: (400) Bad Request.
at System.Net.WebClient.UploadFile(Uri address, String method, String fileName)
at System.Net.WebClient.UploadFile(String address, String fileName)
But, when I check token with the following link: https://graph.facebook.com/me?access_token=myToken Facebook returns user info. That means that token is valid. But, if this request returns error code, where I can find information about error codes?
This solution works perfectly for some users, for other users it works unstable ( 4 of 6 videos uploading failed. Facebook returns that: "connection closed by remote server"). And have not worked for some users with error: "The remote server returned an error: (400) Bad Request".
What is wrong in my code?
I've solve the problem. I have start using facebook SDK for .NET http://facebooksdk.net/ and it works for me.
Facebook.FacebookClient fb = new FacebookClient(facebookEditTask.facebookToken);
fb.PostCompleted += (o, e) =>
{
if (e.Cancelled || e.Error != null)
{
return;
}
var result = e.GetResultData();
facebookVideoUrl = CreateLinkToVideo(result.ToString());
};
dynamic parameters = new ExpandoObject();
parameters.source = new FacebookMediaStream
{
ContentType = "video/mp4",
FileName = Path.GetFileName(facebookEditTask.FilePath)
}.SetValue(File.OpenRead(facebookEditTask.FilePath));
parameters.message = fbMessage;
Task t = fb.PostTaskAsync("me/videos",
new { message = fbMessage, parameters.source });