30 lines
1011 B
TypeScript
30 lines
1011 B
TypeScript
import type { LinkError } from './channelLink';
|
|
|
|
/** 便捷分享的访客链接:`/s/{id}#k={K}`。分享始终是加密模式,没有所有者链接(完成时已丢弃) */
|
|
export interface ParsedShareLink {
|
|
id: string;
|
|
/** 解密密钥 K,只放内存 */
|
|
key: string;
|
|
}
|
|
|
|
export type ShareLinkResult = { ok: true; link: ParsedShareLink } | { ok: false; error: LinkError };
|
|
|
|
const ID_RE = /^[A-Za-z0-9_-]{22}$/;
|
|
const KEY_RE = /^[A-Za-z0-9_-]{43}$/;
|
|
|
|
export function parseShareLink(input: string): ShareLinkResult {
|
|
let url: URL;
|
|
try {
|
|
url = new URL(input.trim());
|
|
} catch {
|
|
return { ok: false, error: 'bad_url' };
|
|
}
|
|
const m = /^\/s\/([^/]+)\/?$/.exec(url.pathname);
|
|
if (!m?.[1]) return { ok: false, error: 'bad_url' };
|
|
if (!ID_RE.test(m[1])) return { ok: false, error: 'bad_id' };
|
|
|
|
const key = new URLSearchParams(url.hash.replace(/^#/, '')).get('k');
|
|
if (key === null || !KEY_RE.test(key)) return { ok: false, error: 'bad_key' };
|
|
return { ok: true, link: { id: m[1], key } };
|
|
}
|