diff --git a/.env.example b/.env.example index aa83756..d665c35 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,7 @@ CHANNEL_ID=C0XXXYYYZZZ CLOSURE_DAY=25 +DEBUG=0 +DEBUG_DATE= JOB_HOUR=10 JOB_MONTH_END=11 JOB_MONTH_START=2 diff --git a/README.md b/README.md index 1ecc1ba..7fa127f 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ The app uses `.env` config which is based on `.env.example`: - `CHANNEL_ID` – Slack channel ID for messaging - `ClOSURE_DAY` – day of month on which the worklog agenda closes (defaults to `25`) +- `DEBUG` – set `1` to disable sending messages and only output to console (defaults to `0`) +- `DEBUG_DATE` – when `DEBUG=1` use this to simulate a specific date for test run (defaults to `undefined`) - `JOB_HOUR` – hour at which the messaging schedule runs daily (defaults to `10`) - `JOB_MONTH_END` – month in which the messaging schedule ends (defaults to `11`) - `JOB_MONTH_START` – month in which the messaging schedule starts (defaults to `2`) diff --git a/src/app.ts b/src/app.ts index 4288145..f7207c1 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,6 +4,8 @@ import { Range, RecurrenceRule, scheduleJob } from 'node-schedule'; import { MAX_MONTH } from './constants'; import { CHANNEL_ID, + DEBUG, + DEBUG_DATE, JOB_HOUR, JOB_MONTH_END, JOB_MONTH_START, @@ -35,6 +37,12 @@ logger.logInfo( JSON.stringify({ CHANNEL_ID, JOB_MONTH_START, JOB_MONTH_END, JOB_HOUR, TZ }), ); +if (DEBUG) { + logger.logInfo('Running in DEBUG mode, not actually sending to Slack.'); + if (DEBUG_DATE) logger.logInfo(`Using DEBUG_DATE: ${DEBUG_DATE}`); + run().catch(logger.logError); +} + const shutdownGracefully = () => { job.cancel(); process.exit(0); diff --git a/src/date.ts b/src/date.ts index 6b9f23e..975af5e 100644 --- a/src/date.ts +++ b/src/date.ts @@ -7,9 +7,9 @@ import { SUNDAY, SUNDAY_DIFF, } from './constants'; -import { CLOSURE_DAY } from './environment'; +import { CLOSURE_DAY, DEBUG_DATE } from './environment'; -export const now = () => new Date(); +export const now = () => (DEBUG_DATE ? new Date(DEBUG_DATE) : new Date()); export const formatMonth = (date: Date) => date.getMonth() + 1; @@ -30,3 +30,9 @@ export const getFirstNotificationDay = () => export const getLastNotificationDay = () => getFinalDay() - LAST_NOTIFICATION_DAYS; + +export const isFinalDayAtWeekend = () => { + const date = now(); + date.setDate(CLOSURE_DAY); + return [SATURDAY, SUNDAY].includes(date.getDay()); +}; diff --git a/src/environment.ts b/src/environment.ts index 9f3b3ec..22a1d2a 100644 --- a/src/environment.ts +++ b/src/environment.ts @@ -4,6 +4,8 @@ dotenv.config(); export const CHANNEL_ID = process.env.CHANNEL_ID ?? ''; export const CLOSURE_DAY = Number(process.env.CLOSURE_DAY ?? '25'); +export const DEBUG = process.env.DEBUG === '1'; +export const DEBUG_DATE = DEBUG ? process.env.DEBUG_DATE : undefined; export const JOB_HOUR = Number(process.env.JOB_HOUR ?? '10'); export const JOB_MONTH_END = Number(process.env.JOB_MONTH_END ?? '11'); export const JOB_MONTH_START = Number(process.env.JOB_MONTH_START ?? '2'); diff --git a/src/messages.ts b/src/messages.ts index 94b4f6c..f523874 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -4,7 +4,7 @@ import { JANUARY, LAST_NOTIFICATION_DAYS, } from './constants'; -import { formatMonth, getFinalDay, now } from './date'; +import { formatMonth, getFinalDay, isFinalDayAtWeekend, now } from './date'; import { CLOSURE_DAY } from './environment'; import { NotificationDay } from './types'; @@ -27,8 +27,20 @@ const getPeriod = () => { return `${startDay}.${startMonth}. – ${endDay}.${endMonth}. včetně`; }; -export const createFirstMessage = () => - `Ahoj 👋, blíží se nám další uzávěrka fakturačního období, tentokrát *${getPeriod()}*. Začněte si prosím chystat vaše worklogy a mějte vše *${getFinalDay()}. do 12:00* připraveno. Díky moc! 🫶`; +export const createFirstMessage = () => { + const message = [ + `Ahoj 👋, blíží se nám další uzávěrka fakturačního období, tentokrát *${getPeriod()}*.`, + ]; + if (isFinalDayAtWeekend()) { + message.push( + `Jelikož nám konec období vychází na víkend, musíme vše uzavřít v pátek.`, + ); + } + message.push( + `Začněte si prosím chystat vaše worklogy a mějte vše *${getFinalDay()}. do 12:00* připraveno. Díky moc! 🫶`, + ); + return message.join(' '); +}; export const createNotificationMessage = (day: NotificationDay) => { const days = day === LAST_NOTIFICATION_DAYS ? 'den' : 'dny'; diff --git a/src/send-message.ts b/src/send-message.ts index cf3a2c5..6b11c46 100644 --- a/src/send-message.ts +++ b/src/send-message.ts @@ -1,8 +1,15 @@ import { client } from './client'; -import { CHANNEL_ID } from './environment'; +import { CHANNEL_ID, DEBUG } from './environment'; import { logger } from './logger'; import { SendMessageProperties } from './types'; +const handleSend = async ({ text }: SendMessageProperties) => + client.chat.postMessage({ + channel: CHANNEL_ID, + mrkdwn: true, + text, + }); + const formatError = (error: unknown) => { if (error instanceof Error) return error; return new Error(String(error)); @@ -10,11 +17,7 @@ const formatError = (error: unknown) => { export const sendMessage = async ({ text }: SendMessageProperties) => { try { - await client.chat.postMessage({ - channel: CHANNEL_ID, - mrkdwn: true, - text, - }); + if (!DEBUG) await handleSend({ text }); logger.logSuccess(`SENT: ${text}`); } catch (error: unknown) { logger.logError(formatError(error));