-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathreminder.ts
201 lines (175 loc) · 7.22 KB
/
reminder.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import { opendiscord, api, utilities } from "#opendiscord"
import * as discord from "discord.js"
import { safeTimeout, parseDate, convertTime } from "./utils/time"
/**## ODReminderManager `class`
* This is an OD Reminders manager.
*
* This class manages all registered reminders in the bot. Only reminders which are available in this manager can be auto-updated.
*
* All reminders which are added, removed or modified in this manager will be updated automatically in the database.
*/
export class ODReminderManager extends api.ODManager<ODReminder> {
id: api.ODId = new api.ODId("od-reminders:manager")
// Track scheduled reminders timeouts/intervals
static scheduledReminders = new Map<api.ODValidId,{timeout: NodeJS.Timeout|null}>()
constructor(debug: api.ODDebugger) {
super(debug, "reminder")
}
}
/**## ODReminderDataJson `interface`
* The JSON representatation from a single reminder property.
*/
export interface ODReminderDataJson {
/**The id of this property. */
id:string,
/**The value of this property. */
value:api.ODValidJsonType
}
/**## ODReminderDataJson `interface`
* The JSON representatation from a single reminder.
*/
export interface ODReminderJson {
/**The id of this reminder. */
id:string,
/**The version of Open Ticket used to create this reminder & store it in the database. */
version:string,
/**The full list of properties/variables related to this reminder. */
data:ODReminderDataJson[]
}
/**## ODReminderIds `type`
* This interface is a list of ids available in the `ODReminder` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODReminderIds {
"od-reminders:name":ODReminderData<string>,
"od-reminders:channel":ODReminderData<string>,
"od-reminders:text":ODReminderData<string>,
"od-reminders:embed-color":ODReminderData<discord.ColorResolvable>,
"od-reminders:embed-title":ODReminderData<string|null>,
"od-reminders:embed-description":ODReminderData<string|null>,
"od-reminders:embed-footer":ODReminderData<string|null>,
"od-reminders:embed-author":ODReminderData<string|null>,
"od-reminders:embed-timestamp":ODReminderData<boolean|null>,
"od-reminders:embed-image":ODReminderData<string|null>,
"od-reminders:embed-thumbnail":ODReminderData<string|null>,
"od-reminders:author-image":ODReminderData<string|null>,
"od-reminders:footer-image":ODReminderData<string|null>,
"od-reminders:ping":ODReminderData<string|null>,
"od-reminders:start-time":ODReminderData<string>,
"od-reminders:interval":ODReminderData<{value:number,unit:"seconds"|"minutes"|"hours"|"days"|"months"|"years"}>,
"od-reminders:paused":ODReminderData<boolean>
}
/**## ODReminder `class`
* This is an OD Reminders plugin reminder.
*
* This class contains all data related to this reminder (parsed from the database).
*/
export class ODReminder extends api.ODManager<ODReminderData<api.ODValidJsonType>> {
/**The id of this reminder */
id:api.ODId
constructor(id:api.ODValidId, data:ODReminderData<api.ODValidJsonType>[]){
super()
this.id = new api.ODId(id)
data.forEach((data) => {
this.add(data)
})
}
/**Convert this reminder to a JSON object for storing this reminder in the database. */
toJson(version:api.ODVersion): ODReminderJson {
const data = this.getAll().map((data) => {
return {
id:data.id.toString(),
value:data.value
}
})
return {
id:this.id.toString(),
version:version.toString(),
data
}
}
/**Create a reminder from a JSON object in the database. */
static fromJson(json:ODReminderJson): ODReminder {
return new ODReminder(json.id,json.data.map((data) => new ODReminderData(data.id,data.value)))
}
get<ReminderId extends keyof ODReminderIds>(id:ReminderId): ODReminderIds[ReminderId]
get(id:api.ODValidId): ODReminderData<api.ODValidJsonType>|null
get(id:api.ODValidId): ODReminderData<api.ODValidJsonType>|null {
return super.get(id)
}
remove<ReminderId extends keyof ODReminderIds>(id:ReminderId): ODReminderIds[ReminderId]
remove(id:api.ODValidId): ODReminderData<api.ODValidJsonType>|null
remove(id:api.ODValidId): ODReminderData<api.ODValidJsonType>|null {
return super.remove(id)
}
exists(id:keyof ODReminderIds): boolean
exists(id:api.ODValidId): boolean
exists(id:api.ODValidId): boolean {
return super.exists(id)
}
schedule() {
const paused = this.get("od-reminders:paused").value;
if (paused) return; //don't continue if paused
const now = new Date();
const rawInterval = this.get("od-reminders:interval").value;
const interval = convertTime(rawInterval.value, rawInterval.unit);
let startOffset = 0;
const rawStartTime = this.get("od-reminders:start-time").value;
if (rawStartTime !== "now") {
const startTime = parseDate(rawStartTime);
if (startTime) {
const diff = startTime.getTime() - now.getTime();
startOffset = diff > 0 ? diff : Math.max(0, interval + diff);
}
}
let timeout: {timeout: NodeJS.Timeout|null} = {timeout:null};
ODReminderManager.scheduledReminders.set(this.id,timeout);
const callback = () => {
if (this.get("od-reminders:paused").value) return; //don't continue if paused
this.send();
safeTimeout(callback, interval, timeout);
};
safeTimeout(callback, startOffset, timeout);
}
// Send the reminder to the channel
async send() {
try {
const guild = opendiscord.client.mainServer
if (!guild) return
const channel = await opendiscord.client.fetchGuildTextChannel(guild, this.get("od-reminders:channel").value)
if (!channel) return
await channel.send((await opendiscord.builders.messages.get("od-reminders:reminder-message").build("other",{reminder:this})).message)
this.get("od-reminders:start-time").value = utilities.dateString(new Date())
} catch (err) {
process.emit("uncaughtException",err)
opendiscord.log("Error sending reminder! (See error above)","error")
}
}
}
/**## ODReminderData `class`
* This is OD Reminders plugin Reminder data.
*
* This class contains a single property for a Reminder. (string, number, boolean, object, array, null)
*
* When this property is edited, the database will be updated automatically.
*/
export class ODReminderData<DataType extends api.ODValidJsonType> extends api.ODManagerData {
/**The value of this property. */
#value: DataType
constructor(id:api.ODValidId, value:DataType){
super(id)
this.#value = value
}
/**The value of this property. */
set value(value:DataType){
this.#value = value
this._change()
}
get value(): DataType {
return this.#value
}
/**Refresh the database. Is only required to be used when updating `ODReminderData` with an object/array as value. */
refreshDatabase(){
this._change()
}
}