Skip to content

Commit 1cacd88

Browse files
committed
feat: add parse comment first pass
1 parent de50707 commit 1cacd88

File tree

7 files changed

+198
-274
lines changed

7 files changed

+198
-274
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"dependencies": {
2626
"@probot/serverless-lambda": "^0.2.0",
2727
"all-contributors-cli": "^5.7.0",
28+
"compromise": "^11.13.0",
2829
"probot": "^7.4.0"
2930
},
3031
"devDependencies": {

src/processIssueComment.js

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,19 @@ const OptionsConfig = require('./OptionsConfig')
44
const ContentFiles = require('./ContentFiles')
55

66
const getUserDetails = require('./utils/getUserDetails')
7-
// const parseComment = require('./parse-comment')
7+
const parseComment = require('./utils/parse-comment')
88

99
const { GIHUB_BOT_NAME } = require('./utils/settings')
1010
const { AllContributorBotError } = require('./utils/errors')
1111

12-
async function processIssueComment({ context, commentReply }) {
13-
const repository = new Repository({
14-
...context.repo(),
15-
github: context.github,
16-
})
17-
const optionsConfig = new OptionsConfig({
18-
repository,
19-
commentReply,
20-
})
21-
await optionsConfig.fetch()
22-
23-
// TODO parse comment and gain intentions
24-
// const { who, contributions } = parseComment(commentBody)
25-
// We had trouble reading your comment. Basic usage:\n\n\`@${GIHUB_BOT_NAME} please add jakebolam for code\`
26-
const who = 'jakebolam'
27-
const contributions = ['code']
28-
12+
async function processAddContributor({
13+
context,
14+
commentReply,
15+
repository,
16+
optionsConfig,
17+
who,
18+
contributions,
19+
}) {
2920
const { name, avatar_url, profile } = await getUserDetails({
3021
github: context.github,
3122
username: who,
@@ -55,9 +46,7 @@ async function processIssueComment({ context, commentReply }) {
5546
title: `docs: add ${who} as a contributor`,
5647
body: `Adds ${who} as a contributor for ${contributions.join(
5748
', ',
58-
)}.\n\nThis was requested by ${commentReply.replyingToWho()} [in this comment](${
59-
commentReply.replyingToWhere()
60-
})`,
49+
)}.\n\nThis was requested by ${commentReply.replyingToWho()} [in this comment](${commentReply.replyingToWhere()})`,
6150
filesByPath: filesByPathToUpdate,
6251
branchName: `all-contributors/add-${who}`,
6352
})
@@ -67,6 +56,46 @@ async function processIssueComment({ context, commentReply }) {
6756
)
6857
}
6958

59+
async function processIssueComment({ context, commentReply }) {
60+
const repository = new Repository({
61+
...context.repo(),
62+
github: context.github,
63+
})
64+
const optionsConfig = new OptionsConfig({
65+
repository,
66+
commentReply,
67+
})
68+
await optionsConfig.fetch()
69+
70+
const commentBody = context.payload.comment.body
71+
const parsedComment = parseComment(commentBody)
72+
if (!parsedComment.action) {
73+
commentReply.reply(`I could not determine your intention.`)
74+
commentReply.reply(
75+
`Basic usage: @${GIHUB_BOT_NAME} please add jakebolam for code, doc`,
76+
)
77+
return
78+
}
79+
80+
if (parsedComment.action === 'add') {
81+
await processAddContributor({
82+
context,
83+
commentReply,
84+
repository,
85+
optionsConfig,
86+
who: parsedComment.who,
87+
contributions: parsedComment.contributions,
88+
})
89+
return
90+
}
91+
92+
commentReply.reply(`I'm not sure how to ${parsedComment.action}`)
93+
commentReply.reply(
94+
`Basic usage: @${GIHUB_BOT_NAME} please add jakebolam for code, doc`,
95+
)
96+
return
97+
}
98+
7099
function hasMentionedBotName(context) {
71100
const commentBody = context.payload.comment.body
72101
const hasMentionedBotName = commentBody.includes(GIHUB_BOT_NAME)

src/utils/parse-comment/index.js

Lines changed: 88 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,89 @@
1-
// const chrono = require('chrono-node')
2-
//
3-
// const matcher = /^remind @?([^\s]+)(?: to )?(.*)$/
4-
//
5-
// const parser = new chrono.Chrono()
6-
// parser.refiners.push(require('./lib/refiners/start-of-day'))
7-
//
8-
// const options = {
9-
// forwardDate: true,
10-
// startOfDay: 9
11-
// }
12-
//
13-
// module.exports = (input, from) => {
14-
// const match = input.match(matcher)
15-
// if (!match) {
16-
// // This doesn't look like a reminder, so bail early
17-
// return null
18-
// }
19-
//
20-
// // Pull out the initial matches
21-
// let [, who, what] = match
22-
//
23-
// // Use chrono to extract the `when` from the `what`
24-
// const when = parser.parse(what, from, options)
25-
//
26-
// if (when.length < 1) {
27-
// // What kind of reminder doesn't have a date?
28-
// return null
29-
// }
30-
//
31-
// // Remove any time expressions from the `what`
32-
// when.forEach(w => {
33-
// what = what.replace(w.text, '')
34-
// })
35-
//
36-
// // Clean up whitespace and common connecting words
37-
// what = what.trim()
38-
// what = what.replace(/^(to|that) /, '').replace(/ on$/, '')
39-
//
40-
// return {who, what, when: when[0].start.date()}
1+
const nlp = require('compromise')
2+
3+
const validContributionTypes = [
4+
'blog',
5+
'bug',
6+
'code',
7+
'design',
8+
'doc',
9+
'eventOrganizing',
10+
'example',
11+
'financial',
12+
'fundingFinding',
13+
'ideas',
14+
'infra',
15+
'platform',
16+
'plugin',
17+
'question',
18+
'review',
19+
'security',
20+
'talk',
21+
'test',
22+
'tool',
23+
'translation',
24+
'tutorial',
25+
'userTesting',
26+
'video',
27+
]
28+
29+
// TODO
30+
// const contributionTypeMappings = {
31+
// 'event organizing': 'eventOrganizing',
32+
// 'funding finding': 'fundingFinding',
33+
// 'user testing': 'user testing',
4134
// }
35+
36+
const Contributions = {}
37+
38+
validContributionTypes.forEach(type => {
39+
Contributions[type] = 'Contribution'
40+
})
41+
42+
const plugin = {
43+
words: {
44+
...Contributions,
45+
},
46+
patterns: {
47+
// 'add #person for #Contribution': 'AddContributor',
48+
// "i can't (log|sign|get) in to my? #Software": 'LoginIssue'
49+
},
50+
}
51+
nlp.plugin(plugin)
52+
53+
function parseAddComment(doc, action) {
54+
const who = doc.match(`${action} [.]`).data()[0].normal
55+
56+
// TODO: handle plurals (e.g. some said docs)
57+
const contributions = doc
58+
.match('#Contribution')
59+
.data()
60+
.map(data => {
61+
// This removes whitespace, commas etc
62+
return data.normal
63+
})
64+
65+
return {
66+
action: 'add',
67+
who,
68+
contributions,
69+
}
70+
}
71+
72+
function parseComment(message) {
73+
const doc = nlp(message)
74+
75+
if (doc.verbs().data().length === 0) {
76+
return {}
77+
}
78+
79+
const action = doc.verbs().data()[0].normal
80+
if (action === 'add') {
81+
return parseAddComment(doc, action)
82+
}
83+
84+
return {
85+
action,
86+
}
87+
}
88+
89+
module.exports = parseComment

src/utils/parse-comment/refiners/start-of-day.js

Lines changed: 0 additions & 14 deletions
This file was deleted.

test/fixtures/issue_comment.created.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
"created_at": "2019-01-10T08:36:52Z",
8080
"updated_at": "2019-01-10T08:36:52Z",
8181
"author_association": "MEMBER",
82-
"body": "@AllContributorsBot please add jakebolam for code"
82+
"body": "@AllContributorsBot please add jakebolam for code, doc and infra"
8383
},
8484
"repository": {
8585
"id": 164268911,
Lines changed: 26 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,28 @@
1-
describe('parse-comment', () => {
2-
test('Example test', () => {
3-
expect(true).toBe(true)
1+
const parseComment = require('../../../src/utils/parse-comment')
2+
const { GIHUB_BOT_NAME } = require('../../../src//utils/settings')
3+
4+
describe('parseComment', () => {
5+
test('Basic intent to add', () => {
6+
expect(
7+
parseComment(
8+
`@${GIHUB_BOT_NAME} please add jakebolam for doc, infra and code`,
9+
),
10+
).toEqual({
11+
action: 'add',
12+
who: 'jakebolam',
13+
contributions: ['doc', 'infra', 'code'],
14+
})
415
})
16+
//
17+
// test('Basic intent to add (with plurals)', () => {
18+
// expect(
19+
// parseComment(
20+
// `@${GIHUB_BOT_NAME} please add jakebolam for docs, infra and code`,
21+
// ),
22+
// ).toEqual({
23+
// action: 'add',
24+
// who: 'jakebolam',
25+
// contributions: ['doc', 'infra', 'code'],
26+
// })
27+
// })
528
})
6-
7-
// process.env.TZ = 'UTC'
8-
//
9-
// const expect = require('expect')
10-
// const parseReminder = require('..')
11-
//
12-
// // All time expressions will be relative to Wednesday, July 5 at 4:03:02.0 UTC
13-
// const REFERENCE_DATE = new Date(2017, 6, 5, 4, 3, 2, 0)
14-
//
15-
// describe('parse-reminder', () => {
16-
// const examples = {
17-
// 'nothing to see here': null,
18-
//
19-
// 'remind me nope': null,
20-
//
21-
// 'remind me to call the doctor tomorrow': {
22-
// who: 'me', when: new Date(2017, 6, 6, 9, 0, 0, 0), what: 'call the doctor'
23-
// },
24-
//
25-
// 'remind me to send invites at 3pm tomorrow': {
26-
// who: 'me', when: new Date(2017, 6, 6, 15, 0, 0, 0), what: 'send invites'
27-
// },
28-
//
29-
// 'remind me 8/28 to wish Jamie happy birthday': {
30-
// who: 'me', when: new Date(2017, 7, 28, 9, 0, 0, 0), what: 'wish Jamie happy birthday'
31-
// },
32-
//
33-
// 'remind me to wish Jamie happy birthday on 8/28': {
34-
// who: 'me', when: new Date(2017, 7, 28, 9, 0, 0, 0), what: 'wish Jamie happy birthday'
35-
// },
36-
//
37-
// 'remind me in 10 minutes to change the laundry': {
38-
// who: 'me', when: new Date(2017, 6, 5, 4, 13, 2, 0), what: 'change the laundry'
39-
// },
40-
//
41-
// 'remind me tomorrow 10 PM to eat': {
42-
// who: 'me', when: new Date(2017, 6, 6, 22, 0, 0, 0), what: 'eat'
43-
// },
44-
//
45-
// 'remind me on 18 Feb to be alive': {
46-
// who: 'me', when: new Date(2018, 1, 18, 9, 0, 0, 0), what: 'be alive'
47-
// },
48-
//
49-
// 'remind me Tuesday to watch pogo': {
50-
// who: 'me', when: new Date(2017, 6, 11, 9, 0, 0, 0), what: 'watch pogo'
51-
// },
52-
//
53-
// 'remind me Tuesday': {
54-
// who: 'me', when: new Date(2017, 6, 11, 9, 0, 0, 0), what: ''
55-
// },
56-
//
57-
// 'remind me to go to the dentist on Aug 4 at 3': {
58-
// // FIXME: add refiner to prefer work hours for times without am/pm
59-
// who: 'me', when: new Date(2017, 7, 4, 3, 0, 0, 0), what: 'go to the dentist'
60-
// },
61-
//
62-
// 'remind me to followup with Kathy in 2 weeks': {
63-
// who: 'me', when: new Date(2017, 6, 19, 9, 0, 0, 0), what: 'followup with Kathy'
64-
// },
65-
//
66-
// 'remind me in 2 weeks to followup with Kathy': {
67-
// who: 'me', when: new Date(2017, 6, 19, 9, 0, 0, 0), what: 'followup with Kathy'
68-
// },
69-
//
70-
// 'remind me at 4:00 to check in with Dan': {
71-
// // FIXME: fix future refiner to work with times later in the day
72-
// who: 'me', when: new Date(2017, 6, 5, 4, 0, 0, 0), what: 'check in with Dan'
73-
// },
74-
//
75-
// 'remind me 10am to go to work': {
76-
// // FIXME: fix future refiner to work with times later in the day
77-
// who: 'me', when: new Date(2017, 6, 5, 10, 0, 0, 0), what: 'go to work'
78-
// },
79-
//
80-
// 'remind me that the oil needs changed on Oct 4': {
81-
// who: 'me', when: new Date(2017, 9, 4, 9, 0, 0, 0), what: 'the oil needs changed'
82-
// },
83-
//
84-
// 'remind me next Friday to open the pod bay doors': {
85-
// who: 'me', when: new Date(2017, 6, 14, 9, 0, 0, 0), what: 'open the pod bay doors'
86-
// },
87-
//
88-
// 'remind me tomorrow at noon to buy the new iPhone': {
89-
// who: 'me', when: new Date(2017, 6, 6, 12, 0, 0, 0), what: 'buy the new iPhone'
90-
// },
91-
//
92-
// 'remind someone to have coffee tomorrow at noon': {
93-
// who: 'someone', when: new Date(2017, 6, 6, 12, 0, 0, 0), what: 'have coffee'
94-
// },
95-
//
96-
// 'remind @meaku to have coffee tomorrow at noon': {
97-
// who: 'meaku', when: new Date(2017, 6, 6, 12, 0, 0, 0), what: 'have coffee'
98-
// },
99-
//
100-
// 'remind @probot/everyone to have coffee tomorrow at noon': {
101-
// who: 'probot/everyone', when: new Date(2017, 6, 6, 12, 0, 0, 0), what: 'have coffee'
102-
// }
103-
// }
104-
//
105-
// // eslint-disable-next-line guard-for-in
106-
// for (const example in examples) {
107-
// it(`parses "${example}"`, () => {
108-
// expect(parseReminder(example, REFERENCE_DATE)).toEqual(examples[example])
109-
// })
110-
// }
111-
// })

0 commit comments

Comments
 (0)