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
+```