Skip to content
This repository has been archived by the owner on Sep 28, 2021. It is now read-only.

Commit

Permalink
feat: add apprise (#81)
Browse files Browse the repository at this point in the history
* feat: add apprise
  • Loading branch information
sibalzer committed Jun 7, 2021
1 parent 7e5a40f commit 3e458d5
Show file tree
Hide file tree
Showing 16 changed files with 162 additions and 45 deletions.
6 changes: 6 additions & 0 deletions config.ini.example
Expand Up @@ -30,6 +30,12 @@ chat_id=123456789,987654321
; Desktop only - Soll der default Browser automatisch geoeffnet werden
enable=true

[APPRISE]
; true, wenn Apprise verwendet werden soll; sonst false
enable=true
; Verschiedene Benachritigungsservice. Mehrere durch Komma trennen -> https://github.com/caronc/apprise
service_urls=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
; Wartezeit zwischen den Abfragen eine zu kleine Wartezeit führt zu einem IP-Ban (Default: 5min, kann aber empirisch verkleinert werden)
sleep_between_requests_in_s=150
Expand Down
6 changes: 2 additions & 4 deletions requirements.txt
@@ -1,8 +1,6 @@
requests==2.25.1
tkcalendar==1.6.1
python_telegram_bot==13.3
telegram==0.0.1
pytest==6.2.4
requests-mock==1.9.3
freezegun==1.1.0
tkcalendar==1.6.1
tkcalendar==1.6.1
apprise==0.9.3
69 changes: 48 additions & 21 deletions src/alerts.py
@@ -1,13 +1,11 @@
"""alert service handler"""

import apprise
import smtplib
import webbrowser
import logging
from email.message import EmailMessage
from email.utils import formatdate
from telegram.ext import Updater
from telegram.parsemode import ParseMode
from telegram.error import TelegramError

from common import APPOINTMENT_URL
from settings import settings
Expand All @@ -18,22 +16,22 @@
def alert(msg: str) -> None:
"""Calls alert services with message"""
if settings.EMAIL_ENABLE:
log.debug("[EMAIL] try to send _e-mail")
log.debug("[EMAIL] try to send e-mail")
try:
send_mail(msg)
log.debug("[EMAIL] sending _e-mail was successful")
except smtplib.SMTPException as _e:
log.error(f"[EMAIL] Couldn't send mail: {_e}")
log.info("[EMAIL] sending e-mail was successful")
except smtplib.SMTPException as ex:
log.error(f"[EMAIL] Couldn't send mail: {ex}")
else:
log.debug("[EMAIL] enable is not set to true. Skipping...")

if settings.TELEGRAM_ENABLE:
log.debug("[TELEGRAM] Try to send telegram message")
try:
send_telegram_msg(msg)
log.debug("[TELEGRAM] Sending telegram message was successful")
except TelegramError as _e:
log.error(f"[TELEGRAM] Couldn't send Telegram message: {_e}")
send_telegram(msg)
log.info("[TELEGRAM] Sending telegram message was successful")
except Exception as ex:
log.error(f"[TELEGRAM] Couldn't send Telegram message: {ex}")
else:
log.debug(
"[TELEGRAM] enable is not set to true. Skipping...")
Expand All @@ -42,13 +40,24 @@ def alert(msg: str) -> None:
log.debug("[WEBBROWSER] try to open browser")
try:
webbrowser.open(APPOINTMENT_URL, new=1, autoraise=True)
log.debug("[WEBBROWSER] Open browser was successful")
except webbrowser.Error as _e:
log.error(f"[WEBBROWSER] Couldn't open browser: {_e}")
log.info("[WEBBROWSER] Open browser was successful")
except webbrowser.Error as ex:
log.error(f"[WEBBROWSER] Couldn't open browser: {ex}")
else:
log.debug(
"[WEBBROWSER] enable is not set to true. Skipping...")

if settings.APPRISE_ENABLE:
log.debug(f"[APPRISE] try to send Apprise Notification")
try:
send_apprise(msg)
log.info(
f"[APPRISE] sending Apprise Notification was successful")
except Exception as ex:
log.error(f"Couldn't send Apprise Notification: {ex}")
else:
log.debug(f"[APPRISE] send_apprise is not set to true skipping")


def send_mail(msg: str) -> None:
"""email alert service"""
Expand All @@ -66,12 +75,30 @@ def send_mail(msg: str) -> None:
smtp.send_message(mail)


def send_telegram_msg(msg: str) -> None:
def send_telegram(msg: str) -> None:
"""telegram alert service"""
update = Updater(settings.TELEGRAM_TOKEN)
appobj = apprise.Apprise()

url = f"tgram://{settings.TELEGRAM_TOKEN}"
for chat_id in settings.TELEGRAM_CHAT_IDS:
update.bot.send_message(
chat_id=chat_id,
text=f"*{msg}*\n{APPOINTMENT_URL}",
parse_mode=ParseMode.MARKDOWN
)
url += f"/{chat_id}"

appobj.add(url)

appobj.notify(
body=f"{APPOINTMENT_URL}",
title=f"*{msg}*",
)


def send_apprise(msg: str) -> None:
"""apprise alert service"""
appobj = apprise.Apprise()

for url in settings.APPRISE_SERVICE_URIS:
appobj.add(url)

appobj.notify(
body=f"{APPOINTMENT_URL}",
title=f"*{msg}*",
)
5 changes: 3 additions & 2 deletions src/common.py
Expand Up @@ -14,7 +14,7 @@


MAIL_REGEX = r"\b(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])\b"
NOTIFIERS = ["EMAIL", "TELEGRAM", "WEBBROWSER"]
NOTIFIERS = ["EMAIL", "TELEGRAM", "WEBBROWSER", "APPRISE"]
NOTIFIER_REGEX = {
"sender": MAIL_REGEX,
"user": r"^[^ ]*$", # match anything execpt space
Expand All @@ -25,7 +25,8 @@
"receivers": r"\b" + MAIL_REGEX + r"(," + MAIL_REGEX + r")*\b",
# I hope this covers all possible tokens
"token": r"^[a-zA-Z0-9\:\-]+$",
"chat_ids": r"^\d{5,}(,\d{5,})*$" # matches a list of numbers
"chat_ids": r"^\d{5,}(,\d{5,})*$", # matches a list of numbers
"service_uris": r"\b[^ ]+\b", # match anything not a space
}


Expand Down
12 changes: 9 additions & 3 deletions src/config_generator.py
Expand Up @@ -19,6 +19,9 @@
"TELEGRAM": {
"token": "Token",
"chat_ids": "Chat-ID(s)"
},
"APPRISE": {
"service_urls": "Different Service URLs"
}
}

Expand Down Expand Up @@ -85,7 +88,8 @@ def get_input():
if search_group_appointments.get():
config_dict["COMMON"]["group_size"] = group_size.get()
else:
config_dict["COMMON"]["birthdate"] = birthday.get_date().strftime("%d.%m.%Y")
config_dict["COMMON"]["birthdate"] = birthday.get_date().strftime(
"%d.%m.%Y")
config_dict["COMMON"]["zip_code"] = plz.get()
for item in NOTIFIERS:
config_dict[item.upper()]["enable"] = str(
Expand Down Expand Up @@ -229,7 +233,8 @@ def close_settings_window():
plz.grid(row=5, column=1)
group_size.grid_remove()

tk.Label(tk_window, text="Benachrichtigung", font="bold").grid(row=6, column=1)
tk.Label(tk_window, text="Benachrichtigung",
font="bold").grid(row=6, column=1)
for item in NOTIFIERS:
enable[item] = tk.BooleanVar()
enable[item].set(False)
Expand Down Expand Up @@ -277,7 +282,8 @@ def get_notifier_credentials(notifier):
match = None
config_for_group_input = ""
while config_for_group_input.lower() not in ["j", "n"]:
config_for_group_input = input('Soll nach Gruppenterminen gesucht werden? (j/n): ')
config_for_group_input = input(
'Soll nach Gruppenterminen gesucht werden? (j/n): ')
config_for_group = config_for_group_input.lower() == "j"
while match is None and not config_for_group:
birthday = input('Bitte den Geburtstag eingeben: ')
Expand Down
12 changes: 12 additions & 0 deletions src/config_skeleton.py
Expand Up @@ -83,6 +83,18 @@
"regex": BOOL_REGEX
},
},
"APPRISE": {
"enable": {
"default": False,
"type": bool,
"regex": BOOL_REGEX
},
"service_uris": {
"default": 30,
"type": list,
"regex": NOTIFIER_REGEX["service_uris"]
},
},
"ADVANCED": {
"cooldown_between_requests": {
"default": 30,
Expand Down
7 changes: 7 additions & 0 deletions tests/configs/test-config-apprise.ini
@@ -0,0 +1,7 @@
[COMMON]
birthdate=5.5.1900
zip_code=37042

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname
4 changes: 4 additions & 0 deletions tests/configs/test-config-invalid-advanced.ini
Expand Up @@ -19,6 +19,10 @@ chat_ids=123456789,987654321
[WEBBROWSER]
enable=true

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
cooldown_between_requests=60a
cooldown_between_failed_requests=10a
Expand Down
33 changes: 33 additions & 0 deletions tests/configs/test-config-invalid-apprise.ini
@@ -0,0 +1,33 @@
[COMMON]
zip_code=49042
birthdate=23.6.1912

[EMAIL]
enable=true
sender=sender@server.de
user=username
password=secret
server=mail.server.de
port=465
receivers=sender@server.de,guenni@server.de,frida@server.de

[TELEGRAM]
enable=true
token=äöäöü:TOKEN
chat_ids=12345ab6789,9876c54321

[WEBBROWSER]
enable=true

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
cooldown_between_requests=60
cooldown_between_failed_requests=10
cooldown_after_ip_ban=10800
cooldown_after_success=900
jitter=5
sleep_at_night=false
user_agent=impfbot_v3
4 changes: 4 additions & 0 deletions tests/configs/test-config-invalid-birthdate.ini
Expand Up @@ -19,6 +19,10 @@ chat_ids=123456789,987654321
[WEBBROWSER]
enable=true

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
cooldown_between_requests=60
cooldown_between_failed_requests=10
Expand Down
4 changes: 4 additions & 0 deletions tests/configs/test-config-invalid-email.ini
Expand Up @@ -19,6 +19,10 @@ chat_ids=123456789,987654321
[WEBBROWSER]
enable=true

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
cooldown_between_requests=60
cooldown_between_failed_requests=10
Expand Down
4 changes: 4 additions & 0 deletions tests/configs/test-config-invalid-telegram.ini
Expand Up @@ -19,6 +19,10 @@ chat_ids=12345ab6789,9876c54321
[WEBBROWSER]
enable=true

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
cooldown_between_requests=60
cooldown_between_failed_requests=10
Expand Down
4 changes: 4 additions & 0 deletions tests/configs/test-config-valid.ini
Expand Up @@ -19,6 +19,10 @@ chat_ids=123456789,987654321
[WEBBROWSER]
enable=true

[APPRISE]
enable=true
service_uris=discord://webhook_id/webhook_token,matrix://hostname

[ADVANCED]
cooldown_between_requests=60
cooldown_between_failed_requests=10
Expand Down
23 changes: 15 additions & 8 deletions tests/test_alerts.py
Expand Up @@ -5,7 +5,7 @@


@mock.patch('alerts.send_mail')
@mock.patch('alerts.send_telegram_msg')
@mock.patch('alerts.send_telegram')
@mock.patch('webbrowser.open', return_value=None)
def test_alert(browser_mock, telegram_mock, email_mock):
load("tests/configs/test-config.ini")
Expand Down Expand Up @@ -35,17 +35,14 @@ def test_send_email(smtp_mock):
smtp_mock_obj.send_message.assert_called_once()


@mock.patch('telegram.bot.Bot._validate_token', return_value=None)
@mock.patch('telegram.bot.Bot.send_message', return_value=None)
def test_send_telegram_msg(telegram_send_mock, telegram_validate_token_mock):
@mock.patch('apprise.Apprise.notify', return_value=None)
def test_send_telegram_msg(apprise_notify_mock):
load("tests/configs/test-config-telegram.ini")

msg = 'test'
alerts.send_telegram_msg(msg)
alerts.send_telegram(msg)

for chat_id in settings.TELEGRAM_CHAT_IDS:
assert telegram_send_mock.call_count == len(settings.TELEGRAM_CHAT_IDS)
assert telegram_send_mock.call_args[1]["chat_id"] in settings.TELEGRAM_CHAT_IDS
assert apprise_notify_mock.called_once()


@mock.patch('webbrowser.open', return_value=None)
Expand All @@ -56,3 +53,13 @@ def test_open_browser(webbrowser_mock):

webbrowser_mock.assert_called_once_with(
alerts.APPOINTMENT_URL, new=1, autoraise=True)


@mock.patch('apprise.Apprise.notify', return_value=None)
def test_send_apprise(apprise_notify_mock):
load("tests/configs/test-config-apprise.ini")

msg = 'test'
alerts.send_apprise(msg)

assert apprise_notify_mock.called_once()

0 comments on commit 3e458d5

Please sign in to comment.