Ziggo GO - Skip Ads

Automatically skip ads on Ziggo GO by skipping directly to the end of each ad break.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name           Ziggo GO - Skip Ads
// @name:nl        Ziggo GO - Reclame overslaan
// @namespace      http://tampermonkey.net/
// @version        1.2.1
// @description    Automatically skip ads on Ziggo GO by skipping directly to the end of each ad break.
// @description:nl Spoel automatisch de reclames door op Ziggo GO naar het einde van de reclame.
// @author         JxxIT
// @license        MIT
// @match          *://*.ziggogo.tv/*
// @icon           https://www.google.com/s2/favicons?sz=64&domain=ziggogo.tv
// @grant          none
// ==/UserScript==

(function () {
  "use strict";

  let video = null;
  let adBreaks = [];
  let currentSegment = -1;

  /**
   * Debugging helper to log information to the console.
   */
  function logDebugInfo(message, data) {
    console.groupCollapsed(`DEBUG: ${message}`);
    if (data) console.log(data);
    console.groupEnd();
  }

  /**
   * Find the segment in which the current time is or the nearest future segment.
   */
  function findCurrentSegment() {
    logDebugInfo("Finding current segment...", {
      video,
      adBreaks,
      currentSegment,
    });

    if (!video || adBreaks.length === 0) {
      logDebugInfo("No video or ad breaks found.");
      return;
    }

    const currentTime = video.currentTime * 1000; // Convert to milliseconds
    const previousSegment = currentSegment;

    logDebugInfo("Current time...", currentTime);

    // Find the current or next segment
    currentSegment = adBreaks.findIndex(
      (ad) => currentTime >= ad.startTime && currentTime < ad.endTime
    );

    logDebugInfo("Current segment index...", currentSegment);

    if (currentSegment === -1) {
      logDebugInfo("No current segment found. Finding next segment...");
      currentSegment = adBreaks.findIndex((ad) => currentTime < ad.startTime);
    }

    logDebugInfo("Segment checked", {
      currentTime,
      previousSegment,
      currentSegment,
    });
  }

  /**
   * Check and skip if the user is in an advertising block.
   */
  function handleAdSkipping() {
    logDebugInfo("Handling ad skipping...", {
      currentSegment,
      adBreaks,
    });

    if (currentSegment < 0 || currentSegment >= adBreaks.length) {
      logDebugInfo("No valid current segment. Skipping ad skipping.");
      return;
    }

    const ad = adBreaks[currentSegment];
    const adStart = ad.startTime / 1000; // Convert to seconds
    const adEnd = ad.endTime / 1000;

    logDebugInfo("Ad start and end times...", {
      adStart,
      adEnd,
    });

    if (video.currentTime >= adStart && video.currentTime < adEnd) {
      logDebugInfo(`Ad detected. Skipping to ${adEnd}`, {
        adStart,
        adEnd,
      });
      //video.pause();
      video.currentTime = adEnd;
      //video.play();
    } else {
      logDebugInfo("No ad detected. Not skipping.");
    }
  }

  /**
   * Add time update and interaction events to check jumping and playing times.
   */
  function attachListeners() {
    logDebugInfo("Attaching listeners...", {
      video,
    });

    if (!video.adBypassAttached) {
      video.adBypassAttached = true;

      video.addEventListener("timeupdate", () => {
        logDebugInfo("Time update event...", {
          video,
        });
        findCurrentSegment(); // Check which segment we are in
        handleAdSkipping(); // Skip if necessary
      });

      video.addEventListener("seeked", () => {
        logDebugInfo("Seeked event...", {
          video,
        });
        findCurrentSegment();
        handleAdSkipping();
      });
    } else {
      logDebugInfo("Listeners already attached.");
    }
  }

  /**
   * Merge consecutive ad segments into a single segment.
   */
  function mergeAdSegments(adBreaks) {
    const mergedAdBreaks = [adBreaks[0]];

    for (let i = 1; i < adBreaks.length; i++) {
      const currentAd = adBreaks[i];
      const lastMergedAd = mergedAdBreaks[mergedAdBreaks.length - 1];

      if (currentAd.startTime === lastMergedAd.endTime) {
        // Consecutive ad segments, merge them
        lastMergedAd.endTime = currentAd.endTime;
      } else {
        mergedAdBreaks.push(currentAd);
      }
    }

    return mergedAdBreaks;
  }

  /**
   * Process new advertising blocks and set the video.
   */
  function handleVideo(newAdBreaks) {
    logDebugInfo("Handling video...", {
      newAdBreaks,
    });

    video = document.querySelector("video");

    if (!video) {
      logDebugInfo("No video element found!");
      return;
    }

    if (newAdBreaks.length === 0) {
      logDebugInfo("No ads found :)");
      return;
    }

    adBreaks = mergeAdSegments(newAdBreaks);
    logDebugInfo("Merged ad breaks", adBreaks);

    findCurrentSegment(); // Calculate the right segment
    handleAdSkipping(); // Check the current time immediately
    attachListeners(); // Adding Eventlistans
  }

  // Override console.info to intercept advertising updates
  const originalConsoleInfo = console.info;
  console.info = function (...args) {
    if (args[2] === "event::adBreaksUpdateEvent") {
      logDebugInfo("Ad update received", args[3]);
      handleVideo(args[3]?.adBreaks || []);
    } else {
      originalConsoleInfo.apply(console, args);
    }
  };
})();