mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-06 12:52:26 +00:00
Add DM attachment upload and preview flow
This commit is contained in:
1 parent
fdf0c185be
commit
9ea9fe2f08
8 files changed
+1309
-87
No files matched your search
@@ -0,0 +1,162 @@
|
||||
import { devLogger } from "../utils/logger.js";
|
||||
|
||||
export const ATTACHMENT_KIND = 15;
|
||||
|
||||
const HEX_64_REGEX = /^[0-9a-f]{64}$/i;
|
||||
|
||||
const TAG_NAMES = Object.freeze({
|
||||
hash: "x",
|
||||
url: "url",
|
||||
name: "name",
|
||||
type: "type",
|
||||
size: "size",
|
||||
key: "k",
|
||||
});
|
||||
|
||||
function normalizeTagValue(value) {
|
||||
if (typeof value !== "string") {
|
||||
if (value === undefined || value === null) {
|
||||
return "";
|
||||
}
|
||||
return String(value);
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
function normalizeHash(value) {
|
||||
const normalized = normalizeTagValue(value).toLowerCase();
|
||||
if (!normalized) {
|
||||
return "";
|
||||
}
|
||||
return HEX_64_REGEX.test(normalized) ? normalized : "";
|
||||
}
|
||||
|
||||
function normalizeNumber(value) {
|
||||
const numeric = Number(value);
|
||||
if (!Number.isFinite(numeric) || numeric < 0) {
|
||||
return null;
|
||||
}
|
||||
return Math.floor(numeric);
|
||||
}
|
||||
|
||||
export function parseAttachmentTags(tags) {
|
||||
if (!Array.isArray(tags)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fields = {
|
||||
x: "",
|
||||
url: "",
|
||||
name: "",
|
||||
type: "",
|
||||
size: null,
|
||||
key: "",
|
||||
};
|
||||
|
||||
tags.forEach((tag) => {
|
||||
if (!Array.isArray(tag) || tag.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
const name = normalizeTagValue(tag[0]).toLowerCase();
|
||||
const value = normalizeTagValue(tag[1]);
|
||||
|
||||
switch (name) {
|
||||
case TAG_NAMES.hash:
|
||||
fields.x = normalizeHash(value);
|
||||
break;
|
||||
case TAG_NAMES.url:
|
||||
fields.url = value;
|
||||
break;
|
||||
case TAG_NAMES.name:
|
||||
fields.name = value;
|
||||
break;
|
||||
case TAG_NAMES.type:
|
||||
fields.type = value;
|
||||
break;
|
||||
case TAG_NAMES.size:
|
||||
fields.size = normalizeNumber(value);
|
||||
break;
|
||||
case TAG_NAMES.key:
|
||||
fields.key = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
if (!fields.x && !fields.url) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
x: fields.x,
|
||||
url: fields.url,
|
||||
name: fields.name,
|
||||
type: fields.type,
|
||||
size: fields.size,
|
||||
key: fields.key,
|
||||
encrypted: Boolean(fields.key),
|
||||
};
|
||||
}
|
||||
|
||||
export function extractAttachmentsFromMessage(message) {
|
||||
if (!message || typeof message !== "object") {
|
||||
return [];
|
||||
}
|
||||
|
||||
const event =
|
||||
(message.message && typeof message.message === "object"
|
||||
? message.message
|
||||
: null) ||
|
||||
(message.event && typeof message.event === "object" ? message.event : null);
|
||||
|
||||
if (!event || Number(event.kind) !== ATTACHMENT_KIND) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const attachment = parseAttachmentTags(event.tags);
|
||||
if (!attachment) {
|
||||
devLogger.warn("[attachments] Attachment event missing tags.");
|
||||
return [];
|
||||
}
|
||||
|
||||
return [attachment];
|
||||
}
|
||||
|
||||
export function formatAttachmentSize(bytes) {
|
||||
if (!Number.isFinite(bytes)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const units = ["B", "KB", "MB", "GB"];
|
||||
let size = Math.max(bytes, 0);
|
||||
let unitIndex = 0;
|
||||
|
||||
while (size >= 1024 && unitIndex < units.length - 1) {
|
||||
size /= 1024;
|
||||
unitIndex += 1;
|
||||
}
|
||||
|
||||
const rounded = size >= 10 || unitIndex === 0 ? Math.round(size) : size.toFixed(1);
|
||||
return `${rounded} ${units[unitIndex]}`;
|
||||
}
|
||||
|
||||
export function describeAttachment(attachment) {
|
||||
if (!attachment || typeof attachment !== "object") {
|
||||
return "Attachment";
|
||||
}
|
||||
|
||||
const name = typeof attachment.name === "string" ? attachment.name.trim() : "";
|
||||
if (name) {
|
||||
return `Attachment: ${name}`;
|
||||
}
|
||||
|
||||
if (attachment.type) {
|
||||
return `Attachment (${attachment.type})`;
|
||||
}
|
||||
|
||||
return "Attachment";
|
||||
}
|
||||
|
||||
export { TAG_NAMES as ATTACHMENT_TAG_NAMES };
|
||||
Reference in new issue
Block a user