diff options
author | crupest <crupest@outlook.com> | 2022-12-01 19:19:47 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2022-12-02 13:35:35 +0800 |
commit | b44f957e6d886387e9f275dfb623540ae0acd737 (patch) | |
tree | dee523de3ff29067fa0202135a322079b295df4c /docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs | |
parent | 462ae43246799469f0c6cdac5e45e1a9d0f5da2e (diff) | |
download | crupest-b44f957e6d886387e9f275dfb623540ae0acd737.tar.gz crupest-b44f957e6d886387e9f275dfb623540ae0acd737.tar.bz2 crupest-b44f957e6d886387e9f275dfb623540ae0acd737.zip |
Restructure crupest-api.
Diffstat (limited to 'docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs')
-rw-r--r-- | docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs b/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs new file mode 100644 index 0000000..f5ccc09 --- /dev/null +++ b/docker/crupest-api/CrupestApi/CrupestApi.Todos/TodosService.cs @@ -0,0 +1,144 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Mime; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; + +namespace CrupestApi.Todos; + +public class TodosItem +{ + public string Status { get; set; } = default!; + public string Title { get; set; } = default!; + public bool Closed { get; set; } + public string Color { get; set; } = default!; +} + +public class TodosService +{ + private readonly IOptionsSnapshot<TodosConfiguration> _options; + private readonly ILogger<TodosService> _logger; + + public TodosService(IOptionsSnapshot<TodosConfiguration> options, ILogger<TodosService> logger) + { + _options = options; + _logger = logger; + } + + private static string CreateGraphQLQuery(TodosConfiguration todoConfiguration) + { + return $$""" +{ + user(login: "{{todoConfiguration.Username}}") { + projectV2(number: {{todoConfiguration.ProjectNumber}}) { + items(last: {{todoConfiguration.Count}}) { + nodes { + __typename + content { + __typename + ... on Issue { + title + closed + } + ... on PullRequest { + title + closed + } + ... on DraftIssue { + title + } + } + } + } + } + } +} +"""; + } + + + public async Task<List<TodosItem>> GetTodosAsync() + { + var todoOptions = _options.Value; + if (todoOptions is null) + { + throw new Exception("Fail to get todos configuration."); + } + + _logger.LogInformation("Username: {}; ProjectNumber: {}; Count: {}", todoOptions.Username, todoOptions.ProjectNumber, todoOptions.Count); + _logger.LogInformation("Getting todos from GitHub GraphQL API..."); + + using var httpClient = new HttpClient(); + + using var requestContent = new StringContent(JsonSerializer.Serialize(new + { + query = CreateGraphQLQuery(todoOptions) + })); + requestContent.Headers.ContentType = new MediaTypeHeaderValue(MediaTypeNames.Application.Json, Encoding.UTF8.WebName); + + using var request = new HttpRequestMessage(HttpMethod.Post, "https://api.github.com/graphql"); + request.Content = requestContent; + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", todoOptions.Token); + request.Headers.TryAddWithoutValidation("User-Agent", todoOptions.Username); + + using var response = await httpClient.SendAsync(request); + var responseBody = await response.Content.ReadAsStringAsync(); + + _logger.LogInformation("GitHub server returned status code: {}", response.StatusCode); + _logger.LogInformation("GitHub server returned body: {}", responseBody); + + if (response.IsSuccessStatusCode) + { + using var responseJson = JsonSerializer.Deserialize<JsonDocument>(responseBody); + if (responseJson is null) + { + throw new Exception("Fail to deserialize response body."); + } + + var nodes = responseJson.RootElement.GetProperty("data").GetProperty("user").GetProperty("projectV2").GetProperty("items").GetProperty("nodes").EnumerateArray(); + + var result = new List<TodosItem>(); + + foreach (var node in nodes) + { + var content = node.GetProperty("content"); + var title = content.GetProperty("title").GetString(); + if (title is null) + { + throw new Exception("Fail to get title."); + } + JsonElement closedElement; + bool closed; + if (content.TryGetProperty("closed", out closedElement)) + { + closed = closedElement.GetBoolean(); + } + else + { + closed = false; + } + + result.Add(new TodosItem + { + Title = title, + Status = closed ? "Done" : "Todo", + Closed = closed, + Color = closed ? "green" : "blue" + }); + } + + return result; + } + else + { + const string message = "Fail to get todos from GitHub."; + _logger.LogError(message); + throw new Exception(message); + } + } +} |