hangupsthread: use hour timer to re-poll for presence

Google seems to forget to send us presence after a while, so if
nothing is heard in presence terms for an hour, repoll all the known
ids to retrigger google sending us presence notifications.

Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
diff --git a/hangupsthread.py b/hangupsthread.py
index 6708a36..ba78d55 100644
--- a/hangupsthread.py
+++ b/hangupsthread.py
@@ -21,6 +21,8 @@
 
         self.xmpp = xmpp
         self.remote = remote
+        self.presence_timer = None # filled in on first incoming presence
+        self.presence_timer_lock = threading.Lock()
 
         super().__init__(name='HangupsThread-{}'.format(remote))
 
@@ -39,6 +41,8 @@
         self.client.on_connect.fire()
         self.loop.run_until_complete(self.client.connect())
         logging.info('Hangups thread stopped for {}.'.format(self.remote))
+        if self.presence_timer is not None:
+            self.presence_timer.cancel()
 
     def _stop(self):
         yield from self.client.disconnect()
@@ -49,7 +53,23 @@
         if self.loop is not None:
             self.loop.call_soon_threadsafe(asyncio.async, self._stop())
 
+    def _presence_timer_run(self):
+        # if we haven't heard from google for a while, re-query all
+        # the presence states just to remind it that we exist
+        # without this, presence seems to get forgotten eventually
+        # by the server
+        logging.info('Presence Timer fired, requerying presence for {}'.format(self.remote))
+        self.loop.call_soon_threadsafe(asyncio.async, self._on_connect_common())
+
+    def presence_timer_reset(self):
+        with self.presence_timer_lock:
+            if self.presence_timer is not None:
+                self.presence_timer.cancel()
+            self.presence_timer = threading.Timer(3600, self._presence_timer_run)
+            self.presence_timer.start()
+
     def incoming_presence(self, user, pres):
+        self.presence_timer_reset()
         mood_message  = ''
         for segment in pres.mood_message.mood_content.segment:
             mood_message += segment.text