Try to keep to announcement schedule even if we miss an iteration.
authorCMDR furrycat <elite@furrycat.net>
Fri, 7 Oct 2016 09:12:04 +0000 (10:12 +0100)
committerCMDR furrycat <elite@furrycat.net>
Fri, 7 Oct 2016 09:12:04 +0000 (10:12 +0100)
bot.py
db.py

diff --git a/bot.py b/bot.py
index 52483f1..e35c44c 100755 (executable)
--- a/bot.py
+++ b/bot.py
@@ -1104,6 +1104,27 @@ def manage_announcements(message, command, raw):
 
 @asyncio.coroutine
 def announce(announcement):
+  # Adhere to schedule.
+  last_spoke = None
+  if announcement['interval']:
+    if announcement['start_date'] or announcement['last_spoke']:
+      now = int(time.time())
+      if announcement['start_date']:
+        start = announcement['start_date']
+      else:
+        start = announcement['last_spoke']
+      intervals = math.floor((now - start) / announcement['interval'])
+      if intervals:
+        # We missed a schedule.
+        scheduled = start + intervals * announcement['interval']
+        if now - scheduled > max(60, announcement['interval'] / 2):
+          log.info('Announcement {} should have been given at {}'.format(announcement['id'], iso8601(scheduled)))
+          db.set_announcement(client, announcement['id'], digest = announcement['digest'] if 'digest' in announcement else None, last_spoke = scheduled)
+          return
+      # Give the announcement now but set the original schedule.
+      last_spoke = start + announcement['interval']
+      log.info('Forcing last_spoke for announcement {} to {} in line with schedule'.format(announcement['id'], iso8601(last_spoke)))
+
   channel = None
   channel_id = str(announcement['channel_id'])
   if channel_id == 'private':
@@ -1119,7 +1140,7 @@ def announce(announcement):
   if channel is None:
     log.warning("Can't get channel for announcement {}".format(announcement['id']))
     # Set last_spoke so we don't spam.
-    db.set_announcement(client, announcement['id'], announcement['digest'] if 'digest' in announcement else None)
+    db.set_announcement(client, announcement['id'], digest = announcement['digest'] if 'digest' in announcement else None, last_spoke = last_spoke)
     return
 
   voice_only = announcement['voice_id'] == announcement['channel_id']
@@ -1165,7 +1186,7 @@ def announce(announcement):
       else:
         log.info("Didn't bother with announcement {}".format(announcement['id']))
       # Set last_spoke even if we chose not to announce.
-      db.set_announcement(client, announcement['id'], digest)
+      db.set_announcement(client, announcement['id'], digest = digest, last_spoke = last_spoke)
       if not announce:
         return
       if announcement['voice_id']:
diff --git a/db.py b/db.py
index 1217bdf..409d7fa 100644 (file)
--- a/db.py
+++ b/db.py
@@ -106,9 +106,10 @@ class DBConnection(object):
       yield dict(row)
     self.close_db()
 
-  def set_announcement(self, client, id, digest):
-    now = self.now()
-    cursor = self.query('update announcements set last_spoke=?, digest=? where id=?', [now, digest, id])
+  def set_announcement(self, client, id, digest = None, last_spoke = None):
+    if last_spoke is None:
+      last_spoke = self.now()
+    cursor = self.query('update announcements set last_spoke=?, digest=? where id=?', [last_spoke, digest, id])
     self.dbh.commit()
     self.close_db()