diff --git a/scripts/javascript/cs-fit-to-window.user.js b/scripts/javascript/cs-fit-to-window.user.js new file mode 100644 index 0000000..e71176c --- /dev/null +++ b/scripts/javascript/cs-fit-to-window.user.js @@ -0,0 +1,130 @@ +// ==UserScript== +// @name CrackStreams - Fit Video to Window +// @namespace https://git.okseby.com/okseby/crunchbang +// @version 1.0 +// @description Adds a button that expands the video player to fill the browser window (not real fullscreen) +// @author seby +// @match https://crackstreams.mx/stream/* +// @match https://footybite.ac/event/* +// @updateURL https://git.okseby.com/okseby/crunchbang/raw/branch/main/scripts/javascript/fit-to-window.user.js +// @downloadURL https://git.okseby.com/okseby/crunchbang/raw/branch/main/scripts/javascript/fit-to-window.user.js +// @grant none +// @run-at document-idle +// ==/UserScript== + +(function () { + "use strict"; + + const PLAYER_SELECTOR = "#videoPlayer"; + const BUTTON_ID = "fit-to-window-btn"; + + let isFitted = false; + let placeholder = null; // marks where the player used to live in the DOM + let originalStyle = null; + + function getPlayer() { + return document.querySelector(PLAYER_SELECTOR); + } + + function makeButton() { + const btn = document.createElement("button"); + btn.id = BUTTON_ID; + btn.textContent = "Fit to Window"; + Object.assign(btn.style, { + position: "fixed", + top: "10px", + right: "10px", + zIndex: "2147483647", + padding: "8px 14px", + fontSize: "14px", + fontWeight: "600", + color: "#fff", + background: "#2563eb", + border: "none", + borderRadius: "6px", + cursor: "pointer", + boxShadow: "0 2px 6px rgba(0,0,0,0.4)", + fontFamily: "system-ui, sans-serif", + opacity: "0.08", + transition: "opacity 0.2s ease", + }); + btn.addEventListener("mouseenter", () => { + btn.style.opacity = "1"; + }); + btn.addEventListener("mouseleave", () => { + btn.style.opacity = "0.08"; + }); + btn.addEventListener("click", toggleFit); + document.body.appendChild(btn); + return btn; + } + + function toggleFit() { + const player = getPlayer(); + if (!player) return; + + const btn = document.getElementById(BUTTON_ID); + + if (!isFitted) { + // Save original position info so we can restore later + placeholder = document.createComment("fit-to-window-placeholder"); + player.parentNode.insertBefore(placeholder, player); + + originalStyle = player.getAttribute("style") || ""; + + Object.assign(player.style, { + position: "fixed", + top: "0", + left: "0", + width: "100vw", + height: "100vh", + margin: "0", + zIndex: "2147483646", + background: "#000", + }); + + // Make the iframe/video inside stretch fully too + const inner = player.querySelector("iframe, video"); + if (inner) { + inner.style.width = "100%"; + inner.style.height = "100%"; + } + + document.documentElement.style.overflow = "hidden"; + document.body.style.overflow = "hidden"; + + isFitted = true; + if (btn) btn.textContent = "Exit Fit"; + } else { + // Restore original style/position + if (originalStyle !== null) { + player.setAttribute("style", originalStyle); + } else { + player.removeAttribute("style"); + } + + if (placeholder && placeholder.parentNode) { + placeholder.parentNode.insertBefore(player, placeholder); + placeholder.remove(); + } + + document.documentElement.style.overflow = ""; + document.body.style.overflow = ""; + + isFitted = false; + if (btn) btn.textContent = "Fit to Window"; + } + } + + function init() { + if (document.getElementById(BUTTON_ID)) return; + if (!getPlayer()) { + // Player might load slightly after DOM ready; retry briefly + setTimeout(init, 500); + return; + } + makeButton(); + } + + init(); +})(); diff --git a/scripts/javascript/privatehd-seed-timer.user.js b/scripts/javascript/privatehd-seed-timer.user.js index fda7820..1b567a5 100644 --- a/scripts/javascript/privatehd-seed-timer.user.js +++ b/scripts/javascript/privatehd-seed-timer.user.js @@ -1,15 +1,17 @@ // ==UserScript== // @name PrivateHD Seed Timer -// @namespace https://privatehd.to/ +// @namespace https://git.okseby.com/okseby/crunchbang // @version 1.0.0 // @description Shows required seed time and whether you can stop seeding each torrent, based on file size. -// @author you +// @author seby // @match https://privatehd.to/profile/*/active* +// @updateURL https://git.okseby.com/okseby/crunchbang/raw/branch/main/scripts/javascript/privatehd-seed-timer.user.js +// @downloadURL https://git.okseby.com/okseby/crunchbang/raw/branch/main/scripts/javascript/privatehd-seed-timer.user.js // @grant none // ==/UserScript== (function () { - 'use strict'; + "use strict"; // --------------------------------------------------------------------------- // Formula: required seed time in hours, where x = size in GB @@ -18,8 +20,8 @@ // x >= 50 → 100 * ln(x) - 219.2023 h // --------------------------------------------------------------------------- function requiredHours(sizeGB) { - if (sizeGB <= 1) return 72; - if (sizeGB < 50) return 72 + 2 * sizeGB; + if (sizeGB <= 1) return 72; + if (sizeGB < 50) return 72 + 2 * sizeGB; return 100 * Math.log(sizeGB) - 219.2023; } @@ -29,7 +31,7 @@ function parseSizeToGB(str) { const m = str.trim().match(/([\d.]+)\s*(B|KB|MB|GB|TB)/i); if (!m) return null; - const val = parseFloat(m[1]); + const val = parseFloat(m[1]); const unit = m[2].toUpperCase(); const factors = { B: 1e-9, KB: 1e-6, MB: 1e-3, GB: 1, TB: 1e3 }; return val * (factors[unit] ?? 1); @@ -42,11 +44,11 @@ // --------------------------------------------------------------------------- function parseElapsedHours(str) { let hours = 0; - const days = str.match(/(\d+)\s*d/); - const hrs = str.match(/(\d+)\s*h/); - const mins = str.match(/(\d+)\s*m/); + const days = str.match(/(\d+)\s*d/); + const hrs = str.match(/(\d+)\s*h/); + const mins = str.match(/(\d+)\s*m/); if (days) hours += parseInt(days[1], 10) * 24; - if (hrs) hours += parseInt(hrs[1], 10); + if (hrs) hours += parseInt(hrs[1], 10); if (mins) hours += parseInt(mins[1], 10) / 60; return hours; } @@ -56,63 +58,63 @@ // --------------------------------------------------------------------------- function fmtHours(h) { const days = Math.floor(h / 24); - const hrs = Math.floor(h % 24); + const hrs = Math.floor(h % 24); const mins = Math.round((h % 1) * 60); if (days > 0) return `${days}d ${hrs}h`; - return `${hrs}h ${String(mins).padStart(2, '0')}m`; + return `${hrs}h ${String(mins).padStart(2, "0")}m`; } // --------------------------------------------------------------------------- // Add a "Seed Status" column header // --------------------------------------------------------------------------- - const thead = document.querySelector('table thead tr'); + const thead = document.querySelector("table thead tr"); if (!thead) return; - const th = document.createElement('th'); - th.textContent = 'Seed Status'; - th.style.whiteSpace = 'nowrap'; + const th = document.createElement("th"); + th.textContent = "Seed Status"; + th.style.whiteSpace = "nowrap"; thead.appendChild(th); // --------------------------------------------------------------------------- // Process each data row // --------------------------------------------------------------------------- - const rows = document.querySelectorAll('table tbody tr'); + const rows = document.querySelectorAll("table tbody tr"); - rows.forEach(row => { - const cells = row.querySelectorAll('td'); + rows.forEach((row) => { + const cells = row.querySelectorAll("td"); // Column layout (0-indexed): // 0: icon | 1: name+stats | 2: progress | 3: status | 4: client // 5: upload | 6: download | 7: left | 8: ratio | 9: started | 10: updated | 11: For - const nameCell = cells[1]; - const forCell = cells[11]; // "For" — how long you've been seeding + const nameCell = cells[1]; + const forCell = cells[11]; // "For" — how long you've been seeding if (!nameCell || !forCell) { - const td = document.createElement('td'); - td.textContent = '—'; + const td = document.createElement("td"); + td.textContent = "—"; row.appendChild(td); return; } // File size lives inside the name cell: fa-database span - const sizeSpan = nameCell.querySelector('.fa-database'); + const sizeSpan = nameCell.querySelector(".fa-database"); const sizeText = sizeSpan ? sizeSpan.textContent.trim() : null; - const sizeGB = sizeText ? parseSizeToGB(sizeText) : null; + const sizeGB = sizeText ? parseSizeToGB(sizeText) : null; const elapsedText = forCell.textContent.trim(); - const elapsed = parseElapsedHours(elapsedText); - const required = sizeGB !== null ? requiredHours(sizeGB) : null; + const elapsed = parseElapsedHours(elapsedText); + const required = sizeGB !== null ? requiredHours(sizeGB) : null; - const td = document.createElement('td'); - td.style.whiteSpace = 'nowrap'; - td.style.verticalAlign = 'middle'; + const td = document.createElement("td"); + td.style.whiteSpace = "nowrap"; + td.style.verticalAlign = "middle"; if (required === null) { - td.textContent = 'No size data'; - td.style.color = '#999'; + td.textContent = "No size data"; + td.style.color = "#999"; } else { const remaining = required - elapsed; - const canStop = remaining <= 0; + const canStop = remaining <= 0; if (canStop) { td.innerHTML = @@ -127,5 +129,4 @@ row.appendChild(td); }); - })();