From 510e566f8a930c49e5e0e249e897bc9bc05dc482 Mon Sep 17 00:00:00 2001
From: Aleksandr Statciuk <github@oiya.xyz>
Date: Mon, 7 Feb 2022 05:53:30 +0300
Subject: [PATCH] wip

---
 scripts/commands/generate-playlists.js        | 121 +++++-------------
 scripts/generators/index.js                   |   2 +
 scripts/generators/index_language_m3u.js      |  22 ++++
 scripts/generators/index_region_m3u.js        |  22 ++++
 .../expected/.gh-pages/index.language.m3u     |  13 ++
 .../expected/.gh-pages/index.region.m3u       |  31 +++++
 6 files changed, 121 insertions(+), 90 deletions(-)
 create mode 100644 scripts/generators/index_language_m3u.js
 create mode 100644 scripts/generators/index_region_m3u.js
 create mode 100644 tests/__data__/expected/.gh-pages/index.language.m3u
 create mode 100644 tests/__data__/expected/.gh-pages/index.region.m3u

diff --git a/scripts/commands/generate-playlists.js b/scripts/commands/generate-playlists.js
index ebefbae5d..f37a43eaf 100644
--- a/scripts/commands/generate-playlists.js
+++ b/scripts/commands/generate-playlists.js
@@ -1,22 +1,19 @@
-const { create: createPlaylist } = require('../core/playlist')
-const { db, logger, generator, file, api } = require('../core')
+const { db, generator, api } = require('../core')
 const _ = require('lodash')
 
 async function main() {
   const streams = await loadStreams()
-  // console.log(streams)
+
   await generator.generate('categories', streams)
   await generator.generate('countries', streams)
   await generator.generate('languages', streams)
   await generator.generate('regions', streams)
-  await generator.generate('index_m3u', streams)
-  await generator.generate('index_nsfw_m3u', streams)
   await generator.generate('index_category_m3u', streams)
   await generator.generate('index_country_m3u', streams)
-
-  // await generateIndexCountry()
-  // await generateIndexLanguage()
-  // await generateIndexRegion()
+  await generator.generate('index_language_m3u', streams)
+  await generator.generate('index_m3u', streams)
+  await generator.generate('index_nsfw_m3u', streams)
+  await generator.generate('index_region_m3u', streams)
 }
 
 main()
@@ -38,6 +35,10 @@ async function loadStreams() {
   let languages = await api.languages.all()
   languages = _.keyBy(languages, 'code')
 
+  await api.regions.load()
+  let regions = await api.regions.all()
+  regions = _.keyBy(regions, 'code')
+
   await api.guides.load()
   let guides = await api.guides.all()
   guides = _.groupBy(guides, 'channel')
@@ -54,6 +55,26 @@ async function loadStreams() {
         const [_, code] = item.split('/')
         return code
       })
+      stream.regions = channel.broadcast_area
+        .reduce((acc, item) => {
+          const [type, code] = item.split('/')
+          switch (type) {
+            case 'r':
+              acc.push(regions[code])
+              break
+            case 's':
+              const [c] = item.split('-')
+              const r1 = _.filter(regions, { countries: [c] })
+              acc = acc.concat(r1)
+              break
+            case 'c':
+              const r2 = _.filter(regions, { countries: [code] })
+              acc = acc.concat(r2)
+              break
+          }
+          return acc
+        }, [])
+        .filter(i => i)
       stream.categories = channel.categories.map(id => categories[id])
       stream.languages = channel.languages.map(code => languages[code])
       stream.guides = guides[stream.channel_id] ? guides[stream.channel_id].map(g => g.url) : []
@@ -61,90 +82,10 @@ async function loadStreams() {
       stream.broadcast_area = []
       stream.categories = []
       stream.languages = []
+      stream.regions = []
       stream.guides = []
     }
 
     return stream
   })
 }
-
-// async function generateIndexLanguage() {
-//   logger.info(`Generating index.language.m3u...`)
-
-//   await generator.generate(
-//     `${PUBLIC_PATH}/index.language.m3u`,
-//     {},
-//     {
-//       onLoad: function (items) {
-//         let results = items
-//           .filter(item => !item.languages || !item.languages.length)
-//           .map(item => {
-//             const newItem = _.cloneDeep(item)
-//             newItem.group_title = 'Undefined'
-//             newItem.categories = []
-//             return newItem
-//           })
-//         for (const language of languages) {
-//           let filtered = items
-//             .filter(item => {
-//               return (
-//                 Array.isArray(item.languages) &&
-//                 item.languages.map(c => c.code).includes(language.code)
-//               )
-//             })
-//             .map(item => {
-//               const newItem = _.cloneDeep(item)
-//               newItem.group_title = language.name
-//               return newItem
-//             })
-//           results = results.concat(filtered)
-//         }
-
-//         return results
-//       },
-//       sortBy: item => {
-//         if (item.group_title === 'Undefined') return '_'
-//         return item.group_title
-//       }
-//     }
-//   )
-// }
-
-// async function generateIndexRegion() {
-//   logger.info(`Generating index.region.m3u...`)
-
-//   await generator.generate(
-//     `${PUBLIC_PATH}/index.region.m3u`,
-//     {},
-//     {
-//       onLoad: function (items) {
-//         let results = items
-//           .filter(item => !item.regions.length)
-//           .map(item => {
-//             const newItem = _.cloneDeep(item)
-//             newItem.group_title = 'Undefined'
-//             newItem.categories = []
-//             return newItem
-//           })
-//         for (const region of regions) {
-//           let filtered = items
-//             .filter(item => {
-//               return item.regions.map(c => c.code).includes(region.code)
-//             })
-//             .map(item => {
-//               const newItem = _.cloneDeep(item)
-//               newItem.group_title = region.name
-//               return newItem
-//             })
-//           results = results.concat(filtered)
-//         }
-
-//         return results
-//       },
-//       sortBy: item => {
-//         if (item.group_title === 'Undefined') return '_'
-//         return item.group_title
-//       }
-//     }
-//   )
-// }
diff --git a/scripts/generators/index.js b/scripts/generators/index.js
index b60b09793..50e75cfeb 100644
--- a/scripts/generators/index.js
+++ b/scripts/generators/index.js
@@ -6,3 +6,5 @@ exports.index_m3u = require('./index_m3u')
 exports.index_nsfw_m3u = require('./index_nsfw_m3u')
 exports.index_category_m3u = require('./index_category_m3u')
 exports.index_country_m3u = require('./index_country_m3u')
+exports.index_language_m3u = require('./index_language_m3u')
+exports.index_region_m3u = require('./index_region_m3u')
diff --git a/scripts/generators/index_language_m3u.js b/scripts/generators/index_language_m3u.js
new file mode 100644
index 000000000..4f9889be5
--- /dev/null
+++ b/scripts/generators/index_language_m3u.js
@@ -0,0 +1,22 @@
+const api = require('../core/api')
+const _ = require('lodash')
+
+module.exports = async function (streams = []) {
+	streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false)
+	let items = []
+	streams.forEach(stream => {
+		if (!stream.languages.length) return items.push(stream)
+
+		stream.languages.forEach(language => {
+			const item = _.cloneDeep(stream)
+			item.group_title = language.name
+			items.push(item)
+		})
+	})
+	items = _.sortBy(items, i => {
+		if (i.group_title === 'Undefined') return '_'
+		return i.group_title
+	})
+
+	return { filepath: 'index.language.m3u', items }
+}
diff --git a/scripts/generators/index_region_m3u.js b/scripts/generators/index_region_m3u.js
new file mode 100644
index 000000000..86f00f2fb
--- /dev/null
+++ b/scripts/generators/index_region_m3u.js
@@ -0,0 +1,22 @@
+const api = require('../core/api')
+const _ = require('lodash')
+
+module.exports = async function (streams = []) {
+	streams = _.filter(streams, s => !s.channel || s.channel.is_nsfw === false)
+	let items = []
+	streams.forEach(stream => {
+		if (!stream.regions.length) return items.push(stream)
+
+		stream.regions.forEach(region => {
+			const item = _.cloneDeep(stream)
+			item.group_title = region.name
+			items.push(item)
+		})
+	})
+	items = _.sortBy(items, i => {
+		if (i.group_title === 'Undefined') return '_'
+		return i.group_title
+	})
+
+	return { filepath: 'index.region.m3u', items }
+}
diff --git a/tests/__data__/expected/.gh-pages/index.language.m3u b/tests/__data__/expected/.gh-pages/index.language.m3u
new file mode 100644
index 000000000..2d6aa2a7e
--- /dev/null
+++ b/tests/__data__/expected/.gh-pages/index.language.m3u
@@ -0,0 +1,13 @@
+#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml"
+#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="English",BBC News HD (720p) [Not 24/7]
+http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8
+#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="French",Meteomedia
+http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
+#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Russian",ЛДПР ТВ (1080p)
+http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
+#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Valencian",ATV (720p) [Offline]
+https://iptv-all.lanesh4d0w.repl.co/andorra/atv
+#EXTINF:-1 tvg-id="" tvg-country="" tvg-language="" tvg-logo="" group-title="Undefined",Daawah TV
+http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
+#EXTINF:-1 tvg-id="" tvg-country="" tvg-language="" tvg-logo="" group-title="Undefined",Tastemade
+https://tastemade-freetv16min-plex.amagi.tv/hls/amagi_hls_data_tastemade-tastemadefreetv16-plex/CDN/playlist.m3u8
diff --git a/tests/__data__/expected/.gh-pages/index.region.m3u b/tests/__data__/expected/.gh-pages/index.region.m3u
new file mode 100644
index 000000000..73ec6be9b
--- /dev/null
+++ b/tests/__data__/expected/.gh-pages/index.region.m3u
@@ -0,0 +1,31 @@
+#EXTM3U x-tvg-url="https://iptv-org.github.io/epg/guides/ad/andorradifusio.ad.epg.xml,https://iptv-org.github.io/epg/guides/ch/tv.blue.ch.epg.xml,https://iptv-org.github.io/epg/guides/ru/tv.yandex.ru.epg.xml,https://iptv-org.github.io/epg/guides/uk/ontvtonight.com.epg.xml,https://iptv-org.github.io/epg/guides/uk/sky.com.epg.xml"
+#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Americas",Meteomedia
+http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
+#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Asia",ЛДПР ТВ (1080p)
+http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
+#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Commonwealth of Independent States",ЛДПР ТВ (1080p)
+http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
+#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Europe",ATV (720p) [Offline]
+https://iptv-all.lanesh4d0w.repl.co/andorra/atv
+#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe",ЛДПР ТВ (1080p)
+http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
+#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Europe, the Middle East and Africa",ATV (720p) [Offline]
+https://iptv-all.lanesh4d0w.repl.co/andorra/atv
+#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Europe, the Middle East and Africa",ЛДПР ТВ (1080p)
+http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
+#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="North America",Meteomedia
+http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
+#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Northern America",Meteomedia
+http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
+#EXTINF:-1 tvg-id="AndorraTV.ad" tvg-country="AD" tvg-language="Valencian" tvg-logo="" group-title="Worldwide",ATV (720p) [Offline]
+https://iptv-all.lanesh4d0w.repl.co/andorra/atv
+#EXTINF:-1 tvg-id="BBCNews.uk" tvg-country="INT" tvg-language="English" tvg-logo="https://raw.githubusercontent.com/Tapiosinn/tv-logos/master/countries/united-kingdom/bbc-news-uk.png" group-title="Worldwide",BBC News HD (720p) [Not 24/7]
+http://1111296894.rsc.cdn77.org/LS-ATL-54548-6/playlist.m3u8
+#EXTINF:-1 tvg-id="MeteoMedia.ca" tvg-country="CA" tvg-language="French" tvg-logo="https://s1.twnmm.com/images/en_ca/mobile/logos/twn-mobile-logo.png" group-title="Worldwide",Meteomedia
+http://encodercdn1.frontline.ca/encoder181/output/Meteo_Media_720p/playlist.m3u8
+#EXTINF:-1 tvg-id="LDPRTV.ru" tvg-country="RU" tvg-language="Russian" tvg-logo="https://iptvx.one/icn/ldpr-tv.png" group-title="Worldwide",ЛДПР ТВ (1080p)
+http://46.46.143.222:1935/live/mp4:ldpr.stream/playlist.m3u8
+#EXTINF:-1 tvg-id="" tvg-country="" tvg-language="" tvg-logo="" group-title="Undefined",Daawah TV
+http://51.15.246.58:8081/daawahtv/daawahtv2/playlist.m3u8
+#EXTINF:-1 tvg-id="" tvg-country="" tvg-language="" tvg-logo="" group-title="Undefined",Tastemade
+https://tastemade-freetv16min-plex.amagi.tv/hls/amagi_hls_data_tastemade-tastemadefreetv16-plex/CDN/playlist.m3u8