trying to fix some CORS issues

This commit is contained in:
Keep Creating Online
2025-02-03 17:52:11 -05:00
parent f5e3484cbc
commit 6f76711af6
2 changed files with 111 additions and 75 deletions

View File

@@ -700,44 +700,46 @@ class bitvidApp {
async loadVideos() { async loadVideos() {
console.log("Starting loadVideos..."); console.log("Starting loadVideos...");
// 1) If there's an existing subscription, unsubscribe it // If we already have a subscription, dont unsubscribe/resubscribe—
if (this.videoSubscription) { // just update the UI from local cache.
this.videoSubscription.unsub(); if (!this.videoSubscription) {
this.videoSubscription = null; // First-time load: show “Loading...” message
}
// 2) Show "Loading..." message
if (this.videoList) {
this.videoList.innerHTML = `
<p class="text-center text-gray-500">
Loading videos...
</p>`;
}
try {
// 3) Force a bulk fetch
await nostrClient.fetchVideos();
// 4) Instead of reusing the entire fetched array,
// use getActiveVideos() for the final display:
const newestActive = nostrClient.getActiveVideos();
this.renderVideoList(newestActive);
// 5) Subscribe for updates
this.videoSubscription = nostrClient.subscribeVideos((video) => {
// Whenever we get a new or updated event, re-render the newest set:
const activeAll = nostrClient.getActiveVideos();
this.renderVideoList(activeAll);
});
} catch (err) {
console.error("Could not load videos:", err);
this.showError("Could not load videos from relays.");
if (this.videoList) { if (this.videoList) {
this.videoList.innerHTML = ` this.videoList.innerHTML = `
<p class="text-center text-gray-500"> <p class="text-center text-gray-500">
No videos available at this time. Loading videos...
</p>`; </p>`;
} }
// 1) Do a bulk fetch once
try {
await nostrClient.fetchVideos();
} catch (err) {
console.error("Could not load videos initially:", err);
this.showError("Could not load videos from relays.");
if (this.videoList) {
this.videoList.innerHTML = `
<p class="text-center text-gray-500">
No videos available at this time.
</p>`;
}
return;
}
// 2) Render the newest set after the fetch
const newestActive = nostrClient.getActiveVideos();
this.renderVideoList(newestActive);
// 3) Create a single subscription that updates our UI
this.videoSubscription = nostrClient.subscribeVideos(() => {
// Each time a new/updated event arrives, we just re-render from local
const updatedAll = nostrClient.getActiveVideos();
this.renderVideoList(updatedAll);
});
} else {
// If weve already subscribed before, just update from cache
const allCached = nostrClient.getActiveVideos();
this.renderVideoList(allCached);
} }
} }
@@ -1017,26 +1019,27 @@ class bitvidApp {
return; return;
} }
// Look up the video in our subscription map // 1) Check local 'videosMap' or 'nostrClient.getActiveVideos()'
let matchedVideo = Array.from(this.videosMap.values()).find( let matchedVideo = Array.from(this.videosMap.values()).find(
(v) => v.magnet === decodedMagnet (v) => v.magnet === decodedMagnet
); );
// If not found in the map, do a fallback fetch
if (!matchedVideo) { if (!matchedVideo) {
const allVideos = await nostrClient.fetchVideos(); // Instead of forcing a full `fetchVideos()`,
matchedVideo = allVideos.find((v) => v.magnet === decodedMagnet); // try looking in the activeVideos from local cache:
const activeVideos = nostrClient.getActiveVideos();
matchedVideo = activeVideos.find((v) => v.magnet === decodedMagnet);
} }
// If still not found, you can do a single event-based approach or just show an error:
if (!matchedVideo) { if (!matchedVideo) {
this.showError("No matching video found."); this.showError("No matching video found in local cache.");
return; return;
} }
// Update our tracking // Update tracking
this.currentMagnetUri = decodedMagnet; this.currentMagnetUri = decodedMagnet;
// Hand off to the method that already sets modal fields and streams // Delegate to the main method
await this.playVideoByEventId(matchedVideo.id); await this.playVideoByEventId(matchedVideo.id);
} catch (error) { } catch (error) {
console.error("Error in playVideo:", error); console.error("Error in playVideo:", error);
@@ -1465,27 +1468,31 @@ class bitvidApp {
return video; return video;
} }
// 2) Bulk fetch from relays // 2) Already in nostrClient.allEvents?
const allFromBulk = await nostrClient.fetchVideos(); // (assuming nostrClient.allEvents is a Map of id => video)
const fromAll = nostrClient.allEvents.get(eventId);
// 2a) Deduplicate so we only keep newest version per root if (fromAll && !fromAll.deleted) {
const newestPerRoot = dedupeToNewestByRoot(allFromBulk); this.videosMap.set(eventId, fromAll);
return fromAll;
// 2b) Find the requested ID within the deduplicated set
video = newestPerRoot.find((v) => v.id === eventId);
if (video) {
// Store it in our local map, so we can open it instantly next time
this.videosMap.set(video.id, video);
return video;
} }
// 3) Final fallback: direct single-event fetch // 3) Direct single-event fetch (fewer resources than full fetchVideos)
const single = await nostrClient.getEventById(eventId); const single = await nostrClient.getEventById(eventId);
if (single && !single.deleted) { if (single && !single.deleted) {
this.videosMap.set(single.id, single); this.videosMap.set(single.id, single);
return single; return single;
} }
// 4) If you wanted a final fallback, you could do it here:
// But it's typically better to avoid repeated full fetches
// console.log("Falling back to full fetchVideos...");
// const allFetched = await nostrClient.fetchVideos();
// video = allFetched.find(v => v.id === eventId && !v.deleted);
// if (video) {
// this.videosMap.set(video.id, video);
// return video;
// }
// Not found or was deleted // Not found or was deleted
return null; return null;
} }

View File

@@ -7,8 +7,6 @@ export class TorrentClient {
this.client = new WebTorrent(); this.client = new WebTorrent();
this.currentTorrent = null; this.currentTorrent = null;
this.TIMEOUT_DURATION = 60000; // 60 seconds this.TIMEOUT_DURATION = 60000; // 60 seconds
// We remove the “statsInterval” since were not using it here anymore
// this.statsInterval = null;
} }
log(msg) { log(msg) {
@@ -43,6 +41,7 @@ export class TorrentClient {
return false; return false;
}; };
// Check if already active
if (checkActivation()) return; if (checkActivation()) return;
registration.addEventListener("activate", () => { registration.addEventListener("activate", () => {
@@ -60,6 +59,9 @@ export class TorrentClient {
}); });
} }
// --------------------------
// UPDATED: setupServiceWorker
// --------------------------
async setupServiceWorker() { async setupServiceWorker() {
try { try {
const isBraveBrowser = await this.isBrave(); const isBraveBrowser = await this.isBrave();
@@ -83,6 +85,7 @@ export class TorrentClient {
throw new Error("Please enable WebRTC in Brave Shield settings"); throw new Error("Please enable WebRTC in Brave Shield settings");
} }
// Unregister any existing SW
const registrations = await navigator.serviceWorker.getRegistrations(); const registrations = await navigator.serviceWorker.getRegistrations();
for (const registration of registrations) { for (const registration of registrations) {
await registration.unregister(); await registration.unregister();
@@ -90,17 +93,13 @@ export class TorrentClient {
await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, 1000));
} }
const currentPath = window.location.pathname; // Directly register sw.min.js at /src/sw.min.js
const basePath = currentPath.substring( // with a scope that covers /src/ (which includes /src/webtorrent).
0, this.log("Registering service worker at /src/sw.min.js...");
currentPath.lastIndexOf("/") + 1
);
this.log("Registering service worker...");
const registration = await navigator.serviceWorker.register( const registration = await navigator.serviceWorker.register(
"./sw.min.js", "/src/sw.min.js",
{ {
scope: basePath, scope: "/src/",
updateViaCache: "none", updateViaCache: "none",
} }
); );
@@ -129,6 +128,7 @@ export class TorrentClient {
await this.waitForServiceWorkerActivation(registration); await this.waitForServiceWorkerActivation(registration);
this.log("Service worker activated"); this.log("Service worker activated");
// Make sure the SW is fully ready
const readyRegistration = await Promise.race([ const readyRegistration = await Promise.race([
navigator.serviceWorker.ready, navigator.serviceWorker.ready,
new Promise((_, reject) => new Promise((_, reject) =>
@@ -171,8 +171,14 @@ export class TorrentClient {
throw new Error("Service worker setup failed"); throw new Error("Service worker setup failed");
} }
// 2) Create WebTorrent server // ------------------------------------------------
this.client.createServer({ controller: registration }); // UPDATED: Pass pathPrefix to createServer
// so that it uses /src/webtorrent/... for streaming
// ------------------------------------------------
this.client.createServer({
controller: registration,
pathPrefix: "/src/webtorrent",
});
this.log("WebTorrent server created"); this.log("WebTorrent server created");
const isFirefoxBrowser = this.isFirefox(); const isFirefoxBrowser = this.isFirefox();
@@ -202,11 +208,37 @@ export class TorrentClient {
} }
} }
// Minimal handleChromeTorrent — no internal setInterval // Minimal handleChromeTorrent
handleChromeTorrent(torrent, videoElement, resolve, reject) { handleChromeTorrent(torrent, videoElement, resolve, reject) {
const file = torrent.files.find((f) => // OPTIONAL: Listen for “warning” events
/\.(mp4|webm|mkv)$/.test(f.name.toLowerCase()) torrent.on("warning", (err) => {
); if (err && typeof err.message === "string") {
if (
err.message.includes("CORS") ||
err.message.includes("Access-Control-Allow-Origin")
) {
console.warn(
"CORS warning detected. Attempting to remove the failing webseed/tracker."
);
// Example cleanup approach...
if (torrent._opts?.urlList?.length) {
torrent._opts.urlList = torrent._opts.urlList.filter((url) => {
return !url.includes("distribution.bbb3d.renderfarming.net");
});
console.warn("Cleaned up webseeds =>", torrent._opts.urlList);
}
if (torrent._opts?.announce?.length) {
torrent._opts.announce = torrent._opts.announce.filter((url) => {
return !url.includes("fastcast.nz");
});
console.warn("Cleaned up trackers =>", torrent._opts.announce);
}
}
}
});
// Then proceed with normal file selection
const file = torrent.files.find((f) => /\.(mp4|webm|mkv)$/i.test(f.name));
if (!file) { if (!file) {
return reject(new Error("No compatible video file found in torrent")); return reject(new Error("No compatible video file found in torrent"));
} }
@@ -215,7 +247,7 @@ export class TorrentClient {
videoElement.muted = true; videoElement.muted = true;
videoElement.crossOrigin = "anonymous"; videoElement.crossOrigin = "anonymous";
// Catch video errors // Catch video-level errors
videoElement.addEventListener("error", (e) => { videoElement.addEventListener("error", (e) => {
this.log("Video error:", e.target.error); this.log("Video error:", e.target.error);
}); });
@@ -227,7 +259,6 @@ export class TorrentClient {
}); });
}); });
// Actually stream
try { try {
file.streamTo(videoElement); file.streamTo(videoElement);
this.currentTorrent = torrent; this.currentTorrent = torrent;
@@ -237,7 +268,6 @@ export class TorrentClient {
reject(err); reject(err);
} }
// Also handle torrent error events
torrent.on("error", (err) => { torrent.on("error", (err) => {
this.log("Torrent error (Chrome path):", err); this.log("Torrent error (Chrome path):", err);
reject(err); reject(err);
@@ -286,7 +316,6 @@ export class TorrentClient {
*/ */
async cleanup() { async cleanup() {
try { try {
// No local interval to clear here
if (this.currentTorrent) { if (this.currentTorrent) {
this.currentTorrent.destroy(); this.currentTorrent.destroy();
} }