Sangam / SOAP2DAY video downloader

// ==UserScript==
// @name         SOAP2DAY video downloader
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Script to download videos from soap2day sites.
// @author       Sangam
// @require      http://code.jquery.com/jquery-3.3.1.min.js
// @match        https://soap2day.ac/*
// @match        https://soap2day.sh/*
// @match        https://s2dfree.to/*
// @match        https://s2dfree.cc/*
// @match        https://s2dfree.de/*
// @match        https://s2dfree.is/*
// @match        https://s2dfree.in/*
// @match        https://s2dfree.nl/*
// @icon         https://www.google.com/s2/favicons?domain=s2dfree.in
// @grant        none
// @license MIT
// ==/UserScript==

const html = `<style>
.sh-btn {
    background-image: linear-gradient(#f99a52, #db579d);
    font-weight: bold;
    color: white;
    cursor: pointer;
    padding: 5px 10px;
    border-radius: 5px;
    box-shadow: 0 0 5px black;
    width: auto;
}

.sh-btn:active {
    transform: scale(0.9);
}
</style>
<!-- <div class="downloader-icon">Search & Download</div> -->
<style>
.sh-popup {
    position: fixed;
    bottom: 40px;
    right: 20px;
    z-index: 100000;
    height: 600px;
    width: 300px;
    background: #3a0455;
    color:white;
    border: 5px solid #b566dd;
    padding: 10px;
    border-radius: 5px;
    overflow: auto;
}

.sh-column {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.sh-input{
    margin: 5px;
    color:black;
}
.sh-downloadable-video:first-child{
    margin : 100px auto 5px;
}
.sh-downloadable-video{
    padding : 5px;
    margin: 5px;
    background: #3a0455;
    color:white;
}
</style>
<div class="sh-popup">
<div class="sh-column sh-search-season-links">
    <input class="sh-input" id="sh-season" type="number" placeholder="Season" value="1" />
    <div class="sh-btn" id="sh-search-season-links-btn">Search season links</div>
</div>
<hr />
<div class="sh-column">
    <span id="sh-searched-links">Haven't searched yet.</span>
</div>
<hr />
<div class="sh-column sh-convert-to-iframes">
    <input class="sh-input" id="sh-starting-range" type="number" placeholder="Starting range" value="1" />
    <input class="sh-input" id="sh-ending-range" type="number" placeholder="Ending range" value="2" />
    <div class="sh-btn" id="sh-convert-to-iframes-btn">Convert to iframe</div>
</div>
<hr />
<div class="sh-column" id="sh-iframes">
    Haven't added iframes yet
</div>
<hr />
<div class="sh-column sh-replace-with-videos">
    <div class="sh-btn" id="sh-replace-with-videos-btn">Replace Iframes with videos</div>
</div>
<hr />
<div class="sh-column" id="sh-videos">
    Haven't added videos yet
</div>
<hr />
<div class="sh-column" id="sh-alternatives">
</div>
</div>`;
if (window.self === window.top) {
  $("body").append(html);
  $("#sh-alternatives").append("Alternatives");
  const alternatives = [
    "https://soap2day.ac",
    "https://soap2day.sh",
    "https://s2dfree.to",
    "https://s2dfree.cc",
    "https://s2dfree.de",
    "https://s2dfree.is",
    "https://s2dfree.in",
    "https://s2dfree.nl",
  ];
  alternatives.forEach(hostname => $("#sh-alternatives").append(`<a href="${hostname+location.pathname}" target="_blank">${hostname}</a>`));
}

let episodesLinkMap = {};
let episodeLinks = [];
let iframeIndexes = [];

function searchForLinks() {
  const seasonNumber = parseInt($("#sh-season").val());
  const links = $(`h4:contains('Season${seasonNumber}')`).parent().find("a");
  if (links.length == 0) {
    return $("#sh-searched-links").html("No links found");
  }
  window.links = links;
  episodeLinks = [];
  episodesLinkMap = {};
  links.each((i, ele) => {
    const link = location.origin + ele.attributes.href.value;
    episodesLinkMap[link] = ele.textContent;
    episodeLinks.unshift(link);
  });
  $("#sh-searched-links").html(`Found ${links.length} links<br>`);
}

function addIframe(ind) {
  const frameId = `sh-iframe-${ind}`;
  const link = episodeLinks[ind];
  $("body").append(`<div><iframe class="sh-iframe" id="${frameId}" src="${link}" height="500px" width="500px" /><div>`);
  $("#sh-iframes").append(`<div><a id="${frameId}-link" href="#${frameId}">${episodesLinkMap[link]} - <span id="sh-video-status">loading</span></a><div>`);
  const timer = setInterval(function () {
    if ($(`#${frameId}`).contents().find("video").length == 1) {
      $(`#${frameId}-link #sh-video-status`).html("loaded");
      clearInterval(timer);
    }
  }, 1000);
  iframeIndexes.push(ind);
}

function convertToIframes() {
  if (episodeLinks.length == 0) {
    return alert("Please search for links first!");
  }
  $("iframe").remove();
  $("#sh-iframes").html('<h4>Iframes</h4>');
  let startingRange = parseInt($("#sh-starting-range").val());
  if (startingRange < 1) {
    return alert("Starting range shouldn't be less than 1!");
  }
  let endingRange = parseInt($("#sh-ending-range").val());
  if (endingRange > episodeLinks.length) {
    return alert(`Ending range shouldn't be greater than ${episodeLinks.length}!`);
  }
  iframeIndexes = [];
  $(".sh-downloadable-video").remove();
  while (startingRange <= endingRange) {
    addIframe(startingRange - 1);
    startingRange++;
  }
}

function addVideo(link, ind) {
  const episodeName = episodesLinkMap[episodeLinks[iframeIndexes[ind]]];
  const videoId = `sh-video-${ind}`;
  $("body").append(`<div class="sh-downloadable-video sh-column" id="${videoId}"><h4>${episodeName}</h4><video src="${link}" height="240" width="400" controls poster="${$(".thumbnail img").attr("src")}"/><div>`);
  $("#sh-videos").append(`<div><a href="#${videoId}">${episodeName}</a><div>`);
}

function replaceWithVideos() {
  const links = [];
  const videos = $("iframe").contents().find("video");
  if ($("iframe").length != videos.length) {
    return alert("Videos haven't fetched yet! please wait.");
  }
  $("#sh-videos").html("<h4>Videos</h4>");
  videos.each((i, ele) => {
    links.push(ele.src);
  });
  $("#sh-iframes").html('Iframes converted into videos');
  $("iframe").remove();
  links.forEach(addVideo)
}

$("#sh-search-season-links-btn").click(searchForLinks);
$("#sh-convert-to-iframes-btn").click(convertToIframes);
$("#sh-replace-with-videos-btn").click(replaceWithVideos);