Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name SkyShowtime Date and Language
- // @namespace http://tampermonkey.net/
- // @version 2.0
- // @description Presreće XHR i fetch zahtjeve na SkyShowtime te automatski prikazuje offerEndTs (epoch) konvertiran u lokalni datum unutar tipke, formatiran kao dd.mm.yyyy. HH:mm:ss. Također, kad se u xhr sadrži "vod", ispod datuma se ispisuju zastavice za balkanske jezike, sortirane abecedno (Bosanski, Hrvatski, Slovenski, Srpski).
- // @match https://www.skyshowtime.com/*
- // @grant none
- // @run-at document-idle
- // ==/UserScript==
- (function() {
- 'use strict';
- console.log("SkyShowtime Datum Intercept script loaded");
- // Dodajemo tipku u donji desni kut
- let btn = document.createElement("button");
- btn.id = "skyDatumBtn";
- btn.innerText = "Dostupno do:"; // Početni tekst
- btn.style.position = "fixed";
- btn.style.bottom = "20px";
- btn.style.right = "20px";
- btn.style.zIndex = "9999";
- btn.style.padding = "10px";
- btn.style.backgroundColor = "#795FE3";
- btn.style.color = "#fff";
- btn.style.border = "none";
- btn.style.borderRadius = "5px";
- btn.style.cursor = "default";
- document.documentElement.appendChild(btn);
- // Globalna varijabla za čuvanje osnovnog teksta (npr. datum)
- let baseText = "";
- // Funkcija za formatiranje datuma u oblik "dd.mm.yyyy. HH:mm:ss"
- function formatDate(date) {
- const dd = ("0" + date.getDate()).slice(-2);
- const mm = ("0" + (date.getMonth() + 1)).slice(-2);
- const yyyy = date.getFullYear();
- const hh = ("0" + date.getHours()).slice(-2);
- const min = ("0" + date.getMinutes()).slice(-2);
- const ss = ("0" + date.getSeconds()).slice(-2);
- return `${dd}.${mm}.${yyyy}. ${hh}:${min}:${ss}`;
- }
- // Izdvajamo token iz URL-a – dio nakon "/watch/asset"
- const prefix = "/watch/asset";
- let token = "";
- function updateToken(){
- let path = window.location.pathname;
- if (path.startsWith(prefix)) {
- token = path.slice(prefix.length);
- console.log("Extracted token:", token);
- } else {
- token = "";
- console.log("URL ne sadrži očekivani prefiks:", prefix);
- }
- }
- updateToken();
- // Funkcija koja obrađuje API podatke: traži offerEndTs i konvertira epoch u lokalni datum
- function processApiData(data) {
- if (!data) return;
- let offerVal = data.offerEndTs;
- if (offerVal === undefined || offerVal === null) {
- offerVal = findOfferEndTs(data);
- }
- if (offerVal !== undefined && offerVal !== null) {
- let epoch;
- if (typeof offerVal === "number") {
- epoch = offerVal;
- } else if (typeof offerVal === "string") {
- let epochStr = offerVal.replace(/[{}]/g, '').trim();
- epoch = parseInt(epochStr, 10);
- } else {
- console.error("Nepodržani tip offerEndTs:", typeof offerVal);
- return;
- }
- if (!isNaN(epoch)) {
- let dateObj = new Date(epoch);
- let localDate = formatDate(dateObj);
- baseText = "Dostupno do: " + localDate;
- btn.innerHTML = baseText;
- console.log("OfferEndTs processed, local date:", localDate);
- }
- }
- }
- // Rekurzivna pretraga za offerEndTs u objektu
- function findOfferEndTs(obj) {
- if (typeof obj !== 'object' || obj === null) return null;
- if (obj.hasOwnProperty('offerEndTs')) return obj.offerEndTs;
- for (let key in obj) {
- if (obj.hasOwnProperty(key)) {
- let result = findOfferEndTs(obj[key]);
- if (result) return result;
- }
- }
- return null;
- }
- // Funkcija koja obrađuje podatke iz "vod" zahtjeva - filtrira audio i titlove
- function processVodData(data) {
- if (!data) return;
- // Ako je podatak unutar "asset", koristimo ga, inače direktno data
- let assetData = data.asset || data;
- // Definiramo mape: allowedLocales s HTML zastavicama i languageNames s nazivima jezika
- const allowedLocales = {
- "hr-HR": '<img src="https://flagcdn.com/24x18/hr.png" style="vertical-align:middle;" title="Hrvatski">',
- "sl-SI": '<img src="https://flagcdn.com/24x18/si.png" style="vertical-align:middle;" title="Slovenski">',
- "sr-RS": '<img src="https://flagcdn.com/24x18/rs.png" style="vertical-align:middle;" title="Srpski">',
- "bs-BA": '<img src="https://flagcdn.com/24x18/ba.png" style="vertical-align:middle;" title="Bosanski">'
- };
- const languageNames = {
- "hr-HR": "Hrvatski",
- "sl-SI": "Slovenski",
- "sr-RS": "Srpski",
- "bs-BA": "Bosanski"
- };
- let audioTracks = assetData.audioTracks || [];
- let subtitleTracks = assetData.subtitleTracks || [];
- let audioLangs = []; // ovdje ćemo spremati kodove jezika
- let subtitleLangs = [];
- if (Array.isArray(audioTracks)) {
- audioTracks.forEach(track => {
- if ((track.type === "Stereo" || track.type === "Surround") && allowedLocales[track.locale]) {
- if (!audioLangs.includes(track.locale)) {
- audioLangs.push(track.locale);
- }
- }
- });
- }
- if (Array.isArray(subtitleTracks)) {
- subtitleTracks.forEach(track => {
- if (track.type === "SUB" && allowedLocales[track.locale]) {
- if (!subtitleLangs.includes(track.locale)) {
- subtitleLangs.push(track.locale);
- }
- }
- });
- }
- // Sortiramo po abecedi koristeći nazive jezika
- audioLangs.sort((a, b) => languageNames[a].localeCompare(languageNames[b]));
- subtitleLangs.sort((a, b) => languageNames[a].localeCompare(languageNames[b]));
- // Ažuriraj tipku samo ako pronađemo barem jedan jezik
- if (audioLangs.length > 0 || subtitleLangs.length > 0) {
- let newHTML = baseText;
- if (audioLangs.length > 0) {
- // Za audio, spajamo zastavice
- let audioHTML = audioLangs.map(code => allowedLocales[code]).join(" ");
- newHTML += "<br>Audio: " + audioHTML;
- }
- if (subtitleLangs.length > 0) {
- let subtitleHTML = subtitleLangs.map(code => allowedLocales[code]).join(" ");
- newHTML += "<br>Titlovi: " + subtitleHTML;
- }
- btn.innerHTML = newHTML;
- console.log("Processed VOD data, audio:", audioLangs, "titlovi:", subtitleLangs);
- } else {
- console.log("Processed VOD data ali nisu pronađeni valjani audio ili titlovi.");
- }
- }
- // Overrideamo window.fetch da presretnemo API odgovore
- const originalFetch = window.fetch;
- window.fetch = async function(...args) {
- const response = await originalFetch.apply(this, args);
- try {
- let url = args[0] ? args[0].toString() : "";
- if (url.toLowerCase().includes("node?slug=") &&
- (url.includes(token) || url.includes(encodeURIComponent(token)))) {
- console.log("Intercepted fetch request:", url);
- const clonedResponse = response.clone();
- clonedResponse.json().then(data => {
- if (data && JSON.stringify(data).includes("offerEndTs")) {
- console.log("Fetch response intercepted:", data);
- processApiData(data);
- }
- }).catch(e => {
- console.log("Fetch response not JSON:", e);
- });
- } else if (url.toLowerCase().includes("vod")) {
- console.log("Intercepted fetch VOD request:", url);
- const clonedResponse = response.clone();
- clonedResponse.json().then(data => {
- console.log("Fetch VOD response intercepted:", data);
- processVodData(data);
- }).catch(e => {
- console.log("Fetch VOD response not JSON:", e);
- });
- }
- } catch(e) {
- console.error("Error intercepting fetch response:", e);
- }
- return response;
- };
- // Overrideamo XMLHttpRequest da presretnemo njegove odgovore
- const originalXHR = window.XMLHttpRequest;
- function newXHR() {
- const xhr = new originalXHR();
- const originalOpen = xhr.open;
- xhr.open = function(method, url, async, user, password) {
- this._url = url;
- return originalOpen.apply(this, arguments);
- };
- xhr.addEventListener("load", function() {
- if (this._url && this._url.toLowerCase().includes("node?slug=") &&
- (this._url.includes(token) || this._url.includes(encodeURIComponent(token)))) {
- console.log("Intercepted XHR request:", this._url);
- try {
- let data = JSON.parse(this.responseText);
- if (data && JSON.stringify(data).includes("offerEndTs")) {
- console.log("XHR response intercepted:", data);
- processApiData(data);
- }
- } catch(e) {
- console.error("Error parsing XHR response:", e);
- }
- }
- if (this._url && this._url.toLowerCase().includes("vod")) {
- console.log("Intercepted XHR VOD request:", this._url);
- try {
- let data = JSON.parse(this.responseText);
- processVodData(data);
- } catch(e) {
- console.error("Error parsing XHR VOD response:", e);
- }
- }
- });
- return xhr;
- }
- window.XMLHttpRequest = newXHR;
- // Sakriva tipku kada se pokrene video
- document.addEventListener("play", function(e) {
- if (e.target.tagName && e.target.tagName.toUpperCase() === "VIDEO") {
- console.log("Video started, hiding button");
- btn.style.display = "none";
- }
- }, true);
- // Pokaži tipku kada video završi
- document.addEventListener("ended", function(e) {
- if (e.target.tagName && e.target.tagName.toUpperCase() === "VIDEO") {
- console.log("Video ended, showing button");
- btn.style.display = "block";
- }
- }, true);
- // Ako se navigira na novi sadržaj unutar SPA, resetiramo token i tipku
- const wrapHistoryMethod = method => {
- const original = history[method];
- return function(...args) {
- const result = original.apply(this, args);
- window.dispatchEvent(new Event("locationchange"));
- return result;
- };
- };
- history.pushState = wrapHistoryMethod("pushState");
- history.replaceState = wrapHistoryMethod("replaceState");
- window.addEventListener("popstate", () => window.dispatchEvent(new Event("locationchange")));
- window.addEventListener("locationchange", function() {
- updateToken();
- btn.innerHTML = "Dostupno do:"; // reset tipke
- baseText = "";
- if (!document.querySelector("video")) {
- btn.style.display = "block";
- }
- });
- })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement