mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2025-09-08 23:18:43 +00:00
trying to fix some CORS issues
This commit is contained in:
115
src/js/app.js
115
src/js/app.js
@@ -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, don’t 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 we’ve 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;
|
||||||
}
|
}
|
||||||
|
@@ -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 we’re 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();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user