feat: support sign

This commit is contained in:
zcong1993 2020-06-19 17:25:50 +08:00
parent 3665621f64
commit 86fe51fbd3
6 changed files with 162 additions and 33 deletions

View File

@ -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.

View File

@ -11,6 +11,9 @@ inputs:
body:
description: 'Post Body to send'
required: true
secret:
description: 'If use sign secret'
required: false
runs:
using: 'node12'

123
dist/index.js vendored
View File

@ -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 += `&timestamp=${ts}&sign=${sign}`;
}
return url;
}
}
exports.DingBot = DingBot;
//# sourceMappingURL=index.js.map
/***/ }),
/***/ 810:
/***/ (function(module, __unusedexports, __webpack_require__) {

View File

@ -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",

View File

@ -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

View File

@ -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<void> {
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(