def get(self): auth_entity = None auth_entity_str_key = self.request.get('auth_entity') if auth_entity_str_key: auth_entity = ndb.Key(urlsafe=auth_entity_str_key).get() if not auth_entity.blog_ids or not auth_entity.blog_hostnames: auth_entity = None if not auth_entity: self.messages.add( "Couldn't fetch your blogs. Maybe you're not a Blogger user?") state = self.request.get('state') if not state: # state doesn't currently come through for Blogger. not sure why. doesn't # matter for now since we don't plan to implement listen or publish. state = self.construct_state_param_for_add(feature='webmention') if not auth_entity: self.maybe_add_or_delete_source(Blogger, auth_entity, state) return vars = { 'action': '/blogger/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe(), 'blogs': [{'id': id, 'title': title, 'domain': host} for id, title, host in zip(auth_entity.blog_ids, auth_entity.blog_titles, auth_entity.blog_hostnames)], } logging.info('Rendering choose_blog.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write(JINJA_ENV.get_template('choose_blog.html').render(**vars))
def _render_preview(self, result, include_link=False): """Renders a preview CreationResult as HTML. Args: result: CreationResult include_link: boolean Returns: CreationResult with the rendered HTML in content """ state = { 'source_key': self.source.key.urlsafe().decode(), 'source_url': self.source_url(), 'target_url': self.target_url(), 'include_link': include_link, } vars = { 'source': self.preprocess_source(self.source), 'preview': result.content, 'description': result.description, 'webmention_endpoint': util.host_url(self) + '/publish/webmention', 'state': util.encode_oauth_state(state), } vars.update(state) logging.info('Rendering preview with template vars %s', pprint.pformat(vars)) return gr_source.creation_result( JINJA_ENV.get_template('preview.html').render(**vars))
def finish(self, auth_entity, state=None): if auth_entity: if int(auth_entity.blog_id) == 0: self.messages.add( 'Please try again and choose a blog before clicking Authorize.' ) return self.redirect('/') # Check if this is a self-hosted WordPress blog site_info = WordPress.get_site_info(self, auth_entity) if site_info is None: return elif site_info.get('jetpack'): logging.info('This is a self-hosted WordPress blog! %s %s', auth_entity.key_id(), auth_entity.blog_id) self.response.headers['Content-Type'] = 'text/html' self.response.out.write( JINJA_ENV.get_template( 'confirm_self_hosted_wordpress.html').render( auth_entity_key=auth_entity.key.urlsafe().decode(), state=state, )) return self.maybe_add_or_delete_source(WordPress, auth_entity, state)
def finish(self, auth_entity, state=None): if not auth_entity: self.maybe_add_or_delete_source(Tumblr, auth_entity, state) return vars = { 'action': '/tumblr/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe().decode(), 'blogs': [ { 'id': b['name'], 'title': b.get('title', ''), 'domain': util.domain_from_link(b['url']) } # user_json is the user/info response: # http://www.tumblr.com/docs/en/api/v2#user-methods for b in json_loads(auth_entity.user_json)['user']['blogs'] if b.get('name') and b.get('url') ], } logging.info('Rendering choose_blog.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write( JINJA_ENV.get_template('choose_blog.html').render(**vars))
def _render_preview(self, result, include_link=False): """Renders a preview CreationResult as HTML. Args: result: CreationResult include_link: boolean Returns: CreationResult with the rendered HTML in content """ state = { 'source_key': self.source.key.urlsafe(), 'source_url': self.source_url(), 'target_url': self.target_url(), 'include_link': include_link, } vars = { 'source': self.preprocess_source(self.source), 'preview': result.content, 'description': result.description, 'webmention_endpoint': util.host_url(self) + '/publish/webmention', 'state': util.encode_oauth_state(state), } vars.update(state) logging.info('Rendering preview with template vars %s', pprint.pformat(vars)) return gr_source.creation_result( JINJA_ENV.get_template('preview.html').render(**vars))
def finish(self, auth_entity, state=None): if not auth_entity: self.maybe_add_or_delete_source(Medium, auth_entity, state) return user = json_loads(auth_entity.user_json)['data'] username = user['username'] if not username.startswith('@'): username = '******' + username # fetch publications this user contributes or subscribes to. # (sadly medium's API doesn't tell us the difference unless we fetch each # pub's metadata separately.) # https://github.com/Medium/medium-api-docs/#user-content-listing-the-users-publications auth_entity.publications_json = auth_entity.get( oauth_medium.API_BASE + 'users/%s/publications' % user['id']).text auth_entity.put() pubs = json_loads(auth_entity.publications_json).get('data') if not pubs: self.maybe_add_or_delete_source(Medium, auth_entity, state, id=username) return # add user profile to start of pubs list user['id'] = username pubs.insert(0, user) vars = { 'action': '/medium/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe(), 'blogs': [{ 'id': p['id'], 'title': p.get('name', ''), 'url': p.get('url', ''), 'pretty_url': util.pretty_link(str(p.get('url', ''))), 'image': p.get('imageUrl', ''), } for p in pubs if p.get('id')], } logging.info('Rendering choose_blog.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write( JINJA_ENV.get_template('choose_blog.html').render(**vars))
def get(self): auth_entity = None auth_entity_str_key = self.request.get('auth_entity') if auth_entity_str_key: auth_entity = ndb.Key(urlsafe=auth_entity_str_key).get() if not auth_entity.blog_ids or not auth_entity.blog_hostnames: auth_entity = None if not auth_entity: self.messages.add( "Couldn't fetch your blogs. Maybe you're not a Blogger user?") state = self.request.get('state') if not state: # state doesn't currently come through for Blogger. not sure why. doesn't # matter for now since we don't plan to implement listen or publish. state = self.construct_state_param_for_add(feature='webmention') if not auth_entity: self.maybe_add_or_delete_source(Blogger, auth_entity, state) return vars = { 'action': '/blogger/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe(), 'blogs': [{ 'id': id, 'title': title, 'domain': host } for id, title, host in zip(auth_entity.blog_ids, auth_entity.blog_titles, auth_entity.blog_hostnames)], } logging.info('Rendering choose_blog.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write( JINJA_ENV.get_template('choose_blog.html').render(**vars))
def finish(self, auth_entity, state=None): if not auth_entity: self.maybe_add_or_delete_source(Medium, auth_entity, state) return user = json.loads(auth_entity.user_json)['data'] username = user['username'] if not username.startswith('@'): username = '******' + username # fetch publications this user contributes or subscribes to. # (sadly medium's API doesn't tell us the difference unless we fetch each # pub's metadata separately.) # https://github.com/Medium/medium-api-docs/#user-content-listing-the-users-publications auth_entity.publications_json = auth_entity.get( oauth_medium.API_BASE + 'users/%s/publications' % user['id']).text auth_entity.put() pubs = json.loads(auth_entity.publications_json).get('data') if not pubs: self.maybe_add_or_delete_source(Medium, auth_entity, state, id=username) return # add user profile to start of pubs list user['id'] = username pubs.insert(0, user) vars = { 'action': '/medium/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe(), 'blogs': [{ 'id': p['id'], 'title': p.get('name', ''), 'url': p.get('url', ''), 'pretty_url': util.pretty_link(str(p.get('url', ''))), 'image': p.get('imageUrl', ''), } for p in pubs if p.get('id')], } logging.info('Rendering choose_blog.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write(JINJA_ENV.get_template('choose_blog.html').render(**vars))
def finish(self, auth_entity, state=None): id = util.decode_oauth_state(state).get('id') if auth_entity and json.loads(auth_entity.pages_json) and not id: # this user has FB page(s), and we don't know whether they want to sign # themselves up or one of their pages, so ask them. vars = { 'action': '/facebook/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe(), 'choices': [json.loads(auth_entity.user_json)] + json.loads(auth_entity.pages_json), } logging.info('Rendering choose_facebook.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write( JINJA_ENV.get_template('choose_facebook.html').render(**vars)) return # this user has no FB page(s), or we know the one they want to sign up. self.finish_oauth_flow(auth_entity, state)
def finish(self, auth_entity, state=None): if not auth_entity: self.maybe_add_or_delete_source(Tumblr, auth_entity, state) return vars = { 'action': '/tumblr/add', 'state': state, 'auth_entity_key': auth_entity.key.urlsafe(), 'blogs': [{'id': b['name'], 'title': b.get('title', ''), 'domain': util.domain_from_link(b['url'])} # user_json is the user/info response: # http://www.tumblr.com/docs/en/api/v2#user-methods for b in json.loads(auth_entity.user_json)['user']['blogs'] if b.get('name') and b.get('url')], } logging.info('Rendering choose_blog.html with %s', vars) self.response.headers['Content-Type'] = 'text/html' self.response.out.write(JINJA_ENV.get_template('choose_blog.html').render(**vars))
def finish(self, auth_entity, state=None): if auth_entity: if int(auth_entity.blog_id) == 0: self.messages.add( 'Please try again and choose a blog before clicking Authorize.') return self.redirect('/') # Check if this is a self-hosted WordPress blog site_info = WordPress.get_site_info(self, auth_entity) if site_info is None: return elif site_info.get('jetpack'): logging.info('This is a self-hosted WordPress blog! %s %s', auth_entity.key.id(), auth_entity.blog_id) self.response.headers['Content-Type'] = 'text/html' self.response.out.write( JINJA_ENV.get_template('confirm_self_hosted_wordpress.html').render( auth_entity_key=auth_entity.key.urlsafe(), state=state, )) return self.maybe_add_or_delete_source(WordPress, auth_entity, state)
def attempt_single_item(self, item): """Attempts to preview or publish a single mf2 item. Args: item: mf2 item dict from mf2py Returns: CreationResult """ self.maybe_inject_silo_content(item) obj = microformats2.json_to_object(item) ignore_formatting = self.ignore_formatting(item) if ignore_formatting: prop = microformats2.first_props(item.get('properties', {})) content = microformats2.get_text(prop.get('content')) if content: obj['content'] = content.strip() # which original post URL to include? in order of preference: # 1. rel-shortlink (background: https://github.com/snarfed/bridgy/issues/173) # 2. original user-provided URL if it redirected # 3. u-url if available # 4. actual final fetched URL if self.shortlink: obj['url'] = self.shortlink elif self.source_url() != self.fetched.url: obj['url'] = self.source_url() elif 'url' not in obj: obj['url'] = self.fetched.url logging.debug('Converted to ActivityStreams object: %s', json.dumps(obj, indent=2)) # posts and comments need content obj_type = obj.get('objectType') if obj_type in ('note', 'article', 'comment'): if (not obj.get('content') and not obj.get('summary') and not obj.get('displayName')): return gr_source.creation_result( abort=False, error_plain='Could not find content in %s' % self.fetched.url, error_html='Could not find <a href="http://microformats.org/">content</a> in %s' % self.fetched.url) self.preprocess(obj) include_link = self.include_link(item) if not self.authorize(): return gr_source.creation_result(abort=True) # RIP Facebook comments/likes. https://github.com/snarfed/bridgy/issues/350 if (isinstance(self.source, FacebookPage) and (obj_type == 'comment' or obj.get('verb') == 'like')): return gr_source.creation_result( abort=True, error_plain='Facebook comments and likes are no longer supported. :(', error_html='<a href="https://github.com/snarfed/bridgy/issues/350">' 'Facebook comments and likes are no longer supported.</a> :(') if self.PREVIEW: result = self.source.gr_source.preview_create( obj, include_link=include_link, ignore_formatting=ignore_formatting) self.entity.published = result.content or result.description if not self.entity.published: return result # there was an error state = { 'source_key': self.source.key.urlsafe(), 'source_url': self.source_url(), 'target_url': self.target_url(), 'include_link': include_link, } vars = {'source': self.preprocess_source(self.source), 'preview': result.content, 'description': result.description, 'webmention_endpoint': self.request.host_url + '/publish/webmention', 'state': util.encode_oauth_state(state), } vars.update(state) logging.info('Rendering preview with template vars %s', pprint.pformat(vars)) return gr_source.creation_result( JINJA_ENV.get_template('preview.html').render(**vars)) else: result = self.source.gr_source.create( obj, include_link=include_link, ignore_formatting=ignore_formatting) self.entity.published = result.content if not result.content: return result # there was an error if 'url' not in self.entity.published: self.entity.published['url'] = obj.get('url') self.entity.type = self.entity.published.get('type') or models.get_type(obj) self.entity.type_label = self.source.TYPE_LABELS.get(self.entity.type) self.response.headers['Content-Type'] = 'application/json' logging.info('Returning %s', json.dumps(self.entity.published, indent=2)) self.response.headers['Location'] = self.entity.published['url'].encode('utf-8') self.response.status = 201 return gr_source.creation_result( json.dumps(self.entity.published, indent=2))