VietCat commited on
Commit
36f7d1c
·
1 Parent(s): 58e56a8

update tampermonkey file

Browse files
Files changed (2) hide show
  1. .gitignore +1 -0
  2. js/tmpmk.js +197 -0
.gitignore CHANGED
@@ -5,3 +5,4 @@ __pycache__/
5
  *.log
6
  *.mp4
7
  /tmp/*
 
 
5
  *.log
6
  *.mp4
7
  /tmp/*
8
+ .DS_Store
js/tmpmk.js ADDED
@@ -0,0 +1,197 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // ==UserScript==
2
+ // @name YouTube Download Manager
3
+ // @namespace https://vietcat.dev/
4
+ // @version 1.3
5
+ // @description Download YouTube Premium videos via custom Hugging Face API with CSP-safe DOM handling.
6
+ // @author vietcat
7
+ // @match https://www.youtube.com/watch*
8
+ // @grant GM_xmlhttpRequest
9
+ // @grant GM_addStyle
10
+ // @connect vietcat-remotedownloader.hf.space
11
+ // ==/UserScript==
12
+
13
+ (function () {
14
+ 'use strict';
15
+
16
+ const API_BASE = 'https://vietcat-remotedownloader.hf.space';
17
+ const state = {
18
+ tasks: [],
19
+ cookies: ''
20
+ };
21
+
22
+ function createUI() {
23
+ const container = document.createElement('div');
24
+ container.id = 'yt-download-popup';
25
+
26
+ const box = document.createElement('div');
27
+ box.style.background = '#202020';
28
+ box.style.color = 'white';
29
+ box.style.padding = '10px';
30
+ box.style.borderRadius = '8px';
31
+ box.style.width = '300px';
32
+
33
+ const cookieToggleBtn = document.createElement('button');
34
+ cookieToggleBtn.textContent = '🛠️ Cookie Settings';
35
+ cookieToggleBtn.style.marginBottom = '6px';
36
+ cookieToggleBtn.style.display = 'block';
37
+
38
+ const cookieInput = document.createElement('textarea');
39
+ cookieInput.placeholder = 'Paste your Netscape-format cookies here';
40
+ cookieInput.style.width = '100%';
41
+ cookieInput.style.height = '100px';
42
+ cookieInput.style.display = 'none';
43
+ cookieInput.addEventListener('input', () => {
44
+ state.cookies = cookieInput.value.trim();
45
+ updateDownloadButtonState();
46
+ });
47
+
48
+ cookieToggleBtn.addEventListener('click', () => {
49
+ cookieInput.style.display = cookieInput.style.display === 'none' ? 'block' : 'none';
50
+ });
51
+
52
+ const button = document.createElement('button');
53
+ button.id = 'yt-start-download';
54
+ button.textContent = '📥 Download Video';
55
+ button.style.padding = '6px 12px';
56
+ button.style.background = '#ff0000';
57
+ button.style.color = 'white';
58
+ button.style.border = 'none';
59
+ button.style.borderRadius = '5px';
60
+ button.style.cursor = 'pointer';
61
+ button.disabled = true;
62
+
63
+ const list = document.createElement('div');
64
+ list.id = 'yt-download-list';
65
+ list.style.marginTop = '10px';
66
+
67
+ box.appendChild(cookieToggleBtn);
68
+ box.appendChild(cookieInput);
69
+ box.appendChild(button);
70
+ box.appendChild(list);
71
+ container.appendChild(box);
72
+ document.body.appendChild(container);
73
+
74
+ GM_addStyle(`
75
+ #yt-download-popup {
76
+ position: fixed;
77
+ top: 10px;
78
+ left: 10px;
79
+ z-index: 99999;
80
+ }
81
+ #yt-download-list .item {
82
+ background: #333;
83
+ padding: 8px;
84
+ border-radius: 6px;
85
+ margin-top: 6px;
86
+ font-size: 12px;
87
+ }
88
+ #yt-download-list .item a {
89
+ color: #00ffcc;
90
+ text-decoration: none;
91
+ display: inline-block;
92
+ margin-top: 4px;
93
+ }
94
+ #yt-download-list .item button {
95
+ margin-top: 4px;
96
+ background: transparent;
97
+ color: white;
98
+ border: 1px solid #555;
99
+ border-radius: 3px;
100
+ padding: 2px 6px;
101
+ cursor: pointer;
102
+ }
103
+ `);
104
+
105
+ button.addEventListener('click', startDownload);
106
+ }
107
+
108
+ function updateDownloadButtonState() {
109
+ const btn = document.getElementById('yt-start-download');
110
+ btn.disabled = !state.cookies;
111
+ }
112
+
113
+ function updateList() {
114
+ const list = document.getElementById('yt-download-list');
115
+ while (list.firstChild) list.removeChild(list.firstChild);
116
+
117
+ state.tasks.forEach(task => {
118
+ const el = document.createElement('div');
119
+ el.className = 'item';
120
+
121
+ const title = document.createElement('div');
122
+ const strong = document.createElement('strong');
123
+ strong.textContent = task.shortUrl;
124
+ title.appendChild(strong);
125
+ el.appendChild(title);
126
+
127
+ const status = document.createElement('div');
128
+ status.textContent = `Status: ${task.status}`;
129
+ el.appendChild(status);
130
+
131
+ if (task.status === 'done') {
132
+ const a = document.createElement('a');
133
+ a.href = task.downloadUrl;
134
+ a.target = '_blank';
135
+ a.download = '';
136
+ a.textContent = '⬇️ Download';
137
+ el.appendChild(a);
138
+ }
139
+
140
+ const remove = document.createElement('button');
141
+ remove.textContent = '❌ Xoá';
142
+ remove.addEventListener('click', () => {
143
+ state.tasks = state.tasks.filter(t => t.id !== task.id);
144
+ updateList();
145
+ });
146
+
147
+ el.appendChild(remove);
148
+ list.appendChild(el);
149
+ });
150
+ }
151
+
152
+ function startDownload() {
153
+ const url = location.href;
154
+ const shortUrl = url.split('?')[0].replace('https://www.', '').replace('youtube.com/watch', 'yt');
155
+ const taskId = Date.now().toString();
156
+
157
+ state.tasks.push({ id: taskId, shortUrl, status: 'downloading...', downloadUrl: '' });
158
+ updateList();
159
+
160
+ const encodedCookie = btoa(state.cookies);
161
+
162
+ GM_xmlhttpRequest({
163
+ method: 'POST',
164
+ url: `${API_BASE}/download`,
165
+ headers: { 'Content-Type': 'application/json' },
166
+ data: JSON.stringify({ url, cookie: encodedCookie }),
167
+ onload: (response) => {
168
+ try {
169
+ const json = JSON.parse(response.responseText);
170
+ const task = state.tasks.find(t => t.id === taskId);
171
+ if (json.download_url) {
172
+ task.status = 'done';
173
+ task.downloadUrl = `${API_BASE}${json.download_url}`;
174
+ } else {
175
+ task.status = 'error';
176
+ }
177
+ } catch (e) {
178
+ const task = state.tasks.find(t => t.id === taskId);
179
+ if (task) task.status = 'failed';
180
+ }
181
+ updateList();
182
+ },
183
+ onerror: () => {
184
+ const task = state.tasks.find(t => t.id === taskId);
185
+ if (task) task.status = 'error';
186
+ updateList();
187
+ }
188
+ });
189
+ }
190
+
191
+ const waitForReady = setInterval(() => {
192
+ if (document.body && !document.getElementById('yt-download-popup')) {
193
+ clearInterval(waitForReady);
194
+ createUI();
195
+ }
196
+ }, 1000);
197
+ })();