mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-01 05:04:33 +00:00
Merge pull request #692 from chrisk325/patch-29
fix unusual type content streams fetching, use addon provided type + minor fix to scrobbling + fix duplicate declaration in the Mal PR
This commit is contained in:
commit
56b292f79a
4 changed files with 54 additions and 19 deletions
|
|
@ -271,7 +271,6 @@ const AndroidVideoPlayer: React.FC = () => {
|
||||||
|
|
||||||
const nextEpisodeHook = useNextEpisode(type, season, episode, groupedEpisodes, (metadataResult as any)?.groupedEpisodes, episodeId);
|
const nextEpisodeHook = useNextEpisode(type, season, episode, groupedEpisodes, (metadataResult as any)?.groupedEpisodes, episodeId);
|
||||||
|
|
||||||
const currentTmdbId = (metadata as any)?.tmdbId || (metadata as any)?.external_ids?.tmdb_id;
|
|
||||||
|
|
||||||
const { segments: skipIntervals, outroSegment } = useSkipSegments({
|
const { segments: skipIntervals, outroSegment } = useSkipSegments({
|
||||||
imdbId: resolvedImdbId || (id?.startsWith('tt') ? id : undefined),
|
imdbId: resolvedImdbId || (id?.startsWith('tt') ? id : undefined),
|
||||||
|
|
|
||||||
|
|
@ -1576,7 +1576,8 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
let tmdbId;
|
let tmdbId;
|
||||||
let stremioId = id;
|
let stremioId = id;
|
||||||
// Use TMDB-resolved type if available — handles "other", "Movie", etc.
|
// Use TMDB-resolved type if available — handles "other", "Movie", etc.
|
||||||
let effectiveStreamType: string = resolvedTypeRef.current || normalizedType;
|
// Use metadata.type first (from addon meta response), then TMDB-resolved, then normalized
|
||||||
|
let effectiveStreamType: string = metadata?.type || resolvedTypeRef.current || normalizedType;
|
||||||
|
|
||||||
if (id.startsWith('tmdb:')) {
|
if (id.startsWith('tmdb:')) {
|
||||||
tmdbId = id.split(':')[1];
|
tmdbId = id.split(':')[1];
|
||||||
|
|
@ -1631,7 +1632,8 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
const allStremioAddons = await stremioService.getInstalledAddons();
|
const allStremioAddons = await stremioService.getInstalledAddons();
|
||||||
const localScrapers = await localScraperService.getInstalledScrapers();
|
const localScrapers = await localScraperService.getInstalledScrapers();
|
||||||
|
|
||||||
const requestedStreamType = type;
|
// Use the best available type — not raw type which may be "other"
|
||||||
|
const requestedStreamType = metadata?.type || resolvedTypeRef.current || normalizedType;
|
||||||
|
|
||||||
const pickEligibleStreamAddons = (requestType: string) =>
|
const pickEligibleStreamAddons = (requestType: string) =>
|
||||||
allStremioAddons.filter(addon => {
|
allStremioAddons.filter(addon => {
|
||||||
|
|
|
||||||
|
|
@ -309,14 +309,6 @@ export function useTraktAutosync(options: TraktAutosyncOptions) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip if session was already stopped (e.g. after background/pause).
|
|
||||||
// Without this, the fallback "force start" block inside handleProgressUpdate
|
|
||||||
// would fire a new /scrobble/start on the first periodic save after a remount,
|
|
||||||
// bypassing the hasStopped guard in handlePlaybackStart entirely.
|
|
||||||
if (hasStopped.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const rawProgress = (currentTime / duration) * 100;
|
const rawProgress = (currentTime / duration) * 100;
|
||||||
const progressPercent = Math.min(100, Math.max(0, rawProgress));
|
const progressPercent = Math.min(100, Math.max(0, rawProgress));
|
||||||
|
|
@ -340,6 +332,19 @@ export function useTraktAutosync(options: TraktAutosyncOptions) {
|
||||||
lastSyncTime.current = now;
|
lastSyncTime.current = now;
|
||||||
lastSyncProgress.current = progressPercent;
|
lastSyncProgress.current = progressPercent;
|
||||||
|
|
||||||
|
// If this update crossed the completion threshold, Trakt will have silently
|
||||||
|
// scrobbled it. Mark complete now so unmount/background don't fire a second
|
||||||
|
// /scrobble/stop above threshold and create a duplicate history entry.
|
||||||
|
if (progressPercent >= autosyncSettings.completionThreshold) {
|
||||||
|
isSessionComplete.current = true;
|
||||||
|
const ck = getContentKey(options);
|
||||||
|
const existing = recentlyStoppedSessions.get(ck);
|
||||||
|
if (existing) {
|
||||||
|
recentlyStoppedSessions.set(ck, { ...existing, isComplete: true, progress: progressPercent });
|
||||||
|
}
|
||||||
|
logger.log(`[TraktAutosync] Threshold reached via immediate progress update (${progressPercent.toFixed(1)}%), marking session complete`);
|
||||||
|
}
|
||||||
|
|
||||||
// Update local storage sync status
|
// Update local storage sync status
|
||||||
await storageService.updateTraktSyncStatus(
|
await storageService.updateTraktSyncStatus(
|
||||||
options.id,
|
options.id,
|
||||||
|
|
@ -375,6 +380,19 @@ export function useTraktAutosync(options: TraktAutosyncOptions) {
|
||||||
lastSyncTime.current = now;
|
lastSyncTime.current = now;
|
||||||
lastSyncProgress.current = progressPercent;
|
lastSyncProgress.current = progressPercent;
|
||||||
|
|
||||||
|
// If this periodic update crossed the completion threshold, Trakt will have
|
||||||
|
// silently scrobbled it. Mark complete now so unmount/background don't fire
|
||||||
|
// a second /scrobble/stop above threshold and create a duplicate history entry.
|
||||||
|
if (progressPercent >= autosyncSettings.completionThreshold) {
|
||||||
|
isSessionComplete.current = true;
|
||||||
|
const ck = getContentKey(options);
|
||||||
|
const existing = recentlyStoppedSessions.get(ck);
|
||||||
|
if (existing) {
|
||||||
|
recentlyStoppedSessions.set(ck, { ...existing, isComplete: true, progress: progressPercent });
|
||||||
|
}
|
||||||
|
logger.log(`[TraktAutosync] Threshold reached via progress update (${progressPercent.toFixed(1)}%), marking session complete to prevent duplicate scrobble`);
|
||||||
|
}
|
||||||
|
|
||||||
// Update local storage sync status
|
// Update local storage sync status
|
||||||
await storageService.updateTraktSyncStatus(
|
await storageService.updateTraktSyncStatus(
|
||||||
options.id,
|
options.id,
|
||||||
|
|
@ -385,7 +403,6 @@ export function useTraktAutosync(options: TraktAutosyncOptions) {
|
||||||
currentTime
|
currentTime
|
||||||
);
|
);
|
||||||
|
|
||||||
// Progress sync logging removed
|
|
||||||
logger.log(`[TraktAutosync] Trakt: Progress updated to ${progressPercent.toFixed(1)}%`);
|
logger.log(`[TraktAutosync] Trakt: Progress updated to ${progressPercent.toFixed(1)}%`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,12 +325,21 @@ async function searchAddonCatalog(
|
||||||
// meta addon by ID prefix matching. Setting it here causes 404s when two addons
|
// meta addon by ID prefix matching. Setting it here causes 404s when two addons
|
||||||
// are installed and one returns IDs the other can't serve metadata for.
|
// are installed and one returns IDs the other can't serve metadata for.
|
||||||
|
|
||||||
const normalizedCatalogType = type ? type.toLowerCase() : type;
|
// Always lowercase the item's own type first
|
||||||
if (normalizedCatalogType && content.type !== normalizedCatalogType) {
|
if (content.type) {
|
||||||
content.type = normalizedCatalogType;
|
|
||||||
} else if (content.type) {
|
|
||||||
content.type = content.type.toLowerCase();
|
content.type = content.type.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Only stamp the catalog type if the item doesn't already have a standard type.
|
||||||
|
// Prevents catalog type "other" from overwriting correct types like "movie"/"series"
|
||||||
|
// that the addon already set on individual items.
|
||||||
|
const normalizedCatalogType = type ? type.toLowerCase() : type;
|
||||||
|
const STANDARD_TYPES = new Set(['movie', 'series', 'anime.movie', 'anime.series', 'anime', 'tv', 'channel']);
|
||||||
|
if (normalizedCatalogType && !STANDARD_TYPES.has(content.type) && STANDARD_TYPES.has(normalizedCatalogType)) {
|
||||||
|
content.type = normalizedCatalogType;
|
||||||
|
} else if (normalizedCatalogType && !content.type) {
|
||||||
|
content.type = normalizedCatalogType;
|
||||||
|
}
|
||||||
return content;
|
return content;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -384,9 +393,17 @@ function dedupeAndStampResults(results: StreamingContent[], catalogType: string)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.from(bestById.values()).map(item =>
|
const normalizedCatalogType = catalogType ? catalogType.toLowerCase() : catalogType;
|
||||||
catalogType && item.type !== catalogType ? { ...item, type: catalogType } : item
|
const STANDARD_TYPES = new Set(['movie', 'series', 'anime.movie', 'anime.series', 'anime', 'tv', 'channel']);
|
||||||
);
|
|
||||||
|
return Array.from(bestById.values()).map(item => {
|
||||||
|
// Only stamp catalog type if item doesn't already have a standard type.
|
||||||
|
// Prevents "other" from overwriting correct types like "movie"/"series".
|
||||||
|
if (normalizedCatalogType && !STANDARD_TYPES.has(item.type) && STANDARD_TYPES.has(normalizedCatalogType)) {
|
||||||
|
return { ...item, type: normalizedCatalogType };
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildSectionName(
|
function buildSectionName(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue