[PYTHON] I tried APN (remote notification) using Parse.com REST API

Parse.com supports Push Notification. I can send a push notification from the dashboard with a UI that is easy to understand, Alternatively, you can use the REST API to send push notifications from the app side. It was a little difficult to understand how to finely control using DeviceToken, so I will write about it.

Send to Parse API

Push notification requires at least ʻalert, so if you use curl, specify as follows and send. The X-Parse-Application-Id (Application ID) and X-Parse-REST-API-Key` (REST API Key) can be obtained from the Dashboard Overview. After that, if you are logged in and looking at the Document, you can execute it as it is because the Key is directly embedded in the code example !!

curl -X POST \
  -H "X-Parse-Application-Id: <Application ID>" \
  -H "X-Parse-REST-API-Key: <REST API Key>" \
  -H "Content-Type: application/json" \
  -d '{
        "data": {
          "alert": "The Giants won against the Mets 2-3."
        }
      }' \
  https://api.parse.com/1/push

About Parse Notification format

In simple terms, it will be in the JSON format below. Since the condition is specified in where, you can send Push Notificaiton to a specific terminal by specifying deviceToken here.

--In place of data, put the notification data of iOS or Android --Easy to specify the date and time of transmission and expiration date --Condition Query can be specified in place of where --Since general conditional operators such as $ lt (less then) and $ in (contained in) are available, flexible requests are possible.

parse_push.py


{'where': {'deviceToken': [],                   #Condition specification using Query API
    },
    'push_time': '2013-01-23T12:00:00Z',        #Notification start date and time(iso)
    'expiration_interval': '518400',            #expiration date
    'expiration_time': '2013-01-23T21:08:39Z',  #Expiration date and time specified(iso)
    'data': {
        'alert': 'message',
        'badge': 'Increment',                   # Number or 'Increment'(iOS only).
        'sound': 'sound bundle',                # iOS only.
        'content-available': '1',               # Newsstand content count(iOS only).
        'action': 'Intent',                     # Android only.
        'title': 'Notification!!',              # Android only.
    }
}

If you specify the conditional operator, it looks like this.

parse_push2.py


{'data': {'alert': 'push notification message!',
          'badge': 'Increment',
          'sound': 'default'},
 'where': {'deviceToken': {'$in': [u'<deviceToken1>', u'<deviceToken2>']}}}

Code example

Written in Python, it looks like this.

apn.py


# coding: utf-8

PARSE_API_BASE = 'https://api.parse.com'
PARSE_PUSH_API = '/1/push'
PARSE_PUSH_URL = PARSE_API_BASE + PARSE_PUSH_API
#Specify the Key required for Push Notification with HTTP Header
HEADERS = {
    "X-Parse-Application-Id": "<Application ID>",
    "X-Parse-REST-API-Key": "<REST API Key>",
    "X-Parse-Master-Key": "<Master Key>",
    "Content-Type": "application/json"
}


class APNMessageQueue(object):
    """ APN(Apple Push notification)Save messages for
    """
    structure = {
        'user_id': lambda x: (x is not None and len(x) > 0),
        'notify_token': lambda x: (x is not None and len(x) > 0),
        'message': lambda x: (x is not None and len(x) > 0),
    }

    def __init__(self, *args, **kwargs):
        for k in self.structure.keys():
            self.__setattr__(k, kwargs.get(k, None))

    @classmethod
    def create(cls, user_id, notify_token, message):
        src_props = dict(
            user_id=user_id,
            notify_token=notify_token,
            message=message,
        )
        props = {}

        for k, func in cls.structure.iteritems():
            value = src_props.get(k)
            if func(value):
                props[k] = value

        if props:
            return APNMessageQueue(**props)
        return None


def create_notify_message(message, badge='Increment', sound='default'):
    """Create Push Notification format from Notification message

    Args:
        message:Alert message.
        badge:Batch count('Increment'Is Parse.com original).
        sound:Notification sound effect.

    Return:
PushNotification format string.

    """
    return {'alert': message, 'badge': badge, 'sound': sound}


def create_request_data(notify_token, apn_data):
    """Parse Notification format Template format data creation

    Args:
        notify_token:Device token or list of it.
        apn_data:Apple Push Notification data.

    Returns:
ParseNotification format Template format data.

    """
    request_data = {'data': apn_data}
    if isinstance(notify_token, list):
        request_data['where'] = {'deviceToken': {'$in': notify_token}}
    else:
        request_data['where'] = {'deviceToken': notify_token}
    return request_data


def process_do_send(request_data):
    """ParseNotification format Send PushNotification by passing template format data

    Args:
        request_data:ParseNotification format Template format data

    Returns:
Returns normal termination or error

    """
    import json
    from urllib2 import Request, urlopen, URLError

    payload = json.dumps(request_data)
    request = Request(PARSE_PUSH_URL, payload, HEADERS)
    try:
        response = urlopen(request)
        data = json.loads(response.read())
        if isinstance(data, dict):
            return data.get('result', False)
    except URLError, e:
        if hasattr(e, 'reason'):
            print 'We failed to reach a server.'
            print 'Reason: %s' % e.reason
        elif hasattr(e, 'code'):
            print 'The server couldn\'t fulfill the request.'
            print 'Error code: %d' % e.code
    return False


def send_notification(notify_queue_list):
    """Send Push Notification to APNs

Broadcast Push Notification message to APNs server

    Args:
        notify_queue_list:APNMessageQueue list

    """
    from itertools import groupby
    notify_sorted_queue_list = sorted(notify_queue_list, key=lambda x: x.message)
    #Send the same message together
    for message, group in groupby(notify_sorted_queue_list, key=lambda x: x.message):
        distict_tokens = list(set([user.notify_token for user in group]))
        aps_data = create_notify_message(message)
        request_data = create_request_data(distict_tokens, aps_data)
        print request_data
        process_do_send(request_data)

The user side is like this

main.py


# coding: utf-8

def send_push_parse_for_apn(message):
    import models
    import apn

    #Get a list of deviceTokens for Notification from user data
    targets = [x for x in models.User.find_by_existing_notify_token() if x is not None]
    notify_token_list = [apn.APNMessageQueue(x.user_id, x.notify_token, message) for x in targets]

    if len(notify_token_list) > 0:
        #Launch
        apn.send_notification(notify_token_list)

if __name__ == '__main__':
    send_push_parse_for_apn('Abo!!')

Recommended Posts

I tried APN (remote notification) using Parse.com REST API
I tried using Remote API on GAE / J
I tried using the checkio API
I tried using YOUTUBE Data API V3
I tried using UnityCloudBuild API from Python
I tried using the BigQuery Storage API
I tried using AWS Rekognition's Detect Labels API
I tried using the Google Cloud Vision API
I tried using parameterized
I tried using argparse
I tried using mimesis
I tried using anytree
I tried using Summpy
I tried using coturn
I tried using Pipenv
I tried using matplotlib
I tried using "Anvil".
I tried using Hubot
I tried using ESPCN
I tried using openpyxl
I tried using Ipython
I tried using PyCaret
I tried using cron
I tried using ngrok
I tried using face_recognition
I tried using Jupyter
I tried using PyCaret
I tried using Heapq
I tried using doctest
I tried using folium
I tried using jinja2
I tried using folium
I tried using time-window
I tried using the API of the salmon data project
[I tried using Pythonista 3] Introduction
I tried using easydict (memo).
I tried face recognition using Face ++
I tried using Random Forest
I tried using BigQuery ML
I tried using git inspector
[Python] I tried using OpenPose
I tried using magenta / TensorFlow
I tried using AWS Chalice
I tried using Slack emojinator
I tried to search videos using Youtube Data API (beginner)
I tried using Microsoft's Cognitive Services facial expression recognition API
[Python] I tried collecting data using the API of wikipedia
[For beginners] I tried using the Tensorflow Object Detection API
I tried using Rotrics Dex Arm # 2
Get Salesforce data using REST API
I tried to create Quip API
I tried the Naro novel API 2
I tried using Rotrics Dex Arm
I tried using GrabCut of OpenCV
I tried scoring a transvestite contest using Face ++'s Detect API
I tried using the COTOHA API (there is code on GitHub)
I tried to analyze my favorite singer (SHISHAMO) using Spotify API
I tried using Thonny (Python / IDE)
I tried to touch Tesla's API
I tried server-client communication using tmux
I tried the Naruro novel API