trash_compare_profile
Compare your quality profile against TRaSH Guides recommendations to identify missing custom formats, scoring differences, and quality settings adjustments.
Instructions
Compare your quality profile against TRaSH Guides recommendations. Shows missing custom formats, scoring differences, and quality settings. Requires the corresponding *arr service to be configured.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| service | Yes | Which service | |
| profileId | Yes | Your quality profile ID to compare | |
| trashProfile | Yes | TRaSH profile name to compare against |
Implementation Reference
- src/index.ts:847-869 (registration)Tool registration: defines the 'trash_compare_profile' tool with its input schema (service, profileId, trashProfile). Listed among TRaSH Guides tools (always available).
{ name: "trash_compare_profile", description: "Compare your quality profile against TRaSH Guides recommendations. Shows missing custom formats, scoring differences, and quality settings. Requires the corresponding *arr service to be configured.", inputSchema: { type: "object" as const, properties: { service: { type: "string", enum: ["radarr", "sonarr"], description: "Which service", }, profileId: { type: "number", description: "Your quality profile ID to compare", }, trashProfile: { type: "string", description: "TRaSH profile name to compare against", }, }, required: ["service", "profileId", "trashProfile"], }, }, - src/index.ts:2219-2335 (handler)Handler: the switch-case handler for 'trash_compare_profile'. Fetches the user's quality profile from the configured *arr service via client.getQualityProfiles() and the TRaSH reference profile via trashClient.getProfile(), then compares their allowed qualities and custom formats, returning matching, missing, and extra items plus recommendations.
case "trash_compare_profile": { const { service, profileId, trashProfile } = args as { service: TrashService; profileId: number; trashProfile: string; }; // Get client const client = service === 'radarr' ? clients.radarr : clients.sonarr; if (!client) { return { content: [{ type: "text", text: JSON.stringify({ error: `${service} not configured. Cannot compare profiles.` }, null, 2), }], isError: true, }; } // Fetch both profiles const [userProfiles, trashProfileData] = await Promise.all([ client.getQualityProfiles(), trashClient.getProfile(service, trashProfile), ]); const userProfile = userProfiles.find(p => p.id === profileId); if (!userProfile) { return { content: [{ type: "text", text: JSON.stringify({ error: `Profile ID ${profileId} not found`, availableProfiles: userProfiles.map(p => ({ id: p.id, name: p.name })), }, null, 2), }], isError: true, }; } if (!trashProfileData) { return { content: [{ type: "text", text: JSON.stringify({ error: `TRaSH profile '${trashProfile}' not found`, hint: "Use trash_list_profiles to see available profiles", }, null, 2), }], isError: true, }; } // Compare qualities const userQualities = new Set<string>( userProfile.items .filter(i => i.allowed) .map(i => i.quality?.name || i.name) .filter((n): n is string => n !== undefined) ); const trashQualities = new Set<string>( trashProfileData.items .filter(i => i.allowed) .map(i => i.name) ); const qualityComparison = { matching: [...userQualities].filter(q => trashQualities.has(q)), missingFromYours: [...trashQualities].filter(q => !userQualities.has(q)), extraInYours: [...userQualities].filter(q => !trashQualities.has(q)), }; // Compare custom formats const userCFNames = new Set( (userProfile.formatItems || []) .filter(f => f.score !== 0) .map(f => f.name) ); const trashCFNames = new Set(Object.keys(trashProfileData.formatItems || {})); const cfComparison = { matching: [...userCFNames].filter(cf => trashCFNames.has(cf)), missingFromYours: [...trashCFNames].filter(cf => !userCFNames.has(cf)), extraInYours: [...userCFNames].filter(cf => !trashCFNames.has(cf)), }; return { content: [{ type: "text", text: JSON.stringify({ yourProfile: { name: userProfile.name, id: userProfile.id, upgradeAllowed: userProfile.upgradeAllowed, cutoff: userProfile.cutoff, }, trashProfile: { name: trashProfileData.name, upgradeAllowed: trashProfileData.upgradeAllowed, cutoff: trashProfileData.cutoff, }, qualityComparison, customFormatComparison: cfComparison, recommendations: [ ...(qualityComparison.missingFromYours.length > 0 ? [`Enable these qualities: ${qualityComparison.missingFromYours.join(', ')}`] : []), ...(cfComparison.missingFromYours.length > 0 ? [`Add these custom formats: ${cfComparison.missingFromYours.slice(0, 5).join(', ')}${cfComparison.missingFromYours.length > 5 ? ` and ${cfComparison.missingFromYours.length - 5} more` : ''}`] : []), ...(userProfile.upgradeAllowed !== trashProfileData.upgradeAllowed ? [`Set upgradeAllowed to ${trashProfileData.upgradeAllowed}`] : []), ], }, null, 2), }], }; } - src/trash-client.ts:259-273 (helper)Helper: TrashClient.getProfile() fetches a TRaSH quality profile by service and name from the GitHub RAW URLs, with caching.
async getProfile(service: TrashService, profileName: string): Promise<TrashQualityProfile | null> { const key = `${service}/${profileName}`; const cached = cache.getProfile(key); if (cached) return cached; try { const profile = await fetchJSON<TrashQualityProfile>( `${TRASH_BASE_URL}/${service}/quality-profiles/${profileName}.json` ); cache.setProfile(key, profile); return profile; } catch { return null; } } - src/arr-client.ts:472-474 (helper)Helper: ArrClient.getQualityProfiles() fetches the user's quality profiles from the configured *arr application via its REST API.
async getQualityProfiles(): Promise<QualityProfile[]> { return this.request<QualityProfile[]>('/qualityprofile'); }