ai-chatbot/lib/storage/retired-storage.ts

40 lines
1.8 KiB
TypeScript

/** Permanently decommissioned storage. Historical records remain for reference. */
export const RETIRED_STORAGE_URL_PATTERN = '^https?://s3[.]1080p[.]hk([/:?#]|$)';
export const RETIRED_STORAGE_MESSAGE = '旧存储已停用,源文件已无法恢复,请重新上传。';
export function normalizeLegacyAliyunStorageUrl(value: string | null | undefined): string | null {
if (!value) return null;
try {
let url = new URL(value, 'https://local.invalid');
if (url.pathname === '/api/image-proxy' || url.pathname === '/api/canvas/3d/model-proxy') {
url = new URL(url.searchParams.get('url') || '');
}
if (url.hostname !== 'demo-sparkai.oss-cn-shanghai.aliyuncs.com') return null;
url.protocol = 'https:';
url.hash = '';
for (const name of ['Signature', 'OSSAccessKeyId', 'Expires', 'security-token']) url.searchParams.delete(name);
url.searchParams.sort();
return url.toString();
} catch { return null; }
}
export function isLegacyAliyunStorageConfig(config: { bucket?: string | null; endpoint?: string | null; publicUrl?: string | null }): boolean {
if (normalizeLegacyAliyunStorageUrl(config.publicUrl)) return true;
try {
return config.bucket === 'demo-sparkai' && new URL(config.endpoint || '').hostname.endsWith('.aliyuncs.com');
} catch { return false; }
}
export function isRetiredStorageUrl(value: string | null | undefined): boolean {
if (!value) return false;
try {
const url = new URL(value, 'https://local.invalid');
if (url.hostname === 's3.1080p.hk') return true;
if (url.pathname === '/api/image-proxy' || url.pathname === '/api/canvas/3d/model-proxy') {
const source = url.searchParams.get('url');
return Boolean(source && new URL(source).hostname === 's3.1080p.hk');
}
} catch { /* Relative local assets and non-URL values are not retired storage. */ }
return false;
}