mirror of
https://github.com/ranaldsgift/KefinTweaks.git
synced 2026-11-05 07:42:47 +01:00
187 lines
6.5 KiB
JavaScript
187 lines
6.5 KiB
JavaScript
// KefinTweaks Studios Cache Manager
|
|
// Handles fetching, processing, and caching of Popular TV Networks
|
|
(function() {
|
|
'use strict';
|
|
|
|
const LOG = (...args) => console.log('[KefinTweaks Movies Cache]', ...args);
|
|
const WARN = (...args) => console.warn('[KefinTweaks Movies Cache]', ...args);
|
|
const ERR = (...args) => console.error('[KefinTweaks Movies Cache]', ...args);
|
|
|
|
// 1 week
|
|
const CACHE_TTL = 7 * 24 * 60 * 60 * 1000;
|
|
const IMDB_TOP_250_CACHE_TTL = 24 * 60 * 60 * 1000; // 24 hours for ID list
|
|
|
|
// State
|
|
let movies = null;
|
|
let imdbTop250Movies = null;
|
|
let isInitializing = false;
|
|
|
|
/**
|
|
* Fetches and caches all movies across all libraries.
|
|
* You should not use this for anything related to UserData
|
|
* The cache for this is long, and this is intended to simply be an "archive" of all movies across all libraries.
|
|
* @returns {Promise<Array>} - Array of movie objects
|
|
*/
|
|
async function fetchAndCacheMovies() {
|
|
// IndexedDBCache
|
|
const cacheName = 'movies_library';
|
|
const cache = window.IndexedDBCache;
|
|
|
|
// Check cache first
|
|
const cached = await cache.get(cacheName);
|
|
if (cached) {
|
|
LOG('Using cached Movies');
|
|
return cached;
|
|
}
|
|
|
|
try {
|
|
LOG('Fetching Movies...');
|
|
|
|
// We need to refactor this to pull the data in chunks of 100 items at a time in order to backfill the cache
|
|
// We will populate 100 items at a time into the library cache.
|
|
// Each group will contain the index of the last item in the group so we can resume from there
|
|
// When resuming, we should first verify if the previous item based on the same sorting and startindex/limit is still the same
|
|
// We just check the last item in the indexed db cache and make the same query starting at that index
|
|
// If it's the same then we can resume from there, if not then we need to start from the beginning
|
|
const allMoviesQuery = `${ApiClient.serverAddress()}/Items?IncludeItemTypes=Movie&Recursive=true&Fields=ProviderIds`;
|
|
|
|
const movieResult = await apiHelper.getQuery(allMoviesQuery);
|
|
|
|
// Resolve the data (cached or fresh)
|
|
let allMovies = [];
|
|
if (movieResult && movieResult.Items) {
|
|
allMovies = movieResult.Items;
|
|
}
|
|
|
|
LOG(`Fetched ${allMovies.length} Movies`);
|
|
|
|
// Cache the results
|
|
const userId = ApiClient.getCurrentUserId();
|
|
await cache.set(cacheName, allMovies, userId, CACHE_TTL);
|
|
|
|
return allMovies;
|
|
} catch (err) {
|
|
ERR('Error fetching Movies:', err);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initializes the cache
|
|
*/
|
|
async function initialize() {
|
|
if (isInitializing) return;
|
|
|
|
if (movies) return;
|
|
|
|
isInitializing = true;
|
|
try {
|
|
movies = await fetchAndCacheMovies();
|
|
} finally {
|
|
isInitializing = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetches IMDb Top 250 movies using client-side filtering
|
|
* @returns {Promise<Array>} - List of matched Movie items
|
|
*/
|
|
async function fetchImdbTop250Data() {
|
|
const CACHE_KEY_IDS = 'kefinTweaks_imdbTop250_ids';
|
|
|
|
let imdbIds = null;
|
|
|
|
// 1. Get IDs (Local Cache or Fetch GitHub)
|
|
try {
|
|
const cachedIds = localStorage.getItem(CACHE_KEY_IDS);
|
|
if (cachedIds) {
|
|
const parsed = JSON.parse(cachedIds);
|
|
if (Date.now() - parsed.timestamp < IMDB_TOP_250_CACHE_TTL) {
|
|
imdbIds = parsed.ids;
|
|
}
|
|
}
|
|
} catch (e) { WARN('Error reading IMDb Top 250 cache:', e); }
|
|
|
|
if (!imdbIds) {
|
|
LOG('Fetching IMDb Top 250 list from GitHub...');
|
|
try {
|
|
const response = await fetch('https://raw.githubusercontent.com/theapache64/top250/master/top250_min.json');
|
|
if (!response.ok) throw new Error('Failed to fetch Top 250 JSON');
|
|
const data = await response.json();
|
|
|
|
// Extract IDs
|
|
imdbIds = data.map(entry => {
|
|
// entry.imdb_url e.g. "http://www.imdb.com/title/tt0111161/"
|
|
const match = entry.imdb_url && entry.imdb_url.match(/\/title\/(tt\d+)/);
|
|
return match ? match[1] : null;
|
|
}).filter(Boolean);
|
|
|
|
// Cache
|
|
localStorage.setItem(CACHE_KEY_IDS, JSON.stringify({
|
|
timestamp: Date.now(),
|
|
ids: imdbIds
|
|
}));
|
|
} catch (err) {
|
|
ERR('Failed to fetch IMDb Top 250 list:', err);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
if (!imdbIds || imdbIds.length === 0) return [];
|
|
|
|
return imdbIds;
|
|
}
|
|
|
|
async function getImdbTop250Movies() {
|
|
const cacheName = 'imdbTop250Movies';
|
|
const cache = window.IndexedDBCache;
|
|
const cached = await cache.get(cacheName);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
|
|
if (!imdbTop250Movies) {
|
|
const imdbIds = await fetchImdbTop250Data();
|
|
const allMovies = await getMovies();
|
|
|
|
// 3. Client-side Match
|
|
const matchedMovies = [];
|
|
const idsSet = new Set(imdbIds); // Faster lookup
|
|
|
|
for (const movie of allMovies) {
|
|
if (movie.ProviderIds && movie.ProviderIds.Imdb && idsSet.has(movie.ProviderIds.Imdb)) {
|
|
matchedMovies.push(movie);
|
|
}
|
|
}
|
|
imdbTop250Movies = matchedMovies;
|
|
}
|
|
const userId = ApiClient.getCurrentUserId();
|
|
await cache.set(cacheName, imdbTop250Movies, userId, IMDB_TOP_250_CACHE_TTL);
|
|
return imdbTop250Movies || [];
|
|
}
|
|
|
|
async function getMovies() {
|
|
if (!movies) {
|
|
movies = await fetchAndCacheMovies();
|
|
}
|
|
return movies || [];
|
|
}
|
|
|
|
// Expose API
|
|
window.MoviesCache = {
|
|
init: initialize,
|
|
getMovies: getMovies,
|
|
getImdbTop250Movies: getImdbTop250Movies,
|
|
// Also expose the fetcher if we need to force refresh
|
|
refresh: async () => {
|
|
const cache = window.IndexedDBCache;
|
|
cache.delete('movies_library');
|
|
movies = await fetchAndCacheMovies();
|
|
return movies;
|
|
}
|
|
};
|
|
|
|
LOG('Module loaded');
|
|
|
|
})();
|