File size: 5,949 Bytes
ed2e9a7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
const express = require('express');
const { addonBuilder, getRouter } = require('stremio-addon-sdk');
const cors = require('cors');
const fs = require('fs');
const path = require('path');
const manifest = {
id: 'hy.yourtvshows.org',
version: '1.0.0',
name: 'TV Club',
description: 'Stream TV series categorized by genre with search capability',
resources: ['catalog', 'stream', 'meta'],
types: ['series'],
idPrefixes: ['tt'],
catalogs: [
{
id: 'main-catalog',
type: 'series',
name: 'All Series',
extra: [
{ name: 'genre', options: [] },
{ name: 'search', isRequired: false }
]
}
]
};
const builder = new addonBuilder(manifest);
// Function to read JSON files
function readJSONFile(filename) {
const filePath = path.join(__dirname, filename);
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
}
// Load and parse series data files
const seriesDataFiles = fs.readdirSync(__dirname)
.filter(file => file.endsWith('_series_data.json'));
console.log("Found series data files:", seriesDataFiles);
// Store catalogs and metadata
const catalogs = [];
const metaData = {};
// Process each series data file dynamically
seriesDataFiles.forEach(filename => {
const data = readJSONFile(filename);
const catalogType = 'series'; // Assuming 'series' for all catalogs
// Add categories to genre options in manifest
Object.keys(data).forEach(category => {
if (!manifest.catalogs[0].extra[0].options.includes(category)) {
manifest.catalogs[0].extra[0].options.push(category);
}
});
// Process each category in the file
Object.entries(data).forEach(([category, seriesList]) => {
// Add series metadata for each series in the category
seriesList.forEach(series => {
const seriesMeta = {
id: series.id,
type: catalogType,
name: series.name,
genres: [category],
poster: series.poster || null
};
// Store metadata and catalog information
metaData[series.id] = {
...seriesMeta,
seasons: series.seasons.map(season => ({
season: season.season,
episodes: season.episodes.map(ep => ({
episode: ep.episode,
stream_url: ep.stream_url
}))
}))
};
catalogs.push({
category,
meta: seriesMeta
});
});
});
});
// Catalog handler to list series by genre and enable search
builder.defineCatalogHandler(({ type, extra }) => {
return new Promise((resolve) => {
if (type === 'series') {
const genre = extra.genre;
const searchQuery = extra.search ? extra.search.toLowerCase() : null;
let seriesCatalog = catalogs
.filter(catalog => !genre || catalog.category === genre) // Filter by genre if provided
.map(catalog => catalog.meta);
// Filter by search query if provided
if (searchQuery) {
seriesCatalog = seriesCatalog.filter(meta =>
meta.name.toLowerCase().includes(searchQuery)
);
}
resolve({ metas: seriesCatalog });
} else {
resolve({ metas: [] });
}
});
});
// Meta handler to get details of a specific series
builder.defineMetaHandler(({ id }) => {
return new Promise((resolve) => {
const seriesMeta = metaData[id];
if (seriesMeta) {
resolve({
meta: {
id: seriesMeta.id,
type: 'series',
name: seriesMeta.name,
poster: seriesMeta.poster,
genres: seriesMeta.genres,
seasons: seriesMeta.seasons.map(season => ({
number: season.season,
episodes: season.episodes.map(ep => ({
id: `${seriesMeta.id}:${season.season}:${ep.episode}`,
title: `Episode ${ep.episode}`,
season: season.season,
number: ep.episode
}))
}))
}
});
} else {
resolve({});
}
});
});
// Stream handler to fetch specific episode streams
builder.defineStreamHandler(({ type, id }) => {
return new Promise((resolve) => {
if (type === 'series') {
const [seriesId, seasonNumber, episodeNumber] = id.split(':');
const seriesMeta = metaData[seriesId];
if (seriesMeta) {
const season = seriesMeta.seasons.find(s => s.season == seasonNumber);
if (season) {
const episode = season.episodes.find(e => e.episode == episodeNumber);
if (episode) {
resolve({
streams: [{
title: `${seriesMeta.name} S${seasonNumber}E${episodeNumber}`,
url: episode.stream_url
}]
});
return;
}
}
}
}
resolve({ streams: [] });
});
});
const addonInterface = builder.getInterface();
const app = express();
app.use(cors());
app.use('/', getRouter(addonInterface));
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something went wrong!');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`TV Club Stremio Addon running on port ${PORT}`);
});
|