Merge branch 'v2' into v2-dev

v2
xiaojunnuo 2025-08-07 10:23:44 +08:00
commit b1b3e39fcd
5 changed files with 144 additions and 2 deletions

View File

@ -14,6 +14,7 @@
},
"scripts": {
"start": "lerna bootstrap --hoist",
"start:server": "cd ./packages/ui/certd-server && npm start",
"devb": "lerna run dev-build",
"i-all": "lerna link && lerna exec npm install ",
"publish": "npm run prepublishOnly2 && lerna publish --force-publish=pro/plus-core --conventional-commits --create-release github && npm run afterpublishOnly && npm run commitAll",

View File

@ -461,7 +461,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
cron = cron.replace("* *", "0 0");
}
if (cron.startsWith("*")) {
cron = cron.replace("*", "0");
cron = cron.replace(/\*/g, "0");
}
const triggerId = trigger.id;
const name = this.buildCronKey(pipelineId, triggerId);

View File

@ -12,3 +12,4 @@ export * from './bark/index.js';
export * from './feishu/index.js';
export * from './dingtalk/index.js';
export * from './vocechat/index.js';
export * from './onebot/index.js';

View File

@ -0,0 +1,140 @@
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from "@certd/pipeline";
import axios from "axios";
/**
* : https://github.com/botuniverse/onebot-11
* : https://ayakasuki.com/
*/
@IsNotification({
name: 'onebot',
title: 'OneBot V11 通知',
desc: '通过动态拼接URL发送 OneBot V11 协议消息',
needPlus: false,
})
export class OneBotNotification extends BaseNotification {
// 基础服务地址(不含路径)
@NotificationInput({
title: '服务地址',
component: {
placeholder: 'http://xxxx.xxxx.xxxx',
},
helper: 'OneBot 服务的基础地址不包含action路径',
required: true,
rules: [
{
validator: (value) => /^https?:\/\/\S+$/.test(value),
message: '请输入有效的HTTP/HTTPS地址'
}
]
})
baseUrl = '';
// 目标类型选择
@NotificationInput({
title: '目标类型',
component: {
name: 'a-select',
options: [
{ value: 'group', label: '群聊' },
{ value: 'private', label: '私聊' },
],
},
required: true,
helper: '选择消息发送的目标类型',
})
targetType = 'group';
// 目标ID配置
@NotificationInput({
title: '目标ID',
component: {
placeholder: '123456789',
},
helper: '群聊ID或用户ID纯数字',
required: true,
rules: [
{
validator: (value) => /^\d+$/.test(value),
message: 'ID必须为纯数字'
}
]
})
targetId = '';
// 鉴权密钥(非必填)
@NotificationInput({
title: '鉴权密钥',
component: {
placeholder: 'xxxxxxxxxx',
},
helper: '(选填)访问API的授权令牌无token时留空',
required: false, // 关键修改点
})
accessToken = '';
// 构建完整请求URL支持无token场景
private buildFullUrl(): string {
const action = this.targetType === 'group'
? 'send_group_msg'
: 'send_private_msg';
let url = `${this.baseUrl}/${action}`;
// 动态添加access_token参数仅当存在时
if (this.accessToken) {
url += `?access_token=${encodeURIComponent(this.accessToken)}`;
}
return url;
}
// 构建消息内容
private buildMessage(body: NotificationBody): string {
return body.title
? `${body.title}\n${body.content}`
: body.content;
}
// 构建请求体(动态字段)
private buildRequestBody(body: NotificationBody): object {
return {
[this.targetType === 'group' ? 'group_id' : 'user_id']: Number(this.targetId),
message: this.buildMessage(body),
auto_escape: false
};
}
// 发送通知主逻辑
async send(body: NotificationBody) {
const fullUrl = this.buildFullUrl();
const requestBody = this.buildRequestBody(body);
try {
console.debug("[ONEBOT] 最终请求URL:", fullUrl);
console.debug("[ONEBOT] 请求体:", JSON.stringify(requestBody));
console.debug("[ONEBOT] 使用Token:", !!this.accessToken); // 明确token使用状态
const response = await axios.post(fullUrl, requestBody, {
timeout: 5000,
headers: {
'Content-Type': 'application/json',
'User-Agent': 'Certd-Notification/1.0'
}
});
// 响应验证(保持不变)
if (response.data?.retcode !== 0) {
throw new Error(`[${response.data.retcode}] ${response.data.message}`);
}
return response.data;
} catch (error) {
console.error('[ONEBOT] 请求失败:', {
url: fullUrl,
tokenUsed: !!this.accessToken, // 记录token使用状态
error: error.response?.data || error.message
});
throw new Error(`OneBot通知发送失败: ${error.message}`);
}
}
}

View File

@ -54,7 +54,7 @@ async function login() {
'redirectTo': 'https://www.51dns.com/domain',
'_token': _token
}
console.log(JSON.stringify(obj, null, 2))
// console.log(JSON.stringify(obj, null, 2)) // Avoid logging sensitive data
const res2 = await instance.request({
url: 'https://www.51dns.com/login',
method: 'post',