Aller au contenu

Plugin Development

Ce contenu n’est pas encore disponible dans votre langue.

Apprise plugins, also called services, are Python classes that inherit from NotifyBase. The fastest way to build a new one is to start from a working plugin that resembles your target integration, then adapt its URL shape, parsing, and send logic.

This pattern is ideal for:

  • Writing to a local destination (stdout, file, syslog)
  • Prototyping a URL schema before adding networking
apprise/plugins/demo.py
from .base import NotifyBase
from ..common import NotifyType
from ..locale import gettext_lazy as _
class NotifyDemo(NotifyBase):
service_name = _("Apprise Demo Notification")
protocol = "demo"
setup_url = "https://appriseit.com/services/demo/"
# Disable throttling for a purely local plugin
request_rate_per_sec = 0
templates = (
"{schema}://",
)
def url(self, *args, **kwargs):
params = self.url_parameters(*args, **kwargs)
return "{schema}://?{params}".format(
schema=self.protocol,
params=self.urlencode(params),
)
def send(self, body, title="", notify_type=NotifyType.INFO, **kwargs):
self.throttle()
print(f"{notify_type} - {title} - {body}")
return True
@staticmethod
def parse_url(url):
# demo:// has no host, so verify_host must be False
return NotifyBase.parse_url(url, verify_host=False)

Apprise determines what the schema:// it has been provided and then launches the Notification Plugin’s YourPlugin.parse_url() call to do the rest.

Usually the first call made in your parse_url() function is to call the parent one (from NotifyBase). Doing so allows Apprise to extract further common URL parts such as schema, host, port, user, password, and fullpath. Your parse_url() should focus on the pieces that are specific to your service, then return a dict whose keys match your __init__() signature.

A key rule that the unit tests enforce is that your template metadata must map cleanly to __init__() arguments, either directly (same name) or through map_to.

URLBase defines common SSL verification and socket timeouts as URL arguments:

  • verify controls verify_certificate
  • rto controls the socket read timeout
  • cto controls the socket connect timeout

The url_identifier property exists to uniquely identify one configuration from another so cached or persistent data does not clobber different configurations. It is also how Apprise generates a consistent, stable unique id from a URL.

  • Include scheme or protocol, credentials, and upstream connection identity.
  • Exclude targets (channels, recipients, endpoints).
  • Exclude most GET parameters. Only include a GET parameter if it fundamentally changes how the upstream communication works.

If two URLs describe the same effective configuration, they should generate the same url_identifier, and therefore the same url_id().

Also note the storage switch:

  • If store=no is set, url_id() returns None, and url() should preserve store=no in its output.

Example:

@property
def url_identifier(self):
return (
self.secure_protocol if self.secure else self.protocol,
self.user,
self.password,
self.host,
self.port if self.port else (443 if self.secure else 80),
)

If your plugin performs repeated upstream lookups (OAuth tokens, discovery calls, resolved identifiers, capability checks), you should consider enabling persistent storage. It will save you from doing the check down the road and make your plugin that much faster!

To opt in, set a class-level storage_mode:

from apprise.common import PersistentStoreMode
class NotifyMyService(NotifyBase):
# ...
storage_mode = PersistentStoreMode.AUTO

Guidance:

  • Use PersistentStoreMode.AUTO for most plugins.
  • Use PersistentStoreMode.FLUSH only when the cached data is expensive to recompute and you want stronger durability.
  • Leave the default behaviour (memory-only) if your plugin should never persist state, or if caching provides little benefit.

When combined with a well-formed url_identifier (configuration identity only), multiple instances targeting different recipients can reuse the same cache for the same upstream configuration.

__len__() allows authors and tooling to identify how many targets are loaded into a plugin.

  • If you do not override it, the base implementation returns 1.
  • Override it in plugins that support multiple targets, usually returning len(self.targets) with a minimum of 1.

If your plugin needs extra packages, declare them in requirements so Apprise can report what is required or recommended.

from ..locale import gettext_lazy as _
requirements = {
"details": _("This plugin requires cryptography for message signing."),
"packages_required": ["cryptography>=42"],
"packages_recommended": ["orjson>=3"],
}

The following identifies the default values of variables defined in your plugin automatically if not otherwise overridden.

NotifyBase inherits from the URLBase object which sets these defaults:

AttributeDefaultPurposeWhen To Override
request_rate_per_sec0Base throttle interval (seconds). 0 disables throttling at the URLBase level.Typically override at NotifyBase or your plugin, not at URLBase.
socket_connect_timeout4.0Default connect timeout, used when cto is not provided.If your service routinely needs longer TCP handshakes.
socket_read_timeout4.0Default read timeout, used when rto is not provided.If your service returns slowly or streams responses.
verify_certificateTrueSSL certificate verification, used when verify is not provided.Only if your service runs in controlled networks with self-signed certs and you are comfortable allowing verify=no.
templates()Documentation templates.Almost always, so tooling and docs can describe the plugin accurately.
template_tokens{}Metadata describing URL path tokens.Almost always, for non-trivial schemas.
template_args{ verify, rto, cto }Common URL args and their defaults.Usually extend rather than replace.
template_kwargs{}Metadata for prefixed key/value arguments.If you support +headers, :payload, -params, etc.

Your plugin should be configured to inherit from NotifyBase granting you these defaults

AttributeDefaultPurposeWhen To Override
enabledTrueIf False, the plugin is not used.Disable for platform-specific or dependency-specific reasons.
category"native"Classifies plugin origin (native vs custom).Usually leave as-is.
requirements.detailsNoneHuman-friendly requirements text.If you need to explain optional or required packages.
requirements.packages_required[]Required packages for full function.If your plugin requires extra libraries.
requirements.packages_recommended[]Optional packages that improve function.If you can run without them, but benefit from them.
service_urlNoneVendor or upstream product URL.For public services, set this.
setup_urlNoneApprise setup page for your service.Set this to your appriseit.com/services/<service>/ page.
request_rate_per_sec5.5Default throttle interval (seconds).Tune for vendor rate limits, or set to 0 for local-only.
image_sizeNonePreferred image size, for attachment pre-scaling.Set when your service expects a specific size.
body_maxlen32768Max body characters before truncation.Set based on upstream constraints.
title_maxlen250Max title characters. Set 0 if titles are not supported.Set to 0 for title-less endpoints, or tune to vendor constraints.
body_max_line_count0Max number of lines to keep. 0 disables line truncation.If upstream is line-sensitive.
persistent_storageTrueAllows the persistent store to be used.If your plugin must never store identifiers or state.
storage_modememoryDefault persistent store mode.Rare, but can be tuned for special behaviours.
timezoneNoneUses server-detected timezone when None.If your service must always operate in a specific timezone.
notify_formattextDefault message format.If your service is Markdown or HTML-first.
overflow_modeupstreamDefault overflow strategy.If you want Apprise to split, truncate, or alter overflow behaviour.
interpret_emojisFalseEmoji interpretation.If the upstream service benefits from emoji conversion.
attachment_supportFalseAttachment enablement.Set to True if you accept attachments.
default_html_tag_id"b"Used to inject title into body for title-less services.Rare, unless you want different formatting.

Apprise validates types using a strict pattern: ((choice|list):)?(string|bool|int|float).

TypeWhere usedMeaningRequired directivesNotes
stringtokens, argsA single stringnoneCommon for hostnames, tokens, and names.
inttokens, argsA single integernoneUse min and max to bound port values, counts, etc.
floattokens, argsA single floatnoneUse min and max for bounds.
booltokens, argsA boolean flagdefault (required for args)Boolean args must provide a default.
choice:stringtokens, argsOne value from a fixed setvaluesChoice entries must provide values, and default must be one of them if specified.
choice:inttokens, argsOne integer from a fixed setvaluesUse for mode selectors or enumerations.
choice:floattokens, argsOne float from a fixed setvaluesRare, but supported.
list:stringtokens, argsA list of stringsdelimList entries must provide delimiters.
list:inttokens, argsA list of integersdelimSplit and then coerce to int.
list:floattokens, argsA list of floatsdelimSplit and then coerce to float.

Additional rules that matter:

  • choice:bool is not allowed, use bool instead.
  • regex must be a 2-tuple (pattern, option), and patterns must start with ^ and end with $. |
  • If required or private are not provided, they default to False.
  • If values is a dictionary, it is converted to a list of keys.

These examples focus only on how template metadata, __init__(), and parse_url() connect.

No tokens are required when the templates do not include custom {token} entries.

class MyPlugin(NotifyBase):
## Plugin variables here (intentionally omitted)
secure_protocol = "foobar"
templates = ("{schema}://",)
def __init__(self, *args, **kwargs):
# Rest of code here
super().__init__(*args, **kwargs)

The unit tests enforce allowed keys and type constraints.

DirectiveWhere usedMeaning
nametokens, args, kwargsHuman-friendly label, usually wrapped in gettext_lazy().
typetokens, argsValue type, validated by the strict type regex.
requiredtokens, argsMarks an entry as mandatory. If omitted, defaults to False.
privatetokens, argsMarks an entry as sensitive. If omitted, defaults to False.
defaultargsDefault used when the URL does not specify a value. Required for bool args.
valueschoice typesAllowed values for choice types, required for any choice:* type.
min, maxint, floatBounds for numeric types.
regextokens, argsValidation regex, always (pattern, option) with ^...$ anchoring.
delimlist typesDelimiters used for list splitting, required for list:* types.
prefixkwargsRequired for kwargs, must be one of :, +, or -.
map_totokens, args, kwargsMaps a key to a different __init__() argument name. Tests enforce it maps to a function argument (or a framework keyword).
alias_ofargs, kwargsDeclares an alias for an existing token or arg, often used to make YAML configuration easier.
grouptokensUsed for grouping when multiple tokens map into a list-style entry.

Framework-recognized map targets include common URL fields and shared arguments, even if they are not in your plugin __init__(), such as user, password, host, port, schema, fullpath, format, overflow, emojis, tz, verify, cto, rto, and store.

Apprise uses your template metadata as a contract, and tests enforce consistency:

  • Every item in template_tokens must map to a real __init__() argument, either directly (same key name) or using map_to.
  • Aliases (alias_of) are allowed in args and kwargs, not in tokens.
  • Every alias_of must point to a real token or arg, and cannot just point to itself unless it also exists in tokens.
  • For kwargs entries, prefix is required, and must be one of :, +, or -.

Two functions should work together:

  • parse_url() should extract every argument you expose through template_args and template_kwargs.
  • url() should emit a URL that can recreate the same object, and should generate the same url_identifier when re-instantiated.

This table documents the most common directives supported by template_tokens, template_args, and template_kwargs.

DirectiveWhere usedMeaning
nametokens, args, kwargsHuman-friendly label, usually wrapped in gettext_lazy().
typetokens, argsValue type, such as string, int, bool, choice:string, list:string.
requiredtokens, argsMarks an entry as mandatory for initialization or validation.
defaultargsDefault used when the URL does not specify a value. Required for bool types.
privatetokens, argsMarks a value as sensitive and should be hidden or masked in privacy views.
regextokens, argsA 2-tuple (pattern, flags) used to validate values. Patterns should be anchored with ^ and $.
valueschoice typesAllowed values for choice:* types. If a default is provided, it must be in values.
delimlist typesAllowed delimiters for list:* types.
prefixkwargsRequired for kwargs entries, defines injection prefix :, +, or -.
map_totokens, args, kwargsMaps the directive key to a different __init__() argument name.
alias_ofargs, kwargsProvides an alternative name that behaves exactly like another token or argument.
  • A tuple of URL patterns (strings) showing valid forms.
  • Use {schema} in templates, and keep tokens consistent across templates.

It is documentation and structured metadata that can be used by tooling to describe supported URL shapes.

Variables taken from the URL core structure such:

schema://credentials/direction/?options=
| |
| variables here |

Args describe query string arguments. NotifyBase already provides format, overflow, emojis, store, and tz. URLBase already provides verify, rto, and cto.

Common patterns:

  • Use alias_of to add synonyms.
  • Use map_to to map user-facing arg names onto your __init__() parameter names.
  • Use a default to clearly document behaviour.

Kwargs are for prefixed arguments that can appear multiple times, typically used for key/value injection:

  • + is often used for headers
  • - is often used for URL parameters
  • : is often used for payload extras

If your plugin needs extra packages, declare them in requirements so Apprise can report what is required or recommended.

Example:

from ..locale import gettext_lazy as _
requirements = {
"details": _("This plugin requires cryptography for message signing."),
"packages_required": ["cryptography>=42"],
"packages_recommended": ["orjson>=3"],
}

Plugins can opt into attachment support by setting attachment_support = True. If you enable this, be prepared for calls where body or title may be empty.

Also note that NotifyBase provides URL-level behaviour flags like format, overflow, emojis, and persistent storage (store).