UNPKG

koishi-plugin-adapter-iirose

Version:
113 lines (97 loc) 4.56 kB
import { h } from 'koishi'; import { IIROSE_Bot } from '../bot/bot'; export async function clearMsg(msg: string, bot: IIROSE_Bot) { // 处理 markdown 元素:移除开头的 `\\\\\\*\n` 前缀 // 处理 markdown 元素:移除开头的 `&#092;&#092;&#092;*\n` (即 \\\*\n) 前缀 // IIROSE 发送的原始消息中,反斜杠被编码为 HTML 实体 msg = msg.replace(/^(?:&#092;){3}\*\n\s*/, ''); // 处理 a 元素:移除开头的反斜杠 msg = msg.replace(/\\(https*:\/\/[\s\S]+)/g, '$1'); // 优先处理历史遗留的图片格式 `[url#e]`,将其转换为裸链接 msg = msg.replace(/\[((https*:\/\/[\s\S]+?\.(png|jpg|jpeg|gif))(#e)*)\]/g, '$1'); async function replaceAsync(str: string, regex: RegExp, asyncFn: (...args: any[]) => Promise<string>) { const promises: Promise<string>[] = []; str.replace(regex, (...args) => { promises.push(asyncFn(...args)); return ''; }); const data = await Promise.all(promises); return str.replace(regex, () => data.shift()!); } // 处理图片 (同步) const imageUrlRegex = /((?:https?:\/\/[\s\S]+?)\.(?:png|jpg|jpeg|gif)(?:#e)?)/g; msg = msg.replace(imageUrlRegex, (match) => { const cleanUrl = match.replace(/#e$/, ''); return h.image(cleanUrl).toString(); }); // 处理音频 (同步) const audioUrlRegex = /((?:https?:\/\/[\s\S]+?)\.weba)/g; msg = msg.replace(audioUrlRegex, (match) => { // 将 .weba 结尾的链接转换为 audio 元素 return h.audio(match).toString(); }); // 处理视频 (同步) const videoUrlRegex = /\[((?:https?:\/\/[\s\S]+?)\.(?:mp4|webm|ogg))\]/g; msg = msg.replace(videoUrlRegex, (match, url) => { // 将 [url.mp4] 格式转换为 video 元素 return h.video(url).toString(); }); // 处理 at-by-name (异步) // 消耗前后空格,但将空格捕获以便在替换时放回 // 匹配一个或多个前导空格,以便在消息开头正确处理 at const atNameRegex = /(\s+)((?:\[\*[\s\S]+?\*\])+)(\s)/g; msg = await replaceAsync(msg, atNameRegex, async (raw, space1, mentionBlock, space2, offset, originalString) => { const name = mentionBlock.slice(2, -2); const isMultiBlock = mentionBlock.lastIndexOf('[*') > 0; const user = await bot.internal.getUserByName(name); // 如果 at 元素位于消息开头(或只由空格开头),则不保留前面的空格 const leadingSpace = (offset === 0 || originalString.substring(0, offset).trim() === '') ? '' : space1; if (user) { return `${leadingSpace}${h('at', { id: user.id, name }).toString()}${space2}`; } else if (isMultiBlock) { return `${leadingSpace}${h('at', { id: 'error', name }).toString()}${space2}`; } return raw; }); // 处理 at-by-id (异步) const atIdRegex = /(\s+)((?:\[@[\s\S]+?@\])+)(\s)/g; msg = await replaceAsync(msg, atIdRegex, async (raw, space1, mentionBlock, space2, offset, originalString) => { const id = mentionBlock.slice(2, -2); const isMultiBlock = mentionBlock.lastIndexOf('[@') > 0; const user = await bot.getUser(id); // 如果 at 元素位于消息开头(或只由空格开头),则不保留前面的空格 const leadingSpace = (offset === 0 || originalString.substring(0, offset).trim() === '') ? '' : space1; if (user) { return `${leadingSpace}${h('at', { id, name: user.name }).toString()}${space2}`; } else if (isMultiBlock) { return `${leadingSpace}${h('at', { id: 'error', name: id }).toString()}${space2}`; } return raw; }); // 处理 sharp 元素(提及频道) const sharpRegex = /(\s+)((?:\[_[\s\S]+?_\])+)(\s)/g; msg = await replaceAsync(msg, sharpRegex, async (raw, space1, mentionBlock, space2, offset, originalString) => { // 如果 sharp 元素位于消息开头(或只由空格开头),则不保留前面的空格 const leadingSpace = (offset === 0 || originalString.substring(0, offset).trim() === '') ? '' : space1; const channelId = mentionBlock.slice(2, -2); // 移除频道ID末尾的下划线 const cleanChannelId = channelId.replace(/_+$/, ''); return `${leadingSpace}${h('sharp', { id: cleanChannelId }).toString()}${space2}`; }); return msg; }