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

Commit

Permalink
feat!: Telegram Integration; Config Validation
Browse files Browse the repository at this point in the history
  • Loading branch information
sibalzer committed May 27, 2021
2 parents 8b09c97 + 917b446 commit 874f26c
Show file tree
Hide file tree
Showing 16 changed files with 186 additions and 44 deletions.
66 changes: 62 additions & 4 deletions README.md
Expand Up @@ -10,32 +10,90 @@ Ein kleines Wochenend-Projekt von mir. Der Bot überwacht die REST-API des niede
>
> Derzeit fragt der Bot alle 5min die API ab ich würde das gerne etwas optmieren brauche dafür aber Hilfe poste dazu deine Settings [hier](https://github.com/sibalzer/impfbot/issues/6)
## Setup 🤖
## 🤖 Setup

### Voraussetzungen

- python 3.x mit py-Launcher via https://www.python.org/downloads/

### Schritt für Schritt 📝
### 📝 Anleitung

Am Beispiel von Windows:

1. Python von hier laden und installieren: https://www.python.org/downloads/
2. Den Bot runterladen (Rechts oben der grüne Button und da ZIP-Archiv oder [hier](https://github.com/sibalzer/impfbot/archive/refs/heads/main.zip))
3. Das Archiv (Die Zip Datei) entpacken
4. `config.ini.example` nach `config.ini` umbennen und deine Daten eintragen (PLZ, Geburtstag, Email Server Daten
5. Doppelklick auf `test_mail.bat` um die E-Mail Einstellungen zu prüfen
5. Doppelklick auf `windows_validate.bat` um die Einstellungen zu prüfen
6. Doppelklick auf `windows_start.bat`

Für Fortgeschrittene steht alternativ auch ein Docker-Container zur Verfügung. Siehe dazu [docker](https://github.com/sibalzer/impfbot/tree/main/docker).

### Einrichten von Telegram 📣

1. https://t.me/BotFather anschreiben und Bot erstellen. Den Token dann in die `config.ini` kopieren.
Folgende Schritte muss für jeden ausgeführt werden, der Nachrichten
Folgende Schritte muss für jeden ausgeführt werden, der Nachrichten empfangen will
2. https://t.me/userinfobot anschreiben und "Id"-Nummer in die `config.ini` kopieren (mit `.` getrennt).
3. Wichtig! Mit dem eigenen Bot muss vorher eine Konversation begonnen werden! (Url steht in der Bothfather Nachricht und dann start drücken)
4. Validieren das auch alles funktioniert: Doppelklick auf `test_telegram.bat`


### config.ini Parameter

- \[COMMON\]: Allgemeine Einstellungen
- `geburtstag` - Geburtstag der Abgefragt werden soll. Beispiel: `23.6.1912`
- `postleitzahl` - Fünfstellige PLZ für die Postleitzahl der Bot Benachrichtigungen schicken soll. Beispiel: `49123`
- \[EMAIL\]: Email Einstellungen
- `enable` - Legt fest ob E-Mails versendet werden sollen. `true` wenn ja, sonst `false`.
- `sender` - Die E-Mail Adresse von der die Benachrichtigungen versendet werden sollen. Beispiel: `versender@server.tld`
- `password` - Das Passwort für die Versender-E-Mail Adresse.
- `server` - Beispiel: `smtp.server.tld`
- `port` - Der Port für den SMTP-Server. Beispiel: `465`
- `empfaenger` - Eine Liste der E-Mail Adressen an die eine Nachricht geschickt werden soll. Beispiel: `sender@server.de,foo@server.de,hoo@server.de` oder (nur an sich selber) `sender@server.de`
- \[TELEGRAM\]: Email Einstellungen
- `enable_telegram` - Legt fest ob Telegram Nachrichten versendet werden sollen. `true` wenn ja, sonst `false`.
- `token` - Der Bot-Token von https://t.me/BotFather
- `chat_id` - User-ID des Empfängers: nutze dazu https://t.me/userinfobot
- \[WEBBROWSER\]: Webbrowser Einstallungen
- `enable_telegram` - Legt fest ob der Browser automatisch geöffnet werden soll. (Nur auf Desktop-Systemen) `true` wenn ja, sonst `false`.
- \[ADVANCED\]: Einstallungen für fortgeschrittene hier wirds experimentell
- `sleep_between_requests_in_s` - Wartezeit zwischen den Abfragen eine zu kleine Wartezeit führt zu einem IP-Ban (Default: 5min, kann aber empirisch verkleinert werden)
- `sleep_between_failed_requests_in_s` - Wartezeit zwischen fehlgeschlagenen Versuchen. Bei jedem weiteren wird die Wartezeit nochmal hinzuaddiert, um einen IP Ban zu verhindern. D.h. fünf Fehlschläge = Wartezeit von 5*30s bis zum nächsen Aufruf
- `sleep_after_ipban_in_min` - Wenn eine Abfrage 10x fehlschlaegt ist die IP vermutlich gebannt. Standardmaeßig wird dann 3h gewartet.
- `jitter` - Zufällige Zeitspanne von 0-jtter Sekunden die auf die Wartezeiten addiert wird (Default: `15`)
- `sleep_at_night` - Legt fest ob der Bot nachts schlafen soll (Default: `true` da eh keine Termine veröffentlicht werden)
- `user_agent`- Der User Agent im Header übermittel wird (Default: `true`)

Beispiel Config:
```ini
[COMMON]
geburtstag=23.06.1910
postleitzahl=49049

[EMAIL]
enable=true
sender=beispielsender@server.tld,beispielsmfaenger@server.tld
password=xxxxxxxxxx
server=github@simonbalzer.de
port=465
empfaenger=github@simonbalzer.de

[TELEGRAM]
enable_telegram=true
token=***REMOVED***
chat_id=

[WEBBROWSER]
open_browser=true

[ADVANCED]
sleep_between_requests_in_s=300
sleep_between_failed_requests_in_s=30
sleep_after_ipban_in_min=180
jitter=15
sleep_at_night=true
user_agent=impfbot
```
## Support & Contributing

### Feedback & Probleme bei einrichten
Expand Down
8 changes: 4 additions & 4 deletions config.ini.example
@@ -1,5 +1,5 @@
[COMMON]
geburtstag=23.06.1984
geburtstag=23.6.1912
postleitzahl=42042

[EMAIL]
Expand Down Expand Up @@ -30,13 +30,13 @@ open_browser=true

[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=300
sleep_between_requests_in_s=150
;Wartezeit zwischen fehlgeschlagenen Versuchen. Bei jedem weiteren wird die Wartezeit nochmal hinzuaddiert. D.h. fünf Fehlschläge = Wartezeit von 5*30s bis zum nächsen Aufruf
sleep_between_failed_requests_in_s=30
sleep_between_failed_requests_in_s=15
;Wenn eine Abfrage 10x fehlschlaegt ist die IP vermutlich gebannt. Standardmaeßig wird dann 3h gewartet
sleep_after_ipban_in_min=180
;Zufällige Zeitspanne von 0-jtter die auf die Wartezeiten addiert wird
jitter=15
jitter=5
;Legt fest ob der Bot nachts schlafen soll (Default: true da eh keine Termine veröffentlicht werden)
sleep_at_night=true
;User-Agent für die Anfrage an die API
Expand Down
3 changes: 2 additions & 1 deletion linux_start.sh
@@ -1,2 +1,3 @@
pip3 install -r requirements.txt
#!/bin/bash
pip3 install -q -r requirements.txt
python3 src/impfbot.py
3 changes: 3 additions & 0 deletions linux_validate.sh
@@ -0,0 +1,3 @@
#!/bin/bash
pip3 install -q -r requirements.txt
python3 src/validate_config.py
3 changes: 3 additions & 0 deletions mac_start.command
@@ -0,0 +1,3 @@
#!/bin/bash
pip3 install -q -r requirements.txt
python3 src/impfbot.py
3 changes: 3 additions & 0 deletions mac_validate.command
@@ -0,0 +1,3 @@
#!/bin/bash
pip3 install -q -r requirements.txt
python3 src/validate_config.py
38 changes: 34 additions & 4 deletions src/alerts.py
Expand Up @@ -14,23 +14,48 @@

log = logging.getLogger(__name__)

verbose_print = False


def verbose_info(msg: str) -> None:
if verbose_print:
log.info(msg)


def alert(msg: str, verbose: bool = False) -> None:
global verbose_print
verbose_print = verbose

def alert(msg: str) -> None:
if settings.SEND_EMAIL:
verbose_info(f"[EMAIL] try to send e-mail")
try:
send_mail(msg)
verbose_info(f"[EMAIL] sending e-mail was successful")
except Exception as e:
log.error(f"Couldn't send mail: {e}")
else:
verbose_info(f"[EMAIL] send_mail is not set to true skipping")

if settings.SEND_TELEGRAM_MSG:
verbose_info(f"[TELEGRAM] try to send telegram message")
try:
send_telegram_msg(msg)
verbose_info(f"[TELEGRAM] sending telegram message was successful")
except Exception as e:
log.error(f"Couldn't send Telegram message: {e}")
else:
verbose_info(
f"[TELEGRAM] send_telegram_msg is not set to true skipping")

if settings.OPEN_BROWSER:
verbose_info(f"[WEBBROWSER] try to open browser")
try:
webbrowser.open(appointment_url)
verbose_info(f"[WEBBROWSER] open browser was successful")
except Exception as e:
log.error(f"Couldn't open browser: {e}")
else:
verbose_info(f"[WEBBROWSER] open_browser is not set to true skipping")


def send_mail(msg: str) -> None:
Expand All @@ -43,9 +68,14 @@ def send_mail(msg: str) -> None:
mail['subject'] = msg
mail.set_content(appointment_url)

with smtplib.SMTP_SSL(settings.SERVER, settings.PORT)as smtp:
smtp.login(settings.SENDER, settings.PASSWORD)
smtp.send_message(mail)
if settings.PORT == '465':
with smtplib.SMTP_SSL(settings.SERVER, settings.PORT)as smtp:
smtp.login(settings.SENDER, settings.PASSWORD)
smtp.send_message(mail)
else:
with smtplib.SMTP(settings.SERVER, settings.PORT)as smtp:
smtp.login(settings.SENDER, settings.PASSWORD)
smtp.send_message(mail)


def send_telegram_msg(msg: str) -> None:
Expand Down
8 changes: 5 additions & 3 deletions src/impfbot.py
@@ -1,8 +1,8 @@
from datetime import datetime
from log import log
import settings
import api_wrapper
import alerts
from datetime import datetime

from common import sleep, sleep_until, is_night

Expand All @@ -14,10 +14,12 @@ def check_for_slot() -> None:
birthdate_timestamp=int(
datetime.now().timestamp() -
(datetime.now() - settings.BIRTHDATE).total_seconds()),
max_retries=5,
max_retries=10,
sleep_after_error=settings.SLEEP_BETWEEN_FAILED_REQUESTS_IN_S,
sleep_after_shadowban=settings.SLEEP_AFTER_DETECTED_SHADOWBAN_IN_MIN
)
if not result:
log.error("Result is emtpy. (Invalid ZIP Code (PLZ))")
for elem in result:
if not elem['outOfStock']:
log.info(
Expand All @@ -26,7 +28,7 @@ def check_for_slot() -> None:
msg = f"Freier Impfslot ({elem['freeSlotSizeOnline']})! {elem['vaccineName']}/{elem['vaccineType']}"
alerts.alert(msg)

sleep(60*15, 15)
sleep(settings.COOLDOWN_AFTER_FOUND_IN_MIN, 0)
else:
log.info("No free slot.")
except Exception as e:
Expand Down
38 changes: 29 additions & 9 deletions src/settings.py
@@ -1,6 +1,7 @@
import configparser
import datetime
import logging
import sys

log = logging.getLogger(__name__)

Expand All @@ -9,12 +10,27 @@

try:
ZIP = config["COMMON"]["postleitzahl"]
if len(ZIP) != 5:
raise Exception('Non 5 digit ZIP-Code')
if ZIP[0:2] not in ['19', '21', '26', '27', '28', '29', '30', '31', '34', '37', '38', '48', '49']:
log.warning(
"[EMAIL] Are you sure that you are living in lower saxony? Because your ZIP-Code seem suspicious...")
except KeyError as e:
log.warning(
f"[COMMON] '{e}' is missing in Config. Cant run without Zip-Code. Exit.")
sys.exit(1)
except Exception as e:
log.warning(f"[COMMON] Invalid ZIP-Code: {e}")

try:
BIRTHDATE = datetime.datetime.strptime(
config["COMMON"]["geburtstag"], r"%d.%m.%Y")
except KeyError as e:
log.warning(
f"[COMMON] '{e}' is missing in Config. Set Email to False")
SEND_EMAIL = False
f"[COMMON] '{e}' is missing in Config. Cant run without birthdate. Exit.")
sys.exit(1)
except Exception as e:
log.warning(f"[COMMON] Invalid birthdate: {e}")

try:
SEND_EMAIL = True if config["EMAIL"]["enable"].lower() == "true" else False
Expand All @@ -31,15 +47,14 @@
EMAIL_RECEIVERS = config["EMAIL"]["empfaenger"].split(',')
PORT = config["EMAIL"]["port"]
except KeyError as e:
log.warning(
f"[EMAIL] '{e}' is missing in Config. Set Email to False")
log.warning(f"[EMAIL] '{e}' is missing in Config. Set Email to False")
SEND_EMAIL = False

try:
SEND_TELEGRAM_MSG = True if config["TELEGRAM"]["enable_telegram"].lower() == "true" else False
SEND_TELEGRAM_MSG = True if config["TELEGRAM"]["enable_telegram"].lower(
) == "true" else False
except KeyError:
log.warning(
"[TELEGRAM] 'enable_telegram' is missing in Config. Set False")
log.warning("[TELEGRAM] 'enable_telegram' is missing in Config. Set False")
SEND_TELEGRAM_MSG = False

try:
Expand All @@ -55,8 +70,7 @@
OPEN_BROWSER = True if config["WEBBROWSER"]["open_browser"].lower(
) == "true" else False
except KeyError:
log.warning(
"'open_browser' is missing in Config. Set False")
log.warning("'open_browser' is missing in Config. Set False")
OPEN_BROWSER = False

try:
Expand All @@ -81,6 +95,12 @@
except KeyError:
log.warning("'sleep_after_ipban_in_min' is missing in Config. Set 3h")
SLEEP_AFTER_DETECTED_SHADOWBAN_IN_MIN = 60*180
try:
COOLDOWN_AFTER_FOUND_IN_MIN = int(
config["ADVANCED"]["cooldown_after_found_in_min"])*60
except KeyError:
log.warning("'cooldown_after_found_in_min' is missing in Config. Set 15min")
COOLDOWN_AFTER_FOUND_IN_MIN = 60*15

try:
JITTER = int(
Expand Down
7 changes: 0 additions & 7 deletions src/test_email.py

This file was deleted.

7 changes: 0 additions & 7 deletions src/test_telegram.py

This file was deleted.

38 changes: 38 additions & 0 deletions src/validate_config.py
@@ -0,0 +1,38 @@
import argparse
from log import log
from alerts import alert


parser = argparse.ArgumentParser()
parser.add_argument('-a', '--alert', default=False, action='store_true',
help='validate alert with a test message. Default=False')
arg = parser.parse_args()

log.info(f"validate config.ini")

import settings

log.info(f"settings validation finished")

result = None
if arg.alert:
result = "yes"
else:
print("Do you want to send a test message? yes/no")
result = input()
while True:
if result in ["yes", "y", "ja", "j"]:
alert("Test", verbose=True)
log.info(f"Finished: Sending test massages")
break
elif result in ["no", "n", "nein"]:
break
else:
print("Invalid input")
print("Do you want to send a test message? yes/no")
result = input()

log.info(f"finished validation script")

if not arg.alert:
input()
2 changes: 0 additions & 2 deletions test_mail.bat

This file was deleted.

2 changes: 0 additions & 2 deletions test_telegram.bat

This file was deleted.

2 changes: 1 addition & 1 deletion windows_start.bat
@@ -1,2 +1,2 @@
py -3 -m pip install -r requirements.txt
py -3 -m pip install -q -r requirements.txt
py -3 src/impfbot.py
2 changes: 2 additions & 0 deletions windows_validate.bat
@@ -0,0 +1,2 @@
py -3 -m pip install -q -r requirements.txt
py -3 src/validate_config.py

0 comments on commit 874f26c

Please sign in to comment.