refacto: réécriture des textes, messages et commentaires

This commit is contained in:
ElPouki committed 2026-09-15 15:30:20 +02:00
1 parent 6a3cb21adf
commit 586eccbbb3
118 files changed
+1621 -2159

No files matched your search

+36 -36
View File
@@ -7,7 +7,7 @@ const router = Router()
const PLEX_TV_API = 'https://plex.tv/api/v2'
// ── Fetch avec bypass SSL pour les serveurs locaux ────────────────────────────
// ── Serveur Plex local : certificat non vérifié ───────────────────────────────
function getServerFetch(serverUrl: string) {
return (url: string, opts: any = {}) =>
undiciFetch(url, {
@@ -16,7 +16,6 @@ function getServerFetch(serverUrl: string) {
})
}
// ── Fetch vers plex.tv (certificat valide, pas besoin de bypass) ──────────────
async function plexFetch(url: string, options: RequestInit = {}): Promise<any> {
const res = await fetch(url, {
...options,
@@ -28,7 +27,10 @@ async function plexFetch(url: string, options: RequestInit = {}): Promise<any> {
...(options.headers ?? {}),
},
})
if (!res.ok) throw new Error(`Plex ${res.status}: ${await res.text()}`)
if (!res.ok) {
logger.debug('plex', `plex.tv HTTP ${res.status} : ${await res.text().catch(() => '')}`)
throw new Error(`Plex a répondu HTTP ${res.status}`)
}
const text = await res.text()
return text ? JSON.parse(text) : {}
}
@@ -43,7 +45,6 @@ function mapServers(resources: any[]) {
}))
}
// POST /api/plex/connect — auth plex.tv + liste serveurs
router.post('/plex/connect', requireAuth, async (req, res) => {
const { username, password, code } = req.body
if (!username || !password) { res.status(400).json({ error: 'Email et mot de passe requis' }); return }
@@ -56,23 +57,22 @@ router.post('/plex/connect', requireAuth, async (req, res) => {
body : params.toString(),
})
const token = authData.authToken ?? authData.user?.authToken
if (!token) throw new Error('Token non reçu')
if (!token) throw new Error('Plex n\'a pas renvoyé de jeton d\'accès')
const resources = await plexFetch('https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1&includeIPv6=1', { headers: { 'X-Plex-Token': token } })
const servers = mapServers(resources)
logger.info('plex', `Auth réussie pour ${username} — ${servers.length} serveur(s)`)
logger.info('plex', `Connexion Plex réussie pour ${username} (${servers.length} serveur(s))`)
res.json({ ok: true, token, servers })
} catch (err) {
const msg = err instanceof Error ? err.message : 'Erreur inconnue'
const msg = err instanceof Error ? err.message : 'Erreur inattendue, consultez les journaux'
if (msg.includes('401')) {
res.status(401).json({ error: '2FA requis ou identifiants incorrects', requires2FA: true })
res.status(401).json({ error: 'Identifiants incorrects, ou code de validation en deux étapes requis', requires2FA: true })
} else {
logger.error('plex', `Auth échouée : ${msg}`)
res.status(401).json({ error: 'Authentification échouée — vérifiez vos identifiants' })
logger.error('plex', `Échec de l'authentification Plex : ${msg}`)
res.status(401).json({ error: 'Échec de l\'authentification : vérifiez vos identifiants' })
}
}
})
// POST /api/plex/oauth/start — démarre le flow OAuth
router.post('/plex/oauth/start', requireAuth, async (_req, res) => {
try {
const data = await plexFetch(`${PLEX_TV_API}/pins`, {
@@ -82,18 +82,17 @@ router.post('/plex/oauth/start', requireAuth, async (_req, res) => {
})
const pinId = data.id
const pinCode = data.code
if (!pinId || !pinCode) throw new Error('Pin non reçu')
if (!pinId || !pinCode) throw new Error('Plex n\'a pas renvoyé de code PIN')
const authUrl = `https://app.plex.tv/auth#?clientID=fankarr&code=${pinCode}&context%5Bdevice%5D%5Bproduct%5D=FanKarr&forwardUrl=https%3A%2F%2Fplex.tv`
logger.info('plex', `OAuth démarré — pinId ${pinId}`)
logger.info('plex', `Connexion Plex démarrée (PIN ${pinId})`)
res.json({ ok: true, pinId, pinCode, authUrl })
} catch (err) {
const msg = err instanceof Error ? err.message : 'Erreur'
logger.error('plex', `OAuth start échoué : ${msg}`)
const msg = err instanceof Error ? err.message : 'Erreur inattendue, consultez les journaux'
logger.error('plex', `Échec du démarrage de la connexion Plex : ${msg}`)
res.status(500).json({ error: msg })
}
})
// GET /api/plex/oauth/poll/:pinId — vérifie si l'OAuth est complété
router.get('/plex/oauth/poll/:pinId', requireAuth, async (req, res) => {
const pinId = String(req.params.pinId)
try {
@@ -102,22 +101,20 @@ router.get('/plex/oauth/poll/:pinId', requireAuth, async (req, res) => {
if (!token) { res.json({ ok: false, pending: true }); return }
const resources = await plexFetch('https://plex.tv/api/v2/resources?includeHttps=1&includeRelay=1&includeIPv6=1', { headers: { 'X-Plex-Token': token } })
const servers = mapServers(resources)
logger.info('plex', `OAuth complété — ${servers.length} serveur(s)`)
logger.info('plex', `Connexion Plex réussie (${servers.length} serveur(s))`)
res.json({ ok: true, pending: false, token, servers })
} catch (err) {
const msg = err instanceof Error ? err.message : 'Erreur'
const msg = err instanceof Error ? err.message : 'Erreur inattendue, consultez les journaux'
res.status(500).json({ error: msg })
}
})
// POST /api/plex/setup — enregistre l'agent Fankai + crée la bibliothèque
router.post('/plex/setup', requireAuth, async (req, res) => {
const { token, serverUrl, libraryName, libraryPath } = req.body
if (!token || !serverUrl || !libraryName || !libraryPath) {
res.status(400).json({ error: 'token, serverUrl, libraryName, libraryPath requis' }); return
res.status(400).json({ error: 'Jeton Plex, serveur, nom et dossier de la bibliothèque requis' }); return
}
// Fetch avec SSL bypass pour les appels vers le serveur Plex local
const serverFetch = getServerFetch(serverUrl)
const headers: Record<string, string> = { 'X-Plex-Token': token, 'Accept': 'application/json' }
@@ -127,7 +124,7 @@ router.post('/plex/setup', requireAuth, async (req, res) => {
let groupId: string | null = null
let agentSetupOk = false
// ── Étape 1 : Enregistrer le provider Fankai ─────────────
// ── Étape 1 : enregistrer l'agent Fankai ─────────────────
try {
const providersRes = await serverFetch(`${serverUrl}/media/providers/metadata`, { headers })
if (providersRes.ok) {
@@ -140,7 +137,7 @@ router.post('/plex/setup', requireAuth, async (req, res) => {
}
if (provider) {
agentIdentifier = provider.identifier ?? agentIdentifier
steps.push({ step: 'provider', ok: true, message: `Provider enregistré (${agentIdentifier})` })
steps.push({ step: 'provider', ok: true, message: `Agent Fankai enregistré (${agentIdentifier})` })
}
const groupsRes = await serverFetch(`${serverUrl}/media/providers/metadata/group`, { headers })
if (groupsRes.ok) {
@@ -156,22 +153,22 @@ router.post('/plex/setup', requireAuth, async (req, res) => {
}
if (group) {
groupId = String(group.id ?? '')
steps.push({ step: 'group', ok: true, message: `Groupe d'agents créé (ID: ${groupId})` })
steps.push({ step: 'group', ok: true, message: `Groupe d'agents prêt (ID : ${groupId})` })
agentSetupOk = true
}
}
} else {
const status = providersRes.status
steps.push({ step: 'agent', ok: false, message: `Agent non configuré (HTTP ${status} — Plex < 1.43 ?) — setup manuel requis` })
logger.warn('plex', `Setup agent Fankai — HTTP ${status} depuis ${serverUrl}`)
steps.push({ step: 'agent', ok: false, message: `Agent Fankai non configuré (HTTP ${status}, Plex antérieur à 1.43 ?) : configuration manuelle nécessaire` })
logger.warn('plex', `Configuration de l'agent Fankai : HTTP ${status} depuis ${serverUrl}`)
}
} catch (err) {
const msg = err instanceof Error ? err.message : 'Erreur'
steps.push({ step: 'agent', ok: false, message: `Agent non configuré — setup manuel requis` })
logger.warn('plex', `Setup agent Fankai échoué : ${msg}`)
const msg = err instanceof Error ? err.message : 'Erreur inattendue, consultez les journaux'
steps.push({ step: 'agent', ok: false, message: `Agent Fankai non configuré : configuration manuelle nécessaire` })
logger.warn('plex', `Échec de la configuration de l'agent Fankai : ${msg}`)
}
// ── Étape 2 : Créer la bibliothèque ──────────────────────
// ── Étape 2 : créer la bibliothèque ──────────────────────
try {
const params = new URLSearchParams({
type : 'show',
@@ -183,14 +180,17 @@ router.post('/plex/setup', requireAuth, async (req, res) => {
})
if (groupId) params.set('metadataAgentProviderGroupId', groupId)
const libRes = await serverFetch(`${serverUrl}/library/sections?${params}`, { method: 'POST', headers })
if (!libRes.ok) throw new Error(`HTTP ${libRes.status}: ${await libRes.text()}`)
steps.push({ step: 'library', ok: true, message: `Bibliothèque "${libraryName}" créée` })
logger.info('plex', `Bibliothèque "${libraryName}" créée sur ${serverUrl}`)
if (!libRes.ok) {
logger.debug('plex', `Création de bibliothèque HTTP ${libRes.status} : ${await libRes.text().catch(() => '')}`)
throw new Error(`le serveur Plex a répondu HTTP ${libRes.status}`)
}
steps.push({ step: 'library', ok: true, message: `Bibliothèque « ${libraryName} » créée` })
logger.info('plex', `Bibliothèque « ${libraryName} » créée sur ${serverUrl}`)
res.json({ ok: true, agentSetupOk, steps, manualSetup: !agentSetupOk })
} catch (err) {
const msg = err instanceof Error ? err.message : 'Erreur'
steps.push({ step: 'library', ok: false, message: `Création bibliothèque échouée : ${msg}` })
logger.error('plex', `Création bibliothèque échouée : ${msg}`)
const msg = err instanceof Error ? err.message : 'Erreur inattendue, consultez les journaux'
steps.push({ step: 'library', ok: false, message: `Échec de la création de la bibliothèque : ${msg}` })
logger.error('plex', `Échec de la création de la bibliothèque : ${msg}`)
res.status(500).json({ ok: false, steps, error: msg })
}
})