prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Make .seen persist over bot restarts
  Currently, when a Willie-based bot is restarted, it loses all the info about who it saw. It is quite inconvenient, as restarts are required quite often, especially on networks where there are lots of netsplits going on and the bot loses its nick to them all the time. The proposed solution would be to keep a persistent DB containing the relevant info from which old records may or may not be auto-deleted at regular intervals.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `willie/modules/seen.py`
  Content:
  ```
  1 # coding=utf8
  2 """
  3 seen.py - Willie Seen Module
  4 Copyright 2008, Sean B. Palmer, inamidst.com
  5 Copyright © 2012, Elad Alfassa <elad@fedoraproject.org>
  6 Licensed under the Eiffel Forum License 2.
  7 
  8 http://willie.dftba.net
  9 """
  10 from __future__ import unicode_literals
  11 
  12 import time
  13 import datetime
  14 from willie.tools import Ddict, Identifier, get_timezone, format_time
  15 from willie.module import commands, rule, priority
  16 
  17 seen_dict = Ddict(dict)
  18 
  19 
  20 @commands('seen')
  21 def seen(bot, trigger):
  22     """Reports when and where the user was last seen."""
  23     if not trigger.group(2):
  24         bot.say(".seen <nick> - Reports when <nick> was last seen.")
  25         return
  26     nick = Identifier(trigger.group(2).strip())
  27     if nick in seen_dict:
  28         timestamp = seen_dict[nick]['timestamp']
  29         channel = seen_dict[nick]['channel']
  30         message = seen_dict[nick]['message']
  31 
  32         tz = get_timezone(bot.db, bot.config, None, trigger.nick,
  33                           trigger.sender)
  34         saw = datetime.datetime.utcfromtimestamp(timestamp)
  35         timestamp = format_time(bot.db, bot.config, tz, trigger.nick,
  36                                 trigger.sender, saw)
  37 
  38         msg = "I last saw {} at {}".format(nick, timestamp)
  39         if Identifier(channel) == trigger.sender:
  40             msg = msg + " in here, saying " + message
  41         else:
  42             msg += " in another channel."
  43         bot.say(str(trigger.nick) + ': ' + msg)
  44     else:
  45         bot.say("Sorry, I haven't seen %s around." % nick)
  46 
  47 
  48 @rule('(.*)')
  49 @priority('low')
  50 def note(bot, trigger):
  51     if not trigger.is_privmsg:
  52         nick = Identifier(trigger.nick)
  53         seen_dict[nick]['timestamp'] = time.time()
  54         seen_dict[nick]['channel'] = trigger.sender
  55         seen_dict[nick]['message'] = trigger
  56
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/willie/modules/seen.py b/willie/modules/seen.py
  --- a/willie/modules/seen.py
  +++ b/willie/modules/seen.py
  @@ -11,11 +11,9 @@
   
   import time
   import datetime
  -from willie.tools import Ddict, Identifier, get_timezone, format_time
  +from willie.tools import Identifier, get_timezone, format_time
   from willie.module import commands, rule, priority
   
  -seen_dict = Ddict(dict)
  -
   
   @commands('seen')
   def seen(bot, trigger):
  @@ -23,11 +21,11 @@
       if not trigger.group(2):
           bot.say(".seen <nick> - Reports when <nick> was last seen.")
           return
  -    nick = Identifier(trigger.group(2).strip())
  -    if nick in seen_dict:
  -        timestamp = seen_dict[nick]['timestamp']
  -        channel = seen_dict[nick]['channel']
  -        message = seen_dict[nick]['message']
  +    nick = trigger.group(2).strip()
  +    timestamp = bot.db.get_nick_value(nick, 'seen_timestamp')
  +    if timestamp:
  +        channel = bot.db.get_nick_value(nick, 'seen_channel')
  +        message = bot.db.get_nick_value(nick, 'seen_message')
   
           tz = get_timezone(bot.db, bot.config, None, trigger.nick,
                             trigger.sender)
  @@ -42,14 +40,13 @@
               msg += " in another channel."
           bot.say(str(trigger.nick) + ': ' + msg)
       else:
  -        bot.say("Sorry, I haven't seen %s around." % nick)
  +        bot.say("Sorry, I haven't seen {} around.".format(nick))
   
   
   @rule('(.*)')
   @priority('low')
   def note(bot, trigger):
       if not trigger.is_privmsg:
  -        nick = Identifier(trigger.nick)
  -        seen_dict[nick]['timestamp'] = time.time()
  -        seen_dict[nick]['channel'] = trigger.sender
  -        seen_dict[nick]['message'] = trigger
  +        bot.db.set_nick_value(trigger.nick, 'seen_timestamp', time.time())
  +        bot.db.set_nick_value(trigger.nick, 'seen_channel', trigger.sender)
  +        bot.db.set_nick_value(trigger.nick, 'seen_message', trigger)
  
verification_info: {"golden_diff": "diff --git a/willie/modules/seen.py b/willie/modules/seen.py\n--- a/willie/modules/seen.py\n+++ b/willie/modules/seen.py\n@@ -11,11 +11,9 @@\n \n import time\n import datetime\n-from willie.tools import Ddict, Identifier, get_timezone, format_time\n+from willie.tools import Identifier, get_timezone, format_time\n from willie.module import commands, rule, priority\n \n-seen_dict = Ddict(dict)\n-\n \n @commands('seen')\n def seen(bot, trigger):\n@@ -23,11 +21,11 @@\n     if not trigger.group(2):\n         bot.say(\".seen <nick> - Reports when <nick> was last seen.\")\n         return\n-    nick = Identifier(trigger.group(2).strip())\n-    if nick in seen_dict:\n-        timestamp = seen_dict[nick]['timestamp']\n-        channel = seen_dict[nick]['channel']\n-        message = seen_dict[nick]['message']\n+    nick = trigger.group(2).strip()\n+    timestamp = bot.db.get_nick_value(nick, 'seen_timestamp')\n+    if timestamp:\n+        channel = bot.db.get_nick_value(nick, 'seen_channel')\n+        message = bot.db.get_nick_value(nick, 'seen_message')\n \n         tz = get_timezone(bot.db, bot.config, None, trigger.nick,\n                           trigger.sender)\n@@ -42,14 +40,13 @@\n             msg += \" in another channel.\"\n         bot.say(str(trigger.nick) + ': ' + msg)\n     else:\n-        bot.say(\"Sorry, I haven't seen %s around.\" % nick)\n+        bot.say(\"Sorry, I haven't seen {} around.\".format(nick))\n \n \n @rule('(.*)')\n @priority('low')\n def note(bot, trigger):\n     if not trigger.is_privmsg:\n-        nick = Identifier(trigger.nick)\n-        seen_dict[nick]['timestamp'] = time.time()\n-        seen_dict[nick]['channel'] = trigger.sender\n-        seen_dict[nick]['message'] = trigger\n+        bot.db.set_nick_value(trigger.nick, 'seen_timestamp', time.time())\n+        bot.db.set_nick_value(trigger.nick, 'seen_channel', trigger.sender)\n+        bot.db.set_nick_value(trigger.nick, 'seen_message', trigger)\n", "issue": "Make .seen persist over bot restarts\nCurrently, when a Willie-based bot is restarted, it loses all the info about who it saw. It is quite inconvenient, as restarts are required quite often, especially on networks where there are lots of netsplits going on and the bot loses its nick to them all the time. The proposed solution would be to keep a persistent DB containing the relevant info from which old records may or may not be auto-deleted at regular intervals.\n\n", "before_files": [{"content": "# coding=utf8\n\"\"\"\nseen.py - Willie Seen Module\nCopyright 2008, Sean B. Palmer, inamidst.com\nCopyright \u00a9 2012, Elad Alfassa <elad@fedoraproject.org>\nLicensed under the Eiffel Forum License 2.\n\nhttp://willie.dftba.net\n\"\"\"\nfrom __future__ import unicode_literals\n\nimport time\nimport datetime\nfrom willie.tools import Ddict, Identifier, get_timezone, format_time\nfrom willie.module import commands, rule, priority\n\nseen_dict = Ddict(dict)\n\n\n@commands('seen')\ndef seen(bot, trigger):\n    \"\"\"Reports when and where the user was last seen.\"\"\"\n    if not trigger.group(2):\n        bot.say(\".seen <nick> - Reports when <nick> was last seen.\")\n        return\n    nick = Identifier(trigger.group(2).strip())\n    if nick in seen_dict:\n        timestamp = seen_dict[nick]['timestamp']\n        channel = seen_dict[nick]['channel']\n        message = seen_dict[nick]['message']\n\n        tz = get_timezone(bot.db, bot.config, None, trigger.nick,\n                          trigger.sender)\n        saw = datetime.datetime.utcfromtimestamp(timestamp)\n        timestamp = format_time(bot.db, bot.config, tz, trigger.nick,\n                                trigger.sender, saw)\n\n        msg = \"I last saw {} at {}\".format(nick, timestamp)\n        if Identifier(channel) == trigger.sender:\n            msg = msg + \" in here, saying \" + message\n        else:\n            msg += \" in another channel.\"\n        bot.say(str(trigger.nick) + ': ' + msg)\n    else:\n        bot.say(\"Sorry, I haven't seen %s around.\" % nick)\n\n\n@rule('(.*)')\n@priority('low')\ndef note(bot, trigger):\n    if not trigger.is_privmsg:\n        nick = Identifier(trigger.nick)\n        seen_dict[nick]['timestamp'] = time.time()\n        seen_dict[nick]['channel'] = trigger.sender\n        seen_dict[nick]['message'] = trigger\n", "path": "willie/modules/seen.py"}], "after_files": [{"content": "# coding=utf8\n\"\"\"\nseen.py - Willie Seen Module\nCopyright 2008, Sean B. Palmer, inamidst.com\nCopyright \u00a9 2012, Elad Alfassa <elad@fedoraproject.org>\nLicensed under the Eiffel Forum License 2.\n\nhttp://willie.dftba.net\n\"\"\"\nfrom __future__ import unicode_literals\n\nimport time\nimport datetime\nfrom willie.tools import Identifier, get_timezone, format_time\nfrom willie.module import commands, rule, priority\n\n\n@commands('seen')\ndef seen(bot, trigger):\n    \"\"\"Reports when and where the user was last seen.\"\"\"\n    if not trigger.group(2):\n        bot.say(\".seen <nick> - Reports when <nick> was last seen.\")\n        return\n    nick = trigger.group(2).strip()\n    timestamp = bot.db.get_nick_value(nick, 'seen_timestamp')\n    if timestamp:\n        channel = bot.db.get_nick_value(nick, 'seen_channel')\n        message = bot.db.get_nick_value(nick, 'seen_message')\n\n        tz = get_timezone(bot.db, bot.config, None, trigger.nick,\n                          trigger.sender)\n        saw = datetime.datetime.utcfromtimestamp(timestamp)\n        timestamp = format_time(bot.db, bot.config, tz, trigger.nick,\n                                trigger.sender, saw)\n\n        msg = \"I last saw {} at {}\".format(nick, timestamp)\n        if Identifier(channel) == trigger.sender:\n            msg = msg + \" in here, saying \" + message\n        else:\n            msg += \" in another channel.\"\n        bot.say(str(trigger.nick) + ': ' + msg)\n    else:\n        bot.say(\"Sorry, I haven't seen {} around.\".format(nick))\n\n\n@rule('(.*)')\n@priority('low')\ndef note(bot, trigger):\n    if not trigger.is_privmsg:\n        bot.db.set_nick_value(trigger.nick, 'seen_timestamp', time.time())\n        bot.db.set_nick_value(trigger.nick, 'seen_channel', trigger.sender)\n        bot.db.set_nick_value(trigger.nick, 'seen_message', trigger)\n", "path": "willie/modules/seen.py"}]}