epg/sites/mncvision.id/mncvision.id.config.js
Toha f0cadf182e
Optimize mncvision.id grabber connection.
Currently while fetching guide for every channels, there will be one additional
connection used to set the language cookie. This optimization change this behaviour
by setting the language cookie once and then use those cookie for the rest of the
channels unless there's change in channel language.

Assume there are 10 channels and each channel only use one connection. Before the
optimization the connections made are 20 (1 for guide fetch, 1 for set language,
then multiplied by 10), and after the optimization the connections made are 11
(1 for set language, 1 for guide fetch multiplied by 10).

Signed-off-by: Toha <tohenk@yahoo.com>
2023-11-21 22:42:02 +07:00

165 lines
4.6 KiB
JavaScript

const _ = require('lodash')
const axios = require('axios')
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')
dayjs.extend(utc)
dayjs.extend(timezone)
dayjs.extend(customParseFormat)
const languages = { en: 'english', id: 'indonesia' }
const cookies = {}
const timeout = 30000
module.exports = {
site: 'mncvision.id',
days: 2,
url: 'https://www.mncvision.id/schedule/table',
request: {
method: 'POST',
data({ channel, date }) {
const formData = new URLSearchParams()
formData.append('search_model', 'channel')
formData.append('af0rmelement', 'aformelement')
formData.append('fdate', date.format('YYYY-MM-DD'))
formData.append('fchannel', channel.site_id)
formData.append('submit', 'Search')
return formData
},
async headers({ channel }) {
const headers = {
'Content-Type': 'application/x-www-form-urlencoded'
}
if (channel && !cookies[channel.lang]) {
cookies[channel.lang] = await loadLangCookies(channel)
if (cookies[channel.lang]) {
headers.Cookie = cookies[channel.lang]
}
}
return headers
},
jar: null
},
async parser({ content, headers, date, channel}) {
const programs = []
if (!cookies[channel.lang]) {
cookies[channel.lang] = parseCookies(headers)
}
const [$, items] = parseItems(content)
for (const item of items) {
const $item = $(item)
const start = parseStart($item, date)
const duration = parseDuration($item)
const stop = start.add(duration, 'm')
const description = await loadDescription($item, cookies[channel.lang])
programs.push({
title: parseTitle($item),
season: parseSeason($item),
episode: parseEpisode($item),
description,
start,
stop
})
}
return programs
},
async channels({lang = 'id'}) {
const axios = require('axios')
const cheerio = require('cheerio')
const result = await axios
.get('https://www.mncvision.id/schedule')
.then(response => response.data)
.catch(console.error)
const $ = cheerio.load(result)
const items = $('select[name="fchannel"] option').toArray()
const channels = items.map(item => {
const $item = $(item)
return {
lang,
site_id: $item.attr('value'),
name: $item.text().split(' - ')[0].trim()
}
})
return channels
}
}
function parseSeason($item) {
const title = parseTitle($item)
const [, season] = title.match(/ S(\d+)/) || [null, null]
return season ? parseInt(season) : null
}
function parseEpisode($item) {
const title = parseTitle($item)
const [, episode] = title.match(/ Ep (\d+)/) || [null, null]
return episode ? parseInt(episode) : null
}
function parseDuration($item) {
let duration = $item.find('td:nth-child(3)').text()
const match = duration.match(/(\d{2}):(\d{2})/)
const hours = parseInt(match[1])
const minutes = parseInt(match[2])
return hours * 60 + minutes
}
function parseStart($item, date) {
let time = $item.find('td:nth-child(1)').text()
time = `${date.format('DD/MM/YYYY')} ${time}`
return dayjs.tz(time, 'DD/MM/YYYY HH:mm', 'Asia/Jakarta')
}
function parseTitle($item) {
return $item.find('td:nth-child(2) > a').text()
}
function parseItems(content) {
const $ = cheerio.load(content)
return [$, $('tr[valign="top"]').toArray()]
}
function loadLangCookies(channel) {
const url = `https://www.mncvision.id/language_switcher/setlang/${languages[channel.lang]}/`
return axios
.get(url, { timeout })
.then(r => parseCookies(r.headers))
.catch(error => console.error(error.message))
}
async function loadDescription($item, cookies) {
const url = $item.find('a').attr('href')
if (!url) return null
const content = await axios
.get(url, {
headers: { 'X-Requested-With': 'XMLHttpRequest', Cookie: cookies },
timeout
})
.then(r => r.data)
.catch(error => console.error(error.message))
if (!content) return null
const $page = cheerio.load(content)
const description = $page('.synopsis').text().trim()
return description !== '-' ? description : null
}
function parseCookies(headers) {
return Array.isArray(headers['set-cookie']) ? headers['set-cookie'].join(';') : null
}