yeago/django-subscription

New Feature: Delivery

Closed this issue · 3 comments

Right now only emitting/sending of notifications is taken care of by (by Backends).

There are no options for Delivery of messages.

Sometimes, like the EmailBackend, there is no delivery, when you emit(), you are delivering.

So, my current idea (just based on Facebook really):

-Emit sends things to 'undelivered' list.
-A context processor or AJAX update or something moves it to the 'unacknowledged' list
-The user actively clicks on the notification and its now 'acknowledged'

Because my goal of this project is to allow as many people on the boat as possible, even people who don't find the above useful, I haven't included this. For now its here: https://github.com/subsume/django-subscription/blob/master/subscription/examples/redis-delivery.py

I'm thinking

SUBSCRIPTION_BACKENDS = {
   'redis': 'project.subscription_backends.RedisBackend',
   'email': 'project.subscription_backends.EmailBackend'
}

then Later:

notifications = Subscription.objects.user_delivery('redis',user_obj)

Now, what does 'notifications' look like? Maybe it doesn't matter, since the delivery() function will be completely custom to the backend author and you can return whatever you like.

jpic commented

Now, what does 'notifications' look like? Maybe it doesn't matter, since the delivery() function will be completely custom to the backend author and you can return whatever you like.

Three reasons to agree with you:

  • **kwargs are passed up to whatever method i want to override
  • the user can just subclass the backend and override the default serialization/deserialization functions
  • it worked for me ;)

The user actively clicks on the notification and its now 'acknowledged'

Facebook sorts notifications by kind, in the three notification icons you can see in the top left corner: poeple, chat and planet.

Maybe we could support that feature in python and js by default ... because maybe it's easier for the user to have a single queue with a system that supports multiple queues, than to implement multiple queues with a system that supports single queues.

I propose to do the sorting if a "queue" argument is passed. For example:

    Subscription.objects.emit(
        u'%(actor)s commented on %(target)s',
        subscribers_of=comment.content_object,
        dont_send_to=[comment.user],
        format_kwargs={
            'comment': comment,
        }, 
        actor=comment.user,
        queue='chat',
    )

    results = mybackend.user_delivery(group_by_kwarg='queue')

In that case, user_delivery() could return the list of undelivered notifications of the 'chat' queue in groups['undelivered']['chat'].

Of course, supporting this in JS is another story. But maybe we could provide a nice JS API which makes it easy to specify a list of queues.

What do you think of this feature ? Can you imagine how it could be useful to you too ?

jpic commented

We might need counts after all, because maybe you want to display the last 3 notifications in the facebook-ish dropdown, but still display the actual count... I shouldn't have trashed that code after all ...

Here a backend design proposal for the model part:

  • serialize(self, user, text, context): serialize a notification and kwargs for a particular user
  • unserialize(self, data): undo the above, those methods are optionnal
  • acknowledge(self, user, timestamp): push an activity from the unacknowledged queue to the acknoledged queue
  • emit(self,text,subscribers_of=None,dont_send_to=None,send_only_to=None,actor=None, actor_display_other=None,actor_display_self=None,context=None, queue=None): it's the renamed __init__, with format_kwargs and **kwargs merged into context, and queue added
  • user_emit(self,user,text,**kwargs): emit a notification for one user
  • purge(self, older_than): optionnal method to remove notifications that are older than the given argument (facebook only keeps them for 7 days i think)

As for the delivery method, here are the features i think can be useful to everybody (reversed from our own needs which is a facebook clone, including a notifications page per queue and a live notifications dropdown):

  • count annotations
  • optionnal grouping by state
  • optionnal grouping by queue
  • optionnal grouping by day
  • optionnal grouping by any combination of the above
  • optionnal filter by queue
  • limit: max number of notifications per group
  • an option for unserialise to not unserialize things that cannot be reserialised, because it is not needed to unserialise the datetime and then delete it in the view that re-serialises it in JSON for JS
  • an option to push undelivered to unacknowledged

So the arguments could look like this: get_notifications(self, user, clear_undelivered=True, group_by=None, queues=None, annotate_counts=False, limit=None, minimal_unserialisation=False)

When group_by can be a list with any of 'state', 'queue', 'group' in any order, and queues a list of queues to filter in.