Package: universal-notifications
UNMAINTAINEDPLEASE NOTE: this library is not actively maintained and receives
only minimal updates necessary.  Most of it is no longer in active use
at Ro.universal_notificationsHigh-level framework for notificationsThis project is intended to provide a convenient way to send notifications using multiple
notification backends (e.g., e-mail, SMS, push).Setting upTo start usinguniversal_notificationsplease adduniversal_notificationstoINSTALLED_APPSin your Django project, and then migrate the app:./manage.py migrate universal_notifications.If you intend to use any other type of notification than WS, then UNIVERSAL_NOTIFICATIONS_CATEGORIES
must be defined (seeUnsubscriber)Basic usageWebSocket notificationsE-mail notificationsSMS notificationsPush notificationsUnsubscriberUnsubscriber APIFakeEmailSend viewNotification historyWebSocket notificationsTo have Universal Notifications receive WS notifications (ie. to mark notification as received)
add to your settings.py:WS4REDIS_SUBSCRIBER = 'universal_notifications.backends.websockets.RedisSignalSubscriber'Upon receiving a WS, “ws_received” signal will be emitted with json data received in the message, and all emails
subscribed to that channel. Sample usage:fromuniversal_notifications.signalsimportws_receiveddefyour_handler(sender,message_data,channel_emails,**kwargs):passws_received.connect(your_handler)Simple example of using WS notifications:classOrderShippedWS(WSNotification):message='order_shipped'serializer_class=OrderSerializer# ... somewhere in a viewOrderShippedWS(item=order,receivers=[user],context={}).send()E-mail notificationsclassOrderShippedEmail(EmailNotification):email_name='order_shipped'email_subject=_('Order no. {{item.pk}} has been shipped.')categories=["newsletter"]sendgrid_asm={"group_id":1}use_premailer=False# disable Premailer for this email# ... somewhere in a viewOrderShippedEmail(item=order,receivers=[user],context={},attachments=[("invoice.pdf",open("invoice.pdf").read(),"application/pdf")]).send()Attachements parameter has to be a list of(filename, content, mime_type)triples.categories,sendgrid_asm,use_premailerfields are optional, they can be used withdjango-sendgridto enable metrics by category and unsubscribe groups.Email subject will be taken from the<title></title>tags in the template if it is not set in notification class.SettingsUNIVERSAL_NOTIFICATIONS_IS_SECURE (bool, default: False) - set https protocol andis_securevariableUNIVERSAL_NOTIFICATIONS_USE_PREMAILER (bool, default: True) - use premailer to append CSS styles inline (speedup tests a lot when False)SMS notificationsSupported platforms:Twilio- default engineAmazonSNSSettingsUNIVERSAL_NOTIFICATIONS_SMS_ENGINE - set engineUNIVERSAL_NOTIFICATIONS_VALIDATE_MOBILE (bool)UNIVERSAL_NOTIFICATIONS_SMS_SEND_IN_TASK (bool, default True)Engine settinsgs:TwilioUNIVERSAL_NOTIFICATIONS_TWILIO_API_ENABLED (bool)UNIVERSAL_NOTIFICATIONS_TWILIO_ENABLE_PROXY (bool)UNIVERSAL_NOTIFICATIONS_TWILIO_ACCOUNT (string)UNIVERSAL_NOTIFICATIONS_TWILIO_TOKEN (string)UNIVERSAL_NOTIFICATIONS_TWILIO_REPORT_ERRORS (list of integers)Amazon SNSUNIVERSAL_NOTIFICATIONS_AMAZON_SNS_API_ENABLED (bool)AWS_ACCESS_KEY_ID (string)AWS_SECRET_ACCESS_KEY (string)AWS_DEFAULT_REGION (string) - default us-east-1Simple example of use:classOrderShippedSMS(SMSNotification):message=_('{{receiver.first_name}}, order no. {{item.pk}} has been shipped.')defprepare_receivers(self):return{x.shipping_address.phoneforxinself.receivers}classSyncOrderShippedSMS(OrderShippedSMS):send_async=False# by default taken from UNIVERSAL_NOTIFICATIONS_SMS_SEND_IN_TASK# ... somewhere in a viewOrderShippedSMS(item=order,receivers=[user],context={}).send(Push notificationsFirst of all, to use push notifications, you must provide a list of availabledeviceslinked to users.
For more information, please check outsources.Supported platforms:FCM- Android, iOS, WebGCM- Android, iOS, WebAPNS- iOSTo make push notifications work on all supported platforms, a few properties need to be set:UNIVERSAL_NOTIFICATIONS_MOBILE_APPS[app_id]APNS_CERTIFICATE - APNS certificate file (.pem)FCM_API_KEY - Firebase API keyGCM_API_KEY - Google Cloud Messaging API keyGCM_POST_URL - Google Cloud Messaging post urlSettings related to Apple Push Notification service:APNS_HOSTAPNS_PORTAPNS_FEEDBACK_HOSTAPNS_FEEDBACK_PORTAPNS_ERROR_TIMEOUTAPNS_MAX_NOTIFICATION_SIZESimple example of use:classOrderShippedPush(PushNotification):title=_('Order no. {{item.pk}} has been shipped.')description=_('This can also use {{item.pk}}')# optional# ... somewhere in a viewOrderShippedPush(item=order,receivers=[user],context={}).send()UnsubscriberThis section refers to all notifications except WebSockets, which by default are not prone to unsubscriptions
(however this can be changed by setting check_subscription to True).Each category for each type must be explicitly declared in config (with label). If it is not there, exception
will be raised on attempt to send such notification. This requirement is to prevent situation, that notification
of given type is send to user who would not wish to receive it, but cannot unsubscribe from it (since it is not
present in the config).Since categories can be changed with configuration, labels should be specified for them, since they can’t be
hardcoded in client’s app.There is one special category: “system”. This category should not be declared in configuration, and notification
with such category will always pass.Sample configuration:UNIVERSAL_NOTIFICATIONS_CATEGORIES={"push":{"default":_("This is a label for default category you'll send to FE"),"chat":_('Category for chat messages'),"promotions":_('Promotions',)},"email":{"default":_("This is a label for default category you'll send to FE"),"chat":_('Category for chat messages'),"newsletter":_('Newsletter',)},"sms":{"default":_("This is a label for default category you'll send to FE"),"chat":_('Category for chat messages'),"newsletter":_('Newsletter',)},"test":{"default":_("This is a label for default category you'll send to FE"),},},If you want to allow different types of users to have different categories of notifications, you can
do it with configuration:# not required. If defined, specific types of users will only get notifications from allowed categories.# requires a bit more configuration - helper function to check if notification category is allowed for userUNIVERSAL_NOTIFICATIONS_USER_CATEGORIES_MAPPING={"for_admin":{"push":["default","chat","promotions"],"email":["default","chat","newsletter"],"sms":["default","chat","newsletter"]},"for_user":{"push":["default","chat","promotions"],"email":["default","newsletter"],# chat skipped"sms":["default","chat","newsletter"]}},# path to the file we will import user definitions for UNIVERSAL_NOTIFICATIONS_USER_CATEGORIES_MAPPINGUNIVERSAL_NOTIFICATIONS_USER_DEFINITIONS_FILE='tests.user_conf'# from file: tests/user_conf.pydeffor_admin(user):returnuser.is_superuserdeffor_user(user):returnnotuser.is_superuserIn the example above, functions “for_admin” & “for_user” should be defined in file tests/user_conf.py. Each
function takes user as a parameter, and should return either True or False.If given notification type is not present for given user, user will neither be able to receive it nor unsubscribe it.Unsubscriber APIThe current subscriptions can be obtained with a API described below. Please note, that API does not provide label for “unsubscribe_from_all”, since is always present and can be hardcoded in FE module. Categories however may vary, that’s why labels for them must be returned from BE.# GET /subscriptionsreturn{"unsubscribe_from_all":bool,# False by default"each_type_for_given_user":{"each_category_for_given_type_for_given_user":bool,# True(default) if subscribed, False if unsubscribed"unsubscribe_from_all":bool# False by default}"labels":{"each_type_for_given_user":{"each_category_for_given_type_for_given_user":string,}}}Unsubscriptions may be edited using following API:# PUT /subscriptionsdata={"unsubscribe_from_all":bool,# False by default"each_type_for_given_user":{"each_category_for_given_type_for_given_user":bool,# True(default) if subscribed, False if unsubscribed"unsubscribe_from_all":bool# False by default}}Please note, that if any type/category for type is ommited, it is reseted to default value.FakeEmailSend viewuniversal_notifications.backends.emails.views.FakeEmailSendis a view that helps testing email templates.
To start using it, addurl(r'^emails/',include('universal_notifications.backends.emails.urls'))to your urls.py, and specify receiver email address usingUNIVERSAL_NOTIFICATIONS_FAKE_EMAIL_TO.After that you can make a request to the new url withtemplateparameter, for instance:http://localhost:8000/emails/?template=reset_password, which  will send an email usingemails/email_reset_password.htmlas the template.Notification historyBy default all notifications that have been sent are stored in theNotificationHistoryobject in the database, but
this behavior can be changed, and therefore the database will not be used to store notification history (but you will
still receive notification history in your app log, on theinfolevel).To disable using database, setUNIVERSAL_NOTIFICATIONS_HISTORY_USE_DATABASEtoFalse(default:True),
and to disable any history tracking, setUNIVERSAL_NOTIFICATIONS_HISTORYtoFalse(default:True).