Helper script to show downlaod links for ovagames.com
// ==UserScript==
// @name OvaGames Links Extractor
// @namespace https://tampermonkey.net/
// @version 1.1
// @description Helper script to show downlaod links for ovagames.com
// @author pandamoon21
//
// @match https://www.ovagames.com/*
//
// @icon https://www.google.com/s2/favicons?sz=64&domain=ovagames.com
//
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @grant GM_setClipboard
// @run-at document-idle
// @license MIT
// ==/UserScript==
(function() {
'use strict';
// --- CSS STYLES ---
GM_addStyle(`
#ova-panel {
position: fixed; top: 10px; right: 10px; width: 400px; max-height: 90vh;
background: #1e1e2e; color: #cdd6f4; z-index: 100000;
border: 2px solid #a6e3a1; border-radius: 8px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
box-shadow: 0 10px 30px rgba(0,0,0,0.5); display: none;
display: flex; flex-direction: column;
animation: ovaSlideIn 0.3s ease-out;
}
@keyframes ovaSlideIn { from { transform: translateX(20px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
#ova-header {
padding: 12px 15px; background: #11111b; border-bottom: 1px solid #313244;
display: flex; justify-content: space-between; align-items: center;
border-radius: 6px 6px 0 0;
flex-shrink: 0;
}
.ova-header-title { font-weight:bold; color:#fff; font-size: 14px; }
#ova-content { overflow-y: auto; padding: 10px; flex-grow: 1; scrollbar-width: thin; position: relative; }
/* Footer for Global Actions */
#ova-footer {
padding: 10px; background: #11111b; border-top: 1px solid #313244;
display: flex; justify-content: center; gap: 10px;
border-radius: 0 0 6px 6px;
flex-shrink: 0;
}
.ova-section { margin-bottom: 15px; background: #313244; border-radius: 6px; padding: 10px; display: flex; flex-direction: column; }
.ova-section-title { font-weight: bold; color: #f9e2af; font-size: 13px; margin-bottom: 8px; padding-bottom: 5px; border-bottom: 1px solid #45475a; }
.ova-link-row {
display: flex; justify-content: space-between; align-items: center;
padding: 6px; background: #1e1e2e; margin-bottom: 4px; border-radius: 4px;
transition: background 0.2s;
}
.ova-link-row:hover { background: #28283d; }
.ova-link-name { font-size: 12px; font-weight: bold; color: #a6e3a1; }
/* Section Footer (Show/Copy Section) */
.ova-section-footer {
margin-top: 8px; padding-top: 8px; border-top: 1px dashed #45475a;
display: flex; justify-content: flex-end; gap: 8px;
}
/* Buttons */
.ova-actions { display: flex; gap: 5px; }
button { cursor: pointer; border: none; font-family: sans-serif; }
.btn-sm { padding: 4px 10px; border-radius: 4px; font-size: 11px; font-weight: 600; }
.btn-blue { background: #89b4fa; color: #111; }
.btn-blue:hover { background: #b4befe; }
.btn-green { background: #a6e3a1; color: #111; }
.btn-green:hover { background: #94e2d5; }
.btn-action {
padding: 5px 12px; border-radius: 4px; font-size: 11px; font-weight: bold;
background: #45475a; color: #cdd6f4; border: 1px solid #585b70;
}
.btn-action:hover { background: #585b70; color: #fff; }
.btn-global { background: #f38ba8; color: #111; border: none; font-size: 12px; padding: 8px 16px; }
.btn-global:hover { background: #eba0ac; }
/* Text Viewer Overlay */
#ova-viewer {
position: absolute; top: 0; left: 0; right: 0; bottom: 0;
background: #1e1e2e; z-index: 10; display: none; flex-direction: column;
padding: 10px;
}
#ova-viewer textarea {
flex-grow: 1; background: #11111b; color: #a6e3a1; border: 1px solid #45475a;
padding: 10px; font-family: monospace; font-size: 11px; resize: none; margin-bottom: 10px;
white-space: pre; overflow-wrap: normal; overflow-x: scroll;
}
.viewer-controls { display: flex; gap: 10px; }
.viewer-controls button { flex: 1; padding: 8px; border-radius: 4px; font-weight: bold; }
#ova-float-btn {
position: fixed; bottom: 20px; right: 20px;
background: #a6e3a1; color: #111; padding: 12px 20px;
border-radius: 50px; cursor: pointer; font-weight: bold;
box-shadow: 0 4px 10px rgba(0,0,0,0.3); z-index: 99999;
border: none; transition: transform 0.2s;
font-family: sans-serif; font-size: 14px;
}
#ova-float-btn:hover { transform: scale(1.05); }
`);
// --- HELPER FUNCTIONS ---
function cleanName(text) {
return text.replace(/^[•\-\s]+/, '').replace(/[•]/g, '').trim().toUpperCase();
}
// --- MAIN LOGIC ---
function fetchAndExtract() {
const btn = document.getElementById('ova-float-btn');
if(btn) btn.textContent = '⏳ Fetching...';
GM_xmlhttpRequest({
method: 'GET',
url: window.location.href,
onload: function(response) {
const parser = new DOMParser();
const doc = parser.parseFromString(response.responseText, "text/html");
const groups = doc.querySelectorAll('.dl-wraps-item');
const extractedData = [];
groups.forEach(group => {
const titleElement = group.querySelector('b');
const sectionTitle = titleElement ? titleElement.textContent.trim() : "Download Section";
const links = group.querySelectorAll('a[href]');
const linkItems = [];
links.forEach(link => {
const formattedName = cleanName(link.textContent);
if (formattedName && link.href) {
linkItems.push({ name: formattedName, url: link.href });
}
});
if (linkItems.length > 0) {
extractedData.push({ title: sectionTitle, links: linkItems });
}
});
renderPanel(extractedData);
if(btn) btn.textContent = '🔗 Show Links';
}
});
}
function renderPanel(data) {
let panel = document.getElementById('ova-panel');
if (!panel) {
panel = document.createElement('div');
panel.id = 'ova-panel';
document.body.appendChild(panel);
}
let contentHtml = '';
let totalLinks = 0;
if (data.length === 0) {
contentHtml = '<div style="padding:20px; text-align:center; color:#fab387;">No links found.<br><small>Make sure you are on a game post page.</small></div>';
} else {
data.forEach((section, index) => {
totalLinks += section.links.length;
let linksHtml = '';
section.links.forEach(link => {
linksHtml += `
<div class="ova-link-row">
<span class="ova-link-name">${link.name}</span>
<div class="ova-actions">
<button class="btn-sm btn-blue" onclick="window.open('${link.url}', '_blank')">OPEN</button>
<button class="btn-sm btn-green copy-single-btn" data-url="${link.url}">COPY</button>
</div>
</div>`;
});
// Section structure with footer buttons
contentHtml += `
<div class="ova-section">
<div class="ova-section-title">${section.title}</div>
${linksHtml}
<div class="ova-section-footer">
<button class="btn-action copy-section-btn" data-index="${index}">Copy Section</button>
<button class="btn-action show-section-btn" data-index="${index}">Show Links</button>
</div>
</div>`;
});
}
panel.innerHTML = `
<div id="ova-header">
<div class="ova-header-title">Extracted Links (${totalLinks})</div>
<button id="ova-close" style="background:transparent;border:none;color:#fff;cursor:pointer;font-size:16px;">✕</button>
</div>
<div id="ova-content">
${contentHtml}
<div id="ova-viewer">
<textarea id="ova-viewer-text" readonly></textarea>
<div class="viewer-controls">
<button id="ova-viewer-copy" class="btn-green">Copy Text</button>
<button id="ova-viewer-close" class="btn-action">Close</button>
</div>
</div>
</div>
<div id="ova-footer">
<button id="ova-copy-all" class="btn-global">COPY ALL</button>
<button id="ova-show-all" class="btn-global" style="background:#89b4fa;">SHOW ALL LINKS</button>
</div>
`;
// --- Event Listeners ---
document.getElementById('ova-close').onclick = () => panel.style.display = 'none';
// Helper to show the Text Viewer
const showViewer = (text) => {
const viewer = document.getElementById('ova-viewer');
const textArea = document.getElementById('ova-viewer-text');
textArea.value = text;
viewer.style.display = 'flex';
};
// Viewer Controls
document.getElementById('ova-viewer-close').onclick = () => {
document.getElementById('ova-viewer').style.display = 'none';
};
document.getElementById('ova-viewer-copy').onclick = function() {
const text = document.getElementById('ova-viewer-text');
text.select();
GM_setClipboard(text.value);
flashButton(this, 'Copied!');
};
// 1. Single Copy Buttons
panel.querySelectorAll('.copy-single-btn').forEach(btn => {
btn.onclick = function() {
GM_setClipboard(this.dataset.url);
flashButton(this, '✓');
};
});
// 2. Section Actions
panel.querySelectorAll('.copy-section-btn').forEach(btn => {
btn.onclick = function() {
const idx = this.dataset.index;
const txt = data[idx].links.map(l => l.url).join('\n');
GM_setClipboard(txt);
flashButton(this, 'Copied!');
};
});
panel.querySelectorAll('.show-section-btn').forEach(btn => {
btn.onclick = function() {
const idx = this.dataset.index;
const txt = data[idx].links.map(l => l.url).join('\n');
showViewer(txt);
};
});
// 3. Global Actions
const copyAllBtn = document.getElementById('ova-copy-all');
const showAllBtn = document.getElementById('ova-show-all');
if (data.length > 0) {
const allLinksText = data.flatMap(section => section.links.map(l => l.url)).join('\n');
copyAllBtn.onclick = function() {
GM_setClipboard(allLinksText);
flashButton(this, 'DONE!');
};
showAllBtn.onclick = function() {
showViewer(allLinksText);
};
} else {
copyAllBtn.style.display = 'none';
showAllBtn.style.display = 'none';
}
panel.style.display = 'flex';
}
function flashButton(btn, text) {
const originalText = btn.textContent;
btn.textContent = text;
btn.style.opacity = '0.8';
setTimeout(() => {
btn.textContent = originalText;
btn.style.opacity = '1';
}, 1000);
}
function init() {
const btn = document.createElement('button');
btn.id = 'ova-float-btn';
btn.textContent = '🔗 Extract Links';
btn.onclick = function() {
const panel = document.getElementById('ova-panel');
if (panel && panel.innerHTML !== '') {
panel.style.display = panel.style.display === 'none' ? 'flex' : 'none';
} else {
fetchAndExtract();
}
};
document.body.appendChild(btn);
}
init();
})();