码桶
发现社区成员的开源项目
parser.ts2.4 KB
export interface ParsedMeeting {
meetingId?: string; // 纯数字会议号 (如 739646719)
dmCode?: string; // 加密短码 (如 KbRZ4JuHSC4B)
dedupHash: string; // 唯一判断 Hash
topic?: string; // 会议主题
rawText: string;
}
export function parseMeetingText(text: string): ParsedMeeting {
const trimmed = text.trim();
// 1. 提取短码 dm 链接: https://meeting.tencent.com/dm/KbRZ4JuHSC4B
const dmMatch = trimmed.match(/meeting\.tencent\.com\/dm\/([a-zA-Z0-9]+)/);
const dmCode = dmMatch ? dmMatch[1] : undefined;
// 2. 提取会议主题
const topicMatch = trimmed.match(/会议主题[::]\s*(.+)/);
const topic = topicMatch ? topicMatch[1].trim() : undefined;
// 3. 提取会议号数字 (如 739-646-719 或 739646719 或 739-646-7190)
// 支持带连字符或无连字符的7-11位数字
let meetingId: string | undefined = undefined;
// 先搜带有 "腾讯会议:" 或 "腾讯会议:" 后面的数字
const taggedMatch = trimmed.match(/(?:#\s*)?腾讯会议[::]?\s*([\d\-\s]+)/);
if (taggedMatch) {
const rawNum = taggedMatch[1].replace(/[\-\s]/g, '');
if (rawNum.length >= 7 && rawNum.length <= 11) {
meetingId = rawNum;
}
}
// 如果没有搜到带标签的,全局正则搜索 7-11 位符合结构的数字
if (!meetingId) {
const numMatches = trimmed.match(/\b\d{3,4}[\-\s]?\d{3,4}[\-\s]?\d{3,4}\b/g);
if (numMatches && numMatches.length > 0) {
// 取第一个看起来像会议号的
const cleaned = numMatches[0].replace(/[\-\s]/g, '');
if (cleaned.length >= 7 && cleaned.length <= 11) {
meetingId = cleaned;
}
}
}
// 如果只有纯数字串输入
if (!meetingId && /^\d[\d\-\s]{5,12}\d$/.test(trimmed)) {
const cleaned = trimmed.replace(/[\-\s]/g, '');
if (cleaned.length >= 7 && cleaned.length <= 11) {
meetingId = cleaned;
}
}
// 计算 Dedup Hash
let dedupHash = '';
if (meetingId) {
dedupHash = `mid:${meetingId}`;
} else if (dmCode) {
dedupHash = `dm:${dmCode}`;
} else {
// 兜底直接使用原文本的简单 Hash
dedupHash = `raw:${simpleHash(trimmed)}`;
}
return {
meetingId,
dmCode,
dedupHash,
topic,
rawText: trimmed,
};
}
function simpleHash(str: string): string {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = (hash << 5) - hash + char;
hash |= 0;
}
return Math.abs(hash).toString(36);
}