1 | 'use strict'
|
2 |
|
3 | var Trello = require('node-trello')
|
4 | var Promise = require('bluebird')
|
5 | var moment = require('moment')
|
6 | var _ = require('lodash')
|
7 |
|
8 | module.exports = function initializeModule (options) {
|
9 | var t = Promise.promisifyAll(new Trello(options.trelloKey, options.trelloToken))
|
10 | var mainBoard
|
11 | var dailyLabel
|
12 |
|
13 | function init (boardName) {
|
14 | return Promise.try(function () {
|
15 | return findBoard(boardName || options.trelloBoard)
|
16 | }).then(function (board) {
|
17 | mainBoard = board
|
18 |
|
19 | return Promise.resolve(getLabelId(options.trelloLabel)).then((label) => {
|
20 | dailyLabel = label
|
21 | return mainBoard
|
22 | })
|
23 | }).catch(function (err) {
|
24 | console.log('Error initiating', err)
|
25 | })
|
26 | }
|
27 |
|
28 | function getLabelId (labelName) {
|
29 | return Promise.try(() => mainBoard || init())
|
30 | .then((board) => t.getAsync('/1/boards/' + board.id + '/labels/'))
|
31 | .then((labels) => _.find(labels, {name: labelName}))
|
32 | .then((label) => label.id)
|
33 | .catch((err) => {
|
34 | if (err) throw new Error(`Unable to get label`)
|
35 | })
|
36 | }
|
37 |
|
38 | function findBoard (boardName) {
|
39 | return Promise.try(function () {
|
40 | return t.getAsync('/1/members/me')
|
41 | }).then(function (data) {
|
42 | return data.idBoards
|
43 | }).map(function (id) {
|
44 | return t.getAsync('/1/boards/' + id, {lists: 'all'})
|
45 | }).filter(function (board) {
|
46 | return board.name === boardName
|
47 | }).then(function (boards) {
|
48 | if (boardName === undefined) {
|
49 | throw new Error('boardName not set in ENV')
|
50 | } else if (boards.length === 0) {
|
51 | throw new Error('No results found.')
|
52 | } else {
|
53 | return boards[0]
|
54 | }
|
55 | }).catch(function (err) {
|
56 | console.log('Error finding board', err)
|
57 | })
|
58 | }
|
59 |
|
60 | function getOrCreateList (board, listName) {
|
61 | return Promise.filter(board.lists, function (list) {
|
62 | return list.name === listName
|
63 | }).filter(function (list) {
|
64 | return list.closed === false
|
65 | }).then(function (lists) {
|
66 | if (lists.length > 0) {
|
67 | return lists[0]
|
68 | } else {
|
69 | return createList({
|
70 | name: listName,
|
71 | board: board,
|
72 | position: 'top'
|
73 | })
|
74 | }
|
75 | }).catch(function (err) {
|
76 | console.log('Error in getOrCreateList', err)
|
77 | })
|
78 | }
|
79 |
|
80 | function createList (opts) {
|
81 | return Promise.try(function () {
|
82 | return t.postAsync('/1/lists', {
|
83 | name: opts.name,
|
84 | idBoard: opts.board,
|
85 | idListSource: opts.sourceList,
|
86 | position: opts.position
|
87 | })
|
88 | }).catch(function (err) {
|
89 | console.log('Error creating list', err)
|
90 | })
|
91 | }
|
92 |
|
93 | function moveCardPosition (opts) {
|
94 | return Promise.resolve().then(function () {
|
95 | return t.getAsync('/1/lists/' + opts.targetList, {cards: 'open'})
|
96 | }).then(function (result) {
|
97 | return _.sortBy(result.cards, 'desc')
|
98 | }).filter(function (card) {
|
99 | return (opts.dailyOnly && _.includes(card.idLabels, dailyLabel))
|
100 | }).then(function (cards) {
|
101 | return cards.reduce(function (prev, card) {
|
102 | return prev.then(function () {
|
103 | return t.putAsync('/1/cards/' + card.id, {pos: card.desc || opts.pos})
|
104 | })
|
105 | }, Promise.resolve())
|
106 | }).catch(function (err) {
|
107 | console.log('Error in moveCardPosition', err)
|
108 | })
|
109 | }
|
110 |
|
111 | function checkDefaultLists (listName, processListName) {
|
112 | return Promise.try(function () {
|
113 | return mainBoard || init()
|
114 | }).then(function (board) {
|
115 | return Promise.all([
|
116 | getOrCreateList(board, listName || options.todayList),
|
117 | getOrCreateList(board, processListName || 'Daily Processes')
|
118 | ]).spread(function (targetList, sourceList) {
|
119 | return {
|
120 | boardId: board.id,
|
121 | targetList: targetList.id,
|
122 | sourceList: sourceList.id
|
123 | }
|
124 | })
|
125 | })
|
126 | }
|
127 |
|
128 | function getOpenLists () {
|
129 | return Promise.try(function () {
|
130 | return mainBoard || init()
|
131 | }).then(function (board) {
|
132 | return t.getAsync('/1/boards/' + board.id + '/lists/open')
|
133 | }).catch(function (err) {
|
134 | if (err) throw new Error('Unable to get lists')
|
135 | })
|
136 | }
|
137 |
|
138 | function archiveEmptyLists () {
|
139 | return Promise.try(function () {
|
140 | return mainBoard || init()
|
141 | }).then(function (board) {
|
142 | return t.getAsync('/1/boards/' + board.id + '/lists?cards=open')
|
143 | }).filter(function (list) {
|
144 | return _.isEmpty(list.cards)
|
145 | }).then(function (lists) {
|
146 | lists = _.groupBy(lists, 'name')
|
147 | for (var name in lists) {
|
148 | if (lists.hasOwnProperty(name)) {
|
149 | _.each(lists[name], function (list, key) {
|
150 | if (key !== 0) {
|
151 | t.putAsync('/1/lists/' + list.id + '/closed?value=true')
|
152 | }
|
153 | })
|
154 | }
|
155 | }
|
156 | })
|
157 | }
|
158 |
|
159 |
|
160 | function getLists () {
|
161 | return Promise.try(function () {
|
162 | return getOpenLists()
|
163 | }).then(function (lists) {
|
164 | return lists.forEach(function (list) {
|
165 | console.log(list.name)
|
166 | return list.name
|
167 | })
|
168 | }).catch(function (err) {
|
169 | if (err) throw new Error('Could not list list names')
|
170 | })
|
171 | }
|
172 |
|
173 |
|
174 | function listCards (listName) {
|
175 | return Promise.try(function () {
|
176 | return getOpenLists()
|
177 | }).filter(function (list) {
|
178 | return list.name === listName
|
179 | }).then(function (list) {
|
180 | return t.getAsync('/1/lists/' + list[0].id, {cards: 'open'})
|
181 | }).then(function (list) {
|
182 | return Promise.map(list.cards, function (card) {
|
183 | if (card.closed === false) {
|
184 | console.log(card.name)
|
185 | }
|
186 | })
|
187 | }).catch(function (err) {
|
188 | if (err) throw new Error('Could not find list')
|
189 | })
|
190 | }
|
191 |
|
192 | function createToday () {
|
193 | return Promise.try(function () {
|
194 | return mainBoard || init()
|
195 | }).then(function (board) {
|
196 | return checkDefaultLists(options.todayList)
|
197 | }).then(function (result) {
|
198 | Promise.try(function () {
|
199 | return createList({
|
200 | name: moment().format('MMMM Do, YYYY'),
|
201 | board: result.boardId,
|
202 | sourceList: result.sourceList,
|
203 | position: '3'
|
204 | })
|
205 | }).then(function (list) {
|
206 | return t.postAsync('/1/lists/' + list.id + '/moveAllCards', {
|
207 | idBoard: result.boardId,
|
208 | idList: result.targetList
|
209 | })
|
210 | }).then(function () {
|
211 | return moveCardPosition({
|
212 | targetList: result.targetList,
|
213 | dailyLabel: dailyLabel,
|
214 | dailyOnly: true,
|
215 | pos: 'top'
|
216 | })
|
217 | }).then(function () {
|
218 | return removeDuplicates(options.todayList)
|
219 | }).then(function () {
|
220 | return archiveEmptyLists()
|
221 | }).then(function () {
|
222 | console.log('Done')
|
223 | })
|
224 | }).catch(function (err) {
|
225 | console.log('Error in createToday', err)
|
226 | })
|
227 | }
|
228 |
|
229 | function createCard (cardText, list, position) {
|
230 | return Promise.try(function () {
|
231 | return mainBoard || init()
|
232 | }).then(function (board) {
|
233 | return checkDefaultLists(list)
|
234 | }).then(function (result) {
|
235 | return t.postAsync('/1/cards', {
|
236 | name: cardText,
|
237 | pos: position || 'top',
|
238 | due: null,
|
239 | idList: result.targetList,
|
240 | urlSource: null
|
241 | })
|
242 | }).then(function () {
|
243 | console.log('Created card:', cardText)
|
244 | }).catch(function (err) {
|
245 | console.log('Error creating card', err)
|
246 | })
|
247 | }
|
248 |
|
249 | function removeDuplicates (listName, args) {
|
250 | return Promise.try(function () {
|
251 | return mainBoard || init()
|
252 | }).then(function (board) {
|
253 | return checkDefaultLists(listName || options.todayList)
|
254 | }).then(function (result) {
|
255 | if (listName == null) {
|
256 | return result.targetList
|
257 | } else {
|
258 | return Promise.try(function () {
|
259 | return getOpenLists()
|
260 | }).filter(function (result) {
|
261 | return listName === result.name
|
262 | }).then(function (result) {
|
263 | return result[0].id
|
264 | }).catch(function (err) {
|
265 | console.log('Unable to find ' + listName, err)
|
266 | })
|
267 | }
|
268 | }).then(function (result) {
|
269 | return Promise.try(function () {
|
270 | return t.getAsync('/1/lists/' + result, {cards: 'open'})
|
271 | }).then(function (result) {
|
272 | return _.difference(result.cards, _.uniq(result.cards, 'name'))
|
273 | }).filter(function (card) {
|
274 | if (args.label) {
|
275 | return Promise.resolve(getLabelId(args.label)).then((labelId) => {
|
276 | return (_.includes(card.idLabels, labelId))
|
277 | })
|
278 | } else {
|
279 | return (_.includes(card.idLabels, dailyLabel))
|
280 | }
|
281 | }).map(function (card) {
|
282 | return Promise.try(function () {
|
283 | return t.delAsync('/1/cards/' + card.id)
|
284 | }).then(function () {
|
285 |
|
286 | })
|
287 | }).then(function (result) {
|
288 |
|
289 | })
|
290 | }).catch(function (err) {
|
291 | console.log('Error removing duplicates', err)
|
292 | })
|
293 | }
|
294 |
|
295 | return {
|
296 | getLists: getLists,
|
297 | archive: archiveEmptyLists,
|
298 | listCards: listCards,
|
299 | createCard: createCard,
|
300 | createToday: createToday,
|
301 | removeDuplicates: removeDuplicates
|
302 | }
|
303 | }
|