markdown support

pull/5/head
Chris Caron 2018-02-19 20:59:19 -05:00
parent e6106de81b
commit 602b9bab6f
9 changed files with 133 additions and 27 deletions

View File

@ -21,8 +21,10 @@
import re
import logging
from markdown import markdown
from .common import NotifyType
from .common import NotifyFormat
from .utils import parse_list
from .utils import compat_is_basestring
@ -217,9 +219,14 @@ class Apprise(object):
"""
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
@ -228,12 +235,28 @@ class Apprise(object):
if not (title or body):
return False
# Tracks conversions
conversion_map = dict()
# Iterate over our loaded plugins
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:
# Send notification
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
status = False

View File

@ -24,9 +24,10 @@ __copywrite__ = 'Copyright 2017 Chris Caron <lead2gold@gmail.com>'
from .common import NotifyType
from .common import NOTIFY_TYPES
from .common import NOTIFY_IMAGE_SIZES
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 .Apprise import Apprise
@ -43,5 +44,5 @@ __all__ = [
# Reference
'NotifyType', 'NotifyImageSize', 'NotifyFormat', 'NOTIFY_TYPES',
'NOTIFY_IMAGE_SIZES',
'NOTIFY_IMAGE_SIZES', 'NOTIFY_FORMATS',
]

View File

@ -53,3 +53,20 @@ NOTIFY_IMAGE_SIZES = (
NotifyImageSize.XY_128,
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,
)

View File

@ -36,6 +36,8 @@ from ..utils import parse_bool
from ..utils import is_hostname
from ..common import NOTIFY_IMAGE_SIZES
from ..common import NOTIFY_TYPES
from ..common import NotifyFormat
from ..common import NOTIFY_FORMATS
from ..AppriseAsset import AppriseAsset
@ -60,24 +62,11 @@ HTTP_ERROR_MAP = {
}
# HTML New Line Delimiter
NOTIFY_NEWLINE = '\n'
NOTIFY_NEWLINE = '\r\n'
# Used to break a path list into parts
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:
# http://www.regular-expressions.info/email.html
IS_EMAIL_RE = re.compile(
@ -327,7 +316,7 @@ class NotifyBase(object):
return is_hostname(hostname)
@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.
@ -343,10 +332,10 @@ class NotifyBase(object):
results['secure'] = (results['schema'][-1] == 's')
# Our default notification format
results['notify_format'] = NotifyFormat.TEXT
results['notify_format'] = default_format
# Support SSL Certificate 'verify' keyword. Default to being enabled
results['verify'] = True
results['verify'] = verify_host
if 'verify' in results['qsd']:
results['verify'] = parse_bool(

View File

@ -25,7 +25,7 @@ from socket import error as SocketError
from email.mime.text import MIMEText
from .NotifyBase import NotifyBase
from .NotifyBase import NotifyFormat
from ..common import NotifyFormat
class WebBaseLogin(object):

View File

@ -20,8 +20,8 @@ import re
import requests
from .NotifyBase import NotifyBase
from .NotifyBase import NotifyFormat
from .NotifyBase import HTTP_ERROR_MAP
from ..common import NotifyFormat
# Extend HTTP Error Messages
NMA_HTTP_ERROR_MAP = HTTP_ERROR_MAP.copy()

View File

@ -47,8 +47,8 @@ from json import loads
from json import dumps
from .NotifyBase import NotifyBase
from .NotifyBase import NotifyFormat
from .NotifyBase import HTTP_ERROR_MAP
from ..common import NotifyFormat
from ..common import NotifyImageSize
from ..utils import compat_is_basestring

View File

@ -5,3 +5,4 @@ oauthlib
urllib3
six
click >= 5.0
markdown

View File

@ -25,6 +25,7 @@ from apprise import AppriseAsset
from apprise.Apprise import SCHEMA_MAP
from apprise import NotifyBase
from apprise import NotifyType
from apprise import NotifyFormat
from apprise import NotifyImageSize
from apprise.Apprise import __load_matrix
@ -107,7 +108,8 @@ def test_apprise():
class GoodNotification(NotifyBase):
def __init__(self, **kwargs):
super(GoodNotification, self).__init__()
super(GoodNotification, self).__init__(
notify_format=NotifyFormat.HTML)
def notify(self, **kwargs):
# Pretend everything is okay
@ -205,6 +207,79 @@ def test_apprise():
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):
"""
API: AppriseAsset() object