From 899a8ce7b34c4892d3d41135b4885f4cab532595 Mon Sep 17 00:00:00 2001 From: Grizouille Date: Fri, 7 Nov 2025 13:58:19 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20des=20fonctionnalit=C3=A9e=20pour=20nex?= =?UTF-8?q?tcloud?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deezer_downloader/configuration.py | 2 +- deezer_downloader/deezer.py | 3 + deezer_downloader/nextcloud.py | 69 +++++++++++++++++++++ deezer_downloader/update_nextcloud_files.py | 35 +++++++++++ deezer_downloader/web/app.py | 12 +++- deezer_downloader/web/music_backend.py | 12 ++-- 6 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 deezer_downloader/nextcloud.py create mode 100644 deezer_downloader/update_nextcloud_files.py diff --git a/deezer_downloader/configuration.py b/deezer_downloader/configuration.py index 2e7f14e..958369f 100644 --- a/deezer_downloader/configuration.py +++ b/deezer_downloader/configuration.py @@ -16,7 +16,7 @@ def load_config(config_abs): config = ConfigParser() config.read(config_abs) - assert list(config.keys()) == ['DEFAULT', 'mpd', 'download_dirs', 'debug', 'http', 'proxy', 'threadpool', 'deezer', 'youtubedl'], f"Validating config file failed. Check {config_abs}" + assert list(config.keys()) == ['DEFAULT', 'mpd', 'download_dirs', 'debug', 'http', 'proxy', 'threadpool', 'deezer', 'youtubedl', 'nextcloud', 'nextcloud_ssh_scan_files'], f"Validating config file failed. Check {config_abs}" if config['mpd'].getboolean('use_mpd'): if not config['mpd']['music_dir_root'].startswith(config['download_dirs']['base']): diff --git a/deezer_downloader/deezer.py b/deezer_downloader/deezer.py index ea3d8d1..f07d187 100644 --- a/deezer_downloader/deezer.py +++ b/deezer_downloader/deezer.py @@ -15,6 +15,7 @@ from mutagen.flac import FLAC, Picture from mutagen.mp3 import MP3 from mutagen.id3 import PictureType, TIT2, TALB, TPE1, TRCK, TDRC, TPOS, APIC, TPE2 from mutagen import MutagenError +from deezer_downloader.update_nextcloud_files import call_scan # BEGIN TYPES @@ -244,6 +245,8 @@ def download_song(song: dict, output_file: str) -> None: print(f"Warning: Could not write metadata to file: {e}") except Exception as e: raise DeezerApiException(f"Could not write song to disk: {e}") from e + + call_scan(output_file) print("Download finished: {}".format(output_file)) diff --git a/deezer_downloader/nextcloud.py b/deezer_downloader/nextcloud.py new file mode 100644 index 0000000..caa3733 --- /dev/null +++ b/deezer_downloader/nextcloud.py @@ -0,0 +1,69 @@ +import jwt # PyJWT +from jwt import InvalidTokenError +from jwt import ExpiredSignatureError +import os +from flask import jsonify, abort, session +from deezer_downloader.configuration import config + +#def setJwtInCookieToResponse(request, response): +# jwt_token = request.args.get("jwt") +# if not jwt_token: +# return response +# +# response.set_cookie( +# "access_token", +# jwt_token, +# max_age=60*60*24, +# httponly=True, +# secure=True # True si HTTPS +# ) +# return response + +def addJwtInUserSession(request): + if 'user_uid' in session: + return + + jwt_token = request.args.get(config["nextcloud"]["jwt_name_parameter"]) + if not jwt_token: + return abort(403) + + try: + decoded = jwt.decode(jwt_token, config["nextcloud"]["public_key"], algorithms=["ES256"]) + iss = decoded.get("iss") + iat = decoded.get("iat") + exp = decoded.get("exp") + userdata = decoded.get("userdata", {}) + email = userdata.get("email") + uid = userdata.get("uid") + display_name = userdata.get("displayName") + + print("✅ JWT décodé :") + print("Iss:", iss) + print("Issued At:", iat) + print("Expires:", exp) + print("Email:", email) + print("UID:", uid) + print("Display Name:", display_name) + + #base_dir_user = base_dir.format(user=uid) + #config["download_dirs"]["base"] = base_dir_user + + session['user_uid'] = uid + session['user_email'] = email + session['user_displayName'] = display_name + session['user_base_dir'] = config["download_dirs"]["base"] + "\\" + uid + #createDownloadDirectoriesIfNotExist() + + print(f"✅ Download base dir set to: {session['user_base_dir']}") + except ExpiredSignatureError: + return jsonify({"error": "Token expired"}), 401 + except InvalidTokenError as e: + print("❌ Erreur de validation du token :", e) + +def createDownloadDirectoriesIfNotExist(): + os.makedirs(config["download_dirs"]["base"], exist_ok=True) + os.makedirs(config["download_dirs"]["songs"], exist_ok=True) + os.makedirs(config["download_dirs"]["albums"], exist_ok=True) + os.makedirs(config["download_dirs"]["zips"], exist_ok=True) + os.makedirs(config["download_dirs"]["playlists"], exist_ok=True) + os.makedirs(config["download_dirs"]["youtubedl"], exist_ok=True) \ No newline at end of file diff --git a/deezer_downloader/update_nextcloud_files.py b/deezer_downloader/update_nextcloud_files.py new file mode 100644 index 0000000..1b4665a --- /dev/null +++ b/deezer_downloader/update_nextcloud_files.py @@ -0,0 +1,35 @@ +import paramiko +import os +from deezer_downloader.configuration import config + +def call_scan(directory_path): + if not config['nextcloud_ssh_scan_files']['host']: + return + host = config['nextcloud_ssh_scan_files']['host'] + port = config['nextcloud_ssh_scan_files']['port'] + username = config['nextcloud_ssh_scan_files']['username'] + password = config['nextcloud_ssh_scan_files']['password'] + + directory_path = os.path.dirname(directory_path) + directory_path = directory_path.replace(config['download_dirs']['base'] + "\\", "") + print("Path Nexcloud Scan " + directory_path) + # Commande à exécuter + cmd = 'sudo /home/nextclouddeezer/scan_deezerDl_folder.sh "{dir}"'.format(dir=directory_path) + + # Création de la connexion SSH + ssh = paramiko.SSHClient() + ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # accepter clés inconnues + ssh.connect(hostname=host, port=port, username=username, password=password) + + # Exécuter la commande + stdin, stdout, stderr = ssh.exec_command(cmd) + + # Afficher les résultats + print("STDOUT:") + print(stdout.read().decode()) + + print("STDERR:") + print(stderr.read().decode()) + + # Fermer la connexion + ssh.close() \ No newline at end of file diff --git a/deezer_downloader/web/app.py b/deezer_downloader/web/app.py index 624dfbb..279daea 100644 --- a/deezer_downloader/web/app.py +++ b/deezer_downloader/web/app.py @@ -4,17 +4,19 @@ from subprocess import Popen, PIPE from functools import wraps import requests import atexit -from flask import Flask, render_template, request, jsonify +from flask import Flask, render_template, request, jsonify, session, make_response from markupsafe import escape from flask_autoindex import AutoIndex import warnings import giphypop from deezer_downloader.configuration import config -from deezer_downloader.web.music_backend import sched +from deezer_downloader.web.music_backend import sched, check_and_set_download_dirs_exist from deezer_downloader.deezer import deezer_search, init_deezer_session +from deezer_downloader.nextcloud import addJwtInUserSession app = Flask(__name__) +app.secret_key = "vilvhmqerjgùqrgojpùqjgvnùzevoijrpùvqpzejgijzepgùg" auto_index = AutoIndex(app, config["download_dirs"]["base"], add_url_rules=False) auto_index.add_icon_rule('music.png', ext='m3u8') @@ -82,6 +84,9 @@ def validate_schema(*parameters_to_check): return wrapper return decorator +@app.before_request +def beforeRequest(): + addJwtInUserSession(request) @app.route("/") def index(): @@ -117,7 +122,7 @@ def autoindex(path="."): media_url = "https://cataas.com/cat" template_context = {'gif_url': media_url} - return auto_index.render_autoindex(path, template_context=template_context) + return auto_index.render_autoindex(path=session['user_base_dir'], template_context=template_context) @app.route('/queue', methods=['GET']) @@ -168,6 +173,7 @@ def deezer_download_song_or_album(): add_to_playlist: True|False (add to mpd playlist) create_zip: True|False (create a zip for the album) """ + check_and_set_download_dirs_exist() user_input = request.get_json(force=True) desc = "Downloading {}".format(user_input['type']) if user_input['type'] == "track": diff --git a/deezer_downloader/web/music_backend.py b/deezer_downloader/web/music_backend.py index a1e0740..2ad8982 100644 --- a/deezer_downloader/web/music_backend.py +++ b/deezer_downloader/web/music_backend.py @@ -4,6 +4,7 @@ from os.path import basename import mpd import platform from zipfile import ZipFile, ZIP_DEFLATED +from flask import session from deezer_downloader.configuration import config from deezer_downloader.youtubedl import youtubedl_download @@ -16,15 +17,16 @@ from deezer_downloader.threadpool_queue import ThreadpoolScheduler, report_progr sched = ThreadpoolScheduler() -def check_download_dirs_exist(): +def check_and_set_download_dirs_exist(): + config["download_dirs"]["songs"] = os.path.join(session['user_base_dir'], "DeezerDownload", "songs") + config["download_dirs"]["zips"] = os.path.join(session['user_base_dir'], "DeezerDownload","zips") + config["download_dirs"]["albums"] = os.path.join(session['user_base_dir'], "DeezerDownload","albums") + config["download_dirs"]["playlists"] = os.path.join(session['user_base_dir'], "DeezerDownload","playlists") + config["download_dirs"]["youtubedl"] = os.path.join(session['user_base_dir'], "DeezerDownload","youtubedl") for directory in [config["download_dirs"]["songs"], config["download_dirs"]["zips"], config["download_dirs"]["albums"], config["download_dirs"]["playlists"], config["download_dirs"]["youtubedl"]]: os.makedirs(directory, exist_ok=True) - -check_download_dirs_exist() - - def make_song_paths_relative_to_mpd_root(songs, prefix=""): # ensure last slash config["mpd"]["music_dir_root"] = os.path.join(config["mpd"]["music_dir_root"], '')