feat: github app 增加issue回复监听以及tailchat消息发送

pull/56/head
moonrailgun 2 years ago
parent d56bf4fa79
commit a81e7b86ec

@ -5,20 +5,21 @@
"description": "Tailchat github integrations",
"author": "moonrailgun",
"license": "ISC",
"homepage": "https://github.com//",
"homepage": "https://github.com/msgbyte/tailchat",
"keywords": [
"probot",
"github",
"probot-app"
],
"scripts": {
"dev": "nodemon --watch 'src/**' --ext 'ts' --ignore 'src/**/*.spec.ts' --exec \"ts-node --transpile-only src/index.ts\"",
"dev": "nodemon --watch \"src/**\" --ext \"ts\" --ignore \"src/**/*.spec.ts\" --exec \"ts-node --transpile-only src/index.ts\"",
"build": "tsc",
"test": "jest"
},
"dependencies": {
"axios": "^0.21.1",
"probot": "^12.2.4"
"probot": "^12.2.4",
"probot-metadata": "^2.1.0"
},
"devDependencies": {
"@types/jest": "^28.1.0",

@ -1,7 +1,10 @@
import { Probot } from 'probot';
import metadata from 'probot-metadata';
import { TailchatClient } from './client';
import { configPath, generateErrorBlock } from './utils';
const configPath = '.tailchat/topic.json';
const LABEL = 'tailchat-topic';
const TOPIC_KEY = 'tailchatTopicId';
export function app(app: Probot) {
if (
@ -25,13 +28,13 @@ export function app(app: Probot) {
return;
}
const { data } = await ctx.octokit.repos.getContent(
ctx.repo({
path: configPath,
})
);
try {
const { data } = await ctx.octokit.repos.getContent(
ctx.repo({
path: configPath,
})
);
if (!(!Array.isArray(data) && 'content' in data)) {
throw new Error('config file type error');
}
@ -47,9 +50,19 @@ export function app(app: Probot) {
throw new Error('config format error');
}
console.log(json);
// TODO: 发送到tailchat
// 发送到tailchat
const topic = await tailchatClient.call(
'plugin:com.msgbyte.topic.create',
{
groupId,
panelId,
content: `${ctx.payload.issue.user.login} create Issue\n\ntitle: ${
ctx.payload.issue.title
}\ncontent: ${ctx.payload.issue.body ?? ''}\n\nwebsite: ${
ctx.payload.issue.html_url
}`,
}
);
await Promise.all([
ctx.octokit.issues.createComment(
@ -60,22 +73,73 @@ export function app(app: Probot) {
ctx.octokit.issues.addLabels(
ctx.repo({
issue_number: ctx.payload.issue.number,
labels: ['tailchat-topic'],
labels: [LABEL],
})
),
metadata(ctx).set(TOPIC_KEY, topic._id),
]);
} catch (err) {
console.error(err);
await ctx.octokit.issues.createComment(
ctx.issue({
body: `Tailchat topic create error, please checkout your config in \`${configPath}\`!`,
body: generateErrorBlock(err),
})
);
}
});
app.on('issue_comment.created', async () => {
app.on('issue_comment.created', async (ctx) => {
if (ctx.isBot) {
return;
}
// 发送到tailchat
try {
const topicId = await metadata(ctx).get(TOPIC_KEY);
if (!topicId) {
return;
}
const { data } = await ctx.octokit.repos.getContent(
ctx.repo({
path: configPath,
})
);
if (!(!Array.isArray(data) && 'content' in data)) {
throw new Error('config file type error');
}
// 是配置文件
const content = Buffer.from(data.content, 'base64').toString();
const json = await JSON.parse(content);
const groupId = json['groupId'];
const panelId = json['panelId'];
if (!groupId || !panelId) {
throw new Error('config format error');
}
// 发送到tailchat
await tailchatClient.call('plugin:com.msgbyte.topic.createComment', {
groupId,
panelId,
topicId,
content: `${ctx.payload.comment.user.login} reply Issue\n\ncontent: ${
ctx.payload.issue.body ?? ''
}\n\nWebsite: ${ctx.payload.comment.html_url}`,
});
} catch (err) {
console.error(err);
await ctx.octokit.issues.createComment(
ctx.issue({
body: generateErrorBlock(err),
})
);
}
});
app.on('installation.created', async (ctx) => {

@ -4,6 +4,7 @@ import crypto from 'crypto';
export class TailchatClient {
request: AxiosInstance;
jwt: string | null = null;
loginP: Promise<void>;
constructor(
public url: string,
@ -25,7 +26,7 @@ export class TailchatClient {
return val;
});
this.login();
this.loginP = this.login();
}
async login() {
@ -45,17 +46,32 @@ export class TailchatClient {
console.log(await this.whoami());
} catch (err) {
console.error(err);
throw new Error();
throw err;
}
}
async call(action: string, params = {}) {
const { data } = await this.request.post(
'/api/' + action.replace(/\./g, '/'),
params
);
try {
await Promise.resolve(this.loginP); // 等待loigin完毕. 用于serverless服务
const { data } = await this.request.post(
'/api/' + action.replace(/\./g, '/'),
params
);
return data;
return data;
} catch (err: any) {
const data: string = err?.response?.data;
if (data) {
throw new Error(
JSON.stringify({
action,
data,
})
);
} else {
throw err;
}
}
}
async whoami() {

@ -0,0 +1,9 @@
export const configPath = '.tailchat/topic.json';
export function generateErrorBlock(err: unknown) {
const detail = err instanceof Error ? err : new Error(String(err));
const errorBlock =
'```' + detail.name + detail.message + '\n' + (detail.stack ?? '') + '```';
return `Tailchat occur error, please checkout your config in \`${configPath}\`! \nError:\nw${errorBlock}`;
}

@ -122,6 +122,7 @@ importers:
nock: ^13.0.5
nodemon: ^2.0.18
probot: ^12.2.4
probot-metadata: ^2.1.0
smee-client: ^1.2.2
ts-jest: ^26.4.4
ts-node: ^10.9.1
@ -129,6 +130,7 @@ importers:
dependencies:
axios: 0.21.4
probot: 12.2.8
probot-metadata: 2.1.0_probot@12.2.8
devDependencies:
'@types/jest': 28.1.8
'@types/node': 18.7.11
@ -25073,6 +25075,14 @@ packages:
engines: {node: '>=6'}
dev: false
/probot-metadata/2.1.0_probot@12.2.8:
resolution: {integrity: sha512-0e8+fZ5tE2EbsSgN1zGHfjFNs17DEbG5b0zYq2HlEL6u+8JJRZraUMtwsi0QdtB2eMrenYfEy76aBfnfzFcrRw==}
peerDependencies:
probot: '>=10'
dependencies:
probot: 12.2.8
dev: false
/probot/12.2.8:
resolution: {integrity: sha512-O2WqJmgXUijAOTHaIBEW3jC5OU9Rq+eUg/AEBI5zkAUZaxzJMQvXvGvhVsdFE3Zt9Z3ceGN8Z2cgN+NTItSrCQ==}
engines: {node: '>=10.21'}

@ -120,7 +120,7 @@ class GroupTopicService extends TcService {
this.roomcastNotify(ctx, groupId, 'create', json);
return true;
return json;
}
/**

Loading…
Cancel
Save