mirror of https://github.com/certd/certd
perf: 通知支持自定义webhook、anpush、iyuu、server酱
parent
cf7a3e6f70
commit
cbccd9e3d0
|
@ -40,7 +40,7 @@ admin/123456
|
||||||
## 三、如何升级
|
## 三、如何升级
|
||||||
|
|
||||||
### 1. 应用商店安装,直接更新镜像即可
|
### 1. 应用商店安装,直接更新镜像即可
|
||||||
|
`docker`->`容器编排`->`左侧选择Certd-xxxx`->`更新镜像`
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -97,8 +97,8 @@ export abstract class BaseNotification implements INotification {
|
||||||
async onTestRequest() {
|
async onTestRequest() {
|
||||||
await this.send({
|
await this.send({
|
||||||
userId: 0,
|
userId: 0,
|
||||||
title: "测试通知",
|
title: "【Certd】测试通知",
|
||||||
content: "测试通知",
|
content: "测试通知\n\n查看详情:http://www.baidu.com",
|
||||||
pipeline: {
|
pipeline: {
|
||||||
id: 1,
|
id: 1,
|
||||||
title: "测试流水线",
|
title: "测试流水线",
|
||||||
|
|
|
@ -37,11 +37,6 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
editRequest,
|
editRequest,
|
||||||
delRequest
|
delRequest
|
||||||
},
|
},
|
||||||
form: {
|
|
||||||
labelCol: {
|
|
||||||
span: 6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
width: 200
|
width: 200
|
||||||
},
|
},
|
||||||
|
|
|
@ -39,7 +39,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
},
|
},
|
||||||
form: {
|
form: {
|
||||||
labelCol: {
|
labelCol: {
|
||||||
span: 6
|
//固定label宽度
|
||||||
|
span: null,
|
||||||
|
style: {
|
||||||
|
width: "145px"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
|
|
|
@ -58,6 +58,13 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
||||||
form: {
|
form: {
|
||||||
wrapper: {
|
wrapper: {
|
||||||
width: "1050px"
|
width: "1050px"
|
||||||
|
},
|
||||||
|
labelCol: {
|
||||||
|
//固定label宽度
|
||||||
|
span: null,
|
||||||
|
style: {
|
||||||
|
width: "145px"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
rowHandle: {
|
rowHandle: {
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline';
|
||||||
|
|
||||||
|
@IsNotification({
|
||||||
|
name: 'anpush',
|
||||||
|
title: 'AnPush',
|
||||||
|
desc: 'https://anpush.com',
|
||||||
|
})
|
||||||
|
export class AnPushNotification extends BaseNotification {
|
||||||
|
@NotificationInput({
|
||||||
|
title: 'API密钥',
|
||||||
|
component: {
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
helper: '[获取API密钥](https://anpush.com/push/tool) ',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
token = '';
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: '通道ID',
|
||||||
|
component: {
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
helper: '[获取通道ID](https://anpush.com/push/setting)创建通道,复制通道id,填入此处',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
channel = '';
|
||||||
|
|
||||||
|
async send(body: NotificationBody) {
|
||||||
|
if (!this.token) {
|
||||||
|
throw new Error('token不能为空');
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
url: `https://api.anpush.com/push/${this.token}`,
|
||||||
|
method: 'POST',
|
||||||
|
timeout: 0,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
title: body.title,
|
||||||
|
content: body.content,
|
||||||
|
channel: this.channel,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
await this.http.request(config);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,2 +1,6 @@
|
||||||
export * from './qywx/index.js';
|
export * from './qywx/index.js';
|
||||||
export * from './email/index.js';
|
export * from './email/index.js';
|
||||||
|
export * from './iyuu/index.js';
|
||||||
|
export * from './webhook/index.js';
|
||||||
|
export * from './serverchan/index.js';
|
||||||
|
export * from './anpush/index.js';
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline';
|
||||||
|
|
||||||
|
@IsNotification({
|
||||||
|
name: 'iyuu',
|
||||||
|
title: '爱语飞飞微信通知(iyuu)',
|
||||||
|
desc: 'https://iyuu.cn/',
|
||||||
|
})
|
||||||
|
export class IyuuNotification extends BaseNotification {
|
||||||
|
@NotificationInput({
|
||||||
|
title: 'Token令牌',
|
||||||
|
component: {
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
helper: 'https://iyuu.cn/ 微信扫码获取',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
token = '';
|
||||||
|
|
||||||
|
async send(body: NotificationBody) {
|
||||||
|
if (!this.token) {
|
||||||
|
throw new Error('token不能为空');
|
||||||
|
}
|
||||||
|
const res = await this.http.request({
|
||||||
|
url: `https://iyuu.cn/${this.token}.send`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
text: body.title,
|
||||||
|
desp: body.content,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res.errcode !== 0) {
|
||||||
|
throw new Error(res.errmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline';
|
||||||
|
|
||||||
|
@IsNotification({
|
||||||
|
name: 'serverchan',
|
||||||
|
title: 'Server酱',
|
||||||
|
desc: 'https://sct.ftqq.com/',
|
||||||
|
})
|
||||||
|
export class ServerChanNotification extends BaseNotification {
|
||||||
|
@NotificationInput({
|
||||||
|
title: '服务地址',
|
||||||
|
value: 'https://sctapi.ftqq.com',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
endpoint = 'https://sctapi.ftqq.com';
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: 'SendKey',
|
||||||
|
component: {
|
||||||
|
placeholder: 'https://sctapi.ftqq.com/<SENDKEY>.send',
|
||||||
|
},
|
||||||
|
helper: 'https://sct.ftqq.com/ 微信扫码获取',
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
sendKey = '';
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: '消息通道号',
|
||||||
|
component: {
|
||||||
|
placeholder: '9|66',
|
||||||
|
},
|
||||||
|
helper: '可以不填,最多两个通道,[通道配置说明](https://sct.ftqq.com/sendkey)',
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
channel: string;
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: '是否隐藏IP',
|
||||||
|
component: {
|
||||||
|
name: 'a-switch',
|
||||||
|
vModel: 'checked',
|
||||||
|
},
|
||||||
|
required: false,
|
||||||
|
})
|
||||||
|
noip: boolean;
|
||||||
|
|
||||||
|
async send(body: NotificationBody) {
|
||||||
|
if (!this.sendKey) {
|
||||||
|
throw new Error('sendKey不能为空');
|
||||||
|
}
|
||||||
|
await this.http.request({
|
||||||
|
url: `${this.endpoint}/${this.sendKey}.send`,
|
||||||
|
method: 'POST',
|
||||||
|
data: {
|
||||||
|
text: body.title,
|
||||||
|
desp: body.content,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { BaseNotification, IsNotification, NotificationBody, NotificationInput } from '@certd/pipeline';
|
||||||
|
|
||||||
|
@IsNotification({
|
||||||
|
name: 'webhook',
|
||||||
|
title: '自定义webhook',
|
||||||
|
desc: '根据模版自定义http请求',
|
||||||
|
})
|
||||||
|
export class WebhookNotification extends BaseNotification {
|
||||||
|
@NotificationInput({
|
||||||
|
title: 'webhook地址',
|
||||||
|
component: {
|
||||||
|
placeholder: '',
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
webhook = '';
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: '请求方式',
|
||||||
|
value: 'post',
|
||||||
|
component: {
|
||||||
|
name: 'a-select',
|
||||||
|
placeholder: 'post/put',
|
||||||
|
options: [
|
||||||
|
{ value: 'post', label: 'post' },
|
||||||
|
{ value: 'put', label: 'put' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
method = '';
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: 'ContentType',
|
||||||
|
value: 'json',
|
||||||
|
component: {
|
||||||
|
name: 'a-select',
|
||||||
|
options: [
|
||||||
|
{ value: 'application/json', label: 'json' },
|
||||||
|
{ value: 'application/x-www-form-urlencoded', label: 'x-www-form-urlencoded' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
contentType = '';
|
||||||
|
|
||||||
|
@NotificationInput({
|
||||||
|
title: '消息body模版',
|
||||||
|
value: `{
|
||||||
|
title:"{title}",
|
||||||
|
content:"{content}"
|
||||||
|
}`,
|
||||||
|
component: {
|
||||||
|
name: 'a-textarea',
|
||||||
|
rows: 4,
|
||||||
|
},
|
||||||
|
col: {
|
||||||
|
span: 24,
|
||||||
|
},
|
||||||
|
helper: `根据实际的webhook接口,构建一个json对象作为参数,支持{title}和{content}两个变量,变量用{}包裹,字符串需要双引号`,
|
||||||
|
required: true,
|
||||||
|
})
|
||||||
|
template = '';
|
||||||
|
|
||||||
|
async send(body: NotificationBody) {
|
||||||
|
if (!this.template) {
|
||||||
|
throw new Error('模版不能为空');
|
||||||
|
}
|
||||||
|
|
||||||
|
const bodyStr = this.template.replaceAll('{title}', body.title).replaceAll('{content}', body.content);
|
||||||
|
|
||||||
|
const data = JSON.parse(bodyStr);
|
||||||
|
|
||||||
|
await this.http.request({
|
||||||
|
url: this.webhook,
|
||||||
|
method: this.method,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': `${this.contentType}; charset=UTF-8`,
|
||||||
|
},
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue