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

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

@ -5,20 +5,21 @@
"description": "Tailchat github integrations", "description": "Tailchat github integrations",
"author": "moonrailgun", "author": "moonrailgun",
"license": "ISC", "license": "ISC",
"homepage": "https://github.com//", "homepage": "https://github.com/msgbyte/tailchat",
"keywords": [ "keywords": [
"probot", "probot",
"github", "github",
"probot-app" "probot-app"
], ],
"scripts": { "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", "build": "tsc",
"test": "jest" "test": "jest"
}, },
"dependencies": { "dependencies": {
"axios": "^0.21.1", "axios": "^0.21.1",
"probot": "^12.2.4" "probot": "^12.2.4",
"probot-metadata": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^28.1.0", "@types/jest": "^28.1.0",

@ -1,7 +1,10 @@
import { Probot } from 'probot'; import { Probot } from 'probot';
import metadata from 'probot-metadata';
import { TailchatClient } from './client'; 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) { export function app(app: Probot) {
if ( if (
@ -25,13 +28,13 @@ export function app(app: Probot) {
return; return;
} }
const { data } = await ctx.octokit.repos.getContent(
ctx.repo({
path: configPath,
})
);
try { try {
const { data } = await ctx.octokit.repos.getContent(
ctx.repo({
path: configPath,
})
);
if (!(!Array.isArray(data) && 'content' in data)) { if (!(!Array.isArray(data) && 'content' in data)) {
throw new Error('config file type error'); throw new Error('config file type error');
} }
@ -47,9 +50,19 @@ export function app(app: Probot) {
throw new Error('config format error'); throw new Error('config format error');
} }
console.log(json); // 发送到tailchat
const topic = await tailchatClient.call(
// TODO: 发送到tailchat '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([ await Promise.all([
ctx.octokit.issues.createComment( ctx.octokit.issues.createComment(
@ -60,22 +73,73 @@ export function app(app: Probot) {
ctx.octokit.issues.addLabels( ctx.octokit.issues.addLabels(
ctx.repo({ ctx.repo({
issue_number: ctx.payload.issue.number, issue_number: ctx.payload.issue.number,
labels: ['tailchat-topic'], labels: [LABEL],
}) })
), ),
metadata(ctx).set(TOPIC_KEY, topic._id),
]); ]);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
await ctx.octokit.issues.createComment( await ctx.octokit.issues.createComment(
ctx.issue({ 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 // 发送到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) => { app.on('installation.created', async (ctx) => {

@ -4,6 +4,7 @@ import crypto from 'crypto';
export class TailchatClient { export class TailchatClient {
request: AxiosInstance; request: AxiosInstance;
jwt: string | null = null; jwt: string | null = null;
loginP: Promise<void>;
constructor( constructor(
public url: string, public url: string,
@ -25,7 +26,7 @@ export class TailchatClient {
return val; return val;
}); });
this.login(); this.loginP = this.login();
} }
async login() { async login() {
@ -45,17 +46,32 @@ export class TailchatClient {
console.log(await this.whoami()); console.log(await this.whoami());
} catch (err) { } catch (err) {
console.error(err); console.error(err);
throw new Error(); throw err;
} }
} }
async call(action: string, params = {}) { async call(action: string, params = {}) {
const { data } = await this.request.post( try {
'/api/' + action.replace(/\./g, '/'), await Promise.resolve(this.loginP); // 等待loigin完毕. 用于serverless服务
params 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() { 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 nock: ^13.0.5
nodemon: ^2.0.18 nodemon: ^2.0.18
probot: ^12.2.4 probot: ^12.2.4
probot-metadata: ^2.1.0
smee-client: ^1.2.2 smee-client: ^1.2.2
ts-jest: ^26.4.4 ts-jest: ^26.4.4
ts-node: ^10.9.1 ts-node: ^10.9.1
@ -129,6 +130,7 @@ importers:
dependencies: dependencies:
axios: 0.21.4 axios: 0.21.4
probot: 12.2.8 probot: 12.2.8
probot-metadata: 2.1.0_probot@12.2.8
devDependencies: devDependencies:
'@types/jest': 28.1.8 '@types/jest': 28.1.8
'@types/node': 18.7.11 '@types/node': 18.7.11
@ -25073,6 +25075,14 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: false 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: /probot/12.2.8:
resolution: {integrity: sha512-O2WqJmgXUijAOTHaIBEW3jC5OU9Rq+eUg/AEBI5zkAUZaxzJMQvXvGvhVsdFE3Zt9Z3ceGN8Z2cgN+NTItSrCQ==} resolution: {integrity: sha512-O2WqJmgXUijAOTHaIBEW3jC5OU9Rq+eUg/AEBI5zkAUZaxzJMQvXvGvhVsdFE3Zt9Z3ceGN8Z2cgN+NTItSrCQ==}
engines: {node: '>=10.21'} engines: {node: '>=10.21'}

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

Loading…
Cancel
Save