mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-09 08:30:06 -04:00
Merge branch 'patch-2025.01.2' into patch-2025.04.1
This commit is contained in:
commit
281a581ed8
7 changed files with 2600 additions and 114 deletions
20
Dockerfile
Normal file
20
Dockerfile
Normal file
|
@ -0,0 +1,20 @@
|
|||
FROM node:22-alpine
|
||||
ARG GIT_REPO=https://github.com/iptv-org/epg.git
|
||||
ARG GIT_BRANCH=master
|
||||
ARG USER=iptv-org
|
||||
ARG WORKDIR=/epg
|
||||
WORKDIR $WORKDIR
|
||||
RUN apk update \
|
||||
&& apk upgrade --no-cache \
|
||||
&& apk add --no-cache git tzdata bash \
|
||||
&& npm install -g npm@latest \
|
||||
&& git clone --depth 1 -b $(echo "${GIT_BRANCH} ${GIT_REPO}") . \
|
||||
&& npm install \
|
||||
&& mkdir /public \
|
||||
&& adduser -D $USER \
|
||||
&& chown -R $USER $WORKDIR \
|
||||
&& cd $WORKDIR \
|
||||
&& apk del git
|
||||
USER $USER
|
||||
EXPOSE 3000
|
||||
CMD [ "npx", "pm2-runtime", "pm2.config.js" ]
|
142
README.md
142
README.md
|
@ -7,6 +7,7 @@ Tools for downloading the EPG (Electronic Program Guide) for thousands of TV cha
|
|||
- ✨ [Installation](#installation)
|
||||
- 🚀 [Usage](#usage)
|
||||
- 💫 [Update](#update)
|
||||
- 🐋 [Docker](#docker)
|
||||
- 📺 [Playlists](#playlists)
|
||||
- 🗄 [Database](#database)
|
||||
- 👨💻 [API](#api)
|
||||
|
@ -39,13 +40,15 @@ npm install
|
|||
|
||||
## Usage
|
||||
|
||||
To start the download of the guide, select one of the [supported sites](SITES.md) and paste its name into the command below:
|
||||
To start the download of the guide, select one of the supported sites from [SITES.md](SITES.md) file and paste its name into the command below:
|
||||
|
||||
```sh
|
||||
npm run grab --- --site=example.com
|
||||
```
|
||||
|
||||
And once the download is complete, the guide will be saved to the `guide.xml` file.
|
||||
Then run it and wait for the guide to finish downloading. When finished, a new `guide.xml` file will appear in the current directory.
|
||||
|
||||
You can also customize the behavior of the script using this options:
|
||||
|
||||
```sh
|
||||
Usage: npm run grab --- [options]
|
||||
|
@ -55,35 +58,13 @@ Options:
|
|||
-c, --channels <path> Path to *.channels.xml file (required if the "--site" attribute is
|
||||
not specified)
|
||||
-o, --output <path> Path to output file (default: "guide.xml")
|
||||
-l, --lang <code> Filter channels by language (ISO 639-2 code)
|
||||
-t, --timeout <milliseconds> Override the default timeout for each request
|
||||
-d, --delay <milliseconds> Override the default delay between request
|
||||
-l, --lang <code> Allows to limit the download to channels in the specified language only (ISO 639-1 code)
|
||||
-t, --timeout <milliseconds> Timeout for each request in milliseconds (default: 0)
|
||||
-d, --delay <milliseconds> Delay between request in milliseconds (default: 0)
|
||||
-x, --proxy <url> Use the specified proxy (example: "socks5://username:password@127.0.0.1:1234")
|
||||
--days <days> Override the number of days for which the program will be loaded
|
||||
(defaults to the value from the site config)
|
||||
--maxConnections <number> Limit on the number of concurrent requests (default: 1)
|
||||
--cron <expression> Schedule a script run (example: "0 0 * * *")
|
||||
--gzip Create a compressed version of the guide as well (default: false)
|
||||
```
|
||||
|
||||
### Access the guide by URL
|
||||
|
||||
You can make the guide available via URL by running your own server:
|
||||
|
||||
```sh
|
||||
npm run serve
|
||||
```
|
||||
|
||||
After that, the guide will be available at the link:
|
||||
|
||||
```
|
||||
http://localhost:3000/guide.xml
|
||||
```
|
||||
|
||||
In addition it will be available to other devices on the same local network at the address:
|
||||
|
||||
```
|
||||
http://<your_local_ip_address>:3000/guide.xml
|
||||
--days <days> Number of days for which the program will be loaded (defaults to the value from the site config)
|
||||
--maxConnections <number> Number of concurrent requests (default: 1)
|
||||
--gzip Specifies whether or not to create a compressed version of the guide (default: false)
|
||||
```
|
||||
|
||||
### Parallel downloading
|
||||
|
@ -116,12 +97,42 @@ npm run grab --- --channels=path/to/custom.channels.xml
|
|||
|
||||
### Run on schedule
|
||||
|
||||
If you want to download the guide automatically on a schedule, you need to pass a valid [cron expression](https://crontab.guru/) to the script using the `--cron` attribute:
|
||||
To download the guide on a schedule, you can use the included process manager. Just run it with desire [cron expression](https://crontab.guru/) and the `grab` options:
|
||||
|
||||
```sh
|
||||
npm run grab --- --site=example.com --cron="0 0 * * *"
|
||||
npx pm2 start npm --no-autorestart --cron-restart="0 0,12 * * *" -- run grab --- --site=example.com
|
||||
```
|
||||
|
||||
To track the process, you can use the command:
|
||||
|
||||
```sh
|
||||
npx pm2 logs
|
||||
```
|
||||
|
||||
For more info go to [pm2](https://pm2.keymetrics.io/docs/usage/quick-start/) documentation.
|
||||
|
||||
### Access the guide by URL
|
||||
|
||||
You can make the guide available via URL by running your own server. The easiest way to do this is to run this command:
|
||||
|
||||
```sh
|
||||
npx serve
|
||||
```
|
||||
|
||||
After that, the guide will be available at the link:
|
||||
|
||||
```
|
||||
http://localhost:3000/guide.xml
|
||||
```
|
||||
|
||||
In addition it will be available to other devices on the same local network at the address:
|
||||
|
||||
```
|
||||
http://<your_local_ip_address>:3000/guide.xml
|
||||
```
|
||||
|
||||
For more info go to [serve](https://github.com/vercel/serve) documentation.
|
||||
|
||||
## Update
|
||||
|
||||
If you have downloaded the repository code according to the instructions above, then to update it will be enough to run the command:
|
||||
|
@ -136,6 +147,73 @@ And then update all the dependencies:
|
|||
npm install
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
### Build an image
|
||||
|
||||
```sh
|
||||
docker build -t iptv-org/epg --no-cache .
|
||||
```
|
||||
|
||||
### Create and run container
|
||||
|
||||
```sh
|
||||
docker run -p 3000:3000 -e SITE=example.com iptv-org/epg
|
||||
```
|
||||
|
||||
To use your [custom channel list](#use-custom-channel-list) pass the path to it via the [--volume](https://docs.docker.com/engine/storage/volumes/#options-for---volume) option:
|
||||
|
||||
```sh
|
||||
docker run -p 3000:3000 -v /path/to/channels.xml:/epg/channels.xml iptv-org/epg
|
||||
```
|
||||
|
||||
By default, the guide will be downloaded only once and saved to the `/epg/public/guide.xml` file inside the container.
|
||||
|
||||
From the outside, it will be available at this link:
|
||||
|
||||
```
|
||||
http://localhost:3000/guide.xml
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```
|
||||
http://<your_local_ip_address>:3000/guide.xml
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
To fine-tune the execution, you can pass environment variables to the container as follows:
|
||||
|
||||
```sh
|
||||
docker run \
|
||||
-p 5000:3000 \
|
||||
-e SITE=example.com \
|
||||
-e CLANG=fr \
|
||||
-e CRON="0 0,12 * * *" \
|
||||
-e PROXY="socks5://username:password@127.0.0.1:1234" \
|
||||
-e MAX_CONNECTIONS=10 \
|
||||
-e GZIP=true \
|
||||
-e DAYS=14 \
|
||||
-e TIMEOUT=5 \
|
||||
-e DELAY=2 \
|
||||
iptv-org/epg
|
||||
```
|
||||
|
||||
| Variable | Description |
|
||||
| --------------- | ------------------------------------------------------------------------------------------------------------------------- |
|
||||
| SITE | Name of the site to parse |
|
||||
| CLANG | Limit the download to channels in the specified language only ([ISO 639-1](https://en.wikipedia.org/wiki/ISO_639-1) code) |
|
||||
| CRON | A [cron expression](https://crontab.guru/) describing the schedule of the guide loadings (by default will run once) |
|
||||
| PROXY | Use the specified proxy |
|
||||
| MAX_CONNECTIONS | Limit on the number of concurrent requests (default: 1) |
|
||||
| GZIP | Boolean value indicating whether to create a compressed version of the guide (default: false) |
|
||||
| DAYS | Number of days for which the guide will be loaded (defaults to the value from the site config) |
|
||||
| TIMEOUT | Timeout for each request in milliseconds (default: 0) |
|
||||
| DELAY | Delay between request in milliseconds (default: 0) |
|
||||
|
||||
For more info go to [Docker](https://docs.docker.com/get-started/) documentation.
|
||||
|
||||
## Playlists
|
||||
|
||||
Playlists with already linked guides can be found in the [iptv-org/iptv](https://github.com/iptv-org/iptv) repository.
|
||||
|
|
1785
package-lock.json
generated
1785
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -12,7 +12,6 @@
|
|||
"sites:init": "npx tsx scripts/commands/sites/init.ts",
|
||||
"sites:update": "npx tsx scripts/commands/sites/update.ts",
|
||||
"grab": "npx tsx scripts/commands/epg/grab.ts",
|
||||
"serve": "npx serve",
|
||||
"lint": "npx eslint \"{scripts,tests,sites}/**/*.{ts,mts,js}\"",
|
||||
"test": "run-script-os",
|
||||
"test:win32": "SET \"TZ=Pacific/Nauru\" && npx jest --runInBand",
|
||||
|
@ -63,7 +62,6 @@
|
|||
"cli-progress": "^3.12.0",
|
||||
"commander": "^8.2.0",
|
||||
"consola": "^3.2.3",
|
||||
"cron": "^2.4.3",
|
||||
"csv-parser": "^3.0.0",
|
||||
"cwait": "^1.1.2",
|
||||
"dayjs": "^1.11.10",
|
||||
|
@ -93,6 +91,7 @@
|
|||
"pako": "^2.1.0",
|
||||
"parse-duration": "^1.0.0",
|
||||
"pdf-parse": "^1.1.1",
|
||||
"pm2": "^5.4.3",
|
||||
"readline": "^1.3.0",
|
||||
"run-script-os": "^1.1.6",
|
||||
"serve": "^14.2.4",
|
||||
|
|
23
pm2.config.js
Normal file
23
pm2.config.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: 'serve',
|
||||
script: 'npx serve -- public',
|
||||
instances: 1,
|
||||
watch: false,
|
||||
autorestart: true
|
||||
},
|
||||
{
|
||||
name: 'grab',
|
||||
script: process.env.SITE
|
||||
? `npm run grab -- --site=${process.env.SITE} ${
|
||||
process.env.CLANG ? `--lang=${process.env.CLANG}` : ''
|
||||
} --output=public/guide.xml`
|
||||
: 'npm run grab -- --channels=channels.xml --output=public/guide.xml',
|
||||
cron_restart: process.env.CRON || null,
|
||||
instances: 1,
|
||||
watch: false,
|
||||
autorestart: false
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,35 +1,49 @@
|
|||
import { Logger, Timer, Storage, Collection } from '@freearhey/core'
|
||||
import { program } from 'commander'
|
||||
import { CronJob } from 'cron'
|
||||
import { Option, program } from 'commander'
|
||||
import { QueueCreator, Job, ChannelsParser } from '../../core'
|
||||
import { Channel } from 'epg-grabber'
|
||||
import path from 'path'
|
||||
import { SITES_DIR } from '../../constants'
|
||||
|
||||
program
|
||||
.option('-s, --site <name>', 'Name of the site to parse')
|
||||
.option(
|
||||
.addOption(new Option('-s, --site <name>', 'Name of the site to parse'))
|
||||
.addOption(
|
||||
new Option(
|
||||
'-c, --channels <path>',
|
||||
'Path to *.channels.xml file (required if the "--site" attribute is not specified)'
|
||||
)
|
||||
.option('-o, --output <path>', 'Path to output file', 'guide.xml')
|
||||
.option('-l, --lang <code>', 'Filter channels by language (ISO 639-2 code)')
|
||||
.option('-t, --timeout <milliseconds>', 'Override the default timeout for each request')
|
||||
.option('-d, --delay <milliseconds>', 'Override the default delay between request')
|
||||
.option('-x, --proxy <url>', 'Use the specified proxy')
|
||||
.option(
|
||||
)
|
||||
.addOption(new Option('-o, --output <path>', 'Path to output file').default('guide.xml'))
|
||||
.addOption(new Option('-l, --lang <code>', 'Filter channels by language (ISO 639-1 code)'))
|
||||
.addOption(
|
||||
new Option('-t, --timeout <milliseconds>', 'Override the default timeout for each request').env(
|
||||
'TIMEOUT'
|
||||
)
|
||||
)
|
||||
.addOption(
|
||||
new Option('-d, --delay <milliseconds>', 'Override the default delay between request').env(
|
||||
'DELAY'
|
||||
)
|
||||
)
|
||||
.addOption(new Option('-x, --proxy <url>', 'Use the specified proxy').env('PROXY'))
|
||||
.addOption(
|
||||
new Option(
|
||||
'--days <days>',
|
||||
'Override the number of days for which the program will be loaded (defaults to the value from the site config)',
|
||||
value => parseInt(value)
|
||||
'Override the number of days for which the program will be loaded (defaults to the value from the site config)'
|
||||
)
|
||||
.option(
|
||||
'--maxConnections <number>',
|
||||
'Limit on the number of concurrent requests',
|
||||
value => parseInt(value),
|
||||
1
|
||||
.argParser(value => parseInt(value))
|
||||
.env('DAYS')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--maxConnections <number>', 'Limit on the number of concurrent requests')
|
||||
.default(1)
|
||||
.env('MAX_CONNECTIONS')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--gzip', 'Create a compressed version of the guide as well')
|
||||
.default(false)
|
||||
.env('GZIP')
|
||||
)
|
||||
.option('--cron <expression>', 'Schedule a script run (example: "0 0 * * *")')
|
||||
.option('--gzip', 'Create a compressed version of the guide as well', false)
|
||||
.parse(process.argv)
|
||||
|
||||
export type GrabOptions = {
|
||||
|
@ -42,7 +56,6 @@ export type GrabOptions = {
|
|||
delay?: string
|
||||
lang?: string
|
||||
days?: number
|
||||
cron?: string
|
||||
proxy?: string
|
||||
}
|
||||
|
||||
|
@ -81,19 +94,9 @@ async function main() {
|
|||
}
|
||||
logger.info(` found ${parsedChannels.count()} channel(s)`)
|
||||
|
||||
let runIndex = 1
|
||||
if (options.cron) {
|
||||
const cronJob = new CronJob(options.cron, async () => {
|
||||
logger.info(`run #${runIndex}:`)
|
||||
await runJob({ logger, parsedChannels })
|
||||
runIndex++
|
||||
})
|
||||
cronJob.start()
|
||||
} else {
|
||||
logger.info(`run #${runIndex}:`)
|
||||
logger.info('run:')
|
||||
runJob({ logger, parsedChannels })
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue