using File_Folder_Helper.Day.Q32024.WorkItems; using Microsoft.Extensions.Logging; using Microsoft.TeamFoundation.WorkItemTracking.WebApi; using Microsoft.VisualStudio.Services.Common; using Microsoft.VisualStudio.Services.WebApi; using System.Collections.ObjectModel; using System.Net.Http.Headers; using System.Text; using System.Text.Json; using System.Web; namespace File_Folder_Helper.Day.Q32024; internal static partial class Helper20240830 { private static string GetIds(HttpClient httpClient, string basePage, string api, string query) { StringBuilder result = new(); Task httpResponseMessageTask = httpClient.GetAsync(string.Concat(basePage, api, query)); httpResponseMessageTask.Wait(); if (!httpResponseMessageTask.Result.IsSuccessStatusCode) throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString()); Task streamTask = httpResponseMessageTask.Result.Content.ReadAsStreamAsync(); streamTask.Wait(); if (!streamTask.Result.CanRead) throw new NullReferenceException(nameof(streamTask)); WIQL.Root? root = JsonSerializer.Deserialize(streamTask.Result, WIQL.WIQLRootSourceGenerationContext.Default.Root); streamTask.Result.Dispose(); if (root is null || root.WorkItems is null) throw new NullReferenceException(nameof(root)); foreach (WIQL.WorkItem workItem in root.WorkItems) _ = result.Append(workItem.Id).Append(','); if (result.Length > 0) _ = result.Remove(result.Length - 1, 1); return result.ToString(); } private static ReadOnlyCollection GetWorkItems(HttpClient httpClient, string basePage, string api, string sourceDirectory, string ids) { List results = []; string json; string file; Value? value; JsonElement[] jsonElements; Task httpResponseMessageTask = httpClient.GetAsync(string.Concat(basePage, api, $"/workitems?ids={ids}")); httpResponseMessageTask.Wait(); if (!httpResponseMessageTask.Result.IsSuccessStatusCode) throw new Exception(httpResponseMessageTask.Result.StatusCode.ToString()); Task streamTask = httpResponseMessageTask.Result.Content.ReadAsStreamAsync(); streamTask.Wait(); if (!streamTask.Result.CanRead) throw new NullReferenceException(nameof(streamTask)); JsonElement? result = JsonSerializer.Deserialize(streamTask.Result); if (result is null || result.Value.ValueKind != JsonValueKind.Object) throw new NullReferenceException(nameof(result)); JsonProperty[] jsonProperties = result.Value.EnumerateObject().ToArray(); foreach (JsonProperty jsonProperty in jsonProperties) { if (jsonProperty.Value.ValueKind != JsonValueKind.Array) continue; jsonElements = jsonProperty.Value.EnumerateArray().ToArray(); foreach (JsonElement jsonElement in jsonElements) { json = jsonElement.GetRawText(); value = JsonSerializer.Deserialize(json, ValueSourceGenerationContext.Default.Value); if (value is null) continue; file = Path.Combine(sourceDirectory, $"{-1}-{value.Id}.json"); File.WriteAllText(file, json); results.Add(new(value, -1, json)); } } return new(results); } private static void CompareWorkItems(WorkItemTrackingHttpClient workItemTrackingHttpClient, string project, string site, ReadOnlyCollection valueWithReqCollection) { ArgumentNullException.ThrowIfNull(workItemTrackingHttpClient); if (string.IsNullOrEmpty(project)) throw new ArgumentException($"'{nameof(project)}' cannot be null or empty.", nameof(project)); if (string.IsNullOrEmpty(site)) throw new ArgumentException($"'{nameof(site)}' cannot be null or empty.", nameof(site)); ArgumentNullException.ThrowIfNull(valueWithReqCollection); // https://stackoverflow.com/questions/18153998/how-do-i-remove-all-html-tags-from-a-string-without-knowing-which-tags-are-in-it } private static void CompareWorkItems(HttpClient httpClient, string sourceDirectory, string basePage, string api, string query, WorkItemTrackingHttpClient workItemTrackingHttpClient, string project, string site) { string ids = GetIds(httpClient, basePage, api, query); ReadOnlyCollection valueWithReqCollection = string.IsNullOrEmpty(ids) ? new([]) : GetWorkItems(httpClient, basePage, api, sourceDirectory, ids); CompareWorkItems(workItemTrackingHttpClient, project, site, valueWithReqCollection); } private static void CreateWorkItems(ILogger logger, string sourceDirectory, string api, string site, string query, string project, string basePage, string baseAddress, byte[] bytes, MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue, WorkItemTrackingHttpClient workItemTrackingHttpClient, HttpClient httpClient) { string base64 = Convert.ToBase64String(bytes); httpClient.DefaultRequestHeaders.Authorization = new("Basic", base64); httpClient.DefaultRequestHeaders.Accept.Add(mediaTypeWithQualityHeaderValue); logger.LogInformation("{baseAddress}{basePage}/{project}{api}{query}", baseAddress, basePage, HttpUtility.HtmlEncode(project), api, query); CompareWorkItems(httpClient, sourceDirectory, basePage, api, query, workItemTrackingHttpClient, project, site); } internal static void CompareWorkItems(ILogger logger, List args) { string api = args[6]; string pat = args[8]; string site = args[2]; string query = args[7]; string project = args[5]; string basePage = args[4]; string baseAddress = args[3]; string sourceDirectory = args[0]; VssBasicCredential credential = new("", pat); byte[] bytes = Encoding.ASCII.GetBytes($":{pat}"); VssConnection connection = new(new(string.Concat(baseAddress, basePage)), credential); MediaTypeWithQualityHeaderValue mediaTypeWithQualityHeaderValue = new("application/json"); WorkItemTrackingHttpClient workItemTrackingHttpClient = connection.GetClient(); HttpClient httpClient = new(new HttpClientHandler() { UseDefaultCredentials = true }) { BaseAddress = new(baseAddress) }; CreateWorkItems(logger, sourceDirectory, api, site, query, project, basePage, baseAddress, bytes, mediaTypeWithQualityHeaderValue, workItemTrackingHttpClient, httpClient); } }