mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-21 00:32:04 +00:00
KITSU id prefix fix
This commit is contained in:
parent
4367be97f8
commit
a0d33be096
3 changed files with 93 additions and 17 deletions
|
|
@ -868,6 +868,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
}
|
}
|
||||||
|
|
||||||
let hasStreamResource = false;
|
let hasStreamResource = false;
|
||||||
|
let supportsIdPrefix = false;
|
||||||
|
|
||||||
|
// Extract ID prefix from the ID
|
||||||
|
const idPrefix = id.split(':')[0];
|
||||||
|
|
||||||
for (const resource of addon.resources) {
|
for (const resource of addon.resources) {
|
||||||
// Check if the current element is a ResourceObject
|
// Check if the current element is a ResourceObject
|
||||||
|
|
@ -877,6 +881,14 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
Array.isArray(typedResource.types) &&
|
Array.isArray(typedResource.types) &&
|
||||||
typedResource.types.includes(type)) {
|
typedResource.types.includes(type)) {
|
||||||
hasStreamResource = true;
|
hasStreamResource = true;
|
||||||
|
|
||||||
|
// Check if this addon supports the ID prefix
|
||||||
|
if (Array.isArray(typedResource.idPrefixes)) {
|
||||||
|
supportsIdPrefix = typedResource.idPrefixes.includes(idPrefix);
|
||||||
|
} else {
|
||||||
|
// If no idPrefixes specified, assume it supports all prefixes
|
||||||
|
supportsIdPrefix = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -884,12 +896,19 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
else if (typeof resource === 'string' && resource === 'stream' && addon.types) {
|
else if (typeof resource === 'string' && resource === 'stream' && addon.types) {
|
||||||
if (Array.isArray(addon.types) && addon.types.includes(type)) {
|
if (Array.isArray(addon.types) && addon.types.includes(type)) {
|
||||||
hasStreamResource = true;
|
hasStreamResource = true;
|
||||||
|
// For simple string resources, check addon-level idPrefixes
|
||||||
|
if (addon.idPrefixes && Array.isArray(addon.idPrefixes)) {
|
||||||
|
supportsIdPrefix = addon.idPrefixes.includes(idPrefix);
|
||||||
|
} else {
|
||||||
|
// If no idPrefixes specified, assume it supports all prefixes
|
||||||
|
supportsIdPrefix = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasStreamResource;
|
return hasStreamResource && supportsIdPrefix;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Initialize scraper statuses for tracking
|
// Initialize scraper statuses for tracking
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,11 @@ import { colors } from '../styles';
|
||||||
const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
|
const ANDROID_STATUSBAR_HEIGHT = StatusBar.currentHeight || 0;
|
||||||
|
|
||||||
// Trakt configuration
|
// Trakt configuration
|
||||||
const TRAKT_CLIENT_ID = 'd7271f7dd57d8aeff63e99408610091a6b1ceac3b3a541d1031a48f429b7942c';
|
const TRAKT_CLIENT_ID = process.env.EXPO_PUBLIC_TRAKT_CLIENT_ID as string;
|
||||||
|
|
||||||
|
if (!TRAKT_CLIENT_ID) {
|
||||||
|
throw new Error('Missing EXPO_PUBLIC_TRAKT_CLIENT_ID environment variable');
|
||||||
|
}
|
||||||
const discovery = {
|
const discovery = {
|
||||||
authorizationEndpoint: 'https://trakt.tv/oauth/authorize',
|
authorizationEndpoint: 'https://trakt.tv/oauth/authorize',
|
||||||
tokenEndpoint: 'https://api.trakt.tv/oauth/token',
|
tokenEndpoint: 'https://api.trakt.tv/oauth/token',
|
||||||
|
|
|
||||||
|
|
@ -926,47 +926,72 @@ class StremioService {
|
||||||
// Map Stremio types to local scraper types
|
// Map Stremio types to local scraper types
|
||||||
const scraperType = type === 'series' ? 'tv' : type;
|
const scraperType = type === 'series' ? 'tv' : type;
|
||||||
|
|
||||||
// Parse the Stremio ID to extract IMDb ID and season/episode info
|
// Parse the Stremio ID to extract ID and season/episode info
|
||||||
let tmdbId: string | null = null;
|
let tmdbId: string | null = null;
|
||||||
let season: number | undefined = undefined;
|
let season: number | undefined = undefined;
|
||||||
let episode: number | undefined = undefined;
|
let episode: number | undefined = undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const idParts = id.split(':');
|
const idParts = id.split(':');
|
||||||
let baseImdbId: string;
|
let baseId: string;
|
||||||
|
let idType: 'imdb' | 'kitsu' | 'tmdb' = 'imdb';
|
||||||
|
|
||||||
// Handle different episode ID formats
|
// Handle different episode ID formats
|
||||||
if (idParts[0] === 'series') {
|
if (idParts[0] === 'series') {
|
||||||
// Format: series:imdbId:season:episode
|
// Format: series:imdbId:season:episode or series:kitsu:7442:season:episode
|
||||||
baseImdbId = idParts[1];
|
baseId = idParts[1];
|
||||||
if (scraperType === 'tv' && idParts.length >= 4) {
|
if (scraperType === 'tv' && idParts.length >= 4) {
|
||||||
season = parseInt(idParts[2], 10);
|
season = parseInt(idParts[2], 10);
|
||||||
episode = parseInt(idParts[3], 10);
|
episode = parseInt(idParts[3], 10);
|
||||||
}
|
}
|
||||||
|
// Check if it's a kitsu ID
|
||||||
|
if (idParts[1] === 'kitsu') {
|
||||||
|
idType = 'kitsu';
|
||||||
|
baseId = idParts[2]; // kitsu:7442:season:episode -> baseId = 7442
|
||||||
|
if (scraperType === 'tv' && idParts.length >= 5) {
|
||||||
|
season = parseInt(idParts[3], 10);
|
||||||
|
episode = parseInt(idParts[4], 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (idParts[0].startsWith('tt')) {
|
} else if (idParts[0].startsWith('tt')) {
|
||||||
// Format: imdbId:season:episode (direct IMDb ID)
|
// Format: imdbId:season:episode (direct IMDb ID)
|
||||||
baseImdbId = idParts[0];
|
baseId = idParts[0];
|
||||||
|
idType = 'imdb';
|
||||||
if (scraperType === 'tv' && idParts.length >= 3) {
|
if (scraperType === 'tv' && idParts.length >= 3) {
|
||||||
season = parseInt(idParts[1], 10);
|
season = parseInt(idParts[1], 10);
|
||||||
episode = parseInt(idParts[2], 10);
|
episode = parseInt(idParts[2], 10);
|
||||||
}
|
}
|
||||||
|
} else if (idParts[0] === 'kitsu') {
|
||||||
|
// Format: kitsu:7442:season:episode (direct Kitsu ID)
|
||||||
|
baseId = idParts[1];
|
||||||
|
idType = 'kitsu';
|
||||||
|
if (scraperType === 'tv' && idParts.length >= 4) {
|
||||||
|
season = parseInt(idParts[2], 10);
|
||||||
|
episode = parseInt(idParts[3], 10);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fallback: assume first part is the ID
|
// Fallback: assume first part is the ID
|
||||||
baseImdbId = idParts[0];
|
baseId = idParts[0];
|
||||||
if (scraperType === 'tv' && idParts.length >= 3) {
|
if (scraperType === 'tv' && idParts.length >= 3) {
|
||||||
season = parseInt(idParts[1], 10);
|
season = parseInt(idParts[1], 10);
|
||||||
episode = parseInt(idParts[2], 10);
|
episode = parseInt(idParts[2], 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert IMDb ID to TMDB ID using TMDBService
|
// Only try to convert to TMDB ID for IMDb IDs (local scrapers need TMDB)
|
||||||
const tmdbService = TMDBService.getInstance();
|
if (idType === 'imdb') {
|
||||||
const tmdbIdNumber = await tmdbService.findTMDBIdByIMDB(baseImdbId);
|
const tmdbService = TMDBService.getInstance();
|
||||||
|
const tmdbIdNumber = await tmdbService.findTMDBIdByIMDB(baseId);
|
||||||
if (tmdbIdNumber) {
|
|
||||||
tmdbId = tmdbIdNumber.toString();
|
if (tmdbIdNumber) {
|
||||||
|
tmdbId = tmdbIdNumber.toString();
|
||||||
|
} else {
|
||||||
|
return; // Skip local scrapers if we can't convert the ID
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return; // Skip local scrapers if we can't convert the ID
|
// For kitsu IDs, skip local scrapers as they don't support kitsu
|
||||||
|
logger.log('🔧 [getStreams] Skipping local scrapers for kitsu ID:', baseId);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return; // Skip local scrapers if ID parsing fails
|
return; // Skip local scrapers if ID parsing fails
|
||||||
|
|
@ -1008,6 +1033,11 @@ class StremioService {
|
||||||
logger.log(`📋 [getStreams] Checking addon ${addon.id} resources:`, JSON.stringify(addon.resources));
|
logger.log(`📋 [getStreams] Checking addon ${addon.id} resources:`, JSON.stringify(addon.resources));
|
||||||
|
|
||||||
let hasStreamResource = false;
|
let hasStreamResource = false;
|
||||||
|
let supportsIdPrefix = false;
|
||||||
|
|
||||||
|
// Extract ID prefix from the ID
|
||||||
|
const idPrefix = id.split(':')[0];
|
||||||
|
logger.log(`🔍 [getStreams] Checking if addon supports ID prefix: ${idPrefix}`);
|
||||||
|
|
||||||
// Iterate through the resources array, checking each element
|
// Iterate through the resources array, checking each element
|
||||||
for (const resource of addon.resources) {
|
for (const resource of addon.resources) {
|
||||||
|
|
@ -1018,6 +1048,16 @@ class StremioService {
|
||||||
Array.isArray(typedResource.types) &&
|
Array.isArray(typedResource.types) &&
|
||||||
typedResource.types.includes(type)) {
|
typedResource.types.includes(type)) {
|
||||||
hasStreamResource = true;
|
hasStreamResource = true;
|
||||||
|
|
||||||
|
// Check if this addon supports the ID prefix
|
||||||
|
if (Array.isArray(typedResource.idPrefixes)) {
|
||||||
|
supportsIdPrefix = typedResource.idPrefixes.includes(idPrefix);
|
||||||
|
logger.log(`🔍 [getStreams] Addon ${addon.id} supports prefixes: ${typedResource.idPrefixes.join(', ')}`);
|
||||||
|
} else {
|
||||||
|
// If no idPrefixes specified, assume it supports all prefixes
|
||||||
|
supportsIdPrefix = true;
|
||||||
|
logger.log(`🔍 [getStreams] Addon ${addon.id} has no prefix restrictions, assuming support`);
|
||||||
|
}
|
||||||
break; // Found the stream resource object, no need to check further
|
break; // Found the stream resource object, no need to check further
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1025,18 +1065,31 @@ class StremioService {
|
||||||
else if (typeof resource === 'string' && resource === 'stream' && addon.types) {
|
else if (typeof resource === 'string' && resource === 'stream' && addon.types) {
|
||||||
if (Array.isArray(addon.types) && addon.types.includes(type)) {
|
if (Array.isArray(addon.types) && addon.types.includes(type)) {
|
||||||
hasStreamResource = true;
|
hasStreamResource = true;
|
||||||
|
// For simple string resources, check addon-level idPrefixes
|
||||||
|
if (addon.idPrefixes && Array.isArray(addon.idPrefixes)) {
|
||||||
|
supportsIdPrefix = addon.idPrefixes.includes(idPrefix);
|
||||||
|
logger.log(`🔍 [getStreams] Addon ${addon.id} supports prefixes: ${addon.idPrefixes.join(', ')}`);
|
||||||
|
} else {
|
||||||
|
// If no idPrefixes specified, assume it supports all prefixes
|
||||||
|
supportsIdPrefix = true;
|
||||||
|
logger.log(`🔍 [getStreams] Addon ${addon.id} has no prefix restrictions, assuming support`);
|
||||||
|
}
|
||||||
break; // Found the simple stream resource string and type support
|
break; // Found the simple stream resource string and type support
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const canHandleRequest = hasStreamResource && supportsIdPrefix;
|
||||||
|
|
||||||
if (!hasStreamResource) {
|
if (!hasStreamResource) {
|
||||||
logger.log(`❌ [getStreams] Addon ${addon.id} does not support streaming ${type}`);
|
logger.log(`❌ [getStreams] Addon ${addon.id} does not support streaming ${type}`);
|
||||||
|
} else if (!supportsIdPrefix) {
|
||||||
|
logger.log(`❌ [getStreams] Addon ${addon.id} supports ${type} but not ID prefix ${idPrefix}`);
|
||||||
} else {
|
} else {
|
||||||
logger.log(`✅ [getStreams] Addon ${addon.id} supports streaming ${type}`);
|
logger.log(`✅ [getStreams] Addon ${addon.id} supports streaming ${type} with prefix ${idPrefix}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasStreamResource;
|
return canHandleRequest;
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.log('📊 [getStreams] Stream capable addons:', streamAddons.map(a => a.id));
|
logger.log('📊 [getStreams] Stream capable addons:', streamAddons.map(a => a.id));
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue