Telegram control over attachments displayed before or after content (#883)

pull/887/head
Chris Caron 2023-06-04 22:28:44 -04:00 committed by GitHub
parent c60e35841f
commit 3346977297
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 97 additions and 23 deletions

View File

@ -84,6 +84,23 @@ IS_CHAT_ID_RE = re.compile(
)
class TelegramContentPlacement:
"""
The Telegram Content Placement
"""
# Before Attachments
BEFORE = "before"
# After Attachments
AFTER = "after"
# Identify Placement Categories
TELEGRAM_CONTENT_PLACEMENT = (
TelegramContentPlacement.BEFORE,
TelegramContentPlacement.AFTER,
)
class NotifyTelegram(NotifyBase):
"""
A wrapper for Telegram Notifications
@ -319,11 +336,17 @@ class NotifyTelegram(NotifyBase):
'to': {
'alias_of': 'targets',
},
'content': {
'name': _('Content Placement'),
'type': 'choice:string',
'values': TELEGRAM_CONTENT_PLACEMENT,
'default': TelegramContentPlacement.BEFORE,
},
})
def __init__(self, bot_token, targets, detect_owner=True,
include_image=False, silent=None, preview=None, topic=None,
**kwargs):
content=None, **kwargs):
"""
Initialize Telegram Object
"""
@ -349,6 +372,15 @@ class NotifyTelegram(NotifyBase):
self.preview = self.template_args['preview']['default'] \
if preview is None else bool(preview)
# Setup our content placement
self.content = self.template_args['content']['default'] \
if not isinstance(content, str) else content.lower()
if self.content and self.content not in TELEGRAM_CONTENT_PLACEMENT:
msg = 'The content placement specified ({}) is invalid.'\
.format(content)
self.logger.warning(msg)
raise TypeError(msg)
if topic:
try:
self.topic = int(topic)
@ -713,6 +745,15 @@ class NotifyTelegram(NotifyBase):
'Failed to send Telegram type image to {}.',
payload['chat_id'])
if attach and self.content == TelegramContentPlacement.AFTER:
# Send our attachments now (if specified and if it exists)
if not self._send_attachments(
chat_id=payload['chat_id'], notify_type=notify_type,
attach=attach):
has_error = True
continue
# Always call throttle before any remote server i/o is made;
# Telegram throttles to occur before sending the image so that
# content can arrive together.
@ -775,19 +816,35 @@ class NotifyTelegram(NotifyBase):
self.logger.info('Sent Telegram notification.')
if attach:
# Send our attachments now (if specified and if it exists)
for attachment in attach:
if not self.send_media(
payload['chat_id'], notify_type,
attach=attachment):
if attach and self.content == TelegramContentPlacement.BEFORE:
# Send our attachments now (if specified and if it exists) as
# it was identified to send the content before the attachments
# which is now done.
if not self._send_attachments(
chat_id=payload['chat_id'],
notify_type=notify_type,
attach=attach):
# We failed; don't continue
has_error = True
break
has_error = True
continue
self.logger.info(
'Sent Telegram attachment: {}.'.format(attachment))
return not has_error
def _send_attachments(self, chat_id, notify_type, attach):
"""
Sends our attachments
"""
has_error = False
# Send our attachments now (if specified and if it exists)
for attachment in attach:
if not self.send_media(chat_id, notify_type, attach=attachment):
# We failed; don't continue
has_error = True
break
self.logger.info(
'Sent Telegram attachment: {}.'.format(attachment))
return not has_error
@ -802,6 +859,7 @@ class NotifyTelegram(NotifyBase):
'detect': 'yes' if self.detect_owner else 'no',
'silent': 'yes' if self.silent else 'no',
'preview': 'yes' if self.preview else 'no',
'content': self.content,
}
if self.topic:
@ -885,6 +943,10 @@ class NotifyTelegram(NotifyBase):
# Store our chat ids (as these are the remaining entries)
results['targets'] = entries
# content to be displayed 'before' or 'after' attachments
if 'content' in results['qsd'] and len(results['qsd']['content']):
results['content'] = results['qsd']['content']
# Support the 'to' variable so that we can support rooms this way too
# The 'to' makes it easier to use yaml configuration
if 'to' in results['qsd'] and len(results['qsd']['to']):

View File

@ -106,6 +106,10 @@ apprise_url_tests = (
('tgram://bottest@123456789:abcdefg_hijklmnop/id1/?topic=invalid', {
'instance': TypeError,
}),
# content must be 'before' or 'after'
('tgram://bottest@123456789:abcdefg_hijklmnop/id1/?content=invalid', {
'instance': TypeError,
}),
# Testing image
('tgram://123456789:abcdefg_hijklmnop/lead2gold/?image=Yes', {
'instance': NotifyTelegram,
@ -413,18 +417,26 @@ def test_plugin_telegram_general(mock_post):
assert payload['text'] == \
'<b>special characters</b>\r\n\'"This can\'t\t\r\nfail us"\'\r\n'
# Test sending attachments
attach = AppriseAttachment(os.path.join(TEST_VAR_DIR, 'apprise-test.gif'))
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO,
attach=attach) is True
for content in ('before', 'after'):
# Test our content settings
obj = NotifyTelegram(
bot_token=bot_token, targets='12345', content=content)
# Reset our mock
mock_post.reset_mock()
# Test sending attachments
attach = AppriseAttachment(
os.path.join(TEST_VAR_DIR, 'apprise-test.gif'))
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO,
attach=attach) is True
# An invalid attachment will cause a failure
path = os.path.join(TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg')
attach = AppriseAttachment(path)
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO,
attach=path) is False
# An invalid attachment will cause a failure
path = os.path.join(
TEST_VAR_DIR, '/invalid/path/to/an/invalid/file.jpg')
attach = AppriseAttachment(path)
assert obj.notify(
body='body', title='title', notify_type=NotifyType.INFO,
attach=path) is False
obj = NotifyTelegram(bot_token=bot_token, targets=None)
# No user detected; this happens after our firsst notification