autobounty/index.js

121 lines
3.7 KiB
JavaScript
Raw Normal View History

2017-06-10 15:07:15 +00:00
/*
2018-01-22 11:24:19 +00:00
* Bot that receives a POST request (from a GitHub issue comment webhook)
* and in case it's a comment that has "@autobounty <decimal> <currency>"
* awards that bounty to the address posted earlier in the thread (by the
* commiteth bot).
* REVIEW parsing, non-persisting storage of addresses, hardcoded string length.
* Depends on commiteth version as of 2017-06-10.
*/
2018-03-19 21:37:38 +00:00
const config = require('./config')
const bot = require('./bot')
const crypto = require('crypto')
2018-02-10 18:55:24 +00:00
2018-01-17 16:48:56 +00:00
2017-06-09 10:15:53 +00:00
var express = require('express'),
2018-01-23 15:36:34 +00:00
cors = require('cors'),
helmet = require('helmet'),
app = express(),
bodyParser = require('body-parser'),
2018-03-19 21:37:38 +00:00
jsonParser = bodyParser.json()
2017-03-07 11:24:01 +00:00
2018-03-19 21:37:38 +00:00
app.use(cors())
app.use(helmet())
2018-01-17 16:48:56 +00:00
// Receive a POST request at the url specified by an env. var.
2018-01-23 15:36:34 +00:00
app.post(`${config.urlEndpoint}`, jsonParser, function (req, res, next) {
if (!req.body || !req.body.action) {
2018-03-19 21:37:38 +00:00
return res.sendStatus(400)
} else if (!bot.needsFunding(req)) {
2018-03-19 21:37:38 +00:00
return res.sendStatus(204)
}
2018-03-19 21:37:38 +00:00
validation = validateRequest(req)
2018-02-10 18:55:24 +00:00
if (validation.correct) {
setTimeout(() => {
processRequest(req)
.then(() => {
2018-03-19 21:37:38 +00:00
bot.info('issue well funded: ' + req.body.issue.url)
2018-02-10 18:55:24 +00:00
})
.catch((err) => {
2018-03-19 21:37:38 +00:00
bot.error('Error processing request: ' + req.body.issue.url)
bot.error('Error: ' + err)
bot.error('Dump: ', req.body)
})
}, config.delayInMiliSeconds)
2018-02-10 18:55:24 +00:00
} else {
2018-03-19 21:37:38 +00:00
bot.error('Error validating issue: ' + req.body.issue.url)
bot.error('Error: ' + validation.error)
2018-02-10 18:55:24 +00:00
}
2018-03-19 21:37:38 +00:00
return res.sendStatus(200)
})
2018-02-10 18:55:24 +00:00
const validateRequest = function (req) {
2018-03-19 21:37:38 +00:00
validation = {correct: false, error: ''}
webhookSecret = process.env.WEBHOOK_SECRET
2018-02-10 18:55:24 +00:00
if(!webhookSecret) {
validation.error = 'Github Webhook Secret key not found. ' +
2018-03-19 21:37:38 +00:00
'Please set env variable WEBHOOK_SECRET to github\'s webhook secret value'
2018-02-10 18:55:24 +00:00
} else {
2018-03-19 21:37:38 +00:00
const blob = JSON.stringify(req.body)
const hmac = crypto.createHmac('sha1', webhookSecret)
const ourSignature = `sha1=${hmac.update(blob).digest('hex')}`
2018-02-10 18:55:24 +00:00
2018-03-19 21:37:38 +00:00
const theirSignature = req.get('X-Hub-Signature')
2018-02-10 18:55:24 +00:00
2018-03-19 21:37:38 +00:00
const bufferA = Buffer.from(ourSignature, 'utf8')
const bufferB = Buffer.from(theirSignature, 'utf8')
2018-02-10 18:55:24 +00:00
2018-03-19 21:37:38 +00:00
const safe = crypto.timingSafeEqual(bufferA, bufferB)
2018-02-10 18:55:24 +00:00
if (safe) {
2018-03-19 21:37:38 +00:00
validation.correct = true
2018-02-10 18:55:24 +00:00
} else {
validation.error = 'Invalid signature. Check that WEBHOOK_SECRET ' +
2018-03-19 21:37:38 +00:00
'env variable matches github\'s webhook secret value'
2018-02-10 18:55:24 +00:00
}
}
2018-03-19 21:37:38 +00:00
return validation
2018-02-10 18:55:24 +00:00
}
const processRequest = function (req) {
2018-03-19 21:37:38 +00:00
// const wallet = bot.wallet
2018-02-10 18:55:24 +00:00
2018-03-19 21:37:38 +00:00
const from = config.sourceAddress
const to = bot.getAddress(req)
// Asynchronous requests for Gas Price and Amount
2018-03-19 21:37:38 +00:00
const amountPromise = bot.getAmount(req)
const gasPricePromise = bot.getGasPrice()
return new Promise((resolve, reject) => {
2018-01-25 12:02:47 +00:00
Promise.all([amountPromise, gasPricePromise])
.then(function (results) {
2018-03-19 21:37:38 +00:00
const amount = results[0]
const gasPrice = results[1]
2018-02-13 12:05:39 +00:00
bot.sendTransaction(to, amount, gasPrice)
.then(function (hash) {
2018-03-19 21:37:38 +00:00
bot.logTransaction(hash)
resolve()
})
.catch(function (err) {
2018-03-19 21:37:38 +00:00
reject(err)
})
})
.catch(function (err) {
2018-03-19 21:37:38 +00:00
reject(err)
})
})
}
2017-03-07 11:24:01 +00:00
const port = process.env.PORT || 8181
2018-01-23 15:36:34 +00:00
app.listen(port, function () {
2018-03-19 21:37:38 +00:00
bot.info('Autobounty listening on port', port)
})