iptv-org / epg

Utilities for downloading the EPG (Electronic Program Guide) for thousands of TV channels from hundreds of sources.
https://iptv-org.github.io/
The Unlicense
1.89k stars 222 forks source link

Update meo.pt.config.js for description #2455

Closed thomraider12 closed 3 days ago

thomraider12 commented 1 month ago

Hello! With this PR, we could get a description on the "meo.pt" EPG! This would help a lot of portuguese projects. Thanks.

davidclaeysquinones commented 2 weeks ago

Your proposed changes aren't working as you expect.

The response from https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramsFromChannels does not include any program details. So the change you proposed won't add any addition information.

Instead the program details should be retrieved from https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramDetails.

It is quite tricky to call this endpoint for each program. I've worked out some code but I wasn't able to give it a final validation since my IP got blacklisted (to many tries).

So the meo.pt.config.js file should look something like this :

const { DateTime } = require('luxon')
const axios = require('axios')

module.exports = {
  site: 'meo.pt',
  days: 2,
  url: 'https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramsFromChannels',
  request: {
    method: 'POST',
    headers: {
      Origin: 'https://www.meo.pt'
    },
    data: function ({ channel, date }) {
      return {
        service: 'channelsguide',
        channels: [channel.site_id],
        dateStart: date.format('YYYY-MM-DDT00:00:00-00:00'),
        dateEnd: date.add(1, 'd').format('YYYY-MM-DDT00:00:00-00:00'),
        accountID: ''
      }
    }
  },
  async parser({ content }) {
    let programs = []
    const items = parseItems(content)
    items.forEach(item => {
      const start = parseStart(item)
      let stop = parseStop(item)
      if (stop < start) {
        stop = stop.plus({ days: 1 })
      }
      programs.push({
        title: item.name,
        start,
        stop,
        description: item.description || '',  // Inclui a descrição se existir
        icon: item.icon || ''  // Inclui o ícone se existir
      })
    })

    return programs
  },
  async channels() {
    const data = await axios
      .post(`https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getGridAnon`, null, {
        headers: {
          Origin: 'https://www.meo.pt'
        }
      })
      .then(r => r.data)
      .catch(console.log)

    return data.d.channels
      .map(item => {
        return {
          lang: 'pt',
          site_id: item.sigla,
          name: item.name
        }
      })
      .filter(channel => channel.site_id)
  }
}

// Funções utilitárias
function parseStart(item) {
  return DateTime.fromFormat(`${item.date} ${item.timeIni}`, 'd-M-yyyy HH:mm', {
    zone: 'Europe/Lisbon'
  }).toUTC()
}

function parseStop(item) {
  return DateTime.fromFormat(`${item.date} ${item.timeEnd}`, 'd-M-yyyy HH:mm', {
    zone: 'Europe/Lisbon'
  }).toUTC()
}

async function parseItems(content) {
  if (!content) return []
  const data = JSON.parse(content)
  let programs = data?.d?.channels?.[0]?.programs

  programs = Array.isArray(programs) ? programs : []

  for(let index in programs)
  {
    let program = programs[index]
    const detail = await getProgramDetails(program.uniqueId)

    program.description = detail.description
    program.icon = detail.progImageM
  }

  return programs;
}

async function getProgramDetails(programId){

  const details = await axios.post(`https://authservice.apps.meo.pt/Services/GridTv/GridTvMng.svc/getProgramDetails`, 
    {
      service: 'programdetail',
      programID: programId,
      accountID: '',
    }, 
    {
    headers: {
      'Content-Type': 'application/json',
       Origin: 'https://www.meo.pt'
    }
  })
  .then(r => {
    return r.data.d
  })
  .catch(console.log)

  return details || {}
}

Please be aware that once you get this additional data you also will need to modify the test suite accordingly. Otherwise the test for the provider will fail and the maintainers will rightly refuse to merge your PR.

If after some time my IP gets removed from the blacklist I'm going to try to give it a final validation and let you know.

davidclaeysquinones commented 2 weeks ago

I've been editing my previous comment in order to accommodate code changes. However there is one mayor hurdle, since each program needs a separate request in order to retrieve details, a lot of requests are submitted. In fact this causes so many requests that the site blocks your IP temporarily.

Right know I'm working on caching the program details based on the seriesId. However there is no guarantee this will avoid being rate limited and could bring some problems of its own.

thomraider12 commented 3 days ago

I tested it. Sorry but it didn't work.