Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

兼容飞书的抽象整理完成 #43

Merged
merged 14 commits into from
Apr 7, 2024
29 changes: 28 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,33 @@ issue 被 assign 后,在 IM 群中提醒当事人。
详见 https://github.com/mosn/layotto/issues/800

如果开启该功能,good first issue 必须满足一定的label 规范、命名规范, 详见 https://mosn.io/layotto/#/zh/development/label-spec
### 7. 接入其他IM

- 代码:仿照dingtalk.js编写自己的xxxim.js,然后把自己的xxxim.js在src/dao/im.js里面导入。在接口里面根据im的配置type在if分支里面调用自己写的接口。
- ` if(group['type']==='dingtalk'){
return dingtalk.sendMarkdown(group,content,atUid,uidArr);
}else{
///// 其他IM接入示例
return otherim.sendMarkdown(group,content,atUid,uidArr);
}`
- 配置:在config.json里面填写im的type为自己的im类型。
- `
"good-first-issue-notifier": {
"enable": true,
"channels": [
{
"type": "dingtalk",
"urls": [
"https://oapi.dingtalk.com/robot/send?access_token=66113ea1b10247d25149158fb4b765da6c3c57bddca2682215122cc205e2ac70"
],
"title": "goodFirstIssue认领",
"atUid": [],
"atAll": true
}
]
}
`

## 使用文档

- [如何在钉钉群里添加“项目管理机器人”](pm_bot.md)
Expand All @@ -145,4 +172,4 @@ issue 被 assign 后,在 IM 群中提醒当事人。


## Roadmap
见 issue 区
见 issue 区
188 changes: 8 additions & 180 deletions src/dao/dangerous_issue.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
const fs = require("fs");
const moment = require("moment");
const fetch = require("node-fetch");
const config = require("../../configs/config.json");
const {getConfig} = require("../const");
const { getConn, query } = require("./mysql_conn");
const { getImDao } = require("./im");
const {utils} = require("../utils/time_utils");

const mysqlDao = {
Expand Down Expand Up @@ -45,7 +44,6 @@ const mysqlDao = {

const dingTalkDao = {
issuesForDingTalk: new Map(),

livenessCheck: new Map(),
start: function () { },
// put the issue into the memory list
Expand Down Expand Up @@ -78,7 +76,7 @@ const dingTalkDao = {
sendLiveness:async function(livenessCheckElement,owner,ownerDingTalkGroupConfig){
if (livenessCheckElement > 0) {
let livenessContent = this.concatLivenessContent(owner, livenessCheckElement, ownerDingTalkGroupConfig);
await this.send(livenessContent, null, false, true, "liveness", ownerDingTalkGroupConfig);
await getImDao.send(livenessContent, null, false, true, "liveness", ownerDingTalkGroupConfig);
} else {
await this.sendSuccessLivecheck(owner, ownerDingTalkGroupConfig)
}
Expand All @@ -91,7 +89,7 @@ const dingTalkDao = {
const ownerDingTalkGroupConfig = getConfig(null, config.orgRepoConfig[owner]['dingTalkGroupConfig'], config.generalConfig['dingTalkGroupConfig']);
if (value.length > 0) {
let issueContent = this.concatIssueContent(owner, value, ownerDingTalkGroupConfig);
await this.send(issueContent, null, false, true, "issue", ownerDingTalkGroupConfig);
await getImDao().send(issueContent, null, false, true, "issue", ownerDingTalkGroupConfig);
} else {
await this.sendNoIssue(owner, ownerDingTalkGroupConfig)
}
Expand Down Expand Up @@ -209,7 +207,7 @@ const dingTalkDao = {
`注:liveness check会检查每个项目的健康情况,如果满足下列条件会被归类为“腐烂级”项目:\n` +
`- 存在大于30天未回复的 issue \n` +
`- 连续4周活跃度小于20\n`;
await this.send(content, null, false, false, "liveness", dingTalkGroupConfig);
await getImDao().send(content, null, false, false, "liveness", dingTalkGroupConfig);
},
sendNoIssue: async function (owner, dingTalkGroupConfig) {
let awards = [
Expand All @@ -234,178 +232,10 @@ const dingTalkDao = {
let idx = Math.floor(Math.random() * awards.length);
let content = awards[idx].content;
let img = awards[idx].img;
await this.send(content, null, false, false, "issue", dingTalkGroupConfig);
await this.sendImage(img, null, false, false, "issue", owner, dingTalkGroupConfig);
},
/**
* 这里的owner等于owner好像
* @param content
* @param atUid
* @param isAtAll
* @param isNegative
* @param topicType
* @param dingTalkGroupConfig
*/
send: async function (content, atUid, isAtAll, isNegative, topicType,dingTalkGroupConfig) {
const topicTypeLiveness = "liveness";
const topicTypeIssue = "issue";
const groups = dingTalkGroupConfig["groups"]

for (let group of groups) {
// 1.validate
// 检查url是否为空
if (group['url'] == null || group['url'].length === 0) {
console.log("DingTalk url is empty");
continue;
}
// check topic projects
// 检查group.topicProjects中是否包含project
// if (!this.interested(group['topicProjects'], project)) {
// continue;
// }
// check topicTypesIgnore
// 检查group['topicTypesIgnore']是否为*或者是否等于topicType
if (this.isIgnoredTopicType(group['topicTypesIgnore'], topicType)) {
continue;
}
// check topicTypesOnly
// 检查group['topicTypesOnly']是否为*或者是否等于topicType
if (!this.interestedTopicType(group['topicTypesOnly'], topicType)) {
continue;
}
// check owner in content
// 检查content中是否有group.owner,没有则替换this.owner
let newContent = content;
await getImDao().send(content, null, false, false, "issue", dingTalkGroupConfig);
await getImDao().sendImage(img, null, false, false, "issue", owner, dingTalkGroupConfig);
}

// append text
// 添加链接文本
if (topicType === topicTypeIssue) {
if (isNegative) {
newContent += this.nullToEmpty(group['issueWarningText']);
} else {
//没有issue,不会发消息,这个实际没有用到
newContent += this.nullToEmpty(group['issueCongratulationText']);
}
} else if (topicType === topicTypeLiveness) {
if (isNegative) {
newContent += this.nullToEmpty(group['livenessWarningText']);
} else {
newContent += this.nullToEmpty(group['livenessCongratulationText']);
}
}
let uidArr = [];
if (atUid != null) {
uidArr = atUid;
}
// 2. send request
//发送请求
return fetch(group.url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
at: {
atMobiles: [""],
atUserIds: uidArr,
isAtAll: isAtAll,
},
text: {
content: newContent,
},
msgtype: "text",
title: ``,
}),
})
// 3. parse
.then((res) => {
return res.json();
})
.then((json) => {
console.log( `发送钉钉:${newContent}结果:`)
console.log(json)
});
}
},
nullToEmpty(str) {
// 如果str为null,则返回空字符串
if (str == null) {
return "";
}
// 否则返回str
return str;
},
interested: function (topicProjects, project) {
// 如果topicProjects为空或者长度为0或者topicProjects为*
if (
topicProjects == null ||
topicProjects.length == 0 ||
topicProjects == "*"
) {
// 返回true
return true;
}
// 如果topicProjects中包含project
if (topicProjects.indexOf(project) >= 0) {
// 返回true
return true;
}
// 否则返回false
return false;
},
sendImage: async function (imageUrl, atUid, isAtAll, isNegative, topicType,owner,option) {
const groups = option["groups"]
for (let group of groups) {
// 1.validate
if (group.url == null || group.url.length == 0) {
console.log("send image:DingTalk url is empty");
continue;
}
// check topic project
// if (!this.interested(group['topicProjects'], project)) {
// continue;
// }
// check topicTypesIgnore
if (this.isIgnoredTopicType(group['topicTypesIgnore'], topicType)) {
continue;
}
// check topicTypesOnly
if (!this.interestedTopicType(group['topicTypesOnly'], topicType)) {
continue;
}
// check owner in content
let nickName = owner;
if (group['nickName'] != null) {
nickName = group['nickName'];
}
// 2. send request
return fetch(group.url, {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
msgtype: "markdown",
markdown: {
title: nickName,
text: `![](${imageUrl}) \n`,
},
at: {
atMobiles: [""],
atUserIds: [atUid],
isAtAll: isAtAll,
},
}),
})
// 3. parse
.then((res) => {
return res.json();
})
.then((json) => console.log("发送图片结果:",json));
}
},
};

const fsDAOImpl = {
Expand Down Expand Up @@ -492,9 +322,7 @@ module.exports = {
fsDAOImpl.commit();
dingTalkDao.commit();
},
getDingTalkDao() {
return dingTalkDao;
},

getMysqlDao(){
return mysqlDao;
}
Expand Down
Loading