GithubHelp home page GithubHelp logo

jgorset / facepy Goto Github PK

View Code? Open in Web Editor NEW
863.0 56.0 203.0 415 KB

Facepy makes it really easy to use Facebook's Graph API with Python

License: MIT License

Makefile 0.85% Python 99.15%
facebook graph api-client python

facepy's Introduction

https://raw.githubusercontent.com/jgorset/facepy/master/docs/banner.png

version pythons downloads build license

Usage

from facepy import GraphAPI

# Initialize the Graph API with a valid access token (optional,
# but will allow you to do all sorts of fun stuff).
graph = GraphAPI(oauth_access_token)

# Get my latest posts
graph.get('me/posts')

# Post a photo of a parrot
graph.post(
    path = 'me/photos',
    source = open('parrot.jpg', 'rb')
)

Facepy can do more than reading your latest posts and posting photographs of parrots, but you'll have to read the documentation to find out how.

Please note that Facepy does not do authentication with Facebook; it only consumes its API. To get an access token to consume the API on behalf of a user, use a suitable OAuth library for your platform (if you're using Django, for example, you might use Fandjango).

Installation

$ pip install facepy

Contribute

  • Fork the repository.
  • Do your thing (preferably on a feature branch).
  • Write a test that demonstrates that the bug was fixed or the feature works as expected.
  • Send a pull request and bug me until I merge it!

I love you

Johannes Gorset made this. You should tweet me if you can't get it to work. In fact, you should tweet me anyway.

I love Schibsted

I work at Schibsted Products & Technology with a bunch of awesome folks who are every bit as passionate about building things as I am. If you're using Facepy, we probably want to hire you.

facepy's People

Contributors

abulte avatar adefossez avatar cpickett avatar epalakovichcarr avatar gerardo-orozco avatar hargup avatar honzajavorek avatar itbabu avatar jgorset avatar jjmaestro avatar kevinjdolan avatar madssj avatar maraujop avatar mattbillenstein avatar merwok avatar mgalgs avatar mittenchops avatar msabramo avatar nagyv avatar paulgb avatar pazur avatar pirsquare avatar princearora111 avatar reikje avatar richid avatar simon-weber avatar thelinuxkid avatar tijs avatar timkurvers avatar tomwys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

facepy's Issues

Easier way to create a GraphAPI client with app access token

I find it a little bothersome to import and call a function to instantiate a GraphAPI client with an app access token.

What do you think about adding an alternate constructor in the form of a class method GraphAPI.with_app_token(app_id, app_secret_key)?

Test suite should use facebook test users

The test suite should create a new test user upon startup as to avoid false errors from facebooks rate-limiting Error: (#341) Feed action request limit reached.

I've already done this a couple of times on a different project, and would like to take a stab at it.

Python3 support?

Hi,

I'm getting an error when installing facepy on py3k

Downloading/unpacking facepy (from django-fairepart==0.1)
  Downloading facepy-0.8.4.tar.gz
  Running setup.py egg_info for package facepy
    Traceback (most recent call last):
      File "<string>", line 16, in <module>
      File "/Users/thoas/Sites/Python/Ulule/django-fairepart/.tox/py33-1.6.X/build/facepy/setup.py", line 10, in <module>
        execfile('facepy/version.py')
    NameError: name 'execfile' is not defined
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 16, in <module>

  File "/Users/thoas/Sites/Python/Ulule/django-fairepart/.tox/py33-1.6.X/build/facepy/setup.py", line 10, in <module>

    execfile('facepy/version.py')

NameError: name 'execfile' is not defined

I have seen you have added py3k support by removing version.py, do you have released a new version on PyPi yet?

Thank you.

requests installed as dependency?

I was wondering if requests should not be installed as a dependency of facepy automatically? Currently when i do 'pip install facepy' it does not install requests and fandjango (which i use facepy with) gives an could not load facepy error.

ERROR Failed to post link: (#100) Missing message or attachment

I'm trying to post a few links at a time using the batch feature but i'm running into an error declaring i'm missing the message part of the link (at least that's what i think the error means).

ERROR Failed to post link: (#100) Missing message or attachment

My batch looks like this:

      for id in friends.split(','):
        r = {
            'method': 'POST',
            'relative_url': '%d/feed' % int(id),
            'body': {
                'link': link,
                'message': message
            }
        }

        requests.append(r)

    batch = graph.batch(requests)

that looks fine to me but perhaps i'm missing something.

TypeError while using batch request to POST

even pulling the standard example from facebook API documentations on batch requests - still gives the TypeError.

api.batch([{ "method":"POST", "name":"first", "relative_url":"me/feed", "body":"message=Test status update"},{"method":"GET","depends_on":"first", "relative_url":"me/feed?limit=1"}])

with type error traceback:

TypeError                                 Traceback (most recent call last)
<ipython-input-98-9094d6b71ed7> in <module>()
----> 1 x,y = graph.batch([{ "method":"POST", "name":"first", "relative_url":"me/feed", "body":"message=Test status update"},{"method":"GET","depends_on":"first", "relative_url":"me/feed?limit=1"}])

/usr/local/lib/python2.7/dist-packages/facepy/graph_api.pyc in batch(self, requests)
    129         for request in requests:
    130             if 'body' in request:
--> 131                 request['body'] = urlencode(request['body'])
    132 
    133         responses = self.post(

/usr/lib/python2.7/urllib.pyc in urlencode(query, doseq)
   1296             # non-empty strings will fail this
   1297             if len(query) and not isinstance(query[0], tuple):
-> 1298                 raise TypeError
   1299             # zero-length sequences of all types will get here and succeed,
   1300             # but that's a minor nit - since the original implementation

TypeError: not a valid non-string sequence or mapping object

Issue with pictures in facebook posts

I posted this facebook graph api question on stackoverflow assuming it's unrelated to facepy but just to be sure i'm asking here as well.

http://facebook.stackoverflow.com/questions/8505736/picture-for-feed-post-never-shows-up-on-wall

I think i tried just about anything but perhaps i'm overlooking something. I've used a CURL example in that question but the actual facepy code looks like this:

def create_post(token, wall_owner, message, link, picture, name, caption, description):
    graph = GraphAPI(token)
    try:
        response = graph.post(
            path = '%s/feed' % wall_owner,
            link = link,
            picture = picture,
            name = name,
            caption = caption,
            description = description,
            message = message,
        )
        logger.debug(response, exc_info=True)
    except GraphAPI.Error, e:
        logger.error('Posting to wall failed, error: %s' % e)

@task()
def wall_post_topic(topic):
    create_post(
        topic.author.oauth_token.token,
        topic.author.facebook_id,
        "I posted a new topic",
        "%s%s" % (settings.FACEBOOK_APPLICATION_URL, reverse('topic', kwargs={ 'topic_id' : topic.id })),
        topic.wall_illustration,
        topic.title,
        "Can you predict it?",
        topic.description,
    )

[Errno 32] Broken pipe

If I reload the browser fast many times on views with facepy queries this error shows:

Exception happened during processing of request from ('127.0.0.1', 60668)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 582, in process_request_thread
self.finish_request(request, client_address)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 323, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 150, in init
super(WSGIRequestHandler, self).init(_args, *_kwargs)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 640, in init
self.finish()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/SocketServer.py", line 693, in finish
self.wfile.flush()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 303, in flush
self._sock.sendall(view[write_offset:write_offset+buffer_size])
error: [Errno 32] Broken pipe

Unexpected behavior for SignedRequest.User#has_authorized_application

Facepy derives whether a user has authorized an application from the presence of the user's Facebook ID in his/her signed request, but that is not necessarily indicative of authorization. For example, the signed request Facebook yields an application upon deauthorization includes the user's Facebook ID.

Facebook offers no documentation on the subject, but it seems fair to assume that a user's authorization status may be derived from the presence of an OAuth access token.

Rate limiting

What happens when we get rate limited, how can I check if I get rate limited, what does facebook return when you get rate limited?

Is it possible already to do this with Facepy? What kind of exception does facepy return when youre being rate limited? I will try it out myself, but my connection is really slow here with a VPN. (Living in China), so if anybody knows this already would be great! Thanks a lot.

The "page" parameter on gets

Hi,

I'm trying to get all the Facebook friends of a certain user. I understand how to do such a request (I just do graph_obj.get("me/friends").

I'm less clear about the issue of paging.

I understand, from the Facebook docs, that Facebook might need to give me more data by giving me a "next" link. First of all, when I make a request for my friends list, Facebook provides me a next link, but it's to a page that has an empty list for data.

As for Facepy, you write in the docs that you can set "Page=True" and then you get back a generator. Does this mean I can now use this generate to run over all the objects, and be sure that Facepy gets any more using the "Next" links if necessary?

I ask because it seems that, if I try to get everything from the generator, it not only gets back the data, but also the metadata like "next" links as well, which I'm not sure why it needs to do.

Thanks for the help!

Adding real-time updates / subscriptions

Hi there!

I have started working on real-time updates / subscriptions in a feature branch: feature/realtime-subscriptions.

So far, it involves a small refactor of GraphAPI into a Base class so that we can segregate functionality into its own container class (FQL, Subscriptions and any other future FB Graph functionality).

I would love if you could have a look and discuss how you see it. If you think everything looks OK, I will add more documentation (and re-write the current doc to accomodate the small changes) and send a pull request when everything is clean an ready.

So far, I added tests for everything (still missing some small branch coverage, I think) and method documentation.

Any ideas / improvements are welcomed :) I will start using this in a little prototype we (@TwoApart) are working on, so hopefully it will be used in real life soon :)

Cheers,

facepy error

|system||ruby-1.8.7-p371| Tylers-MacBook-Pro in ~/Desktop/code/fb_bday_wisher
± |master ✗| → python fb_bday_wisher.py build
Traceback (most recent call last):
File "fb_bday_wisher.py", line 36, in
graph.post(friend['id']+ '/feed', 0, message = bday_wish)
File "/Library/Python/2.7/site-packages/facepy/graph_api.py", line 64, in post
retry=retry
File "/Library/Python/2.7/site-packages/facepy/graph_api.py", line 239, in _query
return load(method, url, data)[0]
File "/Library/Python/2.7/site-packages/facepy/graph_api.py", line 201, in load
result = self._parse(response.content)
File "/Library/Python/2.7/site-packages/facepy/graph_api.py", line 281, in _parse
error.get('code', None)
facepy.exceptions.OAuthError: 200 Feed story publishing to other users is disabled for this application

I have the Graph API exlporer configured correctly, yet i cannot get it to run locally by using the python command.

Any fixes?

Thanks

How to tag users in photo?

hello,

i'm trying to publish a photo with tag users.

example

graph.post(
path = '%s/feed' % wall_owner,
picture = picture,
message = message,
tags = ("user_id", "user_name")
)

but the parameter "tags" do nothing. Is this possible with facepy? if yes, how ?

Separate FQL from GraphAPI

FQL is not a part of the Graph API as per Facebook's documentation, so it doesn't make any sense for it to be part of the GraphAPI class. We should maintain backwards compatibility in GraphAPI#fql, but create a new class FQL with methods query and multiquery.

'dict' object has no attribute 'page'

Hi, a can't build a simple is liked validation, this the code:


from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from facepy import SignedRequest

FACEBOOK_APPLICATION_SECRET_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxx"

@csrf_exempt
def index(request):
if 'signed_request' in request.REQUEST:
signed_request = SignedRequest.parse(request.REQUEST.get('signed_request'), FACEBOOK_APPLICATION_SECRET_KEY)
if signed_request.page.is_liked:
return HttpResponse("yes!")
else:
return HttpResponse("no")
else:
return HttpResponse("no signed request")


and return:
'dict' object has no attribute 'page'

Need help getting this installed

hi Johannes,

I ran export PYTHONPATH=$PYTHONPATH:/Library/Python/2.7/site-packages

Outcome:

Traceback (most recent call last):
File "fb_bday_wisher.py", line 12, in
from facepy import GraphAPI
ImportError: No module named facepy

Regards,
Tyler

Retry on failure

Recently Facebook often returns following error on my requests:

{'error_code': 1, 'error_msg': 'An unknown error occurred'}

If I re-execute query, it starts working. So my proposition is to implement GraphAPI with retry option.

I think that there should be implemented two classes that inherits from GraphAPI:

  • GraphAPISafeRetry
  • GraphAPIForceRetry

First implementation retries only when we are sure that retry could help and it can't break anything (ie. we can safety retry on GET request, but POST requests are more tricky). Second implementation retries when we think that retry could help, and we have great chance that it will not break anything (but we are not 100% sure).

Do you have any better name than ForceRetry (it suggests that we retry always but it is not true).

Needs proxy support

I needed to run this on a machine with http and https proxy support. Solved this by subclassing GraphAPI and adding proxies parameter to the requests call in the load method. Would be really nice if it would discover and use proxies, second choice would be to allow user to config proxies.

facepy & py2exe issues

My application is working great when I run via command line, but If I compile via py2exe I get the following error:

  File "facepy\graph_api.pyc", line 41, in get
  File "facepy\graph_api.pyc", line 242, in _query
  File "facepy\graph_api.pyc", line 242, in _query
  File "facepy\graph_api.pyc", line 242, in _query
  File "facepy\graph_api.pyc", line 239, in _query
  File "facepy\graph_api.pyc", line 199, in load
facepy.exceptions.HTTPError: [Errno 185090050] _ssl.c:340: error:0B084002:x509 certificate routines:X509_load_cert_crl_file:system lib

Issues with Requests 0.5.0?

It appears another library I am using has installed requests 0.5.0. Before I roll it back, is there any particular reason why requests 0.4.1 or earlier or specified or is this just what has been confirmed to work?

Support for second error format

Facebook has another error format (which may be undocumented). Sample response:

{'error_code': 1, 'error_msg': 'An unknown error occurred'}

This format should be supported when raising errors.

Question about photo posting

Hello there,

I am using the facepy.GraphAPI to post a photo. The source, path and name parameters are configured ok, but I also want to tag a facebook friend on the photo. As documented on the graph API, i cannot pass a dict() as the tags parameter because it accepts an array object. Any thoughts on how I can do that with facepy and the graph.post() method?

Modularization

--> branch: TwoApart/feature/modularization

Re-posting my thoughts on the refactor / cleanup:

  • facepy.client: leave GraphAPI alone as a raw client that offers a nice wrap around HTTP verbs agains Facebook GraphAPI endpoint.
  • facepy.api: implement the Facebook GraphAPI contracts in methods, grouped as much as possible in classes (RealtimeUpdates, Fql, Auth, etc.). This class would lightly process the input and return light datastructures (i.e. dictionaries).
  • facepy.mapper: implement a top layer of Object-Oriented Mapping like facebookis doing. It should be optional, wrapping API methods one-by-one and only mapping the dictionaries returned by the methods to Python objects. Actually, we migth be able to use other Python projects that map JSON to objects... just an idea. [OPTIONAL, makes much more sense in another project]

This way, each layer is completely optional. Everybody can use and access whatever they want. And we all WIN :)

So far, I have pretty much all the refactor ready in a separate branch: TwoApart/feature/modularization. It's a HUGE refactor and cleanup, so I highly recommend to read a clone of the repo by itself... there aren't those many "changes" but the diffs are veery large and "don't make much sense". The coverage is also pretty high as well, ~97%. I've kept all of the relevant tests.

I also think there is still work to do (apart from updating the documentation once the branch is stable enough), such as consistently use patch decorator in tests to help readability, improve the docstrings of several methods, go over some parts of the api.graph_api module and re-check with the Facebook spec how good/close we are, etc...

Anyway ,just wanted to post an update so that you can have a look and comment :)

Thanks!

facepy import error

|system||ruby-1.9.3-p194| Tylers-MacBook-Pro in ~/Desktop/code/phpfog/fb_bday_wisher
± |master ✗| → af update superf1
Uploading Application:
Checking for available resources: OK
Processing resources: OK
Packing application: /Users/tyler/.rvm/gems/ruby-1.9.3-p194/gems/af-0.3.18.11/lib/cli/zip_util.rb:63: warning: Insecure world writable dir /Users/tyler/.rvm in PATH, mode 040777
OK
Uploading (53K): OK
Push Status: OK
Stopping Application 'superf1': OK
Staging Application 'superf1': OK
Starting Application 'superf1': ..
Error: Application [superf1] failed to start, logs information below.

====> /logs/stderr.log <====

Traceback (most recent call last):
File "fb_bday_wisher.py", line 12, in
import facepy
ImportError: No module named facepy

Error 306: Error retrieving file '/logs/stdout.log'

Weird behaviour when there is a JSON object conaining a "data" attribute

Hi,
still love your work and use it in quite alot of projects! :)

But I guess there is something wrong when I try to GET an "apprequest", I only get the contents of the "data" attribute which is "tracking data here" but nothing else. I guess its some kind of conflict between "data" variables in your facepy Code and "data" attributes inside the json structure.

{
"id": "222162114516955",
"application": {
"name": "-----------------------------------",
"canvas_name": "-----------------",
"namespace": "-------------------",
"id": "--------------------"
},
"to": {
"name": "------------",
"id": "------------"
},
"from": {
"name": "----------",
"id": "----------"
},
"data": "tracking data here",
"message": "---------------------------",
"created_time": "2011-11-03T11:10:35+0000",
"type": "apprequest"
}

I try to figure out whats wrong but Im not the best coder. ;)

get_extended_access_token fails without specific error

I'm not sure how to share a reproducible example without giving away my app secret, so suffice to say that get_application_access_token(app_id, app_secret) and GraphAPI(token) both work as expected, so my parameters seem fine.

I'm getting the following traceback from get_extended_access_token(token, app_id, app_secret). I know there's not a whole lot of detail here, but do you have any suggestions for what I might be doing wrong? Does the original token need to have a specific permission set for this to work?

Traceback (most recent call last):
File "fb_api.py", line 31, in
ext_token = utils.get_extended_access_token(token, app_id, app_secret)
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/utils.py", line 23, in get_extended_access_token
fb_exchange_token = access_token
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 42, in get
retry = retry
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 240, in _query
return self._query(method, path, data, page, retry - 1)
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 240, in _query
return self._query(method, path, data, page, retry - 1)
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 240, in _query
return self._query(method, path, data, page, retry - 1)
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 237, in _query
return load(method, url, data)[0]
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 201, in load
result = self._parse(response.content)
File "/Library/Python/2.7/site-packages/facepy-0.8.2-py2.7.egg/facepy/graph_api.py", line 279, in _parse
error.get('code', None)
facepy.exceptions.OAuthError

Method for getting app GraphAPI

Method for getting GraphAPI for app (from app secret and id). Something like this:

import re

from django.conf import settings
import facepy

def get_application_graph_api():
    kwargs = {
        'client_id': settings.FACEBOOK_APP_ID,
        'client_secret': settings.FACEBOOK_APP_SECRET,
        'grant_type': 'client_credentials',
    }
    access_token_string = facepy.GraphAPI().get('oauth/access_token', **kwargs)
    match = re.match(r"^access_token=(?P<access_token>.*)$", access_token_string)
    if match:
        return facepy.GraphAPI(match.groups()[0])
    raise facepy.FacepyError('no access_token in response')

Long lived access token

Support for getting long tokens would be fabulous. Here is some snippet written by Tomasz Pazurkiewicz for our internal use:

    def get_long_lived_access_token(self, access_token):
        url_base = 'https://graph.facebook.com/oauth/access_token?'
        args = {
            'client_id': settings.FACEBOOK_APP_ID,
            'client_secret': settings.FACEBOOK_APP_SECRET,
            'grant_type': 'fb_exchange_token',
            'fb_exchange_token': access_token,
        }
        data = urllib.urlopen(url_base + urllib.urlencode(args)).read()
        try:
            access_token = parse_qs(data)['access_token'][-1]
        except KeyError:
            pass
        return access_token

me/picture returns '' (empty string)

Because me/picture returns a 302 response, so content is empty.
Facepy should check for status_code != 200 and returns http header o something

Facebook error responce can contain no error code.

For some errors facebook returns dict with error, but without error code i.e:
{'error': {'message': "The action you're trying to publish is invalid..............", 'type': 'Exception'}}

File "facepy/graph_api.py", line 223, in _parse
raise self.FacebookError(data['error']['message'], data['error']['code'])
KeyError: 'code'

Python 3 Support

So far, I've cloned facepy from the repo, run 2to3 over it and although it's totally useless at first, all it takes to add Python 3 support is change line 196 of graph_api.py (GraphAPI._query load method "result = self._parse(response.content)") to "result = response.json"

Requests has built in JSON support and works with both Python 2 and 3. If you left it as is, there were all sorts of errors about strings and bytes and such.

Sorry about the illegibility, I'm tired but figured this could be useful for someone.

facepy on appengine

hi,

trying to user facepy in an appengine app I got the following issue:
facepy/graph_api.py", line 5, in
import requests
ImportError: No module named requests

to try this I copied the facepy directory in my apps root directory, if I run a file from the shell importing facepy it works fine.. probably rather an appengine issue than a facepy issue ? but maybe any idea how to resolve this ?

thanks

Remove test user utilities

We should move the utilities for creating test users to the facebook library in the interest of keeping facepy lean (ref #64).

ImportError: cannot import name certs

I am trying to use facepy in GAE.
When download requests package and put in in facepy folder.
I write import facepy in my views.py file.

Here is the error

import_string() failed for 'myapp.views.index'. Possible reasons are: - missing init.py in a package; - package or module path not included in sys.path; - duplicated package or module name taking precedence in sys.path; - missing module, class, function or variable; Debugged import: - 'myapp' found in 'D:\PythonProj\posttofacebook\myapp*init*.pyc'. - 'myapp.views' not found. Original exception: ImportError: cannot import name certs

Facebook occasionally hands out signed requests with missing page-data that trip up Facepy

An example of such a signed request is below:

{
    "user_id": "614741055",
    "algorithm": "HMAC-SHA256",
    "expires": 1352804400,
    "oauth_token": "<redacted>",
    "user": {"locale": "en_GB", "country": "no", "age": {"max": 99, "min": 21}},
    "issued_at": 1352798635,
    "page": {
        "liked": true,
        "id": "149778835032883"
    }
}

Here, the page.admin key is missing. Occasionally, the page.liked key is missing too.

When either is left out, KeyErrors are thrown.

Signed request parsing fails when "user" element isn't present

If one obtains the authResponse signed request from the Javascript SDK (response.authResponse.signedRequest), passes it to the server, and attempts to parse with Facepy, this exception is thrown:

Exception Type: KeyError at [URL]
Exception Value: 'user'
...

File "/home/ben/.virtualenvs/memorable/local/lib/python2.7/site-packages/facepy/signed_request.py" in parse
  81.                 locale = psr['user'].get('locale', None),

This is because the signed request handling expects a user element to be present, when this is not always the case.

(in this case, the response looks something like:)

{'algorithm': 'HMAC-SHA256', 'code': '2.ADB4AhExWy34xQ2O.3600.1336518000.1-420094|wJVdm1spqMtjtyff0bTmOaAztOY', 'issued_at': 1336512002, 'user_id': '4302094'}

I'm not sure how many people will run into this issue in practice, and I'm also not sure why the API doesn't return the user element within the signed request in this case (The docs do note that "A signed_request is simply a data transfer mechanism and does not imply any defined structure or format of data carried in the request.").

The reason I was attempting to pass the signed request this way is for easy testing of a canvas app without having to load it in the canvas chrome, but still making use of the signed request to verify that the access token passed in matches the user ID passed in.

Certificate error when trying to post to feed

I'm, only occasionally it seems, getting a certificate error when trying to post to the facebook feed:

Task customers.tasks.sender_wall_post[b6befb28-99b0-42cc-bf2e-c8bfff781f27] raised exception: HTTPError(SSLError(CertificateError("hostname 'graph.facebook.com' doesn't match 'm.facebook.com'",),),)

Stacktrace (most recent call last):

  File "celery/task/trace.py", line 224, in trace_task
    R = retval = fun(*args, **kwargs)
  File "customers/tasks.py", line 50, in sender_wall_post
    type='link',
  File "facepy/graph_api.py", line 64, in post
    retry=retry
  File "facepy/graph_api.py", line 239, in _query
    return load(method, url, data)[0]
  File "facepy/graph_api.py", line 199, in load
    raise HTTPError(exception.message)

Did Facebook mess up their wildcard SSL certificates or is facepy being too strict? If the last this would be an urllib issue i guess but since Facepy only has to work with facebook i thought it made sense to post this here first...

pip install facepy install fails

When I run pip install facepy I see the following error:

Downloading/unpacking facepy==0.6.2
  Running setup.py egg_info for package facepy
    Traceback (most recent call last):
      File "<string>", line 14, in <module>
      File "/Users/MGstaff/Documents/inkjoy_workspace/branches/phase-2-dev/vEnv/build/facepy/setup.py", line 3, in <module>
        readme = open('README.rst').read()
    IOError: [Errno 2] No such file or directory: 'README.rst'
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

Pagination with since.

If you do query like:

graph.get(url, paginate=True, since=since)

you could expect that generator will yeld as long, as you are receiving posts newest than since. It is not true, it will probably yield forever (I'm not sure what will happen if number of posts newest than since is below limit).

I see three things that we could do with that:

  1. Say that it is by design and we don't care.
  2. Throw exception/log warring if you use paginate and since together.
  3. Implement it so it works as expected.

What do you think?

JSON decoding should create Decimals, not floats

I’m using facepy to implement the new Facebook payments that use local currency. An example payment object contains this data:

"refundable_amount": {
    "amount": "1000.00",
    "currency": "CAD" 
},
"payout_foreign_exchange_rate": 0.95036535

Now as you can see, the amount paid can be converted to Decimal manually, but the USD exchange rate is decoded to a float, which cannot be used reasonably for financial operations. If facepy used json.loads(data, parse_float=decimal.Decimal) in https://github.com/jgorset/facepy/blob/master/facepy/graph_api.py#L262 , my life would be easier :) Can I make a PR and hope for a quick release?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.