Skip to content

Commit 36e09b2

Browse files
committed
Use temporally persistent calendar event ID.
1 parent b695b9e commit 36e09b2

File tree

2 files changed

+26
-10
lines changed

2 files changed

+26
-10
lines changed

DL444.CquSchedule.Backend/Services/CalendarService.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Security.Cryptography;
23
using System.Text;
34
using DL444.CquSchedule.Backend.Models;
45
using Ical.Net;
@@ -22,7 +23,7 @@ internal interface ICalendarService
2223
{
2324
int VacationCalendarServeDays { get; }
2425

25-
string GetCalendar(Term currentTerm, Schedule schedule, CalenderEventCategories eventCategories = CalenderEventCategories.All, int remindTime = 15);
26+
string GetCalendar(string username, Term currentTerm, Schedule schedule, CalenderEventCategories eventCategories = CalenderEventCategories.All, int remindTime = 15);
2627
string GetEmptyCalendar();
2728
}
2829

@@ -37,7 +38,7 @@ public CalendarService(IConfiguration config, IWellknownDataService wellknown, I
3738

3839
public int VacationCalendarServeDays { get; }
3940

40-
public string GetCalendar(Term currentTerm, Schedule schedule, CalenderEventCategories eventCategories, int remindTime)
41+
public string GetCalendar(string username, Term currentTerm, Schedule schedule, CalenderEventCategories eventCategories, int remindTime)
4142
{
4243
if (DateTimeOffset.Now > currentTerm.EndDate.AddDays(VacationCalendarServeDays)
4344
|| DateTimeOffset.Now < currentTerm.StartDate.AddDays(-VacationCalendarServeDays))
@@ -57,7 +58,7 @@ public string GetCalendar(Term currentTerm, Schedule schedule, CalenderEventCate
5758
{
5859
continue;
5960
}
60-
calendar.Events.Add(GetCalendarEvent(entry, currentTerm, week, remindTime, descriptionBuilder));
61+
calendar.Events.Add(GetCalendarEvent(username, entry, currentTerm, week, remindTime, descriptionBuilder));
6162
}
6263
}
6364
}
@@ -66,7 +67,7 @@ public string GetCalendar(Term currentTerm, Schedule schedule, CalenderEventCate
6667
{
6768
foreach (var exam in schedule.Exams)
6869
{
69-
calendar.Events.Add(GetCalendarEvent(exam, remindTime));
70+
calendar.Events.Add(GetCalendarEvent(username, exam, remindTime));
7071
}
7172
}
7273

@@ -75,7 +76,7 @@ public string GetCalendar(Term currentTerm, Schedule schedule, CalenderEventCate
7576

7677
public string GetEmptyCalendar() => new CalendarSerializer(new Calendar()).SerializeToString();
7778

78-
private CalendarEvent GetCalendarEvent(ScheduleEntry entry, Term currentTerm, ScheduleWeek week, int remindTime, StringBuilder descriptionBuilder)
79+
private CalendarEvent GetCalendarEvent(string username, ScheduleEntry entry, Term currentTerm, ScheduleWeek week, int remindTime, StringBuilder descriptionBuilder)
7980
{
8081
TimeSpan startTime = wellknown.Schedule[entry.StartSession - 1].StartOffset;
8182
int endSession = Math.Min(entry.EndSession, wellknown.Schedule.Count);
@@ -97,7 +98,7 @@ private CalendarEvent GetCalendarEvent(ScheduleEntry entry, Term currentTerm, Sc
9798
descriptionBuilder.Append(locService.GetString("CalendarLecturer", locService.DefaultCulture, entry.Lecturer));
9899
}
99100

100-
return new CalendarEvent()
101+
var calendarEvent = new CalendarEvent()
101102
{
102103
Summary = entry.Name,
103104
DtStart = GetTime(currentTerm.StartDate, week.WeekNumber, entry.DayOfWeek, startTime),
@@ -113,12 +114,14 @@ private CalendarEvent GetCalendarEvent(ScheduleEntry entry, Term currentTerm, Sc
113114
}
114115
}
115116
};
117+
calendarEvent.Uid = GetUid(calendarEvent, username);
118+
return calendarEvent;
116119
}
117120

118-
private static CalendarEvent GetCalendarEvent(ExamEntry exam, int remindTime)
121+
private static CalendarEvent GetCalendarEvent(string username, ExamEntry exam, int remindTime)
119122
{
120123
bool roomSimplified = exam.Room != null && !exam.Room.Equals(exam.SimplifiedRoom, StringComparison.Ordinal);
121-
return new CalendarEvent()
124+
var calendarEvent = new CalendarEvent()
122125
{
123126
Summary = exam.Name,
124127
DtStart = new CalDateTime(exam.StartTime.UtcDateTime),
@@ -134,6 +137,8 @@ private static CalendarEvent GetCalendarEvent(ExamEntry exam, int remindTime)
134137
}
135138
}
136139
};
140+
calendarEvent.Uid = GetUid(calendarEvent, username);
141+
return calendarEvent;
137142
}
138143

139144
private static CalDateTime GetTime(DateTimeOffset termStartDate, int week, int dayOfWeek, TimeSpan time)
@@ -143,6 +148,17 @@ private static CalDateTime GetTime(DateTimeOffset termStartDate, int week, int d
143148
return new CalDateTime(dateTime.UtcDateTime);
144149
}
145150

151+
private static string GetUid(CalendarEvent calendarEvent, string ancillaryIdentifier)
152+
{
153+
// UIDs must be unique across events and temporally persistent at the same time,
154+
// or clients might briefly show duplicated events during refresh.
155+
// This property choice ensures that no duplicated UIDs will be generated even if
156+
// the user has conflicting schedules, while minimizing the likelihood of UID changes
157+
// in the event of schedule updates (summary and time rarely change).
158+
var idSource = $"{ancillaryIdentifier}, {calendarEvent.Summary}, {calendarEvent.DtStart}, {calendarEvent.DtEnd}";
159+
return Convert.ToBase64String(SHA256.HashData(Encoding.UTF8.GetBytes(idSource)));
160+
}
161+
146162
private readonly IWellknownDataService wellknown;
147163
private readonly ILocalizationService locService;
148164
}

DL444.CquSchedule.Backend/SubscriptionFunction.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ private async Task<HttpResponseData> GetScheduleAsync(HttpRequestData req, strin
9797
try
9898
{
9999
Term term = await termTask;
100-
return req.CreateStringContentResponse(HttpStatusCode.OK, calendarService.GetCalendar(term, schedule, eventCategories), calendarContentType);
100+
return req.CreateStringContentResponse(HttpStatusCode.OK, calendarService.GetCalendar(username, term, schedule, eventCategories), calendarContentType);
101101
}
102102
catch (CosmosException ex)
103103
{
@@ -274,7 +274,7 @@ public async Task<HttpResponseData> RunPostAsync([HttpTrigger(AuthorizationLevel
274274

275275
if (!credential.ShouldSaveCredential)
276276
{
277-
string ics = calendarService.GetCalendar(term, schedule);
277+
string ics = calendarService.GetCalendar(credential.Username, term, schedule);
278278
var response = new CquSchedule.Models.Response<IcsSubscription>(true, new IcsSubscription(null, ics), successMessage);
279279
return IcsSubscriptionResponseSerializerContext.Default.GetSerializedResponse(req, response);
280280
}

0 commit comments

Comments
 (0)