def subscribe(source, handler): """Subscribes to a source. Also receives some past posts and adds propagate tasks for them. http://documentation.superfeedr.com/subscribers.html#addingfeedswithpubsubhubbub Args: source: Blogger, Tumblr, or WordPress handler: :class:`webapp2.RequestHandler` """ if appengine_config.DEBUG: logging.info('Running in dev_appserver, not subscribing to Superfeedr') return data = { 'hub.mode': 'subscribe', 'hub.topic': source.feed_url(), 'hub.callback': '%s/%s/notify/%s' % ( util.host_url(handler), source.SHORT_NAME, source.key.id()), # TODO # 'hub.secret': 'xxx', 'format': 'json', 'retrieve': 'true', } logging.info('Adding Superfeedr subscription: %s', data) resp = util.requests_post( PUSH_API_URL, data=data, auth=HTTPBasicAuth(appengine_config.SUPERFEEDR_USERNAME, appengine_config.SUPERFEEDR_TOKEN), headers=util.REQUEST_HEADERS) resp.raise_for_status() handle_feed(resp.text, source)
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 _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 subscribe(source): """Subscribes to a source. Also receives some past posts and adds propagate tasks for them. http://documentation.superfeedr.com/subscribers.html#addingfeedswithpubsubhubbub Args: source: Blogger, Tumblr, or WordPress """ if appengine_info.LOCAL: logger.info('Running locally, not subscribing to Superfeedr') return data = { 'hub.mode': 'subscribe', 'hub.topic': source.feed_url(), 'hub.callback': util.host_url(f'/{source.SHORT_NAME}/notify/{source.key_id()}'), # TODO # 'hub.secret': 'xxx', 'format': 'json', 'retrieve': 'true', } logger.info(f'Adding Superfeedr subscription: {data}') resp = util.requests_post(PUSH_API_URL, data=data, auth=HTTPBasicAuth(SUPERFEEDR_USERNAME, SUPERFEEDR_TOKEN)) handle_feed(resp.json(), source)
def post(self): self.request.headers[ 'Content-Type'] = 'application/x-www-form-urlencoded' logging.debug('Params: %s', list(self.request.params.items())) if not self.lease( ndb.Key(urlsafe=self.request.params['response_key'])): return source = self.source = self.entity.source.get() if not source: logging.warning('Source not found! Dropping response.') return logging.info('Source: %s %s, %s', source.label(), source.key_id(), source.bridgy_url(self)) poll_estimate = self.entity.created - datetime.timedelta(seconds=61) logging.info('Created by this poll: %s/%s', util.host_url(self), logs.url(poll_estimate, source.key)) self.activities = [json_loads(a) for a in self.entity.activities_json] response_obj = json_loads(self.entity.response_json) if (not source.is_activity_public(response_obj) or not all(source.is_activity_public(a) for a in self.activities)): logging.info('Response or activity is non-public. Dropping.') self.complete() return self.send_webmentions()
def get(self, site=None): self.head(site) self.response.out.write("""\ <!DOCTYPE html> <html><head> <link rel="webmention" href="%s/publish/webmention"> </head> <body>Nothing here! <a href="/about">Try the docs instead.</a></body> </html>""" % util.host_url(self))
def dispatch_request(self): token = request.values['token'] domains = [d.key.id() for d in Domain.query(Domain.tokens == token)] if not domains: indieauth_start = util.host_url(f'/indieauth/start?token={token}') self.error( f'Not connected to Bridgy. <a href="{indieauth_start}" target="_blank"">Connect now!</a>', 404) return jsonify(domains)
def test_host_url(self): with app.test_request_context(): self.assertEqual('http://localhost/', util.host_url()) self.assertEqual('http://localhost/asdf', util.host_url('asdf')) self.assertEqual('http://localhost/foo/bar', util.host_url('/foo/bar')) with app.test_request_context(base_url='https://a.xyz', path='/foo'): self.assertEqual('https://a.xyz/', util.host_url()) self.assertEqual('https://a.xyz/asdf', util.host_url('asdf')) self.assertEqual('https://a.xyz/foo/bar', util.host_url('/foo/bar'))
def dispatch_request(self): logger.debug(f'Params: {list(request.values.items())}') if not self.lease(ndb.Key(urlsafe=request.values['response_key'])): return ('', ERROR_HTTP_RETURN_CODE) if getattr(g, 'failed', None) else 'OK' source = g.source poll_estimate = self.entity.created - datetime.timedelta(seconds=61) poll_url = util.host_url(logs.url(poll_estimate, source.key)) logger.info(f'Created by this poll: {poll_url}') self.activities = [json_loads(a) for a in self.entity.activities_json] response_obj = json_loads(self.entity.response_json) if (not source.is_activity_public(response_obj) or not all(source.is_activity_public(a) for a in self.activities)): logger.info('Response or activity is non-public. Dropping.') self.complete() return '' self.send_webmentions() return ('', ERROR_HTTP_RETURN_CODE) if getattr(g, 'failed', None) else 'OK'
def source_url(self, target_url): # determine which activity to use try: activity = self.activities[0] if self.entity.urls_to_activity: urls_to_activity = json_loads(self.entity.urls_to_activity) if urls_to_activity: activity = self.activities[urls_to_activity[target_url]] except (KeyError, IndexError): logging.warning( """\ Hit https://github.com/snarfed/bridgy/issues/237 KeyError! target url %s not in urls_to_activity: %s activities: %s""", target_url, self.entity.urls_to_activity, self.activities) self.abort(util.ERROR_HTTP_RETURN_CODE) # generate source URL id = activity['id'] parsed = util.parse_tag_uri(id) post_id = parsed[1] if parsed else id parts = [ util.host_url(self), self.entity.type, self.source.SHORT_NAME, self.source.key.string_id(), post_id ] if self.entity.type != 'post': # parse and add response id. (we know Response key ids are always tag URIs) _, response_id = util.parse_tag_uri(self.entity.key.string_id()) reaction_id = response_id if self.entity.type in ('like', 'react', 'repost', 'rsvp'): response_id = response_id.split('_')[ -1] # extract responder user id parts.append(response_id) if self.entity.type == 'react': parts.append(reaction_id) return '/'.join(parts)
def bridgy_url(self, handler): """Returns the Bridgy page URL for this source.""" return util.host_url(handler) + self.bridgy_path()
def _last_poll_url(self, source): return '%s/%s' % (util.host_url(self), logs.url(source.last_poll_attempt, source.key))
def _last_poll_url(self, source): return util.host_url(logs.url(source.last_poll_attempt, source.key))
def head(self, site=None): self.response.headers['Link'] = ( '<%s/publish/webmention>; rel="webmention"' % util.host_url(self))
def app_url(self): return util.host_url()
def __init__(self, url): self.url = url self.host_url = u.host_url(url) self.path = u.path(url)