haraberget commited on
Commit
a82d576
·
verified ·
1 Parent(s): beb9575

Create bridge.js

Browse files

For autosaving mp4 to 1hit.no from WanGP

Files changed (1) hide show
  1. bridge.js +289 -0
bridge.js ADDED
@@ -0,0 +1,289 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ (() => {
2
+ // Clean up an earlier copy
3
+ window.oneHitBridge?.close?.();
4
+ document.getElementById("onehit-mp4-popup")?.remove();
5
+
6
+ // Remember processed URLs during this browser page session
7
+ const sent = window.__oneHitSent || (window.__oneHitSent = {
8
+ add: new Set(),
9
+ sub: new Set()
10
+ });
11
+
12
+ let currentUrl = "";
13
+ let autoSend = false;
14
+ let busy = false;
15
+ let maximized = false;
16
+
17
+ const popup = document.createElement("div");
18
+ popup.id = "onehit-mp4-popup";
19
+ popup.style.cssText = `
20
+ position:fixed;right:20px;bottom:20px;width:390px;
21
+ z-index:2147483647;background:#17191f;color:white;
22
+ border:1px solid #555;border-radius:10px;
23
+ box-shadow:0 5px 25px #0009;font:13px Arial,sans-serif;
24
+ overflow:hidden;
25
+ `;
26
+
27
+ popup.innerHTML = `
28
+ <div id="oh-head" style="
29
+ display:flex;align-items:center;justify-content:space-between;
30
+ padding:12px;background:#292d38;cursor:move;user-select:none">
31
+ <strong>🎬 1hit MP4 Bridge</strong>
32
+ <div style="display:flex;gap:5px">
33
+ <button id="oh-min">—</button>
34
+ <button id="oh-max">□</button>
35
+ <button id="oh-close">✕</button>
36
+ </div>
37
+ </div>
38
+
39
+ <div id="oh-content" style="padding:14px">
40
+ <div id="oh-status" style="color:#aaa;margin-bottom:8px">
41
+ Looking for MP4 videos...
42
+ </div>
43
+
44
+ <textarea id="oh-url" readonly placeholder="Waiting for MP4..."
45
+ style="box-sizing:border-box;width:100%;height:65px;
46
+ background:#252832;color:white;border:1px solid #555;
47
+ border-radius:5px;padding:8px;resize:vertical"></textarea>
48
+
49
+ <div style="display:flex;align-items:center;gap:10px;margin-top:12px">
50
+ <label style="flex:1">
51
+ Endpoint
52
+ <select id="oh-endpoint" style="
53
+ display:block;width:100%;margin-top:4px;padding:8px;
54
+ background:#252832;color:white;border:1px solid #555;border-radius:5px">
55
+ <option value="add">add.php</option>
56
+ <option value="sub">sub.php</option>
57
+ </select>
58
+ </label>
59
+
60
+ <label style="display:flex;align-items:center;gap:6px;padding-top:17px;cursor:pointer">
61
+ <input id="oh-auto" type="checkbox">
62
+ AUTO SEND
63
+ </label>
64
+ </div>
65
+
66
+ <button id="oh-send" style="
67
+ width:100%;margin-top:12px;padding:10px;
68
+ background:#2863a0;color:white;border:0;border-radius:5px;cursor:pointer">
69
+ Send current MP4
70
+ </button>
71
+
72
+ <div id="oh-count" style="color:#999;margin-top:8px;font-size:11px"></div>
73
+
74
+ <div id="oh-footer" style="
75
+ display:flex;justify-content:space-between;align-items:center;
76
+ flex-wrap:wrap;gap:8px;border-top:1px solid #444;
77
+ margin-top:12px;padding-top:10px;font-size:12px">
78
+ <a href="https://1hit.no/kaggle" target="_blank" rel="noopener"
79
+ style="color:#70b8ff;text-decoration:none">↗ 1hit.no/kaggle</a>
80
+ <a href="https://chatgpt.com" target="_blank" rel="noopener"
81
+ style="color:#aaa;text-decoration:none">Built with ChatGPT ↗</a>
82
+ </div>
83
+ </div>
84
+ `;
85
+
86
+ document.body.appendChild(popup);
87
+
88
+ const $ = id => popup.querySelector("#oh-" + id);
89
+ const status = $("status");
90
+ const urlBox = $("url");
91
+
92
+ function updateUI() {
93
+ const endpoint = $("endpoint").value;
94
+ const done = currentUrl && sent[endpoint].has(currentUrl);
95
+
96
+ $("send").disabled = !currentUrl || done || busy;
97
+ $("send").textContent = done
98
+ ? "Already sent ✓"
99
+ : endpoint === "add" ? "Send to add.php" : "Send to sub.php";
100
+
101
+ $("send").style.opacity = $("send").disabled ? ".5" : "1";
102
+
103
+ $("count").textContent =
104
+ `Remembered: ${sent.add.size} add.php · ${sent.sub.size} sub.php`;
105
+ }
106
+
107
+ async function sendCurrent(automatic = false) {
108
+ const url = currentUrl;
109
+ const endpoint = $("endpoint").value;
110
+
111
+ if (!url || busy || sent[endpoint].has(url)) return;
112
+
113
+ busy = true;
114
+ updateUI();
115
+
116
+ status.textContent = `Sending to ${endpoint}.php...`;
117
+ status.style.color = "#f0c674";
118
+
119
+ try {
120
+ let request;
121
+
122
+ if (endpoint === "add") {
123
+ request = fetch(
124
+ "https://1hit.no/kaggle/add.php/?url=" + encodeURIComponent(url),
125
+ { method: "GET", mode: "no-cors" }
126
+ );
127
+ } else {
128
+ request = fetch("https://1hit.no/kaggle/sub.php", {
129
+ method: "POST",
130
+ mode: "no-cors",
131
+ headers: {
132
+ "Content-Type": "text/plain;charset=UTF-8"
133
+ },
134
+ body: JSON.stringify({
135
+ url,
136
+ client_id: "Wan2GP-Kaggle"
137
+ })
138
+ });
139
+ }
140
+
141
+ await request;
142
+
143
+ // The no-cors response cannot confirm server-side completion.
144
+ sent[endpoint].add(url);
145
+
146
+ status.textContent = automatic
147
+ ? `AUTO: request sent to ${endpoint}.php ✓`
148
+ : `Request sent to ${endpoint}.php ✓`;
149
+
150
+ status.style.color = "#70d99a";
151
+ } catch (error) {
152
+ status.textContent = `Request failed: ${error.message}`;
153
+ status.style.color = "#ff7777";
154
+ } finally {
155
+ busy = false;
156
+ updateUI();
157
+ }
158
+ }
159
+
160
+ function findVideos() {
161
+ const urls = [...document.querySelectorAll("video")]
162
+ .map(v => v.currentSrc || v.src || v.querySelector("source")?.src || "")
163
+ .filter(url =>
164
+ /^https:\/\//i.test(url) &&
165
+ /\.mp4(?:[?#]|$)/i.test(url)
166
+ );
167
+
168
+ const best =
169
+ urls.find(url => url.includes("/gradio_api/file=")) ||
170
+ urls.at(-1);
171
+
172
+ if (best && best !== currentUrl) {
173
+ currentUrl = best;
174
+ urlBox.value = best;
175
+
176
+ status.textContent = "New MP4 detected ✓";
177
+ status.style.color = "#70d99a";
178
+
179
+ updateUI();
180
+
181
+ if (autoSend) sendCurrent(true);
182
+ }
183
+ }
184
+
185
+ // AUTO SEND toggle
186
+ $("auto").onchange = () => {
187
+ autoSend = $("auto").checked;
188
+
189
+ status.textContent = autoSend
190
+ ? "AUTO SEND enabled — scanning every 10 seconds."
191
+ : "AUTO SEND disabled — manual mode.";
192
+
193
+ status.style.color = autoSend ? "#70d99a" : "#aaa";
194
+ };
195
+
196
+ $("endpoint").onchange = updateUI;
197
+ $("send").onclick = () => sendCurrent(false);
198
+
199
+ // Minimize / restore
200
+ $("min").onclick = () => {
201
+ const content = $("content");
202
+ const hidden = content.style.display === "none";
203
+
204
+ content.style.display = hidden ? "block" : "none";
205
+ $("min").textContent = hidden ? "—" : "+";
206
+ };
207
+
208
+ // Maximize / restore
209
+ $("max").onclick = () => {
210
+ maximized = !maximized;
211
+
212
+ if (maximized) {
213
+ popup.dataset.oldStyle = JSON.stringify({
214
+ width: popup.style.width,
215
+ height: popup.style.height,
216
+ top: popup.style.top,
217
+ left: popup.style.left,
218
+ right: popup.style.right,
219
+ bottom: popup.style.bottom,
220
+ borderRadius: popup.style.borderRadius
221
+ });
222
+
223
+ popup.style.width = "min(700px, calc(100vw - 30px))";
224
+ popup.style.height = "min(85vh, 750px)";
225
+ popup.style.top = "50%";
226
+ popup.style.left = "50%";
227
+ popup.style.right = "auto";
228
+ popup.style.bottom = "auto";
229
+ popup.style.transform = "translate(-50%, -50%)";
230
+
231
+ $("content").style.overflow = "auto";
232
+ $("content").style.maxHeight = "calc(85vh - 50px)";
233
+ $("max").textContent = "❐";
234
+ } else {
235
+ const old = JSON.parse(popup.dataset.oldStyle || "{}");
236
+ Object.assign(popup.style, old);
237
+ popup.style.transform = "";
238
+
239
+ $("content").style.maxHeight = "";
240
+ $("max").textContent = "□";
241
+ }
242
+ };
243
+
244
+ // Drag using the header
245
+ let drag = null;
246
+
247
+ $("head").addEventListener("pointerdown", e => {
248
+ if (e.target.closest("button") || maximized) return;
249
+
250
+ const rect = popup.getBoundingClientRect();
251
+
252
+ drag = {
253
+ x: e.clientX - rect.left,
254
+ y: e.clientY - rect.top
255
+ };
256
+
257
+ $("head").setPointerCapture(e.pointerId);
258
+ });
259
+
260
+ $("head").addEventListener("pointermove", e => {
261
+ if (!drag) return;
262
+
263
+ popup.style.left = `${e.clientX - drag.x}px`;
264
+ popup.style.top = `${e.clientY - drag.y}px`;
265
+ popup.style.right = "auto";
266
+ popup.style.bottom = "auto";
267
+ });
268
+
269
+ $("head").addEventListener("pointerup", () => drag = null);
270
+ $("head").addEventListener("pointercancel", () => drag = null);
271
+
272
+ // Scan immediately, then every 10 seconds
273
+ findVideos();
274
+ const timer = setInterval(findVideos, 10000);
275
+
276
+ $("close").onclick = () => {
277
+ clearInterval(timer);
278
+ popup.remove();
279
+ delete window.oneHitBridge;
280
+ };
281
+
282
+ window.oneHitBridge = {
283
+ scan: findVideos,
284
+ close: () => $("close").click(),
285
+ sent
286
+ };
287
+
288
+ updateUI();
289
+ })();