Skip to content

Development_API

Chris Caron edited this page Dec 16, 2023 · 30 revisions

Table of Contents

Development API

Apprise is very easy to use as a developer. The Apprise() object handles everything for you, meanwhile the AppriseAsset() Object allows you to stray away from some default configuration to personalize the users experience (and perhaps fit your application better):

Some additional functionality is available via the The Apprise Notification Object for those who want to manage the notifications themselves.

Another useful class that can help you out with sending notifications is the The LogCapture Object. It can be used to capture the events that surrounded the success (and potential failure) of the notifications being delivered so that you can work with them.

The Apprise Object

The Apprise() object is the heart and soul of this library. To instantiate an instance of the object, one might do the following:

# Import this library
import apprise

# create an Apprise instance and assign it to variable `apobj`
apobj = apprise.Apprise()

add(): Add a New Notification Service By URL(s)

Use the add() function to append the notification URLs we want to provide notifications for.

# Add all of the notification services by their server url.
# A sample email notification
isokay = apobj.add('mailto://myemail:[email protected]')

# add() will return a True if the URL was successfully parsed and added into
# our notification pool.  Otherwise it returns False.

# A sample pushbullet notification
isokay = apobj.add('pbul://o.gn5kj6nfhv736I7jC3cj3QLRiyhgl98b')

# You can additionally add URLs via a list/set/tuple:
isokay = apobj.add([
   # A sample growl service
   'growl://192.168.40.23',

   # Our Microsoft Windows desktop
   'windows://',
])

Tagging

Tagging is a great way to add a richer experience to the notification flow. You can associate one or more tags with the notifications you choose to add(). Doing so grants you to flexibility to later call on just some (or all) of the services you added. It effectively grants you the additional ability to filter notifications based on your workflow.

Here is an example:

# import our library
import apprise

# Create our object
apobj = apprise.Apprise()

# Add a tag by a simple string
apobj.add('json://localhost/tagA/', tag="TagA")

# Add 2 tags by string; the comma and/or space auto delimit
# our entries (spaces and comma's are ignored):
apobj.add('json://localhost/tagAB/', tag="TagA, TagB")

# Add 2 tags using a list; this works with tuples and sets too!
apobj.add('json://localhost/tagCD/', tag=["TagC", "TagD"])

notify() : Send Notification(s)

You can now send a notification to all of the loaded notifications services by just providing it a title and a body like so:

# Then notify these services any time you desire. The below would
# notify all of the services loaded into our Apprise object.
apobj.notify(
    body='what a great notification service!',
    title='my notification title',
)

Developers should know that Apprise passes everything it gets as is which will work for most circumstances. However sometimes it's useful to let apprise know the data you're feeding it. This information is used to guarantee that the upstream provider can handle the content, and if it can't, it will be modified so that it does.

# Include the NotifyFormat object
from apprise import NotifyFormat

# our body might be read from a file, it might be just input from
# our end users
body="""
...a lot of content
that could span multiple lines ...
"""

# Now we can send our notification while controlling the input source
# and knowing the upstream plugins will be able to handle it
apobj.notify(
    body=body,
    # Possible formats are TEXT, MARDOWN, and HTML
    body_format=NotifyFormat.TEXT,
)

async_notify() : Leveraging Await to Send Notification(s)

Under the hood, Apprise will attempt to send all of your notifications asynchronously which means it will acquire it's own event loop. If you already have one going, then you can still send your notifications using await like so:

import asyncio

async my_event_loop():
    # assumes you declared your apobj (as identified above)
    # You can trigger it asynchronously now like so:
    results = await apobj.async_notify(
        body='what a great async friendly notification service!',
        title='my notification title')

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

Leverage Tagging

If you associated tags with your notification services when you called add() earlier, you can leverage it's full potential through the notify() function here. Tagging however allows you to trigger notifications only when a criteria is met. The tagging logic can be interpreted as follows:

apprise.notify(tag=match) Notify Services Having Tag(s):
"TagA" TagA
"TagA, TagB" TagA OR TagB
['TagA', 'TagB'] TagA OR TagB
[('TagA', 'TagC'), 'TagB'] (TagA AND TagC) OR TagB
[('TagB', 'TagC')] TagB AND TagC

Now that we've added our services and assigned them tags, this is how we can access them:

# Has TagA
apobj.notify(
    body="a body", title='a title', tag="tagA")

# Has TagA OR TagB
apobj.notify(
    body="a body", title='a title', tag=["tagA", "TagB"])

# Has TagA AND TagB
apobj.notify(
    body="a body", title='a title', tag=[("tagA", "TagB")])

# Has TagA OR TagB OR (TagC AND TagD)
apobj.notify(
    body="a body", title='a title', tag=["tagA", "TagB", ["TagC", "TagD"]])

# No reference to tags; alert all of the added services
apobj.notify(body="my body", title="my title")

Tagging and Categories

Another use case for tagging might be to instead interpret them as categories. A system owner could simply fill their code with clean logic like:

#... stuff happening
apobj.notify(body="a body", title='a title', tag="service-message")

# ... uh oh, something went wrong
apobj.notify(body="a body", title='a title', tag="debug-message")

# ... more stuff happening
apobj.notify(body="a body", title='a title', tag="broadcast-notice")
# ...

The idea would be that somewhere when the Apprise Object (apobj) was first created, you (as a system owner) would have retrieved the user settings and only load the tags based on what they're interested in:

# import our library
import apprise

# Create our object
apobj = apprise.Apprise()

# Poll our user for their setting and add them
apobj.add('mailto://myuser:[email protected]', tag=[
   # Services we want our user subscribed to:
   "service-message",
   "broadcast-notice"
])

Takeaway: In this example (above), the user would never be notified for "debug-message" calls. Yet the developer of this system does not need to provide any additional logic around the apprise calls other than the tag that should trigger the notification. Just let Apprise handle the logic of what notifications to send for you.

Message Types and Themes

By default, all notifications are sent as type NotifyType.INFO using the default theme. The following other types are included with this theme:

Notification Type Text Representation Image
NotifyType.INFO info Build Status
NotifyType.SUCCESS success Build Status
NotifyType.WARNING warning Build Status
NotifyType.FAILURE failure Build Status

Should you want to send a notification using a different status, simply include it as part of your notify() call:

# Import our NotifyType
from apprise import NotifyType

# Then notify these services any time you desire. The below would
# notify all of the services loaded into our Apprise object as a WARNING.
apobj.notify(
    body='what a great notification service!',
    title='my notification title',
    notify_type=NotifyType.WARNING,
)

You can alter the theme as well; this is discussed lower down using the the Apprise Asset Object.

len(): Returns Number of Notification Services loaded

We can retrieve a list of the active and loaded notification services by using python's built in len() function.

# len(apobj) returns the number of notifications loaded
# the below calls this and prints it to the screen:
print("There are %d notification services loaded" % len(apobj))

clear(): Reset our Apprise Object

If you ever want to reset our Apprise object, and eliminate all of the services we had previously loaded into it, you can use the clear() function.

# clears out all of the loaded notification services associated with our
# Apprise Object.
apobj.clear()

details(): Dynamic View Into Available Notification Services Apprise Offers

Developers who wish to be able to generate information based on this library dynamically can use the details()* function:

# returns an object containing details about the plugin for dynamic integration.
apobj.details()

The output will look like:

{
    "version": "0.5.2",
    "asset": {
        "default_extension": ".png",
        "app_desc": "Apprise Notifications",
        "image_path_mask": "https://github.com/caronc/apprise/raw/master/apprise/assets/themes/{THEME}/apprise-{TYPE}-{XY}{EXTENSION}",
        "app_id": "Apprise",
        "theme": "default",
        "image_url_logo": "https://github.com/caronc/apprise/raw/master/apprise/assets/themes/{THEME}/apprise-logo.png",
        "image_url_mask": "https://github.com/caronc/apprise/raw/master/apprise/assets/themes/{THEME}/apprise-{TYPE}-{XY}{EXTENSION}"
    },
    "schemas": [
        {
            "service_name": "Boxcar",
            "setup_url": "https://github.com/caronc/apprise/wiki/Notify_boxcar",
            "service_url": "https://boxcar.io/",
            "protocols": null,
            "secure_protocols": [
                "boxcar"
            ]
        },
        {
            "service_name": "Discord",
            "setup_url": "https://github.com/caronc/apprise/wiki/Notify_discored",
            "service_url": "https://discordapp.com/",
            "protocols": null,
            "secure_protocols": [
                "discord"
            ]
        },
        {
            "service_name": "E-Mail",
            "setup_url": "https://github.com/caronc/apprise/wiki/Notify_email",
            "service_url": null,
            "protocols": [
                "mailto"
            ],
            "secure_protocols": [
                "mailtos"
            ]
        },

        "... etc, ..."

    ],
    "details": {
        "templates": {
           ...
        },
        "tokens": {
           ...
        },
        "args": {
           ...
        },
        "kwargs": {
           ...
        },
    },
}

The idea behind the details() function is that it allows developers to pass details back through their program letting their users know what notifications are supported. Thus as this library deprecates and introduces new notification services, calling front end applications (built around the details() function) can automatically serve this information back to their user base.

More detailed information about this object can be found here.

The Apprise Asset Object

The apprise object allows you to customize your alarms by offering it different images, different sources and different themes. Different notification services support different ways of passing images into it (and some don't support images at all). Apprise offers a way of supporting both local and hosted images and looks after passing the correct one to the correct service (when requested).

Even when you're just using the Apprise() object, behind the scenes a generic AppriseAsset() object is created which retrieves all of it's information from this path: https://github.com/caronc/apprise/tree/master/apprise/assets/themes/default (which is the default theme directory).

A default AppriseAsset() object might have the following defined in it:

Variable Default Type Description
app_id Apprise String A Short Identifier defining the name of the application.
app_desc Apprise Notifications String A brief way of describing your notification system
app_url https://github.com/caronc/apprise String The URL someone could go to to find more information about your application if they so desired.
image_url_mask https://github.com/caronc/apprise/raw/master
/apprise/assets/themes/{THEME}/apprise-{TYPE}-{XY}{EXTENSION}
String A URL accessible from the internet that contains the images you want your notifications to reference. The URL should make use of available TEMPLATES MASKS that are encapsulated in {} brackets.
image_path_mask abspath(join(
dirname(__file__),
'assets',
'themes', '{THEME}',
'apprise-{TYPE}-{XY}{EXTENSION}',
))
String A locally accessible path that contains the images you want your notifications to reference. The path should make use of available TEMPLATES MASKS that are encapsulated in {} brackets.
Note: Don't let the python code above confuse you. It is used to dynamically figure out the path relative to where you installed apprise to so that it can point to the image files the product ships with.

The AppriseAsset() object also performs some dynamic templating of the specified image and URL paths. First I'll explain the template values, and then I'll explain how it works:

Template Value Variable Type Default Description
{THEME} theme String default The theme to reference.
{EXTENSION} default_extension String .png The image file extension
{TYPE} The type of notification being preformed. For example, if the user calling the notify() function specifies a notify_type of NotifyType.WARNING, the string warning would be placed as the {TYPE}
{XY} The image size to use which is in the format of AAxBB (as an example 72x72). Depending on the notification service being called; this value will vary. If you plan on defining your own images, you should facilitate the sizes: 32x32, 72x72, 128x128, and 256x256

Every time the notify() function is called from the Apprise object, it uses the URL and/or local path and applies all of the templated masked values so that it can figure out what image to display. Here is an example how one might over-ride apprise to suit their own custom project needs:

# Import this library
import apprise

# Create our AppriseAsset and populate it with some of our new values:
asset = apprise.AppriseAsset(
   # The following would allow you to support:
   # C:\Path\To\My\Images\info-32x32.jpeg
   # C:\Path\To\My\Images\warning-72x72.jpeg
   # etc...
   image_path_mask="C:\Path\To\My\Images\{TYPE}-{XY}{EXTENSION}",
   default_extension=".jpeg"
)

# Change our name a bit:
asset.app_id = "My App"
asset.app_desc = "My App Announcement"
asset.app_url = "http://nuxref.com/"

# create an Apprise instance and assign it our asset we created:
apobj = apprise.Apprise(asset=asset)

# At this point you can use the Apprise() object knowing that all of the
# default configuration has been over-ridden.

The Apprise Notification Object

The The Apprise Object actually already does a really good managing these for you. But if you want to manage the notifications yourself here is how you can do it:

# Import this library
import apprise

# Instantiate an object. This is what the apprise object
# would have otherwise done under the hood:
 obj = apprise.Apprise.instantiate('glib://')

# Now you can use the notify() function to pass notifications.
# notify() is similar to Apprise.notify() except the overhead of
# of tagging is not present.  There also no handling of the
# the text input type (HTML, MARKUP, etc).  This is on you
# to manipulate before passing in the content.
obj.notify(
    body=u"A test message",
    title=u"a title",
)

# send() is a very low level call which directly posts the
# body and title you specify to the remote notification server
# There is NO data manipulation here, no overflow handling
# nothing.  But this allows you to free form your own
# messages and pass them along using the apprise handling
obj.send(
    body=u"A test message",
    title=u"a title",
)

Features

Pickle/Serialization Support

You can Serialize your loaded notifications so they can be restored later on:

import apprise
import pickle

# Instantiate our object
apobj = apprise.Apprise()

# Add our URLs
apobj.add("json://localhost")
apobj.add("xml://localhost")
apobj.add("form://localhost")
apobj.add("mailto://user:pass@localhost")

# Now serialize our object for any purpose
serialized = pickle.dumps(apobj)

# Consider even storing it to disk if you wanted:
with open("myfile.txt", "w") as file:
    file.write(serialized)

With respect to the above example, we could later (or in another application) reload our object back as it was without having to re-add all the URLs again:

# Restore our Apprise Object
apobj = pickle.loads(serialized)

# Perhaps we previously wrote it to disk, well we can load our data this way as well:
with open("myfile.txt", "r+") as file:
   apobj = pickle.loads(file.read())
Clone this wiki locally