1- import { Probot } from 'probot' ;
1+ import { ApplicationFunction , Probot } from 'probot' ;
22import metadata from 'probot-metadata' ;
33import { 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' ;
512import * as dotenv from 'dotenv' ; // see https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import
613dotenv . config ( ) ;
714
@@ -24,7 +31,7 @@ const tailchatAppSecret = process.env.TAILCHAT_APP_SECRET;
2431const 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) {
168180function 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+ }
0 commit comments