Understanding “runwithfriends” facebook-app sample code

落花浮王杯 提交于 2019-12-23 02:05:24

问题


this is my first web-programming experience so I hope my questions doesn't sound very dumb. I have been stucked on this for many days.

I am trying to understand a sample code: https://github.com/facebook/runwithfriends

However I am not understanding very well how the information flow works and how can I modify that sample (i.e. how the code works).

For example, in the following section of the code:

class RecentRunsHandler(BaseHandler):
"""Show recent runs for the user and friends"""
def get(self):
    if self.user:
        friends = {}
        for friend in select_random(
                User.get_by_key_name(self.user.friends), 30):
            friends[friend.user_id] = friend

        self.render(u'runs',
            friends=friends,
            user_recent_runs=Run.find_by_user_ids(
                [self.user.user_id], limit=5),
            friends_runs=Run.find_by_user_ids(friends.keys()),
        )
    else:
        self.render(u'welcome')

As I understand (along with HTML) is useful for showing friends that are using the same app, and if I understand correctly, here is the essential part:

*friends_runs=Run.find_by_user_ids(friends.keys())*

But what if I want to show any given friend. How can I do it?

Summarizing, I would like to know:

1- How the flow of the code works? (I don't fully understand the explanation here)

2- How can I manipulate the code so to get, for example, to show a list of friends of the user (not necessary that use the same app)? Moreover, Can I show friends filtered by some characteristic (for example, gender)?

Thanks a lot!


回答1:


The python "SDK" for facebook I use I took from https://gist.github.com/1190267 and combined it with the code from the example app to achieve the functionality I wanted both for a canvas app and for website usage.

It depends whether you're using facebook with websites or a canvas application. For a canvas application you probably could do well with the javascript SDK but for a "login with facebook" I required serverside logic that should work with javascript turned off so I've completed that solution with details you might have help to know. You can try make small changes of that specific app 'runwithfriends' to get an understanding which code does what. The project you're looking at contains some outdated practice though:

  • getting and setting cookies is likely preferable now doing with webapp2's builtin functions for this instead of the code that comes with the FB example app

  • logging in and out is now done with OAuth 2.0 so it's likely that the login system you're looking at is outdated and you need to use OAuth 2.0 which is described here. I much rather do login/logout serverside so I did an OAuth 2.0 pure python solution to login / logout following the authentication steps mentioned in the tutorial from FB. I had to clear the cookie to log a user out which was not documented.

  • To upgrade to python 2.7 I had to also modify so that HTTP header did not cast to unicode. I don't know why but otherwise it complained that headers were "not strings"

To more elaborately answer your specific questions:

1) The requesthandler class you posted is a subclass of a BaseHandler so to fully understand what it does you can look at the BaseHandler class since what you are posting is a BAseHandler. The BaseHandler uses django templates for rendering and if you want to can switch the template engine to jinja2 which is remmended. Further the code accesses the user object inherited from the BaseHandler and does some operations on it and renders it to a template. You can try make a requesthandler of your own, subclass BaseHandler and do what you want.

2) I could manipulate the code and I'm not an expert so you should be able to do it too. I wanted a simple FB app to display random images and I could manipulate it to select random images via blobs and render to to a template while keeping the facebook base functions. A function to use for getting the user using the Graph API I do this:

def parse_signed_request(signed_request, secret):
    """
    Parse signed_request given by Facebook (usually via POST),
    decrypt with app secret.

    Arguments:
    signed_request -- Facebook's signed request given through POST
    secret -- Application's app_secret required to decrpyt signed_request
    """

    if '.' in signed_request:
        (esig, payload) = signed_request.split('.')
    else:
        return {}

    sig = urlsafe_b64decode(str(esig))
    data = _parse_json(urlsafe_b64decode(str(payload)))

    if not isinstance(data, dict):
        raise SignedRequestError('Pyload is not a json string!')
        return {}

    if data['algorithm'].upper() == 'HMAC-SHA256':
        if hmac.new(secret, payload, hashlib.sha256).digest() == sig:
            return data
    else:

        raise SignedRequestError('Not HMAC-SHA256 encrypted!')

    return {}


def get_user_from_cookie(cookies, app_id, app_secret):
    """Parses the cookie set by the official Facebook JavaScript SDK.

    cookies should be a dictionary-like object mapping cookie names to
    cookie values.

    If the user is logged in via Facebook, we return a dictionary with the
    keys "uid" and "access_token". The former is the user's Facebook ID,
    and the latter can be used to make authenticated requests to the Graph API.
    If the user is not logged in, we return None.

    Download the official Facebook JavaScript SDK at
    http://github.com/facebook/connect-js/. Read more about Facebook
    authentication at http://developers.facebook.com/docs/authentication/.
    """
    cookie = cookies.get('fbsr_' + app_id, '')
    if not cookie:
        return None
    response = parse_signed_request(cookie, app_secret)
    if not response:
        return None

    args = dict(code=response['code'], client_id=app_id,
                client_secret=app_secret, redirect_uri='')

    file = \
        urllib.urlopen('https://graph.facebook.com/oauth/access_token?'
                       + urllib.urlencode(args))
    try:
        token_response = file.read()
    finally:
        file.close()

    access_token = cgi.parse_qs(token_response)['access_token'][-1]
    logging.debug('returning cookie')
    return dict(uid=response['user_id'], access_token=access_token)

See http://developers.facebook.com/docs/api for complete documentation for the API. And you can get the the official Facebook JavaScript SDK at http://github.com/facebook/connect-js/

I'm now writing code to sync a webapp2_extras.auth account with facebook so that custom accounts and facebook accounts can co-exist and we're discussing solutions for this in the webapp2 groups and categories. The current way I do it is adding the recommended current_user to a basehandler and using that as the FB identity while working on "merging" my class FBUser that is a custom class for facebook users that autheorized my website and/or canvas application to sync with webapp2_extras.auth.models.User which is an expando model so it can just add the properties it doesn't have such as facebookid, firstname, lastname, etc.

@property
def current_user(self):
    if not hasattr(self, '_current_user'):
        self._current_user = None
        cookie = get_user_from_cookie(self.request.cookies,
                facebookconf.FACEBOOK_APP_ID,
                facebookconf.FACEBOOK_APP_SECRET)
        if cookie:

            # Store a local instance of the user data so we don't need
            # a round-trip to Facebook on every request
            user = FBUser.get_by_key_name(cookie['uid'])
            if not user:
                graph = GraphAPI(cookie['access_token'])
                profile = graph.get_object('me')
                user = FBUser(key_name=str(profile['id']),
                              id=str(profile['id']),
                              name=profile['name'],
                              profile_url=profile['link'],
                              access_token=cookie['access_token'])
                user.put()
            elif user.access_token != cookie['access_token']:
                user.access_token = cookie['access_token']
                user.put()
            self._current_user = user
    return self._current_user

You can also solve your authentication with session objects and build your authentication system around that. That is what I do when using both custom accounts and facebook accounts and you're welcome to have a lok at my repository for more code examples how to intregrate facebook with google app engine using python 2.7.



来源:https://stackoverflow.com/questions/8675810/understanding-runwithfriends-facebook-app-sample-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!