def __getattr__(self, name): """Overridden to pass auth_entity to :class:`granary.googleplus.GooglePlus`.""" if name == 'gr_source' and self.auth_entity: self.gr_source = gr_googleplus.GooglePlus(auth_entity=self.auth_entity.get()) return self.gr_source return getattr(super(GooglePlusPage, self), name)
def setUp(self): super(GooglePlusTest, self).setUp() self.auth_entity = oauth_googleplus.GooglePlusAuth( id='my_string_id', user_json=json.dumps({ 'displayName': 'Bob', }), creds_json=CREDS_JSON) self.googleplus = googleplus.GooglePlus(auth_entity=self.auth_entity)
def get(self): """Handles an API GET. Request path is of the form /site/user_id/group_id/app_id/activity_id , where each element except site is an optional string object id. """ # parse path args = urllib.unquote(self.request.path).strip('/').split('/') if not args or len(args) > MAX_PATH_LEN: raise exc.HTTPNotFound('Expected 1-%d path elements; found %d' % (MAX_PATH_LEN, len(args))) # make source instance site = args.pop(0) if site == 'twitter': src = twitter.Twitter( access_token_key=util.get_required_param(self, 'access_token_key'), access_token_secret=util.get_required_param(self, 'access_token_secret')) elif site == 'facebook': src = facebook.Facebook( access_token=util.get_required_param(self, 'access_token')) elif site == 'flickr': src = flickr.Flickr( access_token_key=util.get_required_param(self, 'access_token_key'), access_token_secret=util.get_required_param(self, 'access_token_secret')) elif site == 'instagram': src = instagram.Instagram( access_token=util.get_required_param(self, 'access_token')) elif site == 'google+': auth_entity = util.get_required_param(self, 'auth_entity') src = googleplus.GooglePlus(auth_entity=ndb.Key(urlsafe=auth_entity).get()) else: src_cls = source.sources.get(site) if not src_cls: raise exc.HTTPNotFound('Unknown site %r' % site) src = src_cls(**self.request.params) # handle default path elements args = [None if a in defaults else a for a, defaults in zip(args, PATH_DEFAULTS)] user_id = args[0] if args else None # fetch actor if necessary actor = None if self.request.get('format') == 'atom': # atom needs actor args = [None if a in defaults else a # handle default path elements for a, defaults in zip(args, PATH_DEFAULTS)] user_id = args[0] if args else None actor = src.get_actor(user_id) if src else {} # get activities and write response response = src.get_activities_response(*args, **self.get_kwargs()) self.write_response(response, actor=actor)
def get(self): try: cookie = 'SID=%(SID)s; SSID=%(SSID)s; HSID=%(HSID)s' % self.request.params except KeyError: return self.abort(400, 'Query parameters SID, SSID, and HSID are required') logging.info('Fetching with Cookie: %s', cookie) resp = urllib2.urlopen(urllib2.Request( 'https://plus.google.com/', headers={ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0', 'Cookie': cookie, }), timeout=60) body = resp.read().decode('utf-8') logging.info('Response: %s', resp.getcode()) host_url = self.request.host_url + '/' if resp.getcode() in (401, 403) or 'href="https://accounts.google.com/Logout' not in body: self.response.headers['Content-Type'] = 'application/atom+xml' self.response.out.write(atom.activities_to_atom([{ 'object': { 'url': self.request.url, 'content': 'Your plusstreamfeed (Google+ Atom feed) cookie isn\'t working. <a href="%s">Click here to regenerate your feed!</a>' % host_url, }, }], {}, title='plusstreamfeed (Google+ Atom feed)', host_url=host_url, request_url=self.request.path_url)) return elif resp.getcode() != 200: return self.abort(502, "Google+ fetch failed") actor = {} name_email = re.compile(r'title="Google Account: ([^"]+)"').search(body) if name_email: logging.info('Logged in for user %s', name_email.group(1)) actor = {'displayName': name_email.group(1)} else: logging.warning("Couldn't determine Google user!") activities = [ a for a in googleplus.GooglePlus(None, None).html_to_activities(body) if a.get('verb') != 'like' ] self.response.headers['Content-Type'] = 'application/atom+xml' self.response.out.write(atom.activities_to_atom( activities, actor, title='plusstreamfeed (Google+ Atom feed)', host_url=host_url, request_url=self.request.path_url, xml_base='https://plus.google.com/'))
def setUp(self): super(GooglePlusTest, self).setUp() self.auth_entity = oauth_googleplus.GooglePlusAuth( id='my_string_id', user_json=json.dumps({ 'displayName': 'Bob', }), creds_json=json.dumps({ 'access_token': 'my token', 'client_id': appengine_config.GOOGLE_CLIENT_ID, 'client_secret': appengine_config.GOOGLE_CLIENT_SECRET, 'refresh_token': 'my refresh token', 'token_expiry': '', 'token_uri': '', 'user_agent': '', 'invalid': '', })) self.googleplus = googleplus.GooglePlus(auth_entity=self.auth_entity)
def test_live(self): resp = requests.get(URL) resp.raise_for_status() activities = googleplus.GooglePlus().html_to_activities(resp.text) self.assertEqual(10, len(activities)) import json; print json.dumps(activities, indent=2) found = set() for a in activities: self.assertTrue(a['actor']) for field in 'id', 'url': self.assertTrue(a['object'][field], field) for field in 'content', 'replies', 'tags', 'image': if a['object'].get(field): found.add(field) for field in 'content', 'replies', 'tags', 'image': self.assertIn(field, found)
def get(self): """Handles an API GET. Request path is of the form /site/user_id/group_id/app_id/activity_id , where each element except site is an optional string object id. """ # parse path args = urllib.unquote(self.request.path).strip('/').split('/') if not args or len(args) > MAX_PATH_LEN: raise exc.HTTPNotFound('Expected 1-%d path elements; found %d' % (MAX_PATH_LEN, len(args))) # make source instance site = args.pop(0) if site == 'twitter': src = twitter.Twitter(access_token_key=util.get_required_param( self, 'access_token_key'), access_token_secret=util.get_required_param( self, 'access_token_secret')) elif site == 'facebook': src = facebook.Facebook( access_token=util.get_required_param(self, 'access_token')) elif site == 'flickr': src = flickr.Flickr(access_token_key=util.get_required_param( self, 'access_token_key'), access_token_secret=util.get_required_param( self, 'access_token_secret')) elif site == 'instagram': src = instagram.Instagram(scrape=True) elif site == 'google+': auth_entity = util.get_required_param(self, 'auth_entity') src = googleplus.GooglePlus(auth_entity=ndb.Key( urlsafe=auth_entity).get()) else: src_cls = source.sources.get(site) if not src_cls: raise exc.HTTPNotFound('Unknown site %r' % site) src = src_cls(**self.request.params) # decode tag URI ids for i, arg in enumerate(args): parsed = util.parse_tag_uri(arg) if parsed: domain, id = parsed if domain != src.DOMAIN: raise exc.HTTPBadRequest( 'Expected domain %s in tag URI %s, found %s' % (src.DOMAIN, arg, domain)) args[i] = id # check if request is cached cache = self.request.get('cache', '').lower() != 'false' if cache: cache_key = 'R %s' % self.request.path cached = memcache.get(cache_key) if cached: logging.info('Serving cached response %r', cache_key) self.write_response(cached['response'], actor=cached['actor'], url=src.BASE_URL) return # handle default path elements args = [ None if a in defaults else a for a, defaults in zip(args, PATH_DEFAULTS) ] user_id = args[0] if args else None # get activities (etc) try: if len(args) >= 2 and args[1] == '@blocks': response = {'items': src.get_blocklist()} else: response = src.get_activities_response(*args, **self.get_kwargs(src)) except (NotImplementedError, ValueError) as e: self.abort(400, str(e)) # other exceptions are handled by webutil.handlers.handle_exception(), # which uses interpret_http_exception(), etc. # fetch actor if necessary actor = response.get('actor') if not actor and self.request.get('format') == 'atom': # atom needs actor args = [ None if a in defaults else a # handle default path elements for a, defaults in zip(args, PATH_DEFAULTS) ] user_id = args[0] if args else None actor = src.get_actor(user_id) if src else {} self.write_response(response, actor=actor, url=src.BASE_URL) # cache response if cache: logging.info('Caching response in %r', cache_key) memcache.set(cache_key, { 'response': response, 'actor': actor }, src.RESPONSE_CACHE_TIME)