Esempio n. 1
0
    def get_activities_response(self, **kwargs):
        type = self.auth_entity.get().type
        kwargs.setdefault('fetch_events', True)
        kwargs.setdefault('fetch_news', type == 'user')
        kwargs.setdefault('event_owner_id', self.key.id())

        try:
            activities = super(FacebookPage,
                               self).get_activities_response(**kwargs)
        except urllib2.HTTPError as e:
            code, body = util.interpret_http_exception(e)

            # use a function so any new exceptions (JSON decoding, missing keys) don't
            # clobber the original exception so we can re-raise it below.
            def dead_token():
                try:
                    err = json.loads(body)['error']
                    return (err.get('code') in DEAD_TOKEN_ERROR_CODES
                            or err.get('error_subcode')
                            in DEAD_TOKEN_ERROR_SUBCODES
                            or err.get('message') in DEAD_TOKEN_ERROR_MESSAGES)
                except:
                    logging.exception(
                        "Couldn't determine whether token is still valid")
                    return False

            if code == '401':
                if not dead_token() and type == 'user':
                    # ask the user to reauthenticate. if this API call fails, it will raise
                    # urllib2.HTTPError instead of DisableSource, so that we don't disable
                    # the source without notifying.
                    #
                    # TODO: for pages, fetch the owners/admins and notify them.
                    self.gr_source.create_notification(
                        self.key.id(),
                        "Bridgy's access to your account has expired. Click here to renew it now!",
                        'https://brid.gy/facebook/start')
                raise models.DisableSource()

            raise

        # update the resolved_object_ids and post_publics caches
        def parsed_post_id(id):
            parsed = gr_facebook.Facebook.parse_id(id)
            return parsed.post if parsed.post else id

        resolved = self._load_cache('resolved_object_ids')
        for activity in activities['items']:
            obj = activity.get('object', {})
            obj_id = parsed_post_id(obj.get('fb_id'))
            ids = obj.get('fb_object_for_ids')
            if obj_id and ids:
                resolved[obj_id] = obj_id
                for id in ids:
                    resolved[parsed_post_id(id)] = obj_id

        for activity in activities['items']:
            self.is_activity_public(activity)

        return activities
Esempio n. 2
0
    def test_handle_disable_source(self):
        self.mox.StubOutWithMock(testutil.FakeSource, 'get_activities')
        testutil.FakeSource.get_activities(
            activity_id='000', user_id=self.source.key.string_id()).AndRaise(
                models.DisableSource())
        self.mox.ReplayAll()

        resp = self.check_response('/post/fake/%s/000', expected_status=401)
        self.assertIn("Bridgy's access to your account has expired", resp.body)
Esempio n. 3
0
  def get_activities_response(self, *args, **kwargs):
    """Set user_id manually.

    ...since Reddit sometimes (always?) 400s our calls to
    https://oauth.reddit.com/api/v1/me (via PRAW's Reddit.user.me() ).
    """
    kwargs.setdefault('user_id', self.username)
    if kwargs.get('count'):
      kwargs['count'] = min(kwargs['count'], 10)

    try:
      return super().get_activities_response(*args, **kwargs)
    except NotFound:
      # this user was deleted or banned
      raise models.DisableSource()
Esempio n. 4
0
    def poll(self, source):
        """Actually runs the poll.

    Stores property names and values to update in source.updates.
    """
        if source.last_activities_etag or source.last_activity_id:
            logging.debug('Using ETag %s, last activity id %s',
                          source.last_activities_etag, source.last_activity_id)

        #
        # Step 1: fetch activities:
        # * posts by the user
        # * search all posts for the user's domain URLs to find links
        #
        cache = util.CacheDict()
        if source.last_activities_cache_json:
            cache.update(json.loads(source.last_activities_cache_json))

        try:
            # search for links first so that the user's activities and responses
            # override them if they overlap
            links = source.search_for_links()

            # this user's own activities (and user mentions)
            resp = source.get_activities_response(
                fetch_replies=True,
                fetch_likes=True,
                fetch_shares=True,
                fetch_mentions=True,
                count=50,
                etag=source.last_activities_etag,
                min_id=source.last_activity_id,
                cache=cache)
            etag = resp.get('etag')  # used later
            user_activities = resp.get('items', [])

            # these map ids to AS objects
            responses = {a['id']: a for a in links}
            activities = {a['id']: a for a in links + user_activities}

        except Exception, e:
            code, body = util.interpret_http_exception(e)
            if code == '401':
                msg = 'Unauthorized error: %s' % e
                logging.warning(msg, exc_info=True)
                source.updates['poll_status'] = 'ok'
                raise models.DisableSource(msg)
            elif code in util.HTTP_RATE_LIMIT_CODES:
                logging.warning(
                    'Rate limited. Marking as error and finishing. %s', e)
                source.updates.update({
                    'poll_status': 'error',
                    'rate_limited': True
                })
                return
            elif (code
                  and int(code) / 100 == 5) or util.is_connection_failure(e):
                logging.error(
                    'API call failed. Marking as error and finishing. %s: %s\n%s',
                    code, body, e)
                self.abort(ERROR_HTTP_RETURN_CODE)
            else:
                raise