feat: support upto 15 days of listings
- change default timespan to 6 - parallize tv listing chunks special thanks to @majortom9 https://github.com/jef/zap2xml/issues/41#issuecomment-3092418305
This commit is contained in:
14
README.md
14
README.md
@@ -45,26 +45,26 @@ See [Environment variables](#environment-variables) for configuration options.
|
|||||||
### Environment variables
|
### Environment variables
|
||||||
|
|
||||||
| Variable | Description | Type | Default |
|
| Variable | Description | Type | Default |
|
||||||
| ------------- | --------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------- |
|
| ------------- | --------------------------------------------------------------------------------------------------------------- | ------ | -------------------------------- |
|
||||||
| `LINEUP_ID` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | String | `USA-lineupId-DEFAULT` (Attenna) |
|
| `LINEUP_ID` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | String | `USA-lineupId-DEFAULT` (Attenna) |
|
||||||
| `TIMESPAN` | Either 3 or 6 hours of shows | Integer | 3 |
|
| `TIMESPAN` | Either 3 or 6 hours of shows | String | 3 |
|
||||||
| `PREF` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | String | (empty) |
|
| `PREF` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | String | (empty) |
|
||||||
| `COUNTRY` | Country code (default: `US`) | String | US |
|
| `COUNTRY` | Country code (default: `US`) | String | US |
|
||||||
| `POSTAL_CODE` | Postal code of where shows are available. | Integer | 30309 |
|
| `POSTAL_CODE` | Postal code of where shows are available. | String | 30309 |
|
||||||
| `USER_AGENT` | Custom user agent string for HTTP requests. | String | Uses random if not specified |
|
| `USER_AGENT` | Custom user agent string for HTTP requests. | String | Uses random if not specified |
|
||||||
| `TZ` | Timezone | String | System default |
|
| `TZ` | Timezone | String | System default |
|
||||||
| `SLEEP_TIME` | Sleep time before next run in seconds (default: 10800, Only used with Docker.) | Integer | 10800 |
|
| `SLEEP_TIME` | Sleep time before next run in seconds (default: 10800, Only used with Docker.) | String | 10800 |
|
||||||
| `OUTPUT_FILE` | Output file name (default: xmltv.xml) | String | xmltv.xml |
|
| `OUTPUT_FILE` | Output file name (default: xmltv.xml) | String | xmltv.xml |
|
||||||
|
|
||||||
### Command line arguments
|
### Command line arguments
|
||||||
|
|
||||||
| Argument | Description | Type | Default |
|
| Argument | Description | Type | Default |
|
||||||
| -------------- | --------------------------------------------------------------------------------------------------------------- | ------- | -------------------------------- |
|
| -------------- | --------------------------------------------------------------------------------------------------------------- | ------ | -------------------------------- |
|
||||||
| `--lineupId` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | String | `USA-lineupId-DEFAULT` (Attenna) |
|
| `--lineupId` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | String | `USA-lineupId-DEFAULT` (Attenna) |
|
||||||
| `--timespan` | Either 3 or 6 hours of shows | Integer | 3 |
|
| `--timespan` | Either 3 or 6 hours of shows | String | 3 |
|
||||||
| `--pref` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | String | (empty) |
|
| `--pref` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | String | (empty) |
|
||||||
| `--country` | Country code (default: `US`) | String | US |
|
| `--country` | Country code (default: `US`) | String | US |
|
||||||
| `--postalCode` | Postal code of where shows are available. | Integer | 30309 |
|
| `--postalCode` | Postal code of where shows are available. | String | 30309 |
|
||||||
| `--userAgent` | Custom user agent string for HTTP requests. | String | Uses random if not specified |
|
| `--userAgent` | Custom user agent string for HTTP requests. | String | Uses random if not specified |
|
||||||
| `--timezone` | Timezone | String | System default |
|
| `--timezone` | Timezone | String | System default |
|
||||||
| `--outputFile` | Output file name (default: xmltv.xml) | String | xmltv.xml |
|
| `--outputFile` | Output file name (default: xmltv.xml) | String | xmltv.xml |
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const config = {
|
|||||||
timespan:
|
timespan:
|
||||||
process.env["TIMESPAN"] ||
|
process.env["TIMESPAN"] ||
|
||||||
process.argv.find((arg) => arg.startsWith("--timespan="))?.split("=")[1] ||
|
process.argv.find((arg) => arg.startsWith("--timespan="))?.split("=")[1] ||
|
||||||
"3",
|
"6",
|
||||||
country:
|
country:
|
||||||
process.env["COUNTRY"] ||
|
process.env["COUNTRY"] ||
|
||||||
process.argv.find((arg) => arg.startsWith("--country="))?.split("=")[1] ||
|
process.argv.find((arg) => arg.startsWith("--country="))?.split("=")[1] ||
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ Usage: node dist/index.js [options]
|
|||||||
Options:
|
Options:
|
||||||
--help Show this help message
|
--help Show this help message
|
||||||
--lineupId=ID Lineup ID (default: USA-lineupId-DEFAULT)
|
--lineupId=ID Lineup ID (default: USA-lineupId-DEFAULT)
|
||||||
--timespan=NUM Timespan in hours (default: 3)
|
--timespan=NUM Timespan in hours (up to 360 = 15 days, default: 6)
|
||||||
--pref=LIST User preferences, comma separated. Can be m, p, and h (default: empty)'
|
--pref=LIST User preferences, comma separated. Can be m, p, and h (default: empty)'
|
||||||
--country=CON Country code (default: USA)
|
--country=CON Country code (default: USA)
|
||||||
--postalCode=ZIP Postal code (default: 30309)
|
--postalCode=ZIP Postal code (default: 30309)
|
||||||
|
|||||||
@@ -78,10 +78,10 @@ export interface GridApiResponse {
|
|||||||
channels: Channel[];
|
channels: Channel[];
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildUrl() {
|
function buildUrl(time: number, timespan: number): string {
|
||||||
const params = {
|
const params = {
|
||||||
lineupId: config.lineupId,
|
lineupId: config.lineupId,
|
||||||
timespan: config.timespan,
|
timespan: timespan.toString(),
|
||||||
headendId: "lineupId",
|
headendId: "lineupId",
|
||||||
country: config.country,
|
country: config.country,
|
||||||
timezone: config.timezone,
|
timezone: config.timezone,
|
||||||
@@ -90,7 +90,7 @@ function buildUrl() {
|
|||||||
pref: config.pref + "16,128" || "16,128",
|
pref: config.pref + "16,128" || "16,128",
|
||||||
aid: "orbebb",
|
aid: "orbebb",
|
||||||
languagecode: "en-us",
|
languagecode: "en-us",
|
||||||
time: Math.floor(Date.now() / 1000).toString(),
|
time: time.toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const urlParams = new URLSearchParams(params).toString();
|
const urlParams = new URLSearchParams(params).toString();
|
||||||
@@ -101,19 +101,47 @@ function buildUrl() {
|
|||||||
export async function getTVListings(): Promise<GridApiResponse> {
|
export async function getTVListings(): Promise<GridApiResponse> {
|
||||||
console.log("Fetching TV listings");
|
console.log("Fetching TV listings");
|
||||||
|
|
||||||
const url = buildUrl();
|
const totalHours = parseInt(config.timespan, 10);
|
||||||
|
const chunkHours = 6; // Gracenote allows up to 6 hours per request
|
||||||
|
const now = Math.floor(Date.now() / 1000); // Current time in UNIX timestamp
|
||||||
|
const channelsMap: Map<string, Channel> = new Map();
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const fetchPromises: Promise<void>[] = [];
|
||||||
|
|
||||||
|
for (let offset = 0; offset < totalHours; offset += chunkHours) {
|
||||||
|
const time = now + offset * 3600;
|
||||||
|
const url = buildUrl(time, chunkHours);
|
||||||
|
|
||||||
|
const fetchPromise = fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
"User-Agent": config.userAgent || "",
|
"User-Agent": config.userAgent || "",
|
||||||
},
|
},
|
||||||
});
|
}).then(async (response) => {
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Failed to fetch: ${response.status} ${response.statusText}`,
|
`Failed to fetch: ${response.status} ${response.statusText}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const chunkData = (await response.json()) as GridApiResponse;
|
||||||
|
|
||||||
return (await response.json()) as GridApiResponse;
|
for (const newChannel of chunkData.channels) {
|
||||||
|
if (!channelsMap.has(newChannel.channelId)) {
|
||||||
|
// Clone channel with its events
|
||||||
|
channelsMap.set(newChannel.channelId, {
|
||||||
|
...newChannel,
|
||||||
|
events: [...newChannel.events],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const existingChannel = channelsMap.get(newChannel.channelId)!;
|
||||||
|
existingChannel.events.push(...newChannel.events);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
fetchPromises.push(fetchPromise);
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(fetchPromises);
|
||||||
|
|
||||||
|
return { channels: Array.from(channelsMap.values()) };
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user