UNPKG

15 kBtext/coffeescriptView Raw
1# Description:
2# enable communication with Phabricator via Conduit api
3#
4# Dependencies:
5#
6# Configuration:
7# PHABRICATOR_URL
8# PHABRICATOR_API_KEY
9#
10# Commands:
11# hubot phab version - give the version of hubot-phabs loaded
12# hubot phab new <project>[:<template>] <name of the task> - creates a new task
13# hubot phab paste <name of the paste> - creates a new paste
14# hubot phab count <project> - counts how many tasks a project has
15# hubot phab bl <id> - blacklists an id from phabs_hear
16# hubot phab unbl <id> - removes an id from blacklist
17# hubot phab Txx - gives information about task Txx
18# hubot phab Txx + <some comment> - add a comment to task Txx
19# hubot phab Txx in <project-tag> - add a tag to task Txx
20# hubot phab Txx to [project:]<columns> - move task Txx to columns
21# hubot phab Txx is <status> - modifies task Txx status
22# hubot phab Txx is <priority> - modifies task Txx priority
23# hubot phab assign Txx to <user> - assigns task Txx to comeone
24# hubot phab Txx next [<key>] - outputs next checkbox found in task Txx
25# hubot phab Txx prev [<key>] - outputs last checked checkbox found in task Txx
26# hubot phab Txx check [<key>] - update task Txx description by checking a box
27# hubot phab Txx uncheck [<key>] - update task Txx description by unchecking a box
28# hubot phab user <user> - checks if user is known or not
29# hubot phab me as <email> - makes caller known with <email>
30# hubot phab user <user> = <email> - associates user to email
31# hubot phab search [all] search terms - searches for terms in tasks ([all] to search non-open)
32# hubot phab [all] <project> search terms - searches terms in project ([all] to search non-open)
33# hubot phid <phid> - returns info about an arbitrary phid
34#
35# Author:
36# mose
37
38Phabricator = require '../lib/phabricator'
39moment = require 'moment'
40path = require 'path'
41
42module.exports = (robot) ->
43
44 robot.phab ?= new Phabricator robot, process.env
45 phab = robot.phab
46
47 # hubot phab version - give the version of hubot-phabs loaded
48 robot.respond /ph(?:ab)? version *$/, (msg) ->
49 pkg = require path.join __dirname, '..', 'package.json'
50 msg.send "hubot-phabs module is version #{pkg.version}"
51 msg.finish()
52
53 # hubot phab new <project>[:<template>] <name of the task>
54 robot.respond (
55 /ph(?:ab)? new ([-_a-zA-Z0-9]+)(?::([-_a-zA-Z0-9]+))? ([^=]+)(?: = (.*))? *$/
56 ), (msg) ->
57 data = {
58 project: msg.match[1]
59 template: msg.match[2]
60 title: msg.match[3]
61 description: msg.match[4]
62 user: msg.envelope.user
63 }
64 phab.getPermission(msg.envelope.user, 'phuser')
65 .then ->
66 phab.createTask(data)
67 .then (res) ->
68 phab.recordId res.user, res.id
69 msg.send "Task T#{res.id} created = #{res.url}"
70 .catch (e) ->
71 msg.send e
72 msg.finish()
73
74 # hubot phab paste <name of the paste> - creates a new paste
75 robot.respond /ph(?:ab)? paste (.*)$/, (msg) ->
76 title = msg.match[1]
77 phab.getPermission(msg.envelope.user, 'phuser')
78 .then ->
79 phab.createPaste(msg.envelope.user, title)
80 .then (id) ->
81 url = process.env.PHABRICATOR_URL + "/paste/edit/#{id}"
82 msg.send "Paste P#{id} created = edit on #{url}"
83 .catch (e) ->
84 msg.send e
85 msg.finish()
86
87 # hubot phab count <project> - counts how many tasks a project has
88 robot.respond (/ph(?:ab)? count ([-_a-zA-Z0-9]+) *$/), (msg) ->
89 project = msg.match[1]
90 name = null
91 phab.getProject(project)
92 .then (proj) ->
93 name = proj.data.name
94 phab.listTasks(proj.data.phid)
95 .then (body) ->
96 if Object.keys(body['result']).length is 0
97 msg.send "#{name} has no tasks."
98 else
99 msg.send "#{name} has #{Object.keys(body['result']).length} tasks."
100 .catch (e) ->
101 msg.send e
102 msg.finish()
103
104 # hubot phab bl <id> - blacklists <id> from auto-resopnses
105 robot.respond /ph(?:ab)? bl ((?:T|F|P|M|B|Q|L|V|D)(?:[0-9]+)|(?:r[A-Z]+[a-f0-9]{10,}))/, (msg) ->
106 phab.getPermission(msg.envelope.user, 'phuser')
107 .then ->
108 phab.blacklist msg.match[1]
109 msg.send "Ok. #{msg.match[1]} won't react anymore to auto-detection."
110 .catch (e) ->
111 msg.send e
112 msg.finish()
113
114 # hubot phab unbl <id> - blacklists <id> from auto-resopnses
115 robot.respond /ph(?:ab)? unbl ((?:T|F|P|M|B|Q|L|V|D)(?:[0-9]+)|(?:r[A-Z]+[a-f0-9]{10,}))/, (msg) ->
116 phab.getPermission(msg.envelope.user, 'phuser')
117 .then ->
118 phab.unblacklist msg.match[1]
119 msg.send "Ok. #{msg.match[1]} now will react to auto-detection."
120 .catch (e) ->
121 msg.send e
122 msg.finish()
123
124 # hubot phab Txx - gives information about task Txxx
125 robot.respond /ph(?:ab)?(?: T([0-9]+)| (last))? *$/, (msg) ->
126 what = msg.match[1] or msg.match[2]
127 id = null
128 body = null
129 phab.getId(msg.envelope.user, what)
130 .bind(id)
131 .bind(body)
132 .then (@id) ->
133 phab.getTask(@id)
134 .then (@body) ->
135 phab.getUserByPhid(@body.result.ownerPHID)
136 .then (owner) ->
137 status = @body.result.status
138 priority = @body.result.priority
139 title = @body.result.title
140 if @body.result.status is 'open'
141 ago = moment(@body.result.dateCreated, 'X').fromNow()
142 else
143 ago = moment(@body.result.dateModified, 'X').fromNow()
144 phab.recordId msg.envelope.user, @id
145 msg.send "T#{@id} - #{title} (#{status} #{ago}, #{priority}, owner #{owner})"
146 .catch (e) ->
147 msg.send e
148 msg.finish()
149
150 # hubot phab Txx + <some comment> - add a comment to task Txx
151 robot.respond /ph(?:ab)?(?: T([0-9]+)| (last))? \+ (.+) *$/, (msg) ->
152 what = msg.match[1] or msg.match[2]
153 comment = msg.match[3]
154 id = null
155 phab.getPermission(msg.envelope.user, 'phuser')
156 .then ->
157 phab.getId(msg.envelope.user, what)
158 .then (id) ->
159 phab.addComment(msg.envelope.user, id, comment)
160 .then (id) ->
161 msg.send "Ok. Added comment \"#{comment}\" to T#{id}."
162 .catch (e) ->
163 msg.send e
164 msg.finish()
165
166 # hubot phab Txx <status> - modifies task Txxx status
167 robot.respond new RegExp(
168 "ph(?:ab)?(?: T([0-9]+)| (last))? (?:is )?(#{Object.keys(phab.statuses).join('|')})" +
169 '(?: (?:=|\\+) (.+))? *$'
170 ), (msg) ->
171 what = msg.match[1] or msg.match[2]
172 status = msg.match[3]
173 comment = msg.match[4]
174 phab.getPermission(msg.envelope.user, 'phuser')
175 .then ->
176 phab.getId(msg.envelope.user, what)
177 .then (id) ->
178 phab.doActions(msg.envelope.user, id, "is #{status}", comment)
179 .then (back) ->
180 if back.message? and back.message isnt ''
181 msg.send "Ok, T#{back.id} now has #{back.message}."
182 if back.notices.length > 0
183 for notice in back.notices
184 msg.send notice
185 .catch (e) ->
186 msg.send e
187 msg.finish()
188
189 # hubot phab Txx <priority> - modifies task Txxx priority
190 robot.respond new RegExp(
191 "ph(?:ab)?(?: T([0-9]+)| (last))? (?:is )?(#{Object.keys(phab.priorities).join('|')})" +
192 '(?: (?:=|\\+) (.+))? *$'
193 ), (msg) ->
194 what = msg.match[1] or msg.match[2]
195 priority = msg.match[3]
196 comment = msg.match[4]
197 phab.getPermission(msg.envelope.user, 'phuser')
198 .then ->
199 phab.getId(msg.envelope.user, what)
200 .then (id) ->
201 phab.doActions(msg.envelope.user, id, "is #{priority}", comment)
202 .then (back) ->
203 if back.message? and back.message isnt ''
204 msg.send "Ok, T#{back.id} now has #{back.message}."
205 if back.notices.length > 0
206 for notice in back.notices
207 msg.send notice
208 .catch (e) ->
209 msg.send e
210 msg.finish()
211
212 robot.respond new RegExp(
213 'ph(?:ab)?(?: T([0-9]+)| (last))?((?:' +
214 ' is [^ ]+|' +
215 ' on [^ ]+|' +
216 ' for [^ ]+|' +
217 ' to [^ ]+|' +
218 ' sub [^ ]+|' +
219 ' unsub [^ ]+|' +
220 ' in [^ ]+|' +
221 ' not in [^ ]+)*)' +
222 '(?: (?:=|\\+) (.+))? *$'
223 ), (msg) ->
224 what = msg.match[1] or msg.match[2]
225 commands = msg.match[3]
226 comment = msg.match[4]
227 phab.getPermission(msg.envelope.user, 'phuser')
228 .then ->
229 phab.getId(msg.envelope.user, what)
230 .then (id) ->
231 phab.doActions(msg.envelope.user, id, commands, comment)
232 .then (back) ->
233 if back.message? and back.message isnt ''
234 msg.send "Ok, T#{back.id} now has #{back.message}."
235 if back.notices.length > 0
236 for notice in back.notices
237 msg.send notice
238 .catch (e) ->
239 msg.send e
240 msg.finish()
241
242 # hubot phab Txx next [<key>]- outputs the next checkbox in a given task
243 robot.respond /ph(?:ab)?(?: T([0-9]+)| (last))? next(?: (.+))? *$/, (msg) ->
244 what = msg.match[1] or msg.match[2]
245 key = msg.match[3]
246 id = null
247 phab.getPermission(msg.envelope.user, 'phuser')
248 .bind(id)
249 .then ->
250 phab.getId(msg.envelope.user, what)
251 .then (@id) ->
252 phab.nextCheckbox(msg.envelope.user, @id, key)
253 .then (line) ->
254 msg.send "Next on T#{@id} is: #{line}"
255 .catch (e) ->
256 msg.send e
257 msg.finish()
258
259 # hubot phab Txx prev [<key>]- outputs the last checked checkbox in a given task
260 robot.respond /ph(?:ab)?(?: T([0-9]+)| (last))? prev(?:ious)?(?: (.+))? *$/, (msg) ->
261 what = msg.match[1] or msg.match[2]
262 key = msg.match[3]
263 id = null
264 phab.getPermission(msg.envelope.user, 'phuser')
265 .bind(id)
266 .then ->
267 phab.getId(msg.envelope.user, what)
268 .then (@id) ->
269 phab.prevCheckbox(msg.envelope.user, @id, key)
270 .then (line) ->
271 msg.send "Previous on T#{@id} is: #{line}"
272 .catch (e) ->
273 msg.send e
274 msg.finish()
275
276 # hubot phab Txx check [<key>] - update task Txx description by checking a box
277 robot.respond /ph(?:ab)?(?: T([0-9]+)| (last))? check(!)?(?: ([^\+]+))?(?: \+ (.+))? *$/, (msg) ->
278 what = msg.match[1] or msg.match[2]
279 withNext = msg.match[3]
280 key = msg.match[4]
281 comment = msg.match[5]
282 id = null
283 phab.getPermission(msg.envelope.user, 'phuser')
284 .bind(id)
285 .then ->
286 phab.getId(msg.envelope.user, what)
287 .then (@id) ->
288 phab.checkCheckbox(msg.envelope.user, @id, key, withNext, comment)
289 .then (line) ->
290 msg.send "Checked on T#{@id}: #{line[0]}"
291 if line[1]?
292 msg.send "Next on T#{@id}: #{line[1]}"
293 .catch (e) ->
294 msg.send e
295 msg.finish()
296
297 # hubot phab Txx uncheck [<key>] - update task Txx description by unchecking a box
298 robot.respond /ph(?:ab)?(?: T([0-9]+)| (last))? uncheck(!)?(?: ([^\+]+))?(?: \+ (.+))? *$/
299 , (msg) ->
300 what = msg.match[1] or msg.match[2]
301 withNext = msg.match[3]
302 key = msg.match[4]
303 comment = msg.match[5]
304 id = null
305 phab.getPermission(msg.envelope.user, 'phuser')
306 .bind(id)
307 .then ->
308 phab.getId(msg.envelope.user, what)
309 .then (@id) ->
310 phab.uncheckCheckbox(msg.envelope.user, @id, key, withNext, comment)
311 .then (line) ->
312 msg.send "Unchecked on T#{@id}: #{line[0]}"
313 if line[1]?
314 msg.send "Previous on T#{@id}: #{line[1]}"
315 .catch (e) ->
316 msg.send e
317 msg.finish()
318
319 # hubot phab user <user> - checks if user is known or not
320 robot.respond /ph(?:ab)? (?:user|who) ([^ ]*) *$/, (msg) ->
321 assignee = { name: msg.match[1] }
322 phab.getPermission(msg.envelope.user, 'phuser')
323 .then ->
324 phab.getUser(msg.envelope.user, assignee)
325 .then (userPhid) ->
326 msg.send "Hey I know #{assignee.name}, he's #{userPhid}"
327 .catch (e) ->
328 msg.send e
329 msg.finish()
330
331 # hubot phab me as <email> - makes caller known with <email>
332 robot.respond /ph(?:ab)? me as (.*@.*) *$/, (msg) ->
333 email = msg.match[1]
334 phab.getPermission(msg.envelope.user, 'phuser')
335 .then ->
336 msg.envelope.user.email_address = msg.match[1]
337 phab.getUser(msg.envelope.user, msg.envelope.user)
338 .then (userPhid) ->
339 msg.send "Now I know you, you are #{userPhid}"
340 .catch (e) ->
341 msg.send e
342 msg.finish()
343
344 # hubot phab user <user> = <email> - associates user to email
345 robot.respond /ph(?:ab)? user ([^ ]*) *?= *?([^ ]*@.*) *$/, (msg) ->
346 assignee = { name: msg.match[1], email_address: msg.match[2] }
347 phab.getPermission(msg.envelope.user, 'phuser')
348 .then ->
349 phab.getUser(msg.envelope.user, assignee)
350 .then (userPhid) ->
351 msg.send "Now I know #{assignee.name}, he's #{userPhid}"
352 .catch (e) ->
353 msg.send e
354 msg.finish()
355
356 # hubot phab [all] [limit] search <search terms> - searches for terms in project
357 robot.respond /ph(?:ab)?( all)?(?: (\d+))? search (.+)$/, (msg) ->
358 status = if msg.match[1]?
359 undefined
360 else
361 'open'
362 limit = msg.match[2] or 3
363 terms = msg.match[3]
364 phab.searchAllTask(terms, status, limit)
365 .then (payload) ->
366 if payload.result.data.length is 0
367 msg.send "There is no task matching '#{terms}'."
368 else
369 for task in payload.result.data
370 if task.fields.status.name is 'Open'
371 ago = moment(task.fields.dateCreated, 'X').fromNow()
372 else
373 ago = moment(task.fields.dateModified, 'X').fromNow()
374 msg.send "#{process.env.PHABRICATOR_URL}/T#{task.id} - #{task.fields['name']}" +
375 " (#{task.fields.status.name} #{ago})"
376 if payload.result.cursor.after?
377 msg.send '... and there is more.'
378 .catch (e) ->
379 msg.send e
380 msg.finish()
381
382 # hubot phab [all] [limit] <project> <search terms> - searches for terms in project
383 robot.respond /ph(?:ab)?( all)?(?: (\d+))? ([^ ]+) (.+)$/, (msg) ->
384 status = if msg.match[1]?
385 undefined
386 else
387 'open'
388 limit = msg.match[2] or 3
389 project = msg.match[3]
390 terms = msg.match[4]
391 name = null
392 phab.getProject(project)
393 .then (proj) ->
394 name = proj.data.name
395 phab.searchTask(proj.data.phid, terms, status, limit)
396 .then (payload) ->
397 if payload.result.data.length is 0
398 msg.send "There is no task matching '#{terms}' in project '#{name}'."
399 else
400 for task in payload.result.data
401 if task.fields.status.name is 'Open'
402 ago = moment(task.fields.dateCreated, 'X').fromNow()
403 else
404 ago = moment(task.fields.dateModified, 'X').fromNow()
405 msg.send "#{process.env.PHABRICATOR_URL}/T#{task.id} - #{task.fields['name']}" +
406 " (#{task.fields.status.name} #{ago})"
407 if payload.result.cursor.after?
408 msg.send '... and there is more.'
409 .catch (e) ->
410 msg.send e
411 msg.finish()
412
413 # hubot phid <phid> - returns info about an arbitrary phid
414 robot.respond /phid ([^ ]+) *$/, (msg) ->
415 item = msg.match[1]
416 if /^PHID-/.test item
417 phab.getPHID(item)
418 .then (data) ->
419 msg.send "#{item} is #{data.name} - #{data.uri} (#{data.status})"
420 .catch (e) ->
421 msg.send e
422 msg.finish()
423 else
424 phab.genericInfo(item)
425 .then (body) ->
426 if Object.keys(body.result).length < 1
427 msg.send "#{item} not found."
428 else
429 msg.send "#{item} is #{body.result[item].phid}"
430 .catch (e) ->
431 msg.send e
432 msg.finish()