Giter Club home page Giter Club logo

django-push-notifications's Introduction

django-push-notifications

Jazzband

GitHub Actions

Code coverage

A minimal Django app that implements Device models that can send messages through APNS, FCM/GCM, WNS and WebPush.

The app implements four models: GCMDevice, APNSDevice, WNSDevice and WebPushDevice. Those models share the same attributes:
  • name (optional): A name for the device.
  • active (default True): A boolean that determines whether the device will be sent notifications.
  • user (optional): A foreign key to auth.User, if you wish to link the device to a specific user.
  • device_id (optional): A UUID for the device obtained from Android/iOS/Windows APIs, if you wish to uniquely identify it.
  • registration_id (required): The FCM/GCM registration id or the APNS token for the device.

The app also implements an admin panel, through which you can test single and bulk notifications. Select one or more FCM/GCM, APNS, WNS or WebPush devices and in the action dropdown, select "Send test message" or "Send test message in bulk", accordingly. Note that sending a non-bulk test message to more than one device will just iterate over the devices and send multiple single messages. UPDATE_ON_DUPLICATE_REG_ID: Transform create of an existing Device (based on registration id) into a update. See below Update of device with duplicate registration ID for more details.

Dependencies

  • Python 3.7+
  • Django 2.2+
  • For the API module, Django REST Framework 3.7+ is required.
  • For WebPush (WP), pywebpush 1.3.0+ is required (optional). py-vapid 1.3.0+ is required for generating the WebPush private key; however this step does not need to occur on the application server.
  • For Apple Push (APNS), apns2 0.3+ is required (optional).
  • For FCM, firebase-admin 6.2+ is required (optional).

Setup

You can install the library directly from pypi using pip:

$ pip install django-push-notifications[WP,APNS,FCM]

Edit your settings.py file:

INSTALLED_APPS = (
    ...
    "push_notifications"
)

# Import the firebase service
from firebase_admin import auth

# Initialize the default app (either use `GOOGLE_APPLICATION_CREDENTIALS` environment variable, or pass a firebase_admin.credentials.Certificate instance)
default_app = firebase_admin.initialize_app()

PUSH_NOTIFICATIONS_SETTINGS = {
    "APNS_CERTIFICATE": "/path/to/your/certificate.pem",
    "APNS_TOPIC": "com.example.push_test",
    "WNS_PACKAGE_SECURITY_ID": "[your package security id, e.g: 'ms-app://e-3-4-6234...']",
    "WNS_SECRET_KEY": "[your app secret key, e.g.: 'KDiejnLKDUWodsjmewuSZkk']",
    "WP_PRIVATE_KEY": "/path/to/your/private.pem",
    "WP_CLAIMS": {'sub': "mailto:[email protected]"}
}

Note

To migrate from legacy FCM APIs to HTTP v1, see docs/FCM.

Note

If you need to support multiple mobile applications from a single Django application, see Multiple Application Support for details.

Note

If you are planning on running your project with APNS_USE_SANDBOX=True, then make sure you have set the development certificate as your APNS_CERTIFICATE. Otherwise the app will not be able to connect to the correct host. See settings for details.

For more information about how to generate certificates, see docs/APNS.

You can learn more about APNS certificates here.

Native Django migrations are in use. manage.py migrate will install and migrate all models.

Settings list

All settings are contained in a PUSH_NOTIFICATIONS_SETTINGS dict.

For APNS, you are required to include APNS_CERTIFICATE. For WNS, you need both the WNS_PACKAGE_SECURITY_KEY and the WNS_SECRET_KEY.

General settings

  • USER_MODEL: Your user model of choice. Eg. myapp.User. Defaults to settings.AUTH_USER_MODEL.
  • UPDATE_ON_DUPLICATE_REG_ID: Transform create of an existing Device (based on registration id) into a update. See below Update of device with duplicate registration ID for more details.
  • UNIQUE_REG_ID: Forces the registration_id field on all device models to be unique.

APNS settings

  • APNS_CERTIFICATE: Absolute path to your APNS certificate file. Certificates with passphrases are not supported. If iOS application was build with "Release" flag, you need to use production certificate, otherwise debug. Read more about Generation of an APNS PEM file.
  • APNS_AUTH_KEY_PATH: Absolute path to your APNS signing key file for Token-Based Authentication . Use this instead of APNS_CERTIFICATE if you are using .p8 signing key certificate.
  • APNS_AUTH_KEY_ID: The 10-character Key ID you obtained from your Apple developer account
  • APNS_TEAM_ID: 10-character Team ID you use for developing your company’s apps for iOS.
  • APNS_TOPIC: The topic of the remote notification, which is typically the bundle ID for your app. If you omit this header and your APNs certificate does not specify multiple topics, the APNs server uses the certificate’s Subject as the default topic.
  • APNS_USE_ALTERNATIVE_PORT: Use port 2197 for APNS, instead of default port 443.
  • APNS_USE_SANDBOX: Use 'api.development.push.apple.com', instead of default host 'api.push.apple.com'. Default value depends on DEBUG setting of your environment: if DEBUG is True and you use production certificate, you should explicitly set APNS_USE_SANDBOX to False.

FCM/GCM settings

  • FIREBASE_APP: Firebase app instance that is used to send the push notification. If not provided, the app will be using the default app instance that you've instantiated with firebase_admin.initialize_app().
  • FCM_MAX_RECIPIENTS: The maximum amount of recipients that can be contained per bulk message. If the registration_ids list is larger than that number, multiple bulk messages will be sent. Defaults to 1000 (the maximum amount supported by FCM).

WNS settings

  • WNS_PACKAGE_SECURITY_KEY: TODO
  • WNS_SECRET_KEY: TODO

WP settings

  • WP_PRIVATE_KEY: Absolute path to your private certificate file: os.path.join(BASE_DIR, "private_key.pem")
  • WP_CLAIMS: Dictionary with default value for the sub, (subject), sent to the webpush service, This would be used by the service if they needed to reach out to you (the sender). Could be a url or mailto e.g. {'sub': "mailto:[email protected]"}.
  • WP_ERROR_TIMEOUT: The timeout on WebPush POSTs. (Optional)

For more information about how to configure WebPush, see docs/WebPush.

Sending messages

FCM/GCM and APNS services have slightly different semantics. The app tries to offer a common interface for both when using the models.

from push_notifications.models import APNSDevice, GCMDevice

device = GCMDevice.objects.get(registration_id=gcm_reg_id)
# The first argument will be sent as "message" to the intent extras Bundle
# Retrieve it with intent.getExtras().getString("message")
device.send_message("You've got mail")
# If you want to customize, send an extra dict and a None message.
# the extras dict will be mapped into the intent extras Bundle.
# For dicts where all values are keys this will be sent as url parameters,
# but for more complex nested collections the extras dict will be sent via
# the bulk message api.
device.send_message(None, extra={"foo": "bar"})
device.send_message(None, extra={"foo": "bar"}, use_fcm_notifications=False) # Silent message with custom data.
# You may also pass a Firebase message object.
device.send_message(messaging.Message(
notification=messaging.Notification(

title='Hello World', body='What a beautiful day.'

),

)) # If you want to use gcm.send_message directly, you will have to use messaging.Message.

device = APNSDevice.objects.get(registration_id=apns_token) device.send_message("You've got mail") # Alert message may only be sent as text. device.send_message(None, badge=5) # No alerts but with badge. device.send_message(None, content_available=1, extra={"foo": "bar"}) # Silent message with custom data. # alert with title and body. device.send_message(message={"title" : "Game Request", "body" : "Bob wants to play poker"}, extra={"foo": "bar"}) device.send_message("Hello again", thread_id="123", extra={"foo": "bar"}) # set thread-id to allow iOS to merge notifications

Note

APNS does not support sending payloads that exceed 2048 bytes (increased from 256 in 2014). The message is only one part of the payload, if once constructed the payload exceeds the maximum size, an APNSDataOverflow exception will be raised before anything is sent. Reference: Apple Payload Documentation

Web Push accepts only one variable (message), which is passed directly to pywebpush. This message can be a simple string, which will be used as your notification's body, or it can be contain any data supported by pywebpush<https://github.com/web-push-libs/pywebpush>.

Simple example:

from push_notifications.models import WebPushDevice

device = WebPushDevice.objects.get(registration_id=wp_reg_id)

device.send_message("You've got mail")

Note

To customize the notification title using this method, edit the "TITLE DEFAULT" string in your navigatorPush.service.js file.

JSON example:

import json
from push_notifications.models import WebPushDevice

device = WebPushDevice.objects.get(registration_id=wp_reg_id)

title = "Message Received"
message = "You've got mail"
data = json.dumps({"title": title, "message": message})

device.send_message(data)

Sending messages in bulk

from push_notifications.models import APNSDevice, GCMDevice

devices = GCMDevice.objects.filter(user__first_name="James")
devices.send_message("Happy name day!")

Sending messages in bulk makes use of the bulk mechanics offered by GCM and APNS. It is almost always preferable to send bulk notifications instead of single ones.

It's also possible to pass badge parameter as a function which accepts token parameter in order to set different badge value per user. Assuming User model has a method get_badge returning badge count for a user:

devices.send_message(
    "Happy name day!",
    badge=lambda token: APNSDevice.objects.get(registration_id=token).user.get_badge()
)

Firebase

django-push-notifications supports Firebase Cloud Messaging v1.

When using FCM, django-push-notifications will automatically use the notification and data messages format to be conveniently handled by Firebase devices. You may want to check the payload to see if it matches your needs, and review your notification statuses in FCM Diagnostic console.

# Create a FCM device
fcm_device = GCMDevice.objects.create(registration_id="token", user=the_user)

# Send a notification message
fcm_device.send_message("This is a message")

# Send a notification message with additionnal payload
fcm_device.send_message("This is a enriched message", extra={"title": "Notification title", "icon": "icon_ressource"})

# Send a notification message with additionnal payload (alternative syntax)
fcm_device.send_message("This is a enriched message", title="Notification title", badge=6)

# Send a notification message with extra data
fcm_device.send_message("This is a message with data", extra={"other": "content", "misc": "data"})

# Send a notification message with options
fcm_device.send_message("This is a message", time_to_live=3600)

# Send a data message only
fcm_device.send_message(None, extra={"other": "content", "misc": "data"})

Behind the scenes, a Firebase Message will be created. You can also create this yourself and pass it to the send_message method instead.

Sending FCM/GCM messages to topic members

FCM/GCM topic messaging allows your app server to send a message to multiple devices that have opted in to a particular topic. Based on the publish/subscribe model, topic messaging supports unlimited subscriptions per app. Developers can choose any topic name that matches the regular expression, "/topics/[a-zA-Z0-9-_.~%]+". Note: gcm_send_bulk_message must be used when sending messages to topic subscribers, and setting the first param to any value other than None will result in a 400 Http error.

from push_notifications.gcm import send_message, dict_to_fcm_message

# Create message object from dictonary. You can also directly create a messaging.Message object.
message = dict_to_fcm_message({"body": "Hello members of my_topic!"})
# First param is "None" because no Registration_id is needed, the message will be sent to all devices subscribed to the topic.
send_message(None, message, to="/topics/my_topic")

Reference: FCM Documentation

Exceptions

  • NotificationError(Exception): Base exception for all notification-related errors.
  • apns.APNSError(NotificationError): Something went wrong upon sending APNS notifications.
  • apns.APNSDataOverflow(APNSError): The APNS payload exceeds its maximum size and cannot be sent.

Django REST Framework (DRF) support

ViewSets are available for both APNS and GCM devices in two permission flavors:

  • APNSDeviceViewSet and GCMDeviceViewSet

    • Permissions as specified in settings (AllowAny by default, which is not recommended)
    • A device may be registered without associating it with a user
  • APNSDeviceAuthorizedViewSet and GCMDeviceAuthorizedViewSet

    • Permissions are IsAuthenticated and custom permission IsOwner, which will only allow the request.user to get and update devices that belong to that user
    • Requires a user to be authenticated, so all devices will be associated with a user

When creating an APNSDevice, the registration_id is validated to be a 64-character or 200-character hexadecimal string. Since 2016, device tokens are to be increased from 32 bytes to 100 bytes.

Routes can be added one of two ways:

from push_notifications.api.rest_framework import APNSDeviceAuthorizedViewSet, GCMDeviceAuthorizedViewSet
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register(r'device/apns', APNSDeviceAuthorizedViewSet)
router.register(r'device/gcm', GCMDeviceAuthorizedViewSet)

urlpatterns = patterns('',
    # URLs will show up at <api_root>/device/apns
    url(r'^', include(router.urls)),
    # ...
)
  • Using as_view (specify which views to include)
from push_notifications.api.rest_framework import APNSDeviceAuthorizedViewSet

urlpatterns = patterns('',
    # Only allow creation of devices by authenticated users
    url(r'^device/apns/?$', APNSDeviceAuthorizedViewSet.as_view({'post': 'create'}), name='create_apns_device'),
    # ...
)

Update of device with duplicate registration ID

The DRF viewset enforce the uniqueness of the registration ID. In same use case it may cause issue: If an already registered mobile change its user and it will fail to register because the registration ID already exist.

When option UPDATE_ON_DUPLICATE_REG_ID is set to True, then any creation of device with an already existing registration ID will be transformed into an update.

The UPDATE_ON_DUPLICATE_REG_ID only works with DRF.

django-push-notifications's People

Contributors

antwan avatar arthurprs avatar bertonha avatar brad avatar ceoy avatar datagreed avatar emperorcezar avatar evdoks avatar fpurchess avatar galedragon avatar goinnn avatar hohenstaufen avatar jackfengji avatar jamaalscarlett avatar jezdez avatar jleclanche avatar koutoftimer avatar kronosapiens avatar lukeburden avatar matthewh avatar odinuge avatar pre-commit-ci[bot] avatar randomknowledge avatar sevdog avatar simonkern avatar sww314 avatar t-io avatar ticosax avatar vially avatar wtayyeb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-push-notifications's Issues

bigint out of range

Im getting a bigint out of range exception in my app. Im using Apache cordova to build my app and the device id im getting is 'ecb1c3515b1474cc'. Im using device.uuid to get this number. Any help is really appreciated

Encoding problem (it seems)

Hello,

I'm doing some tests to use this library in the backend for my app. I've managed to register and android device but when I'm trying to send a test message the following exception arises:

'dict' object has no attribute 'encode'
Request Method: GET
Request URL: http://192.168.100.9:8000/pedidos/testpush/send/
Django Version: 1.6.1
Exception Type: AttributeError
Exception Value:
'dict' object has no attribute 'encode'
Exception Location: /usr/local/lib/python3.3/dist-packages/push_notifications/gcm.py in gcm_send_message, line 70
Python Executable: /usr/bin/python3m
Python Version: 3.3.2
Python Path:
['/home/nicolas/app-domicilios/backend',
'/home/nicolas/app-domicilios/backend/src/django-uuidfield',
'/home/nicolas/app-domicilios/backend',
'/usr/lib/python3.3',
'/usr/lib/python3.3/plat-x86_64-linux-gnu',
'/usr/lib/python3.3/lib-dynload',
'/usr/local/lib/python3.3/dist-packages',
'/usr/lib/python3/dist-packages']

I'm using django-rest-framework and Python3. The following code executes when I'm trying to send the message:

@api_view(['GET'])
def send(request):
if request.method == 'GET':

    devices = GCMDevice.objects.all()
    for d in devices:
        d.send_message({"teeesst": "yeeeees"})

    template = loader.get_template('pedidos/index.html')
    context = RequestContext(request, {
        'devices': devices,
    })

    return HttpResponse(template.render(context))

I don't know what is the problem.

Thank you in advance!

Python3 compatibility

hello.
I have tested GCM push on python 3.

error occured.

(InteractiveConsole)
>>> from push_notifications.models import GCMDevice
>>> GCMDevice.objects.filter(name='1')
[<GCMDevice: GCMDevice object>]
>>> GCMDevice.objects.filter(name='1').send_message({'A':'B'})
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python33\lib\site-packages\push_notifications\models.py", line 37, in
 send_message
    collapse_key="message"
  File "C:\Python33\lib\site-packages\push_notifications\gcm.py", line 102, in g
cm_send_bulk_message
    return _gcm_send(data, "application/json")
  File "C:\Python33\lib\site-packages\push_notifications\gcm.py", line 47, in _g
cm_send
    response = urlopen(request)
  File "C:\Python33\lib\urllib\request.py", line 156, in urlopen
    return opener.open(url, data, timeout)
  File "C:\Python33\lib\urllib\request.py", line 467, in open
    req = meth(req)
  File "C:\Python33\lib\urllib\request.py", line 1179, in do_request_
    raise TypeError(msg)
TypeError: POST data should be bytes or an iterable of bytes. It cannot be of ty
pe str.

so, I modifed source code. gcm.py (101)

data = json.dumps(values)
# to
data = json.dumps(values).encode('utf-8')

test once again
error occured

(InteractiveConsole)
>>> from push_notifications.models import GCMDevice
>>> GCMDevice.objects.filter(name='1').send_message({'A':'B'})
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python33\lib\site-packages\push_notifications\models.py", line 37, in
 send_message
    collapse_key="message"
  File "C:\Python33\lib\site-packages\push_notifications\gcm.py", line 102, in g
cm_send_bulk_message
    return _gcm_send(data, "application/json")
  File "C:\Python33\lib\site-packages\push_notifications\gcm.py", line 50, in _g
cm_send
    if result.startswith("Error="):
TypeError: startswith first arg must be bytes or a tuple of bytes, not str

so, I modified source code. gcm.py (48)

result = response.read()
# to
result = response.read().decode('utf-8')

try test again.

message sent to my android phone. very well :)
thanks to read.

Development and Production Certificates

Sweet library, thanks for creating :)! Is there a way to specify both the development and production certificates so it automatically uses the correct one when on dev vs production? Thanks!

APNS Feedback service seems broken

I tried to test the feedback service but it returns only a empty list. But maybe I do something wrong

  1. send notification to 2 devices --> both received (no sandbox devices)

  2. delete app from one device

  3. send another notification to both devices --> one received

  4. run code in shell_plus:
    from push_notifications.models import _apns_create_socket
    print get_expired_tokens()

    get_expired_tokens() always returns a empty list.

Extending the models

Hi Team.

I would like to extend the basics models of django-push-notification.
How would be the best way to do that?

Thanks for your greate job!

South Support

It would be nice to have an initial south migration file coming with django-push-notifications

Unknown column 'push_notifications_apnsdevice.date_created' in 'field list'

I'm getting an error because I updated from 1.0.1 to 1.1.0, which includes some new model fields. I also see that there is a matching migration for this change. I currently have this library as an installed application in a Django 1.7 app. What is the best way to run this migration (or otherwise update the database to the proper state)?

is_active vs active flag

according to the doc, the flag is "is_active" but it's actually "active", it's also "active" as the column name on the created tables

Migration Errors

Somehow a new migration slipped in, that broke our integration since it refers to a custom user object 'accounts.User'.

"django.db.utils.DatabaseError: relation "accounts_user" does not exist"

btw: what do you think about integration tests? ;-)

Pip install broken for version 0.9

(buddyup)george@george-ubuntu:~/buddyup$ pip install django-push-notifications
Downloading/unpacking django-push-notifications
Downloading django-push-notifications-0.9.tar.gz
Running setup.py egg_info for package django-push-notifications
Traceback (most recent call last):
  File "<string>", line 16, in <module>
  File "/home/george/.virtualenvs/buddyup/build/django-push-notifications/setup.py", line 6, in <module>
    README = open(os.path.join(os.path.dirname(__file__), "README.rst")).read()
IOError: [Errno 2] No such file or directory: '/home/george/.virtualenvs/buddyup/build/django-push-notifications/README.rst'
Complete output from command python setup.py egg_info:
Traceback (most recent call last):

File "<string>", line 16, in <module>

File "/home/george/.virtualenvs/buddyup/build/django-push-notifications/setup.py", line 6, in <module>

README = open(os.path.join(os.path.dirname(__file__), "README.rst")).read()

IOError: [Errno 2] No such file or directory:      '/home/george/.virtualenvs/buddyup/build/django-push-notifications/README.rst'

----------------------------------------
Command python setup.py egg_info failed with error code 1 in     /home/george/.virtualenvs/buddyup/build/django-push-notifications

GCM device id displayed as integer in admin

When edit a GCM device record the id value is displayed as integer but the field require hex value to validate the form.

You have to convert the integer value in hex manually before save the record.

Encountered "error: [Errno 32] Broken pipe" when push in bulk to APNS

Encountered error when push in bulk to APNS.

Traceback (most recent call last):
  File "app/tasks.py", line 172, in push_bulk
    apns_devices.send_message(message=message, extra=extra)
  File "/home/user/.virtualenvs/user/local/lib/python2.7/site-packages/push_notifications/models.py", line 68, in send_message
    return apns_send_bulk_message(registration_ids=list(self.values_list("registration_id", flat=True)), data=message, **kwargs)
  File "/home/user/.virtualenvs/user/local/lib/python2.7/site-packages/push_notifications/apns.py", line 113, in apns_send_bulk_message
    _apns_send(registration_id, data, socket=socket, **kwargs)
  File "/home/user/.virtualenvs/user/local/lib/python2.7/site-packages/push_notifications/apns.py", line 87, in _apns_send
    socket.write(data)
  File "/usr/lib/python2.7/ssl.py", line 172, in write
    return self._sslobj.write(data)
error: [Errno 32] Broken pipe

Removing the unique device constraint

I want to remove the unique device id constraint - there are a lot of situations where we want to allow multiple users to register on the same device. What's the best way to do this? Also does removing the constraint on the db level (/ model level? ) cause any parts of the code to change in its function?

PEM key asked

Hello, I'm trying to send push notifications to iOS but it keeps asking me the PEM passphrase key when I try to send a notification. What can I do?

Binary Interface Version

Hi all,

Thanks for your work on this package. I've noticed that you are using a relatively old binary interface (version 0, as opposed to the current version 2). Do you have plans on changing the interface that you use? Do you see any advantages in using version 0? From my understanding, versions 1 and 2 might give more descriptive feedback whereas version 0 (at least when it was first released) simply closed the connection if bad data were received.

Thanks!
aryeh

New south migrations are not backwards compatible

Hey guys,

By coincidence, by running a test with my deployment, just noticed that the new migrations that you introduced are not compatible with older versions of Django, as it uses accounts.user rather than auth.user.

APNS_FEEDBACK_HOST setting is mixed up for production and sandbox environments

Current state:

if settings.DEBUG:
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_HOST", "gateway.sandbox.push.apple.com")
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_FEEDBACK_HOST", "feedback.push.apple.com")
else:
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_HOST", "gateway.push.apple.com")
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_FEEDBACK_HOST", "feedback.sandbox.push.apple.com")

should be:

if settings.DEBUG:
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_HOST", "gateway.sandbox.push.apple.com")
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_FEEDBACK_HOST", "feedback.sandbox.push.apple.com")
else:
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_HOST", "gateway.push.apple.com")
    PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_FEEDBACK_HOST", "feedback.push.apple.com")

can't install package

Hi @adys,

I just realized there is a small issue of whom it's not possible to install the package.
The setup.py refers to the django settings - which leads to an exception during installation, because the django environment is initialized when in pip-context (stracktrace below)

https://github.com/Adys/django-push-notifications/blob/master/push_notifications/__init__.py#L8

I'd suggest to store the reference to the settings somewhere else than init.py
If you tell me where you'd like to store the reference, i can write a fix.

Cheers,
Florian

Running setup.py egg_info for package django-push-notifications
    Traceback (most recent call last):
      File "<string>", line 16, in <module>
      File "django-push-notifications/setup.py", line 24, in <module>
        import push_notifications
      File "push_notifications/__init__.py", line 8, in <module>
        PUSH_NOTIFICATIONS_SETTINGS = getattr(settings, "PUSH_NOTIFICATIONS_SETTINGS", {})
      File ".env/local/lib/python2.7/site-packages/django/utils/functional.py", line 184, in inner
        self._setup()
      File ".env/local/lib/python2.7/site-packages/django/conf/__init__.py", line 40, in _setup
        raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
    ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
  File "<string>", line 16, in <module>
  File ".env/src/django-push-notifications/setup.py", line 24, in <module>
    import push_notifications
  File "push_notifications/__init__.py", line 8, in <module>
    PUSH_NOTIFICATIONS_SETTINGS = getattr(settings, "PUSH_NOTIFICATIONS_SETTINGS", {})
  File ".env/local/lib/python2.7/site-packages/django/utils/functional.py", line 184, in inner
    self._setup()
  File ".env/local/lib/python2.7/site-packages/django/conf/__init__.py", line 40, in _setup
    raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
----------------------------------------
Command python setup.py egg_info failed with error code 1 in .env/src/django-push-notifications

Exception information:
Traceback (most recent call last):
  File ".env/local/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg/pip/basecommand.py", line 107, in main
    status = self.run(options, args)
  File ".env/local/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg/pip/commands/install.py", line 256, in run
    requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
  File ".env/local/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg/pip/req.py", line 993, in prepare_files
    req_to_install.run_egg_info()
  File ".env/local/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg/pip/req.py", line 236, in run_egg_info
    command_desc='python setup.py egg_info')
  File ".env/local/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg/pip/util.py", line 612, in call_subprocess
    % (command_desc, proc.returncode, cwd))
InstallationError: Command python setup.py egg_info failed with error code 1 in .env/src/django-push-notifications

global name 'urllib2' is not defined

Hi @adys,

You refer to urllib2, but have a condition importing urllib instead of urllib2 if present. This leads to errors when urllib2 is not defined. The cause it that no push notification can be sent at all.

The first occurence, that I saw was: 7028bfd

Cheers,
Florian

API for APNS Feedback service

When sending bulk messages, if there is a device token that's no longer installed, and you send a message to all the users, it fails silently.

It seems like it's possible to get an error on the first failed device, although I'm not sure about that. But, even if it was, if there were several, it would mean repeated calls until all of them were removed.

The best way to remove the invalid id's is to use the feedback service. For what it's worth, I've hacked this together, and I can clean it up if there isn't already something close to being done.

GCMDevice registration_id is not unique

Because registration_id is a text field and has variable length.
But I think it is a very important property, just as you said in another issue.
Can we use Charfield (255) instead?

Binary packing breaks APNS message sending in Python 3

With django-push-notifications 1.0.1 on Python 3.4, I try to send an APNS message with the example code found on the PyPI page. I get this traceback:

  File "/venv/lib/python3.4/site-packages/push_notifications/models.py", line 83, in send_message
    return apns_send_message(registration_id=self.registration_id, data=message, **kwargs)
  File "/venv/lib/python3.4/site-packages/push_notifications/apns.py", line 104, in apns_send_message
    return _apns_send(registration_id, data, **kwargs)
  File "/venv/lib/python3.4/site-packages/push_notifications/apns.py", line 85, in _apns_send
    data = _apns_pack_message(token, data)
  File "/venv/lib/python3.4/site-packages/push_notifications/apns.py", line 50, in _apns_pack_message
    return struct.pack(format, b"\0", 32, unhexlify(token), len(data), data)
struct.error: argument for 's' must be a bytes object

I created this little block of code to test how it works differently in Python 3.4:

import struct
from binascii import unhexlify
format = '!cH32sH40s'
token = '985f786c2e0ac57f2e371409a660e5d22fbc291c77fd795df3048f8e3cb3df7f'
data = '{"aps":{"sound":"chime","alert":"Ping"}}'
struct.pack(format, b"\0", 32, unhexlify(token), 40, data)

# In Python 2.7.6, you get this:
#'\x00\x00 \x98_xl.\n\xc5\x7f.7\x14\t\xa6`\xe5\xd2/\xbc)\x1cw\xfdy]\xf3\x04\x8f\x8e<\xb3\xdf\x7f\x00({"aps":{"sound":"chime","alert":"Ping"}}'

# In Python 3.4, you get this:
# *** struct.error: argument for 's' must be a bytes object

I think the difference is in how Python 3 handles the b"\0" string, but I can't make it work.

Examples in documentation are incorrect

I believe what you mean is:

device = GCMDevice( registration_id = client.device_token )
device.send_message( "string" )

device = APNSDevice( registration_id = client.device_token )
device.send_message( "string" )

Where is the log?

Thanks for the author,first.
I have an problem when using this app. When I try to send message in admin backend or by code, my phone did not get any notification. Why it fail? How to get the log, so that I can debug it?
I don't have any clue.
Who can help me? Thanks!

Wrong key used for messages

Using this django app to send messages will crash apps built with PhoneGap and using the PhoneGap push notification plugin. It's because the use of "msg" instead of "message" to key the message. This commit fixes the problem:

tsanders-kalloop@853fb89

Move to setuptools

Based on a comment by @jleclanche - move from using distutils to setuptools.

I've prepared a simple pull request that works on my machine, but doesn't really take advantage of setuptools - What is it that you'd want to get out of this?

Question: APNS_ERROR_TIMEOUT in _apns_check_errors

This is rather a question than an issue

I'm noticing, that when I'm sending an Apple push notifications to a malformed device id, no error is thrown. When checking _apns_check_errors() function in apns.py in the very beginning I see the following:

timeout = SETTINGS["APNS_ERROR_TIMEOUT"]
    if timeout is None:
        return  # assume everything went fine!

Meanwhile settings.py default APNS_ERROR_TIMEOUT to None. If I understand it correctly, if APNS_ERROR_TIMEOUT is not manually assigned to some number, APNS will never be asked for an error code.

Is it the expected behaviour?

Documentation is very useful

Hey men, i'm very interesting in this app, but, is very difficult use him, you haven't something docs or examples, can you make some examples or docs?

Thank you

Please, label: question :D

Migration problem.

Error in migration: push_notifications:0001_initial
DatabaseError: (1170, "BLOB/TEXT column 'registration_id' used in key specification without a key length")

SSLV3_ALERT_HANDSHAKE_FAILURE error

I am on Django 1.7 with Python 3.3 and followed all the instructions on your README file. I have the absolute path for the pem file in PUSH_NOTIFICATIONS_SETTINGS. Yet, when I try to send a push notification, it throws

[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:548)

I am able to send a push notification using a simple php script (with device_token the same registration_id) and the sam pem file though. Any thoughts?

Sujit

Encoding issues when sending test notification to Android device

Hi,

I just discovered this django app and it seems like it answers exactly the problem of managing easily both Android and iOS devices. That's truly awesome work!

However, when installing it on my Django1.6/Python3 setup, I encounter an error when sending a test notification (sending a test notification in bulk works just fine).

TypeError at /admin/push_notifications/gcmdevice/
POST data should be bytes or an iterable of bytes. It cannot be of type str.

I could solve the problem by changing line 73 of gcm.py from
data = urlencode(values)
to
data = urlencode(values).encode('utf-8')

However, I ignore if it causes a compatibility problem with Python2.

Sending json to GCM

There is a comment in the example code:

the extras dict will be maped into the intent extras Bundle. Remember, GCM converts everything to strings!

This is actually because you are sending the extras bundle encoded in the url, as opposed to sending a json body. The manner in which this is done causes an extras bundle with non-string values to raise an exception, as you try to call .encode('utf-8') on them. A better solution would be to send as json, as you do for the bulk messages.

I am preparing a pull request to make these adjustments

Typo in PUSH_NOTIFICATIONS_SETTINGS

PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_FEEDBACK_HOST", "feedback.push.apple")

should be
PUSH_NOTIFICATIONS_SETTINGS.setdefault("APNS_FEEDBACK_HOST", "feedback.push.apple.com")

[GCM] ValueError: badly formed hexadecimal UUID string

First of: this is a well written and documented library, so kudos to the creator(s).

I have some trouble understanding why the GCM device_id is a UUIDField. Both the ANDROID_ID and the device id, retrieved from TelephonyManager, are not documented as a UUID as far as I know and they don't need to be generated by the third-party server, just stored for reference. Could someone elaborate on that?

When I add a GCM device through the admin interface, the form throws the following error:
ValueError: badly formed hexadecimal UUID string

The device_id is entered as a 16 character string, like 8af79c6314cac480. The same error is thrown when using the UUID constructor: uuid.UUID('8af79c6314cac480'), while uuid.UUID(int=0x8af79c6314cac480) works fine.

This might be an issue caused by django-uuidfield, but I'm posting it here because I'd like to know why a UUIDField is used in the first place.

Installation Fails

I am running pip install django-push-notifications in a virtual env and it fails because the setup.py is not able to find README.rst in the package. Here is the trace for what is going on:

(rb)gsharma$ pip install django-push-notifications
Downloading/unpacking django-push-notifications
  Running setup.py egg_info for package django-push-notifications
    Traceback (most recent call last):
      File "<string>", line 16, in <module>
      File "/Users/gsharma/Sites/rb/build/django-push-notifications/setup.py", line 6, in <module>
        README = open(os.path.join(os.path.dirname(**file**), "README.rst")).read()
    IOError: [Errno 2] No such file or directory: '/Users/gsharma/Sites/rb/build/django-push-notifications/README.rst'
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):

  File "<string>", line 16, in <module>

  File "/Users/gsharma/Sites/rb/build/django-push-notifications/setup.py", line 6, in <module>
README = open(os.path.join(os.path.dirname(__file__), "README.rst")).read()

IOError: [Errno 2] No such file or directory: '/Users/gsharma/Sites/rb/build/django-push-notifications/README.rst'

---

Command python setup.py egg_info failed with error code 1 in /Users/gsharma/Sites/rb/build/django-push-notifications

Thanks,
Gaurav

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.