2017-02-11 21:27:47 +00:00
import * as EventEmitter from 'events' ;
2017-01-31 15:12:49 +00:00
import * as express from 'express' ;
2017-02-11 21:39:37 +00:00
const crypto = require ( 'crypto' ) ;
2017-01-31 15:43:06 +00:00
import User from '../models/user' ;
2018-03-28 16:20:40 +00:00
import config from '../../../conf' ;
import queue from '../../../queue' ;
2017-01-31 15:12:49 +00:00
2017-01-31 15:43:06 +00:00
module . exports = async ( app : express.Application ) = > {
2017-01-31 15:12:49 +00:00
if ( config . github_bot == null ) return ;
2017-01-31 15:43:06 +00:00
const bot = await User . findOne ( {
username_lower : config.github_bot.username.toLowerCase ( )
} ) ;
if ( bot == null ) {
console . warn ( ` GitHub hook bot specified, but not found: @ ${ config . github_bot . username } ` ) ;
return ;
}
const post = text = > require ( '../endpoints/posts/create' ) ( { text } , bot ) ;
2017-02-11 21:27:47 +00:00
const handler = new EventEmitter ( ) ;
2017-01-31 15:12:49 +00:00
2017-02-11 21:27:47 +00:00
app . post ( '/hooks/github' , ( req , res , next ) = > {
2017-08-10 13:06:47 +00:00
// req.headers['x-hub-signature'] および
// req.headers['x-github-event'] は常に string ですが、型定義の都合上
// string | string[] になっているので string を明示しています
2018-03-28 16:20:40 +00:00
// if ((new Buffer(req.headers['x-hub-signature'] as string)).equals(new Buffer(`sha1=${crypto.createHmac('sha1', config.github_bot.hook_secret).update(JSON.stringify(req.body)).digest('hex')}`))) {
2017-08-10 13:06:47 +00:00
handler . emit ( req . headers [ 'x-github-event' ] as string , req . body ) ;
2017-02-16 11:08:28 +00:00
res . sendStatus ( 200 ) ;
2018-03-28 16:20:40 +00:00
// } else {
// res.sendStatus(400);
// }
2017-02-11 21:27:47 +00:00
} ) ;
2017-01-31 15:12:49 +00:00
2017-03-17 16:42:43 +00:00
handler . on ( 'status' , event = > {
const state = event . state ;
switch ( state ) {
2017-03-31 11:24:14 +00:00
case 'error' :
2017-03-17 16:42:43 +00:00
case 'failure' :
2017-03-17 16:51:08 +00:00
const commit = event . commit ;
2017-03-17 20:42:07 +00:00
const parent = commit . parents [ 0 ] ;
2018-03-28 16:20:40 +00:00
queue . create ( 'gitHubFailureReport' , {
userId : bot._id ,
parentUrl : parent.url ,
htmlUrl : commit.html_url ,
message : commit.commit.message ,
} ) . save ( ) ;
2017-03-17 16:42:43 +00:00
break ;
}
} ) ;
2017-01-31 19:25:02 +00:00
handler . on ( 'push' , event = > {
2017-02-11 21:44:16 +00:00
const ref = event . ref ;
2017-03-14 00:37:07 +00:00
switch ( ref ) {
case 'refs/heads/master' :
const pusher = event . pusher ;
const compare = event . compare ;
2017-03-16 15:21:32 +00:00
const commits = event . commits ;
post ( [
2017-03-17 16:22:28 +00:00
` Pushed by ** ${ pusher . name } ** with ?[ ${ commits . length } commit ${ commits . length > 1 ? 's' : '' } ]( ${ compare } ): ` ,
2017-03-17 17:47:55 +00:00
commits . reverse ( ) . map ( commit = > ` ・[?[ ${ commit . id . substr ( 0 , 7 ) } ]( ${ commit . url } )] ${ commit . message . split ( '\n' ) [ 0 ] } ` ) . join ( '\n' ) ,
2017-03-16 15:21:32 +00:00
] . join ( '\n' ) ) ;
2017-03-14 00:37:07 +00:00
break ;
case 'refs/heads/release' :
const commit = event . commits [ 0 ] ;
2017-03-16 15:21:32 +00:00
post ( ` RELEASED: ${ commit . message } ` ) ;
2017-03-14 00:37:07 +00:00
break ;
}
2017-01-31 15:12:49 +00:00
} ) ;
2017-01-31 15:43:06 +00:00
handler . on ( 'issues' , event = > {
2017-02-11 21:44:16 +00:00
const issue = event . issue ;
const action = event . action ;
2017-01-31 15:43:06 +00:00
let title : string ;
2017-01-31 19:07:30 +00:00
switch ( action ) {
2017-03-26 12:34:04 +00:00
case 'opened' : title = 'Issue opened' ; break ;
case 'closed' : title = 'Issue closed' ; break ;
case 'reopened' : title = 'Issue reopened' ; break ;
2017-01-31 16:04:32 +00:00
default : return ;
2017-01-31 15:43:06 +00:00
}
2017-03-14 00:37:07 +00:00
post ( ` ${ title } : < ${ issue . number } >「 ${ issue . title } 」 \ n ${ issue . html_url } ` ) ;
2017-01-31 15:43:06 +00:00
} ) ;
2017-01-31 19:25:02 +00:00
handler . on ( 'issue_comment' , event = > {
2017-02-11 21:44:16 +00:00
const issue = event . issue ;
const comment = event . comment ;
const action = event . action ;
2017-01-31 19:25:02 +00:00
let text : string ;
switch ( action ) {
2017-03-14 00:37:07 +00:00
case 'created' : text = ` Commented to「 ${ issue . title } 」: ${ comment . user . login } 「 ${ comment . body } 」 \ n ${ comment . html_url } ` ; break ;
2017-01-31 19:25:02 +00:00
default : return ;
}
post ( text ) ;
} ) ;
2017-02-17 01:25:23 +00:00
handler . on ( 'watch' , event = > {
2017-02-11 21:44:16 +00:00
const sender = event . sender ;
2017-08-28 17:56:07 +00:00
post ( ` ⭐️ Starred by ** ${ sender . login } ** ⭐️ ` ) ;
2017-02-07 14:52:58 +00:00
} ) ;
2017-01-31 19:25:02 +00:00
handler . on ( 'fork' , event = > {
2017-02-11 21:44:16 +00:00
const repo = event . forkee ;
2017-08-28 17:56:07 +00:00
post ( ` 🍴 Forked: \ n ${ repo . html_url } 🍴 ` ) ;
2017-01-31 19:25:02 +00:00
} ) ;
handler . on ( 'pull_request' , event = > {
2017-02-11 21:44:16 +00:00
const pr = event . pull_request ;
const action = event . action ;
2017-01-31 19:25:02 +00:00
let text : string ;
switch ( action ) {
case 'opened' : text = ` New Pull Request:「 ${ pr . title } 」 \ n ${ pr . html_url } ` ; break ;
case 'reopened' : text = ` Pull Request Reopened:「 ${ pr . title } 」 \ n ${ pr . html_url } ` ; break ;
case 'closed' :
text = pr . merged
? ` Pull Request Merged!:「 ${ pr . title } 」 \ n ${ pr . html_url } `
: ` Pull Request Closed:「 ${ pr . title } 」 \ n ${ pr . html_url } ` ;
break ;
default : return ;
}
post ( text ) ;
} ) ;
2017-01-31 15:12:49 +00:00
} ;