mirror of
https://github.com/Tech-Workers-Coalition-Italia/mobilizon-reshare.git
synced 2025-01-28 16:20:10 +01:00
Fix markdown cropping (#128)
* fixed error log * changed telegram publisher to use HTML format * fixed dataclass update issue * docker: Add python-telegram-bot. * docker: mobilizon-reshare: Reenable non deterministic tests. Co-authored-by: Giacomo Leidi <goodoldpaul@autistici.org>
This commit is contained in:
parent
434438fd20
commit
5804b55dd8
@ -12,8 +12,10 @@
|
||||
#:use-module (gnu packages openstack)
|
||||
#:use-module (gnu packages python-build)
|
||||
#:use-module (gnu packages python-check)
|
||||
#:use-module (gnu packages python-crypto)
|
||||
#:use-module (gnu packages python-web)
|
||||
#:use-module (gnu packages python-xyz)
|
||||
#:use-module (gnu packages qt)
|
||||
#:use-module (gnu packages time)
|
||||
#:use-module (ice-9 popen)
|
||||
#:use-module (ice-9 rdelim)
|
||||
@ -203,6 +205,130 @@ Facebook authentication.")
|
||||
"This package provides a database migrations tool for Tortoise ORM.")
|
||||
(license #f)))
|
||||
|
||||
(define-public python-pytest-tornado5
|
||||
(package
|
||||
(name "python-pytest-tornado5")
|
||||
(version "2.0.0")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "pytest-tornado5" version))
|
||||
(sha256
|
||||
(base32 "0qb62jw2w0xr6y942yp0qxiy755bismjfpnxaxjjm05gy2pymr8d"))))
|
||||
(build-system python-build-system)
|
||||
(propagated-inputs (list python-pytest python-tornado))
|
||||
(home-page "https://github.com/vidartf/pytest-tornado")
|
||||
(synopsis
|
||||
"Fixtures and markers to simplify testing of Tornado applications")
|
||||
(description
|
||||
"This package provides a @code{py.test} plugin providing fixtures and markers to
|
||||
simplify testing of asynchronous tornado applications.")
|
||||
(license license:asl2.0)))
|
||||
|
||||
(define-public python-rethinkdb
|
||||
(package
|
||||
(name "python-rethinkdb")
|
||||
(version "2.4.8")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "rethinkdb" version))
|
||||
(sha256
|
||||
(base32 "1vmap0la5j8xpigyp5bqph9cb6dskyw76y37n3vb16l9rlmsfxcz"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
`(#:tests? #f))
|
||||
(propagated-inputs (list python-six))
|
||||
(home-page "https://github.com/RethinkDB/rethinkdb-python")
|
||||
(synopsis "Python driver library for the RethinkDB database server.")
|
||||
(description "Python driver library for the RethinkDB database server.")
|
||||
(license #f)))
|
||||
|
||||
(define-public python-apscheduler
|
||||
(package
|
||||
(name "python-apscheduler")
|
||||
(version "3.8.1")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "APScheduler" version))
|
||||
(sha256
|
||||
(base32 "0m93bz9qpw6iwhay68bwljjcfyzcbh2rq0lc2yp4iamxrzml9wsw"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
`(#:phases
|
||||
(modify-phases %standard-phases
|
||||
(replace 'check
|
||||
(lambda* (#:key tests? #:allow-other-keys)
|
||||
(when tests?
|
||||
;; FIXME: Currently python-kazoo fails to build.
|
||||
(delete-file "tests/test_jobstores.py")
|
||||
(invoke "pytest")))))))
|
||||
(propagated-inputs
|
||||
(list python-pytz
|
||||
python-setuptools
|
||||
python-six
|
||||
python-tzlocal))
|
||||
(native-inputs
|
||||
(list python-mock
|
||||
python-pyqt
|
||||
python-twisted
|
||||
python-gevent
|
||||
python-setuptools-scm
|
||||
python-sqlalchemy
|
||||
python-redis
|
||||
python-pymongo
|
||||
python-rethinkdb
|
||||
python-pytest
|
||||
python-pytest-asyncio
|
||||
python-pytest-cov
|
||||
python-pytest-tornado5))
|
||||
(home-page "https://github.com/agronholm/apscheduler")
|
||||
(synopsis "In-process task scheduler with Cron-like capabilities")
|
||||
(description "In-process task scheduler with Cron-like capabilities")
|
||||
(license license:expat)))
|
||||
|
||||
(define-public python-apscheduler-3.6.3
|
||||
(package (inherit python-apscheduler)
|
||||
(version "3.6.3")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "APScheduler" version))
|
||||
(sha256
|
||||
(base32 "0i72qpqgrgq6bb9vwsac46m7bqb6mq92g5nf2gydmfvgxng25d9v"))))))
|
||||
|
||||
(define-public python-telegram-bot
|
||||
(package
|
||||
(name "python-telegram-bot")
|
||||
(version "13.10")
|
||||
(source
|
||||
(origin
|
||||
(method url-fetch)
|
||||
(uri (pypi-uri "python-telegram-bot" version))
|
||||
(sha256
|
||||
(base32 "0ghyq044s0zi67hxwxdjjfvh37wr86pi5kmpq7harx11311mbifj"))))
|
||||
(build-system python-build-system)
|
||||
(arguments
|
||||
;; FIXME: Most tests require network access. Some of them can
|
||||
;; be run from the git repository but many still fail due
|
||||
;; to vendoring of a seemingly heavily patched urllib3.
|
||||
`(#:tests? #f))
|
||||
(native-inputs
|
||||
(list python-beautifulsoup4
|
||||
python-pytest
|
||||
python-flaky))
|
||||
(propagated-inputs
|
||||
(list python-apscheduler-3.6.3
|
||||
python-cachetools
|
||||
python-certifi
|
||||
python-pytz
|
||||
python-tornado-6))
|
||||
(home-page "https://python-telegram-bot.org/")
|
||||
(synopsis "We have made you a wrapper you can't refuse")
|
||||
(description "We have made you a wrapper you can't refuse")
|
||||
(license #f)))
|
||||
|
||||
(define-public mobilizon-reshare.git
|
||||
(let ((source-version (with-input-from-file
|
||||
(string-append %source-dir
|
||||
@ -236,9 +362,8 @@ Facebook authentication.")
|
||||
(when tests?
|
||||
(invoke "python" "-m" "pytest"
|
||||
;; This test fails because of the unvendoring
|
||||
;; of toml from dynaconf and
|
||||
;; because they depend on system timezone.
|
||||
"-k" "not test_get_settings_failure_invalid_toml and not test_format_event"))))
|
||||
;; of toml from dynaconf.
|
||||
"-k" "not test_get_settings_failure_invalid_toml"))))
|
||||
(add-before 'sanity-check 'set-dummy-config
|
||||
(lambda _
|
||||
;; This is needed to prevent the tool from
|
||||
@ -268,6 +393,7 @@ Facebook authentication.")
|
||||
python-jinja2
|
||||
python-markdownify
|
||||
python-requests
|
||||
python-telegram-bot
|
||||
python-tweepy
|
||||
python-tortoise-orm))
|
||||
(home-page
|
||||
|
@ -11,7 +11,7 @@ from jinja2 import Environment, FileSystemLoader, Template
|
||||
from mobilizon_reshare.config.config import get_settings
|
||||
from mobilizon_reshare.event.event import MobilizonEvent
|
||||
from mobilizon_reshare.models.publication import Publication as PublicationModel
|
||||
from .exceptions import PublisherError, InvalidAttribute
|
||||
from .exceptions import InvalidAttribute
|
||||
|
||||
JINJA_ENV = Environment(loader=FileSystemLoader("/"))
|
||||
|
||||
@ -34,7 +34,7 @@ class LoggerMixin:
|
||||
def _log_critical(self, msg, *args, **kwargs):
|
||||
self.__log(logging.CRITICAL, msg, *args, **kwargs)
|
||||
|
||||
def __log(self, level, msg, raise_error: PublisherError = None, *args, **kwargs):
|
||||
def __log(self, level, msg, raise_error: type = None, *args, **kwargs):
|
||||
method = inspect.currentframe().f_back.f_back.f_code.co_name
|
||||
logger.log(level, f"{self}.{method}(): {msg}", *args, **kwargs)
|
||||
if raise_error is not None:
|
||||
@ -91,13 +91,9 @@ class AbstractPlatform(ABC, LoggerMixin, ConfLoaderMixin):
|
||||
"""
|
||||
Sends a message to the target channel
|
||||
"""
|
||||
message = self._preprocess_message(message)
|
||||
response = self._send(message, event)
|
||||
self._validate_response(response)
|
||||
|
||||
def _preprocess_message(self, message: str):
|
||||
return message
|
||||
|
||||
@abstractmethod
|
||||
def _validate_response(self, response):
|
||||
raise NotImplementedError # pragma: no cover
|
||||
@ -146,7 +142,9 @@ class AbstractEventFormatter(LoggerMixin, ConfLoaderMixin):
|
||||
Retrieves a message from the event itself.
|
||||
"""
|
||||
event = self._preprocess_event(event)
|
||||
return event.format(self.get_message_template())
|
||||
message = event.format(self.get_message_template())
|
||||
message = self._preprocess_message(message)
|
||||
return message
|
||||
|
||||
def get_message_template(self) -> Template:
|
||||
"""
|
||||
@ -175,6 +173,9 @@ class AbstractEventFormatter(LoggerMixin, ConfLoaderMixin):
|
||||
event = self._preprocess_event(event)
|
||||
return event.format(self.get_recap_fragment_template())
|
||||
|
||||
def _preprocess_message(self, message: str):
|
||||
return message
|
||||
|
||||
|
||||
@dataclass
|
||||
class BasePublication:
|
||||
|
@ -1,12 +1,11 @@
|
||||
import re
|
||||
from typing import Optional
|
||||
|
||||
import pkg_resources
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
from requests import Response
|
||||
|
||||
from mobilizon_reshare.event.event import MobilizonEvent
|
||||
from mobilizon_reshare.formatting.description import html_to_markdown
|
||||
from mobilizon_reshare.publishers.abstract import (
|
||||
AbstractEventFormatter,
|
||||
AbstractPlatform,
|
||||
@ -33,42 +32,6 @@ 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:
|
||||
"""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
|
||||
@ -76,13 +39,38 @@ class TelegramFormatter(AbstractEventFormatter):
|
||||
self._log_error("No description was found", raise_error=InvalidEvent)
|
||||
|
||||
def _validate_message(self, message: str) -> None:
|
||||
if len(message) >= 4096:
|
||||
if (
|
||||
len("".join(BeautifulSoup(message, "html.parser").findAll(text=True)))
|
||||
>= 4096
|
||||
):
|
||||
self._log_error("Message is too long", raise_error=InvalidMessage)
|
||||
|
||||
def _preprocess_event(self, event: MobilizonEvent):
|
||||
event.description = html_to_markdown(event.description)
|
||||
event.name = html_to_markdown(event.name)
|
||||
return event
|
||||
def _preprocess_message(self, message: str) -> str:
|
||||
|
||||
html = BeautifulSoup(message, "html.parser")
|
||||
# replacing paragraphs
|
||||
for tag in html.findAll(["p", "br"]):
|
||||
tag.append("\n")
|
||||
tag.replaceWithChildren()
|
||||
# replacing headers
|
||||
for tag in html.findAll(["h1", "h2", "h3"]):
|
||||
if tag.text: # only if they are not empty
|
||||
tag.name = "b"
|
||||
tag.insert_after("\n")
|
||||
tag.insert_before("\n")
|
||||
else:
|
||||
tag.decompose()
|
||||
# removing lists
|
||||
for tag in html.findAll("ul"):
|
||||
tag.unwrap()
|
||||
# replacing list elements with dots
|
||||
for tag in html.findAll(["li"]):
|
||||
tag.insert(0, "• ")
|
||||
tag.unwrap()
|
||||
# cleaning html trailing whitespace
|
||||
for tag in html.findAll("a"):
|
||||
tag["href"] = tag["href"].replace(" ", "").strip().lstrip()
|
||||
return str(html)
|
||||
|
||||
|
||||
class TelegramPlatform(AbstractPlatform):
|
||||
@ -92,9 +80,6 @@ class TelegramPlatform(AbstractPlatform):
|
||||
|
||||
name = "telegram"
|
||||
|
||||
def _preprocess_message(self, message: str):
|
||||
return TelegramFormatter.escape_message(message)
|
||||
|
||||
def validate_credentials(self):
|
||||
res = requests.get(f"https://api.telegram.org/bot{self.conf.token}/getMe")
|
||||
data = self._validate_response(res)
|
||||
@ -107,11 +92,7 @@ class TelegramPlatform(AbstractPlatform):
|
||||
def _send(self, message: str, event: Optional[MobilizonEvent] = None) -> Response:
|
||||
return requests.post(
|
||||
url=f"https://api.telegram.org/bot{self.conf.token}/sendMessage",
|
||||
json={
|
||||
"chat_id": self.conf.chat_id,
|
||||
"text": message,
|
||||
"parse_mode": "markdownv2",
|
||||
},
|
||||
json={"chat_id": self.conf.chat_id, "text": message, "parse_mode": "html"},
|
||||
)
|
||||
|
||||
def _validate_response(self, res):
|
||||
|
@ -1,8 +1,8 @@
|
||||
*{{ name }}*
|
||||
<strong>{{ name }}</strong>
|
||||
|
||||
🕒 {{ begin_datetime.format('DD MMMM, HH:mm') }} - {{ end_datetime.format('DD MMMM, HH:mm') }}
|
||||
{% if location %}📍 {{ location }}{% endif %}
|
||||
|
||||
{{ description }}
|
||||
|
||||
[Link]({{mobilizon_link}})
|
||||
<a href="{{mobilizon_link}}">Link</a>
|
@ -1,3 +1,4 @@
|
||||
import dataclasses
|
||||
from functools import partial
|
||||
from typing import Iterable, Optional
|
||||
from uuid import UUID
|
||||
@ -167,7 +168,9 @@ async def build_publications(event: MobilizonEvent) -> list[EventPublication]:
|
||||
await event_model.build_publication_by_publisher_name(name)
|
||||
for name in get_active_publishers()
|
||||
]
|
||||
return list(EventPublication.from_orm(m, event) for m in models)
|
||||
return list(
|
||||
EventPublication.from_orm(m, dataclasses.replace(event)) for m in models
|
||||
)
|
||||
|
||||
|
||||
@atomic(CONNECTION_NAME)
|
||||
|
166
poetry.lock
generated
166
poetry.lock
generated
@ -36,6 +36,32 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "apscheduler"
|
||||
version = "3.6.3"
|
||||
description = "In-process task scheduler with Cron-like capabilities"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[package.dependencies]
|
||||
pytz = "*"
|
||||
six = ">=1.4.0"
|
||||
tzlocal = ">=1.2"
|
||||
|
||||
[package.extras]
|
||||
asyncio = ["trollius"]
|
||||
doc = ["sphinx", "sphinx-rtd-theme"]
|
||||
gevent = ["gevent"]
|
||||
mongodb = ["pymongo (>=2.8)"]
|
||||
redis = ["redis (>=3.0)"]
|
||||
rethinkdb = ["rethinkdb (>=2.4.0)"]
|
||||
sqlalchemy = ["sqlalchemy (>=0.8)"]
|
||||
testing = ["pytest", "pytest-cov", "pytest-tornado5", "mock", "pytest-asyncio (<0.6)", "pytest-asyncio"]
|
||||
tornado = ["tornado (>=4.3)"]
|
||||
twisted = ["twisted"]
|
||||
zookeeper = ["kazoo"]
|
||||
|
||||
[[package]]
|
||||
name = "arrow"
|
||||
version = "1.1.1"
|
||||
@ -92,6 +118,14 @@ soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""}
|
||||
html5lib = ["html5lib"]
|
||||
lxml = ["lxml"]
|
||||
|
||||
[[package]]
|
||||
name = "cachetools"
|
||||
version = "4.2.2"
|
||||
description = "Extensible memoizing collections and decorators"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "~=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2021.10.8"
|
||||
@ -391,6 +425,26 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
|
||||
[package.dependencies]
|
||||
six = ">=1.5"
|
||||
|
||||
[[package]]
|
||||
name = "python-telegram-bot"
|
||||
version = "13.10"
|
||||
description = "We have made you a wrapper you can't refuse"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
APScheduler = "3.6.3"
|
||||
cachetools = "4.2.2"
|
||||
certifi = "*"
|
||||
pytz = ">=2018.6"
|
||||
tornado = ">=6.1"
|
||||
|
||||
[package.extras]
|
||||
json = ["ujson"]
|
||||
passport = ["cryptography (!=3.4,!=3.4.1,!=3.4.2,!=3.4.3)"]
|
||||
socks = ["pysocks"]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2021.3"
|
||||
@ -399,6 +453,17 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "pytz-deprecation-shim"
|
||||
version = "0.1.0.post0"
|
||||
description = "Shims to make deprecation of pytz easier"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7"
|
||||
|
||||
[package.dependencies]
|
||||
tzdata = {version = "*", markers = "python_version >= \"3.6\""}
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.25.1"
|
||||
@ -480,6 +545,14 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6,<4.0"
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
version = "6.1"
|
||||
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">= 3.5"
|
||||
|
||||
[[package]]
|
||||
name = "tortoise-orm"
|
||||
version = "0.17.8"
|
||||
@ -526,6 +599,30 @@ category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2021.5"
|
||||
description = "Provider of IANA time zone data"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=2"
|
||||
|
||||
[[package]]
|
||||
name = "tzlocal"
|
||||
version = "4.1"
|
||||
description = "tzinfo object for the local timezone"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
|
||||
[package.dependencies]
|
||||
pytz-deprecation-shim = "*"
|
||||
tzdata = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[package.extras]
|
||||
devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"]
|
||||
test = ["pytest-mock (>=3.3)", "pytest (>=4.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.7"
|
||||
@ -542,7 +639,7 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = "^3.9"
|
||||
content-hash = "5c405fa6ef97b2f9f81e5cf3ea24313142fcf712b6dda7eda87facb0d281f153"
|
||||
content-hash = "1001a2815c4da3a9e3ce5fed65bcbd2b962bec3dc64180cf217430f2a9d32b9e"
|
||||
|
||||
[metadata.files]
|
||||
aerich = [
|
||||
@ -557,6 +654,10 @@ appdirs = [
|
||||
{file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
|
||||
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
|
||||
]
|
||||
apscheduler = [
|
||||
{file = "APScheduler-3.6.3-py2.py3-none-any.whl", hash = "sha256:e8b1ecdb4c7cb2818913f766d5898183c7cb8936680710a4d3a966e02262e526"},
|
||||
{file = "APScheduler-3.6.3.tar.gz", hash = "sha256:3bb5229eed6fbbdafc13ce962712ae66e175aa214c69bed35a06bffcf0c5e244"},
|
||||
]
|
||||
arrow = [
|
||||
{file = "arrow-1.1.1-py3-none-any.whl", hash = "sha256:77a60a4db5766d900a2085ce9074c5c7b8e2c99afeaa98ad627637ff6f292510"},
|
||||
{file = "arrow-1.1.1.tar.gz", hash = "sha256:dee7602f6c60e3ec510095b5e301441bc56288cb8f51def14dcb3079f623823a"},
|
||||
@ -578,6 +679,10 @@ beautifulsoup4 = [
|
||||
{file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"},
|
||||
{file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
|
||||
]
|
||||
cachetools = [
|
||||
{file = "cachetools-4.2.2-py3-none-any.whl", hash = "sha256:2cc0b89715337ab6dbba85b5b50effe2b0c74e035d83ee8ed637cf52f12ae001"},
|
||||
{file = "cachetools-4.2.2.tar.gz", hash = "sha256:61b5ed1e22a0924aed1d23b478f37e8d52549ff8a961de2909c69bf950020cff"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"},
|
||||
{file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"},
|
||||
@ -756,10 +861,18 @@ python-dateutil = [
|
||||
{file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"},
|
||||
{file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"},
|
||||
]
|
||||
python-telegram-bot = [
|
||||
{file = "python-telegram-bot-13.10.tar.gz", hash = "sha256:d2c555431821f4ace0c1b7ce12af41999f01b793b275dee131f1034d08c01e3e"},
|
||||
{file = "python_telegram_bot-13.10-py3-none-any.whl", hash = "sha256:833f39110f5d019b39a6c6fcbabd6ea1627eaaa0a26e618c0be099568672d791"},
|
||||
]
|
||||
pytz = [
|
||||
{file = "pytz-2021.3-py2.py3-none-any.whl", hash = "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c"},
|
||||
{file = "pytz-2021.3.tar.gz", hash = "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326"},
|
||||
]
|
||||
pytz-deprecation-shim = [
|
||||
{file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"},
|
||||
{file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.25.1-py2.py3-none-any.whl", hash = "sha256:c210084e36a42ae6b9219e00e48287def368a26d03a048ddad7bfee44f75871e"},
|
||||
{file = "requests-2.25.1.tar.gz", hash = "sha256:27973dd4a904a4f13b263a19c866c13b92a39ed1c964655f025f3f8d3d75b804"},
|
||||
@ -789,6 +902,49 @@ tomlkit = [
|
||||
{file = "tomlkit-0.8.0-py3-none-any.whl", hash = "sha256:b824e3466f1d475b2b5f1c392954c6cb7ea04d64354ff7300dc7c14257dc85db"},
|
||||
{file = "tomlkit-0.8.0.tar.gz", hash = "sha256:29e84a855712dfe0e88a48f6d05c21118dbafb283bb2eed614d46f80deb8e9a1"},
|
||||
]
|
||||
tornado = [
|
||||
{file = "tornado-6.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:d371e811d6b156d82aa5f9a4e08b58debf97c302a35714f6f45e35139c332e32"},
|
||||
{file = "tornado-6.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:0d321a39c36e5f2c4ff12b4ed58d41390460f798422c4504e09eb5678e09998c"},
|
||||
{file = "tornado-6.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9de9e5188a782be6b1ce866e8a51bc76a0fbaa0e16613823fc38e4fc2556ad05"},
|
||||
{file = "tornado-6.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:61b32d06ae8a036a6607805e6720ef00a3c98207038444ba7fd3d169cd998910"},
|
||||
{file = "tornado-6.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:3e63498f680547ed24d2c71e6497f24bca791aca2fe116dbc2bd0ac7f191691b"},
|
||||
{file = "tornado-6.1-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:6c77c9937962577a6a76917845d06af6ab9197702a42e1346d8ae2e76b5e3675"},
|
||||
{file = "tornado-6.1-cp35-cp35m-win32.whl", hash = "sha256:6286efab1ed6e74b7028327365cf7346b1d777d63ab30e21a0f4d5b275fc17d5"},
|
||||
{file = "tornado-6.1-cp35-cp35m-win_amd64.whl", hash = "sha256:fa2ba70284fa42c2a5ecb35e322e68823288a4251f9ba9cc77be04ae15eada68"},
|
||||
{file = "tornado-6.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a00ff4561e2929a2c37ce706cb8233b7907e0cdc22eab98888aca5dd3775feb"},
|
||||
{file = "tornado-6.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:748290bf9112b581c525e6e6d3820621ff020ed95af6f17fedef416b27ed564c"},
|
||||
{file = "tornado-6.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:e385b637ac3acaae8022e7e47dfa7b83d3620e432e3ecb9a3f7f58f150e50921"},
|
||||
{file = "tornado-6.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:25ad220258349a12ae87ede08a7b04aca51237721f63b1808d39bdb4b2164558"},
|
||||
{file = "tornado-6.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:65d98939f1a2e74b58839f8c4dab3b6b3c1ce84972ae712be02845e65391ac7c"},
|
||||
{file = "tornado-6.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:e519d64089b0876c7b467274468709dadf11e41d65f63bba207e04217f47c085"},
|
||||
{file = "tornado-6.1-cp36-cp36m-win32.whl", hash = "sha256:b87936fd2c317b6ee08a5741ea06b9d11a6074ef4cc42e031bc6403f82a32575"},
|
||||
{file = "tornado-6.1-cp36-cp36m-win_amd64.whl", hash = "sha256:cc0ee35043162abbf717b7df924597ade8e5395e7b66d18270116f8745ceb795"},
|
||||
{file = "tornado-6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7250a3fa399f08ec9cb3f7b1b987955d17e044f1ade821b32e5f435130250d7f"},
|
||||
{file = "tornado-6.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ed3ad863b1b40cd1d4bd21e7498329ccaece75db5a5bf58cd3c9f130843e7102"},
|
||||
{file = "tornado-6.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:dcef026f608f678c118779cd6591c8af6e9b4155c44e0d1bc0c87c036fb8c8c4"},
|
||||
{file = "tornado-6.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:70dec29e8ac485dbf57481baee40781c63e381bebea080991893cd297742b8fd"},
|
||||
{file = "tornado-6.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:d3f7594930c423fd9f5d1a76bee85a2c36fd8b4b16921cae7e965f22575e9c01"},
|
||||
{file = "tornado-6.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:3447475585bae2e77ecb832fc0300c3695516a47d46cefa0528181a34c5b9d3d"},
|
||||
{file = "tornado-6.1-cp37-cp37m-win32.whl", hash = "sha256:e7229e60ac41a1202444497ddde70a48d33909e484f96eb0da9baf8dc68541df"},
|
||||
{file = "tornado-6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:cb5ec8eead331e3bb4ce8066cf06d2dfef1bfb1b2a73082dfe8a161301b76e37"},
|
||||
{file = "tornado-6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:20241b3cb4f425e971cb0a8e4ffc9b0a861530ae3c52f2b0434e6c1b57e9fd95"},
|
||||
{file = "tornado-6.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:c77da1263aa361938476f04c4b6c8916001b90b2c2fdd92d8d535e1af48fba5a"},
|
||||
{file = "tornado-6.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:fba85b6cd9c39be262fcd23865652920832b61583de2a2ca907dbd8e8a8c81e5"},
|
||||
{file = "tornado-6.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:1e8225a1070cd8eec59a996c43229fe8f95689cb16e552d130b9793cb570a288"},
|
||||
{file = "tornado-6.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d14d30e7f46a0476efb0deb5b61343b1526f73ebb5ed84f23dc794bdb88f9d9f"},
|
||||
{file = "tornado-6.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8f959b26f2634a091bb42241c3ed8d3cedb506e7c27b8dd5c7b9f745318ddbb6"},
|
||||
{file = "tornado-6.1-cp38-cp38-win32.whl", hash = "sha256:34ca2dac9e4d7afb0bed4677512e36a52f09caa6fded70b4e3e1c89dbd92c326"},
|
||||
{file = "tornado-6.1-cp38-cp38-win_amd64.whl", hash = "sha256:6196a5c39286cc37c024cd78834fb9345e464525d8991c21e908cc046d1cc02c"},
|
||||
{file = "tornado-6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f0ba29bafd8e7e22920567ce0d232c26d4d47c8b5cf4ed7b562b5db39fa199c5"},
|
||||
{file = "tornado-6.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:33892118b165401f291070100d6d09359ca74addda679b60390b09f8ef325ffe"},
|
||||
{file = "tornado-6.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7da13da6f985aab7f6f28debab00c67ff9cbacd588e8477034c0652ac141feea"},
|
||||
{file = "tornado-6.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:e0791ac58d91ac58f694d8d2957884df8e4e2f6687cdf367ef7eb7497f79eaa2"},
|
||||
{file = "tornado-6.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:66324e4e1beede9ac79e60f88de548da58b1f8ab4b2f1354d8375774f997e6c0"},
|
||||
{file = "tornado-6.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a48900ecea1cbb71b8c71c620dee15b62f85f7c14189bdeee54966fbd9a0c5bd"},
|
||||
{file = "tornado-6.1-cp39-cp39-win32.whl", hash = "sha256:d3d20ea5782ba63ed13bc2b8c291a053c8d807a8fa927d941bd718468f7b950c"},
|
||||
{file = "tornado-6.1-cp39-cp39-win_amd64.whl", hash = "sha256:548430be2740e327b3fe0201abe471f314741efcb0067ec4f2d7dcfb4825f3e4"},
|
||||
{file = "tornado-6.1.tar.gz", hash = "sha256:33c6e81d7bd55b468d2e793517c909b139960b6c790a60b7991b9b6b76fb9791"},
|
||||
]
|
||||
tortoise-orm = [
|
||||
{file = "tortoise-orm-0.17.8.tar.gz", hash = "sha256:1f5020e9964d32a4d6ed685d466b5d7285de328a63ee92ee988c1e4baf8fefbf"},
|
||||
{file = "tortoise_orm-0.17.8-py3-none-any.whl", hash = "sha256:f18c41bb83be4748a6ca259ed7309ca954b35f5790971824bbc79a11d2b1ef3b"},
|
||||
@ -801,6 +957,14 @@ typing-extensions = [
|
||||
{file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
|
||||
{file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
|
||||
]
|
||||
tzdata = [
|
||||
{file = "tzdata-2021.5-py2.py3-none-any.whl", hash = "sha256:3eee491e22ebfe1e5cfcc97a4137cd70f092ce59144d81f8924a844de05ba8f5"},
|
||||
{file = "tzdata-2021.5.tar.gz", hash = "sha256:68dbe41afd01b867894bbdfd54fa03f468cfa4f0086bfb4adcd8de8f24f3ee21"},
|
||||
]
|
||||
tzlocal = [
|
||||
{file = "tzlocal-4.1-py3-none-any.whl", hash = "sha256:28ba8d9fcb6c9a782d6e0078b4f6627af1ea26aeaa32b4eab5324abc7df4149f"},
|
||||
{file = "tzlocal-4.1.tar.gz", hash = "sha256:0f28015ac68a5c067210400a9197fc5d36ba9bc3f8eaf1da3cbd59acdfed9e09"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.26.7-py2.py3-none-any.whl", hash = "sha256:c4fdf4019605b6e5423637e01bc9fe4daef873709a7973e195ceba0a62bbc844"},
|
||||
{file = "urllib3-1.26.7.tar.gz", hash = "sha256:4987c65554f7a2dbf30c18fd48778ef124af6fab771a377103da0585e2336ece"},
|
||||
|
@ -23,6 +23,7 @@ appdirs = "~1.4"
|
||||
tweepy = "~4.1"
|
||||
facebook-sdk = {git = "https://github.com/mobolic/facebook-sdk.git"}
|
||||
aerich = "~0.6"
|
||||
python-telegram-bot = "^13.10"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
responses = "~0.13"
|
||||
|
@ -26,27 +26,6 @@ def test_message_length_failure(event):
|
||||
TelegramFormatter().validate_event(event)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"message, result",
|
||||
[
|
||||
["", ""],
|
||||
["a#b", "ab"],
|
||||
["-", "\\-"],
|
||||
["(", "\\("],
|
||||
["!", "\\!"],
|
||||
[")", "\\)"],
|
||||
[")!", "\\)\\!"],
|
||||
["[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):
|
||||
assert TelegramFormatter().escape_message(message) == result
|
||||
|
||||
|
||||
def test_event_validation(event):
|
||||
event.description = None
|
||||
with pytest.raises(InvalidEvent):
|
||||
|
Loading…
x
Reference in New Issue
Block a user