From 4a729893825fc9a8b4c8177ddd16cfd10da074bb Mon Sep 17 00:00:00 2001 From: dgw Date: Sat, 19 Jun 2021 00:55:23 -0500 Subject: [PATCH] Add caching & force-update command; release v0.2.0 --- NEWS | 9 ++++++++ setup.cfg | 2 +- sopel_rtfm/__init__.py | 51 +++++++++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 11 deletions(-) diff --git a/NEWS b/NEWS index b06bd4b..1c3d82b 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,12 @@ +0.2.0 +===== + +Added: +* Caching behavior: The configured Sphinx inventory is fetched at startup, and + re-fetched automatically every 24 hours +* Bot admins can force an update with the new `.rtfmupdate` command + + 0.1.1 ===== diff --git a/setup.cfg b/setup.cfg index 9edc672..6c8fc45 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = sopel-rtfm -version = 0.1.1 +version = 0.2.0 description = A plugin to suggest documentation links when someone asks a basic question. author = dgw author_email = dgw@technobabbl.es diff --git a/sopel_rtfm/__init__.py b/sopel_rtfm/__init__.py index fbd6a62..69ff6ea 100644 --- a/sopel_rtfm/__init__.py +++ b/sopel_rtfm/__init__.py @@ -5,6 +5,7 @@ """ from __future__ import unicode_literals, absolute_import, division, print_function +from datetime import datetime import os from urllib.error import URLError from urllib.parse import urlparse @@ -47,22 +48,44 @@ def configure(config): def setup(bot): bot.config.define_section('rtfm', RTFMSection) + bot.memory['rtfm_base'] = ( + bot.config.rtfm.link_base or + os.path.dirname(bot.config.rtfm.inventory) + ) + + if not bot.memory['rtfm_base'].endswith('/'): + bot.memory['rtfm_base'] += '/' + + update_sphinx_objects(bot) + + +@module.interval(3600) +def update_sphinx_objects(bot, force=False): + now = datetime.utcnow() + age = now - bot.memory.get('rtfm_cache_time', datetime.fromtimestamp(0)) + + if not force and age.total_seconds() < 86400: # 1 day / 24 hours in seconds + LOGGER.debug("Inventory cache is under one day old, skipping update.") + return + + LOGGER.debug("Beginning inventory cache update.") + try: inv = sphobjinv.Inventory(url=bot.config.rtfm.inventory) except ValueError: # invalid URL, probably - LOGGER.error( + LOGGER.exception( 'Could not fetch inventory file; URL seems to be malformed: %s', bot.config.rtfm.inventory, ) - raise + return except (SphobjinvError, URLError) as e: # couldn't fetch due to urllib error or unrecognized file format - LOGGER.error( + LOGGER.exception( 'Could not fetch inventory file: %s', str(e), ) - raise + return objects = { name: url @@ -79,15 +102,11 @@ def setup(bot): ] } - bot.memory['rtfm_base'] = ( - bot.config.rtfm.link_base or - os.path.dirname(bot.config.rtfm.inventory) - ) bot.memory['rtfm_inventory'] = inv bot.memory['rtfm_objects'] = objects + bot.memory['rtfm_cache_time'] = now - if not bot.memory['rtfm_base'].endswith('/'): - bot.memory['rtfm_base'] += '/' + LOGGER.debug("Finished updating inventory cache.") def shutdown(bot): @@ -116,3 +135,15 @@ def suggest_doc_link(bot, trigger): link = bot.memory['rtfm_base'] + bot.memory['rtfm_objects'][result] bot.say(link) + + +@module.commands('rtfmupdate') +@module.require_admin +def force_update(bot, trigger): + """Force an update of the target Sphinx object inventory. + + In lieu of restarting the bot or waiting for the next automatic refresh + (every 24 hours), a bot admin can force an immediate update. + """ + bot.reply("Attempting to update Sphinx objects.") + update_sphinx_objects(bot, force=True)