refactor: Phase 1 code cleanup - constants, logging, and repository organization
This commit is contained in:
@@ -479,5 +479,100 @@ module.exports = function(ctx, helpers) {
|
||||
});
|
||||
}, 'arr-auto-setup'));
|
||||
|
||||
// Fetch quality profiles from an arr service (Radarr/Sonarr)
|
||||
router.get('/arr/quality-profiles', ctx.asyncHandler(async (req, res) => {
|
||||
const { service, url, apiKey } = req.query;
|
||||
|
||||
if (!service || !['radarr', 'sonarr'].includes(service)) {
|
||||
return ctx.errorResponse(res, 400, 'Service must be radarr or sonarr');
|
||||
}
|
||||
|
||||
// Resolve API key: from query param, or from stored credentials
|
||||
let resolvedKey = apiKey;
|
||||
let resolvedUrl = url;
|
||||
|
||||
if (!resolvedKey) {
|
||||
resolvedKey = await ctx.credentialManager.retrieve(`arr.${service}.apikey`);
|
||||
}
|
||||
if (!resolvedKey) {
|
||||
resolvedKey = await ctx.credentialManager.retrieve(`service.${service}.apikey`);
|
||||
}
|
||||
|
||||
if (!resolvedUrl) {
|
||||
const metadata = await ctx.credentialManager.getMetadata(`arr.${service}.apikey`);
|
||||
resolvedUrl = metadata?.url;
|
||||
}
|
||||
if (!resolvedUrl) {
|
||||
try {
|
||||
const services = await ctx.servicesStateManager.read();
|
||||
const svcList = Array.isArray(services) ? services : services.services || [];
|
||||
const found = svcList.find(s => s.id === service);
|
||||
if (found?.externalUrl) resolvedUrl = found.externalUrl;
|
||||
else if (found?.url) resolvedUrl = found.url;
|
||||
} catch (e) { /* ignore */ }
|
||||
}
|
||||
|
||||
if (!resolvedKey || !resolvedUrl) {
|
||||
return ctx.errorResponse(res, 400, 'Could not resolve API key or URL for this service');
|
||||
}
|
||||
|
||||
const baseUrl = resolvedUrl.replace(/\/+$/, '');
|
||||
|
||||
try {
|
||||
const profilesRes = await ctx.fetchT(`${baseUrl}/api/v3/qualityprofile`, {
|
||||
headers: { 'X-Api-Key': resolvedKey, 'Accept': 'application/json' },
|
||||
signal: AbortSignal.timeout(10000)
|
||||
});
|
||||
|
||||
if (!profilesRes.ok) {
|
||||
return ctx.errorResponse(res, profilesRes.status === 401 ? 401 : 502,
|
||||
profilesRes.status === 401 ? 'Invalid API key' : `Failed to fetch profiles (HTTP ${profilesRes.status})`);
|
||||
}
|
||||
|
||||
const profiles = await profilesRes.json();
|
||||
const mapped = profiles.map(p => ({ id: p.id, name: p.name }));
|
||||
|
||||
// Load stored profile preference
|
||||
const metadata = await ctx.credentialManager.getMetadata(`arr.${service}.apikey`);
|
||||
const storedProfileId = metadata?.qualityProfileId || null;
|
||||
|
||||
res.json({ success: true, profiles: mapped, storedProfileId });
|
||||
} catch (e) {
|
||||
if (e.cause?.code === 'ECONNREFUSED') {
|
||||
return ctx.errorResponse(res, 502, 'Connection refused — is the service running?');
|
||||
}
|
||||
if (e.name === 'AbortError') {
|
||||
return ctx.errorResponse(res, 504, 'Connection timeout');
|
||||
}
|
||||
return ctx.errorResponse(res, 500, e.message);
|
||||
}
|
||||
}, 'arr-quality-profiles'));
|
||||
|
||||
// Save quality profile preference (without re-storing API key)
|
||||
router.post('/arr/quality-profiles', ctx.asyncHandler(async (req, res) => {
|
||||
const { service, qualityProfileId, qualityProfileName } = req.body;
|
||||
|
||||
if (!service || !['radarr', 'sonarr'].includes(service)) {
|
||||
return ctx.errorResponse(res, 400, 'Service must be radarr or sonarr');
|
||||
}
|
||||
if (!qualityProfileId) {
|
||||
return ctx.errorResponse(res, 400, 'qualityProfileId required');
|
||||
}
|
||||
|
||||
const credKey = `arr.${service}.apikey`;
|
||||
const existing = await ctx.credentialManager.getMetadata(credKey);
|
||||
|
||||
if (!existing) {
|
||||
return ctx.errorResponse(res, 404, 'No stored credentials for this service');
|
||||
}
|
||||
|
||||
// Merge quality profile into existing metadata
|
||||
existing.qualityProfileId = qualityProfileId;
|
||||
existing.qualityProfileName = qualityProfileName || null;
|
||||
await ctx.credentialManager.storeMetadata(credKey, existing);
|
||||
|
||||
res.json({ success: true, message: `Quality profile updated for ${service}` });
|
||||
}, 'arr-quality-profile-save'));
|
||||
|
||||
return router;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user