RemoteDownloader / js /tmpmk.js
VietCat's picture
update tampermonkey file
36f7d1c
// ==UserScript==
// @name YouTube Download Manager
// @namespace https://vietcat.dev/
// @version 1.3
// @description Download YouTube Premium videos via custom Hugging Face API with CSP-safe DOM handling.
// @author vietcat
// @match https://www.youtube.com/watch*
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @connect vietcat-remotedownloader.hf.space
// ==/UserScript==
(function () {
'use strict';
const API_BASE = 'https://vietcat-remotedownloader.hf.space';
const state = {
tasks: [],
cookies: ''
};
function createUI() {
const container = document.createElement('div');
container.id = 'yt-download-popup';
const box = document.createElement('div');
box.style.background = '#202020';
box.style.color = 'white';
box.style.padding = '10px';
box.style.borderRadius = '8px';
box.style.width = '300px';
const cookieToggleBtn = document.createElement('button');
cookieToggleBtn.textContent = '🛠️ Cookie Settings';
cookieToggleBtn.style.marginBottom = '6px';
cookieToggleBtn.style.display = 'block';
const cookieInput = document.createElement('textarea');
cookieInput.placeholder = 'Paste your Netscape-format cookies here';
cookieInput.style.width = '100%';
cookieInput.style.height = '100px';
cookieInput.style.display = 'none';
cookieInput.addEventListener('input', () => {
state.cookies = cookieInput.value.trim();
updateDownloadButtonState();
});
cookieToggleBtn.addEventListener('click', () => {
cookieInput.style.display = cookieInput.style.display === 'none' ? 'block' : 'none';
});
const button = document.createElement('button');
button.id = 'yt-start-download';
button.textContent = '📥 Download Video';
button.style.padding = '6px 12px';
button.style.background = '#ff0000';
button.style.color = 'white';
button.style.border = 'none';
button.style.borderRadius = '5px';
button.style.cursor = 'pointer';
button.disabled = true;
const list = document.createElement('div');
list.id = 'yt-download-list';
list.style.marginTop = '10px';
box.appendChild(cookieToggleBtn);
box.appendChild(cookieInput);
box.appendChild(button);
box.appendChild(list);
container.appendChild(box);
document.body.appendChild(container);
GM_addStyle(`
#yt-download-popup {
position: fixed;
top: 10px;
left: 10px;
z-index: 99999;
}
#yt-download-list .item {
background: #333;
padding: 8px;
border-radius: 6px;
margin-top: 6px;
font-size: 12px;
}
#yt-download-list .item a {
color: #00ffcc;
text-decoration: none;
display: inline-block;
margin-top: 4px;
}
#yt-download-list .item button {
margin-top: 4px;
background: transparent;
color: white;
border: 1px solid #555;
border-radius: 3px;
padding: 2px 6px;
cursor: pointer;
}
`);
button.addEventListener('click', startDownload);
}
function updateDownloadButtonState() {
const btn = document.getElementById('yt-start-download');
btn.disabled = !state.cookies;
}
function updateList() {
const list = document.getElementById('yt-download-list');
while (list.firstChild) list.removeChild(list.firstChild);
state.tasks.forEach(task => {
const el = document.createElement('div');
el.className = 'item';
const title = document.createElement('div');
const strong = document.createElement('strong');
strong.textContent = task.shortUrl;
title.appendChild(strong);
el.appendChild(title);
const status = document.createElement('div');
status.textContent = `Status: ${task.status}`;
el.appendChild(status);
if (task.status === 'done') {
const a = document.createElement('a');
a.href = task.downloadUrl;
a.target = '_blank';
a.download = '';
a.textContent = '⬇️ Download';
el.appendChild(a);
}
const remove = document.createElement('button');
remove.textContent = '❌ Xoá';
remove.addEventListener('click', () => {
state.tasks = state.tasks.filter(t => t.id !== task.id);
updateList();
});
el.appendChild(remove);
list.appendChild(el);
});
}
function startDownload() {
const url = location.href;
const shortUrl = url.split('?')[0].replace('https://www.', '').replace('youtube.com/watch', 'yt');
const taskId = Date.now().toString();
state.tasks.push({ id: taskId, shortUrl, status: 'downloading...', downloadUrl: '' });
updateList();
const encodedCookie = btoa(state.cookies);
GM_xmlhttpRequest({
method: 'POST',
url: `${API_BASE}/download`,
headers: { 'Content-Type': 'application/json' },
data: JSON.stringify({ url, cookie: encodedCookie }),
onload: (response) => {
try {
const json = JSON.parse(response.responseText);
const task = state.tasks.find(t => t.id === taskId);
if (json.download_url) {
task.status = 'done';
task.downloadUrl = `${API_BASE}${json.download_url}`;
} else {
task.status = 'error';
}
} catch (e) {
const task = state.tasks.find(t => t.id === taskId);
if (task) task.status = 'failed';
}
updateList();
},
onerror: () => {
const task = state.tasks.find(t => t.id === taskId);
if (task) task.status = 'error';
updateList();
}
});
}
const waitForReady = setInterval(() => {
if (document.body && !document.getElementById('yt-download-popup')) {
clearInterval(waitForReady);
createUI();
}
}, 1000);
})();