From 7463ca4b19f4757e41302640f740f4d71994a348 Mon Sep 17 00:00:00 2001 From: CaoMeiYouRen <996881204@qq.com> Date: Sat, 9 Nov 2024 18:20:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=20=E9=92=89?= =?UTF-8?q?=E9=92=89=E6=9C=BA=E5=99=A8=E4=BA=BA=E6=8E=A8=E9=80=81=20?= =?UTF-8?q?=E7=9A=84=E7=B1=BB=E5=9E=8B=E5=A3=B0=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- examples/01-example.ts | 4 +- src/push/dingtalk.ts | 73 ++++++++++++++++++++++++++------ src/push/dingtalk/Markdown.ts | 53 ++++++++--------------- src/push/dingtalk/Text.ts | 40 +++++++---------- src/push/dingtalk/action-card.ts | 38 +++++++++++++++++ src/push/dingtalk/feed-card.ts | 19 +++++++++ src/push/dingtalk/link.ts | 17 ++++++++ src/push/dingtalk/template.ts | 68 ----------------------------- src/push/wechat-app.ts | 2 +- 10 files changed, 172 insertions(+), 144 deletions(-) create mode 100644 src/push/dingtalk/action-card.ts create mode 100644 src/push/dingtalk/feed-card.ts create mode 100644 src/push/dingtalk/link.ts delete mode 100644 src/push/dingtalk/template.ts diff --git a/README.md b/README.md index 0e9951c..23390c1 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ const dingtalk = new Dingtalk({ DINGTALK_ACCESS_TOKEN, DINGTALK_SECRET, }) -dingtalk.send('你好', '你好,我很可爱 - 钉钉机器人') +dingtalk.send('你好', '你好,我很可爱 - 钉钉机器人', { msgtype: 'markdown' }) // 企业微信群机器人。官方文档:https://developer.work.weixin.qq.com/document/path/91770 // 企业微信群机器人的使用需要两人以上加入企业,如果个人使用微信推送建议使用 企业微信应用+微信插件 推送。虽然需要配置的内容更多了,但是无需下载企业微信,网页端即可完成操作。 diff --git a/examples/01-example.ts b/examples/01-example.ts index 7e5bfd4..4e766fb 100644 --- a/examples/01-example.ts +++ b/examples/01-example.ts @@ -1,6 +1,6 @@ import { AxiosResponse } from 'axios' import colors from '@colors/colors' -import { ServerChanTurbo, ServerChanV3, CustomEmail, Dingtalk, WechatRobot, WechatApp, PushPlus, IGot, Qmsg, XiZhi, PushDeer, Discord, OneBot, Telegram, PushPlusTemplateType, CustomEmailType, OneBotMsgType, WechatRobotMsgType, WechatAppMsgType, PushPlusChannelType } from '../src' +import { ServerChanTurbo, ServerChanV3, CustomEmail, Dingtalk, WechatRobot, WechatApp, PushPlus, IGot, Qmsg, XiZhi, PushDeer, Discord, OneBot, Telegram, PushPlusTemplateType, CustomEmailType, WechatRobotMsgType, WechatAppMsgType, PushPlusChannelType } from '../src' import { warn } from '../src/utils/helper' import { SendResponse } from '../src/interfaces/response' @@ -64,7 +64,7 @@ export async function batchPushAllInOne(title: string, desp?: string): Promise

export interface DingtalkResponse { errcode: number @@ -79,7 +81,7 @@ export class Dingtalk implements Send { return signStr } - private async push(message: MessageTemplateAbs): Promise> { + private async push(data: DingtalkOption): Promise> { const timestamp = Date.now() const sign = this.getSign(timestamp) const result = await ajax({ @@ -93,7 +95,7 @@ export class Dingtalk implements Send { sign, access_token: this.ACCESS_TOKEN, }, - data: message.get(), + data, }) Debugger('Result is %s, %s。', result.data.errcode, result.data.errmsg) if (result.data.errcode === 310000) { @@ -114,11 +116,58 @@ export class Dingtalk implements Send { */ async send(title: string, desp?: string, option?: DingtalkOption): Promise> { Debugger('title: "%s", desp: "%s", option: %O', title, desp, option) - if (!desp) { - return this.push(new Text(title)) + switch (option.msgtype) { + case 'text': + return this.push({ + msgtype: 'text', + text: { + content: `${title}${desp ? `\n${desp}` : ''}`, + }, + ...option, + }) + case 'markdown': + return this.push({ + msgtype: 'markdown', + markdown: { + title, + text: `# ${title}${desp ? `\n\n${desp}` : ''}`, + }, + ...option, + }) + case 'link': + return this.push({ + msgtype: 'link', + link: { + title, + text: desp || '', + picUrl: option?.link?.picUrl || '', + messageUrl: option.link?.messageUrl || '', + }, + ...option, + }) + case 'actionCard': + return this.push({ + msgtype: 'actionCard', + actionCard: { + title, + text: desp || '', + btnOrientation: option?.actionCard?.btnOrientation || '0', + btns: (option?.actionCard as any)?.btns, + singleTitle: (option?.actionCard as any)?.singleTitle, + singleURL: (option?.actionCard as any)?.singleURL, + }, + ...option, + }) + case 'feedCard': + return this.push({ + msgtype: 'feedCard', + feedCard: { + links: option?.feedCard?.links || [], + }, + ...option, + }) + default: + throw new Error('msgtype is required!') } - const markDown = new Markdown() - markDown.setTitle(title).add(`# ${title}`).add(`${desp}`) - return this.push(markDown) } } diff --git a/src/push/dingtalk/Markdown.ts b/src/push/dingtalk/Markdown.ts index 06ec92a..1c22509 100644 --- a/src/push/dingtalk/Markdown.ts +++ b/src/push/dingtalk/Markdown.ts @@ -1,39 +1,20 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { MessageTemplateAbs } from './template' - -class Markdown extends MessageTemplateAbs { - items: string[] - title: string - constructor() { - super() - this.msgtype = 'markdown' - this.canAt = true - this.items = [] +/** + * 钉钉 markdown 消息 + * + * @author CaoMeiYouRen + * @date 2024-11-09 + * @export + * @interface Markdown + */ +export interface Markdown { + msgtype: 'markdown' + markdown: { + title: string + text: string } - - setTitle(title: string) { - this.title = title - return this - } - - add(text: string | string[]) { - if (Array.isArray(text)) { - this.items.concat(text) - } else { - this.items.push(text) - } - - return this - } - - get() { - return this.render({ - markdown: { - title: this.title, - text: this.items.join('\n'), - }, - }) + at?: { + atMobiles?: string[] + atUserIds?: string[] + isAtAll?: boolean } } - -export { Markdown } diff --git a/src/push/dingtalk/Text.ts b/src/push/dingtalk/Text.ts index 3729cfd..d33eb82 100644 --- a/src/push/dingtalk/Text.ts +++ b/src/push/dingtalk/Text.ts @@ -1,27 +1,19 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -import { MessageTemplateAbs } from './template' - -class Text extends MessageTemplateAbs { - content: string - constructor(content: string) { - super() - this.msgtype = 'text' - this.canAt = true - this.setContent(content) +/** + * 文本消息 + * + * @author CaoMeiYouRen + * @date 2024-11-09 + * @export + * @interface Text + */ +export interface Text { + msgtype: 'text' + text: { + content: string } - - setContent(content: string) { - this.content = content - return this - } - - get() { - return this.render({ - text: { - content: this.content, - }, - }) + at?: { + atMobiles?: string[] + atUserIds?: string[] + isAtAll?: boolean } } - -export { Text } diff --git a/src/push/dingtalk/action-card.ts b/src/push/dingtalk/action-card.ts new file mode 100644 index 0000000..763cec0 --- /dev/null +++ b/src/push/dingtalk/action-card.ts @@ -0,0 +1,38 @@ +// 整体跳转 +export type OverallJump = { + // 单个按钮的标题。设置此项和 singleURL 后,btns无效。 + singleTitle: string + // 点击消息跳转的URL + singleURL: string +} + +// 独立跳转 +export type IndependentJump = { + btns: { + // 按钮的标题 + title: string + // 点击按钮触发的URL + actionURL: string + }[] +} + +/** + * 动作卡片消息 + * + * @author CaoMeiYouRen + * @date 2024-11-09 + * @export + * @interface ActionCard + */ +export interface ActionCard { + msgtype: 'actionCard' + actionCard: { + // 首屏会话透出的展示内容 + title: string + // markdown 格式的消息内容 + text: string + // 0:按钮竖直排列;1:按钮横向排列 + btnOrientation?: '0' | '1' + } & (OverallJump | IndependentJump) +} + diff --git a/src/push/dingtalk/feed-card.ts b/src/push/dingtalk/feed-card.ts new file mode 100644 index 0000000..b2ede30 --- /dev/null +++ b/src/push/dingtalk/feed-card.ts @@ -0,0 +1,19 @@ +export interface FeedCardLink { + title: string + messageURL: string + picURL: string +} +/** + * 订阅卡片消息 + * + * @author CaoMeiYouRen + * @date 2024-11-09 + * @export + * @interface FeedCard + */ +export interface FeedCard { + msgtype: 'feedCard' + feedCard: { + links: FeedCardLink[] + } +} diff --git a/src/push/dingtalk/link.ts b/src/push/dingtalk/link.ts new file mode 100644 index 0000000..d9f1962 --- /dev/null +++ b/src/push/dingtalk/link.ts @@ -0,0 +1,17 @@ +/** + * 链接消息 + * + * @author CaoMeiYouRen + * @date 2024-11-09 + * @export + * @interface Link + */ +export interface Link { + msgtype: 'link' + link: { + text: string + title: string + picUrl?: string + messageUrl: string + } +} diff --git a/src/push/dingtalk/template.ts b/src/push/dingtalk/template.ts deleted file mode 100644 index 49f9540..0000000 --- a/src/push/dingtalk/template.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint-disable @typescript-eslint/explicit-module-boundary-types */ -class MessageTemplateAbs { - canAt: boolean - isAtAll: boolean - atMobiles: Set - atDingtalkIds: Set - msgtype: string - constructor() { - this.canAt = false - this.isAtAll = false - this.atMobiles = new Set() - this.atDingtalkIds = new Set() - if (new.target === MessageTemplateAbs) { - throw new Error('抽象类不可以实例化') - } - } - - render(options: unknown) { - return Object.assign({ - msgtype: this.msgtype, - }, options, this.canAt - ? { - at: { - atMobiles: Array.from(this.atMobiles), - atDingtalkIds: Array.from(this.atDingtalkIds), - isAtAll: this.isAtAll, - }, - } - : {}) - } - - get(): any { - throw new Error('抽象方法render不可以调用') - } - - toJsonString(): string { - throw new Error('抽象方法toJsonString不可以调用') - } - - atAll() { - this.isAtAll = true - return this - } - - atPhone(phones: string | string[]) { - if (phones instanceof Array) { - phones.forEach((phone) => { - this.atMobiles.add(phone) - }) - } else { - this.atMobiles.add(phones) - } - return this - } - - atId(ids: string | string[]) { - if (ids instanceof Array) { - ids.forEach((phone) => { - this.atDingtalkIds.add(phone) - }) - } else { - this.atDingtalkIds.add(ids) - } - return this - } -} - -export { MessageTemplateAbs } diff --git a/src/push/wechat-app.ts b/src/push/wechat-app.ts index 501d9dd..a39a0c3 100644 --- a/src/push/wechat-app.ts +++ b/src/push/wechat-app.ts @@ -1,6 +1,6 @@ import debug from 'debug' import { Send } from '../interfaces/send' -import { error, warn } from '@/utils/helper' +import { warn } from '@/utils/helper' import { ajax } from '@/utils/ajax' import { SendResponse } from '@/interfaces/response'