// ==UserScript== // @name Skrypt umożliwiający pobieranie materiałów ze znanych serwisów VOD. // @version 7.2.4 // @description Skrypt służący do pobierania materiałów ze znanych serwisów VOD. // Działa poprawnie tylko z rozszerzeniem Tampermonkey. // Cześć kodu pochodzi z: // miniskrypt.blogspot.com, // miniskrypt.hubaiitv.pl // @author Przmus, zacny // @namespace http://www.ipla.tv/ // @source https://github.com/zacny/voddownloader // @include /^https://(vod|cyfrowa)\.tvp\.pl/video/.*$/ // @include /^https?://.*\.tvp.(pl|info)/sess/TVPlayer2/embed.*$/ // @include /^https?://((?!wiadomosci).)*\.tvp\.pl/\d{6,}/.*$/ // @include https://www.tvpparlament.pl/sess/* // @include https://www.ipla.tv/* // @include https://player.pl/* // @include https://*.cda.pl/* // @include https://vod.pl/* // @include https://redir.atmcdn.pl/* // @include https://*.redcdn.pl/file/o2/redefine/partner/* // @include https://partner.ipla.tv/embed/* // @include https://wideo.wp.pl/* // @include https://ninateka.pl/* // @include https://www.arte.tv/*/videos/* // @include https://pulsembed.eu/* // @include https://tv-trwam.pl/local-vods/* // @exclude http://www.tvp.pl/sess/* // @exclude /^https?://(bialystok|gorzow|krakow|olsztyn|rzeszow|wroclaw|bydgoszcz|katowice|lublin|opole|szczecin|gdansk|kielce|lodz|poznan|warszawa)\.tvp.\pl/.*$/ // @exclude /^https?://.*\.vod\.tvp\.pl/\d{6,}/.*$/ // @exclude https://www.cda.pl/iframe/* // @grant GM_getResourceText // @grant GM_xmlhttpRequest // @grant GM_download // @grant GM_setClipboard // @grant GM_info // @connect tvp.pl // @connect getmedia.redefine.pl // @connect distro.redefine.pl // @connect player-api.dreamlab.pl // @connect api.arte.tv // @connect b2c.redefine.pl // @connect player.pl // @connect api-trwam.app.insysgo.pl // @run-at document-end // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/platform/1.3.5/platform.min.js // @require https://gitcdn.xyz/cdn/zacny/voddownloader/4b17a120f521eaddf476d6e8fe3be152d506f244/lib/js/mdb-with-waves-patch.js // @require https://gitcdn.xyz/cdn/kapetan/jquery-observe/ca67b735bb3ae8d678d1843384ebbe7c02466c61/jquery-observe.js // @resource buttons_css https://raw.githubusercontent.com/zacny/voddownloader/master/lib/css/voddownloader-buttons.css // @resource content_css https://raw.githubusercontent.com/zacny/voddownloader/master/lib/css/voddownloader-content.css // @downloadURL https://update.greasyfork.icu/scripts/6049/Skrypt%20umo%C5%BCliwiaj%C4%85cy%20pobieranie%20materia%C5%82%C3%B3w%20ze%20znanych%20serwis%C3%B3w%20VOD.user.js // @updateURL https://update.greasyfork.icu/scripts/6049/Skrypt%20umo%C5%BCliwiaj%C4%85cy%20pobieranie%20materia%C5%82%C3%B3w%20ze%20znanych%20serwis%C3%B3w%20VOD.meta.js // ==/UserScript== (function vodDownloader($, platform, Waves) { 'use strict'; var Exception = (function(error, templateParams) { this.error = error; this.templateParams = Array.isArray(templateParams) ? templateParams : [templateParams]; }); var Tool = (function(Tool) { Tool.deleteParametersFromUrl = function(url){ return decodeURIComponent(url.replace(/\?.*/,'')); }; Tool.getUrlParameter = function(paramName, url){ var results = new RegExp('[\?&]' + paramName + '=([^&#]*)').exec(url); if (results==null) { return null; } return decodeURIComponent(results[1]) || 0; }; Tool.formatConsoleMessage = function(message, params){ console.log.apply(this, $.merge([message], params)); }; var removeNotAllowedFileNameChars = function(input){ var regexp = new RegExp('[\/:*?"<>|]+', 'g'); return input.replace(regexp, '').replace(/\s+/g, ' '); }; Tool.downloadFile = function(fileUrl, title){ var extension = Tool.deleteParametersFromUrl(fileUrl.split('.').pop()); var movieTitle = (title !== undefined && title !== '' ) ? title : 'nieznany'; var name = removeNotAllowedFileNameChars(movieTitle) + '.' + extension; GM_download(fileUrl, name); }; Tool.template = function(templates, ...keys){ return (function(...values) { var dict = values[values.length - 1] || {}; var result = [templates[0]]; keys.forEach(function(key, i) { var value = Number.isInteger(key) ? values[key] : dict[key]; result.push(value, templates[i + 1]); }); return result.join(''); }); }; Tool.getRealUrl = function(){ var topUrl = window.sessionStorage.getItem(config.storage.topWindowLocation); return topUrl !== null ? topUrl : window.location.href; }; Tool.isTopWindow = function(){ return window.top === window.self; }; Tool.pad = function(number, characters){ return(1e15+number+"").slice(-characters) }; Tool.mapDescription = function(data){ var defaults = $.extend({}, config.description.defaults); var sourceDescriptions = config.description.sources[data.source] || {}; var descriptionVariant = sourceDescriptions[data.key] || {}; return $.extend(true, defaults, data, descriptionVariant); }; return Tool; }(Tool || {})); const config = { attempts: 10, attemptTimeout: 1500, storage: { doNotWarn: 'voddownloader.doNotwarnIfIncorrectPluginSettingsDetected', topWindowLocation: 'voddownloader.topWindowLocation' }, urlParamPattern: '#', urlParamDefaultKey: 'videoId', urlPartPattern: '~', include: { fontawesome: { id: 'fontawesome', css: 'https://use.fontawesome.com/releases/v5.8.2/css/all.css' }, bootstrap: { id: 'bootstrap', css: 'https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css' }, mdb: { id: 'mdb', css: 'https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.8.2/css/mdb.min.css', } }, error: { id: { caption: 'Nie udało się odnaleźć idetyfikatora.', template: Tool.template`Algorytm rozpoznawania identyfikatora wideo na stronie: ${0} \ zakończył się niepowodzeniem. Może to oznaczać błąd skryptu lub zmiany w portalu.`, }, tvnId: { caption: 'Nie udało się odnaleźć idetyfikatora.', template: Tool.template`Algorytm rozpoznawania identyfikatora wideo na stronie: ${0} \ zakończył się niepowodzeniem.\nJeżeli jest to główna strona programu oznacza to, \ że nie udało się odnaleźć identyfikatora ostatniego odcinka. Wejdź na stronę odcinka \ i spróbuj ponownie.\nMoże to również oznaczać błąd skryptu lub zmiany w portalu.`, }, call: { caption: 'Błąd pobierania informacji o materiale.', template: Tool.template`Wystąpił błąd w wykonaniu skryptu w kroku: ${0} na stronie: ${1} \ Zgłoś problem autorom skryptu.`, }, noSource: { caption: 'Nie udało się odnaleźć metadanych tego materiału.', template: Tool.template`Materiał ze strony ${0} nie posiada zdefiniowanych metadanych potrzebnych do \ działania skryptu lub są one nieprawidłowe.\n Może to oznaczać, że nie jest to materiał publicznie dostępny, nie posiada zdefiniowanych źródeł lub nie \ mogą one zostać wyświetlone w przeglądarce bez dodatkowego oprogramowania albo jest to materiał \ umieszczony w płatnej strefie.`, type: 'info' }, timeout: { caption: 'Zbyt długi czas odpowiedzi.', template: Tool.template`Dla kroku: ${0} na stronie "${1}" nie dotarły \ informacje zwrotne.\nPrzypuszczalnie jest to problem sieciowy. Spróbuj ponownie za jakiś czas.` }, noParent: { caption: 'Brak zakładki ze stroną główną.', template: Tool.template`Została zamknięta zakładka ze stroną na której został uruchomiony skrypt. \ Ta zakładka nie może przez to działać poprawnie. Otwórz ponownie stronę główną: \n ${0} \n by przywrócić prawidłowe funkcjonowanie skryptu.` } }, description: { defaults: { index: 99, language: 'polski', audio: 'MPEG AAC' }, sources: { IPLA: { '1080p': {video: 'H264 MPEG-4 AVC, 4011 kb/s, 1920x1080, 25fps, 16:9', index: 1}, '720p': {video: 'H264 MPEG-4 AVC, 1672 kb/s, 1280x720, 25fps, 16:9', index: 2}, '576p': {video: 'H264 MPEG-4 AVC, 1175 kb/s, 1024x576, 25fps, 16:9', index: 3}, '384p': {video: 'H264 MPEG-4 AVC, 256 kb/s, 484x272, 25fps, 16:9', index: 4} }, WP: { HQ: {video: 'H264 MPEG-4 AVC, 1804 kb/s, 1280x720, 24fps, 16:9', index: 1}, LQ: {video: 'H264 MPEG-4 AVC, 616 kb/s, 640x360, 24fps, 16:9', index: 2} }, TVN: { 'HD': {video: 'H264 MPEG-4 AVC, 2776 kb/s, 1280x720, 25fps, 16:9', index: 1}, 'Bardzo wysoka': {video: 'H264 MPEG-4 AVC, 1786 kb/s, 1280x720, 25fps, 16:9', index: 2}, 'Wysoka': {video: 'H264 MPEG-4 AVC, 1191 kb/s, 720x576, 25fps, 5:4', index: 3}, 'Standard': {video: 'H264 MPEG-4 AVC, 794 kb/s, 720x576, 25fps, 5:4', index: 4}, 'Średnia': {video: 'H264 MPEG-4 AVC, 596 kb/s, 640x480, 25fps, 4:3', index: 5}, 'Niska': {video: 'H264 MPEG-4 AVC, 417 kb/s, 512x384, 25fps, 4:3', index: 6}, 'Bardzo niska': {video: 'H264 MPEG-4 AVC, 238 kb/s, 320x240, 25fps, 4:3', index: 7} }, VOD: { '1080':{video: 'H264 MPEG-4 AVC, 1920x1080, 25fps, 16:9', index: 1}, '720': {video: 'H264 MPEG-4 AVC, 1280x720, 25fps, 16:9', index: 2}, '576': {video: 'H264 MPEG-4 AVC, 1024x576, 25fps, 16:9', index: 3}, '480': {video: 'H264 MPEG-4 AVC, 854x480, 25fps, 16:9', index: 4}, '360': {video: 'H264 MPEG-4 AVC, 640x360, 25fps, 16:9', index: 5}, '240': {video: 'H264 MPEG-4 AVC, 426x240, 25fps, 16:9', index: 6} }, TVP: { '9100000': {video: 'H264 MPEG-4 AVC, 21030 kb/s, 1920x1080, 25fps, 16:9', index: 1}, '5420000': {video: 'H264 MPEG-4 AVC, 9875 kb/s, 1280x720, 25fps, 16:9', index: 2}, '2850000': {video: 'H264 MPEG-4 AVC, 4661 kb/s, 960x540, 25fps, 16:9', index: 3}, '1750000': {video: 'H264 MPEG-4 AVC, 1782 kb/s, 800x450, 25fps, 16:9', index: 4}, '1500000': {video: 'H264 MPEG-4 AVC, 1487 kb/s, 720x404, 25fps, 16:9', index: 5}, '1250000': {video: 'H264 MPEG-4 AVC, 1255 kb/s, 640x360, 25fps, 16:9', index: 6}, '820000': {video: 'H264 MPEG-4 AVC, 809 kb/s, 480x270, 25fps, 16:9', index: 7}, '590000': {video: 'H264 MPEG-4 AVC, 581 kb/s, 398x224, 25fps, 199:112', index: 8} }, ARTE: { '2200': {video: 'H264 MPEG-4 AVC, 2438 kb/s, 1280x720, 25fps, 16:9', index: 1}, '1500': {video: 'H264 MPEG-4 AVC, 1619 kb/s, 720x406, 25fps, 360:203', index: 2}, '800': {video: 'H264 MPEG-4 AVC, 805 kb/s, 640x360, 25fps, 16:9', index: 3}, '300': {video: 'H264 MPEG-4 AVC, 357 kb/s, 384x216, 25fps, 16:9', index: 4} }, NINATEKA: { 'video/mp4': {video: 'H264 MPEG-4 AVC, 900 kb/s, 640x360, 25fps, 16:9', index: 1}, 'application/x-mpegURL': {description: "H264 MPEG-4 video stream with multiple resolutions", format: "HLS", index: 2}, 'application/dash+xml': {description: "MPEG-DASH video stream with multiple resolutions", format: "MPD", index: 3}, }, CDA: { '1080p': {video: 'H264 MPEG-4 AVC, 1920x1080, 16:9', index: 1}, '720p': {video: 'H264 MPEG-4 AVC, 1280x720, 16:9', index: 2}, '480p': {video: 'H264 MPEG-4 AVC, 854x480, 427:240', index: 3}, '360p': {video: 'H264 MPEG-4 AVC, 640x360, 16:9', index: 4}, }, TRWAM: { '3': {video: 'H264 MPEG-4 AVC, 640x360, 16:9', index: 1}, '2': {description: "H264 MPEG-4 video stream with multiple resolutions", format: "HLS", index: 2}, '9': {description: "MPEG-DASH video stream with multiple resolutions", format: "MPD", index: 3}, } } } }; var Step = (function(properties){ var step = { urlTemplateParts: [], urlTemplate: '', before: function(input){return input}, after: function (output) {return output}, resultUrlParams: function (input, template) { var urlParams = {}; $.each(input, function (key, value) { template = template.replace(new RegExp(config.urlParamPattern + key,'g'), value); urlParams[key] = value; }); return { url: template, urlParams: urlParams }; }, resolveUrl: function (input, partIndex) { return this.resultUrlParams(input, this.resolveUrlParts(partIndex)); }, isRemote: function(){ return this.urlTemplate.length > 0; }, method: 'GET', headers: {}, responseType: 'json', retryErrorCodes: [], methodParam: function(){return {}}, resolveUrlParts: function(partIndex){ if(this.urlTemplateParts.length){ return this.urlTemplate.replace(config.urlPartPattern, this.urlTemplateParts[partIndex]); } return this.urlTemplate; } }; return $.extend(true, step, properties); }); var Notification = (function(Notification) { var create = function(title, bodyContent, special) { var specialContentClasses = special ? ' special-color white-text' : ''; var content = $('
').addClass('toast notification' + specialContentClasses).attr('role', 'alert') .attr('aria-live', 'assertive').attr('aria-atomic', 'true') .attr('name', special ? 'special' : 'normal').attr('data-delay', '5000'); var header = $('
').addClass('toast-header special-color-dark white-text'); var warnIcon = $('').addClass('fas fa-exclamation-triangle pr-2'); var notificationTitle = $('').addClass('mr-auto').text(title); var time = $('').text(new Date().toLocaleTimeString()); var close = $('