Сократить служебные теги SHiNE и сохранить обратную совместимость

This commit is contained in:
AidarKC
2026-08-12 13:14:23 +04:00
parent 4d80ab639e
commit 8f32e82d14
15 changed files with 144 additions and 86 deletions
+19 -12
View File
@@ -1,7 +1,6 @@
import { buildArweaveDataUrl, validateArweaveTxId, validateSha256Hex } from './arweave-file-service.js';
const ATTACH_PREFIX = '<SHiNE:attach;';
const ATTACH_BLOCK_RE = /^<SHiNE:attach;([^>]*)>\n?/u;
const ATTACH_BLOCK_RE = /^<(?:SHiNE|S):(attach|att);([^>]*)>\n?/u;
export const MAX_MESSAGE_ATTACHMENTS = 10;
const RECENT_UNAVAILABLE_MS = 20 * 60 * 1000;
const IMAGE_EXTENSIONS = new Set(['apng', 'avif', 'bmp', 'gif', 'jpeg', 'jpg', 'png', 'svg', 'webp']);
@@ -33,8 +32,8 @@ function normalizeName(name) {
}
function normalizePreview(input = {}) {
const previewTxId = String(input.previewAr || input.ar || input.txId || '').trim();
const previewSha256Hex = String(input.previewSha256 || input.sha256 || input.sha256Hex || '').trim().toLowerCase();
const previewTxId = String(input.preAr || input.previewAr || input.ar || input.txId || '').trim();
const previewSha256Hex = String(input.preSha256 || input.previewSha256 || input.sha256 || input.sha256Hex || '').trim().toLowerCase();
if (!previewTxId || !previewSha256Hex) return null;
if (!validateArweaveTxId(previewTxId)) return null;
if (!validateSha256Hex(previewSha256Hex)) return null;
@@ -47,9 +46,11 @@ function normalizePreview(input = {}) {
export function normalizeAttachment(input = {}) {
const txId = String(input.ar || input.txId || '').trim();
const sha256Hex = String(input.sha256 || input.sha256Hex || '').trim().toLowerCase();
const size = Number(input.size || input.sizeBytes || 0);
const name = normalizeName(input.name || input.fileName || 'file');
const size = Number(input.sz || input.size || input.sizeBytes || 0);
const name = normalizeName(input.nm || input.name || input.fileName || 'file');
const preview = normalizePreview(input.preview || {
preAr: input.preAr,
preSha256: input.preSha256,
previewAr: input.previewAr,
previewSha256: input.previewSha256,
});
@@ -75,9 +76,9 @@ export function buildAttachmentBlock(attachment) {
const item = normalizeAttachment(attachment);
const encodedName = encodeURIComponent(item.name);
const previewFields = item.preview
? `;previewAr=${item.preview.ar};previewSha256=${item.preview.sha256}`
? `;preAr=${item.preview.ar};preSha256=${item.preview.sha256}`
: '';
return `<SHiNE:attach;v=${item.preview ? 2 : 1};name=${encodedName};size=${item.size};sha256=${item.sha256};ar=${item.ar}${previewFields}>`;
return `<S:att;v=1;nm=${encodedName};sz=${item.size};sha256=${item.sha256};ar=${item.ar}${previewFields}>`;
}
export function composeMessageWithAttachments(text, attachments = []) {
@@ -105,16 +106,22 @@ export function parseMessageAttachments(rawText) {
let rest = String(rawText || '');
const attachments = [];
while (rest.startsWith(ATTACH_PREFIX)) {
while (true) {
const match = rest.match(ATTACH_BLOCK_RE);
if (!match) break;
const fields = parseFields(match[1]);
const fields = parseFields(match[2]);
try {
const version = Number(fields.v || 0);
if (version !== 1 && version !== 2) {
throw new Error('unsupported attachment version');
}
attachments.push(normalizeAttachment({
name: decodeURIComponent(String(fields.name || 'file')),
size: fields.size,
nm: decodeURIComponent(String(fields.nm || fields.name || 'file')),
sz: fields.sz || fields.size,
sha256: fields.sha256,
ar: fields.ar,
preAr: fields.preAr,
preSha256: fields.preSha256,
previewAr: fields.previewAr,
previewSha256: fields.previewSha256,
}));