diff --git a/Dockerfile b/Dockerfile
index b8a651c..ccad950 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -3,9 +3,12 @@ FROM python:3.11.8-alpine3.19
LABEL maintainer="BreizhHardware"
ADD ntfy.py /
+ADD ntfy_api.py /
ADD requirements.txt /
ADD entrypoint.sh /
-RUN apk add --no-cache sqlite-dev sqlite-libs gcc musl-dev
+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
RUN pip install -r requirements.txt
# Définir les variables d'environnement pour username et password
@@ -13,6 +16,11 @@ ENV USERNAME="" \
PASSWORD="" \
NTFY_URL="" \
GHNTFY_TIMEOUT="3600" \
- GHREPO=""
+ GHNTFY_TOKEN=""
+
+# Exposer le port 5000 pour l'API et le port 80 pour le serveur web
+EXPOSE 5000 80
+
+COPY nginx.conf /etc/nginx/nginx.conf
ENTRYPOINT ["/entrypoint.sh"]
diff --git a/entrypoint.sh b/entrypoint.sh
index dfb8e20..3940da6 100644
--- a/entrypoint.sh
+++ b/entrypoint.sh
@@ -3,5 +3,8 @@
# Génère le contenu du fichier auth.txt à partir des variables d'environnement
echo -n "$USERNAME:$PASSWORD" | base64 > /auth.txt
+# Démarrer nginx en arrière-plan
+nginx -g 'daemon off;' &
+
# Exécute le script Python
exec python ./ntfy.py
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..43de228
--- /dev/null
+++ b/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+ Github-Ntfy Add a repo
+
+
+
+
+
+
Github-Ntfy
+
Add a repo
+
+
+
Watched Repositories
+
+
+
+
+
\ No newline at end of file
diff --git a/nginx.conf b/nginx.conf
new file mode 100644
index 0000000..60b9b1b
--- /dev/null
+++ b/nginx.conf
@@ -0,0 +1,32 @@
+events {
+ worker_connections 1024;
+}
+
+http {
+ include mime.types;
+ default_type application/octet-stream;
+
+ server {
+ listen 80;
+
+ location / {
+ root /var/www/html;
+ index index.html;
+ }
+
+ location /app_repo {
+ proxy_pass http://127.0.0.1:5000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+ location /watched_repos {
+ proxy_pass http://127.0.0.1:5000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+ }
+}
diff --git a/ntfy.py b/ntfy.py
index 3b126e0..91400e6 100644
--- a/ntfy.py
+++ b/ntfy.py
@@ -2,8 +2,8 @@ import requests
import time
import os
import logging
-import json
import sqlite3
+import subprocess
# Configurer le logger
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
@@ -14,16 +14,9 @@ github_headers = {}
if github_token:
github_headers['Authorization'] = f"token {github_token}"
-repo_list_env = os.environ.get('GHREPO')
-watched_repos_list = json.loads(repo_list_env) if repo_list_env else []
-
-if not watched_repos_list:
- logger.error("Aucun dépôt n'a été spécifié. Veuillez spécifier les dépôts à surveiller dans l'environnement GHREPO")
- exit(1)
# Connexion à la base de données pour stocker les versions précédentes
-db_path = '/github-ntfy/ghntfy_versions.db'
-conn = sqlite3.connect(db_path)
+conn = sqlite3.connect('/github-ntfy/ghntfy_versions.db', check_same_thread=False)
cursor = conn.cursor()
# Création de la table si elle n'existe pas
@@ -33,6 +26,26 @@ conn.commit()
logger.info("Démarrage de la surveillance des versions...")
+conn2 = sqlite3.connect('/github-ntfy/watched_repos.db', check_same_thread=False)
+cursor2 = conn2.cursor()
+
+cursor2.execute('''CREATE TABLE IF NOT EXISTS watched_repos
+ (id INTEGER PRIMARY KEY, repo TEXT)''')
+conn2.commit()
+
+
+def get_watched_repos():
+ cursor2.execute("SELECT * FROM watched_repos")
+ watched_repos = cursor2.fetchall()
+ watched_repos = []
+ for repo in watched_repos:
+ watched_repos.append(repo[1])
+ return watched_repos
+
+
+def start_api():
+ subprocess.Popen(["python", "ntfy_api.py"])
+
def get_latest_releases(watched_repos):
releases = []
@@ -101,6 +114,7 @@ def send_to_ntfy(releases, auth, url):
if __name__ == "__main__":
+ start_api()
with open('/auth.txt', 'r') as f:
auth = f.read().strip()
ntfy_url = os.environ.get('NTFY_URL')
@@ -108,11 +122,13 @@ if __name__ == "__main__":
if auth and ntfy_url:
while True:
+ watched_repos_list = get_watched_repos()
latest_release = get_latest_releases(watched_repos_list)
if latest_release:
send_to_ntfy(latest_release, auth, ntfy_url)
time.sleep(timeout) # Attendre une heure avant de vérifier à nouveau
else:
logger.error("Usage: python ntfy.py")
- logger.error("auth: can be generataed by the folowing command: echo -n 'username:password' | base64 and need to be stored in a file named auth.txt")
+ logger.error(
+ "auth: can be generataed by the folowing command: echo -n 'username:password' | base64 and need to be stored in a file named auth.txt")
logger.error("NTFY_URL: the url of the ntfy server need to be stored in an environment variable named NTFY_URL")
diff --git a/ntfy_api.py b/ntfy_api.py
new file mode 100644
index 0000000..91fc906
--- /dev/null
+++ b/ntfy_api.py
@@ -0,0 +1,60 @@
+from flask import Flask, request, jsonify
+from flask_cors import CORS
+import sqlite3
+
+app = Flask(__name__)
+CORS(app)
+
+
+def get_db_connection():
+ conn = sqlite3.connect('/github-ntfy/watched_repos.db')
+ conn.row_factory = sqlite3.Row
+ return conn
+
+
+def close_db_connection(conn):
+ conn.close()
+
+
+@app.route('/app_repo', methods=['POST'])
+def app_repo():
+ data = request.json
+ repo = data.get('repo')
+
+ # Vérifier si le champ 'repo' est présent dans les données JSON
+ if not repo:
+ return jsonify({"error": "Le champ 'repo' est requis."}), 400
+
+ # Établir une connexion à la base de données
+ conn = get_db_connection()
+ cursor = conn.cursor()
+
+ try:
+ # Vérifier si le dépôt existe déjà dans la base de données
+ cursor.execute("SELECT * FROM watched_repos WHERE repo=?", (repo,))
+ existing_repo = cursor.fetchone()
+ if existing_repo:
+ return jsonify({"error": f"Le dépôt {repo} existe déjà."}), 409
+
+ # Ajouter le dépôt à la base de données
+ cursor.execute("INSERT INTO watched_repos (repo) VALUES (?)", (repo,))
+ conn.commit()
+ return jsonify({"message": f"Le dépôt {repo} a été ajouté à la liste des dépôts surveillés."})
+ finally:
+ # Fermer la connexion à la base de données
+ close_db_connection(conn)
+
+
+@app.route('/watched_repos', methods=['GET'])
+def get_watched_repos():
+ db = get_db_connection()
+ cursor = db.cursor()
+ cursor.execute("SELECT repo FROM watched_repos")
+ watched_repos = [repo[0] for repo in cursor.fetchall()]
+ cursor.close()
+ db.close()
+ return jsonify(watched_repos)
+
+
+if __name__ == "__main__":
+ app.run(debug=True)
diff --git a/requirements.txt b/requirements.txt
index e8dedf8..322bf8e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,4 @@
requests==2.31.0
-pysqlite3==0.5.2
\ No newline at end of file
+pysqlite3==0.5.2
+flask==3.0.2
+flask-cors==4.0.0
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..f106fc1
--- /dev/null
+++ b/script.js
@@ -0,0 +1,45 @@
+document.getElementById('addRepoForm').addEventListener('submit', function(event) {
+ event.preventDefault();
+ let repoName = document.getElementById('repo').value;
+ fetch('/app_repo', {
+ method: 'POST',
+ headers: {
+ 'Access-Control-Allow-Origin': '*',
+ 'Content-Type': 'application/json'
+ },
+ body: JSON.stringify({repo: repoName})
+ })
+ .then(response => {
+ if (response.ok) {
+ // Si la requête s'est bien déroulée, actualiser la liste des dépôts surveillés
+ refreshWatchedRepos();
+ } else {
+ throw new Error('Erreur lors de l\'ajout du dépôt');
+ }
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ });
+});
+
+function refreshWatchedRepos() {
+ fetch('/watched_repos')
+ .then(response => response.json())
+ .then(data => {
+ const watchedReposList = document.getElementById('watchedReposList');
+ // Vider la liste actuelle
+ watchedReposList.innerHTML = '';
+ // Ajouter chaque dépôt surveillé à la liste
+ data.forEach(repo => {
+ const listItem = document.createElement('li');
+ listItem.textContent = repo;
+ watchedReposList.appendChild(listItem);
+ });
+ })
+ .catch(error => {
+ console.error('Error:', error);
+ });
+}
+
+// Appeler la fonction pour charger les dépôts surveillés au chargement de la page
+refreshWatchedRepos();
\ No newline at end of file