6 Commits

Author SHA1 Message Date
e9987b4d39 Remove network ID setting
Not needed anymore.
2019-04-24 13:32:14 +01:00
5a9edda1cd Add Gitea integration
Support for Gitea organization hooks, based on GitHub hooks code.

closes #24
2019-04-24 13:27:18 +01:00
2a3077d733 3.1.2 2019-04-17 11:14:11 +01:00
1255d7ce19 Fix another wrong const 2019-04-17 11:13:49 +01:00
d9e09ce041 3.1.1 2019-04-17 09:38:19 +01:00
a0f982432e Fix syntax error (variable re-assignment) 2019-04-17 09:38:00 +01:00
6 changed files with 190 additions and 19 deletions

View File

@@ -24,7 +24,6 @@ As usual in Hubot, you can add all config as environment variables.
| `KREDITS_WALLET_PATH` | Path to an Etherum wallet JSON file (default: `./wallet.json`) | | `KREDITS_WALLET_PATH` | Path to an Etherum wallet JSON file (default: `./wallet.json`) |
| `KREDITS_WALLET_PASSWORD` | Wallet password | | `KREDITS_WALLET_PASSWORD` | Wallet password |
| `KREDITS_PROVIDER_URL` | Ethereum JSON-RPC URL (default: `http://localhost:7545`) | | `KREDITS_PROVIDER_URL` | Ethereum JSON-RPC URL (default: `http://localhost:7545`) |
| `KREDITS_NETWORK_ID` | The ethereum network ID to use (default: 100 = local) |
## Integrations ## Integrations

View File

@@ -7,7 +7,6 @@ const Kredits = require('kredits-contracts');
const walletPath = process.env.KREDITS_WALLET_PATH || './wallet.json'; const walletPath = process.env.KREDITS_WALLET_PATH || './wallet.json';
const walletJson = fs.readFileSync(walletPath); const walletJson = fs.readFileSync(walletPath);
const providerUrl = process.env.KREDITS_PROVIDER_URL; const providerUrl = process.env.KREDITS_PROVIDER_URL;
const networkId = parseInt(process.env.KREDITS_NETWORK_ID || 100);
const ipfsConfig = { const ipfsConfig = {
host: process.env.IPFS_API_HOST || 'localhost', host: process.env.IPFS_API_HOST || 'localhost',
@@ -149,6 +148,7 @@ module.exports = async function(robot) {
// //
require('./integrations/github')(robot, kredits); require('./integrations/github')(robot, kredits);
require('./integrations/gitea')(robot, kredits);
if (typeof process.env.KREDITS_MEDIAWIKI_URL !== 'undefined') { if (typeof process.env.KREDITS_MEDIAWIKI_URL !== 'undefined') {
require('./integrations/mediawiki')(robot, kredits); require('./integrations/mediawiki')(robot, kredits);

179
integrations/gitea.js Normal file
View File

@@ -0,0 +1,179 @@
const util = require('util');
const fetch = require('node-fetch');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
module.exports = async function(robot, kredits) {
function messageRoom(message) {
robot.messageRoom(process.env.KREDITS_ROOM, message);
}
robot.logger.debug('[hubot-kredits] Loading Gitea integration...');
let repoBlackList = [];
if (process.env.KREDITS_GITEA_REPO_BLACKLIST) {
repoBlackList = process.env.KREDITS_GITEA_REPO_BLACKLIST.split(',');
robot.logger.debug('[hubot-kredits] Ignoring Gitea actions from ', util.inspect(repoBlackList));
}
const Contributor = kredits.Contributor;
const Contribution = kredits.Contribution;
function getContributorByGiteaUser(username) {
return Contributor.all().then(contributors => {
const contrib = contributors.find(c => {
return c.gitea_username === username;
});
if (!contrib) {
throw new Error(`No contributor found for ${username}`);
} else {
return contrib;
}
});
}
function createContribution(giteaUser, date, time, amount, description, url, details) {
return getContributorByGiteaUser(giteaUser).then(contributor => {
robot.logger.debug(`[hubot-kredits] Creating contribution token for ${amount}₭S to ${giteaUser} for ${url}...`);
const contributionAttr = {
contributorId: contributor.id,
contributorIpfsHash: contributor.ipfsHash,
date,
time,
amount,
url,
description,
details,
kind: 'dev'
};
return Contribution.addContribution(contributionAttr).catch(error => {
robot.logger.error(`[hubot-kredits] Error:`, error);
messageRoom(`I tried to add a contribution for ${giteaUser} for ${url}, but I encountered an error when submitting the tx:`);
messageRoom(error.message);
});
});
}
function amountFromLabels(labels) {
const kreditsLabel = labels.map(l => l.name)
.filter(n => n.match(/^kredits/))[0];
// No label, no kredits
if (typeof kreditsLabel === 'undefined') { return 0; }
// TODO move to config maybe?
let amount;
switch(kreditsLabel) {
case 'kredits-1':
amount = 500;
break;
case 'kredits-2':
amount = 1500;
break;
case 'kredits-3':
amount = 5000;
break;
}
return amount;
}
async function handleGiteaIssueClosed(data) {
const issue = data.issue;
const repoName = data.repository.full_name;
const web_url = `${data.repository.html_url}/issues/${issue.id}`;
const description = `${repoName}: ${issue.title}`;
const amount = amountFromLabels(issue.labels);
const assignees = issue.assignees ? issue.assignees.map(a => a.login) : [];
[ date, time ] = issue.closed_at.split('T');
if (amount === 0) {
robot.logger.info('[hubot-kredits] Kredits amount from issue label is zero; ignoring');
return Promise.resolve();
} else if (repoBlackList.includes(repoName)) {
robot.logger.debug(`[hubot-kredits] ${repoName} is on black list; ignoring`);
return Promise.resolve();
}
let recipients;
if (assignees.length > 0) {
recipients = assignees;
} else {
recipients = [issue.user.login];
}
for (const recipient of recipients) {
try {
await createContribution(recipient, date, time, amount, description, web_url,
{ issue, repository: data.repository });
await sleep(60000);
}
catch (err) { robot.logger.error(err); }
}
return Promise.resolve();
}
async function handleGiteaPullRequestClosed(data) {
const pull_request = data.pull_request;
const repoName = data.repository.full_name;
const web_url = pull_request.html_url;
const description = `${repoName}: ${pull_request.title}`;
const amount = amountFromLabels(pull_request.labels);
const assignees = pull_request.assignees ? pull_request.assignees.map(a => a.login) : [];
[ date, time ] = pull_request.merged_at.split('T');
if (amount === 0) {
robot.logger.info('[hubot-kredits] Kredits amount from issue label is zero; ignoring');
return Promise.resolve();
} else if (repoBlackList.includes(repoName)) {
robot.logger.debug(`[hubot-kredits] ${repoName} is on black list; ignoring`);
return Promise.resolve();
}
let recipients;
if (assignees.length > 0) {
recipients = assignees;
} else {
recipients = [pull_request.user.login];
}
for (const recipient of recipients) {
try {
await createContribution(recipient, date, time, amount, description, web_url,
{ pull_request, repository: data.repository });
await sleep(60000);
}
catch (err) { robot.logger.error(err); }
}
return Promise.resolve();
}
robot.router.post('/incoming/kredits/gitea/'+process.env.KREDITS_WEBHOOK_TOKEN, (req, res) => {
const evt = req.header('X-Gitea-Event');
let data = req.body;
// For some reason data is contained in a payload property on one
// machine, but directly in the root of the object on others
if (data.payload) { data = JSON.parse(data.payload); }
robot.logger.info(`Received Gitea hook. Event: ${evt}, action: ${data.action}`);
if (evt === 'pull_request' && data.action === 'closed' && data.pull_request.merged) {
handleGiteaPullRequestClosed(data);
res.sendStatus(200);
}
else if (evt === 'issues' && data.action === 'closed') {
handleGiteaIssueClosed(data);
res.sendStatus(200);
} else {
res.sendStatus(200);
}
});
};

View File

@@ -13,7 +13,7 @@ module.exports = async function(robot, kredits) {
robot.logger.debug('[hubot-kredits] Loading GitHub integration...'); robot.logger.debug('[hubot-kredits] Loading GitHub integration...');
const repoBlackList = []; let repoBlackList = [];
if (process.env.KREDITS_GITHUB_REPO_BLACKLIST) { if (process.env.KREDITS_GITHUB_REPO_BLACKLIST) {
repoBlackList = process.env.KREDITS_GITHUB_REPO_BLACKLIST.split(','); repoBlackList = process.env.KREDITS_GITHUB_REPO_BLACKLIST.split(',');
robot.logger.debug('[hubot-kredits] Ignoring GitHub actions from ', util.inspect(repoBlackList)); robot.logger.debug('[hubot-kredits] Ignoring GitHub actions from ', util.inspect(repoBlackList));
@@ -167,7 +167,7 @@ module.exports = async function(robot, kredits) {
robot.router.post('/incoming/kredits/github/'+process.env.KREDITS_WEBHOOK_TOKEN, (req, res) => { robot.router.post('/incoming/kredits/github/'+process.env.KREDITS_WEBHOOK_TOKEN, (req, res) => {
const evt = req.header('X-GitHub-Event'); const evt = req.header('X-GitHub-Event');
const data = req.body; let data = req.body;
// For some reason data is contained in a payload property on one // For some reason data is contained in a payload property on one
// machine, but directly in the root of the object on others // machine, but directly in the root of the object on others
if (data.payload) { data = JSON.parse(data.payload); } if (data.payload) { data = JSON.parse(data.payload); }

19
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{ {
"name": "hubot-kredits", "name": "hubot-kredits",
"version": "3.1.0", "version": "3.1.2",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
@@ -1175,14 +1175,12 @@
} }
}, },
"kredits-contracts": { "kredits-contracts": {
"version": "5.1.1", "version": "github:67P/kredits-contracts#09b78e1e8f0e9a458324e95dcdf1e7eb1d662eee",
"resolved": "https://registry.npmjs.org/kredits-contracts/-/kredits-contracts-5.1.1.tgz", "from": "github:67P/kredits-contracts#feature/gitea_site",
"integrity": "sha512-hEM/ZOcoYejOix8LMG/mMVQVoD/9q18yjQTXeQwuX2x/APP95CH8HK/UsPIqxXtMP1L3XklWnMuqTVbYUc5UYg==",
"requires": { "requires": {
"ethers": "^4.0.27", "ethers": "^4.0.27",
"ipfs-http-client": "^30.1.1", "ipfs-http-client": "^30.1.1",
"kosmos-schemas": "^2.0.0", "kosmos-schemas": "^2.0.0",
"rsvp": "^4.8.2",
"tv4": "^1.3.0" "tv4": "^1.3.0"
}, },
"dependencies": { "dependencies": {
@@ -1364,9 +1362,9 @@
} }
}, },
"multicodec": { "multicodec": {
"version": "0.5.0", "version": "0.5.1",
"resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.0.tgz", "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.1.tgz",
"integrity": "sha512-lKsJeT4cKeSq0rVEWhO3oSBgDN4sMY1sNZKlvl68g/ZAahjPS1KIVyF4IqhuYmCdtOyKs4Q4hQ6M0C3iqRnuqQ==", "integrity": "sha512-Q5glyZLdXVbbBxvRYHLQHpu8ydVf1422Z+v9fU47v2JCkiue7n+JcFS7uRv0cQW8hbVtgdtIDgYWPWaIKEXuXA==",
"requires": { "requires": {
"varint": "^5.0.0" "varint": "^5.0.0"
} }
@@ -1732,11 +1730,6 @@
"optimist": "~0.3.5" "optimist": "~0.3.5"
} }
}, },
"rsvp": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/rsvp/-/rsvp-4.8.4.tgz",
"integrity": "sha512-6FomvYPfs+Jy9TfXmBpBuMWNH94SgCsZmJKcanySzgNNP6LjWxBvyLTa9KaMfDDM5oxRfrKDB0r/qeRsLwnBfA=="
},
"safe-buffer": { "safe-buffer": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",

View File

@@ -1,6 +1,6 @@
{ {
"name": "hubot-kredits", "name": "hubot-kredits",
"version": "3.1.0", "version": "3.1.2",
"description": "Kosmos Kredits functionality for chat bots", "description": "Kosmos Kredits functionality for chat bots",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
@@ -14,7 +14,7 @@
"ethers": "^4.0.27", "ethers": "^4.0.27",
"group-array": "^0.3.3", "group-array": "^0.3.3",
"kosmos-schemas": "^1.1.2", "kosmos-schemas": "^1.1.2",
"kredits-contracts": "^5.1.1", "kredits-contracts": "github:67P/kredits-contracts#feature/gitea_site",
"node-cron": "^2.0.3", "node-cron": "^2.0.3",
"node-fetch": "^2.3.0", "node-fetch": "^2.3.0",
"prompt": "^1.0.0" "prompt": "^1.0.0"