diff --git a/synapse/push/__init__.py b/synapse/push/__init__.py
index b6d01a82a0..4862d0de27 100644
--- a/synapse/push/__init__.py
+++ b/synapse/push/__init__.py
@@ -54,6 +54,9 @@ class Pusher(object):
self.failing_since = failing_since
self.alive = True
+ # The last value of last_active_time that we saw
+ self.last_last_active_time = 0
+
@defer.inlineCallbacks
def _actions_for_event(self, ev):
"""
@@ -273,6 +276,22 @@ class Pusher(object):
"""
pass
+ def reset_badge_count(self):
+ pass
+
+ def presence_changed(self, state):
+ """
+ We clear badge counts whenever a user's last_active time is bumped
+ This is by no means perfect but I think it's the best we can do
+ without read receipts.
+ """
+ if 'last_active' in state.state:
+ last_active = state.state['last_active']
+ if last_active > self.last_last_active_time:
+ logger.info("Resetting badge count for %s", self.user_name)
+ self.reset_badge_count()
+ self.last_last_active_time = last_active
+
def _value_for_dotted_key(dotted_key, event):
parts = dotted_key.split(".")
diff --git a/synapse/push/httppusher.py b/synapse/push/httppusher.py
index 22532fcc6a..d592bc2fd2 100644
--- a/synapse/push/httppusher.py
+++ b/synapse/push/httppusher.py
@@ -71,11 +71,12 @@ class HttpPusher(Pusher):
# we may have to fetch this over federation and we
# can't trust it anyway: is it worth it?
#'from_display_name': 'Steve Stevington'
- #'counts': { -- we don't mark messages as read yet so
+ 'counts': { #-- we don't mark messages as read yet so
# we have no way of knowing
- # 'unread': 1,
+ # Just set the badge to 1 until we have read receipts
+ 'unread': 1,
# 'missed_calls': 2
- # },
+ },
'devices': [
{
'app_id': self.app_id,
@@ -111,3 +112,34 @@ class HttpPusher(Pusher):
if 'rejected' in resp:
rejected = resp['rejected']
defer.returnValue(rejected)
+
+ @defer.inlineCallbacks
+ def reset_badge_count(self):
+ d = {
+ 'notification': {
+ 'id': '',
+ 'type': None,
+ 'from': '',
+ 'counts': {
+ 'unread': 0,
+ 'missed_calls': 0
+ },
+ 'devices': [
+ {
+ 'app_id': self.app_id,
+ 'pushkey': self.pushkey,
+ 'pushkey_ts': long(self.pushkey_ts / 1000),
+ 'data': self.data_minus_url,
+ }
+ ]
+ }
+ }
+ try:
+ resp = yield self.httpCli.post_json_get_json(self.url, d)
+ except:
+ logger.exception("Failed to push %s ", self.url)
+ defer.returnValue(False)
+ rejected = []
+ if 'rejected' in resp:
+ rejected = resp['rejected']
+ defer.returnValue(rejected)
\ No newline at end of file
diff --git a/synapse/push/pusherpool.py b/synapse/push/pusherpool.py
index 2dfecf178b..65ab4f46e1 100644
--- a/synapse/push/pusherpool.py
+++ b/synapse/push/pusherpool.py
@@ -18,6 +18,7 @@ from twisted.internet import defer
from httppusher import HttpPusher
from synapse.push import PusherConfigException
+from synapse.api.constants import PresenceState
import logging
import json
@@ -32,6 +33,22 @@ class PusherPool:
self.pushers = {}
self.last_pusher_started = -1
+ distributor = self.hs.get_distributor()
+ distributor.observe(
+ "user_presence_changed", self.user_presence_changed
+ )
+
+ @defer.inlineCallbacks
+ def user_presence_changed(self, user, state):
+ user_name = user.to_string()
+
+ # until we have read receipts, pushers use this to reset a user's
+ # badge counters to zero
+ for p in self.pushers.values():
+ if p.user_name == user_name:
+ yield p.presence_changed(state)
+
+
@defer.inlineCallbacks
def start(self):
pushers = yield self.store.get_all_pushers()
|