mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-10-27 07:52:24 +00:00
Guard upload when info hash is unavailable
This commit is contained in:
1 parent
f52da2581b
commit
a3374f0569
3 files changed
+66
-11
No files matched your search
@@ -209,12 +209,12 @@
|
||||
<div class="space-y-2">
|
||||
<label for="input-url" class="block text-sm font-medium text-text">Video URL</label>
|
||||
<input id="input-url" type="url" class="input" placeholder="https://example.com/video.mp4" />
|
||||
<p class="text-xs text-muted">Direct link to a hosted video file.</p>
|
||||
<p class="text-xs text-muted">Primary hosted video source (URL-first playback).</p>
|
||||
</div>
|
||||
<div class="space-y-2">
|
||||
<label for="input-magnet" class="block text-sm font-medium text-text">Magnet Link</label>
|
||||
<input id="input-magnet" type="text" class="input" placeholder="magnet:?xt=urn:btih:..." />
|
||||
<p class="text-xs text-muted">Optional P2P fallback or primary source.</p>
|
||||
<p class="text-xs text-muted">Optional WebTorrent fallback when the URL is unavailable.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -31,6 +31,15 @@ import {
|
||||
} from "./videoNotePayload.js";
|
||||
|
||||
const STATUS_VARIANTS = new Set(["info", "success", "error", "warning"]);
|
||||
const INFO_HASH_PATTERN = /^[a-f0-9]{40}$/;
|
||||
|
||||
function normalizeInfoHash(value) {
|
||||
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
||||
}
|
||||
|
||||
function isValidInfoHash(value) {
|
||||
return INFO_HASH_PATTERN.test(value);
|
||||
}
|
||||
|
||||
function createDefaultSettings() {
|
||||
return {
|
||||
@@ -187,10 +196,10 @@ class R2Service {
|
||||
primaryVariant.m = mimeType;
|
||||
}
|
||||
|
||||
const normalizedHash =
|
||||
typeof infoHash === "string" ? infoHash.trim().toLowerCase() : "";
|
||||
const normalizedHash = normalizeInfoHash(infoHash);
|
||||
if (
|
||||
normalizedHash &&
|
||||
isValidInfoHash(normalizedHash) &&
|
||||
(!primaryVariant.x || !String(primaryVariant.x).trim())
|
||||
) {
|
||||
primaryVariant.x = normalizedHash;
|
||||
@@ -705,14 +714,27 @@ class R2Service {
|
||||
} else {
|
||||
// Construct the Magnet Link
|
||||
// magnet:?xt=urn:btih:<infoHash>&dn=<filename>&ws=<publicUrl>
|
||||
const normalizedInfoHash = normalizeInfoHash(infoHash);
|
||||
const hasValidInfoHash = isValidInfoHash(normalizedInfoHash);
|
||||
let generatedMagnet = "";
|
||||
let generatedWs = "";
|
||||
|
||||
if (infoHash) {
|
||||
const encodedDn = encodeURIComponent(file.name);
|
||||
const encodedWs = encodeURIComponent(publicUrl);
|
||||
generatedMagnet = `magnet:?xt=urn:btih:${infoHash}&dn=${encodedDn}&ws=${encodedWs}`;
|
||||
generatedWs = publicUrl;
|
||||
if (hasValidInfoHash) {
|
||||
const encodedDn = encodeURIComponent(file.name);
|
||||
const encodedWs = encodeURIComponent(publicUrl);
|
||||
generatedMagnet = `magnet:?xt=urn:btih:${normalizedInfoHash}&dn=${encodedDn}&ws=${encodedWs}`;
|
||||
generatedWs = publicUrl;
|
||||
} else {
|
||||
if (infoHash) {
|
||||
userLogger.warn(
|
||||
"Invalid info hash provided. Skipping magnet and webseed generation.",
|
||||
infoHash
|
||||
);
|
||||
}
|
||||
this.setCloudflareUploadStatus(
|
||||
"Info hash missing or invalid. Publishing URL-first without WebTorrent fallback.",
|
||||
"warning"
|
||||
);
|
||||
}
|
||||
|
||||
const rawVideoPayload = {
|
||||
@@ -731,7 +753,7 @@ class R2Service {
|
||||
const mergedNip71 = this.buildNip71MetadataForUpload(metadata?.nip71, {
|
||||
publicUrl,
|
||||
file,
|
||||
infoHash,
|
||||
infoHash: hasValidInfoHash ? normalizedInfoHash : "",
|
||||
});
|
||||
if (mergedNip71 && Object.keys(mergedNip71).length) {
|
||||
rawVideoPayload.nip71 = mergedNip71;
|
||||
|
||||
@@ -10,6 +10,16 @@ import {
|
||||
import { createTorrentMetadata } from "../../utils/torrentHash.js";
|
||||
import { sanitizeBucketName } from "../../storage/r2-mgmt.js";
|
||||
|
||||
const INFO_HASH_PATTERN = /^[a-f0-9]{40}$/;
|
||||
|
||||
function normalizeInfoHash(value) {
|
||||
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
||||
}
|
||||
|
||||
function isValidInfoHash(value) {
|
||||
return INFO_HASH_PATTERN.test(value);
|
||||
}
|
||||
|
||||
export class UploadModal {
|
||||
constructor({
|
||||
authService,
|
||||
@@ -671,6 +681,29 @@ export class UploadModal {
|
||||
userLogger.warn("Failed to calculate info hash:", hashErr);
|
||||
}
|
||||
|
||||
const normalizedInfoHash = normalizeInfoHash(infoHash);
|
||||
const hasValidInfoHash = isValidInfoHash(normalizedInfoHash);
|
||||
|
||||
if (!hasValidInfoHash) {
|
||||
const proceed = confirm(
|
||||
"We couldn't calculate a valid info hash. Publishing will continue with URL-first playback only, and WebTorrent fallback will be unavailable. Continue?"
|
||||
);
|
||||
if (!proceed) {
|
||||
this.updateUploadStatus(
|
||||
"Upload canceled. A valid info hash is required for WebTorrent fallback.",
|
||||
"warning"
|
||||
);
|
||||
this.isUploading = false;
|
||||
this.submitButton.disabled = false;
|
||||
this.updateProgress(null);
|
||||
return;
|
||||
}
|
||||
this.updateUploadStatus(
|
||||
"Continuing without WebTorrent fallback (info hash unavailable).",
|
||||
"warning"
|
||||
);
|
||||
}
|
||||
|
||||
// 2. Upload
|
||||
await this.r2Service.uploadVideo({
|
||||
npub,
|
||||
@@ -678,7 +711,7 @@ export class UploadModal {
|
||||
thumbnailFile,
|
||||
torrentFile,
|
||||
metadata,
|
||||
infoHash,
|
||||
infoHash: hasValidInfoHash ? normalizedInfoHash : "",
|
||||
settingsInput: this.collectSettingsForm(),
|
||||
publishVideoNote: this.publishVideoNote,
|
||||
onReset: () => this.resetForm(),
|
||||
|
||||
Reference in new issue
Block a user