add auto seasonal lists
This commit is contained in:
52
SEASONAL_LISTS.md
Normal file
52
SEASONAL_LISTS.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# Seasonal Lists Documentation
|
||||||
|
|
||||||
|
This document explains how to use seasonal lists with the Jellyfin Spotlight system.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
To enable seasonal lists, set `useSeasonalLists = true` in the main script.js file.
|
||||||
|
|
||||||
|
## Seasonal Periods
|
||||||
|
|
||||||
|
The system automatically detects the following periods:
|
||||||
|
|
||||||
|
### Special Events (take precedence over seasons)
|
||||||
|
- **New Year**: January 1-7 → `newyear_list.txt`
|
||||||
|
- **Valentine's day**: February 10-20 → `valentine_list.txt`
|
||||||
|
- **Easter**: 1 week around Easter Sunday → `easter_list.txt`
|
||||||
|
- **Halloween**: October 20-31 → `halloween_list.txt`
|
||||||
|
|
||||||
|
### Regular Seasons
|
||||||
|
- **Spring**: March-May → `spring_list.txt`
|
||||||
|
- **Summer**: June-August → `summer_list.txt`
|
||||||
|
- **Autumn**: September-November → `autumn_list.txt`
|
||||||
|
- **Winter**: December-February → `winter_list.txt`
|
||||||
|
|
||||||
|
## List Files
|
||||||
|
|
||||||
|
Create the following files in your `featured` directory:
|
||||||
|
|
||||||
|
- `spring_list.txt` - Spring movies/shows
|
||||||
|
- `summer_list.txt` - Summer movies/shows
|
||||||
|
- `autumn_list.txt` - Autumn movies/shows
|
||||||
|
- `winter_list.txt` - Winter movies/shows
|
||||||
|
- `newyear_list.txt` - New Year themed content
|
||||||
|
- `valentine_list.txt` - Romance/Valentine themed content
|
||||||
|
- `easter_list.txt` - Easter/Family themed content
|
||||||
|
- `halloween_list.txt` - Horror/Halloween themed content
|
||||||
|
|
||||||
|
## File Format
|
||||||
|
|
||||||
|
Each seasonal list file follows the same format as the main `list.txt`:
|
||||||
|
|
||||||
|
```
|
||||||
|
Title of List [muteon/muteoff]
|
||||||
|
movie_id_1
|
||||||
|
movie_id_2
|
||||||
|
series_id_1
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fallback
|
||||||
|
|
||||||
|
If seasonal lists are disabled or a seasonal file doesn't exist, the system will fall back to using the default `list.txt` file.
|
||||||
2
list.txt
2
list.txt
@@ -1,4 +1,4 @@
|
|||||||
Spotlight MuteOn
|
Title of List [muteon/muteoff]
|
||||||
f81c9b854e3edc62fb049e252c488115 Hunger Games
|
f81c9b854e3edc62fb049e252c488115 Hunger Games
|
||||||
7d515072462d6cedd74de8e2df71888f Interstellar
|
7d515072462d6cedd74de8e2df71888f Interstellar
|
||||||
df4f3da3066455404e6b874d22ba86aa Fast X
|
df4f3da3066455404e6b874d22ba86aa Fast X
|
||||||
|
|||||||
91
script.js
91
script.js
@@ -15,6 +15,19 @@ let plotMaxLength = 550; // Maximum number of characters in the plot
|
|||||||
let trailerMaxLength = 0; // Default value 0; length measured in ms, set to 0 to disable, could be used instead of SponsorBlock
|
let trailerMaxLength = 0; // Default value 0; length measured in ms, set to 0 to disable, could be used instead of SponsorBlock
|
||||||
let startTrailerMuted = true; // Default value true; set to false to start the video unmuted
|
let startTrailerMuted = true; // Default value true; set to false to start the video unmuted
|
||||||
|
|
||||||
|
// Seasonal lists configuration
|
||||||
|
let useSeasonalLists = false; // Set to true to enable automatic seasonal list switching
|
||||||
|
const seasonalLists = {
|
||||||
|
spring: 'spring_list.txt', // spring (march-may)
|
||||||
|
summer: 'summer_list.txt', // summer (june-august)
|
||||||
|
autumn: 'autumn_list.txt', // autumn (september-november)
|
||||||
|
winter: 'winter_list.txt', // winter (december-february)
|
||||||
|
newyear: 'newyear_list.txt', // new year (1.-7. januar)
|
||||||
|
valentine: 'valentine_list.txt', // valentines day (10.-20. februar)
|
||||||
|
easter: 'easter_list.txt', // easter (variable dates, March-April)
|
||||||
|
halloween: 'halloween_list.txt' // halloween (20.-31. october)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Language specific strings
|
// Language specific strings
|
||||||
// currently implemented: en, de, fr, es, it, pl, nl
|
// currently implemented: en, de, fr, es, it, pl, nl
|
||||||
@@ -91,6 +104,78 @@ const setLanguage = (language) => {
|
|||||||
|
|
||||||
const languageIndex = setLanguage(browserLanguage);
|
const languageIndex = setLanguage(browserLanguage);
|
||||||
|
|
||||||
|
// Seasonal list detection
|
||||||
|
const getCurrentSeason = () => {
|
||||||
|
if (!useSeasonalLists) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const now = new Date();
|
||||||
|
const month = now.getMonth() + 1; // 1-12
|
||||||
|
const day = now.getDate();
|
||||||
|
|
||||||
|
// Special events (take precedence over seasons)
|
||||||
|
// new year: 1-7 january
|
||||||
|
if (month === 1 && day <= 7) return 'newyear';
|
||||||
|
|
||||||
|
// valentines day: 10-20 february
|
||||||
|
if (month === 2 && day >= 10 && day <= 20) return 'valentine';
|
||||||
|
|
||||||
|
// halloween: 20-31 cotober
|
||||||
|
if (month === 10 && day >= 20) return 'halloween';
|
||||||
|
|
||||||
|
// Easter calculation (simplified - around March-April)
|
||||||
|
const easterStart = getEasterPeriod(now.getFullYear());
|
||||||
|
if (isInEasterPeriod(now, easterStart)) return 'easter';
|
||||||
|
|
||||||
|
// Regular seasons
|
||||||
|
if (month >= 3 && month <= 5) return 'spring'; // march-may
|
||||||
|
if (month >= 6 && month <= 8) return 'summer'; // june-august
|
||||||
|
if (month >= 9 && month <= 11) return 'autumn'; // september-november
|
||||||
|
if (month === 12 || month <= 2) return 'winter'; // december-february
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Simplified Easter calculation (Western Easter)
|
||||||
|
const getEasterPeriod = (year) => {
|
||||||
|
const a = year % 19;
|
||||||
|
const b = Math.floor(year / 100);
|
||||||
|
const c = year % 100;
|
||||||
|
const d = Math.floor(b / 4);
|
||||||
|
const e = b % 4;
|
||||||
|
const f = Math.floor((b + 8) / 25);
|
||||||
|
const g = Math.floor((b - f + 1) / 3);
|
||||||
|
const h = (19 * a + b - d - g + 15) % 30;
|
||||||
|
const i = Math.floor(c / 4);
|
||||||
|
const k = c % 4;
|
||||||
|
const l = (32 + 2 * e + 2 * i - h - k) % 7;
|
||||||
|
const m = Math.floor((a + 11 * h + 22 * l) / 451);
|
||||||
|
const month = Math.floor((h + l - 7 * m + 114) / 31);
|
||||||
|
const day = ((h + l - 7 * m + 114) % 31) + 1;
|
||||||
|
|
||||||
|
return { month, day };
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if current date is in Easter period (2 weeks around Easter)
|
||||||
|
const isInEasterPeriod = (currentDate, easter) => {
|
||||||
|
const easterDate = new Date(currentDate.getFullYear(), easter.month - 1, easter.day);
|
||||||
|
const timeDiff = Math.abs(currentDate.getTime() - easterDate.getTime());
|
||||||
|
const daysDiff = Math.ceil(timeDiff / (1000 * 3600 * 24));
|
||||||
|
return daysDiff <= 7; // 1 week before and after Easter
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the appropriate list filename based on season
|
||||||
|
const getSeasonalListFileName = () => {
|
||||||
|
const season = getCurrentSeason();
|
||||||
|
if (!season || !seasonalLists[season]) {
|
||||||
|
console.log('Using default list:', listFileName);
|
||||||
|
return listFileName;
|
||||||
|
}
|
||||||
|
console.log(`Using seasonal list for ${season}:`, seasonalLists[season]);
|
||||||
|
return seasonalLists[season];
|
||||||
|
};
|
||||||
|
|
||||||
// Get SponsorBlock-Data for the outro/intro segment of the trailer
|
// Get SponsorBlock-Data for the outro/intro segment of the trailer
|
||||||
const fetchSponsorBlockData = async (videoId) => {
|
const fetchSponsorBlockData = async (videoId) => {
|
||||||
try {
|
try {
|
||||||
@@ -679,8 +764,9 @@ const checkBackdropAndLogo = movie => {
|
|||||||
).catch(() => fetchRandomMovie());
|
).catch(() => fetchRandomMovie());
|
||||||
};
|
};
|
||||||
|
|
||||||
const readCustomList = () =>
|
const readCustomList = () => {
|
||||||
fetch(listFileName + '?' + new Date().getTime())
|
const currentListFile = getSeasonalListFileName();
|
||||||
|
return fetch(currentListFile + '?' + new Date().getTime())
|
||||||
.then(response => response.ok ? response.text() : null)
|
.then(response => response.ok ? response.text() : null)
|
||||||
.then(text => {
|
.then(text => {
|
||||||
if (!text || !text.trim()) {
|
if (!text || !text.trim()) {
|
||||||
@@ -723,6 +809,7 @@ const readCustomList = () =>
|
|||||||
console.error('Error reading List.txt. Falling back to random selection.');
|
console.error('Error reading List.txt. Falling back to random selection.');
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const fetchRandomMovie = () => {
|
const fetchRandomMovie = () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user