mirror of
https://github.com/iptv-org/epg.git
synced 2025-05-09 08:30:06 -04:00
Merge pull request #1984 from iptv-org/add-tv.vera.com.uy
Add guide from tv.vera.com.uy
This commit is contained in:
commit
4c62b2f365
8 changed files with 279 additions and 0 deletions
17
.github/workflows/tv.vera.com.uy.yml
vendored
Normal file
17
.github/workflows/tv.vera.com.uy.yml
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
name: tv.vera.com.uy
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 3 * * *'
|
||||
workflow_dispatch:
|
||||
workflow_run:
|
||||
workflows: [_trigger]
|
||||
types:
|
||||
- completed
|
||||
jobs:
|
||||
load:
|
||||
uses: ./.github/workflows/_load.yml
|
||||
with:
|
||||
site: ${{github.workflow}}
|
||||
secrets:
|
||||
APP_ID: ${{ secrets.APP_ID }}
|
||||
APP_PRIVATE_KEY: ${{ secrets.APP_PRIVATE_KEY }}
|
3
sites/tv.vera.com.uy/__data__/content.json
Normal file
3
sites/tv.vera.com.uy/__data__/content.json
Normal file
File diff suppressed because one or more lines are too long
3
sites/tv.vera.com.uy/__data__/no_content.json
Normal file
3
sites/tv.vera.com.uy/__data__/no_content.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
{"count":0,"limit":500,"offset":0,"data":[]}
|
1
sites/tv.vera.com.uy/__data__/no_session.json
Normal file
1
sites/tv.vera.com.uy/__data__/no_session.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"message":"Error de validacion de los datos","name":"ValidationError","status":400,"src":"veratv-be","info":{"errors":[{"msg":"tipo puede ser usuario o anonima","param":"_error","nestedErrors":[{"value":"anonim","msg":"Invalid value","param":"tipo","location":"body"},{"msg":"Invalid value","param":"usuario","location":"body"},{"msg":"Invalid value","param":"dominio","location":"body"},{"value":"anonim","msg":"Invalid value","param":"tipo","location":"body"}]}]}}
|
1
sites/tv.vera.com.uy/__data__/session.json
Normal file
1
sites/tv.vera.com.uy/__data__/session.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"id_sesion":494613071,"token":"MpDY52p1V6g511VSABp1015B","id_servicio":3,"id_frontend":1196,"id_dispositivo":0,"id_usuario":0,"dominio":"","usuario":"","id_referencia":"","tipo":"anonima","expiracion_inicial":"2023-02-08 06:37:36","ip":"179.27.154.242","ip_referenciada":"188.242.48.93","jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOnsidGlwbyI6ImFub25pbWEifSwic3ViIjoiTXBEWTUycDFWNmc1MTFWU0FCcDEwMTVCIiwicHJuIjp7ImlkX3NlcnZpY2lvIjozLCJpZF9mcm9udGVuZCI6MTE5NiwiaXAiOiIxNzkuMjcuMTU0LjI0MiIsImlwX3JlZmVyZW5jaWFkYSI6IjE4OC4yNDIuNDguOTMiLCJpZF9kaXNwb3NpdGl2byI6MH0sImF1ZCI6IkFwcHNcL1dlYnMgRnJvbnRlbmRzIiwiaWF0IjoxNjc1ODI3NDU2LCJleHAiOjE2NzU4NDkwNTZ9.8bAQciQl5DOIZF7GgCl6ad-KJUSpqQREetozGv_IH5s","accesos":null}
|
58
sites/tv.vera.com.uy/tv.vera.com.uy.channels.xml
Normal file
58
sites/tv.vera.com.uy/tv.vera.com.uy.channels.xml
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<site site="tv.vera.com.uy">
|
||||
<channels>
|
||||
<channel lang="es" xmltv_id="1000xHoraTV.uy" site_id="2sh8l">1000XHora TV</channel>
|
||||
<channel lang="es" xmltv_id="ADULive.uy" site_id="2s6nx">Adu Live</channel>
|
||||
<channel lang="es" xmltv_id="ANPITV.uy" site_id="2s6nj">ANPI TV</channel>
|
||||
<channel lang="es" xmltv_id="AntelEventos.uy" site_id="2st0v">Antel Eventos</channel>
|
||||
<channel lang="es" xmltv_id="APlusV.uy" site_id="2sh8q">A + V</channel>
|
||||
<channel lang="es" xmltv_id="ArtigasTelevision.uy" site_id="2s6nt">Artigas Televisión</channel>
|
||||
<channel lang="es" xmltv_id="CamaradeRepresentantes.uy" site_id="2s68m">Cámara de Representantes</channel>
|
||||
<channel lang="es" xmltv_id="CamaradeSenadores.uy" site_id="2s68v">Cámara de Senadores</channel>
|
||||
<channel lang="es" xmltv_id="Canal11TreintayTres.uy" site_id="2s6nv">Canal 11 Treinta y Tres</channel>
|
||||
<channel lang="es" xmltv_id="Canal11TV.uy" site_id="2s6nm">Canal 11 Las Piedras</channel>
|
||||
<channel lang="es" xmltv_id="Canal12Melo.uy" site_id="2s6n0">Canal 12 Melo</channel>
|
||||
<channel lang="es" xmltv_id="Canal23Florida.uy" site_id="2s6n6">Canal 23 Florida</channel>
|
||||
<channel lang="es" xmltv_id="Canal26.mx" site_id="2s685">Canal 26-Radio y Televisión de Aguascalientes</channel>
|
||||
<channel lang="es" xmltv_id="Canal2Lascano.uy" site_id="2s6nk">Canal 2 Lascano</channel>
|
||||
<channel lang="es" xmltv_id="Canal2SanCarlos.uy" site_id="2s6n8">Canal 2 HD San Carlos</channel>
|
||||
<channel lang="es" xmltv_id="Canal2VisionCanaria.uy" site_id="2s6nh">Canal 2 Visión Canaria</channel>
|
||||
<channel lang="es" xmltv_id="Canal4Chuy.uy" site_id="2s6n1">Canal 4 Chuy</channel>
|
||||
<channel lang="es" xmltv_id="Canal4JuanLacaze.uy" site_id="2s6nf">Canal 4 Juan Lacaze</channel>
|
||||
<channel lang="es" xmltv_id="Canal4Paysandu.uy" site_id="2s6pl">Canal 4 Paysandú</channel>
|
||||
<channel lang="es" xmltv_id="Canal4Salto.uy" site_id="2s6p4">Canal 4 Salto</channel>
|
||||
<channel lang="es" xmltv_id="Canal4Tacuarembo.uy" site_id="2s6p5">Canal 4 Tacuarembó</channel>
|
||||
<channel lang="es" xmltv_id="Canal5.uy" site_id="2s6nd">Canal 5</channel>
|
||||
<channel lang="es" xmltv_id="Canal6Durazno.uy" site_id="2s6pn">Canal 6 Durazno</channel>
|
||||
<channel lang="es" xmltv_id="Canal7PuntadelEste.uy" site_id="2sh83">Canal 7 Punta</channel>
|
||||
<channel lang="es" xmltv_id="Canal8Artigas.uy" site_id="2s6p1">Canal 8 Artigas</channel>
|
||||
<channel lang="es" xmltv_id="Canal8Durazno.uy" site_id="2s6pf">Canal 8 Durazno</channel>
|
||||
<channel lang="es" xmltv_id="Canal8Rivera.uy" site_id="2sh84">Canal 8 Rivera</channel>
|
||||
<channel lang="es" xmltv_id="Canal8Salto.uy" site_id="2s6nr">Canal 8 Salto</channel>
|
||||
<channel lang="es" xmltv_id="Canal9Telerocha.uy" site_id="2s6nn">Canal 9 Telerocha</channel>
|
||||
<channel lang="es" xmltv_id="CanalM.uy" site_id="2s68d">Canal M</channel>
|
||||
<channel lang="es" xmltv_id="CardinalTV.uy" site_id="2s6pw">Cardinal TV</channel>
|
||||
<channel lang="es" xmltv_id="DuraznoTV.uy" site_id="2s6rm">Durazno TV</channel>
|
||||
<channel lang="es" xmltv_id="DWEspanol.de" site_id="2s689">DW (Español)</channel>
|
||||
<channel lang="es" xmltv_id="ElCanaldelaRegion.uy" site_id="2s6rb">El Canal de la Región - Noreste Canelones</channel>
|
||||
<channel lang="es" xmltv_id="FTC.uy" site_id="2s6rj">Florida Televisora Color HD</channel>
|
||||
<channel lang="es" xmltv_id="LatinaTVPaysandu.uy" site_id="2s6rd">Latina TV Paysandú</channel>
|
||||
<channel lang="es" xmltv_id="MaronasEntertainment.uy" site_id="2s68s">Maroñas Entertainment</channel>
|
||||
<channel lang="es" xmltv_id="MIEM.uy" site_id="2str3">MIEM</channel>
|
||||
<channel lang="es" xmltv_id="MiMovilTV.uy" site_id="2s6gj">Mi Móvil TV</channel>
|
||||
<channel lang="es" xmltv_id="PantallaIMPO.uy" site_id="2s6r9">Pantalla IMPO</channel>
|
||||
<channel lang="es" xmltv_id="Plazacanal.uy" site_id="2s6r5">Plazacanal Treinta y Tres</channel>
|
||||
<channel lang="es" xmltv_id="RDTV.uy" site_id="2s6r4">RDTV 24HS</channel>
|
||||
<channel lang="es" xmltv_id="RioUruguayTV.uy" site_id="2s6rl">Rio Uruguay TV</channel>
|
||||
<channel lang="es" xmltv_id="Siemprecine.uy" site_id="2s6r3">Siemprecine</channel>
|
||||
<channel lang="es" xmltv_id="TeleR.uy" site_id="2s6r7">Tele R</channel>
|
||||
<channel lang="es" xmltv_id="Telesur.ve" site_id="2s68c">Telesur</channel>
|
||||
<channel lang="es" xmltv_id="TVCiudad.uy" site_id="2s6r2">TV CIUDAD</channel>
|
||||
<channel lang="es" xmltv_id="TVLPando.uy" site_id="2s6rs">TVL Pando</channel>
|
||||
<channel lang="es" xmltv_id="UCL.uy" site_id="2s6p7">Canal UCL</channel>
|
||||
<channel lang="es" xmltv_id="UruguayPresidencia.uy" site_id="2s6ny">Uruguay Presidencia</channel>
|
||||
<!-- <channel lang="es" xmltv_id="" site_id="2s68w">France 24</channel> -->
|
||||
<!-- <channel lang="es" xmltv_id="" site_id="2sf4f">+DEPORTESUY</channel> -->
|
||||
<!-- <channel lang="es" xmltv_id="" site_id="2sffq">Eventos TV</channel> -->
|
||||
</channels>
|
||||
</site>
|
108
sites/tv.vera.com.uy/tv.vera.com.uy.config.js
Normal file
108
sites/tv.vera.com.uy/tv.vera.com.uy.config.js
Normal file
|
@ -0,0 +1,108 @@
|
|||
const axios = require('axios')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const timezone = require('dayjs/plugin/timezone')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
dayjs.extend(customParseFormat)
|
||||
|
||||
const API_ENDPOINT = 'https://cds-frontend.vera.com.uy/api-contenidos'
|
||||
|
||||
module.exports = {
|
||||
site: 'tv.vera.com.uy',
|
||||
days: 2,
|
||||
async url({ date, channel }) {
|
||||
const session = await loadSessionDetails()
|
||||
if (!session || !session.token) return null
|
||||
|
||||
return `${API_ENDPOINT}/canales/epg/${
|
||||
channel.site_id
|
||||
}?limit=500&dias_siguientes=0&fecha=${date.format('YYYY-MM-DD')}&token=${session.token}`
|
||||
},
|
||||
request: {
|
||||
async headers() {
|
||||
const session = await loadSessionDetails()
|
||||
if (!session || !session.jwt) return null
|
||||
|
||||
return {
|
||||
authorization: `Bearer ${session.jwt}`,
|
||||
'x-frontend-id': 1196,
|
||||
'x-service-id': 3,
|
||||
'x-system-id': 1
|
||||
}
|
||||
}
|
||||
},
|
||||
parser({ content }) {
|
||||
let programs = []
|
||||
let items = parseItems(content)
|
||||
items.forEach(item => {
|
||||
programs.push({
|
||||
title: item.nombre_programa,
|
||||
sub_title: item.subtitle,
|
||||
description: item.descripcion_programa,
|
||||
start: parseStart(item),
|
||||
stop: parseStop(item)
|
||||
})
|
||||
})
|
||||
|
||||
return programs
|
||||
},
|
||||
async channels({ lang }) {
|
||||
const session = await loadSessionDetails()
|
||||
if (!session || !session.jwt || !session.token) return null
|
||||
|
||||
const data = await axios
|
||||
.get(`${API_ENDPOINT}/listas/68?token=${session.token}`, {
|
||||
headers: {
|
||||
authorization: `Bearer ${session.jwt}`,
|
||||
'x-frontend-id': 1196,
|
||||
'x-service-id': 3,
|
||||
'x-system-id': 1
|
||||
}
|
||||
})
|
||||
.then(r => r.data)
|
||||
.catch(console.error)
|
||||
|
||||
return data.contenidos.map(c => {
|
||||
return {
|
||||
lang: 'es',
|
||||
site_id: c.public_id,
|
||||
name: c.nombre
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function parseStart(item) {
|
||||
return dayjs.tz(item.fecha_hora_inicio, 'YYYY-MM-DD HH:mm:ss', 'America/Montevideo')
|
||||
}
|
||||
|
||||
function parseStop(item) {
|
||||
return dayjs.tz(item.fecha_hora_fin, 'YYYY-MM-DD HH:mm:ss', 'America/Montevideo')
|
||||
}
|
||||
|
||||
function parseItems(content) {
|
||||
const data = JSON.parse(content)
|
||||
if (!data || !Array.isArray(data.data)) return []
|
||||
|
||||
return data.data
|
||||
}
|
||||
|
||||
function loadSessionDetails() {
|
||||
return axios
|
||||
.post(
|
||||
'https://veratv-be.vera.com.uy/api/sesiones',
|
||||
{
|
||||
tipo: 'anonima'
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(r => r.data)
|
||||
.catch(console.log)
|
||||
}
|
88
sites/tv.vera.com.uy/tv.vera.com.uy.test.js
Normal file
88
sites/tv.vera.com.uy/tv.vera.com.uy.test.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
// npm run channels:parse -- --config=./sites/tv.vera.com.uy/tv.vera.com.uy.config.js --output=./sites/tv.vera.com.uy/tv.vera.com.uy.channels.xml
|
||||
// npx epg-grabber --config=sites/tv.vera.com.uy/tv.vera.com.uy.config.js --channels=sites/tv.vera.com.uy/tv.vera.com.uy.channels.xml --output=guide.xml --days=2
|
||||
|
||||
const { parser, url, request } = require('./tv.vera.com.uy.config.js')
|
||||
const fs = require('fs')
|
||||
const axios = require('axios')
|
||||
const path = require('path')
|
||||
const dayjs = require('dayjs')
|
||||
const utc = require('dayjs/plugin/utc')
|
||||
const customParseFormat = require('dayjs/plugin/customParseFormat')
|
||||
dayjs.extend(customParseFormat)
|
||||
dayjs.extend(utc)
|
||||
|
||||
jest.mock('axios')
|
||||
|
||||
axios.post.mockImplementation((url, data, opts) => {
|
||||
if (
|
||||
url === 'https://veratv-be.vera.com.uy/api/sesiones' &&
|
||||
JSON.stringify(opts.headers) ===
|
||||
JSON.stringify({
|
||||
'Content-Type': 'application/json'
|
||||
}) &&
|
||||
JSON.stringify(data) ===
|
||||
JSON.stringify({
|
||||
tipo: 'anonima'
|
||||
})
|
||||
) {
|
||||
return Promise.resolve({
|
||||
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/session.json')))
|
||||
})
|
||||
} else {
|
||||
return Promise.resolve({
|
||||
data: JSON.parse(fs.readFileSync(path.resolve(__dirname, '__data__/no_session.json')))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const date = dayjs.utc('2023-02-11', 'YYYY-MM-DD').startOf('d')
|
||||
const channel = {
|
||||
site_id: '2s6nd',
|
||||
xmltv_id: 'Canal5.uy'
|
||||
}
|
||||
|
||||
it('can generate valid url', async () => {
|
||||
const result = await url({ date, channel })
|
||||
|
||||
expect(result).toBe(
|
||||
`https://cds-frontend.vera.com.uy/api-contenidos/canales/epg/2s6nd?limit=500&dias_siguientes=0&fecha=2023-02-11&token=MpDY52p1V6g511VSABp1015B`
|
||||
)
|
||||
})
|
||||
|
||||
it('can generate valid request headers', async () => {
|
||||
const result = await request.headers()
|
||||
|
||||
expect(result).toMatchObject({
|
||||
authorization:
|
||||
'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOnsidGlwbyI6ImFub25pbWEifSwic3ViIjoiTXBEWTUycDFWNmc1MTFWU0FCcDEwMTVCIiwicHJuIjp7ImlkX3NlcnZpY2lvIjozLCJpZF9mcm9udGVuZCI6MTE5NiwiaXAiOiIxNzkuMjcuMTU0LjI0MiIsImlwX3JlZmVyZW5jaWFkYSI6IjE4OC4yNDIuNDguOTMiLCJpZF9kaXNwb3NpdGl2byI6MH0sImF1ZCI6IkFwcHNcL1dlYnMgRnJvbnRlbmRzIiwiaWF0IjoxNjc1ODI3NDU2LCJleHAiOjE2NzU4NDkwNTZ9.8bAQciQl5DOIZF7GgCl6ad-KJUSpqQREetozGv_IH5s',
|
||||
'x-frontend-id': 1196,
|
||||
'x-service-id': 3,
|
||||
'x-system-id': 1
|
||||
})
|
||||
})
|
||||
|
||||
it('can parse response', () => {
|
||||
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json'), 'utf8')
|
||||
let results = parser({ content })
|
||||
results = results.map(p => {
|
||||
p.start = p.start.toJSON()
|
||||
p.stop = p.stop.toJSON()
|
||||
return p
|
||||
})
|
||||
|
||||
expect(results[0]).toMatchObject({
|
||||
start: '2023-02-11T02:30:00.000Z',
|
||||
stop: '2023-02-11T04:00:00.000Z',
|
||||
title: 'Canal 5 Noticias rep.',
|
||||
sub_title: '',
|
||||
description: ''
|
||||
})
|
||||
})
|
||||
|
||||
it('can handle empty guide', () => {
|
||||
const results = parser({
|
||||
content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.json'), 'utf8')
|
||||
})
|
||||
|
||||
expect(results).toMatchObject([])
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue