From 91cc7bc9bfe588331e93f162563cc57d10a66d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20MARQUET?= <72651575+BreizhHardware@users.noreply.github.com> Date: Mon, 23 Dec 2024 12:20:13 +0000 Subject: [PATCH] =?UTF-8?q?First=20it=C3=A9ration=20for=20discord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 + README.md | 5 ++- ntfy.py | 21 +++++++-- send_discord.py | 114 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 send_discord.py diff --git a/Dockerfile b/Dockerfile index a074be4..a76fd45 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,7 @@ ADD requirements.txt / ADD entrypoint.sh / ADD send_ntfy.py / ADD send_gotify.py / +ADD send_discord.py / ADD index.html /var/www/html/index.html ADD script.js /var/www/html/script.js RUN apk add --no-cache sqlite-dev sqlite-libs gcc musl-dev nginx @@ -25,6 +26,7 @@ ENV USERNAME="" \ DOCKER_PASSWORD="" \ GOTIFY_URL="" \ GOTIFY_TOKEN="" \ + DISCORD_WEBHOOK_URL="" \ FLASK_ENV=production # Exposer le port 5000 pour l'API et le port 80 pour le serveur web diff --git a/README.md b/README.md index f820b79..35e6b7d 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ services: - DOCKER_PASSWORD= # Default is empty (Docker Hub password) - GOTIFY_URL=gotify_url # Required if gotify is used - GOTIFY_TOKEN= # Required if gotify is used + - DISCORD_WEBHOOK_URL= # Required if discord is used volumes: - /path/to/github-ntfy:/github-ntfy/ ports: @@ -51,6 +52,7 @@ services: - DOCKER_PASSWORD= # Default is empty (Docker Hub password) - GOTIFY_URL=gotify_url # Required if gotify is used - GOTIFY_TOKEN= # Required if gotify is used + - DISCORD_WEBHOOK_URL= # Required if discord is used volumes: - /path/to/github-ntfy:/github-ntfy/ ports: @@ -73,6 +75,7 @@ services: - DOCKER_PASSWORD= # Default is empty (Docker Hub password) - GOTIFY_URL=gotify_url # Required if gotify is used - GOTIFY_TOKEN= # Required if gotify is used + - DISCORD_WEBHOOK_URL= # Required if discord is used volumes: - /path/to/github-ntfy:/github-ntfy/ ports: @@ -102,7 +105,7 @@ If you want to contribut, feel free to open a pull request (CONTRIBUTION.md comm - [x] Add Docker Hub compatibility - [ ] Rework of the web interface - [x] Compatibility with Gotify -- [ ] Compatibility with Discord Webhook +- [x] Compatibility with Discord Webhook - [x] Compatibility and distribution for arm64 and armv7 ## Show your support diff --git a/ntfy.py b/ntfy.py index a5e26a3..260ceb6 100644 --- a/ntfy.py +++ b/ntfy.py @@ -13,6 +13,10 @@ from send_gotify import ( github_send_to_gotify, docker_send_to_gotify, ) +from send_discord import ( + github_send_to_discord, + docker_send_to_discord, +) # Configuring the logger logging.basicConfig( @@ -29,6 +33,8 @@ if github_token: docker_username = os.environ.get("DOCKER_USERNAME") docker_password = os.environ.get("DOCKER_PASSWORD") +discord_webhook_url = os.environ.get("DISCORD_WEBHOOK_URL") + def create_dockerhub_token(username, password): url = "https://hub.docker.com//v2/users/login" @@ -177,26 +183,34 @@ if __name__ == "__main__": ntfy_url = os.environ.get("NTFY_URL") gotify_url = os.environ.get("GOTIFY_URL") gotify_token = os.environ.get("GOTIFY_TOKEN") + discord_webhook_url = os.environ.get("DISCORD_WEBHOOK_URL") timeout = float(os.environ.get("GHNTFY_TIMEOUT")) - if auth and ntfy_url: + if auth and (ntfy_url or gotify_url or discord_webhook_url): while True: github_watched_repos_list = get_watched_repos() github_latest_release = get_latest_releases(github_watched_repos_list) docker_watched_repos_list = get_docker_watched_repos() docker_latest_release = get_latest_docker_releases(docker_watched_repos_list) - if ntfy_url != "": + + if ntfy_url: if github_latest_release: github_send_to_ntfy(github_latest_release, auth, ntfy_url) if docker_latest_release: docker_send_to_ntfy(docker_latest_release, auth, ntfy_url) - if gotify_url != "" and gotify_token != "": + if gotify_url and gotify_token: if github_latest_release: github_send_to_gotify(github_latest_release, gotify_token, gotify_url) if docker_latest_release: docker_send_to_gotify(docker_latest_release, gotify_token, gotify_url) + if discord_webhook_url: + if github_latest_release: + github_send_to_discord(github_latest_release, discord_webhook_url) + if docker_latest_release: + docker_send_to_discord(docker_latest_release, discord_webhook_url) + time.sleep(timeout) # Wait an hour before checking again else: logger.error("Usage: python ntfy.py") @@ -211,4 +225,5 @@ if __name__ == "__main__": logger.error( "GOTIFY_TOKEN: the token of the gotify server need to be stored in an environment variable named GOTIFY_TOKEN" ) + logger.error("DISCORD_WEBHOOK_URL: the webhook URL for Discord notifications need to be stored in an environment variable named DISCORD_WEBHOOK_URL") logger.error("GHNTFY_TIMEOUT: the time interval between each check") diff --git a/send_discord.py b/send_discord.py new file mode 100644 index 0000000..a0c3c9a --- /dev/null +++ b/send_discord.py @@ -0,0 +1,114 @@ +import requests +import sqlite3 +import logging + +conn = sqlite3.connect( + "/github-ntfy/ghntfy_versions.db", + check_same_thread=False, +) +cursor = conn.cursor() + +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", +) +logger = logging.getLogger(__name__) + + +def github_send_to_discord(releases, webhook_url): + for release in releases: + app_name = release["repo"].split("/")[-1] # Getting the application name from the repo + version_number = release["tag_name"] # Getting the version number + app_url = release["html_url"] # Getting the application URL + changelog = release["changelog"] # Getting the changelog + release_date = release["published_at"] # Getting the release date + release_date = release_date.replace("T", " ").replace("Z", "") # Formatting the release date + + # Checking if the version has changed since the last time + cursor.execute( + "SELECT version FROM versions WHERE repo=?", + (app_name,), + ) + previous_version = cursor.fetchone() + if previous_version and previous_version[0] == version_number: + logger.info(f"The version of {app_name} has not changed. No notification sent.") + continue # Move on to the next application + + # Creating the embed message + embed = { + "title": f"New version for {app_name}", + "url": app_url, + "color": "#027d21", + "fields": [ + { + "name": "Version", + "value": version_number, + "inline": True + }, + { + "name": "Published on", + "value": release_date, + "inline": True + }, + { + "name": "Changelog", + "value": changelog, + "inline": False + } + ] + } + + data = { + "embeds": [embed] + } + response = requests.post(webhook_url, json=data) + if response.status_code == 204: + logger.info(f"Message sent to Discord for {app_name}") + else: + logger.error(f"Failed to send message to Discord. Status code: {response.status_code}") + +def docker_send_to_discord(releases, webhook_url): + for release in releases: + app_name = release["repo"].split("/")[-1] # Getting the application name from the repo + digest_number = release["digest"] + app_url = release["html_url"] # Getting the application URL + release_date = release["published_at"] # Getting the release date + release_date = release_date.replace("T", " ").replace("Z", "") # Formatting the release date + + # Checking if the version has changed since the last time + cursor.execute( + "SELECT digest FROM docker_versions WHERE repo=?", + (app_name,), + ) + previous_digest = cursor.fetchone() + if previous_digest and previous_digest[0] == digest_number: + logger.info(f"The digest of {app_name} has not changed. No notification sent.") + continue # Move on to the next application + + # Creating the embed message + embed = { + "title": f"New version for {app_name}", + "url": app_url, + "color": "#027d21", + "fields": [ + { + "name": "Digest", + "value": digest_number, + "inline": True + }, + { + "name": "Published on", + "value": release_date, + "inline": True + } + ] + } + + data = { + "embeds": [embed] + } + response = requests.post(webhook_url, json=data) + if response.status_code == 204: + logger.info(f"Message sent to Discord for {app_name}") + else: + logger.error(f"Failed to send message to Discord. Status code: {response.status_code}") \ No newline at end of file