Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

7 changed files with 47 additions and 121 deletions

View file

@ -1,25 +0,0 @@
name: Build Docker Image
on:
push:
branches:
- main
jobs:
build:
name: push docker image to docker hub
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: login to docker hub
id: docker-hub
env:
username: ${{secrets.DOCKER_USERNAME}}
password: ${{secrets.DOCKER_TOKEN}}
run: |
docker login -u $username -p $password
- name: build the docker image
id: build-docker-image
run: |
docker build -t michivonah/ep-alerts:latest .
- name: push the docker image
id: push-docker-image
run: docker push michivonah/ep-alerts:latest

1
.gitignore vendored
View file

@ -1,3 +1,2 @@
.env
__pycache__
venv

View file

@ -1,4 +1,4 @@
FROM python:3.12
FROM python:3.11
# Create directory
RUN mkdir app
@ -11,7 +11,6 @@ COPY requirements.txt .
# Set enviromental variables
ENV DISCORD_WEBHOOK "https://discord.com/api/webhooks/XXXXXXXXXXXXXX/YYYYYYYYYYYYYYYYYYYYYYYYY"
ENV SUBS "383533, 323530, 353030"
ENV NOTIFICATION_TYPE "discord"
# Install needed packages
RUN pip3 install --upgrade pip

View file

@ -1,11 +1,10 @@
# Themepark Wait Time Alerts
![](media/banner.jpg)
A tool which alerts you when the waiting times of subscribed attractions in your favourite themepark sinks or increase. The notifications are sent to a Discord webhook or to your ntfy-server. Powered by the [wartezeiten.app](https://www.wartezeiten.app/page/api.html) API.
# Europapark Waitingtime Alerts via Discord Webhook
A tool which alerts you when the waiting times of subscribed europapark attractions sinks or increase. Powered by the [wartezeiten.app](https://www.wartezeiten.app/page/api.html) API.
GitHub: https://github.com/michivonah/themepark-alerts <br>
GitHub: https://github.com/michivonah/europapark-alerts <br>
Docker: https://hub.docker.com/r/michivonah/ep-alerts
Host it on your own server:
Host it on your server:
1. Install docker on your system
```apt-get install docker.io docker-compose -y```
@ -16,15 +15,9 @@ Host it on your own server:
## Enviormental variables
These environment variables are supported
| Variable | Description | Example | Required |
| --- | --- | --- | --- |
| NOTIFICATION_TYPE | Define which type of notification you want use. Supported are: discord, ntfy | ``discord`` | yes |
| CHECK_INTERVAL | Defines how often the API is requested and the waittimes are checked for updates (in seconds) | ``30`` | no |
| DISCORD_WEBHOOK | The URL of your discord webhook | ``https://discord.com/api/webhooks/XXXXXXXXXXXXXX/YYYYYYYYYYYYYYYYYYYYYYYYY`` | no* |
| NTFY_URL | The URL to your ntfy topic | ``https://ntfy.example.com/mytopic`` | no* |
| NTFY_ACCESS_TOKEN | Optional access token for authenticating against your ntfy server if authentication is enabled. | ``tk_2cdbcfea1702cc3bd2c874beab1`` | no |
| SUBS | Your subscribed attractions with ID from wartezeiten.app API | ``383533,323530,353030`` | yes |
| THEMEPARK | Select your desired themepark from the wartezeiten.app API. Defaults to ``europapark`` | ``europapark`` | no |
| Variable | Description | Example |
| --- | --- | --- |
| DISCORD_WEBHOOK | The URL of your discord webhook | ``https://discord.com/api/webhooks/XXXXXXXXXXXXXX/YYYYYYYYYYYYYYYYYYYYYYYYY`` |
| SUBS | Your subscribed attractions with ID from wartezeiten.app API | ``383533,323530,353030`` |
> *Depending on the selected service for notifications (``NOTIFICATION_TYPE``) ether ``DISCORD_WEBHOOK`` or ``NTFY_URL`` is required.
> Required enviromental variables: DISCORD_WEBHOOK, SUBS

106
main.py
View file

@ -1,10 +1,11 @@
# Themepark Wait Time Alerts
# Michi von Ah - October 2023 (Last Updated on October 2024)
# Europapark Waiting Time alerts to Discord
# Michi von Ah - October 2023
# Thanks to https://www.wartezeiten.app/ for their API
import requests
import os
from dotenv import load_dotenv
from discord_webhook import DiscordWebhook
import time
load_dotenv()
@ -12,90 +13,49 @@ load_dotenv()
# Global defintions
subscribedAttractions = os.getenv('SUBS').split(",")
currentTimes = {}
refreshTime = int(os.getenv('CHECK_INTERVAL')) if os.getenv('CHECK_INTERVAL') else 30
notificationType = os.getenv('NOTIFICATION_TYPE') if os.getenv('NOTIFICATION_TYPE') else "discord"
themepark = os.getenv('THEMEPARK') if os.getenv('THEMEPARK') else "europapark"
refreshTime = 30
# Send messagess via specified notificationType
def sendMessage(message, notificationType):
match notificationType.lower():
case "ntfy":
endpoint = os.getenv('NTFY_URL')
accessToken = os.getenv('NTFY_ACCESS_TOKEN')
if accessToken:
header = {
"Authorization":f"Bearer {accessToken}"
}
try:
response = requests.post(url=endpoint, headers=header, data=message)
except Exception as error:
raise Exception(f"Got an error while sending the notification: {error}")
else:
try:
response = requests.post(url=endpoint, data=message)
except Exception as error:
raise Exception(f"Got an error while sending the notification: {error}")
return response
case "discord" | _:
endpoint = os.getenv('DISCORD_WEBHOOK')
data = {
"content": message,
}
try:
response = requests.post(url=endpoint, json=data)
return response
except Exception as error:
raise Exception(f"Got an error while sending the notification: {error}")
# Send messagess via Discord Webhook
def sendMessage(message):
webhookUrl = os.getenv('DISCORD_WEBHOOK')
webhook = DiscordWebhook(url=webhookUrl, content=message)
response = webhook.execute()
return response
# Check for the current waiting times
def checkTimes(subscribedAttractions, themepark):
try:
endpoint = "https://api.wartezeiten.app/v1/waitingtimes"
def checkTimes(subscribedAttractions):
endpoint = "https://api.wartezeiten.app/v1/waitingtimes"
header = {
"language":"de",
"park":themepark
}
header = {
"language":"de",
"park":"europapark"
}
req = requests.get(url=endpoint, headers=header)
except:
raise Exception(f"API Request to endpoint {endpoint} failed.")
try:
result = req.json()
except:
raise Exception("Format of API response is invalid. (JSON expected)")
try:
attractions = result
for attraction in attractions:
if isinstance(attraction, dict) and "code" in attraction:
if attraction["code"] in subscribedAttractions:
if attraction["status"] == "opened":
refreshTime = 30
if not attraction["code"] in currentTimes: currentTimes[attraction["code"]] = attraction["waitingtime"];
if currentTimes[attraction["code"]] > attraction["waitingtime"]:
sendMessage(f"Waiting time of {attraction['name']} sank to {attraction['waitingtime']} Minutes!", notificationType)
elif currentTimes[attraction["code"]] < attraction["waitingtime"]:
sendMessage(f"Waiting time for {attraction['name']} increased to {attraction['waitingtime']} Minutes!", notificationType)
currentTimes[attraction["code"]] = attraction["waitingtime"]
else:
refreshTime = 180
req = requests.get(url = endpoint, headers = header)
result = req.json()
attractions = result
for attraction in attractions:
if attraction["code"] in subscribedAttractions:
if attraction["status"] == "opened":
refreshTime = 30
if not attraction["code"] in currentTimes: currentTimes[attraction["code"]] = attraction["waitingtime"];
if currentTimes[attraction["code"]] > attraction["waitingtime"]:
sendMessage(f"Waiting time of {attraction['name']} sank to {attraction['waitingtime']} Minutes!")
elif currentTimes[attraction["code"]] < attraction["waitingtime"]:
sendMessage(f"Waiting time for {attraction['name']} increased to {attraction['waitingtime']} Minutes!")
currentTimes[attraction["code"]] = attraction["waitingtime"]
else:
print(f"Info: Attraction was skipped because it has an invalid data structure. Affected attraction: {attraction}")
except Exception as error:
raise Exception(f"Got an error while checking for differences since the last API call. Error: {error}")
refreshTime = 180
# Main Loop
# Checks every 30 seconds for changes in the waiting times of the subscribed attractions
# If some attractions are closed the check will only be executed every 180 seconds
if __name__ == '__main__':
print("Themepark Wait Time Alerts")
print("EP Waiting Time Alerting Tool")
print("By Michi von Ah")
print("Big thanks to the wartezeiten.app API!")
while True:
try:
checkTimes(subscribedAttractions, themepark)
print(f"Checked for updates at {time.strftime('%H:%M:%S', time.localtime())}")
except Exception as error:
raise Exception(error)
checkTimes(subscribedAttractions)
print(f"Checked for updates at {time.strftime('%H:%M:%S', time.localtime())}")
time.sleep(refreshTime)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

View file

@ -1,4 +1,4 @@
# requirements.txt
python-dotenv==1.1.1
pipenv==2025.0.4
requests==2.32.5
python-dotenv==1.0.0
#discord.py
discord-webhook==1.3.0