Application Helpers
-------------------

The payload delivered to push-client will be passed onto a helper program that can modify it as needed before passing it onto
the postal service (see `Helper Output Format <#helper-output-format>`__).

The helper receives two arguments ``infile`` and ``outfile``. The message is delivered via ``infile`` and the transformed
version is placed in ``outfile``.

This is the simplest possible useful helper, which simply passes the message through unchanged::

    #!/usr/bin/python3

    import sys
    f1, f2 = sys.argv[1:3]
    open(f2, "w").write(open(f1).read())

Helpers need to be added to the click package manifest::

    {
        "name": "com.ubuntu.developer.ralsina.hello",
        "description": "description of hello",
        "framework": "ubuntu-sdk-14.10-qml-dev2",
        "architecture": "all",
        "title": "hello",
        "hooks": {
            "hello": {
                "apparmor": "hello.json",
                "desktop": "hello.desktop"
            },
            "helloHelper": {
                "apparmor": "helloHelper-apparmor.json",
                "push-helper": "helloHelper.json"
            }
        },
        "version": "0.2",
        "maintainer": "Roberto Alsina <roberto.alsina@canonical.com>"
    }

Here, we created a helloHelper entry in hooks that has an apparmor profile and an additional JSON file for the push-helper hook.

helloHelper-apparmor.json must contain **only** the push-notification-client policy group::

    {
        "policy_groups": [
            "push-notification-client"
        ],
        "policy_version": 1.2
    }

And helloHelper.json must have at least a exec key with the path to the helper executable relative to the json, and optionally
an app_id key containing the short id of one of the apps in the package (in the format packagename_appname without a version).
If the app_id is not specified, the helper will be used for all apps in the package::

    {
        "exec": "helloHelper",
        "app_id": "com.ubuntu.developer.ralsina.hello_hello"
    }

.. note:: For deb packages, helpers should be installed into /usr/lib/ubuntu-push-client/legacy-helpers/ as part of the package.

Helper Output Format
--------------------

Helpers output has two parts, the postal message (in the "message" key) and a notification to be presented to the user (in the "notification" key).

.. note:: This format **will** change with future versions of the SDK and it **may** be incompatible.

Here's a simple example::

    {
        "message": "foobar",
        "notification": {
            "tag": "foo",
            "card": {
                "summary": "yes",
                "body": "hello",
                "popup": true,
                "persist": true,
                "timestamp": 1407160197
            }
            "sound": "buzz.mp3",
            "vibrate": {
                "pattern": [200, 100],
                "repeat": 2
            }
            "emblem-counter": {
                "count": 12,
                "visible": true
            }
        }
    }

The notification can contain a **tag** field, which can later be used by the `persistent notification management API. <#persistent-notification-management>`__

:message: (optional) A JSON object that is passed as-is to the application via PopAll.
:notification: (optional) Describes the user-facing notifications triggered by this push message.

The notification can contain a **card**. A card describes a specific notification to be given to the user,
and has the following fields:

:summary: (required) a title. The card will not be presented if this is missing.
:body: longer text, defaults to empty.
:actions: If empty (the default), a bubble notification is non-clickable.
          If you add a URL, then bubble notifications are clickable and launch that URL. One use for this is using a URL like
          ``appid://com.ubuntu.developer.ralsina.hello/hello/current-user-version`` which will switch to the app or launch
          it if it's not running. See `URLDispatcher <https://wiki.ubuntu.com/URLDispatcher>`__ for more information.

:icon: An icon relating to the event being notified. Defaults to empty (no icon);
       a secondary icon relating to the application will be shown as well, regardless of this field.
:timestamp: Seconds since the unix epoch, only used for persist (for now). If zero or unset, defaults to current timestamp.
:persist: Whether to show in notification centre; defaults to false
:popup: Whether to show in a bubble. Users can disable this, and can easily miss them, so don't rely on it exclusively. Defaults to false.

.. note:: Keep in mind that the precise way in which each field is presented to the user depends on factors such as
          whether it's shown as a bubble or in the notification centre, or even the version of Ubuntu Touch the user
          has on their device.

The notification can contain a **sound** field. This is either a boolean (play a predetermined sound) or the path to a sound file. The user can disable it, so don't rely on it exclusively.
Defaults to empty (no sound). The path is relative, and will be looked up in (a) the application's .local/share/<pkgname>, and (b)
standard xdg dirs.

The notification can contain a **vibrate** field, causing haptic feedback, which can be either a boolean (if true, vibrate a predetermined way) or an object that has the following content:

:pattern: a list of integers describing a vibration pattern (duration of alternating vibration/no vibration times, in milliseconds).
:repeat: number of times the pattern has to be repeated (defaults to 1, 0 is the same as 1).

The notification can contain a **emblem-counter** field, with the following content:

:count: a number to be displayed over the application's icon in the launcher.
:visible: set to true to show the counter, or false to hide it.

.. note:: Unlike other notifications, emblem-counter needs to be cleaned by the app itself.
          Please see `the persistent notification management section. <#persistent-notification-management>`__

.. FIXME crosslink to hello example app on each method

Security
~~~~~~~~

To use the push API, applications need to request permission in their security profile, using something like this::

    {
        "policy_groups": [
            "networking",
            "push-notification-client"
        ],
        "policy_version": 1.2
    }


Ubuntu Push Server API
----------------------

The Ubuntu Push server is located at https://push.ubuntu.com and has a single endpoint: ``/notify``.
To notify a user, your application has to do a POST with ``Content-type: application/json``.

.. note:: The contents of the data field are arbitrary. They should be enough for your helper to build
          a notification using it, and decide whether it should be displayed or not. Keep in mind
          that this will be processed by more than one version of the helper, because the user may be using
          an older version of your app.

Here is an example of the POST body using all the fields::

    {
        "appid": "com.ubuntu.music_music",
        "expire_on": "2014-10-08T14:48:00.000Z",
        "token": "LeA4tRQG9hhEkuhngdouoA==",
        "clear_pending": true,
        "replace_tag": "tagname",
        "data": {
            "id": 43578,
            "timestamp": 1409583746,
            "serial": 1254,
            "sender": "Joe",
            "snippet": "Hi there!"
        }
    }


:appid: ID of the application that will receive the notification, as described in the client side documentation.
:expire_on: Expiration date/time for this message, in `ISO8601 Extendend format <http://en.wikipedia.org/wiki/ISO_8601>`__
:token: The token identifying the user+device to which the message is directed, as described in the client side documentation.
:clear_pending: Discards all previous pending notifications. Usually in response to getting a "too-many-pending" error.
:replace_tag: If there's a pending notification with the same tag, delete it before queuing this new one.
:data: A JSON object.
