2022-03-02 08:59:49 +01:00
|
|
|
|
import re
|
2021-11-20 15:40:10 +01:00
|
|
|
|
from typing import Optional
|
2021-10-19 07:35:18 +02:00
|
|
|
|
|
2021-07-12 22:17:49 +02:00
|
|
|
|
import pkg_resources
|
2021-04-23 17:04:27 +02:00
|
|
|
|
import requests
|
2022-01-18 01:39:00 +01:00
|
|
|
|
from bs4 import BeautifulSoup
|
2021-08-27 23:45:24 +02:00
|
|
|
|
from requests import Response
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
2021-10-02 18:09:03 +02:00
|
|
|
|
from mobilizon_reshare.event.event import MobilizonEvent
|
|
|
|
|
from mobilizon_reshare.publishers.abstract import (
|
|
|
|
|
AbstractEventFormatter,
|
|
|
|
|
AbstractPlatform,
|
|
|
|
|
)
|
2021-08-27 23:45:24 +02:00
|
|
|
|
from mobilizon_reshare.publishers.exceptions import (
|
2021-07-05 21:44:11 +02:00
|
|
|
|
InvalidBot,
|
|
|
|
|
InvalidEvent,
|
|
|
|
|
InvalidResponse,
|
2021-10-24 21:32:28 +02:00
|
|
|
|
InvalidMessage,
|
2021-07-05 21:44:11 +02:00
|
|
|
|
)
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
|
|
|
|
|
2021-10-02 18:09:03 +02:00
|
|
|
|
class TelegramFormatter(AbstractEventFormatter):
|
2021-07-12 22:17:49 +02:00
|
|
|
|
default_template_path = pkg_resources.resource_filename(
|
2021-08-16 10:49:52 +02:00
|
|
|
|
"mobilizon_reshare.publishers.templates", "telegram.tmpl.j2"
|
2021-07-12 22:17:49 +02:00
|
|
|
|
)
|
2021-07-05 21:44:11 +02:00
|
|
|
|
|
2021-10-16 01:25:45 +02:00
|
|
|
|
default_recap_template_path = pkg_resources.resource_filename(
|
|
|
|
|
"mobilizon_reshare.publishers.templates", "telegram_recap.tmpl.j2"
|
|
|
|
|
)
|
|
|
|
|
|
2021-10-17 14:09:24 +02:00
|
|
|
|
default_recap_header_template_path = pkg_resources.resource_filename(
|
|
|
|
|
"mobilizon_reshare.publishers.templates", "telegram_recap_header.tmpl.j2"
|
|
|
|
|
)
|
|
|
|
|
|
2021-10-02 18:09:03 +02:00
|
|
|
|
_conf = ("publisher", "telegram")
|
2021-08-27 23:45:24 +02:00
|
|
|
|
|
2021-11-27 23:31:44 +01:00
|
|
|
|
def _validate_event(self, event: MobilizonEvent) -> None:
|
2021-10-05 15:32:07 +02:00
|
|
|
|
description = event.description
|
|
|
|
|
if not (description and description.strip()):
|
|
|
|
|
self._log_error("No description was found", raise_error=InvalidEvent)
|
2021-10-02 18:09:03 +02:00
|
|
|
|
|
2021-11-27 23:31:44 +01:00
|
|
|
|
def _validate_message(self, message: str) -> None:
|
2022-01-18 01:39:00 +01:00
|
|
|
|
if (
|
|
|
|
|
len("".join(BeautifulSoup(message, "html.parser").findAll(text=True)))
|
|
|
|
|
>= 4096
|
|
|
|
|
):
|
2021-11-27 23:31:44 +01:00
|
|
|
|
self._log_error("Message is too long", raise_error=InvalidMessage)
|
2021-10-02 18:09:03 +02:00
|
|
|
|
|
2022-01-18 01:39:00 +01:00
|
|
|
|
def _preprocess_message(self, message: str) -> str:
|
2022-03-02 08:59:49 +01:00
|
|
|
|
"""
|
|
|
|
|
This function converts HTML5 to Telegram's HTML dialect
|
|
|
|
|
:param message: a HTML5 string
|
|
|
|
|
:return: a HTML string compatible with Telegram
|
|
|
|
|
"""
|
2022-01-18 01:39:00 +01:00
|
|
|
|
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()
|
2022-03-02 08:59:49 +01:00
|
|
|
|
s = str(html)
|
|
|
|
|
return re.sub(r"\n{2,}", "\n\n", s).strip() # remove multiple newlines
|
2021-10-02 18:09:03 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TelegramPlatform(AbstractPlatform):
|
|
|
|
|
"""
|
|
|
|
|
Telegram publisher class.
|
|
|
|
|
"""
|
|
|
|
|
|
2021-10-24 21:32:28 +02:00
|
|
|
|
name = "telegram"
|
|
|
|
|
|
2021-07-05 21:44:11 +02:00
|
|
|
|
def validate_credentials(self):
|
2021-10-17 14:05:16 +02:00
|
|
|
|
res = requests.get(f"https://api.telegram.org/bot{self.conf.token}/getMe")
|
2021-05-02 10:37:46 +02:00
|
|
|
|
data = self._validate_response(res)
|
|
|
|
|
|
2021-10-17 14:05:16 +02:00
|
|
|
|
if not self.conf.username == data.get("result", {}).get("username"):
|
2021-07-05 21:44:11 +02:00
|
|
|
|
self._log_error(
|
2021-09-27 09:20:01 +02:00
|
|
|
|
"Found a different bot than the expected one", raise_error=InvalidBot,
|
2021-07-05 21:44:11 +02:00
|
|
|
|
)
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
2021-11-20 15:40:10 +01:00
|
|
|
|
def _send(self, message: str, event: Optional[MobilizonEvent] = None) -> Response:
|
2021-10-02 18:09:03 +02:00
|
|
|
|
return requests.post(
|
|
|
|
|
url=f"https://api.telegram.org/bot{self.conf.token}/sendMessage",
|
2022-01-18 01:39:00 +01:00
|
|
|
|
json={"chat_id": self.conf.chat_id, "text": message, "parse_mode": "html"},
|
2021-10-02 18:09:03 +02:00
|
|
|
|
)
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
2021-05-02 10:37:46 +02:00
|
|
|
|
def _validate_response(self, res):
|
2021-07-07 11:45:54 +02:00
|
|
|
|
try:
|
2021-10-24 21:32:28 +02:00
|
|
|
|
|
2021-07-07 11:45:54 +02:00
|
|
|
|
res.raise_for_status()
|
|
|
|
|
except requests.exceptions.HTTPError as e:
|
|
|
|
|
self._log_error(
|
2021-12-05 17:21:43 +01:00
|
|
|
|
f"Server returned invalid data: {str(e)}\n{res.text}",
|
|
|
|
|
raise_error=InvalidResponse,
|
2021-07-07 11:45:54 +02:00
|
|
|
|
)
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
data = res.json()
|
2021-07-05 21:44:11 +02:00
|
|
|
|
except Exception as e:
|
|
|
|
|
self._log_error(
|
|
|
|
|
f"Server returned invalid json data: {str(e)}",
|
|
|
|
|
raise_error=InvalidResponse,
|
|
|
|
|
)
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
2021-05-02 10:37:46 +02:00
|
|
|
|
if not data.get("ok"):
|
2021-07-05 21:44:11 +02:00
|
|
|
|
self._log_error(
|
2021-09-27 09:20:01 +02:00
|
|
|
|
f"Invalid request (response: {data})", raise_error=InvalidResponse,
|
2021-07-05 21:44:11 +02:00
|
|
|
|
)
|
2021-04-23 17:04:27 +02:00
|
|
|
|
|
|
|
|
|
return data
|
2021-07-05 21:44:11 +02:00
|
|
|
|
|
2021-07-21 09:13:32 +02:00
|
|
|
|
|
2021-10-02 18:09:03 +02:00
|
|
|
|
class TelegramPublisher(TelegramPlatform):
|
|
|
|
|
|
|
|
|
|
_conf = ("publisher", "telegram")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TelegramNotifier(TelegramPlatform):
|
|
|
|
|
|
|
|
|
|
_conf = ("notifier", "telegram")
|