using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; namespace FictionArchive.Service.NovelService.Services.SourceAdapters.Novelpia; public class NovelpiaAuthMessageHandler : DelegatingHandler { private readonly HttpClient _httpClient; private readonly IMemoryCache _cache; private readonly NovelpiaConfiguration _configuration; private const string CacheKey = "novelpia_loginkey"; private const string LoginUrl = "/proc/login"; private const string LoginSuccessMessage = "감사합니다"; private const string UserAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36"; public NovelpiaAuthMessageHandler(HttpClient httpClient, IOptions configuration, IMemoryCache cache) { _httpClient = httpClient; _configuration = configuration.Value; _cache = cache; } protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { string loginKey = await GetLoginKey(); request.Headers.Add("cookie", $"LOGINKEY={loginKey}"); request.Headers.UserAgent.ParseAdd(UserAgent); return await base.SendAsync(request, cancellationToken); } private async Task GetLoginKey() { if (!_cache.TryGetValue(CacheKey, out string? loginKey)) { var random = new Random(); var characters = "0123456789abcdef"; var firstPart = new string(Enumerable.Range(0, 32).Select(_ => characters[random.Next(characters.Length)]).ToArray()); var secondPart = new string(Enumerable.Range(0, 32).Select(_ => characters[random.Next(characters.Length)]).ToArray()); loginKey = firstPart + "_" + secondPart; HttpRequestMessage loginMessage = new HttpRequestMessage(HttpMethod.Post, LoginUrl); loginMessage.Headers.Add("cookie", $"LOGINKEY={loginKey}"); loginMessage.Headers.UserAgent.ParseAdd(UserAgent); loginMessage.Content = new FormUrlEncodedContent(new Dictionary { { "redirecturl", string.Empty }, { "email", _configuration.Username }, { "wd", _configuration.Password } }); var response = await _httpClient.SendAsync(loginMessage); using (var streamReader = new StreamReader(response.Content.ReadAsStream())) { if (streamReader.ReadToEnd().Contains(LoginSuccessMessage)) { _cache.Set(CacheKey, loginKey); } } } return loginKey; } }