Example #1
0
def get_digest_for_list(list_owner, list_id, dev_mode):
    digest_start_time, digest_end_time, max_cache_age = _get_digest_timestamps()

    api = _get_digest_twitter_api(
        max_cache_age, key='%s/%s' % (list_owner, list_id))

    user, had_error = twitterappengine.exec_twitter_api(
        lambda: api.GetUser(list_owner),
        error_detail='user %s' % list_owner)
    if not had_error:
        timezone = twitterdisplay.get_timezone_for_user(user)
    else:
        timezone = None

    fetcher = ListTwitterFetcher(api, list_owner, list_id, digest_start_time)
    statuses, had_error = fetcher.fetch()

    return _process_digest_statuses(
        statuses,
        digest_start_time,
        digest_end_time,
        had_error,
        dev_mode,
        timezone=timezone)
Example #2
0
    def _get_signed_in(self):
        twitter_id = self._session.twitter_id
        logging.info('Serving feed for %s' % twitter_id)

        user, had_error = twitterappengine.exec_twitter_api(
            lambda: self._api.GetUser(twitter_id),
            error_detail='user %s' % twitter_id)

        if had_error:
            self._write_error(500)
            return

        stream = data.StreamData.get_timeline_for_user(twitter_id)

        threshold_time = time.time() - FEED_STATUS_INTERVAL_SEC

        # It's wasteful to serve the hub the full set of items in the feed, so
        # we use a variant of the feed windowing technique described at
        # http://code.google.com/p/pubsubhubbub/wiki/PublisherEfficiency#Feed_windowing
        # to only give it new items. We treat the If-Modified-Since header as
        # an indication of the items that the hub already has, but we allow one
        # hour of overlap, in case of items getting dropped, replication delay,
        # cosmic rays, etc.
        if self._user_agent_contains('appid: pubsubhubbub'):
            if_modified_since = self._get_if_modified_since()
            if if_modified_since:
                logging.info('If-Modified-Since: %d' % if_modified_since)
                threshold_time = if_modified_since - IF_MODIFIED_SINCE_INTERVAL_SEC
                # Since we're serving a partial response, we don't want proxies
                # caching it.
                self.response.headers['Cache-Control'] = 'private'

        # We want the feed to have all tweets from the past day, but also at
        # at least 10 items.
        feed_status_ids = []
        if stream:
            for status_id, status_timestamp_sec in stream.status_pairs():
                if status_timestamp_sec < threshold_time and \
                        len(feed_status_ids) >= MIN_FEED_ITEMS:
                    break
                feed_status_ids.append(status_id)

        logging.info('  Feed has %d items' % len(feed_status_ids))

        status_data = data.StatusData.get_by_status_ids(feed_status_ids)
        statuses = [s.to_status() for s in status_data]

        timezone = twitterdisplay.get_timezone_for_user(user)

        # We don't actually want statuses grouped, instead we want one status
        # per item.
        status_groups = [
            twitterdisplay.DisplayStatusGroup(
                user=status.user,
                statuses=[status],
                thumbnail_size=thumbnails.LARGE_THUMBNAIL,
                timezone=timezone)
            for status in statuses
        ]

        updated_date = datetime.datetime.utcnow()

        self._write_template('birdfeeder/feed.atom', {
              'feed_title': '@%s Twitter Timeline' % user.screen_name,
              'updated_date_iso': updated_date.isoformat(),
              'feed_url': self.request.url,
              'status_groups': status_groups,
            },
            content_type='application/atom+xml')

        self._add_last_modified_header(updated_date)
Example #3
0
    def _get_signed_in(self):
        twitter_id = self._session.twitter_id
        logging.info('Serving feed for %s' % twitter_id)

        user, had_error = twitterappengine.exec_twitter_api(
            lambda: self._caching_api.GetUser(user_id=twitter_id,
                                              include_entities=False),
            error_detail='user %s' % twitter_id)

        if had_error:
            self._write_error(500)
            return

        stream = data.StreamData.get_timeline_for_user(twitter_id)

        threshold_time = time.time() - FEED_STATUS_INTERVAL_SEC

        if self._should_use_feed_windowing():
            if_modified_since = self._get_if_modified_since()
            if if_modified_since:
                logging.info('If-Modified-Since: %d' % if_modified_since)
                threshold_time = if_modified_since - IF_MODIFIED_SINCE_INTERVAL_SEC
                # Since we're serving a partial response, we don't want proxies
                # caching it.
                self.response.headers['Cache-Control'] = 'private'
            elif 'pubsubhubbub' in self.request.headers['User-Agent']:
                # Google's PubSubHubbub hub no longer seems to send an
                # If-Modified-Since header, but it crawls often enough that we
                # can use a shorter interval for it.
                threshold_time = time.time() - PUBSUBHUBBUB_HUB_INTERVAL_SEC
                self.response.headers['Cache-Control'] = 'private'

        # We want the feed to have all tweets from the past day, but also at
        # at least 10 items.
        feed_status_ids = []
        if stream:
            for status_id, status_timestamp_sec in stream.status_pairs():
                if status_timestamp_sec < threshold_time and \
                        len(feed_status_ids) >= MIN_FEED_ITEMS:
                    break
                feed_status_ids.append(status_id)

        logging.info('  Feed has %d items' % len(feed_status_ids))

        status_data = data.StatusData.get_by_status_ids(feed_status_ids)
        statuses = [s.to_status() for s in status_data]

        timezone = twitterdisplay.get_timezone_for_user(user)

        # We don't actually want statuses grouped, instead we want one status
        # per item.
        status_groups = [
            twitterdisplay.DisplayStatusGroup(
                user=status.user,
                statuses=[status],
                thumbnail_size=thumbnails.LARGE_THUMBNAIL,
                timezone=timezone)
            for status in statuses
        ]

        updated_date = datetime.datetime.utcnow()

        self._write_template('birdfeeder/feed.atom', {
              'feed_title': '@%s Twitter Timeline' % user.screen_name,
              'updated_date_iso': updated_date.isoformat(),
              'feed_url': self.request.url,
              'status_groups': status_groups,
            },
            content_type='application/atom+xml')

        self._add_last_modified_header(updated_date)