trakt scrobble imrpovements

This commit is contained in:
tapframe 2025-10-05 22:59:40 +05:30
parent 25988bdb7b
commit 13d72338a5

View file

@ -1570,17 +1570,17 @@ export class TraktService {
return null; return null;
} }
// Clean IMDB ID - some APIs want it without 'tt' prefix // Ensure IMDb ID includes the 'tt' prefix for Trakt scrobble payloads
const cleanImdbId = contentData.imdbId.startsWith('tt') const imdbIdWithPrefix = contentData.imdbId.startsWith('tt')
? contentData.imdbId.substring(2) ? contentData.imdbId
: contentData.imdbId; : `tt${contentData.imdbId}`;
const payload = { const payload = {
movie: { movie: {
title: contentData.title, title: contentData.title,
year: contentData.year, year: contentData.year,
ids: { ids: {
imdb: cleanImdbId imdb: imdbIdWithPrefix
} }
}, },
progress: Math.round(progress * 100) / 100 // Round to 2 decimal places progress: Math.round(progress * 100) / 100 // Round to 2 decimal places
@ -1614,23 +1614,23 @@ export class TraktService {
// Add show IMDB ID if available // Add show IMDB ID if available
if (contentData.showImdbId) { if (contentData.showImdbId) {
const cleanShowImdbId = contentData.showImdbId.startsWith('tt') const showImdbWithPrefix = contentData.showImdbId.startsWith('tt')
? contentData.showImdbId.substring(2) ? contentData.showImdbId
: contentData.showImdbId; : `tt${contentData.showImdbId}`;
payload.show.ids.imdb = cleanShowImdbId; payload.show.ids.imdb = showImdbWithPrefix;
} }
// Add episode IMDB ID if available (for specific episode IDs) // Add episode IMDB ID if available (for specific episode IDs)
if (contentData.imdbId && contentData.imdbId !== contentData.showImdbId) { if (contentData.imdbId && contentData.imdbId !== contentData.showImdbId) {
const cleanEpisodeImdbId = contentData.imdbId.startsWith('tt') const episodeImdbWithPrefix = contentData.imdbId.startsWith('tt')
? contentData.imdbId.substring(2) ? contentData.imdbId
: contentData.imdbId; : `tt${contentData.imdbId}`;
if (!payload.episode.ids) { if (!payload.episode.ids) {
payload.episode.ids = {}; payload.episode.ids = {};
} }
payload.episode.ids.imdb = cleanEpisodeImdbId; payload.episode.ids.imdb = episodeImdbWithPrefix;
} }
logger.log('[TraktService] Episode payload built:', payload); logger.log('[TraktService] Episode payload built:', payload);
@ -1818,23 +1818,26 @@ export class TraktService {
// Record this stop attempt // Record this stop attempt
this.lastStopCalls.set(watchingKey, now); this.lastStopCalls.set(watchingKey, now);
// Respect higher user threshold by pausing below effective threshold
const effectiveThreshold = Math.max(80, this.completionThreshold);
const result = await this.queueRequest(async () => { const result = await this.queueRequest(async () => {
if (progress < effectiveThreshold) {
return await this.pauseWatching(contentData, progress);
}
return await this.stopWatching(contentData, progress); return await this.stopWatching(contentData, progress);
}); });
if (result) { if (result) {
this.currentlyWatching.delete(watchingKey); this.currentlyWatching.delete(watchingKey);
// Mark as scrobbled if >= 80% to prevent future duplicates and restarts // Mark as scrobbled if >= user threshold to prevent future duplicates and restarts
if (progress >= this.completionThreshold) { if (progress >= this.completionThreshold) {
this.scrobbledItems.add(watchingKey); this.scrobbledItems.add(watchingKey);
this.scrobbledTimestamps.set(watchingKey, Date.now()); this.scrobbledTimestamps.set(watchingKey, Date.now());
logger.log(`[TraktService] Marked as scrobbled to prevent restarts: ${watchingKey}`); logger.log(`[TraktService] Marked as scrobbled to prevent restarts: ${watchingKey}`);
} }
// The stop endpoint automatically handles the 80%+ completion logic const action = progress >= effectiveThreshold ? 'scrobbled' : 'paused';
// and will mark as scrobbled if >= 80%, or pause if < 80%
const action = progress >= this.completionThreshold ? 'scrobbled' : 'paused';
logger.log(`[TraktService] Stopped watching ${contentData.type}: ${contentData.title} (${progress.toFixed(1)}% - ${action})`); logger.log(`[TraktService] Stopped watching ${contentData.type}: ${contentData.title} (${progress.toFixed(1)}% - ${action})`);
return true; return true;
@ -1913,19 +1916,22 @@ export class TraktService {
this.lastStopCalls.set(watchingKey, Date.now()); this.lastStopCalls.set(watchingKey, Date.now());
// BYPASS QUEUE: Call API directly for immediate response // BYPASS QUEUE: Respect higher user threshold by pausing below effective threshold
const result = await this.stopWatching(contentData, progress); const effectiveThreshold = Math.max(80, this.completionThreshold);
const result = progress < effectiveThreshold
? await this.pauseWatching(contentData, progress)
: await this.stopWatching(contentData, progress);
if (result) { if (result) {
this.currentlyWatching.delete(watchingKey); this.currentlyWatching.delete(watchingKey);
// Mark as scrobbled if >= 80% to prevent future duplicates and restarts // Mark as scrobbled if >= user threshold to prevent future duplicates and restarts
if (progress >= this.completionThreshold) { if (progress >= this.completionThreshold) {
this.scrobbledItems.add(watchingKey); this.scrobbledItems.add(watchingKey);
this.scrobbledTimestamps.set(watchingKey, Date.now()); this.scrobbledTimestamps.set(watchingKey, Date.now());
} }
const action = progress >= this.completionThreshold ? 'scrobbled' : 'paused'; const action = progress >= effectiveThreshold ? 'scrobbled' : 'paused';
logger.log(`[TraktService] IMMEDIATE: Stopped watching ${contentData.type}: ${contentData.title} (${progress.toFixed(1)}% - ${action})`); logger.log(`[TraktService] IMMEDIATE: Stopped watching ${contentData.type}: ${contentData.title} (${progress.toFixed(1)}% - ${action})`);
return true; return true;