diff --git a/.github/workflows/mon-programme-tv.be.yml b/.github/workflows/mon-programme-tv.be.yml
new file mode 100644
index 00000000..ff7e45ed
--- /dev/null
+++ b/.github/workflows/mon-programme-tv.be.yml
@@ -0,0 +1,17 @@
+name: mon-programme-tv.be
+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 }}
diff --git a/sites/mon-programme-tv.be/__data__/content.html b/sites/mon-programme-tv.be/__data__/content.html
new file mode 100644
index 00000000..56f66da8
--- /dev/null
+++ b/sites/mon-programme-tv.be/__data__/content.html
@@ -0,0 +1,688 @@
+
+
+
+
+
+
+ Le programme TV de LN24 - jeudi, ce soir et cette semaine. Découvrez le programme télé de LN24, gratuit et personnalisé! 19/01/2023
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Connexion J'ai un compte
+
+ Créer mon compte
+
+
+
Menu
+
+

+
+
+
+
+
Ne ratez plus vos émissions favorites!
+
Inscrivez-vous et créez votre programme TV personnalisé
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
Matinée
07:00 Le point sur l'info Information
08:00 Le point sur l'info Information
10:00 Le point sur l'info Information
11:00 Le point sur l'info Information
Après-midi
14:00 Le point sur l'info Information
15:00 Le point sur l'info Information
16:00 Le point sur l'info Information
17:00 Le point sur l'info Information
+
+
+
+
+
+
+
+
+
Films de la soirée
+
+
+
20:15
+
+ Invisible Man
+ Thriller - 1:55 - Etats-Unis - 2020
+
+
+
+
+
+
+
+
+
20:35
+
+ Chien
+ Comédie dramatique - 1:25 - France - 2017
+
+
+
+
+
+
+
+
21:10
+
+ Midway
+ Guerre - 2:15 - Etats-Unis - 2019
+
+
+
+
+
+
+
+
+
+
+
22:35
+
+ Edge of Tomorrow
+ Science-fiction - 1:55 - Etats-Unis - 2014
+
+
+
+
+
+
+
+
Séries de la soirée
+
+
+
20:35
+
+ Balthazar
+ Policier - 0:55 - France - 2022
+
+
+
+
+
+
+
20:55
+
+ Cry Wolf
+ Drame - 0:55 - Danemark - 2020
+
+
+
+
+
+
+
21:10
+
+ Balthazar
+ Policier - 0:55 - France - 2022
+
+
+
+
+
+
+
21:55
+
+ Je te promets
+ Drame - 0:55 - France - 2023
+
+
+
+
+
+
+
22:05
+
+ Balthazar
+ Policier - 1:00 - France - 2021
+
+
+
+
+
+
+
+
22:45
+
+ Cry Wolf
+ Drame - 0:55 - Danemark - 2020
+
+
+
+
+
+
+
23:45
+
+ FBI
+ Policier - 0:50 - Etats-Unis - 2018
+
+
+
+
+
+
Magazine & Divertissements
+
+
+
21:10
+
+ Envoyé spécial
+ Reportage - 1:50 - France - 2023
+
+
+
+
+
+
+
+
+
+
Sport de la soirée
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sites/mon-programme-tv.be/__data__/no_content.html b/sites/mon-programme-tv.be/__data__/no_content.html
new file mode 100644
index 00000000..296fa994
--- /dev/null
+++ b/sites/mon-programme-tv.be/__data__/no_content.html
@@ -0,0 +1,414 @@
+
+
+
+
+
+
+ Le programme TV de LN24 - vendredi, ce soir et cette semaine. Découvrez le programme télé de LN24, gratuit et personnalisé! 19/01/2024
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Connexion J'ai un compte
+
+ Créer mon compte
+
+
+
Menu
+
+

+
+
+
+
+
Ne ratez plus vos émissions favorites!
+
Inscrivez-vous et créez votre programme TV personnalisé
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sites/mon-programme-tv.be/mon-programme-tv.be.channels.xml b/sites/mon-programme-tv.be/mon-programme-tv.be.channels.xml
new file mode 100644
index 00000000..41f2e275
--- /dev/null
+++ b/sites/mon-programme-tv.be/mon-programme-tv.be.channels.xml
@@ -0,0 +1,116 @@
+
+
+
+ 13EME RUE
+ AB3
+ ABXPLORE
+ ACTION
+ ALTICE STUDIO
+ ANIMAUX
+ ARTE
+ AUTOMOTO
+ BBC ENTERTAINMENT
+ BE 1
+ BE CINE
+ BE SERIES
+ BFM TV
+ BOING
+ BOOMERANG
+ C8
+ CANAL J
+ CANVAS
+ CARTOON NETWORK
+ CHASSE & PECHE
+ CINE + CLASSIC BE
+ CINE + FRISSON BE
+ CINE + PREMIER BE
+ CLUB RTL
+ CNEWS
+ COMEDIE +
+ CSTAR
+ DISCOVERY CHANNEL
+ DISNEY CHANNEL
+ DISNEY JUNIOR
+ EEN
+ E! ENTERTAINMENT
+ EQUIDIA
+ EUROSPORT
+ EUROSPORT NL
+ EUROSPORT 2
+ FRANCE 2
+ FRANCE 24
+ FRANCE 3
+ FRANCE 4
+ FRANCE 5
+ GAME ONE
+ GULLI
+ HISTOIRE
+ KETNET
+ KTO
+ LA TROIS
+ LA UNE (RTBF)
+ LCI
+ LN24
+ M6
+ M6 MUSIC
+ MANGAS
+ MELODY
+ MEZZO
+ MTV
+ NATIONAL GEOGRAPHIC CHANNEL
+ NATIONAL GEOGRAPHIC WILD
+ NAUTICAL CHANNEL
+ NICKELODEON
+ NJAM !
+ NPO1
+ NPO2
+ NPO3
+ PARAMOUNT CHANNEL
+ PIWI +
+ PLANETE +
+ PLANETE+ AE
+ PLANETE+ CI
+ VIER
+ VIJF
+ PLAYBOY TV
+ PLUG RTL
+ RAI 1
+ RMC SPORT 2
+ RTL TVI
+ RTS UN
+ RTS DEUX
+ SCIENCE & VIE TV
+ STUDIO100tv
+ SYFY
+ TCM CINEMA
+ TELETOON +
+ TF1
+ TF1 Séries Films
+ TIJI
+ TIPIK
+ TMC
+ TOUTE L'HISTOIRE
+ TRACE URBAN
+ TV5 MONDE
+ TV BREIZH
+ USHUAIA TV
+ VOO Sport World 1
+ VOO Sport World 2
+ VOO Sport World 3
+ VTM
+ VTM2
+ VTM3
+ VTM4
+ VTM KIDS
+ Warner TV
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sites/mon-programme-tv.be/mon-programme-tv.be.config.js b/sites/mon-programme-tv.be/mon-programme-tv.be.config.js
new file mode 100644
index 00000000..f1e7d856
--- /dev/null
+++ b/sites/mon-programme-tv.be/mon-programme-tv.be.config.js
@@ -0,0 +1,100 @@
+const cheerio = require('cheerio')
+const axios = require('axios')
+const dayjs = require('dayjs')
+const utc = require('dayjs/plugin/utc')
+const timezone = require('dayjs/plugin/timezone')
+
+dayjs.extend(utc)
+dayjs.extend(timezone)
+
+module.exports = {
+ site: 'mon-programme-tv.be',
+ days: 2,
+ url({ date, channel }) {
+ return `https://www.mon-programme-tv.be/chaine/${date.format('DDMMYYYY')}/${
+ channel.site_id
+ }.html`
+ },
+ parser: function ({ content, date }) {
+ let programs = []
+ const items = parseItems(content)
+ items.forEach(item => {
+ const $item = cheerio.load(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: parseTitle($item),
+ description: parseDescription($item),
+ category: parseCategory($item),
+ icon: parseIcon($item),
+ start,
+ stop
+ })
+ })
+
+ return programs
+ },
+ async channels() {
+ const data = await axios
+ .get(`https://www.mon-programme-tv.be/chaine/toutes-les-chaines-television.html`)
+ .then(r => r.data)
+ .catch(console.log)
+ const $ = cheerio.load(data)
+
+ const channels = []
+ $('.list-chaines > ul > li').each((i, el) => {
+ const [, site_id] = $(el)
+ .find('a')
+ .attr('href')
+ .match(/\/chaine\/(.*).html/) || [null, null]
+ const [, name] = $(el)
+ .find('a')
+ .attr('title')
+ .match(/Programme TV ce soir (.*)/) || [null, null]
+
+ channels.push({
+ site_id,
+ name,
+ lang: 'fr'
+ })
+ })
+
+ return channels
+ }
+}
+
+function parseTitle($item) {
+ return $item('.title').text().trim()
+}
+
+function parseDescription($item) {
+ return $item('.episode').text().trim()
+}
+
+function parseCategory($item) {
+ return $item('.type').text().trim()
+}
+
+function parseIcon($item) {
+ return $item('.image img').data('src')
+}
+
+function parseStart($item, date) {
+ const time = $item('.hour').text().trim()
+
+ return dayjs.tz(`${date.format('YYYY-MM-DD')} ${time}`, 'YYYY-MM-DD HH:mm', 'Europe/Brussels')
+}
+
+function parseItems(content) {
+ const $ = cheerio.load(content)
+
+ return $('.box').toArray()
+}
diff --git a/sites/mon-programme-tv.be/mon-programme-tv.be.test.js b/sites/mon-programme-tv.be/mon-programme-tv.be.test.js
new file mode 100644
index 00000000..b4a07f3d
--- /dev/null
+++ b/sites/mon-programme-tv.be/mon-programme-tv.be.test.js
@@ -0,0 +1,66 @@
+// npm run channels:parse -- --config=./sites/mon-programme-tv.be/mon-programme-tv.be.config.js --output=./sites/mon-programme-tv.be/mon-programme-tv.be.channels.xml
+// npx epg-grabber --config=sites/mon-programme-tv.be/mon-programme-tv.be.config.js --channels=sites/mon-programme-tv.be/mon-programme-tv.be.channels.xml --output=guide.xml --days=2
+
+const { parser, url } = require('./mon-programme-tv.be.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('2023-01-19', 'YYYY-MM-DD').startOf('d')
+const channel = {
+ site_id: '1873/programme-television-ln24',
+ xmltv_id: 'LN24.be'
+}
+
+it('can generate valid url', () => {
+ expect(url({ date, channel })).toBe(
+ 'https://www.mon-programme-tv.be/chaine/19012023/1873/programme-television-ln24.html'
+ )
+})
+
+it('can parse response', () => {
+ const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.html'))
+ const results = parser({ content, date }).map(p => {
+ p.start = p.start.toJSON()
+ p.stop = p.stop.toJSON()
+ return p
+ })
+
+ expect(results[0]).toMatchObject({
+ start: '2023-01-19T05:30:00.000Z',
+ stop: '2023-01-19T05:55:00.000Z',
+ title: 'LN Matin',
+ category: 'Magazine Actualité',
+ icon: 'https://dnsmptv-img.pragma-consult.be/imgs/picto/132/Reportage_1.jpg'
+ })
+
+ expect(results[1]).toMatchObject({
+ start: '2023-01-19T05:55:00.000Z',
+ stop: '2023-01-19T06:00:00.000Z',
+ title: 'Météo',
+ category: 'Météo',
+ icon: 'https://dnsmptv-img.pragma-consult.be/imgs/picto/132/Meteo.jpg'
+ })
+
+ expect(results[8]).toMatchObject({
+ start: '2023-01-19T08:00:00.000Z',
+ stop: '2023-01-19T08:05:00.000Z',
+ title: 'Le journal',
+ description: "L'information de la mi-journée avec des JT...",
+ category: 'Journal',
+ icon: 'https://dnsmptv-img.pragma-consult.be/imgs/picto/132/journal.jpg'
+ })
+})
+
+it('can handle empty guide', () => {
+ const results = parser({
+ content: fs.readFileSync(path.resolve(__dirname, '__data__/no_content.html')),
+ date
+ })
+
+ expect(results).toMatchObject([])
+})