diff --git a/commands/remind/delete-reminder.js b/commands/remind/delete-reminder.js index 916cdcf8..1178005c 100644 --- a/commands/remind/delete-reminder.js +++ b/commands/remind/delete-reminder.js @@ -7,14 +7,16 @@ module.exports = class DeleteReminderCommand extends Command { aliases: ['delete-remind', 'delete-timer', 'del-reminder', 'del-remind', 'del-timer'], group: 'remind', memberName: 'delete-reminder', - description: 'Deletes your reminder.' + description: 'Deletes your reminder(s) set in this channel.' }); } async run(msg) { - const exists = await this.client.timers.exists(msg.channel.id, msg.author.id); - if (!exists) return msg.reply('🕰️ You do not have a reminder set in this channel.'); - await this.client.timers.deleteTimer(msg.channel.id, msg.author.id); - return msg.say('🕰️ Your reminder has been deleted.'); + const found = this.client.timers.findAll(msg.channel.id, msg.author.id); + if (!found.size) return msg.reply('🕰️ You do not have a reminder set in this channel.'); + for (const timer of found.values()) { + await timer.delete(); + } + return msg.say('🕰️ Your reminder(s) set in this channel have been deleted.'); } }; diff --git a/commands/remind/remind.js b/commands/remind/remind.js index 6d12bd8b..0b563c6c 100644 --- a/commands/remind/remind.js +++ b/commands/remind/remind.js @@ -21,14 +21,12 @@ module.exports = class RemindCommand extends Command { } async run(msg, { time }) { - const exists = await this.client.timers.exists(msg.channel.id, msg.author.id); - if (exists) return msg.reply('🕰️ Only one reminder can be set per channel per user.'); const timeMs = time.startDate.getTime() - Date.now(); if (timeMs > 0x7FFFFFFF) return msg.reply('🕰️ Reminders have a maximum length of ~24.84 days.'); if (timeMs < 0) return msg.reply('🕰️ What do you expect me to do, time travel?'); const display = moment().add(timeMs, 'ms').fromNow(); const title = time.eventTitle ? shorten(time.eventTitle, 500) : 'something'; - await this.client.timers.setTimer(msg.channel.id, timeMs, msg.author.id, title); + await this.client.timers.setTimer(null, msg.channel.id, timeMs, msg.author.id, title); return msg.say(`🕰️ Okay, I will remind you **"${title}"** ${display}.`); } }; diff --git a/package.json b/package.json index 7bddb748..ad4ea23c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "xiao", - "version": "136.4.1", + "version": "136.5.0", "description": "Your personal server companion.", "main": "Xiao.js", "private": true, diff --git a/structures/remind/Timer.js b/structures/remind/Timer.js new file mode 100644 index 00000000..b44a531b --- /dev/null +++ b/structures/remind/Timer.js @@ -0,0 +1,41 @@ +const crypto = require('crypto'); + +module.exports = class Timer { + constructor(client, id, channelID, userID, time, title) { + Object.defineProperty(this, 'client', { value: client }); + + this.id = id || crypto.randomBytes(16).toString('hex'); + this.channelID = channelID; + this.userID = userID; + this.time = time; + this.title = title; + this.timeout = this.setTimeout(time); + } + + stringify() { + return JSON.stringify({ + id: this.id, + channelID: this.channelID, + userID: this.userID, + time: new Date(Date.now() + this.time).toISOString(), + title: this.title + }); + } + + setTimeout(time) { + return setTimeout(async () => { + try { + const channel = await this.client.channels.fetch(this.channelID); + await channel.send(`🕰️ <@${this.userID}>, you wanted me to remind you of: **"${this.title}"**.`); + } finally { + await this.client.redis.hdel('timer', id); + } + }, time); + } + + delete() { + clearTimeout(this.timeout); + this.client.timers.delete(this.id); + return this.client.redis.hdel('timer', this.id); + } +}; diff --git a/structures/remind/TimerManager.js b/structures/remind/TimerManager.js index 7eadc351..edde5db3 100644 --- a/structures/remind/TimerManager.js +++ b/structures/remind/TimerManager.js @@ -1,41 +1,28 @@ -module.exports = class TimerManager { +const Collection = require('@discordjs/collection'); +const Timer = require('./Timer'); + +module.exports = class TimerManager extends Collection { constructor(client) { Object.defineProperty(this, 'client', { value: client }); - - this.timeouts = new Map(); } async fetchAll() { const timers = await this.client.redis.hgetall('timer'); for (let data of Object.values(timers)) { data = JSON.parse(data); - await this.setTimer(data.channelID, new Date(data.time) - new Date(), data.userID, data.title, false); + await this.setTimer(data.id, data.channelID, new Date(data.time) - new Date(), data.userID, data.title, false); } return this; } - async setTimer(channelID, time, userID, title, updateRedis = true) { - const data = { time: new Date(Date.now() + time).toISOString(), channelID, userID, title }; - const timeout = setTimeout(async () => { - try { - const channel = await this.client.channels.fetch(channelID); - await channel.send(`🕰️ <@${userID}>, you wanted me to remind you of: **"${title}"**.`); - } finally { - await this.client.redis.hdel('timer', `${channelID}-${userID}`); - } - }, time); - if (updateRedis) await this.client.redis.hset('timer', { [`${channelID}-${userID}`]: JSON.stringify(data) }); - this.timeouts.set(`${channelID}-${userID}`, timeout); - return timeout; + async setTimer(id, channelID, time, userID, title, updateRedis = true) { + const timer = new Timer(this.client, id, channelID, userID, time, title); + if (updateRedis) await this.client.redis.hset('timer', { [timer.id]: timer.stringify() }); + this.set(timer.id, timer); + return timer; } - deleteTimer(channelID, userID) { - clearTimeout(this.timeouts.get(`${channelID}-${userID}`)); - this.timeouts.delete(`${channelID}-${userID}`); - return this.client.redis.hdel('timer', `${channelID}-${userID}`); - } - - exists(channelID, userID) { - return this.client.redis.hexists('timer', `${channelID}-${userID}`); + findAll(channelID, userID) { + return this.filter(timer => timer.channelID === channelID && timer.userID === userID); } };