1
0
mirror of https://github.com/XFox111/bonch-calendar.git synced 2026-06-30 10:52:41 +03:00

feat!: active users stats and improved logging and healthcheck

This commit is contained in:
2026-05-22 09:40:19 +00:00
parent 6a2b6980f9
commit 7f88891429
20 changed files with 629 additions and 82 deletions
+55
View File
@@ -0,0 +1,55 @@
namespace BonchCalendar.Services;
public class IssueTrackingService
{
private bool _isLastFacultyFetchSuccessful = true;
private readonly List<string> _unsuccessfulGroupFetches = [];
private readonly List<string> _unsuccessfulTimetableFetches = [];
public void TrackFacultyFetch(bool isSuccessful) =>
_isLastFacultyFetchSuccessful = isSuccessful;
public void TrackGroupFetch(int facultyId, int course, bool isSuccessful)
{
string key = $"{facultyId}/{course}";
if (!isSuccessful)
{
if (!_unsuccessfulGroupFetches.Contains(key))
_unsuccessfulGroupFetches.Add(key);
}
else
_unsuccessfulGroupFetches.Remove(key);
}
public void TrackTimetableFetch(int facultyId, int groupId, bool isSuccessful)
{
string key = $"{facultyId}/{groupId}";
if (!isSuccessful)
{
if (!_unsuccessfulTimetableFetches.Contains(key))
_unsuccessfulTimetableFetches.Add(key);
}
else
_unsuccessfulTimetableFetches.Remove(key);
}
public Dictionary<string, object> GetReport()
{
Dictionary<string, object> report = [];
if (!_isLastFacultyFetchSuccessful)
report.Add("/faculties", false);
if (_unsuccessfulGroupFetches.Count > 0)
report.Add("/groups", _unsuccessfulGroupFetches);
if (_unsuccessfulTimetableFetches.Count > 0)
report.Add("/timetable", _unsuccessfulTimetableFetches);
return report;
}
}
+2
View File
@@ -118,6 +118,8 @@ public partial class ParsingService
https://nav.sut.ru/?cab=k{auditoriumMatch.Groups["wing"].Value}-{auditoriumMatch.Groups["room"].Value}
""";
str += "\n\n" + "Создано при помощи сервиса Бонч.Календарь: https://bonch.xfox111.net";
return str;
}
+66
View File
@@ -0,0 +1,66 @@
using Ical.Net;
using Ical.Net.CalendarComponents;
using Ical.Net.Serialization;
namespace BonchCalendar.Services;
public class TimetableService(
ApiService apiService,
ParsingService parsingService,
ILogger<TimetableService> logger,
IHostEnvironment environment
)
{
public async Task<string?> TryServingFromCacheAsync(int groupId)
{
string cacheFile = GetCachePath(groupId);
if (!File.Exists(cacheFile) || (DateTime.UtcNow - File.GetLastWriteTimeUtc(cacheFile)).TotalHours >= 6)
return null;
if (environment.IsDevelopment())
{
logger.LogWarning("Caching is disabled for development environment.");
return null;
}
return await File.ReadAllTextAsync(cacheFile);
}
public async Task<string> GetTimetableAsync(int facultyId, int groupId, bool saveToCache = true, Action<Calendar>? transform = null)
{
DateTime semesterStartDate = await apiService.GetSemesterStartDateAsync(groupId);
string groupName = (await apiService.GetGroupsListAsync(facultyId, 0))[groupId];
string classesRaw = await apiService.GetScheduleDocumentAsync(groupId, TimetableType.Classes);
List<CalendarEvent> timetable = [.. parsingService.ParseGeneralTimetable(classesRaw, semesterStartDate, groupName)];
TimetableType[] types = [TimetableType.Attestations, TimetableType.Exams, TimetableType.ExamsForExtramural];
foreach (TimetableType type in types)
{
classesRaw = await apiService.GetScheduleDocumentAsync(groupId, type);
timetable.AddRange(parsingService.ParseExamTimetable(classesRaw, groupName));
}
Calendar calendar = new();
calendar.AddTimeZone(new VTimeZone("Europe/Moscow"));
calendar.Properties.Add(new CalendarProperty("X-WR-CALNAME", groupName));
calendar.Properties.Add(new CalendarProperty("X-WR-TIMEZONE", "Europe/Moscow"));
calendar.Properties.Add(new CalendarProperty("REFRESH-INTERVAL;VALUE=DURATION", "PT6H"));
calendar.Events.AddRange(timetable);
transform?.Invoke(calendar);
string content = new CalendarSerializer().SerializeToString(calendar)!;
if (saveToCache)
{
string cacheFile = GetCachePath(groupId);
await File.WriteAllTextAsync(cacheFile, content);
logger.LogInformation("Cache updated: {CacheFile}", cacheFile);
}
return content;
}
private static string GetCachePath(int groupId) =>
Path.Combine(Path.GetTempPath(), $"bonch_cal_{groupId}.ics");
}