Skip to content

Commit 2590242

Browse files
committed
feat: github 开放平台机器人增加监听消息回调到github issue comment
1 parent d120772 commit 2590242

File tree

8 files changed

+209
-168
lines changed

8 files changed

+209
-168
lines changed

apps/github-app/.env.example

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ LOG_LEVEL=debug
1010
WEBHOOK_PROXY_URL=
1111

1212
# Tailchat
13-
TAILCHAT_API_URL=https://paw-server-nightly.moonrailgun.com
13+
TAILCHAT_WEB_URL=https://nightly.paw.msgbyte.com
14+
TAILCHAT_API_URL=https://tailchat-nightly.moonrailgun.com
1415
TAILCHAT_APP_ID=
1516
TAILCHAT_APP_SECRET=

apps/github-app/api/github/webhooks/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// Reference: https://probot.github.io/docs/deployment/#vercel
33

44
const { createNodeMiddleware, createProbot } = require('probot');
5-
const app = require('../../../src/app').app;
5+
const appFn = require('../../../src/app').appFn;
66

7-
module.exports = createNodeMiddleware(app, {
7+
module.exports = createNodeMiddleware(appFn, {
88
probot: createProbot(),
99
webhooksPath: '/api/github/webhooks',
1010
});

apps/github-app/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919
},
2020
"dependencies": {
2121
"axios": "^0.21.1",
22+
"body-parser": "^1.20.1",
2223
"dotenv": "^16.0.3",
23-
"probot": "^12.2.4",
24+
"lodash": "^4.17.21",
25+
"probot": "^12.3.0",
2426
"probot-metadata": "^2.1.0"
2527
},
2628
"devDependencies": {
29+
"@types/body-parser": "^1.19.2",
2730
"@types/jest": "^28.1.0",
31+
"@types/lodash": "^4.14.191",
2832
"@types/node": "^18.0.0",
2933
"jest": "27.5.1",
3034
"nock": "^13.0.5",

apps/github-app/src/app.ts

Lines changed: 108 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1-
import { Probot } from 'probot';
1+
import { ApplicationFunction, Probot } from 'probot';
22
import metadata from 'probot-metadata';
33
import { TailchatClient } from './client';
4-
import { configPath, generateErrorBlock } from './utils';
4+
import {
5+
configPath,
6+
generateErrorBlock,
7+
generateTopicCommentCreateContent,
8+
generateTopicCreateContent,
9+
} from './utils';
10+
import bodyParser from 'body-parser';
11+
import _ from 'lodash';
512
import * as dotenv from 'dotenv'; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
613
dotenv.config();
714

@@ -24,7 +31,7 @@ const tailchatAppSecret = process.env.TAILCHAT_APP_SECRET;
2431
const tailchatWebUrl =
2532
process.env.TAILCHAT_WEB_URL || process.env.TAILCHAT_API_URL;
2633

27-
export function app(app: Probot) {
34+
export const appFn: ApplicationFunction = (app, { getRouter }) => {
2835
app.on('issues.opened', async (ctx) => {
2936
if (ctx.isBot) {
3037
return;
@@ -54,12 +61,15 @@ export function app(app: Probot) {
5461
{
5562
groupId,
5663
panelId,
57-
content: `[b]${
58-
ctx.payload.issue.user.login
59-
}[/b] create Issue:\n\nTitle: ${ctx.payload.issue.title}\n[markdown]${
60-
ctx.payload.issue.body ?? ''
61-
}[/markdown]\n\nWebsite: ${ctx.payload.issue.html_url}`,
64+
content: generateTopicCreateContent(
65+
ctx.payload.issue.user.login,
66+
ctx.payload.issue.title,
67+
ctx.payload.issue.body ?? '',
68+
ctx.payload.issue.html_url
69+
),
6270
meta: {
71+
tailchatHost: tailchatClient.url,
72+
installationId: ctx.payload.installation?.id,
6373
githubRepoOwner: ctx.payload.repository.owner.login,
6474
githubRepoName: ctx.payload.repository.name,
6575
githubIssueNumber: ctx.payload.issue.number,
@@ -130,11 +140,11 @@ export function app(app: Probot) {
130140
groupId,
131141
panelId,
132142
topicId,
133-
content: `[b]${
134-
ctx.payload.comment.user.login
135-
}[/b] reply Issue:\n\n[markdown]${
136-
ctx.payload.comment.body ?? ''
137-
}[/markdown]\n\nWebsite: ${ctx.payload.comment.html_url}`,
143+
content: generateTopicCommentCreateContent(
144+
ctx.payload.comment.user.login,
145+
ctx.payload.comment.body ?? '',
146+
ctx.payload.comment.html_url
147+
),
138148
});
139149
} catch (err) {
140150
console.error(err);
@@ -158,7 +168,9 @@ export function app(app: Probot) {
158168
// installationTargetRepositories,
159169
// });
160170
// });
161-
}
171+
172+
buildRouter(app, getRouter);
173+
};
162174

163175
/**
164176
* 从配置文件中创建上下文
@@ -168,23 +180,99 @@ export function app(app: Probot) {
168180
function createTailchatContextWithConfig(githubRaw: string) {
169181
const content = Buffer.from(githubRaw, 'base64').toString();
170182
const json = JSON.parse(content);
171-
const tailchatHost = json['tailchatHost'];
183+
const tailchatHost = json['tailchatHost'] ?? defaultTailchatApiUrl;
172184
const groupId = json['groupId'];
173185
const panelId = json['panelId'];
174186

175187
if (!groupId || !panelId) {
176188
throw new Error('config format error');
177189
}
178190

179-
const tailchatClient = new TailchatClient(
180-
tailchatHost ?? defaultTailchatApiUrl,
181-
tailchatAppId,
182-
tailchatAppSecret
183-
);
191+
const tailchatClient = createTailchatClient(tailchatHost);
184192

185193
return {
186194
tailchatClient,
187195
groupId,
188196
panelId,
189197
};
190198
}
199+
200+
function createTailchatClient(tailchatHost = defaultTailchatApiUrl) {
201+
const tailchatClient = new TailchatClient(
202+
tailchatHost,
203+
tailchatAppId,
204+
tailchatAppSecret
205+
);
206+
207+
return tailchatClient;
208+
}
209+
210+
function buildRouter(
211+
app: Probot,
212+
getRouter: Parameters<ApplicationFunction>[1]['getRouter']
213+
) {
214+
if (getRouter) {
215+
getRouter('/')
216+
.get('/', (_req, res) => {
217+
res.send('Hello World! Github app server is working!');
218+
})
219+
.post('/message/webhook', bodyParser.json(), (req, res) => {
220+
(async () => {
221+
try {
222+
// 根据收件箱内容向 Github Issue 创建话题
223+
const inboxItem = req.body ?? {};
224+
if (inboxItem.type !== 'plugin:com.msgbyte.topic.comment') {
225+
// 如果不是回复消息,则跳过
226+
return;
227+
}
228+
229+
const newComment: any =
230+
_.last(_.get(inboxItem, ['payload', 'comments'])) ?? {};
231+
const meta = _.get(inboxItem, ['payload', 'meta']) ?? {};
232+
if (
233+
!meta.installationId ||
234+
!meta.githubRepoOwner ||
235+
!meta.githubRepoName ||
236+
!meta.githubIssueNumber
237+
) {
238+
console.warn('Cannot pass meta info check:', { meta });
239+
return;
240+
}
241+
if (!newComment.author || !newComment.content) {
242+
console.warn(
243+
'Cannot get "newComment.author" or "newComment.content"'
244+
);
245+
return;
246+
}
247+
248+
// 发送到github comment
249+
const octokit = await app.auth(Number(meta.installationId));
250+
const tailchatClient = createTailchatClient(meta.tailchatHost);
251+
const userInfo = await tailchatClient.call('user.getUserInfo', {
252+
userId: newComment.author,
253+
});
254+
255+
const payload = {
256+
owner: meta.githubRepoOwner,
257+
repo: meta.githubRepoName,
258+
issue_number: meta.githubIssueNumber,
259+
body: `[${_.get(userInfo, [
260+
'data',
261+
'nickname',
262+
])}] 在 Tailchat 回复:\n\`\`\`\n${
263+
newComment.content ?? ''
264+
}\n\`\`\``,
265+
};
266+
267+
console.log('正在向Github Issue创建回复:', payload);
268+
269+
await octokit.issues.createComment(payload);
270+
} catch (err) {
271+
console.error(err);
272+
}
273+
})();
274+
275+
res.send('Success!');
276+
});
277+
}
278+
}

apps/github-app/src/client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export class TailchatClient {
5151
console.log('tailchat openapp login success!');
5252

5353
// 尝试调用函数
54-
this.whoami().then(console.log);
54+
// this.whoami().then(console.log);
5555
} catch (err) {
5656
console.error(err);
5757
throw new Error('登录失败, 请检查应用凭证');

apps/github-app/src/index.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
11
import { run } from 'probot';
2-
import { app } from './app';
2+
import { appFn } from './app';
33

4-
run(app).then((server) => {
5-
server.router('/').get('/', (_req, res) => {
6-
res.send('Hello World! Github app server is working!');
7-
});
8-
});
4+
run(appFn);

apps/github-app/src/utils.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,33 @@ export function generateErrorBlock(err: unknown) {
1111

1212
return `Tailchat occur error, please checkout your config in \`${configPath}\`! \n${errorBlock}`;
1313
}
14+
15+
/**
16+
* 生成创建话题的内容
17+
*/
18+
export function generateTopicCreateContent(
19+
user: string,
20+
title: string,
21+
body: string,
22+
url: string
23+
) {
24+
return `[b]${user}[/b] create Issue:
25+
[b]Title: ${title}[/b]
26+
[markdown]${body}[/markdown]
27+
28+
Website: ${url}`;
29+
}
30+
31+
/**
32+
* 生成创建话题的内容
33+
*/
34+
export function generateTopicCommentCreateContent(
35+
user: string,
36+
body: string,
37+
url: string
38+
) {
39+
return `[b]${user}[/b] reply Issue:
40+
[markdown]${body}[/markdown]
41+
42+
Website: ${url}`;
43+
}

0 commit comments

Comments
 (0)