const cheerio = require('cheerio') const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') const timezone = require('dayjs/plugin/timezone') const customParseFormat = require('dayjs/plugin/customParseFormat') const doFetch = require('../../scripts/core/fetch') const debug = require('debug')('site:mytelly.co.uk') dayjs.extend(utc) dayjs.extend(timezone) dayjs.extend(customParseFormat) doFetch.setDebugger(debug) const detailedGuide = true const tz = 'Europe/London' module.exports = { site: 'mytelly.co.uk', days: 2, url({ date, channel }) { return `https://www.mytelly.co.uk/tv-guide/listings/channel/${ channel.site_id }.html?dt=${date.format('YYYY-MM-DD')}` }, async parser({ content, date, channel }) { const programs = [] if (content) { const queues = [] const $ = cheerio.load(content) $('table.table > tbody > tr').toArray() .forEach(el => { const td = $(el).find('td:eq(1)') const title = td.find('h5 a') if (detailedGuide) { queues.push(title.attr('href')) } else { const subtitle = td.find('h6') const time = $(el).find('td:eq(0)') let start = parseTime(date, time.text().trim()) const prev = programs[programs.length - 1] 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: parseText(title), subTitle: parseText(subtitle), start, stop }) } }) if (queues.length) { await doFetch(queues, (url, res) => { const $ = cheerio.load(res) const time = $('center > h5 > b').text() const title = parseText($('.inner-heading.sub h2')) const subTitle = parseText($('.tab-pane > h5 > strong')) const description = parseText($('.tab-pane > .tvbody > p')) const image = $('.program-media-image img').attr('src') const category = $('.schedule-attributes-genres span').toArray() .map(el => $(el).text()) const casts = $('.single-cast-head:not([id])').toArray() .map(el => { const cast = { name: parseText($(el).find('a')) } const [, role] = $(el).text().match(/\((.*)\)/) || [null, null] if (role) { cast.role = role } return cast }) const [start, stop] = parseStartStop(date, time) let season, episode if (subTitle) { const [, ses, epi] = subTitle.match(/Season (\d+), Episode (\d+)/) || [null, null] if (ses) { season = parseInt(ses) } if (epi) { episode = parseInt(epi) } } programs.push({ title, subTitle, description, image, category, season, episode, actor: casts.filter(c => c.role === 'Actor').map(c => c.name), director: casts.filter(c => c.role === 'Director').map(c => c.name), presenter: casts.filter(c => c.role === 'Presenter').map(c => c.name), start, stop }) }) } } return programs }, async channels() { const channels = {} const queues = [{ t: 'p', m: 'post', u: 'https://www.mytelly.co.uk/getform' }] await doFetch(queues, (queue, res) => { // process form -> provider if (queue.t === 'p') { const $ = cheerio.load(res) $('#guide_provider option').toArray() .forEach(el => { const opt = $(el) const provider = opt.attr('value') queues.push({ t: 'r', m: 'post', u: 'https://www.mytelly.co.uk/getregions', params: { provider } }) }) } // process provider -> region if (queue.t === 'r') { const now = dayjs() for (const r of Object.values(res)) { const params = { provider: queue.params.provider, region: r.title, TVperiod: 'Night', date: now.format('YYYY-MM-DD'), st: 0, u_time: now.format('HHmm'), is_mobile: 1 } queues.push({ t: 's', m: 'post', u: 'https://www.mytelly.co.uk/tv-guide/schedule', params }) } } // process schedule -> channels if (queue.t === 's') { const $ = cheerio.load(res) $('.channelname') .each((i, el) => { const name = $(el).find('center > a:eq(1)').text() const url = $(el).find('center > a:eq(1)').attr('href') const [, number, slug] = url.match(/\/(\d+)\/(.*)\.html$/) const site_id = `${number}/${slug}` if (channels[site_id] === undefined) { channels[site_id] = { lang: 'en', site_id, name } } }) } }) return Object.values(channels) } } function parseStartStop(date, time) { const [s, e] = time.split(' - ') const start = parseTime(date, s) let stop = parseTime(date, e) if (stop.isBefore(start)) { stop = stop.add(1, 'd') } return [start, stop] } function parseTime(date, time) { return dayjs.tz(`${date.format('YYYY-MM-DD')} ${time}`, 'YYYY-MM-DD H:mm a', tz) } function parseText($item) { let text = $item.text() .replace(/\t/g, '') .replace(/\n/g, ' ') .trim() while (true) { if (text.match(/ /)) { text = text.replace(/ /g, ' ') continue } break } return text }