Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
147 changes: 77 additions & 70 deletions sites/telebilbao.es/telebilbao.es.config.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,77 @@
const dayjs = require('dayjs')
const cheerio = require('cheerio')
const table2array = require('table2array')
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)

require('dayjs/locale/es')

module.exports = {
site: 'telebilbao.es',
days: 1,
url: 'https://www.telebilbao.es/programacion-2/',
request: {
cache: {
ttl: 24 * 60 * 60 * 1000 // 1 day
}
},
parser({ content, date }) {
let programs = []
const items = parseItems(content, date)
items.forEach(item => {
const prev = programs[programs.length - 1]
let start = parseStart(item, date)
if (prev) {
if (start.isBefore(prev.start)) {
start = start.add(1, 'd')
date = date.add(1, 'd')
}
prev.stop = start
}
const stop = start.add(30, 'm')

programs.push({
title: item.title,
start,
stop
})
})

return programs
}
}

function parseStart(item, date) {
return dayjs.tz(`${date.format('YYYY-MM-DD')} ${item.time}`, 'YYYY-MM-DD HH:mm', 'Europe/Madrid')
}

function parseItems(content, date) {
const $ = cheerio.load(content)
const tableHtml = $('table.programacion').html()
let tableArray = table2array(`<table>${tableHtml}</table>`)
const day = date.locale('es').format('dddd\nD MMMM').toUpperCase()
if (!tableArray[0]) return []
const indexOfColumn = tableArray[0].indexOf(day)
tableArray.pop()
const items = []
tableArray.forEach(row => {
items.push({
time: row[0],
title: row[indexOfColumn]
})
})

return items.filter(i => Boolean(i.time))
}
const dayjs = require('dayjs')

Check failure on line 1 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
const cheerio = require('cheerio')

Check failure on line 2 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
const table2array = require('table2array')

Check failure on line 3 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
const utc = require('dayjs/plugin/utc')

Check failure on line 4 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
const timezone = require('dayjs/plugin/timezone')

Check failure on line 5 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
const customParseFormat = require('dayjs/plugin/customParseFormat')

Check failure on line 6 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'

Check failure on line 7 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
dayjs.extend(utc)

Check failure on line 8 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
dayjs.extend(timezone)

Check failure on line 9 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'
dayjs.extend(customParseFormat)

Check failure on line 10 in sites/telebilbao.es/telebilbao.es.config.js

View workflow job for this annotation

GitHub Actions / main

Expected linebreaks to be 'CRLF' but found 'LF'

require('dayjs/locale/es')

module.exports = {
site: 'telebilbao.es',
days: 1,
url: 'https://www.telebilbao.es/programacion-2/',
request: {
cache: {
ttl: 24 * 60 * 60 * 1000 // 1 day
}
},
parser({ content, date }) {
let programs = []
const items = parseItems(content, date)
items.forEach(item => {
const prev = programs.at(-1)
let start = parseStart(item, date)
if (prev) {
if (start.isBefore(prev.start)) {
start = start.add(1, 'd')
date = date.add(1, 'd')
}
prev.stop = start
}
const stop = start.add(30, 'm')

programs.push({
title: item.title,
start,
stop
})
})

return programs
}
}

function parseStart(item, date) {
return dayjs.tz(`${date.format('YYYY-MM-DD')} ${item.time}`, 'YYYY-MM-DD HH:mm', 'Europe/Madrid')
}

function removeAccents(value) {
return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '')
}

function parseItems(content, date) {
const $ = cheerio.load(content)
const tableHtml = $('table.programacion').html()
let tableArray = table2array(`<table>${tableHtml}</table>`)
const day = removeAccents(date.locale('es').format('dddd\nD MMMM')).toUpperCase()
if (!tableArray[0]) return []
for(let i = 0; i < tableArray[0].length; i++) {
tableArray[0][i] = removeAccents(tableArray[0][i]).toUpperCase()
}
const indexOfColumn = tableArray[0].indexOf(day)
tableArray.pop()
const items = []
tableArray.forEach(row => {
items.push({
time: row[0],
title: row[indexOfColumn]
})
})

return items.filter(i => Boolean(i.time))
}
98 changes: 54 additions & 44 deletions sites/telebilbao.es/telebilbao.es.test.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,54 @@
const { parser, url } = require('./telebilbao.es.config.js')
const fs = require('fs')
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)

const date = dayjs.utc('2025-01-16', 'YYYY-MM-DD').startOf('d')

it('can generate valid url', () => {
expect(url).toBe('https://www.telebilbao.es/programacion-2/')
})

it('can parse response', () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
let results = parser({ content, date })
results = results.map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
return p
})

expect(results.length).toBe(50)
expect(results[0]).toMatchObject({
start: '2025-01-16T06:00:00.000Z',
stop: '2025-01-16T06:30:00.000Z',
title: 'BAI HORIXE'
})
expect(results[49]).toMatchObject({
start: '2025-01-17T07:30:00.000Z',
stop: '2025-01-17T08:00:00.000Z',
title: 'LA KAPITAL'
})
})

it('can handle empty guide', () => {
const results = parser({
date,
content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html'))
})
expect(results).toMatchObject([])
})
const { parser, url } = require('./telebilbao.es.config.js')
const fs = require('fs')
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)

const date = dayjs.utc('2025-01-16', 'YYYY-MM-DD').startOf('d')

it('can generate valid url', () => {
expect(url).toBe('https://www.telebilbao.es/programacion-2/')
})

it('can parse response', () => {
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
let results = parser({ content, date })
results = results.map(p => {
p.start = p.start.toJSON()
p.stop = p.stop.toJSON()
return p
})

expect(results.length).toBe(50)
expect(results[0]).toMatchObject({
start: '2025-01-16T06:00:00.000Z',
stop: '2025-01-16T06:30:00.000Z',
title: 'BAI HORIXE'
})
expect(results[49]).toMatchObject({
start: '2025-01-17T07:30:00.000Z',
stop: '2025-01-17T08:00:00.000Z',
title: 'LA KAPITAL'
})
})

it('can parse response with accents', () => {
const date = dayjs.utc('2025-01-18', 'YYYY-MM-DD').startOf('d')
const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
let results = parser({ content, date })

expect(results.length).toBe(50)

results.forEach(r => expect(r.title).not.toBeUndefined())
})

it('can handle empty guide', () => {
const results = parser({
date,
content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html'))
})
expect(results).toMatchObject([])
})
Loading