CoolFace
Apppublic

mikmc5/comedy

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
index.js259 linesDownload Raw Back to root
1const { addonBuilder, serveHTTP } = require('stremio-addon-sdk');2const axios = require('axios');3const fs = require('fs').promises;4const path = require('path');5const winston = require('winston');6const schedule = require('node-schedule');7 8// Winston logger configuration9const logger = winston.createLogger({10    level: 'debug',11    format: winston.format.combine(12        winston.format.timestamp(),13        winston.format.printf(({ level, message, timestamp }) => {14            return `${timestamp} ${level}: ${message}`;15        })16    ),17    transports: [18        new winston.transports.Console(),19        new winston.transports.File({ filename: 'addon.log' })20    ]21});22 23const TMDB_API_KEY = 'f051e7366c6105ad4f9aafe4733d9dae';24const TMDB_BASE_URL = 'https://api.themoviedb.org/3';25const CACHE_DIR = path.join(__dirname, 'cache');26const CATALOG_CACHE_FILE = path.join(CACHE_DIR, 'catalog_cache.json');27const META_CACHE_FILE = path.join(CACHE_DIR, 'meta_cache.json');28 29let catalogCache = {};30let metaCache = {};31 32const manifest = {33    id: 'org.stremio.uk-comedy-movies',34    version: '1.0.0',35    name: 'UK Comedy Movies',36    description: 'Stremio Add-on to showcase UK comedy movies from 2015 onward with a rating above 4',37    catalogs: [38        {39            id: 'uk-comedy-movies-catalog',40            name: 'UK Comedy Movies',41            type: 'Easynews',42            pageSize: 25,43            extra: [{ name: 'search', isRequired: false }]44        }45    ],46    resources: ['catalog', 'meta'],47    types: ['movie'],48    idPrefixes: ['tmdb']49};50 51const builder = new addonBuilder(manifest);52 53async function ensureCacheDirectory() {54    try {55        await fs.mkdir(CACHE_DIR, { recursive: true });56        logger.debug('Cache directory ensured');57    } catch (error) {58        logger.error('Error creating cache directory:', error);59    }60}61 62async function loadCache() {63    try {64        const catalogData = await fs.readFile(CATALOG_CACHE_FILE, 'utf8');65        catalogCache = JSON.parse(catalogData);66        logger.debug(`Catalog cache loaded. Items: ${catalogCache.data ? catalogCache.data.length : 0}`);67    } catch (error) {68        logger.info('No existing catalog cache found. Will create a new one.');69    }70 71    try {72        const metaData = await fs.readFile(META_CACHE_FILE, 'utf8');73        metaCache = JSON.parse(metaData);74        logger.debug(`Meta cache loaded. Items: ${Object.keys(metaCache).length}`);75    } catch (error) {76        logger.info('No existing meta cache found. Will create a new one.');77    }78}79 80async function saveCache() {81    try {82        await fs.writeFile(CATALOG_CACHE_FILE, JSON.stringify(catalogCache));83        await fs.writeFile(META_CACHE_FILE, JSON.stringify(metaCache));84        logger.debug('Cache saved successfully');85    } catch (error) {86        logger.error('Error saving cache:', error);87    }88}89 90async function fetchUKComedyMovies() {91    let page = 1;92    let totalPages = 1;93    const allResults = [];94 95    try {96        do {97            const url = `${TMDB_BASE_URL}/discover/movie?api_key=${TMDB_API_KEY}&with_genres=35&with_original_language=en&with_origin_country=GB&primary_release_date.gte=2015-01-01&primary_release_date.lte=2024-12-31&page=${page}`;98            logger.debug(`Requesting TMDB: ${url}`);99 100            const response = await axios.get(url);101            const { results, total_pages } = response.data;102            totalPages = total_pages;103 104            logger.debug(`Page ${page}/${totalPages} fetched. Results: ${results.length}`);105 106            // Filter movies with a rating above 4107            const filteredResults = results.filter(movie => movie.vote_average > 4);108            allResults.push(...filteredResults);109 110            page++;111        } while (page <= totalPages);112 113        allResults.sort((a, b) => new Date(b.release_date) - new Date(a.release_date));114        logger.info(`Total UK Comedy movies fetched after filtering: ${allResults.length}`);115        return allResults;116    } catch (error) {117        logger.error('Error fetching UK Comedy movies:', error);118        return [];119    }120}121 122async function fetchMovieMetadata(movieId) {123    try {124        const url = `${TMDB_BASE_URL}/movie/${movieId}?api_key=${TMDB_API_KEY}`;125        const response = await axios.get(url);126        return response.data;127    } catch (error) {128        logger.error(`Error fetching metadata for movie ID ${movieId}:`, error.message);129        return { error: 'Failed to fetch movie data' };130    }131}132 133async function updateCatalogAndMetaCache() {134    logger.info('Updating catalog and meta cache...');135    try {136        const results = await fetchUKComedyMovies();137        catalogCache = {138            timestamp: Date.now(),139            data: results140        };141 142        // Fetch meta information for all movies143        for (const movie of results) {144            const movieId = movie.id;145            logger.debug(`Fetching meta for movie ID: ${movieId}`);146            const movieData = await fetchMovieMetadata(movieId);147            metaCache[movieId] = {148                timestamp: Date.now(),149                data: movieData150            };151        }152 153        await saveCache();154        logger.info(`Catalog and meta cache updated. Items: ${results.length}`);155    } catch (error) {156        logger.error('Error updating catalog and meta cache:', error);157    }158}159 160builder.defineCatalogHandler(async (args) => {161    const searchQuery = args.extra && args.extra.search ? args.extra.search : '';162    logger.debug(`Catalog request received. Query: "${searchQuery}"`);163 164    let results = catalogCache.data || [];165    logger.debug(`Catalog cache has ${results.length} items`);166 167    if (searchQuery) {168        results = results.filter(movie => 169            movie.title.toLowerCase().includes(searchQuery.toLowerCase())170        );171        logger.debug(`Filtered results for "${searchQuery}": ${results.length}`);172    }173 174    const metas = results.map(item => ({175        id: `tmdb-${item.id}`,176        type: 'movie',177        name: item.title,178        poster: item.poster_path ? `https://image.tmdb.org/t/p/w500${item.poster_path}` : null,179        description: item.overview || 'No description available',180        releaseInfo: item.release_date ? item.release_date.split('-')[0] : 'Unknown'181    }));182 183    logger.info(`Catalog request processed. Query: "${searchQuery}", Results: ${metas.length}`);184    return { metas };185});186 187builder.defineMetaHandler(async (args) => {188    const id = args.id.split('-')[1];189    logger.debug(`Meta request received for movie ID: ${id}`);190 191    if (!metaCache[id]) {192        logger.warn(`Meta not found for movie ID: ${id}`);193        return { meta: null };194    }195 196    const movieData = metaCache[id].data;197 198    if (movieData.error) {199        logger.warn(`Meta request failed for movie ID: ${id}`);200        return { meta: null };201    }202 203    const { 204        title, 205        overview, 206        poster_path, 207        release_date, 208        genres, 209        runtime, 210        vote_average, 211        backdrop_path 212    } = movieData;213 214    logger.info(`Meta request processed for movie ID: ${id}`);215    return {216        meta: {217            id: args.id,218            type: 'movie',219            name: title || 'Unknown Title',220            poster: poster_path ? `https://image.tmdb.org/t/p/w500${poster_path}` : null,221            background: backdrop_path ? `https://image.tmdb.org/t/p/w1280${backdrop_path}` : null,222            description: overview || 'No description available',223            releaseInfo: release_date ? release_date.split('-')[0] : 'Unknown',224            genre: genres && Array.isArray(genres) ? genres.map(g => g.name) : [],225            runtime: runtime ? `${runtime} min` : 'Unknown',226            rating: vote_average ? vote_average.toFixed(1) : 'N/A',227        }228    };229});230 231async function startServer() {232    await ensureCacheDirectory();233    await loadCache();234 235    async function refreshCache() {236        logger.info('Scheduled update: Refreshing catalog and meta cache');237        await updateCatalogAndMetaCache();238    }239 240    // Schedule cache refresh every day at midnight241    schedule.scheduleJob('0 0 * * *', refreshCache);242 243    // Initial cache refresh if needed244    if (!catalogCache.timestamp || Date.now() - catalogCache.timestamp > 24 * 60 * 60 * 1000) {245        logger.info('Initial cache refresh needed');246        await refreshCache();247    } else {248        logger.info('Cache is up to date. Next refresh scheduled for midnight');249    }250 251    const interface = builder.getInterface();252    const port = process.env.PORT || 3000;253 254    logger.info(`Starting Stremio Add-on server on port ${port}`);255    serveHTTP(interface, { port });256}257 258startServer();259