feat: 飞书单点登录和通知功能
This commit is contained in:
@@ -21,6 +21,14 @@ const config = {
|
||||
baseUrl: process.env.JIRA_BASE_URL,
|
||||
botId: process.env.JIRA_BOT_ID || '',
|
||||
botName: process.env.JIRA_BOT_NAME
|
||||
},
|
||||
lark: {
|
||||
appId: process.env.LARK_APP_ID || '',
|
||||
appSecret: process.env.LARK_APP_SECRET || '',
|
||||
webhookUrl: process.env.LARK_WEBHOOK_URL || '',
|
||||
webhookSecret: process.env.LARK_WEBHOOK_SECRET || '',
|
||||
redirectUri: process.env.LARK_REDIRECT_URI || '',
|
||||
adminIds: (process.env.ADMIN_IDS || '').split(',').map(id => id.trim()).filter(id => id)
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
121
src/config/larkRules.js
Normal file
121
src/config/larkRules.js
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
* 飞书提醒规则管理
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const crypto = require('crypto');
|
||||
const logger = require('../utils/logger');
|
||||
|
||||
const DATA_FILE = path.join(__dirname, '../../data/larkRules.json');
|
||||
|
||||
//确保数据文件存在
|
||||
function ensureDataFile() {
|
||||
const dir = path.dirname(DATA_FILE);
|
||||
if (!fs.existsSync(dir)) {
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
if (!fs.existsSync(DATA_FILE)) {
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify({ rules: [] }, null, 2));
|
||||
}
|
||||
}
|
||||
|
||||
//读取所有规则
|
||||
function getAllRules() {
|
||||
ensureDataFile();
|
||||
try {
|
||||
const data = fs.readFileSync(DATA_FILE, 'utf-8');
|
||||
return JSON.parse(data).rules || [];
|
||||
} catch (e) {
|
||||
logger.error('[LarkRules] Failed to read rules:', e.message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
//保存所有规则
|
||||
function saveAllRules(rules) {
|
||||
ensureDataFile();
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify({ rules }, null, 2));
|
||||
}
|
||||
|
||||
//获取单个规则
|
||||
function getRule(id) {
|
||||
return getAllRules().find(r => r.id === id);
|
||||
}
|
||||
|
||||
//创建规则
|
||||
function createRule(rule) {
|
||||
const rules = getAllRules();
|
||||
const newRule = {
|
||||
id: crypto.randomUUID(),
|
||||
createdAt: new Date().toISOString(),
|
||||
enabled: true,
|
||||
...rule
|
||||
};
|
||||
rules.push(newRule);
|
||||
saveAllRules(rules);
|
||||
logger.info(`[LarkRules] created rule: ${newRule.name} (${newRule.id})`);
|
||||
return newRule;
|
||||
}
|
||||
|
||||
//更新规则
|
||||
function updateRule(id, updates) {
|
||||
const rules = getAllRules();
|
||||
const index = rules.findIndex(r => r.id === id);
|
||||
if (index === -1) {
|
||||
throw new Error('Rule not found');
|
||||
}
|
||||
rules[index] = { ...rules[index], ...updates, id, updatedAt: new Date().toISOString() };
|
||||
saveAllRules(rules);
|
||||
logger.info(`[LarkRules] updated rule: ${rules[index].name} (${id})`);
|
||||
return rules[index];
|
||||
}
|
||||
|
||||
//删除规则
|
||||
function deleteRule(id) {
|
||||
const rules = getAllRules();
|
||||
const index = rules.findIndex(r => r.id === id);
|
||||
if (index === -1) {
|
||||
throw new Error('Rule not found');
|
||||
}
|
||||
const deleted = rules.splice(index, 1)[0];
|
||||
saveAllRules(rules);
|
||||
logger.info(`[LarkRules] deleted rule: ${deleted.name} (${id})`);
|
||||
return deleted;
|
||||
}
|
||||
|
||||
//根据事件类型获取匹配的规则
|
||||
function getRulesByEvent(eventType) {
|
||||
return getAllRules().filter(r => r.enabled && r.event === eventType);
|
||||
}
|
||||
|
||||
//支持的事件类型
|
||||
const EVENT_TYPES = [
|
||||
{ value: 'issue.opened', label: '新建 Issue' },
|
||||
{ value: 'issue.closed', label: '关闭 Issue' },
|
||||
{ value: 'issue.reopened', label: '重开 Issue' },
|
||||
{ value: 'issue.assigned', label: '指派 Issue' },
|
||||
{ value: 'issue.unassigned', label: '取消指派 Issue' },
|
||||
{ value: 'issue.edited', label: '编辑 Issue' },
|
||||
{ value: 'issue.label_updated', label: 'Issue 标签变更' },
|
||||
{ value: 'issue.milestoned', label: 'Issue 里程碑变更' },
|
||||
{ value: 'issue.comment', label: 'Issue 评论' },
|
||||
{ value: 'pr.opened', label: '新建合并请求' },
|
||||
{ value: 'pr.closed', label: '关闭合并请求' },
|
||||
{ value: 'pr.merged', label: '合并请求已合并' },
|
||||
{ value: 'pr.reopened', label: '重开合并请求' },
|
||||
{ value: 'release.created', label: '创建发布' },
|
||||
{ value: 'release.published', label: '发布版本' },
|
||||
{ value: 'release.deleted', label: '删除发布' },
|
||||
{ value: 'release.updated', label: '更新发布' }
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
getAllRules,
|
||||
getRule,
|
||||
createRule,
|
||||
updateRule,
|
||||
deleteRule,
|
||||
getRulesByEvent,
|
||||
EVENT_TYPES
|
||||
};
|
||||
@@ -2,7 +2,7 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
//读取配置文件路径
|
||||
const configPath = path.join(__dirname, '../../mappings.json');
|
||||
const configPath = path.join(__dirname, '../../data/mappings.json');
|
||||
|
||||
let mappingsConfig = null;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user