diff --git a/package.json b/package.json index 75944de..fe16023 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "googleapis": "^34.0.0", "moment": "^2.22.2", "node-schedule": "^0.6.0", - "hubot-routines": "https://github.com/tolstoyevsky/hubot-routines.git" + "hubot-routines": "git+https://github.com/tolstoyevsky/hubot-routines.git", + "hubot-engine": "git+https://github.com/seven48/hubot-engine.git" }, "devDependencies": { "eslint": "^5.5.0", diff --git a/src/routes/ill/iAmIll.js b/src/routes/ill/iAmIll.js index 0151cc7..f166fd9 100644 --- a/src/routes/ill/iAmIll.js +++ b/src/routes/ill/iAmIll.js @@ -1,24 +1,36 @@ const routines = require('hubot-routines') -module.exports = async msg => { - const user = msg.message.user +const { AbstractView } = require('hubot-engine') - // if already ill - if (user.sick) { - msg.send('Я уже слышал, что ты болеешь. :thinking:') - - return +class View extends AbstractView { + init (options) { + options.app = 'ill' } - const message = routines.buildMessageWithButtons( - 'Очень жаль. Ты в состоянии работать из дома в эти дни?', - [ - ['Да', 'Болею и работаю'], - ['Нет', 'Болею и не работаю'] - ] - ) + callback (msg) { + const user = msg.message.user + + // if already ill + if (user.sick) { + msg.send('Я уже слышал, что ты болеешь. :thinking:') + + return + } + + const message = routines.buildMessageWithButtons( + 'Очень жаль. Ты в состоянии работать из дома в эти дни?', + [ + ['Да', 'Болею и работаю'], + ['Нет', 'Болею и не работаю'] + ] + ) - user.sickConfirming = true + user.sickConfirming = true - msg.send(message) + this.app.set() + + msg.send(message) + } } + +module.exports = View diff --git a/src/routes/ill/iAmNotIll.js b/src/routes/ill/iAmNotIll.js index 57a644e..50c5d89 100644 --- a/src/routes/ill/iAmNotIll.js +++ b/src/routes/ill/iAmNotIll.js @@ -2,40 +2,51 @@ const moment = require('moment') const vars = require('./../../vars') const utils = require('./../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = msg => { - const user = msg.message.user +class View extends AbstractView { + init (options) { + options.app = 'ill' + } - if (!user.sick) { - msg.send('Я ничего не знал о твоей болезни. :thinking:') + callback (msg) { + const user = msg.message.user - return - } + if (!user.sick) { + msg.send('Я ничего не знал о твоей болезни. :thinking:') + + return + } + + this.app.clear() + + let isCalendar = String() - let isCalendar = String() - - if (vars.GOOGLE_API && user.sick.eventId) { - utils.getEventFromCalendar(msg.robot, user.sick.eventId) - .then(event => { - const startDate = moment(user.sick.start, 'DD.MM.YYYY') - const yesterday = moment() - - if (utils.isEqualDate(startDate, yesterday)) { - isCalendar = ' Я удалил событие из календаря.' - return utils.deleteEventFromCalendar(msg.robot, user.sick.eventId) - } else { - event.data.end = { date: yesterday.format('YYYY-MM-DD') } - isCalendar = ' Я исправил событие в календаре.' - return utils.updateEventFromCalendar(msg.robot, user.sick.eventId, event.data) - } - }).then(() => { - delete user.sick - - msg.send(`Рад видеть тебя снова!${isCalendar}`) - }) - } else if (user.sick) { - delete user.sick - - msg.send(`Рад видеть тебя снова!`) + if (vars.GOOGLE_API && user.sick.eventId) { + utils.getEventFromCalendar(msg.robot, user.sick.eventId) + .then(event => { + const startDate = moment(user.sick.start, 'DD.MM.YYYY') + const yesterday = moment() + + if (utils.isEqualDate(startDate, yesterday)) { + isCalendar = ' Я удалил событие из календаря.' + return utils.deleteEventFromCalendar(msg.robot, user.sick.eventId) + } else { + event.data.end = { date: yesterday.format('YYYY-MM-DD') } + isCalendar = ' Я исправил событие в календаре.' + return utils.updateEventFromCalendar(msg.robot, user.sick.eventId, event.data) + } + }).then(() => { + delete user.sick + + msg.send(`Рад видеть тебя снова!${isCalendar}`) + }) + } else if (user.sick) { + delete user.sick + + msg.send(`Рад видеть тебя снова!`) + } } } + +module.exports = View diff --git a/src/routes/ill/illAgree.js b/src/routes/ill/illAgree.js index 91dd88c..eb7cd80 100644 --- a/src/routes/ill/illAgree.js +++ b/src/routes/ill/illAgree.js @@ -1,20 +1,30 @@ const routines = require('hubot-routines') -module.exports = msg => { - const user = msg.message.user +const { AbstractView } = require('hubot-engine') - if (user.sick) return - if (!(typeof user.sickConfirming === 'boolean')) return +class View extends AbstractView { + init (options) { + options.app = 'ill' + } - user.sickConfirming = msg.match[1].toLowerCase() + callback (msg) { + const user = msg.message.user - const message = routines.buildMessageWithButtons( - 'Я понял. Согласовано ли отсутствие с руководителем/тимлидом?', - [ - ['Да', 'Да, они предупреждены, что я болею'], - ['Нет', 'Нет, они не предупреждены, что я болею'] - ] - ) + if (user.sick) return + if (!(typeof user.sickConfirming === 'boolean')) return - msg.send(message) + user.sickConfirming = msg.match[1].toLowerCase() + + const message = routines.buildMessageWithButtons( + 'Я понял. Согласовано ли отсутствие с руководителем/тимлидом?', + [ + ['Да', 'Да, они предупреждены, что я болею'], + ['Нет', 'Нет, они не предупреждены, что я болею'] + ] + ) + + msg.send(message) + } } + +module.exports = View diff --git a/src/routes/ill/yesTheyAreNotified.js b/src/routes/ill/yesTheyAreNotified.js index c67f44e..82c4bca 100644 --- a/src/routes/ill/yesTheyAreNotified.js +++ b/src/routes/ill/yesTheyAreNotified.js @@ -2,45 +2,56 @@ const moment = require('moment') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const user = msg.message.user - const today = moment() - const tomorrow = moment().add(1, 'days') - - if (user.sick) return - if (!(typeof user.sickConfirming === 'string')) return - - if (msg.match[1].toLowerCase() === 'да, они предупреждены, что я болею') { - const isWork = user.sickConfirming === 'болею и работаю' - - if (!user.sick) { - user.sick = Object() - } +class View extends AbstractView { + init (options) { + options.app = 'ill' + } - let isCalendar = vars.GOOGLE_API ? ' Я добавил событие в календарь.' : '' - if (vars.GOOGLE_API) { - utils.addEventToCalendar( - msg.robot, - today.format('YYYY-MM-DD'), - tomorrow.format('YYYY-MM-DD'), - user, - isWork ? vars.GOOGLE_EVENT_SICK_WITH_WORK : vars.GOOGLE_EVENT_SICK - ).then(eventId => { user.sick.eventId = eventId }) + callback (msg) { + const user = msg.message.user + const today = moment() + const tomorrow = moment().add(1, 'days') + + if (user.sick) return + if (!(typeof user.sickConfirming === 'string')) return + + if (msg.match[1].toLowerCase() === 'да, они предупреждены, что я болею') { + const isWork = user.sickConfirming === 'болею и работаю' + + if (!user.sick) { + user.sick = Object() + } + + let isCalendar = vars.GOOGLE_API ? ' Я добавил событие в календарь.' : '' + if (vars.GOOGLE_API) { + utils.addEventToCalendar( + msg.robot, + today.format('YYYY-MM-DD'), + tomorrow.format('YYYY-MM-DD'), + user, + isWork ? vars.GOOGLE_EVENT_SICK_WITH_WORK : vars.GOOGLE_EVENT_SICK + ).then(eventId => { user.sick.eventId = eventId }) + } + + user.sick.start = today.format(vars.CREATION_DATE_FORMAT) + user.sick.isWork = isWork + delete user.sickConfirming + this.app.clear() + + msg.robot.messageRoom( + vars.LEAVE_COORDINATION_CHANNEL, + `@${user.name} болеет и ${isWork ? 'работает' : 'не может работать'} из дома` + ) + + msg.send(`Ok. Выздоравливай поскорее.${isCalendar} Когда ты выйдешь на работу, скажи мне \`я не болею\`.`) + } else { + this.app.clear() + delete user.sickConfirming + msg.send('Тогда сначала предупреди, а потом вернись и повтори все снова!') } - - user.sick.start = today.format(vars.CREATION_DATE_FORMAT) - user.sick.isWork = isWork - delete user.sickConfirming - - msg.robot.messageRoom( - vars.LEAVE_COORDINATION_CHANNEL, - `@${user.name} болеет и ${isWork ? 'работает' : 'не может работать'} из дома` - ) - - msg.send(`Ok. Выздоравливай поскорее.${isCalendar} Когда ты выйдешь на работу, скажи мне \`я не болею\`.`) - } else { - delete user.sickConfirming - msg.send('Тогда сначала предупреди, а потом вернись и повтори все снова!') } } + +module.exports = View diff --git a/src/routes/leave/customerNotified.js b/src/routes/leave/customerNotified.js index 24b8faa..a15b147 100644 --- a/src/routes/leave/customerNotified.js +++ b/src/routes/leave/customerNotified.js @@ -1,18 +1,23 @@ const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const username = msg.message.user.name - const state = await utils.getStateFromBrain(msg.robot, username) - const answer = msg.match[1].toLowerCase().trim() +class View extends AbstractView { + async callback (msg) { + const username = msg.message.user.name + const state = await utils.getStateFromBrain(msg.robot, username) + const answer = msg.match[1].toLowerCase().trim() - if (!state.reportToCustomer) { - if (answer === 'да, предупрежден') { - state.reportToCustomer = true - msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Пользователь @${username} только что сообщил, что предупредил заказчика о своем отпуске.`) - msg.send(':thumbsup:') - } else { - msg.send('Обязательно предупреди! :fearful:') + if (!state.reportToCustomer) { + if (answer === 'да, предупрежден') { + state.reportToCustomer = true + msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Пользователь @${username} только что сообщил, что предупредил заказчика о своем отпуске.`) + msg.send(':thumbsup:') + } else { + msg.send('Обязательно предупреди! :fearful:') + } } } } + +module.exports = View diff --git a/src/routes/leave/iAmPlanningToGoOnLeave.js b/src/routes/leave/iAmPlanningToGoOnLeave.js index a6e53cb..88a26ba 100644 --- a/src/routes/leave/iAmPlanningToGoOnLeave.js +++ b/src/routes/leave/iAmPlanningToGoOnLeave.js @@ -3,35 +3,46 @@ const routines = require('hubot-routines') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const username = msg.message.user.name - const state = await utils.getStateFromBrain(msg.robot, username) - const answer = msg.match[1].toLowerCase().trim() - - if (state.n === vars.CONFIRM_STATE) { - if (answer === 'да, планирую') { - const deadline = moment(state.creationDate, vars.CREATION_DATE_FORMAT).add(vars.MAXIMUM_LENGTH_OF_WAIT, 'days').format('DD.MM') - const from = moment(`${state.leaveStart.day}.${state.leaveStart.month}`, 'D.M').format('DD.MM') - const to = moment(`${state.leaveEnd.day}.${state.leaveEnd.month}`, 'D.M').format('DD.MM') - - const buttonsMessage = routines.buildMessageWithButtons( - `Пользователь @${username} хочет в отпуск с ${from} по ${to}. Ответ нужно дать до ${deadline}.`, - [ - ['Одобрить', `${msg.robot.alias} одобрить заявку @${username}`], - ['Отклонить', `${msg.robot.alias} отклонить заявку @${username}`] - ] - ) - msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, buttonsMessage) - - state.requestStatus = vars.PENDING_STATUS - state.reportToCustomer = false - - msg.send(`Заявка на отпуск отправлена. Ответ поступит не позже чем через ${utils.noname(vars.MAXIMUM_LENGTH_OF_WAIT)}.`) - } else { - msg.send('Я прервал процесс формирования заявки на отпуск.') - } +class View extends AbstractView { + init (options) { + options.app = 'leave' + } + + async callback (msg) { + const username = msg.message.user.name + const state = await utils.getStateFromBrain(msg.robot, username) + const answer = msg.match[1].toLowerCase().trim() + + if (state.n === vars.CONFIRM_STATE) { + if (answer === 'да, планирую') { + const deadline = moment(state.creationDate, vars.CREATION_DATE_FORMAT).add(vars.MAXIMUM_LENGTH_OF_WAIT, 'days').format('DD.MM') + const from = moment(`${state.leaveStart.day}.${state.leaveStart.month}`, 'D.M').format('DD.MM') + const to = moment(`${state.leaveEnd.day}.${state.leaveEnd.month}`, 'D.M').format('DD.MM') + + const buttonsMessage = routines.buildMessageWithButtons( + `Пользователь @${username} хочет в отпуск с ${from} по ${to}. Ответ нужно дать до ${deadline}.`, + [ + ['Одобрить', `${msg.robot.alias} одобрить заявку @${username}`], + ['Отклонить', `${msg.robot.alias} отклонить заявку @${username}`] + ] + ) + msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, buttonsMessage) - state.n = vars.INIT_STATE + state.requestStatus = vars.PENDING_STATUS + state.reportToCustomer = false + + msg.send(`Заявка на отпуск отправлена. Ответ поступит не позже чем через ${utils.noname(vars.MAXIMUM_LENGTH_OF_WAIT)}.`) + } else { + msg.send('Я прервал процесс формирования заявки на отпуск.') + } + + this.app.clear() + + state.n = vars.INIT_STATE + } } } + +module.exports = View diff --git a/src/routes/leave/leaveRequestApprove.js b/src/routes/leave/leaveRequestApprove.js index f0b20a5..fb5419e 100644 --- a/src/routes/leave/leaveRequestApprove.js +++ b/src/routes/leave/leaveRequestApprove.js @@ -3,57 +3,63 @@ const routines = require('hubot-routines') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async (msg) => { - const action = msg.match[1] - const username = msg.match[2].trim() - - if (!await routines.isAdmin(msg.robot, msg.message.user.name)) { - return msg.send(vars.ACCESS_DENIED_MSG) +class View extends AbstractView { + init (options) { + options.app = 'leave' + options.admin = true } - const state = await utils.getStateFromBrain(msg.robot, username) - const user = await routines.findUserByName(msg.robot, username) + async callback (msg) { + const action = msg.match[1] + const username = msg.match[2].trim() - if (!user) { - return msg.send(vars.UNKNOWN_USER_MSG) - } + const state = await utils.getStateFromBrain(msg.robot, username) + const user = await routines.findUserByName(msg.robot, username) - if (state.requestStatus !== vars.PENDING_STATUS) { - return msg.send('У этого пользователя нет ожидающей ответа заявки.') - } + if (!user) { + return msg.send(vars.UNKNOWN_USER_MSG) + } + + if (state.requestStatus !== vars.PENDING_STATUS) { + return msg.send('У этого пользователя нет ожидающей ответа заявки.') + } - if (action === 'одобрить') { - state.requestStatus = vars.APPROVED_STATUS + if (action === 'одобрить') { + state.requestStatus = vars.APPROVED_STATUS - const start = state.leaveStart - const leaveStart = moment( - `${start.day}.${start.month}.${start.year}`, - 'DD.MM.YYYY' - ).format('YYYY-MM-DD') + const start = state.leaveStart + const leaveStart = moment( + `${start.day}.${start.month}.${start.year}`, + 'DD.MM.YYYY' + ).format('YYYY-MM-DD') - const end = state.leaveEnd - const leaveEnd = moment( - `${end.day}.${end.month}.${end.year}`, - 'DD.MM.YYYY' - ).add(1, 'day').format('YYYY-MM-DD') + const end = state.leaveEnd + const leaveEnd = moment( + `${end.day}.${end.month}.${end.year}`, + 'DD.MM.YYYY' + ).add(1, 'day').format('YYYY-MM-DD') - if (vars.GOOGLE_API) { - utils.addEventToCalendar(msg.robot, leaveStart, leaveEnd, user, vars.GOOGLE_EVENT_VACATION) - .then(eventId => { state.eventId = eventId }) + if (vars.GOOGLE_API) { + utils.addEventToCalendar(msg.robot, leaveStart, leaveEnd, user, vars.GOOGLE_EVENT_VACATION) + .then(eventId => { state.eventId = eventId }) + } + } else { + utils.cleanupState(state) } - } else { - utils.cleanupState(state) - } - const result = action === 'одобрить' ? 'одобрена' : 'отклонена' + const result = action === 'одобрить' ? 'одобрена' : 'отклонена' - if (msg.message.room !== vars.LEAVE_COORDINATION_CHANNEL) { - const admin = msg.message.user.name - msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Заявка на отпуск пользователя @${username} была ${result} пользователем @${admin}.`) - } + if (msg.message.room !== vars.LEAVE_COORDINATION_CHANNEL) { + const admin = msg.message.user.name + msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Заявка на отпуск пользователя @${username} была ${result} пользователем @${admin}.`) + } - msg.send(`Заявка @${username} ${result}. Я отправлю этому пользователю уведомление об этом.`) + msg.send(`Заявка @${username} ${result}. Я отправлю этому пользователю уведомление об этом.`) - msg.robot.adapter.sendDirect({ user: { name: username } }, `Заявка на отпуск ${result}.`) + msg.robot.adapter.sendDirect({ user: { name: username } }, `Заявка на отпуск ${result}.`) + } } + +module.exports = View diff --git a/src/routes/leave/leaveRequestCancel.js b/src/routes/leave/leaveRequestCancel.js index 4649acb..c929b39 100644 --- a/src/routes/leave/leaveRequestCancel.js +++ b/src/routes/leave/leaveRequestCancel.js @@ -1,33 +1,37 @@ -const routines = require('hubot-routines') - const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async (msg) => { - if (!await routines.isAdmin(msg.robot, msg.message.user.name)) { - return msg.send(vars.ACCESS_DENIED_MSG) +class View extends AbstractView { + init (options) { + options.app = 'leave' + options.admin = true } - const username = msg.match[2].trim() - const state = await utils.getStateFromBrain(msg.robot, username) + async callback (msg) { + const username = msg.match[2].trim() + const state = await utils.getStateFromBrain(msg.robot, username) - if (state.requestStatus === vars.APPROVED_STATUS) { - utils.cleanupState(state) + if (state.requestStatus === vars.APPROVED_STATUS) { + utils.cleanupState(state) - if (msg.message.room !== vars.LEAVE_COORDINATION_CHANNEL) { - msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Пользователь @${msg.message.user.name} отменил заявку на отпуск пользователя @${username}.`) - } + if (msg.message.room !== vars.LEAVE_COORDINATION_CHANNEL) { + msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Пользователь @${msg.message.user.name} отменил заявку на отпуск пользователя @${username}.`) + } - if (vars.GOOGLE_API && state.eventId) { - utils.deleteEventFromCalendar(msg.robot, state.eventId) - delete state.eventId - } + if (vars.GOOGLE_API && state.eventId) { + utils.deleteEventFromCalendar(msg.robot, state.eventId) + delete state.eventId + } - msg.robot.adapter.sendDirect({ user: { name: username } }, `Упс, пользователь @${msg.message.user.name} только что отменил твою заявку на отпуск.`) - msg.send(`Отпуск пользователя @${username} отменен.`) - } else if (state.requestStatus === vars.PENDING_STATUS) { - msg.send('Отменить можно только одобренные заявки. Используй команду \'отклонить\'.') - } else { - msg.send('Этот человек не собирается в отпуск.') + msg.robot.adapter.sendDirect({ user: { name: username } }, `Упс, пользователь @${msg.message.user.name} только что отменил твою заявку на отпуск.`) + msg.send(`Отпуск пользователя @${username} отменен.`) + } else if (state.requestStatus === vars.PENDING_STATUS) { + msg.send('Отменить можно только одобренные заявки. Используй команду \'отклонить\'.') + } else { + msg.send('Этот человек не собирается в отпуск.') + } } } + +module.exports = View diff --git a/src/routes/leave/leaveStart.js b/src/routes/leave/leaveStart.js index 3b6fe64..e1c4b05 100644 --- a/src/routes/leave/leaveStart.js +++ b/src/routes/leave/leaveStart.js @@ -3,87 +3,100 @@ const moment = require('moment') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async function (msg) { - const username = msg.match[1] ? msg.message.user.name : msg.match[3] - const user = await routines.findUserByName(msg.robot, username) +class View extends AbstractView { + init (options) { + options.app = 'leave' + } - if (!user) return msg.send(vars.UNKNOWN_USER_MSG) + async callback (msg) { + const username = msg.match[1] ? msg.message.user.name : msg.match[3] + const user = await routines.findUserByName(msg.robot, username) - const state = await utils.getStateFromBrain(msg.robot, username) + if (!user) return msg.send(vars.UNKNOWN_USER_MSG) - if (msg.match[2]) { // @username хочет в отпуск - const admin = await routines.findUserByName(msg.robot, msg.message.user.name) + const state = await utils.getStateFromBrain(msg.robot, username) - if (!await routines.isAdmin(msg.robot, admin.name)) { - msg.send(vars.ACCESS_DENIED_MSG) - return - } + if (msg.match[2]) { // @username хочет в отпуск + const admin = await routines.findUserByName(msg.robot, msg.message.user.name) - admin.vivaLasVegas = admin.vivaLasVegas || {} - admin.vivaLasVegas.allocation = username - } + if (!await routines.isAdmin(msg.robot, admin.name)) { + msg.send(vars.ACCESS_DENIED_MSG) + return + } - if (state.n !== undefined && state.n !== vars.INIT_STATE && state.n < vars.CONFIRM_STATE) { - const appeal = msg.match[1] ? 'ты хочешь' : `@${username} хочет` - const leaveStart = state.leaveStart - const leaveEnd = state.leaveEnd - let infoMessage + admin.vivaLasVegas = admin.vivaLasVegas || {} + admin.vivaLasVegas.allocation = username + } - switch (state.n) { - case 1: { - infoMessage = '\n' - break - } - case 2: { - infoMessage = `\nИтак, ${appeal} в отпуск с ${moment(`${leaveStart.day}.${leaveStart.month}`, vars.DATE_FORMAT).format('DD.MM')}.\n` - break + if (state.n !== undefined && state.n !== vars.INIT_STATE && state.n < vars.CONFIRM_STATE) { + const appeal = msg.match[1] ? 'ты хочешь' : `@${username} хочет` + const leaveStart = state.leaveStart + const leaveEnd = state.leaveEnd + let infoMessage + + switch (state.n) { + case 1: { + infoMessage = '\n' + break + } + case 2: { + infoMessage = `\nИтак, ${appeal} в отпуск с ${moment(`${leaveStart.day}.${leaveStart.month}`, vars.DATE_FORMAT).format('DD.MM')}.\n` + break + } + case 3: { + infoMessage = `\nИтак, ${appeal} уйти в отпуск с ${moment(`${leaveStart.day}.${leaveStart.month}`, vars.DATE_FORMAT).format('DD.MM')} по ${moment(`${leaveEnd.day}.${leaveEnd.month}`, vars.DATE_FORMAT).format('DD.MM')}.\n` + break + } } - case 3: { - infoMessage = `\nИтак, ${appeal} уйти в отпуск с ${moment(`${leaveStart.day}.${leaveStart.month}`, vars.DATE_FORMAT).format('DD.MM')} по ${moment(`${leaveEnd.day}.${leaveEnd.month}`, vars.DATE_FORMAT).format('DD.MM')}.\n` - break + + if (state.n === 3) { + const message = routines.buildMessageWithButtons( + `${vars.ANGRY_MSG}${infoMessage}${vars.statesMessages[state.n]}`, + [ + ['Да', msg.match[1] ? 'Да, планирую' : 'Да, планирует'], + ['Нет', msg.match[1] ? 'Нет, не планирую' : 'Нет, не планирует'] + ] + ) + msg.send(message) + } else { + const message = vars.statesMessages[state.n].replace('%s', appeal) + msg.send(`${vars.ANGRY_MSG}${infoMessage}${message}`) } - } - if (state.n === 3) { - const message = routines.buildMessageWithButtons( - `${vars.ANGRY_MSG}${infoMessage}${vars.statesMessages[state.n]}`, - [ - ['Да', msg.match[1] ? 'Да, планирую' : 'Да, планирует'], - ['Нет', msg.match[1] ? 'Нет, не планирую' : 'Нет, не планирует'] - ] - ) - msg.send(message) - } else { - const message = vars.statesMessages[state.n].replace('%s', appeal) - msg.send(`${vars.ANGRY_MSG}${infoMessage}${message}`) + this.app.set() + + return } - return - } + if (state.requestStatus === vars.APPROVED_STATUS) { + if (msg.match[2]) { // @username хочет в отпуск + msg.send('Заявка этого пользователя уже была одобрена.') + } else { + msg.send('Твоя предыдущая заявка была одобрена, так что сначала отгуляй этот отпуск.') + } - if (state.requestStatus === vars.APPROVED_STATUS) { - if (msg.match[2]) { // @username хочет в отпуск - msg.send('Заявка этого пользователя уже была одобрена.') - } else { - msg.send('Твоя предыдущая заявка была одобрена, так что сначала отгуляй этот отпуск.') + return } - return - } + if (state.requestStatus === vars.PENDING_STATUS) { + if (msg.match[2]) { // @username хочет в отпуск + msg.send('У этого пользователя уже есть заявка на отпуск.') + } else { + msg.send('Твоя заявка на отпуск уже отправлена. Дождись ответа.') + } - if (state.requestStatus === vars.PENDING_STATUS) { - if (msg.match[2]) { // @username хочет в отпуск - msg.send('У этого пользователя уже есть заявка на отпуск.') - } else { - msg.send('Твоя заявка на отпуск уже отправлена. Дождись ответа.') + return } - return - } + state.creationDate = moment().format(vars.CREATION_DATE_FORMAT) + state.n = vars.FROM_STATE - state.creationDate = moment().format(vars.CREATION_DATE_FORMAT) - state.n = vars.FROM_STATE + this.app.set() - msg.send(`Ok, с какого числа? (${vars.USER_FRIENDLY_DATE_FORMAT})`) + msg.send(`Ok, с какого числа? (${vars.USER_FRIENDLY_DATE_FORMAT})`) + } } + +module.exports = View diff --git a/src/routes/leave/requestsList.js b/src/routes/leave/requestsList.js index 836be1e..efb365c 100644 --- a/src/routes/leave/requestsList.js +++ b/src/routes/leave/requestsList.js @@ -2,51 +2,56 @@ const moment = require('moment') const routines = require('hubot-routines') const vars = require('../../vars') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - if (!await routines.isAdmin(msg.robot, msg.message.user.name)) { - msg.send(vars.ACCESS_DENIED_MSG) - return +class View extends AbstractView { + init (options) { + options.app = 'leave' + options.admin = true } - const users = await routines.getAllUsers(msg.robot) + async callback (msg) { + const users = await routines.getAllUsers(msg.robot) - const formatLine = user => { - const username = user.name - const from = user.vivaLasVegas.leaveStart - const to = user.vivaLasVegas.leaveEnd + const formatLine = user => { + const username = user.name + const from = user.vivaLasVegas.leaveStart + const to = user.vivaLasVegas.leaveEnd - const formattedDate = - moment(`${from.day}.${from.month}.${from.year}`, 'D.M.YYYY').format('DD.MM.YYYY') + - ' - ' + - moment(`${to.day}.${to.month}.${to.year}`, 'D.M.YYYY').format('DD.MM.YYYY') + const formattedDate = + moment(`${from.day}.${from.month}.${from.year}`, 'D.M.YYYY').format('DD.MM.YYYY') + + ' - ' + + moment(`${to.day}.${to.month}.${to.year}`, 'D.M.YYYY').format('DD.MM.YYYY') - return ` @${username} ${formattedDate}` - } + return ` @${username} ${formattedDate}` + } - const sorting = (a, b, format) => { - const first = moment(a, format) - const second = moment(b, format) + const sorting = (a, b, format) => { + const first = moment(a, format) + const second = moment(b, format) - return first.unix() - second.unix() - } + return first.unix() - second.unix() + } - const approved = users - .filter(user => user.vivaLasVegas && user.vivaLasVegas.requestStatus === vars.APPROVED_STATUS) - .sort((a, b) => sorting(a.vivaLasVegas.leaveStart, b.vivaLasVegas.leaveStart, '')) - .map(formatLine) - .join('\n') - const pending = users - .filter(user => user.vivaLasVegas && user.vivaLasVegas.requestStatus === vars.PENDING_STATUS) - .sort((a, b) => sorting(a.vivaLasVegas.leaveStart, b.vivaLasVegas.leaveStart, '')) - .map(formatLine) - .join('\n') + const approved = users + .filter(user => user.vivaLasVegas && user.vivaLasVegas.requestStatus === vars.APPROVED_STATUS) + .sort((a, b) => sorting(a.vivaLasVegas.leaveStart, b.vivaLasVegas.leaveStart, '')) + .map(formatLine) + .join('\n') + const pending = users + .filter(user => user.vivaLasVegas && user.vivaLasVegas.requestStatus === vars.PENDING_STATUS) + .sort((a, b) => sorting(a.vivaLasVegas.leaveStart, b.vivaLasVegas.leaveStart, '')) + .map(formatLine) + .join('\n') - const result = [] + const result = [] - if (approved) result.push(`*Одобренные заявки:*\n ${approved}`) - if (pending) result.push(`*Ожидающие подтверждения:*\n ${pending}`) - if (!result.length) result.push('Никто не собирается в отпуск.') + if (approved) result.push(`*Одобренные заявки:*\n ${approved}`) + if (pending) result.push(`*Ожидающие подтверждения:*\n ${pending}`) + if (!result.length) result.push('Никто не собирается в отпуск.') - msg.send(result.join('\n')) + msg.send(result.join('\n')) + } } + +module.exports = View diff --git a/src/routes/leave/userIsPlanningToGoOnLeave.js b/src/routes/leave/userIsPlanningToGoOnLeave.js index a4263de..28494b8 100644 --- a/src/routes/leave/userIsPlanningToGoOnLeave.js +++ b/src/routes/leave/userIsPlanningToGoOnLeave.js @@ -3,56 +3,66 @@ const routines = require('hubot-routines') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const answer = msg.match[1].toLowerCase().trim() - const customer = await routines.findUserByName(msg.robot, msg.message.user.name) - - if (!customer.vivaLasVegas.allocation) { - msg.send(vars.CONFUSED_MSG) - return +class View extends AbstractView { + init (options) { + options.app = 'leave' + options.admin = true } - const user = await routines.findUserByName(msg.robot, customer.vivaLasVegas.allocation) - const state = await utils.getStateFromBrain(msg.robot, user.name) + async callback (msg) { + const answer = msg.match[1].toLowerCase().trim() + const customer = await routines.findUserByName(msg.robot, msg.message.user.name) - if (state.n !== vars.CONFIRM_STATE) { - msg.send(vars.CONFUSED_MSG) - return - } + if (!customer.vivaLasVegas.allocation) { + msg.send(vars.CONFUSED_MSG) + return + } - if (answer === 'да, планирует') { - const from = moment(`${state.leaveStart.day}.${state.leaveStart.month}`, 'D.M') - const to = moment(`${state.leaveEnd.day}.${state.leaveEnd.month}`, 'D.M') + const user = await routines.findUserByName(msg.robot, customer.vivaLasVegas.allocation) + const state = await utils.getStateFromBrain(msg.robot, user.name) + + if (state.n !== vars.CONFIRM_STATE) { + msg.send(vars.CONFUSED_MSG) + return + } - state.requestStatus = vars.APPROVED_STATUS - state.reportToCustomer = false + if (answer === 'да, планирует') { + const from = moment(`${state.leaveStart.day}.${state.leaveStart.month}`, 'D.M') + const to = moment(`${state.leaveEnd.day}.${state.leaveEnd.month}`, 'D.M') - const googleEvent = vars.GOOGLE_API ? 'Событие добавлено в календарь.' : '' + state.requestStatus = vars.APPROVED_STATUS + state.reportToCustomer = false - if (vars.GOOGLE_API) { - const startDay = from.format('YYYY-MM-DD') - const endDay = to.add(1, 'day').format('YYYY-MM-DD') + const googleEvent = vars.GOOGLE_API ? 'Событие добавлено в календарь.' : '' - utils.addEventToCalendar(msg.robot, startDay, endDay, user, vars.GOOGLE_EVENT_VACATION) - .then(eventId => { state.eventId = eventId }) + if (vars.GOOGLE_API) { + const startDay = from.format('YYYY-MM-DD') + const endDay = to.add(1, 'day').format('YYYY-MM-DD') + + utils.addEventToCalendar(msg.robot, startDay, endDay, user, vars.GOOGLE_EVENT_VACATION) + .then(eventId => { state.eventId = eventId }) + } + + const message = `Пользователем @${customer.name} только что создана и одобрена заявка на отпуск @${user.name} c ${from.format('DD.MM')} по ${to.format('DD.MM')}.` + msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, message) + msg.send(`Заявка на отпуск для пользователя @${user.name} создана и одобрена. ${googleEvent}`) + const question = routines.buildMessageWithButtons( + `Привет, тебе оформлен отпуск с ${from.format('DD.MM')} по ${to.format('DD.MM')}. Заказчик предупрежден?`, + [ + ['Да', 'Да, предупрежден'], + ['Нет', 'Нет, не предупрежден'] + ] + ) + msg.robot.adapter.sendDirect({ user: { name: user.name } }, question) + } else if (answer === 'нет, не планирует') { + msg.send('Я прервал процесс формирования заявки на отпуск.') } - const message = `Пользователем @${customer.name} только что создана и одобрена заявка на отпуск @${user.name} c ${from.format('DD.MM')} по ${to.format('DD.MM')}.` - msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, message) - msg.send(`Заявка на отпуск для пользователя @${user.name} создана и одобрена. ${googleEvent}`) - const question = routines.buildMessageWithButtons( - `Привет, тебе оформлен отпуск с ${from.format('DD.MM')} по ${to.format('DD.MM')}. Заказчик предупрежден?`, - [ - ['Да', 'Да, предупрежден'], - ['Нет', 'Нет, не предупрежден'] - ] - ) - msg.robot.adapter.sendDirect({ user: { name: user.name } }, question) - } else if (answer === 'нет, не планирует') { - msg.send('Я прервал процесс формирования заявки на отпуск.') + delete state.n + delete customer.vivaLasVegas.allocation } - - delete state.n - delete customer.vivaLasVegas.allocation } + +module.exports = View diff --git a/src/routes/leave/vivaReset.js b/src/routes/leave/vivaReset.js index e779a2a..91c4729 100644 --- a/src/routes/leave/vivaReset.js +++ b/src/routes/leave/vivaReset.js @@ -2,55 +2,60 @@ const moment = require('moment') const routines = require('hubot-routines') const vars = require('../../vars') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - if (!await routines.isAdmin(msg.robot, msg.message.user.name)) { - return msg.send(vars.ACCESS_DENIED_MSG) +class View extends AbstractView { + init (options) { + options.admin = true } - const username = msg.match[2] - const leaveStart = msg.match[3] === '*' ? null : moment(msg.match[3], 'D.M.YYYY') - const leaveEnd = msg.match[4] === '*' ? null : moment(msg.match[4], 'D.M.YYYY') + async callback (msg) { + const username = msg.match[2] + const leaveStart = msg.match[3] === '*' ? null : moment(msg.match[3], 'D.M.YYYY') + const leaveEnd = msg.match[4] === '*' ? null : moment(msg.match[4], 'D.M.YYYY') - if (![leaveStart, leaveEnd].every(item => item === null || item.isValid())) { - return msg.send(vars.INVALID_DATE_MSG) - } - - const user = await routines.findUserByName(msg.robot, username) - - if (user) { - let day, month, year - const dates = {} - - if (!user.vivaLasVegas || !user.vivaLasVegas.leaveStart || !user.vivaLasVegas.leaveEnd) { - return msg.send('У этого пользователя не планировался отпуск.') + if (![leaveStart, leaveEnd].every(item => item === null || item.isValid())) { + return msg.send(vars.INVALID_DATE_MSG) } - if (leaveStart) { - day = leaveStart.date() - month = leaveStart.month() + 1 - year = leaveStart.year() - user.vivaLasVegas.leaveStart = { day, month, year } - dates.leaveStart = moment(`${day}.${month}.${year}`, 'D.M.YYYY').format('DD.MM.YYYY') + const user = await routines.findUserByName(msg.robot, username) + + if (user) { + let day, month, year + const dates = {} + + if (!user.vivaLasVegas || !user.vivaLasVegas.leaveStart || !user.vivaLasVegas.leaveEnd) { + return msg.send('У этого пользователя не планировался отпуск.') + } + + if (leaveStart) { + day = leaveStart.date() + month = leaveStart.month() + 1 + year = leaveStart.year() + user.vivaLasVegas.leaveStart = { day, month, year } + dates.leaveStart = moment(`${day}.${month}.${year}`, 'D.M.YYYY').format('DD.MM.YYYY') + } else { + const leaveDate = Object.values(user.vivaLasVegas.leaveStart).join('.') + dates.leaveStart = moment(leaveDate, 'D.M.YYYY').format('DD.MM.YYYY') + } + + if (leaveEnd) { + day = leaveEnd.date() + month = leaveEnd.month() + 1 + year = leaveEnd.year() + user.vivaLasVegas.leaveEnd = { day, month, year } + dates.leaveEnd = moment(`${day}.${month}.${year}`, 'D.M.YYYY').format('DD.MM.YYYY') + } else { + const leaveDate = Object.values(user.vivaLasVegas.leaveEnd).join('.') + dates.leaveEnd = moment(leaveDate, 'D.M.YYYY').format('DD.MM.YYYY') + } + + user.vivaLasVegas.requestStatus = vars.APPROVED_STATUS + msg.send(`Даты отпуска успешно перезаписаны!\n@${username} в отпуске с ${dates.leaveStart} по ${dates.leaveEnd}.`) } else { - const leaveDate = Object.values(user.vivaLasVegas.leaveStart).join('.') - dates.leaveStart = moment(leaveDate, 'D.M.YYYY').format('DD.MM.YYYY') + msg.send('*Ошибка*. Не удалось найти пользователя.') } - - if (leaveEnd) { - day = leaveEnd.date() - month = leaveEnd.month() + 1 - year = leaveEnd.year() - user.vivaLasVegas.leaveEnd = { day, month, year } - dates.leaveEnd = moment(`${day}.${month}.${year}`, 'D.M.YYYY').format('DD.MM.YYYY') - } else { - const leaveDate = Object.values(user.vivaLasVegas.leaveEnd).join('.') - dates.leaveEnd = moment(leaveDate, 'D.M.YYYY').format('DD.MM.YYYY') - } - - user.vivaLasVegas.requestStatus = vars.APPROVED_STATUS - msg.send(`Даты отпуска успешно перезаписаны!\n@${username} в отпуске с ${dates.leaveStart} по ${dates.leaveEnd}.`) - } else { - msg.send('*Ошибка*. Не удалось найти пользователя.') } } + +module.exports = View diff --git a/src/routes/time-off/timeOffIsNotNeeded.js b/src/routes/time-off/timeOffIsNotNeeded.js index 2e5013e..dda4c5f 100644 --- a/src/routes/time-off/timeOffIsNotNeeded.js +++ b/src/routes/time-off/timeOffIsNotNeeded.js @@ -1,29 +1,42 @@ const routines = require('hubot-routines') -module.exports = async msg => { - const errorMsg = 'Этот пользователь и не собирался брать отгул.' - const user = msg.message.user +const { AbstractView } = require('hubot-engine') - if (!user.timeOff || !user.timeOff.allocation) { - return msg.send(errorMsg) +class View extends AbstractView { + init (options) { + options.app = 'timeOff' + options.admin = true } - const candidate = await routines.findUserByName( - msg.robot, - user.timeOff.allocation - ) + async callback (msg) { + const errorMsg = 'Этот пользователь и не собирался брать отгул.' + const user = msg.message.user - if (!candidate.timeOff.list.find(item => !item.type)) { - return msg.send(errorMsg) - } + if (!user.timeOff || !user.timeOff.allocation) { + return msg.send(errorMsg) + } + + const candidate = await routines.findUserByName( + msg.robot, + user.timeOff.allocation + ) + + if (!candidate.timeOff.list.find(item => !item.type)) { + return msg.send(errorMsg) + } - // Deleting all nullable type attribute - candidate.timeOff.list = candidate.timeOff.list.filter(item => { - return item.type - }) + // Deleting all nullable type attribute + candidate.timeOff.list = candidate.timeOff.list.filter(item => { + return item.type + }) - delete user.timeOff.allocation - delete user.vivaLasVegas.n + delete user.timeOff.allocation + delete user.vivaLasVegas.n - msg.send(`Отгул для @${candidate.name} отменен.`) + this.app.clear() + + msg.send(`Отгул для @${candidate.name} отменен.`) + } } + +module.exports = View diff --git a/src/routes/time-off/timeOffType.js b/src/routes/time-off/timeOffType.js index 29a23d8..4fd4ba8 100644 --- a/src/routes/time-off/timeOffType.js +++ b/src/routes/time-off/timeOffType.js @@ -3,54 +3,66 @@ const routines = require('hubot-routines') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const errorMsg = 'Я не знал, что пользователь собирался брать отгул. Если хочешь сообщить об отгуле, скажи @username хочет отгул.' - const user = msg.message.user - - if (!user.timeOff || !user.timeOff.allocation) { - return msg.send(errorMsg) +class View extends AbstractView { + init (options) { + options.app = 'timeOff' + options.admin = true } - const candidate = await routines.findUserByName(msg.robot, user.timeOff.allocation) + async callback (msg) { + const errorMsg = 'Я не знал, что пользователь собирался брать отгул. Если хочешь сообщить об отгуле, скажи @username хочет отгул.' + const user = msg.message.user - if (!candidate) { - return msg.send(errorMsg) - } + if (!user.timeOff || !user.timeOff.allocation) { + return msg.send(errorMsg) + } - candidate.timeOff = candidate.timeOff || {} - candidate.timeOff.list = candidate.timeOff.list || [] + const candidate = await routines.findUserByName(msg.robot, user.timeOff.allocation) - if (!candidate.timeOff.list.find(item => !item.type)) { - return msg.send(errorMsg) - } + if (!candidate) { + return msg.send(errorMsg) + } - const start = moment(candidate.timeOff.list.find(item => !item.type)) - .format('YYYY-MM-DD') - - const end = moment(start, 'YYYY-MM-DD') - .add(1, 'day') - .format('YYYY-MM-DD') - - const timeOffType = (msg.match[1] || msg.match[2] || msg.match[3]).toLowerCase() - const description = `Отгул ${timeOffType}` - const date = candidate.timeOff.list.find(item => !item.type).date - - if (vars.GOOGLE_API) { - utils.addEventToCalendar( - msg.robot, - start, - end, - candidate, - 'Отгул', - description - ) - } + candidate.timeOff = candidate.timeOff || {} + candidate.timeOff.list = candidate.timeOff.list || [] + + if (!candidate.timeOff.list.find(item => !item.type)) { + return msg.send(errorMsg) + } + + const start = moment(candidate.timeOff.list.find(item => !item.type)) + .format('YYYY-MM-DD') - candidate.timeOff.list.find(item => !item.type).type = timeOffType - delete user.timeOff.allocation - delete user.vivaLasVegas.n + const end = moment(start, 'YYYY-MM-DD') + .add(1, 'day') + .format('YYYY-MM-DD') - msg.send(`Отлично. Значит @${candidate.name} берет отгул ${timeOffType} ${date}.`) - msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Пользователем @${user.name} только что оформлен отгул ${timeOffType} для @${candidate.name} на ${date}.`) + const timeOffType = (msg.match[1] || msg.match[2] || msg.match[3]).toLowerCase() + const description = `Отгул ${timeOffType}` + const date = candidate.timeOff.list.find(item => !item.type).date + + if (vars.GOOGLE_API) { + utils.addEventToCalendar( + msg.robot, + start, + end, + candidate, + 'Отгул', + description + ) + } + + candidate.timeOff.list.find(item => !item.type).type = timeOffType + delete user.timeOff.allocation + delete user.vivaLasVegas.n + + this.app.clear() + + msg.send(`Отлично. Значит @${candidate.name} берет отгул ${timeOffType} ${date}.`) + msg.robot.messageRoom(vars.LEAVE_COORDINATION_CHANNEL, `Пользователем @${user.name} только что оформлен отгул ${timeOffType} для @${candidate.name} на ${date}.`) + } } + +module.exports = View diff --git a/src/routes/time-off/userWantsTimeOff.js b/src/routes/time-off/userWantsTimeOff.js index 1a1481a..46c5e4c 100644 --- a/src/routes/time-off/userWantsTimeOff.js +++ b/src/routes/time-off/userWantsTimeOff.js @@ -1,40 +1,50 @@ const routines = require('hubot-routines') const vars = require('../../vars') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const user = msg.message.user - const username = msg.match[2] - const candidate = await routines.findUserByName(msg.robot, username) - - if (!await routines.isAdmin(msg.robot, user.name)) return msg.send(vars.ACCESS_DENIED_MSG) - - if (!candidate) return msg.send(vars.UNKNOWN_USER_MSG) - - if (user.timeOff && user.timeOff.allocation) { - const correctUser = await routines.findUserByName(msg.robot, user.timeOff.allocation) - if (!correctUser.timeOff.list || !correctUser.timeOff.list.find(user => !user.type)) { - return msg.send( - `Дaвай по порядку. Какого числа @${correctUser.name} хочет взять отгул?` - ) - } else { - const date = correctUser.timeOff.list.find(item => !item.type).date - return msg.send(routines.buildMessageWithButtons( - `Дaвай по порядку. Какой отгул хочет взять @${correctUser.name} ${date}?`, - [ - ['С отработкой', 'С отработкой'], - ['За свой счет', 'За свой счет'], - ['В счет отпуска', 'В счет отпуска'], - ['Отмена', 'Отгул не нужен'] - ] - )) - } +class View extends AbstractView { + init (options) { + options.app = 'timeOff' + options.admin = true } - candidate.timeOff = candidate.timeOff || {} - user.timeOff = user.timeOff || {} + async callback (msg) { + const user = msg.message.user + const username = msg.match[2] + const candidate = await routines.findUserByName(msg.robot, username) + + if (!candidate) return msg.send(vars.UNKNOWN_USER_MSG) + + this.app.set() + + if (user.timeOff && user.timeOff.allocation) { + const correctUser = await routines.findUserByName(msg.robot, user.timeOff.allocation) + if (!correctUser.timeOff.list || !correctUser.timeOff.list.find(user => !user.type)) { + return msg.send( + `Дaвай по порядку. Какого числа @${correctUser.name} хочет взять отгул?` + ) + } else { + const date = correctUser.timeOff.list.find(item => !item.type).date + return msg.send(routines.buildMessageWithButtons( + `Дaвай по порядку. Какой отгул хочет взять @${correctUser.name} ${date}?`, + [ + ['С отработкой', 'С отработкой'], + ['За свой счет', 'За свой счет'], + ['В счет отпуска', 'В счет отпуска'], + ['Отмена', 'Отгул не нужен'] + ] + )) + } + } + + candidate.timeOff = candidate.timeOff || {} + user.timeOff = user.timeOff || {} - user.timeOff.allocation = username + user.timeOff.allocation = username - msg.send(`Когда @${candidate.name} хочет взять отгул?`) + msg.send(`Когда @${candidate.name} хочет взять отгул?`) + } } + +module.exports = View diff --git a/src/routes/work-from-home/workFromHome.js b/src/routes/work-from-home/workFromHome.js index 26266ec..f7eac96 100644 --- a/src/routes/work-from-home/workFromHome.js +++ b/src/routes/work-from-home/workFromHome.js @@ -1,9 +1,20 @@ const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async function (msg) { - const state = await utils.getStateFromBrain(msg.robot, msg.message.user.name) +class View extends AbstractView { + init (options) { + options.app = 'workFromHome' + } - state.n = vars.WAITING_DATE_STATE - msg.send(`Ok, в какой день? (сегодня/завтра/${vars.USER_FRIENDLY_DATE_FORMAT})`) + async callback (msg) { + const state = await utils.getStateFromBrain(msg.robot, msg.message.user.name) + + this.app.set() + + state.n = vars.WAITING_DATE_STATE + msg.send(`Ok, в какой день? (сегодня/завтра/${vars.USER_FRIENDLY_DATE_FORMAT})`) + } } + +module.exports = View diff --git a/src/routes/work-from-home/workFromHomeAgree.js b/src/routes/work-from-home/workFromHomeAgree.js index f2fab6d..f14f208 100644 --- a/src/routes/work-from-home/workFromHomeAgree.js +++ b/src/routes/work-from-home/workFromHomeAgree.js @@ -3,39 +3,52 @@ const moment = require('moment') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async msg => { - const username = msg.message.user.name - const state = await utils.getStateFromBrain(msg.robot, username) - const answer = msg.match[1].toLowerCase().trim() +class View extends AbstractView { + init (options) { + options.app = 'workFromHome' + } + + async callback (msg) { + const username = msg.message.user.name + const state = await utils.getStateFromBrain(msg.robot, username) + const answer = msg.match[1].toLowerCase().trim() + + if (state.n === vars.WAITING_CONFIRMATION_STATE) { + if (answer === 'да, согласован') { + const { dateRequested } = state - if (state.n === vars.WAITING_CONFIRMATION_STATE) { - if (answer === 'да, согласован') { - const { dateRequested } = state + state.n = vars.INIT_STATE - state.n = vars.INIT_STATE + state.dateOfWorkFromHome = state.dateOfWorkFromHome || [] + state.dateOfWorkFromHome.push({ date: dateRequested }) + state.dateRequested = null - state.dateOfWorkFromHome = state.dateOfWorkFromHome || [] - state.dateOfWorkFromHome.push({ date: dateRequested }) - state.dateRequested = null + if (vars.GOOGLE_API) { + const date = moment(dateRequested, vars.CREATION_DATE_FORMAT) + const startDay = date.format('YYYY-MM-DD') + const endDay = date.add(1, 'days').format('YYYY-MM-DD') + const user = await routines.findUserByName(msg.robot, username) + const event = state.dateOfWorkFromHome.find(item => item.date === dateRequested) - if (vars.GOOGLE_API) { - const date = moment(dateRequested, vars.CREATION_DATE_FORMAT) - const startDay = date.format('YYYY-MM-DD') - const endDay = date.add(1, 'days').format('YYYY-MM-DD') - const user = await routines.findUserByName(msg.robot, username) - const event = state.dateOfWorkFromHome.find(item => item.date === dateRequested) + utils.addEventToCalendar(msg.robot, startDay, endDay, user, vars.GOOGLE_EVENT_WORK_FROM_HOME) + .then(eventId => { event.eventId = eventId }) - utils.addEventToCalendar(msg.robot, startDay, endDay, user, vars.GOOGLE_EVENT_WORK_FROM_HOME) - .then(eventId => { event.eventId = eventId }) + msg.send(`Отлично. Я создал событие в календаре. Ты работаешь из дома ${dateRequested}.`) + } else { + msg.send(`Отлично. Ты работаешь из дома ${dateRequested}.`) + } - msg.send(`Отлично. Я создал событие в календаре. Ты работаешь из дома ${dateRequested}.`) + this.app.clear() } else { - msg.send(`Отлично. Ты работаешь из дома ${dateRequested}.`) + state.n = vars.INIT_STATE + msg.send('Тогда сначала согласуй, а потом пробуй еще раз (ты знаешь где меня найти).') + + this.app.clear() } - } else { - state.n = vars.INIT_STATE - msg.send('Тогда сначала согласуй, а потом пробуй еще раз (ты знаешь где меня найти).') } } } + +module.exports = View diff --git a/src/routes/work-from-home/workFromHomeCancel.js b/src/routes/work-from-home/workFromHomeCancel.js index 5c188cc..f654b23 100644 --- a/src/routes/work-from-home/workFromHomeCancel.js +++ b/src/routes/work-from-home/workFromHomeCancel.js @@ -3,55 +3,65 @@ const routines = require('hubot-routines') const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async (msg) => { - const state = await utils.getStateFromBrain(msg.robot, msg.message.user.name) - - state.dateOfWorkFromHome = state.dateOfWorkFromHome || [] +class View extends AbstractView { + init (options) { + options.app = 'workFromHome' + } - const upcomingEvents = state.dateOfWorkFromHome.filter(item => { - const today = moment().startOf('day') - const event = moment( - typeof item === 'string' ? item : item.date, - vars.CREATION_DATE_FORMAT - ) - return event.isSameOrAfter(today) - }) + async callback (msg) { + const state = await utils.getStateFromBrain(msg.robot, msg.message.user.name) - if (upcomingEvents.length === 0) { - return msg.send('У тебя нет запланированных дней работы из дома.') - } + state.dateOfWorkFromHome = state.dateOfWorkFromHome || [] - if (upcomingEvents.length === 1) { - const scheduledDay = upcomingEvents[0] - state.dateOfWorkFromHome = state.dateOfWorkFromHome.filter(item => { - if (typeof item === 'string') { - return item !== (typeof scheduledDay === 'string' ? scheduledDay : scheduledDay.date) - } else { - return item.date !== scheduledDay.date - } + const upcomingEvents = state.dateOfWorkFromHome.filter(item => { + const today = moment().startOf('day') + const event = moment( + typeof item === 'string' ? item : item.date, + vars.CREATION_DATE_FORMAT + ) + return event.isSameOrAfter(today) }) - if (vars.GOOGLE_API && scheduledDay.eventId) { - utils.deleteEventFromCalendar(msg.robot, scheduledDay.eventId) + if (upcomingEvents.length === 0) { + return msg.send('У тебя нет запланированных дней работы из дома.') } - return msg.send(`У тебя был запланирован день работы из дома на ${typeof scheduledDay === 'string' ? scheduledDay : scheduledDay.date}. Я отменил его.`) - } + if (upcomingEvents.length === 1) { + const scheduledDay = upcomingEvents[0] + state.dateOfWorkFromHome = state.dateOfWorkFromHome.filter(item => { + if (typeof item === 'string') { + return item !== (typeof scheduledDay === 'string' ? scheduledDay : scheduledDay.date) + } else { + return item.date !== scheduledDay.date + } + }) - if (upcomingEvents.length >= 2) { - const buttons = upcomingEvents.map(item => { - if (typeof item === 'string') { - return [item, `Не работаю из дома ${item}`] - } else { - return [item.date, `Не работаю из дома ${item.date}`] + if (vars.GOOGLE_API && scheduledDay.eventId) { + utils.deleteEventFromCalendar(msg.robot, scheduledDay.eventId) } - }) - buttons.push(['Отмена', 'Я не отменяю работу из дома']) - const message = routines.buildMessageWithButtons( - 'У тебя запланировано несколько дней работы из дома. О каком идет речь?', - buttons - ) - msg.send(message) + + return msg.send(`У тебя был запланирован день работы из дома на ${typeof scheduledDay === 'string' ? scheduledDay : scheduledDay.date}. Я отменил его.`) + } + + if (upcomingEvents.length >= 2) { + const buttons = upcomingEvents.map(item => { + if (typeof item === 'string') { + return [item, `Не работаю из дома ${item}`] + } else { + return [item.date, `Не работаю из дома ${item.date}`] + } + }) + buttons.push(['Отмена', 'Я не отменяю работу из дома']) + const message = routines.buildMessageWithButtons( + 'У тебя запланировано несколько дней работы из дома. О каком идет речь?', + buttons + ) + this.app.set() + msg.send(message) + } } } + +module.exports = View diff --git a/src/routes/work-from-home/workFromHomeCancelDate.js b/src/routes/work-from-home/workFromHomeCancelDate.js index 16b0601..9106980 100644 --- a/src/routes/work-from-home/workFromHomeCancelDate.js +++ b/src/routes/work-from-home/workFromHomeCancelDate.js @@ -1,36 +1,47 @@ const vars = require('../../vars') const utils = require('../../utils') +const { AbstractView } = require('hubot-engine') -module.exports = async (msg) => { - const state = await utils.getStateFromBrain(msg.robot, msg.message.user.name) - const date = msg.match[2] +class View extends AbstractView { + init (options) { + options.app = 'workFromHome' + } - state.dateOfWorkFromHome = state.dateOfWorkFromHome || [] + async callback (msg) { + const state = await utils.getStateFromBrain(msg.robot, msg.message.user.name) + const date = msg.match[2] - const event = state.dateOfWorkFromHome.find(item => { - if (typeof item === 'string') { - return item === date - } else { - return item.date === date - } - }) + state.dateOfWorkFromHome = state.dateOfWorkFromHome || [] - if (!event) { - return msg.send(`У тебя не запланирован день работы из дома на ${date}`) - } + const event = state.dateOfWorkFromHome.find(item => { + if (typeof item === 'string') { + return item === date + } else { + return item.date === date + } + }) - if (vars.GOOGLE_API && event.eventId) { - utils.deleteEventFromCalendar(msg.robot, event.eventId) - msg.send('Я тебя понял. :ok_hand: Убираю событие из календаря.') - } else { - msg.send('Я тебя понял. :ok_hand:') - } + if (!event) { + return msg.send(`У тебя не запланирован день работы из дома на ${date}`) + } - state.dateOfWorkFromHome = state.dateOfWorkFromHome.filter(item => { - if (typeof item === 'string') { - return item !== date + if (vars.GOOGLE_API && event.eventId) { + utils.deleteEventFromCalendar(msg.robot, event.eventId) + msg.send('Я тебя понял. :ok_hand: Убираю событие из календаря.') } else { - return item.date !== date + msg.send('Я тебя понял. :ok_hand:') } - }) + + state.dateOfWorkFromHome = state.dateOfWorkFromHome.filter(item => { + if (typeof item === 'string') { + return item !== date + } else { + return item.date !== date + } + }) + + this.app.clear() + } } + +module.exports = View diff --git a/src/routes/work-from-home/workFromHomeContinue.js b/src/routes/work-from-home/workFromHomeContinue.js index b732757..b843281 100644 --- a/src/routes/work-from-home/workFromHomeContinue.js +++ b/src/routes/work-from-home/workFromHomeContinue.js @@ -1,11 +1,22 @@ -module.exports = (msg) => { - const choices = [ - 'Правда жизни такова - чем больше хочешь что-то изменить, тем больше всё остаётся на своих местах…', - 'Чем старше становится человек, тем больше он противится переменам, особенно переменам к лучшему.', - 'Не откладывайте на завтра то, что можно сделать сегодня.', - 'Не будь болваном. Никогда не откладывай на завтра то, что можешь сделать послезавтра.', - 'Свободен лишь тот, кто владеет собой.', - 'Твоя ответственность безмерна — ты свободен.' - ] - msg.send(msg.random(choices)) +const { AbstractView } = require('hubot-engine') + +class View extends AbstractView { + init (options) { + options.app = 'workFromHome' + } + + callback (msg) { + const choices = [ + 'Правда жизни такова - чем больше хочешь что-то изменить, тем больше всё остаётся на своих местах…', + 'Чем старше становится человек, тем больше он противится переменам, особенно переменам к лучшему.', + 'Не откладывайте на завтра то, что можно сделать сегодня.', + 'Не будь болваном. Никогда не откладывай на завтра то, что можешь сделать послезавтра.', + 'Свободен лишь тот, кто владеет собой.', + 'Твоя ответственность безмерна — ты свободен.' + ] + msg.send(msg.random(choices)) + this.app.clear() + } } + +module.exports = View diff --git a/src/viva.js b/src/viva.js index 8d93d37..5c17745 100644 --- a/src/viva.js +++ b/src/viva.js @@ -112,27 +112,95 @@ module.exports = async (robot) => { }) } + const { Router } = require('hubot-engine') + const router = new Router(robot) + + // Leave + router.respond( + /(хочу в отпуск)|(@?(.+) хочет в отпуск)\s*/i, + require('./routes/leave/leaveStart') + ) + router.respond( + /(Да, планирую|Нет, не планирую)\s*$/i, + require('./routes/leave/iAmPlanningToGoOnLeave') + ) + router.respond( + /(отменить заявку @?(.+))\s*/i, + require('./routes/leave/leaveRequestCancel') + ) + router.respond( + /(одобрить|отклонить) заявку @?(.+)\s*/i, + require('./routes/leave/leaveRequestApprove') + ) + router.respond( + /(Да, планирует|Нет, не планирует)\s*/i, + require('./routes/leave/userIsPlanningToGoOnLeave') + ) + router.respond( + /список заявок\s*/i, + require('./routes/leave/requestsList') + ) + router.respond( + /(Да, предупрежден|Нет, не предупрежден)\s*$/i, + require('./routes/leave/customerNotified') + ) + + // Ill + router.respond( + /(я )?(болею|заболел)\s*$/i, + require('./routes/ill/iAmIll') + ) + router.respond( + /(я )?(не болею|выздоровел)\s*/i, + require('./routes/ill/iAmNotIll') + ) + router.respond( + /(Болею и работаю|Болею и не работаю)\s*/i, + require('./routes/ill/illAgree') + ) + router.respond( + /(Да, они предупреждены, что я болею|Нет, они не предупреждены, что я болею)/i, + require('./routes/ill/yesTheyAreNotified') + ) + + // Time-off + router.respond( + /(отгул не нужен)\s*/i, + require('./routes/time-off/timeOffIsNotNeeded') + ) + router.respond( + /(с отработкой)|(за свой счет)|(в счет отпуска)\s*/i, + require('./routes/time-off/timeOffType') + ) + router.respond( + /(@?(.+) хочет отгул)\s*/i, + require('./routes/time-off/userWantsTimeOff') + ) + + // workFromHome + router.respond( + /работаю (из )?дома\s*/i, + require('./routes/work-from-home/workFromHome') + ) + router.respond( + /(Да, согласован|Нет, не согласован)\s*$/i, + require('./routes/work-from-home/workFromHomeAgree') + ) + router.respond( + /не работаю (из )?дома\s*$/i, + require('./routes/work-from-home/workFromHomeCancel') + ) + router.respond( + /не работаю (из )?дома (\d{2}.\d{2}.\d{4})\s*$/i, + require('./routes/work-from-home/workFromHomeCancelDate') + ) + router.respond( + /Я не отменяю работу из дома\s*$/, + require('./routes/work-from-home/workFromHomeContinue') + ) + robot.respond(/(меня не будет( в офисе)?)|((я )?не в офисе)|((я )?не буду в офисе)\s*/i, require('./routes/notInOffice')) - robot.respond(/(хочу в отпуск)|(@?(.+) хочет в отпуск)\s*/i, require('./routes/leave/leaveStart')) - robot.respond(/работаю (из )?дома\s*/i, require('./routes/work-from-home/workFromHome')) - robot.respond(/не работаю (из )?дома\s*$/i, require('./routes/work-from-home/workFromHomeCancel')) - robot.respond(/не работаю (из )?дома (\d{2}.\d{2}.\d{4})\s*$/i, require('./routes/work-from-home/workFromHomeCancelDate')) - robot.respond(/Я не отменяю работу из дома\s*$/, require('./routes/work-from-home/workFromHomeContinue')) robot.respond(vars.regExpMonthYear, require('./routes/monthYearRoute')) - robot.respond(/(Да, планирует|Нет, не планирует)\s*/i, require('./routes/leave/userIsPlanningToGoOnLeave')) - robot.respond(/(Да, планирую|Нет, не планирую)\s*$/i, require('./routes/leave/iAmPlanningToGoOnLeave')) - robot.respond(/(Да, согласован|Нет, не согласован)\s*$/i, require('./routes/work-from-home/workFromHomeAgree')) - robot.respond(/(Да, предупрежден|Нет, не предупрежден)\s*$/i, require('./routes/leave/customerNotified')) - robot.respond(/(отменить заявку @?(.+))\s*/i, require('./routes/leave/leaveRequestCancel')) - robot.respond(/(одобрить|отклонить) заявку @?(.+)\s*/i, require('./routes/leave/leaveRequestApprove')) - robot.respond(/список заявок\s*/i, require('./routes/leave/requestsList')) - robot.respond(/(я )?(болею|заболел)\s*$/i, require('./routes/ill/iAmIll')) - robot.respond(/(Болею и работаю|Болею и не работаю)\s*/i, require('./routes/ill/illAgree')) - robot.respond(/(Да, они предупреждены, что я болею|Нет, они не предупреждены, что я болею)/i, require('./routes/ill/yesTheyAreNotified')) - robot.respond(/(я )?(не болею|выздоровел)\s*/i, require('./routes/ill/iAmNotIll')) - robot.respond(/(@?(.+) хочет отгул)\s*/i, require('./routes/time-off/userWantsTimeOff')) - robot.respond(/(с отработкой)|(за свой счет)|(в счет отпуска)\s*/i, require('./routes/time-off/timeOffType')) - robot.respond(/(отгул не нужен)\s*/i, require('./routes/time-off/timeOffIsNotNeeded')) /** * Overwrites vacation dates. *