diff --git a/README.md b/README.md index 0410905..134a7f8 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,24 @@ Send dingding simple notify message. } ``` +## sign + +```yaml +- name: Send dingding notify + uses: zcong1993/actions-ding@master + with: + dingToken: ${{ secrets.DING_TOKEN }} ++ secret: ${{ secrets.DING_SECRET }} # if secret set, action will call API with sign + body: | + { + "msgtype": "link", + "link": { + "text": "这个即将发布的新版本,创始人陈航(花名“无招”)称它为“红树林”。而在此之前,每当面临重大升级,产品经理们都会取一个应景的代号,这一次,为什么是“红树林”?", + "title": "时代的火车向前开", + "picUrl": "", + "messageUrl": "https://www.dingtalk.com/s?__biz=MzA4NjMwMTA2Ng==&mid=2650316842&idx=1&sn=60da3ea2b29f1dcc43a7c8e4a7c97a16&scene=2&srcid=09189AnRJEdIiWVaKltFzNTw&from=timeline&isappinstalled=0&key=&ascene=2&uin=&devicetype=android-23&version=26031933&nettype=WIFI" + } + } +``` + put any kind of message body [dingding](https://ding-doc.dingtalk.com/doc#/serverapi2/qf2nxq) support into `body` field. diff --git a/action.yml b/action.yml index be47bfb..f00acb6 100644 --- a/action.yml +++ b/action.yml @@ -11,6 +11,9 @@ inputs: body: description: 'Post Body to send' required: true + secret: + description: 'If use sign secret' + required: false runs: using: 'node12' diff --git a/dist/index.js b/dist/index.js index 1cefad7..4b1c26d 100644 --- a/dist/index.js +++ b/dist/index.js @@ -383,35 +383,36 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); const core = __importStar(__webpack_require__(116)); -const axios_1 = __importDefault(__webpack_require__(452)); +const ding_bot_1 = __webpack_require__(808); const endpoint = 'https://oapi.dingtalk.com/robot/send'; function run() { - var _a, _b, _c; + var _a, _b; return __awaiter(this, void 0, void 0, function* () { try { const token = core.getInput('dingToken'); const body = core.getInput('body'); + const secretStr = core.getInput('secret'); + const secret = secretStr === '' ? undefined : secretStr; + const data = JSON.parse(body); + if (secret) { + core.info('get secret, sign mode'); + } core.info(`Send body: ${body}`); + const dingBot = new ding_bot_1.DingBot({ + endpoint, + accessToken: token, + signKey: secret + }); try { - const resp = yield axios_1.default({ - method: 'post', - url: `${endpoint}?access_token=${token}`, - data: body, - headers: { - 'Content-Type': 'application/json' - } - }); - if (resp.data.errcode !== 0) { - core.setFailed((_a = resp.data) === null || _a === void 0 ? void 0 : _a.errmsg); + const resp = yield dingBot.rawSend(data); + if ((resp === null || resp === void 0 ? void 0 : resp.errcode) !== 0) { + core.setFailed(resp === null || resp === void 0 ? void 0 : resp.errmsg); } } catch (requestErr) { - core.error(`send request error, status: ${(_b = requestErr.response) === null || _b === void 0 ? void 0 : _b.status}, data: ${(_c = requestErr.response) === null || _c === void 0 ? void 0 : _c.data}`); + core.error(`send request error, status: ${(_a = requestErr.response) === null || _a === void 0 ? void 0 : _a.status}, data: ${(_b = requestErr.response) === null || _b === void 0 ? void 0 : _b.data}`); core.setFailed(requestErr.message); } } @@ -654,6 +655,28 @@ exports.getState = getState; /***/ }), +/***/ 187: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +exports.createSign = void 0; +const crypto_1 = __webpack_require__(417); +const sha256 = (str, key) => { + const h = crypto_1.createHmac('SHA256', key); + h.update(str); + return h.digest('base64'); +}; +exports.createSign = (key, ts) => { + const str = `${ts}\n${key}`; + const sign = sha256(str, key); + return encodeURIComponent(sign); +}; +//# sourceMappingURL=sign.js.map + +/***/ }), + /***/ 211: /***/ (function(module) { @@ -1664,6 +1687,13 @@ module.exports = require("stream"); /***/ }), +/***/ 417: +/***/ (function(module) { + +module.exports = require("crypto"); + +/***/ }), + /***/ 419: /***/ (function(module, __unusedexports, __webpack_require__) { @@ -2470,6 +2500,67 @@ module.exports = require("zlib"); /***/ }), +/***/ 808: +/***/ (function(__unusedmodule, exports, __webpack_require__) { + +"use strict"; + +Object.defineProperty(exports, "__esModule", { value: true }); +exports.DingBot = void 0; +const axios_1 = __webpack_require__(452); +const sign_1 = __webpack_require__(187); +const endpoint = 'https://oapi.dingtalk.com/robot/send'; +class DingBot { + constructor(options) { + this.options = options; + if (!this.options.endpoint) { + this.options.endpoint = endpoint; + } + } + async sendTextMsg(msg) { + return this.send(msg); + } + async sendLinkMsg(msg) { + return this.send(msg); + } + async sendMarkdownMsg(msg) { + return this.send(msg); + } + async sendActionCardMsg(msg) { + return this.send(msg); + } + async sendFeedCardMsg(msg) { + return this.send(msg); + } + async send(msg) { + const data = await this.rawSend(msg); + if (data.errcode !== 0) { + throw new Error(data.errmsg); + } + } + async rawSend(msg) { + const { data } = await axios_1.default.request({ + method: 'post', + url: this.buildUrl(), + data: msg, + }); + return data; + } + buildUrl() { + let url = `${endpoint}?access_token=${this.options.accessToken}`; + if (this.options.signKey) { + const ts = new Date().getTime(); + const sign = sign_1.createSign(this.options.signKey, ts); + url += `×tamp=${ts}&sign=${sign}`; + } + return url; + } +} +exports.DingBot = DingBot; +//# sourceMappingURL=index.js.map + +/***/ }), + /***/ 810: /***/ (function(module, __unusedexports, __webpack_require__) { diff --git a/package.json b/package.json index 45da81d..910cf71 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "license": "MIT", "dependencies": { "@actions/core": "^1.2.4", - "axios": "^0.19.2" + "@zcong/ding-bot": "^0.1.0" }, "devDependencies": { "@types/jest": "^26.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4ef4d5..40627ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,6 @@ dependencies: '@actions/core': registry.npmjs.org/@actions/core/1.2.4 - axios: registry.npmjs.org/axios/0.19.2 + '@zcong/ding-bot': registry.npmjs.org/@zcong/ding-bot/0.1.0 devDependencies: '@types/jest': registry.npmjs.org/@types/jest/26.0.0 '@types/node': registry.npmjs.org/@types/node/14.0.13 @@ -1043,6 +1043,16 @@ packages: registry: 'https://registry.npmjs.com/' tarball: 'https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-3.3.0.tgz' version: 3.3.0 + registry.npmjs.org/@zcong/ding-bot/0.1.0: + dependencies: + axios: registry.npmjs.org/axios/0.19.2 + dev: false + name: '@zcong/ding-bot' + resolution: + integrity: sha512-2T3cPUb1xnOcLMBi6H3hcscleM5E+UoO+Ly0L2EmLpbZUCYcWSfOBUT+wmHCR345h01s8L+YkjGM5hpBjvGBxQ== + registry: 'https://registry.npmjs.com/' + tarball: 'https://registry.npmjs.org/@zcong/ding-bot/-/ding-bot-0.1.0.tgz' + version: 0.1.0 registry.npmjs.org/@zeit/ncc/0.22.3: dev: true hasBin: true @@ -7308,8 +7318,8 @@ specifiers: '@types/jest': ^26.0.0 '@types/node': ^14.0.13 '@typescript-eslint/parser': ^3.3.0 + '@zcong/ding-bot': ^0.1.0 '@zeit/ncc': ^0.22.3 - axios: ^0.19.2 eslint: ^7.2.0 eslint-plugin-github: ^4.0.1 eslint-plugin-jest: ^23.13.2 diff --git a/src/index.ts b/src/index.ts index 57f94e4..2630163 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,25 +1,30 @@ import * as core from '@actions/core' -import axios from 'axios' +import {DingBot} from '@zcong/ding-bot' const endpoint = 'https://oapi.dingtalk.com/robot/send' async function run(): Promise { try { - const token: string = core.getInput('dingToken') - const body: string = core.getInput('body') + const token = core.getInput('dingToken') + const body = core.getInput('body') + const secretStr = core.getInput('secret') + const secret = secretStr === '' ? undefined : secretStr + const data = JSON.parse(body) + if (secret) { + core.info('get secret, sign mode') + } core.info(`Send body: ${body}`) - try { - const resp = await axios({ - method: 'post', - url: `${endpoint}?access_token=${token}`, - data: body, - headers: { - 'Content-Type': 'application/json' - } - }) + const dingBot = new DingBot({ + endpoint, + accessToken: token, + signKey: secret + }) - if (resp.data.errcode !== 0) { - core.setFailed(resp.data?.errmsg) + try { + const resp = await dingBot.rawSend(data) + + if (resp?.errcode !== 0) { + core.setFailed(resp?.errmsg) } } catch (requestErr) { core.error(