diff --git a/apps/github-app/package.json b/apps/github-app/package.json index ebffc4f4..8c05763e 100644 --- a/apps/github-app/package.json +++ b/apps/github-app/package.json @@ -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", diff --git a/apps/github-app/src/app.ts b/apps/github-app/src/app.ts index afab7eb9..be276828 100644 --- a/apps/github-app/src/app.ts +++ b/apps/github-app/src/app.ts @@ -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) => { diff --git a/apps/github-app/src/client.ts b/apps/github-app/src/client.ts index da4abecf..6f67549a 100644 --- a/apps/github-app/src/client.ts +++ b/apps/github-app/src/client.ts @@ -4,6 +4,7 @@ import crypto from 'crypto'; export class TailchatClient { request: AxiosInstance; jwt: string | null = null; + loginP: Promise; 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() { diff --git a/apps/github-app/src/utils.ts b/apps/github-app/src/utils.ts new file mode 100644 index 00000000..5c623df1 --- /dev/null +++ b/apps/github-app/src/utils.ts @@ -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}`; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9eb82319..93fe06d9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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'} diff --git a/server/plugins/com.msgbyte.topic/services/topic.service.ts b/server/plugins/com.msgbyte.topic/services/topic.service.ts index f00b51de..dcec56d5 100644 --- a/server/plugins/com.msgbyte.topic/services/topic.service.ts +++ b/server/plugins/com.msgbyte.topic/services/topic.service.ts @@ -120,7 +120,7 @@ class GroupTopicService extends TcService { this.roomcastNotify(ctx, groupId, 'create', json); - return true; + return json; } /**