Compare commits

..

No commits in common. "main" and "1.0.10" have entirely different histories.
main ... 1.0.10

15 changed files with 181 additions and 800 deletions

View File

@ -38,11 +38,6 @@ jobs:
id: meta
uses: docker/metadata-action@v5
with:
labels: |
org.opencontainers.image.title=epg-info
org.opencontainers.image.description=Docker image of https://github.com/iptv-org/epg
org.opencontainers.image.authors=Davidquinonescl
org.opencontainers.image.documentation=https://git.claeyscloud.com/david/epg-info-docker/src/branch/main/README.md
images: |
davidquinonescl/epg-info
git.claeyscloud.com/david/epg-info

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
github: davidclaeysquinones

View File

@ -24,11 +24,6 @@ jobs:
id: meta
uses: docker/metadata-action@v5
with:
labels: |
org.opencontainers.image.title=epg-info
org.opencontainers.image.description=Docker image of https://github.com/iptv-org/epg
org.opencontainers.image.authors=Davidquinonescl
org.opencontainers.image.documentation=https://github.com/davidclaeysquinones/epg-info-docker/blob/main/README.md
images: ghcr.io/davidclaeysquinones/epg-info
tags: |
type=semver,pattern={{raw}}

View File

@ -1,10 +1,8 @@
FROM node:22-alpine
FROM node:21-alpine
ARG GIT_REPO=https://github.com/iptv-org/epg.git
ARG GIT_BRANCH=master
ENV CRON_SCHEDULE="0 0,12 * * *"
ENV API_URL="https://iptv-org.github.io/api"
ENV DAYS=14
ENV DELAY=0
ENV MAX_CONNECTIONS=10
ENV ENABLE_FIXES=false
ARG BIN_FOLDER=/bin
@ -24,8 +22,7 @@ RUN apk update \
&& mkdir $(echo "${BIN_FOLDER}/${EPG_FOLDER}") -p \
&& git -C $(echo "${BIN_FOLDER}") clone --depth 1 -b $(echo "${GIT_BRANCH} ${GIT_REPO}") \
&& cd $WORKDIR && npm install && npm update \
&& rm -rf .sites \
&& rm -rf .husky \
&& rm .eslintrc.json \
&& rm -rf .github \
&& rm -rf .git \
&& rm .gitignore \
@ -43,20 +40,14 @@ RUN apk update \
&& rm -rf node_modules/**/.github \
&& rm -rf node_modules/**/docs \
&& rm -rf node_modules/**/LICENSE \
&& rm -rf node_modules/**/license \
&& rm -rf node_modules/**/**.md \
&& rm -rf node_modules/**/**/LICENSE \
&& rm -rf node_modules/**/**/license \
&& rm -rf node_modules/**/**/.github \
&& rm -rf node_modules/**/**/**.md \
&& ln -s /config/channels.xml $(echo "${WORKDIR}/channels.xml") \
&& mkdir /public
COPY start.sh $WORKDIR
COPY serve.json $WORKDIR
COPY pm2.config.js $WORKDIR
RUN chmod +x "$START_SCRIPT" \
&& apk del git curl \
&& rm -rf /var/cache/apk/*
SHELL ["/bin/bash", "-c"]
ENTRYPOINT bash $START_SCRIPT chron-schedule="$CRON_SCHEDULE" work-dir="$WORKDIR" days="$DAYS" delay=$DELAY max_connections="$MAX_CONNECTIONS" enable_fixes="$ENABLE_FIXES" api_url="$API_URL"
ENTRYPOINT bash $START_SCRIPT chron-schedule="$CRON_SCHEDULE" work-dir="$WORKDIR" days="$DAYS" max_connections="$MAX_CONNECTIONS" enable_fixes="$ENABLE_FIXES"
EXPOSE 3000

View File

@ -1,9 +0,0 @@
MIT License
Copyright (c) 2024 David Claeys
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

155
README.md
View File

@ -11,7 +11,7 @@ A public mirror is available at https://github.com/davidclaeysquinones/epg-info-
[pm2](https://www.npmjs.com/package/pm2)<br>
[serve](https://www.npmjs.com/package/serve)<br>
The image is based on `node:22-alpine` in order to be more lightweight.
The image is based on `node:21-alpine` in order to be more lightweight.
The `pm2` and `serve` packages are used in order to run the application in the container.
## Docker image
@ -32,34 +32,19 @@ You can do this by creating a mapping in the `/config` folder.
#### Custom fixes
Through the `ENABLE_FIXES` variable custom provider fixes can be applied to the container.
By default some fixes are available. These fixes have been validated before being added to this repo.
However this option is disabled by default since you might only want to run the unmodified source.
If you have suggestions or a problem with them please submit an issue.
This the list of the provided custom fixes :
| Provider | Author(s) | Status |
|--------------------|------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| movistarplus.es | [davidclaeysquinones](https://github.com/davidclaeysquinones) | [PR](https://github.com/iptv-org/epg/pull/2440) pending approval |
| orangetv.orange.es | [fraudiay79](https://github.com/fraudiay79) and [davidclaeysquinones](https://github.com/davidclaeysquinones) | [PR](https://github.com/iptv-org/epg/pull/2485) merged since commit [8a8262e](https://github.com/iptv-org/epg/commit/8a8262eacb46b2d35df7eb11f46de22263eab053) |
| pickx.be | [davidclaeysquinones](https://github.com/davidclaeysquinones) and [BellezaEmporium](https://github.com/BellezaEmporium) | [PR](https://github.com/iptv-org/epg/pull/2525) merged since commit [fd91a9c](https://github.com/iptv-org/epg/commit/fd91a9c532b476f6e192a564371d30e766b762ab) |
| telenet.tv | [davidclaeysquinones](https://github.com/davidclaeysquinones) | [PR](https://github.com/iptv-org/epg/pull/2429) merged since commit [fd382db](https://github.com/iptv-org/epg/commit/fd382db08da7a96150928b8dcfef115e29e661d3) |
| web.magentatv.de | [klausellus-wallace](https://github.com/klausellus-wallace) | [PR](https://github.com/iptv-org/epg/pull/2458) merged since commit [61afe09](https://github.com/iptv-org/epg/commit/61afe090b6e7892cc5426457d960e9452222f885) |
By default some fixes are available. If you have suggestions or a problem with them please submit an issue.
If for some reason you want to include your own provider fixes this is possible by creation a mapping in the `/fixes` folder.<br>
The expected structure is */fixes/`provider_name`/`provider_name`.config.js*.<br>
It is recommended that you take existing provider code as a base for your customisations.
### Environment Variables
| Variable | Description | Default |
|-------------------------------|----------------------------------------------------------------------------|----------------------------------|
| CRON_SCHEDULE | CRON expression describing the recurrence for epg retrieval. | `0 0,12 * * *` |
| DAYS | Describes the desired amount of days in the future for for epg retrieval. | 14 |
| DELAY | Delay between requests in milliseconds | 0 |
| MAX_CONNECTIONS | The maximum amount of parallel connections that can be established | 10 |
| Variable | Description | Default |
|-------------------------------|----------------------------------------------------------------------------|------------------|
| CRON_SCHEDULE | CRON expression describing the recurrence for epg retrieval. | `0 0,12 * * *` |
| DAYS | Describes the desired amount of days in the future for for epg retrieval. | 14 |
| MAX_CONNECTIONS | The maximum amount of parallel connections that can be established | 10 |
| ENABLE_FIXES | Some fixes to providers take a long time to be merged into the main branch.<br>When this option is enabled some of these fixes will also be included.<br>The source code for these fixes can be seen under the `fixes` folder.<br> Recreate the container when changing this variable in order for it to take effect | false |
| API_URL | The endpoint where channel information will be grabbed | `https://iptv-org.github.io/api` |
### Compose file
@ -87,131 +72,29 @@ services:
This image is bound to the content of the [iptv-org/epg](https://github.com/iptv-org/epg) repository. In the underlying list you can see to which commit each version of the docker image is bound.
Normally when a change is made in the source repository the documentation is updated and a new tag is created in this repository. This is completely normal since the source repository is only cloned during the build process of the docker image.
Normally when a change is made in the source repository the documention is updated and a new tag is created in this repository. This is completely normal since the source repository is only cloned during the build process of the docker image.
Sometimes a new version of this image will be bound to the same source commit. This will happen when improvements are made to the image.
- 1.0.0 &nbsp;
- 1.0.0
[08-01-2024](https://github.com/iptv-org/epg/commit/793c74ca397504fc2afc8fbfa998e0b8e4ca45d9)
- 1.0.1 &nbsp;
- 1.0.1
[08-14-2024](https://github.com/iptv-org/epg/commit/270e85cfae6f0f691c2e6ab7ce511d60fd687565)
- 1.0.2 &nbsp;
- 1.0.2
[09-07-2024](https://github.com/iptv-org/epg/commit/4e3b06a86e225cdd1b9362a683e6770fb68ff28f)
- 1.0.3 &nbsp;
- 1.0.3
[09-14-2024](https://github.com/iptv-org/epg/commit/c69f3c93b1123ddf0fecc62c7067fced59ae4e99)
- 1.0.4 &nbsp;
- 1.0.4
[09-30-2024](https://github.com/iptv-org/epg/commit/d90c7a54b941238cb92391b33d80a75e746d3002)
- 1.0.5 &nbsp;
- 1.0.5
[10-02-2024](https://github.com/iptv-org/epg/commit/713dbf60a1cb9623ffcab6ab370ee9a78b32102b)
- 1.0.6 &nbsp;
- 1.0.6
[10-02-2024](https://github.com/iptv-org/epg/commit/713dbf60a1cb9623ffcab6ab370ee9a78b32102b)<br>Adds possibility to enable custom fixes
- 1.0.7 &nbsp;
- 1.0.7
[10-02-2024](https://github.com/iptv-org/epg/commit/713dbf60a1cb9623ffcab6ab370ee9a78b32102b)<br>Adds improvement to the docker image size
- 1.0.8 &nbsp;
- 1.0.8
[10-10-2024](https://github.com/iptv-org/epg/commit/2241bc261fd37b8b16e036a0b61167030a5ce2e6)
- 1.0.9 &nbsp;
- 1.0.9
[10-12-2024](https://github.com/iptv-org/epg/commit/fd382db08da7a96150928b8dcfef115e29e661d3)
- 1.0.10
[10-14-2024 12:50](https://github.com/iptv-org/epg/commit/a3e7661f95103cbee4bcb78bd483396680e9abfc)
- 1.0.11
[10-14-2024 17:34](https://github.com/iptv-org/epg/commit/7610f7b9f5cc1ccab8d17f3408a95d31b36ace7c)
- 1.0.12
[10-14-2024](https://github.com/iptv-org/epg/commit/7610f7b9f5cc1ccab8d17f3408a95d31b36ace7c)<br>Fix Pickx.be url
- 1.0.13
[10-14-2024](https://github.com/iptv-org/epg/commit/7610f7b9f5cc1ccab8d17f3408a95d31b36ace7c)<br>Add custom fix for web.magentatv.de
- 1.0.14
[10-14-2024](https://github.com/iptv-org/epg/commit/7610f7b9f5cc1ccab8d17f3408a95d31b36ace7c)<br>Change fix for movistarplus.es in order to work with new API
- 1.0.15
[11-26-2024](https://github.com/iptv-org/epg/commit/d15911006e163262c0c7f267deae28160c0d7a8f)<br>Add option to customize channel endpoint
- 1.0.16
[11-26-2024](https://github.com/iptv-org/epg/commit/d15911006e163262c0c7f267deae28160c0d7a8f)<br>Fix icons for movistarplus.es
- 1.0.17
[11-26-2024](https://github.com/iptv-org/epg/commit/d15911006e163262c0c7f267deae28160c0d7a8f)<br>Update fix for pickx.be
- 1.0.18
[11-27-2024 01:51](https://github.com/iptv-org/epg/commit/78dad4cfb4fc16f078c3b44b5534779c7c645b6b)
- 1.0.19
[11-27-2024 15:43](https://github.com/iptv-org/epg/commit/e5f0850b3b2e35ed394f00ac68b699eaabc4f0e4)
- 1.0.20
[11-28-2024](https://github.com/iptv-org/epg/commit/da18b70ddb1c3950e5a315411fd9aeaf60b6092c)
- 1.0.21
[11-28-2024](https://github.com/iptv-org/epg/commit/da18b70ddb1c3950e5a315411fd9aeaf60b6092c)<br>Add orangetv.es
- 1.0.22
[11-30-2024](https://github.com/iptv-org/epg/commit/1883338c0aee9909ac4567312b25701d10a765f2)
- 1.0.23
[12-02-2024](https://github.com/iptv-org/epg/commit/296d6162ecbeb1b3c3e392845187d30624d50aa2)
- 1.0.24
[12-02-2024](https://github.com/iptv-org/epg/commit/296d6162ecbeb1b3c3e392845187d30624d50aa2)<br>Fix for movistarplus.es channel grabber
- 1.0.25
[12-04-2024](https://github.com/iptv-org/epg/commit/864e0ac2c4761d926b203a85a382a4bdc87fbc17)
- 1.0.26
[12-05-2024](https://github.com/iptv-org/epg/commit/581441834af6f089c3930ad2d7ff1de2c701a6d9)
- 1.0.27
[12-07-2024](https://github.com/iptv-org/epg/commit/ce4f3e69358385d1fb8e79df8129c63d6314a802)
- 1.0.28
[12-08-2024](https://github.com/iptv-org/epg/commit/f9c8fc1b2dd63465564aba0c720096574980c58f)
- 1.0.29
[12-11-2024](https://github.com/iptv-org/epg/commit/581f5e0ca94bd6d05c33f53951df078d702b2510)
- 1.0.30
[12-16-2024](https://github.com/iptv-org/epg/commit/b9bbd32d354315eb292e3b82da09785e575a9781)
- 1.0.31
[12-17-2024](https://github.com/iptv-org/epg/commit/7237a62d94c5691f7f467b334f846efce93b08ff)<br>Fix for Pickx.be + mayor program updates
- 1.0.32
[12-20-2024](https://github.com/iptv-org/epg/commit/f00d53cb7be3cd7f6625897709cab005fe1b3dc4)
- 1.0.33
[12-21-2024](https://github.com/iptv-org/epg/commit/c108aa586e25d2e8914baeca6c05cc6755718665)
- 1.0.34
[12-27-2024](https://github.com/iptv-org/epg/commit/141fc210c4b7109e8ba09299d4f49c451ae0db4e)
- 1.0.35
[12-31-2024 06:25](https://github.com/iptv-org/epg/commit/7e7efaa48717d6b96f6d05aa9cf73271750d788b)
- 1.0.36
[12-31-2024 17:32](https://github.com/iptv-org/epg/commit/5ffe285c1e5882e905c5aaee672849f6f89e5cf3)
- 1.0.37
[01-09-2025](https://github.com/iptv-org/epg/commit/8e39af2a4d7c15f442a3e686144278e97151d46e)
- 1.0.38
[01-13-2025](https://github.com/iptv-org/epg/commit/9a565f16f4016e49d17b762477e0f6d29bb0f970)
- 1.0.39
[01-14-2025](https://github.com/iptv-org/epg/commit/76df1541d8b0b90533ea74dcbb7815c27425b608)
- 1.0.40
[01-14-2025](https://github.com/iptv-org/epg/commit/76df1541d8b0b90533ea74dcbb7815c27425b608)<br> Fixes issue with api url
- 1.0.41
[01-15-2025](https://github.com/iptv-org/epg/commit/65331dff1c6728c3012e314e51d40da85d2d7f3c)
- 1.0.42
[01-15-2025](https://github.com/iptv-org/epg/commit/5958c77c65a652285da64ad8a77d137306ca46d7)
- 1.0.43
[01-20-2025](https://github.com/iptv-org/epg/commit/7b2cfba7f5d4df8c01ff74a7c26d7695cb750244)
- 1.0.44
[01-21-2025](https://github.com/iptv-org/epg/commit/b69d61af5e46cea4f7dcb15a00d897397c23defa)
- 1.0.45
[01-23-2025](https://github.com/iptv-org/epg/commit/bc4b7fcfd51325cc597ccce13821f355dd0fbc72)
- 1.0.46
[01-27-2025](https://github.com/iptv-org/epg/commit/a45a346ec83cae3863b8d0e1cbe7abd99d6fef36)
- 1.0.47
[01-29-2025](https://github.com/iptv-org/epg/commit/106ae083d243df825958dcf4fea1d48d2765cf72)
- 1.0.48
[01-30-2025](https://github.com/iptv-org/epg/commit/e57dfaff41f498ffbfe79ecadd37f7f254dad0cc)
- 1.0.49
[02-02-2025](https://github.com/iptv-org/epg/commit/6b45cd9bd60058fdb7b974ad610c2d6565317f3b)
- 1.0.50
[02-05-2025](https://github.com/iptv-org/epg/commit/7f6849869f7182ddfa1a01b08a160ff8d2129441)
- 1.0.51
[02-11-2025](https://github.com/iptv-org/epg/commit/6cbe64f2dde47a3eb042cac35932989a7eefb2db)
- 1.0.52
[02-18-2025](https://github.com/iptv-org/epg/commit/39c4c5143e7cf7591ac49227e73e564be70c7615)
- 1.0.53
[02-23-2025](https://github.com/iptv-org/epg/commit/2721fe1ba06761fd06799a233dda27af6184fd17)
- 1.0.54
[03-07-2025](https://github.com/iptv-org/epg/commit/40c9af82d6f7f4e562cd239237fdf46a396d5728)
- 1.0.55
[03-11-2025](https://github.com/iptv-org/epg/commit/40c9af82d6f7f4e562cd239237fdf46a396d5728)
- 1.0.56
[03-16-2025](https://github.com/iptv-org/epg/commit/cf82b4089ef00c1fc94b7751652bfa598f8ab06a)
- 1.0.57
[03-25-2025](https://github.com/iptv-org/epg/commit/138842009bb3f9135430cdc667502ffa51d4a295)
- 1.0.58
[04-04-2025](https://github.com/iptv-org/epg/commit/4df25c92bcad1e4892640f532eae71cf9f5e7b95)
- 1.0.59
[04-04-2025](https://github.com/iptv-org/epg/commit/4df25c92bcad1e4892640f532eae71cf9f5e7b95)<br>Includes fixes for new configuration changes
- 1.0.60
[04-07-2025](https://github.com/iptv-org/epg/commit/7e1fbcbe154f4efd5c81341351cceb06f71b79a0)
- 1.0.61
[04-07-2025](https://github.com/iptv-org/epg/commit/7e1fbcbe154f4efd5c81341351cceb06f71b79a0)<br>Add delay option
[10-14-2024](https://github.com/iptv-org/epg/commit/a3e7661f95103cbee4bcb78bd483396680e9abfc)

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<!--This is a sample of a channel you can add look at https://github.com/iptv-org/epg/tree/master/sites for the complete list-->
<channel site="pickx.be" lang="nl" xmltv_id="Een.be" site_id="UID50037">VRT 1</channel>
<!--<channel site="movistarplus.es" lang="es" xmltv_id="24Horas.es" site_id="24H">24 Horas</channel>-->
<channel site="movistarplus.es" lang="es" xmltv_id="24Horas.es" site_id="24H">24 Horas</channel>
</channels>

View File

@ -1,60 +1,74 @@
const axios = require('axios')
const cheerio = require('cheerio')
const dayjs = require('dayjs')
const { DateTime } = require('luxon')
const API_PROD_ENDPOINT = 'https://www.movistarplus.es/programacion-tv'
const API_IMAGE_ENDPOINT = 'https://www.movistarplus.es/recorte/n/caratulaH/';
module.exports = {
site: 'movistarplus.es',
days: 2,
url({ channel, date }) {
return `https://www.movistarplus.es/programacion-tv/${channel.site_id}/${date.format(
'YYYY-MM-DD'
)}`
url: function ({ date }) {
return `${API_PROD_ENDPOINT}/${date.format('YYYY-MM-DD')}?v=json`
},
parser({ content }) {
parser({ content, channel, date }) {
let programs = []
let items = parseItems(content)
let items = parseItems(content, channel)
if (!items.length) return programs
items.forEach(el => {
let guideDate = date
items.forEach(item => {
let startTime = DateTime.fromFormat(
`${guideDate.format('YYYY-MM-DD')} ${item.HORA_INICIO}`,
'yyyy-MM-dd HH:mm',
{
zone: 'Europe/Madrid'
}
).toUTC()
let stopTime = DateTime.fromFormat(
`${guideDate.format('YYYY-MM-DD')} ${item.HORA_FIN}`,
'yyyy-MM-dd HH:mm',
{
zone: 'Europe/Madrid'
}
).toUTC()
if (stopTime < startTime) {
guideDate = guideDate.add(1, 'd')
stopTime = stopTime.plus({ days: 1 })
}
programs.push({
title: el.item.name,
start: dayjs(el.item.startDate),
stop: dayjs(el.item.endDate)
title: item.TITULO,
icon: parseIcon(item, channel),
category: item.GENERO,
start: startTime,
stop: stopTime
})
})
return programs
},
async channels() {
const html = await axios
.get('https://www.movistarplus.es/programacion-tv')
const axios = require('axios')
const dayjs = require('dayjs')
const data = await axios
.get(`${API_PROD_ENDPOINT}/${dayjs().format('YYYY-MM-DD')}?v=json`)
.then(r => r.data)
.catch(console.log)
const $ = cheerio.load(html)
let scheme = $('script:contains(ItemList)').html()
scheme = JSON.parse(scheme)
return scheme.itemListElement.map(el => {
const urlParts = el.item.url.split('/')
const site_id = urlParts.pop().toLowerCase()
return Object.values(data.data).map(item => {
return {
lang: 'es',
name: el.item.name,
site_id
site_id: item.DATOS_CADENA.CODIGO,
name: item.DATOS_CADENA.NOMBRE
}
})
}
}
function parseItems(content) {
try {
const $ = cheerio.load(content)
let scheme = $('script:contains("@type": "ItemList")').html()
scheme = JSON.parse(scheme)
if (!scheme || !Array.isArray(scheme.itemListElement)) return []
return scheme.itemListElement
} catch {
return []
}
function parseIcon(item, channel) {
return `${API_IMAGE_ENDPOINT}/M${channel.site_id}P${item.ELEMENTO}`;
}
function parseItems(content, channel) {
const json = typeof content === 'string' ? JSON.parse(content) : content
if (!(`${channel.site_id}-CODE` in json.data)) return []
const data = json.data[`${channel.site_id}-CODE`]
return data ? data.PROGRAMAS : []
}

View File

@ -1,172 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<channels>
<channel site="orangetv.orange.es" lang="es" xmltv_id="La1.es" site_id="1010">LA 1 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="La2.es" site_id="1062">La 2 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="24Horas.es" site_id="12051">24 Horas</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Teledeporte.es" site_id="1063">TDP HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Clan.es" site_id="1064">Clan HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Antena3.es" site_id="1011">Antena 3 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Cuatro.es" site_id="1012">Cuatro HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Telecinco.es" site_id="1013">Telecinco HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaSexta.es" site_id="1014">laSexta HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Selekt.es" site_id="11045">SELEKT</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="StarChannelSpain.es" site_id="11001">STAR Channel</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="AMC.es" site_id="11011">AMC</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="AMCBreak.es" site_id="11009">AMC Break</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="AMCCrime.es" site_id="11042">AMC CRIME</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="WarnerTV.es" site_id="11007">Warner TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="AXN.es" site_id="11002">AXN</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ComedyCentral.es" site_id="11005">Comedy Central</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Calle13Universal.es" site_id="11003">Calle 13</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="XTRM.es" site_id="12057">XTRM</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Syfy.es" site_id="11004">SYFY</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="COSMO.es" site_id="11006">Cosmo</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Enfamilia.es" site_id="11063">Enfamilia</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Decasa.es" site_id="11027">Decasa</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CanalCocina.es" site_id="11020">CanalCocina</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeSeries.es" site_id="11093">Runtime Series</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="FactoriadeFiccion.es" site_id="1032">FDF</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Neox.es" site_id="1027">Neox</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Energy.es" site_id="1030">Energy</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Atreseries.es" site_id="1042">Atreseries</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Divinity.es" site_id="1034">Divinity</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Nova.es" site_id="1028">Nova</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CanalHollywood.es" site_id="11010">Canal Hollywood</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="AXNMovies.es" site_id="11008">AXN Movies</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Somos.es" site_id="11029">Somos</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TCM.es" site_id="11012">TCM</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="SundanceTV.es" site_id="11052">Sundance TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Dark.es" site_id="11053">Dark</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeCineSeries.es" site_id="1089">Runtime Cine y Series</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeThriller.es" site_id="11091">Runtime Thriller/Terror</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeAccion.es" site_id="11094">Runtime Acción</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeComedia.es" site_id="11092">Runtime Comedia</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeCrimen.es" site_id="11095">Runtime Crimen</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RuntimeRomance.es" site_id="11096">Runtime Romance</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RunTimeClasicos.es" site_id="11097">RunTime Clásicos</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CinesVerdi.es" site_id="11098">Cines Verdi TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CineFeelGood.es" site_id="11099">Cine Feel Good</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ParamountNetwork.es" site_id="12032">Paramount Network</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DreamWorksChannel.es" site_id="1085">Dreamworks</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="BomCine.es" site_id="2063">Bom Cine</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DKISS.es" site_id="1044">DKISS</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TEN.es" site_id="12054">Ten</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Odisea.es" site_id="11018">Odisea</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Mega.es" site_id="1016">Mega</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Trece.es" site_id="1017">TR3CE</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DMAX.es" site_id="1018">DMAX</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaOtra.es" site_id="2061">La otra HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Boing.es" site_id="1021">Boing</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ToonGogglesenEspanol.us" site_id="11100">Toon Goggles</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NickJr.es" site_id="11055">Nick JR</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DisneyJunior.es" site_id="11015">Disney Junior</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Nickelodeon.es" site_id="11016">Nick</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="BeMad.es" site_id="1043">Be Mad TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Historia.es" site_id="11019">Canal Historia</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NationalGeographic.es" site_id="11017">National Geographic</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NationalGeographicWild.es" site_id="1008">NatGeo Wild</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DiscoveryChannel.es" site_id="1039">Discovery</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NatureTime.es" site_id="1084">NatureTime</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="La7.es" site_id="2011">7RM HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LevanteTV.es" site_id="2070">Levante TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CanalSur.es" site_id="1035">Canal Sur</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CanalSur2.es" site_id="2022">CanalSur 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CanalSurAndalucia.es" site_id="2031">Andalucía TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="7TVAndalucia.e" site_id="2065">7 TV Andalucia</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TV3.es" site_id="2008">TV3 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TV3CAT.es" site_id="1036">TV3CAT</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="324.es" site_id="2050">3/24</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TelevisioCastello.es" site_id="2067">TV Castellon</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="La8Mediterraneo.es" site_id="2062">8 Mediterraneo</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="APunt.es" site_id="2057">A punt HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="IB3.es" site_id="2013">IB3 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TelevisionCanaria.es" site_id="2059">RTV Canaria HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ETB1.es" site_id="2014">ETB1 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ETB2.es" site_id="1037">ETB2 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ETB3.es" site_id="2032">ETB3</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ETB4.es" site_id="2037">ETB4</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ETBBasque.es" site_id="1037">ETB Basque</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="GaliciaTVEuropa.es" site_id="2052">TVG HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TVG2.es" site_id="2053">TVG2 HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TPA7.es" site_id="2009">TPA HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TeleVigo.es" site_id="2068">Televigo</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="GaliciaTVEuropa.es" site_id="1038">Galicia TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CeutaTV.es" site_id="2002">TV Ceuta</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TVR.es" site_id="2055">TVR HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NavarraTV.es" site_id="2060">Navarra TV HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NavarraTV2.es" site_id="2029">Navarra TV2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Telemadrid.es" site_id="12050">Telemadrid HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="RealMadridTV.es" site_id="12052">Real Madrid</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="SevillaFCTV.es" site_id="2081">SEVILLA FC Televisión</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="BetisTV.es" site_id="1019">Betis TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeonesporMovistarPlusPlus.es" site_id="1023">M+ Liga de Campeones</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones1porMovistarPlusPlus.es" site_id="1050">M+ Liga de Campeones 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones2porMovistarPlusPlus.es" site_id="1051">M+ Liga de Campeones 3</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones3porMovistarPlusPlus.es" site_id="1052">M+ Liga de Campeones 4</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones4porMovistarPlusPlus.es" site_id="1053">M+ Liga de Campeones 5</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones5porMovistarPlusPlus.es" site_id="1054">M+ Liga de Campeones 6</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones6porMovistarPlusPlus.es" site_id="1055">M+ Liga de Campeones 7</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones7porMovistarPlusPlus.es" site_id="1056">M+ Liga de Campeones 8</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones8porMovistarPlusPlus.es" site_id="11036">M+ Liga de Campeones 9</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones9porMovistarPlusPlus.es" site_id="1096">M+ Liga de Campeones 10</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones10porMovistarPlusPlus.es" site_id="1097">M+ Liga de Campeones 11</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones11porMovistarPlusPlus.es" site_id="1098">M+ Liga de Campeones 12</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones12porMovistarPlusPlus.es" site_id="1099">M+ Liga de Campeones 13</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones13porMovistarPlusPlus.es" site_id="11065">M+ Liga de Campeones 14</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones14porMovistarPlusPlus.es" site_id="11066">M+ Liga de Campeones 15</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones15porMovistarPlusPlus.es" site_id="11067">M+ Liga de Campeones 16</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LigadeCampeones16porMovistarPlusPlus.es" site_id="11068">M+ Liga de Campeones 17</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaTVUHDporMovistarPlusPlus.es" site_id="11043">M LALIGA TV UHD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaTVporMovistarPlusPlus.es" site_id="11013">M+ LALIGA TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLiga1porMovistarPlusPlus.es" site_id="11026">M+ LALIGA TV 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaTV2porMovistarPlusPlus.es" site_id="1057">M+ LALIGATV 3</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaTV3porMovistarPlusPlus.es" site_id="1058">M+ LALIGATV 4</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaTV.es" site_id="11129">LA LIGA TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DAZNLaLiga.es" site_id="11077">DAZN LALIGA</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DAZNLaLiga2.es" site_id="11080">DAZN LALIGA 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaHypermotion.es" site_id="11083">LALIGATV HYPERMOTION</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaHypermotion2.es" site_id="11084">LALIGATV HYPERMOTION 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="LaLigaHypermotion3.es" site_id="11085">LALIGATV HYPERMOTION 3</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="GOLPLAY.es" site_id="11031">GOL PLAY</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Mezzo.fr" site_id="1031">Mezzo HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="MTV00s.uk" site_id="1026">MTV 00s</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="HITTV.es" site_id="2046">HIT TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="MTV.es" site_id="11050">MTV España</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="MTVLive.us" site_id="11051">MTV Live</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="SolMusica.es" site_id="11119">Sol Música</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="StingrayClassica.ca" site_id="12003">Classica HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="StingrayFestival4K.ca" site_id="11060">Festival 4K</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="StingrayDJAZZ.ca" site_id="12004">Djazz</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="StingrayiConcerts.ca" site_id="12002">iConcerts</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="MezzoLive.fr" site_id="12005">MezzoLiveHD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TraceLatina.fr" site_id="11106">TRACE Latina</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TraceUrban.fr" site_id="11107">TRACE Urban</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CaracolTV.co" site_id="1029">Caracol TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="EWTNEspanaLatinAmerica.us" site_id="1068">EWTN</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Gulli.fr" site_id="1077">Gulli</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="France2.fr" site_id="1082">France 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="France5.fr" site_id="1083">France 5</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TraceSportStars.fr" site_id="1095">Trace Sport Stars</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TV5MondeEurope.fr" site_id="11023">TV5MONDE</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="QwestTV.fr" site_id="1088">Qwest TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Eurosport1.fr" site_id="11035">Eurosport 1</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Eurosport2.fr" site_id="11059">Eurosport 2</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="MyZenTV.fr" site_id="11070">Myzen TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="FightSports.us" site_id="12007">FightSports</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="FightBoxHD.nl" site_id="1091">Fight Box HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Gametoon.es" site_id="1086">Gametoon</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="EuronewsSpanish.fr" site_id="1090">Euronews</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="ElToroTV.es" site_id="11049">El Toro TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Motorvision.de" site_id="11105">Motorvision</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Esport3.es" site_id="2038">Esport3</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="BBCNewsEurope.uk" site_id="11021">BBC World HD</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="CNNInternationalEurope.us" site_id="11022">CNN</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="DWEspanol.de" site_id="11024">Deutsche Welle</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="AlJazeeraEnglish.qa" site_id="11025">Al Jazeera</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="PROTV.ba" site_id="11028">Pro TV</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="Ubeat.es" site_id="11061">Ubeat</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="OUTtv.ca" site_id="11072">OUTtv</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="BUENVIAJE.es" site_id="11112">¡BUENVIAJE!</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="TennisChannel.us" site_id="11120">Tennis Channel</channel>
<channel site="orangetv.orange.es" lang="es" xmltv_id="NauticalChannel.it" site_id="11128">Nautical Channel</channel>
</channels>

View File

@ -1,99 +0,0 @@
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
const doFetch = require('@ntlab/sfetch')
const debug = require('debug')('site:orangetv.orange.es')
dayjs.extend(utc)
doFetch.setDebugger(debug)
const API_PROGRAM_ENDPOINT = 'https://epg.orangetv.orange.es/epg/Smartphone_Android/1_PRO'
const API_CHANNEL_ENDPOINT =
'https://pc.orangetv.orange.es/pc/api/rtv/v1/GetChannelList?bouquet_id=1&model_external_id=PC&filter_unsupported_channels=false&client=json'
const API_IMAGE_ENDPOINT = 'https://pc.orangetv.orange.es/pc/api/rtv/v1/images'
module.exports = {
site: 'orangetv.orange.es',
days: 2,
request: {
cache: {
ttl: 24 * 60 * 60 * 1000 // 1 day
}
},
url({ date, segment = 1 }) {
return `${API_PROGRAM_ENDPOINT}/${date.format('YYYYMMDD')}_8h_${segment}.json`
},
async parser({ content, channel, date }) {
const programs = []
const items = parseItems(content, channel)
if (items.length) {
const queues = [
module.exports.url({ date, segment: 2 }),
module.exports.url({ date, segment: 3 })
]
await doFetch(queues, (url, res) => {
items.push(...parseItems(res, channel))
})
programs.push(
...items.map(item => {
return {
title: item.name,
sub_title: item.seriesName,
description: item.description,
category: parseGenres(item),
season: item.seriesSeason ? parseInt(item.seriesSeason) : null,
episode: item.episodeId ? parseInt(item.episodeId) : null,
icon: parseIcon(item),
start: dayjs.utc(item.startDate),
stop: dayjs.utc(item.endDate)
}
})
)
}
return programs
},
async channels() {
const axios = require('axios')
const data = await axios
.get(API_CHANNEL_ENDPOINT)
.then(r => r.data)
.catch(console.error)
return data.response.map(item => {
return {
lang: 'es',
name: item.name,
site_id: item.externalChannelId
}
})
}
}
function parseIcon(item) {
if (item.attachments.length) {
const cover = item.attachments.find(i => i.name.match(/cover/i))
if (cover) {
return `${API_IMAGE_ENDPOINT}${cover.value}`
}
}
}
function parseGenres(item) {
return item.genres.map(i => i.name)
}
function parseItems(content, channel) {
const result = []
const json =
typeof content === 'string' ? JSON.parse(content) : Array.isArray(content) ? content : []
if (Array.isArray(json)) {
json
.filter(i => i.channelExternalId === channel.site_id)
.forEach(i => {
result.push(...i.programs)
})
}
return result
}

View File

@ -1,18 +1,32 @@
// credit for this fix goes to davidclaeysquinones for his PR on https://github.com/iptv-org/epg/pull/2430, https://github.com/iptv-org/epg/pull/2520 and to BellezaEmporium for his PR on https://github.com/iptv-org/epg/pull/2480, https://github.com/iptv-org/epg/pull/2525
const axios = require('axios')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
let apiVersion
let isApiVersionFetched = false
;(async () => {
try {
await fetchApiVersion()
isApiVersionFetched = true
} catch (error) {
console.error('Error during script initialization:', error)
}
})()
dayjs.extend(utc)
module.exports = {
site: 'pickx.be',
days: 2,
async url({ channel, date }) {
if (!apiVersion) {
await fetchApiVersion()
apiVersion: function () {
return apiVersion
},
fetchApiVersion: fetchApiVersion, // Export fetchApiVersion
url: async function ({ channel, date }) {
while (!isApiVersionFetched) {
await new Promise(resolve => setTimeout(resolve, 100)) // Wait for 100 milliseconds
}
return `https://px-epg.azureedge.net/airings/${apiVersion}/${date.format(
'YYYY-MM-DD'
)}/channel/${channel.site_id}?timezone=Europe%2FBrussels`
@ -42,21 +56,19 @@ module.exports = {
episode: item.program.episodeNumber,
actors: item.program.actors,
director: item.program.director ? [item.program.director] : null,
start: dayjs(item.programScheduleStart),
stop: dayjs(item.programScheduleEnd)
start: dayjs.utc(item.programScheduleStart),
stop: dayjs.utc(item.programScheduleEnd)
})
})
}
return programs
},
async channels() {
let channels = []
async channels({ lang = '' }) {
const query = {
operationName: 'getChannels',
variables: {
language: 'fr',
language: lang,
queryParams: {},
id: '0',
params: {
@ -64,60 +76,93 @@ module.exports = {
}
},
query: `query getChannels($language: String!, $queryParams: ChannelQueryParams, $id: String, $params: ChannelParams) {
channels(language: $language, queryParams: $queryParams, id: $id, params: $params) {
id
name
language
radio
}
}`
channels(language: $language, queryParams: $queryParams, id: $id, params: $params) {
id
channelReferenceNumber
name
callLetter
number
logo {
key
url
__typename
}
language
hd
radio
replayable
ottReplayable
playable
ottPlayable
recordable
subscribed
cloudRecordable
catchUpWindowInHours
isOttNPVREnabled
ottNPVRStart
subscription {
channelRef
subscribed
upselling {
upsellable
packages
__typename
}
__typename
}
packages
__typename
}
}`
}
const data = await axios
.post('https://api.proximusmwc.be/tiams/v3/graphql', query)
const result = await axios
.post('https://api.proximusmwc.be/tiams/v2/graphql', query)
.then(r => r.data)
.catch(console.error)
data.data.channels.forEach(channel => {
let lang = channel.language || 'fr'
if (channel.language === 'ger') lang = 'de'
channels.push({
lang,
site_id: channel.id,
name: channel.name
})
})
return channels
return (
result?.data?.channels
.filter(
channel =>
!channel.radio && (!lang || channel.language === (lang === 'de' ? 'ger' : lang))
)
.map(channel => {
return {
lang: channel.language === 'ger' ? 'de' : channel.language,
site_id: channel.id,
name: channel.name
}
}) || []
)
}
}
async function fetchApiVersion() {
const hashUrl = 'https://www.pickx.be/nl/televisie/tv-gids'
const hashData = await axios
.get(hashUrl)
.then(r => {
const re = /"hashes":\["(.*)"\]/
const match = r.data.match(re)
if (match && match[1]) {
return match[1]
} else {
throw new Error('React app version hash not found')
}
})
.catch(console.error)
const versionUrl = `https://www.pickx.be/api/s-${hashData}`
const response = await axios.get(versionUrl, {
headers: {
Origin: 'https://www.pickx.be',
Referer: 'https://www.pickx.be/'
}
})
return new Promise((resolve, reject) => {
function fetchApiVersion() {
return new Promise(async (resolve, reject) => {
try {
// https://px-epg.azureedge.net/version is deprecated
// probably the version url will be changed around over time
//history of used version urls
//const versionUrl = 'https://www.pickx.be/api/s-3b36540f3cef64510112f3f95c2c0cdca321997ed2b1042ad778523235e155eb'
//const versionUrl = 'https://www.pickx.be/api/s-671f172425e1bc74cd0440fd67aaa6cbe68b582f3f401186c2f46ae97e80516b'
//const versionUrl = 'https://www.pickx.be/api/s-a6b4b4fefaa20e438523a6167e63b8504d96b9df8303473349763c4418cffe30'
//const versionUrl = 'https://www.pickx.be/api/s-8546c5fd136241d42aab714d2fe3ccc5671fd899035efae07cd0b8f4eb23994e'
//const versionUrl = 'https://www.pickx.be/api/s-64464ad9a3bc117af5dca620027216ecade6a51c230135a0f134c0ee042ff407';
//const versionUrl = 'https://www.pickx.be/api/s-626d8fdabfb1d44e5a614cd69f4b45d6843fdb63566fc80ea4f97f40e4ea3152';
//const versionUrl = 'https://www.pickx.be/api/s-cefaf96e249e53648c4895c279e7a621233c50b4357d62b0bdf6bff45f31b5c0';
//const versionUrl = 'https://www.pickx.be/api/s-7fa35253080e9665f9c7d9d85e707d6fb1d1bf07ede11965e859fcb57c723949';
//the new strategy to break the provider is to leave old version url's available and to return invalid results on those endpoints
const versionUrl = 'https://www.pickx.be/api/s-0e58be3938175b6b900dfb5233bd5cfc0bcf915b633fe57b935f7ce8dbe5f6eb';
const response = await axios.get(versionUrl, {
headers: {
Origin: 'https://www.pickx.be',
Referer: 'https://www.pickx.be/'
}
})
if (response.status === 200) {
apiVersion = response.data.version
resolve()
@ -126,7 +171,7 @@ async function fetchApiVersion() {
reject(`Failed to fetch API version. Status: ${response.status}`)
}
} catch (error) {
console.error('Error during fetchApiVersion:', error)
console.error('Error fetching API version:', error.message)
reject(error)
}
})

View File

@ -1,5 +1,3 @@
// credit for this fix goes to davidclaeysquinones for his PR on https://github.com/iptv-org/epg/pull/2429
const axios = require('axios')
const dayjs = require('dayjs')

View File

@ -1,232 +0,0 @@
// credit for this fix goes to klausellus-wallace for his PR on https://github.com/iptv-org/epg/pull/2458
const axios = require('axios')
const dayjs = require('dayjs')
const utc = require('dayjs/plugin/utc')
const customParseFormat = require('dayjs/plugin/customParseFormat')
const fetch = require('node-fetch')
const { upperCase } = require('lodash')
let X_CSRFTOKEN
let COOKIE
const cookiesToExtract = ['JSESSIONID', 'CSESSIONID', 'CSRFSESSION']
const extractedCookies = {}
dayjs.extend(utc)
dayjs.extend(customParseFormat)
module.exports = {
site: 'web.magentatv.de',
days: 2,
url: 'https://api.prod.sngtv.magentatv.de/EPG/JSON/PlayBillList',
request: {
method: 'POST',
headers: function () {
return setHeaders()
},
data({ channel, date }) {
return {
count: -1,
isFillProgram: 1,
offset: 0,
properties: [
{
include: 'endtime,genres,id,name,starttime,channelid,pictures,introduce,subName,seasonNum,subNum,cast,country,producedate,externalIds',
name: 'playbill'
}
],
type: 2,
begintime: date.format('YYYYMMDD000000'),
channelid: channel.site_id,
endtime: date.add(1, 'd').format('YYYYMMDD000000')
}
}
},
parser: function ({ content }) {
let programs = []
const items = parseItems(content)
items.forEach(item => {
programs.push({
title: item.name,
description: item.introduce,
image: parseImage(item),
category: parseCategory(item),
start: parseStart(item),
stop: parseStop(item),
sub_title: item.subName,
season: item.seasonNum,
episode: item.subNum,
directors: parseDirectors(item),
producers: parseProducers(item),
adapters: parseAdapters(item),
country: upperCase(item.country),
date: item.producedate,
urls: parseUrls(item)
})
})
return programs
},
async channels() {
const url = 'https://api.prod.sngtv.magentatv.de/EPG/JSON/AllChannel'
const body = {
channelNamespace: 2,
filterlist: [
{
key: 'IsHide',
value: '-1'
}
],
metaDataVer: 'Channel/1.1',
properties: [
{
include: '/channellist/logicalChannel/contentId,/channellist/logicalChannel/name',
name: 'logicalChannel'
}
],
returnSatChannel: 0
}
const params = {
headers: await setHeaders()
}
const data = await axios
.post(url, body, params)
.then(r => r.data)
.catch(console.log)
return data.channellist.map(item => {
return {
lang: 'de',
site_id: item.contentId,
name: item.name
}
})
}
}
function parseCategory(item) {
return item.genres
? item.genres
.replace('und', ',')
.split(',')
.map(i => i.trim())
: []
}
function parseDirectors(item) {
if (!item.cast || !item.cast.director) return [];
return item.cast.director
.replace('und', ',')
.split(',')
.map(i => i.trim());
}
function parseProducers(item) {
if (!item.cast || !item.cast.producer) return [];
return item.cast.producer
.replace('und', ',')
.split(',')
.map(i => i.trim())
}
function parseAdapters(item) {
if (!item.cast || !item.cast.adaptor) return [];
return item.cast.adaptor
.replace('und', ',')
.split(',')
.map(i => i.trim())
}
function parseUrls(item) {
// currently only a imdb id is returned by the api, thus we can construct the url here
if (!item.externalIds) return [];
return JSON.parse(item.externalIds)
.filter(externalId => externalId.type === 'imdb' && externalId.id)
.map(externalId => ({ system: 'imdb', value: `https://www.imdb.com/title/${externalId.id}` }))
}
function parseImage(item) {
if (!Array.isArray(item.pictures) || !item.pictures.length) return null
return item.pictures[0].href
}
function parseStart(item) {
return dayjs.utc(item.starttime, 'YYYY-MM-DD HH:mm:ss')
}
function parseStop(item) {
return dayjs.utc(item.endtime, 'YYYY-MM-DD HH:mm:ss')
}
function parseItems(content) {
const data = JSON.parse(content)
if (!data || !Array.isArray(data.playbilllist)) return []
return data.playbilllist
}
// Function to try to fetch COOKIE and X_CSRFTOKEN
function fetchCookieAndToken() {
return fetch(
'https://api.prod.sngtv.magentatv.de/EPG/JSON/Authenticate?SID=firstup&T=Windows_chrome_118',
{
headers: {
accept: 'application/json, text/javascript, */*; q=0.01',
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'same-origin',
'x-requested-with': 'XMLHttpRequest',
Referer: 'https://web.magentatv.de/',
'Referrer-Policy': 'strict-origin-when-cross-origin'
},
body: '{"terminalid":"00:00:00:00:00:00","mac":"00:00:00:00:00:00","terminaltype":"WEBTV","utcEnable":1,"timezone":"Etc/GMT0","userType":3,"terminalvendor":"Unknown"}',
method: 'POST'
}
)
.then(response => {
// Check if the response status is OK (2xx)
if (!response.ok) {
throw new Error('HTTP request failed')
}
// Extract the set-cookie header
const setCookieHeader = response.headers.raw()['set-cookie']
// Extract the cookies specified in cookiesToExtract
cookiesToExtract.forEach(cookieName => {
const regex = new RegExp(`${cookieName}=(.+?)(;|$)`)
const match = setCookieHeader.find(header => regex.test(header))
if (match) {
const cookieValue = regex.exec(match)[1]
extractedCookies[cookieName] = cookieValue
}
})
return response.json()
})
.then(data => {
if (data.csrfToken) {
X_CSRFTOKEN = data.csrfToken
COOKIE = `JSESSIONID=${extractedCookies.JSESSIONID}; CSESSIONID=${extractedCookies.CSESSIONID}; CSRFSESSION=${extractedCookies.CSRFSESSION}; JSESSIONID=${extractedCookies.JSESSIONID};`
} else {
console.log('csrfToken not found in the response.')
}
})
.catch(error => {
console.error(error)
})
}
function setHeaders() {
return fetchCookieAndToken().then(() => {
return {
X_CSRFTOKEN: X_CSRFTOKEN,
'Content-Type': 'application/json',
Cookie: COOKIE
}
})
}

View File

@ -1,23 +0,0 @@
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 -- --gzip --channels=channels.xml --output=public/guide.xml`,
cron_restart: process.env.CRON || null,
instances: 1,
watch: false,
autorestart: false
}
]
}

View File

@ -6,10 +6,8 @@ for arg in "$@"; do
chron-schedule=*) chron_schedule="${arg#*=}" ;;
work-dir=*) work_dir="${arg#*=}" ;;
days=*) days="${arg#*=}" ;;
delay=*) delay="${arg#*=}" ;;
max_connections=*) max_connections="${arg#*=}" ;;
enable_fixes=*) enable_fixes="${arg#*=}" ;;
api_url=*) api_url="${arg#*=}" ;;
esac
done
@ -17,16 +15,15 @@ echo "chron_schedule : ${chron_schedule}"
cd $work_dir
echo "working dir : " $(pwd)
echo "days : ${days}"
echo "delay : ${delay}"
echo "max_connections : ${max_connections}"
echo "enable_fixes : ${enable_fixes}"
echo "api url : ${api_url}"
if [ "$enable_fixes" = true ] ; then
cp -R /fixes/* /bin/epg/sites/
fi
sed -i -E "s/(https:\x2f\x2fiptv-org.github.io\x2fapi$\123filename\125)/$api_url$\123filename\125/g" $work_dir/scripts/core/apiClient.ts
pm2 --name epg start npm -- run serve
npm run grab -- --channels=channels.xml --maxConnections=$max_connections --days=$days --gzip
ln -s $work_dir/guide.xml /public/guide.xml
ln -s $work_dir/guide.xml.gz /public/guide.xml.gz
pm2-runtime pm2.config.js --name epg --node-args="--no-autorestart --cron-restart="$chron_schedule" --maxConnections=$max_connections --days=$days --delay=$delay"
npm run grab -- --channels=channels.xml --cron="$chron_schedule" --maxConnections=$max_connections --days=$days --gzip