Mercurial > piecrust2
diff piecrust/admin/views/mentions.py @ 1114:8af2ea1f5c34
tasks: Add new `tasks` command and infrastructure, with `mention` task.
* The new command lets `chef` run tasks from a queue.
* The webmention endpoint now adds a mention task.
* Moved mention handling code to a task runner.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Thu, 22 Feb 2018 22:12:45 -0800 |
parents | 98c7dd6ea4ac |
children |
line wrap: on
line diff
--- a/piecrust/admin/views/mentions.py Wed Feb 21 21:21:42 2018 -0800 +++ b/piecrust/admin/views/mentions.py Thu Feb 22 22:12:45 2018 -0800 @@ -1,14 +1,7 @@ -import os -import os.path -import json -import time import logging -import requests -from bs4 import BeautifulSoup -from flask import current_app, g, request, make_response, abort +from flask import g, request, make_response, abort from ..blueprint import foodtruck_bp -from piecrust.app import PieCrustFactory -from piecrust.serving.util import get_requested_page +from piecrust.tasks.base import TaskManager logger = logging.getLogger(__name__) @@ -26,105 +19,18 @@ logger.error("Source and target are the same.") abort(400) - # See if we need to do this synchronously or asynchronously, and other - # things we should know up-front. - wmcfg = g.site.piecrust_app.config.get('webmention') - if wmcfg.get('use_task_queue') is True: - tasks_dir = os.path.join(g.site.piecrust_app.root_dir, '_tasks') - _ensure_dir(tasks_dir) - task_data = { - 'type': 'webmention', - 'data': {'source': src_url, 'target': tgt_url}} - task_path = os.path.join(tasks_dir, '%s.json' % int(time.time())) - with open(task_path, 'w', encoding='utf8') as fp: - json.dump(task_data, fp) - return make_response("Webmention queued.", 202, []) - - # Find if we have a page at the target URL. - # To do that we need to spin up a PieCrust app that knows how the website - # works. Because the website might have been baked with custom settings - # (usually the site root URL) there's a good chance we need to apply - # some variants, which the user can specify in the config. - pcappfac = PieCrustFactory( - current_app.config['FOODTRUCK_ROOT_DIR'], - cache_key='webmention') - if wmcfg.get('config_variant'): - pcappfac.config_variants = [wmcfg.get('config_variant')] - if wmcfg.get('config_variants'): - pcappfac.config_variants = list(wmcfg.get('config_variants')) - if wmcfg.get('config_values'): - pcappfac.config_values = list(wmcfg.get('config_values').items()) - pcapp = pcappfac.create() - try: - req_page = get_requested_page(pcapp, tgt_url) - if req_page.page is None: - abort(404) - except Exception as ex: - logger.error("Can't check webmention target page: %s" % tgt_url) - logger.exception(ex) - abort(404) - - # Grab the source URL's contents and see if anything references the - # target (ours) URL. - src_t = requests.get(src_url) - src_html = BeautifulSoup(src_t.text, 'html.parser') - for link in src_html.find_all('a'): - href = link.get('href') - if href == tgt_url: - break - else: - logger.error("Source '%s' doesn't link to target: %s" % - (src_url, tgt_url)) - abort(400) + # Create the task for handling this mention. + pcapp = g.site.piecrust_app + task_manager = TaskManager(pcapp) + task_id = task_manager.createTask('mention', { + 'source': src_url, + 'target': tgt_url}) - # Find something to quote for this webmention. We find an `h-entry` - # to get a title, excerpt, and/or text. - blurb = None - hentry = src_html.find(class_='h-entry') - if hentry: - try: - pname = hentry.find(class_='p-name') - pauthor = hentry.find(class_='p-author') - blurb = { - 'pname': _bs4_contents_str(pname), - 'pauthor': _bs4_contents_str(pauthor)} - except: # NOQA - logger.error("Couldn't get h-entry info.") - - dirname, _ = os.path.splitext(req_page.page.content_spec) - dirname += '-assets' - _ensure_dir(dirname) - mention_path = os.path.join(dirname, 'mentions.json') - try: - with open(mention_path, 'r', encoding='utf-8') as fp: - mention = json.load(fp) - except IOError: - mention = {'mentions': []} + # Either run the task now in a background process (for cheap and simple + # setups), or leave the task there to be picked up later when someone + # runs the task queue eventually. + wmcfg = pcapp.config.get('webmention') + if not wmcfg.get('use_task_queue'): + g.site.runTask(task_id) - for m in mention['mentions']: - if m['source'] == src_url: - return - - new_mention = {'source': src_url} - if blurb: - new_mention.update(blurb) - - mention['mentions'].append(new_mention) - - with open(mention_path, 'w', encoding='utf-8') as fp: - json.dump(mention, fp) - logger.info("Received webmention from: %s" % src_url) - - return make_response(("Webmention received.", 202, [])) - - -def _bs4_contents_str(node): - return ''.join([str(c).strip() for c in node.contents]) - - -def _ensure_dir(path, mode=0o775): - try: - os.makedirs(path, mode=mode, exist_ok=True) - except OSError: - pass - + return make_response("Webmention queued.", 202, [])