Compare commits

..

3 Commits

Author SHA1 Message Date
0xsysr3ll
b46a7d8804 fix(availability-sync): refine 4k media availability checks for both movies and TV shows
Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me>
2026-01-13 23:37:34 +01:00
0xsysr3ll
844f86d41d fix(availability-sync): use media resolution to determine 4k availability
Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me>
2026-01-13 22:31:56 +01:00
0xsysr3ll
d9aceee3f6 feat(availability-sync): added logging for 4K movie availability checks in Plex and Radarr
Signed-off-by: 0xsysr3ll <0xsysr3ll@pm.me>
2026-01-13 20:23:38 +01:00
3 changed files with 44 additions and 23 deletions

View File

@@ -97,10 +97,7 @@ app
// Register HTTP proxy
if (settings.network.proxy.enabled) {
await createCustomProxyAgent(
settings.network.proxy,
settings.network.forceIpv4First
);
await createCustomProxyAgent(settings.network.proxy);
}
// Migrate library types

View File

@@ -666,6 +666,16 @@ class AvailabilitySync {
): Promise<boolean> {
let existsInRadarr = false;
if (is4k && media.status4k === MediaStatus.AVAILABLE) {
logger.debug(
`Checking if 4K movie [TMDB ID ${media.tmdbId}] exists in Radarr`,
{
label: 'AvailabilitySync',
externalServiceId4k: media.externalServiceId4k,
}
);
}
// Check for availability in all of the available radarr servers
// If any find the media, we will assume the media exists
for (const server of this.radarrServers.filter(
@@ -870,6 +880,32 @@ class AvailabilitySync {
this.plexSeasonsCache[ratingKey4k] =
await this.plexClient?.getChildrenMetadata(ratingKey4k);
}
if (plexMedia) {
if (media.mediaType === 'movie') {
const has4kByWidth = plexMedia.Media?.some(
(mediaItem) => (mediaItem.width ?? 0) >= 2000
);
if (is4k) {
if (ratingKey === ratingKey4k || !has4kByWidth) {
plexMedia = undefined;
}
} else {
const hasNon4kByWidth = plexMedia.Media?.some(
(mediaItem) =>
(mediaItem.width ?? 0) < 2000 && (mediaItem.width ?? 0) > 0
);
if (!hasNon4kByWidth && has4kByWidth) {
plexMedia = undefined;
}
}
} else if (media.mediaType === 'tv' && is4k) {
if (ratingKey === ratingKey4k) {
plexMedia = undefined;
}
}
}
}
if (plexMedia) {

View File

@@ -11,14 +11,9 @@ export let requestInterceptorFunction: (
) => InternalAxiosRequestConfig;
export default async function createCustomProxyAgent(
proxySettings: ProxySettings,
forceIpv4First?: boolean
proxySettings: ProxySettings
) {
const defaultAgent = new Agent({
keepAliveTimeout: 5000,
connections: 50,
connect: forceIpv4First ? { family: 4 } : undefined,
});
const defaultAgent = new Agent({ keepAliveTimeout: 5000 });
const skipUrl = (url: string | URL) => {
const hostname =
@@ -72,23 +67,16 @@ export default async function createCustomProxyAgent(
uri: proxyUrl,
token,
keepAliveTimeout: 5000,
connections: 50,
connect: forceIpv4First ? { family: 4 } : undefined,
});
setGlobalDispatcher(proxyAgent.compose(noProxyInterceptor));
const agentOptions = {
axios.defaults.httpAgent = new HttpProxyAgent(proxyUrl, {
headers: token ? { 'proxy-authorization': token } : undefined,
keepAlive: true,
maxSockets: 50,
maxFreeSockets: 10,
timeout: 5000,
scheduling: 'lifo' as const,
family: forceIpv4First ? 4 : undefined,
};
axios.defaults.httpAgent = new HttpProxyAgent(proxyUrl, agentOptions);
axios.defaults.httpsAgent = new HttpsProxyAgent(proxyUrl, agentOptions);
});
axios.defaults.httpsAgent = new HttpsProxyAgent(proxyUrl, {
headers: token ? { 'proxy-authorization': token } : undefined,
});
requestInterceptorFunction = (config) => {
const url = config.baseURL