feat: 完成简单卡片

This commit is contained in:
zhaoyingbo 2023-09-03 18:59:33 +08:00
parent 686b3efb34
commit 3fbcef7994
11 changed files with 607 additions and 207 deletions

View File

@ -246,9 +246,5 @@ interface User {
* open_id
*/
open_id: string;
/**
* 提醒列表
*/
remindList: string[];
}
```

133
routes/bot/actionMsg.js Normal file
View File

@ -0,0 +1,133 @@
const { genSetRemindCard, genRemindCard } = require("../../utils/genCard");
const { getNextRemindTime } = require("../../utils/nextRemindTime");
const {
upsertUser,
upsertRemindByMessageId,
getRemindRecordByMessageId,
getRemind,
updateNextRemindTime,
updateRemindRecord,
closeRemind,
} = require("../../utils/pb");
const { updateCard } = require("../../utils/sendMsg");
const { trans2LocalTime, getNowStr, getDelayedTimeStr } = require("../../utils/time");
/**
* 是否为Action消息
* @param {LarkUserAction} body
*/
module.exports.isActionMsg = (body) => {
return body?.action;
};
/**
* 获取Action类型
* @param {LarkUserAction} body
* @returns {string} Action类型
*/
const getActionType = (body) => {
return body?.action?.tag;
}
/**
* 处理时间选择事件
* @param {LarkUserAction} body
* @returns
*/
const manageTimePicker = async (body) => {
const userInfo = await upsertUser(body);
const { content } = body?.action?.value;
if (!content) return;
const rawTime = body?.action?.option;
// 将'2023-09-03 10:35 +0700'转换为'2023-09-03 11:35'
const time = trans2LocalTime(rawTime);
// 判断选择的时间是否是将来的时间
if (new Date(time) <= new Date()) {
const card = genSetRemindCard(
"pendingErr",
content,
getNowStr(),
userInfo.userId
);
await updateCard(body.open_message_id, card);
return;
}
const remindInfo = {
owner: userInfo.id,
messageId: body.open_message_id,
subscriberType: "chat_id",
subscriberId: body.open_chat_id,
needReply: false,
delayTime: 0,
cardInfo: {
title: "🍳小煎蛋提醒!",
content: `📝 ${content}`,
},
frequency: "single",
time,
enabled: true,
nextRemindTime: time,
};
// 数据库写入提醒这里根据messageId更新或者创建是为了防止垃圾飞书不更新消息
await upsertRemindByMessageId(remindInfo);
// 更新卡片
const card = genSetRemindCard("confirmed", content, time, userInfo.userId);
await updateCard(body.open_message_id, card);
return;
};
/**
* 处理按钮点击事件
* @param {LarkUserAction} body
*/
const manageBtnClick = async (body) => {
const { result, type, text, remindId } = body?.action?.value;
if (!type) return;
// 当前点击的卡片
const remindRecord = await getRemindRecordByMessageId(body.open_message_id);
// 没有卡片,返回
if (!remindRecord) return;
// 当前卡片的提醒信息
const remind = await getRemind(remindId)
// 没有提醒信息,返回
if (!remind) return;
// 当前时间即为回复时间
const interactTime = getNowStr()
// 创建卡片
const card = genRemindCard(remind, type, { type, text }, interactTime)
// 更新飞书的卡片
await updateCard(body.open_message_id, card)
// 更新remindRecord
const newRecord = {
...remindRecord,
status: type,
interactTime,
result: JSON.stringify({ type, text, result }),
}
await updateRemindRecord(remindRecord.id, newRecord)
// 如果是非延迟的单次提醒到此就结束了
if (type !== 'delayed' && remind.frequency === 'single') {
closeRemind(remind.id)
return
}
// 更新下一次的提醒时间
const nextRemindTime = type === 'delayed' ? getDelayedTimeStr(remind.delayTime) : getNextRemindTime(remind)
await updateNextRemindTime(remind.id, nextRemindTime)
};
/**
* 处理Action消息
* @param {LarkUserAction} body
*/
module.exports.manageActionMsg = async (body) => {
const actionType = getActionType(body);
if (actionType === 'picker_datetime') {
manageTimePicker(body);
}
if (actionType === 'button') {
manageBtnClick(body);
}
return;
};

View File

@ -1,4 +1,6 @@
const { sendMsg } = require("./sendMsg")
const { genSetRemindCard } = require("../../utils/genCard");
const { sendMsg } = require("../../utils/sendMsg");
const { getDelayedTimeStr } = require("../../utils/time");
/**
* 获取事件文本类型
@ -81,10 +83,33 @@ const filterGetInfoCommand = (body) => {
return true
}
module.exports = {
getMsgType,
getChatId,
getMsgText,
filterIllegalMsg,
filterGetInfoCommand,
}
/**
* 发送设置提醒卡片
* @param {LarkMessageEvent} body
*/
const sendSetRemindCard = async (body) => {
const text = getMsgText(body);
const setRemindCard = genSetRemindCard("pending", text, getDelayedTimeStr(1));
await sendMsg("chat_id", getChatId(body), "interactive", setRemindCard);
};
/**
* 处理消息
* @param {LarkMessageEvent} body
*/
module.exports.manageEventMsg = async (body) => {
// 过滤非法消息
if (filterIllegalMsg(body)) return "OK";
// 过滤获取用户信息的指令
if (filterGetInfoCommand(body)) return "OK";
// 发送设置提醒卡片
sendSetRemindCard(body);
};
/**
* 是否为事件消息
* @param {LarkMessageEvent} body
*/
module.exports.isEventMsg = (body) => {
return body?.header?.event_type === "im.message.receive_v1";
}

View File

@ -1,49 +1,25 @@
'use strict'
const { genSetRemindCard } = require("../../utils/genCard")
const { filterIllegalMsg, filterGetInfoCommand, getMsgText, getChatId } = require("../../utils/msgTools")
const { upsertUser } = require("../../utils/pb")
const { sendMsg } = require("../../utils/sendMsg")
/**
*
* @param {LarkMessageEvent} body
* @returns
*/
// const getSenderInfo = async (body) => {
// if (body.event.sender.sender_type === 'user') {
// // 是人发的给注册下
// return await upsertUser(body.event.sender.sender_id)
// }
// return false
// }
"use strict";
/**
* 发送设置提醒卡片
* @param {LarkMessageEvent} body
*/
const sendSetRemindCard = async (body) => {
const text = getMsgText(body)
const setRemindCard = genSetRemindCard(text)
await sendMsg('chat_id', getChatId(body), 'interactive', setRemindCard)
}
const { isEventMsg, manageEventMsg } = require("./eventMsg");
const { isActionMsg, manageActionMsg } = require("./actionMsg");
module.exports = async function (fastify, opts) {
// 机器人验证及分发
fastify.post('/', async function (request, reply) {
console.log(JSON.stringify(request.body))
fastify.post("/", async function (request, reply) {
console.log(JSON.stringify(request.body));
// 验证机器人
if (request.body.type === 'url_verification') {
console.log('url_verification')
return { challenge: request.body.challenge }
if (request.body.type === "url_verification") {
console.log("url_verification");
return { challenge: request.body.challenge };
}
// 过滤非法消息
if (filterIllegalMsg(request.body)) return 'OK'
// 过滤获取用户信息的指令
if (filterGetInfoCommand(request.body)) return 'OK'
// const userInfo = await getSenderInfo(request.body)
// if (!userInfo) return 'OK'
// console.log(userInfo)
// 发送设置提醒卡片
sendSetRemindCard(request.body)
return 'OK'
})
}
if (isEventMsg(request.body)) {
// 处理事件消息
manageEventMsg(request.body);
}
if (isActionMsg(request.body)) {
// 处理Action消息
manageActionMsg(request.body);
}
reply.send('OK')
});
};

View File

@ -7,8 +7,8 @@ exports.initSchedule = async () => {
// 定时任务每15分钟刷新一次token
schedule.scheduleJob('*/15 * * * *', resetAccessToken);
// 定时任务,每分钟检查一次是否有需要提醒的卡片
// schedule.scheduleJob('* * * * *', sendCurrTimeReminds);
schedule.scheduleJob('* * * * *', sendCurrTimeReminds);
// 立即执行一次
resetAccessToken()
// sendCurrTimeReminds()
sendCurrTimeReminds()
}

View File

@ -1,8 +1,9 @@
const { genRemindCard } = require("../utils/genCard")
const { getDelayedRemindTime, getNextRemindTime } = require("../utils/nextRemindTime")
const { getCurrRemind, updateNextRemindTime, getPendingRemindRecord, updateRemindRecord, createRemindRecord } = require("../utils/pb")
const { getNextRemindTime } = require("../utils/nextRemindTime")
const { getCurrRemind, updateNextRemindTime, getPendingRemindRecord, updateRemindRecord, createRemindRecord, closeRemind } = require("../utils/pb")
const { sendMsg, updateCard } = require("../utils/sendMsg")
const { getNowStr } = require("../utils/time")
const { getNowStr, getDelayedTimeStr } = require("../utils/time")
/**
* 更新上一个pending状态的卡片至delayed
*/
@ -32,14 +33,20 @@ const updateLastPendingCardToDelayed = async (remind) => {
const manageRemind = async (remind) => {
// 更新上一个pending状态的卡片至delayed
await updateLastPendingCardToDelayed(remind)
const cardType = remind.needReply ? 'pending' : 'confirmed'
// 生成卡片
const card = genRemindCard(remind, 'pending', null, null)
const card = genRemindCard(remind, cardType, null, null)
// 发送卡片
const messageId = await sendMsg(remind.subscriberType, remind.subscriberId, 'interactive', card)
// 创建remindRecord
await createRemindRecord(remind.id, messageId)
await createRemindRecord(remind.id, messageId, cardType)
// 如果是不需要回复的单次提醒到此就结束了
if (remind.frequency === 'single' && !remind.needReply) {
closeRemind(remind.id)
return
}
// 获取下一次提醒时间不需要回复的直接时下一次提醒时间需要回复的则是当前时间延后10min
const nextRemindTime = remind.needReply ? getDelayedRemindTime(remind.delayTime) : getNextRemindTime(remind)
const nextRemindTime = remind.needReply ? getDelayedTimeStr(remind.delayTime) : getNextRemindTime(remind)
// 更新下一次提醒时间
await updateNextRemindTime(remind.id, nextRemindTime)
}

74
typings.d.ts vendored
View File

@ -10,11 +10,11 @@ interface User {
*
* @example zhaoyingbo
*/
user_id: string;
userId: string;
/**
* open_id
*/
open_id: string;
openId: string;
/**
*
*/
@ -33,6 +33,10 @@ interface Remind {
* id
*/
owner: string;
/**
* Id
*/
messageId: string;
/**
*
*/
@ -128,19 +132,19 @@ interface Remind {
| "workday"
| "holiday";
/**
* 格式为HH:mm
* 格式为HH:mm single类型时仅作展示用yyyy-MM-dd HH:mm
*/
time: string;
/**
* frequency为weekly时有效
* [1-7]frequency为weekly时有效
*/
dayOfWeek: number;
/**
* frequency为monthly时有效
* [1-31]frequency为monthly时有效
*/
dayOfMonth: number;
/**
* frequency为yearly时有效MM-dd
* frequency为 yearly MM-dd
*/
dayOfYear: string;
/**
@ -358,4 +362,62 @@ interface LarkMessageEvent {
*
*/
event: Event;
}
/**
* Action信息
*/
interface LarkUserAction {
/**
* open_id
*/
open_id: string;
/**
*
* @example zhaoyingbo
*/
user_id: string;
/**
* ID
* @example om_038fc0eceed6224a1abc1cdaa4266405
*/
open_message_id: string;
/**
* ID
* @example oc_433b1cb7a9dbb7ebe70a4e1a59cb8bb1
*/
open_chat_id: string;
/**
* ID
* @example 2ee61fe50f4f1657
*/
tenant_key: string;
/**
* token
* @example tV9djUKSjzVnekV7xTg2Od06NFTcsBnj
*/
token: string;
/**
*
*/
action: {
/**
*
*/
value: any;
/**
*
* @example picker_datetime
*/
tag: string;
/**
*
* @example 2023-09-03 10:35 +0800
*/
option: string;
/**
*
*/
timezone: string;
};
}

View File

@ -1,5 +1,3 @@
const { getNowStr } = require("./time");
/**
* 生成提醒时间文本
*/
@ -46,14 +44,14 @@ const genRemindTimeText = (
const genResult = (interactInfo, cardInfo, cardType) => {
// 优先卡片返回的信息
if (interactInfo) {
const { result, text } = interactInfo;
const { type, text } = interactInfo;
if (text) return text;
return {
pending: "未交互",
confirmed: "已确认",
delayed: "已延期",
canceled: "已取消",
}[result];
}[type];
}
if (!cardInfo) {
return {
@ -75,7 +73,7 @@ const genResult = (interactInfo, cardInfo, cardType) => {
/**
* 生成交互按钮
*/
const genActions = (cardInfo, cardType, needReply) => {
const genActions = (id, cardInfo, cardType, needReply) => {
// 如果非交互提醒,不显示按钮
if (!needReply) return null;
// 如果是交互卡片的完成交互状态,不显示按钮
@ -95,8 +93,9 @@ const genActions = (cardInfo, cardType, needReply) => {
canceled: "danger",
}[type],
value: {
result: type,
type,
text,
remindId: id,
},
});
// 需要回复的卡片,显示确认、延期、取消按钮
@ -169,6 +168,7 @@ module.exports.genRemindCard = (
interactTime
) => {
const {
id,
cardInfo,
templateInfo,
needReply,
@ -255,7 +255,7 @@ module.exports.genRemindCard = (
}
: null;
// 待交互卡片且需要回复的显示按钮
const actionsDom = genActions(cardInfo, cardType, needReply);
const actionsDom = genActions(id, cardInfo, cardType, needReply);
// 非交互卡片以及交互完卡片,需要显示提醒信息
const remindInfoDom = genRemindInfo(
needReply,
@ -280,43 +280,143 @@ module.exports.genRemindCard = (
elements.push(remindInfoDom);
}
return JSON.stringify({
config: {
enable_forward: true,
update_multi: true,
},
elements,
header,
});
};
module.exports.genSetRemindCard = (text) => {
return JSON.stringify({
elements: [
/**
* 生成设置提醒卡片
* @param {string} cardType 卡片类型
* @param {*} content 卡片内容
*/
module.exports.genSetRemindCard = (cardType, content, time, userId) => {
const action = {
tag: "action",
actions: [
{
tag: "div",
text: {
content: `📝 ${text}`,
tag: "lark_md",
tag: "picker_datetime",
placeholder: {
tag: "plain_text",
content: "请选择提醒时间",
},
},
{
tag: "action",
actions: [
{
tag: "picker_datetime",
placeholder: {
tag: "plain_text",
content: "请选择提醒时间",
},
value: {
content: text,
},
initial_datetime: getNowStr(),
},
],
layout: "bisected",
value: {
content: `${content}`,
},
initial_datetime: time,
},
],
layout: "bisected",
};
const tip = [
{
tag: "hr",
},
{
tag: "note",
elements: [
{
tag: "img",
img_key: "img_v2_19db22c1-0030-434b-9b54-2a53b99c5f3l",
alt: {
tag: "plain_text",
content: "",
},
},
{
tag: "plain_text",
content: "谁选的时间提醒挂在谁名下呦",
},
],
},
];
const remindInfo = [
{
tag: "column_set",
flex_mode: "none",
background_style: "grey",
columns: [
{
tag: "column",
width: "weighted",
weight: 1,
vertical_align: "top",
elements: [
{
tag: "markdown",
content: `**创建人**\n${userId}`,
},
],
},
{
tag: "column",
width: "weighted",
weight: 1,
vertical_align: "top",
elements: [
{
tag: "markdown",
content: `**提醒时间**\n${time}`,
},
],
},
],
},
];
const errTip = {
tag: "note",
elements: [
{
tag: "plain_text",
content: "🚫请选择将来的时间哦!",
},
],
};
const elements = [
{
tag: "div",
text: {
content: `📝 ${content}`,
tag: "lark_md",
},
},
];
if (cardType === "pendingErr") {
elements.push(action);
elements.push(errTip);
elements.push(...tip);
}
if (cardType === "pending") {
elements.push(action);
elements.push(...tip);
}
if (cardType === "confirmed") {
elements.push(...remindInfo);
}
return JSON.stringify({
config: {
enable_forward: true,
update_multi: true,
},
elements,
header: {
template: "turquoise",
template: {
pending: "turquoise",
pendingErr: "turquoise",
confirmed: "green",
}[cardType],
title: {
content: "✨小煎蛋提醒创建工具",
content: `✨小煎蛋提醒创建${
{
pending: "工具",
pendingErr: "工具",
confirmed: "成功",
}[cardType]
}`,
tag: "plain_text",
},
},

View File

@ -1,3 +1,6 @@
const { getNowDateStr } = require("./time");
const moment = require('moment')
const chineseHoliday = {
'2023-09-29': true,
'2023-09-30': true,
@ -18,40 +21,17 @@ const chineseHoliday = {
* @returns {boolean} 是否是工作日
*/
const judgeIsWorkDay = (time) => {
const dateStr = getNowDateStr(time)
// 是补班
if (chineseHoliday[dateStr] === false) return true;
// 是假期
if (chineseHoliday[dateStr]) return false;
// 是否是日常工作日
const now = time ? new Date(time) : new Date();
const nowDay = now.getDay();
const nowDate = now.getDate();
const nowMonth = now.getMonth();
const nowYear = now.getFullYear();
// 是否是调休
const isHoliday = chineseHoliday[`${nowYear}-${nowMonth + 1}-${nowDate}`]
if (isHoliday) return false;
// 是否是补班
const isMakeUpWorkday = chineseHoliday[`${nowYear}-${nowMonth + 1}-${nowDate + 1}`] === false
if (isMakeUpWorkday) return true;
// 是否是日常工作日
return nowDay !== 0 && nowDay !== 6
}
/**
* 获取下一个工作日或者非工作日日期
* @param {boolean} isWorkday 是否是工作日
* @returns {string} 下一个工作日日期格式yyyy-MM-dd
*/
const getNextday = (isWorkday = true) => {
const now = new Date();
let dayCount = 1;
let nextDay = new Date(now.getTime() + dayCount * 24 * 60 * 60 * 1000)
while ((isWorkday && !judgeIsWorkDay(nextDay)) || (!isWorkday && judgeIsWorkDay(nextDay))) {
dayCount++;
nextDay = new Date(now.getTime() + dayCount * 24 * 60 * 60 * 1000)
}
const nextWorkdayYear = nextDay.getFullYear();
const nextWorkdayMonth = nextDay.getMonth() + 1;
const nextWorkdayDate = nextDay.getDate();
return `${nextWorkdayYear}-${nextWorkdayMonth}-${nextWorkdayDate}`
}
/**
* 获取下次提醒时间
* @param {Remind} remind 提醒信息
@ -59,92 +39,88 @@ const getNextday = (isWorkday = true) => {
*/
module.exports.getNextRemindTime = (remind) => {
const { frequency, time, dayOfWeek, dayOfMonth, dayOfYear } = remind;
const now = new Date();
const nowDay = now.getDay();
const nowDate = now.getDate();
const nowMonth = now.getMonth();
const nowYear = now.getFullYear();
const nowHour = now.getHours();
const nowMinute = now.getMinutes();
// 单次提醒没有下次正常会取delayTime
if (remind.frequency === 'single') return remind.nextRemindTime
// 拆分时间
const [hour, minute] = time.split(':');
// 当前时间
const nowMoment = moment();
// 每天循环
if (frequency === 'daily') {
const remindMoment = moment().hour(hour).minute(minute);
// 判断当前时间是否已经过了今天的提醒时间
if (nowHour > time.split(':')[0] || (nowHour === time.split(':')[0] && nowMinute >= time.split(':')[1])) {
if (!remindMoment.isAfter(nowMoment)) {
// 如果已经过了,那么下次提醒时间为明天的提醒时间
return `${nowYear}-${nowMonth + 1}-${nowDate + 1} ${time}`
} else {
// 否则下次提醒时间为今天的提醒时间
return `${nowYear}-${nowMonth + 1}-${nowDate} ${time}`
remindMoment.add(1, 'day');
}
return remindMoment.format('YYYY-MM-DD HH:mm');
}
// 每周循环
if (frequency === 'weekly') {
const remindMoment = moment().hour(hour).minute(minute).isoWeekday(dayOfWeek);
// 判断当前时间是否已经过了本周的提醒时间
if (nowDay > dayOfWeek || (nowDay === dayOfWeek && (nowHour > time.split(':')[0] || (nowHour === time.split(':')[0] && nowMinute >= time.split(':')[1])))) {
if (!remindMoment.isAfter(nowMoment)) {
// 如果已经过了,那么下次提醒时间为下周的提醒时间
return `${nowYear}-${nowMonth + 1}-${nowDate + 7 - nowDay + dayOfWeek} ${time}`
} else {
// 否则下次提醒时间为本周的提醒时间
return `${nowYear}-${nowMonth + 1}-${nowDate + dayOfWeek - nowDay} ${time}`
remindMoment.add(1, 'week');
}
return remindMoment.format('YYYY-MM-DD HH:mm');
}
// 每月循环
if (frequency === 'monthly') {
// 获取最近应该提醒的日期如果一个月没有31天那么就是最后一天
const dayOfMonthNum = moment().daysInMonth();
const remindMoment = moment().hour(hour).minute(minute).date(dayOfMonthNum < dayOfMonth ? dayOfMonthNum : dayOfMonth);
// 判断当前时间是否已经过了本月的提醒时间
if (nowDate > dayOfMonth || (nowDate === dayOfMonth && (nowHour > time.split(':')[0] || (nowHour === time.split(':')[0] && nowMinute >= time.split(':')[1])))) {
// 如果已经过了,那么下次提醒时间为下月的提醒时间
return `${nowYear}-${nowMonth + 2}-${dayOfMonth} ${time}`
} else {
// 否则下次提醒时间为本月的提醒时间
return `${nowYear}-${nowMonth + 1}-${dayOfMonth} ${time}`
if (!remindMoment.isAfter(nowMoment)) {
// 如果已经过了那么下次提醒时间为下月的提醒时间需要重新判断一下是否有31号
const nextDayOfMonthNum = moment().add(1, 'month').daysInMonth();
remindMoment.add(1, 'month').date(nextDayOfMonthNum < dayOfMonth ? nextDayOfMonthNum : dayOfMonth);
}
return remindMoment.format('YYYY-MM-DD HH:mm');
}
// 每年循环
if (frequency === 'yearly') {
// 月份monont是从0开始
const month = dayOfYear.split('-')[0] - 1;
// 月份的日期
const dayOfMonth = dayOfYear.split('-')[1];
// 获取当月的时间如果当月没有29号那么就是最后一天
const dayOfMonthNum = moment().month(month).daysInMonth();
const remindMoment = moment().hour(hour).minute(minute).month(month).date(dayOfMonthNum < dayOfMonth ? dayOfMonthNum : dayOfMonth);
// 判断当前时间是否已经过了今年的提醒时间
if (nowMonth > parseInt(dayOfYear.split('-')[0]) || (nowMonth === parseInt(dayOfYear.split('-')[0]) && (nowDate > parseInt(dayOfYear.split('-')[1]) || (nowDate === parseInt(dayOfYear.split('-')[1]) && (nowHour > time.split(':')[0] || (nowHour === time.split(':')[0] && nowMinute >= time.split(':')[1])))))) {
// 如果已经过了,那么下次提醒时间为明年的提醒时间
return `${nowYear + 1}-${dayOfYear} ${time}`
} else {
// 否则下次提醒时间为今年的提醒时间
return `${nowYear}-${dayOfYear} ${time}`
if (!remindMoment.isAfter(nowMoment)) {
// 如果已经过了那么下次提醒时间为明年的提醒时间需要重新判断一下是否有29号
const nextDayOfMonthNum = moment().add(1, 'year').month(month).daysInMonth();
remindMoment.add(1, 'year').date(nextDayOfMonthNum < dayOfMonth ? nextDayOfMonthNum : dayOfMonth);
}
return remindMoment.format('YYYY-MM-DD HH:mm');
}
// 工作日循环
if (frequency === 'workday') {
// 获取今天是不是工作日
const isWorkday = judgeIsWorkDay()
// 如果是工作日,且当前时间没过提醒时间,那么下次提醒时间为今天的提醒时间
if (isWorkday && (nowHour < time.split(':')[0] || (nowHour === time.split(':')[0] && nowMinute < time.split(':')[1]))) {
return `${nowYear}-${nowMonth + 1}-${nowDate} ${time}`
const remindMoment = moment().hour(hour).minute(minute);
// 今天是否是工作日
const isWorkday = judgeIsWorkDay();
// 如果今天非工作日或者如果是工作日,且当前时间过了提醒时间,那么下次提醒时间为下次工作日的提醒时间
if (!isWorkday || (isWorkday && !remindMoment.isAfter(nowMoment))) {
remindMoment.add(1, 'day');
while (!judgeIsWorkDay(remindMoment)) {
remindMoment.add(1, 'day');
}
}
// 非工作日或者已经过了提醒时间,那么下次提醒时间为下一个工作日的提醒时间
return `${getNextday()} ${time}`
return remindMoment.format('YYYY-MM-DD HH:mm');
}
// 非工作日循环
if (frequency === 'holiday') {
// 获取今天是不是工作日
const isWorkday = judgeIsWorkDay()
// 如果是非工作日,且当前时间没过提醒时间,那么下次提醒时间为今天的提醒时间
if (!isWorkday && (nowHour < time.split(':')[0] || (nowHour === time.split(':')[0] && nowMinute < time.split(':')[1]))) {
return `${nowYear}-${nowMonth + 1}-${nowDate} ${time}`
const remindMoment = moment().hour(hour).minute(minute);
// 今天是否是工作日
const isWorkday = judgeIsWorkDay();
// 如果今天是工作日或者如果是非工作日,且当前时间过了提醒时间,那么下次提醒时间为下次非工作日的提醒时间
if (isWorkday || (!isWorkday && !remindMoment.isAfter(nowMoment))) {
remindMoment.add(1, 'day');
while (judgeIsWorkDay(remindMoment)) {
remindMoment.add(1, 'day');
}
}
// 工作日或者已经过了提醒时间,那么下次提醒时间为下一个非工作日的提醒时间
return `${getNextday(false)} ${time}`
return remindMoment.format('YYYY-MM-DD HH:mm');
}
}
/**
* 获取delayTime分钟delay之后的提醒时间
* @param {number} delayTime 延迟时间, 单位为分钟, 1 <= delayTime
* @returns {string} delay的提醒时间, 格式为yyyy-MM-dd HH:mm
*/
module.exports.getDelayedRemindTime = (delayTime) => {
const nextRemindTime = new Date(new Date().getTime() + delayTime * 60 * 1000)
const nextRemindYear = nextRemindTime.getFullYear();
const nextRemindMonth = nextRemindTime.getMonth() + 1;
const nextRemindDate = nextRemindTime.getDate();
const nextRemindHour = nextRemindTime.getHours();
const nextRemindMinute = nextRemindTime.getMinutes();
return `${nextRemindYear}-${nextRemindMonth}-${nextRemindDate} ${nextRemindHour}:${nextRemindMinute}`
}

View File

@ -22,6 +22,45 @@ module.exports.getTenantAccessToken = async () => {
return value
}
/**
* 创建新提醒
*/
module.exports.createRemind = async (remind) => {
await pb.collection('remind').create(remind)
}
/**
* 获取提醒信息
*/
module.exports.getRemind = async (id) => {
try {
return await pb.collection('remind').getOne(id)
} catch (err) {
// 没有这个提醒就返回空
if (err.message === "The requested resource wasn't found.") {
return null
} else throw err;
}
}
/**
* 根据messageId更新或者创建提醒
* @param {Remind} remind
*/
module.exports.upsertRemindByMessageId = async (remind) => {
try {
const record = await pb.collection('remind').getFirstListItem(
`messageId = "${remind.messageId}" && enabled = true`
)
await pb.collection('remind').update(record.id, remind)
} catch (err) {
// 没有这个提醒就创建
if (err.message === "The requested resource wasn't found.") {
await pb.collection('remind').create(remind)
} else throw err;
}
}
/**
* 获取当前分钟应该提醒的所有提醒
*/
@ -34,37 +73,88 @@ module.exports.getCurrRemind = async () => {
return items
}
/**
* 获取对应messageId对应的提醒
*/
module.exports.getRemindByMessageId = async (messageId) => {
try {
const record = await pb.collection('remind').getFirstListItem(
`messageId = "${messageId}" && enabled = true`
)
return record
} catch (err) {
// 没有这个提醒不返回
if (err.message === "The requested resource wasn't found.") {
return null
} else throw err;
}
}
/**
* 更新指定Remind的下次提醒时间
* @param {Remind} remindId 提醒信息Id
* @param {string} remindId 提醒信息Id
* @param {string} nextRemindTime 下次提醒时间
*/
module.exports.updateNextRemindTime = async (remindId, nextRemindTime) => {
await pb.collection('remind').update(remindId, { nextRemindTime })
}
/**
* 关闭指定的Remind
* @param {string} remindId 提醒信息Id
*/
module.exports.closeRemind = async (remindId) => {
await pb.collection('remind').update(remindId, { enabled: false })
}
/**
* 获取指定remind的pending状态的remindRecord
* @param {string} remindId remind的id
* @returns {RemindRecord | null} remindRecord
*/
module.exports.getPendingRemindRecord = async (remindId) => {
const record = await pb.collection('remindRecord').getFirstListItem(
`remindId = "${remindId}" && status = "pending"`
)
return record
try {
const record = await pb.collection('remindRecord').getFirstListItem(
`remindId = "${remindId}" && status = "pending"`
)
return record
} catch (err) {
// 没有这个record不返回
if (err.message === "The requested resource wasn't found.") {
return null
} else throw err;
}
}
/**
* 获取指定messageId状态的remindRecord
* @param {string} remindId remind的id
* @returns {RemindRecord | null} remindRecord
*/
module.exports.getRemindRecordByMessageId = async (messageId) => {
try {
const record = await pb.collection('remindRecord').getFirstListItem(
`messageId = "${messageId}"`
)
return record
} catch (err) {
// 没有这个record不返回
if (err.message === "The requested resource wasn't found.") {
return null
} else throw err;
}
}
/**
* 创建remindRecord
*/
module.exports.createRemindRecord = async (remindId, messageId) => {
module.exports.createRemindRecord = async (remindId, messageId, status) => {
const remindRecord = {
remindId,
messageId,
status: 'pending',
status: status,
remindTime: getNowStr(),
interactTime: '',
interactTime: status === 'pending' ? '' : getNowStr(),
result: '',
}
await pb.collection('remindRecord').create(remindRecord)
@ -92,11 +182,10 @@ const getUser = async (userId) => {
* 创建用户
* @param {string} userId 用户id
* @param {string} openId 用户openId
* @param {[]} remindList 用户提醒列表
* @returns {User} 用户信息
*/
const createUser = async (userId, openId, remindList) => {
return await pb.collection("user").create({ userId, openId, remindList })
const createUser = async (userId, openId) => {
return await pb.collection("user").create({ userId, openId })
}
/**
@ -128,7 +217,7 @@ module.exports.upsertUser = async (userInfo) => {
} catch (err) {
// 没有这个用户上传个新的
if (err.message === "The requested resource wasn't found.") {
const user = await createUser(userInfo.user_id, userInfo.open_id, []);
const user = await createUser(userInfo.user_id, userInfo.open_id);
return user;
} else throw err;
}

View File

@ -8,3 +8,39 @@ const moment = require('moment')
module.exports.getNowStr = () => {
return moment().format('YYYY-MM-DD HH:mm')
}
/**
* 获取当前日期的字符串
* @param {string} time 时间
* @returns {string} 当前日期的字符串 YYYY-MM-DD
*/
module.exports.getNowDateStr = (time) => {
const targetTime = time ? new Date(time).getTime() : new Date().getTime()
return moment(targetTime).format('YYYY-MM-DD')
}
/**
* 获取指定分钟后的时间字符串
* @param {number} minutes 分钟数
* @returns {string} 指定分钟后的时间字符串 YYYY-MM-DD HH:mm
*/
module.exports.getDelayedTimeStr = (minutes) => {
return moment().add(minutes, 'minutes').format('YYYY-MM-DD HH:mm')
}
/**
* 转化为当前时区的时间
* @returns {string} 当前时间的字符串 YYYY-MM-DD HH:mm
* @example 2020-12-12 12:12
*/
module.exports.trans2LocalTime = (time) => {
return moment(new Date(time).getTime()).format('YYYY-MM-DD HH:mm')
}
const test = () => {
const dayOfMonth = 31;
const dayOfMonthNum = moment().daysInMonth();
return moment().date(dayOfMonthNum < dayOfMonth ? dayOfMonthNum : dayOfMonth).format('YYYY-MM-DD HH:mm')
}
// console.log(test())