Easy SampleFocus℠ Downloader

Allows downloading from samplefocus.com without tokens.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name Easy SampleFocus℠ Downloader
// @description Allows downloading from samplefocus.com without tokens.
// @description:ar Allows downloading from samplefocus.com without tokens.
// @description:bg Allows downloading from samplefocus.com without tokens.
// @description:cs Allows downloading from samplefocus.com without tokens.
// @description:da Allows downloading from samplefocus.com without tokens.
// @description:de Allows downloading from samplefocus.com without tokens.
// @description:el Allows downloading from samplefocus.com without tokens.
// @description:eo Allows downloading from samplefocus.com without tokens.
// @description:es Allows downloading from samplefocus.com without tokens.
// @description:fi Allows downloading from samplefocus.com without tokens.
// @description:fr Allows downloading from samplefocus.com without tokens.
// @description:fr-CA Allows downloading from samplefocus.com without tokens.
// @description:he Allows downloading from samplefocus.com without tokens.
// @description:hu Allows downloading from samplefocus.com without tokens.
// @description:id Allows downloading from samplefocus.com without tokens.
// @description:it Allows downloading from samplefocus.com without tokens.
// @description:ja Allows downloading from samplefocus.com without tokens.
// @description:ko Allows downloading from samplefocus.com without tokens.
// @description:nb Allows downloading from samplefocus.com without tokens.
// @description:nl Allows downloading from samplefocus.com without tokens.
// @description:pl Allows downloading from samplefocus.com without tokens.
// @description:ro Allows downloading from samplefocus.com without tokens.
// @description:ru Allows downloading from samplefocus.com without tokens.
// @description:sk Allows downloading from samplefocus.com without tokens.
// @description:sr Allows downloading from samplefocus.com without tokens.
// @description:sv Allows downloading from samplefocus.com without tokens.
// @description:th Allows downloading from samplefocus.com without tokens.
// @description:tr Allows downloading from samplefocus.com without tokens.
// @description:uk Allows downloading from samplefocus.com without tokens.
// @description:ug Allows downloading from samplefocus.com without tokens.
// @description:vi Allows downloading from samplefocus.com without tokens.
// @description:zh-CN Allows downloading from samplefocus.com without tokens.
// @description:zh-TW Allows downloading from samplefocus.com without tokens.
// @namespace   https://greasyfork.org/users/1627591
// @author Luftin
// @date 2026-07-25
// @version     1.0.0
// @match       https://samplefocus.com/samples/*
// @grant       none
// @license MIT
// ==/UserScript==

async function downloadFileFromUrl(downloadUrl, name) {
    try {
        const response = await fetch(downloadUrl);

        if (!response.ok) {
            throw new Error("Failed to download file");
        }

        const blob = await response.blob();
        const blobUrl = URL.createObjectURL(blob);

        const a = document.createElement("a");
        a.href = blobUrl;
        a.download = name;

        document.body.appendChild(a);
        a.click();
        a.remove();

        URL.revokeObjectURL(blobUrl);
    } catch (err) {
        console.error(err);
    }
}


function whitespaceToUnderscore(text) {
  return text.replace(/\s/g, "_");
}

async function loaded() {
  console.log("Loaded")

  const allE = document.querySelectorAll("script[type='application/ld+json']");

  allE.forEach((e) => {
    const string = e.innerText.toString();
    let obj = null;
    try{
      obj = JSON.parse(string);
    }catch(e){
      // console.debug("Parsing did not work on", string);
    }

    if(obj && obj.contentUrl){
      const downloadUrl = obj.contentUrl;

      let bpm = null;
      let key = null;
      let sample_name = whitespaceToUnderscore(document.querySelector(".MuiGrid-root.MuiGrid-item.MuiGrid-grid-xs-12.MuiGrid-grid-sm-6.MuiGrid-grid-md-6.MuiGrid-grid-lg-6").children[0].innerText);

      const attributes = document.querySelector("ul.sample-attrs");

      attributes.childNodes.forEach((node) => {
        const attribute = node.children[0].className;
        if (attribute.includes("fa-music")){
          key = whitespaceToUnderscore(node.innerText)
        }

        if (attribute.includes("fa-ellipsis")){
          bpm = whitespaceToUnderscore(node.innerText)
        }
      })

      const fileName = `${sample_name}${bpm ? "_" + bpm : ""}${key ? "_" + key : ""}`;

      async function handleDownloadClick(event) {
          downloadFileFromUrl(downloadUrl, fileName);
      }

      const originalDownloadButton = document.querySelector("*[aria-label='Download'].MuiButton-fullWidth");
      originalDownloadButton.setAttribute("style", "--variant-containedBg: #74be41");
      originalDownloadButton.innerText = "Download";
      console.log(originalDownloadButton);

      originalDownloadButton.addEventListener("click", (e) => {
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
        handleDownloadClick(e)
      }, true)
    }
  });
}


window.addEventListener('load', () => {
  setTimeout(loaded, 500);
});