Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
2f34787
Update tvlistings.ts
jesmannstl Jul 25, 2025
2c3b703
Update xmltv.ts
jesmannstl Jul 25, 2025
da95bec
Update tvlistings.ts
jesmannstl Jul 25, 2025
0d86455
Update README.md
jesmannstl Jul 25, 2025
8644c8b
Update README.md
jesmannstl Jul 25, 2025
6ca7fb7
Update tvlistings.ts
jesmannstl Jul 25, 2025
4b8246d
Add files via upload
jesmannstl Jul 26, 2025
1430851
Update README.md
jesmannstl Jul 26, 2025
b88f82f
Made add Series to non-movie by default
jesmannstl Jul 27, 2025
9ba3fee
Removed --includeSeriesGenre option as built in
jesmannstl Jul 27, 2025
8f0edbf
Update tvlistings.ts
jesmannstl Jul 29, 2025
3c10e5b
updates
roblatour Jul 30, 2025
652277d
Update README.md
jesmannstl Jul 31, 2025
840055d
updates
roblatour Jul 31, 2025
b0476cb
Update config.ts
roblatour Jul 31, 2025
bea355e
Merge upstream changes and resolve README conflicts - Remove --includ…
roblatour Jul 31, 2025
0328c9e
Merge pull request #3 from roblatour/main
jesmannstl Aug 3, 2025
3dcf717
Update <date> add. ep. naming --addAsterisk option
jesmannstl Aug 4, 2025
04d81ff
Update <date> add. ep. naming --addAsterisk option
jesmannstl Aug 4, 2025
33e5472
Update README.md
jesmannstl Aug 4, 2025
28cc6c2
Update README.md --appendAsterisk
jesmannstl Aug 4, 2025
1df1640
Minor correction
jesmannstl Aug 4, 2025
45bb262
Added SYYYYEMMDD to Series without any ex (News)
jesmannstl Aug 4, 2025
8ded7d6
Update ci.yaml
jesmannstl Aug 4, 2025
2e6da8d
Delete .github/workflows/ci.yaml
jesmannstl Aug 4, 2025
6124c7f
Create ci.yml
jesmannstl Aug 4, 2025
d2475c2
Create docker-image.yml
jesmannstl Aug 4, 2025
d1048dc
Update README.md
jesmannstl Aug 4, 2025
a165763
Update nightly-release.yaml
jesmannstl Aug 4, 2025
7dbd11f
Update nightly-release.yaml
jesmannstl Aug 4, 2025
9d5163e
Update README.md
jesmannstl Aug 4, 2025
adc7a67
Update Season Episode if not Movie/Sports
jesmannstl Aug 5, 2025
3c6be3b
Updated Changelog with all updates since 7/22
jesmannstl Aug 6, 2025
2242456
Update xmltv.ts
jesmannstl Aug 6, 2025
122d987
Added changes on this fork
jesmannstl Aug 6, 2025
5fa1723
Update README.md with recent updates
jesmannstl Aug 6, 2025
e6748ef
Update README.md with recent updates
jesmannstl Aug 6, 2025
1c855ed
Added many countries and mediaportal option
jesmannstl Aug 6, 2025
7c11fa0
Updated options and country
jesmannstl Aug 6, 2025
db5eae2
Update Valid Country Codes.md
jesmannstl Aug 6, 2025
7d4f403
Update README.md
jesmannstl Aug 6, 2025
c0c99d4
Removed icon width for better viewing
jesmannstl Aug 7, 2025
dbecf0b
Merge branch 'main' of https://github.com/jesmannstl/zap2xml
jesmannstl Aug 7, 2025
2d1ed65
Update README.md
jesmannstl Aug 7, 2025
1d9a836
Update README.md
jesmannstl Aug 7, 2025
f1fb732
Updated date tag added length
jesmannstl Aug 7, 2025
0850ccb
Update README.md
jesmannstl Aug 7, 2025
9b84599
Update FUNDING.yml
jesmannstl Aug 7, 2025
8710a1f
Postal Code not required except OTA
jesmannstl Aug 8, 2025
dad2b56
Reordered Program fields to match original Perl output order
jesmannstl Aug 8, 2025
0089561
Fixed Sorting by channel/time
jesmannstl Aug 10, 2025
3de1db4
Fixed "dd_progid" tag
jesmannstl Aug 10, 2025
c739794
chore(main): release 2.2.1 (#1)
github-actions[bot] Aug 11, 2025
cae96f3
Update README.md with Lineup links
jesmannstl Aug 11, 2025
7089c83
Update README.md With lineup links
jesmannstl Aug 11, 2025
42983e2
Update tvlistings order to fix bad request
jesmannstl Aug 19, 2025
8da11bd
Added Display Name with Channel Number and Call Sign
jesmannstl Aug 19, 2025
ae890e5
Added --nextpvr option
jesmannstl Aug 19, 2025
4bdcd77
Update CHANGELOG.md
jesmannstl Aug 19, 2025
0abeba5
Changed default sort add sort options
jesmannstl Aug 21, 2025
0368fe7
Merge branch 'main' of https://github.com/jesmannstl/zap2xml
jesmannstl Aug 21, 2025
7b301ae
Update FUNDING.yml
jesmannstl Sep 7, 2025
22835d6
Enhanced buildProgramsXml to check neighboring entries for exact obje…
Fillimerica Oct 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
183 changes: 92 additions & 91 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,91 +1,92 @@
# zap2xml

Automate TV guides to XMLTV format. Easy to use, up-to-date. See below for getting started.

I also _somewhat_ maintain a version of the original in the [historical-perl branch](https://github.com/jef/zap2xml/tree/historical-perl) if you're interested in that.

## How to use

### Node.js

```bash
npm i && npm run build && node dist/index.js
```

See [Command line arguments](#command-line-arguments) for configuration options.

### Docker

| Tag | Description |
| ------- | ----------------------- |
| latest | Stable zap2xml releases |
| nightly | HEAD zap2xml release |

#### docker-compose

```yaml
services:
zap2xml:
container_name: zap2xml
image: ghcr.io/jef/zap2xml:latest
environment:
OUTPUT_FILE: /xmltv/xmltv.xml
volumes:
- ./xmltv:/xmltv
restart: unless-stopped
```

See [Environment variables](#environment-variables) for configuration options.

## Configuration

### Environment variables

| Variable | Description | Default |
| ------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| `LINEUP_ID` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | `USA-lineupId-DEFAULT` (Attenna) |
| `TIMESPAN` | Timespan in hours (up to 360 = 15 days, default: 6) | 6 |
| `PREF` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | (empty) |
| `COUNTRY` | Country code (default: `USA`) | USA |
| `POSTAL_CODE` | Postal code of where shows are available. | 30309 |
| `USER_AGENT` | Custom user agent string for HTTP requests. | Uses random if not specified |
| `TZ` | Timezone | System default |
| `SLEEP_TIME` | Sleep time before next run in seconds (default: 21600, Only used with Docker.) | 21600 |
| `OUTPUT_FILE` | Output file name (default: xmltv.xml) | xmltv.xml |

### Command line arguments

| Argument | Description | Default |
| -------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| `--lineupId` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | `USA-lineupId-DEFAULT` (Attenna) |
| `--timespan` | Timespan in hours (up to 360 = 15 days, default: 6) | 6 |
| `--pref` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | (empty) |
| `--country` | Country code (default: `USA`) | USA |
| `--postalCode` | Postal code of where shows are available. | 30309 |
| `--userAgent` | Custom user agent string for HTTP requests. | Uses random if not specified |
| `--timezone` | Timezone | System default |
| `--outputFile` | Output file name (default: xmltv.xml) | xmltv.xml |

## Setup and running in intervals

### Running natively

You can run zap2xml natively on your system. It is recommended to use a task scheduler to run it in intervals.

Here are some links to get you started on your machine:

- Linux and Raspberry Pi: https://github.com/jef/zap2xml/wiki/Running-on-Linux-and-Raspberry-Pi
- macOS: https://github.com/jef/zap2xml/wiki/Running-on-macOS
- Windows: https://github.com/jef/zap2xml/wiki/Running-on-Windows

If you want to run zap2xml in intervals, you can use a task scheduler like `cron` on Linux or the Task Scheduler on Windows. Each of the wiki pages above has a section on how to set up zap2xml to run in intervals.

### Running in Docker

You can run zap2xml in a Docker container. The `SLEEP_TIME` environment variable can be used to set the interval between runs. The default is 21600 seconds (6 hours).

## FAQ

### How do I get my Lineup ID?

Visit https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID
# zap2xml

Automate TV guides to XMLTV format. Easy to use, up-to-date. See below for getting started.

I also _somewhat_ maintain a version of the original in the [historical-perl branch](https://github.com/jef/zap2xml/tree/historical-perl) if you're interested in that.

## How to use

### Node.js

```bash
npm i && npm run build && node dist/index.js
```

See [Command line arguments](#command-line-arguments) for configuration options.

### Docker

| Tag | Description |
| ------- | ----------------------- |
| latest | Stable zap2xml releases |
| nightly | HEAD zap2xml release |

#### docker-compose

```yaml
services:
zap2xml:
container_name: zap2xml
image: ghcr.io/jef/zap2xml:latest
environment:
OUTPUT_FILE: /xmltv/xmltv.xml
volumes:
- ./xmltv:/xmltv
restart: unless-stopped
```

See [Environment variables](#environment-variables) for configuration options.

## Configuration

### Environment variables

| Variable | Description | Default |
| ------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| `LINEUP_ID` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | `USA-lineupId-DEFAULT` (Attenna) |
| `TIMESPAN` | Timespan in hours (up to 360 = 15 days, default: 6) | 6 |
| `PREF` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | (empty) |
| `COUNTRY` | Country code (default: `USA`) | USA |
| `POSTAL_CODE` | Postal code of where shows are available. | 30309 |
| `USER_AGENT` | Custom user agent string for HTTP requests. | Uses random if not specified |
| `TZ` | Timezone | System default |
| `SLEEP_TIME` | Sleep time before next run in seconds (default: 21600, Only used with Docker.) | 21600 |
| `OUTPUT_FILE` | Output file name (default: xmltv.xml) | xmltv.xml |

### Command line arguments

| Argument | Description | Default |
| -------------- | --------------------------------------------------------------------------------------------------------------- | -------------------------------- |
| `--lineupId` | Lineup ID; Read more in the [Wiki](https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID) | `USA-lineupId-DEFAULT` (Attenna) |
| `--timespan` | Timespan in hours (up to 360 = 15 days, default: 6) | 6 |
| `--pref` | User Preferences, comma separated list. `m` for showing music, `p` for showing pay-per-view, `h` for showing HD | (empty) |
| `--country` | Country code (default: `USA`) | USA |
| `--postalCode` | Postal code of where shows are available. | 30309 |
| `--userAgent` | Custom user agent string for HTTP requests. | Uses random if not specified |
| `--timezone` | Timezone | System default |
| `--includeSeriesGenre` | Add `<category>Series</category>` to programs without a category | |
| `--outputFile` | Output file name (default: xmltv.xml) | xmltv.xml |

## Setup and running in intervals

### Running natively

You can run zap2xml natively on your system. It is recommended to use a task scheduler to run it in intervals.

Here are some links to get you started on your machine:

- Linux and Raspberry Pi: https://github.com/jef/zap2xml/wiki/Running-on-Linux-and-Raspberry-Pi
- macOS: https://github.com/jef/zap2xml/wiki/Running-on-macOS
- Windows: https://github.com/jef/zap2xml/wiki/Running-on-Windows

If you want to run zap2xml in intervals, you can use a task scheduler like `cron` on Linux or the Task Scheduler on Windows. Each of the wiki pages above has a section on how to set up zap2xml to run in intervals.

### Running in Docker

You can run zap2xml in a Docker container. The `SLEEP_TIME` environment variable can be used to set the interval between runs. The default is 21600 seconds (6 hours).

## FAQ

### How do I get my Lineup ID?

Visit https://github.com/jef/zap2xml/wiki/Retrieving-Lineup-ID
136 changes: 68 additions & 68 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,68 @@
import { UserAgent } from "./useragents.js";

export function processLineupId(): string {
const lineupId =
process.env["LINEUP_ID"] ||
process.argv.find((arg) => arg.startsWith("--lineupId="))?.split("=")[1] ||
"USA-lineupId-DEFAULT";

if (lineupId.includes("OTA")) {
return "USA-lineupId-DEFAULT";
}

return lineupId;
}

export function getHeadendId(lineupId: string): string {
if (lineupId.includes("OTA")) {
return "lineupId";
}

const match = lineupId.match(/^(USA|CAN)-(.*?)(?:-[A-Z]+)?$/);

return match?.[2] || "lineup";
}

export function getConfig() {
const lineupId = processLineupId();
const headendId = getHeadendId(lineupId);

return {
baseUrl: "https://tvlistings.gracenote.com/api/grid",
lineupId,
headendId,
timespan:
process.env["TIMESPAN"] ||
process.argv
.find((arg) => arg.startsWith("--timespan="))
?.split("=")[1] ||
"6",
country:
process.env["COUNTRY"] ||
process.argv.find((arg) => arg.startsWith("--country="))?.split("=")[1] ||
"USA",
postalCode:
process.env["POSTAL_CODE"] ||
process.argv
.find((arg) => arg.startsWith("--postalCode="))
?.split("=")[1] ||
"30309",
pref:
process.env["PREF"] ||
process.argv.find((arg) => arg.startsWith("--pref="))?.split("=")[1] ||
"",
timezone: process.env.TZ || "America/New_York",
userAgent:
process.env["USER_AGENT"] ||
process.argv
.find((arg) => arg.startsWith("--userAgent="))
?.split("=")[1] ||
UserAgent,
outputFile:
process.env["OUTPUT_FILE"] ||
process.argv
.find((arg) => arg.startsWith("--outputFile="))
?.split("=")[1] ||
"xmltv.xml",
};
}
import { UserAgent } from "./useragents.js";
export function processLineupId(): string {
const lineupId =
process.env["LINEUP_ID"] ||
process.argv.find((arg) => arg.startsWith("--lineupId="))?.split("=")[1] ||
"USA-lineupId-DEFAULT";
if (lineupId.includes("OTA")) {
return "USA-lineupId-DEFAULT";
}
return lineupId;
}
export function getHeadendId(lineupId: string): string {
if (lineupId.includes("OTA")) {
return "lineupId";
}
const match = lineupId.match(/^(USA|CAN)-(.*?)(?:-[A-Z]+)?$/);
return match?.[2] || "lineup";
}
export function getConfig() {
const lineupId = processLineupId();
const headendId = getHeadendId(lineupId);
return {
baseUrl: "https://tvlistings.gracenote.com/api/grid",
lineupId,
headendId,
timespan:
process.env["TIMESPAN"] ||
process.argv
.find((arg) => arg.startsWith("--timespan="))
?.split("=")[1] ||
"6",
country:
process.env["COUNTRY"] ||
process.argv.find((arg) => arg.startsWith("--country="))?.split("=")[1] ||
"USA",
postalCode:
process.env["POSTAL_CODE"] ||
process.argv
.find((arg) => arg.startsWith("--postalCode="))
?.split("=")[1] ||
"30309",
pref:
process.env["PREF"] ||
process.argv.find((arg) => arg.startsWith("--pref="))?.split("=")[1] ||
"",
timezone: process.env.TZ || "America/New_York",
userAgent:
process.env["USER_AGENT"] ||
process.argv
.find((arg) => arg.startsWith("--userAgent="))
?.split("=")[1] ||
UserAgent,
outputFile:
process.env["OUTPUT_FILE"] ||
process.argv
.find((arg) => arg.startsWith("--outputFile="))
?.split("=")[1] ||
"xmltv.xml",
};
}
Loading