mirror of https://github.com/caronc/apprise
markdown support
parent
e6106de81b
commit
602b9bab6f
|
@ -21,8 +21,10 @@
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import logging
|
import logging
|
||||||
|
from markdown import markdown
|
||||||
|
|
||||||
from .common import NotifyType
|
from .common import NotifyType
|
||||||
|
from .common import NotifyFormat
|
||||||
from .utils import parse_list
|
from .utils import parse_list
|
||||||
from .utils import compat_is_basestring
|
from .utils import compat_is_basestring
|
||||||
|
|
||||||
|
@ -217,9 +219,14 @@ class Apprise(object):
|
||||||
"""
|
"""
|
||||||
self.servers[:] = []
|
self.servers[:] = []
|
||||||
|
|
||||||
def notify(self, title, body, notify_type=NotifyType.INFO):
|
def notify(self, title, body, notify_type=NotifyType.INFO,
|
||||||
|
body_format=None):
|
||||||
"""
|
"""
|
||||||
Send a notification to all of the plugins previously loaded
|
Send a notification to all of the plugins previously loaded.
|
||||||
|
|
||||||
|
If the body_format specified is NotifyFormat.MARKDOWN, it will
|
||||||
|
be converted to HTML if the Notification type expects this.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Initialize our return result
|
# Initialize our return result
|
||||||
|
@ -228,12 +235,28 @@ class Apprise(object):
|
||||||
if not (title or body):
|
if not (title or body):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# Tracks conversions
|
||||||
|
conversion_map = dict()
|
||||||
|
|
||||||
# Iterate over our loaded plugins
|
# Iterate over our loaded plugins
|
||||||
for server in self.servers:
|
for server in self.servers:
|
||||||
|
if server.notify_format not in conversion_map:
|
||||||
|
if body_format == NotifyFormat.MARKDOWN and \
|
||||||
|
server.notify_format == NotifyFormat.HTML:
|
||||||
|
|
||||||
|
# Apply Markdown
|
||||||
|
conversion_map[server.notify_format] = markdown(body)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Store entry directly
|
||||||
|
conversion_map[server.notify_format] = body
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Send notification
|
# Send notification
|
||||||
if not server.notify(
|
if not server.notify(
|
||||||
title=title, body=body, notify_type=notify_type):
|
title=title,
|
||||||
|
body=conversion_map[server.notify_format],
|
||||||
|
notify_type=notify_type):
|
||||||
|
|
||||||
# Toggle our return status flag
|
# Toggle our return status flag
|
||||||
status = False
|
status = False
|
||||||
|
|
|
@ -24,9 +24,10 @@ __copywrite__ = 'Copyright 2017 Chris Caron <lead2gold@gmail.com>'
|
||||||
|
|
||||||
from .common import NotifyType
|
from .common import NotifyType
|
||||||
from .common import NOTIFY_TYPES
|
from .common import NOTIFY_TYPES
|
||||||
from .common import NOTIFY_IMAGE_SIZES
|
|
||||||
from .common import NotifyImageSize
|
from .common import NotifyImageSize
|
||||||
from .plugins.NotifyBase import NotifyFormat
|
from .common import NOTIFY_IMAGE_SIZES
|
||||||
|
from .common import NotifyFormat
|
||||||
|
from .common import NOTIFY_FORMATS
|
||||||
from .plugins.NotifyBase import NotifyBase
|
from .plugins.NotifyBase import NotifyBase
|
||||||
|
|
||||||
from .Apprise import Apprise
|
from .Apprise import Apprise
|
||||||
|
@ -43,5 +44,5 @@ __all__ = [
|
||||||
|
|
||||||
# Reference
|
# Reference
|
||||||
'NotifyType', 'NotifyImageSize', 'NotifyFormat', 'NOTIFY_TYPES',
|
'NotifyType', 'NotifyImageSize', 'NotifyFormat', 'NOTIFY_TYPES',
|
||||||
'NOTIFY_IMAGE_SIZES',
|
'NOTIFY_IMAGE_SIZES', 'NOTIFY_FORMATS',
|
||||||
]
|
]
|
||||||
|
|
|
@ -53,3 +53,20 @@ NOTIFY_IMAGE_SIZES = (
|
||||||
NotifyImageSize.XY_128,
|
NotifyImageSize.XY_128,
|
||||||
NotifyImageSize.XY_256,
|
NotifyImageSize.XY_256,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NotifyFormat(object):
|
||||||
|
"""
|
||||||
|
A list of pre-defined text message formats that can be passed via the
|
||||||
|
apprise library.
|
||||||
|
"""
|
||||||
|
TEXT = 'text'
|
||||||
|
HTML = 'html'
|
||||||
|
MARKDOWN = 'markdown'
|
||||||
|
|
||||||
|
|
||||||
|
NOTIFY_FORMATS = (
|
||||||
|
NotifyFormat.TEXT,
|
||||||
|
NotifyFormat.HTML,
|
||||||
|
NotifyFormat.MARKDOWN,
|
||||||
|
)
|
||||||
|
|
|
@ -36,6 +36,8 @@ from ..utils import parse_bool
|
||||||
from ..utils import is_hostname
|
from ..utils import is_hostname
|
||||||
from ..common import NOTIFY_IMAGE_SIZES
|
from ..common import NOTIFY_IMAGE_SIZES
|
||||||
from ..common import NOTIFY_TYPES
|
from ..common import NOTIFY_TYPES
|
||||||
|
from ..common import NotifyFormat
|
||||||
|
from ..common import NOTIFY_FORMATS
|
||||||
|
|
||||||
from ..AppriseAsset import AppriseAsset
|
from ..AppriseAsset import AppriseAsset
|
||||||
|
|
||||||
|
@ -60,24 +62,11 @@ HTTP_ERROR_MAP = {
|
||||||
}
|
}
|
||||||
|
|
||||||
# HTML New Line Delimiter
|
# HTML New Line Delimiter
|
||||||
NOTIFY_NEWLINE = '\n'
|
NOTIFY_NEWLINE = '\r\n'
|
||||||
|
|
||||||
# Used to break a path list into parts
|
# Used to break a path list into parts
|
||||||
PATHSPLIT_LIST_DELIM = re.compile(r'[ \t\r\n,\\/]+')
|
PATHSPLIT_LIST_DELIM = re.compile(r'[ \t\r\n,\\/]+')
|
||||||
|
|
||||||
|
|
||||||
class NotifyFormat(object):
|
|
||||||
TEXT = 'text'
|
|
||||||
HTML = 'html'
|
|
||||||
MARKDOWN = 'markdown'
|
|
||||||
|
|
||||||
|
|
||||||
NOTIFY_FORMATS = (
|
|
||||||
NotifyFormat.TEXT,
|
|
||||||
NotifyFormat.HTML,
|
|
||||||
NotifyFormat.MARKDOWN,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Regular expression retrieved from:
|
# Regular expression retrieved from:
|
||||||
# http://www.regular-expressions.info/email.html
|
# http://www.regular-expressions.info/email.html
|
||||||
IS_EMAIL_RE = re.compile(
|
IS_EMAIL_RE = re.compile(
|
||||||
|
@ -327,7 +316,7 @@ class NotifyBase(object):
|
||||||
return is_hostname(hostname)
|
return is_hostname(hostname)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_url(url, verify_host=True):
|
def parse_url(url, verify_host=True, default_format=NotifyFormat.TEXT):
|
||||||
"""
|
"""
|
||||||
Parses the URL and returns it broken apart into a dictionary.
|
Parses the URL and returns it broken apart into a dictionary.
|
||||||
|
|
||||||
|
@ -343,10 +332,10 @@ class NotifyBase(object):
|
||||||
results['secure'] = (results['schema'][-1] == 's')
|
results['secure'] = (results['schema'][-1] == 's')
|
||||||
|
|
||||||
# Our default notification format
|
# Our default notification format
|
||||||
results['notify_format'] = NotifyFormat.TEXT
|
results['notify_format'] = default_format
|
||||||
|
|
||||||
# Support SSL Certificate 'verify' keyword. Default to being enabled
|
# Support SSL Certificate 'verify' keyword. Default to being enabled
|
||||||
results['verify'] = True
|
results['verify'] = verify_host
|
||||||
|
|
||||||
if 'verify' in results['qsd']:
|
if 'verify' in results['qsd']:
|
||||||
results['verify'] = parse_bool(
|
results['verify'] = parse_bool(
|
||||||
|
|
|
@ -25,7 +25,7 @@ from socket import error as SocketError
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
|
||||||
from .NotifyBase import NotifyBase
|
from .NotifyBase import NotifyBase
|
||||||
from .NotifyBase import NotifyFormat
|
from ..common import NotifyFormat
|
||||||
|
|
||||||
|
|
||||||
class WebBaseLogin(object):
|
class WebBaseLogin(object):
|
||||||
|
|
|
@ -20,8 +20,8 @@ import re
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from .NotifyBase import NotifyBase
|
from .NotifyBase import NotifyBase
|
||||||
from .NotifyBase import NotifyFormat
|
|
||||||
from .NotifyBase import HTTP_ERROR_MAP
|
from .NotifyBase import HTTP_ERROR_MAP
|
||||||
|
from ..common import NotifyFormat
|
||||||
|
|
||||||
# Extend HTTP Error Messages
|
# Extend HTTP Error Messages
|
||||||
NMA_HTTP_ERROR_MAP = HTTP_ERROR_MAP.copy()
|
NMA_HTTP_ERROR_MAP = HTTP_ERROR_MAP.copy()
|
||||||
|
|
|
@ -47,8 +47,8 @@ from json import loads
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
|
||||||
from .NotifyBase import NotifyBase
|
from .NotifyBase import NotifyBase
|
||||||
from .NotifyBase import NotifyFormat
|
|
||||||
from .NotifyBase import HTTP_ERROR_MAP
|
from .NotifyBase import HTTP_ERROR_MAP
|
||||||
|
from ..common import NotifyFormat
|
||||||
from ..common import NotifyImageSize
|
from ..common import NotifyImageSize
|
||||||
from ..utils import compat_is_basestring
|
from ..utils import compat_is_basestring
|
||||||
|
|
||||||
|
|
|
@ -5,3 +5,4 @@ oauthlib
|
||||||
urllib3
|
urllib3
|
||||||
six
|
six
|
||||||
click >= 5.0
|
click >= 5.0
|
||||||
|
markdown
|
||||||
|
|
|
@ -25,6 +25,7 @@ from apprise import AppriseAsset
|
||||||
from apprise.Apprise import SCHEMA_MAP
|
from apprise.Apprise import SCHEMA_MAP
|
||||||
from apprise import NotifyBase
|
from apprise import NotifyBase
|
||||||
from apprise import NotifyType
|
from apprise import NotifyType
|
||||||
|
from apprise import NotifyFormat
|
||||||
from apprise import NotifyImageSize
|
from apprise import NotifyImageSize
|
||||||
from apprise.Apprise import __load_matrix
|
from apprise.Apprise import __load_matrix
|
||||||
|
|
||||||
|
@ -107,7 +108,8 @@ def test_apprise():
|
||||||
|
|
||||||
class GoodNotification(NotifyBase):
|
class GoodNotification(NotifyBase):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super(GoodNotification, self).__init__()
|
super(GoodNotification, self).__init__(
|
||||||
|
notify_format=NotifyFormat.HTML)
|
||||||
|
|
||||||
def notify(self, **kwargs):
|
def notify(self, **kwargs):
|
||||||
# Pretend everything is okay
|
# Pretend everything is okay
|
||||||
|
@ -205,6 +207,79 @@ def test_apprise():
|
||||||
assert(len(a) == 0)
|
assert(len(a) == 0)
|
||||||
|
|
||||||
|
|
||||||
|
def test_apprise_notify_formats(tmpdir):
|
||||||
|
"""
|
||||||
|
API: Apprise() TextFormat tests
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Caling load matix a second time which is an internal function causes it
|
||||||
|
# to skip over content already loaded into our matrix and thefore accesses
|
||||||
|
# other if/else parts of the code that aren't otherwise called
|
||||||
|
__load_matrix()
|
||||||
|
|
||||||
|
a = Apprise()
|
||||||
|
|
||||||
|
# no items
|
||||||
|
assert(len(a) == 0)
|
||||||
|
|
||||||
|
class TextNotification(NotifyBase):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(TextNotification, self).__init__(
|
||||||
|
notify_format=NotifyFormat.TEXT)
|
||||||
|
|
||||||
|
def notify(self, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
class HtmlNotification(NotifyBase):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(HtmlNotification, self).__init__(
|
||||||
|
notify_format=NotifyFormat.HTML)
|
||||||
|
|
||||||
|
def notify(self, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
class MarkDownNotification(NotifyBase):
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
super(MarkDownNotification, self).__init__(
|
||||||
|
notify_format=NotifyFormat.MARKDOWN)
|
||||||
|
|
||||||
|
def notify(self, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Store our notifications into our schema map
|
||||||
|
SCHEMA_MAP['text'] = TextNotification
|
||||||
|
SCHEMA_MAP['html'] = HtmlNotification
|
||||||
|
SCHEMA_MAP['markdown'] = MarkDownNotification
|
||||||
|
|
||||||
|
# Test Markdown; the above calls the markdown because our good://
|
||||||
|
# defined plugin above was defined to default to HTML which triggers
|
||||||
|
# a markdown to take place if the body_format specified on the notify
|
||||||
|
# call
|
||||||
|
assert(a.add('html://localhost') is True)
|
||||||
|
assert(a.add('html://another.server') is True)
|
||||||
|
assert(a.add('html://and.another') is True)
|
||||||
|
assert(a.add('text://localhost') is True)
|
||||||
|
assert(a.add('text://another.server') is True)
|
||||||
|
assert(a.add('text://and.another') is True)
|
||||||
|
assert(a.add('markdown://localhost') is True)
|
||||||
|
assert(a.add('markdown://another.server') is True)
|
||||||
|
assert(a.add('markdown://and.another') is True)
|
||||||
|
|
||||||
|
assert(len(a) == 9)
|
||||||
|
|
||||||
|
assert(a.notify(title="markdown", body="## Testing Markdown",
|
||||||
|
body_format=NotifyFormat.MARKDOWN) is True)
|
||||||
|
|
||||||
|
assert(a.notify(title="text", body="Testing Text",
|
||||||
|
body_format=NotifyFormat.TEXT) is True)
|
||||||
|
|
||||||
|
assert(a.notify(title="html", body="<b>HTML</b>",
|
||||||
|
body_format=NotifyFormat.HTML) is True)
|
||||||
|
|
||||||
|
|
||||||
def test_apprise_asset(tmpdir):
|
def test_apprise_asset(tmpdir):
|
||||||
"""
|
"""
|
||||||
API: AppriseAsset() object
|
API: AppriseAsset() object
|
||||||
|
|
Loading…
Reference in New Issue