fix: 修复telegram - 符号转义问题

This commit is contained in:
xiaojunnuo
2026-07-02 22:54:24 +08:00
parent b35e7b0702
commit d5882f16be
6 changed files with 134 additions and 40 deletions
@@ -310,27 +310,27 @@ export class RuntimeDepsService {
});
}
async importRuntime(specifier: string,logger?:ILogger) {
async importRuntime(specifier: string, logger?: ILogger) {
if (this.isNativeImportSpecifier(specifier)) {
return await import(specifier);
}
const resolved = await this.resolveImportSpecifier(specifier,logger);
const resolved = await this.resolveImportSpecifier(specifier, logger);
return await import(pathToFileURL(resolved).href);
}
private async resolveImportSpecifier(specifier: string,logger?:ILogger) {
private async resolveImportSpecifier(specifier: string, logger?: ILogger) {
try {
return this.resolveRuntimeSpecifier(specifier).resolved;
} catch (runtimeError: any) {
if (!this.isModuleNotFoundError(runtimeError)) {
throw runtimeError;
}
return await this.resolveMissingRuntimeSpecifier(specifier, runtimeError,logger);
return await this.resolveMissingRuntimeSpecifier(specifier, runtimeError, logger);
}
}
private async resolveMissingRuntimeSpecifier(specifier: string, runtimeError: any,logger?:ILogger) {
private async resolveMissingRuntimeSpecifier(specifier: string, runtimeError: any, logger?: ILogger) {
const packageName = this.parsePackageName(specifier);
const lazyRange = this.lazyDependencies?.[packageName];
if (!lazyRange) {
@@ -341,7 +341,7 @@ export class RuntimeDepsService {
}
}
try {
await this.ensureLazyDependency(packageName,logger);
await this.ensureLazyDependency(packageName, logger);
return this.resolveRuntimeSpecifier(specifier).resolved;
} catch (lazyError: any) {
return this.resolveProjectSpecifier(specifier, lazyError).resolved;
@@ -392,7 +392,7 @@ export class RuntimeDepsService {
return parts[0];
}
private async ensureLazyDependency(packageName: string,logger?:ILogger) {
private async ensureLazyDependency(packageName: string, logger?: ILogger) {
const range = this.lazyDependencies?.[packageName];
if (!range) {
throw new Error(`动态依赖未安装且未配置懒加载版本: ${packageName}`);
@@ -400,7 +400,7 @@ export class RuntimeDepsService {
const dependencies = {
[packageName]: range,
};
await this.ensureDependencies({ dependencies,logger });
await this.ensureDependencies({ dependencies, logger });
}
private isModuleNotFoundError(error: any) {
@@ -444,7 +444,7 @@ export class RuntimeDepsService {
let [pluginType, subtype, name] = parts;
if (parts.length === 2) {
name = subtype;
}else if (parts.length === 3) {
} else if (parts.length === 3) {
//无修改
} else {
const ownerName = owner?.name || pluginKey;
@@ -131,7 +131,7 @@ export class RoleService extends BaseService<RoleEntity> {
async delete(id: any) {
const idArr = this.resolveIdArr(id);
//@ts-ignore
const urs:any = await this.userRoleService.find({ where: { roleId: In(idArr) } });
const urs: any = await this.userRoleService.find({ where: { roleId: In(idArr) } });
if (urs.length > 0) {
throw new Error("该角色已被用户使用,无法删除");
}
@@ -54,13 +54,7 @@ export class AsiaIspClient {
/**
* 生成 HMAC-SHA1 签名,结果做 URL-safe Base64(替换 + → -/ → _
*/
private buildSignature(opts: {
body?: any;
method: string;
nonce: string;
queryString: string;
timestamp: string;
}): string {
private buildSignature(opts: { body?: any; method: string; nonce: string; queryString: string; timestamp: string }): string {
const { body, method, nonce, queryString, timestamp } = opts;
const sk = this.config.accessKeySecret;
@@ -71,13 +65,7 @@ export class AsiaIspClient {
pieces.push(`body=${JSON.stringify(body)}`);
}
pieces.push(
`method=${method}`,
`nonce=${nonce}`,
`queryString=${queryString}`,
`timestamp=${timestamp}`,
`uri=${URI}`
);
pieces.push(`method=${method}`, `nonce=${nonce}`, `queryString=${queryString}`, `timestamp=${timestamp}`, `uri=${URI}`);
const message = pieces.join("&");
const hmac = crypto.createHmac("sha1", sk).update(message).digest("base64");
@@ -88,11 +76,7 @@ export class AsiaIspClient {
/**
* 通用 API 请求(完全对齐 Python 实现)
*/
async doRequest(req: {
method: string;
action: string;
data?: any;
}): Promise<any> {
async doRequest(req: { method: string; action: string; data?: any }): Promise<any> {
const { method, action, data } = req;
const nonce = String(Math.floor(Math.random() * 90000000) + 10000000);
const timestamp = Date.now().toString();
@@ -205,9 +189,8 @@ export class AsiaIspClient {
return certId;
} catch (e: any) {
const msg = e.message || "";
const isExists = msg.includes("Certificate already exists") || e.code ==='80003' ||
msg.includes("Certificate note name already exists") || e.code ==='80010'
//返回数据: {"code":"80010","msg":"Certificate note name already exists","data":null}
const isExists = msg.includes("Certificate already exists") || e.code === "80003" || msg.includes("Certificate note name already exists") || e.code === "80010";
//返回数据: {"code":"80010","msg":"Certificate note name already exists","data":null}
if (!isExists) {
throw e;
}
@@ -240,11 +223,7 @@ export class AsiaIspClient {
* 部署证书到 CDN 域名(修改域名配置,绑定证书)
* PUT /openapi/v3/stat?action=domainModify
*/
async deployCertToDomain(req: {
domain: string;
certId: number;
protocol: string;
}): Promise<void> {
async deployCertToDomain(req: { domain: string; certId: number; protocol: string }): Promise<void> {
await this.doRequest({
method: "PUT",
action: "domainModify",
@@ -256,4 +235,4 @@ export class AsiaIspClient {
});
this.logger.info(`部署证书到域名成功: ${req.domain}, certId=${req.certId}`);
}
}
}
@@ -0,0 +1,115 @@
/// <reference types="mocha" />
/// <reference types="node" />
import assert from "node:assert/strict";
import { TelegramNotification } from "./index.js";
describe("TelegramNotification.replaceText", () => {
let notification: TelegramNotification;
beforeEach(() => {
notification = new TelegramNotification();
});
it("转义横杠字符 -", () => {
const result = notification.replaceText("defense-gameliti-one");
assert.equal(result, "defense\\-gameliti\\-one");
});
it("转义下划线 _", () => {
const result = notification.replaceText("hello_world");
assert.equal(result, "hello\\_world");
});
it("转义星号 *", () => {
const result = notification.replaceText("*bold text*");
assert.equal(result, "\\*bold text\\*");
});
it("转义方括号 []", () => {
const result = notification.replaceText("[link]");
assert.equal(result, "\\[link\\]");
});
it("转义圆括号 ()", () => {
const result = notification.replaceText("(url)");
assert.equal(result, "\\(url\\)");
});
it("转义波浪号 ~", () => {
const result = notification.replaceText("~strike~");
assert.equal(result, "\\~strike\\~");
});
it("转义反引号 `", () => {
const result = notification.replaceText("`code`");
assert.equal(result, "\\`code\\`");
});
it("转义大于号 >", () => {
const result = notification.replaceText(">quote");
assert.equal(result, "\\>quote");
});
it("转义井号 #", () => {
const result = notification.replaceText("#hashtag");
assert.equal(result, "\\#hashtag");
});
it("转义加号 +", () => {
const result = notification.replaceText("+1");
assert.equal(result, "\\+1");
});
it("转义等号 =", () => {
const result = notification.replaceText("a=b");
assert.equal(result, "a\\=b");
});
it("转义竖线 |", () => {
const result = notification.replaceText("a|b");
assert.equal(result, "a\\|b");
});
it("转义花括号 {}", () => {
const result = notification.replaceText("{key: value}");
assert.equal(result, "\\{key: value\\}");
});
it("转义点号 .", () => {
const result = notification.replaceText("example.com");
assert.equal(result, "example\\.com");
});
it("转义感叹号 !", () => {
const result = notification.replaceText("!important");
assert.equal(result, "\\!important");
});
it("转义反斜杠 \\", () => {
const result = notification.replaceText("path\\to\\file");
assert.equal(result, "path\\\\to\\\\file");
});
it("普通文本不做修改", () => {
const result = notification.replaceText("Hello World 123");
assert.equal(result, "Hello World 123");
});
it("空字符串返回空字符串", () => {
const result = notification.replaceText("");
assert.equal(result, "");
});
it("混合多种特殊字符全部正确转义", () => {
const input = "_*[]()~`>#+-=|{}.!\\";
const result = notification.replaceText(input);
assert.equal(result, "\\_\\*\\[\\]\\(\\)\\~\\`\\>\\#\\+\\-\\=\\|\\{\\}\\.\\!\\\\");
});
it("域名中的点号和横杠都被转义", () => {
const result = notification.replaceText("sub-domain.example.com");
assert.equal(result, "sub\\-domain\\.example\\.com");
});
});
@@ -60,7 +60,7 @@ export class TelegramNotification extends BaseNotification {
replaceText(text: string) {
// .*()<> 等都需要用\\进行替换
return text.replace(/[_*[\]()~`>#\+\-=|{}.!]/g, "\\$&");
return text.replace(/[_*[\]()~`>#+\-=|{}.!\\]/g, "\\$&");
// .replace(/([\\_*`|!.[\](){}>+#=~-])/gm, '\\$1')
// return text.replace(/[\\.*()<>]/g, '\\$&');
}
@@ -121,4 +121,4 @@ export class BaotaAutoDeploySiteCert extends AbstractPlusTaskPlugin {
};
}
}
new BaotaAutoDeploySiteCert();
new BaotaAutoDeploySiteCert();