2025-12-17 17:03:50 +09:00
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
|
using Serilog;
|
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
|
using System.Text.Json;
|
|
|
|
|
|
using VTSFetcher.Models;
|
|
|
|
|
|
using VTSFetcher.Repositories.Entities;
|
|
|
|
|
|
|
|
|
|
|
|
namespace VTSFetcher.Services;
|
|
|
|
|
|
|
|
|
|
|
|
public class VtsService
|
|
|
|
|
|
{
|
|
|
|
|
|
private readonly AppSettings _appSettings;
|
|
|
|
|
|
|
|
|
|
|
|
public VtsService(IOptions<AppSettings> options)
|
|
|
|
|
|
{
|
|
|
|
|
|
_appSettings = options.Value;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<VTSResponse> FetchVtsIssues(DateTimeOffset lastFetchTime, string targetProject,
|
|
|
|
|
|
int startAt, CancellationToken ct)
|
|
|
|
|
|
{
|
|
|
|
|
|
var uri = $"{_appSettings.VTS.ApiBaseUrl}/"
|
|
|
|
|
|
+ $"search?jql=project={targetProject} "
|
|
|
|
|
|
+ $"AND updated >= \"{lastFetchTime.ToString("yyyy-MM-dd HH:mm")}\" "
|
|
|
|
|
|
+ $"&fields={_appSettings.VTS.SearchFields}"
|
|
|
|
|
|
+ $"&startAt={startAt}&maxResults=50";
|
|
|
|
|
|
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
|
|
|
|
|
request.Headers.Add("Accept", "application/json");
|
|
|
|
|
|
request.Headers.Add("Authorization", $"Bearer {_appSettings.VTS.AccessToken}");
|
2025-12-25 09:42:24 +09:00
|
|
|
|
Log.Debug("Fetch VTS issues ready. Fetch the issues updated after {last_fetch_time} in Project {target_project}. ({fetch_url})",
|
|
|
|
|
|
lastFetchTime.ToString("yyyy-MM-dd HH:mm"), targetProject, uri);
|
2025-12-17 17:03:50 +09:00
|
|
|
|
|
|
|
|
|
|
using var client = new HttpClient();
|
|
|
|
|
|
var response = await client.SendAsync(request, ct).ConfigureAwait(false);
|
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
|
|
|
|
|
|
|
|
var jsonResponse = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
|
|
|
|
|
|
var vtsResponse = JsonSerializer.Deserialize<VTSResponse>(jsonResponse);
|
|
|
|
|
|
return vtsResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<Issue> FetchVtsIssueAsync(string targetIssueKey, CancellationToken ct)
|
|
|
|
|
|
{
|
|
|
|
|
|
var uri = $"{_appSettings.VTS.ApiBaseUrl}/issue/{targetIssueKey}";
|
|
|
|
|
|
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
|
|
|
|
|
request.Headers.Add("Accept", "application/json");
|
|
|
|
|
|
request.Headers.Add("Authorization", $"Bearer {_appSettings.VTS.AccessToken}");
|
|
|
|
|
|
Log.Debug("Fetch a VTS issue({issue_key}) ready.", targetIssueKey);
|
|
|
|
|
|
|
|
|
|
|
|
using var client = new HttpClient();
|
|
|
|
|
|
var response = await client.SendAsync(request, ct).ConfigureAwait(false);
|
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
|
|
|
|
|
|
|
|
var jsonResponse = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
|
|
|
|
|
|
var issue = JsonSerializer.Deserialize<Issue>(jsonResponse);
|
|
|
|
|
|
return issue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-06 09:36:57 +09:00
|
|
|
|
public async Task<VTSResponse> FetchVtsIssuesByJql(string jql, string targetProject, int startAt, CancellationToken ct)
|
|
|
|
|
|
{
|
|
|
|
|
|
var uri = $"{_appSettings.VTS.ApiBaseUrl}/"
|
|
|
|
|
|
+ $"search?jql={jql} "
|
|
|
|
|
|
+ $"AND project={targetProject} "
|
|
|
|
|
|
+ $"&fields={_appSettings.VTS.SearchFields}"
|
|
|
|
|
|
+ $"&startAt={startAt}&maxResults=50";
|
|
|
|
|
|
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
|
|
|
|
|
request.Headers.Add("Accept", "application/json");
|
|
|
|
|
|
request.Headers.Add("Authorization", $"Bearer {_appSettings.VTS.AccessToken}");
|
|
|
|
|
|
Log.Debug("Fetch VTS issues ready. {fetch_url}", uri);
|
|
|
|
|
|
|
|
|
|
|
|
using var client = new HttpClient();
|
|
|
|
|
|
var response = await client.SendAsync(request, ct).ConfigureAwait(false);
|
|
|
|
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
|
|
|
|
|
|
|
|
var jsonResponse = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
|
|
|
|
|
|
var vtsResponse = JsonSerializer.Deserialize<VTSResponse>(jsonResponse);
|
|
|
|
|
|
return vtsResponse;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-17 17:03:50 +09:00
|
|
|
|
private List<VtsIssue> JsonDeserializeToVtsIssues(string json)
|
|
|
|
|
|
{
|
|
|
|
|
|
var result = new List<VtsIssue>();
|
|
|
|
|
|
var jsonSerializerOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
|
|
|
|
|
|
var vtsResponse = JsonSerializer.Deserialize<VTSResponse>(json, jsonSerializerOptions);
|
|
|
|
|
|
if (vtsResponse?.issues.Length > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
result = [.. vtsResponse.issues.Select(i => new VtsIssue
|
|
|
|
|
|
{
|
|
|
|
|
|
Key = i.key,
|
|
|
|
|
|
Summary = i.fields.summary,
|
|
|
|
|
|
Type = i.fields.issuetype.name,
|
|
|
|
|
|
Status = i.fields.status.name,
|
|
|
|
|
|
Assignee = i.fields.assignee.displayName,
|
|
|
|
|
|
Manager = i.fields.reporter.displayName,
|
|
|
|
|
|
Due = i.fields.duedate ?? new DateTime(1999, 12, 23, 23, 59, 59),
|
|
|
|
|
|
Updated = i.fields.UpdatedAt,
|
|
|
|
|
|
Parent = i.fields.parent?.key,
|
|
|
|
|
|
})];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|