mobilizon link in template (#80)

* added basic recap feature (no error handling)

* introduced abstractpublication

* extracted base reports

* added error report to recap

* added test

* added docs

* implemented publisher and formatter

* fixed API for recap

* removed redundant config validation

* added config sample

* added mobilizon link to templates

* added link format to telegram

* added mobilizon link to recap

* fixed config and emoji
This commit is contained in:
Simone Robutti 2021-10-19 07:35:18 +02:00 committed by GitHub
parent 489d41179e
commit 8de70ef857
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 68 additions and 20 deletions

View File

@ -5,6 +5,9 @@ telegram_validators = [
Validator("publisher.telegram.chat_id", must_exist=True),
Validator("publisher.telegram.msg_template_path", must_exist=True, default=None),
Validator("publisher.telegram.recap_template_path", must_exist=True, default=None),
Validator(
"publisher.telegram.recap_header_template_path", must_exist=True, default=None
),
Validator("publisher.telegram.token", must_exist=True),
Validator("publisher.telegram.username", must_exist=True),
]
@ -13,6 +16,9 @@ zulip_validators = [
Validator("publisher.zulip.subject", must_exist=True),
Validator("publisher.zulip.msg_template_path", must_exist=True, default=None),
Validator("publisher.zulip.recap_template_path", must_exist=True, default=None),
Validator(
"publisher.zulip.recap_header_template_path", must_exist=True, default=None
),
Validator("publisher.zulip.bot_token", must_exist=True),
Validator("publisher.zulip.bot_email", must_exist=True),
]
@ -20,6 +26,9 @@ mastodon_validators = []
twitter_validators = [
Validator("publisher.twitter.msg_template_path", must_exist=True, default=None),
Validator("publisher.twitter.recap_template_path", must_exist=True, default=None),
Validator(
"publisher.twitter.recap_header_template_path", must_exist=True, default=None
),
Validator("publisher.twitter.api_key", must_exist=True),
Validator("publisher.twitter.api_key_secret", must_exist=True),
Validator("publisher.twitter.access_token", must_exist=True),

View File

@ -132,7 +132,7 @@ class AbstractEventFormatter(LoggerMixin, ConfLoaderMixin):
"""
return event
def get_message_from_event(self, event) -> str:
def get_message_from_event(self, event: MobilizonEvent) -> str:
"""
Retrieves a message from the event itself.
"""
@ -147,6 +147,7 @@ class AbstractEventFormatter(LoggerMixin, ConfLoaderMixin):
return JINJA_ENV.get_template(template_path)
def is_message_valid(self, event: MobilizonEvent) -> bool:
# TODO: this thing swallows exception messages. It should be handled differently
try:
self.validate_message(self.get_message_from_event(event))
except PublisherError:

View File

@ -1,9 +1,7 @@
class PublisherError(Exception):
""" Generic publisher error """
def __init__(self, message):
""" :param str message: exception message """
super().__init__(message)
pass
class InvalidAttribute(PublisherError):

View File

@ -1,3 +1,5 @@
import re
import pkg_resources
import requests
from requests import Response
@ -30,17 +32,37 @@ class TelegramFormatter(AbstractEventFormatter):
)
_conf = ("publisher", "telegram")
_escape_characters = [
"-",
".",
"(",
"!",
")",
]
@staticmethod
def restore_links(message: str) -> str:
"""The escape_message function should ignore actually valid links that involve square brackets and parenthesis.
This function de-escapes actual links without altering other escaped square brackets and parenthesis"""
def build_link(match):
result = match.group(0)
for character in TelegramFormatter._escape_characters:
result = result.replace("\\" + character, character)
return result
return re.sub(r"\[(\w*)]\\\(([\w\-/\\.:]*)\\\)", build_link, message,)
@staticmethod
def escape_message(message: str) -> str:
return (
message.replace("-", r"\-")
.replace(".", r"\.")
.replace("(", r"\(")
.replace("!", r"\!")
.replace(")", r"\)")
.replace("#", r"")
)
"""Escape message to comply with Telegram standards"""
for character in TelegramFormatter._escape_characters:
message = message.replace(character, "\\" + character)
# Telegram doesn't use headers so # can be removed
message = message.replace("#", r"")
return TelegramFormatter.restore_links(message)
def validate_event(self, event: MobilizonEvent) -> None:
description = event.description

View File

@ -1,5 +1,5 @@
import pkg_resources
from tweepy import OAuthHandler, API
from tweepy import OAuthHandler, API, TweepyException
from tweepy.models import Status
from mobilizon_reshare.event.event import MobilizonEvent
@ -35,7 +35,9 @@ class TwitterFormatter(AbstractEventFormatter):
self._log_error("No text was found", raise_error=InvalidEvent)
def validate_message(self, message) -> None:
if len(message.encode("utf-8")) > 140:
# TODO this is not precise. It should count the characters according to Twitter's logic but
# Tweepy doesn't seem to support the validation client side
if len(message.encode("utf-8")) > 280:
raise PublisherError("Message is too long")
@ -57,7 +59,10 @@ class TwitterPlatform(AbstractPlatform):
return API(auth)
def _send(self, message: str) -> Status:
return self._get_api().update_status(message)
try:
return self._get_api().update_status(message)
except TweepyException as e:
raise PublisherError from e
def validate_credentials(self):
if not self._get_api().verify_credentials():

View File

@ -3,4 +3,6 @@
🕒 {{ begin_datetime.format('DD MMMM, HH:mm') }} - {{ end_datetime.format('DD MMMM, HH:mm') }}
{% if location %}📍 {{ location }}{% endif %}
{{ description }}
{{ description }}
[Link]({{mobilizon_link}})

View File

@ -2,3 +2,4 @@
🕒 {{ begin_datetime.format('DD MMMM, HH:mm') }} - {{ end_datetime.format('DD MMMM, HH:mm') }}
{% if location %}📍 {{ location }}{% endif %}
🔗 [Link]({{mobilizon_link}})

View File

@ -5,4 +5,5 @@
{% if location %}
📍 {{ location }}
{% endif %}
{% endif %}
{{mobilizon_link}}

View File

@ -2,4 +2,5 @@
🕒 {{ begin_datetime.format('DD MMMM, HH:mm') }} - {{ end_datetime.format('DD MMMM, HH:mm') }}
{% if location %}
📍 {{ location }}
{% endif %}
{% endif %}
🔗 {{mobilizon_link}}

View File

@ -6,4 +6,6 @@
📍 {{ location }}
{% endif %}
{{ description }}
{{ description }}
[Link]({{mobilizon_link}})

View File

@ -5,4 +5,5 @@
{% if location %}
📍 {{ location }}
{% endif %}
{% endif %}
🔗 {{mobilizon_link}}

View File

@ -30,6 +30,11 @@ def test_message_length_failure(event):
["!", "\\!"],
[")", "\\)"],
[")!", "\\)\\!"],
["[link](https://link.com)", "[link](https://link.com)"],
[
"[link](https://link.com) [link2](https://link.com)",
"[link](https://link.com) [link2](https://link.com)",
],
],
)
def test_escape_message(message, result):