diff --git a/sites/maxstream.tv/maxstream.tv.channels.xml b/sites/maxstream.tv/maxstream.tv.channels.xml index 138ce9b30..28e813ea9 100644 --- a/sites/maxstream.tv/maxstream.tv.channels.xml +++ b/sites/maxstream.tv/maxstream.tv.channels.xml @@ -1,132 +1,132 @@ - - - ABC Australia - Al Jazeera - Animal Planet - Animax - Aniplus - ANTARA TV - ANTV - Arirang - afn - AXN - BBC News - Berita Satu - Bioskop Indonesia - Bloomberg - BTV - CBeebies - CCTV 4 - Celestial Movies - CGTN - CGTN Documentary - Chinese Drama - CinemaWorld - Cinemax - Citra Dangdut - Citra Drama - CNA - CNBC Asia - CNBC Indonesia - CNN Indonesia - CNN International - Crime Investigation - Curiosity Channel - DAAI TV - Da Vinci Learning - Discovery Asia - Discovery Channel - DMI TV - DreamWorks - Dunia Anak - Dunia Lain - DW English - Euronews - Fashion TV - Fight Sports - Flik - France 24 - Galaxy - Galaxy Premium - GTV - HBO - HBO Family - HBO Hits - HBO Signature - HGTV - History - HITS - HITS MOVIES - HITS Now - Horee - Horizon Sports - IDX Channel - IMC - Indosiar - Inews - JAK TV - Jawa Pos TV - JTV - KBS World - KIX - Kompas TV - K Plus - Lifetime - Love Nature - MAXEats - MAXKids - MAXReels - MAXSports - MAXStreak - MAXStream TV - MDTV - Mentari TV - Metro TV - MNC TV - Moji - Moonbug - MQTV - MTA TV - Musik Indonesia - My Kidz - New TV Comprehensive - New TV Finance - New TV Variety - NHK World Japan - Nickelodeon - Nick Junior - ONE - Phoenix Chinese - Phoenix Info News - Prambors - RTV - RCTI - Rock Action - Rock Entertainment - Rodja TV - SCTV - Shenzhen TV - Sindo News - Sinpo TV - SPOTV 2 - SPOTV - Studio Universal - The Indonesia Channel - Thrill - TLC - TRANS 7 - Trans TV - TV5 MONDE - TV9 - TVBS News - TV MU - TV MUI - tvN - tvN Movies - TV One - TVRI - TVRI World - U Channel - Zee Bioskop - Zhejiang Int - + + + ABC Australia + Al Jazeera + Animal Planet + Animax + Aniplus + ANTARA TV + ANTV + Arirang + afn + AXN + BBC News + Berita Satu + Bioskop Indonesia + Bloomberg + BTV + CBeebies + CCTV 4 + Celestial Movies + CGTN + CGTN Documentary + Chinese Drama + CinemaWorld + Cinemax + Citra Dangdut + Citra Drama + CNA + CNBC Asia + CNBC Indonesia + CNN Indonesia + CNN International + Crime Investigation + Curiosity Channel + DAAI TV + Da Vinci Learning + Discovery Asia + Discovery Channel + DMI TV + DreamWorks + Dunia Anak + Dunia Lain + DW English + Euronews + Fashion TV + Fight Sports + Flik + France 24 + Galaxy + Galaxy Premium + GTV + HBO + HBO Family + HBO Hits + HBO Signature + HGTV + History + HITS + HITS MOVIES + HITS Now + Horee + Horizon Sports + IDX Channel + IMC + Indosiar + Inews + JAK TV + Jawa Pos TV + JTV + KBS World + KIX + Kompas TV + K Plus + Lifetime + Love Nature + MAXEats + MAXKids + MAXReels + MAXSports + MAXStreak + MAXStream TV + MDTV + Mentari TV + Metro TV + MNC TV + Moji + Moonbug + MQTV + MTA TV + Musik Indonesia + My Kidz + New TV Comprehensive + New TV Finance + New TV Variety + NHK World Japan + Nickelodeon + Nick Junior + ONE + Phoenix Chinese + Phoenix Info News + Prambors + RTV + RCTI + Rock Action + Rock Entertainment + Rodja TV + SCTV + Shenzhen TV + Sindo News + Sinpo TV + SPOTV 2 + SPOTV + Studio Universal + The Indonesia Channel + Thrill + TLC + TRANS 7 + Trans TV + TV5 MONDE + TV9 + TVBS News + TV MU + TV MUI + tvN + tvN Movies + TV One + TVRI + TVRI World + U Channel + Zee Bioskop + Zhejiang Int + diff --git a/sites/maxstream.tv/maxstream.tv.config.js b/sites/maxstream.tv/maxstream.tv.config.js index 1ce8f47c0..53d67705f 100644 --- a/sites/maxstream.tv/maxstream.tv.config.js +++ b/sites/maxstream.tv/maxstream.tv.config.js @@ -1,69 +1,73 @@ -const axios = require('axios') -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 tz = 'Asia/Jakarta' - -module.exports = { - site: 'maxstream.tv', - days: 2, - url({ channel }) { - return `https://vmp.maxstream.tv/api/v3/videos/${channel.site_id}/schedules` - }, - parser({ content, channel, date }) { - const programs = [] - if (content && typeof content === 'string') { - content = JSON.parse(content) - } - if (Array.isArray(content?.data)) { - const schedules = [] - content.data.forEach(item => { - schedules.push(...item.metadata) - }) - const f = dt => dayjs.tz(dt, tz).isSame(date, 'day') - schedules - .filter(entry => entry.parentId === channel.site_id && (f(entry.startTime) || f(entry.endTime))) - .forEach(entry => { - const [, , , season, , , session2, , , episode] = entry.tvProgram.match( - /((\s(\d+)[a-zA-Z]{2})?\s(Season(\s)?||S)(\d+)?)?(\s-\sEps\.(\s)?(\d+))/ - ) || [null, null, null, null, null, null, null, null, null, null] - programs.push({ - title: entry.tvProgram, - description: entry.description, - start: dayjs.tz(entry.startTime, tz), - stop: dayjs.tz(entry.endTime, tz), - season: season || session2 ? parseInt(season || session2) : null, - episode: episode ? parseInt(episode) : null, - image: entry.thumbnail_url - }) - }) - } - - return programs - }, - async channels() { - const channels = [] - const data = await axios - .get('https://vmp.maxstream.tv/api/v3/videos/list?contentType=channel') - .then(response => response.data) - .catch(console.error) - - if (Array.isArray(data?.videos)) { - channels.push(...data.videos - .filter(item => item?.contentType === 'Channel') - .map(item => ({ - lang: 'id', - site_id: item.id, - name: item.translations.id.title - }))) - } - - return channels - } -} +const axios = require('axios') +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 tz = 'Asia/Jakarta' + +module.exports = { + site: 'maxstream.tv', + days: 2, + url({ channel }) { + return `https://vmp.maxstream.tv/api/v3/videos/${channel.site_id}/schedules` + }, + parser({ content, channel, date }) { + const programs = [] + if (content && typeof content === 'string') { + content = JSON.parse(content) + } + if (Array.isArray(content?.data)) { + const schedules = [] + content.data.forEach(item => { + schedules.push(...item.metadata) + }) + const f = dt => dayjs.tz(dt, tz).isSame(date, 'day') + schedules + .filter( + entry => entry.parentId === channel.site_id && (f(entry.startTime) || f(entry.endTime)) + ) + .forEach(entry => { + const [, , , season, , , session2, , , episode] = entry.tvProgram.match( + /((\s(\d+)[a-zA-Z]{2})?\s(Season(\s)?||S)(\d+)?)?(\s-\sEps\.(\s)?(\d+))/ + ) || [null, null, null, null, null, null, null, null, null, null] + programs.push({ + title: entry.tvProgram, + description: entry.description, + start: dayjs.tz(entry.startTime, tz), + stop: dayjs.tz(entry.endTime, tz), + season: season || session2 ? parseInt(season || session2) : null, + episode: episode ? parseInt(episode) : null, + image: entry.thumbnail_url + }) + }) + } + + return programs + }, + async channels() { + const channels = [] + const data = await axios + .get('https://vmp.maxstream.tv/api/v3/videos/list?contentType=channel') + .then(response => response.data) + .catch(console.error) + + if (Array.isArray(data?.videos)) { + channels.push( + ...data.videos + .filter(item => item?.contentType === 'Channel') + .map(item => ({ + lang: 'id', + site_id: item.id, + name: item.translations.id.title + })) + ) + } + + return channels + } +} diff --git a/sites/maxstream.tv/maxstream.tv.test.js b/sites/maxstream.tv/maxstream.tv.test.js index 07b0b9113..6ff7a0713 100644 --- a/sites/maxstream.tv/maxstream.tv.test.js +++ b/sites/maxstream.tv/maxstream.tv.test.js @@ -1,54 +1,51 @@ -const { parser, url } = require('./maxstream.tv.config.js') -const fs = require('fs') -const path = require('path') -const dayjs = require('dayjs') -const utc = require('dayjs/plugin/utc') - -dayjs.extend(utc) - -const date = dayjs.utc('2026-05-02').startOf('d') -const channel = { site_id: '0_86sal99e' } - -it('can generate valid url', () => { - expect(url({ channel })).toBe( - 'https://vmp.maxstream.tv/api/v3/videos/0_86sal99e/schedules' - ) -}) - -it('can parse response', () => { - const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json')) - .toString() - const results = parser({ content, channel, date }).map(p => { - p.start = p.start.toJSON() - p.stop = p.stop.toJSON() - return p - }) - - expect(results.length).toBe(49) - expect(results[0]).toMatchObject({ - title: 'I\'ll Become A Villainess Who Goes Down In History - Eps.12', - description: - 'Seorang gadis bereinkarnasi sebagai tokoh antagonis dalam novel fantasi. Ia bertekad menjadi villain sejati, namun pilihan tindakannya justru mengubah jalan cerita dan memengaruhi hubungan dengan karakter lain.', - start: '2026-05-01T16:30:00.000Z', - stop: '2026-05-01T17:00:00.000Z', - episode: 12 - }) - expect(results[46]).toMatchObject({ - title: 'Haikyu!! 4Th Season - Eps.22', - description: - 'Karasuno melaju ke turnamen nasional dan menghadapi tim-tim elit dengan gaya bermain berbeda. Latihan intens dan strategi baru menguji kemampuan Hinata serta rekan-rekannya dalam menghadapi tekanan pertandingan besar.', - start: '2026-05-02T15:26:00.000Z', - stop: '2026-05-02T16:00:00.000Z', - season: 4, - episode: 22 - }) -}) - -it('can handle empty guide', () => { - const results = parser({ - content: '', - channel - }) - - expect(results).toMatchObject([]) -}) +const { parser, url } = require('./maxstream.tv.config.js') +const fs = require('fs') +const path = require('path') +const dayjs = require('dayjs') +const utc = require('dayjs/plugin/utc') + +dayjs.extend(utc) + +const date = dayjs.utc('2026-05-02').startOf('d') +const channel = { site_id: '0_86sal99e' } + +it('can generate valid url', () => { + expect(url({ channel })).toBe('https://vmp.maxstream.tv/api/v3/videos/0_86sal99e/schedules') +}) + +it('can parse response', () => { + const content = fs.readFileSync(path.resolve(__dirname, '__data__/content.json')).toString() + const results = parser({ content, channel, date }).map(p => { + p.start = p.start.toJSON() + p.stop = p.stop.toJSON() + return p + }) + + expect(results.length).toBe(49) + expect(results[0]).toMatchObject({ + title: "I'll Become A Villainess Who Goes Down In History - Eps.12", + description: + 'Seorang gadis bereinkarnasi sebagai tokoh antagonis dalam novel fantasi. Ia bertekad menjadi villain sejati, namun pilihan tindakannya justru mengubah jalan cerita dan memengaruhi hubungan dengan karakter lain.', + start: '2026-05-01T16:30:00.000Z', + stop: '2026-05-01T17:00:00.000Z', + episode: 12 + }) + expect(results[46]).toMatchObject({ + title: 'Haikyu!! 4Th Season - Eps.22', + description: + 'Karasuno melaju ke turnamen nasional dan menghadapi tim-tim elit dengan gaya bermain berbeda. Latihan intens dan strategi baru menguji kemampuan Hinata serta rekan-rekannya dalam menghadapi tekanan pertandingan besar.', + start: '2026-05-02T15:26:00.000Z', + stop: '2026-05-02T16:00:00.000Z', + season: 4, + episode: 22 + }) +}) + +it('can handle empty guide', () => { + const results = parser({ + content: '', + channel + }) + + expect(results).toMatchObject([]) +}) diff --git a/sites/maxstream.tv/readme.md b/sites/maxstream.tv/readme.md index 3d0557638..6df945a40 100644 --- a/sites/maxstream.tv/readme.md +++ b/sites/maxstream.tv/readme.md @@ -1,21 +1,21 @@ -# maxstream.tv - -https://maxstream.tv/home - -### Download the guide - -```sh -npm run grab --- --channels=sites/maxstream.tv/maxstream.tv.channels.xml -``` - -### Update channel list - -```sh -npm run channels:parse --- --config=./sites/maxstream.tv/maxstream.tv.config.js --output=./sites/maxstream.tv/maxstream.tv.channels.xml -``` - -### Test - -```sh -npm test --- maxstream.tv -``` +# maxstream.tv + +https://maxstream.tv/home + +### Download the guide + +```sh +npm run grab --- --channels=sites/maxstream.tv/maxstream.tv.channels.xml +``` + +### Update channel list + +```sh +npm run channels:parse --- --config=./sites/maxstream.tv/maxstream.tv.config.js --output=./sites/maxstream.tv/maxstream.tv.channels.xml +``` + +### Test + +```sh +npm test --- maxstream.tv +```