Repository: sopel-irc/sopel

Issue:
[tell/remind] Switch to config-name for "db" files
It's kind of silly that the "database" files `tell` and `remind` write use `bot.config.core.host` in the filename. We have a config name, which is already used for the main SQLite database. They should just use it so the core stuff is a bit more predictable.

Will need a migration routine to rename the existing file at module load. That's a prerequisite for merging, whether I create this patch or someone else does.


Discussion:

Resolving patch:
diff --git a/sopel/modules/remind.py b/sopel/modules/remind.py
--- a/sopel/modules/remind.py
+++ b/sopel/modules/remind.py
@@ -2,6 +2,7 @@
 """
 remind.py - Sopel Reminder Module
 Copyright 2011, Sean B. Palmer, inamidst.com
+Copyright 2019, dgw, technobabbl.es
 Licensed under the Eiffel Forum License 2.
 
 https://sopel.chat
@@ -11,6 +12,7 @@
 import codecs
 import collections
 from datetime import datetime
+import logging
 import os
 import re
 import time
@@ -21,6 +23,9 @@
 from sopel.tools.time import get_timezone, format_time, validate_timezone
 
 
+LOGGER = logging.getLogger(__name__)
+
+
 def get_filename(bot):
     """Get the remind database's filename
 
@@ -32,7 +37,7 @@ def get_filename(bot):
     The remind database filename is based on the bot's nick and its
     configured ``core.host``, and it is located in the ``bot``'s ``homedir``.
     """
-    name = bot.nick + '-' + bot.config.core.host + '.reminders.db'
+    name = bot.config.basename + '.reminders.db'
     return os.path.join(bot.config.core.homedir, name)
 
 
@@ -123,6 +128,25 @@ def create_reminder(bot, trigger, duration, message):
 def setup(bot):
     """Load the remind database"""
     bot.rfn = get_filename(bot)
+
+    # Pre-7.0 migration logic. Remove in 8.0 or 9.0.
+    old = bot.nick + '-' + bot.config.core.host + '.reminders.db'
+    old = os.path.join(bot.config.core.homedir, old)
+    if os.path.isfile(old):
+        LOGGER.info("Attempting to migrate old 'remind' database {}..."
+                    .format(old))
+        try:
+            os.rename(old, bot.rfn)
+        except OSError:
+            LOGGER.error("Migration failed!")
+            LOGGER.error("Old filename: {}".format(old))
+            LOGGER.error("New filename: {}".format(bot.rfn))
+            LOGGER.error(
+                "See https://sopel.chat/usage/installing/upgrading-to-sopel-7/#reminder-db-migration")
+        else:
+            LOGGER.info("Migration finished!")
+    # End migration logic
+
     bot.rdb = load_database(bot.rfn)
 
 
diff --git a/sopel/modules/tell.py b/sopel/modules/tell.py
--- a/sopel/modules/tell.py
+++ b/sopel/modules/tell.py
@@ -2,6 +2,7 @@
 """
 tell.py - Sopel Tell and Ask Module
 Copyright 2008, Sean B. Palmer, inamidst.com
+Copyright 2019, dgw, technobabbl.es
 Licensed under the Eiffel Forum License 2.
 
 https://sopel.chat
@@ -9,6 +10,7 @@
 from __future__ import unicode_literals, absolute_import, print_function, division
 
 import io
+import logging
 import os
 import time
 import threading
@@ -20,6 +22,9 @@
 from sopel.tools.time import get_timezone, format_time
 
 
+LOGGER = logging.getLogger(__name__)
+
+
 class TellSection(StaticSection):
     use_private_reminder = ValidatedAttribute(
         'use_private_reminder', parse=bool, default=False)
@@ -51,7 +56,7 @@ def load_reminders(filename):
     """Load tell/ask reminders from a ``filename``.
 
     :param str filename: path to the tell/ask reminders file
-    :return: a dict with the tell/asl reminders
+    :return: a dict with the tell/ask reminders
     :rtype: dict
     """
     result = defaultdict(list)
@@ -84,9 +89,27 @@ def dump_reminders(filename, data):
 
 def setup(bot):
     bot.config.define_section('tell', TellSection)
-    fn = bot.nick + '-' + bot.config.core.host + '.tell.db'
+    fn = bot.config.basename + '.tell.db'
     bot.tell_filename = os.path.join(bot.config.core.homedir, fn)
 
+    # Pre-7.0 migration logic. Remove in 8.0 or 9.0.
+    old = bot.nick + '-' + bot.config.core.host + '.tell.db'
+    old = os.path.join(bot.config.core.homedir, old)
+    if os.path.isfile(old):
+        LOGGER.info("Attempting to migrate old 'tell' database {}..."
+                    .format(old))
+        try:
+            os.rename(old, bot.tell_filename)
+        except OSError:
+            LOGGER.error("Migration failed!")
+            LOGGER.error("Old filename: {}".format(old))
+            LOGGER.error("New filename: {}".format(bot.tell_filename))
+            LOGGER.error(
+                "See https://sopel.chat/usage/installing/upgrading-to-sopel-7/#reminder-db-migration")
+        else:
+            LOGGER.info("Migration finished!")
+    # End migration logic
+
     if not os.path.exists(bot.tell_filename):
         with io.open(bot.tell_filename, 'w', encoding='utf-8') as fd:
             # if we can't open/write into the file, the tell plugin can't work


Test patch:
diff --git a/test/modules/test_modules_remind.py b/test/modules/test_modules_remind.py
--- a/test/modules/test_modules_remind.py
+++ b/test/modules/test_modules_remind.py
@@ -15,6 +15,7 @@
 @pytest.fixture
 def sopel():
     bot = test_tools.MockSopel('Sopel')
+    bot.config.basename = 'default'
     bot.config.core.owner = 'Admin'
     bot.config.core.host = 'chat.freenode.net'
     return bot
@@ -316,7 +317,7 @@ def test_get_filename(sopel):
     filename = remind.get_filename(sopel)
     assert filename == os.path.join(
         sopel.config.core.homedir,
-        'Sopel-chat.freenode.net.reminders.db')
+        'default.reminders.db')
 
 
 def test_load_database_empty(tmpdir):