实体解析器 (entity-parser
)
将 Telegram 实体 (entities) 转换为语义 HTML。
我应该在什么时候用这个插件?
最好永远别用!
虽然这个插件可以生成 HTML,但一般而言最好将文本和实体发送回 Telegram。
仅在极少数情况下才需要将实体转换为 HTML,即你需要在 Telegram 之外使用带 Telegram 格式的文本,例如在网站上显示 Telegram 消息。
请参阅 最好不要使用这个包的情况 部分,确认你是不是有类似的问题要解决。
如果你不确定在你的情况下使用此插件是否合适,请随时在我们的 Telegram 群组 中提问。 在大多数情况下,人们会发现他们实际上并不需要这个插件来解决他们的问题!
安装
根据你的运行时或包管理器在终端中运行以下命令:
deno add jsr:@qz/telegram-entities-parser
bunx jsr add @qz/telegram-entities-parser
pnpm dlx jsr add @qz/telegram-entities-parser
yarn dlx jsr add @qz/telegram-entities-parser
npx jsr add @qz/telegram-entities-parser
基本用法
使用此插件非常简单。 这是一个简单的示例:
import { EntitiesParser } from "@qz/telegram-entities-parser";
import type { Message } from "@qz/telegram-entities-parser/types";
// 为了获得更好的性能,请在函数外部创建实例。
const entitiesParser = new EntitiesParser();
const parse = (message: Message) => entitiesParser.parse({ message });
bot.on(":text", (ctx) => {
const html = parse(ctx.msg); // 将文本转换为 HTML 字符串
});
bot.on(":photo", (ctx) => {
const html = parse(ctx.msg); // 将标题转换为 HTML 字符串
});
2
3
4
5
6
7
8
9
10
11
12
13
14
高级用法
自定义输出的 HTML 标签
这个包将实体转换为语义 HTML,尽可能地遵循最佳实践和标准。 但是,提供的输出可能并不总是你所期望的。
为了解决这个问题,你可以使用自己的 renderer
根据规则自定义环绕文本的 HTML 元素。 你可以通过扩展默认的 Renderer
来修改特定规则,或者通过实现 Renderer
来覆盖所有规则。
要扩展现有的 renderer
,请执行以下操作:
import { EntitiesParser, RendererHtml } from "@qz/telegram-entities-parser";
import type {
CommonEntity,
RendererOutput,
} from "@qz/telegram-entities-parser/types";
// 更改粗体类型实体的规则,
// 但保留 `RendererHtml` 定义的其余类型。
class MyRenderer extends RendererHtml {
override bold(
options: { text: string; entity: CommonEntity },
): RendererOutput {
return {
prefix: '<strong class="tg-bold">',
suffix: "</strong>",
};
}
}
const entitiesParser = new EntitiesParser({ renderer: new MyRenderer() });
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
options
参数接受带有 text
和 entity
参数的对象。
text
:当前实体引用的特定文本。entity
:根据实体类型以不同接口表示,例如Common
、Entity Custom
、Emoji Entity Pre
、Entity Text
或Link Entity Text
。 例如,Mention Entity bold
实体符合Common
接口,而Entity text
实体则符合_link Text
接口,因为它包含其他额外属性,例如Link Entity url
。
以下是接口的完整列表以及每种实体类型的输出:
实体类型 | 接口 | 结果 |
---|---|---|
blockquote | Common | <blockquote class |
bold | Common | <b class |
bot | Common | <span class |
cashtag | Common | <span class |
code | Common | <code class |
custom | Custom | <span class |
email | Common | <a class |
expandable | Common | <blockquote class |
hashtag | Common | <span class |
italic | Common | <i class |
mention | Common | <a class |
phone | Common | <a class |
pre | Pre | <pre class 或 <pre class |
spoiler | Common | <span class |
strikethrough | Common | <del class |
text | Text | <a class |
text | Text | <a class 或 <a class |
underline | Common | <span class |
url | Common | <a class |
如果你不确定哪个接口是正确的,请参考 Renderer 或 Renderer
自定义文本清理器
默认情况下,输出文本经过清理,以确保正确呈现 HTML 并防止 XSS 漏洞。
输入 | 输出 |
---|---|
& | & |
< | & |
> | & |
" | & |
' | & |
例如,结果 <b>粗体<
将被清理为 <b>粗体<
。
你可以在实例化 Entities
时指定 text
来覆盖此行为:
- 如果你未指定
text
,它将默认使用Sanitizer sanitizer
作为清理程序。Html - 将值设置为
false
将跳过清理,保持输出文本为原始文本。 不建议这样做,因为它可能会导致渲染不正确,并使你的应用程序容易受到 XSS 攻击。 如果选择此选项,请确保你正确处理输出文本。 - 如果你提供一个函数,它将被用来代替默认清理程序。
const myTextSanitizer: TextSanitizer = (options: TextSanitizerOption): string =>
// 替换危险的字符
options.text.replaceAll(/[&<>"']/, (match) => {
switch (match) {
case "&":
return "&";
case "<":
return "<";
case ">":
return ">";
case '"':
return """;
case "'":
return "'";
default:
return match;
}
});
// 实施清理。
const entitiesParser = new EntitiesParser({ textSanitizer: myTextSanitizer });
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
最好不要使用这个包的情况
如果你遇到的问题和下面列出的问题类似,你可能不需要使用这个包就能解决问题。
复制和转发同一条消息
使用 forward
即可转发任何类型的消息。
你还可以使用 copy
API。该 API 会执行同样的操作,但不包含指向原始消息的链接。 copy
的行为类似于复制消息并将其发送回 Telegram,使其显示为常规消息而不是转发的消息。
bot.on(":text", async (ctx) => {
// 要发送消息的对话的 ID。
const chatId = -946659600;
// 转发当前消息,不包含原始消息的链接。
await ctx.copyMessage(chatId);
// 转发当前消息,包含原始消息的链接。
await ctx.forwardMessage(chatId);
});
2
3
4
5
6
7
8
回复修改了文本格式的消息
你可以轻松使用 HTML、Markdown 或实体 (entities
) 来回复消息。
bot.on(":text", async (ctx) => {
// 使用 HTML 回复
await ctx.reply("<b>bold</b> <i>italic</i>", { parse_mode: "HTML" });
// 使用 Telegram Markdown V2 回复
await ctx.reply("*bold* _italic_", { parse_mode: "MarkdownV2" });
// 使用实体回复
await ctx.reply("bold italic", {
entities: [
{ offset: 0, length: 5, type: "bold" },
{ offset: 5, length: 6, type: "italic" },
],
});
});
2
3
4
5
6
7
8
9
10
11
12
13
使用 parse-mode 获得更好的格式化体验
使用官方 parse
(解析模式) 插件获得更好的格式化消息构建体验。