mirror of
https://github.com/caronc/apprise.git
synced 2025-01-07 14:39:51 +01:00
Implimented overflow support (upstream, truncate, and split)
This commit is contained in:
parent
0d56da9ac8
commit
cdd72086ee
@ -363,26 +363,30 @@ class Apprise(object):
|
|||||||
# Store entry directly
|
# Store entry directly
|
||||||
conversion_map[server.notify_format] = body
|
conversion_map[server.notify_format] = body
|
||||||
|
|
||||||
try:
|
# Apply our overflow (if defined)
|
||||||
# Send notification
|
for chunk in server._apply_overflow(
|
||||||
if not server.notify(
|
body=conversion_map[server.notify_format], title=title):
|
||||||
title=title,
|
try:
|
||||||
body=conversion_map[server.notify_format],
|
# Send notification
|
||||||
notify_type=notify_type):
|
if not server.notify(
|
||||||
|
title=chunk['title'],
|
||||||
|
body=chunk['body'],
|
||||||
|
notify_type=notify_type):
|
||||||
|
|
||||||
# Toggle our return status flag
|
# Toggle our return status flag
|
||||||
|
status = False
|
||||||
|
|
||||||
|
except TypeError:
|
||||||
|
# These our our internally thrown notifications
|
||||||
|
# TODO: Change this to a custom one such as
|
||||||
|
# AppriseNotifyError
|
||||||
status = False
|
status = False
|
||||||
|
|
||||||
except TypeError:
|
except Exception:
|
||||||
# These our our internally thrown notifications
|
# A catch all so we don't have to abort early
|
||||||
# TODO: Change this to a custom one such as AppriseNotifyError
|
# just because one of our plugins has a bug in it.
|
||||||
status = False
|
logging.exception("Notification Exception")
|
||||||
|
status = False
|
||||||
except Exception:
|
|
||||||
# A catch all so we don't have to abort early
|
|
||||||
# just because one of our plugins has a bug in it.
|
|
||||||
logging.exception("Notification Exception")
|
|
||||||
status = False
|
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
@ -37,6 +37,8 @@ from .common import NotifyImageSize
|
|||||||
from .common import NOTIFY_IMAGE_SIZES
|
from .common import NOTIFY_IMAGE_SIZES
|
||||||
from .common import NotifyFormat
|
from .common import NotifyFormat
|
||||||
from .common import NOTIFY_FORMATS
|
from .common import NOTIFY_FORMATS
|
||||||
|
from .common import OverflowMode
|
||||||
|
from .common import OVERFLOW_MODES
|
||||||
from .plugins.NotifyBase import NotifyBase
|
from .plugins.NotifyBase import NotifyBase
|
||||||
|
|
||||||
from .Apprise import Apprise
|
from .Apprise import Apprise
|
||||||
@ -52,6 +54,6 @@ __all__ = [
|
|||||||
'Apprise', 'AppriseAsset', 'NotifyBase',
|
'Apprise', 'AppriseAsset', 'NotifyBase',
|
||||||
|
|
||||||
# Reference
|
# Reference
|
||||||
'NotifyType', 'NotifyImageSize', 'NotifyFormat', 'NOTIFY_TYPES',
|
'NotifyType', 'NotifyImageSize', 'NotifyFormat', 'OverflowMode',
|
||||||
'NOTIFY_IMAGE_SIZES', 'NOTIFY_FORMATS',
|
'NOTIFY_TYPES', 'NOTIFY_IMAGE_SIZES', 'NOTIFY_FORMATS', 'OVERFLOW_MODES',
|
||||||
]
|
]
|
||||||
|
@ -77,3 +77,31 @@ NOTIFY_FORMATS = (
|
|||||||
NotifyFormat.HTML,
|
NotifyFormat.HTML,
|
||||||
NotifyFormat.MARKDOWN,
|
NotifyFormat.MARKDOWN,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class OverflowMode(object):
|
||||||
|
"""
|
||||||
|
A list of pre-defined modes of how to handle the text when it exceeds the
|
||||||
|
defined maximum message size.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Send the data as is; untouched. Let the upstream server decide how the
|
||||||
|
# content is handled. Some upstream services might gracefully handle this
|
||||||
|
# with expected intentions; others might not.
|
||||||
|
UPSTREAM = 'upstream'
|
||||||
|
|
||||||
|
# Always truncate the text when it exceeds the maximum message size and
|
||||||
|
# send it anyway
|
||||||
|
TRUNCATE = 'truncate'
|
||||||
|
|
||||||
|
# Split the message into multiple smaller messages that fit within the
|
||||||
|
# limits of what is expected. The smaller messages are sent
|
||||||
|
SPLIT = 'split'
|
||||||
|
|
||||||
|
|
||||||
|
# Define our modes so we can verify if we need to
|
||||||
|
OVERFLOW_MODES = (
|
||||||
|
OverflowMode.UPSTREAM,
|
||||||
|
OverflowMode.TRUNCATE,
|
||||||
|
OverflowMode.SPLIT,
|
||||||
|
)
|
||||||
|
@ -45,6 +45,8 @@ from ..utils import is_hostname
|
|||||||
from ..common import NOTIFY_TYPES
|
from ..common import NOTIFY_TYPES
|
||||||
from ..common import NotifyFormat
|
from ..common import NotifyFormat
|
||||||
from ..common import NOTIFY_FORMATS
|
from ..common import NOTIFY_FORMATS
|
||||||
|
from ..common import OverflowMode
|
||||||
|
from ..common import OVERFLOW_MODES
|
||||||
|
|
||||||
from ..AppriseAsset import AppriseAsset
|
from ..AppriseAsset import AppriseAsset
|
||||||
|
|
||||||
@ -120,14 +122,26 @@ class NotifyBase(object):
|
|||||||
image_size = None
|
image_size = None
|
||||||
|
|
||||||
# The maximum allowable characters allowed in the body per message
|
# The maximum allowable characters allowed in the body per message
|
||||||
body_maxlen = 32768
|
# We set it to what would virtually be an infinite value really
|
||||||
|
# 2^63 - 1 = 9223372036854775807
|
||||||
|
body_maxlen = 9223372036854775807
|
||||||
|
|
||||||
# Defines the maximum allowable characters in the title
|
# Defines the maximum allowable characters in the title; set this to zero
|
||||||
|
# if a title can't be used. Titles that are not used but are defined are
|
||||||
|
# automatically placed into the body
|
||||||
title_maxlen = 250
|
title_maxlen = 250
|
||||||
|
|
||||||
|
# Set the maximum line count; if this is set to anything larger then zero
|
||||||
|
# the message (prior to it being sent) will be truncated to this number
|
||||||
|
# of lines. Setting this to zero disables this feature.
|
||||||
|
body_max_line_count = 0
|
||||||
|
|
||||||
# Default Notify Format
|
# Default Notify Format
|
||||||
notify_format = NotifyFormat.TEXT
|
notify_format = NotifyFormat.TEXT
|
||||||
|
|
||||||
|
# Default Overflow Mode
|
||||||
|
overflow_mode = OverflowMode.UPSTREAM
|
||||||
|
|
||||||
# Maintain a set of tags to associate with this specific notification
|
# Maintain a set of tags to associate with this specific notification
|
||||||
tags = set()
|
tags = set()
|
||||||
|
|
||||||
@ -177,6 +191,19 @@ class NotifyBase(object):
|
|||||||
# Provide override
|
# Provide override
|
||||||
self.notify_format = notify_format
|
self.notify_format = notify_format
|
||||||
|
|
||||||
|
if 'overflow' in kwargs:
|
||||||
|
# Store the specified format if specified
|
||||||
|
overflow_mode = kwargs.get('overflow', '')
|
||||||
|
if overflow_mode.lower() not in OVERFLOW_MODES:
|
||||||
|
self.logger.error(
|
||||||
|
'Invalid overflow method %s' % overflow_mode,
|
||||||
|
)
|
||||||
|
raise TypeError(
|
||||||
|
'Invalid overflow method %s' % overflow_mode,
|
||||||
|
)
|
||||||
|
# Provide override
|
||||||
|
self.overflow_mode = overflow_mode
|
||||||
|
|
||||||
if 'tag' in kwargs:
|
if 'tag' in kwargs:
|
||||||
# We want to associate some tags with our notification service.
|
# We want to associate some tags with our notification service.
|
||||||
# the code below gets the 'tag' argument if defined, otherwise
|
# the code below gets the 'tag' argument if defined, otherwise
|
||||||
@ -260,6 +287,78 @@ class NotifyBase(object):
|
|||||||
color_type=color_type,
|
color_type=color_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _apply_overflow(self, body, title=None):
|
||||||
|
"""
|
||||||
|
Takes the message body and title as input. This function then
|
||||||
|
applies any defined overflow restrictions associated with the
|
||||||
|
notification service and may alter the message if/as required.
|
||||||
|
|
||||||
|
The function will always return a list object in the following
|
||||||
|
structure:
|
||||||
|
[
|
||||||
|
{
|
||||||
|
title: 'the title goes here',
|
||||||
|
body: 'the message body goes here',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'the title goes here',
|
||||||
|
body: 'the message body goes here',
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = list()
|
||||||
|
|
||||||
|
if self.title_maxlen <= 0:
|
||||||
|
# Content is appended to body
|
||||||
|
body = '{}\r\n{}'.format(title, body)
|
||||||
|
title = ''
|
||||||
|
|
||||||
|
# Enforce the line count first always
|
||||||
|
if self.body_max_line_count > 0:
|
||||||
|
# Limit results to just the first 2 line otherwise
|
||||||
|
# there is just to much content to display
|
||||||
|
body = re.split('\r*\n', body)
|
||||||
|
body = '\r\n'.join(body[0:self.body_max_line_count])
|
||||||
|
|
||||||
|
if self.overflow_mode == OverflowMode.UPSTREAM:
|
||||||
|
# Nothing to do
|
||||||
|
response.append({
|
||||||
|
'body': body,
|
||||||
|
'title': title,
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
|
||||||
|
elif len(title) > self.title_maxlen:
|
||||||
|
# Truncate our Title
|
||||||
|
title = title[:self.title_maxlen]
|
||||||
|
|
||||||
|
if self.body_maxlen > 0 and len(body) <= self.body_maxlen:
|
||||||
|
response.append({
|
||||||
|
'body': body,
|
||||||
|
'title': title,
|
||||||
|
})
|
||||||
|
return response
|
||||||
|
|
||||||
|
if self.overflow_mode == OverflowMode.TRUNCATE:
|
||||||
|
# Truncate our body and return
|
||||||
|
response.append({
|
||||||
|
'body': body[:self.body_maxlen],
|
||||||
|
'title': title,
|
||||||
|
})
|
||||||
|
# For truncate mode, we're done now
|
||||||
|
return response
|
||||||
|
|
||||||
|
# If we reach here, then we are in SPLIT mode.
|
||||||
|
# For here, we want to split the message as many times as we have to
|
||||||
|
# in order to fit it within the designated limits.
|
||||||
|
response = [{
|
||||||
|
'body': body[i: i + self.body_maxlen],
|
||||||
|
'title': title} for i in range(0, len(body), self.body_maxlen)]
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
def url(self):
|
def url(self):
|
||||||
"""
|
"""
|
||||||
Assembles the URL associated with the notification based on the
|
Assembles the URL associated with the notification based on the
|
||||||
|
@ -280,7 +280,8 @@ class NotifyBoxcar(NotifyBase):
|
|||||||
|
|
||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{schema}://{access}/{secret}/{recipients}/?{args}'.format(
|
return '{schema}://{access}/{secret}/{recipients}/?{args}'.format(
|
||||||
|
@ -148,6 +148,14 @@ class NotifyDBus(NotifyBase):
|
|||||||
# The number of seconds to keep the message present for
|
# The number of seconds to keep the message present for
|
||||||
message_timeout_ms = 13000
|
message_timeout_ms = 13000
|
||||||
|
|
||||||
|
# Limit results to just the first 10 line otherwise there is just to much
|
||||||
|
# content to display
|
||||||
|
body_max_line_count = 10
|
||||||
|
|
||||||
|
# A title can not be used for SMS Messages. Setting this to zero will
|
||||||
|
# cause any title (if defined) to get placed into the message body.
|
||||||
|
title_maxlen = 0
|
||||||
|
|
||||||
# This entry is a bit hacky, but it allows us to unit-test this library
|
# This entry is a bit hacky, but it allows us to unit-test this library
|
||||||
# in an environment that simply doesn't have the gnome packages
|
# in an environment that simply doesn't have the gnome packages
|
||||||
# available to us. It also allows us to handle situations where the
|
# available to us. It also allows us to handle situations where the
|
||||||
@ -249,15 +257,6 @@ class NotifyDBus(NotifyBase):
|
|||||||
"Could not load Gnome notification icon ({}): {}"
|
"Could not load Gnome notification icon ({}): {}"
|
||||||
.format(icon_path, e))
|
.format(icon_path, e))
|
||||||
|
|
||||||
# Limit results to just the first 10 line otherwise
|
|
||||||
# there is just to much content to display
|
|
||||||
body = re.split('[\r\n]+', body)
|
|
||||||
if title:
|
|
||||||
# Place title on first line if it exists
|
|
||||||
body.insert(0, title)
|
|
||||||
|
|
||||||
body = '\r\n'.join(body[0:10])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dbus_iface.Notify(
|
dbus_iface.Notify(
|
||||||
# Application Identifier
|
# Application Identifier
|
||||||
|
@ -249,6 +249,7 @@ class NotifyDiscord(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'tts': 'yes' if self.tts else 'no',
|
'tts': 'yes' if self.tts else 'no',
|
||||||
'avatar': 'yes' if self.avatar else 'no',
|
'avatar': 'yes' if self.avatar else 'no',
|
||||||
'footer': 'yes' if self.footer else 'no',
|
'footer': 'yes' if self.footer else 'no',
|
||||||
|
@ -429,6 +429,7 @@ class NotifyEmail(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'to': self.to_addr,
|
'to': self.to_addr,
|
||||||
'from': self.from_addr,
|
'from': self.from_addr,
|
||||||
'name': self.from_name,
|
'name': self.from_name,
|
||||||
|
@ -543,6 +543,7 @@ class NotifyEmby(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'modal': 'yes' if self.modal else 'no',
|
'modal': 'yes' if self.modal else 'no',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ class NotifyFaast(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{schema}://{authtoken}/?{args}'.format(
|
return '{schema}://{authtoken}/?{args}'.format(
|
||||||
|
@ -26,8 +26,6 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
from .NotifyBase import NotifyBase
|
from .NotifyBase import NotifyBase
|
||||||
from ..common import NotifyImageSize
|
from ..common import NotifyImageSize
|
||||||
|
|
||||||
@ -86,6 +84,14 @@ class NotifyGnome(NotifyBase):
|
|||||||
# Allows the user to specify the NotifyImageSize object
|
# Allows the user to specify the NotifyImageSize object
|
||||||
image_size = NotifyImageSize.XY_128
|
image_size = NotifyImageSize.XY_128
|
||||||
|
|
||||||
|
# Limit results to just the first 10 line otherwise there is just to much
|
||||||
|
# content to display
|
||||||
|
body_max_line_count = 10
|
||||||
|
|
||||||
|
# A title can not be used for SMS Messages. Setting this to zero will
|
||||||
|
# cause any title (if defined) to get placed into the message body.
|
||||||
|
title_maxlen = 0
|
||||||
|
|
||||||
# This entry is a bit hacky, but it allows us to unit-test this library
|
# This entry is a bit hacky, but it allows us to unit-test this library
|
||||||
# in an environment that simply doesn't have the gnome packages
|
# in an environment that simply doesn't have the gnome packages
|
||||||
# available to us. It also allows us to handle situations where the
|
# available to us. It also allows us to handle situations where the
|
||||||
@ -119,15 +125,6 @@ class NotifyGnome(NotifyBase):
|
|||||||
"Gnome Notifications are not supported by this system.")
|
"Gnome Notifications are not supported by this system.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Limit results to just the first 10 line otherwise
|
|
||||||
# there is just to much content to display
|
|
||||||
body = re.split('[\r\n]+', body)
|
|
||||||
if title:
|
|
||||||
# Place title on first line if it exists
|
|
||||||
body.insert(0, title)
|
|
||||||
|
|
||||||
body = '\r\n'.join(body[0:10])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# App initialization
|
# App initialization
|
||||||
Notify.init(self.app_id)
|
Notify.init(self.app_id)
|
||||||
|
@ -223,6 +223,7 @@ class NotifyGrowl(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'priority':
|
'priority':
|
||||||
_map[GrowlPriority.NORMAL] if self.priority not in _map
|
_map[GrowlPriority.NORMAL] if self.priority not in _map
|
||||||
else _map[self.priority],
|
else _map[self.priority],
|
||||||
|
@ -214,6 +214,7 @@ class NotifyIFTTT(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{schema}://{webhook_id}@{events}/?{args}'.format(
|
return '{schema}://{webhook_id}@{events}/?{args}'.format(
|
||||||
|
@ -78,6 +78,7 @@ class NotifyJSON(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine Authentication
|
# Determine Authentication
|
||||||
|
@ -90,6 +90,10 @@ class NotifyJoin(NotifyBase):
|
|||||||
# Allows the user to specify the NotifyImageSize object
|
# Allows the user to specify the NotifyImageSize object
|
||||||
image_size = NotifyImageSize.XY_72
|
image_size = NotifyImageSize.XY_72
|
||||||
|
|
||||||
|
# Limit results to just the first 2 line otherwise there is just to much
|
||||||
|
# content to display
|
||||||
|
body_max_line_count = 2
|
||||||
|
|
||||||
# The maximum allowable characters allowed in the body per message
|
# The maximum allowable characters allowed in the body per message
|
||||||
body_maxlen = 1000
|
body_maxlen = 1000
|
||||||
|
|
||||||
@ -131,17 +135,6 @@ class NotifyJoin(NotifyBase):
|
|||||||
Perform Join Notification
|
Perform Join Notification
|
||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
|
||||||
# Limit results to just the first 2 line otherwise
|
|
||||||
# there is just to much content to display
|
|
||||||
body = re.split('[\r\n]+', body)
|
|
||||||
body[0] = body[0].strip('#').strip()
|
|
||||||
body = '\r\n'.join(body[0:2])
|
|
||||||
|
|
||||||
except (AttributeError, TypeError):
|
|
||||||
# body was None or not of a type string
|
|
||||||
body = ''
|
|
||||||
|
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent': self.app_id,
|
'User-Agent': self.app_id,
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
@ -241,6 +234,7 @@ class NotifyJoin(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{schema}://{apikey}/{devices}/?{args}'.format(
|
return '{schema}://{apikey}/{devices}/?{args}'.format(
|
||||||
|
@ -244,6 +244,7 @@ class NotifyMatrix(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'mode': self.mode,
|
'mode': self.mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,6 +187,7 @@ class NotifyMatterMost(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
default_port = 443 if self.secure else self.default_port
|
default_port = 443 if self.secure else self.default_port
|
||||||
|
@ -206,6 +206,7 @@ class NotifyProwl(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'priority': 'normal' if self.priority not in _map
|
'priority': 'normal' if self.priority not in _map
|
||||||
else _map[self.priority]
|
else _map[self.priority]
|
||||||
}
|
}
|
||||||
|
@ -190,6 +190,7 @@ class NotifyPushBullet(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
recipients = '/'.join([self.quote(x) for x in self.recipients])
|
recipients = '/'.join([self.quote(x) for x in self.recipients])
|
||||||
|
@ -265,6 +265,7 @@ class NotifyPushed(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{schema}://{app_key}/{app_secret}/{targets}/?{args}'.format(
|
return '{schema}://{app_key}/{app_secret}/{targets}/?{args}'.format(
|
||||||
|
@ -95,6 +95,7 @@ class NotifyPushjet(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
default_port = 443 if self.secure else 80
|
default_port = 443 if self.secure else 80
|
||||||
|
@ -253,6 +253,7 @@ class NotifyPushover(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'priority':
|
'priority':
|
||||||
_map[PushoverPriority.NORMAL] if self.priority not in _map
|
_map[PushoverPriority.NORMAL] if self.priority not in _map
|
||||||
else _map[self.priority],
|
else _map[self.priority],
|
||||||
|
@ -148,6 +148,7 @@ class NotifyRocketChat(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine Authentication
|
# Determine Authentication
|
||||||
|
@ -229,6 +229,7 @@ class NotifyRyver(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
'webhook': self.webhook,
|
'webhook': self.webhook,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,6 +90,10 @@ class NotifySNS(NotifyBase):
|
|||||||
# Source: https://docs.aws.amazon.com/sns/latest/api/API_Publish.html
|
# Source: https://docs.aws.amazon.com/sns/latest/api/API_Publish.html
|
||||||
body_maxlen = 140
|
body_maxlen = 140
|
||||||
|
|
||||||
|
# A title can not be used for SMS Messages. Setting this to zero will
|
||||||
|
# cause any title (if defined) to get placed into the message body.
|
||||||
|
title_maxlen = 0
|
||||||
|
|
||||||
def __init__(self, access_key_id, secret_access_key, region_name,
|
def __init__(self, access_key_id, secret_access_key, region_name,
|
||||||
recipients=None, **kwargs):
|
recipients=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
@ -530,6 +534,7 @@ class NotifySNS(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
return '{schema}://{key_id}/{key_secret}/{region}/{targets}/'\
|
return '{schema}://{key_id}/{key_secret}/{region}/{targets}/'\
|
||||||
|
@ -304,6 +304,7 @@ class NotifySlack(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine if there is a botname present
|
# Determine if there is a botname present
|
||||||
|
@ -498,6 +498,7 @@ class NotifyTelegram(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# No need to check the user token because the user automatically gets
|
# No need to check the user token because the user automatically gets
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import re
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
|
|
||||||
from .NotifyBase import NotifyBase
|
from .NotifyBase import NotifyBase
|
||||||
@ -67,6 +66,10 @@ class NotifyWindows(NotifyBase):
|
|||||||
# Allows the user to specify the NotifyImageSize object
|
# Allows the user to specify the NotifyImageSize object
|
||||||
image_size = NotifyImageSize.XY_128
|
image_size = NotifyImageSize.XY_128
|
||||||
|
|
||||||
|
# Limit results to just the first 2 line otherwise there is just to much
|
||||||
|
# content to display
|
||||||
|
body_max_line_count = 2
|
||||||
|
|
||||||
# This entry is a bit hacky, but it allows us to unit-test this library
|
# This entry is a bit hacky, but it allows us to unit-test this library
|
||||||
# in an environment that simply doesn't have the windows packages
|
# in an environment that simply doesn't have the windows packages
|
||||||
# available to us. It also allows us to handle situations where the
|
# available to us. It also allows us to handle situations where the
|
||||||
@ -110,12 +113,6 @@ class NotifyWindows(NotifyBase):
|
|||||||
"Windows Notifications are not supported by this system.")
|
"Windows Notifications are not supported by this system.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Limit results to just the first 2 line otherwise
|
|
||||||
# there is just to much content to display
|
|
||||||
body = re.split('[\r\n]+', body)
|
|
||||||
body[0] = body[0].strip('#').strip()
|
|
||||||
body = '\r\n'.join(body[0:2])
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Register destruction callback
|
# Register destruction callback
|
||||||
message_map = {win32con.WM_DESTROY: self._on_destroy, }
|
message_map = {win32con.WM_DESTROY: self._on_destroy, }
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
# THE SOFTWARE.
|
# THE SOFTWARE.
|
||||||
|
|
||||||
import re
|
|
||||||
import requests
|
import requests
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
|
||||||
@ -58,6 +57,10 @@ class NotifyXBMC(NotifyBase):
|
|||||||
# A URL that takes you to the setup/help of the specific protocol
|
# A URL that takes you to the setup/help of the specific protocol
|
||||||
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_kodi'
|
setup_url = 'https://github.com/caronc/apprise/wiki/Notify_kodi'
|
||||||
|
|
||||||
|
# Limit results to just the first 2 line otherwise there is just to much
|
||||||
|
# content to display
|
||||||
|
body_max_line_count = 2
|
||||||
|
|
||||||
# XBMC uses the http protocol with JSON requests
|
# XBMC uses the http protocol with JSON requests
|
||||||
xbmc_default_port = 8080
|
xbmc_default_port = 8080
|
||||||
|
|
||||||
@ -159,12 +162,6 @@ class NotifyXBMC(NotifyBase):
|
|||||||
Perform XBMC/KODI Notification
|
Perform XBMC/KODI Notification
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Limit results to just the first 2 line otherwise
|
|
||||||
# there is just to much content to display
|
|
||||||
body = re.split('[\r\n]+', body)
|
|
||||||
body[0] = body[0].strip('#').strip()
|
|
||||||
body = '\r\n'.join(body[0:2])
|
|
||||||
|
|
||||||
if self.protocol == self.xbmc_remote_protocol:
|
if self.protocol == self.xbmc_remote_protocol:
|
||||||
# XBMC v2.0
|
# XBMC v2.0
|
||||||
(headers, payload) = self._payload_20(
|
(headers, payload) = self._payload_20(
|
||||||
@ -237,6 +234,7 @@ class NotifyXBMC(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine Authentication
|
# Determine Authentication
|
||||||
|
@ -93,6 +93,7 @@ class NotifyXML(NotifyBase):
|
|||||||
# Define any arguments set
|
# Define any arguments set
|
||||||
args = {
|
args = {
|
||||||
'format': self.notify_format,
|
'format': self.notify_format,
|
||||||
|
'overflow': self.overflow_mode,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Determine Authentication
|
# Determine Authentication
|
||||||
|
@ -25,12 +25,18 @@
|
|||||||
|
|
||||||
from apprise import plugins
|
from apprise import plugins
|
||||||
from apprise import NotifyType
|
from apprise import NotifyType
|
||||||
|
from apprise import NotifyBase
|
||||||
from apprise import Apprise
|
from apprise import Apprise
|
||||||
from apprise import AppriseAsset
|
from apprise import AppriseAsset
|
||||||
from apprise.utils import compat_is_basestring
|
from apprise.utils import compat_is_basestring
|
||||||
from apprise.common import NotifyFormat
|
from apprise.common import NotifyFormat
|
||||||
|
from apprise.common import OverflowMode
|
||||||
|
|
||||||
from json import dumps
|
from json import dumps
|
||||||
|
from random import choice
|
||||||
|
from string import ascii_uppercase as str_alpha
|
||||||
|
from string import digits as str_num
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import mock
|
import mock
|
||||||
|
|
||||||
@ -2883,3 +2889,338 @@ def test_notify_telegram_plugin(mock_post, mock_get):
|
|||||||
except TypeError:
|
except TypeError:
|
||||||
# Exception should be thrown about the fact no token was specified
|
# Exception should be thrown about the fact no token was specified
|
||||||
assert(True)
|
assert(True)
|
||||||
|
|
||||||
|
|
||||||
|
def test_notify_overflow_truncate():
|
||||||
|
"""
|
||||||
|
API: Overflow Truncate Functionality Testing
|
||||||
|
|
||||||
|
"""
|
||||||
|
#
|
||||||
|
# A little preparation
|
||||||
|
#
|
||||||
|
|
||||||
|
# Number of characters per line
|
||||||
|
row = 24
|
||||||
|
|
||||||
|
# Some variables we use to control the data we work with
|
||||||
|
body_len = 1024
|
||||||
|
title_len = 1024
|
||||||
|
|
||||||
|
# Create a large body and title with random data
|
||||||
|
body = ''.join(choice(str_alpha + str_num + ' ') for _ in range(body_len))
|
||||||
|
body = '\r\n'.join([body[i: i + row] for i in range(0, len(body), row)])
|
||||||
|
|
||||||
|
# the new lines add a large amount to our body; lets force the content
|
||||||
|
# back to being 1024 characters.
|
||||||
|
body = body[0:1024]
|
||||||
|
|
||||||
|
# Create our title using random data
|
||||||
|
title = ''.join(choice(str_alpha + str_num) for _ in range(title_len))
|
||||||
|
|
||||||
|
#
|
||||||
|
# First Test: Truncated Title
|
||||||
|
#
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Test title max length
|
||||||
|
title_maxlen = 10
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow='invalid')
|
||||||
|
|
||||||
|
# We should have thrown an exception because our specified overflow
|
||||||
|
# is wrong.
|
||||||
|
assert False
|
||||||
|
|
||||||
|
except TypeError:
|
||||||
|
# Expected to be here
|
||||||
|
assert True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.TRUNCATE)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
assert len(chunks) == 1
|
||||||
|
assert body == chunks[0].get('body')
|
||||||
|
assert title[0:TestNotification.title_maxlen] == chunks[0].get('title')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Next Test: Line Count Control
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Test title max length
|
||||||
|
title_maxlen = 5
|
||||||
|
|
||||||
|
# Maximum number of lines
|
||||||
|
body_max_line_count = 5
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.TRUNCATE)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
assert len(chunks) == 1
|
||||||
|
assert len(chunks[0].get('body').split('\n')) == \
|
||||||
|
TestNotification.body_max_line_count
|
||||||
|
assert title[0:TestNotification.title_maxlen] == chunks[0].get('title')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Next Test: Truncated body
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Test title max length
|
||||||
|
title_maxlen = title_len
|
||||||
|
|
||||||
|
# Enforce a body length of just 10
|
||||||
|
body_maxlen = 10
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.TRUNCATE)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
assert len(chunks) == 1
|
||||||
|
assert body[0:TestNotification.body_maxlen] == chunks[0].get('body')
|
||||||
|
assert title == chunks[0].get('title')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Next Test: Append title to body + Truncated body
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Enforce no title
|
||||||
|
title_maxlen = 0
|
||||||
|
|
||||||
|
# Enforce a body length of just 100
|
||||||
|
body_maxlen = 100
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.TRUNCATE)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
assert len(chunks) == 1
|
||||||
|
|
||||||
|
# The below line should be read carefully... We're actually testing to see
|
||||||
|
# that our title is matched against our body. Behind the scenes, the title
|
||||||
|
# was appended to the body. The body was then truncated to the maxlen.
|
||||||
|
# The thing is, since the title is so large, all of the body was lost
|
||||||
|
# and a good chunk of the title was too. The message sent will just be a
|
||||||
|
# small portion of the title
|
||||||
|
assert len(chunks[0].get('body')) == TestNotification.body_maxlen
|
||||||
|
assert title[0:TestNotification.body_maxlen] == chunks[0].get('body')
|
||||||
|
|
||||||
|
|
||||||
|
def test_notify_overflow_split():
|
||||||
|
"""
|
||||||
|
API: Overflow Split Functionality Testing
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
#
|
||||||
|
# A little preparation
|
||||||
|
#
|
||||||
|
|
||||||
|
# Number of characters per line
|
||||||
|
row = 24
|
||||||
|
|
||||||
|
# Some variables we use to control the data we work with
|
||||||
|
body_len = 1024
|
||||||
|
title_len = 1024
|
||||||
|
|
||||||
|
# Create a large body and title with random data
|
||||||
|
body = ''.join(choice(str_alpha + str_num + ' ') for _ in range(body_len))
|
||||||
|
body = '\r\n'.join([body[i: i + row] for i in range(0, len(body), row)])
|
||||||
|
|
||||||
|
# the new lines add a large amount to our body; lets force the content
|
||||||
|
# back to being 1024 characters.
|
||||||
|
body = body[0:1024]
|
||||||
|
|
||||||
|
# Create our title using random data
|
||||||
|
title = ''.join(choice(str_alpha + str_num) for _ in range(title_len))
|
||||||
|
|
||||||
|
#
|
||||||
|
# First Test: Truncated Title
|
||||||
|
#
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Test title max length
|
||||||
|
title_maxlen = 10
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.SPLIT)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
assert len(chunks) == 1
|
||||||
|
assert body == chunks[0].get('body')
|
||||||
|
assert title[0:TestNotification.title_maxlen] == chunks[0].get('title')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Next Test: Line Count Control
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Test title max length
|
||||||
|
title_maxlen = 5
|
||||||
|
|
||||||
|
# Maximum number of lines
|
||||||
|
body_max_line_count = 5
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.SPLIT)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
assert len(chunks) == 1
|
||||||
|
assert len(chunks[0].get('body').split('\n')) == \
|
||||||
|
TestNotification.body_max_line_count
|
||||||
|
assert title[0:TestNotification.title_maxlen] == chunks[0].get('title')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Next Test: Split body
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Test title max length
|
||||||
|
title_maxlen = title_len
|
||||||
|
|
||||||
|
# Enforce a body length
|
||||||
|
body_maxlen = (body_len / 4)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.SPLIT)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
offset = 0
|
||||||
|
assert len(chunks) == 4
|
||||||
|
for chunk in chunks:
|
||||||
|
# Our title never changes
|
||||||
|
assert title == chunk.get('title')
|
||||||
|
|
||||||
|
# Our body is only broken up; not lost
|
||||||
|
_body = chunk.get('body')
|
||||||
|
assert body[offset: len(_body) + offset] == _body
|
||||||
|
offset += len(_body)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Next Test: Append title to body + split body
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestNotification(NotifyBase):
|
||||||
|
|
||||||
|
# Enforce no title
|
||||||
|
title_maxlen = 0
|
||||||
|
|
||||||
|
# Enforce a body length
|
||||||
|
body_maxlen = (title_len / 4)
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(TestNotification, self).__init__(**kwargs)
|
||||||
|
|
||||||
|
def notify(self, *args, **kwargs):
|
||||||
|
# Pretend everything is okay
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Load our object
|
||||||
|
obj = TestNotification(overflow=OverflowMode.SPLIT)
|
||||||
|
assert obj is not None
|
||||||
|
|
||||||
|
# Verify that we break the title to a max length of our title_max
|
||||||
|
# and that the body remains untouched
|
||||||
|
chunks = obj._apply_overflow(body=body, title=title)
|
||||||
|
|
||||||
|
# Our final product is that our title has been appended to our body to
|
||||||
|
# create one great big body. As a result we'll get quite a few lines back
|
||||||
|
# now.
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
# Our body will look like this in small chunks at the end of the day
|
||||||
|
bulk = title + '\r\n' + body
|
||||||
|
|
||||||
|
# Due to the new line added to the end
|
||||||
|
assert len(chunks) == (
|
||||||
|
(len(bulk) / TestNotification.body_maxlen) +
|
||||||
|
(1 if len(bulk) % TestNotification.body_maxlen else 0))
|
||||||
|
|
||||||
|
for chunk in chunks:
|
||||||
|
# Our title is empty every time
|
||||||
|
assert chunk.get('title') == ''
|
||||||
|
|
||||||
|
_body = chunk.get('body')
|
||||||
|
assert bulk[offset:len(_body)+offset] == _body
|
||||||
|
offset += len(_body)
|
||||||
|
Loading…
Reference in New Issue
Block a user