@@ -5,8 +5,10 @@ type GitHubSchema = components['schemas'];
55
66type GitHubUser = GitHubSchema [ 'simple-user' ] ;
77
8- interface GitHubAction
9- extends Record < 'event_name' | 'actor' | 'server_url' | 'repository' , string > {
8+ interface GitHubAction extends Record <
9+ 'event_name' | 'actor' | 'server_url' | 'repository' ,
10+ string
11+ > {
1012 action ?: string ;
1113 ref ?: string ;
1214 ref_name ?: string ;
@@ -21,148 +23,201 @@ interface GitHubAction
2123}
2224
2325// Helper functions
24- const getActionText = ( action ?: string ) =>
25- action === 'closed' ? '关闭' : action ?. includes ( 'open' ) ? '打开' : '编辑' ;
26-
27- const createLink = ( href : string , text = href ) => ( { tag : 'a' , href, text } ) ;
28-
29- const createText = ( text : string ) => ( { tag : 'text' , text } ) ;
30-
31- // create user link
32- const createUserLink = ( user : GitHubUser ) =>
33- user ? createLink ( user . html_url , user . login ) : createText ( '无' ) ;
26+ const ACTION_TEXT_MAP : Record < string , string > = {
27+ created : '创建' ,
28+ opened : '创建' ,
29+ submitted : '创建' ,
30+ closed : '关闭' ,
31+ reopened : '重新打开' ,
32+ labeled : '添加标签' ,
33+ unlabeled : '移除标签' ,
34+ assigned : '指派' ,
35+ unassigned : '取消指派' ,
36+ edited : '编辑' ,
37+ deleted : '删除' ,
38+ synchronize : '更新' ,
39+ review_requested : '请求审核' ,
40+ } ;
3441
35- const createContentItem = (
36- label : string ,
37- value ?: string | { tag : string ; text : string } ,
38- ) =>
39- [
40- createText ( label ) ,
41- typeof value === 'string'
42- ? createText ( value || '无' )
43- : value || createText ( '无' ) ,
44- ] as [ object , object ] ;
42+ const getActionText = ( action ?: string ) => ( action ? ACTION_TEXT_MAP [ action ] || action : '编辑' ) ;
43+
44+ const createLink = ( href : string , text = href ) => `[${ text } ](${ href } )` ;
45+
46+ const createUserLink = ( user : any ) => ( user ? createLink ( user . html_url , user . login ) : '无' ) ;
47+
48+ // Convert GitHub markdown to Lark card supported format
49+ const sanitizeMarkdown = ( text : string ) : string =>
50+ text
51+ // Remove code blocks
52+ . replace ( / ` ` ` [ \s \S ] * ?` ` ` / g, '[代码块]' )
53+ // Remove inline code
54+ . replace ( / ` [ ^ ` ] + ` / g, match => match . slice ( 1 , - 1 ) )
55+ // Convert images to link text
56+ . replace ( / ! \[ ( [ ^ \] ] * ) \] \( ( [ ^ ) ] + ) \) / g, '🖼️ [$1]($2)' )
57+ // Convert ### headers to bold
58+ . replace ( / ^ # # # \s + ( .+ ) $ / gm, '**$1**' )
59+ // Convert ## headers to bold
60+ . replace ( / ^ # # \s + ( .+ ) $ / gm, '**$1**' )
61+ // Convert # headers to bold
62+ . replace ( / ^ # \s + ( .+ ) $ / gm, '**$1**' )
63+ // Remove HTML comments
64+ . replace ( / < ! - - [ \s \S ] * ?- - > / g, '' )
65+ // Remove HTML tags (keep content)
66+ . replace ( / < [ ^ > ] + > / g, '' )
67+ // Remove excess empty lines
68+ . replace ( / \n { 3 , } / g, '\n\n' )
69+ // Truncate long content
70+ . slice ( 0 , 800 ) + ( text . length > 800 ? '\n...' : '' ) ;
71+
72+ const createContentItem = ( label : string , value ?: string ) =>
73+ `**${ label } ** ${ value ? sanitizeMarkdown ( value ) : '无' } ` ;
74+
75+ interface LarkMessageElement {
76+ tag : string ;
77+ content : string | [ object , object ] [ ] ;
78+ }
4579
4680type EventHandler = (
4781 event : GitHubAction ,
4882 actionText : string ,
4983) => {
5084 title : string ;
51- content : [ object , object ] [ ] ;
85+ elements : LarkMessageElement [ ] ;
5286} ;
5387
5488// Event handlers
5589const eventHandlers : Record < string , EventHandler > = {
56- push : ( {
57- event : { head_commit } ,
58- ref,
59- ref_name,
60- server_url,
61- repository,
62- actor,
63- } ) => ( {
64- title : 'GitHub 代码提交' ,
65- content : [
66- [ createText ( '提交链接:' ) , createLink ( head_commit ! . url ) ] ,
67- [
68- createText ( '代码分支:' ) ,
69- createLink ( `${ server_url } /${ repository } /tree/${ ref_name } ` , ref ) ,
90+ push : ( { event : { head_commit } , ref, ref_name, server_url, repository, actor } ) => {
91+ const commitUrl = head_commit ?. url || `${ server_url } /${ repository } /tree/${ ref_name } ` ;
92+ const commitMessage = head_commit ?. message || 'Create/Delete/Update Branch (No head commit)' ;
93+
94+ return {
95+ title : 'GitHub 代码提交' ,
96+ elements : [
97+ {
98+ tag : 'markdown' ,
99+ content : [
100+ createContentItem ( '提交链接:' , createLink ( commitUrl ) ) ,
101+ createContentItem (
102+ '代码分支:' ,
103+ createLink ( `${ server_url } /${ repository } /tree/${ ref_name } ` , ref_name ) ,
104+ ) ,
105+ createContentItem ( '提交作者:' , createLink ( `${ server_url } /${ actor } ` , actor ) ) ,
106+ createContentItem ( '提交信息:' , commitMessage ) ,
107+ ] . join ( '\n' ) ,
108+ } ,
70109 ] ,
71- [ createText ( '提交作者:' ) , createLink ( `${ server_url } /${ actor } ` , actor ) ] ,
72- [ createText ( '提交信息:' ) , createText ( head_commit ! . message ) ] ,
73- ] ,
74- } ) ,
110+ } ;
111+ } ,
75112
76113 issues : ( { event : { issue } } , actionText ) => ( {
77114 title : `GitHub issue ${ actionText } :${ issue ?. title } ` ,
78- content : [
79- [ createText ( '链接:' ) , createLink ( issue ! . html_url ) ] ,
80- [
81- createText ( '作者:' ) ,
82- createLink ( issue ! . user ! . html_url ! , issue ! . user ! . login ) ,
83- ] ,
84- [
85- createText ( '指派:' ) ,
86- issue ?. assignee
87- ? createLink ( issue . assignee . html_url ! , issue . assignee . login )
88- : createText ( '无' ) ,
89- ] ,
90- [
91- createText ( '标签:' ) ,
92- createText ( issue ?. labels ?. map ( ( { name } ) => name ) . join ( ', ' ) || '无' ) ,
93- ] ,
94- [ createText ( '里程碑:' ) , createText ( issue ?. milestone ?. title || '无' ) ] ,
95- [ createText ( '描述:' ) , createText ( issue ?. body || '无' ) ] ,
115+ elements : [
116+ {
117+ tag : 'markdown' ,
118+ content : [
119+ createContentItem ( '链接:' , createLink ( issue ! . html_url ) ) ,
120+ createContentItem ( '作者:' , createUserLink ( issue ! . user ! ) ) ,
121+ createContentItem ( '指派:' , issue ?. assignee ? createUserLink ( issue . assignee ) : '无' ) ,
122+ createContentItem ( '标签:' , issue ?. labels ?. map ( ( { name } ) => name ) . join ( ', ' ) || '无' ) ,
123+ createContentItem ( '里程碑:' , issue ?. milestone ?. title || '无' ) ,
124+ createContentItem ( '描述:' , issue ?. body || '无' ) ,
125+ ] . join ( '\n' ) ,
126+ } ,
96127 ] ,
97128 } ) ,
98129
99130 pull_request : ( { event : { pull_request } } , actionText ) => ( {
100131 title : `GitHub PR ${ actionText } :${ pull_request ?. title } ` ,
101- content : [
102- [ createText ( '链接:' ) , createLink ( pull_request ! . html_url ) ] ,
103- [
104- createText ( '作者:' ) ,
105- createLink ( pull_request ! . user . html_url , pull_request ! . user . login ) ,
106- ] ,
107- [
108- createText ( '指派:' ) ,
109- pull_request ?. assignee
110- ? createLink (
111- pull_request . assignee . html_url ,
112- pull_request . assignee . login ,
113- )
114- : createText ( '无' ) ,
115- ] ,
116- [
117- createText ( '标签:' ) ,
118- createText (
119- pull_request ?. labels ?. map ( ( { name } ) => name ) . join ( ', ' ) || '无' ,
120- ) ,
121- ] ,
122- [
123- createText ( '里程碑:' ) ,
124- createText ( pull_request ?. milestone ?. title || '无' ) ,
125- ] ,
126- [ createText ( '描述:' ) , createText ( pull_request ?. body || '无' ) ] ,
132+ elements : [
133+ {
134+ tag : 'markdown' ,
135+ content : [
136+ createContentItem ( '链接:' , createLink ( pull_request ! . html_url ) ) ,
137+ createContentItem ( '作者:' , createUserLink ( pull_request ! . user ) ) ,
138+ createContentItem (
139+ '指派:' ,
140+ pull_request ?. assignee ? createUserLink ( pull_request . assignee ) : '无' ,
141+ ) ,
142+ createContentItem (
143+ '标签:' ,
144+ pull_request ?. labels ?. map ( ( { name } ) => name ) . join ( ', ' ) || '无' ,
145+ ) ,
146+ createContentItem ( '里程碑:' , pull_request ?. milestone ?. title || '无' ) ,
147+ createContentItem ( '描述:' , pull_request ?. body || '无' ) ,
148+ ] . join ( '\n' ) ,
149+ } ,
127150 ] ,
128151 } ) ,
129152
130153 discussion : ( { event : { discussion } } , actionText ) => ( {
131154 title : `GitHub 讨论 ${ actionText } :${ discussion ?. title || '无' } ` ,
132- content : [
133- createContentItem ( '链接:' , discussion ?. html_url ) ,
134- createContentItem (
135- '作者:' ,
136- createUserLink ( discussion ! . user as GitHubUser ) ,
137- ) ,
138- createContentItem ( '描述:' , discussion ?. body || '无' ) ,
155+ elements : [
156+ {
157+ tag : 'markdown' ,
158+ content : [
159+ createContentItem ( '链接:' , createLink ( discussion ! . html_url ) ) ,
160+ createContentItem ( '作者:' , createUserLink ( discussion ! . user as GitHubUser ) ) ,
161+ createContentItem ( '描述:' , discussion ?. body || '无' ) ,
162+ ] . join ( '\n' ) ,
163+ } ,
139164 ] ,
140165 } ) ,
141166
142167 issue_comment : ( { event : { comment, issue } } ) => ( {
143168 title : `GitHub issue 评论:${ issue ?. title || '未知 issue' } ` ,
144- content : [
145- createContentItem ( '链接:' , comment ?. html_url ) ,
146- createContentItem ( '作者:' , createUserLink ( comment ! . user ! ) ) ,
147- createContentItem ( '描述:' , comment ?. body || '无' ) ,
169+ elements : [
170+ {
171+ tag : 'markdown' ,
172+ content : [
173+ createContentItem ( '链接:' , createLink ( comment ! . html_url ) ) ,
174+ createContentItem ( '作者:' , createUserLink ( comment ! . user ! ) ) ,
175+ createContentItem ( '描述:' , comment ?. body || '无' ) ,
176+ ] . join ( '\n' ) ,
177+ } ,
148178 ] ,
149179 } ) ,
150180
151181 discussion_comment : ( { event : { comment, discussion } } ) => ( {
152182 title : `GitHub 讨论评论:${ discussion ?. title || '无' } ` ,
153- content : [
154- createContentItem ( '链接:' , comment ?. html_url ) ,
155- createContentItem ( '作者:' , createUserLink ( comment ! . user ! ) ) ,
156- createContentItem ( '描述:' , comment ?. body || '无' ) ,
183+ elements : [
184+ {
185+ tag : 'markdown' ,
186+ content : [
187+ createContentItem ( '链接:' , createLink ( comment ! . html_url ) ) ,
188+ createContentItem ( '作者:' , createUserLink ( comment ! . user ! ) ) ,
189+ createContentItem ( '描述:' , comment ?. body || '无' ) ,
190+ ] . join ( '\n' ) ,
191+ } ,
157192 ] ,
158193 } ) ,
159194
160195 release : ( { event : { release } } ) => ( {
161196 title : `GitHub Release 发布:${ release ! . name || release ! . tag_name } ` ,
162- content : [
163- createContentItem ( '链接:' , release ! . html_url ) ,
164- createContentItem ( '作者:' , createUserLink ( release ! . author ) ) ,
165- createContentItem ( '描述:' , release ! . body ! ) ,
197+ elements : [
198+ {
199+ tag : 'markdown' ,
200+ content : [
201+ createContentItem ( '链接:' , createLink ( release ! . html_url ) ) ,
202+ createContentItem ( '作者:' , createUserLink ( release ! . author ) ) ,
203+ createContentItem ( '描述:' , release ?. body || '无' ) ,
204+ ] . join ( '\n' ) ,
205+ } ,
206+ ] ,
207+ } ) ,
208+
209+ pull_request_review_comment : ( { event : { comment, pull_request } } ) => ( {
210+ title : `GitHub PR 代码评论:${ pull_request ?. title || '未知 PR' } ` ,
211+ elements : [
212+ {
213+ tag : 'markdown' ,
214+ content : [
215+ createContentItem ( '链接:' , createLink ( comment ! . html_url ) ) ,
216+ createContentItem ( '作者:' , createUserLink ( comment ! . user ! ) ) ,
217+ createContentItem ( 'PR:' , createLink ( pull_request ! . html_url , `#${ pull_request ! . number } ` ) ) ,
218+ createContentItem ( '评论:' , comment ?. body || '无' ) ,
219+ ] . join ( '\n' ) ,
220+ } ,
166221 ] ,
167222 } ) ,
168223} ;
@@ -178,19 +233,23 @@ const processEvent = (event: GitHubAction) => {
178233 try {
179234 return handler ( event , actionText ) ;
180235 } catch ( cause ) {
181- throw new Error (
182- `Error processing ${ event_name } event: ${ ( cause as Error ) . message } ` ,
183- { cause } ,
184- ) ;
236+ throw new Error ( `Error processing ${ event_name } event: ${ ( cause as Error ) . message } ` , { cause } ) ;
185237 }
186238} ;
187239
188- // Main execution:Processing GitHub Events and Outputting Results
240+ // Main execution
189241const event = JSON . parse ( ( await stdin ( ) ) || '{}' ) as GitHubAction ;
190- const zh_cn = processEvent ( event ) ;
191-
192- if ( zh_cn ) console . log ( JSON . stringify ( { post : { zh_cn } } ) ) ;
193- else
194- throw new Error (
195- `Unsupported ${ event . event_name } event & ${ event . action } action` ,
196- ) ;
242+ const result = processEvent ( event ) ;
243+
244+ if ( ! result ) throw new Error ( `Unsupported ${ event . event_name } event & ${ event . action } action` ) ;
245+
246+ const card = {
247+ schema : '2.0' ,
248+ config : { wide_screen_mode : true } ,
249+ header : {
250+ title : { tag : 'plain_text' , content : result . title } ,
251+ template : 'blue' ,
252+ } ,
253+ body : { elements : result . elements } ,
254+ } ;
255+ console . log ( JSON . stringify ( card ) ) ;
0 commit comments