diff --git a/config.xml b/config.xml index 336f3047..bc714c18 100644 --- a/config.xml +++ b/config.xml @@ -1,5 +1,5 @@ - + Megacubo An intuitive, free and open source IPTV player. @@ -65,7 +65,7 @@ - + diff --git a/package.json b/package.json index 85040a5f..3bb38d84 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "megacubo", "displayName": "Megacubo", - "version": "17.4.3", + "version": "17.4.4", "description": "A intuitive and multi-language IPTV player.", "repository": { "type": "git", diff --git a/www/nodejs-project/assets/images/background-1920x1080.jpg b/www/nodejs-project/assets/images/background-1920x1080.jpg new file mode 100644 index 00000000..442c2ff9 Binary files /dev/null and b/www/nodejs-project/assets/images/background-1920x1080.jpg differ diff --git a/www/nodejs-project/assets/images/background-3840x2160.jpg b/www/nodejs-project/assets/images/background-3840x2160.jpg new file mode 100644 index 00000000..b141fbe3 Binary files /dev/null and b/www/nodejs-project/assets/images/background-3840x2160.jpg differ diff --git a/www/nodejs-project/assets/js/app/index.js b/www/nodejs-project/assets/js/app/index.js index 79442be0..c553a58f 100644 --- a/www/nodejs-project/assets/js/app/index.js +++ b/www/nodejs-project/assets/js/app/index.js @@ -49,7 +49,7 @@ function theming(image, video, color, fontColor, animate){ console.warn('theming', image, video, color, fontColor, animate); var bg = document.getElementById('background'), splash = document.getElementById('splash'), data = localStorage.getItem('background-data'); var defaultData = { - image: screen.width > 1920 ? './assets/images/background-3840x2160.png' : './assets/images/background-1920x1080.png', + image: screen.width > 1920 ? './assets/images/background-3840x2160.jpg' : './assets/images/background-1920x1080.jpg', video: '', color: '#15002C', fontColor: '#FFFFFF', diff --git a/www/nodejs-project/lang/ar.json b/www/nodejs-project/lang/ar.json index d7355699..584e9518 100644 --- a/www/nodejs-project/lang/ar.json +++ b/www/nodejs-project/lang/ar.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "أعد تشغيل Megacubo بحيث يكون للتغييرات تأثير", "SHOW_FUN_LETTERS": "إظهار عناوين ممتعة في الفئة \"{0}\"", "SHOW_LOGOS": "عرض الشعارات", + "SHOW_POPULAR_SEARCHES": "عرض البحوث الشعبية في \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "إظهار الإصدارات الغير مدعومة", "SHUTDOWN": "إيقاف التشغيل", "SKIP": "تخطي", diff --git a/www/nodejs-project/lang/bn.json b/www/nodejs-project/lang/bn.json index 9861a3e2..06fd4dbf 100644 --- a/www/nodejs-project/lang/bn.json +++ b/www/nodejs-project/lang/bn.json @@ -488,6 +488,7 @@ "SHOULD_RESTART": "মেগাকুবো পুনরায় চালু করুন যাতে পরিবর্তনের প্রভাব থাকে", "SHOW_FUN_LETTERS": "\"{0}\" বিভাগে মজাদার শিরোনামগুলি দেখান", "SHOW_LOGOS": "লগ", + "SHOW_POPULAR_SEARCHES": "\"{0}\" এ জনপ্রিয় গবেষণা দেখান", "SHOW_UNSUPPORTED_VERSIONS": "নিরবচ্ছিন্ন সংস্করণগুলি দেখান", "SHUTDOWN": "সুইচ বন্ধ", "SIMILARARTIST": "অনুরূপ শিল্পী", diff --git a/www/nodejs-project/lang/de.json b/www/nodejs-project/lang/de.json index 5885c9dc..5619d4e8 100644 --- a/www/nodejs-project/lang/de.json +++ b/www/nodejs-project/lang/de.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Starten Sie Megacubo neu, damit die Änderungen wirksam werden", "SHOW_FUN_LETTERS": "Zeigen Sie lustige Titel in der Kategorie \"{0}\"", "SHOW_LOGOS": "Logos anzeigen.", + "SHOW_POPULAR_SEARCHES": "Zeigen Sie beliebte Forschung in \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Zeigen Sie nicht unterstützte Versionen", "SHUTDOWN": "Stilllegen", "SKIP": "Überspringen", diff --git a/www/nodejs-project/lang/el.json b/www/nodejs-project/lang/el.json index 84a4e87c..8cc87d15 100644 --- a/www/nodejs-project/lang/el.json +++ b/www/nodejs-project/lang/el.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Επανεκκινήστε το megacubo για τις αλλαγές που πρέπει να τεθούν σε ισχύ", "SHOW_FUN_LETTERS": "Εμφάνιση τίτλων διασκέδασης στην κατηγορία \"{0}\"", "SHOW_LOGOS": "Εμφάνιση λογότυπων", + "SHOW_POPULAR_SEARCHES": "Εμφάνιση δημοφιλούς έρευνας στο \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Εμφάνιση μη υποστηριζόμενων εκδόσεων", "SHUTDOWN": "ΤΕΡΜΑΤΙΣΜΟΣ ΛΕΙΤΟΥΡΓΙΑΣ", "SKIP": "Παραλείπω", diff --git a/www/nodejs-project/lang/en.json b/www/nodejs-project/lang/en.json index ef69291b..5ef44871 100644 --- a/www/nodejs-project/lang/en.json +++ b/www/nodejs-project/lang/en.json @@ -311,7 +311,7 @@ "PARENTAL_CONTROL": "Parental control", "PASSWORD": "Password", "PASSWORD_NOT_MATCH": "Password does not match", - "PASTE_SERVER_ADDRESS": "Glue below your server address below", + "PASTE_SERVER_ADDRESS": "Paste below your server address below", "PAUSE": "Pause", "PAUSED": "Paused", "PERFORMANCE_MODE": "Performance mode", @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Restart Megacubo for the changes to take effect", "SHOW_FUN_LETTERS": "Show fun titles in category \"{0}\"", "SHOW_LOGOS": "Show logos", + "SHOW_POPULAR_SEARCHES": "Show popular searches in \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Show unsupported versions", "SHUTDOWN": "Shutdown", "SKIP": "Skip", diff --git a/www/nodejs-project/lang/es.json b/www/nodejs-project/lang/es.json index 9a6ba475..eefd6f26 100644 --- a/www/nodejs-project/lang/es.json +++ b/www/nodejs-project/lang/es.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Reinicie la aplicación para que los cambios surtan efecto", "SHOW_FUN_LETTERS": "Mostrar títulos divertidos en la categoría \"{0}\"", "SHOW_LOGOS": "Mostrar logos", + "SHOW_POPULAR_SEARCHES": "Muestre buscas populares en \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Mostrar versiones no compatibles", "SHUTDOWN": "Shutdown", "SKIP": "Saltar", diff --git a/www/nodejs-project/lang/fr.json b/www/nodejs-project/lang/fr.json index 39365231..8035fab6 100644 --- a/www/nodejs-project/lang/fr.json +++ b/www/nodejs-project/lang/fr.json @@ -311,7 +311,7 @@ "PARENTAL_CONTROL": "Contrôle parental", "PASSWORD": "Mot de passe", "PASSWORD_NOT_MATCH": "Le mot de passe ne correspond pas", - "PASTE_SERVER_ADDRESS": "Glue en dessous de l'adresse de votre serveur ci-dessous", + "PASTE_SERVER_ADDRESS": "Paste en dessous de l'adresse de votre serveur ci-dessous", "PAUSE": "Pause", "PAUSED": "S'arrêta", "PERFORMANCE_MODE": "Mode Performance", @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Redémarrez Megacubo pour que les changements prennent effet", "SHOW_FUN_LETTERS": "Afficher les titres amusants dans la catégorie \"{0}\"", "SHOW_LOGOS": "Montrer des logos", + "SHOW_POPULAR_SEARCHES": "Montrez des recherches populaires dans \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Afficher les versions non soutenues", "SHUTDOWN": "Fermer", "SKIP": "Sauter", diff --git a/www/nodejs-project/lang/hi.json b/www/nodejs-project/lang/hi.json index 10048915..3732cdf5 100644 --- a/www/nodejs-project/lang/hi.json +++ b/www/nodejs-project/lang/hi.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "प्रभावी होने के लिए परिवर्तनों के लिए मेगाकाबो को पुनरारंभ करें", "SHOW_FUN_LETTERS": "श्रेणी में मजेदार शीर्षक दिखाएं \"{0}\"", "SHOW_LOGOS": "लोगो दिखाएं", + "SHOW_POPULAR_SEARCHES": "\"{0}\" में लोकप्रिय शोध दिखाएं", "SHOW_UNSUPPORTED_VERSIONS": "असमर्थित संस्करण दिखाएं", "SHUTDOWN": "बंद करना", "SKIP": "छोडना", diff --git a/www/nodejs-project/lang/id.json b/www/nodejs-project/lang/id.json index daa14255..07e6d199 100644 --- a/www/nodejs-project/lang/id.json +++ b/www/nodejs-project/lang/id.json @@ -488,6 +488,7 @@ "SHOULD_RESTART": "Restart megacubo sehingga perubahan memiliki efek", "SHOW_FUN_LETTERS": "Tampilkan judul yang menyenangkan di kategori \"{0}\"", "SHOW_LOGOS": "Catatan", + "SHOW_POPULAR_SEARCHES": "Tunjukkan penelitian populer di \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Tunjukkan versi yang tidak tertekan", "SHUTDOWN": "Mematikan", "SIMILARARTIST": "Artis serupa", diff --git a/www/nodejs-project/lang/it.json b/www/nodejs-project/lang/it.json index 721adb1e..9d84d5de 100644 --- a/www/nodejs-project/lang/it.json +++ b/www/nodejs-project/lang/it.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Riavviare l'applicazione per rendere effettive le modifiche", "SHOW_FUN_LETTERS": "Mostra titoli divertenti nella categoria \"{0}\"", "SHOW_LOGOS": "Mostra loghi", + "SHOW_POPULAR_SEARCHES": "Mostra una ricerca popolare in \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Mostra versioni non supportate", "SHUTDOWN": "Spegnere", "SKIP": "Saltare", diff --git a/www/nodejs-project/lang/ja.json b/www/nodejs-project/lang/ja.json index 9f40ebfb..b9198859 100644 --- a/www/nodejs-project/lang/ja.json +++ b/www/nodejs-project/lang/ja.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "変更が有効になるためにMegaCuboを再起動します", "SHOW_FUN_LETTERS": "カテゴリ「{0}」で楽しいタイトルを表示する", "SHOW_LOGOS": "ロゴを表示します", + "SHOW_POPULAR_SEARCHES": "「{0}」で人気のある研究を見せる", "SHOW_UNSUPPORTED_VERSIONS": "サポートされていないバージョンを表示します", "SHUTDOWN": "シャットダウン", "SKIP": "スキップ", diff --git a/www/nodejs-project/lang/pa.json b/www/nodejs-project/lang/pa.json index 90a4e19e..009a4acd 100644 --- a/www/nodejs-project/lang/pa.json +++ b/www/nodejs-project/lang/pa.json @@ -488,6 +488,7 @@ "SHOULD_RESTART": "ਮੈਗਾੱਕੋ ਨੂੰ ਮੁੜ ਚਾਲੂ ਕਰੋ ਤਾਂ ਜੋ ਤਬਦੀਲੀਆਂ ਦਾ ਪ੍ਰਭਾਵ ਹੋਵੇ", "SHOW_FUN_LETTERS": "ਸ਼੍ਰੇਣੀ ਵਿੱਚ ਮਜ਼ਾਕ ਦੇ ਸਿਰਲੇਖ ਦਿਖਾਓ", "SHOW_LOGOS": "ਲਾਗ", + "SHOW_POPULAR_SEARCHES": "\"{0}\" ਵਿੱਚ ਪ੍ਰਸਿੱਧ ਖੋਜ ਵੇਖੋ", "SHOW_UNSUPPORTED_VERSIONS": "ਅਣਚਾਹੇ ਸੰਸਕਰਣ ਦਿਖਾਓ", "SHUTDOWN": "ਬੰਦ ਕਰਨ ਲਈ", "SIMILARARTIST": "ਸਮਾਨ ਕਲਾਕਾਰ", diff --git a/www/nodejs-project/lang/pl.json b/www/nodejs-project/lang/pl.json index 9720052c..1fe86c5a 100644 --- a/www/nodejs-project/lang/pl.json +++ b/www/nodejs-project/lang/pl.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Uruchom ponownie Megacubo, aby wprowadzić efekt zmian", "SHOW_FUN_LETTERS": "Pokaż zabawne tytuły w kategorii „{0}”", "SHOW_LOGOS": "Pokaż logo.", + "SHOW_POPULAR_SEARCHES": "Pokaż popularne badania w „{0}”", "SHOW_UNSUPPORTED_VERSIONS": "Pokaż nieobsługiwane wersje", "SHUTDOWN": "Zamknąć", "SKIP": "Pomijać", diff --git a/www/nodejs-project/lang/pt.json b/www/nodejs-project/lang/pt.json index 17f270c1..8bd0a9a1 100644 --- a/www/nodejs-project/lang/pt.json +++ b/www/nodejs-project/lang/pt.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Reinicie o Megacubo para que as alterações tenham efeito", "SHOW_FUN_LETTERS": "Mostre títulos divertidos na categoria \"{0}\"", "SHOW_LOGOS": "Mostrar logos", + "SHOW_POPULAR_SEARCHES": "Mostrar pesquisas populares em \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Mostre versões não suportadas", "SHUTDOWN": "Desligar", "SKIP": "Pular", diff --git a/www/nodejs-project/lang/ru.json b/www/nodejs-project/lang/ru.json index fa059c2e..1429e62f 100644 --- a/www/nodejs-project/lang/ru.json +++ b/www/nodejs-project/lang/ru.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Перезапустите Megacubo для изменения вступления в силу", "SHOW_FUN_LETTERS": "Показать забавные названия в категории \"{0}\"", "SHOW_LOGOS": "Показать логотипы", + "SHOW_POPULAR_SEARCHES": "Показать популярное исследование в \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Показать неподдерживаемые версии", "SHUTDOWN": "Неисправность", "SKIP": "Пропускать", diff --git a/www/nodejs-project/lang/sq.json b/www/nodejs-project/lang/sq.json index ebbaa5c2..ed51f9de 100644 --- a/www/nodejs-project/lang/sq.json +++ b/www/nodejs-project/lang/sq.json @@ -414,6 +414,7 @@ "SHOULD_RESTART": "Restart Megacubo për ndryshimet që do të hyjnë në fuqi", "SHOW_FUN_LETTERS": "Trego tituj argëtues në kategorinë \"{0}\"", "SHOW_LOGOS": "Trego logot", + "SHOW_POPULAR_SEARCHES": "Tregoni hulumtime popullore në \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Tregoni versione të pambështetura", "SHUTDOWN": "Fike", "SKIP": "Kaloj", diff --git a/www/nodejs-project/lang/sw.json b/www/nodejs-project/lang/sw.json index 928f3c12..ebe28e65 100644 --- a/www/nodejs-project/lang/sw.json +++ b/www/nodejs-project/lang/sw.json @@ -488,6 +488,7 @@ "SHOULD_RESTART": "Anzisha tena megacubo ili mabadiliko yawe na athari", "SHOW_FUN_LETTERS": "Onyesha majina ya kufurahisha katika kitengo cha \"{0}\"", "SHOW_LOGOS": "Logi", + "SHOW_POPULAR_SEARCHES": "Onyesha utafiti maarufu katika \"{0}\"", "SHOW_UNSUPPORTED_VERSIONS": "Onyesha matoleo yasiyopinduliwa", "SHUTDOWN": "Kuzima", "SIMILARARTIST": "Msanii kama huyo", diff --git a/www/nodejs-project/lang/te.json b/www/nodejs-project/lang/te.json index 82a8ff62..9fac5f34 100644 --- a/www/nodejs-project/lang/te.json +++ b/www/nodejs-project/lang/te.json @@ -488,6 +488,7 @@ "SHOULD_RESTART": "మెగాకుబోను పున art ప్రారంభించండి, తద్వారా మార్పులు ప్రభావం చూపుతాయి", "SHOW_FUN_LETTERS": "\"{0}\" వర్గంలో సరదా శీర్షికలను చూపించు", "SHOW_LOGOS": "లాగ్", + "SHOW_POPULAR_SEARCHES": "\"{0}\" లో జనాదరణ పొందిన పరిశోధనలను చూపించు", "SHOW_UNSUPPORTED_VERSIONS": "రోడ్ డ్రెడ్ చేయని సంస్కరణలను చూపించు", "SHUTDOWN": "స్విచ్ ఆఫ్", "SIMILARARTIST": "ఇలాంటి కళాకారుడు", diff --git a/www/nodejs-project/modules/bookmarks/bookmarks.js b/www/nodejs-project/modules/bookmarks/bookmarks.js index 1d7f37a1..3ec14638 100644 --- a/www/nodejs-project/modules/bookmarks/bookmarks.js +++ b/www/nodejs-project/modules/bookmarks/bookmarks.js @@ -38,9 +38,11 @@ class Bookmarks extends EntriesGroup { hook(entries, path){ if(!path) { const bmEntry = {name: global.lang.BOOKMARKS, fa: 'fas fa-star', type: 'group', renderer: this.entries.bind(this)} + if(this.data.length) bmEntry.details = this.data.map(e => e.name).unique().slice(0, 3).join(', ') +'...' global.options.insertEntry(bmEntry, entries, -3, global.lang.MY_LISTS, global.lang.CATEGORY_MOVIES_SERIES) + return entries } - let isBookmarkable = path.startsWith(global.lang.CATEGORY_MOVIES_SERIES) || path.startsWith(global.lang.LIVE +'/'+ global.lang.MORE) || path.startsWith(global.lang.BOOKMARKS) + let isBookmarkable = path.startsWith(global.lang.CATEGORY_MOVIES_SERIES) || path.startsWith(global.lang.SEARCH) || path.startsWith(global.lang.LIVE +'/'+ global.lang.MORE) || path.startsWith(global.lang.BOOKMARKS) if(!isBookmarkable && path.startsWith(global.lang.MY_LISTS) && !entries.some(this.groupFilter)){ isBookmarkable = true } diff --git a/www/nodejs-project/modules/channels/channels.js b/www/nodejs-project/modules/channels/channels.js index b66c5e84..22d6d529 100644 --- a/www/nodejs-project/modules/channels/channels.js +++ b/www/nodejs-project/modules/channels/channels.js @@ -1617,11 +1617,22 @@ class Channels extends ChannelsKids { name: global.lang.ONLY_KNOWN_CHANNELS_IN_X.format(global.lang.TRENDING), type: 'check', action: (e, checked) => { - global.config.set('only-known-channels-in-been-watched', checked) + global.config.set('only-known-channels-in-trending', checked) global.watching.update().catch(console.error) }, checked: () => { - return global.config.get('only-known-channels-in-been-watched') + return global.config.get('only-known-channels-in-trending') + } + }, + { + name: global.lang.SHOW_POPULAR_SEARCHES.format(global.lang.TRENDING), + type: 'check', + action: (e, checked) => { + global.config.set('popular-searches-in-trending', checked) + global.watching.update().catch(console.error) + }, + checked: () => { + return global.config.get('popular-searches-in-trending') } }, { diff --git a/www/nodejs-project/modules/config/defaults.js b/www/nodejs-project/modules/config/defaults.js index 6cf1ec9d..5fb9b9eb 100644 --- a/www/nodejs-project/modules/config/defaults.js +++ b/www/nodejs-project/modules/config/defaults.js @@ -70,7 +70,7 @@ module.exports = { 'live-stream-fmt': 'auto', 'locale': '', 'miniplayer-auto': true, - 'only-known-channels-in-been-watched': true, + 'only-known-channels-in-trending': true, 'osd-speak': false, 'parental-control': 'remove', 'parental-control-terms': '.', @@ -82,6 +82,7 @@ module.exports = { 'stretch-logos': false, 'search-missing-logos': true, 'show-logos': true, + 'popular-searches-in-trending': true, 'startup-window': '', 'status-flags-type': false, 'subtitles': true, diff --git a/www/nodejs-project/modules/countries/countries.json b/www/nodejs-project/modules/countries/countries.json index 789f120c..c4e25560 100644 --- a/www/nodejs-project/modules/countries/countries.json +++ b/www/nodejs-project/modules/countries/countries.json @@ -326,7 +326,7 @@ "fr": "Azerbaïdjan", "it": "Azerbaigian", "nl": "Azerbeidzjan", - "pt": "Azerbeijão", + "pt": "Azerbaijão", "lat": 40.5, "lng": 47.5, "tz": [ diff --git a/www/nodejs-project/modules/discovery/providers/public-lists.js b/www/nodejs-project/modules/discovery/providers/public-lists.js index d92ebdf1..7b73fd41 100644 --- a/www/nodejs-project/modules/discovery/providers/public-lists.js +++ b/www/nodejs-project/modules/discovery/providers/public-lists.js @@ -1,5 +1,86 @@ const Events = require('events') +const FreeTVMap = { + "al": ["playlist_albania.m3u8"], + "ad": ["playlist_andorra.m3u8"], + "ar": ["playlist_argentina.m3u8", "playlist_zz_news_ar.m3u8", "playlist_zz_documentaries_ar.m3u8"], + "au": ["playlist_australia.m3u8"], + "at": ["playlist_austria.m3u8"], + "az": ["playlist_azerbaijan.m3u8"], + "by": ["playlist_belarus.m3u8"], + "be": ["playlist_belgium.m3u8"], + "ba": ["playlist_bosnia_and_herzegovina.m3u8"], + "br": ["playlist_brazil.m3u8"], + "bg": ["playlist_bulgaria.m3u8"], + "ca": ["playlist_canada.m3u8"], + "td": ["playlist_chad.m3u8"], + "cl": ["playlist_chile.m3u8"], + "cn": ["playlist_china.m3u8"], + "cr": ["playlist_costa_rica.m3u8"], + "hr": ["playlist_croatia.m3u8"], + "cy": ["playlist_cyprus.m3u8"], + "cz": ["playlist_czech_republic.m3u8"], + "dk": ["playlist_denmark.m3u8"], + "do": ["playlist_dominican_republic.m3u8"], + "ee": ["playlist_estonia.m3u8"], + "fo": ["playlist_faroe_islands.m3u8"], + "fi": ["playlist_finland.m3u8"], + "fr": ["playlist_france.m3u8"], + "ge": ["playlist_georgia.m3u8"], + "de": ["playlist_germany.m3u8"], + "gr": ["playlist_greece.m3u8"], + "gl": ["playlist_greenland.m3u8"], + "hk": ["playlist_hong_kong.m3u8", "playlist_hongkong.m3u8"], + "hu": ["playlist_hungary.m3u8"], + "is": ["playlist_iceland.m3u8"], + "in": ["playlist_india.m3u8"], + "ir": ["playlist_iran.m3u8"], + "iq": ["playlist_iraq.m3u8"], + "ie": ["playlist_ireland.m3u8"], + "il": ["playlist_israel.m3u8"], + "it": ["playlist_italy.m3u8"], + "jp": ["playlist_japan.m3u8"], + "kr": ["playlist_korea.m3u8"], + "xk": ["playlist_kosovo.m3u8"], + "lv": ["playlist_latvia.m3u8"], + "lt": ["playlist_lithuania.m3u8"], + "lu": ["playlist_luxembourg.m3u8"], + "mo": ["playlist_macau.m3u8"], + "mt": ["playlist_malta.m3u8"], + "mx": ["playlist_mexico.m3u8"], + "md": ["playlist_moldova.m3u8"], + "mc": ["playlist_monaco.m3u8"], + "me": ["playlist_montenegro.m3u8"], + "nl": ["playlist_netherlands.m3u8"], + "kp": ["playlist_north_korea.m3u8"], + "mk": ["playlist_north_macedonia.m3u8"], + "no": ["playlist_norway.m3u8"], + "py": ["playlist_paraguay.m3u8"], + "pe": ["playlist_peru.m3u8"], + "pl": ["playlist_poland.m3u8"], + "pt": ["playlist_portugal.m3u8"], + "qa": ["playlist_qatar.m3u8"], + "ro": ["playlist_romania.m3u8"], + "ru": ["playlist_russia.m3u8"], + "sm": ["playlist_san_marino.m3u8"], + "sa": ["playlist_saudi_arabia.m3u8"], + "rs": ["playlist_serbia.m3u8"], + "sk": ["playlist_slovakia.m3u8"], + "si": ["playlist_slovenia.m3u8"], + "so": ["playlist_somalia.m3u8"], + "es": ["playlist_spain.m3u8", "playlist_spain_vod.m3u8", "playlist_zz_news_es.m3u8"], + "se": ["playlist_sweden.m3u8"], + "ch": ["playlist_switzerland.m3u8"], + "tw": ["playlist_taiwan.m3u8"], + "tt": ["playlist_trinidad.m3u8"], + "tr": ["playlist_turkey.m3u8"], + "gb": ["playlist_uk.m3u8"], + "ua": ["playlist_ukraine.m3u8"], + "ae": ["playlist_united_arab_emirates.m3u8"], + "us": ["playlist_usa.m3u8", "playlist_usa_vod.m3u8"], + "ve": ["playlist_venezuela.m3u8"] +} + class PublicLists extends Events { constructor(opts={}){ super() @@ -12,8 +93,17 @@ class PublicLists extends Events { } async load() { if (!Object.keys(this.data).length) { + Object.keys(FreeTVMap).forEach(code => { + if(!this.data[code]) this.data[code] = [] + this.data[code].push(...FreeTVMap[code].map(n => { + return 'https://github.com/Free-TV/IPTV/raw/master/playlists/'+ n + })) + }) await global.cloud.get('configure').then(c => { - this.data = c['legal-iptv'] || {} + Object.keys(c['legal-iptv']).forEach(code => { + if(!this.data[code]) this.data[code] = [] + this.data[code].push(c['legal-iptv'][code]) + }) }).catch(console.error) } this.isReady = true @@ -31,10 +121,10 @@ class PublicLists extends Events { async discovery(adder){ await this.ready() let locs = await global.lang.getActiveCountries(0).catch(console.error) - if(Array.isArray(locs) || !locs.length){ - locs.push = [global.lang.countryCode] + if(!Array.isArray(locs) || !locs.length){ + locs = [global.lang.countryCode] } - let lists = locs.map(code => this.data[code]).filter(c => c) + let lists = locs.map(code => this.data[code]).flat().filter(c => c) if(lists.length){ const maxLists = 48, factor = 0.9 // factor here adds some gravity to grant higher priority to community lists instead if(lists.length > maxLists){ @@ -58,14 +148,20 @@ class PublicLists extends Events { name: this.countries.getCountryName(countryCode, global.lang.locale), type: 'group', url: this.data[countryCode], - renderer: async data => { + renderer: async () => { let err global.lists.manager.openingList = true - let ret = await global.lists.manager.directListRenderer(data, {fetch: true}).catch(e => err = e) + let ret = [] + for(const url of this.data[countryCode]) { + let es = await global.lists.manager.directListRenderer({url}, {fetch: true}).catch(e => err = e) + if(Array.isArray(es)) { + ret.push(...es.filter(e => e.name != global.lang.EMPTY)) + } + } global.lists.manager.openingList = false global.osd.hide('list-open') if(err) throw err - return ret + return global.lists.sort(ret) } } }) diff --git a/www/nodejs-project/modules/explorer/client.js b/www/nodejs-project/modules/explorer/client.js index 2d0b56fe..5252995e 100644 --- a/www/nodejs-project/modules/explorer/client.js +++ b/www/nodejs-project/modules/explorer/client.js @@ -557,8 +557,8 @@ class ExplorerPointer extends ExplorerSelectionMemory { if(this.debug) { console.log('pointer selectedIndex =', a.tabIndex, a) } - //console.log('AVOID SCROLL', avoidScroll, a.offsetTop, this._scrollContainer.scrollTop, this._scrollContainer.offsetHeight, traceback()) if(avoidScroll && (a.offsetTop < this._scrollContainer.scrollTop || a.offsetTop >= (this._scrollContainer.scrollTop + this._scrollContainer.offsetHeight - 4))){ + console.log('AVOID SCROLL IGNORED', a.offsetTop, [this._scrollContainer.scrollTop, this._scrollContainer.offsetHeight], traceback()) avoidScroll = false } if(!avoidScroll) { @@ -2058,10 +2058,11 @@ class Explorer extends ExplorerLoading { if(this.ranging){ const changed = [], shouldUpdateRange = config['show-logos'] && this.currentEntries.length > (this.viewSizeX * this.viewSizeY) if(shouldUpdateRange){ - let rgx = new RegExp(' { if(!elements[e.tabindex]) return @@ -2089,6 +2090,7 @@ class Explorer extends ExplorerLoading { changed.push(n) } }) + this._scrollContainer.scrollTop = currentScrolltop // scroll was somehow being changed from function start to this point this.app.emit('explorer-update-range', this.range, this.path) if(changed.length){ if(this.debug){ diff --git a/www/nodejs-project/modules/lists/common.js b/www/nodejs-project/modules/lists/common.js index 07ba9e3e..738239b1 100644 --- a/www/nodejs-project/modules/lists/common.js +++ b/www/nodejs-project/modules/lists/common.js @@ -37,7 +37,7 @@ class Fetcher extends Events { this.list.skipValidating = true this.list.start().then(resolve).catch(err => { this.error = err - this.master.loader.addListNow(this.url, this.atts.progress).then(() => { + this.master.loader.addListNow(this.url, this.atts).then(() => { this.list.start().then(resolve).catch(err => { this.error += ' '+ err this.list.destroy() diff --git a/www/nodejs-project/modules/lists/index.js b/www/nodejs-project/modules/lists/index.js index d10d8e32..98032b25 100644 --- a/www/nodejs-project/modules/lists/index.js +++ b/www/nodejs-project/modules/lists/index.js @@ -24,7 +24,7 @@ class Index extends Common { if(!terms.length){ return resolve({}) } - terms.forEach(t => { + terms.forEach(t => { ret[t.name] = Array.isArray(t.terms) ? t.terms : this.terms(t.terms) results[t.name] = false }) @@ -254,9 +254,14 @@ class Index extends Common { } let results = [] ks.forEach(listUrl => { - let ls = smap[listUrl]['n'] - if(opts.group){ - ls.push(...smap[listUrl]['g']) + let ls + if(opts.groupsOnly) { + ls = smap[listUrl]['g'] + } else { + ls = smap[listUrl]['n'] + if(opts.group){ + ls.push(...smap[listUrl]['g']) + } } smap[listUrl] = ls }) diff --git a/www/nodejs-project/modules/lists/loader.js b/www/nodejs-project/modules/lists/loader.js index ef73092e..0b8afe90 100644 --- a/www/nodejs-project/modules/lists/loader.js +++ b/www/nodejs-project/modules/lists/loader.js @@ -210,16 +210,20 @@ class ListsLoader extends Events { } urls.filter(u => this.pings[u] == 0).forEach(u => delete this.pings[u]) } - async addListNow(url, progress) { // reserved for manual list adding + async addListNow(url, atts={}) { // reserved for manual list adding const uid = parseInt(Math.random() * 1000000) const progressListener = p => { - if(p.progressId == uid) progress(p.progress) - } + if(p.progressId == uid) atts.progress(p.progress) + } await global.Download.waitNetworkConnection() await this.prepareUpdater() - progress && this.updater.on('progress', progressListener) - await this.updater.update(url, {uid}).catch(console.error) - progress && this.updater.removeListener('progress', progressListener) + atts.progress && this.updater.on('progress', progressListener) + console.error('addListNow '+ JSON.stringify(atts)) + await this.updater.update(url, { + uid, + timeout: atts.timeout + }).catch(console.error) + atts.progress && this.updater.removeListener('progress', progressListener) this.updater && this.updater.close && this.updater.close() this.master.addList(url, 1) } diff --git a/www/nodejs-project/modules/lists/manager.js b/www/nodejs-project/modules/lists/manager.js index e8791d55..ef1d61b3 100644 --- a/www/nodejs-project/modules/lists/manager.js +++ b/www/nodejs-project/modules/lists/manager.js @@ -469,7 +469,7 @@ class Manager extends ManagerEPG { progress: p => { global.osd.show(global.lang.RECEIVING_LIST +' '+ p +'%', 'fa-mega spin-x-alt', 'add-list-progress-'+ uid, 'persistent') }, - timeout: global.config.get('read-timeout') + timeout: Math.max(90, global.config.get('read-timeout')) // some servers take too long to respond with the list }, this.master) let err, entries = await fetch.getMap().catch(e => err = e) this.addingList = false diff --git a/www/nodejs-project/modules/lists/update-list-index.js b/www/nodejs-project/modules/lists/update-list-index.js index e81acc57..e198c09a 100644 --- a/www/nodejs-project/modules/lists/update-list-index.js +++ b/www/nodejs-project/modules/lists/update-list-index.js @@ -16,6 +16,7 @@ class UpdateListIndex extends ListIndexUtils { this.forceDownload = forceDownload === true this.uid = parseInt(Math.random() * 100000000000) this.tmpOutputFile = global.paths.temp +'/'+ this.uid +'.out.tmp' + this.timeout = global.config.get('read-timeout') this.linesMapPtr = 0 this.linesMap = [] this.debug = false @@ -79,7 +80,7 @@ class UpdateListIndex extends ListIndexUtils { path = 'http:' + path } if(path.match(new RegExp('^https?:'))){ - console.error('UpdateListIndex fetch '+ path) + console.error('UpdateListIndex fetch '+ path +' ('+ this.timeout +')') let resolved const opts = { debug: this.debug, @@ -90,7 +91,7 @@ class UpdateListIndex extends ListIndexUtils { headers: { 'accept-charset': 'utf-8, *;q=0.1' }, - timeout: global.config.get('read-timeout'), // some servers will take too long to send the initial response + timeout: this.timeout, // some servers will take too long to send the initial response downloadLimit: 200 * (1024 * 1024), // 200Mb encoding: 'utf8' } diff --git a/www/nodejs-project/modules/lists/updater-worker.js b/www/nodejs-project/modules/lists/updater-worker.js index 75f409eb..447bd571 100644 --- a/www/nodejs-project/modules/lists/updater-worker.js +++ b/www/nodejs-project/modules/lists/updater-worker.js @@ -56,6 +56,9 @@ class ListsUpdater extends Common { const key = global.LIST_DATA_KEY_MASK.format(url) const file = global.storage.resolve(key) const updater = new UpdateListIndex(url, url, file, this, Object.assign({}, updateMeta), params.force === true) + if(typeof(params.timeout) == 'number') { + updater.timeout = params.timeout + } updateMeta.updateAfter = now + 180 if(this.debug) { console.log('updater - should 2', url, should) diff --git a/www/nodejs-project/modules/options/options.js b/www/nodejs-project/modules/options/options.js index 2218c0c4..193b3ff5 100644 --- a/www/nodejs-project/modules/options/options.js +++ b/www/nodejs-project/modules/options/options.js @@ -1034,7 +1034,7 @@ class Options extends OptionsExportImport { fa: 'fas fa-plug', type: 'slider', mask: 'time', - range: {start: 3, end: 30}, + range: {start: 3, end: 60}, action: (data, value) => { global.config.set('connect-timeout-secs', value) }, diff --git a/www/nodejs-project/modules/search/search.js b/www/nodejs-project/modules/search/search.js index b3a93887..3666ceda 100644 --- a/www/nodejs-project/modules/search/search.js +++ b/www/nodejs-project/modules/search/search.js @@ -166,28 +166,34 @@ class Search extends Events { } return es } - async results(terms){ - let u = global.ucWords(terms) - this.currentSearch = { - name: u, - url: global.mega.build(u, {terms, mediaType: this.searchMediaType}) - } - console.log('will search', terms, { - partial: this.searchInaccurate, - type: this.searchMediaType, - typeStrict: this.searchStrict, - group: this.searchMediaType != 'live' + async searchGroups(terms) { + const map = {}, entries = [] + const es = await this.search(terms, {groupsOnly: true}) + es.forEach(e => { + if(typeof(map[e.source]) == 'undefined') map[e.source] = {} + if(typeof(map[e.source][e.groupName]) == 'undefined') map[e.source][e.groupName] = {} }) + Object.keys(map).forEach(url => { + Object.keys(map[url]).forEach(name => { + entries.push({name, type: 'group', renderer: () => global.lists.group({group: name, url})}) + }) + }) + return global.lists.sort(entries) + } + async search(terms, atts={}) { const policy = global.config.get('parental-control') const parentalControlActive = ['remove', 'block'].includes(policy) - const isAdultQueryBlocked = policy == 'remove' && !global.lists.parentalControl.allow(u) - let es = await global.lists.search(terms, { + const isAdultQueryBlocked = policy == 'remove' && !global.lists.parentalControl.allow(terms) + const opts = { partial: this.searchInaccurate, type: this.searchMediaType, typeStrict: this.searchStrict, group: this.searchMediaType != 'live', parentalControl: policy == 'remove' ? false : undefined // allow us to count blocked results - }) + } + Object.assign(opts, atts) + console.log('will search', terms, opts) + let es = await global.lists.search(terms, opts) es = (es.results && es.results.length) ? es.results : ((es.maybe && es.maybe.length) ? es.maybe : []) console.log('has searched', terms, es.length, parentalControlActive, isAdultQueryBlocked) if(isAdultQueryBlocked) { @@ -216,6 +222,15 @@ class Search extends Events { es = global.lists.parentalControl.filter(es) } } + return es + } + async results(terms){ + let u = global.ucWords(terms) + this.currentSearch = { + name: u, + url: global.mega.build(u, {terms, mediaType: this.searchMediaType}) + } + const es = await this.search(terms) global.ui.emit('current-search', terms, this.searchMediaType) if(!global.lists.loaded(true)) { es.unshift(global.lists.manager.noListsEntry()) @@ -313,14 +328,15 @@ class Search extends Events { } let es = await global.channels.search(terms, this.searchInaccurate) es = es.map(e => global.channels.toMetaEntry(e)) + const gs = await this.searchGroups(terms) + es.push(...gs.map(e => e)) let minResultsWanted = (global.config.get('view-size-x') * global.config.get('view-size-y')) - 3 if(global.config.get('search-youtube') && es.length < minResultsWanted){ let ys = await this.ytLiveResults(terms).catch(console.error) if(Array.isArray(ys)) { es.push(...ys.slice(0, minResultsWanted - es.length)) } - } - es = global.lists.sort(es) + } if(!global.lists.loaded(true)) { es.unshift(global.lists.manager.noListsEntry()) } diff --git a/www/nodejs-project/modules/watching/watching.js b/www/nodejs-project/modules/watching/watching.js index c01d86ab..8c44fc53 100644 --- a/www/nodejs-project/modules/watching/watching.js +++ b/www/nodejs-project/modules/watching/watching.js @@ -8,7 +8,7 @@ class Watching extends EntriesGroup { this.currentRawEntries = null this.updateIntervalSecs = global.cloud.expires['watching-country'] || 300 global.config.on('change', (keys, data) => { - if (keys.includes('only-known-channels-in-been-watched') || keys.includes('parental-control') || keys.includes('parental-control-terms')) { + if (keys.includes('only-known-channels-in-trending') || keys.includes('popular-searches-in-trending') || keys.includes('parental-control') || keys.includes('parental-control-terms')) { this.update().catch(console.error) } }) @@ -186,13 +186,24 @@ class Watching extends EntriesGroup { }) data = global.lists.parentalControl.filter(data) this.currentRawEntries = data.slice(0) - const adultContentOnly = global.config.get('parental-control') == 'only', onlyKnownChannels = !adultContentOnly && global.config.get('only-known-channels-in-been-watched') - let groups = {}, gcount = {}, gentries = [] - let sentries = await global.search.searchSuggestionEntries() - let gsearches = [], searchTerms = sentries.map(s => s.search_term).filter(s => s.length >= 3).filter(s => !global.channels.isChannel(s)).filter(s => global.lists.parentalControl.allow(s)).map(s => global.lists.terms(s)) + let searchTerms = [], groups = {}, gcount = {}, gsearches = [], gentries = [] + const adultContentOnly = global.config.get('parental-control') == 'only' + const onlyKnownChannels = !adultContentOnly && global.config.get('only-known-channels-in-trending') + const popularSearches = global.config.get('popular-searches-in-trending') + if(popularSearches) { + const sdata = {}, sentries = await global.search.searchSuggestionEntries() + sentries.map(s => s.search_term).filter(s => s.length >= 3).filter(s => !global.channels.isChannel(s)).filter(s => global.lists.parentalControl.allow(s)).forEach(name => { + sdata[name] = {name, terms: global.lists.terms(name)} + }) + const filtered = await global.lists.has(Object.values(sdata)) + Object.keys(filtered).forEach(name => { + if(!filtered[name]) return + searchTerms.push(sdata[name].terms) + }) + } data.forEach((entry, i) => { let ch = global.channels.isChannel(entry.terms.name) - if (!ch) { + if (popularSearches && !ch) { searchTerms.some(terms => { if (global.lists.match(terms, entry.terms.name)) { const name = terms.join(' ') diff --git a/www/nodejs-project/package.json b/www/nodejs-project/package.json index b6c8386f..ea59ded4 100644 --- a/www/nodejs-project/package.json +++ b/www/nodejs-project/package.json @@ -59,7 +59,7 @@ "url": "https://megacubo.tv" }, "icon": "./default_icon.png", - "version": "17.4.3", + "version": "17.4.4", "theme": { "fullScreen": true },