Вынес httpclient в отдельный сервис

This commit is contained in:
2025-11-21 03:56:04 +03:00
parent f7c8db4921
commit 8ba1aea46a
4 changed files with 164 additions and 105 deletions

View File

@@ -8,6 +8,7 @@ public class UpdateJwtJob(
IConfiguration configuration, IConfiguration configuration,
ILogger<UpdateJwtJob> logger, ILogger<UpdateJwtJob> logger,
IHttpClientFactory httpClientFactory, IHttpClientFactory httpClientFactory,
ModeusHttpClient modeusHttpClient,
ModeusService modeusService) : IJob ModeusService modeusService) : IJob
{ {
private const int MaxAttempts = 5; // Максимальное число попыток private const int MaxAttempts = 5; // Максимальное число попыток
@@ -70,7 +71,7 @@ public class UpdateJwtJob(
} }
configuration["TOKEN"] = body.Jwt; configuration["TOKEN"] = body.Jwt;
modeusService.SetToken(body.Jwt); modeusHttpClient.SetToken(body.Jwt);
await File.WriteAllTextAsync(GlobalConsts.JwtFilePath, await File.WriteAllTextAsync(GlobalConsts.JwtFilePath,
body.Jwt + "\n" + DateTime.Now.ToString("O"), cts.Token); body.Jwt + "\n" + DateTime.Now.ToString("O"), cts.Token);
logger.LogInformation("JWT успешно обновлён"); logger.LogInformation("JWT успешно обновлён");

View File

@@ -52,7 +52,7 @@ if (!string.IsNullOrEmpty(tgChatId) && !string.IsNullOrEmpty(tgToken))
options.ChatId = tgChatId; options.ChatId = tgChatId;
options.AccessToken = tgToken; options.AccessToken = tgToken;
options.FormatterConfiguration.UseEmoji = true; options.FormatterConfiguration.UseEmoji = true;
options.FormatterConfiguration.ReadableApplicationName = "Sfedu Schedule"; options.FormatterConfiguration.ReadableApplicationName = "Modeus Schedule Proxy";
options.LogLevel = new Dictionary<string, LogLevel> options.LogLevel = new Dictionary<string, LogLevel>
{ {
{ "Default", LogLevel.Error }, { "Default", LogLevel.Error },
@@ -68,8 +68,9 @@ builder.Services.AddHttpClient("modeus", client =>
{ {
client.BaseAddress = new Uri(configuration["MODEUS_URL"]!); client.BaseAddress = new Uri(configuration["MODEUS_URL"]!);
}); });
builder.Services.AddSingleton<ModeusService>(); builder.Services.AddSingleton<ModeusHttpClient>();
builder.Services.AddHttpClient("authClient"); builder.Services.AddScoped<ModeusService>();
builder.Services.AddHttpClient<ModeusHttpClient>("authClient");
builder.Services.AddAuthentication() builder.Services.AddAuthentication()
.AddScheme<AuthenticationSchemeOptions, ApiKeyAuthenticationHandler>( .AddScheme<AuthenticationSchemeOptions, ApiKeyAuthenticationHandler>(

View File

@@ -0,0 +1,132 @@
using System.Text;
using System.Text.Json;
using Microsoft.Net.Http.Headers;
using ModeusSchedule.Abstractions;
using ModeusSchedule.Abstractions.DTO;
namespace SfeduSchedule.Services;
public class ModeusHttpClient
{
private readonly HttpClient _httpClient;
private readonly IConfiguration _configuration;
private readonly ILogger<ModeusHttpClient> _logger;
public ModeusHttpClient(IHttpClientFactory httpClientFactory,
ILogger<ModeusHttpClient> logger,
IConfiguration configuration)
{
_httpClient = httpClientFactory.CreateClient("modeus");
_logger = logger;
_configuration = configuration;
SetToken(_configuration["TOKEN"]); // Установка предустановленного токена при инициализации, на случай если нет возможности связи с AUTH сервисом
}
public void SetToken(string? token)
{
if (string.IsNullOrWhiteSpace(token)) {
_logger.LogError("SetToken: Предоставленный токен пустой.");
return;
}
_httpClient.DefaultRequestHeaders.Remove(HeaderNames.Authorization);
_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, GlobalConsts.JsonSerializerOptions),
Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.LogError("GetScheduleAsync: Неуспешный статус при получении расписания: {StatusCode}, Request: {msr}",
response.StatusCode, msr);
return null;
}
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);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.LogError("GetAttendeesAsync: Неуспешный статус при получении расписания: {StatusCode}, eventId: {eventId}",
response.StatusCode, eventId);
}
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, GlobalConsts.JsonSerializerOptions),
Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.LogError("GetScheduleAsync: Неуспешный статус при получении расписания: {StatusCode}, Request: {requestDto}",
response.StatusCode, requestDto);
return null;
}
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,
sort = "+fullName",
size = 10,
page = 0
}), Encoding.UTF8, "application/json");
var response = await _httpClient.SendAsync(request);
_logger.LogInformation("GetGuidAsync: Ответ получен: {StatusCode}", response.StatusCode);
if (response.StatusCode != System.Net.HttpStatusCode.OK)
{
_logger.LogError("GetGuidAsync: Неуспешный статус при получении расписания: {StatusCode}, Name: {fullName}",
response.StatusCode, fullName);
return null;
}
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;
}
}

View File

@@ -1,10 +1,8 @@
using System.Text;
using System.Text.Json; using System.Text.Json;
using Ical.Net; using Ical.Net;
using Ical.Net.CalendarComponents; using Ical.Net.CalendarComponents;
using Ical.Net.DataTypes; using Ical.Net.DataTypes;
using Ical.Net.Serialization; using Ical.Net.Serialization;
using Microsoft.Net.Http.Headers;
using ModeusSchedule.Abstractions; using ModeusSchedule.Abstractions;
using ModeusSchedule.Abstractions.DTO; using ModeusSchedule.Abstractions.DTO;
@@ -13,110 +11,18 @@ namespace SfeduSchedule.Services;
public class ModeusService public class ModeusService
{ {
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
private readonly HttpClient _httpClient;
private readonly ILogger<ModeusService> _logger;
public ModeusService(IHttpClientFactory httpClientFactory, private readonly ILogger<ModeusService> _logger;
private readonly ModeusHttpClient _modeusHttpClient;
public ModeusService(
ILogger<ModeusService> logger, ILogger<ModeusService> logger,
IConfiguration configuration) IConfiguration configuration,
ModeusHttpClient modeusHttpClient)
{ {
_httpClient = httpClientFactory.CreateClient("modeus"); _modeusHttpClient = modeusHttpClient;
_logger = logger; _logger = logger;
_configuration = configuration; _configuration = configuration;
SetToken(_configuration["TOKEN"]); // Установка предустановленного токена при инициализации, на случай если нет возможности связи с AUTH сервисом
}
public void SetToken(string? token)
{
if (string.IsNullOrWhiteSpace(token)) {
_logger.LogError("SetToken: Предоставленный токен пустой.");
return;
}
_httpClient.DefaultRequestHeaders.Remove(HeaderNames.Authorization);
_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, GlobalConsts.JsonSerializerOptions),
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, GlobalConsts.JsonSerializerOptions),
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,
sort = "+fullName",
size = 10,
page = 0
}), 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) public async Task<Schedule?> GetScheduleJsonAsync(ModeusScheduleRequest msr)
@@ -287,4 +193,23 @@ public class ModeusService
serializedCalendar?.Length ?? 0); serializedCalendar?.Length ?? 0);
return serializedCalendar; return serializedCalendar;
} }
#region Проксирование методов из ModeusHttpClient
public async Task<string?> SearchRoomsAsync(RoomSearchRequest request)
{
return await _modeusHttpClient.SearchRoomsAsync(request);
}
public async Task<string?> GetScheduleAsync(ModeusScheduleRequest msr)
{
return await _modeusHttpClient.GetScheduleAsync(msr);
}
public async Task<string?> GetGuidAsync(string fullname)
{
return await _modeusHttpClient.GetGuidAsync(fullname);
}
#endregion
} }