@@ -2,6 +2,7 @@ import { SlashCommandBuilder } from '@discordjs/builders'
2
2
import { MessageEmbed } from 'discord.js'
3
3
import moment from 'moment-timezone'
4
4
import { async } from 'node-ical'
5
+ import { start } from 'pm2'
5
6
import { DiscordClient , DiscordCommandInteraction } from '../types/customTypes'
6
7
7
8
exports . name = 'wochenplan'
@@ -17,22 +18,22 @@ export const data = new SlashCommandBuilder()
17
18
option . setName ( 'datum' ) . setDescription ( 'Das Datum, das angezeigt werden soll. Format: DD.MM.YYYY' ) ,
18
19
)
19
20
20
- async function wochenplan ( client : DiscordClient , interaction : DiscordCommandInteraction , pNow , pCourseAndSemester ) {
21
+ async function wochenplan ( client : DiscordClient , interaction : DiscordCommandInteraction , date , pCourseAndSemester ) {
21
22
let returnData = { }
22
23
for ( const entry in client . config . calendars ) {
23
24
// eslint-disable-next-line no-await-in-loop
24
25
returnData = { ...returnData , ...( await async . fromURL ( client . config . calendars [ entry ] ) ) }
25
26
}
26
27
27
28
const relevantEvents = [ ]
28
- const curWeekday = pNow . getDay ( ) === 0 ? 6 : pNow . getDay ( ) - 1
29
- const startOfWeek = new Date ( pNow . setDate ( pNow . getDate ( ) - curWeekday ) )
29
+ const curWeekday = date . getDay ( ) === 0 ? 6 : date . getDay ( ) - 1
30
+ const startOfWeek = new Date ( date . setDate ( date . getDate ( ) - curWeekday ) )
30
31
startOfWeek . setHours ( 0 , 0 , 0 )
31
32
32
33
const rangeStart = moment ( startOfWeek )
33
34
const rangeEnd = rangeStart . clone ( ) . add ( 7 , 'days' )
34
35
35
- filterEvents ( returnData , rangeStart , rangeEnd , pCourseAndSemester , interaction , relevantEvents )
36
+ filterEvents ( returnData , rangeStart , rangeEnd , interaction , relevantEvents )
36
37
37
38
const embed = new MessageEmbed ( )
38
39
. setAuthor ( {
@@ -139,29 +140,16 @@ function filterEvents(
139
140
returnData : any ,
140
141
rangeStart : moment . Moment ,
141
142
rangeEnd : moment . Moment ,
142
- pCourseAndSemester : any ,
143
143
pMessageOrInteraction : any ,
144
144
relevantEvents : any [ ] ,
145
145
) {
146
146
for ( const i in returnData ) {
147
147
const event = returnData [ i ]
148
148
if ( returnData [ i ] . type === 'VEVENT' ) {
149
- const title = event . summary
150
149
const startDate = moment ( event . start )
151
150
const endDate = moment ( event . end )
152
- const duration = parseInt ( endDate . format ( 'x' ) ) - parseInt ( startDate . format ( 'x' ) )
153
- secondFIlter (
154
- event ,
155
- startDate ,
156
- rangeStart ,
157
- rangeEnd ,
158
- pCourseAndSemester ,
159
- pMessageOrInteraction ,
160
- title ,
161
- relevantEvents ,
162
- duration ,
163
- endDate ,
164
- )
151
+ const duration = Number . parseInt ( endDate . format ( 'x' ) , 10 ) - Number . parseInt ( startDate . format ( 'x' ) , 10 )
152
+ secondFIlter ( event , startDate , rangeStart , rangeEnd , pMessageOrInteraction , relevantEvents , duration , endDate )
165
153
}
166
154
}
167
155
}
@@ -171,62 +159,75 @@ function secondFIlter(
171
159
startDate : any ,
172
160
rangeStart : moment . Moment ,
173
161
rangeEnd : moment . Moment ,
174
- pCourseAndSemester : any ,
175
162
pMessageOrInteraction : any ,
176
- title : any ,
177
163
relevantEvents : any [ ] ,
178
164
duration : number ,
179
165
endDate : any ,
180
166
) {
181
167
if ( typeof event . rrule === 'undefined' ) {
182
168
if ( startDate . isBetween ( rangeStart , rangeEnd ) ) {
183
- pushToWeeksEvents ( pMessageOrInteraction , event , relevantEvents )
169
+ pushToWeeksEvents ( pMessageOrInteraction , event , relevantEvents , event . start , event . end )
184
170
}
185
171
} else {
186
- const dates = event . rrule . between ( rangeStart . toDate ( ) , rangeEnd . toDate ( ) , true )
187
-
172
+ /**
173
+ * Complicated case - if an RRULE exists, handle multiple recurrences of the event.
174
+ * For recurring events, get the set of event start dates that fall within the range
175
+ * of dates we're looking for.
176
+ */
177
+ const dates = event . rrule . between ( rangeStart . toDate ( ) , rangeEnd . toDate ( ) , true , ( ) => true )
178
+
179
+ /**
180
+ * The "dates" array contains the set of dates within our desired date range range that are valid
181
+ * for the recurrence rule. *However*, it's possible for us to have a specific recurrence that
182
+ * had its date changed from outside the range to inside the range. One way to handle this is
183
+ * to add *all* recurrence override entries into the set of dates that we check, and then later
184
+ * filter out any recurrences that don't actually belong within our range.
185
+ */
188
186
if ( event . recurrences !== undefined ) {
189
187
for ( const recurrence in event . recurrences ) {
188
+ /**
189
+ * Only add dates that weren't already in the range we added from the rrule so that
190
+ * we don't double-add those events.
191
+ */
190
192
if ( moment ( new Date ( recurrence ) ) . isBetween ( rangeStart , rangeEnd ) !== true ) {
191
193
dates . push ( new Date ( recurrence ) )
192
194
}
193
195
}
194
196
}
195
197
196
- for ( const date of dates ) {
198
+ for ( const i in dates ) {
199
+ /**
200
+ * Reccurence date.
201
+ */
202
+ const date = dates [ i ]
197
203
let curEvent = event
198
204
let relevantRecurrence = true
199
- let curDuration = duration
200
205
201
206
startDate = moment ( date )
207
+ endDate = startDate . clone ( ) . add ( moment . duration ( moment ( curEvent . end ) . diff ( curEvent . start ) ) . asHours ( ) , 'hours' )
202
208
203
209
const dateLookupKey = date . toISOString ( ) . substring ( 0 , 10 )
204
-
205
210
if ( curEvent . recurrences !== undefined && curEvent . recurrences [ dateLookupKey ] !== undefined ) {
206
211
curEvent = curEvent . recurrences [ dateLookupKey ]
207
212
startDate = moment ( curEvent . start )
208
- curDuration = parseInt ( moment ( curEvent . end ) . format ( 'x' ) ) - parseInt ( startDate . format ( 'x' ) )
213
+ endDate = startDate . clone ( ) . add ( moment . duration ( moment ( curEvent . end ) . diff ( curEvent . start ) ) . asHours ( ) , 'hours' )
209
214
} else if ( curEvent . exdate !== undefined && curEvent . exdate [ dateLookupKey ] !== undefined ) {
210
215
relevantRecurrence = false
211
216
}
212
217
213
- endDate = moment ( parseInt ( startDate . format ( 'x' ) ) + curDuration , 'x' )
214
-
215
218
if ( endDate . isBefore ( rangeStart ) || startDate . isAfter ( rangeEnd ) ) {
216
219
relevantRecurrence = false
217
220
}
218
221
219
222
if ( relevantRecurrence === true ) {
220
- pushToWeeksEvents ( pMessageOrInteraction , event , relevantEvents )
223
+ pushToWeeksEvents ( pMessageOrInteraction , curEvent , startDate , endDate , relevantEvents )
221
224
}
222
225
}
223
226
}
224
227
}
225
228
226
- // TODO: Weekplan still not recocnizing all events (e.g. 28.04.2022 OFE is missing)
227
-
228
- function pushToWeeksEvents ( interaction , event , relevantEvents ) {
229
- if ( doubleEntry ( relevantEvents , event ) ) {
229
+ function pushToWeeksEvents ( interaction , event , event_start , event_end , relevantEvents ) {
230
+ if ( doubleEntry ( relevantEvents , event , event_start , event_end ) ) {
230
231
return
231
232
}
232
233
const roles = interaction . member . roles . cache . map ( role => role )
@@ -238,7 +239,17 @@ function pushToWeeksEvents(interaction, event, relevantEvents) {
238
239
searchQuery = event . summary . toString ( )
239
240
}
240
241
if ( roles [ role ] . name . toLowerCase ( ) . trim ( ) === searchQuery . toLowerCase ( ) . trim ( ) ) {
241
- relevantEvents . push ( event )
242
+ /**
243
+ * Add entry with new key.
244
+ * Key increments by one (determined by length).
245
+ */
246
+ relevantEvents [ Object . keys ( relevantEvents ) . length ] = {
247
+ start : event_start ,
248
+ end : event_end ,
249
+ summary : event . summary ,
250
+ description : event . description ,
251
+ location : event . location ,
252
+ }
242
253
}
243
254
}
244
255
}
@@ -247,9 +258,11 @@ function pushToWeeksEvents(interaction, event, relevantEvents) {
247
258
* Check if the new element added to @link{array} creates a duplicate
248
259
* @param {any[] } array array to check
249
260
* @param {any } new_element new element on which to check if duplicate
261
+ * @param {Date } start_date end date of event
262
+ * @param {Date } end_date start date of event
250
263
* @returns {boolean }
251
264
*/
252
- function doubleEntry ( array : any [ ] , new_element : any ) : boolean {
265
+ function doubleEntry ( array : any [ ] , new_element : any , start_date : Date , end_date : Date ) : boolean {
253
266
/**
254
267
* Always return false, if array has no entry
255
268
* There are no possible duplicates if there is nothing in the array
@@ -265,9 +278,9 @@ function doubleEntry(array: any[], new_element: any): boolean {
265
278
if (
266
279
array [ entry ] . start === new_element . start &&
267
280
array [ entry ] . summary === new_element . summary &&
268
- array [ entry ] . start . getDay ( ) === new_element . start . getDay ( )
281
+ array [ entry ] . start . getDay ( ) === start_date &&
282
+ array [ entry ] . end . getDay ( ) === end_date
269
283
) {
270
- console . log ( new_element . start . getDay ( ) )
271
284
return true
272
285
}
273
286
}
0 commit comments