From 0ac48126aa3f69ded8ad0b7e83b1324360b25def Mon Sep 17 00:00:00 2001 From: MasutaYunikon Date: Fri, 22 May 2026 22:34:17 +0200 Subject: [PATCH] feat: ajout du parametre auto download --- server/routes/requests.ts | 16 +++-- server/routes/settings.ts | 21 ++++--- server/settings.ts | 4 +- src/views/settings/UsersView.vue | 103 ++++++++++++++++++++++++++++++- 4 files changed, 127 insertions(+), 17 deletions(-) diff --git a/server/routes/requests.ts b/server/routes/requests.ts index 54e7c98..b83f959 100644 --- a/server/routes/requests.ts +++ b/server/routes/requests.ts @@ -8,6 +8,7 @@ import { } from '../requests.js' import { dispatchDownload } from '../torrent-clients/index.js' import { readSerieData } from '../lib/github-cache.js' +import { readSettings } from '../settings.js' import { logger } from '../logger.js' const router = Router() @@ -56,10 +57,17 @@ router.patch('/requests/:id', requireAdmin, async (req, res) => { const id = String(req.params.id) if (action === 'approve') { request = approveRequest(id) - // Lancer le(s) téléchargement(s) correspondant à la demande - autoDownloadRequest(request).catch(err => - logger.warn('requests', `Auto-dl échoué pour "${request.serieName}" : ${err instanceof Error ? err.message : err}`) - ) + // Lancer le(s) téléchargement(s) si au moins un requester est autorisé + const { requestAutoDownloadUsers } = readSettings() + const enabled = requestAutoDownloadUsers === 'all' + ? true + : Array.isArray(requestAutoDownloadUsers) && requestAutoDownloadUsers.length > 0 + && request.requesters.some(r => (requestAutoDownloadUsers as string[]).includes(r.userId)) + if (enabled) { + autoDownloadRequest(request).catch(err => + logger.warn('requests', `Auto-dl échoué pour "${request.serieName}" : ${err instanceof Error ? err.message : err}`) + ) + } } else if (action === 'reject') request = rejectRequest(id, rejectionMessage) else if (action === 'complete') request = completeRequest(id) else { res.status(400).json({ error: 'Action invalide (approve | reject | complete)' }); return } diff --git a/server/routes/settings.ts b/server/routes/settings.ts index c8a8a6a..3286ba5 100644 --- a/server/routes/settings.ts +++ b/server/routes/settings.ts @@ -10,17 +10,18 @@ router.get('/settings', requireAuth, (_req, res) => { }) router.post('/settings', requireAuth, (req, res) => { - const { mediaPath, completePath, organizeMode, category, nfoSupport, autoImport, devMode, deleteTorrentOnMove, autoUnimportMissing } = req.body + const { mediaPath, completePath, organizeMode, category, nfoSupport, autoImport, devMode, deleteTorrentOnMove, autoUnimportMissing, requestAutoDownloadUsers } = req.body const patch: Record = {} - if (mediaPath !== undefined) patch.mediaPath = mediaPath - if (completePath !== undefined) patch.completePath = completePath - if (organizeMode !== undefined) patch.organizeMode = organizeMode - if (category !== undefined) patch.category = category - if (nfoSupport !== undefined) patch.nfoSupport = nfoSupport - if (autoImport !== undefined) patch.autoImport = autoImport - if (devMode !== undefined) patch.devMode = devMode - if (deleteTorrentOnMove !== undefined) patch.deleteTorrentOnMove = deleteTorrentOnMove - if (autoUnimportMissing !== undefined) patch.autoUnimportMissing = autoUnimportMissing + if (mediaPath !== undefined) patch.mediaPath = mediaPath + if (completePath !== undefined) patch.completePath = completePath + if (organizeMode !== undefined) patch.organizeMode = organizeMode + if (category !== undefined) patch.category = category + if (nfoSupport !== undefined) patch.nfoSupport = nfoSupport + if (autoImport !== undefined) patch.autoImport = autoImport + if (devMode !== undefined) patch.devMode = devMode + if (deleteTorrentOnMove !== undefined) patch.deleteTorrentOnMove = deleteTorrentOnMove + if (autoUnimportMissing !== undefined) patch.autoUnimportMissing = autoUnimportMissing + if (requestAutoDownloadUsers !== undefined) patch.requestAutoDownloadUsers = requestAutoDownloadUsers const updated = writeSettings(patch) logger.info('api', 'Paramètres mis à jour') res.json(updated) diff --git a/server/settings.ts b/server/settings.ts index 967521c..ca858b5 100644 --- a/server/settings.ts +++ b/server/settings.ts @@ -13,7 +13,7 @@ export interface Settings { autoImport : boolean devMode : boolean deleteTorrentOnMove : boolean - requestAutoImport : boolean // demandes users : import auto ou validation admin + requestAutoDownloadUsers: 'all' | string[] // IDs users autorisés au dl auto sur approbation ; [] = désactivé jellyfinUrl : string // URL du serveur Jellyfin (ex: http://jellyfin:8096) jellyfinAdminToken : string // Token admin Jellyfin pour la sync } @@ -27,7 +27,7 @@ const defaults: Settings = { autoImport : true, devMode : false, deleteTorrentOnMove: false, - requestAutoImport : false, + requestAutoDownloadUsers: [], jellyfinUrl : '', jellyfinAdminToken : '', } diff --git a/src/views/settings/UsersView.vue b/src/views/settings/UsersView.vue index 5e0a73d..f905f10 100644 --- a/src/views/settings/UsersView.vue +++ b/src/views/settings/UsersView.vue @@ -94,6 +94,61 @@ + +
+
+

Téléchargement automatique

+

+ Quand une demande est approuvée, lancer automatiquement le téléchargement pour les utilisateurs sélectionnés. +

+
+ +
+ + + + +
+ + + + +

Paramètre sauvegardé.

+
+
+
@@ -203,6 +258,12 @@ const users = ref([]) const invites = ref([]) const copied = ref(null) +// ── Téléchargement auto des demandes ────────────────────────── +const autoDownloadAll = ref(false) +const autoDownloadUserIds = ref([]) +const autoDownloadSaved = ref(false) +let autoDownloadTimer: ReturnType | null = null + // ── Modals ──────────────────────────────────────────────────── const userModal = ref<{ mode : 'create' | 'edit' @@ -233,7 +294,47 @@ async function loadInvites() { if (res.ok) invites.value = await res.json() } -onMounted(() => { loadUsers(); loadInvites() }) +async function loadAutoDownloadSetting() { + const res = await fetch('/api/settings', { credentials: 'include' }) + if (!res.ok) return + const s = await res.json() + const val = s.requestAutoDownloadUsers ?? [] + if (val === 'all') { + autoDownloadAll.value = true + autoDownloadUserIds.value = [] + } else { + autoDownloadAll.value = false + autoDownloadUserIds.value = Array.isArray(val) ? val : [] + } +} + +async function saveAutoDownloadSetting() { + const value = autoDownloadAll.value ? 'all' : autoDownloadUserIds.value + await fetch('/api/settings', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + credentials: 'include', + body: JSON.stringify({ requestAutoDownloadUsers: value }), + }) + autoDownloadSaved.value = true + if (autoDownloadTimer) clearTimeout(autoDownloadTimer) + autoDownloadTimer = setTimeout(() => { autoDownloadSaved.value = false }, 2000) +} + +function toggleAutoDownloadAll(e: Event) { + autoDownloadAll.value = (e.target as HTMLInputElement).checked + if (autoDownloadAll.value) autoDownloadUserIds.value = [] + saveAutoDownloadSetting() +} + +function toggleAutoDownloadUser(userId: string) { + const idx = autoDownloadUserIds.value.indexOf(userId) + if (idx >= 0) autoDownloadUserIds.value.splice(idx, 1) + else autoDownloadUserIds.value.push(userId) + saveAutoDownloadSetting() +} + +onMounted(() => { loadUsers(); loadInvites(); loadAutoDownloadSetting() }) // ── Users ───────────────────────────────────────────────────── function openCreateUser() {