The only ripper youll need because its practically the only one that works.
// ==UserScript==
// @name SampleFocus Ripper
// @namespace http://tampermonkey.net/
// @version 5.0
// @description The only ripper youll need because its practically the only one that works.
// @author MassaHex
// @license MIT
// @icon https://www.google.com/s2/favicons?sz=64&domain=samplefocus.com
// @match https://samplefocus.com/*
// @grant none
// ==/UserScript==
(function () {
"use strict";
const Ripper = {
config: {
red: "#ee534f",
green: "#4caf50",
blue: "#64b5f6",
yellow: "#ff9800",
},
state: {
mp3Buffer: new Set(),
owned: new Set(),
},
init() {
this.injectStyles();
this.loadOwned();
this.sniffNetwork();
setInterval(() => this.refreshUI(), 800);
},
injectStyles() {
if (document.getElementById("ripper-style")) return;
const s = document.createElement("style");
s.id = "ripper-style";
s.innerHTML = `
/* kill native tooltips */
.MuiTooltip-popper,[role="tooltip"]{display:none!important}
/* wrapper */
.ripper-wrap{position:relative;display:flex;flex-direction:column;width:100%}
/* tooltip (RESTORED 4.0 STYLE) */
.ripper-tooltip{
position:absolute;
padding:8px 12px;
font-size:11px;
background:#121212;
color:#fff;
border:1px solid #444;
border-radius:6px;
box-shadow:0 8px 24px rgba(0,0,0,0.8);
pointer-events:none;
opacity:0;
visibility:hidden;
transition:.15s;
white-space:nowrap;
z-index:9999;
/* CRITICAL FIX: lock position so it doesn't drift when hidden */
top:100%;
right:0;
transform:none;
}
/* ONLY reposition when visible */
.sample-card:hover .ripper-tooltip{
opacity:1;
visibility:visible;
top:calc(100% + 5px);
right:0;
}
.sample-hero .ripper-tooltip{
opacity:1;
visibility:visible;
top:calc(100% + 12px);
left:50%;
right:auto;
transform:translateX(-50%);
}
.sample-card:hover .ripper-tooltip{opacity:1;visibility:visible;top:calc(100% + 5px);right:0}
.sample-hero .ripper-tooltip{opacity:1;visibility:visible;top:calc(100% + 12px);left:50%;transform:translateX(-50%)}
.ripper-tooltip-header{font-weight:900;color:${this.config.red};font-size:10px;margin-bottom:2px}
/* HERO BUTTON FIX */
.sample-hero button[aria-label="Download"],
.sample-hero span[aria-label="Download"]{
background:#fff!important;
border:1.5px solid #d0d0d0!important;
box-shadow:none!important;
}
/* HERO STATES */
.sample-hero .ripper-owned{border:1.5px solid ${this.config.green}!important}
.sample-hero .ripper-owned i{color:${this.config.green}!important}
.sample-hero .ripper-buy{border:1.5px solid ${this.config.blue}!important}
.sample-hero .ripper-buy i{color:${this.config.blue}!important}
/* CARD ICON COLORS ONLY (NO BORDER CHANGE) */
.sample-card .ripper-owned i{color:${this.config.green}!important}
.sample-card .ripper-buy i{color:${this.config.blue}!important}
/* MP3 BUTTON (RECTANGLE FIXED) */
.ripper-mp3{
margin-top:6px;
width:100%;
height:34px;
display:flex;
align-items:center;
justify-content:center;
border-radius:6px;
cursor:pointer;
color:#fff;
}
.ripper-mp3.ready{background:${this.config.red}}
.ripper-mp3.wait{background:${this.config.yellow};cursor:wait}
`;
document.head.appendChild(s);
},
loadOwned() {
const raw = localStorage.getItem("downloadedSamples");
if (!raw) return;
try {
const parsed = JSON.parse(raw);
(parsed instanceof Array ? parsed : [parsed]).forEach((id) =>
this.state.owned.add(String(id)),
);
} catch {
raw.split(",").forEach((id) => this.state.owned.add(id.trim()));
}
},
sniffNetwork() {
const orig = window.fetch;
window.fetch = async (...a) => {
const url = typeof a[0] === "string" ? a[0] : a[0].url;
if (url && url.includes(".mp3"))
this.state.mp3Buffer.add(url.split("?")[0]);
return orig(...a);
};
},
extract(container) {
const img = container.querySelector('img[src*="/sample_files/"]');
if (!img) return {};
const id = img.src.match(/\/sample_files\/(\d+)\//)?.[1];
let url = null;
for (const u of this.state.mp3Buffer) {
if (u.includes(`/${id}/`)) {
url = u;
break;
}
}
let rawName = "";
// --- HERO PAGE (guaranteed reliable) ---
if (container.classList.contains("sample-hero")) {
const parts = window.location.pathname.split("/samples/");
if (parts[1]) rawName = parts[1].split("/")[0];
}
// --- CARD LINK (second best) ---
if (!rawName) {
const link = container.querySelector('a[href*="/samples/"]');
if (link) {
const parts = link.href.split("/samples/");
if (parts[1]) rawName = parts[1].split("/")[0];
}
}
// --- LAST RESORT: visible text ---
if (!rawName) {
const t = container.querySelector(
'[role="heading"], .sample-card-link div',
);
if (t) rawName = t.textContent.trim();
}
// --- FINAL FALLBACK ---
if (!rawName) rawName = "sample";
const clean = rawName
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
return {
id,
url,
name: clean,
fileName: `${clean}.mp3`,
};
},
refreshUI() {
document.querySelectorAll(".sample-card,.sample-hero").forEach((c) => {
const btn = c.querySelector('[aria-label="Download"]');
if (!btn) return;
const data = this.extract(c);
const owned = this.state.owned.has(String(data.id));
/* ICON LOGIC FIXED */
btn.classList.remove("ripper-owned", "ripper-buy");
if (owned) {
btn.classList.add("ripper-owned");
btn.innerHTML = '<i class="fas fa-download"></i>';
} else {
btn.classList.add("ripper-buy");
btn.innerHTML = '<i class="fas fa-shopping-bag"></i>';
}
/* WRAPPER + MP3 BUTTON */
if (!c.querySelector(".ripper-wrap")) {
const wrap = document.createElement("div");
wrap.className = "ripper-wrap";
const mp3 = document.createElement("div");
mp3.className = "ripper-mp3 wait";
mp3.innerHTML = '<i class="fas fa-hourglass-half"></i>';
const tip = document.createElement("div");
tip.className = "ripper-tooltip";
wrap.appendChild(mp3);
wrap.appendChild(tip);
btn.parentNode.appendChild(wrap);
mp3.onclick = (e) => {
e.stopPropagation();
const fresh = this.extract(c);
if (!fresh.url) return;
mp3.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
fetch(fresh.url)
.then((r) => r.blob())
.then((b) => {
const a = document.createElement("a");
a.href = URL.createObjectURL(b);
a.download = `${fresh.name}_${fresh.id}.mp3`;
a.click();
mp3.innerHTML = '<i class="fas fa-check"></i>';
setTimeout(() => {
mp3.innerHTML = '<i class="fas fa-download"></i>';
}, 1200);
});
};
}
const mp3 = c.querySelector(".ripper-mp3");
const tip = c.querySelector(".ripper-tooltip");
if (data.url) {
mp3.classList.remove("wait");
mp3.classList.add("ready");
mp3.innerHTML = '<i class="fas fa-download"></i>';
tip.innerHTML =
'<div class="ripper-tooltip-header">READY</div><div>Download Preview MP3</div>';
} else {
mp3.classList.add("wait");
mp3.innerHTML = '<i class="fas fa-hourglass-half"></i>';
tip.innerHTML =
'<div class="ripper-tooltip-header">SCANNING</div><div>Awaiting Sample Preview</div>';
}
/* auto sniff */
c.addEventListener("mouseenter", () => {
const w = c.querySelector('[class*="waveform"]');
if (w)
w.dispatchEvent(new MouseEvent("mouseover", { bubbles: true }));
});
});
},
};
Ripper.init();
})();