All checks were successful
Create and publish a Docker image / Publish image (push) Successful in 4m58s
278 lines
14 KiB
C#
278 lines
14 KiB
C#
using System.Text.Json;
|
||
using Ical.Net.CalendarComponents;
|
||
using Ical.Net.DataTypes;
|
||
using Ical.Net.Serialization;
|
||
using Microsoft.Net.Http.Headers;
|
||
using SfeduSchedule.Abstractions;
|
||
|
||
namespace SfeduSchedule.Services
|
||
{
|
||
public class ModeusService
|
||
{
|
||
private readonly HttpClient _httpClient;
|
||
private readonly ILogger<ModeusService> _logger;
|
||
private readonly IConfiguration _configuration;
|
||
|
||
public ModeusService(HttpClient httpClient, ILogger<ModeusService> logger, IConfiguration configuration)
|
||
{
|
||
_httpClient = httpClient;
|
||
_logger = logger;
|
||
_configuration = configuration;
|
||
_httpClient.BaseAddress = new Uri("https://sfedu.modeus.org/");
|
||
var token = _configuration["TOKEN"];
|
||
_httpClient.DefaultRequestHeaders.Add(HeaderNames.Authorization, $"Bearer {token}");
|
||
}
|
||
|
||
public async Task<string?> GetScheduleAsync(ModeusScheduleRequest msr)
|
||
{
|
||
var request = new HttpRequestMessage(HttpMethod.Post,
|
||
$"schedule-calendar-v2/api/calendar/events/search?tz={_configuration["TZ"]!}");
|
||
request.Content = new StringContent(JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions),
|
||
System.Text.Encoding.UTF8, "application/json");
|
||
var response = await _httpClient.SendAsync(request);
|
||
_logger.LogInformation("GetScheduleAsync: Ответ получен: {StatusCode}", response.StatusCode);
|
||
response.EnsureSuccessStatusCode();
|
||
return await response.Content.ReadAsStringAsync();
|
||
}
|
||
|
||
public async Task<List<Attendees>> GetAttendeesAsync(Guid eventId)
|
||
{
|
||
var request = new HttpRequestMessage(HttpMethod.Get,
|
||
$"schedule-calendar-v2/api/calendar/events/{eventId}/attendees");
|
||
var response = await _httpClient.SendAsync(request);
|
||
_logger.LogInformation("GetAttendeesAsync: Ответ получен: {StatusCode}", response.StatusCode);
|
||
response.EnsureSuccessStatusCode();
|
||
List<Attendees>? attendees;
|
||
try
|
||
{
|
||
attendees = Attendees.FromJson(await response.Content.ReadAsStringAsync());
|
||
return attendees;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "GetAttendeesAsync: Deserialization failed.");
|
||
}
|
||
return new List<Attendees>();
|
||
}
|
||
|
||
public async Task<string?> SearchRoomsAsync(RoomSearchRequest requestDto)
|
||
{
|
||
var request = new HttpRequestMessage(HttpMethod.Post, $"schedule-calendar-v2/api/campus/rooms/search");
|
||
request.Content =
|
||
new StringContent(JsonSerializer.Serialize(requestDto, GlobalVariables.JsonSerializerOptions),
|
||
System.Text.Encoding.UTF8, "application/json");
|
||
var response = await _httpClient.SendAsync(request);
|
||
_logger.LogInformation("SearchRoomsAsync: Ответ получен: {StatusCode}", response.StatusCode);
|
||
response.EnsureSuccessStatusCode();
|
||
return await response.Content.ReadAsStringAsync();
|
||
}
|
||
|
||
public async Task<string?> GetGuidAsync(string fullName)
|
||
{
|
||
var request = new HttpRequestMessage(HttpMethod.Post, $"schedule-calendar-v2/api/people/persons/search");
|
||
request.Content = new StringContent(JsonSerializer.Serialize(new
|
||
{
|
||
fullName = fullName,
|
||
sort = "+fullName",
|
||
size = 10,
|
||
page = 0
|
||
}), System.Text.Encoding.UTF8, "application/json");
|
||
var response = await _httpClient.SendAsync(request);
|
||
|
||
_logger.LogInformation("GetGuidAsync: Ответ получен: {StatusCode}", response.StatusCode);
|
||
response.EnsureSuccessStatusCode();
|
||
|
||
var json = await response.Content.ReadAsStringAsync();
|
||
|
||
string? personId;
|
||
try
|
||
{
|
||
personId = JsonDocument.Parse(json).RootElement
|
||
.GetProperty("_embedded")
|
||
.GetProperty("persons")[0]
|
||
.GetProperty("id")
|
||
.GetString();
|
||
}
|
||
catch
|
||
{
|
||
_logger.LogWarning(
|
||
"GetGuidAsync: Не удалось получить идентификатор пользователя, {FullName}, json: {Json}", fullName,
|
||
json);
|
||
return null;
|
||
}
|
||
|
||
return personId;
|
||
}
|
||
|
||
public async Task<Schedule?> GetScheduleJsonAsync(ModeusScheduleRequest msr)
|
||
{
|
||
var schedule = await GetScheduleAsync(msr);
|
||
if (schedule == null)
|
||
{
|
||
_logger.LogError("GetScheduleJsonAsync: Schedule is null. Request: {@msr}", msr);
|
||
throw new Exception("Schedule is null");
|
||
}
|
||
|
||
Schedule? scheduleJson;
|
||
try
|
||
{
|
||
scheduleJson = Schedule.FromJson(schedule);
|
||
switch (scheduleJson)
|
||
{
|
||
case null:
|
||
_logger.LogError(
|
||
"GetScheduleJsonAsync: scheduleJson is null. Schedule: {Schedule}\n Request: {msr}",
|
||
schedule, JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions));
|
||
break;
|
||
case { Embedded: null }:
|
||
_logger.LogError(
|
||
"GetScheduleJsonAsync: scheduleJson.Embedded is null. Response: {@response}\nscheduleJson: {@scheduleJson}\n Request: {msr}",
|
||
schedule, scheduleJson, JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions));
|
||
break;
|
||
case { Embedded.Events: null }:
|
||
_logger.LogError(
|
||
"GetScheduleJsonAsync: scheduleJson.Embedded.Events is null. Response: {@response}\nEmbedded: {@Embedded}\n Request: {msr}",
|
||
schedule, scheduleJson.Embedded, JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions));
|
||
break;
|
||
case { Embedded.Events.Length: 0 }:
|
||
_logger.LogWarning(
|
||
"GetScheduleJsonAsync: scheduleJson.Embedded.Events is empty. Embedded: {@Embedded}\n Request: {msr}",
|
||
scheduleJson.Embedded, JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions));
|
||
break;
|
||
default:
|
||
return scheduleJson;
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex,
|
||
"GetScheduleJsonAsync: Deserialization failed. Schedule: {Schedule}\n Request: {msr}", schedule,
|
||
JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions));
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
public async Task<string?> GetIcsAsync(ModeusScheduleRequest msr)
|
||
{
|
||
Schedule? scheduleJson = await GetScheduleJsonAsync(msr);
|
||
if (scheduleJson == null)
|
||
{
|
||
_logger.LogError("GetIcsAsync: scheduleJson is null after deserialization. Request: " + JsonSerializer.Serialize(msr, GlobalVariables.JsonSerializerOptions));
|
||
return null;
|
||
}
|
||
|
||
var calendar = new Ical.Net.Calendar();
|
||
calendar.AddTimeZone(new VTimeZone(_configuration["TZ"]!));
|
||
|
||
foreach (var e in scheduleJson.Embedded.Events)
|
||
{
|
||
// Получение названия аудитории для события
|
||
string? roomName = null;
|
||
if (scheduleJson.Embedded.EventLocations != null && scheduleJson.Embedded.Rooms != null &&
|
||
scheduleJson.Embedded.EventRooms != null)
|
||
{
|
||
var eventLocation = scheduleJson.Embedded.EventLocations.FirstOrDefault(el => el.EventId == e.Id);
|
||
if (eventLocation != null
|
||
&& eventLocation.Links != null
|
||
&& eventLocation.Links.EventRooms != null
|
||
&& eventLocation.Links.EventRooms.Href != null)
|
||
{
|
||
var eventRoomId = eventLocation.Links.EventRooms.Href.Split('/').Last();
|
||
var EventRoom =
|
||
scheduleJson.Embedded.EventRooms.FirstOrDefault(er =>
|
||
er.Id.ToString().ToLower() == eventRoomId);
|
||
if (EventRoom != null)
|
||
{
|
||
var roomId = EventRoom.Links.Room.Href.Split('/').Last();
|
||
var room = scheduleJson.Embedded.Rooms.FirstOrDefault(r =>
|
||
r.Id.ToString().ToLower() == roomId);
|
||
if (room != null)
|
||
roomName = room.Name;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Получение преподавателей для события
|
||
string teachersNames = "";
|
||
if (scheduleJson.Embedded.EventOrganizers != null && scheduleJson.Embedded.EventAttendees != null &&
|
||
scheduleJson.Embedded.Persons != null)
|
||
{
|
||
// Получаем eventOrganizer
|
||
var eventOrganizers =
|
||
scheduleJson.Embedded.EventOrganizers.FirstOrDefault(eo => eo.EventId == e.Id);
|
||
if (eventOrganizers != null &&
|
||
eventOrganizers.Links.EventAttendees != null)
|
||
{
|
||
// Получаем eventAttendee id
|
||
// Тут может прийти массив или 1 объект
|
||
Self[] eventAttendeeIds = Array.Empty<Self>();
|
||
if (eventOrganizers.Links.EventAttendees.Value.Self != null)
|
||
eventAttendeeIds = new[] { eventOrganizers.Links.EventAttendees.Value.Self };
|
||
else if (eventOrganizers.Links.EventAttendees.Value.SelfArray != null)
|
||
eventAttendeeIds = eventOrganizers.Links.EventAttendees.Value.SelfArray;
|
||
|
||
if (eventAttendeeIds.Length > 0)
|
||
{
|
||
foreach (var eventAttendeeId in eventAttendeeIds)
|
||
{
|
||
var attendeeId = eventAttendeeId.Href.Split('/').Last();
|
||
// Получаем eventAttendee
|
||
var eventAttendee =
|
||
scheduleJson.Embedded.EventAttendees.FirstOrDefault(ea =>
|
||
ea.Id.ToString().ToLower() == attendeeId);
|
||
if (eventAttendee != null)
|
||
{
|
||
var personId = eventAttendee.Links.Person.Href.Split('/').Last();
|
||
// Получаем person
|
||
var teacher = scheduleJson.Embedded.Persons.FirstOrDefault(p =>
|
||
p.Id.ToString().ToLower() == personId);
|
||
if (teacher != null)
|
||
teachersNames += (string.IsNullOrEmpty(teachersNames) ? "" : ", ") +
|
||
teacher.FullName;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// Получение короткого названия для события
|
||
string shortNameCourse = "";
|
||
if (scheduleJson.Embedded.CourseUnitRealizations != null)
|
||
{
|
||
try
|
||
{
|
||
var courseUnitRealizationsLinks = e.Links["course-unit-realization"];
|
||
var courseUnitRealizationId = courseUnitRealizationsLinks.Href.Split('/').Last();
|
||
if (!string.IsNullOrEmpty(courseUnitRealizationId))
|
||
{
|
||
var courseUnitRealization = scheduleJson.Embedded.CourseUnitRealizations
|
||
.FirstOrDefault(cu => cu.Id.ToString().ToLower() == courseUnitRealizationId);
|
||
if (courseUnitRealization != null)
|
||
shortNameCourse = courseUnitRealization.NameShort ?? "";
|
||
}
|
||
}
|
||
catch (Exception)
|
||
{
|
||
// Ignored
|
||
}
|
||
}
|
||
|
||
calendar.Events.Add(new CalendarEvent
|
||
{
|
||
Summary = (string.IsNullOrEmpty(shortNameCourse) ? "" : shortNameCourse + " / ") + e.Name,
|
||
Description = e.NameShort + (string.IsNullOrEmpty(roomName) ? "" : $"\nАудитория: {roomName}") +
|
||
(string.IsNullOrEmpty(teachersNames) ? "" : $"\nПреподаватели: {teachersNames}"),
|
||
Start = new CalDateTime(e.StartsAtLocal, _configuration["TZ"]!),
|
||
End = new CalDateTime(e.EndsAtLocal, _configuration["TZ"]!),
|
||
});
|
||
}
|
||
|
||
var serializer = new CalendarSerializer();
|
||
var serializedCalendar = serializer.SerializeToString(calendar);
|
||
_logger.LogInformation("GetIcsAsync: Serialized calendar created. Length: {Length}",
|
||
serializedCalendar?.Length ?? 0);
|
||
return serializedCalendar;
|
||
}
|
||
}
|
||
} |