'use strict'; const conf = require('>/conf'); // Resolution rank so we can compare "what you own" against a candidate release. function rankFromWidth(w){ w = Number(w) || 0; if(w >= 3000) return 4; // 4k if(w >= 1700) return 3; // 1080p if(w >= 1000) return 2; // 720p if(w > 0) return 1; // sd return 0; } function rankFromLabel(label){ label = String(label || '').toLowerCase(); if(/2160|4k|uhd/.test(label)) return 4; if(label.includes('1080')) return 3; if(label.includes('720')) return 2; if(label.includes('480')) return 1; return 0; } function labelFromRank(rank){ return ['', '480p', '720p', '1080p', '4k'][rank] || ''; } async function embyGet(pathAndQuery){ let sep = pathAndQuery.includes('?') ? '&' : '?'; let res = await fetch(`${conf.emby.url}${pathAndQuery}${sep}api_key=${conf.emby.apiKey}`); if(!res.ok) throw new Error(`Emby ${res.status}`); return await res.json(); } // Is this movie already in the library, and at what best quality? Never throws — an // unreachable Emby just means "unknown", so search still works. async function movieInLibrary(tmdbId){ try{ let data = await embyGet(`/Items?Recursive=true&IncludeItemTypes=Movie&AnyProviderIdEquals=tmdb.${tmdbId}&Fields=Width`); let items = data.Items || []; if(!items.length) return { owned: false, rank: 0, quality: '' }; let rank = Math.max(...items.map(i => rankFromWidth(i.Width))); return { owned: true, rank, quality: labelFromRank(rank), count: items.length }; }catch(error){ return { owned: false, rank: 0, quality: '', unknown: true }; } } // Which episodes of a series are already present, grouped by season( season -> count). async function seriesInventory(tmdbId){ try{ let s = await embyGet(`/Items?Recursive=true&IncludeItemTypes=Series&AnyProviderIdEquals=tmdb.${tmdbId}&Fields=ProviderIds`); let series = (s.Items || [])[0]; if(!series) return { owned: false, have: {} }; let ep = await embyGet(`/Shows/${series.Id}/Episodes`); let sets = {}; for(let e of ep.Items || []){ let sn = e.ParentIndexNumber, en = e.IndexNumber; if(sn == null || en == null || sn === 0) continue; // skip specials (sets[sn] = sets[sn] || new Set()).add(en); } let have = {}; for(let sn of Object.keys(sets)) have[sn] = sets[sn].size; return { owned: true, seriesId: series.Id, have }; }catch(error){ return { owned: false, have: {}, unknown: true }; } } module.exports = { movieInLibrary, seriesInventory, rankFromWidth, rankFromLabel, labelFromRank };